diff --git a/.env.dev b/.env.dev new file mode 100644 index 0000000..17fd0de --- /dev/null +++ b/.env.dev @@ -0,0 +1 @@ +VITE_APP_BASE_URL=/ diff --git a/.env.pord b/.env.pord new file mode 100644 index 0000000..17fd0de --- /dev/null +++ b/.env.pord @@ -0,0 +1 @@ +VITE_APP_BASE_URL=/ diff --git a/.env.test b/.env.test new file mode 100644 index 0000000..17fd0de --- /dev/null +++ b/.env.test @@ -0,0 +1 @@ +VITE_APP_BASE_URL=/ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a547bf3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,24 @@ +# 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? diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..a7cea0b --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["Vue.volar"] +} diff --git a/env.d.ts b/env.d.ts new file mode 100644 index 0000000..323c78a --- /dev/null +++ b/env.d.ts @@ -0,0 +1,7 @@ +/// + +declare module '*.vue' { + import type { DefineComponent } from 'vue' + const component: DefineComponent<{}, {}, any> + export default component +} diff --git a/index.html b/index.html new file mode 100644 index 0000000..542f7e7 --- /dev/null +++ b/index.html @@ -0,0 +1,13 @@ + + + + + + + hi快下载 + + +
+ + + diff --git a/package.json b/package.json new file mode 100644 index 0000000..71e91a5 --- /dev/null +++ b/package.json @@ -0,0 +1,36 @@ +{ + "name": "hi-download", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite --mode dev", + "build:test": "vite build --mode test", + "build:prod": "vite build --mode pord", + "preview": "vite preview" + }, + "dependencies": { + "@tailwindcss/vite": "^4.1.18", + "axios": "^1.13.2", + "clsx": "^2.1.1", + "lucide-vue-next": "^0.562.0", + "reka-ui": "^2.7.0", + "tailwindcss": "^4.1.18", + "vue": "^3.5.24", + "vue-sonner": "^2.0.9" + }, + "devDependencies": { + "@tsconfig/node24": "^24.0.3", + "@types/node": "^24.10.4", + "@vitejs/plugin-vue": "^6.0.1", + "@vue/tsconfig": "^0.8.1", + "prettier": "^3.8.0", + "prettier-plugin-tailwindcss": "^0.7.2", + "tailwind-merge": "^3.4.0", + "tw-animate-css": "^1.4.0", + "typescript": "^5.9.3", + "vite": "^7.2.4", + "vite-svg-loader": "^5.1.0", + "vue-tsc": "^3.2.2" + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..2959cbd --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,1921 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@tailwindcss/vite': + specifier: ^4.1.18 + version: 4.1.18(vite@7.3.1(@types/node@24.10.9)(jiti@2.6.1)(lightningcss@1.30.2)) + axios: + specifier: ^1.13.2 + version: 1.13.2 + clsx: + specifier: ^2.1.1 + version: 2.1.1 + lucide-vue-next: + specifier: ^0.562.0 + version: 0.562.0(vue@3.5.27(typescript@5.9.3)) + reka-ui: + specifier: ^2.7.0 + version: 2.7.0(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3)) + tailwindcss: + specifier: ^4.1.18 + version: 4.1.18 + vue: + specifier: ^3.5.24 + version: 3.5.27(typescript@5.9.3) + vue-sonner: + specifier: ^2.0.9 + version: 2.0.9 + devDependencies: + '@tsconfig/node24': + specifier: ^24.0.3 + version: 24.0.4 + '@types/node': + specifier: ^24.10.4 + version: 24.10.9 + '@vitejs/plugin-vue': + specifier: ^6.0.1 + version: 6.0.3(vite@7.3.1(@types/node@24.10.9)(jiti@2.6.1)(lightningcss@1.30.2))(vue@3.5.27(typescript@5.9.3)) + '@vue/tsconfig': + specifier: ^0.8.1 + version: 0.8.1(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3)) + prettier: + specifier: ^3.8.0 + version: 3.8.0 + prettier-plugin-tailwindcss: + specifier: ^0.7.2 + version: 0.7.2(prettier@3.8.0) + tailwind-merge: + specifier: ^3.4.0 + version: 3.4.0 + tw-animate-css: + specifier: ^1.4.0 + version: 1.4.0 + typescript: + specifier: ^5.9.3 + version: 5.9.3 + vite: + specifier: ^7.2.4 + version: 7.3.1(@types/node@24.10.9)(jiti@2.6.1)(lightningcss@1.30.2) + vite-svg-loader: + specifier: ^5.1.0 + version: 5.1.0(vue@3.5.27(typescript@5.9.3)) + vue-tsc: + specifier: ^3.2.2 + version: 3.2.2(typescript@5.9.3) + +packages: + + '@babel/helper-string-parser@7.27.1': + resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.28.5': + resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.28.6': + resolution: {integrity: sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/types@7.28.6': + resolution: {integrity: sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==} + engines: {node: '>=6.9.0'} + + '@esbuild/aix-ppc64@0.27.2': + resolution: {integrity: sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.27.2': + resolution: {integrity: sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.27.2': + resolution: {integrity: sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.27.2': + resolution: {integrity: sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.27.2': + resolution: {integrity: sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.27.2': + resolution: {integrity: sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.27.2': + resolution: {integrity: sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.27.2': + resolution: {integrity: sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.27.2': + resolution: {integrity: sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.27.2': + resolution: {integrity: sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.27.2': + resolution: {integrity: sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.27.2': + resolution: {integrity: sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.27.2': + resolution: {integrity: sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.27.2': + resolution: {integrity: sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.27.2': + resolution: {integrity: sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.27.2': + resolution: {integrity: sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.27.2': + resolution: {integrity: sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.27.2': + resolution: {integrity: sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.27.2': + resolution: {integrity: sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.27.2': + resolution: {integrity: sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.27.2': + resolution: {integrity: sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openharmony-arm64@0.27.2': + resolution: {integrity: sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.27.2': + resolution: {integrity: sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.27.2': + resolution: {integrity: sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.27.2': + resolution: {integrity: sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.27.2': + resolution: {integrity: sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@floating-ui/core@1.7.3': + resolution: {integrity: sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==} + + '@floating-ui/dom@1.7.4': + resolution: {integrity: sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==} + + '@floating-ui/utils@0.2.10': + resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==} + + '@floating-ui/vue@1.1.9': + resolution: {integrity: sha512-BfNqNW6KA83Nexspgb9DZuz578R7HT8MZw1CfK9I6Ah4QReNWEJsXWHN+SdmOVLNGmTPDi+fDT535Df5PzMLbQ==} + + '@internationalized/date@3.10.1': + resolution: {integrity: sha512-oJrXtQiAXLvT9clCf1K4kxp3eKsQhIaZqxEyowkBcsvZDdZkbWrVmnGknxs5flTD0VGsxrxKgBCZty1EzoiMzA==} + + '@internationalized/number@3.6.5': + resolution: {integrity: sha512-6hY4Kl4HPBvtfS62asS/R22JzNNy8vi/Ssev7x6EobfCp+9QIB2hKvI2EtbdJ0VSQacxVNtqhE/NmF/NZ0gm6g==} + + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + + '@rolldown/pluginutils@1.0.0-beta.53': + resolution: {integrity: sha512-vENRlFU4YbrwVqNDZ7fLvy+JR1CRkyr01jhSiDpE1u6py3OMzQfztQU2jxykW3ALNxO4kSlqIDeYyD0Y9RcQeQ==} + + '@rollup/rollup-android-arm-eabi@4.55.2': + resolution: {integrity: sha512-21J6xzayjy3O6NdnlO6aXi/urvSRjm6nCI6+nF6ra2YofKruGixN9kfT+dt55HVNwfDmpDHJcaS3JuP/boNnlA==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.55.2': + resolution: {integrity: sha512-eXBg7ibkNUZ+sTwbFiDKou0BAckeV6kIigK7y5Ko4mB/5A1KLhuzEKovsmfvsL8mQorkoincMFGnQuIT92SKqA==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.55.2': + resolution: {integrity: sha512-UCbaTklREjrc5U47ypLulAgg4njaqfOVLU18VrCrI+6E5MQjuG0lSWaqLlAJwsD7NpFV249XgB0Bi37Zh5Sz4g==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.55.2': + resolution: {integrity: sha512-dP67MA0cCMHFT2g5XyjtpVOtp7y4UyUxN3dhLdt11at5cPKnSm4lY+EhwNvDXIMzAMIo2KU+mc9wxaAQJTn7sQ==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.55.2': + resolution: {integrity: sha512-WDUPLUwfYV9G1yxNRJdXcvISW15mpvod1Wv3ok+Ws93w1HjIVmCIFxsG2DquO+3usMNCpJQ0wqO+3GhFdl6Fow==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.55.2': + resolution: {integrity: sha512-Ng95wtHVEulRwn7R0tMrlUuiLVL/HXA8Lt/MYVpy88+s5ikpntzZba1qEulTuPnPIZuOPcW9wNEiqvZxZmgmqQ==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.55.2': + resolution: {integrity: sha512-AEXMESUDWWGqD6LwO/HkqCZgUE1VCJ1OhbvYGsfqX2Y6w5quSXuyoy/Fg3nRqiwro+cJYFxiw5v4kB2ZDLhxrw==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.55.2': + resolution: {integrity: sha512-ZV7EljjBDwBBBSv570VWj0hiNTdHt9uGznDtznBB4Caj3ch5rgD4I2K1GQrtbvJ/QiB+663lLgOdcADMNVC29Q==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.55.2': + resolution: {integrity: sha512-uvjwc8NtQVPAJtq4Tt7Q49FOodjfbf6NpqXyW/rjXoV+iZ3EJAHLNAnKT5UJBc6ffQVgmXTUL2ifYiLABlGFqA==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.55.2': + resolution: {integrity: sha512-s3KoWVNnye9mm/2WpOZ3JeUiediUVw6AvY/H7jNA6qgKA2V2aM25lMkVarTDfiicn/DLq3O0a81jncXszoyCFA==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-loong64-gnu@4.55.2': + resolution: {integrity: sha512-gi21faacK+J8aVSyAUptML9VQN26JRxe484IbF+h3hpG+sNVoMXPduhREz2CcYr5my0NE3MjVvQ5bMKX71pfVA==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-loong64-musl@4.55.2': + resolution: {integrity: sha512-qSlWiXnVaS/ceqXNfnoFZh4IiCA0EwvCivivTGbEu1qv2o+WTHpn1zNmCTAoOG5QaVr2/yhCoLScQtc/7RxshA==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-ppc64-gnu@4.55.2': + resolution: {integrity: sha512-rPyuLFNoF1B0+wolH277E780NUKf+KoEDb3OyoLbAO18BbeKi++YN6gC/zuJoPPDlQRL3fIxHxCxVEWiem2yXw==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-ppc64-musl@4.55.2': + resolution: {integrity: sha512-g+0ZLMook31iWV4PvqKU0i9E78gaZgYpSrYPed/4Bu+nGTgfOPtfs1h11tSSRPXSjC5EzLTjV/1A7L2Vr8pJoQ==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.55.2': + resolution: {integrity: sha512-i+sGeRGsjKZcQRh3BRfpLsM3LX3bi4AoEVqmGDyc50L6KfYsN45wVCSz70iQMwPWr3E5opSiLOwsC9WB4/1pqg==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-riscv64-musl@4.55.2': + resolution: {integrity: sha512-C1vLcKc4MfFV6I0aWsC7B2Y9QcsiEcvKkfxprwkPfLaN8hQf0/fKHwSF2lcYzA9g4imqnhic729VB9Fo70HO3Q==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.55.2': + resolution: {integrity: sha512-68gHUK/howpQjh7g7hlD9DvTTt4sNLp1Bb+Yzw2Ki0xvscm2cOdCLZNJNhd2jW8lsTPrHAHuF751BygifW4bkQ==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.55.2': + resolution: {integrity: sha512-1e30XAuaBP1MAizaOBApsgeGZge2/Byd6wV4a8oa6jPdHELbRHBiw7wvo4dp7Ie2PE8TZT4pj9RLGZv9N4qwlw==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.55.2': + resolution: {integrity: sha512-4BJucJBGbuGnH6q7kpPqGJGzZnYrpAzRd60HQSt3OpX/6/YVgSsJnNzR8Ot74io50SeVT4CtCWe/RYIAymFPwA==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-openbsd-x64@4.55.2': + resolution: {integrity: sha512-cT2MmXySMo58ENv8p6/O6wI/h/gLnD3D6JoajwXFZH6X9jz4hARqUhWpGuQhOgLNXscfZYRQMJvZDtWNzMAIDw==} + cpu: [x64] + os: [openbsd] + + '@rollup/rollup-openharmony-arm64@4.55.2': + resolution: {integrity: sha512-sZnyUgGkuzIXaK3jNMPmUIyJrxu/PjmATQrocpGA1WbCPX8H5tfGgRSuYtqBYAvLuIGp8SPRb1O4d1Fkb5fXaQ==} + cpu: [arm64] + os: [openharmony] + + '@rollup/rollup-win32-arm64-msvc@4.55.2': + resolution: {integrity: sha512-sDpFbenhmWjNcEbBcoTV0PWvW5rPJFvu+P7XoTY0YLGRupgLbFY0XPfwIbJOObzO7QgkRDANh65RjhPmgSaAjQ==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.55.2': + resolution: {integrity: sha512-GvJ03TqqaweWCigtKQVBErw2bEhu1tyfNQbarwr94wCGnczA9HF8wqEe3U/Lfu6EdeNP0p6R+APeHVwEqVxpUQ==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-gnu@4.55.2': + resolution: {integrity: sha512-KvXsBvp13oZz9JGe5NYS7FNizLe99Ny+W8ETsuCyjXiKdiGrcz2/J/N8qxZ/RSwivqjQguug07NLHqrIHrqfYw==} + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.55.2': + resolution: {integrity: sha512-xNO+fksQhsAckRtDSPWaMeT1uIM+JrDRXlerpnWNXhn1TdB3YZ6uKBMBTKP0eX9XtYEP978hHk1f8332i2AW8Q==} + cpu: [x64] + os: [win32] + + '@swc/helpers@0.5.18': + resolution: {integrity: sha512-TXTnIcNJQEKwThMMqBXsZ4VGAza6bvN4pa41Rkqoio6QBKMvo+5lexeTMScGCIxtzgQJzElcvIltani+adC5PQ==} + + '@tailwindcss/node@4.1.18': + resolution: {integrity: sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ==} + + '@tailwindcss/oxide-android-arm64@4.1.18': + resolution: {integrity: sha512-dJHz7+Ugr9U/diKJA0W6N/6/cjI+ZTAoxPf9Iz9BFRF2GzEX8IvXxFIi/dZBloVJX/MZGvRuFA9rqwdiIEZQ0Q==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [android] + + '@tailwindcss/oxide-darwin-arm64@4.1.18': + resolution: {integrity: sha512-Gc2q4Qhs660bhjyBSKgq6BYvwDz4G+BuyJ5H1xfhmDR3D8HnHCmT/BSkvSL0vQLy/nkMLY20PQ2OoYMO15Jd0A==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + '@tailwindcss/oxide-darwin-x64@4.1.18': + resolution: {integrity: sha512-FL5oxr2xQsFrc3X9o1fjHKBYBMD1QZNyc1Xzw/h5Qu4XnEBi3dZn96HcHm41c/euGV+GRiXFfh2hUCyKi/e+yw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + '@tailwindcss/oxide-freebsd-x64@4.1.18': + resolution: {integrity: sha512-Fj+RHgu5bDodmV1dM9yAxlfJwkkWvLiRjbhuO2LEtwtlYlBgiAT4x/j5wQr1tC3SANAgD+0YcmWVrj8R9trVMA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [freebsd] + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.18': + resolution: {integrity: sha512-Fp+Wzk/Ws4dZn+LV2Nqx3IilnhH51YZoRaYHQsVq3RQvEl+71VGKFpkfHrLM/Li+kt5c0DJe/bHXK1eHgDmdiA==} + engines: {node: '>= 10'} + cpu: [arm] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-gnu@4.1.18': + resolution: {integrity: sha512-S0n3jboLysNbh55Vrt7pk9wgpyTTPD0fdQeh7wQfMqLPM/Hrxi+dVsLsPrycQjGKEQk85Kgbx+6+QnYNiHalnw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-musl@4.1.18': + resolution: {integrity: sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@tailwindcss/oxide-linux-x64-gnu@4.1.18': + resolution: {integrity: sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@tailwindcss/oxide-linux-x64-musl@4.1.18': + resolution: {integrity: sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@tailwindcss/oxide-wasm32-wasi@4.1.18': + resolution: {integrity: sha512-LffYTvPjODiP6PT16oNeUQJzNVyJl1cjIebq/rWWBF+3eDst5JGEFSc5cWxyRCJ0Mxl+KyIkqRxk1XPEs9x8TA==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + bundledDependencies: + - '@napi-rs/wasm-runtime' + - '@emnapi/core' + - '@emnapi/runtime' + - '@tybys/wasm-util' + - '@emnapi/wasi-threads' + - tslib + + '@tailwindcss/oxide-win32-arm64-msvc@4.1.18': + resolution: {integrity: sha512-HjSA7mr9HmC8fu6bdsZvZ+dhjyGCLdotjVOgLA2vEqxEBZaQo9YTX4kwgEvPCpRh8o4uWc4J/wEoFzhEmjvPbA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + '@tailwindcss/oxide-win32-x64-msvc@4.1.18': + resolution: {integrity: sha512-bJWbyYpUlqamC8dpR7pfjA0I7vdF6t5VpUGMWRkXVE3AXgIZjYUYAK7II1GNaxR8J1SSrSrppRar8G++JekE3Q==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + + '@tailwindcss/oxide@4.1.18': + resolution: {integrity: sha512-EgCR5tTS5bUSKQgzeMClT6iCY3ToqE1y+ZB0AKldj809QXk1Y+3jB0upOYZrn9aGIzPtUsP7sX4QQ4XtjBB95A==} + engines: {node: '>= 10'} + + '@tailwindcss/vite@4.1.18': + resolution: {integrity: sha512-jVA+/UpKL1vRLg6Hkao5jldawNmRo7mQYrZtNHMIVpLfLhDml5nMRUo/8MwoX2vNXvnaXNNMedrMfMugAVX1nA==} + peerDependencies: + vite: ^5.2.0 || ^6 || ^7 + + '@tanstack/virtual-core@3.13.18': + resolution: {integrity: sha512-Mx86Hqu1k39icq2Zusq+Ey2J6dDWTjDvEv43PJtRCoEYTLyfaPnxIQ6iy7YAOK0NV/qOEmZQ/uCufrppZxTgcg==} + + '@tanstack/vue-virtual@3.13.18': + resolution: {integrity: sha512-6pT8HdHtTU5Z+t906cGdCroUNA5wHjFXsNss9gwk7QAr1VNZtz9IQCs2Nhx0gABK48c+OocHl2As+TMg8+Hy4A==} + peerDependencies: + vue: ^2.7.0 || ^3.0.0 + + '@trysound/sax@0.2.0': + resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} + engines: {node: '>=10.13.0'} + + '@tsconfig/node24@24.0.4': + resolution: {integrity: sha512-2A933l5P5oCbv6qSxHs7ckKwobs8BDAe9SJ/Xr2Hy+nDlwmLE1GhFh/g/vXGRZWgxBg9nX/5piDtHR9Dkw/XuA==} + + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + + '@types/node@24.10.9': + resolution: {integrity: sha512-ne4A0IpG3+2ETuREInjPNhUGis1SFjv1d5asp8MzEAGtOZeTeHVDOYqOgqfhvseqg/iXty2hjBf1zAOb7RNiNw==} + + '@types/web-bluetooth@0.0.21': + resolution: {integrity: sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==} + + '@vitejs/plugin-vue@6.0.3': + resolution: {integrity: sha512-TlGPkLFLVOY3T7fZrwdvKpjprR3s4fxRln0ORDo1VQ7HHyxJwTlrjKU3kpVWTlaAjIEuCTokmjkZnr8Tpc925w==} + engines: {node: ^20.19.0 || >=22.12.0} + peerDependencies: + vite: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 + vue: ^3.2.25 + + '@volar/language-core@2.4.27': + resolution: {integrity: sha512-DjmjBWZ4tJKxfNC1F6HyYERNHPYS7L7OPFyCrestykNdUZMFYzI9WTyvwPcaNaHlrEUwESHYsfEw3isInncZxQ==} + + '@volar/source-map@2.4.27': + resolution: {integrity: sha512-ynlcBReMgOZj2i6po+qVswtDUeeBRCTgDurjMGShbm8WYZgJ0PA4RmtebBJ0BCYol1qPv3GQF6jK7C9qoVc7lg==} + + '@volar/typescript@2.4.27': + resolution: {integrity: sha512-eWaYCcl/uAPInSK2Lze6IqVWaBu/itVqR5InXcHXFyles4zO++Mglt3oxdgj75BDcv1Knr9Y93nowS8U3wqhxg==} + + '@vue/compiler-core@3.5.27': + resolution: {integrity: sha512-gnSBQjZA+//qDZen+6a2EdHqJ68Z7uybrMf3SPjEGgG4dicklwDVmMC1AeIHxtLVPT7sn6sH1KOO+tS6gwOUeQ==} + + '@vue/compiler-dom@3.5.27': + resolution: {integrity: sha512-oAFea8dZgCtVVVTEC7fv3T5CbZW9BxpFzGGxC79xakTr6ooeEqmRuvQydIiDAkglZEAd09LgVf1RoDnL54fu5w==} + + '@vue/compiler-sfc@3.5.27': + resolution: {integrity: sha512-sHZu9QyDPeDmN/MRoshhggVOWE5WlGFStKFwu8G52swATgSny27hJRWteKDSUUzUH+wp+bmeNbhJnEAel/auUQ==} + + '@vue/compiler-ssr@3.5.27': + resolution: {integrity: sha512-Sj7h+JHt512fV1cTxKlYhg7qxBvack+BGncSpH+8vnN+KN95iPIcqB5rsbblX40XorP+ilO7VIKlkuu3Xq2vjw==} + + '@vue/language-core@3.2.2': + resolution: {integrity: sha512-5DAuhxsxBN9kbriklh3Q5AMaJhyOCNiQJvCskN9/30XOpdLiqZU9Q+WvjArP17ubdGEyZtBzlIeG5nIjEbNOrQ==} + + '@vue/reactivity@3.5.27': + resolution: {integrity: sha512-vvorxn2KXfJ0nBEnj4GYshSgsyMNFnIQah/wczXlsNXt+ijhugmW+PpJ2cNPe4V6jpnBcs0MhCODKllWG+nvoQ==} + + '@vue/runtime-core@3.5.27': + resolution: {integrity: sha512-fxVuX/fzgzeMPn/CLQecWeDIFNt3gQVhxM0rW02Tvp/YmZfXQgcTXlakq7IMutuZ/+Ogbn+K0oct9J3JZfyk3A==} + + '@vue/runtime-dom@3.5.27': + resolution: {integrity: sha512-/QnLslQgYqSJ5aUmb5F0z0caZPGHRB8LEAQ1s81vHFM5CBfnun63rxhvE/scVb/j3TbBuoZwkJyiLCkBluMpeg==} + + '@vue/server-renderer@3.5.27': + resolution: {integrity: sha512-qOz/5thjeP1vAFc4+BY3Nr6wxyLhpeQgAE/8dDtKo6a6xdk+L4W46HDZgNmLOBUDEkFXV3G7pRiUqxjX0/2zWA==} + peerDependencies: + vue: 3.5.27 + + '@vue/shared@3.5.27': + resolution: {integrity: sha512-dXr/3CgqXsJkZ0n9F3I4elY8wM9jMJpP3pvRG52r6m0tu/MsAFIe6JpXVGeNMd/D9F4hQynWT8Rfuj0bdm9kFQ==} + + '@vue/tsconfig@0.8.1': + resolution: {integrity: sha512-aK7feIWPXFSUhsCP9PFqPyFOcz4ENkb8hZ2pneL6m2UjCkccvaOhC/5KCKluuBufvp2KzkbdA2W2pk20vLzu3g==} + peerDependencies: + typescript: 5.x + vue: ^3.4.0 + peerDependenciesMeta: + typescript: + optional: true + vue: + optional: true + + '@vueuse/core@12.8.2': + resolution: {integrity: sha512-HbvCmZdzAu3VGi/pWYm5Ut+Kd9mn1ZHnn4L5G8kOQTPs/IwIAmJoBrmYk2ckLArgMXZj0AW3n5CAejLUO+PhdQ==} + + '@vueuse/metadata@12.8.2': + resolution: {integrity: sha512-rAyLGEuoBJ/Il5AmFHiziCPdQzRt88VxR+Y/A/QhJ1EWtWqPBBAxTAFaSkviwEuOEZNtW8pvkPgoCZQ+HxqW1A==} + + '@vueuse/shared@12.8.2': + resolution: {integrity: sha512-dznP38YzxZoNloI0qpEfpkms8knDtaoQ6Y/sfS0L7Yki4zh40LFHEhur0odJC6xTHG5dxWVPiUWBXn+wCG2s5w==} + + alien-signals@3.1.2: + resolution: {integrity: sha512-d9dYqZTS90WLiU0I5c6DHj/HcKkF8ZyGN3G5x8wSbslulz70KOxaqCT0hQCo9KOyhVqzqGojvNdJXoTumZOtcw==} + + aria-hidden@1.2.6: + resolution: {integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==} + engines: {node: '>=10'} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + axios@1.13.2: + resolution: {integrity: sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==} + + boolbase@1.0.0: + resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + clsx@2.1.1: + resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} + engines: {node: '>=6'} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + commander@7.2.0: + resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} + engines: {node: '>= 10'} + + css-select@5.2.2: + resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==} + + css-tree@2.2.1: + resolution: {integrity: sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} + + css-tree@2.3.1: + resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + + css-what@6.2.2: + resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==} + engines: {node: '>= 6'} + + csso@5.0.5: + resolution: {integrity: sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} + + csstype@3.2.3: + resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + + defu@6.1.4: + resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + + dom-serializer@2.0.0: + resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} + + domelementtype@2.3.0: + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + + domhandler@5.0.3: + resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} + engines: {node: '>= 4'} + + domutils@3.2.2: + resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + enhanced-resolve@5.18.4: + resolution: {integrity: sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==} + engines: {node: '>=10.13.0'} + + entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + + entities@7.0.0: + resolution: {integrity: sha512-FDWG5cmEYf2Z00IkYRhbFrwIwvdFKH07uV8dvNy0omp/Qb1xcyCWp2UDtcwJF4QZZvk0sLudP6/hAu42TaqVhQ==} + engines: {node: '>=0.12'} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + + esbuild@0.27.2: + resolution: {integrity: sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==} + engines: {node: '>=18'} + hasBin: true + + estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + follow-redirects@1.15.11: + resolution: {integrity: sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + form-data@4.0.5: + resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} + engines: {node: '>= 6'} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + jiti@2.6.1: + resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} + hasBin: true + + lightningcss-android-arm64@1.30.2: + resolution: {integrity: sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + + lightningcss-darwin-arm64@1.30.2: + resolution: {integrity: sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.30.2: + resolution: {integrity: sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.30.2: + resolution: {integrity: sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.30.2: + resolution: {integrity: sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.30.2: + resolution: {integrity: sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-arm64-musl@1.30.2: + resolution: {integrity: sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-x64-gnu@1.30.2: + resolution: {integrity: sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-linux-x64-musl@1.30.2: + resolution: {integrity: sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-win32-arm64-msvc@1.30.2: + resolution: {integrity: sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.30.2: + resolution: {integrity: sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.30.2: + resolution: {integrity: sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==} + engines: {node: '>= 12.0.0'} + + lucide-vue-next@0.562.0: + resolution: {integrity: sha512-LN0BLGKMFulv0lnfK29r14DcngRUhIqdcaL0zXTt2o0oS9odlrjCGaU3/X9hIihOjjN8l8e+Y9G/famcNYaI7Q==} + peerDependencies: + vue: '>=3.0.1' + + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + mdn-data@2.0.28: + resolution: {integrity: sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==} + + mdn-data@2.0.30: + resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + muggle-string@0.4.1: + resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==} + + nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + nth-check@2.1.1: + resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + + ohash@2.0.11: + resolution: {integrity: sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==} + + path-browserify@1.0.1: + resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@4.0.3: + resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} + engines: {node: '>=12'} + + postcss@8.5.6: + resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} + engines: {node: ^10 || ^12 || >=14} + + prettier-plugin-tailwindcss@0.7.2: + resolution: {integrity: sha512-LkphyK3Fw+q2HdMOoiEHWf93fNtYJwfamoKPl7UwtjFQdei/iIBoX11G6j706FzN3ymX9mPVi97qIY8328vdnA==} + engines: {node: '>=20.19'} + peerDependencies: + '@ianvs/prettier-plugin-sort-imports': '*' + '@prettier/plugin-hermes': '*' + '@prettier/plugin-oxc': '*' + '@prettier/plugin-pug': '*' + '@shopify/prettier-plugin-liquid': '*' + '@trivago/prettier-plugin-sort-imports': '*' + '@zackad/prettier-plugin-twig': '*' + prettier: ^3.0 + prettier-plugin-astro: '*' + prettier-plugin-css-order: '*' + prettier-plugin-jsdoc: '*' + prettier-plugin-marko: '*' + prettier-plugin-multiline-arrays: '*' + prettier-plugin-organize-attributes: '*' + prettier-plugin-organize-imports: '*' + prettier-plugin-sort-imports: '*' + prettier-plugin-svelte: '*' + peerDependenciesMeta: + '@ianvs/prettier-plugin-sort-imports': + optional: true + '@prettier/plugin-hermes': + optional: true + '@prettier/plugin-oxc': + optional: true + '@prettier/plugin-pug': + optional: true + '@shopify/prettier-plugin-liquid': + optional: true + '@trivago/prettier-plugin-sort-imports': + optional: true + '@zackad/prettier-plugin-twig': + optional: true + prettier-plugin-astro: + optional: true + prettier-plugin-css-order: + optional: true + prettier-plugin-jsdoc: + optional: true + prettier-plugin-marko: + optional: true + prettier-plugin-multiline-arrays: + optional: true + prettier-plugin-organize-attributes: + optional: true + prettier-plugin-organize-imports: + optional: true + prettier-plugin-sort-imports: + optional: true + prettier-plugin-svelte: + optional: true + + prettier@3.8.0: + resolution: {integrity: sha512-yEPsovQfpxYfgWNhCfECjG5AQaO+K3dp6XERmOepyPDVqcJm+bjyCVO3pmU+nAPe0N5dDvekfGezt/EIiRe1TA==} + engines: {node: '>=14'} + hasBin: true + + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + + reka-ui@2.7.0: + resolution: {integrity: sha512-m+XmxQN2xtFzBP3OAdIafKq7C8OETo2fqfxcIIxYmNN2Ch3r5oAf6yEYCIJg5tL/yJU2mHqF70dCCekUkrAnXA==} + peerDependencies: + vue: '>= 3.2.0' + + rollup@4.55.2: + resolution: {integrity: sha512-PggGy4dhwx5qaW+CKBilA/98Ql9keyfnb7lh4SR6shQ91QQQi1ORJ1v4UinkdP2i87OBs9AQFooQylcrrRfIcg==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + svgo@3.3.2: + resolution: {integrity: sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==} + engines: {node: '>=14.0.0'} + hasBin: true + + tailwind-merge@3.4.0: + resolution: {integrity: sha512-uSaO4gnW+b3Y2aWoWfFpX62vn2sR3skfhbjsEnaBI81WD1wBLlHZe5sWf0AqjksNdYTbGBEd0UasQMT3SNV15g==} + + tailwindcss@4.1.18: + resolution: {integrity: sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==} + + tapable@2.3.0: + resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==} + engines: {node: '>=6'} + + tinyglobby@0.2.15: + resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} + engines: {node: '>=12.0.0'} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + tw-animate-css@1.4.0: + resolution: {integrity: sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ==} + + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} + hasBin: true + + undici-types@7.16.0: + resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} + + vite-svg-loader@5.1.0: + resolution: {integrity: sha512-M/wqwtOEjgb956/+m5ZrYT/Iq6Hax0OakWbokj8+9PXOnB7b/4AxESHieEtnNEy7ZpjsjYW1/5nK8fATQMmRxw==} + peerDependencies: + vue: '>=3.2.13' + + vite@7.3.1: + resolution: {integrity: sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@types/node': ^20.19.0 || >=22.12.0 + jiti: '>=1.21.0' + less: ^4.0.0 + lightningcss: ^1.21.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + vscode-uri@3.1.0: + resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==} + + vue-demi@0.14.10: + resolution: {integrity: sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==} + engines: {node: '>=12'} + hasBin: true + peerDependencies: + '@vue/composition-api': ^1.0.0-rc.1 + vue: ^3.0.0-0 || ^2.6.0 + peerDependenciesMeta: + '@vue/composition-api': + optional: true + + vue-sonner@2.0.9: + resolution: {integrity: sha512-i6BokNlNDL93fpzNxN/LZSn6D6MzlO+i3qXt6iVZne3x1k7R46d5HlFB4P8tYydhgqOrRbIZEsnRd3kG7qGXyw==} + peerDependencies: + '@nuxt/kit': ^4.0.3 + '@nuxt/schema': ^4.0.3 + nuxt: ^4.0.3 + peerDependenciesMeta: + '@nuxt/kit': + optional: true + '@nuxt/schema': + optional: true + nuxt: + optional: true + + vue-tsc@3.2.2: + resolution: {integrity: sha512-r9YSia/VgGwmbbfC06hDdAatH634XJ9nVl6Zrnz1iK4ucp8Wu78kawplXnIDa3MSu1XdQQePTHLXYwPDWn+nyQ==} + hasBin: true + peerDependencies: + typescript: '>=5.0.0' + + vue@3.5.27: + resolution: {integrity: sha512-aJ/UtoEyFySPBGarREmN4z6qNKpbEguYHMmXSiOGk69czc+zhs0NF6tEFrY8TZKAl8N/LYAkd4JHVd5E/AsSmw==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + +snapshots: + + '@babel/helper-string-parser@7.27.1': {} + + '@babel/helper-validator-identifier@7.28.5': {} + + '@babel/parser@7.28.6': + dependencies: + '@babel/types': 7.28.6 + + '@babel/types@7.28.6': + dependencies: + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 + + '@esbuild/aix-ppc64@0.27.2': + optional: true + + '@esbuild/android-arm64@0.27.2': + optional: true + + '@esbuild/android-arm@0.27.2': + optional: true + + '@esbuild/android-x64@0.27.2': + optional: true + + '@esbuild/darwin-arm64@0.27.2': + optional: true + + '@esbuild/darwin-x64@0.27.2': + optional: true + + '@esbuild/freebsd-arm64@0.27.2': + optional: true + + '@esbuild/freebsd-x64@0.27.2': + optional: true + + '@esbuild/linux-arm64@0.27.2': + optional: true + + '@esbuild/linux-arm@0.27.2': + optional: true + + '@esbuild/linux-ia32@0.27.2': + optional: true + + '@esbuild/linux-loong64@0.27.2': + optional: true + + '@esbuild/linux-mips64el@0.27.2': + optional: true + + '@esbuild/linux-ppc64@0.27.2': + optional: true + + '@esbuild/linux-riscv64@0.27.2': + optional: true + + '@esbuild/linux-s390x@0.27.2': + optional: true + + '@esbuild/linux-x64@0.27.2': + optional: true + + '@esbuild/netbsd-arm64@0.27.2': + optional: true + + '@esbuild/netbsd-x64@0.27.2': + optional: true + + '@esbuild/openbsd-arm64@0.27.2': + optional: true + + '@esbuild/openbsd-x64@0.27.2': + optional: true + + '@esbuild/openharmony-arm64@0.27.2': + optional: true + + '@esbuild/sunos-x64@0.27.2': + optional: true + + '@esbuild/win32-arm64@0.27.2': + optional: true + + '@esbuild/win32-ia32@0.27.2': + optional: true + + '@esbuild/win32-x64@0.27.2': + optional: true + + '@floating-ui/core@1.7.3': + dependencies: + '@floating-ui/utils': 0.2.10 + + '@floating-ui/dom@1.7.4': + dependencies: + '@floating-ui/core': 1.7.3 + '@floating-ui/utils': 0.2.10 + + '@floating-ui/utils@0.2.10': {} + + '@floating-ui/vue@1.1.9(vue@3.5.27(typescript@5.9.3))': + dependencies: + '@floating-ui/dom': 1.7.4 + '@floating-ui/utils': 0.2.10 + vue-demi: 0.14.10(vue@3.5.27(typescript@5.9.3)) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + + '@internationalized/date@3.10.1': + dependencies: + '@swc/helpers': 0.5.18 + + '@internationalized/number@3.6.5': + dependencies: + '@swc/helpers': 0.5.18 + + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/sourcemap-codec@1.5.5': {} + + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + + '@rolldown/pluginutils@1.0.0-beta.53': {} + + '@rollup/rollup-android-arm-eabi@4.55.2': + optional: true + + '@rollup/rollup-android-arm64@4.55.2': + optional: true + + '@rollup/rollup-darwin-arm64@4.55.2': + optional: true + + '@rollup/rollup-darwin-x64@4.55.2': + optional: true + + '@rollup/rollup-freebsd-arm64@4.55.2': + optional: true + + '@rollup/rollup-freebsd-x64@4.55.2': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.55.2': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.55.2': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.55.2': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.55.2': + optional: true + + '@rollup/rollup-linux-loong64-gnu@4.55.2': + optional: true + + '@rollup/rollup-linux-loong64-musl@4.55.2': + optional: true + + '@rollup/rollup-linux-ppc64-gnu@4.55.2': + optional: true + + '@rollup/rollup-linux-ppc64-musl@4.55.2': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.55.2': + optional: true + + '@rollup/rollup-linux-riscv64-musl@4.55.2': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.55.2': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.55.2': + optional: true + + '@rollup/rollup-linux-x64-musl@4.55.2': + optional: true + + '@rollup/rollup-openbsd-x64@4.55.2': + optional: true + + '@rollup/rollup-openharmony-arm64@4.55.2': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.55.2': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.55.2': + optional: true + + '@rollup/rollup-win32-x64-gnu@4.55.2': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.55.2': + optional: true + + '@swc/helpers@0.5.18': + dependencies: + tslib: 2.8.1 + + '@tailwindcss/node@4.1.18': + dependencies: + '@jridgewell/remapping': 2.3.5 + enhanced-resolve: 5.18.4 + jiti: 2.6.1 + lightningcss: 1.30.2 + magic-string: 0.30.21 + source-map-js: 1.2.1 + tailwindcss: 4.1.18 + + '@tailwindcss/oxide-android-arm64@4.1.18': + optional: true + + '@tailwindcss/oxide-darwin-arm64@4.1.18': + optional: true + + '@tailwindcss/oxide-darwin-x64@4.1.18': + optional: true + + '@tailwindcss/oxide-freebsd-x64@4.1.18': + optional: true + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.18': + optional: true + + '@tailwindcss/oxide-linux-arm64-gnu@4.1.18': + optional: true + + '@tailwindcss/oxide-linux-arm64-musl@4.1.18': + optional: true + + '@tailwindcss/oxide-linux-x64-gnu@4.1.18': + optional: true + + '@tailwindcss/oxide-linux-x64-musl@4.1.18': + optional: true + + '@tailwindcss/oxide-wasm32-wasi@4.1.18': + optional: true + + '@tailwindcss/oxide-win32-arm64-msvc@4.1.18': + optional: true + + '@tailwindcss/oxide-win32-x64-msvc@4.1.18': + optional: true + + '@tailwindcss/oxide@4.1.18': + optionalDependencies: + '@tailwindcss/oxide-android-arm64': 4.1.18 + '@tailwindcss/oxide-darwin-arm64': 4.1.18 + '@tailwindcss/oxide-darwin-x64': 4.1.18 + '@tailwindcss/oxide-freebsd-x64': 4.1.18 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.18 + '@tailwindcss/oxide-linux-arm64-gnu': 4.1.18 + '@tailwindcss/oxide-linux-arm64-musl': 4.1.18 + '@tailwindcss/oxide-linux-x64-gnu': 4.1.18 + '@tailwindcss/oxide-linux-x64-musl': 4.1.18 + '@tailwindcss/oxide-wasm32-wasi': 4.1.18 + '@tailwindcss/oxide-win32-arm64-msvc': 4.1.18 + '@tailwindcss/oxide-win32-x64-msvc': 4.1.18 + + '@tailwindcss/vite@4.1.18(vite@7.3.1(@types/node@24.10.9)(jiti@2.6.1)(lightningcss@1.30.2))': + dependencies: + '@tailwindcss/node': 4.1.18 + '@tailwindcss/oxide': 4.1.18 + tailwindcss: 4.1.18 + vite: 7.3.1(@types/node@24.10.9)(jiti@2.6.1)(lightningcss@1.30.2) + + '@tanstack/virtual-core@3.13.18': {} + + '@tanstack/vue-virtual@3.13.18(vue@3.5.27(typescript@5.9.3))': + dependencies: + '@tanstack/virtual-core': 3.13.18 + vue: 3.5.27(typescript@5.9.3) + + '@trysound/sax@0.2.0': {} + + '@tsconfig/node24@24.0.4': {} + + '@types/estree@1.0.8': {} + + '@types/node@24.10.9': + dependencies: + undici-types: 7.16.0 + + '@types/web-bluetooth@0.0.21': {} + + '@vitejs/plugin-vue@6.0.3(vite@7.3.1(@types/node@24.10.9)(jiti@2.6.1)(lightningcss@1.30.2))(vue@3.5.27(typescript@5.9.3))': + dependencies: + '@rolldown/pluginutils': 1.0.0-beta.53 + vite: 7.3.1(@types/node@24.10.9)(jiti@2.6.1)(lightningcss@1.30.2) + vue: 3.5.27(typescript@5.9.3) + + '@volar/language-core@2.4.27': + dependencies: + '@volar/source-map': 2.4.27 + + '@volar/source-map@2.4.27': {} + + '@volar/typescript@2.4.27': + dependencies: + '@volar/language-core': 2.4.27 + path-browserify: 1.0.1 + vscode-uri: 3.1.0 + + '@vue/compiler-core@3.5.27': + dependencies: + '@babel/parser': 7.28.6 + '@vue/shared': 3.5.27 + entities: 7.0.0 + estree-walker: 2.0.2 + source-map-js: 1.2.1 + + '@vue/compiler-dom@3.5.27': + dependencies: + '@vue/compiler-core': 3.5.27 + '@vue/shared': 3.5.27 + + '@vue/compiler-sfc@3.5.27': + dependencies: + '@babel/parser': 7.28.6 + '@vue/compiler-core': 3.5.27 + '@vue/compiler-dom': 3.5.27 + '@vue/compiler-ssr': 3.5.27 + '@vue/shared': 3.5.27 + estree-walker: 2.0.2 + magic-string: 0.30.21 + postcss: 8.5.6 + source-map-js: 1.2.1 + + '@vue/compiler-ssr@3.5.27': + dependencies: + '@vue/compiler-dom': 3.5.27 + '@vue/shared': 3.5.27 + + '@vue/language-core@3.2.2': + dependencies: + '@volar/language-core': 2.4.27 + '@vue/compiler-dom': 3.5.27 + '@vue/shared': 3.5.27 + alien-signals: 3.1.2 + muggle-string: 0.4.1 + path-browserify: 1.0.1 + picomatch: 4.0.3 + + '@vue/reactivity@3.5.27': + dependencies: + '@vue/shared': 3.5.27 + + '@vue/runtime-core@3.5.27': + dependencies: + '@vue/reactivity': 3.5.27 + '@vue/shared': 3.5.27 + + '@vue/runtime-dom@3.5.27': + dependencies: + '@vue/reactivity': 3.5.27 + '@vue/runtime-core': 3.5.27 + '@vue/shared': 3.5.27 + csstype: 3.2.3 + + '@vue/server-renderer@3.5.27(vue@3.5.27(typescript@5.9.3))': + dependencies: + '@vue/compiler-ssr': 3.5.27 + '@vue/shared': 3.5.27 + vue: 3.5.27(typescript@5.9.3) + + '@vue/shared@3.5.27': {} + + '@vue/tsconfig@0.8.1(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3))': + optionalDependencies: + typescript: 5.9.3 + vue: 3.5.27(typescript@5.9.3) + + '@vueuse/core@12.8.2(typescript@5.9.3)': + dependencies: + '@types/web-bluetooth': 0.0.21 + '@vueuse/metadata': 12.8.2 + '@vueuse/shared': 12.8.2(typescript@5.9.3) + vue: 3.5.27(typescript@5.9.3) + transitivePeerDependencies: + - typescript + + '@vueuse/metadata@12.8.2': {} + + '@vueuse/shared@12.8.2(typescript@5.9.3)': + dependencies: + vue: 3.5.27(typescript@5.9.3) + transitivePeerDependencies: + - typescript + + alien-signals@3.1.2: {} + + aria-hidden@1.2.6: + dependencies: + tslib: 2.8.1 + + asynckit@0.4.0: {} + + axios@1.13.2: + dependencies: + follow-redirects: 1.15.11 + form-data: 4.0.5 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + + boolbase@1.0.0: {} + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + clsx@2.1.1: {} + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + commander@7.2.0: {} + + css-select@5.2.2: + dependencies: + boolbase: 1.0.0 + css-what: 6.2.2 + domhandler: 5.0.3 + domutils: 3.2.2 + nth-check: 2.1.1 + + css-tree@2.2.1: + dependencies: + mdn-data: 2.0.28 + source-map-js: 1.2.1 + + css-tree@2.3.1: + dependencies: + mdn-data: 2.0.30 + source-map-js: 1.2.1 + + css-what@6.2.2: {} + + csso@5.0.5: + dependencies: + css-tree: 2.2.1 + + csstype@3.2.3: {} + + defu@6.1.4: {} + + delayed-stream@1.0.0: {} + + detect-libc@2.1.2: {} + + dom-serializer@2.0.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + entities: 4.5.0 + + domelementtype@2.3.0: {} + + domhandler@5.0.3: + dependencies: + domelementtype: 2.3.0 + + domutils@3.2.2: + dependencies: + dom-serializer: 2.0.0 + domelementtype: 2.3.0 + domhandler: 5.0.3 + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + enhanced-resolve@5.18.4: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.3.0 + + entities@4.5.0: {} + + entities@7.0.0: {} + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + esbuild@0.27.2: + optionalDependencies: + '@esbuild/aix-ppc64': 0.27.2 + '@esbuild/android-arm': 0.27.2 + '@esbuild/android-arm64': 0.27.2 + '@esbuild/android-x64': 0.27.2 + '@esbuild/darwin-arm64': 0.27.2 + '@esbuild/darwin-x64': 0.27.2 + '@esbuild/freebsd-arm64': 0.27.2 + '@esbuild/freebsd-x64': 0.27.2 + '@esbuild/linux-arm': 0.27.2 + '@esbuild/linux-arm64': 0.27.2 + '@esbuild/linux-ia32': 0.27.2 + '@esbuild/linux-loong64': 0.27.2 + '@esbuild/linux-mips64el': 0.27.2 + '@esbuild/linux-ppc64': 0.27.2 + '@esbuild/linux-riscv64': 0.27.2 + '@esbuild/linux-s390x': 0.27.2 + '@esbuild/linux-x64': 0.27.2 + '@esbuild/netbsd-arm64': 0.27.2 + '@esbuild/netbsd-x64': 0.27.2 + '@esbuild/openbsd-arm64': 0.27.2 + '@esbuild/openbsd-x64': 0.27.2 + '@esbuild/openharmony-arm64': 0.27.2 + '@esbuild/sunos-x64': 0.27.2 + '@esbuild/win32-arm64': 0.27.2 + '@esbuild/win32-ia32': 0.27.2 + '@esbuild/win32-x64': 0.27.2 + + estree-walker@2.0.2: {} + + fdir@6.5.0(picomatch@4.0.3): + optionalDependencies: + picomatch: 4.0.3 + + follow-redirects@1.15.11: {} + + form-data@4.0.5: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + hasown: 2.0.2 + mime-types: 2.1.35 + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + math-intrinsics: 1.1.0 + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + + gopd@1.2.0: {} + + graceful-fs@4.2.11: {} + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + jiti@2.6.1: {} + + lightningcss-android-arm64@1.30.2: + optional: true + + lightningcss-darwin-arm64@1.30.2: + optional: true + + lightningcss-darwin-x64@1.30.2: + optional: true + + lightningcss-freebsd-x64@1.30.2: + optional: true + + lightningcss-linux-arm-gnueabihf@1.30.2: + optional: true + + lightningcss-linux-arm64-gnu@1.30.2: + optional: true + + lightningcss-linux-arm64-musl@1.30.2: + optional: true + + lightningcss-linux-x64-gnu@1.30.2: + optional: true + + lightningcss-linux-x64-musl@1.30.2: + optional: true + + lightningcss-win32-arm64-msvc@1.30.2: + optional: true + + lightningcss-win32-x64-msvc@1.30.2: + optional: true + + lightningcss@1.30.2: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.30.2 + lightningcss-darwin-arm64: 1.30.2 + lightningcss-darwin-x64: 1.30.2 + lightningcss-freebsd-x64: 1.30.2 + lightningcss-linux-arm-gnueabihf: 1.30.2 + lightningcss-linux-arm64-gnu: 1.30.2 + lightningcss-linux-arm64-musl: 1.30.2 + lightningcss-linux-x64-gnu: 1.30.2 + lightningcss-linux-x64-musl: 1.30.2 + lightningcss-win32-arm64-msvc: 1.30.2 + lightningcss-win32-x64-msvc: 1.30.2 + + lucide-vue-next@0.562.0(vue@3.5.27(typescript@5.9.3)): + dependencies: + vue: 3.5.27(typescript@5.9.3) + + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + + math-intrinsics@1.1.0: {} + + mdn-data@2.0.28: {} + + mdn-data@2.0.30: {} + + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + muggle-string@0.4.1: {} + + nanoid@3.3.11: {} + + nth-check@2.1.1: + dependencies: + boolbase: 1.0.0 + + ohash@2.0.11: {} + + path-browserify@1.0.1: {} + + picocolors@1.1.1: {} + + picomatch@4.0.3: {} + + postcss@8.5.6: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + prettier-plugin-tailwindcss@0.7.2(prettier@3.8.0): + dependencies: + prettier: 3.8.0 + + prettier@3.8.0: {} + + proxy-from-env@1.1.0: {} + + reka-ui@2.7.0(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3)): + dependencies: + '@floating-ui/dom': 1.7.4 + '@floating-ui/vue': 1.1.9(vue@3.5.27(typescript@5.9.3)) + '@internationalized/date': 3.10.1 + '@internationalized/number': 3.6.5 + '@tanstack/vue-virtual': 3.13.18(vue@3.5.27(typescript@5.9.3)) + '@vueuse/core': 12.8.2(typescript@5.9.3) + '@vueuse/shared': 12.8.2(typescript@5.9.3) + aria-hidden: 1.2.6 + defu: 6.1.4 + ohash: 2.0.11 + vue: 3.5.27(typescript@5.9.3) + transitivePeerDependencies: + - '@vue/composition-api' + - typescript + + rollup@4.55.2: + dependencies: + '@types/estree': 1.0.8 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.55.2 + '@rollup/rollup-android-arm64': 4.55.2 + '@rollup/rollup-darwin-arm64': 4.55.2 + '@rollup/rollup-darwin-x64': 4.55.2 + '@rollup/rollup-freebsd-arm64': 4.55.2 + '@rollup/rollup-freebsd-x64': 4.55.2 + '@rollup/rollup-linux-arm-gnueabihf': 4.55.2 + '@rollup/rollup-linux-arm-musleabihf': 4.55.2 + '@rollup/rollup-linux-arm64-gnu': 4.55.2 + '@rollup/rollup-linux-arm64-musl': 4.55.2 + '@rollup/rollup-linux-loong64-gnu': 4.55.2 + '@rollup/rollup-linux-loong64-musl': 4.55.2 + '@rollup/rollup-linux-ppc64-gnu': 4.55.2 + '@rollup/rollup-linux-ppc64-musl': 4.55.2 + '@rollup/rollup-linux-riscv64-gnu': 4.55.2 + '@rollup/rollup-linux-riscv64-musl': 4.55.2 + '@rollup/rollup-linux-s390x-gnu': 4.55.2 + '@rollup/rollup-linux-x64-gnu': 4.55.2 + '@rollup/rollup-linux-x64-musl': 4.55.2 + '@rollup/rollup-openbsd-x64': 4.55.2 + '@rollup/rollup-openharmony-arm64': 4.55.2 + '@rollup/rollup-win32-arm64-msvc': 4.55.2 + '@rollup/rollup-win32-ia32-msvc': 4.55.2 + '@rollup/rollup-win32-x64-gnu': 4.55.2 + '@rollup/rollup-win32-x64-msvc': 4.55.2 + fsevents: 2.3.3 + + source-map-js@1.2.1: {} + + svgo@3.3.2: + dependencies: + '@trysound/sax': 0.2.0 + commander: 7.2.0 + css-select: 5.2.2 + css-tree: 2.3.1 + css-what: 6.2.2 + csso: 5.0.5 + picocolors: 1.1.1 + + tailwind-merge@3.4.0: {} + + tailwindcss@4.1.18: {} + + tapable@2.3.0: {} + + tinyglobby@0.2.15: + dependencies: + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + + tslib@2.8.1: {} + + tw-animate-css@1.4.0: {} + + typescript@5.9.3: {} + + undici-types@7.16.0: {} + + vite-svg-loader@5.1.0(vue@3.5.27(typescript@5.9.3)): + dependencies: + svgo: 3.3.2 + vue: 3.5.27(typescript@5.9.3) + + vite@7.3.1(@types/node@24.10.9)(jiti@2.6.1)(lightningcss@1.30.2): + dependencies: + esbuild: 0.27.2 + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + postcss: 8.5.6 + rollup: 4.55.2 + tinyglobby: 0.2.15 + optionalDependencies: + '@types/node': 24.10.9 + fsevents: 2.3.3 + jiti: 2.6.1 + lightningcss: 1.30.2 + + vscode-uri@3.1.0: {} + + vue-demi@0.14.10(vue@3.5.27(typescript@5.9.3)): + dependencies: + vue: 3.5.27(typescript@5.9.3) + + vue-sonner@2.0.9: {} + + vue-tsc@3.2.2(typescript@5.9.3): + dependencies: + '@volar/typescript': 2.4.27 + '@vue/language-core': 3.2.2 + typescript: 5.9.3 + + vue@3.5.27(typescript@5.9.3): + dependencies: + '@vue/compiler-dom': 3.5.27 + '@vue/compiler-sfc': 3.5.27 + '@vue/runtime-dom': 3.5.27 + '@vue/server-renderer': 3.5.27(vue@3.5.27(typescript@5.9.3)) + '@vue/shared': 3.5.27 + optionalDependencies: + typescript: 5.9.3 diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..2c3a369 Binary files /dev/null and b/public/favicon.ico differ diff --git a/src/App.vue b/src/App.vue new file mode 100644 index 0000000..89b690d --- /dev/null +++ b/src/App.vue @@ -0,0 +1,26 @@ + + + + + diff --git a/src/components/ui/button/Button.vue b/src/components/ui/button/Button.vue new file mode 100644 index 0000000..374320b --- /dev/null +++ b/src/components/ui/button/Button.vue @@ -0,0 +1,29 @@ + + + diff --git a/src/components/ui/button/index.ts b/src/components/ui/button/index.ts new file mode 100644 index 0000000..5262d70 --- /dev/null +++ b/src/components/ui/button/index.ts @@ -0,0 +1,35 @@ +import type { VariantProps } from 'class-variance-authority' +import { cva } from 'class-variance-authority' + +export { default as Button } from './Button.vue' + +export const buttonVariants = cva( + "inline-flex cursor-pointer items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", + { + variants: { + variant: { + default: 'bg-primary text-primary-foreground hover:bg-primary/90', + destructive: + 'bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60', + outline: + 'border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50', + secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80', + ghost: 'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50', + link: 'text-primary underline-offset-4 hover:underline', + }, + size: { + default: 'h-9 px-4 py-2 has-[>svg]:px-3', + sm: 'h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5', + lg: 'h-10 rounded-md px-6 has-[>svg]:px-4', + icon: 'size-9', + 'icon-sm': 'size-8', + 'icon-lg': 'size-10', + }, + }, + defaultVariants: { + variant: 'default', + size: 'default', + }, + }, +) +export type ButtonVariants = VariantProps diff --git a/src/components/ui/input/Input.vue b/src/components/ui/input/Input.vue new file mode 100644 index 0000000..e5135c1 --- /dev/null +++ b/src/components/ui/input/Input.vue @@ -0,0 +1,33 @@ + + + diff --git a/src/components/ui/input/index.ts b/src/components/ui/input/index.ts new file mode 100644 index 0000000..9976b86 --- /dev/null +++ b/src/components/ui/input/index.ts @@ -0,0 +1 @@ +export { default as Input } from "./Input.vue" diff --git a/src/components/ui/sonner/Sonner.vue b/src/components/ui/sonner/Sonner.vue new file mode 100644 index 0000000..6830896 --- /dev/null +++ b/src/components/ui/sonner/Sonner.vue @@ -0,0 +1,42 @@ + + + diff --git a/src/components/ui/sonner/index.ts b/src/components/ui/sonner/index.ts new file mode 100644 index 0000000..6673112 --- /dev/null +++ b/src/components/ui/sonner/index.ts @@ -0,0 +1 @@ +export { default as Toaster } from "./Sonner.vue" diff --git a/src/lib/utils.ts b/src/lib/utils.ts new file mode 100644 index 0000000..c66a9d9 --- /dev/null +++ b/src/lib/utils.ts @@ -0,0 +1,7 @@ +import type { ClassValue } from "clsx" +import { clsx } from "clsx" +import { twMerge } from "tailwind-merge" + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)) +} diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..94336c5 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,6 @@ +import { createApp } from 'vue' +import './styles/index.css' +import App from './App.vue' +import '@/utils/openinstall.ts' + +createApp(App).mount('#app') diff --git a/src/pages/Home/Liquid-button-bg.png b/src/pages/Home/Liquid-button-bg.png new file mode 100644 index 0000000..7211f47 Binary files /dev/null and b/src/pages/Home/Liquid-button-bg.png differ diff --git a/src/pages/Home/bg-desktop.webp b/src/pages/Home/bg-desktop.webp new file mode 100644 index 0000000..67822bb Binary files /dev/null and b/src/pages/Home/bg-desktop.webp differ diff --git a/src/pages/Home/bg-mobile.webp b/src/pages/Home/bg-mobile.webp new file mode 100644 index 0000000..f2ffe7c Binary files /dev/null and b/src/pages/Home/bg-mobile.webp differ diff --git a/src/pages/Home/components/DownloadButton.vue b/src/pages/Home/components/DownloadButton.vue new file mode 100644 index 0000000..2f41740 --- /dev/null +++ b/src/pages/Home/components/DownloadButton.vue @@ -0,0 +1,66 @@ + + + diff --git a/src/pages/Home/components/Group 105.svg b/src/pages/Home/components/Group 105.svg new file mode 100644 index 0000000..e2c1136 --- /dev/null +++ b/src/pages/Home/components/Group 105.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/pages/Home/components/Group 106.svg b/src/pages/Home/components/Group 106.svg new file mode 100644 index 0000000..42552bf --- /dev/null +++ b/src/pages/Home/components/Group 106.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/pages/Home/components/Group 107.svg b/src/pages/Home/components/Group 107.svg new file mode 100644 index 0000000..26e3f17 --- /dev/null +++ b/src/pages/Home/components/Group 107.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/pages/Home/components/Group 108.svg b/src/pages/Home/components/Group 108.svg new file mode 100644 index 0000000..ea8d296 --- /dev/null +++ b/src/pages/Home/components/Group 108.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/pages/Home/connected-bg.png b/src/pages/Home/connected-bg.png new file mode 100644 index 0000000..b7a217a Binary files /dev/null and b/src/pages/Home/connected-bg.png differ diff --git a/src/pages/Home/connected-mobile-bg.png b/src/pages/Home/connected-mobile-bg.png new file mode 100644 index 0000000..e4c284a Binary files /dev/null and b/src/pages/Home/connected-mobile-bg.png differ diff --git a/src/pages/Home/hiLogo.svg b/src/pages/Home/hiLogo.svg new file mode 100644 index 0000000..6264878 --- /dev/null +++ b/src/pages/Home/hiLogo.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/pages/Home/image-1.png b/src/pages/Home/image-1.png new file mode 100644 index 0000000..526f87e Binary files /dev/null and b/src/pages/Home/image-1.png differ diff --git a/src/pages/Home/index.vue b/src/pages/Home/index.vue new file mode 100644 index 0000000..fc94bd0 --- /dev/null +++ b/src/pages/Home/index.vue @@ -0,0 +1,182 @@ + + + + + diff --git a/src/pages/Home/logo.svg b/src/pages/Home/logo.svg new file mode 100644 index 0000000..b23a2dd --- /dev/null +++ b/src/pages/Home/logo.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/pages/Home/mobile-logo.svg b/src/pages/Home/mobile-logo.svg new file mode 100644 index 0000000..7be4d9c --- /dev/null +++ b/src/pages/Home/mobile-logo.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/pages/Home/screenshot-desktop.webp b/src/pages/Home/screenshot-desktop.webp new file mode 100644 index 0000000..047cb64 Binary files /dev/null and b/src/pages/Home/screenshot-desktop.webp differ diff --git a/src/pages/Home/screenshot-mobile.png b/src/pages/Home/screenshot-mobile.png new file mode 100644 index 0000000..bde8220 Binary files /dev/null and b/src/pages/Home/screenshot-mobile.png differ diff --git a/src/pages/Home/x-logo.png b/src/pages/Home/x-logo.png new file mode 100644 index 0000000..5c647a2 Binary files /dev/null and b/src/pages/Home/x-logo.png differ diff --git a/src/styles/index.css b/src/styles/index.css new file mode 100644 index 0000000..9912913 --- /dev/null +++ b/src/styles/index.css @@ -0,0 +1,186 @@ +@font-face { + font-family: 'Roboto'; + src: url('/src/styles/roboto.woff2') format('woff2'); + font-weight: 100 900; + font-style: normal; + font-display: swap; +} +html, body { + background: #000; +} +.lucid-glass-bar { + /* 基础背景:Figma 中通常是叠加的,这里取中值确保通透度 */ + background: rgb(255 255 255 / 6%); + + /* 核心模糊 */ + @apply backdrop-blur-[36px]; + + /* 圆角:由于你有 border-image,建议使用这种方式保留圆角 */ + border-radius: 999px; + + /* 边框:Figma 的 border-image 在 CSS 圆角容器上会有兼容问题 + 建议改用单纯的 border 配合 rgba 以达到线性渐变的效果 */ + border: 1px solid rgba(255, 255, 255, 0.2); + + /* 阴影叠加:按照 Figma 从上到下的顺序转换 */ + box-shadow: + /* 1. 这里的 #F2F2F280 33px 扩散是导致发白的主因,建议将其放在最底层并调低不透明度 */ + inset 0px 0px 33px 0px rgba(242, 242, 242, 0.15), + + /* 2. 右下角的反向高光 (原本的 -3px -4.5px) */ + inset 0px -2px 1.5px -3px rgba(179, 179, 179, 0.5), + + /* 3. 左上角的微弱亮边 */ + inset 3px 4.5px 1.5px -3px rgba(179, 179, 179, 0.2), + + /* 4. 核心受光面 (Figma: 4.5px 4.5px #FFFFFF80) */ + inset 4.5px 4.5px 1.5px -5.25px rgba(255, 255, 255, 0.4), + + /* 5. 核心背光面 (Figma: -4.5px -4.5px #FFFFFF80) */ + inset -4.5px -4.5px 1.5px -5.25px rgba(255, 255, 255, 0.3); +} + +@import "tailwindcss"; +@import "tw-animate-css"; + +@layer components { + .container { + width: 100%; + margin-left: auto; + margin-right: auto; + + /* 1. 移动端默认:左右 18px 边距 */ + padding-left: 18px; + padding-right: 18px; + + /* 2. 桌面端逻辑:当屏幕达到 1440px 及以上 */ + @media (width >= 1440px) { + /* 计算公式: + 内容区固定为 1268px + 侧边留白 = (1440 - 1268) / 2 = 86px + */ + max-width: 1268px; + + /* 此时 padding 可以设为 0,因为 max-width 配合 margin: auto 已经产生了 86px 的留白 */ + padding-left: 0; + padding-right: 0; + } + } +} +@custom-variant dark (&:is(.dark *)); + +@theme inline { + --radius-sm: calc(var(--radius) - 4px); + --radius-md: calc(var(--radius) - 2px); + --radius-lg: var(--radius); + --radius-xl: calc(var(--radius) + 4px); + --color-background: var(--background); + --color-foreground: var(--foreground); + --color-card: var(--card); + --color-card-foreground: var(--card-foreground); + --color-popover: var(--popover); + --color-popover-foreground: var(--popover-foreground); + --color-primary: var(--primary); + --color-primary-foreground: var(--primary-foreground); + --color-secondary: var(--secondary); + --color-secondary-foreground: var(--secondary-foreground); + --color-muted: var(--muted); + --color-muted-foreground: var(--muted-foreground); + --color-accent: var(--accent); + --color-accent-foreground: var(--accent-foreground); + --color-destructive: var(--destructive); + --color-border: var(--border); + --color-input: var(--input); + --color-ring: var(--ring); + --color-chart-1: var(--chart-1); + --color-chart-2: var(--chart-2); + --color-chart-3: var(--chart-3); + --color-chart-4: var(--chart-4); + --color-chart-5: var(--chart-5); + --color-sidebar: var(--sidebar); + --color-sidebar-foreground: var(--sidebar-foreground); + --color-sidebar-primary: var(--sidebar-primary); + --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); + --color-sidebar-accent: var(--sidebar-accent); + --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); + --color-sidebar-border: var(--sidebar-border); + --color-sidebar-ring: var(--sidebar-ring); +} + +:root { + --radius: 0.625rem; + --background: oklch(1 0 0); + --foreground: oklch(0.145 0 0); + --card: oklch(1 0 0); + --card-foreground: oklch(0.145 0 0); + --popover: oklch(1 0 0); + --popover-foreground: oklch(0.145 0 0); + --primary: oklch(0.205 0 0); + --primary-foreground: oklch(0.985 0 0); + --secondary: oklch(0.97 0 0); + --secondary-foreground: oklch(0.205 0 0); + --muted: oklch(0.97 0 0); + --muted-foreground: oklch(0.556 0 0); + --accent: oklch(0.97 0 0); + --accent-foreground: oklch(0.205 0 0); + --destructive: oklch(0.577 0.245 27.325); + --border: oklch(0.922 0 0); + --input: oklch(0.922 0 0); + --ring: oklch(0.708 0 0); + --chart-1: oklch(0.646 0.222 41.116); + --chart-2: oklch(0.6 0.118 184.704); + --chart-3: oklch(0.398 0.07 227.392); + --chart-4: oklch(0.828 0.189 84.429); + --chart-5: oklch(0.769 0.188 70.08); + --sidebar: oklch(0.985 0 0); + --sidebar-foreground: oklch(0.145 0 0); + --sidebar-primary: oklch(0.205 0 0); + --sidebar-primary-foreground: oklch(0.985 0 0); + --sidebar-accent: oklch(0.97 0 0); + --sidebar-accent-foreground: oklch(0.205 0 0); + --sidebar-border: oklch(0.922 0 0); + --sidebar-ring: oklch(0.708 0 0); +} + +.dark { + --background: oklch(0.145 0 0); + --foreground: oklch(0.985 0 0); + --card: oklch(0.205 0 0); + --card-foreground: oklch(0.985 0 0); + --popover: oklch(0.205 0 0); + --popover-foreground: oklch(0.985 0 0); + --primary: oklch(0.922 0 0); + --primary-foreground: oklch(0.205 0 0); + --secondary: oklch(0.269 0 0); + --secondary-foreground: oklch(0.985 0 0); + --muted: oklch(0.269 0 0); + --muted-foreground: oklch(0.708 0 0); + --accent: oklch(0.269 0 0); + --accent-foreground: oklch(0.985 0 0); + --destructive: oklch(0.704 0.191 22.216); + --border: oklch(1 0 0 / 10%); + --input: oklch(1 0 0 / 15%); + --ring: oklch(0.556 0 0); + --chart-1: oklch(0.488 0.243 264.376); + --chart-2: oklch(0.696 0.17 162.48); + --chart-3: oklch(0.769 0.188 70.08); + --chart-4: oklch(0.627 0.265 303.9); + --chart-5: oklch(0.645 0.246 16.439); + --sidebar: oklch(0.205 0 0); + --sidebar-foreground: oklch(0.985 0 0); + --sidebar-primary: oklch(0.488 0.243 264.376); + --sidebar-primary-foreground: oklch(0.985 0 0); + --sidebar-accent: oklch(0.269 0 0); + --sidebar-accent-foreground: oklch(0.985 0 0); + --sidebar-border: oklch(1 0 0 / 10%); + --sidebar-ring: oklch(0.556 0 0); +} + +@layer base { + * { + @apply border-border outline-ring/50; + } + body { + @apply bg-background text-foreground; + } +} diff --git a/src/styles/roboto.woff2 b/src/styles/roboto.woff2 new file mode 100644 index 0000000..0943c6b Binary files /dev/null and b/src/styles/roboto.woff2 differ diff --git a/src/utils/constant.ts b/src/utils/constant.ts new file mode 100644 index 0000000..dad7cb4 --- /dev/null +++ b/src/utils/constant.ts @@ -0,0 +1,7 @@ +// utils/constant.ts +const BASE_URL = window.location.origin // 自动获取当前域名 + +export const downLoadAndroid = `${BASE_URL}/download/app-arm64-v8a-release.apk` +export const downLoadMac = `${BASE_URL}/download/HiFastVPN-1.0.0+100-macos.dmg` +export const downLoadWin = `${BASE_URL}/download/HiFastVPN-0.0.2-windows-setup.exe` +export const downLoadIos = 'https://apps.apple.com/us/app/hi%E5%BF%ABvpn/id6755683167' diff --git a/src/utils/openinstall.ts b/src/utils/openinstall.ts new file mode 100644 index 0000000..65faf54 --- /dev/null +++ b/src/utils/openinstall.ts @@ -0,0 +1,72 @@ +import { getAllQuertString } from '@/utils/url-utils.ts' + +/** + * OpenInstall sdk 用于上报h5邀请参数 + * 自动注册openinstall sdk 挂在到window对象上 通过window.OI_SDK访问 + * sdk初始化时会自动检索url上的参数并作为拉起下载或唤醒app时的参数 + */ +const script = document.createElement('script') +script.type = 'text/javascript' +script.charset = 'UTF-8' +script.src = 'https://web.cdn.openinstall.io/openinstall.js' +document.head.appendChild(script) + +script.addEventListener('load', () => { + window.OI_SDK = new OpenInstallSdk() +}) + +class OpenInstallSdk { + public urlQuery: any // openinstall.js中提供的api,解析当前网页url中的查询参数并对data进行赋值 + + public OI: Record // openinstall 实例 + + constructor() { + this.OI = {} + this.urlQuery = window.OpenInstall.parseUrlParams() + const id = getAllQuertString('id') + if (id) { + this.urlQuery = { + platform: 'merchant', + code: id, + } + } + this.init() + } + + async init() { + try { + this.OI = new window.OpenInstall({ + appKey: 'alf57p', + onready: function () { // 初始化成功回调方法。当初始化完成后,会自动进入 + this.schemeWakeup()// 尝试使用scheme打开App(主要用于Android以及iOS的QQ环境中) + const m = this + const button = document.getElementById('downloadButton_apple') + const button1 = document.getElementById('downloadButton_android') + const ic = getAllQuertString('ic') + if (button) { + button.onclick = function () { + if (ic) { + m.wakeupOrInstall({ data: { platform: 'download', inviteCode: ic } }) + } else { + m.wakeupOrInstall()// 此方法为scheme、Universal Link唤醒以及引导下载的作用(必须调用且不可额外自行跳转下载) + } + return false + } + } + if (button1) { + button1.onclick = function () { + if (ic) { + m.wakeupOrInstall({ data: { platform: 'download', inviteCode: ic } }) + } else { + m.wakeupOrInstall()// 此方法为scheme、Universal Link唤醒以及引导下载的作用(必须调用且不可额外自行跳转下载) + } + return false + } + } + }, + }, this.urlQuery)// 初始化时传入data,作为一键拉起/App传参安装时候的参数 + } catch (e) { + console.log(e, 'OpenInstall——sdk初始化失败') + } + } +} diff --git a/src/utils/request/cancel.ts b/src/utils/request/cancel.ts new file mode 100644 index 0000000..f63a223 --- /dev/null +++ b/src/utils/request/cancel.ts @@ -0,0 +1,58 @@ +import type { AxiosRequestConfig, Canceler } from 'axios' +import axios from 'axios' + +// Used to store the identification and cancellation function of each request +let pendingMap = new Map() + +const getPendingUrl = (config: AxiosRequestConfig) => [config.method, config.url].join('&') + +export class AxiosCanceler { + /** + * Add request + * @param {Object} config + */ + addPending(config: AxiosRequestConfig): void { + this.removePending(config) + const url = getPendingUrl(config) + config.cancelToken = config.cancelToken + || new axios.CancelToken((cancel) => { + if (!pendingMap.has(url)) { + // If there is no current request in pending, add it + pendingMap.set(url, cancel) + } + }) + } + + /** + * @description: Clear all pending + */ + removeAllPending(): void { + pendingMap.forEach((cancel) => { + cancel?.() + }) + pendingMap.clear() + } + + /** + * Removal request + * @param {Object} config + */ + removePending(config: AxiosRequestConfig): void { + const url = getPendingUrl(config) + + if (pendingMap.has(url)) { + // If there is a current request identifier in pending, + // the current request needs to be cancelled and removed + const cancel = pendingMap.get(url) + cancel && cancel(url) + pendingMap.delete(url) + } + } + + /** + * @description: reset + */ + reset(): void { + pendingMap = new Map() + } +} diff --git a/src/utils/request/core.ts b/src/utils/request/core.ts new file mode 100644 index 0000000..c6bb05a --- /dev/null +++ b/src/utils/request/core.ts @@ -0,0 +1,269 @@ +import type { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios' +import axios from 'axios' +import { AxiosCanceler } from './cancel' +import { toast } from 'vue-sonner' +export interface ExtraConfig { + /** + * 默认值 1 错误等级 0-忽略,1-warning,2-error + */ + errorLevel?: 0 | 1 | 2 + /** + * 默认true 是否携带token + */ + withToken?: boolean + /** + * 默认true 是否处理响应 + */ + handleResponse?: boolean + /** + * 默认false 是否取消重复请求 + */ + cancelRepetition?: boolean + /** + * 默认false 是否返回axios完整响应 + */ + originResponseData?: boolean + /** + * 默认token 存储key + */ + tokenKey?: string + /** + * 获取token的方法 + */ + getToken?: () => string + /** + * 自定义header方法,此方法返回的header会覆盖默认的header + */ + formatHeader?: (header: Record) => Record +} + +export interface RequestConfig extends AxiosRequestConfig { + extraConfig?: ExtraConfig +} + +interface ResponseType extends AxiosResponse { + config: RequestConfig +} + +const ERROR_MESSAGES: Record = { + '200': '成功', + '500': '内部服务器错误', + '10001': '数据库查询错误', + '10002': '数据库更新错误', + '10003': '数据库插入错误', + '10004': '数据库删除错误', + '20001': '用户已存在', + '20002': '用户不存在', + '20003': '用户密码错误', + '20004': '用户已禁用', + '20005': '余额不足', + '20006': '停止注册', + '20007': '未绑定Telegram', + '20008': '用户未绑定OAuth方式', + '20009': '邀请码错误', + '30001': '节点已存在', + '30002': '节点不存在', + '30003': '节点组已存在', + '30004': '节点组不存在', + '30005': '节点组不为空', + '400': '参数错误', + '40002': '用户令牌为空', + '40003': '用户令牌无效', + '40004': '用户令牌已过期', + '40005': '您还没有登录', + '401': '请求过多', + '50001': '优惠券不存在', + '50002': '优惠券已被使用', + '50003': '优惠券不匹配', + '60001': '订阅已过期', + '60002': '订阅不可用', + '60003': '用户已有订阅', + '60004': '订阅已被使用', + '60005': '单一订阅模式超出限制', + '60006': '订阅配额限制', + '70001': '验证码错误', + '80001': '队列入队错误', + '90001': '调试模式已启用', + '90002': '发送短信错误', + '90003': '短信功能未启用', + '90004': '电子邮件功能未启用', + '90005': '不支持的登录方式', + '90006': '身份验证器不支持此方式', + '90007': '电话区号为空', + '90008': '密码为空', + '90009': '区号为空', + '90010': '需要密码或验证码', + '90011': '电子邮件已存在', + '90012': '电话号码已存在', + '90013': '设备已存在', + '90014': '电话号码错误', + '90015': '此账户今日已达到发送次数限制', + '90017': '设备不存在', + '90018': '用户 ID 不匹配', + '61001': '订单不存在', + '61002': '支付方式未找到', + '61003': '订单状态错误', + '61004': '重置周期不足', + '61005': '存在没用完的流量', +} + +export default class Request { + public axiosInstance: AxiosInstance + + private config: RequestConfig + + constructor(config: RequestConfig) { + this.config = config + this.axiosInstance = axios.create(config) + this.init() + } + + static defaultConfig: Required = { + errorLevel: 2, + withToken: true, + handleResponse: true, + cancelRepetition: false, + originResponseData: false, + tokenKey: 'token', + formatHeader: (headers) => { + return headers + }, + getToken: () => '', + } + + private errorReport(lv: number, message: string) { + toast(message) + } + + private init() { + const axiosCanceler = new AxiosCanceler() + + this.axiosInstance.interceptors.request.use( + (config: RequestConfig) => { + const mergeExtraConfig = { + ...Request.defaultConfig, + ...this.config.extraConfig, + ...config.extraConfig, + } + + // if (config.data && !(config.data instanceof FormData)) { + // const plainText = JSON.stringify(config.data) + // config.data = HiAesUtil.encryptData(plainText, encryptionKey) + // } + // + // if (config.method?.toLowerCase() === 'get' || config.params) { + // const paramsToEncrypt = config.params || {} + // const plainParamsText = JSON.stringify(paramsToEncrypt) + // const encryptedParams = HiAesUtil.encryptData(plainParamsText, encryptionKey) + // + // config.params = { + // data: encryptedParams.data, + // time: encryptedParams.time, + // } + // } + + config.headers = mergeExtraConfig.formatHeader({ + ...this.config.headers, + ...config.headers, + lang: 'zh_CN', + // 'login-type': 'device', + ...(mergeExtraConfig.withToken && { + [mergeExtraConfig.tokenKey]: mergeExtraConfig.getToken(), + }), + } as any) + config.extraConfig = mergeExtraConfig + if (mergeExtraConfig.cancelRepetition) { + axiosCanceler.addPending(config) + } + return config + }, + (error) => { + this.errorReport(error?.config.extraConfig.errorLevel, error) + return Promise.reject(error) + }, + ) + + this.axiosInstance.interceptors.response.use( + (response: ResponseType) => { + const { data, config } = response + const responseData = response.data.data + + // if (responseData && responseData.data && responseData.time) { + // try { + // const decryptedStr = HiAesUtil.decryptData( + // responseData.data, + // responseData.time, + // encryptionKey, + // ) + // responseData = JSON.parse(decryptedStr) + // } catch (e) { + // console.error('解密失败:', e) + // return Promise.reject({ message: '数据解密异常' }) + // } + // } + axiosCanceler.removePending(config) + + if (data.code !== 200) { + const msg = ERROR_MESSAGES[data.code] || response.data?.msg || data?.error || '未知错误' + if (data.code == 40004 || data.code == 40003 || data.code == 40005) { + toast.error(msg) + return + } + + if (config.extraConfig?.handleResponse) { + this.errorReport(config.extraConfig.errorLevel ?? 2, msg) + return Promise.reject({ + ...data, + message: msg, + }) + } + } + + return config.extraConfig?.originResponseData ? response : responseData + }, + (error) => { + const status = error?.response?.status + const code = error?.code + let message = error?.message + if (status === 401) { + return + } + if (code === 'ECONNABORTED') { + message = '网络环境太差,请求超时' + } else if (code === 'Network Error' || message === 'Network Error') { + if (error.response) { + message = `${error.response.status}:network连接失败,请求中断` + } else { + message = '网络好像出现问题了' + } + } + if (error.__CANCEL__) { + console.warn('request canceled', error?.message) + } else { + this.errorReport(error?.config?.extraConfig?.errorLevel, message) + } + return Promise.reject(error) + }, + ) + } + + public get(url: string, params?: Record, config?: RequestConfig): Promise { + return this.axiosInstance.get(url, { ...config, params }) + } + + public post(url: string, data?: D, config?: RequestConfig): Promise { + return this.axiosInstance.post(url, data, { ...config }) + } + + public put(url: string, data?: D, config?: RequestConfig): Promise { + return this.axiosInstance.put(url, data, { ...config }) + } + + public patch(url: string, data?: D, config?: RequestConfig): Promise { + return this.axiosInstance.patch(url, data, { ...config }) + } + + public delete(url: string, params?: D, config?: RequestConfig): Promise { + return this.axiosInstance.delete(url, { ...config, params }) + } +} diff --git a/src/utils/request/index.ts b/src/utils/request/index.ts new file mode 100644 index 0000000..eafe3c5 --- /dev/null +++ b/src/utils/request/index.ts @@ -0,0 +1,16 @@ +import Request from './core' +export * from './core' +const baseUrl = import.meta.env.VITE_APP_BASE_URL + +const request = new Request({ + baseURL: baseUrl, + timeout: 6000, + headers: {}, + extraConfig: { + /** 这里是核心配置,一般不需要再去修改request/core.ts */ + tokenKey: 'Authorization', + getToken: () => localStorage.getItem('Authorization') || '', + }, +}) + +export default request diff --git a/src/utils/url-utils.ts b/src/utils/url-utils.ts new file mode 100644 index 0000000..c8c24d9 --- /dev/null +++ b/src/utils/url-utils.ts @@ -0,0 +1,157 @@ +/** + * 拼接参数 + * @param {Object} data + */ +export const param = data => { + if (!data) { + return '' + } + + let url = '' + for (const k in data) { + const value = data[k] !== undefined ? data[k] : '' + url += `&${k}=${encodeURIComponent(value)}` + } + return url ? url.substr(1) : '' +} +/** + * 拼接参数,处理对象类型数据 + */ +export const paramToObj = data => { + if (!data) { + return '' + } + let url = '' + for (const k in data) { + const value = data[k] !== undefined ? data[k] : '' + if (typeof value === 'object') { + url += `&${k}=${encodeURIComponent(JSON.stringify(value))}` + } else { + url += `&${k}=${encodeURIComponent(value)}` + } + } + return url ? url.substr(1) : '' +} + +/** + * 为了获取微信登录的code + * @param {string} name + */ +export const getQueryString = name => { + const reg = `(^|&)${name}=([^&]*)(&|$)` + const query = window.location.search.substr(1) || window.location.hash.split('?')[1] + const r = query ? query.match(reg) : null + if (r != null) return decodeURIComponent(r[2]) + return null +} + +/** + * 为了获取URL上的值 + * @param {*} name 需要获取的key + * @param {*} isMerge 是否合并hash和search,search优先级高 + */ +export const getAllQuertString = (name, isMerge = true) => { + const reg = `(?:^|&)${name}=([^&]*)(?:&|$)` + const search = window.location.search.substr(1) + const hash = window.location.hash.split('?')[1] + const searchR = search ? search.match(reg) && search.match(reg)![1] : null + const hashR = hash ? hash.match(reg) && hash.match(reg)![1] : null + if (isMerge) { + const result = searchR || hashR + return result ? unescape(result) : null + } + return { + search: searchR ? unescape(searchR) : null, + hash: hashR ? unescape(hashR) : null, + } +} + +/** + * 授权时把所有参数进行筛选,防止二次授权存在多个code情况 + * @param {string} url + */ +export function parseURL(url) { + const a = document.createElement('a') + a.href = url + const protocol = a.protocol.replace(':', '') + const host = a.hostname + const path = a.pathname.replace(/^([^\/])/, '/$1') + return { + href: `${protocol}://${host}${path}?`, + source: url, + protocol, + host, + port: a.port, + query: a.search, + params: (function () { + const params = {} + const seg = a.search.replace(/^\?/, '').split('&') + const len = seg.length + let p + for (let i = 0; i < len; i++) { + if (seg[i]) { + p = seg[i].split('=') + params[p[0]] = p[1] + } + } + return params + }()), + hash: a.hash.replace('#', ''), + path, + } +} + +/** + * 获取url query对象 + */ +export function urlGetParam() { + const t = location.search + .substring(1) + .split('&') + .filter(item => !!item) + const f = {} + for (let i = 0; i < t.length; i++) { + const x = t[i].split('=') + f[x[0]] = x[1] + } + return f +} + +/** + * 批量删除地址参数 + * @param {array} removes 需要删除的参数 + * @param {boolean} hash 返回的链接是否拼上hash值 + */ +export function removeUrlQuery(removes, isHash = false) { + const currentParam = urlGetParam() + removes.forEach(removeItem => { + delete currentParam[removeItem] + }) + return `${location.origin}${location.pathname}?${param(currentParam)}${ + isHash ? location.hash : '' + }` +} + +/** + * 获取链接上的keyValue + */ +export function hrefKeyValue(key, url) { + const reg = new RegExp(/(\w+)=(\w+)/, 'gi') + const currentUrl = url || location.href + const results = currentUrl.match(reg) + if (results) { + const resultKeyValues = results.map(o => ({ + [o.split('=')[0]]: o.split('=')[1], + })) + const result = resultKeyValues.find(o => o.hasOwnProperty(key)) + return (result && result[key]) || null + } + return null +} +/** + * 替换url中的参数 + */ +export function replaceQueryString(url, name, value) { + const re = new RegExp(name + '=[^&]*', 'gi') + return url.replace(re, name + '=' + value) +} diff --git a/tsconfig.app.json b/tsconfig.app.json new file mode 100644 index 0000000..8d16e42 --- /dev/null +++ b/tsconfig.app.json @@ -0,0 +1,16 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + "types": ["vite/client"], + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "erasableSyntaxOnly": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true + }, + "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"] +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..6421ddd --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,18 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + } + ], + /* 必须在根目录也加上这部分,让 shadcn 的脚本能读到 */ + "compilerOptions": { + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} 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/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..b3fe030 --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,35 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import tailwindcss from '@tailwindcss/vite' +import svgLoader from 'vite-svg-loader' + +// https://vite.dev/config/ +export default defineConfig({ + plugins: [vue(), tailwindcss(),svgLoader()], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)), + }, + }, + server: { + proxy: { + // 将所有以 /api 开头的请求转发到目标服务器 + // 1. 匹配所有以 /public 开头的请求 + '/api/v1': { + target: 'https://hifastvpn.com', + changeOrigin: true, + // rewrite: (path) => path.replace(/^\/api/, ''), + autoRewrite: true, + // 3. 关键:将路径重写,在前面补上 /api/v1 + // 验证请求是否进入代理,可以在终端看到打印 + configure: (proxy, _options) => { + proxy.on('proxyReq', (proxyReq, req, _res) => { + console.log('代理请求:', req.method, req.url, ' -> ', proxyReq.path) + }) + }, + }, + }, + }, +})