diff --git a/package.json b/package.json index be55dcb..5a72c69 100644 --- a/package.json +++ b/package.json @@ -14,16 +14,16 @@ "react-dom": "^19.0.0" }, "devDependencies": { - "@eslint/js": "^9.21.0", - "@types/react": "^19.0.10", + "@eslint/js": "^9.23.0", + "@types/react": "^19.0.12", "@types/react-dom": "^19.0.4", "@vitejs/plugin-react": "^4.3.4", - "eslint": "^9.21.0", - "eslint-plugin-react-hooks": "^5.1.0", + "eslint": "^9.23.0", + "eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-refresh": "^0.4.19", "globals": "^16.0.0", - "typescript": "~5.7.3", - "typescript-eslint": "^8.25.0", - "vite": "^6.1.1" + "typescript": "~5.8.2", + "typescript-eslint": "^8.28.0", + "vite": "^6.2.3" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9944dc4..968562b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -16,38 +16,38 @@ importers: version: 19.0.0(react@19.0.0) devDependencies: '@eslint/js': - specifier: ^9.21.0 - version: 9.21.0 + specifier: ^9.23.0 + version: 9.23.0 '@types/react': - specifier: ^19.0.10 - version: 19.0.10 + specifier: ^19.0.12 + version: 19.0.12 '@types/react-dom': specifier: ^19.0.4 - version: 19.0.4(@types/react@19.0.10) + version: 19.0.4(@types/react@19.0.12) '@vitejs/plugin-react': specifier: ^4.3.4 - version: 4.3.4(vite@6.1.1) + version: 4.3.4(vite@6.2.3) eslint: - specifier: ^9.21.0 - version: 9.21.0 + specifier: ^9.23.0 + version: 9.23.0 eslint-plugin-react-hooks: - specifier: ^5.1.0 - version: 5.1.0(eslint@9.21.0) + specifier: ^5.2.0 + version: 5.2.0(eslint@9.23.0) eslint-plugin-react-refresh: specifier: ^0.4.19 - version: 0.4.19(eslint@9.21.0) + version: 0.4.19(eslint@9.23.0) globals: specifier: ^16.0.0 version: 16.0.0 typescript: - specifier: ~5.7.3 - version: 5.7.3 + specifier: ~5.8.2 + version: 5.8.2 typescript-eslint: - specifier: ^8.25.0 - version: 8.25.0(eslint@9.21.0)(typescript@5.7.3) + specifier: ^8.28.0 + version: 8.28.0(eslint@9.23.0)(typescript@5.8.2) vite: - specifier: ^6.1.1 - version: 6.1.1 + specifier: ^6.2.3 + version: 6.2.3 packages: @@ -63,16 +63,16 @@ packages: resolution: {integrity: sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==} engines: {node: '>=6.9.0'} - '@babel/core@7.26.9': - resolution: {integrity: sha512-lWBYIrF7qK5+GjY5Uy+/hEgp8OJWOD/rpy74GplYRhEauvbHDeFB8t5hPOZxCZ0Oxf4Cc36tK51/l3ymJysrKw==} + '@babel/core@7.26.10': + resolution: {integrity: sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==} engines: {node: '>=6.9.0'} - '@babel/generator@7.26.9': - resolution: {integrity: sha512-kEWdzjOAUMW4hAyrzJ0ZaTOu9OmpyDIQicIh0zg0EEcEkYXZb2TjtBhnHi2ViX7PKwZqF4xwqfAm299/QMP3lg==} + '@babel/generator@7.27.0': + resolution: {integrity: sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==} engines: {node: '>=6.9.0'} - '@babel/helper-compilation-targets@7.26.5': - resolution: {integrity: sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==} + '@babel/helper-compilation-targets@7.27.0': + resolution: {integrity: sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA==} engines: {node: '>=6.9.0'} '@babel/helper-module-imports@7.25.9': @@ -101,12 +101,12 @@ packages: resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==} engines: {node: '>=6.9.0'} - '@babel/helpers@7.26.9': - resolution: {integrity: sha512-Mz/4+y8udxBKdmzt/UjPACs4G3j5SshJJEFFKxlCGPydG4JAHXxjWjAwjd09tf6oINvl1VfMJo+nB7H2YKQ0dA==} + '@babel/helpers@7.27.0': + resolution: {integrity: sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==} engines: {node: '>=6.9.0'} - '@babel/parser@7.26.9': - resolution: {integrity: sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A==} + '@babel/parser@7.27.0': + resolution: {integrity: sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==} engines: {node: '>=6.0.0'} hasBin: true @@ -122,170 +122,170 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/template@7.26.9': - resolution: {integrity: sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==} + '@babel/template@7.27.0': + resolution: {integrity: sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==} engines: {node: '>=6.9.0'} - '@babel/traverse@7.26.9': - resolution: {integrity: sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg==} + '@babel/traverse@7.27.0': + resolution: {integrity: sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==} engines: {node: '>=6.9.0'} - '@babel/types@7.26.9': - resolution: {integrity: sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw==} + '@babel/types@7.27.0': + resolution: {integrity: sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==} engines: {node: '>=6.9.0'} - '@esbuild/aix-ppc64@0.24.2': - resolution: {integrity: sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==} + '@esbuild/aix-ppc64@0.25.1': + resolution: {integrity: sha512-kfYGy8IdzTGy+z0vFGvExZtxkFlA4zAxgKEahG9KE1ScBjpQnFsNOX8KTU5ojNru5ed5CVoJYXFtoxaq5nFbjQ==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] - '@esbuild/android-arm64@0.24.2': - resolution: {integrity: sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==} + '@esbuild/android-arm64@0.25.1': + resolution: {integrity: sha512-50tM0zCJW5kGqgG7fQ7IHvQOcAn9TKiVRuQ/lN0xR+T2lzEFvAi1ZcS8DiksFcEpf1t/GYOeOfCAgDHFpkiSmA==} engines: {node: '>=18'} cpu: [arm64] os: [android] - '@esbuild/android-arm@0.24.2': - resolution: {integrity: sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==} + '@esbuild/android-arm@0.25.1': + resolution: {integrity: sha512-dp+MshLYux6j/JjdqVLnMglQlFu+MuVeNrmT5nk6q07wNhCdSnB7QZj+7G8VMUGh1q+vj2Bq8kRsuyA00I/k+Q==} engines: {node: '>=18'} cpu: [arm] os: [android] - '@esbuild/android-x64@0.24.2': - resolution: {integrity: sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==} + '@esbuild/android-x64@0.25.1': + resolution: {integrity: sha512-GCj6WfUtNldqUzYkN/ITtlhwQqGWu9S45vUXs7EIYf+7rCiiqH9bCloatO9VhxsL0Pji+PF4Lz2XXCES+Q8hDw==} engines: {node: '>=18'} cpu: [x64] os: [android] - '@esbuild/darwin-arm64@0.24.2': - resolution: {integrity: sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==} + '@esbuild/darwin-arm64@0.25.1': + resolution: {integrity: sha512-5hEZKPf+nQjYoSr/elb62U19/l1mZDdqidGfmFutVUjjUZrOazAtwK+Kr+3y0C/oeJfLlxo9fXb1w7L+P7E4FQ==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] - '@esbuild/darwin-x64@0.24.2': - resolution: {integrity: sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==} + '@esbuild/darwin-x64@0.25.1': + resolution: {integrity: sha512-hxVnwL2Dqs3fM1IWq8Iezh0cX7ZGdVhbTfnOy5uURtao5OIVCEyj9xIzemDi7sRvKsuSdtCAhMKarxqtlyVyfA==} engines: {node: '>=18'} cpu: [x64] os: [darwin] - '@esbuild/freebsd-arm64@0.24.2': - resolution: {integrity: sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==} + '@esbuild/freebsd-arm64@0.25.1': + resolution: {integrity: sha512-1MrCZs0fZa2g8E+FUo2ipw6jw5qqQiH+tERoS5fAfKnRx6NXH31tXBKI3VpmLijLH6yriMZsxJtaXUyFt/8Y4A==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-x64@0.24.2': - resolution: {integrity: sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==} + '@esbuild/freebsd-x64@0.25.1': + resolution: {integrity: sha512-0IZWLiTyz7nm0xuIs0q1Y3QWJC52R8aSXxe40VUxm6BB1RNmkODtW6LHvWRrGiICulcX7ZvyH6h5fqdLu4gkww==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] - '@esbuild/linux-arm64@0.24.2': - resolution: {integrity: sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==} + '@esbuild/linux-arm64@0.25.1': + resolution: {integrity: sha512-jaN3dHi0/DDPelk0nLcXRm1q7DNJpjXy7yWaWvbfkPvI+7XNSc/lDOnCLN7gzsyzgu6qSAmgSvP9oXAhP973uQ==} engines: {node: '>=18'} cpu: [arm64] os: [linux] - '@esbuild/linux-arm@0.24.2': - resolution: {integrity: sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==} + '@esbuild/linux-arm@0.25.1': + resolution: {integrity: sha512-NdKOhS4u7JhDKw9G3cY6sWqFcnLITn6SqivVArbzIaf3cemShqfLGHYMx8Xlm/lBit3/5d7kXvriTUGa5YViuQ==} engines: {node: '>=18'} cpu: [arm] os: [linux] - '@esbuild/linux-ia32@0.24.2': - resolution: {integrity: sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==} + '@esbuild/linux-ia32@0.25.1': + resolution: {integrity: sha512-OJykPaF4v8JidKNGz8c/q1lBO44sQNUQtq1KktJXdBLn1hPod5rE/Hko5ugKKZd+D2+o1a9MFGUEIUwO2YfgkQ==} engines: {node: '>=18'} cpu: [ia32] os: [linux] - '@esbuild/linux-loong64@0.24.2': - resolution: {integrity: sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==} + '@esbuild/linux-loong64@0.25.1': + resolution: {integrity: sha512-nGfornQj4dzcq5Vp835oM/o21UMlXzn79KobKlcs3Wz9smwiifknLy4xDCLUU0BWp7b/houtdrgUz7nOGnfIYg==} engines: {node: '>=18'} cpu: [loong64] os: [linux] - '@esbuild/linux-mips64el@0.24.2': - resolution: {integrity: sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==} + '@esbuild/linux-mips64el@0.25.1': + resolution: {integrity: sha512-1osBbPEFYwIE5IVB/0g2X6i1qInZa1aIoj1TdL4AaAb55xIIgbg8Doq6a5BzYWgr+tEcDzYH67XVnTmUzL+nXg==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] - '@esbuild/linux-ppc64@0.24.2': - resolution: {integrity: sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==} + '@esbuild/linux-ppc64@0.25.1': + resolution: {integrity: sha512-/6VBJOwUf3TdTvJZ82qF3tbLuWsscd7/1w+D9LH0W/SqUgM5/JJD0lrJ1fVIfZsqB6RFmLCe0Xz3fmZc3WtyVg==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] - '@esbuild/linux-riscv64@0.24.2': - resolution: {integrity: sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==} + '@esbuild/linux-riscv64@0.25.1': + resolution: {integrity: sha512-nSut/Mx5gnilhcq2yIMLMe3Wl4FK5wx/o0QuuCLMtmJn+WeWYoEGDN1ipcN72g1WHsnIbxGXd4i/MF0gTcuAjQ==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] - '@esbuild/linux-s390x@0.24.2': - resolution: {integrity: sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==} + '@esbuild/linux-s390x@0.25.1': + resolution: {integrity: sha512-cEECeLlJNfT8kZHqLarDBQso9a27o2Zd2AQ8USAEoGtejOrCYHNtKP8XQhMDJMtthdF4GBmjR2au3x1udADQQQ==} engines: {node: '>=18'} cpu: [s390x] os: [linux] - '@esbuild/linux-x64@0.24.2': - resolution: {integrity: sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==} + '@esbuild/linux-x64@0.25.1': + resolution: {integrity: sha512-xbfUhu/gnvSEg+EGovRc+kjBAkrvtk38RlerAzQxvMzlB4fXpCFCeUAYzJvrnhFtdeyVCDANSjJvOvGYoeKzFA==} engines: {node: '>=18'} cpu: [x64] os: [linux] - '@esbuild/netbsd-arm64@0.24.2': - resolution: {integrity: sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==} + '@esbuild/netbsd-arm64@0.25.1': + resolution: {integrity: sha512-O96poM2XGhLtpTh+s4+nP7YCCAfb4tJNRVZHfIE7dgmax+yMP2WgMd2OecBuaATHKTHsLWHQeuaxMRnCsH8+5g==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-x64@0.24.2': - resolution: {integrity: sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==} + '@esbuild/netbsd-x64@0.25.1': + resolution: {integrity: sha512-X53z6uXip6KFXBQ+Krbx25XHV/NCbzryM6ehOAeAil7X7oa4XIq+394PWGnwaSQ2WRA0KI6PUO6hTO5zeF5ijA==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] - '@esbuild/openbsd-arm64@0.24.2': - resolution: {integrity: sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==} + '@esbuild/openbsd-arm64@0.25.1': + resolution: {integrity: sha512-Na9T3szbXezdzM/Kfs3GcRQNjHzM6GzFBeU1/6IV/npKP5ORtp9zbQjvkDJ47s6BCgaAZnnnu/cY1x342+MvZg==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-x64@0.24.2': - resolution: {integrity: sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==} + '@esbuild/openbsd-x64@0.25.1': + resolution: {integrity: sha512-T3H78X2h1tszfRSf+txbt5aOp/e7TAz3ptVKu9Oyir3IAOFPGV6O9c2naym5TOriy1l0nNf6a4X5UXRZSGX/dw==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] - '@esbuild/sunos-x64@0.24.2': - resolution: {integrity: sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==} + '@esbuild/sunos-x64@0.25.1': + resolution: {integrity: sha512-2H3RUvcmULO7dIE5EWJH8eubZAI4xw54H1ilJnRNZdeo8dTADEZ21w6J22XBkXqGJbe0+wnNJtw3UXRoLJnFEg==} engines: {node: '>=18'} cpu: [x64] os: [sunos] - '@esbuild/win32-arm64@0.24.2': - resolution: {integrity: sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==} + '@esbuild/win32-arm64@0.25.1': + resolution: {integrity: sha512-GE7XvrdOzrb+yVKB9KsRMq+7a2U/K5Cf/8grVFRAGJmfADr/e/ODQ134RK2/eeHqYV5eQRFxb1hY7Nr15fv1NQ==} engines: {node: '>=18'} cpu: [arm64] os: [win32] - '@esbuild/win32-ia32@0.24.2': - resolution: {integrity: sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==} + '@esbuild/win32-ia32@0.25.1': + resolution: {integrity: sha512-uOxSJCIcavSiT6UnBhBzE8wy3n0hOkJsBOzy7HDAuTDE++1DJMRRVCPGisULScHL+a/ZwdXPpXD3IyFKjA7K8A==} engines: {node: '>=18'} cpu: [ia32] os: [win32] - '@esbuild/win32-x64@0.24.2': - resolution: {integrity: sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==} + '@esbuild/win32-x64@0.25.1': + resolution: {integrity: sha512-Y1EQdcfwMSeQN/ujR5VayLOJ1BHaK+ssyk0AEzPjC+t1lITgsnccPqFjb6V+LsTp/9Iov4ysfjxLaGJ9RPtkVg==} engines: {node: '>=18'} cpu: [x64] os: [win32] - '@eslint-community/eslint-utils@4.4.1': - resolution: {integrity: sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==} + '@eslint-community/eslint-utils@4.5.1': + resolution: {integrity: sha512-soEIOALTfTK6EjmKMMoLugwaP0rzkad90iIWd1hMO9ARkSAyjfMfkRRhLvD5qH7vvM0Cg72pieUfR6yh6XxC4w==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 @@ -298,16 +298,20 @@ packages: resolution: {integrity: sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/config-helpers@0.2.0': + resolution: {integrity: sha512-yJLLmLexii32mGrhW29qvU3QBVTu0GUmEf/J4XsBtVhp4JkIUFN/BjWqTF63yRvGApIDpZm5fa97LtYtINmfeQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/core@0.12.0': resolution: {integrity: sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/eslintrc@3.3.0': - resolution: {integrity: sha512-yaVPAiNAalnCZedKLdR21GOGILMLKPyqSLWaAjQFvYA2i/ciDi8ArYVr69Anohb6cH2Ukhqti4aFnYyPm8wdwQ==} + '@eslint/eslintrc@3.3.1': + resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@9.21.0': - resolution: {integrity: sha512-BqStZ3HX8Yz6LvsF5ByXYrtigrV5AXADWLAGc7PH/1SxOb7/FIYYMszZZWiUou/GB9P2lXWk2SV4d+Z8h0nknw==} + '@eslint/js@9.23.0': + resolution: {integrity: sha512-35MJ8vCPU0ZMxo7zfev2pypqTwWTofFZO6m4KAtdoFhRpLJUpHTZZ+KB3C7Hb1d7bULYwO4lJXGCi5Se+8OMbw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/object-schema@2.1.6': @@ -368,98 +372,103 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} - '@rollup/rollup-android-arm-eabi@4.34.8': - resolution: {integrity: sha512-q217OSE8DTp8AFHuNHXo0Y86e1wtlfVrXiAlwkIvGRQv9zbc6mE3sjIVfwI8sYUyNxwOg0j/Vm1RKM04JcWLJw==} + '@rollup/rollup-android-arm-eabi@4.37.0': + resolution: {integrity: sha512-l7StVw6WAa8l3vA1ov80jyetOAEo1FtHvZDbzXDO/02Sq/QVvqlHkYoFwDJPIMj0GKiistsBudfx5tGFnwYWDQ==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.34.8': - resolution: {integrity: sha512-Gigjz7mNWaOL9wCggvoK3jEIUUbGul656opstjaUSGC3eT0BM7PofdAJaBfPFWWkXNVAXbaQtC99OCg4sJv70Q==} + '@rollup/rollup-android-arm64@4.37.0': + resolution: {integrity: sha512-6U3SlVyMxezt8Y+/iEBcbp945uZjJwjZimu76xoG7tO1av9VO691z8PkhzQ85ith2I8R2RddEPeSfcbyPfD4hA==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.34.8': - resolution: {integrity: sha512-02rVdZ5tgdUNRxIUrFdcMBZQoaPMrxtwSb+/hOfBdqkatYHR3lZ2A2EGyHq2sGOd0Owk80oV3snlDASC24He3Q==} + '@rollup/rollup-darwin-arm64@4.37.0': + resolution: {integrity: sha512-+iTQ5YHuGmPt10NTzEyMPbayiNTcOZDWsbxZYR1ZnmLnZxG17ivrPSWFO9j6GalY0+gV3Jtwrrs12DBscxnlYA==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.34.8': - resolution: {integrity: sha512-qIP/elwR/tq/dYRx3lgwK31jkZvMiD6qUtOycLhTzCvrjbZ3LjQnEM9rNhSGpbLXVJYQ3rq39A6Re0h9tU2ynw==} + '@rollup/rollup-darwin-x64@4.37.0': + resolution: {integrity: sha512-m8W2UbxLDcmRKVjgl5J/k4B8d7qX2EcJve3Sut7YGrQoPtCIQGPH5AMzuFvYRWZi0FVS0zEY4c8uttPfX6bwYQ==} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.34.8': - resolution: {integrity: sha512-IQNVXL9iY6NniYbTaOKdrlVP3XIqazBgJOVkddzJlqnCpRi/yAeSOa8PLcECFSQochzqApIOE1GHNu3pCz+BDA==} + '@rollup/rollup-freebsd-arm64@4.37.0': + resolution: {integrity: sha512-FOMXGmH15OmtQWEt174v9P1JqqhlgYge/bUjIbiVD1nI1NeJ30HYT9SJlZMqdo1uQFyt9cz748F1BHghWaDnVA==} cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.34.8': - resolution: {integrity: sha512-TYXcHghgnCqYFiE3FT5QwXtOZqDj5GmaFNTNt3jNC+vh22dc/ukG2cG+pi75QO4kACohZzidsq7yKTKwq/Jq7Q==} + '@rollup/rollup-freebsd-x64@4.37.0': + resolution: {integrity: sha512-SZMxNttjPKvV14Hjck5t70xS3l63sbVwl98g3FlVVx2YIDmfUIy29jQrsw06ewEYQ8lQSuY9mpAPlmgRD2iSsA==} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.34.8': - resolution: {integrity: sha512-A4iphFGNkWRd+5m3VIGuqHnG3MVnqKe7Al57u9mwgbyZ2/xF9Jio72MaY7xxh+Y87VAHmGQr73qoKL9HPbXj1g==} + '@rollup/rollup-linux-arm-gnueabihf@4.37.0': + resolution: {integrity: sha512-hhAALKJPidCwZcj+g+iN+38SIOkhK2a9bqtJR+EtyxrKKSt1ynCBeqrQy31z0oWU6thRZzdx53hVgEbRkuI19w==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.34.8': - resolution: {integrity: sha512-S0lqKLfTm5u+QTxlFiAnb2J/2dgQqRy/XvziPtDd1rKZFXHTyYLoVL58M/XFwDI01AQCDIevGLbQrMAtdyanpA==} + '@rollup/rollup-linux-arm-musleabihf@4.37.0': + resolution: {integrity: sha512-jUb/kmn/Gd8epbHKEqkRAxq5c2EwRt0DqhSGWjPFxLeFvldFdHQs/n8lQ9x85oAeVb6bHcS8irhTJX2FCOd8Ag==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.34.8': - resolution: {integrity: sha512-jpz9YOuPiSkL4G4pqKrus0pn9aYwpImGkosRKwNi+sJSkz+WU3anZe6hi73StLOQdfXYXC7hUfsQlTnjMd3s1A==} + '@rollup/rollup-linux-arm64-gnu@4.37.0': + resolution: {integrity: sha512-oNrJxcQT9IcbcmKlkF+Yz2tmOxZgG9D9GRq+1OE6XCQwCVwxixYAa38Z8qqPzQvzt1FCfmrHX03E0pWoXm1DqA==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.34.8': - resolution: {integrity: sha512-KdSfaROOUJXgTVxJNAZ3KwkRc5nggDk+06P6lgi1HLv1hskgvxHUKZ4xtwHkVYJ1Rep4GNo+uEfycCRRxht7+Q==} + '@rollup/rollup-linux-arm64-musl@4.37.0': + resolution: {integrity: sha512-pfxLBMls+28Ey2enpX3JvjEjaJMBX5XlPCZNGxj4kdJyHduPBXtxYeb8alo0a7bqOoWZW2uKynhHxF/MWoHaGQ==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-loongarch64-gnu@4.34.8': - resolution: {integrity: sha512-NyF4gcxwkMFRjgXBM6g2lkT58OWztZvw5KkV2K0qqSnUEqCVcqdh2jN4gQrTn/YUpAcNKyFHfoOZEer9nwo6uQ==} + '@rollup/rollup-linux-loongarch64-gnu@4.37.0': + resolution: {integrity: sha512-yCE0NnutTC/7IGUq/PUHmoeZbIwq3KRh02e9SfFh7Vmc1Z7atuJRYWhRME5fKgT8aS20mwi1RyChA23qSyRGpA==} cpu: [loong64] os: [linux] - '@rollup/rollup-linux-powerpc64le-gnu@4.34.8': - resolution: {integrity: sha512-LMJc999GkhGvktHU85zNTDImZVUCJ1z/MbAJTnviiWmmjyckP5aQsHtcujMjpNdMZPT2rQEDBlJfubhs3jsMfw==} + '@rollup/rollup-linux-powerpc64le-gnu@4.37.0': + resolution: {integrity: sha512-NxcICptHk06E2Lh3a4Pu+2PEdZ6ahNHuK7o6Np9zcWkrBMuv21j10SQDJW3C9Yf/A/P7cutWoC/DptNLVsZ0VQ==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.34.8': - resolution: {integrity: sha512-xAQCAHPj8nJq1PI3z8CIZzXuXCstquz7cIOL73HHdXiRcKk8Ywwqtx2wrIy23EcTn4aZ2fLJNBB8d0tQENPCmw==} + '@rollup/rollup-linux-riscv64-gnu@4.37.0': + resolution: {integrity: sha512-PpWwHMPCVpFZLTfLq7EWJWvrmEuLdGn1GMYcm5MV7PaRgwCEYJAwiN94uBuZev0/J/hFIIJCsYw4nLmXA9J7Pw==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.34.8': - resolution: {integrity: sha512-DdePVk1NDEuc3fOe3dPPTb+rjMtuFw89gw6gVWxQFAuEqqSdDKnrwzZHrUYdac7A7dXl9Q2Vflxpme15gUWQFA==} + '@rollup/rollup-linux-riscv64-musl@4.37.0': + resolution: {integrity: sha512-DTNwl6a3CfhGTAOYZ4KtYbdS8b+275LSLqJVJIrPa5/JuIufWWZ/QFvkxp52gpmguN95eujrM68ZG+zVxa8zHA==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.37.0': + resolution: {integrity: sha512-hZDDU5fgWvDdHFuExN1gBOhCuzo/8TMpidfOR+1cPZJflcEzXdCy1LjnklQdW8/Et9sryOPJAKAQRw8Jq7Tg+A==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.34.8': - resolution: {integrity: sha512-8y7ED8gjxITUltTUEJLQdgpbPh1sUQ0kMTmufRF/Ns5tI9TNMNlhWtmPKKHCU0SilX+3MJkZ0zERYYGIVBYHIA==} + '@rollup/rollup-linux-x64-gnu@4.37.0': + resolution: {integrity: sha512-pKivGpgJM5g8dwj0ywBwe/HeVAUSuVVJhUTa/URXjxvoyTT/AxsLTAbkHkDHG7qQxLoW2s3apEIl26uUe08LVQ==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.34.8': - resolution: {integrity: sha512-SCXcP0ZpGFIe7Ge+McxY5zKxiEI5ra+GT3QRxL0pMMtxPfpyLAKleZODi1zdRHkz5/BhueUrYtYVgubqe9JBNQ==} + '@rollup/rollup-linux-x64-musl@4.37.0': + resolution: {integrity: sha512-E2lPrLKE8sQbY/2bEkVTGDEk4/49UYRVWgj90MY8yPjpnGBQ+Xi1Qnr7b7UIWw1NOggdFQFOLZ8+5CzCiz143w==} cpu: [x64] os: [linux] - '@rollup/rollup-win32-arm64-msvc@4.34.8': - resolution: {integrity: sha512-YHYsgzZgFJzTRbth4h7Or0m5O74Yda+hLin0irAIobkLQFRQd1qWmnoVfwmKm9TXIZVAD0nZ+GEb2ICicLyCnQ==} + '@rollup/rollup-win32-arm64-msvc@4.37.0': + resolution: {integrity: sha512-Jm7biMazjNzTU4PrQtr7VS8ibeys9Pn29/1bm4ph7CP2kf21950LgN+BaE2mJ1QujnvOc6p54eWWiVvn05SOBg==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.34.8': - resolution: {integrity: sha512-r3NRQrXkHr4uWy5TOjTpTYojR9XmF0j/RYgKCef+Ag46FWUTltm5ziticv8LdNsDMehjJ543x/+TJAek/xBA2w==} + '@rollup/rollup-win32-ia32-msvc@4.37.0': + resolution: {integrity: sha512-e3/1SFm1OjefWICB2Ucstg2dxYDkDTZGDYgwufcbsxTHyqQps1UQf33dFEChBNmeSsTOyrjw2JJq0zbG5GF6RA==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.34.8': - resolution: {integrity: sha512-U0FaE5O1BCpZSeE6gBl3c5ObhePQSfk9vDRToMmTkbhCOgW4jqvtS5LGyQ76L1fH8sM0keRp4uDTsbjiUyjk0g==} + '@rollup/rollup-win32-x64-msvc@4.37.0': + resolution: {integrity: sha512-LWbXUBwn/bcLx2sSsqy7pK5o+Nr+VCoRoAohfJ5C/aBio9nfJmGQqHAhU6pwxV/RmyTk5AqdySma7uwWGlmeuA==} cpu: [x64] os: [win32] @@ -478,6 +487,9 @@ packages: '@types/estree@1.0.6': resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} + '@types/estree@1.0.7': + resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==} + '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} @@ -486,54 +498,54 @@ packages: peerDependencies: '@types/react': ^19.0.0 - '@types/react@19.0.10': - resolution: {integrity: sha512-JuRQ9KXLEjaUNjTWpzuR231Z2WpIwczOkBEIvbHNCzQefFIT0L8IqE6NV6ULLyC1SI/i234JnDoMkfg+RjQj2g==} + '@types/react@19.0.12': + resolution: {integrity: sha512-V6Ar115dBDrjbtXSrS+/Oruobc+qVbbUxDFC1RSbRqLt5SYvxxyIDrSC85RWml54g+jfNeEMZhEj7wW07ONQhA==} - '@typescript-eslint/eslint-plugin@8.25.0': - resolution: {integrity: sha512-VM7bpzAe7JO/BFf40pIT1lJqS/z1F8OaSsUB3rpFJucQA4cOSuH2RVVVkFULN+En0Djgr29/jb4EQnedUo95KA==} + '@typescript-eslint/eslint-plugin@8.28.0': + resolution: {integrity: sha512-lvFK3TCGAHsItNdWZ/1FkvpzCxTHUVuFrdnOGLMa0GGCFIbCgQWVk3CzCGdA7kM3qGVc+dfW9tr0Z/sHnGDFyg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' + typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/parser@8.25.0': - resolution: {integrity: sha512-4gbs64bnbSzu4FpgMiQ1A+D+urxkoJk/kqlDJ2W//5SygaEiAP2B4GoS7TEdxgwol2el03gckFV9lJ4QOMiiHg==} + '@typescript-eslint/parser@8.28.0': + resolution: {integrity: sha512-LPcw1yHD3ToaDEoljFEfQ9j2xShY367h7FZ1sq5NJT9I3yj4LHer1Xd1yRSOdYy9BpsrxU7R+eoDokChYM53lQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' + typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/scope-manager@8.25.0': - resolution: {integrity: sha512-6PPeiKIGbgStEyt4NNXa2ru5pMzQ8OYKO1hX1z53HMomrmiSB+R5FmChgQAP1ro8jMtNawz+TRQo/cSXrauTpg==} + '@typescript-eslint/scope-manager@8.28.0': + resolution: {integrity: sha512-u2oITX3BJwzWCapoZ/pXw6BCOl8rJP4Ij/3wPoGvY8XwvXflOzd1kLrDUUUAIEdJSFh+ASwdTHqtan9xSg8buw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/type-utils@8.25.0': - resolution: {integrity: sha512-d77dHgHWnxmXOPJuDWO4FDWADmGQkN5+tt6SFRZz/RtCWl4pHgFl3+WdYCn16+3teG09DY6XtEpf3gGD0a186g==} + '@typescript-eslint/type-utils@8.28.0': + resolution: {integrity: sha512-oRoXu2v0Rsy/VoOGhtWrOKDiIehvI+YNrDk5Oqj40Mwm0Yt01FC/Q7nFqg088d3yAsR1ZcZFVfPCTTFCe/KPwg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' + typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/types@8.25.0': - resolution: {integrity: sha512-+vUe0Zb4tkNgznQwicsvLUJgZIRs6ITeWSCclX1q85pR1iOiaj+4uZJIUp//Z27QWu5Cseiw3O3AR8hVpax7Aw==} + '@typescript-eslint/types@8.28.0': + resolution: {integrity: sha512-bn4WS1bkKEjx7HqiwG2JNB3YJdC1q6Ue7GyGlwPHyt0TnVq6TtD/hiOdTZt71sq0s7UzqBFXD8t8o2e63tXgwA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.25.0': - resolution: {integrity: sha512-ZPaiAKEZ6Blt/TPAx5Ot0EIB/yGtLI2EsGoY6F7XKklfMxYQyvtL+gT/UCqkMzO0BVFHLDlzvFqQzurYahxv9Q==} + '@typescript-eslint/typescript-estree@8.28.0': + resolution: {integrity: sha512-H74nHEeBGeklctAVUvmDkxB1mk+PAZ9FiOMPFncdqeRBXxk1lWSYraHw8V12b7aa6Sg9HOBNbGdSHobBPuQSuA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: '>=4.8.4 <5.8.0' + typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/utils@8.25.0': - resolution: {integrity: sha512-syqRbrEv0J1wywiLsK60XzHnQe/kRViI3zwFALrNEgnntn1l24Ra2KvOAWwWbWZ1lBZxZljPDGOq967dsl6fkA==} + '@typescript-eslint/utils@8.28.0': + resolution: {integrity: sha512-OELa9hbTYciYITqgurT1u/SzpQVtDLmQMFzy/N8pQE+tefOyCWT79jHsav294aTqV1q1u+VzqDGbuujvRYaeSQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' + typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/visitor-keys@8.25.0': - resolution: {integrity: sha512-kCYXKAum9CecGVHGij7muybDfTS2sD3t0L4bJsEZLkyrXUImiCTq1M3LG2SRtOhiHFwMR9wAFplpT6XHYjTkwQ==} + '@typescript-eslint/visitor-keys@8.28.0': + resolution: {integrity: sha512-hbn8SZ8w4u2pRwgQ1GlUrPKE+t2XvcCW5tTRF7j6SMYIuYG37XuzIW44JCZPa36evi0Oy2SnM664BlIaAuQcvg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@vitejs/plugin-react@4.3.4': @@ -547,8 +559,8 @@ packages: peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - acorn@8.14.0: - resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==} + acorn@8.14.1: + resolution: {integrity: sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==} engines: {node: '>=0.4.0'} hasBin: true @@ -584,8 +596,8 @@ packages: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} - caniuse-lite@1.0.30001700: - resolution: {integrity: sha512-2S6XIXwaE7K7erT8dY+kLQcpa5ms63XlRkMkReXjle+kf6c5g38vyMl+Z5y8dSxOFDhcFe+nxnn261PLxBSQsQ==} + caniuse-lite@1.0.30001707: + resolution: {integrity: sha512-3qtRjw/HQSMlDWf+X79N206fepf4SOOU6SQLMaq/0KkZLmSjPxAkBOQQ+FxbHKfHmYLZFfdWsO3KA90ceHPSnw==} chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} @@ -623,11 +635,11 @@ packages: deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - electron-to-chromium@1.5.104: - resolution: {integrity: sha512-Us9M2L4cO/zMBqVkJtnj353nQhMju9slHm62NprKTmdF3HH8wYOtNvDFq/JB2+ZRoGLzdvYDiATlMHs98XBM1g==} + electron-to-chromium@1.5.123: + resolution: {integrity: sha512-refir3NlutEZqlKaBLK0tzlVLe5P2wDKS7UQt/3SpibizgsRAPOsqQC3ffw1nlv3ze5gjRQZYHoPymgVZkplFA==} - esbuild@0.24.2: - resolution: {integrity: sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==} + esbuild@0.25.1: + resolution: {integrity: sha512-BGO5LtrGC7vxnqucAe/rmvKdJllfGaYWdyABvyMoXQlfYMb2bbRuReWR5tEGE//4LcNJj9XrkovTqNYRFZHAMQ==} engines: {node: '>=18'} hasBin: true @@ -639,8 +651,8 @@ packages: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} - eslint-plugin-react-hooks@5.1.0: - resolution: {integrity: sha512-mpJRtPgHN2tNAvZ35AMfqeB3Xqeo273QxrHJsbBEPWODRM4r0yB6jfoROqKEYrOn27UtRPpcpHc2UqyBSuUNTw==} + eslint-plugin-react-hooks@5.2.0: + resolution: {integrity: sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==} engines: {node: '>=10'} peerDependencies: eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 @@ -650,8 +662,8 @@ packages: peerDependencies: eslint: '>=8.40' - eslint-scope@8.2.0: - resolution: {integrity: sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==} + eslint-scope@8.3.0: + resolution: {integrity: sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} eslint-visitor-keys@3.4.3: @@ -662,8 +674,8 @@ packages: resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint@9.21.0: - resolution: {integrity: sha512-KjeihdFqTPhOMXTt7StsDxriV4n66ueuF/jfPNC3j/lduHwr/ijDwJMsF+wyMJethgiKi5wniIE243vi07d3pg==} + eslint@9.23.0: + resolution: {integrity: sha512-jV7AbNoFPAY1EkFYpLq5bslU9NLNO8xnEeQXwErNibVryjk67wHVmddTBilc5srIttJDBrB0eMHKZBFbSIABCw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true peerDependencies: @@ -705,8 +717,8 @@ packages: fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - fastq@1.19.0: - resolution: {integrity: sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA==} + fastq@1.19.1: + resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} file-entry-cache@8.0.0: resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} @@ -851,8 +863,8 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - nanoid@3.3.8: - resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==} + nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true @@ -925,12 +937,12 @@ packages: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} - reusify@1.0.4: - resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + reusify@1.1.0: + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - rollup@4.34.8: - resolution: {integrity: sha512-489gTVMzAYdiZHFVA/ig/iYFllCcWFHMvUHI1rpFmkoUtRlQxqh6/yiNqnYibjMZ2b/+FUQwldG+aLsEt6bglQ==} + rollup@4.37.0: + resolution: {integrity: sha512-iAtQy/L4QFU+rTJ1YUjXqJOJzuwEghqWzCEYD2FEghT7Gsy1VdABntrO4CLopA5IkflTyqNiLNwPcOJ3S7UKLg==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -973,8 +985,8 @@ packages: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} - ts-api-utils@2.0.1: - resolution: {integrity: sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w==} + ts-api-utils@2.1.0: + resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==} engines: {node: '>=18.12'} peerDependencies: typescript: '>=4.8.4' @@ -983,20 +995,20 @@ packages: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} - typescript-eslint@8.25.0: - resolution: {integrity: sha512-TxRdQQLH4g7JkoFlYG3caW5v1S6kEkz8rqt80iQJZUYPq1zD1Ra7HfQBJJ88ABRaMvHAXnwRvRB4V+6sQ9xN5Q==} + typescript-eslint@8.28.0: + resolution: {integrity: sha512-jfZtxJoHm59bvoCMYCe2BM0/baMswRhMmYhy+w6VfcyHrjxZ0OJe0tGasydCpIpA+A/WIJhTyZfb3EtwNC/kHQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' + typescript: '>=4.8.4 <5.9.0' - typescript@5.7.3: - resolution: {integrity: sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==} + typescript@5.8.2: + resolution: {integrity: sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==} engines: {node: '>=14.17'} hasBin: true - update-browserslist-db@1.1.2: - resolution: {integrity: sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==} + update-browserslist-db@1.1.3: + resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} hasBin: true peerDependencies: browserslist: '>= 4.21.0' @@ -1004,8 +1016,8 @@ packages: uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - vite@6.1.1: - resolution: {integrity: sha512-4GgM54XrwRfrOp297aIYspIti66k56v16ZnqHvrIM7mG+HjDlAwS7p+Srr7J6fGvEdOJ5JcQ/D9T7HhtdXDTzA==} + vite@6.2.3: + resolution: {integrity: sha512-IzwM54g4y9JA/xAeBPNaDXiBF8Jsgl3VBQ2YQ/wOY6fyW3xMdSoltIV3Bo59DErdqdE6RxUfv8W69DvUorE4Eg==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true peerDependencies: @@ -1075,18 +1087,18 @@ snapshots: '@babel/compat-data@7.26.8': {} - '@babel/core@7.26.9': + '@babel/core@7.26.10': dependencies: '@ampproject/remapping': 2.3.0 '@babel/code-frame': 7.26.2 - '@babel/generator': 7.26.9 - '@babel/helper-compilation-targets': 7.26.5 - '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.9) - '@babel/helpers': 7.26.9 - '@babel/parser': 7.26.9 - '@babel/template': 7.26.9 - '@babel/traverse': 7.26.9 - '@babel/types': 7.26.9 + '@babel/generator': 7.27.0 + '@babel/helper-compilation-targets': 7.27.0 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.10) + '@babel/helpers': 7.27.0 + '@babel/parser': 7.27.0 + '@babel/template': 7.27.0 + '@babel/traverse': 7.27.0 + '@babel/types': 7.27.0 convert-source-map: 2.0.0 debug: 4.4.0 gensync: 1.0.0-beta.2 @@ -1095,15 +1107,15 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/generator@7.26.9': + '@babel/generator@7.27.0': dependencies: - '@babel/parser': 7.26.9 - '@babel/types': 7.26.9 + '@babel/parser': 7.27.0 + '@babel/types': 7.27.0 '@jridgewell/gen-mapping': 0.3.8 '@jridgewell/trace-mapping': 0.3.25 jsesc: 3.1.0 - '@babel/helper-compilation-targets@7.26.5': + '@babel/helper-compilation-targets@7.27.0': dependencies: '@babel/compat-data': 7.26.8 '@babel/helper-validator-option': 7.25.9 @@ -1113,17 +1125,17 @@ snapshots: '@babel/helper-module-imports@7.25.9': dependencies: - '@babel/traverse': 7.26.9 - '@babel/types': 7.26.9 + '@babel/traverse': 7.27.0 + '@babel/types': 7.27.0 transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.26.0(@babel/core@7.26.9)': + '@babel/helper-module-transforms@7.26.0(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.9 + '@babel/core': 7.26.10 '@babel/helper-module-imports': 7.25.9 '@babel/helper-validator-identifier': 7.25.9 - '@babel/traverse': 7.26.9 + '@babel/traverse': 7.27.0 transitivePeerDependencies: - supports-color @@ -1135,126 +1147,126 @@ snapshots: '@babel/helper-validator-option@7.25.9': {} - '@babel/helpers@7.26.9': + '@babel/helpers@7.27.0': dependencies: - '@babel/template': 7.26.9 - '@babel/types': 7.26.9 + '@babel/template': 7.27.0 + '@babel/types': 7.27.0 - '@babel/parser@7.26.9': + '@babel/parser@7.27.0': dependencies: - '@babel/types': 7.26.9 + '@babel/types': 7.27.0 - '@babel/plugin-transform-react-jsx-self@7.25.9(@babel/core@7.26.9)': + '@babel/plugin-transform-react-jsx-self@7.25.9(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.9 + '@babel/core': 7.26.10 '@babel/helper-plugin-utils': 7.26.5 - '@babel/plugin-transform-react-jsx-source@7.25.9(@babel/core@7.26.9)': + '@babel/plugin-transform-react-jsx-source@7.25.9(@babel/core@7.26.10)': dependencies: - '@babel/core': 7.26.9 + '@babel/core': 7.26.10 '@babel/helper-plugin-utils': 7.26.5 - '@babel/template@7.26.9': + '@babel/template@7.27.0': dependencies: '@babel/code-frame': 7.26.2 - '@babel/parser': 7.26.9 - '@babel/types': 7.26.9 + '@babel/parser': 7.27.0 + '@babel/types': 7.27.0 - '@babel/traverse@7.26.9': + '@babel/traverse@7.27.0': dependencies: '@babel/code-frame': 7.26.2 - '@babel/generator': 7.26.9 - '@babel/parser': 7.26.9 - '@babel/template': 7.26.9 - '@babel/types': 7.26.9 + '@babel/generator': 7.27.0 + '@babel/parser': 7.27.0 + '@babel/template': 7.27.0 + '@babel/types': 7.27.0 debug: 4.4.0 globals: 11.12.0 transitivePeerDependencies: - supports-color - '@babel/types@7.26.9': + '@babel/types@7.27.0': dependencies: '@babel/helper-string-parser': 7.25.9 '@babel/helper-validator-identifier': 7.25.9 - '@esbuild/aix-ppc64@0.24.2': + '@esbuild/aix-ppc64@0.25.1': optional: true - '@esbuild/android-arm64@0.24.2': + '@esbuild/android-arm64@0.25.1': optional: true - '@esbuild/android-arm@0.24.2': + '@esbuild/android-arm@0.25.1': optional: true - '@esbuild/android-x64@0.24.2': + '@esbuild/android-x64@0.25.1': optional: true - '@esbuild/darwin-arm64@0.24.2': + '@esbuild/darwin-arm64@0.25.1': optional: true - '@esbuild/darwin-x64@0.24.2': + '@esbuild/darwin-x64@0.25.1': optional: true - '@esbuild/freebsd-arm64@0.24.2': + '@esbuild/freebsd-arm64@0.25.1': optional: true - '@esbuild/freebsd-x64@0.24.2': + '@esbuild/freebsd-x64@0.25.1': optional: true - '@esbuild/linux-arm64@0.24.2': + '@esbuild/linux-arm64@0.25.1': optional: true - '@esbuild/linux-arm@0.24.2': + '@esbuild/linux-arm@0.25.1': optional: true - '@esbuild/linux-ia32@0.24.2': + '@esbuild/linux-ia32@0.25.1': optional: true - '@esbuild/linux-loong64@0.24.2': + '@esbuild/linux-loong64@0.25.1': optional: true - '@esbuild/linux-mips64el@0.24.2': + '@esbuild/linux-mips64el@0.25.1': optional: true - '@esbuild/linux-ppc64@0.24.2': + '@esbuild/linux-ppc64@0.25.1': optional: true - '@esbuild/linux-riscv64@0.24.2': + '@esbuild/linux-riscv64@0.25.1': optional: true - '@esbuild/linux-s390x@0.24.2': + '@esbuild/linux-s390x@0.25.1': optional: true - '@esbuild/linux-x64@0.24.2': + '@esbuild/linux-x64@0.25.1': optional: true - '@esbuild/netbsd-arm64@0.24.2': + '@esbuild/netbsd-arm64@0.25.1': optional: true - '@esbuild/netbsd-x64@0.24.2': + '@esbuild/netbsd-x64@0.25.1': optional: true - '@esbuild/openbsd-arm64@0.24.2': + '@esbuild/openbsd-arm64@0.25.1': optional: true - '@esbuild/openbsd-x64@0.24.2': + '@esbuild/openbsd-x64@0.25.1': optional: true - '@esbuild/sunos-x64@0.24.2': + '@esbuild/sunos-x64@0.25.1': optional: true - '@esbuild/win32-arm64@0.24.2': + '@esbuild/win32-arm64@0.25.1': optional: true - '@esbuild/win32-ia32@0.24.2': + '@esbuild/win32-ia32@0.25.1': optional: true - '@esbuild/win32-x64@0.24.2': + '@esbuild/win32-x64@0.25.1': optional: true - '@eslint-community/eslint-utils@4.4.1(eslint@9.21.0)': + '@eslint-community/eslint-utils@4.5.1(eslint@9.23.0)': dependencies: - eslint: 9.21.0 + eslint: 9.23.0 eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.1': {} @@ -1267,11 +1279,13 @@ snapshots: transitivePeerDependencies: - supports-color + '@eslint/config-helpers@0.2.0': {} + '@eslint/core@0.12.0': dependencies: '@types/json-schema': 7.0.15 - '@eslint/eslintrc@3.3.0': + '@eslint/eslintrc@3.3.1': dependencies: ajv: 6.12.6 debug: 4.4.0 @@ -1285,7 +1299,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/js@9.21.0': {} + '@eslint/js@9.23.0': {} '@eslint/object-schema@2.1.6': {} @@ -1334,191 +1348,196 @@ snapshots: '@nodelib/fs.walk@1.2.8': dependencies: '@nodelib/fs.scandir': 2.1.5 - fastq: 1.19.0 + fastq: 1.19.1 - '@rollup/rollup-android-arm-eabi@4.34.8': + '@rollup/rollup-android-arm-eabi@4.37.0': optional: true - '@rollup/rollup-android-arm64@4.34.8': + '@rollup/rollup-android-arm64@4.37.0': optional: true - '@rollup/rollup-darwin-arm64@4.34.8': + '@rollup/rollup-darwin-arm64@4.37.0': optional: true - '@rollup/rollup-darwin-x64@4.34.8': + '@rollup/rollup-darwin-x64@4.37.0': optional: true - '@rollup/rollup-freebsd-arm64@4.34.8': + '@rollup/rollup-freebsd-arm64@4.37.0': optional: true - '@rollup/rollup-freebsd-x64@4.34.8': + '@rollup/rollup-freebsd-x64@4.37.0': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.34.8': + '@rollup/rollup-linux-arm-gnueabihf@4.37.0': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.34.8': + '@rollup/rollup-linux-arm-musleabihf@4.37.0': optional: true - '@rollup/rollup-linux-arm64-gnu@4.34.8': + '@rollup/rollup-linux-arm64-gnu@4.37.0': optional: true - '@rollup/rollup-linux-arm64-musl@4.34.8': + '@rollup/rollup-linux-arm64-musl@4.37.0': optional: true - '@rollup/rollup-linux-loongarch64-gnu@4.34.8': + '@rollup/rollup-linux-loongarch64-gnu@4.37.0': optional: true - '@rollup/rollup-linux-powerpc64le-gnu@4.34.8': + '@rollup/rollup-linux-powerpc64le-gnu@4.37.0': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.34.8': + '@rollup/rollup-linux-riscv64-gnu@4.37.0': optional: true - '@rollup/rollup-linux-s390x-gnu@4.34.8': + '@rollup/rollup-linux-riscv64-musl@4.37.0': optional: true - '@rollup/rollup-linux-x64-gnu@4.34.8': + '@rollup/rollup-linux-s390x-gnu@4.37.0': optional: true - '@rollup/rollup-linux-x64-musl@4.34.8': + '@rollup/rollup-linux-x64-gnu@4.37.0': optional: true - '@rollup/rollup-win32-arm64-msvc@4.34.8': + '@rollup/rollup-linux-x64-musl@4.37.0': optional: true - '@rollup/rollup-win32-ia32-msvc@4.34.8': + '@rollup/rollup-win32-arm64-msvc@4.37.0': optional: true - '@rollup/rollup-win32-x64-msvc@4.34.8': + '@rollup/rollup-win32-ia32-msvc@4.37.0': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.37.0': optional: true '@types/babel__core@7.20.5': dependencies: - '@babel/parser': 7.26.9 - '@babel/types': 7.26.9 + '@babel/parser': 7.27.0 + '@babel/types': 7.27.0 '@types/babel__generator': 7.6.8 '@types/babel__template': 7.4.4 '@types/babel__traverse': 7.20.6 '@types/babel__generator@7.6.8': dependencies: - '@babel/types': 7.26.9 + '@babel/types': 7.27.0 '@types/babel__template@7.4.4': dependencies: - '@babel/parser': 7.26.9 - '@babel/types': 7.26.9 + '@babel/parser': 7.27.0 + '@babel/types': 7.27.0 '@types/babel__traverse@7.20.6': dependencies: - '@babel/types': 7.26.9 + '@babel/types': 7.27.0 '@types/estree@1.0.6': {} + '@types/estree@1.0.7': {} + '@types/json-schema@7.0.15': {} - '@types/react-dom@19.0.4(@types/react@19.0.10)': + '@types/react-dom@19.0.4(@types/react@19.0.12)': dependencies: - '@types/react': 19.0.10 + '@types/react': 19.0.12 - '@types/react@19.0.10': + '@types/react@19.0.12': dependencies: csstype: 3.1.3 - '@typescript-eslint/eslint-plugin@8.25.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0)(typescript@5.7.3))(eslint@9.21.0)(typescript@5.7.3)': + '@typescript-eslint/eslint-plugin@8.28.0(@typescript-eslint/parser@8.28.0(eslint@9.23.0)(typescript@5.8.2))(eslint@9.23.0)(typescript@5.8.2)': dependencies: '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.25.0(eslint@9.21.0)(typescript@5.7.3) - '@typescript-eslint/scope-manager': 8.25.0 - '@typescript-eslint/type-utils': 8.25.0(eslint@9.21.0)(typescript@5.7.3) - '@typescript-eslint/utils': 8.25.0(eslint@9.21.0)(typescript@5.7.3) - '@typescript-eslint/visitor-keys': 8.25.0 - eslint: 9.21.0 + '@typescript-eslint/parser': 8.28.0(eslint@9.23.0)(typescript@5.8.2) + '@typescript-eslint/scope-manager': 8.28.0 + '@typescript-eslint/type-utils': 8.28.0(eslint@9.23.0)(typescript@5.8.2) + '@typescript-eslint/utils': 8.28.0(eslint@9.23.0)(typescript@5.8.2) + '@typescript-eslint/visitor-keys': 8.28.0 + eslint: 9.23.0 graphemer: 1.4.0 ignore: 5.3.2 natural-compare: 1.4.0 - ts-api-utils: 2.0.1(typescript@5.7.3) - typescript: 5.7.3 + ts-api-utils: 2.1.0(typescript@5.8.2) + typescript: 5.8.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.25.0(eslint@9.21.0)(typescript@5.7.3)': + '@typescript-eslint/parser@8.28.0(eslint@9.23.0)(typescript@5.8.2)': dependencies: - '@typescript-eslint/scope-manager': 8.25.0 - '@typescript-eslint/types': 8.25.0 - '@typescript-eslint/typescript-estree': 8.25.0(typescript@5.7.3) - '@typescript-eslint/visitor-keys': 8.25.0 + '@typescript-eslint/scope-manager': 8.28.0 + '@typescript-eslint/types': 8.28.0 + '@typescript-eslint/typescript-estree': 8.28.0(typescript@5.8.2) + '@typescript-eslint/visitor-keys': 8.28.0 debug: 4.4.0 - eslint: 9.21.0 - typescript: 5.7.3 + eslint: 9.23.0 + typescript: 5.8.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.25.0': + '@typescript-eslint/scope-manager@8.28.0': dependencies: - '@typescript-eslint/types': 8.25.0 - '@typescript-eslint/visitor-keys': 8.25.0 + '@typescript-eslint/types': 8.28.0 + '@typescript-eslint/visitor-keys': 8.28.0 - '@typescript-eslint/type-utils@8.25.0(eslint@9.21.0)(typescript@5.7.3)': + '@typescript-eslint/type-utils@8.28.0(eslint@9.23.0)(typescript@5.8.2)': dependencies: - '@typescript-eslint/typescript-estree': 8.25.0(typescript@5.7.3) - '@typescript-eslint/utils': 8.25.0(eslint@9.21.0)(typescript@5.7.3) + '@typescript-eslint/typescript-estree': 8.28.0(typescript@5.8.2) + '@typescript-eslint/utils': 8.28.0(eslint@9.23.0)(typescript@5.8.2) debug: 4.4.0 - eslint: 9.21.0 - ts-api-utils: 2.0.1(typescript@5.7.3) - typescript: 5.7.3 + eslint: 9.23.0 + ts-api-utils: 2.1.0(typescript@5.8.2) + typescript: 5.8.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.25.0': {} + '@typescript-eslint/types@8.28.0': {} - '@typescript-eslint/typescript-estree@8.25.0(typescript@5.7.3)': + '@typescript-eslint/typescript-estree@8.28.0(typescript@5.8.2)': dependencies: - '@typescript-eslint/types': 8.25.0 - '@typescript-eslint/visitor-keys': 8.25.0 + '@typescript-eslint/types': 8.28.0 + '@typescript-eslint/visitor-keys': 8.28.0 debug: 4.4.0 fast-glob: 3.3.3 is-glob: 4.0.3 minimatch: 9.0.5 semver: 7.7.1 - ts-api-utils: 2.0.1(typescript@5.7.3) - typescript: 5.7.3 + ts-api-utils: 2.1.0(typescript@5.8.2) + typescript: 5.8.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.25.0(eslint@9.21.0)(typescript@5.7.3)': + '@typescript-eslint/utils@8.28.0(eslint@9.23.0)(typescript@5.8.2)': dependencies: - '@eslint-community/eslint-utils': 4.4.1(eslint@9.21.0) - '@typescript-eslint/scope-manager': 8.25.0 - '@typescript-eslint/types': 8.25.0 - '@typescript-eslint/typescript-estree': 8.25.0(typescript@5.7.3) - eslint: 9.21.0 - typescript: 5.7.3 + '@eslint-community/eslint-utils': 4.5.1(eslint@9.23.0) + '@typescript-eslint/scope-manager': 8.28.0 + '@typescript-eslint/types': 8.28.0 + '@typescript-eslint/typescript-estree': 8.28.0(typescript@5.8.2) + eslint: 9.23.0 + typescript: 5.8.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.25.0': + '@typescript-eslint/visitor-keys@8.28.0': dependencies: - '@typescript-eslint/types': 8.25.0 + '@typescript-eslint/types': 8.28.0 eslint-visitor-keys: 4.2.0 - '@vitejs/plugin-react@4.3.4(vite@6.1.1)': + '@vitejs/plugin-react@4.3.4(vite@6.2.3)': dependencies: - '@babel/core': 7.26.9 - '@babel/plugin-transform-react-jsx-self': 7.25.9(@babel/core@7.26.9) - '@babel/plugin-transform-react-jsx-source': 7.25.9(@babel/core@7.26.9) + '@babel/core': 7.26.10 + '@babel/plugin-transform-react-jsx-self': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-transform-react-jsx-source': 7.25.9(@babel/core@7.26.10) '@types/babel__core': 7.20.5 react-refresh: 0.14.2 - vite: 6.1.1 + vite: 6.2.3 transitivePeerDependencies: - supports-color - acorn-jsx@5.3.2(acorn@8.14.0): + acorn-jsx@5.3.2(acorn@8.14.1): dependencies: - acorn: 8.14.0 + acorn: 8.14.1 - acorn@8.14.0: {} + acorn@8.14.1: {} ajv@6.12.6: dependencies: @@ -1550,14 +1569,14 @@ snapshots: browserslist@4.24.4: dependencies: - caniuse-lite: 1.0.30001700 - electron-to-chromium: 1.5.104 + caniuse-lite: 1.0.30001707 + electron-to-chromium: 1.5.123 node-releases: 2.0.19 - update-browserslist-db: 1.1.2(browserslist@4.24.4) + update-browserslist-db: 1.1.3(browserslist@4.24.4) callsites@3.1.0: {} - caniuse-lite@1.0.30001700: {} + caniuse-lite@1.0.30001707: {} chalk@4.1.2: dependencies: @@ -1588,49 +1607,49 @@ snapshots: deep-is@0.1.4: {} - electron-to-chromium@1.5.104: {} + electron-to-chromium@1.5.123: {} - esbuild@0.24.2: + esbuild@0.25.1: optionalDependencies: - '@esbuild/aix-ppc64': 0.24.2 - '@esbuild/android-arm': 0.24.2 - '@esbuild/android-arm64': 0.24.2 - '@esbuild/android-x64': 0.24.2 - '@esbuild/darwin-arm64': 0.24.2 - '@esbuild/darwin-x64': 0.24.2 - '@esbuild/freebsd-arm64': 0.24.2 - '@esbuild/freebsd-x64': 0.24.2 - '@esbuild/linux-arm': 0.24.2 - '@esbuild/linux-arm64': 0.24.2 - '@esbuild/linux-ia32': 0.24.2 - '@esbuild/linux-loong64': 0.24.2 - '@esbuild/linux-mips64el': 0.24.2 - '@esbuild/linux-ppc64': 0.24.2 - '@esbuild/linux-riscv64': 0.24.2 - '@esbuild/linux-s390x': 0.24.2 - '@esbuild/linux-x64': 0.24.2 - '@esbuild/netbsd-arm64': 0.24.2 - '@esbuild/netbsd-x64': 0.24.2 - '@esbuild/openbsd-arm64': 0.24.2 - '@esbuild/openbsd-x64': 0.24.2 - '@esbuild/sunos-x64': 0.24.2 - '@esbuild/win32-arm64': 0.24.2 - '@esbuild/win32-ia32': 0.24.2 - '@esbuild/win32-x64': 0.24.2 + '@esbuild/aix-ppc64': 0.25.1 + '@esbuild/android-arm': 0.25.1 + '@esbuild/android-arm64': 0.25.1 + '@esbuild/android-x64': 0.25.1 + '@esbuild/darwin-arm64': 0.25.1 + '@esbuild/darwin-x64': 0.25.1 + '@esbuild/freebsd-arm64': 0.25.1 + '@esbuild/freebsd-x64': 0.25.1 + '@esbuild/linux-arm': 0.25.1 + '@esbuild/linux-arm64': 0.25.1 + '@esbuild/linux-ia32': 0.25.1 + '@esbuild/linux-loong64': 0.25.1 + '@esbuild/linux-mips64el': 0.25.1 + '@esbuild/linux-ppc64': 0.25.1 + '@esbuild/linux-riscv64': 0.25.1 + '@esbuild/linux-s390x': 0.25.1 + '@esbuild/linux-x64': 0.25.1 + '@esbuild/netbsd-arm64': 0.25.1 + '@esbuild/netbsd-x64': 0.25.1 + '@esbuild/openbsd-arm64': 0.25.1 + '@esbuild/openbsd-x64': 0.25.1 + '@esbuild/sunos-x64': 0.25.1 + '@esbuild/win32-arm64': 0.25.1 + '@esbuild/win32-ia32': 0.25.1 + '@esbuild/win32-x64': 0.25.1 escalade@3.2.0: {} escape-string-regexp@4.0.0: {} - eslint-plugin-react-hooks@5.1.0(eslint@9.21.0): + eslint-plugin-react-hooks@5.2.0(eslint@9.23.0): dependencies: - eslint: 9.21.0 + eslint: 9.23.0 - eslint-plugin-react-refresh@0.4.19(eslint@9.21.0): + eslint-plugin-react-refresh@0.4.19(eslint@9.23.0): dependencies: - eslint: 9.21.0 + eslint: 9.23.0 - eslint-scope@8.2.0: + eslint-scope@8.3.0: dependencies: esrecurse: 4.3.0 estraverse: 5.3.0 @@ -1639,26 +1658,27 @@ snapshots: eslint-visitor-keys@4.2.0: {} - eslint@9.21.0: + eslint@9.23.0: dependencies: - '@eslint-community/eslint-utils': 4.4.1(eslint@9.21.0) + '@eslint-community/eslint-utils': 4.5.1(eslint@9.23.0) '@eslint-community/regexpp': 4.12.1 '@eslint/config-array': 0.19.2 + '@eslint/config-helpers': 0.2.0 '@eslint/core': 0.12.0 - '@eslint/eslintrc': 3.3.0 - '@eslint/js': 9.21.0 + '@eslint/eslintrc': 3.3.1 + '@eslint/js': 9.23.0 '@eslint/plugin-kit': 0.2.7 '@humanfs/node': 0.16.6 '@humanwhocodes/module-importer': 1.0.1 '@humanwhocodes/retry': 0.4.2 - '@types/estree': 1.0.6 + '@types/estree': 1.0.7 '@types/json-schema': 7.0.15 ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.6 debug: 4.4.0 escape-string-regexp: 4.0.0 - eslint-scope: 8.2.0 + eslint-scope: 8.3.0 eslint-visitor-keys: 4.2.0 espree: 10.3.0 esquery: 1.6.0 @@ -1680,8 +1700,8 @@ snapshots: espree@10.3.0: dependencies: - acorn: 8.14.0 - acorn-jsx: 5.3.2(acorn@8.14.0) + acorn: 8.14.1 + acorn-jsx: 5.3.2(acorn@8.14.1) eslint-visitor-keys: 4.2.0 esquery@1.6.0: @@ -1710,9 +1730,9 @@ snapshots: fast-levenshtein@2.0.6: {} - fastq@1.19.0: + fastq@1.19.1: dependencies: - reusify: 1.0.4 + reusify: 1.1.0 file-entry-cache@8.0.0: dependencies: @@ -1828,7 +1848,7 @@ snapshots: ms@2.1.3: {} - nanoid@3.3.8: {} + nanoid@3.3.11: {} natural-compare@1.4.0: {} @@ -1865,7 +1885,7 @@ snapshots: postcss@8.5.3: dependencies: - nanoid: 3.3.8 + nanoid: 3.3.11 picocolors: 1.1.1 source-map-js: 1.2.1 @@ -1886,31 +1906,32 @@ snapshots: resolve-from@4.0.0: {} - reusify@1.0.4: {} + reusify@1.1.0: {} - rollup@4.34.8: + rollup@4.37.0: dependencies: '@types/estree': 1.0.6 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.34.8 - '@rollup/rollup-android-arm64': 4.34.8 - '@rollup/rollup-darwin-arm64': 4.34.8 - '@rollup/rollup-darwin-x64': 4.34.8 - '@rollup/rollup-freebsd-arm64': 4.34.8 - '@rollup/rollup-freebsd-x64': 4.34.8 - '@rollup/rollup-linux-arm-gnueabihf': 4.34.8 - '@rollup/rollup-linux-arm-musleabihf': 4.34.8 - '@rollup/rollup-linux-arm64-gnu': 4.34.8 - '@rollup/rollup-linux-arm64-musl': 4.34.8 - '@rollup/rollup-linux-loongarch64-gnu': 4.34.8 - '@rollup/rollup-linux-powerpc64le-gnu': 4.34.8 - '@rollup/rollup-linux-riscv64-gnu': 4.34.8 - '@rollup/rollup-linux-s390x-gnu': 4.34.8 - '@rollup/rollup-linux-x64-gnu': 4.34.8 - '@rollup/rollup-linux-x64-musl': 4.34.8 - '@rollup/rollup-win32-arm64-msvc': 4.34.8 - '@rollup/rollup-win32-ia32-msvc': 4.34.8 - '@rollup/rollup-win32-x64-msvc': 4.34.8 + '@rollup/rollup-android-arm-eabi': 4.37.0 + '@rollup/rollup-android-arm64': 4.37.0 + '@rollup/rollup-darwin-arm64': 4.37.0 + '@rollup/rollup-darwin-x64': 4.37.0 + '@rollup/rollup-freebsd-arm64': 4.37.0 + '@rollup/rollup-freebsd-x64': 4.37.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.37.0 + '@rollup/rollup-linux-arm-musleabihf': 4.37.0 + '@rollup/rollup-linux-arm64-gnu': 4.37.0 + '@rollup/rollup-linux-arm64-musl': 4.37.0 + '@rollup/rollup-linux-loongarch64-gnu': 4.37.0 + '@rollup/rollup-linux-powerpc64le-gnu': 4.37.0 + '@rollup/rollup-linux-riscv64-gnu': 4.37.0 + '@rollup/rollup-linux-riscv64-musl': 4.37.0 + '@rollup/rollup-linux-s390x-gnu': 4.37.0 + '@rollup/rollup-linux-x64-gnu': 4.37.0 + '@rollup/rollup-linux-x64-musl': 4.37.0 + '@rollup/rollup-win32-arm64-msvc': 4.37.0 + '@rollup/rollup-win32-ia32-msvc': 4.37.0 + '@rollup/rollup-win32-x64-msvc': 4.37.0 fsevents: 2.3.3 run-parallel@1.2.0: @@ -1941,27 +1962,27 @@ snapshots: dependencies: is-number: 7.0.0 - ts-api-utils@2.0.1(typescript@5.7.3): + ts-api-utils@2.1.0(typescript@5.8.2): dependencies: - typescript: 5.7.3 + typescript: 5.8.2 type-check@0.4.0: dependencies: prelude-ls: 1.2.1 - typescript-eslint@8.25.0(eslint@9.21.0)(typescript@5.7.3): + typescript-eslint@8.28.0(eslint@9.23.0)(typescript@5.8.2): dependencies: - '@typescript-eslint/eslint-plugin': 8.25.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0)(typescript@5.7.3))(eslint@9.21.0)(typescript@5.7.3) - '@typescript-eslint/parser': 8.25.0(eslint@9.21.0)(typescript@5.7.3) - '@typescript-eslint/utils': 8.25.0(eslint@9.21.0)(typescript@5.7.3) - eslint: 9.21.0 - typescript: 5.7.3 + '@typescript-eslint/eslint-plugin': 8.28.0(@typescript-eslint/parser@8.28.0(eslint@9.23.0)(typescript@5.8.2))(eslint@9.23.0)(typescript@5.8.2) + '@typescript-eslint/parser': 8.28.0(eslint@9.23.0)(typescript@5.8.2) + '@typescript-eslint/utils': 8.28.0(eslint@9.23.0)(typescript@5.8.2) + eslint: 9.23.0 + typescript: 5.8.2 transitivePeerDependencies: - supports-color - typescript@5.7.3: {} + typescript@5.8.2: {} - update-browserslist-db@1.1.2(browserslist@4.24.4): + update-browserslist-db@1.1.3(browserslist@4.24.4): dependencies: browserslist: 4.24.4 escalade: 3.2.0 @@ -1971,11 +1992,11 @@ snapshots: dependencies: punycode: 2.3.1 - vite@6.1.1: + vite@6.2.3: dependencies: - esbuild: 0.24.2 + esbuild: 0.25.1 postcss: 8.5.3 - rollup: 4.34.8 + rollup: 4.37.0 optionalDependencies: fsevents: 2.3.3 diff --git a/src/App.css b/src/App.css index be887b6..c5862ea 100644 --- a/src/App.css +++ b/src/App.css @@ -45,9 +45,6 @@ height: 10000px; transform-origin: 0 0; background-color: white; - background-image: linear-gradient(#ddd 1px, transparent 1px), - linear-gradient(90deg, #ddd 1px, transparent 1px); - background-size: 100px 100px; } .target { @@ -126,4 +123,152 @@ body, .reset-button:hover { background: #fff5f5; border-color: #ef5350; +} + +/* Preset Selection */ +.preset-selection { + margin-bottom: 20px; +} + +.preset-buttons { + display: flex; + gap: 10px; + flex-wrap: wrap; +} + +.preset-button { + padding: 8px 16px; + background: white; + border: 1px solid #ddd; + border-radius: 8px; + cursor: pointer; + transition: all 0.2s ease; +} + +.preset-button.active { + background: #646cff; + color: white; + border-color: #646cff; +} + +.preset-button:hover:not(.active) { + background: #f5f5f5; + border-color: #646cff; +} + +/* Mode Selection */ +.mode-selection { + margin-bottom: 20px; +} + +.radio-group { + display: flex; + flex-direction: column; + gap: 10px; +} + +.radio-group label { + display: flex; + align-items: center; + gap: 8px; + cursor: pointer; +} + +/* Break Screen */ +.break-screen { + position: fixed; + top: 0; + left: 0; + width: 100vw; + height: 100vh; + background-color: rgba(0, 0, 0, 0.5); + display: flex; + justify-content: center; + align-items: center; + z-index: 2000; +} + +.break-container { + background-color: white; + padding: 30px; + border-radius: 10px; + box-shadow: 0 5px 20px rgba(0, 0, 0, 0.2); + max-width: 500px; + text-align: center; +} + +.break-container h2 { + margin-top: 0; + color: #213547; +} + +.break-container button { + margin-top: 20px; + padding: 10px 20px; + background-color: #646cff; + color: white; + border: none; + border-radius: 8px; + cursor: pointer; + font-size: 16px; + transition: all 0.2s; +} + +.break-container button:hover { + background-color: #4e57cc; +} + +/* Resize Warning Popup */ +.resize-warning { + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + z-index: 2000; + background-color: rgba(0, 0, 0, 0.5); + width: 100%; + height: 100%; + display: flex; + justify-content: center; + align-items: center; + animation: fadeIn 0.3s ease-out; +} + +.resize-warning-content { + background-color: white; + padding: 20px 30px; + border-radius: 10px; + box-shadow: 0 5px 20px rgba(0, 0, 0, 0.2); + max-width: 400px; + text-align: center; +} + +.resize-warning-content h3 { + margin-top: 0; + color: #213547; +} + +.resize-warning-content button { + margin-top: 15px; + padding: 8px 20px; + background-color: #646cff; + color: white; + border: none; + border-radius: 8px; + cursor: pointer; + font-size: 14px; + transition: all 0.2s; +} + +.resize-warning-content button:hover { + background-color: #4e57cc; +} + +@keyframes fadeIn { + from { + opacity: 0; + } + to { + opacity: 1; + } } \ No newline at end of file diff --git a/src/App.tsx b/src/App.tsx index f28b439..e077b14 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -10,6 +10,8 @@ import { AccelerationSettings, Round, CONSTANTS, + ZoomPreset, + AppMode, } from './types'; import { generateTargets, getRandomTarget } from './utils/target'; import { @@ -35,6 +37,13 @@ function App() { const [zoomLevel, setZoomLevel] = useState(CONSTANTS.ZOOM_LEVELS.default); const [stats, setStats] = useState(createInitialStats()); + // Study mode state + const [mode, setMode] = useState('freestyle'); + const [currentPreset, setCurrentPreset] = useState('A'); + const [presetsCompleted, setPresetsCompleted] = useState([]); + const [targetCount, setTargetCount] = useState(0); + const [studyComplete, setStudyComplete] = useState(false); + // Load settings from localStorage or use defaults const [settings, setSettings] = useState(() => { const savedState = loadState(); @@ -68,6 +77,9 @@ function App() { const touchStartDistance = useRef(0); const wasReset = useRef(false); + // Add a new state for the resize warning popup + const [showResizeWarning, setShowResizeWarning] = useState(false); + useEffect(() => { const savedState = loadState(); if (savedState?.stats) { @@ -96,9 +108,51 @@ function App() { const initialZoom = 0.2; setZoomLevel(initialZoom); setViewportOffset(calculateInitialViewport(initialZoom)); - setStats(previous => ({ ...previous, startTime: Date.now() })); + setStats(createInitialStats()); + + setTargetCount(0); + setPresetsCompleted([]); + setStudyComplete(false); }; + // Apply preset when it changes + useEffect(() => { + if (currentPreset) { + setSettings(prev => ({ + ...prev, + enabled: true, + preset: currentPreset, + accelerationCurve: [...CONSTANTS.PRESETS[currentPreset]] + })); + } + }, [currentPreset]); + + // Handle moving to next preset in study mode + useEffect(() => { + if (mode !== 'study') return; + + if (targetCount >= CONSTANTS.STUDY_TARGETS_PER_PRESET) { + // Add current preset to completed list + if (!presetsCompleted.includes(currentPreset)) { + setPresetsCompleted(prev => [...prev, currentPreset]); + } + + // Directly move to the next preset without showing break screen + const allPresets: ZoomPreset[] = ['A', 'B', 'C', 'D']; + const currentIndex = allPresets.indexOf(currentPreset); + + if (currentIndex < allPresets.length - 1) { + // Move to next preset + const nextPreset = allPresets[currentIndex + 1]; + setCurrentPreset(nextPreset); + setTargetCount(0); + } else { + // All presets completed + setStudyComplete(true); + } + } + }, [targetCount, currentPreset, mode, presetsCompleted]); + useEffect(() => { const container = containerRef.current; if (!container) return; @@ -115,6 +169,36 @@ function App() { const worldY = viewportOffset.y + cursorY / zoomLevel; const scrollAmount = processWheelDelta(-event.deltaY); + const now = Date.now(); + + // Determine zoom direction (positive scrollAmount = zoom in, negative = zoom out) + const direction = scrollAmount > 0 ? 'in' : 'out'; + + // Update zoom timing stats + setStats(previous => { + // If we're already zooming in the same direction, add to the time + if (previous.isZooming && previous.zoomDirection === direction && previous.lastZoomTime) { + const timeDelta = now - previous.lastZoomTime; + // Only count if it's a reasonable time (less than 500ms between events) + const shouldCount = timeDelta < 500; + + return { + ...previous, + lastZoomTime: now, + zoomInTime: previous.zoomInTime + (direction === 'in' && shouldCount ? timeDelta : 0), + zoomOutTime: previous.zoomOutTime + (direction === 'out' && shouldCount ? timeDelta : 0), + zoomDirection: direction + }; + } + + // Otherwise start new zoom tracking + return { + ...previous, + isZooming: true, + lastZoomTime: now, + zoomDirection: direction + }; + }); if (isFinite(scrollAmount)) { zoomSpeedSamples.current = updateWheelSamples(zoomSpeedSamples.current, scrollAmount); @@ -149,8 +233,29 @@ function App() { } }; + // Stop zoom timing when wheel events stop + const handleZoomEnd = () => { + setStats(previous => ({ + ...previous, + isZooming: false, + lastZoomTime: 0, + zoomDirection: null + })); + }; + container.addEventListener('wheel', handleWheelEvent, { passive: false }); - return () => container.removeEventListener('wheel', handleWheelEvent); + + // Add a listener to detect when zooming stops (after 300ms of no wheel events) + let zoomEndTimer: number; + container.addEventListener('wheel', () => { + clearTimeout(zoomEndTimer); + zoomEndTimer = window.setTimeout(handleZoomEnd, 300); + }); + + return () => { + container.removeEventListener('wheel', handleWheelEvent); + clearTimeout(zoomEndTimer); + }; }, [zoomLevel, viewportOffset, settings]); const handleTouchStart = (event: React.TouchEvent) => { @@ -210,7 +315,7 @@ function App() { }; const handleClick = (event: React.MouseEvent) => { - if (!containerRef.current || currentTarget === null) return; + if (!containerRef.current || currentTarget === null || studyComplete) return; // If this was a drag operation or very slow click (likely a drag attempt), ignore it if (isDragging.current || Date.now() - dragStartTime.current > 200) { @@ -228,14 +333,41 @@ function App() { if (distanceToTarget <= target.radius) { const timeElapsed = Date.now() - stats.startTime; - setRounds(previous => [...previous, createNewRound(timeElapsed, stats.misclicks, settings)]); + + // Create and save the round with zoom timing data + const newRound = createNewRound( + timeElapsed, + stats.misclicks, + { + ...settings, + preset: mode === 'study' ? currentPreset : settings.preset + }, + stats.zoomInTime, + stats.zoomOutTime + ); + + setRounds(previous => [...previous, newRound]); + + // Update stats and reset zoom timing data setStats({ startTime: Date.now(), misclicks: 0, targetsHit: stats.targetsHit + 1, times: [...stats.times, timeElapsed], + zoomInTime: 0, + zoomOutTime: 0, + lastZoomTime: 0, + isZooming: false, + zoomDirection: null }); + + // Set next target setCurrentTarget(getRandomTarget(currentTarget, CONSTANTS.TARGET_COUNT)); + + // If in study mode, increment target count + if (mode === 'study') { + setTargetCount(prev => prev + 1); + } } else { setStats(previous => ({ ...previous, @@ -249,80 +381,106 @@ function App() { setRounds([]); setStats(createInitialStats()); setSettings(createDefaultSettings()); - initializeGame(); wasReset.current = true; + initializeGame(); + + // Close any open panels + setShowSettings(false); + setShowRounds(false); + + // Show the initial instructions screen setShowInstructions(true); } }; + const handleModeChange = (newMode: AppMode) => { + // Reset data when changing modes + if (newMode !== mode) { + if (window.confirm('Changing modes will reset your current data. Continue?')) { + setMode(newMode); + setRounds([]); + setStats(createInitialStats()); + + // Reset study mode stats when changing modes + if (newMode === 'study') { + setTargetCount(0); + setPresetsCompleted([]); + setCurrentPreset('A'); + setStudyComplete(false); + } + + // Reset the game + initializeGame(); + } + } else { + setMode(newMode); + } + }; + + // Calculate average time + const averageTime = calculateAverageTime(stats.times); + + // Add a resize handler to regenerate targets when window size changes + useEffect(() => { + let resizeTimer: number; + + const handleResize = () => { + // Don't regenerate if in study mode to avoid disrupting the test + if (mode !== 'study') { + clearTimeout(resizeTimer); + + resizeTimer = window.setTimeout(() => { + const newTargets = generateTargets(); + setTargets(newTargets); + + // If we're targeting something, make sure it's still valid + if (currentTarget !== null) { + setCurrentTarget(getRandomTarget(currentTarget, CONSTANTS.TARGET_COUNT)); + } + + // Show resize warning + setShowResizeWarning(true); + }, 500); // Add a delay to detect when resizing is "done" + } + }; + + window.addEventListener('resize', handleResize); + return () => { + window.removeEventListener('resize', handleResize); + clearTimeout(resizeTimer); + }; + }, [currentTarget, mode]); + return (
-
- - - - - - - -
- - setShowSettings(false)} - /> - - setShowRounds(false)} - /> - - setShowInstructions(false)} - /> -
- Targets: {stats.targetsHit} • - Misclicks: {stats.misclicks} • - Avg Time: {calculateAverageTime(stats.times)} ms • - Zoom: {zoomLevel.toFixed(2)}x + + Targets hit: {stats.targetsHit} + + + Average time:{' '} + {averageTime ? `${averageTime.toFixed(2)}ms` : '-'} + + + Misclicks: {stats.misclicks} + + {mode === 'study' && ( + + Preset: {currentPreset} ({targetCount}/{CONSTANTS.STUDY_TARGETS_PER_PRESET}) + + )}
+ +
+ + + + +
+ + setShowSettings(false)} + /> + + setShowRounds(false)} + /> + + setShowInstructions(false)} + onModeSelect={handleModeChange} + /> + + {studyComplete && ( +
+
+

Study Complete!

+

You've completed all presets in the study (100 trials). Thank you for participating!

+

You can now export your data or continue experimenting in freestyle mode.

+
+ + +
+
+
+ )} + + {/* Resize warning popup */} + {showResizeWarning && ( +
+
+

Window Resized

+

Target positions have been reset to match your new window size.

+ +
+
+ )}
); } diff --git a/src/components/Instructions.css b/src/components/Instructions.css index 53c863f..ae50ae0 100644 --- a/src/components/Instructions.css +++ b/src/components/Instructions.css @@ -15,10 +15,12 @@ background: white; border-radius: 12px; padding: 30px; - max-width: 500px; + max-width: 600px; width: 90%; box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15); position: relative; + max-height: 90vh; + overflow-y: auto; } .instructions-header { @@ -39,6 +41,12 @@ line-height: 1.6; } +.instructions-content h3 { + margin-top: 25px; + margin-bottom: 15px; + color: #213547; +} + .instructions-content ul { padding-left: 20px; margin: 15px 0; @@ -63,6 +71,7 @@ cursor: pointer; font-weight: 500; transition: all 0.2s; + font-size: 16px; } .got-it-button:hover { @@ -77,4 +86,84 @@ border-radius: 4px; font-family: monospace; margin: 0 2px; +} + +/* Mode Selection Styles */ +.mode-selection { + background: #f8fafc; + padding: 20px; + border-radius: 8px; + margin: 20px 0; + border: 1px solid #e2e8f0; +} + +.mode-selection .radio-group { + display: flex; + flex-direction: column; + gap: 15px; +} + +.mode-selection label { + display: flex; + flex-direction: column; + padding: 15px; + border: 1px solid #e2e8f0; + border-radius: 8px; + background: white; + cursor: pointer; + transition: all 0.2s; + position: relative; +} + +.mode-selection label:hover { + border-color: #646cff; + box-shadow: 0 2px 8px rgba(100, 108, 255, 0.1); +} + +.mode-selection input[type="radio"] { + position: absolute; + top: 15px; + left: 15px; +} + +.mode-label { + font-weight: bold; + color: #213547; + margin-left: 25px; + font-size: 16px; +} + +.mode-description { + margin: 8px 0 0 25px; + color: #64748b; + font-size: 14px; +} + +.mode-selection input[type="radio"]:checked + .mode-label { + color: #646cff; +} + +.mode-selection input[type="radio"]:checked ~ .mode-description { + color: #4a5568; +} + +.warning-message { + background-color: #fff8e1; + border-left: 4px solid #ffb300; + padding: 15px; + border-radius: 4px; + margin: 20px 0; +} + +.warning-message h3 { + color: #e65100; + margin-top: 0; + margin-bottom: 10px; + display: flex; + align-items: center; +} + +.warning-message p { + margin: 0; + color: #333; } \ No newline at end of file diff --git a/src/components/Instructions.tsx b/src/components/Instructions.tsx index a4d416a..731c2cf 100644 --- a/src/components/Instructions.tsx +++ b/src/components/Instructions.tsx @@ -1,16 +1,29 @@ -import React from 'react'; +import React, { useState } from 'react'; +import { AppMode } from '../types'; import './Instructions.css'; interface InstructionsProps { visible: boolean; onClose: () => void; + onModeSelect: (mode: AppMode) => void; } -export const Instructions: React.FC = ({ visible, onClose }) => { +export const Instructions: React.FC = ({ + visible, + onClose, + onModeSelect +}) => { + const [selectedMode, setSelectedMode] = useState('freestyle'); + + const handleStart = () => { + onModeSelect(selectedMode); + onClose(); + }; + if (!visible) return null; return ( -
+
e.stopPropagation()}>

Welcome to ✨ ZoomAccel ✨!

@@ -21,6 +34,35 @@ export const Instructions: React.FC = ({ visible, onClose }) This is a simulation that measures target acquisition performance with different zoom acceleration curves.

+
+

Select Mode

+
+ + +
+
+ +

Instructions

  • Click the green targets as quickly and accurately as possible @@ -39,14 +81,22 @@ export const Instructions: React.FC = ({ visible, onClose })
+
+

⚠️ Important

+

+ Resizing your browser window will reset the target positions to match the new window dimensions. + Please avoid resizing during Study Mode to maintain consistent test conditions. +

+
+

Try different acceleration curves to find what works best for you!

-
diff --git a/src/components/Settings.tsx b/src/components/Settings.tsx index 314a02f..5beb783 100644 --- a/src/components/Settings.tsx +++ b/src/components/Settings.tsx @@ -1,5 +1,5 @@ import React, { useState } from 'react'; -import { AccelerationSettings } from '../types'; +import { AccelerationSettings, ZoomPreset, AppMode, CONSTANTS } from '../types'; import { updateSettingsCurve } from '../utils/settings'; import { clamp } from '../utils/math'; import './Settings.css'; @@ -7,6 +7,8 @@ import './Settings.css'; interface SettingsProps { settings: AccelerationSettings; onSettingsChange: (settings: AccelerationSettings) => void; + mode: AppMode; + onModeChange: (mode: AppMode) => void; visible: boolean; onClose: () => void; } @@ -14,6 +16,8 @@ interface SettingsProps { export const Settings: React.FC = ({ settings, onSettingsChange, + mode, + onModeChange, visible, onClose, }) => { @@ -66,6 +70,18 @@ export const Settings: React.FC = ({ } }; + const handlePresetChange = (preset: ZoomPreset) => { + onSettingsChange({ + ...settings, + preset, + accelerationCurve: [...CONSTANTS.PRESETS[preset]] + }); + }; + + const handleModeChange = (newMode: AppMode) => { + onModeChange(newMode); + }; + if (!visible) return null; return ( @@ -75,6 +91,47 @@ export const Settings: React.FC = ({
+
+

Mode

+
+ + +
+
+ +
+

Preset Curves

+
+ {Object.keys(CONSTANTS.PRESETS).map((presetKey) => ( + + ))} +
+
+