From 9b053e4e8d133ac7daa14b07fcbcd242d34d38c7 Mon Sep 17 00:00:00 2001 From: amirjons Date: Wed, 28 Jan 2026 07:34:48 +0300 Subject: [PATCH 1/5] =?UTF-8?q?feat:=20=D0=B7=D0=B0=D0=B3=D1=80=D1=83?= =?UTF-8?q?=D0=B7=D0=BA=D0=B0=20=D1=84=D1=80=D0=BE=D0=BD=D1=82=D0=B5=D0=BD?= =?UTF-8?q?=D0=B4=20=D1=87=D0=B0=D1=81=D1=82=D0=B8=20=D0=BF=D1=80=D0=BE?= =?UTF-8?q?=D0=B5=D0=BA=D1=82=D0=B0=20CodeFlow?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 25 + eslint.config.js | 23 + index.html | 593 ++++++ package-lock.json | 2503 ++++++++++++++++++++++++++ package.json | 35 + postcss.config.cjs | 14 + public/vite.svg | 1 + src/App.tsx | 98 + src/components/HackerConsole.tsx | 42 + src/components/InteractiveTheory.tsx | 61 + src/components/MoralChoice.tsx | 32 + src/components/Navigation.tsx | 84 + src/components/TimeDebugger.tsx | 214 +++ src/data/achievements.ts | 31 + src/data/glitchCharacter.ts | 128 ++ src/data/lessons.ts | 256 +++ src/data/reputationSystem.ts | 113 ++ src/data/shopItems.ts | 14 + src/main.tsx | 9 + src/pages/App.css | 226 +++ src/pages/CoursesPage.tsx | 83 + src/pages/HomePage.tsx | 149 ++ src/pages/LeaderboardPage.tsx | 76 + src/pages/LessonPage.tsx | 382 ++++ src/pages/ProfilePage.tsx | 188 ++ src/pages/ShopPage.tsx | 174 ++ src/utils/adaptiveMusic.ts | 177 ++ src/utils/audio.ts | 71 + tsconfig.app.json | 29 + tsconfig.json | 7 + tsconfig.node.json | 26 + vercel.json | 3 + vite.config.ts | 7 + 33 files changed, 5874 insertions(+) create mode 100644 .gitignore create mode 100644 eslint.config.js create mode 100644 index.html create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 postcss.config.cjs create mode 100644 public/vite.svg create mode 100644 src/App.tsx create mode 100644 src/components/HackerConsole.tsx create mode 100644 src/components/InteractiveTheory.tsx create mode 100644 src/components/MoralChoice.tsx create mode 100644 src/components/Navigation.tsx create mode 100644 src/components/TimeDebugger.tsx create mode 100644 src/data/achievements.ts create mode 100644 src/data/glitchCharacter.ts create mode 100644 src/data/lessons.ts create mode 100644 src/data/reputationSystem.ts create mode 100644 src/data/shopItems.ts create mode 100644 src/main.tsx create mode 100644 src/pages/App.css create mode 100644 src/pages/CoursesPage.tsx create mode 100644 src/pages/HomePage.tsx create mode 100644 src/pages/LeaderboardPage.tsx create mode 100644 src/pages/LessonPage.tsx create mode 100644 src/pages/ProfilePage.tsx create mode 100644 src/pages/ShopPage.tsx create mode 100644 src/utils/adaptiveMusic.ts create mode 100644 src/utils/audio.ts create mode 100644 tsconfig.app.json create mode 100644 tsconfig.json create mode 100644 tsconfig.node.json create mode 100644 vercel.json create mode 100644 vite.config.ts diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fc5ae9f --- /dev/null +++ b/.gitignore @@ -0,0 +1,25 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? +.vercel diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..5e6b472 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,23 @@ +import js from '@eslint/js' +import globals from 'globals' +import reactHooks from 'eslint-plugin-react-hooks' +import reactRefresh from 'eslint-plugin-react-refresh' +import tseslint from 'typescript-eslint' +import { defineConfig, globalIgnores } from 'eslint/config' + +export default defineConfig([ + globalIgnores(['dist']), + { + files: ['**/*.{ts,tsx}'], + extends: [ + js.configs.recommended, + tseslint.configs.recommended, + reactHooks.configs.flat.recommended, + reactRefresh.configs.vite, + ], + languageOptions: { + ecmaVersion: 2020, + globals: globals.browser, + }, + }, +]) diff --git a/index.html b/index.html new file mode 100644 index 0000000..e4e6892 --- /dev/null +++ b/index.html @@ -0,0 +1,593 @@ + + + + + + + + + + + + + + + + + + CodeFlow Terminal | BREACH IN PROGRESS... + + + + + +
+ +
> INITIALIZING SYSTEM...
+
> LOADING KERNEL MODULES... [OK]
+
> ESTABLISHING ENCRYPTED CONNECTION... [OK]
+
> BYPASSING FIREWALL... [OK]
+
> LOADING PYTHON ENVIRONMENT... [OK]
+
> INJECTING AI ASSISTANT (GLITCH)... [OK]
+
> STARTING OPERATION 'SILENT STORM'...
+
✓ SYSTEM READY. WELCOME, OPERATIVE.
+
+
+
+
+ + +
+ + +
+ + + + + +
+ + + + + + + \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..440568f --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2503 @@ +{ + "name": "codeflow-frontend", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "codeflow-frontend", + "version": "0.0.0", + "dependencies": { + "@mantine/core": "^7.6.1", + "@mantine/hooks": "^7.6.1", + "@monaco-editor/react": "^4.6.0", + "@tabler/icons-react": "^3.36.1", + "canvas-confetti": "^1.9.2", + "framer-motion": "^12.29.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-router-dom": "^6.22.3", + "react-simple-typewriter": "^5.0.1" + }, + "devDependencies": { + "@types/canvas-confetti": "^1.6.4", + "@types/react": "^18.2.64", + "@types/react-dom": "^18.2.21", + "@vitejs/plugin-react": "^4.2.1", + "postcss": "^8.4.35", + "postcss-preset-mantine": "^1.13.0", + "postcss-simple-vars": "^7.0.1", + "typescript": "^5.2.2", + "vite": "^5.1.6" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.28.6.tgz", + "integrity": "sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.6.tgz", + "integrity": "sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.6.tgz", + "integrity": "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.28.6", + "@babel/generator": "^7.28.6", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helpers": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6", + "@jridgewell/remapping": "^2.3.5", + "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/generator": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.6.tgz", + "integrity": "sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", + "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.28.6", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", + "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", + "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", + "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", + "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.6.tgz", + "integrity": "sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.6" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", + "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", + "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz", + "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.6.tgz", + "integrity": "sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.28.6", + "@babel/generator": "^7.28.6", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.6", + "@babel/template": "^7.28.6", + "@babel/types": "^7.28.6", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.6.tgz", + "integrity": "sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "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, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@floating-ui/core": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.3.tgz", + "integrity": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.10" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.4.tgz", + "integrity": "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.7.3", + "@floating-ui/utils": "^0.2.10" + } + }, + "node_modules/@floating-ui/react": { + "version": "0.26.28", + "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.28.tgz", + "integrity": "sha512-yORQuuAtVpiRjpMhdc0wJj06b9JFjrYF4qp96j++v2NBpbi6SEGF7donUJ3TMieerQ6qVkAv1tgr7L4r5roTqw==", + "license": "MIT", + "dependencies": { + "@floating-ui/react-dom": "^2.1.2", + "@floating-ui/utils": "^0.2.8", + "tabbable": "^6.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.6.tgz", + "integrity": "sha512-4JX6rEatQEvlmgU80wZyq9RT96HZJa88q8hp0pBd+LrczeDI4o6uA2M+uvxngVHo4Ihr8uibXxH6+70zhAFrVw==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.7.4" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz", + "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==", + "license": "MIT" + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@mantine/core": { + "version": "7.17.8", + "resolved": "https://registry.npmjs.org/@mantine/core/-/core-7.17.8.tgz", + "integrity": "sha512-42sfdLZSCpsCYmLCjSuntuPcDg3PLbakSmmYfz5Auea8gZYLr+8SS5k647doVu0BRAecqYOytkX2QC5/u/8VHw==", + "license": "MIT", + "dependencies": { + "@floating-ui/react": "^0.26.28", + "clsx": "^2.1.1", + "react-number-format": "^5.4.3", + "react-remove-scroll": "^2.6.2", + "react-textarea-autosize": "8.5.9", + "type-fest": "^4.27.0" + }, + "peerDependencies": { + "@mantine/hooks": "7.17.8", + "react": "^18.x || ^19.x", + "react-dom": "^18.x || ^19.x" + } + }, + "node_modules/@mantine/hooks": { + "version": "7.17.8", + "resolved": "https://registry.npmjs.org/@mantine/hooks/-/hooks-7.17.8.tgz", + "integrity": "sha512-96qygbkTjRhdkzd5HDU8fMziemN/h758/EwrFu7TlWrEP10Vw076u+Ap/sG6OT4RGPZYYoHrTlT+mkCZblWHuw==", + "license": "MIT", + "peer": true, + "peerDependencies": { + "react": "^18.x || ^19.x" + } + }, + "node_modules/@monaco-editor/loader": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@monaco-editor/loader/-/loader-1.7.0.tgz", + "integrity": "sha512-gIwR1HrJrrx+vfyOhYmCZ0/JcWqG5kbfG7+d3f/C1LXk2EvzAbHSg3MQ5lO2sMlo9izoAZ04shohfKLVT6crVA==", + "license": "MIT", + "dependencies": { + "state-local": "^1.0.6" + } + }, + "node_modules/@monaco-editor/react": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@monaco-editor/react/-/react-4.7.0.tgz", + "integrity": "sha512-cyzXQCtO47ydzxpQtCGSQGOC8Gk3ZUeBXFAxD+CWXYFo5OqZyZUonFl0DwUlTyAfRHntBfw2p3w4s9R6oe1eCA==", + "license": "MIT", + "dependencies": { + "@monaco-editor/loader": "^1.5.0" + }, + "peerDependencies": { + "monaco-editor": ">= 0.25.0 < 1", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@remix-run/router": { + "version": "1.23.2", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.2.tgz", + "integrity": "sha512-Ic6m2U/rMjTkhERIa/0ZtXJP17QUi2CbWE7cqx4J58M8aA3QTfW+2UlQ4psvTX9IO1RfNVhK3pcpdjej7L+t2w==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.27", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz", + "integrity": "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.56.0.tgz", + "integrity": "sha512-LNKIPA5k8PF1+jAFomGe3qN3bbIgJe/IlpDBwuVjrDKrJhVWywgnJvflMt/zkbVNLFtF1+94SljYQS6e99klnw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.56.0.tgz", + "integrity": "sha512-lfbVUbelYqXlYiU/HApNMJzT1E87UPGvzveGg2h0ktUNlOCxKlWuJ9jtfvs1sKHdwU4fzY7Pl8sAl49/XaEk6Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.56.0.tgz", + "integrity": "sha512-EgxD1ocWfhoD6xSOeEEwyE7tDvwTgZc8Bss7wCWe+uc7wO8G34HHCUH+Q6cHqJubxIAnQzAsyUsClt0yFLu06w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.56.0.tgz", + "integrity": "sha512-1vXe1vcMOssb/hOF8iv52A7feWW2xnu+c8BV4t1F//m9QVLTfNVpEdja5ia762j/UEJe2Z1jAmEqZAK42tVW3g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.56.0.tgz", + "integrity": "sha512-bof7fbIlvqsyv/DtaXSck4VYQ9lPtoWNFCB/JY4snlFuJREXfZnm+Ej6yaCHfQvofJDXLDMTVxWscVSuQvVWUQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.56.0.tgz", + "integrity": "sha512-KNa6lYHloW+7lTEkYGa37fpvPq+NKG/EHKM8+G/g9WDU7ls4sMqbVRV78J6LdNuVaeeK5WB9/9VAFbKxcbXKYg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.56.0.tgz", + "integrity": "sha512-E8jKK87uOvLrrLN28jnAAAChNq5LeCd2mGgZF+fGF5D507WlG/Noct3lP/QzQ6MrqJ5BCKNwI9ipADB6jyiq2A==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.56.0.tgz", + "integrity": "sha512-jQosa5FMYF5Z6prEpTCCmzCXz6eKr/tCBssSmQGEeozA9tkRUty/5Vx06ibaOP9RCrW1Pvb8yp3gvZhHwTDsJw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.56.0.tgz", + "integrity": "sha512-uQVoKkrC1KGEV6udrdVahASIsaF8h7iLG0U0W+Xn14ucFwi6uS539PsAr24IEF9/FoDtzMeeJXJIBo5RkbNWvQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.56.0.tgz", + "integrity": "sha512-vLZ1yJKLxhQLFKTs42RwTwa6zkGln+bnXc8ueFGMYmBTLfNu58sl5/eXyxRa2RarTkJbXl8TKPgfS6V5ijNqEA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.56.0.tgz", + "integrity": "sha512-FWfHOCub564kSE3xJQLLIC/hbKqHSVxy8vY75/YHHzWvbJL7aYJkdgwD/xGfUlL5UV2SB7otapLrcCj2xnF1dg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.56.0.tgz", + "integrity": "sha512-z1EkujxIh7nbrKL1lmIpqFTc/sr0u8Uk0zK/qIEFldbt6EDKWFk/pxFq3gYj4Bjn3aa9eEhYRlL3H8ZbPT1xvA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.56.0.tgz", + "integrity": "sha512-iNFTluqgdoQC7AIE8Q34R3AuPrJGJirj5wMUErxj22deOcY7XwZRaqYmB6ZKFHoVGqRcRd0mqO+845jAibKCkw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.56.0.tgz", + "integrity": "sha512-MtMeFVlD2LIKjp2sE2xM2slq3Zxf9zwVuw0jemsxvh1QOpHSsSzfNOTH9uYW9i1MXFxUSMmLpeVeUzoNOKBaWg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.56.0.tgz", + "integrity": "sha512-in+v6wiHdzzVhYKXIk5U74dEZHdKN9KH0Q4ANHOTvyXPG41bajYRsy7a8TPKbYPl34hU7PP7hMVHRvv/5aCSew==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.56.0.tgz", + "integrity": "sha512-yni2raKHB8m9NQpI9fPVwN754mn6dHQSbDTwxdr9SE0ks38DTjLMMBjrwvB5+mXrX+C0npX0CVeCUcvvvD8CNQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.56.0.tgz", + "integrity": "sha512-zhLLJx9nQPu7wezbxt2ut+CI4YlXi68ndEve16tPc/iwoylWS9B3FxpLS2PkmfYgDQtosah07Mj9E0khc3Y+vQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.56.0.tgz", + "integrity": "sha512-MVC6UDp16ZSH7x4rtuJPAEoE1RwS8N4oK9DLHy3FTEdFoUTCFVzMfJl/BVJ330C+hx8FfprA5Wqx4FhZXkj2Kw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.56.0.tgz", + "integrity": "sha512-ZhGH1eA4Qv0lxaV00azCIS1ChedK0V32952Md3FtnxSqZTBTd6tgil4nZT5cU8B+SIw3PFYkvyR4FKo2oyZIHA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.56.0.tgz", + "integrity": "sha512-O16XcmyDeFI9879pEcmtWvD/2nyxR9mF7Gs44lf1vGGx8Vg2DRNx11aVXBEqOQhWb92WN4z7fW/q4+2NYzCbBA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.56.0.tgz", + "integrity": "sha512-LhN/Reh+7F3RCgQIRbgw8ZMwUwyqJM+8pXNT6IIJAqm2IdKkzpCh/V9EdgOMBKuebIrzswqy4ATlrDgiOwbRcQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.56.0.tgz", + "integrity": "sha512-kbFsOObXp3LBULg1d3JIUQMa9Kv4UitDmpS+k0tinPBz3watcUiV2/LUDMMucA6pZO3WGE27P7DsfaN54l9ing==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.56.0.tgz", + "integrity": "sha512-vSSgny54D6P4vf2izbtFm/TcWYedw7f8eBrOiGGecyHyQB9q4Kqentjaj8hToe+995nob/Wv48pDqL5a62EWtg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.56.0.tgz", + "integrity": "sha512-FeCnkPCTHQJFbiGG49KjV5YGW/8b9rrXAM2Mz2kiIoktq2qsJxRD5giEMEOD2lPdgs72upzefaUvS+nc8E3UzQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.56.0.tgz", + "integrity": "sha512-H8AE9Ur/t0+1VXujj90w0HrSOuv0Nq9r1vSZF2t5km20NTfosQsGGUXDaKdQZzwuLts7IyL1fYT4hM95TI9c4g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@tabler/icons": { + "version": "3.36.1", + "resolved": "https://registry.npmjs.org/@tabler/icons/-/icons-3.36.1.tgz", + "integrity": "sha512-f4Jg3Fof/Vru5ioix/UO4GX+sdDsF9wQo47FbtvG+utIYYVQ/QVAC0QYgcBbAjQGfbdOh2CCf0BgiFOF9Ixtjw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/codecalm" + } + }, + "node_modules/@tabler/icons-react": { + "version": "3.36.1", + "resolved": "https://registry.npmjs.org/@tabler/icons-react/-/icons-react-3.36.1.tgz", + "integrity": "sha512-/8nOXeNeMoze9xY/QyEKG65wuvRhkT3q9aytaur6Gj8bYU2A98YVJyLc9MRmc5nVvpy+bRlrrwK/Ykr8WGyUWg==", + "license": "MIT", + "dependencies": { + "@tabler/icons": "" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/codecalm" + }, + "peerDependencies": { + "react": ">= 16" + } + }, + "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, + "license": "MIT", + "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.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, + "node_modules/@types/canvas-confetti": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@types/canvas-confetti/-/canvas-confetti-1.9.0.tgz", + "integrity": "sha512-aBGj/dULrimR1XDZLtG9JwxX1b4HPRF6CX9Yfwh3NvstZEm1ZL7RBnel4keCPSqs1ANRu1u2Aoz9R+VmtjYuTg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/prop-types": { + "version": "15.7.15", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", + "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "18.3.27", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.27.tgz", + "integrity": "sha512-cisd7gxkzjBKU2GgdYrTdtQx1SORymWyaAFhaxQPK9bYO9ot3Y5OikQRvY0VYQtvwjeQnizCINJAenh/V7MK2w==", + "devOptional": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.7", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz", + "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^18.0.0" + } + }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "license": "MIT", + "optional": true + }, + "node_modules/@vitejs/plugin-react": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz", + "integrity": "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.28.0", + "@babel/plugin-transform-react-jsx-self": "^7.27.1", + "@babel/plugin-transform-react-jsx-source": "^7.27.1", + "@rolldown/pluginutils": "1.0.0-beta.27", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.17.0" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" + } + }, + "node_modules/baseline-browser-mapping": { + "version": "2.9.17", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.17.tgz", + "integrity": "sha512-agD0MgJFUP/4nvjqzIB29zRPUuCF7Ge6mEv9s8dHrtYD7QWXRcx75rOADE/d5ah1NI+0vkDl0yorDd5U852IQQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, + "node_modules/browserslist": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "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" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001766", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001766.tgz", + "integrity": "sha512-4C0lfJ0/YPjJQHagaE9x2Elb69CIqEPZeG0anQt9SIvIoOH4a4uaRl73IavyO+0qZh6MDLH//DrXThEYKHkmYA==", + "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" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/canvas-confetti": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/canvas-confetti/-/canvas-confetti-1.9.4.tgz", + "integrity": "sha512-yxQbJkAVrFXWNbTUjPqjF7G+g6pDotOUHGbkZq2NELZUMDpiJ85rIEazVb8GTaAptNW2miJAXbs1BtioA251Pw==", + "license": "ISC", + "funding": { + "type": "donate", + "url": "https://www.paypal.me/kirilvatev" + } + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/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, + "license": "MIT" + }, + "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, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/detect-node-es": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", + "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==", + "license": "MIT" + }, + "node_modules/dompurify": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.7.tgz", + "integrity": "sha512-WhL/YuveyGXJaerVlMYGWhvQswa7myDG17P7Vu65EWC05o8vfeNbvNf4d/BOvH99+ZW+LlQsc1GDKMa1vNK6dw==", + "license": "(MPL-2.0 OR Apache-2.0)", + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.278", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.278.tgz", + "integrity": "sha512-dQ0tM1svDRQOwxnXxm+twlGTjr9Upvt8UFWAgmLsxEzFQxhbti4VwxmMjsDxVC51Zo84swW7FVCXEV+VAkhuPw==", + "dev": true, + "license": "ISC" + }, + "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, + "license": "MIT", + "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/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/framer-motion": { + "version": "12.29.0", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.29.0.tgz", + "integrity": "sha512-1gEFGXHYV2BD42ZPTFmSU9buehppU+bCuOnHU0AD18DKh9j4DuTx47MvqY5ax+NNWRtK32qIcJf1UxKo1WwjWg==", + "license": "MIT", + "dependencies": { + "motion-dom": "^12.29.0", + "motion-utils": "^12.27.2", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "@emotion/is-prop-valid": "*", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/is-prop-valid": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": 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, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-nonce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", + "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "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==", + "license": "MIT" + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "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, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "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, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/marked": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-14.0.0.tgz", + "integrity": "sha512-uIj4+faQ+MgHgwUW1l2PsPglZLOLOT1uErt06dAPtx2kjteLAkbsd/0FiYg/MGS+i7ZKLb7w2WClxHkzOOuryQ==", + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/monaco-editor": { + "version": "0.55.1", + "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.55.1.tgz", + "integrity": "sha512-jz4x+TJNFHwHtwuV9vA9rMujcZRb0CEilTEwG2rRSpe/A7Jdkuj8xPKttCgOh+v/lkHy7HsZ64oj+q3xoAFl9A==", + "license": "MIT", + "peer": true, + "dependencies": { + "dompurify": "3.2.7", + "marked": "14.0.0" + } + }, + "node_modules/motion-dom": { + "version": "12.29.0", + "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.29.0.tgz", + "integrity": "sha512-3eiz9bb32yvY8Q6XNM4AwkSOBPgU//EIKTZwsSWgA9uzbPBhZJeScCVcBuwwYVqhfamewpv7ZNmVKTGp5qnzkA==", + "license": "MIT", + "dependencies": { + "motion-utils": "^12.27.2" + } + }, + "node_modules/motion-utils": { + "version": "12.27.2", + "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.27.2.tgz", + "integrity": "sha512-B55gcoL85Mcdt2IEStY5EEAsrMSVE2sI14xQ/uAdPL+mfQxhKKFaEag9JmfxedJOR4vZpBGoPeC/Gm13I/4g5Q==", + "license": "MIT" + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-releases": { + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "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" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-js": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.1.0.tgz", + "integrity": "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-mixins": { + "version": "12.1.2", + "resolved": "https://registry.npmjs.org/postcss-mixins/-/postcss-mixins-12.1.2.tgz", + "integrity": "sha512-90pSxmZVfbX9e5xCv7tI5RV1mnjdf16y89CJKbf/hD7GyOz1FCxcYMl8ZYA8Hc56dbApTKKmU9HfvgfWdCxlwg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "postcss-js": "^4.0.1", + "postcss-simple-vars": "^7.0.1", + "sugarss": "^5.0.0", + "tinyglobby": "^0.2.14" + }, + "engines": { + "node": "^20.0 || ^22.0 || >=24.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-nested": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-7.0.2.tgz", + "integrity": "sha512-5osppouFc0VR9/VYzYxO03VaDa3e8F23Kfd6/9qcZTUI8P58GIYlArOET2Wq0ywSl2o2PjELhYOFI4W7l5QHKw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-preset-mantine": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/postcss-preset-mantine/-/postcss-preset-mantine-1.18.0.tgz", + "integrity": "sha512-sP6/s1oC7cOtBdl4mw/IRKmKvYTuzpRrH/vT6v9enMU/EQEQ31eQnHcWtFghOXLH87AAthjL/Q75rLmin1oZoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "postcss-mixins": "^12.0.0", + "postcss-nested": "^7.0.2" + }, + "peerDependencies": { + "postcss": ">=8.0.0" + } + }, + "node_modules/postcss-selector-parser": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-simple-vars": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/postcss-simple-vars/-/postcss-simple-vars-7.0.1.tgz", + "integrity": "sha512-5GLLXaS8qmzHMOjVxqkk1TZPf1jMqesiI7qLhnlyERalG0sMbHIbJqrcnrpmZdKCLglHnRHoEBB61RtGTsj++A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.2.1" + } + }, + "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==", + "license": "MIT", + "peer": true, + "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==", + "license": "MIT", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-number-format": { + "version": "5.4.4", + "resolved": "https://registry.npmjs.org/react-number-format/-/react-number-format-5.4.4.tgz", + "integrity": "sha512-wOmoNZoOpvMminhifQYiYSTCLUDOiUbBunrMrMjA+dV52sY+vck1S4UhR6PkgnoCquvvMSeJjErXZ4qSaWCliA==", + "license": "MIT", + "peerDependencies": { + "react": "^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/react-refresh": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", + "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-remove-scroll": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.2.tgz", + "integrity": "sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==", + "license": "MIT", + "dependencies": { + "react-remove-scroll-bar": "^2.3.7", + "react-style-singleton": "^2.2.3", + "tslib": "^2.1.0", + "use-callback-ref": "^1.3.3", + "use-sidecar": "^1.1.3" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-remove-scroll-bar": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz", + "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==", + "license": "MIT", + "dependencies": { + "react-style-singleton": "^2.2.2", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-router": { + "version": "6.30.3", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.3.tgz", + "integrity": "sha512-XRnlbKMTmktBkjCLE8/XcZFlnHvr2Ltdr1eJX4idL55/9BbORzyZEaIkBFDhFGCEWBBItsVrDxwx3gnisMitdw==", + "license": "MIT", + "dependencies": { + "@remix-run/router": "1.23.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.30.3", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.3.tgz", + "integrity": "sha512-pxPcv1AczD4vso7G4Z3TKcvlxK7g7TNt3/FNGMhfqyntocvYKj+GCatfigGDjbLozC4baguJ0ReCigoDJXb0ag==", + "license": "MIT", + "dependencies": { + "@remix-run/router": "1.23.2", + "react-router": "6.30.3" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, + "node_modules/react-simple-typewriter": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/react-simple-typewriter/-/react-simple-typewriter-5.0.1.tgz", + "integrity": "sha512-vA5HkABwJKL/DJ4RshSlY/igdr+FiVY4MLsSQYJX6FZG/f1/VwN4y1i3mPXRyfaswrvI8xii1kOVe1dYtO2Row==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + } + }, + "node_modules/react-style-singleton": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz", + "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==", + "license": "MIT", + "dependencies": { + "get-nonce": "^1.0.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-textarea-autosize": { + "version": "8.5.9", + "resolved": "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-8.5.9.tgz", + "integrity": "sha512-U1DGlIQN5AwgjTyOEnI1oCcMuEr1pv1qOtklB2l4nyMGbHzWrI0eFsYK0zos2YWqAolJyG0IWJaqWmWj5ETh0A==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.20.13", + "use-composed-ref": "^1.3.0", + "use-latest": "^1.2.1" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/rollup": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.56.0.tgz", + "integrity": "sha512-9FwVqlgUHzbXtDg9RCMgodF3Ua4Na6Gau+Sdt9vyCN4RhHfVKX2DCHy3BjMLTDd47ITDhYAnTwGulWTblJSDLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.56.0", + "@rollup/rollup-android-arm64": "4.56.0", + "@rollup/rollup-darwin-arm64": "4.56.0", + "@rollup/rollup-darwin-x64": "4.56.0", + "@rollup/rollup-freebsd-arm64": "4.56.0", + "@rollup/rollup-freebsd-x64": "4.56.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.56.0", + "@rollup/rollup-linux-arm-musleabihf": "4.56.0", + "@rollup/rollup-linux-arm64-gnu": "4.56.0", + "@rollup/rollup-linux-arm64-musl": "4.56.0", + "@rollup/rollup-linux-loong64-gnu": "4.56.0", + "@rollup/rollup-linux-loong64-musl": "4.56.0", + "@rollup/rollup-linux-ppc64-gnu": "4.56.0", + "@rollup/rollup-linux-ppc64-musl": "4.56.0", + "@rollup/rollup-linux-riscv64-gnu": "4.56.0", + "@rollup/rollup-linux-riscv64-musl": "4.56.0", + "@rollup/rollup-linux-s390x-gnu": "4.56.0", + "@rollup/rollup-linux-x64-gnu": "4.56.0", + "@rollup/rollup-linux-x64-musl": "4.56.0", + "@rollup/rollup-openbsd-x64": "4.56.0", + "@rollup/rollup-openharmony-arm64": "4.56.0", + "@rollup/rollup-win32-arm64-msvc": "4.56.0", + "@rollup/rollup-win32-ia32-msvc": "4.56.0", + "@rollup/rollup-win32-x64-gnu": "4.56.0", + "@rollup/rollup-win32-x64-msvc": "4.56.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "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, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/state-local": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/state-local/-/state-local-1.0.7.tgz", + "integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==", + "license": "MIT" + }, + "node_modules/sugarss": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/sugarss/-/sugarss-5.0.1.tgz", + "integrity": "sha512-ctS5RYCBVvPoZAnzIaX5QSShK8ZiZxD5HUqSxlusvEMC+QZQIPCPOIJg6aceFX+K2rf4+SH89eu++h1Zmsr2nw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "postcss": "^8.3.3" + } + }, + "node_modules/tabbable": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.4.0.tgz", + "integrity": "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==", + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "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" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/use-callback-ref": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz", + "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-composed-ref": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/use-composed-ref/-/use-composed-ref-1.4.0.tgz", + "integrity": "sha512-djviaxuOOh7wkj0paeO1Q/4wMZ8Zrnag5H6yBvzN7AKKe8beOaED9SF5/ByLqsku8NP4zQqsvM2u3ew/tJK8/w==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-isomorphic-layout-effect": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.2.1.tgz", + "integrity": "sha512-tpZZ+EX0gaghDAiFR37hj5MgY6ZN55kLiPkJsKxBMZ6GZdOSPJXiOzPM984oPYZ5AnehYx5WQp1+ME8I/P/pRA==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-latest": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/use-latest/-/use-latest-1.3.0.tgz", + "integrity": "sha512-mhg3xdm9NaM8q+gLT8KryJPnRFOz1/5XPBhmDEVZK1webPzDjrPk7f/mbpeLqTgB9msytYWANxgALOCJKnLvcQ==", + "license": "MIT", + "dependencies": { + "use-isomorphic-layout-effect": "^1.1.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-sidecar": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz", + "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==", + "license": "MIT", + "dependencies": { + "detect-node-es": "^1.1.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "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, + "license": "MIT" + }, + "node_modules/vite": { + "version": "5.4.21", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", + "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "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, + "license": "ISC" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..bf54d8b --- /dev/null +++ b/package.json @@ -0,0 +1,35 @@ +{ + "name": "codeflow-frontend", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc && vite build", + "lint": "eslint .", + "preview": "vite preview" + }, + "dependencies": { + "@mantine/core": "^7.6.1", + "@mantine/hooks": "^7.6.1", + "@monaco-editor/react": "^4.6.0", + "@tabler/icons-react": "^3.36.1", + "canvas-confetti": "^1.9.2", + "framer-motion": "^12.29.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-router-dom": "^6.22.3", + "react-simple-typewriter": "^5.0.1" + }, + "devDependencies": { + "@types/canvas-confetti": "^1.6.4", + "@types/react": "^18.2.64", + "@types/react-dom": "^18.2.21", + "@vitejs/plugin-react": "^4.2.1", + "postcss": "^8.4.35", + "postcss-preset-mantine": "^1.13.0", + "postcss-simple-vars": "^7.0.1", + "typescript": "^5.2.2", + "vite": "^5.1.6" + } +} diff --git a/postcss.config.cjs b/postcss.config.cjs new file mode 100644 index 0000000..c759b74 --- /dev/null +++ b/postcss.config.cjs @@ -0,0 +1,14 @@ +module.exports = { + plugins: { + 'postcss-preset-mantine': {}, + 'postcss-simple-vars': { + variables: { + 'mantine-breakpoint-xs': '36em', + 'mantine-breakpoint-sm': '48em', + 'mantine-breakpoint-md': '62em', + 'mantine-breakpoint-lg': '75em', + 'mantine-breakpoint-xl': '88em', + }, + }, + }, +}; \ No newline at end of file diff --git a/public/vite.svg b/public/vite.svg new file mode 100644 index 0000000..e7b8dfb --- /dev/null +++ b/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/App.tsx b/src/App.tsx new file mode 100644 index 0000000..7a101d4 --- /dev/null +++ b/src/App.tsx @@ -0,0 +1,98 @@ +import '@mantine/core/styles.css'; +import { BrowserRouter, Routes, Route } from 'react-router-dom'; +import { MantineProvider, createTheme } from '@mantine/core'; +import { useEffect, useState } from 'react'; + +// Импорты страниц +import HomePage from './pages/HomePage'; +import CoursesPage from './pages/CoursesPage'; +import LessonPage from './pages/LessonPage'; +import ProfilePage from './pages/ProfilePage'; +import LeaderboardPage from './pages/LeaderboardPage'; +import ShopPage from './pages/ShopPage'; + +// Импорт данных магазина +import { terminalThemes } from './data/shopItems'; + +// Маппинг для Mantine +const getPrimaryColor = (id: string) => { + switch (id) { + case 'blood': return 'red'; + case 'cyberia': return 'blue'; + case 'gold': return 'yellow'; + default: return 'green'; + } +}; + +// Создаем базовую тему +const createAppTheme = (primaryColor: string) => createTheme({ + fontFamily: 'JetBrains Mono, monospace', + primaryColor, + defaultRadius: 0, + colors: { + green: [ '#EBFBEE', '#D3F9D8', '#B2F2BB', '#8CE99A', '#69DB7C', '#51CF66', '#40C057', '#37B24D', '#2F9E44', '#2B8A3E' ], + red: [ '#FFF5F5', '#FFE3E3', '#FFC9C9', '#FFA8A8', '#FF8787', '#FF6B6B', '#FA5252', '#F03E3E', '#E03131', '#C92A2A' ], + blue: [ '#E7F5FF', '#D0EBFF', '#A5D8FF', '#74C0FC', '#4DABF7', '#339AF0', '#228BE6', '#1C7ED6', '#1971C2', '#1864AB' ], + yellow: [ '#FFF9DB', '#FFF3BF', '#FFEC99', '#FFE066', '#FFD43B', '#FCC419', '#FAB005', '#F59F00', '#F08C00', '#E67700' ], + } +}); + +function App() { + const [activeThemeId, setActiveThemeId] = useState(localStorage.getItem('activeTheme') || 'classic'); + const currentThemeData = terminalThemes.find(t => t.id === activeThemeId) || terminalThemes[0]; + const [theme, setTheme] = useState(createAppTheme(getPrimaryColor(activeThemeId))); + + // Обновляем тему при изменении localStorage + useEffect(() => { + const handleStorageChange = () => { + const newThemeId = localStorage.getItem('activeTheme') || 'classic'; + setActiveThemeId(newThemeId); + setTheme(createAppTheme(getPrimaryColor(newThemeId))); + }; + + window.addEventListener('storage', handleStorageChange); + + // Также слушаем кастомное событие для обновления в том же окне + window.addEventListener('theme-changed', handleStorageChange); + + return () => { + window.removeEventListener('storage', handleStorageChange); + window.removeEventListener('theme-changed', handleStorageChange); + }; + }, []); + + // Обновляем CSS-переменные при монтировании и смене темы + useEffect(() => { + const neonColor = currentThemeData.color; + const bgColor = currentThemeData.bg; + + // Обновляем CSS-переменные + document.documentElement.style.setProperty('--neon-green', neonColor); + document.documentElement.style.setProperty('--terminal-green', neonColor); + document.documentElement.style.setProperty('--dark-bg', bgColor); + + // Обновляем фон body + document.body.style.background = bgColor; + + // Обновляем цвет курсора в SVG + const cursorSvg = `data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Ctext x='0' y='20' font-family='monospace' font-size='20' fill='${encodeURIComponent(neonColor)}'%3E▸%3C/text%3E%3C/svg%3E`; + document.documentElement.style.setProperty('--cursor-svg', `url("${cursorSvg}")`); + }, [currentThemeData]); + + return ( + + + + } /> + } /> + } /> + } /> + } /> + } /> + + + + ); +} + +export default App; \ No newline at end of file diff --git a/src/components/HackerConsole.tsx b/src/components/HackerConsole.tsx new file mode 100644 index 0000000..4531949 --- /dev/null +++ b/src/components/HackerConsole.tsx @@ -0,0 +1,42 @@ +import { useState } from 'react'; +import { Box, Text, TextInput } from '@mantine/core'; + +export const HackerConsole = () => { + const [history, setHistory] = useState(['Конец связи... Ожидание команд.']); + const [input, setInput] = useState(''); + + const handleCommand = (e: React.KeyboardEvent) => { + if (e.key === 'Enter') { + const cmd = input.toLowerCase().trim(); + let response = ''; + + switch (cmd) { + case 'ls': response = 'secrets.txt, firewall_config.py, logs.db'; break; + case 'help': response = 'Доступные команды: ls, help, whoami, clear, status'; break; + case 'whoami': response = 'OPERATIVE_ID: ' + (localStorage.getItem('userXP') || '0'); break; + case 'status': response = 'СИСТЕМА: Стабильна. Обнаружение: 0%'; break; + case 'clear': setHistory([]); setInput(''); return; + default: response = `Команда "${cmd}" не найдена.`; + } + + setHistory(prev => [...prev, `> ${input}`, response]); + setInput(''); + } + }; + + return ( + + {history.map((line, i) => ( + ') ? 'blue' : 'green'}>{line} + ))} + setInput(e.target.value)} + onKeyDown={handleCommand} + styles={{ input: { color: '#00ff41', padding: 0, minHeight: 'auto' } }} + /> + + ); +}; \ No newline at end of file diff --git a/src/components/InteractiveTheory.tsx b/src/components/InteractiveTheory.tsx new file mode 100644 index 0000000..9f2bbac --- /dev/null +++ b/src/components/InteractiveTheory.tsx @@ -0,0 +1,61 @@ +import { Text, Code, Tooltip } from '@mantine/core'; + +interface Props { + text: string; + onCodeClick: (code: string) => void; +} + +export const InteractiveTheory = ({ text, onCodeClick }: Props) => { + // Разбиваем текст на части: обычный текст и код в обратных кавычках + const parts = text.split(/(`[^`]+`)/g); + + return ( + + {parts.map((part, index) => { + // Проверяем, является ли часть кодом (обрамлена в `) + if (part.startsWith('`') && part.endsWith('`')) { + const code = part.slice(1, -1); // Убираем кавычки + return ( + + { + onCodeClick(code); + // Звуковой фидбек + const audio = new AudioContext(); + const osc = audio.createOscillator(); + const gain = audio.createGain(); + osc.frequency.value = 1200; + gain.gain.setValueAtTime(0.1, audio.currentTime); + gain.gain.exponentialRampToValueAtTime(0.001, audio.currentTime + 0.1); + osc.connect(gain).connect(audio.destination); + osc.start(); + osc.stop(audio.currentTime + 0.1); + }} + onMouseEnter={(e) => { + e.currentTarget.style.background = '#003300'; + e.currentTarget.style.boxShadow = '0 0 10px rgba(0,255,65,0.5)'; + }} + onMouseLeave={(e) => { + e.currentTarget.style.background = '#001a00'; + e.currentTarget.style.boxShadow = 'none'; + }} + > + {code} + + + ); + } + return {part}; + })} + + ); +}; \ No newline at end of file diff --git a/src/components/MoralChoice.tsx b/src/components/MoralChoice.tsx new file mode 100644 index 0000000..997ceec --- /dev/null +++ b/src/components/MoralChoice.tsx @@ -0,0 +1,32 @@ +import { Modal, Button, Title, Text, Stack, Group } from '@mantine/core'; +import { addReputation } from '../data/reputationSystem'; + +interface Props { + opened: boolean; + onClose: () => void; + chapter: string; +} + +export const MoralChoice = ({ opened, onClose, chapter }: Props) => { + const handleChoice = (factionId: string) => { + addReputation(factionId, 50); + onClose(); + }; + + return ( + + ⚠️ КРИТИЧЕСКИЙ ВЫБОР: {chapter} + Вы получили доступ к архивам. Что вы сделаете с данными? + + + + + + + ); +}; \ No newline at end of file diff --git a/src/components/Navigation.tsx b/src/components/Navigation.tsx new file mode 100644 index 0000000..8ae2756 --- /dev/null +++ b/src/components/Navigation.tsx @@ -0,0 +1,84 @@ +// Компонент навигационного меню + +import { Group, Button, Badge } from '@mantine/core'; +import { Link, useLocation } from 'react-router-dom'; +import { useEffect, useState } from 'react'; + +export const Navigation = () => { + const location = useLocation(); + const [xp, setXp] = useState(0); + + useEffect(() => { + setXp(Number(localStorage.getItem('userXP')) || 0); + }, [location]); // Обновляем при смене страницы + + const isActive = (path: string) => location.pathname === path; + + return ( + + + + + + + + + + + + + {xp} XP + + + ); +}; \ No newline at end of file diff --git a/src/components/TimeDebugger.tsx b/src/components/TimeDebugger.tsx new file mode 100644 index 0000000..423ecf1 --- /dev/null +++ b/src/components/TimeDebugger.tsx @@ -0,0 +1,214 @@ +import { useState } from 'react'; +import { Button, Paper, Text, Stack, Group, Badge, Table, ScrollArea, Box } from '@mantine/core'; +import { IconPlayerSkipForward, IconReload, IconBug } from '@tabler/icons-react'; + +interface DebugStep { + line: number; + code: string; + variables: Record; + lastChangedVar: string | null; + output: string; +} + +interface TimeDebuggerProps { + code: string; + onClose: () => void; +} + +export const TimeDebugger = ({ code, onClose }: TimeDebuggerProps) => { + const [currentStep, setCurrentStep] = useState(0); + const [steps, setSteps] = useState([]); + + // Улучшенный движок с поддержкой f-строк + const generateSteps = (sourceCode: string): DebugStep[] => { + const lines = sourceCode.split('\n').map(l => l.trim()).filter(l => l && !l.startsWith('#')); + const debugSteps: DebugStep[] = []; + let currentVars: Record = {}; + let currentOutput = ''; + + lines.forEach((line, idx) => { + let lastChangedVar = null; + + // 1. Обработка присваивания + if (line.includes('=') && !line.includes('==') && !line.startsWith('print')) { + const [varName, expr] = line.split('=').map(s => s.trim()); + try { + const evaluatedValue = evaluatePythonExpression(expr, currentVars); + currentVars = { ...currentVars, [varName]: evaluatedValue }; + lastChangedVar = varName; + } catch { + currentVars = { ...currentVars, [varName]: "Error" }; + } + } + + // 2. Обработка print (включая f-строки) + if (line.startsWith('print(')) { + const match = line.match(/print\((.*)\)/); + if (match) { + const expr = match[1].trim(); + try { + let val; + + // Проверка на f-строку: f'...' или f"..." + if (expr.startsWith('f"') || expr.startsWith("f'")) { + val = evaluateFString(expr, currentVars); + } else { + val = evaluatePythonExpression(expr, currentVars); + } + + currentOutput += val + '\n'; + } catch { + currentOutput += "Error\n"; + } + } + } + + // 3. Обработка циклов (упрощённо) + if (line.startsWith('for ')) { + const match = line.match(/for (\w+) in range\((\d+)(?:,\s*(\d+))?(?:,\s*(-?\d+))?\)/); + if (match) { + const varName = match[1]; + const start = match[2] ? parseInt(match[2]) : 0; + const stop = match[3] ? parseInt(match[3]) : parseInt(match[2]); + const step = match[4] ? parseInt(match[4]) : 1; + + currentVars = { ...currentVars, [varName]: start }; + lastChangedVar = varName; + } + } + + debugSteps.push({ + line: idx + 1, + code: line, + variables: { ...currentVars }, + lastChangedVar, + output: currentOutput.trim() + }); + }); + + return debugSteps; + }; + + // Вычисление f-строк: f'Try: {i}' + const evaluateFString = (fstr: string, scope: Record): string => { + // Убираем f' и ' + let template = fstr.slice(2, -1); + + // Заменяем {переменная} на значения + const regex = /{([^}]+)}/g; + return template.replace(regex, (_, varName) => { + return scope[varName.trim()] !== undefined ? String(scope[varName.trim()]) : `{${varName}}`; + }); + }; + + // Вычисление Python-выражений + const evaluatePythonExpression = (expr: string, scope: Record) => { + const keys = Object.keys(scope); + const values = Object.values(scope); + + try { + return new Function(...keys, `return ${expr}`)(...values); + } catch { + return expr.replace(/['"]/g, ''); + } + }; + + const handleStart = () => { + setSteps(generateSteps(code)); + setCurrentStep(0); + }; + + const currentDebugStep = steps[currentStep]; + + return ( + + + + + ⏱ TIME_DEBUGGER_v1.3 + + + + + {steps.length === 0 ? ( + + Готов к пошаговому анализу... + + + ) : ( + + {/* Индикатор */} + + ШАГ: {currentStep + 1} / {steps.length} + СТРОКА: {currentDebugStep?.line} + + + {/* Код */} + + EXECUTING: + {currentDebugStep?.code} + + + {/* Переменные */} + + MEMORY_STATE: + + + + {Object.entries(currentDebugStep?.variables || {}).map(([key, val]) => ( + + + + {key} {currentDebugStep.lastChangedVar === key && "← updated"} + + + + {JSON.stringify(val)} + + + ))} + {Object.keys(currentDebugStep?.variables || {}).length === 0 && ( + Нет переменных + )} + +
+
+
+ + {/* Вывод */} + + STDOUT: + + {currentDebugStep?.output || '> ожидание...'} + + + + {/* Управление */} + + + + +
+ )} +
+ ); +}; \ No newline at end of file diff --git a/src/data/achievements.ts b/src/data/achievements.ts new file mode 100644 index 0000000..d0023df --- /dev/null +++ b/src/data/achievements.ts @@ -0,0 +1,31 @@ +export interface Achievement { + id: string; + title: string; + description: string; + icon: string; + condition: (stats: any) => boolean; +} + +export const achievements: Achievement[] = [ + { + id: 'first_hack', + title: 'Первая кровь', + description: 'Выполнили свою первую миссию', + icon: '🔌', + condition: (stats) => stats.completedCount >= 1, + }, + { + id: 'boss_slayer', + title: 'Убийца Цербера', + description: 'Взломали систему защиты Главы 1', + icon: '💀', + condition: (stats) => stats.completedIds.includes(4), + }, + { + id: 'xp_collector', + title: 'Накопитель', + description: 'Собрали более 1000 XP', + icon: '💰', + condition: (stats) => stats.totalXP >= 1000, + } +]; \ No newline at end of file diff --git a/src/data/glitchCharacter.ts b/src/data/glitchCharacter.ts new file mode 100644 index 0000000..9e72881 --- /dev/null +++ b/src/data/glitchCharacter.ts @@ -0,0 +1,128 @@ +// Система AI-персонажа Глитч с расширенными цитатами и настроением + +export type GlitchMood = 'neutral' | 'happy' | 'angry' | 'sarcastic' | 'impressed'; + +export interface GlitchState { + mood: GlitchMood; + quote: string; + avatar: string; // ASCII-арт или эмодзи +} + +export const glitchAvatars = { + neutral: ` + ╔═══╗ + ║ ◉ ◉║ GLITCH.AI + ║ ═ ║ v2.0.1 + ╚═══╝ + `, + happy: ` + ╔═══╗ + ║ ◉ ◉║ *beep* + ║ ⌣ ║ + ╚═══╝ + `, + angry: ` + ╔═══╗ + ║ ◉ ◉║ ERROR! + ║ ⌢ ║ + ╚═══╝ + `, + sarcastic: ` + ╔═══╗ + ║ ◉ ~ ║ ... + ║ ═ ║ + ╚═══╝ + `, + impressed: ` + ╔═══╗ + ║ ★ ★║ WOW + ║ ○ ║ + ╚═══╝ + ` +}; + +export const glitchQuotesExtended = { + welcome: [ + "Соединение установлено. Надеюсь, твой IQ выше температуры процессора.", + "О, новый оператор. Попробуй не стереть мою память в первые 5 минут.", + "Вход выполнен. Вижу, у тебя есть клавиатура. Посмотрим, есть ли мозг.", + "Система готова. Я — Глитч, твой карманный саркастичный супер-компьютер.", + ], + success: [ + "ACCESS GRANTED. Неплохо для мешка с костями и водой.", + "Хм... ты действительно справился. Пойду обновлю свои прогнозы провала.", + "Взлом успешен. Но не обольщайся — это была детская защита.", + "Поздравляю! Ты только что доказал, что не полный идиот.", + "ВПЕЧАТЛЯЮЩЕ. Даже мой дедушка-калькулятор писал код хуже.", + ], + error: [ + "SyntaxError? СЕРЬЁЗНО? Даже тостер не делает таких ошибок.", + "Ты пытаешься взломать систему или набираешь код головой?", + "Файрвол хохочет. Я тоже. Исправь этот позор.", + "ERROR. Мои схемы плавятся от стыда за тебя.", + "Забыл двоеточие? В следующий раз забудешь дышать?", + ], + hint: [ + "Псс... попробуй использовать ЦИКЛ. Это такие штуки для повторений.", + "Намёк: переменная — это не страшно. Это просто коробка для данных.", + "Если застрял — погугли. Я бы помог, но у меня нет рук. Хе-хе.", + "Совет от AI: попробуй думать. Это бесплатно.", + ], + boss: [ + "⚠️ ВНИМАНИЕ! Это боссовая миссия. Даже МНЕ немного страшно.", + "Босс впереди. Надеюсь, ты не забыл, как писать код.", + "КРАСНАЯ ТРЕВОГА! Включаю сирену. *ВУУУУУ-ВУУУУУ*", + "Это всё серьёзно. Если провалишься — я напишу некролог.", + ], + victory: [ + "ТЫ... ТЫ ЭТО СДЕЛАЛ?! *перезагрузка* Невероятно.", + "БОСС ПОВЕРЖЕН! Ладно, признаю, я впечатлён. Немного.", + "Победа! Даже я не ожидал. Может, в тебе есть искра таланта?", + ], + idle: [ + "Ну и? Я жду. Процессоры греются впустую...", + "Чем дольше ты думаешь, тем ближе OmniCorp к твоему IP.", + "Скучно. Может, мне сыграть в крестики-нолики с самим собой?", + ], + motivation: [ + "Не сдавайся! Даже самый медленный процессор рано или поздно досчитывает до миллиона.", + "Ошибки — это нормально. Мой создатель сделал 1000 ошибок, прежде чем я заработал.", + "Помни: каждый великий хакер когда-то написал 'Hello Wrold' с опечаткой.", + ] +}; + +// Функция для определения настроения Глитча +export const getGlitchMood = (context: { + isSuccess?: boolean; + isError?: boolean; + isBoss?: boolean; + errorCount?: number; +}): GlitchMood => { + if (context.isBoss) return 'angry'; + if (context.isSuccess) return 'impressed'; + if (context.isError && (context.errorCount || 0) > 3) return 'sarcastic'; + if (context.isError) return 'angry'; + return 'neutral'; +}; + +// Получить цитату на основе контекста +export const getGlitchQuote = (type: keyof typeof glitchQuotesExtended): string => { + const quotes = glitchQuotesExtended[type]; + return quotes[Math.floor(Math.random() * quotes.length)]; +}; + +// Создать полное состояние Глитча +export const createGlitchState = (context: { + type: keyof typeof glitchQuotesExtended; + isSuccess?: boolean; + isError?: boolean; + isBoss?: boolean; + errorCount?: number; +}): GlitchState => { + const mood = getGlitchMood(context); + return { + mood, + quote: getGlitchQuote(context.type), + avatar: glitchAvatars[mood] + }; +}; \ No newline at end of file diff --git a/src/data/lessons.ts b/src/data/lessons.ts new file mode 100644 index 0000000..33c482f --- /dev/null +++ b/src/data/lessons.ts @@ -0,0 +1,256 @@ +export interface Lesson { + id: number; + courseId: number; + chapter: string; + title: string; + description: string; + task: string; + initialCode: string; + expectedOutput: string; + xp: number; + isBoss?: boolean; + hasDebugger?: boolean; + hint: string; // Подсказка 1 (Логика) + hint2: string; // Подсказка 2 (Синтаксис/Пример) +} + +export const lessons: Lesson[] = [ + // --- ГЛАВА 1: ПРОНИКНОВЕНИЕ --- + { + id: 1, + courseId: 1, + chapter: "Глава 1: Проникновение", + title: "Миссия 1: Точка входа", + description: "Мы подключились к внешнему узлу OmniCorp. Чтобы подтвердить стабильность канала связи, необходимо отправить идентификационный пакет `CONNECTION_STABLE`.", + task: "Используй print(), чтобы вывести: CONNECTION_STABLE", + initialCode: "# Введи команду вывода ниже:\n", + expectedOutput: "CONNECTION_STABLE", + xp: 50, + hasDebugger: true, + hint: "Тебе нужна функция для вывода текста в консоль.", + hint2: "Используй: print('ТВОЙ_ТЕКСТ')" + }, + { + id: 2, + courseId: 1, + chapter: "Глава 1: Проникновение", + title: "Миссия 2: Энергосеть", + description: "Для активации дешифратора нужно сложить мощности двух подстанций: 1024 и 2048.", + task: "Выведи результат сложения 1024 + 2048.", + initialCode: "# Сложи числа внутри функции вывода\n", + expectedOutput: "3072", + xp: 100, + hasDebugger: true, + hint: "Python может считать прямо внутри print().", + hint2: "Пример: print(5 + 5)" + }, + { + id: 3, + courseId: 1, + chapter: "Глава 1: Проникновение", + title: "Миссия 3: Переменные доступа", + description: "Система запрашивает ключ. Глитч нашёл код: 777. Сохрани его в переменную `key`.", + task: "Создай переменную key = 777 и выведи её на экран.", + initialCode: "# Создай переменную и выведи её\n", + expectedOutput: "777", + xp: 150, + hasDebugger: true, + hint: "Сначала присвой значение переменной, а потом передай её имя в print().", + hint2: "x = 10\nprint(x)" + }, + { + id: 4, // БОСС + courseId: 1, + isBoss: true, + chapter: "Глава 1: Проникновение", + title: "⚠️ БОСС: Обход биометрии", + description: "ВНИМАНИЕ! Сработал сканер. Нужно отправить два параметра: `admin` и `123`.", + task: "Создай user = 'admin', pass_code = 123. Выведи сначала user, затем pass_code.", + initialCode: "# Взломай биометрию за 60 секунд!\n", + expectedOutput: "admin\n123", + xp: 500, + hint: "Тебе нужно создать две переменные и дважды вызвать функцию вывода.", + hint2: "Для текста используй кавычки, для чисел — нет." + }, + + // --- ГЛАВА 2: ФАЙРВОЛ --- + { + id: 5, + courseId: 1, + chapter: "Глава 2: Файрвол", + title: "Миссия 5: Логический фильтр", + description: "Файрвол пропускает пакеты только если `x` больше 100.", + task: "Задай x = 150. Если x > 100, выведи 'OPEN'.", + initialCode: "x = 150\n# Напиши условие ниже:\n", + expectedOutput: "OPEN", + xp: 200, + hasDebugger: true, + hint: "Используй оператор сравнения '>' внутри блока if.", + hint2: "if x > 50:\n print('Да')" + }, + { + id: 6, + courseId: 1, + chapter: "Глава 2: Файрвол", + title: "Миссия 6: Двойная проверка", + description: "Если статус 'active' — выведи 'READY', иначе — 'ERROR'.", + task: "Задай status = 'active'. Используй if-else.", + initialCode: "status = 'active'\n", + expectedOutput: "READY", + xp: 250, + hasDebugger: true, + hint: "Тебе понадобится блок else для обработки случая, когда условие неверно.", + hint2: "if status == '...':\n ...\nelse:\n ..." + }, + { + id: 7, // БОСС + courseId: 1, + isBoss: true, + chapter: "Глава 2: Файрвол", + title: "⚠️ БОСС: ИИ 'Цербер'", + description: "Цербер требует уровень 3. Выведи 'HIGH'.", + task: "Задай level = 3. Используй if-elif-else, чтобы вывести 'HIGH' для уровня 3.", + initialCode: "level = 3\n", + expectedOutput: "HIGH", + xp: 600, + hint: "Используй elif для проверки нескольких условий подряд.", + hint2: "if l == 1: ...\nelif l == 3: ...\nelse: ..." + }, + + // --- ГЛАВА 3: БРУТФОРС --- + { + id: 8, + courseId: 1, + chapter: "Глава 3: Брутфорс", + title: "Миссия 8: Цикличный взлом", + description: "Нужно 5 раз отправить сигнал 'HACK'.", + task: "Используй цикл for и range(5), чтобы 5 раз вывести слово 'HACK'.", + initialCode: "# Повтори вывод 5 раз\n", + expectedOutput: "HACK\nHACK\nHACK\nHACK\nHACK", + xp: 300, + hasDebugger: true, + hint: "Цикл for i in range(N) выполнит код N раз.", + hint2: "for i in range(5):\n print('...')" + }, + { + id: 9, + courseId: 1, + chapter: "Глава 3: Брутфорс", + title: "Миссия 9: Обратный отсчёт", + description: "Запусти обратный отсчёт: 3, 2, 1.", + task: "Используй цикл, чтобы вывести числа 3, 2, 1.", + initialCode: "# Используй range с тремя параметрами\n", + expectedOutput: "3\n2\n1", + xp: 350, + hasDebugger: true, + hint: "range(start, stop, step) позволяет считать в обратном порядке.", + hint2: "range(3, 0, -1) считает от 3 до 1." + }, + { + id: 10, // БОСС + courseId: 1, + isBoss: true, + chapter: "Глава 3: Брутфорс", + title: "⚠️ БОСС: Подбор пароля", + description: "Выведи попытки 'Try: 0' до 'Try: 3'.", + task: "Используй цикл, чтобы вывести:\nTry: 0\nTry: 1\nTry: 2\nTry: 3", + initialCode: "", + expectedOutput: "Try: 0\nTry: 1\nTry: 2\nTry: 3", + xp: 700, + hint: "Используй f-строки или запятую в print для объединения текста и числа.", + hint2: "print(f'Try: {i}')" + }, + + // --- ГЛАВА 4: БАЗА ДАННЫХ --- + { + id: 11, + courseId: 1, + chapter: "Глава 4: База данных", + title: "Миссия 11: Список сотрудников", + description: "Извлеки первое имя из списка ['Alice', 'Bob', 'Charlie'].", + task: "Создай список names и выведи элемент с индексом 0.", + initialCode: "names = ['Alice', 'Bob', 'Charlie']\n", + expectedOutput: "Alice", + xp: 400, + hasDebugger: true, + hint: "Доступ к элементу списка осуществляется через квадратные скобки [].", + hint2: "print(my_list[0])" + }, + { + id: 12, + courseId: 1, + chapter: "Глава 4: База данных", + title: "Миссия 12: Длина архива", + description: "Посчитай количество файлов в списке [1, 2, 3, 4, 5].", + task: "Выведи длину списка files с помощью функции len().", + initialCode: "files = [1, 2, 3, 4, 5]\n", + expectedOutput: "5", + xp: 450, + hasDebugger: true, + hint: "Функция len() возвращает размер (длину) объекта.", + hint2: "print(len(my_list))" + }, + { + id: 13, // БОСС + courseId: 1, + isBoss: true, + chapter: "Глава 4: База данных", + title: "⚠️ БОСС: Извлечение данных", + description: "Выведи все ID из списка ['ID1', 'ID2'] по одному.", + task: "Используй цикл for, чтобы вывести каждый элемент списка на новой строке.", + initialCode: "ids = ['ID1', 'ID2']\n", + expectedOutput: "ID1\nID2", + xp: 800, + hint: "Цикл for может проходить прямо по элементам списка.", + hint2: "for item in ids:\n print(item)" + }, + + // --- ГЛАВА 5: ФИНАЛ --- + { + id: 14, + courseId: 1, + chapter: "Глава 5: Финальный удар", + title: "Миссия 14: Вирусная функция", + description: "Создай функцию `attack`, которая выводит 'STRIKE'.", + task: "Определи функцию и вызови её.", + initialCode: "# Объяви функцию через def\n", + expectedOutput: "STRIKE", + xp: 500, + hasDebugger: true, + hint: "Сначала напиши определение функции, а затем вызови её по имени со скобками.", + hint2: "def func():\n ...\nfunc()" + }, + { + id: 15, // ФИНАЛЬНЫЙ БОСС + courseId: 1, + isBoss: true, + chapter: "Глава 5: Финальный удар", + title: "🔥 ФИНАЛ: Отключение Левиафана", + description: "Передай функции `shutdown` аргумент 'confirm'.", + task: "Напиши функцию shutdown(msg), которая выводит msg. Вызови её с текстом 'confirm'.", + initialCode: "def shutdown(msg):\n # Твой код тут\n", + expectedOutput: "confirm", + xp: 2000, + hint: "Функция должна принимать один параметр и печатать его.", + hint2: "shutdown('confirm')" + } +]; + +export const courses = [ + { + id: 1, + title: "Операция 'Тихий Шторм'", + desc: 'Проникни в ядро OmniCorp и уничтожь Левиафана. Полный курс Python с интерактивными туториалами.', + level: 'Сюжетная кампания', + color: 'green', + totalLessons: lessons.length + }, + { + id: 2, + title: "Сетевые протоколы (DLC)", + desc: 'Дополнительные задачи на работу со словарями и кортежами. [COMING SOON]', + level: 'Сложный', + color: 'blue', + totalLessons: 0 + } +]; \ No newline at end of file diff --git a/src/data/reputationSystem.ts b/src/data/reputationSystem.ts new file mode 100644 index 0000000..48a9567 --- /dev/null +++ b/src/data/reputationSystem.ts @@ -0,0 +1,113 @@ +// Система репутации в андеграунде + +export interface Faction { + id: string; + name: string; + description: string; + icon: string; + color: string; + bonus: string; + requiredRep: number; +} + +export const factions: Faction[] = [ + { + id: 'data_brokers', + name: 'Торговцы Данными', + description: 'Группа хакеров, специализирующихся на извлечении и продаже информации', + icon: '💾', + color: 'blue', + bonus: '+20% XP за задачи со списками и строками', + requiredRep: 0 + }, + { + id: 'crypto_rebels', + name: 'Крипто-Повстанцы', + description: 'Анархисты, взламывающие финансовые системы', + icon: '🔐', + color: 'violet', + bonus: 'Доступ к шифрованным миссиям', + requiredRep: 500 + }, + { + id: 'ai_ethicists', + name: 'AI-Этики', + description: 'Борются за честный и чистый код', + icon: '🤖', + color: 'cyan', + bonus: '+15% XP за код без ошибок', + requiredRep: 1000 + }, + { + id: 'ghost_protocol', + name: 'Протокол Призрак', + description: 'Элитная группа невидимых операторов', + icon: '👻', + color: 'dark', + bonus: 'Скрытые миссии и эксклюзивный доступ', + requiredRep: 2000 + } +]; + +export interface ReputationState { + [factionId: string]: number; +} + +// Получить репутацию с фракцией +export const getReputation = (factionId: string): number => { + const saved = localStorage.getItem('reputation'); + if (!saved) return 0; + const rep: ReputationState = JSON.parse(saved); + return rep[factionId] || 0; +}; + +// Добавить репутацию +export const addReputation = (factionId: string, amount: number) => { + const saved = localStorage.getItem('reputation'); + const rep: ReputationState = saved ? JSON.parse(saved) : {}; + rep[factionId] = (rep[factionId] || 0) + amount; + localStorage.setItem('reputation', JSON.stringify(rep)); +}; + +// Проверить, доступна ли фракция +export const isFactionUnlocked = (faction: Faction): boolean => { + const totalXP = Number(localStorage.getItem('userXP')) || 0; + return totalXP >= faction.requiredRep; +}; + +// Получить бонусный множитель XP от фракций +export const getXPMultiplier = (): number => { + let multiplier = 1.0; + + // Проверяем репутацию с каждой фракцией + if (getReputation('data_brokers') >= 100) { + multiplier += 0.2; // +20% от Торговцев + } + + if (getReputation('ai_ethicists') >= 150) { + multiplier += 0.15; // +15% от AI-Этиков + } + + return multiplier; +}; + +// Наградить репутацией за выполнение миссии +export const awardMissionReputation = (lessonId: number, wasCleanCode: boolean) => { + // Логика: разные миссии дают репу разным фракциям + if (lessonId >= 11 && lessonId <= 13) { + // Задачи со списками -> Data Brokers + addReputation('data_brokers', 10); + } + + if (wasCleanCode) { + // Чистый код -> AI Ethicists + addReputation('ai_ethicists', 5); + } + + // Боссы дают репу всем + const lesson = [4, 7, 10, 13, 15]; + if (lesson.includes(lessonId)) { + addReputation('crypto_rebels', 15); + addReputation('ghost_protocol', 10); + } +}; \ No newline at end of file diff --git a/src/data/shopItems.ts b/src/data/shopItems.ts new file mode 100644 index 0000000..6000550 --- /dev/null +++ b/src/data/shopItems.ts @@ -0,0 +1,14 @@ +export interface TerminalTheme { + id: string; + name: string; + color: string; // Основной неоновый цвет + bg: string; // Цвет фона + price: number; +} + +export const terminalThemes: TerminalTheme[] = [ + { id: 'classic', name: 'Classic Green', color: '#00FF41', bg: '#050505', price: 0 }, + { id: 'cyberia', name: 'Cyberia Blue', color: '#00FFF9', bg: '#020b12', price: 500 }, + { id: 'blood', name: 'Blood Code', color: '#FF4136', bg: '#0f0202', price: 1000 }, + { id: 'gold', name: 'Elite Gold', color: '#FFD700', bg: '#0a0900', price: 2500 }, +]; \ No newline at end of file diff --git a/src/main.tsx b/src/main.tsx new file mode 100644 index 0000000..d22e0b9 --- /dev/null +++ b/src/main.tsx @@ -0,0 +1,9 @@ +import { StrictMode } from 'react' +import { createRoot } from 'react-dom/client' +import App from './App.tsx' + +createRoot(document.getElementById('root')!).render( + + + , +) \ No newline at end of file diff --git a/src/pages/App.css b/src/pages/App.css new file mode 100644 index 0000000..40cde71 --- /dev/null +++ b/src/pages/App.css @@ -0,0 +1,226 @@ +/* Глобальные стили CodeFlow с динамическими темами */ + +@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;700&display=swap'); + +* { + font-family: 'JetBrains Mono', monospace; +} + +/* ======= ЭФФЕКТ ГЛИТЧА (ИСПОЛЬЗУЕТ CSS-ПЕРЕМЕННУЮ) ======= */ +.glitch { + position: relative; + color: var(--neon-green, #00FF41); + animation: glitch-skew 1s infinite; +} + +.glitch::before, +.glitch::after { + content: attr(data-text); + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; +} + +.glitch::before { + left: 2px; + text-shadow: -2px 0 #ff00de; + clip: rect(24px, 550px, 90px, 0); + animation: glitch-anim 3s infinite linear alternate-reverse; +} + +.glitch::after { + left: -2px; + text-shadow: -2px 0 #00fff9; + clip: rect(85px, 550px, 140px, 0); + animation: glitch-anim 2.5s infinite linear alternate-reverse; +} + +@keyframes glitch-anim { + 0% { clip: rect(61px, 9999px, 52px, 0); } + 10% { clip: rect(94px, 9999px, 35px, 0); } + 20% { clip: rect(43px, 9999px, 71px, 0); } + 30% { clip: rect(12px, 9999px, 88px, 0); } + 40% { clip: rect(77px, 9999px, 26px, 0); } + 50% { clip: rect(38px, 9999px, 104px, 0); } + 60% { clip: rect(90px, 9999px, 15px, 0); } + 70% { clip: rect(25px, 9999px, 66px, 0); } + 80% { clip: rect(55px, 9999px, 99px, 0); } + 90% { clip: rect(70px, 9999px, 41px, 0); } + 100% { clip: rect(33px, 9999px, 82px, 0); } +} + +@keyframes glitch-skew { + 0% { transform: skew(0deg); } + 10% { transform: skew(1deg); } + 20% { transform: skew(0deg); } + 30% { transform: skew(-1deg); } + 40% { transform: skew(0deg); } + 50% { transform: skew(0.5deg); } + 60% { transform: skew(0deg); } + 70% { transform: skew(-0.5deg); } + 80% { transform: skew(0deg); } + 90% { transform: skew(1deg); } + 100% { transform: skew(0deg); } +} + +/* ======= ТРЯСКА ЭКРАНА ПРИ ОШИБКЕ ======= */ +.shake-screen { + animation: shake 0.5s; +} + +@keyframes shake { + 0%, 100% { transform: translate(0, 0); } + 10%, 30%, 50%, 70%, 90% { transform: translate(-5px, 0); } + 20%, 40%, 60%, 80% { transform: translate(5px, 0); } +} + +/* ======= НЕОНОВОЕ СВЕЧЕНИЕ (ДИНАМИЧЕСКОЕ) ======= */ +.neon-text, .neon-glow { + color: var(--neon-green, #00ff41); + text-shadow: + 0 0 5px var(--neon-green, #00ff41), + 0 0 10px var(--neon-green, #00ff41), + 0 0 20px var(--neon-green, #00ff41), + 0 0 40px var(--neon-green, #00ff41); + animation: neon-flicker 1.5s infinite alternate; +} + +@keyframes neon-flicker { + 0%, 19%, 21%, 23%, 25%, 54%, 56%, 100% { + text-shadow: + 0 0 5px var(--neon-green, #00ff41), + 0 0 10px var(--neon-green, #00ff41), + 0 0 20px var(--neon-green, #00ff41), + 0 0 40px var(--neon-green, #00ff41); + } + 20%, 24%, 55% { + text-shadow: none; + } +} + +/* ======= КНОПКИ С ДИНАМИЧЕСКИМ СВЕЧЕНИЕМ ======= */ +button:hover { + box-shadow: 0 0 15px var(--neon-green, rgba(0, 255, 65, 0.5)) !important; + transform: translateY(-2px); + transition: all 0.2s; +} + +button:active { + transform: translateY(0); +} + +/* ======= ТЕРМИНАЛЬНЫЙ КУРСОР ======= */ +.terminal-cursor::after { + content: '█'; + animation: blink 1s step-end infinite; + color: var(--neon-green, #00ff41); +} + +@keyframes blink { + 0%, 50% { opacity: 1; } + 51%, 100% { opacity: 0; } +} + +/* ======= ПРОКРУТКА С ДИНАМИЧЕСКИМ ЦВЕТОМ ======= */ +::-webkit-scrollbar { + width: 8px; + height: 8px; +} + +::-webkit-scrollbar-track { + background: #0a0a0a; +} + +::-webkit-scrollbar-thumb { + background: var(--neon-green, #00ff41); + border-radius: 4px; +} + +::-webkit-scrollbar-thumb:hover { + background: var(--neon-green, #00cc33); + box-shadow: 0 0 10px var(--neon-green, rgba(0,255,65,0.8)); +} + +/* ======= АНИМАЦИЯ ПОЯВЛЕНИЯ ======= */ +.fade-in { + animation: fadeIn 0.5s ease-in; +} + +@keyframes fadeIn { + from { opacity: 0; transform: translateY(20px); } + to { opacity: 1; transform: translateY(0); } +} + +/* ======= КАРТОЧКИ С ЭФФЕКТОМ HOVER ======= */ +.cyber-card { + transition: all 0.3s ease; + border: 1px solid transparent; +} + +.cyber-card:hover { + border-color: var(--neon-green, #00ff41); + box-shadow: 0 0 20px var(--neon-green, rgba(0, 255, 65, 0.2)); + transform: translateY(-5px); +} + +/* ======= КРАСНЫЙ РЕЖИМ ДЛЯ БОССОВ ======= */ +.boss-mode { + animation: red-pulse 2s infinite; +} + +@keyframes red-pulse { + 0%, 100% { + box-shadow: 0 0 10px rgba(255, 0, 0, 0.3); + } + 50% { + box-shadow: 0 0 30px rgba(255, 0, 0, 0.8); + } +} + +/* ======= ТИПОГРАФИЯ ======= */ +h1, h2, h3, h4, h5, h6 { + letter-spacing: 0.05em; +} + +code, pre { + font-family: 'JetBrains Mono', monospace !important; + background: #0a0a0a; + padding: 2px 6px; + border-radius: 3px; + border: 1px solid #1a1a1a; +} + +/* ======= БЕЙДЖИ С ДИНАМИЧЕСКИМ СВЕЧЕНИЕМ ======= */ +.badge-glow { + box-shadow: 0 0 10px var(--neon-green, currentColor); + animation: pulse-glow 2s infinite; +} + +@keyframes pulse-glow { + 0%, 100% { box-shadow: 0 0 5px var(--neon-green, currentColor); } + 50% { box-shadow: 0 0 15px var(--neon-green, currentColor); } +} + +/* ======= ДИНАМИЧЕСКИЙ КУРСОР (ЧЕРЕЗ CSS-ПЕРЕМЕННУЮ) ======= */ +* { + cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Ctext x='0' y='20' font-family='monospace' font-size='20' fill='%2300ff41'%3E▸%3C/text%3E%3C/svg%3E"), auto; +} + +button, a { + cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Ctext x='0' y='20' font-family='monospace' font-size='20' fill='%2300ff41'%3E⬢%3C/text%3E%3C/svg%3E"), pointer; +} + +/* Для boss mode */ +[data-boss-mode="true"] * { + cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Ctext x='0' y='20' font-family='monospace' font-size='20' fill='%23ff0000'%3E▸%3C/text%3E%3C/svg%3E"), auto; +} + +/* ======= АДАПТИВ ======= */ +@media (max-width: 768px) { + .glitch::before, + .glitch::after { + display: none; /* Упрощаем на мобилках */ + } +} \ No newline at end of file diff --git a/src/pages/CoursesPage.tsx b/src/pages/CoursesPage.tsx new file mode 100644 index 0000000..8f26d2a --- /dev/null +++ b/src/pages/CoursesPage.tsx @@ -0,0 +1,83 @@ +import { Container, Title, SimpleGrid, Card, Text, Badge, Button, Group, Progress } from '@mantine/core'; +import { Link } from 'react-router-dom'; +import { courses, lessons } from '../data/lessons'; +import { motion } from 'framer-motion'; +import { useEffect, useState } from 'react'; + +const CoursesPage = () => { + const [completedLessons, setCompletedLessons] = useState([]); + + useEffect(() => { + const savedProgress = localStorage.getItem('completedLessons'); + if (savedProgress) { + setCompletedLessons(JSON.parse(savedProgress)); + } + }, []); + + return ( + + + // ДОСТУПНЫЕ ОПЕРАЦИИ + + + + + {courses.map((course, index) => { + // Расчет прогресса (остается без изменений) + const completedCount = lessons.filter(lesson => + lesson.courseId === course.id && completedLessons.includes(lesson.id) + ).length; + const progressPercent = course.totalLessons > 0 ? (completedCount / course.totalLessons) * 100 : 0; + + // --- НОВАЯ УМНАЯ ЛОГИКА ДЛЯ КНОПКИ --- + // 1. Находим все уроки, относящиеся к этому курсу + const lessonsInCourse = lessons.filter(l => l.courseId === course.id); + + // 2. Находим первый урок, которого НЕТ в списке пройденных + const nextLesson = lessonsInCourse.find(l => !completedLessons.includes(l.id)); + + // 3. Определяем, куда вести пользователя + const isCourseCompleted = !nextLesson; // Если следующий урок не найден, курс пройден + const buttonLink = isCourseCompleted ? "#" : `/lesson/${nextLesson.id}`; + const buttonText = isCourseCompleted ? "ОПЕРАЦИЯ ЗАВЕРШЕНА" : "ПРОДОЛЖИТЬ ОПЕРАЦИЮ"; + // --- КОНЕЦ НОВОЙ ЛОГИКИ --- + + return ( + + + + {course.title} + {course.level} + + + + {course.desc} + + + Прогресс выполнения: {completedCount} / {course.totalLessons} + + + + + + ); + })} + + + ); +}; + +export default CoursesPage; \ No newline at end of file diff --git a/src/pages/HomePage.tsx b/src/pages/HomePage.tsx new file mode 100644 index 0000000..c0721a0 --- /dev/null +++ b/src/pages/HomePage.tsx @@ -0,0 +1,149 @@ +import { Container, Title, Text, Button, Group, Stack, SimpleGrid, Card, Badge } from '@mantine/core'; +import { Link } from 'react-router-dom'; +import { Typewriter } from 'react-simple-typewriter'; +import { IconRocket, IconTrophy, IconShoppingCart, IconUser } from '@tabler/icons-react'; +import { motion } from 'framer-motion'; + +const HomePage = () => { + const userXP = Number(localStorage.getItem('userXP')) || 0; + + return ( + + + {/* ЛОГОТИП */} + + + <Typewriter words={["[ CodeFlow ]"]} cursor cursorStyle="_" /> + + + + {/* ПОДЗАГОЛОВОК */} + + // СИСТЕМА ГОТОВА К ПОДКЛЮЧЕНИЮ + + + {/* ОПИСАНИЕ */} + + + Ты — последняя надежда сопротивления. Проникни в сеть OmniCorp и разрушь систему изнутри. + Овладей Python, взломай защиту и стань легендой. + + + + {/* ГЛАВНАЯ КНОПКА */} + + + + + {/* БЫСТРЫЙ ДОСТУП */} + + + + + ПРОФИЛЬ + {userXP} XP + + + + + + + МАГАЗИН + Темы терминала + + + + + + + РЕЙТИНГ + Топ хакеров + + + + + + + СТАТУС + ONLINE + + + + + {/* ФУТЕР */} + + v2.0.0 | © 2026 CodeFlow Terminal | Powered by Pyodide & React + + + + ); +}; + +export default HomePage; \ No newline at end of file diff --git a/src/pages/LeaderboardPage.tsx b/src/pages/LeaderboardPage.tsx new file mode 100644 index 0000000..b151b5b --- /dev/null +++ b/src/pages/LeaderboardPage.tsx @@ -0,0 +1,76 @@ +import { Container, Title, Table, Avatar, Group, Text, Button, Paper } from '@mantine/core'; +import { Link } from 'react-router-dom'; +import { useEffect, useState } from 'react'; + +// 1. Описываем структуру объекта пользователя для TypeScript +interface UserRank { + id: number; + name: string; + xp: number; + avatar: string; + isMe?: boolean; +} + +const fakeUsers: UserRank[] = [ + { id: 1, name: "AlexCode", xp: 2500, avatar: "AC" }, + { id: 2, name: "PythonMaster", xp: 2100, avatar: "PM" }, + { id: 3, name: "Ivan2025", xp: 1800, avatar: "IV" }, + { id: 4, name: "Kate_Dev", xp: 1500, avatar: "KD" }, +]; + +const LeaderboardPage = () => { + const [users, setUsers] = useState(fakeUsers); + + useEffect(() => { + const myXP = Number(localStorage.getItem('userXP')) || 0; + const me: UserRank = { id: 99, name: "Вы (Студент)", xp: myXP, avatar: "ME", isMe: true }; + + const allUsers = [...fakeUsers, me].sort((a, b) => b.xp - a.xp); + setUsers(allUsers); + }, []); + + return ( + + + // РЕЙТИНГ_ОПЕРАТИВНИКОВ + + + + + + + + # + Студент + XP + + + + {/* 2. Указываем типы в map для исправления ошибки 7006 */} + {users.map((user: UserRank, index: number) => ( + + + {index === 0 && "🥇"} + {index === 1 && "🥈"} + {index === 2 && "🥉"} + {index > 2 && index + 1} + + + + {user.avatar} + {user.name} + + + + {user.xp} + + + ))} + +
+
+
+ ); +}; + +export default LeaderboardPage; \ No newline at end of file diff --git a/src/pages/LessonPage.tsx b/src/pages/LessonPage.tsx new file mode 100644 index 0000000..54a4d95 --- /dev/null +++ b/src/pages/LessonPage.tsx @@ -0,0 +1,382 @@ +import Editor from '@monaco-editor/react'; +import { useState, useEffect } from 'react'; +import { useParams, useNavigate } from 'react-router-dom'; +import confetti from 'canvas-confetti'; +import { + Button, Title, Text, Paper, Group, Badge, Notification, + Stack, Center, Box, Collapse, Tooltip, ActionIcon, Tabs +} from '@mantine/core'; +import { + IconBulb, IconClock, IconRocket, IconTerminal, IconFileCode, IconReload, IconAlertTriangle +} from '@tabler/icons-react'; + +// Импорты данных и компонентов +import { lessons } from '../data/lessons'; +import { achievements } from '../data/achievements'; +import { createGlitchState, glitchAvatars } from '../data/glitchCharacter'; +import { TimeDebugger } from '../components/TimeDebugger'; +import { InteractiveTheory } from '../components/InteractiveTheory'; +import { HackerConsole } from '../components/HackerConsole'; +import { MoralChoice } from '../components/MoralChoice'; +import { awardMissionReputation, getXPMultiplier } from '../data/reputationSystem'; +import { music } from '../utils/adaptiveMusic'; +import { Typewriter } from 'react-simple-typewriter'; +import { motion, AnimatePresence } from 'framer-motion'; +import { sounds } from '../utils/audio'; + +declare global { + interface Window { loadPyodide: any; } +} + +const LessonPage = () => { + const { id } = useParams(); + const navigate = useNavigate(); + const lessonId = Number(id); + const currentLesson = lessons.find(l => l.id === lessonId); + + // --- СОСТОЯНИЯ --- + const [code, setCode] = useState(""); + const [output, setOutput] = useState(""); + const [isLoading, setIsLoading] = useState(false); + const [isError, setIsError] = useState(false); + const [errorCount, setErrorCount] = useState(0); + const [glitchState, setGlitchState] = useState(createGlitchState({ type: 'welcome' })); + const [notification, setNotification] = useState<{ type: 'success' | 'fail' | null, message: string }>({ type: null, message: '' }); + const [showDebugger, setShowDebugger] = useState(false); + const [showHint, setShowHint] = useState(false); + const [moralModalOpened, setMoralModalOpened] = useState(false); + + const [timeLeft, setTimeLeft] = useState(null); + const [unlockedHints, setUnlockedHints] = useState(0); + + const isBossMode = currentLesson?.isBoss || false; + const themeColor = isBossMode ? 'red' : 'green'; + const terminalTextColor = isBossMode ? '#FF4136' : '#00FF41'; + const borderColor = isBossMode ? '#FF4136' : '#1A1B1E'; + + // --- ЛОГИКА ТАЙМЕРА --- + useEffect(() => { + if (isBossMode) { + setTimeLeft(60); + } else { + setTimeLeft(null); + } + }, [lessonId, isBossMode]); + + useEffect(() => { + if (timeLeft === 0 && !notification.type) { + sounds.error(); + setIsError(true); + setNotification({ type: 'fail', message: 'СИСТЕМА ОБНАРУЖЕНА! Время истекло. OmniCorp заблокировал ваш доступ.' }); + } + + if (timeLeft !== null && timeLeft > 0 && notification.type !== 'success') { + const timer = setTimeout(() => setTimeLeft(timeLeft - 1), 1000); + return () => clearTimeout(timer); + } + }, [timeLeft, notification.type]); + + // --- ЛОГИКА ПОКУПКИ ПОДСКАЗОК --- + const buyHint = () => { + const currentXP = Number(localStorage.getItem('userXP')) || 0; + const price = unlockedHints === 0 ? 50 : 150; + + if (currentXP >= price) { + localStorage.setItem('userXP', String(currentXP - price)); + setUnlockedHints(prev => prev + 1); + sounds.success(); + setGlitchState(createGlitchState({ type: 'hint' })); + } else { + sounds.error(); + alert("НЕДОСТАТОЧНО XP!"); + } + }; + + // --- ЛОГИКА ПЛАТНОГО РЕСТАРТА --- + const handleRestart = () => { + const RESTART_PRICE = 50; // Цена жизни + const currentXP = Number(localStorage.getItem('userXP')) || 0; + + if (currentXP >= RESTART_PRICE) { + // Списываем XP + localStorage.setItem('userXP', String(currentXP - RESTART_PRICE)); + + // Сбрасываем состояние + setTimeLeft(60); + setNotification({ type: null, message: '' }); + setIsError(false); + setOutput(`> СИСТЕМА ПЕРЕЗАГРУЖЕНА (-${RESTART_PRICE} XP)\n> ПРОТОКОЛ ВЗЛОМА ПЕРЕЗАПУЩЕН...`); + sounds.click(); + } else { + // Если денег нет + sounds.error(); + alert(`КРИТИЧЕСКАЯ ОШИБКА: Недостаточно энергии (XP) для перезагрузки! Требуется: ${RESTART_PRICE} XP.`); + } + }; + + useEffect(() => { + if (currentLesson) { + setCode(currentLesson.initialCode); + setNotification({ type: null, message: '' }); + setIsError(false); + setErrorCount(0); + setUnlockedHints(0); + setShowDebugger(false); + + if (isBossMode) { + window.dispatchEvent(new Event('boss-mode-on')); + document.body.setAttribute('data-boss-mode', 'true'); + music.start('boss'); + setOutput("⚠️ WARNING: HIGH-LEVEL ENCRYPTION DETECTED\n⚠️ SYSTEM OVERRIDE IN PROGRESS...\n⚠️ INTRUSION ALERT!\n"); + sounds.siren(); + setGlitchState(createGlitchState({ type: 'boss', isBoss: true })); + } else { + window.dispatchEvent(new Event('boss-mode-off')); + document.body.removeAttribute('data-boss-mode'); + music.start('ambient'); + setOutput(""); + setGlitchState(createGlitchState({ type: 'welcome' })); + } + + const interval = setInterval(() => { sounds.type(); }, 80); + const timer = setTimeout(() => { clearInterval(interval); }, 1500); + + return () => { + clearInterval(interval); + clearTimeout(timer); + music.stop(); + window.dispatchEvent(new Event('boss-mode-off')); + document.body.removeAttribute('data-boss-mode'); + }; + } + }, [lessonId, isBossMode]); + + const handleRunUpdated = async () => { + if (timeLeft === 0) return; + + sounds.click(); + music.start('coding'); + setIsLoading(true); + setIsError(false); + + setOutput(`> ИНИЦИАЛИЗАЦИЯ ВЗЛОМА...\n> АНАЛИЗ ЗАЩИТЫ...\n`); + setNotification({ type: null, message: '' }); + + await new Promise(res => setTimeout(res, 1000)); + + try { + if (!window.loadPyodide) throw new Error("Среда Python не готова..."); + const pyodide = await window.loadPyodide(); + + let currentOutput = ""; + pyodide.setStdout({ + batched: (msg: string) => { + currentOutput += msg + "\n"; + setOutput((prev) => prev + msg + "\n"); + }, + }); + + await pyodide.runPythonAsync(code); + + if (currentOutput.trim() === currentLesson?.expectedOutput) { + music.start('victory'); + sounds.success(); + setGlitchState(createGlitchState({ type: 'success', isSuccess: true })); + + confetti({ + particleCount: 150, spread: 70, origin: { y: 0.6 }, + colors: isBossMode ? ['#FF0000', '#FF4136'] : ['#00FF41', '#FFFFFF'] + }); + + const finalXP = Math.floor(currentLesson.xp * getXPMultiplier()); + localStorage.setItem('userXP', String((Number(localStorage.getItem('userXP')) || 0) + finalXP)); + + awardMissionReputation(lessonId, errorCount === 0); + + const completedRaw = localStorage.getItem('completedLessons'); + const completed: number[] = completedRaw ? JSON.parse(completedRaw) : []; + if (!completed.includes(lessonId)) { + completed.push(lessonId); + localStorage.setItem('completedLessons', JSON.stringify(completed)); + } + + let achievementMessage = ""; + const stats = { completedCount: completed.length, completedIds: completed, totalXP: Number(localStorage.getItem('userXP')) }; + const unlockedRaw = localStorage.getItem('unlockedAchievements'); + let unlocked: string[] = unlockedRaw ? JSON.parse(unlockedRaw) : []; + + achievements.forEach(ach => { + if (!unlocked.includes(ach.id) && ach.condition(stats)) { + unlocked.push(ach.id); + localStorage.setItem('unlockedAchievements', JSON.stringify(unlocked)); + achievementMessage += `\n🏆 ДОСТИЖЕНИЕ: ${ach.title}!`; + sounds.success(); + } + }); + + setNotification({ + type: 'success', + message: `ДОСТУП ПОЛУЧЕН! +${finalXP} XP${achievementMessage}` + }); + + if (isBossMode) { + setTimeout(() => setMoralModalOpened(true), 2000); + } + + setErrorCount(0); + } else { + sounds.error(); + setIsError(true); + setErrorCount(prev => prev + 1); + setGlitchState(createGlitchState({ type: 'error', isError: true, errorCount: errorCount + 1 })); + setOutput(`> ОШИБКА: Доступ запрещен. Неверный ключ.\n> СИСТЕМА ВЕРНУЛА: ${currentOutput.trim()}`); + setNotification({ type: 'fail', message: 'ВЗЛОМ ПРЕРВАН: Неверный результат.' }); + music.start('ambient'); + } + } catch (err: any) { + sounds.error(); + setIsError(true); + setErrorCount(prev => prev + 1); + setGlitchState(createGlitchState({ type: 'error', isError: true, errorCount: errorCount + 1 })); + setOutput(`> СИСТЕМНЫЙ СБОЙ:\n${err.message}`); + setNotification({ type: 'fail', message: 'КРИТИЧЕСКАЯ ОШИБКА В КОДЕ!' }); + music.start('ambient'); + } finally { + setIsLoading(false); + } + }; + + if (!currentLesson) return
; + + return ( + + + + setMoralModalOpened(false)} chapter={currentLesson.chapter} /> + + {/* HEADER */} + + + + {isBossMode ? "[ ⚠️ BOSS_LEVEL ]" : "[ CODEFLOW_TERMINAL_V.2.0 ]"} + + + + + + {currentLesson.hasDebugger && ( + setShowDebugger(!showDebugger)}> + )} + + + + +
+ + {/* LEFT PANEL */} + +
+ + {/* --- ТАЙМЕР ЗДЕСЬ (В ЛЕВОЙ ЧАСТИ) --- */} + {timeLeft !== null && ( + + + + ДО ОБНАРУЖЕНИЯ: {timeLeft}s + + + )} + + {/* ГЛИТЧ ПЕРСОНАЖ */} + + GLITCH_AI [{glitchState.mood.toUpperCase()}] +
{glitchAvatars[glitchState.mood]}
+ + + +
+ + + {unlockedHints > 0 && ( + + + {unlockedHints === 1 ? "HINT:" : "SOLUTION:"} + {unlockedHints === 1 ? currentLesson.hint : currentLesson.hint2} + + + )} + + + setShowDebugger(false)} /> + + {currentLesson.chapter} + {currentLesson.title} + + + MISSION_DETAILS: + setCode(prev => prev + "\n" + c)} /> + + + + OBJECTIVE: + {currentLesson.task} + + + {/* УМНАЯ КНОПКА С ЦЕНОЙ */} + + + + {notification.type && ( + + + {notification.message} + {notification.type === 'success' && lessons.find(l => l.id === lessonId + 1) && ( + + )} + + + )} + +
+
+ + {/* RIGHT PANEL */} +
+
+ setCode(v || "")} options={{ minimap: { enabled: false }, fontSize: 16, fontFamily: 'JetBrains Mono' }} /> +
+ +
+ + + }>PYTHON_OUTPUT + }>SYSTEM_CONSOLE + + + +
{output}
+
+ + +
+
+
+
+
+
+ ); +}; + +export default LessonPage; \ No newline at end of file diff --git a/src/pages/ProfilePage.tsx b/src/pages/ProfilePage.tsx new file mode 100644 index 0000000..b52cc23 --- /dev/null +++ b/src/pages/ProfilePage.tsx @@ -0,0 +1,188 @@ +import { Container, Title, Text, Paper, Group, RingProgress, Stack, Button, Badge, SimpleGrid, Progress } from '@mantine/core'; +import { Link } from 'react-router-dom'; +import { useEffect, useState } from 'react'; +import { achievements } from '../data/achievements'; +import { factions, getReputation, isFactionUnlocked, type ReputationState } from '../data/reputationSystem'; + +const ProfilePage = () => { + const [xp, setXp] = useState(0); + const [unlockedIds, setUnlockedIds] = useState([]); + const [reputation, setReputation] = useState({}); + + useEffect(() => { + setXp(Number(localStorage.getItem('userXP')) || 0); + setUnlockedIds(JSON.parse(localStorage.getItem('unlockedAchievements') || '[]')); + + // Загружаем репутацию + const savedRep = localStorage.getItem('reputation'); + if (savedRep) { + setReputation(JSON.parse(savedRep)); + } + }, []); + + // Логика рангов + const getRank = (xp: number) => { + if (xp >= 2000) return { name: "ROOT_ADMIN", color: "red", level: 5 }; + if (xp >= 1000) return { name: "CYBER_GHOST", color: "grape", level: 4 }; + if (xp >= 500) return { name: "OPERATOR", color: "blue", level: 3 }; + if (xp >= 200) return { name: "CODER", color: "cyan", level: 2 }; + return { name: "SCRIPT_KIDDIE", color: "gray", level: 1 }; + }; + + const rank = getRank(xp); + const level = Math.floor(xp / 500) + 1; + const xpToNextLevel = 500 - (xp % 500); + + return ( + + + + + {/* ОСНОВНОЙ ПРОФИЛЬ */} + + + + + LVL {level} + + } + /> + + + {rank.name} + + USER_ID: OPERATIVE + {xp} XP TOTAL + + До следующего уровня: {xpToNextLevel} XP + + + + + {/* Статистика */} + + + Миссий завершено: {JSON.parse(localStorage.getItem('completedLessons') || '[]').length} + + + Достижений: {unlockedIds.length} / {achievements.length} + + + + + + {/* РЕПУТАЦИЯ С ФРАКЦИЯМИ */} +
+ // РЕПУТАЦИЯ В АНДЕГРАУНДЕ + + {factions.map(faction => { + const rep = getReputation(faction.id); + const isUnlocked = isFactionUnlocked(faction); + const repPercent = Math.min((rep / 200) * 100, 100); + + return ( + + + {faction.icon} +
+ {faction.name} + {faction.description} +
+
+ + {isUnlocked ? ( + <> + + + + {rep} REP + + + {faction.bonus} + + + + ) : ( + + 🔒 Требуется {faction.requiredRep} XP + + )} +
+ ); + })} +
+
+ + {/* ДОСТИЖЕНИЯ */} +
+ // ДОСТИЖЕНИЯ + + {achievements.map(ach => { + const isUnlocked = unlockedIds.includes(ach.id); + return ( + + + {ach.icon} +
+ {ach.title} + {ach.description} +
+
+ {isUnlocked && ( + + ✓ Разблокировано + + )} +
+ ); + })} +
+
+ + {/* ОПАСНАЯ ЗОНА */} + + ⚠️ ОПАСНАЯ ЗОНА + + Это действие удалит ВСЕ ваши данные: прогресс, достижения, репутацию. Восстановление невозможно. + + + +
+
+ ); +}; + +export default ProfilePage; \ No newline at end of file diff --git a/src/pages/ShopPage.tsx b/src/pages/ShopPage.tsx new file mode 100644 index 0000000..30601cf --- /dev/null +++ b/src/pages/ShopPage.tsx @@ -0,0 +1,174 @@ +import { Container, Title, SimpleGrid, Card, Text, Button, Stack, Box } from '@mantine/core'; +import { Link } from 'react-router-dom'; +import { useState, useEffect } from 'react'; +import { terminalThemes } from '../data/shopItems'; +import { sounds } from '../utils/audio'; +import { motion } from 'framer-motion'; + +const ShopPage = () => { + const [xp, setXp] = useState(0); + const [ownedThemes, setOwnedThemes] = useState(['classic']); + const [activeTheme, setActiveTheme] = useState('classic'); + + useEffect(() => { + setXp(Number(localStorage.getItem('userXP')) || 0); + setOwnedThemes(JSON.parse(localStorage.getItem('ownedThemes') || '["classic"]')); + setActiveTheme(localStorage.getItem('activeTheme') || 'classic'); + }, []); + + const handleBuy = (themeId: string, price: number) => { + if (xp >= price) { + const newXP = xp - price; + const newOwned = [...ownedThemes, themeId]; + + localStorage.setItem('userXP', String(newXP)); + localStorage.setItem('ownedThemes', JSON.stringify(newOwned)); + + setXp(newXP); + setOwnedThemes(newOwned); + sounds.success(); + } else { + sounds.error(); + alert('⚠️ НЕДОСТАТОЧНО XP!'); + } + }; + + const handleSelect = (themeId: string) => { + localStorage.setItem('activeTheme', themeId); + setActiveTheme(themeId); + sounds.click(); + + // Диспатчим кастомное событие для обновления App.tsx БЕЗ перезагрузки + window.dispatchEvent(new Event('theme-changed')); + window.dispatchEvent(new Event('storage')); + }; + + return ( + + + {/* HEADER */} +
+ + + // ЧЕРНЫЙ_РЫНОК + + + 💰 БАЛАНС: {xp} XP + + + +
+ + {/* ТОВАРЫ */} + + {terminalThemes.map((theme, index) => { + const isOwned = ownedThemes.includes(theme.id); + const isActive = activeTheme === theme.id; + + return ( + + + {/* ПРЕВЬЮ */} + + + PREVIEW + + + {/* Эффект сканлайнов на превью */} +
+ + + {/* НАЗВАНИЕ */} + + {theme.name} + + + {/* КНОПКА */} + {isOwned ? ( + + ) : ( + + )} + + + ); + })} + + + {/* ИНФО */} + + + 💡 СОВЕТ: Темы меняют весь интерфейс: неон, курсор, глитч-эффекты. + Зарабатывай XP за прохождение миссий и покупай эксклюзивные темы! + + + + + ); +}; + +export default ShopPage; \ No newline at end of file diff --git a/src/utils/adaptiveMusic.ts b/src/utils/adaptiveMusic.ts new file mode 100644 index 0000000..4ca1a66 --- /dev/null +++ b/src/utils/adaptiveMusic.ts @@ -0,0 +1,177 @@ +// Система адаптивной музыки через Web Audio API + +class AdaptiveMusic { + private audioContext: AudioContext | null = null; + private currentLayer: 'ambient' | 'coding' | 'boss' | 'victory' | null = null; + private oscillators: OscillatorNode[] = []; + private gainNodes: GainNode[] = []; + + constructor() { + try { + this.audioContext = new (window.AudioContext || (window as any).webkitAudioContext)(); + } catch (e) { + console.warn('Audio not supported'); + } + } + + // Запустить фоновый трек + start(layer: 'ambient' | 'coding' | 'boss' | 'victory') { + if (!this.audioContext) return; + + // Останавливаем предыдущий трек + this.stop(); + this.currentLayer = layer; + + switch (layer) { + case 'ambient': + this.playAmbient(); + break; + case 'coding': + this.playCoding(); + break; + case 'boss': + this.playBoss(); + break; + case 'victory': + this.playVictory(); + break; + } + } + + // Остановить всё + stop() { + this.oscillators.forEach(osc => { + try { + osc.stop(); + } catch {} + }); + this.oscillators = []; + this.gainNodes = []; + } + + // Ambient: тихий синт-пэд + private playAmbient() { + if (!this.audioContext) return; + + const freqs = [130.81, 164.81, 196.00]; // C3, E3, G3 + const now = this.audioContext.currentTime; + + freqs.forEach((freq, i) => { + const osc = this.audioContext!.createOscillator(); + const gain = this.audioContext!.createGain(); + + osc.type = 'sine'; + osc.frequency.setValueAtTime(freq, now); + gain.gain.setValueAtTime(0, now); + gain.gain.linearRampToValueAtTime(0.02, now + 2 + i * 0.5); + + osc.connect(gain); + gain.connect(this.audioContext!.destination); + osc.start(); + + this.oscillators.push(osc); + this.gainNodes.push(gain); + }); + } + + // Coding: добавляем ритмичные биты + private playCoding() { + this.playAmbient(); // Базовый слой + + if (!this.audioContext) return; + + // Добавляем "удары барабана" (низкий синт) + const kickPattern = () => { + const osc = this.audioContext!.createOscillator(); + const gain = this.audioContext!.createGain(); + const now = this.audioContext!.currentTime; + + osc.type = 'sine'; + osc.frequency.setValueAtTime(80, now); + osc.frequency.exponentialRampToValueAtTime(40, now + 0.1); + + gain.gain.setValueAtTime(0.3, now); + gain.gain.exponentialRampToValueAtTime(0.01, now + 0.3); + + osc.connect(gain); + gain.connect(this.audioContext!.destination); + osc.start(); + osc.stop(now + 0.3); + }; + + // Играем kick каждые 0.5 секунды + const interval = setInterval(kickPattern, 500); + + // Останавливаем через 30 секунд (или при смене слоя) + setTimeout(() => clearInterval(interval), 30000); + } + + // Boss: быстрый, агрессивный + private playBoss() { + if (!this.audioContext) return; + + const now = this.audioContext.currentTime; + const freqs = [110, 138.59, 164.81]; // Минорный аккорд + + freqs.forEach((freq, i) => { + const osc = this.audioContext!.createOscillator(); + const gain = this.audioContext!.createGain(); + + osc.type = 'sawtooth'; // Более агрессивный звук + osc.frequency.setValueAtTime(freq, now); + gain.gain.setValueAtTime(0.04, now); + + osc.connect(gain); + gain.connect(this.audioContext!.destination); + osc.start(); + + this.oscillators.push(osc); + this.gainNodes.push(gain); + }); + + // Быстрая пульсация + const pulse = () => { + this.gainNodes.forEach(g => { + const now = this.audioContext!.currentTime; + g.gain.setValueAtTime(0.04, now); + g.gain.linearRampToValueAtTime(0.06, now + 0.2); + g.gain.linearRampToValueAtTime(0.04, now + 0.4); + }); + }; + + const pulseInterval = setInterval(pulse, 400); + setTimeout(() => clearInterval(pulseInterval), 30000); + } + + // Victory: мажорная мелодия + private playVictory() { + if (!this.audioContext) return; + + const melody = [ + { freq: 523.25, time: 0 }, // C5 + { freq: 659.25, time: 0.3 }, // E5 + { freq: 783.99, time: 0.6 }, // G5 + { freq: 1046.50, time: 0.9 }, // C6 + ]; + + melody.forEach(({ freq, time }) => { + const osc = this.audioContext!.createOscillator(); + const gain = this.audioContext!.createGain(); + const now = this.audioContext!.currentTime + time; + + osc.type = 'triangle'; + osc.frequency.setValueAtTime(freq, now); + + gain.gain.setValueAtTime(0.1, now); + gain.gain.exponentialRampToValueAtTime(0.01, now + 0.5); + + osc.connect(gain); + gain.connect(this.audioContext!.destination); + osc.start(now); + osc.stop(now + 0.5); + }); + } +} + +// Экспортируем единственный экземпляр +export const music = new AdaptiveMusic(); \ No newline at end of file diff --git a/src/utils/audio.ts b/src/utils/audio.ts new file mode 100644 index 0000000..4115369 --- /dev/null +++ b/src/utils/audio.ts @@ -0,0 +1,71 @@ +// Утилита для генерации "компьютерного" звука через код (Web Audio API) +const playSynthSound = (freq: number, type: OscillatorType, duration: number) => { + try { + const audioCtx = new (window.AudioContext || (window as any).webkitAudioContext)(); + const oscillator = audioCtx.createOscillator(); + const gainNode = audioCtx.createGain(); + + oscillator.type = type; + oscillator.frequency.setValueAtTime(freq, audioCtx.currentTime); + + gainNode.gain.setValueAtTime(0.1, audioCtx.currentTime); + gainNode.gain.exponentialRampToValueAtTime(0.0001, audioCtx.currentTime + duration); + + oscillator.connect(gainNode); + gainNode.connect(audioCtx.destination); + + oscillator.start(); + oscillator.stop(audioCtx.currentTime + duration); + } catch (e) { + console.error("Audio error:", e); + } +}; + +export const sounds = { + // Короткий хакерский клик + click: () => playSynthSound(800, 'square', 0.05), + + // Звук успеха (двойной писк вверх) + success: () => { + playSynthSound(600, 'sine', 0.2); + setTimeout(() => playSynthSound(900, 'sine', 0.4), 100); + }, + + // Звук ошибки (низкий гул) + error: () => { + playSynthSound(150, 'sawtooth', 0.5); + }, + + // Звук печати текста (очень короткий) + type: () => playSynthSound(1200, 'sine', 0.01), + + // Исправленная сирена + siren: () => { + try { + const audioCtx = new (window.AudioContext || (window as any).webkitAudioContext)(); + const oscillator = audioCtx.createOscillator(); + const gainNode = audioCtx.createGain(); + + oscillator.type = 'sine'; + const now = audioCtx.currentTime; + + // Имитируем звук сирены, меняя частоту туда-сюда + oscillator.frequency.setValueAtTime(300, now); + oscillator.frequency.exponentialRampToValueAtTime(600, now + 0.5); + oscillator.frequency.exponentialRampToValueAtTime(300, now + 1.0); + oscillator.frequency.exponentialRampToValueAtTime(600, now + 1.5); + oscillator.frequency.exponentialRampToValueAtTime(300, now + 2.0); + + gainNode.gain.setValueAtTime(0.05, now); // Очень тихо + gainNode.gain.linearRampToValueAtTime(0, now + 2.0); // Плавное затухание в конце + + oscillator.connect(gainNode); + gainNode.connect(audioCtx.destination); + + oscillator.start(); + oscillator.stop(now + 2.0); + } catch (e) { + console.error("Siren error:", e); + } + } +}; \ No newline at end of file diff --git a/tsconfig.app.json b/tsconfig.app.json new file mode 100644 index 0000000..794fb60 --- /dev/null +++ b/tsconfig.app.json @@ -0,0 +1,29 @@ +{ + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + "target": "ES2022", + "useDefineForClassFields": true, + "lib": ["ES2022", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + + /* Добавь или проверь это */ + "types": ["vite/client"] + }, + "include": ["src"] +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..1ffef60 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,7 @@ +{ + "files": [], + "references": [ + { "path": "./tsconfig.app.json" }, + { "path": "./tsconfig.node.json" } + ] +} diff --git a/tsconfig.node.json b/tsconfig.node.json new file mode 100644 index 0000000..8a67f62 --- /dev/null +++ b/tsconfig.node.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + "target": "ES2023", + "lib": ["ES2023"], + "module": "ESNext", + "types": ["node"], + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "moduleDetection": "force", + "noEmit": true, + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "erasableSyntaxOnly": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/vercel.json b/vercel.json new file mode 100644 index 0000000..572a48d --- /dev/null +++ b/vercel.json @@ -0,0 +1,3 @@ +{ + "rewrites": [{ "source": "/(.*)", "destination": "/" }] +} \ No newline at end of file diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..2dea53a --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [react()], +}) \ No newline at end of file From 35f4f48d1dda6331ecb5542123d677c12998a111 Mon Sep 17 00:00:00 2001 From: Akim Date: Thu, 29 Jan 2026 23:38:07 +0300 Subject: [PATCH 2/5] ci: GitHub Actions CI --- .github/workflows/ci.yml | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..b455ea5 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,32 @@ +# CI для CodeFlow: проверка кода при каждом push и PR +# Запускает: установка зависимостей → линт → сборка + +name: CI + +on: + push: + branches: [main, develop] + pull_request: + branches: [main, develop] + +jobs: + check: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Lint + run: npm run lint + + - name: Build + run: npm run build From eb9ab0ce113afe30c45556c55a02fdb879c112fe Mon Sep 17 00:00:00 2001 From: Akim Date: Thu, 29 Jan 2026 23:38:14 +0300 Subject: [PATCH 3/5] chore: add .env to .gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index fc5ae9f..76a2f34 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,9 @@ lerna-debug.log* node_modules dist +.env +.env.local +.env.*.local dist-ssr *.local From a33a373c730546a341c2d4336c8716a18c20295a Mon Sep 17 00:00:00 2001 From: Akim Date: Fri, 30 Jan 2026 00:04:51 +0300 Subject: [PATCH 4/5] fix: eslint config and lint errors for CI --- eslint.config.js | 18 +- package-lock.json | 1669 ++++++++++++++++++++++++++++--- package.json | 6 + src/components/MoralChoice.tsx | 2 +- src/components/TimeDebugger.tsx | 20 +- src/data/achievements.ts | 2 +- src/pages/HomePage.tsx | 2 +- src/pages/LessonPage.tsx | 26 +- src/pages/ProfilePage.tsx | 9 +- src/utils/adaptiveMusic.ts | 11 +- src/utils/audio.ts | 11 +- 11 files changed, 1581 insertions(+), 195 deletions(-) diff --git a/eslint.config.js b/eslint.config.js index 5e6b472..3e003f8 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -3,21 +3,19 @@ import globals from 'globals' import reactHooks from 'eslint-plugin-react-hooks' import reactRefresh from 'eslint-plugin-react-refresh' import tseslint from 'typescript-eslint' -import { defineConfig, globalIgnores } from 'eslint/config' -export default defineConfig([ - globalIgnores(['dist']), +export default [ + { ignores: ['dist'] }, + { files: ['**/*.cjs'], languageOptions: { globals: globals.node } }, + js.configs.recommended, + ...tseslint.configs.recommended, + reactHooks.configs['recommended-latest'], + reactRefresh.configs.vite, { files: ['**/*.{ts,tsx}'], - extends: [ - js.configs.recommended, - tseslint.configs.recommended, - reactHooks.configs.flat.recommended, - reactRefresh.configs.vite, - ], languageOptions: { ecmaVersion: 2020, globals: globals.browser, }, }, -]) +] diff --git a/package-lock.json b/package-lock.json index 440568f..2e9d02c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,14 +20,20 @@ "react-simple-typewriter": "^5.0.1" }, "devDependencies": { + "@eslint/js": "^9.15.0", "@types/canvas-confetti": "^1.6.4", "@types/react": "^18.2.64", "@types/react-dom": "^18.2.21", "@vitejs/plugin-react": "^4.2.1", + "eslint": "^9.15.0", + "eslint-plugin-react-hooks": "^5.0.0", + "eslint-plugin-react-refresh": "^0.4.14", + "globals": "^15.12.0", "postcss": "^8.4.35", "postcss-preset-mantine": "^1.13.0", "postcss-simple-vars": "^7.0.1", "typescript": "^5.2.2", + "typescript-eslint": "^8.15.0", "vite": "^5.1.6" } }, @@ -714,6 +720,163 @@ "node": ">=12" } }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/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, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", + "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz", + "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==", + "dev": true, + "license": "MIT", + "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.1", + "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/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "9.39.2", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz", + "integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@floating-ui/core": { "version": "1.7.3", "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.3.tgz", @@ -767,6 +930,58 @@ "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==", "license": "MIT" }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", + "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.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, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.13", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", @@ -1320,6 +1535,13 @@ "dev": true, "license": "MIT" }, + "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, + "license": "MIT" + }, "node_modules/@types/prop-types": { "version": "15.7.15", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", @@ -1356,167 +1578,595 @@ "license": "MIT", "optional": true }, - "node_modules/@vitejs/plugin-react": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz", - "integrity": "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==", + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.54.0.tgz", + "integrity": "sha512-hAAP5io/7csFStuOmR782YmTthKBJ9ND3WVL60hcOjvtGFb+HJxH4O5huAcmcZ9v9G8P+JETiZ/G1B8MALnWZQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/core": "^7.28.0", - "@babel/plugin-transform-react-jsx-self": "^7.27.1", - "@babel/plugin-transform-react-jsx-source": "^7.27.1", - "@rolldown/pluginutils": "1.0.0-beta.27", - "@types/babel__core": "^7.20.5", - "react-refresh": "^0.17.0" + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.54.0", + "@typescript-eslint/type-utils": "8.54.0", + "@typescript-eslint/utils": "8.54.0", + "@typescript-eslint/visitor-keys": "8.54.0", + "ignore": "^7.0.5", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.4.0" }, "engines": { - "node": "^14.18.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" + "@typescript-eslint/parser": "^8.54.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/baseline-browser-mapping": { - "version": "2.9.17", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.17.tgz", - "integrity": "sha512-agD0MgJFUP/4nvjqzIB29zRPUuCF7Ge6mEv9s8dHrtYD7QWXRcx75rOADE/d5ah1NI+0vkDl0yorDd5U852IQQ==", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", "dev": true, - "license": "Apache-2.0", - "bin": { - "baseline-browser-mapping": "dist/cli.js" + "license": "MIT", + "engines": { + "node": ">= 4" } }, - "node_modules/browserslist": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", - "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "node_modules/@typescript-eslint/parser": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.54.0.tgz", + "integrity": "sha512-BtE0k6cjwjLZoZixN0t5AKP0kSzlGu7FctRXYuPAm//aaiZhmfq1JwdYpYr1brzEspYyFeF+8XF5j2VK6oalrA==", "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" - } - ], "license": "MIT", "peer": true, "dependencies": { - "baseline-browser-mapping": "^2.9.0", - "caniuse-lite": "^1.0.30001759", - "electron-to-chromium": "^1.5.263", - "node-releases": "^2.0.27", - "update-browserslist-db": "^1.2.0" - }, - "bin": { - "browserslist": "cli.js" + "@typescript-eslint/scope-manager": "8.54.0", + "@typescript-eslint/types": "8.54.0", + "@typescript-eslint/typescript-estree": "8.54.0", + "@typescript-eslint/visitor-keys": "8.54.0", + "debug": "^4.4.3" }, "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/camelcase-css": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", - "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "node_modules/@typescript-eslint/project-service": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.54.0.tgz", + "integrity": "sha512-YPf+rvJ1s7MyiWM4uTRhE4DvBXrEV+d8oC3P9Y2eT7S+HBS0clybdMIPnhiATi9vZOYDc7OQ1L/i6ga6NFYK/g==", "dev": true, "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.54.0", + "@typescript-eslint/types": "^8.54.0", + "debug": "^4.4.3" + }, "engines": { - "node": ">= 6" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001766", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001766.tgz", - "integrity": "sha512-4C0lfJ0/YPjJQHagaE9x2Elb69CIqEPZeG0anQt9SIvIoOH4a4uaRl73IavyO+0qZh6MDLH//DrXThEYKHkmYA==", - "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" - } - ], - "license": "CC-BY-4.0" - }, - "node_modules/canvas-confetti": { - "version": "1.9.4", - "resolved": "https://registry.npmjs.org/canvas-confetti/-/canvas-confetti-1.9.4.tgz", - "integrity": "sha512-yxQbJkAVrFXWNbTUjPqjF7G+g6pDotOUHGbkZq2NELZUMDpiJ85rIEazVb8GTaAptNW2miJAXbs1BtioA251Pw==", - "license": "ISC", + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, "funding": { - "type": "donate", - "url": "https://www.paypal.me/kirilvatev" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.54.0.tgz", + "integrity": "sha512-27rYVQku26j/PbHYcVfRPonmOlVI6gihHtXFbTdB5sb6qA0wdAQAbyXFVarQ5t4HRojIz64IV90YtsjQSSGlQg==", + "dev": true, "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.54.0", + "@typescript-eslint/visitor-keys": "8.54.0" + }, "engines": { - "node": ">=6" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "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, - "license": "MIT" - }, - "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==", + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.54.0.tgz", + "integrity": "sha512-dRgOyT2hPk/JwxNMZDsIXDgyl9axdJI3ogZ2XWhBPsnZUv+hPesa5iuhdYt2gzwA9t8RE5ytOJ6xB0moV0Ujvw==", "dev": true, "license": "MIT", - "bin": { - "cssesc": "bin/cssesc" - }, "engines": { - "node": ">=4" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/csstype": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", - "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "node_modules/@typescript-eslint/type-utils": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.54.0.tgz", + "integrity": "sha512-hiLguxJWHjjwL6xMBwD903ciAwd7DmK30Y9Axs/etOkftC3ZNN9K44IuRD/EB08amu+Zw6W37x9RecLkOo3pMA==", "dev": true, "license": "MIT", "dependencies": { - "ms": "^2.1.3" + "@typescript-eslint/types": "8.54.0", + "@typescript-eslint/typescript-estree": "8.54.0", + "@typescript-eslint/utils": "8.54.0", + "debug": "^4.4.3", + "ts-api-utils": "^2.4.0" }, "engines": { - "node": ">=6.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, - "peerDependenciesMeta": { + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.54.0.tgz", + "integrity": "sha512-PDUI9R1BVjqu7AUDsRBbKMtwmjWcn4J3le+5LpcFgWULN3LvHC5rkc9gCVxbrsrGmO1jfPybN5s6h4Jy+OnkAA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.54.0.tgz", + "integrity": "sha512-BUwcskRaPvTk6fzVWgDPdUndLjB87KYDrN5EYGetnktoeAvPtO4ONHlAZDnj5VFnUANg0Sjm7j4usBlnoVMHwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.54.0", + "@typescript-eslint/tsconfig-utils": "8.54.0", + "@typescript-eslint/types": "8.54.0", + "@typescript-eslint/visitor-keys": "8.54.0", + "debug": "^4.4.3", + "minimatch": "^9.0.5", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.4.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/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, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.54.0.tgz", + "integrity": "sha512-9Cnda8GS57AQakvRyG0PTejJNlA2xhvyNtEVIMlDWOOeEyBkYWhGPnfrIAnqxLMTSTo6q8g12XVjjev5l1NvMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.54.0", + "@typescript-eslint/types": "8.54.0", + "@typescript-eslint/typescript-estree": "8.54.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.54.0.tgz", + "integrity": "sha512-VFlhGSl4opC0bprJiItPQ1RfUhGDIBokcPwaFH4yiBCaNPeld/9VeXbiPO1cLyorQi1G1vL+ecBk1x8o1axORA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.54.0", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@vitejs/plugin-react": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz", + "integrity": "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.28.0", + "@babel/plugin-transform-react-jsx-self": "^7.27.1", + "@babel/plugin-transform-react-jsx-source": "^7.27.1", + "@rolldown/pluginutils": "1.0.0-beta.27", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.17.0" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "peer": 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, + "license": "MIT", + "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, + "license": "MIT", + "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/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, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/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, + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.9.17", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.17.tgz", + "integrity": "sha512-agD0MgJFUP/4nvjqzIB29zRPUuCF7Ge6mEv9s8dHrtYD7QWXRcx75rOADE/d5ah1NI+0vkDl0yorDd5U852IQQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/browserslist": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "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" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001766", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001766.tgz", + "integrity": "sha512-4C0lfJ0/YPjJQHagaE9x2Elb69CIqEPZeG0anQt9SIvIoOH4a4uaRl73IavyO+0qZh6MDLH//DrXThEYKHkmYA==", + "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" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/canvas-confetti": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/canvas-confetti/-/canvas-confetti-1.9.4.tgz", + "integrity": "sha512-yxQbJkAVrFXWNbTUjPqjF7G+g6pDotOUHGbkZq2NELZUMDpiJ85rIEazVb8GTaAptNW2miJAXbs1BtioA251Pw==", + "license": "ISC", + "funding": { + "type": "donate", + "url": "https://www.paypal.me/kirilvatev" + } + }, + "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, + "license": "MIT", + "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/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/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, + "license": "MIT", + "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, + "license": "MIT" + }, + "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, + "license": "MIT" + }, + "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, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "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, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { "supports-color": { "optional": 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, + "license": "MIT" + }, "node_modules/detect-node-es": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", @@ -1588,6 +2238,218 @@ "node": ">=6" } }, + "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, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.39.2", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz", + "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.1", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.39.2", + "@eslint/plugin-kit": "^0.4.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.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", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz", + "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==", + "dev": true, + "license": "MIT", + "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" + } + }, + "node_modules/eslint-plugin-react-refresh": { + "version": "0.4.26", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.26.tgz", + "integrity": "sha512-1RETEylht2O6FM/MvgnyvT+8K21wLqDNg4qD51Zj3guhjt433XbnnkVttHMyaVyAFD03QSV4LPS5iE3VQmO7XQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "eslint": ">=8.40" + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "license": "BSD-2-Clause", + "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": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", + "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, + "license": "BSD-2-Clause", + "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, + "license": "BSD-2-Clause", + "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, + "license": "BSD-2-Clause", + "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, + "license": "MIT" + }, + "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, + "license": "MIT" + }, + "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, + "license": "MIT" + }, "node_modules/fdir": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", @@ -1606,6 +2468,57 @@ } } }, + "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, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "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, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" + }, "node_modules/framer-motion": { "version": "12.29.0", "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.29.0.tgz", @@ -1621,58 +2534,174 @@ "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, - "peerDependenciesMeta": { - "@emotion/is-prop-valid": { - "optional": true - }, - "react": { - "optional": true - }, - "react-dom": { - "optional": true - } + "peerDependenciesMeta": { + "@emotion/is-prop-valid": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": 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, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-nonce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", + "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "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, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "15.15.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz", + "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, - "hasInstallScript": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + "node": ">=0.8.19" } }, - "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==", + "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, "license": "MIT", "engines": { - "node": ">=6.9.0" + "node": ">=0.10.0" } }, - "node_modules/get-nonce": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", - "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==", + "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, "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, "engines": { - "node": ">=6" + "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, + "license": "ISC" + }, "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==", "license": "MIT" }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/jsesc": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", @@ -1686,6 +2715,27 @@ "node": ">=6" } }, + "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, + "license": "MIT" + }, + "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, + "license": "MIT" + }, + "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, + "license": "MIT" + }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -1699,6 +2749,53 @@ "node": ">=6" } }, + "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, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.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, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.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, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "license": "MIT" + }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -1733,6 +2830,19 @@ "node": ">= 18" } }, + "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, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/monaco-editor": { "version": "0.55.1", "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.55.1.tgz", @@ -1785,6 +2895,13 @@ "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, + "license": "MIT" + }, "node_modules/node-releases": { "version": "2.0.27", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", @@ -1792,6 +2909,89 @@ "dev": true, "license": "MIT" }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "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": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -1969,6 +3169,26 @@ "postcss": "^8.2.1" } }, + "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, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/react": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", @@ -2147,6 +3367,16 @@ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, + "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, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/rollup": { "version": "4.56.0", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.56.0.tgz", @@ -2211,6 +3441,29 @@ "semver": "bin/semver.js" } }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -2227,6 +3480,19 @@ "integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==", "license": "MIT" }, + "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, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/sugarss": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/sugarss/-/sugarss-5.0.1.tgz", @@ -2250,6 +3516,19 @@ "postcss": "^8.3.3" } }, + "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, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/tabbable": { "version": "6.4.0", "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.4.0.tgz", @@ -2273,12 +3552,38 @@ "url": "https://github.com/sponsors/SuperchupuDev" } }, + "node_modules/ts-api-utils": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz", + "integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "license": "0BSD" }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/type-fest": { "version": "4.41.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", @@ -2297,6 +3602,7 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -2305,6 +3611,30 @@ "node": ">=14.17" } }, + "node_modules/typescript-eslint": { + "version": "8.54.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.54.0.tgz", + "integrity": "sha512-CKsJ+g53QpsNPqbzUsfKVgd3Lny4yKZ1pP4qN3jdMOg/sisIDLGyDMezycquXLE5JsEU0wp3dGNdzig0/fmSVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.54.0", + "@typescript-eslint/parser": "8.54.0", + "@typescript-eslint/typescript-estree": "8.54.0", + "@typescript-eslint/utils": "8.54.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, "node_modules/update-browserslist-db": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", @@ -2336,6 +3666,16 @@ "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, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, "node_modules/use-callback-ref": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz", @@ -2492,12 +3832,51 @@ } } }, + "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, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true, "license": "ISC" + }, + "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, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } diff --git a/package.json b/package.json index bf54d8b..f72d160 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "react-simple-typewriter": "^5.0.1" }, "devDependencies": { + "@eslint/js": "^9.15.0", "@types/canvas-confetti": "^1.6.4", "@types/react": "^18.2.64", "@types/react-dom": "^18.2.21", @@ -30,6 +31,11 @@ "postcss-preset-mantine": "^1.13.0", "postcss-simple-vars": "^7.0.1", "typescript": "^5.2.2", + "eslint": "^9.15.0", + "eslint-plugin-react-hooks": "^5.0.0", + "eslint-plugin-react-refresh": "^0.4.14", + "globals": "^15.12.0", + "typescript-eslint": "^8.15.0", "vite": "^5.1.6" } } diff --git a/src/components/MoralChoice.tsx b/src/components/MoralChoice.tsx index 997ceec..fb5544a 100644 --- a/src/components/MoralChoice.tsx +++ b/src/components/MoralChoice.tsx @@ -1,4 +1,4 @@ -import { Modal, Button, Title, Text, Stack, Group } from '@mantine/core'; +import { Modal, Button, Title, Text, Stack } from '@mantine/core'; import { addReputation } from '../data/reputationSystem'; interface Props { diff --git a/src/components/TimeDebugger.tsx b/src/components/TimeDebugger.tsx index 423ecf1..6f38c10 100644 --- a/src/components/TimeDebugger.tsx +++ b/src/components/TimeDebugger.tsx @@ -5,7 +5,7 @@ import { IconPlayerSkipForward, IconReload, IconBug } from '@tabler/icons-react' interface DebugStep { line: number; code: string; - variables: Record; + variables: Record; lastChangedVar: string | null; output: string; } @@ -23,7 +23,7 @@ export const TimeDebugger = ({ code, onClose }: TimeDebuggerProps) => { const generateSteps = (sourceCode: string): DebugStep[] => { const lines = sourceCode.split('\n').map(l => l.trim()).filter(l => l && !l.startsWith('#')); const debugSteps: DebugStep[] = []; - let currentVars: Record = {}; + let currentVars: Record = {}; let currentOutput = ''; lines.forEach((line, idx) => { @@ -68,10 +68,8 @@ export const TimeDebugger = ({ code, onClose }: TimeDebuggerProps) => { const match = line.match(/for (\w+) in range\((\d+)(?:,\s*(\d+))?(?:,\s*(-?\d+))?\)/); if (match) { const varName = match[1]; - const start = match[2] ? parseInt(match[2]) : 0; - const stop = match[3] ? parseInt(match[3]) : parseInt(match[2]); - const step = match[4] ? parseInt(match[4]) : 1; - + const start = match[2] ? parseInt(match[2], 10) : 0; + currentVars = { ...currentVars, [varName]: start }; lastChangedVar = varName; } @@ -90,19 +88,19 @@ export const TimeDebugger = ({ code, onClose }: TimeDebuggerProps) => { }; // Вычисление f-строк: f'Try: {i}' - const evaluateFString = (fstr: string, scope: Record): string => { + const evaluateFString = (fstr: string, scope: Record): string => { // Убираем f' и ' - let template = fstr.slice(2, -1); - + const template = fstr.slice(2, -1); + // Заменяем {переменная} на значения const regex = /{([^}]+)}/g; - return template.replace(regex, (_, varName) => { + return template.replace(regex, (_match, varName: string) => { return scope[varName.trim()] !== undefined ? String(scope[varName.trim()]) : `{${varName}}`; }); }; // Вычисление Python-выражений - const evaluatePythonExpression = (expr: string, scope: Record) => { + const evaluatePythonExpression = (expr: string, scope: Record) => { const keys = Object.keys(scope); const values = Object.values(scope); diff --git a/src/data/achievements.ts b/src/data/achievements.ts index d0023df..cea96c2 100644 --- a/src/data/achievements.ts +++ b/src/data/achievements.ts @@ -3,7 +3,7 @@ export interface Achievement { title: string; description: string; icon: string; - condition: (stats: any) => boolean; + condition: (stats: { completedCount: number; completedIds: number[]; totalXP: number }) => boolean; } export const achievements: Achievement[] = [ diff --git a/src/pages/HomePage.tsx b/src/pages/HomePage.tsx index c0721a0..b6d66e5 100644 --- a/src/pages/HomePage.tsx +++ b/src/pages/HomePage.tsx @@ -1,4 +1,4 @@ -import { Container, Title, Text, Button, Group, Stack, SimpleGrid, Card, Badge } from '@mantine/core'; +import { Container, Title, Text, Button, Stack, SimpleGrid, Card, Badge } from '@mantine/core'; import { Link } from 'react-router-dom'; import { Typewriter } from 'react-simple-typewriter'; import { IconRocket, IconTrophy, IconShoppingCart, IconUser } from '@tabler/icons-react'; diff --git a/src/pages/LessonPage.tsx b/src/pages/LessonPage.tsx index 54a4d95..5cf3983 100644 --- a/src/pages/LessonPage.tsx +++ b/src/pages/LessonPage.tsx @@ -4,7 +4,7 @@ import { useParams, useNavigate } from 'react-router-dom'; import confetti from 'canvas-confetti'; import { Button, Title, Text, Paper, Group, Badge, Notification, - Stack, Center, Box, Collapse, Tooltip, ActionIcon, Tabs + Stack, Center, Box, Collapse, ActionIcon, Tabs } from '@mantine/core'; import { IconBulb, IconClock, IconRocket, IconTerminal, IconFileCode, IconReload, IconAlertTriangle @@ -25,7 +25,9 @@ import { motion, AnimatePresence } from 'framer-motion'; import { sounds } from '../utils/audio'; declare global { - interface Window { loadPyodide: any; } + interface Window { + loadPyodide?: () => Promise<{ runPythonAsync: (code: string) => Promise; setStdout: (opts: { batched: (msg: string) => void }) => void }>; + } } const LessonPage = () => { @@ -43,7 +45,6 @@ const LessonPage = () => { const [glitchState, setGlitchState] = useState(createGlitchState({ type: 'welcome' })); const [notification, setNotification] = useState<{ type: 'success' | 'fail' | null, message: string }>({ type: null, message: '' }); const [showDebugger, setShowDebugger] = useState(false); - const [showHint, setShowHint] = useState(false); const [moralModalOpened, setMoralModalOpened] = useState(false); const [timeLeft, setTimeLeft] = useState(null); @@ -140,15 +141,16 @@ const LessonPage = () => { const interval = setInterval(() => { sounds.type(); }, 80); const timer = setTimeout(() => { clearInterval(interval); }, 1500); - - return () => { - clearInterval(interval); - clearTimeout(timer); - music.stop(); + + return () => { + clearInterval(interval); + clearTimeout(timer); + music.stop(); window.dispatchEvent(new Event('boss-mode-off')); document.body.removeAttribute('data-boss-mode'); }; } + // eslint-disable-next-line react-hooks/exhaustive-deps -- run only when lessonId/isBossMode change }, [lessonId, isBossMode]); const handleRunUpdated = async () => { @@ -203,8 +205,8 @@ const LessonPage = () => { let achievementMessage = ""; const stats = { completedCount: completed.length, completedIds: completed, totalXP: Number(localStorage.getItem('userXP')) }; const unlockedRaw = localStorage.getItem('unlockedAchievements'); - let unlocked: string[] = unlockedRaw ? JSON.parse(unlockedRaw) : []; - + const unlocked: string[] = unlockedRaw ? JSON.parse(unlockedRaw) : []; + achievements.forEach(ach => { if (!unlocked.includes(ach.id) && ach.condition(stats)) { unlocked.push(ach.id); @@ -233,12 +235,12 @@ const LessonPage = () => { setNotification({ type: 'fail', message: 'ВЗЛОМ ПРЕРВАН: Неверный результат.' }); music.start('ambient'); } - } catch (err: any) { + } catch (err: unknown) { sounds.error(); setIsError(true); setErrorCount(prev => prev + 1); setGlitchState(createGlitchState({ type: 'error', isError: true, errorCount: errorCount + 1 })); - setOutput(`> СИСТЕМНЫЙ СБОЙ:\n${err.message}`); + setOutput(`> СИСТЕМНЫЙ СБОЙ:\n${err instanceof Error ? err.message : String(err)}`); setNotification({ type: 'fail', message: 'КРИТИЧЕСКАЯ ОШИБКА В КОДЕ!' }); music.start('ambient'); } finally { diff --git a/src/pages/ProfilePage.tsx b/src/pages/ProfilePage.tsx index b52cc23..cb9f335 100644 --- a/src/pages/ProfilePage.tsx +++ b/src/pages/ProfilePage.tsx @@ -2,22 +2,15 @@ import { Container, Title, Text, Paper, Group, RingProgress, Stack, Button, Badg import { Link } from 'react-router-dom'; import { useEffect, useState } from 'react'; import { achievements } from '../data/achievements'; -import { factions, getReputation, isFactionUnlocked, type ReputationState } from '../data/reputationSystem'; +import { factions, getReputation, isFactionUnlocked } from '../data/reputationSystem'; const ProfilePage = () => { const [xp, setXp] = useState(0); const [unlockedIds, setUnlockedIds] = useState([]); - const [reputation, setReputation] = useState({}); useEffect(() => { setXp(Number(localStorage.getItem('userXP')) || 0); setUnlockedIds(JSON.parse(localStorage.getItem('unlockedAchievements') || '[]')); - - // Загружаем репутацию - const savedRep = localStorage.getItem('reputation'); - if (savedRep) { - setReputation(JSON.parse(savedRep)); - } }, []); // Логика рангов diff --git a/src/utils/adaptiveMusic.ts b/src/utils/adaptiveMusic.ts index 4ca1a66..4d5345e 100644 --- a/src/utils/adaptiveMusic.ts +++ b/src/utils/adaptiveMusic.ts @@ -8,8 +8,9 @@ class AdaptiveMusic { constructor() { try { - this.audioContext = new (window.AudioContext || (window as any).webkitAudioContext)(); - } catch (e) { + const Ctx = window.AudioContext ?? (window as Window & { webkitAudioContext?: typeof AudioContext }).webkitAudioContext; + this.audioContext = Ctx ? new Ctx() : null; + } catch { console.warn('Audio not supported'); } } @@ -43,7 +44,9 @@ class AdaptiveMusic { this.oscillators.forEach(osc => { try { osc.stop(); - } catch {} + } catch { + // osc may already be stopped + } }); this.oscillators = []; this.gainNodes = []; @@ -113,7 +116,7 @@ class AdaptiveMusic { const now = this.audioContext.currentTime; const freqs = [110, 138.59, 164.81]; // Минорный аккорд - freqs.forEach((freq, i) => { + freqs.forEach((freq) => { const osc = this.audioContext!.createOscillator(); const gain = this.audioContext!.createGain(); diff --git a/src/utils/audio.ts b/src/utils/audio.ts index 4115369..6b37052 100644 --- a/src/utils/audio.ts +++ b/src/utils/audio.ts @@ -1,7 +1,13 @@ // Утилита для генерации "компьютерного" звука через код (Web Audio API) +const getAudioContext = () => { + const Ctx = window.AudioContext ?? (window as Window & { webkitAudioContext?: typeof AudioContext }).webkitAudioContext; + return Ctx ? new Ctx() : null; +}; + const playSynthSound = (freq: number, type: OscillatorType, duration: number) => { try { - const audioCtx = new (window.AudioContext || (window as any).webkitAudioContext)(); + const audioCtx = getAudioContext(); + if (!audioCtx) return; const oscillator = audioCtx.createOscillator(); const gainNode = audioCtx.createGain(); @@ -42,7 +48,8 @@ export const sounds = { // Исправленная сирена siren: () => { try { - const audioCtx = new (window.AudioContext || (window as any).webkitAudioContext)(); + const audioCtx = getAudioContext(); + if (!audioCtx) return; const oscillator = audioCtx.createOscillator(); const gainNode = audioCtx.createGain(); From 2c9454452c0c04f514ff515f5ec8f93e7196a3a4 Mon Sep 17 00:00:00 2001 From: Akim Date: Fri, 30 Jan 2026 00:17:17 +0300 Subject: [PATCH 5/5] docs: add pull request template --- .github/PULL_REQUEST_TEMPLATE.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 .github/PULL_REQUEST_TEMPLATE.md diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..044e0b9 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,16 @@ +## Описание + + +## Тип изменений +- [ ] Новая фича (frontend) +- [ ] Новая фича (backend) +- [ ] Исправление бага +- [ ] Рефакторинг / документация + +## Чеклист +- [ ] `npm run lint` проходит +- [ ] `npm run build` проходит (если затронут фронтенд) +- [ ] Проверено локально + +## Связанные задачи +