diff --git a/.env b/.env
new file mode 100644
index 0000000..4f4489e
--- /dev/null
+++ b/.env
@@ -0,0 +1,2 @@
+VITE_ASSETS_URL=https://your-assets-url.com
+VITE_API_BASE_URL=http://localhost:3030
\ No newline at end of file
diff --git a/.env.example b/.env.example
new file mode 100644
index 0000000..4a7f32d
--- /dev/null
+++ b/.env.example
@@ -0,0 +1,8 @@
+# Backend API Base URL (后端服务地址)
+VITE_API_BASE_URL=http://localhost:3000
+
+# Site Key for authentication (站点密钥)
+VITE_SITE_KEY=your-site-key-here
+
+# Assets URL for app icons (应用图标资源地址)
+VITE_ASSETS_URL=http://localhost:3000/assets
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/.npmrc b/.npmrc
new file mode 100644
index 0000000..d67f374
--- /dev/null
+++ b/.npmrc
@@ -0,0 +1 @@
+node-linker=hoisted
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/components.json b/components.json
new file mode 100644
index 0000000..17158ce
--- /dev/null
+++ b/components.json
@@ -0,0 +1,20 @@
+{
+ "$schema": "https://shadcn-vue.com/schema.json",
+ "style": "new-york",
+ "typescript": false,
+ "tailwind": {
+ "config": "",
+ "css": "src/style.css",
+ "baseColor": "neutral",
+ "cssVariables": true,
+ "prefix": ""
+ },
+ "aliases": {
+ "components": "@/components",
+ "composables": "@/composables",
+ "utils": "@/lib/utils",
+ "ui": "@/components/ui",
+ "lib": "@/lib"
+ },
+ "iconLibrary": "lucide"
+}
\ No newline at end of file
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..98d8148
--- /dev/null
+++ b/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ Classworks KV
+
+
+
+
+
+
diff --git a/jsconfig.json b/jsconfig.json
new file mode 100644
index 0000000..0486e3b
--- /dev/null
+++ b/jsconfig.json
@@ -0,0 +1,9 @@
+{
+ "compilerOptions": {
+ "baseUrl": ".",
+ "paths": {
+ "@/*": ["./src/*"]
+ }
+ },
+ "exclude": ["node_modules", "dist"]
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..e1863aa
--- /dev/null
+++ b/package.json
@@ -0,0 +1,43 @@
+{
+ "name": "kv-admin",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "vite build",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "@radix-ui/react-slot": "^1.2.3",
+ "@tailwindcss/vite": "^4.1.13",
+ "@tanstack/vue-table": "^8.21.3",
+ "@vee-validate/zod": "^4.15.1",
+ "@vueuse/core": "^13.9.0",
+ "axios": "^1.12.2",
+ "class-variance-authority": "^0.7.1",
+ "clsx": "^2.1.1",
+ "lucide-react": "^0.544.0",
+ "lucide-vue-next": "^0.544.0",
+ "marked": "^16.3.0",
+ "pinia": "^3.0.3",
+ "radix-vue": "^1.9.17",
+ "reka-ui": "^2.5.1",
+ "tailwind-merge": "^3.3.1",
+ "tailwindcss": "^4.1.13",
+ "vee-validate": "^4.15.1",
+ "vue": "^3.5.21",
+ "vue-router": "^4.5.1",
+ "vue-sonner": "^2.0.9",
+ "zod": "^3.25.76"
+ },
+ "devDependencies": {
+ "@tailwindcss/typography": "^0.5.19",
+ "@vitejs/plugin-vue": "^6.0.1",
+ "@vue/devtools": "^8.0.2",
+ "tw-animate-css": "^1.4.0",
+ "unplugin-vue-router": "^0.15.0",
+ "vite": "^7.1.7",
+ "vite-plugin-vue-devtools": "^8.0.2"
+ }
+}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
new file mode 100644
index 0000000..b47b14d
--- /dev/null
+++ b/pnpm-lock.yaml
@@ -0,0 +1,3915 @@
+lockfileVersion: '9.0'
+
+settings:
+ autoInstallPeers: true
+ excludeLinksFromLockfile: false
+
+importers:
+
+ .:
+ dependencies:
+ '@radix-ui/react-slot':
+ specifier: ^1.2.3
+ version: 1.2.3(react@19.2.0)
+ '@tailwindcss/vite':
+ specifier: ^4.1.13
+ version: 4.1.14(vite@7.1.7(@types/node@24.6.2)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@2.8.1))
+ '@tanstack/vue-table':
+ specifier: ^8.21.3
+ version: 8.21.3(vue@3.5.22)
+ '@vee-validate/zod':
+ specifier: ^4.15.1
+ version: 4.15.1(vue@3.5.22)(zod@3.25.76)
+ '@vueuse/core':
+ specifier: ^13.9.0
+ version: 13.9.0(vue@3.5.22)
+ axios:
+ specifier: ^1.12.2
+ version: 1.12.2
+ class-variance-authority:
+ specifier: ^0.7.1
+ version: 0.7.1
+ clsx:
+ specifier: ^2.1.1
+ version: 2.1.1
+ lucide-react:
+ specifier: ^0.544.0
+ version: 0.544.0(react@19.2.0)
+ lucide-vue-next:
+ specifier: ^0.544.0
+ version: 0.544.0(vue@3.5.22)
+ marked:
+ specifier: ^16.3.0
+ version: 16.3.0
+ pinia:
+ specifier: ^3.0.3
+ version: 3.0.3(vue@3.5.22)
+ radix-vue:
+ specifier: ^1.9.17
+ version: 1.9.17(vue@3.5.22)
+ reka-ui:
+ specifier: ^2.5.1
+ version: 2.5.1(vue@3.5.22)
+ tailwind-merge:
+ specifier: ^3.3.1
+ version: 3.3.1
+ tailwindcss:
+ specifier: ^4.1.13
+ version: 4.1.14
+ vee-validate:
+ specifier: ^4.15.1
+ version: 4.15.1(vue@3.5.22)
+ vue:
+ specifier: ^3.5.21
+ version: 3.5.22
+ vue-router:
+ specifier: ^4.5.1
+ version: 4.5.1(vue@3.5.22)
+ vue-sonner:
+ specifier: ^2.0.9
+ version: 2.0.9
+ zod:
+ specifier: ^3.25.76
+ version: 3.25.76
+ devDependencies:
+ '@tailwindcss/typography':
+ specifier: ^0.5.19
+ version: 0.5.19(tailwindcss@4.1.14)
+ '@vitejs/plugin-vue':
+ specifier: ^6.0.1
+ version: 6.0.1(vite@7.1.7(@types/node@24.6.2)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@2.8.1))(vue@3.5.22)
+ '@vue/devtools':
+ specifier: ^8.0.2
+ version: 8.0.2(vite@7.1.7(@types/node@24.6.2)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@2.8.1))(vue@3.5.22)
+ tw-animate-css:
+ specifier: ^1.4.0
+ version: 1.4.0
+ unplugin-vue-router:
+ specifier: ^0.15.0
+ version: 0.15.0(@vue/compiler-sfc@3.5.22)(vue-router@4.5.1(vue@3.5.22))(vue@3.5.22)
+ vite:
+ specifier: ^7.1.7
+ version: 7.1.7(@types/node@24.6.2)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@2.8.1)
+ vite-plugin-vue-devtools:
+ specifier: ^8.0.2
+ version: 8.0.2(vite@7.1.7(@types/node@24.6.2)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@2.8.1))(vue@3.5.22)
+
+packages:
+
+ '@babel/code-frame@7.27.1':
+ resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/compat-data@7.28.4':
+ resolution: {integrity: sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/core@7.28.4':
+ resolution: {integrity: sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/generator@7.28.3':
+ resolution: {integrity: sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-annotate-as-pure@7.27.3':
+ resolution: {integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-compilation-targets@7.27.2':
+ resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-create-class-features-plugin@7.28.3':
+ resolution: {integrity: sha512-V9f6ZFIYSLNEbuGA/92uOvYsGCJNsuA8ESZ4ldc09bWk/j8H8TKiPw8Mk1eG6olpnO0ALHJmYfZvF4MEE4gajg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
+ '@babel/helper-globals@7.28.0':
+ resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-member-expression-to-functions@7.27.1':
+ resolution: {integrity: sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-module-imports@7.27.1':
+ resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-module-transforms@7.28.3':
+ resolution: {integrity: sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
+ '@babel/helper-optimise-call-expression@7.27.1':
+ resolution: {integrity: sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-plugin-utils@7.27.1':
+ resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-replace-supers@7.27.1':
+ resolution: {integrity: sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
+ '@babel/helper-skip-transparent-expression-wrappers@7.27.1':
+ resolution: {integrity: sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-string-parser@7.27.1':
+ resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-validator-identifier@7.27.1':
+ resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-validator-option@7.27.1':
+ resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helpers@7.28.4':
+ resolution: {integrity: sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/parser@7.28.4':
+ resolution: {integrity: sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==}
+ engines: {node: '>=6.0.0'}
+ hasBin: true
+
+ '@babel/plugin-proposal-decorators@7.28.0':
+ resolution: {integrity: sha512-zOiZqvANjWDUaUS9xMxbMcK/Zccztbe/6ikvUXaG9nsPH3w6qh5UaPGAnirI/WhIbZ8m3OHU0ReyPrknG+ZKeg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-decorators@7.27.1':
+ resolution: {integrity: sha512-YMq8Z87Lhl8EGkmb0MwYkt36QnxC+fzCgrl66ereamPlYToRpIk5nUjKUY3QKLWq8mwUB1BgbeXcTJhZOCDg5A==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-import-attributes@7.27.1':
+ resolution: {integrity: sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-import-meta@7.10.4':
+ resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-jsx@7.27.1':
+ resolution: {integrity: sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-typescript@7.27.1':
+ resolution: {integrity: sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-typescript@7.28.0':
+ resolution: {integrity: sha512-4AEiDEBPIZvLQaWlc9liCavE0xRM0dNca41WtBeM3jgFptfUOSG9z0uteLhq6+3rq+WB6jIvUwKDTpXEHPJ2Vg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/template@7.27.2':
+ resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/traverse@7.28.4':
+ resolution: {integrity: sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/types@7.28.4':
+ resolution: {integrity: sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==}
+ engines: {node: '>=6.9.0'}
+
+ '@electron/get@2.0.3':
+ resolution: {integrity: sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==}
+ engines: {node: '>=12'}
+
+ '@esbuild/aix-ppc64@0.25.10':
+ resolution: {integrity: sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw==}
+ engines: {node: '>=18'}
+ cpu: [ppc64]
+ os: [aix]
+
+ '@esbuild/android-arm64@0.25.10':
+ resolution: {integrity: sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [android]
+
+ '@esbuild/android-arm@0.25.10':
+ resolution: {integrity: sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w==}
+ engines: {node: '>=18'}
+ cpu: [arm]
+ os: [android]
+
+ '@esbuild/android-x64@0.25.10':
+ resolution: {integrity: sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [android]
+
+ '@esbuild/darwin-arm64@0.25.10':
+ resolution: {integrity: sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@esbuild/darwin-x64@0.25.10':
+ resolution: {integrity: sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@esbuild/freebsd-arm64@0.25.10':
+ resolution: {integrity: sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [freebsd]
+
+ '@esbuild/freebsd-x64@0.25.10':
+ resolution: {integrity: sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@esbuild/linux-arm64@0.25.10':
+ resolution: {integrity: sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@esbuild/linux-arm@0.25.10':
+ resolution: {integrity: sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg==}
+ engines: {node: '>=18'}
+ cpu: [arm]
+ os: [linux]
+
+ '@esbuild/linux-ia32@0.25.10':
+ resolution: {integrity: sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ==}
+ engines: {node: '>=18'}
+ cpu: [ia32]
+ os: [linux]
+
+ '@esbuild/linux-loong64@0.25.10':
+ resolution: {integrity: sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg==}
+ engines: {node: '>=18'}
+ cpu: [loong64]
+ os: [linux]
+
+ '@esbuild/linux-mips64el@0.25.10':
+ resolution: {integrity: sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA==}
+ engines: {node: '>=18'}
+ cpu: [mips64el]
+ os: [linux]
+
+ '@esbuild/linux-ppc64@0.25.10':
+ resolution: {integrity: sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA==}
+ engines: {node: '>=18'}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@esbuild/linux-riscv64@0.25.10':
+ resolution: {integrity: sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA==}
+ engines: {node: '>=18'}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@esbuild/linux-s390x@0.25.10':
+ resolution: {integrity: sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew==}
+ engines: {node: '>=18'}
+ cpu: [s390x]
+ os: [linux]
+
+ '@esbuild/linux-x64@0.25.10':
+ resolution: {integrity: sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [linux]
+
+ '@esbuild/netbsd-arm64@0.25.10':
+ resolution: {integrity: sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [netbsd]
+
+ '@esbuild/netbsd-x64@0.25.10':
+ resolution: {integrity: sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [netbsd]
+
+ '@esbuild/openbsd-arm64@0.25.10':
+ resolution: {integrity: sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [openbsd]
+
+ '@esbuild/openbsd-x64@0.25.10':
+ resolution: {integrity: sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [openbsd]
+
+ '@esbuild/openharmony-arm64@0.25.10':
+ resolution: {integrity: sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [openharmony]
+
+ '@esbuild/sunos-x64@0.25.10':
+ resolution: {integrity: sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [sunos]
+
+ '@esbuild/win32-arm64@0.25.10':
+ resolution: {integrity: sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@esbuild/win32-ia32@0.25.10':
+ resolution: {integrity: sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw==}
+ engines: {node: '>=18'}
+ cpu: [ia32]
+ os: [win32]
+
+ '@esbuild/win32-x64@0.25.10':
+ resolution: {integrity: sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw==}
+ 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.9.0':
+ resolution: {integrity: sha512-yaN3brAnHRD+4KyyOsJyk49XUvj2wtbNACSqg0bz3u8t2VuzhC8Q5dfRnrSxjnnbDb+ienBnkn1TzQfE154vyg==}
+
+ '@internationalized/number@3.6.5':
+ resolution: {integrity: sha512-6hY4Kl4HPBvtfS62asS/R22JzNNy8vi/Ssev7x6EobfCp+9QIB2hKvI2EtbdJ0VSQacxVNtqhE/NmF/NZ0gm6g==}
+
+ '@isaacs/fs-minipass@4.0.1':
+ resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==}
+ engines: {node: '>=18.0.0'}
+
+ '@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==}
+
+ '@polka/url@1.0.0-next.29':
+ resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==}
+
+ '@radix-ui/react-compose-refs@1.1.2':
+ resolution: {integrity: sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@radix-ui/react-slot@1.2.3':
+ resolution: {integrity: sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
+ '@rolldown/pluginutils@1.0.0-beta.29':
+ resolution: {integrity: sha512-NIJgOsMjbxAXvoGq/X0gD7VPMQ8j9g0BiDaNjVNVjvl+iKXxL3Jre0v31RmBYeLEmkbj2s02v8vFTbUXi5XS2Q==}
+
+ '@rollup/rollup-android-arm-eabi@4.52.3':
+ resolution: {integrity: sha512-h6cqHGZ6VdnwliFG1NXvMPTy/9PS3h8oLh7ImwR+kl+oYnQizgjxsONmmPSb2C66RksfkfIxEVtDSEcJiO0tqw==}
+ cpu: [arm]
+ os: [android]
+
+ '@rollup/rollup-android-arm64@4.52.3':
+ resolution: {integrity: sha512-wd+u7SLT/u6knklV/ifG7gr5Qy4GUbH2hMWcDauPFJzmCZUAJ8L2bTkVXC2niOIxp8lk3iH/QX8kSrUxVZrOVw==}
+ cpu: [arm64]
+ os: [android]
+
+ '@rollup/rollup-darwin-arm64@4.52.3':
+ resolution: {integrity: sha512-lj9ViATR1SsqycwFkJCtYfQTheBdvlWJqzqxwc9f2qrcVrQaF/gCuBRTiTolkRWS6KvNxSk4KHZWG7tDktLgjg==}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@rollup/rollup-darwin-x64@4.52.3':
+ resolution: {integrity: sha512-+Dyo7O1KUmIsbzx1l+4V4tvEVnVQqMOIYtrxK7ncLSknl1xnMHLgn7gddJVrYPNZfEB8CIi3hK8gq8bDhb3h5A==}
+ cpu: [x64]
+ os: [darwin]
+
+ '@rollup/rollup-freebsd-arm64@4.52.3':
+ resolution: {integrity: sha512-u9Xg2FavYbD30g3DSfNhxgNrxhi6xVG4Y6i9Ur1C7xUuGDW3banRbXj+qgnIrwRN4KeJ396jchwy9bCIzbyBEQ==}
+ cpu: [arm64]
+ os: [freebsd]
+
+ '@rollup/rollup-freebsd-x64@4.52.3':
+ resolution: {integrity: sha512-5M8kyi/OX96wtD5qJR89a/3x5x8x5inXBZO04JWhkQb2JWavOWfjgkdvUqibGJeNNaz1/Z1PPza5/tAPXICI6A==}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@rollup/rollup-linux-arm-gnueabihf@4.52.3':
+ resolution: {integrity: sha512-IoerZJ4l1wRMopEHRKOO16e04iXRDyZFZnNZKrWeNquh5d6bucjezgd+OxG03mOMTnS1x7hilzb3uURPkJ0OfA==}
+ cpu: [arm]
+ os: [linux]
+
+ '@rollup/rollup-linux-arm-musleabihf@4.52.3':
+ resolution: {integrity: sha512-ZYdtqgHTDfvrJHSh3W22TvjWxwOgc3ThK/XjgcNGP2DIwFIPeAPNsQxrJO5XqleSlgDux2VAoWQ5iJrtaC1TbA==}
+ cpu: [arm]
+ os: [linux]
+
+ '@rollup/rollup-linux-arm64-gnu@4.52.3':
+ resolution: {integrity: sha512-NcViG7A0YtuFDA6xWSgmFb6iPFzHlf5vcqb2p0lGEbT+gjrEEz8nC/EeDHvx6mnGXnGCC1SeVV+8u+smj0CeGQ==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@rollup/rollup-linux-arm64-musl@4.52.3':
+ resolution: {integrity: sha512-d3pY7LWno6SYNXRm6Ebsq0DJGoiLXTb83AIPCXl9fmtIQs/rXoS8SJxxUNtFbJ5MiOvs+7y34np77+9l4nfFMw==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@rollup/rollup-linux-loong64-gnu@4.52.3':
+ resolution: {integrity: sha512-3y5GA0JkBuirLqmjwAKwB0keDlI6JfGYduMlJD/Rl7fvb4Ni8iKdQs1eiunMZJhwDWdCvrcqXRY++VEBbvk6Eg==}
+ cpu: [loong64]
+ os: [linux]
+
+ '@rollup/rollup-linux-ppc64-gnu@4.52.3':
+ resolution: {integrity: sha512-AUUH65a0p3Q0Yfm5oD2KVgzTKgwPyp9DSXc3UA7DtxhEb/WSPfbG4wqXeSN62OG5gSo18em4xv6dbfcUGXcagw==}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@rollup/rollup-linux-riscv64-gnu@4.52.3':
+ resolution: {integrity: sha512-1makPhFFVBqZE+XFg3Dkq+IkQ7JvmUrwwqaYBL2CE+ZpxPaqkGaiWFEWVGyvTwZace6WLJHwjVh/+CXbKDGPmg==}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@rollup/rollup-linux-riscv64-musl@4.52.3':
+ resolution: {integrity: sha512-OOFJa28dxfl8kLOPMUOQBCO6z3X2SAfzIE276fwT52uXDWUS178KWq0pL7d6p1kz7pkzA0yQwtqL0dEPoVcRWg==}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@rollup/rollup-linux-s390x-gnu@4.52.3':
+ resolution: {integrity: sha512-jMdsML2VI5l+V7cKfZx3ak+SLlJ8fKvLJ0Eoa4b9/vCUrzXKgoKxvHqvJ/mkWhFiyp88nCkM5S2v6nIwRtPcgg==}
+ cpu: [s390x]
+ os: [linux]
+
+ '@rollup/rollup-linux-x64-gnu@4.52.3':
+ resolution: {integrity: sha512-tPgGd6bY2M2LJTA1uGq8fkSPK8ZLYjDjY+ZLK9WHncCnfIz29LIXIqUgzCR0hIefzy6Hpbe8Th5WOSwTM8E7LA==}
+ cpu: [x64]
+ os: [linux]
+
+ '@rollup/rollup-linux-x64-musl@4.52.3':
+ resolution: {integrity: sha512-BCFkJjgk+WFzP+tcSMXq77ymAPIxsX9lFJWs+2JzuZTLtksJ2o5hvgTdIcZ5+oKzUDMwI0PfWzRBYAydAHF2Mw==}
+ cpu: [x64]
+ os: [linux]
+
+ '@rollup/rollup-openharmony-arm64@4.52.3':
+ resolution: {integrity: sha512-KTD/EqjZF3yvRaWUJdD1cW+IQBk4fbQaHYJUmP8N4XoKFZilVL8cobFSTDnjTtxWJQ3JYaMgF4nObY/+nYkumA==}
+ cpu: [arm64]
+ os: [openharmony]
+
+ '@rollup/rollup-win32-arm64-msvc@4.52.3':
+ resolution: {integrity: sha512-+zteHZdoUYLkyYKObGHieibUFLbttX2r+58l27XZauq0tcWYYuKUwY2wjeCN9oK1Um2YgH2ibd6cnX/wFD7DuA==}
+ cpu: [arm64]
+ os: [win32]
+
+ '@rollup/rollup-win32-ia32-msvc@4.52.3':
+ resolution: {integrity: sha512-of1iHkTQSo3kr6dTIRX6t81uj/c/b15HXVsPcEElN5sS859qHrOepM5p9G41Hah+CTqSh2r8Bm56dL2z9UQQ7g==}
+ cpu: [ia32]
+ os: [win32]
+
+ '@rollup/rollup-win32-x64-gnu@4.52.3':
+ resolution: {integrity: sha512-s0hybmlHb56mWVZQj8ra9048/WZTPLILKxcvcq+8awSZmyiSUZjjem1AhU3Tf4ZKpYhK4mg36HtHDOe8QJS5PQ==}
+ cpu: [x64]
+ os: [win32]
+
+ '@rollup/rollup-win32-x64-msvc@4.52.3':
+ resolution: {integrity: sha512-zGIbEVVXVtauFgl3MRwGWEN36P5ZGenHRMgNw88X5wEhEBpq0XrMEZwOn07+ICrwM17XO5xfMZqh0OldCH5VTA==}
+ cpu: [x64]
+ os: [win32]
+
+ '@sec-ant/readable-stream@0.4.1':
+ resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==}
+
+ '@sindresorhus/is@4.6.0':
+ resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==}
+ engines: {node: '>=10'}
+
+ '@sindresorhus/merge-streams@4.0.0':
+ resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==}
+ engines: {node: '>=18'}
+
+ '@socket.io/component-emitter@3.1.2':
+ resolution: {integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==}
+
+ '@swc/helpers@0.5.17':
+ resolution: {integrity: sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==}
+
+ '@szmarczak/http-timer@4.0.6':
+ resolution: {integrity: sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==}
+ engines: {node: '>=10'}
+
+ '@tailwindcss/node@4.1.14':
+ resolution: {integrity: sha512-hpz+8vFk3Ic2xssIA3e01R6jkmsAhvkQdXlEbRTk6S10xDAtiQiM3FyvZVGsucefq764euO/b8WUW9ysLdThHw==}
+
+ '@tailwindcss/oxide-android-arm64@4.1.14':
+ resolution: {integrity: sha512-a94ifZrGwMvbdeAxWoSuGcIl6/DOP5cdxagid7xJv6bwFp3oebp7y2ImYsnZBMTwjn5Ev5xESvS3FFYUGgPODQ==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [android]
+
+ '@tailwindcss/oxide-darwin-arm64@4.1.14':
+ resolution: {integrity: sha512-HkFP/CqfSh09xCnrPJA7jud7hij5ahKyWomrC3oiO2U9i0UjP17o9pJbxUN0IJ471GTQQmzwhp0DEcpbp4MZTA==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@tailwindcss/oxide-darwin-x64@4.1.14':
+ resolution: {integrity: sha512-eVNaWmCgdLf5iv6Qd3s7JI5SEFBFRtfm6W0mphJYXgvnDEAZ5sZzqmI06bK6xo0IErDHdTA5/t7d4eTfWbWOFw==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@tailwindcss/oxide-freebsd-x64@4.1.14':
+ resolution: {integrity: sha512-QWLoRXNikEuqtNb0dhQN6wsSVVjX6dmUFzuuiL09ZeXju25dsei2uIPl71y2Ic6QbNBsB4scwBoFnlBfabHkEw==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.14':
+ resolution: {integrity: sha512-VB4gjQni9+F0VCASU+L8zSIyjrLLsy03sjcR3bM0V2g4SNamo0FakZFKyUQ96ZVwGK4CaJsc9zd/obQy74o0Fw==}
+ engines: {node: '>= 10'}
+ cpu: [arm]
+ os: [linux]
+
+ '@tailwindcss/oxide-linux-arm64-gnu@4.1.14':
+ resolution: {integrity: sha512-qaEy0dIZ6d9vyLnmeg24yzA8XuEAD9WjpM5nIM1sUgQ/Zv7cVkharPDQcmm/t/TvXoKo/0knI3me3AGfdx6w1w==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@tailwindcss/oxide-linux-arm64-musl@4.1.14':
+ resolution: {integrity: sha512-ISZjT44s59O8xKsPEIesiIydMG/sCXoMBCqsphDm/WcbnuWLxxb+GcvSIIA5NjUw6F8Tex7s5/LM2yDy8RqYBQ==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@tailwindcss/oxide-linux-x64-gnu@4.1.14':
+ resolution: {integrity: sha512-02c6JhLPJj10L2caH4U0zF8Hji4dOeahmuMl23stk0MU1wfd1OraE7rOloidSF8W5JTHkFdVo/O7uRUJJnUAJg==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [linux]
+
+ '@tailwindcss/oxide-linux-x64-musl@4.1.14':
+ resolution: {integrity: sha512-TNGeLiN1XS66kQhxHG/7wMeQDOoL0S33x9BgmydbrWAb9Qw0KYdd8o1ifx4HOGDWhVmJ+Ul+JQ7lyknQFilO3Q==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [linux]
+
+ '@tailwindcss/oxide-wasm32-wasi@4.1.14':
+ resolution: {integrity: sha512-uZYAsaW/jS/IYkd6EWPJKW/NlPNSkWkBlaeVBi/WsFQNP05/bzkebUL8FH1pdsqx4f2fH/bWFcUABOM9nfiJkQ==}
+ 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.14':
+ resolution: {integrity: sha512-Az0RnnkcvRqsuoLH2Z4n3JfAef0wElgzHD5Aky/e+0tBUxUhIeIqFBTMNQvmMRSP15fWwmvjBxZ3Q8RhsDnxAA==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@tailwindcss/oxide-win32-x64-msvc@4.1.14':
+ resolution: {integrity: sha512-ttblVGHgf68kEE4om1n/n44I0yGPkCPbLsqzjvybhpwa6mKKtgFfAzy6btc3HRmuW7nHe0OOrSeNP9sQmmH9XA==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [win32]
+
+ '@tailwindcss/oxide@4.1.14':
+ resolution: {integrity: sha512-23yx+VUbBwCg2x5XWdB8+1lkPajzLmALEfMb51zZUBYaYVPDQvBSD/WYDqiVyBIo2BZFa3yw1Rpy3G2Jp+K0dw==}
+ engines: {node: '>= 10'}
+
+ '@tailwindcss/typography@0.5.19':
+ resolution: {integrity: sha512-w31dd8HOx3k9vPtcQh5QHP9GwKcgbMp87j58qi6xgiBnFFtKEAgCWnDw4qUT8aHwkCp8bKvb/KGKWWHedP0AAg==}
+ peerDependencies:
+ tailwindcss: '>=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1'
+
+ '@tailwindcss/vite@4.1.14':
+ resolution: {integrity: sha512-BoFUoU0XqgCUS1UXWhmDJroKKhNXeDzD7/XwabjkDIAbMnc4ULn5e2FuEuBbhZ6ENZoSYzKlzvZ44Yr6EUDUSA==}
+ peerDependencies:
+ vite: ^5.2.0 || ^6 || ^7
+
+ '@tanstack/table-core@8.21.3':
+ resolution: {integrity: sha512-ldZXEhOBb8Is7xLs01fR3YEc3DERiz5silj8tnGkFZytt1abEvl/GhUmCE0PMLaMPTa3Jk4HbKmRlHmu+gCftg==}
+ engines: {node: '>=12'}
+
+ '@tanstack/virtual-core@3.13.12':
+ resolution: {integrity: sha512-1YBOJfRHV4sXUmWsFSf5rQor4Ss82G8dQWLRbnk3GA4jeP8hQt1hxXh0tmflpC0dz3VgEv/1+qwPyLeWkQuPFA==}
+
+ '@tanstack/vue-table@8.21.3':
+ resolution: {integrity: sha512-rusRyd77c5tDPloPskctMyPLFEQUeBzxdQ+2Eow4F7gDPlPOB1UnnhzfpdvqZ8ZyX2rRNGmqNnQWm87OI2OQPw==}
+ engines: {node: '>=12'}
+ peerDependencies:
+ vue: '>=3.2'
+
+ '@tanstack/vue-virtual@3.13.12':
+ resolution: {integrity: sha512-vhF7kEU9EXWXh+HdAwKJ2m3xaOnTTmgcdXcF2pim8g4GvI7eRrk2YRuV5nUlZnd/NbCIX4/Ja2OZu5EjJL06Ww==}
+ peerDependencies:
+ vue: ^2.7.0 || ^3.0.0
+
+ '@types/cacheable-request@6.0.3':
+ resolution: {integrity: sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==}
+
+ '@types/cors@2.8.19':
+ resolution: {integrity: sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==}
+
+ '@types/estree@1.0.8':
+ resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
+
+ '@types/http-cache-semantics@4.0.4':
+ resolution: {integrity: sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==}
+
+ '@types/keyv@3.1.4':
+ resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==}
+
+ '@types/node@22.18.8':
+ resolution: {integrity: sha512-pAZSHMiagDR7cARo/cch1f3rXy0AEXwsVsVH09FcyeJVAzCnGgmYis7P3JidtTUjyadhTeSo8TgRPswstghDaw==}
+
+ '@types/node@24.6.2':
+ resolution: {integrity: sha512-d2L25Y4j+W3ZlNAeMKcy7yDsK425ibcAOO2t7aPTz6gNMH0z2GThtwENCDc0d/Pw9wgyRqE5Px1wkV7naz8ang==}
+
+ '@types/responselike@1.0.3':
+ resolution: {integrity: sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==}
+
+ '@types/web-bluetooth@0.0.20':
+ resolution: {integrity: sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==}
+
+ '@types/web-bluetooth@0.0.21':
+ resolution: {integrity: sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==}
+
+ '@types/yauzl@2.10.3':
+ resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==}
+
+ '@vee-validate/zod@4.15.1':
+ resolution: {integrity: sha512-329Z4TDBE5Vx0FdbA8S4eR9iGCFFUNGbxjpQ20ff5b5wGueScjocUIx9JHPa79LTG06RnlUR4XogQsjN4tecKA==}
+ peerDependencies:
+ zod: ^3.24.0
+
+ '@vitejs/plugin-vue@6.0.1':
+ resolution: {integrity: sha512-+MaE752hU0wfPFJEUAIxqw18+20euHHdxVtMvbFcOEpjEyfqXH/5DCoTHiVJ0J29EhTJdoTkjEv5YBKU9dnoTw==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ peerDependencies:
+ vite: ^5.0.0 || ^6.0.0 || ^7.0.0
+ vue: ^3.2.25
+
+ '@volar/language-core@2.4.23':
+ resolution: {integrity: sha512-hEEd5ET/oSmBC6pi1j6NaNYRWoAiDhINbT8rmwtINugR39loROSlufGdYMF9TaKGfz+ViGs1Idi3mAhnuPcoGQ==}
+
+ '@volar/source-map@2.4.23':
+ resolution: {integrity: sha512-Z1Uc8IB57Lm6k7q6KIDu/p+JWtf3xsXJqAX/5r18hYOTpJyBn0KXUR8oTJ4WFYOcDzWC9n3IflGgHowx6U6z9Q==}
+
+ '@vue-macros/common@3.0.0-beta.16':
+ resolution: {integrity: sha512-8O2gWxWFiaoNkk7PGi0+p7NPGe/f8xJ3/INUufvje/RZOs7sJvlI1jnR4lydtRFa/mU0ylMXUXXjSK0fHDEYTA==}
+ engines: {node: '>=20.18.0'}
+ peerDependencies:
+ vue: ^2.7.0 || ^3.2.25
+ peerDependenciesMeta:
+ vue:
+ optional: true
+
+ '@vue/babel-helper-vue-transform-on@1.5.0':
+ resolution: {integrity: sha512-0dAYkerNhhHutHZ34JtTl2czVQHUNWv6xEbkdF5W+Yrv5pCWsqjeORdOgbtW2I9gWlt+wBmVn+ttqN9ZxR5tzA==}
+
+ '@vue/babel-plugin-jsx@1.5.0':
+ resolution: {integrity: sha512-mneBhw1oOqCd2247O0Yw/mRwC9jIGACAJUlawkmMBiNmL4dGA2eMzuNZVNqOUfYTa6vqmND4CtOPzmEEEqLKFw==}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ peerDependenciesMeta:
+ '@babel/core':
+ optional: true
+
+ '@vue/babel-plugin-resolve-type@1.5.0':
+ resolution: {integrity: sha512-Wm/60o+53JwJODm4Knz47dxJnLDJ9FnKnGZJbUUf8nQRAtt6P+undLUAVU3Ha33LxOJe6IPoifRQ6F/0RrU31w==}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@vue/compiler-core@3.5.22':
+ resolution: {integrity: sha512-jQ0pFPmZwTEiRNSb+i9Ow/I/cHv2tXYqsnHKKyCQ08irI2kdF5qmYedmF8si8mA7zepUFmJ2hqzS8CQmNOWOkQ==}
+
+ '@vue/compiler-dom@3.5.22':
+ resolution: {integrity: sha512-W8RknzUM1BLkypvdz10OVsGxnMAuSIZs9Wdx1vzA3mL5fNMN15rhrSCLiTm6blWeACwUwizzPVqGJgOGBEN/hA==}
+
+ '@vue/compiler-sfc@3.5.22':
+ resolution: {integrity: sha512-tbTR1zKGce4Lj+JLzFXDq36K4vcSZbJ1RBu8FxcDv1IGRz//Dh2EBqksyGVypz3kXpshIfWKGOCcqpSbyGWRJQ==}
+
+ '@vue/compiler-ssr@3.5.22':
+ resolution: {integrity: sha512-GdgyLvg4R+7T8Nk2Mlighx7XGxq/fJf9jaVofc3IL0EPesTE86cP/8DD1lT3h1JeZr2ySBvyqKQJgbS54IX1Ww==}
+
+ '@vue/devtools-api@6.6.4':
+ resolution: {integrity: sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==}
+
+ '@vue/devtools-api@7.7.7':
+ resolution: {integrity: sha512-lwOnNBH2e7x1fIIbVT7yF5D+YWhqELm55/4ZKf45R9T8r9dE2AIOy8HKjfqzGsoTHFbWbr337O4E0A0QADnjBg==}
+
+ '@vue/devtools-core@8.0.2':
+ resolution: {integrity: sha512-V7eKTTHoS6KfK8PSGMLZMhGv/9yNDrmv6Qc3r71QILulnzPnqK2frsTyx3e2MrhdUZnENPEm6hcb4z0GZOqNhw==}
+ peerDependencies:
+ vue: ^3.0.0
+
+ '@vue/devtools-electron@8.0.2':
+ resolution: {integrity: sha512-Zc0Dh6sp60hF44Qom133PyDwqfbzdLTbxVc0nvwi4D/Ikpe/YF5kCkJHTv8WXcXiEkkzxWaEdOvYgX6CnjYt6w==}
+
+ '@vue/devtools-kit@7.7.7':
+ resolution: {integrity: sha512-wgoZtxcTta65cnZ1Q6MbAfePVFxfM+gq0saaeytoph7nEa7yMXoi6sCPy4ufO111B9msnw0VOWjPEFCXuAKRHA==}
+
+ '@vue/devtools-kit@8.0.2':
+ resolution: {integrity: sha512-yjZKdEmhJzQqbOh4KFBfTOQjDPMrjjBNCnHBvnTGJX+YLAqoUtY2J+cg7BE+EA8KUv8LprECq04ts75wCoIGWA==}
+
+ '@vue/devtools-shared@7.7.7':
+ resolution: {integrity: sha512-+udSj47aRl5aKb0memBvcUG9koarqnxNM5yjuREvqwK6T3ap4mn3Zqqc17QrBFTqSMjr3HK1cvStEZpMDpfdyw==}
+
+ '@vue/devtools-shared@8.0.2':
+ resolution: {integrity: sha512-mLU0QVdy5Lp40PMGSixDw/Kbd6v5dkQXltd2r+mdVQV7iUog2NlZuLxFZApFZ/mObUBDhoCpf0T3zF2FWWdeHw==}
+
+ '@vue/devtools@8.0.2':
+ resolution: {integrity: sha512-/v4J6TfYkcVUXmkqEnTMrN2UcU1r5tFo8toFANAQABvZuPw4nMRGsqHhuJaqOIdlubddOmDSZMO0Hbar5tB1+g==}
+ hasBin: true
+
+ '@vue/language-core@3.1.0':
+ resolution: {integrity: sha512-a7ns+X9vTbdmk7QLrvnZs8s4E1wwtxG/sELzr6F2j4pU+r/OoAv6jJGSz+5tVTU6e4+3rjepGhSP8jDmBBcb3w==}
+ peerDependencies:
+ typescript: '*'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
+ '@vue/reactivity@3.5.22':
+ resolution: {integrity: sha512-f2Wux4v/Z2pqc9+4SmgZC1p73Z53fyD90NFWXiX9AKVnVBEvLFOWCEgJD3GdGnlxPZt01PSlfmLqbLYzY/Fw4A==}
+
+ '@vue/runtime-core@3.5.22':
+ resolution: {integrity: sha512-EHo4W/eiYeAzRTN5PCextDUZ0dMs9I8mQ2Fy+OkzvRPUYQEyK9yAjbasrMCXbLNhF7P0OUyivLjIy0yc6VrLJQ==}
+
+ '@vue/runtime-dom@3.5.22':
+ resolution: {integrity: sha512-Av60jsryAkI023PlN7LsqrfPvwfxOd2yAwtReCjeuugTJTkgrksYJJstg1e12qle0NarkfhfFu1ox2D+cQotww==}
+
+ '@vue/server-renderer@3.5.22':
+ resolution: {integrity: sha512-gXjo+ao0oHYTSswF+a3KRHZ1WszxIqO7u6XwNHqcqb9JfyIL/pbWrrh/xLv7jeDqla9u+LK7yfZKHih1e1RKAQ==}
+ peerDependencies:
+ vue: 3.5.22
+
+ '@vue/shared@3.5.22':
+ resolution: {integrity: sha512-F4yc6palwq3TT0u+FYf0Ns4Tfl9GRFURDN2gWG7L1ecIaS/4fCIuFOjMTnCyjsu/OK6vaDKLCrGAa+KvvH+h4w==}
+
+ '@vueuse/core@10.11.1':
+ resolution: {integrity: sha512-guoy26JQktXPcz+0n3GukWIy/JDNKti9v6VEMu6kV2sYBsWuGiTU8OWdg+ADfUbHg3/3DlqySDe7JmdHrktiww==}
+
+ '@vueuse/core@12.8.2':
+ resolution: {integrity: sha512-HbvCmZdzAu3VGi/pWYm5Ut+Kd9mn1ZHnn4L5G8kOQTPs/IwIAmJoBrmYk2ckLArgMXZj0AW3n5CAejLUO+PhdQ==}
+
+ '@vueuse/core@13.9.0':
+ resolution: {integrity: sha512-ts3regBQyURfCE2BcytLqzm8+MmLlo5Ln/KLoxDVcsZ2gzIwVNnQpQOL/UKV8alUqjSZOlpFZcRNsLRqj+OzyA==}
+ peerDependencies:
+ vue: ^3.5.0
+
+ '@vueuse/metadata@10.11.1':
+ resolution: {integrity: sha512-IGa5FXd003Ug1qAZmyE8wF3sJ81xGLSqTqtQ6jaVfkeZ4i5kS2mwQF61yhVqojRnenVew5PldLyRgvdl4YYuSw==}
+
+ '@vueuse/metadata@12.8.2':
+ resolution: {integrity: sha512-rAyLGEuoBJ/Il5AmFHiziCPdQzRt88VxR+Y/A/QhJ1EWtWqPBBAxTAFaSkviwEuOEZNtW8pvkPgoCZQ+HxqW1A==}
+
+ '@vueuse/metadata@13.9.0':
+ resolution: {integrity: sha512-1AFRvuiGphfF7yWixZa0KwjYH8ulyjDCC0aFgrGRz8+P4kvDFSdXLVfTk5xAN9wEuD1J6z4/myMoYbnHoX07zg==}
+
+ '@vueuse/shared@10.11.1':
+ resolution: {integrity: sha512-LHpC8711VFZlDaYUXEBbFBCQ7GS3dVU9mjOhhMhXP6txTV4EhYQg/KGnQuvt/sPAtoUKq7VVUnL6mVtFoL42sA==}
+
+ '@vueuse/shared@12.8.2':
+ resolution: {integrity: sha512-dznP38YzxZoNloI0qpEfpkms8knDtaoQ6Y/sfS0L7Yki4zh40LFHEhur0odJC6xTHG5dxWVPiUWBXn+wCG2s5w==}
+
+ '@vueuse/shared@13.9.0':
+ resolution: {integrity: sha512-e89uuTLMh0U5cZ9iDpEI2senqPGfbPRTHM/0AaQkcxnpqjkZqDYP8rpfm7edOz8s+pOCOROEy1PIveSW8+fL5g==}
+ peerDependencies:
+ vue: ^3.5.0
+
+ accepts@1.3.8:
+ resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==}
+ engines: {node: '>= 0.6'}
+
+ acorn@8.15.0:
+ resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==}
+ engines: {node: '>=0.4.0'}
+ hasBin: true
+
+ alien-signals@3.0.0:
+ resolution: {integrity: sha512-JHoRJf18Y6HN4/KZALr3iU+0vW9LKG+8FMThQlbn4+gv8utsLIkwpomjElGPccGeNwh0FI2HN6BLnyFLo6OyLQ==}
+
+ ansis@4.2.0:
+ resolution: {integrity: sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==}
+ engines: {node: '>=14'}
+
+ aria-hidden@1.2.6:
+ resolution: {integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==}
+ engines: {node: '>=10'}
+
+ ast-kit@2.1.2:
+ resolution: {integrity: sha512-cl76xfBQM6pztbrFWRnxbrDm9EOqDr1BF6+qQnnDZG2Co2LjyUktkN9GTJfBAfdae+DbT2nJf2nCGAdDDN7W2g==}
+ engines: {node: '>=20.18.0'}
+
+ ast-walker-scope@0.8.2:
+ resolution: {integrity: sha512-3pYeLyDZ6nJew9QeBhS4Nly02269Dkdk32+zdbbKmL6n4ZuaGorwwA+xx12xgOciA8BF1w9x+dlH7oUkFTW91w==}
+ engines: {node: '>=20.18.0'}
+
+ asynckit@0.4.0:
+ resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
+
+ axios@1.12.2:
+ resolution: {integrity: sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==}
+
+ base64id@2.0.0:
+ resolution: {integrity: sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==}
+ engines: {node: ^4.5.0 || >= 5.9}
+
+ baseline-browser-mapping@2.8.10:
+ resolution: {integrity: sha512-uLfgBi+7IBNay8ECBO2mVMGZAc1VgZWEChxm4lv+TobGdG82LnXMjuNGo/BSSZZL4UmkWhxEHP2f5ziLNwGWMA==}
+ hasBin: true
+
+ birpc@2.6.1:
+ resolution: {integrity: sha512-LPnFhlDpdSH6FJhJyn4M0kFO7vtQ5iPw24FnG0y21q09xC7e8+1LeR31S1MAIrDAHp4m7aas4bEkTDTvMAtebQ==}
+
+ boolean@3.2.0:
+ resolution: {integrity: sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==}
+ deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
+
+ browserslist@4.26.3:
+ resolution: {integrity: sha512-lAUU+02RFBuCKQPj/P6NgjlbCnLBMp4UtgTx7vNHd3XSIJF87s9a5rA3aH2yw3GS9DqZAUbOtZdCCiZeVRqt0w==}
+ engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
+ hasBin: true
+
+ buffer-crc32@0.2.13:
+ resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==}
+
+ bundle-name@4.1.0:
+ resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==}
+ engines: {node: '>=18'}
+
+ cacheable-lookup@5.0.4:
+ resolution: {integrity: sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==}
+ engines: {node: '>=10.6.0'}
+
+ cacheable-request@7.0.4:
+ resolution: {integrity: sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==}
+ engines: {node: '>=8'}
+
+ call-bind-apply-helpers@1.0.2:
+ resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
+ engines: {node: '>= 0.4'}
+
+ caniuse-lite@1.0.30001746:
+ resolution: {integrity: sha512-eA7Ys/DGw+pnkWWSE/id29f2IcPHVoE8wxtvE5JdvD2V28VTDPy1yEeo11Guz0sJ4ZeGRcm3uaTcAqK1LXaphA==}
+
+ chokidar@4.0.3:
+ resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==}
+ engines: {node: '>= 14.16.0'}
+
+ chownr@3.0.0:
+ resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==}
+ engines: {node: '>=18'}
+
+ class-variance-authority@0.7.1:
+ resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==}
+
+ clone-response@1.0.3:
+ resolution: {integrity: sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==}
+
+ 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'}
+
+ confbox@0.1.8:
+ resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==}
+
+ confbox@0.2.2:
+ resolution: {integrity: sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==}
+
+ convert-source-map@2.0.0:
+ resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
+
+ cookie-es@1.2.2:
+ resolution: {integrity: sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg==}
+
+ cookie@0.7.2:
+ resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==}
+ engines: {node: '>= 0.6'}
+
+ copy-anything@3.0.5:
+ resolution: {integrity: sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==}
+ engines: {node: '>=12.13'}
+
+ cors@2.8.5:
+ resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==}
+ engines: {node: '>= 0.10'}
+
+ cross-spawn@7.0.6:
+ resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
+ engines: {node: '>= 8'}
+
+ crossws@0.3.5:
+ resolution: {integrity: sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA==}
+
+ cssesc@3.0.0:
+ resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
+ engines: {node: '>=4'}
+ hasBin: true
+
+ csstype@3.1.3:
+ resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
+
+ debug@4.3.7:
+ resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==}
+ engines: {node: '>=6.0'}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+
+ debug@4.4.3:
+ resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
+ engines: {node: '>=6.0'}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+
+ decompress-response@6.0.0:
+ resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==}
+ engines: {node: '>=10'}
+
+ default-browser-id@5.0.0:
+ resolution: {integrity: sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==}
+ engines: {node: '>=18'}
+
+ default-browser@5.2.1:
+ resolution: {integrity: sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==}
+ engines: {node: '>=18'}
+
+ defer-to-connect@2.0.1:
+ resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==}
+ engines: {node: '>=10'}
+
+ define-data-property@1.1.4:
+ resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==}
+ engines: {node: '>= 0.4'}
+
+ define-lazy-prop@3.0.0:
+ resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==}
+ engines: {node: '>=12'}
+
+ define-properties@1.2.1:
+ resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==}
+ engines: {node: '>= 0.4'}
+
+ defu@6.1.4:
+ resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==}
+
+ delayed-stream@1.0.0:
+ resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
+ engines: {node: '>=0.4.0'}
+
+ destr@2.0.5:
+ resolution: {integrity: sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==}
+
+ detect-libc@2.1.1:
+ resolution: {integrity: sha512-ecqj/sy1jcK1uWrwpR67UhYrIFQ+5WlGxth34WquCbamhFA6hkkwiu37o6J5xCHdo1oixJRfVRw+ywV+Hq/0Aw==}
+ engines: {node: '>=8'}
+
+ detect-node@2.1.0:
+ resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==}
+
+ dunder-proto@1.0.1:
+ resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
+ engines: {node: '>= 0.4'}
+
+ electron-to-chromium@1.5.228:
+ resolution: {integrity: sha512-nxkiyuqAn4MJ1QbobwqJILiDtu/jk14hEAWaMiJmNPh1Z+jqoFlBFZjdXwLWGeVSeu9hGLg6+2G9yJaW8rBIFA==}
+
+ electron@36.9.3:
+ resolution: {integrity: sha512-eR5yswsA55zVTPDEIA/PSdVNBLOp0q0Wsavgx0S3BmJYOqKoH1gqzS+hggf0/aY5OvUjVNSHiJJA1VsB5aJUug==}
+ engines: {node: '>= 12.20.55'}
+ hasBin: true
+
+ end-of-stream@1.4.5:
+ resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==}
+
+ engine.io-client@6.6.3:
+ resolution: {integrity: sha512-T0iLjnyNWahNyv/lcjS2y4oE358tVS/SYQNxYXGAJ9/GLgH4VCvOQ/mhTjqU88mLZCQgiG8RIegFHYCdVC+j5w==}
+
+ engine.io-parser@5.2.3:
+ resolution: {integrity: sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==}
+ engines: {node: '>=10.0.0'}
+
+ engine.io@6.6.4:
+ resolution: {integrity: sha512-ZCkIjSYNDyGn0R6ewHDtXgns/Zre/NT6Agvq1/WobF7JXgFff4SeDroKiCO3fNJreU9YG429Sc81o4w5ok/W5g==}
+ engines: {node: '>=10.2.0'}
+
+ enhanced-resolve@5.18.3:
+ resolution: {integrity: sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==}
+ engines: {node: '>=10.13.0'}
+
+ entities@4.5.0:
+ resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
+ engines: {node: '>=0.12'}
+
+ env-paths@2.2.1:
+ resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==}
+ engines: {node: '>=6'}
+
+ error-stack-parser-es@1.0.5:
+ resolution: {integrity: sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==}
+
+ 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'}
+
+ es6-error@4.1.1:
+ resolution: {integrity: sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==}
+
+ esbuild@0.25.10:
+ resolution: {integrity: sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ==}
+ engines: {node: '>=18'}
+ hasBin: true
+
+ escalade@3.2.0:
+ resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
+ engines: {node: '>=6'}
+
+ escape-string-regexp@4.0.0:
+ resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
+ engines: {node: '>=10'}
+
+ estree-walker@2.0.2:
+ resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
+
+ execa@9.6.0:
+ resolution: {integrity: sha512-jpWzZ1ZhwUmeWRhS7Qv3mhpOhLfwI+uAX4e5fOcXqwMR7EcJ0pj2kV1CVzHVMX/LphnKWD3LObjZCoJ71lKpHw==}
+ engines: {node: ^18.19.0 || >=20.5.0}
+
+ exsolve@1.0.7:
+ resolution: {integrity: sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==}
+
+ extract-zip@2.0.1:
+ resolution: {integrity: sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==}
+ engines: {node: '>= 10.17.0'}
+ hasBin: true
+
+ fast-deep-equal@3.1.3:
+ resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
+
+ fd-slicer@1.1.0:
+ resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==}
+
+ fdir@6.5.0:
+ resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==}
+ engines: {node: '>=12.0.0'}
+ peerDependencies:
+ picomatch: ^3 || ^4
+ peerDependenciesMeta:
+ picomatch:
+ optional: true
+
+ figures@6.1.0:
+ resolution: {integrity: sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==}
+ engines: {node: '>=18'}
+
+ 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.4:
+ resolution: {integrity: sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==}
+ engines: {node: '>= 6'}
+
+ fs-extra@8.1.0:
+ resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==}
+ engines: {node: '>=6 <7 || >=8'}
+
+ 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==}
+
+ gensync@1.0.0-beta.2:
+ resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
+ engines: {node: '>=6.9.0'}
+
+ 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'}
+
+ get-stream@5.2.0:
+ resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==}
+ engines: {node: '>=8'}
+
+ get-stream@9.0.1:
+ resolution: {integrity: sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==}
+ engines: {node: '>=18'}
+
+ global-agent@3.0.0:
+ resolution: {integrity: sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==}
+ engines: {node: '>=10.0'}
+
+ globalthis@1.0.4:
+ resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==}
+ engines: {node: '>= 0.4'}
+
+ gopd@1.2.0:
+ resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
+ engines: {node: '>= 0.4'}
+
+ got@11.8.6:
+ resolution: {integrity: sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==}
+ engines: {node: '>=10.19.0'}
+
+ graceful-fs@4.2.11:
+ resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
+
+ h3@1.15.4:
+ resolution: {integrity: sha512-z5cFQWDffyOe4vQ9xIqNfCZdV4p//vy6fBnr8Q1AWnVZ0teurKMG66rLj++TKwKPUP3u7iMUvrvKaEUiQw2QWQ==}
+
+ has-property-descriptors@1.0.2:
+ resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==}
+
+ 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'}
+
+ hookable@5.5.3:
+ resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==}
+
+ http-cache-semantics@4.2.0:
+ resolution: {integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==}
+
+ http2-wrapper@1.0.3:
+ resolution: {integrity: sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==}
+ engines: {node: '>=10.19.0'}
+
+ human-signals@8.0.1:
+ resolution: {integrity: sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==}
+ engines: {node: '>=18.18.0'}
+
+ iron-webcrypto@1.2.1:
+ resolution: {integrity: sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==}
+
+ is-docker@3.0.0:
+ resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ hasBin: true
+
+ is-inside-container@1.0.0:
+ resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==}
+ engines: {node: '>=14.16'}
+ hasBin: true
+
+ is-plain-obj@4.1.0:
+ resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==}
+ engines: {node: '>=12'}
+
+ is-stream@4.0.1:
+ resolution: {integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==}
+ engines: {node: '>=18'}
+
+ is-unicode-supported@2.1.0:
+ resolution: {integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==}
+ engines: {node: '>=18'}
+
+ is-what@4.1.16:
+ resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==}
+ engines: {node: '>=12.13'}
+
+ is-wsl@3.1.0:
+ resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==}
+ engines: {node: '>=16'}
+
+ isexe@2.0.0:
+ resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
+
+ jiti@2.6.1:
+ resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==}
+ hasBin: true
+
+ js-tokens@4.0.0:
+ resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
+
+ jsesc@3.1.0:
+ resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==}
+ engines: {node: '>=6'}
+ hasBin: true
+
+ json-buffer@3.0.1:
+ resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
+
+ json-stringify-safe@5.0.1:
+ resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==}
+
+ json5@2.2.3:
+ resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==}
+ engines: {node: '>=6'}
+ hasBin: true
+
+ jsonfile@4.0.0:
+ resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==}
+
+ keyv@4.5.4:
+ resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
+
+ kolorist@1.8.0:
+ resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==}
+
+ lightningcss-darwin-arm64@1.30.1:
+ resolution: {integrity: sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [darwin]
+
+ lightningcss-darwin-x64@1.30.1:
+ resolution: {integrity: sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [darwin]
+
+ lightningcss-freebsd-x64@1.30.1:
+ resolution: {integrity: sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [freebsd]
+
+ lightningcss-linux-arm-gnueabihf@1.30.1:
+ resolution: {integrity: sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm]
+ os: [linux]
+
+ lightningcss-linux-arm64-gnu@1.30.1:
+ resolution: {integrity: sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [linux]
+
+ lightningcss-linux-arm64-musl@1.30.1:
+ resolution: {integrity: sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [linux]
+
+ lightningcss-linux-x64-gnu@1.30.1:
+ resolution: {integrity: sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [linux]
+
+ lightningcss-linux-x64-musl@1.30.1:
+ resolution: {integrity: sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [linux]
+
+ lightningcss-win32-arm64-msvc@1.30.1:
+ resolution: {integrity: sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [win32]
+
+ lightningcss-win32-x64-msvc@1.30.1:
+ resolution: {integrity: sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [win32]
+
+ lightningcss@1.30.1:
+ resolution: {integrity: sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==}
+ engines: {node: '>= 12.0.0'}
+
+ local-pkg@1.1.2:
+ resolution: {integrity: sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A==}
+ engines: {node: '>=14'}
+
+ lowercase-keys@2.0.0:
+ resolution: {integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==}
+ engines: {node: '>=8'}
+
+ lru-cache@5.1.1:
+ resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
+
+ lucide-react@0.544.0:
+ resolution: {integrity: sha512-t5tS44bqd825zAW45UQxpG2CvcC4urOwn2TrwSH8u+MjeE+1NnWl6QqeQ/6NdjMqdOygyiT9p3Ev0p1NJykxjw==}
+ peerDependencies:
+ react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0
+
+ lucide-vue-next@0.544.0:
+ resolution: {integrity: sha512-mDp/AdGOPIDkpFHnFiTWgQgCST9aBXHVaiobZfOMIvv7nrOukzF/TP+7KoOwrngdWRaH9TMiepMBIX1vsgKJ3g==}
+ peerDependencies:
+ vue: '>=3.0.1'
+
+ magic-string-ast@1.0.2:
+ resolution: {integrity: sha512-8ngQgLhcT0t3YBdn9CGkZqCYlvwW9pm7aWJwd7AxseVWf1RU8ZHCQvG1mt3N5vvUme+pXTcHB8G/7fE666U8Vw==}
+ engines: {node: '>=20.18.0'}
+
+ magic-string@0.30.19:
+ resolution: {integrity: sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==}
+
+ marked@16.3.0:
+ resolution: {integrity: sha512-K3UxuKu6l6bmA5FUwYho8CfJBlsUWAooKtdGgMcERSpF7gcBUrCGsLH7wDaaNOzwq18JzSUDyoEb/YsrqMac3w==}
+ engines: {node: '>= 20'}
+ hasBin: true
+
+ matcher@3.0.0:
+ resolution: {integrity: sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==}
+ engines: {node: '>=10'}
+
+ math-intrinsics@1.1.0:
+ resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
+ engines: {node: '>= 0.4'}
+
+ 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'}
+
+ mimic-response@1.0.1:
+ resolution: {integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==}
+ engines: {node: '>=4'}
+
+ mimic-response@3.1.0:
+ resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==}
+ engines: {node: '>=10'}
+
+ minipass@7.1.2:
+ resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
+ engines: {node: '>=16 || 14 >=14.17'}
+
+ minizlib@3.1.0:
+ resolution: {integrity: sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==}
+ engines: {node: '>= 18'}
+
+ mitt@3.0.1:
+ resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==}
+
+ mlly@1.8.0:
+ resolution: {integrity: sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==}
+
+ mrmime@2.0.1:
+ resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==}
+ engines: {node: '>=10'}
+
+ ms@2.1.3:
+ resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
+
+ 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
+
+ nanoid@5.1.6:
+ resolution: {integrity: sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg==}
+ engines: {node: ^18 || >=20}
+ hasBin: true
+
+ negotiator@0.6.3:
+ resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==}
+ engines: {node: '>= 0.6'}
+
+ node-mock-http@1.0.3:
+ resolution: {integrity: sha512-jN8dK25fsfnMrVsEhluUTPkBFY+6ybu7jSB1n+ri/vOGjJxU8J9CZhpSGkHXSkFjtUhbmoncG/YG9ta5Ludqog==}
+
+ node-releases@2.0.21:
+ resolution: {integrity: sha512-5b0pgg78U3hwXkCM8Z9b2FJdPZlr9Psr9V2gQPESdGHqbntyFJKFW4r5TeWGFzafGY3hzs1JC62VEQMbl1JFkw==}
+
+ normalize-url@6.1.0:
+ resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==}
+ engines: {node: '>=10'}
+
+ npm-run-path@6.0.0:
+ resolution: {integrity: sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==}
+ engines: {node: '>=18'}
+
+ object-assign@4.1.1:
+ resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
+ engines: {node: '>=0.10.0'}
+
+ object-keys@1.1.1:
+ resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==}
+ engines: {node: '>= 0.4'}
+
+ ohash@2.0.11:
+ resolution: {integrity: sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==}
+
+ once@1.4.0:
+ resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
+
+ open@10.2.0:
+ resolution: {integrity: sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==}
+ engines: {node: '>=18'}
+
+ p-cancelable@2.1.1:
+ resolution: {integrity: sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==}
+ engines: {node: '>=8'}
+
+ parse-ms@4.0.0:
+ resolution: {integrity: sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==}
+ engines: {node: '>=18'}
+
+ path-browserify@1.0.1:
+ resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==}
+
+ path-key@3.1.1:
+ resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
+ engines: {node: '>=8'}
+
+ path-key@4.0.0:
+ resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==}
+ engines: {node: '>=12'}
+
+ pathe@2.0.3:
+ resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
+
+ pend@1.2.0:
+ resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==}
+
+ perfect-debounce@1.0.0:
+ resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==}
+
+ perfect-debounce@2.0.0:
+ resolution: {integrity: sha512-fkEH/OBiKrqqI/yIgjR92lMfs2K8105zt/VT6+7eTjNwisrsh47CeIED9z58zI7DfKdH3uHAn25ziRZn3kgAow==}
+
+ picocolors@1.1.1:
+ resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
+
+ picomatch@4.0.3:
+ resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==}
+ engines: {node: '>=12'}
+
+ pinia@3.0.3:
+ resolution: {integrity: sha512-ttXO/InUULUXkMHpTdp9Fj4hLpD/2AoJdmAbAeW2yu1iy1k+pkFekQXw5VpC0/5p51IOR/jDaDRfRWRnMMsGOA==}
+ peerDependencies:
+ typescript: '>=4.4.4'
+ vue: ^2.7.0 || ^3.5.11
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
+ pkg-types@1.3.1:
+ resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==}
+
+ pkg-types@2.3.0:
+ resolution: {integrity: sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==}
+
+ postcss-selector-parser@6.0.10:
+ resolution: {integrity: sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==}
+ engines: {node: '>=4'}
+
+ postcss@8.5.6:
+ resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==}
+ engines: {node: ^10 || ^12 || >=14}
+
+ pretty-ms@9.3.0:
+ resolution: {integrity: sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==}
+ engines: {node: '>=18'}
+
+ progress@2.0.3:
+ resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==}
+ engines: {node: '>=0.4.0'}
+
+ proxy-from-env@1.1.0:
+ resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
+
+ pump@3.0.3:
+ resolution: {integrity: sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==}
+
+ quansync@0.2.11:
+ resolution: {integrity: sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==}
+
+ quick-lru@5.1.1:
+ resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==}
+ engines: {node: '>=10'}
+
+ radix-vue@1.9.17:
+ resolution: {integrity: sha512-mVCu7I2vXt1L2IUYHTt0sZMz7s1K2ZtqKeTIxG3yC5mMFfLBG4FtE1FDeRMpDd+Hhg/ybi9+iXmAP1ISREndoQ==}
+ peerDependencies:
+ vue: '>= 3.2.0'
+
+ radix3@1.1.2:
+ resolution: {integrity: sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==}
+
+ react@19.2.0:
+ resolution: {integrity: sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==}
+ engines: {node: '>=0.10.0'}
+
+ readdirp@4.1.2:
+ resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==}
+ engines: {node: '>= 14.18.0'}
+
+ reka-ui@2.5.1:
+ resolution: {integrity: sha512-QJGB3q21wQ1Kw28HhhNDpjfFe8qpePX1gK4FTBRd68XTh9aEnhR5bTJnlV0jxi8FBPh0xivZBeNFUc3jiGx7mQ==}
+ peerDependencies:
+ vue: '>= 3.2.0'
+
+ resolve-alpn@1.2.1:
+ resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==}
+
+ responselike@2.0.1:
+ resolution: {integrity: sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==}
+
+ rfdc@1.4.1:
+ resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==}
+
+ roarr@2.15.4:
+ resolution: {integrity: sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==}
+ engines: {node: '>=8.0'}
+
+ rollup@4.52.3:
+ resolution: {integrity: sha512-RIDh866U8agLgiIcdpB+COKnlCreHJLfIhWC3LVflku5YHfpnsIKigRZeFfMfCc4dVcqNVfQQ5gO/afOck064A==}
+ engines: {node: '>=18.0.0', npm: '>=8.0.0'}
+ hasBin: true
+
+ run-applescript@7.1.0:
+ resolution: {integrity: sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==}
+ engines: {node: '>=18'}
+
+ scule@1.3.0:
+ resolution: {integrity: sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==}
+
+ semver-compare@1.0.0:
+ resolution: {integrity: sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==}
+
+ semver@6.3.1:
+ resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
+ hasBin: true
+
+ semver@7.7.2:
+ resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==}
+ engines: {node: '>=10'}
+ hasBin: true
+
+ serialize-error@7.0.1:
+ resolution: {integrity: sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==}
+ engines: {node: '>=10'}
+
+ shebang-command@2.0.0:
+ resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
+ engines: {node: '>=8'}
+
+ shebang-regex@3.0.0:
+ resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
+ engines: {node: '>=8'}
+
+ signal-exit@4.1.0:
+ resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
+ engines: {node: '>=14'}
+
+ sirv@3.0.2:
+ resolution: {integrity: sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==}
+ engines: {node: '>=18'}
+
+ socket.io-adapter@2.5.5:
+ resolution: {integrity: sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==}
+
+ socket.io-client@4.8.1:
+ resolution: {integrity: sha512-hJVXfu3E28NmzGk8o1sHhN3om52tRvwYeidbj7xKy2eIIse5IoKX3USlS6Tqt3BHAtflLIkCQBkzVrEEfWUyYQ==}
+ engines: {node: '>=10.0.0'}
+
+ socket.io-parser@4.2.4:
+ resolution: {integrity: sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==}
+ engines: {node: '>=10.0.0'}
+
+ socket.io@4.8.1:
+ resolution: {integrity: sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==}
+ engines: {node: '>=10.2.0'}
+
+ source-map-js@1.2.1:
+ resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
+ engines: {node: '>=0.10.0'}
+
+ speakingurl@14.0.1:
+ resolution: {integrity: sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==}
+ engines: {node: '>=0.10.0'}
+
+ sprintf-js@1.1.3:
+ resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==}
+
+ strip-final-newline@4.0.0:
+ resolution: {integrity: sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==}
+ engines: {node: '>=18'}
+
+ sumchecker@3.0.1:
+ resolution: {integrity: sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==}
+ engines: {node: '>= 8.0'}
+
+ superjson@2.2.2:
+ resolution: {integrity: sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q==}
+ engines: {node: '>=16'}
+
+ tailwind-merge@3.3.1:
+ resolution: {integrity: sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g==}
+
+ tailwindcss@4.1.14:
+ resolution: {integrity: sha512-b7pCxjGO98LnxVkKjaZSDeNuljC4ueKUddjENJOADtubtdo8llTaJy7HwBMeLNSSo2N5QIAgklslK1+Ir8r6CA==}
+
+ tapable@2.2.3:
+ resolution: {integrity: sha512-ZL6DDuAlRlLGghwcfmSn9sK3Hr6ArtyudlSAiCqQ6IfE+b+HHbydbYDIG15IfS5do+7XQQBdBiubF/cV2dnDzg==}
+ engines: {node: '>=6'}
+
+ tar@7.5.1:
+ resolution: {integrity: sha512-nlGpxf+hv0v7GkWBK2V9spgactGOp0qvfWRxUMjqHyzrt3SgwE48DIv/FhqPHJYLHpgW1opq3nERbz5Anq7n1g==}
+ engines: {node: '>=18'}
+
+ tinyglobby@0.2.15:
+ resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==}
+ engines: {node: '>=12.0.0'}
+
+ totalist@3.0.1:
+ resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==}
+ engines: {node: '>=6'}
+
+ 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==}
+
+ type-fest@0.13.1:
+ resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==}
+ engines: {node: '>=10'}
+
+ type-fest@4.41.0:
+ resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==}
+ engines: {node: '>=16'}
+
+ ufo@1.6.1:
+ resolution: {integrity: sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==}
+
+ uncrypto@0.1.3:
+ resolution: {integrity: sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==}
+
+ undici-types@6.21.0:
+ resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
+
+ undici-types@7.13.0:
+ resolution: {integrity: sha512-Ov2Rr9Sx+fRgagJ5AX0qvItZG/JKKoBRAVITs1zk7IqZGTJUwgUr7qoYBpWwakpWilTZFM98rG/AFRocu10iIQ==}
+
+ unicorn-magic@0.3.0:
+ resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==}
+ engines: {node: '>=18'}
+
+ universalify@0.1.2:
+ resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==}
+ engines: {node: '>= 4.0.0'}
+
+ unplugin-utils@0.2.5:
+ resolution: {integrity: sha512-gwXJnPRewT4rT7sBi/IvxKTjsms7jX7QIDLOClApuZwR49SXbrB1z2NLUZ+vDHyqCj/n58OzRRqaW+B8OZi8vg==}
+ engines: {node: '>=18.12.0'}
+
+ unplugin-utils@0.3.0:
+ resolution: {integrity: sha512-JLoggz+PvLVMJo+jZt97hdIIIZ2yTzGgft9e9q8iMrC4ewufl62ekeW7mixBghonn2gVb/ICjyvlmOCUBnJLQg==}
+ engines: {node: '>=20.19.0'}
+
+ unplugin-vue-router@0.15.0:
+ resolution: {integrity: sha512-PyGehCjd9Ny9h+Uer4McbBjjib3lHihcyUEILa7pHKl6+rh8N7sFyw4ZkV+N30Oq2zmIUG7iKs3qpL0r+gXAaQ==}
+ peerDependencies:
+ '@vue/compiler-sfc': ^3.5.17
+ vue-router: ^4.5.1
+ peerDependenciesMeta:
+ vue-router:
+ optional: true
+
+ unplugin@2.3.10:
+ resolution: {integrity: sha512-6NCPkv1ClwH+/BGE9QeoTIl09nuiAt0gS28nn1PvYXsGKRwM2TCbFA2QiilmehPDTXIe684k4rZI1yl3A1PCUw==}
+ engines: {node: '>=18.12.0'}
+
+ update-browserslist-db@1.1.3:
+ resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==}
+ hasBin: true
+ peerDependencies:
+ browserslist: '>= 4.21.0'
+
+ util-deprecate@1.0.2:
+ resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
+
+ vary@1.1.2:
+ resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
+ engines: {node: '>= 0.8'}
+
+ vee-validate@4.15.1:
+ resolution: {integrity: sha512-DkFsiTwEKau8VIxyZBGdO6tOudD+QoUBPuHj3e6QFqmbfCRj1ArmYWue9lEp6jLSWBIw4XPlDLjFIZNLdRAMSg==}
+ peerDependencies:
+ vue: ^3.4.26
+
+ vite-dev-rpc@1.1.0:
+ resolution: {integrity: sha512-pKXZlgoXGoE8sEKiKJSng4hI1sQ4wi5YT24FCrwrLt6opmkjlqPPVmiPWWJn8M8byMxRGzp1CrFuqQs4M/Z39A==}
+ peerDependencies:
+ vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.1 || ^7.0.0-0
+
+ vite-hot-client@2.1.0:
+ resolution: {integrity: sha512-7SpgZmU7R+dDnSmvXE1mfDtnHLHQSisdySVR7lO8ceAXvM0otZeuQQ6C8LrS5d/aYyP/QZ0hI0L+dIPrm4YlFQ==}
+ peerDependencies:
+ vite: ^2.6.0 || ^3.0.0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0
+
+ vite-plugin-inspect@11.3.3:
+ resolution: {integrity: sha512-u2eV5La99oHoYPHE6UvbwgEqKKOQGz86wMg40CCosP6q8BkB6e5xPneZfYagK4ojPJSj5anHCrnvC20DpwVdRA==}
+ engines: {node: '>=14'}
+ peerDependencies:
+ '@nuxt/kit': '*'
+ vite: ^6.0.0 || ^7.0.0-0
+ peerDependenciesMeta:
+ '@nuxt/kit':
+ optional: true
+
+ vite-plugin-vue-devtools@8.0.2:
+ resolution: {integrity: sha512-1069qvMBcyAu3yXQlvYrkwoyLOk0lSSR/gTKy/vy+Det7TXnouGei6ZcKwr5TIe938v/14oLlp0ow6FSJkkORA==}
+ engines: {node: '>=v14.21.3'}
+ peerDependencies:
+ vite: ^6.0.0 || ^7.0.0-0
+
+ vite-plugin-vue-inspector@5.3.2:
+ resolution: {integrity: sha512-YvEKooQcSiBTAs0DoYLfefNja9bLgkFM7NI2b07bE2SruuvX0MEa9cMaxjKVMkeCp5Nz9FRIdcN1rOdFVBeL6Q==}
+ peerDependencies:
+ vite: ^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0
+
+ vite@7.1.7:
+ resolution: {integrity: sha512-VbA8ScMvAISJNJVbRDTJdCwqQoAareR/wutevKanhR2/1EkoXVZVkkORaYm/tNVCjP/UDTKtcw3bAkwOUdedmA==}
+ 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
+
+ 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-router@4.5.1:
+ resolution: {integrity: sha512-ogAF3P97NPm8fJsE4by9dwSYtDwXIY1nFY9T6DyQnGHd1E2Da94w9JIolpe42LJGIl0DwOHBi8TcRPlPGwbTtw==}
+ peerDependencies:
+ vue: ^3.2.0
+
+ 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@3.5.22:
+ resolution: {integrity: sha512-toaZjQ3a/G/mYaLSbV+QsQhIdMo9x5rrqIpYRObsJ6T/J+RyCSFwN2LHNVH9v8uIcljDNa3QzPVdv3Y6b9hAJQ==}
+ peerDependencies:
+ typescript: '*'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
+ webpack-virtual-modules@0.6.2:
+ resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==}
+
+ which@2.0.2:
+ resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
+ engines: {node: '>= 8'}
+ hasBin: true
+
+ wrappy@1.0.2:
+ resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
+
+ ws@8.17.1:
+ resolution: {integrity: sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==}
+ engines: {node: '>=10.0.0'}
+ peerDependencies:
+ bufferutil: ^4.0.1
+ utf-8-validate: '>=5.0.2'
+ peerDependenciesMeta:
+ bufferutil:
+ optional: true
+ utf-8-validate:
+ optional: true
+
+ wsl-utils@0.1.0:
+ resolution: {integrity: sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==}
+ engines: {node: '>=18'}
+
+ xmlhttprequest-ssl@2.1.2:
+ resolution: {integrity: sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==}
+ engines: {node: '>=0.4.0'}
+
+ yallist@3.1.1:
+ resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
+
+ yallist@5.0.0:
+ resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==}
+ engines: {node: '>=18'}
+
+ yaml@2.8.1:
+ resolution: {integrity: sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==}
+ engines: {node: '>= 14.6'}
+ hasBin: true
+
+ yauzl@2.10.0:
+ resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==}
+
+ yoctocolors@2.1.2:
+ resolution: {integrity: sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==}
+ engines: {node: '>=18'}
+
+ zod@3.25.76:
+ resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==}
+
+snapshots:
+
+ '@babel/code-frame@7.27.1':
+ dependencies:
+ '@babel/helper-validator-identifier': 7.27.1
+ js-tokens: 4.0.0
+ picocolors: 1.1.1
+
+ '@babel/compat-data@7.28.4': {}
+
+ '@babel/core@7.28.4':
+ dependencies:
+ '@babel/code-frame': 7.27.1
+ '@babel/generator': 7.28.3
+ '@babel/helper-compilation-targets': 7.27.2
+ '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.4)
+ '@babel/helpers': 7.28.4
+ '@babel/parser': 7.28.4
+ '@babel/template': 7.27.2
+ '@babel/traverse': 7.28.4
+ '@babel/types': 7.28.4
+ '@jridgewell/remapping': 2.3.5
+ convert-source-map: 2.0.0
+ debug: 4.4.3
+ gensync: 1.0.0-beta.2
+ json5: 2.2.3
+ semver: 6.3.1
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/generator@7.28.3':
+ dependencies:
+ '@babel/parser': 7.28.4
+ '@babel/types': 7.28.4
+ '@jridgewell/gen-mapping': 0.3.13
+ '@jridgewell/trace-mapping': 0.3.31
+ jsesc: 3.1.0
+
+ '@babel/helper-annotate-as-pure@7.27.3':
+ dependencies:
+ '@babel/types': 7.28.4
+
+ '@babel/helper-compilation-targets@7.27.2':
+ dependencies:
+ '@babel/compat-data': 7.28.4
+ '@babel/helper-validator-option': 7.27.1
+ browserslist: 4.26.3
+ lru-cache: 5.1.1
+ semver: 6.3.1
+
+ '@babel/helper-create-class-features-plugin@7.28.3(@babel/core@7.28.4)':
+ dependencies:
+ '@babel/core': 7.28.4
+ '@babel/helper-annotate-as-pure': 7.27.3
+ '@babel/helper-member-expression-to-functions': 7.27.1
+ '@babel/helper-optimise-call-expression': 7.27.1
+ '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.4)
+ '@babel/helper-skip-transparent-expression-wrappers': 7.27.1
+ '@babel/traverse': 7.28.4
+ semver: 6.3.1
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-globals@7.28.0': {}
+
+ '@babel/helper-member-expression-to-functions@7.27.1':
+ dependencies:
+ '@babel/traverse': 7.28.4
+ '@babel/types': 7.28.4
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-module-imports@7.27.1':
+ dependencies:
+ '@babel/traverse': 7.28.4
+ '@babel/types': 7.28.4
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-module-transforms@7.28.3(@babel/core@7.28.4)':
+ dependencies:
+ '@babel/core': 7.28.4
+ '@babel/helper-module-imports': 7.27.1
+ '@babel/helper-validator-identifier': 7.27.1
+ '@babel/traverse': 7.28.4
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-optimise-call-expression@7.27.1':
+ dependencies:
+ '@babel/types': 7.28.4
+
+ '@babel/helper-plugin-utils@7.27.1': {}
+
+ '@babel/helper-replace-supers@7.27.1(@babel/core@7.28.4)':
+ dependencies:
+ '@babel/core': 7.28.4
+ '@babel/helper-member-expression-to-functions': 7.27.1
+ '@babel/helper-optimise-call-expression': 7.27.1
+ '@babel/traverse': 7.28.4
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-skip-transparent-expression-wrappers@7.27.1':
+ dependencies:
+ '@babel/traverse': 7.28.4
+ '@babel/types': 7.28.4
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-string-parser@7.27.1': {}
+
+ '@babel/helper-validator-identifier@7.27.1': {}
+
+ '@babel/helper-validator-option@7.27.1': {}
+
+ '@babel/helpers@7.28.4':
+ dependencies:
+ '@babel/template': 7.27.2
+ '@babel/types': 7.28.4
+
+ '@babel/parser@7.28.4':
+ dependencies:
+ '@babel/types': 7.28.4
+
+ '@babel/plugin-proposal-decorators@7.28.0(@babel/core@7.28.4)':
+ dependencies:
+ '@babel/core': 7.28.4
+ '@babel/helper-create-class-features-plugin': 7.28.3(@babel/core@7.28.4)
+ '@babel/helper-plugin-utils': 7.27.1
+ '@babel/plugin-syntax-decorators': 7.27.1(@babel/core@7.28.4)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/plugin-syntax-decorators@7.27.1(@babel/core@7.28.4)':
+ dependencies:
+ '@babel/core': 7.28.4
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-syntax-import-attributes@7.27.1(@babel/core@7.28.4)':
+ dependencies:
+ '@babel/core': 7.28.4
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.28.4)':
+ dependencies:
+ '@babel/core': 7.28.4
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.28.4)':
+ dependencies:
+ '@babel/core': 7.28.4
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-syntax-typescript@7.27.1(@babel/core@7.28.4)':
+ dependencies:
+ '@babel/core': 7.28.4
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-transform-typescript@7.28.0(@babel/core@7.28.4)':
+ dependencies:
+ '@babel/core': 7.28.4
+ '@babel/helper-annotate-as-pure': 7.27.3
+ '@babel/helper-create-class-features-plugin': 7.28.3(@babel/core@7.28.4)
+ '@babel/helper-plugin-utils': 7.27.1
+ '@babel/helper-skip-transparent-expression-wrappers': 7.27.1
+ '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.28.4)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/template@7.27.2':
+ dependencies:
+ '@babel/code-frame': 7.27.1
+ '@babel/parser': 7.28.4
+ '@babel/types': 7.28.4
+
+ '@babel/traverse@7.28.4':
+ dependencies:
+ '@babel/code-frame': 7.27.1
+ '@babel/generator': 7.28.3
+ '@babel/helper-globals': 7.28.0
+ '@babel/parser': 7.28.4
+ '@babel/template': 7.27.2
+ '@babel/types': 7.28.4
+ debug: 4.4.3
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/types@7.28.4':
+ dependencies:
+ '@babel/helper-string-parser': 7.27.1
+ '@babel/helper-validator-identifier': 7.27.1
+
+ '@electron/get@2.0.3':
+ dependencies:
+ debug: 4.4.3
+ env-paths: 2.2.1
+ fs-extra: 8.1.0
+ got: 11.8.6
+ progress: 2.0.3
+ semver: 6.3.1
+ sumchecker: 3.0.1
+ optionalDependencies:
+ global-agent: 3.0.0
+ transitivePeerDependencies:
+ - supports-color
+
+ '@esbuild/aix-ppc64@0.25.10':
+ optional: true
+
+ '@esbuild/android-arm64@0.25.10':
+ optional: true
+
+ '@esbuild/android-arm@0.25.10':
+ optional: true
+
+ '@esbuild/android-x64@0.25.10':
+ optional: true
+
+ '@esbuild/darwin-arm64@0.25.10':
+ optional: true
+
+ '@esbuild/darwin-x64@0.25.10':
+ optional: true
+
+ '@esbuild/freebsd-arm64@0.25.10':
+ optional: true
+
+ '@esbuild/freebsd-x64@0.25.10':
+ optional: true
+
+ '@esbuild/linux-arm64@0.25.10':
+ optional: true
+
+ '@esbuild/linux-arm@0.25.10':
+ optional: true
+
+ '@esbuild/linux-ia32@0.25.10':
+ optional: true
+
+ '@esbuild/linux-loong64@0.25.10':
+ optional: true
+
+ '@esbuild/linux-mips64el@0.25.10':
+ optional: true
+
+ '@esbuild/linux-ppc64@0.25.10':
+ optional: true
+
+ '@esbuild/linux-riscv64@0.25.10':
+ optional: true
+
+ '@esbuild/linux-s390x@0.25.10':
+ optional: true
+
+ '@esbuild/linux-x64@0.25.10':
+ optional: true
+
+ '@esbuild/netbsd-arm64@0.25.10':
+ optional: true
+
+ '@esbuild/netbsd-x64@0.25.10':
+ optional: true
+
+ '@esbuild/openbsd-arm64@0.25.10':
+ optional: true
+
+ '@esbuild/openbsd-x64@0.25.10':
+ optional: true
+
+ '@esbuild/openharmony-arm64@0.25.10':
+ optional: true
+
+ '@esbuild/sunos-x64@0.25.10':
+ optional: true
+
+ '@esbuild/win32-arm64@0.25.10':
+ optional: true
+
+ '@esbuild/win32-ia32@0.25.10':
+ optional: true
+
+ '@esbuild/win32-x64@0.25.10':
+ 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.22)':
+ dependencies:
+ '@floating-ui/dom': 1.7.4
+ '@floating-ui/utils': 0.2.10
+ vue-demi: 0.14.10(vue@3.5.22)
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - vue
+
+ '@internationalized/date@3.9.0':
+ dependencies:
+ '@swc/helpers': 0.5.17
+
+ '@internationalized/number@3.6.5':
+ dependencies:
+ '@swc/helpers': 0.5.17
+
+ '@isaacs/fs-minipass@4.0.1':
+ dependencies:
+ minipass: 7.1.2
+
+ '@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
+
+ '@polka/url@1.0.0-next.29': {}
+
+ '@radix-ui/react-compose-refs@1.1.2(react@19.2.0)':
+ dependencies:
+ react: 19.2.0
+
+ '@radix-ui/react-slot@1.2.3(react@19.2.0)':
+ dependencies:
+ '@radix-ui/react-compose-refs': 1.1.2(react@19.2.0)
+ react: 19.2.0
+
+ '@rolldown/pluginutils@1.0.0-beta.29': {}
+
+ '@rollup/rollup-android-arm-eabi@4.52.3':
+ optional: true
+
+ '@rollup/rollup-android-arm64@4.52.3':
+ optional: true
+
+ '@rollup/rollup-darwin-arm64@4.52.3':
+ optional: true
+
+ '@rollup/rollup-darwin-x64@4.52.3':
+ optional: true
+
+ '@rollup/rollup-freebsd-arm64@4.52.3':
+ optional: true
+
+ '@rollup/rollup-freebsd-x64@4.52.3':
+ optional: true
+
+ '@rollup/rollup-linux-arm-gnueabihf@4.52.3':
+ optional: true
+
+ '@rollup/rollup-linux-arm-musleabihf@4.52.3':
+ optional: true
+
+ '@rollup/rollup-linux-arm64-gnu@4.52.3':
+ optional: true
+
+ '@rollup/rollup-linux-arm64-musl@4.52.3':
+ optional: true
+
+ '@rollup/rollup-linux-loong64-gnu@4.52.3':
+ optional: true
+
+ '@rollup/rollup-linux-ppc64-gnu@4.52.3':
+ optional: true
+
+ '@rollup/rollup-linux-riscv64-gnu@4.52.3':
+ optional: true
+
+ '@rollup/rollup-linux-riscv64-musl@4.52.3':
+ optional: true
+
+ '@rollup/rollup-linux-s390x-gnu@4.52.3':
+ optional: true
+
+ '@rollup/rollup-linux-x64-gnu@4.52.3':
+ optional: true
+
+ '@rollup/rollup-linux-x64-musl@4.52.3':
+ optional: true
+
+ '@rollup/rollup-openharmony-arm64@4.52.3':
+ optional: true
+
+ '@rollup/rollup-win32-arm64-msvc@4.52.3':
+ optional: true
+
+ '@rollup/rollup-win32-ia32-msvc@4.52.3':
+ optional: true
+
+ '@rollup/rollup-win32-x64-gnu@4.52.3':
+ optional: true
+
+ '@rollup/rollup-win32-x64-msvc@4.52.3':
+ optional: true
+
+ '@sec-ant/readable-stream@0.4.1': {}
+
+ '@sindresorhus/is@4.6.0': {}
+
+ '@sindresorhus/merge-streams@4.0.0': {}
+
+ '@socket.io/component-emitter@3.1.2': {}
+
+ '@swc/helpers@0.5.17':
+ dependencies:
+ tslib: 2.8.1
+
+ '@szmarczak/http-timer@4.0.6':
+ dependencies:
+ defer-to-connect: 2.0.1
+
+ '@tailwindcss/node@4.1.14':
+ dependencies:
+ '@jridgewell/remapping': 2.3.5
+ enhanced-resolve: 5.18.3
+ jiti: 2.6.1
+ lightningcss: 1.30.1
+ magic-string: 0.30.19
+ source-map-js: 1.2.1
+ tailwindcss: 4.1.14
+
+ '@tailwindcss/oxide-android-arm64@4.1.14':
+ optional: true
+
+ '@tailwindcss/oxide-darwin-arm64@4.1.14':
+ optional: true
+
+ '@tailwindcss/oxide-darwin-x64@4.1.14':
+ optional: true
+
+ '@tailwindcss/oxide-freebsd-x64@4.1.14':
+ optional: true
+
+ '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.14':
+ optional: true
+
+ '@tailwindcss/oxide-linux-arm64-gnu@4.1.14':
+ optional: true
+
+ '@tailwindcss/oxide-linux-arm64-musl@4.1.14':
+ optional: true
+
+ '@tailwindcss/oxide-linux-x64-gnu@4.1.14':
+ optional: true
+
+ '@tailwindcss/oxide-linux-x64-musl@4.1.14':
+ optional: true
+
+ '@tailwindcss/oxide-wasm32-wasi@4.1.14':
+ optional: true
+
+ '@tailwindcss/oxide-win32-arm64-msvc@4.1.14':
+ optional: true
+
+ '@tailwindcss/oxide-win32-x64-msvc@4.1.14':
+ optional: true
+
+ '@tailwindcss/oxide@4.1.14':
+ dependencies:
+ detect-libc: 2.1.1
+ tar: 7.5.1
+ optionalDependencies:
+ '@tailwindcss/oxide-android-arm64': 4.1.14
+ '@tailwindcss/oxide-darwin-arm64': 4.1.14
+ '@tailwindcss/oxide-darwin-x64': 4.1.14
+ '@tailwindcss/oxide-freebsd-x64': 4.1.14
+ '@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.14
+ '@tailwindcss/oxide-linux-arm64-gnu': 4.1.14
+ '@tailwindcss/oxide-linux-arm64-musl': 4.1.14
+ '@tailwindcss/oxide-linux-x64-gnu': 4.1.14
+ '@tailwindcss/oxide-linux-x64-musl': 4.1.14
+ '@tailwindcss/oxide-wasm32-wasi': 4.1.14
+ '@tailwindcss/oxide-win32-arm64-msvc': 4.1.14
+ '@tailwindcss/oxide-win32-x64-msvc': 4.1.14
+
+ '@tailwindcss/typography@0.5.19(tailwindcss@4.1.14)':
+ dependencies:
+ postcss-selector-parser: 6.0.10
+ tailwindcss: 4.1.14
+
+ '@tailwindcss/vite@4.1.14(vite@7.1.7(@types/node@24.6.2)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@2.8.1))':
+ dependencies:
+ '@tailwindcss/node': 4.1.14
+ '@tailwindcss/oxide': 4.1.14
+ tailwindcss: 4.1.14
+ vite: 7.1.7(@types/node@24.6.2)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@2.8.1)
+
+ '@tanstack/table-core@8.21.3': {}
+
+ '@tanstack/virtual-core@3.13.12': {}
+
+ '@tanstack/vue-table@8.21.3(vue@3.5.22)':
+ dependencies:
+ '@tanstack/table-core': 8.21.3
+ vue: 3.5.22
+
+ '@tanstack/vue-virtual@3.13.12(vue@3.5.22)':
+ dependencies:
+ '@tanstack/virtual-core': 3.13.12
+ vue: 3.5.22
+
+ '@types/cacheable-request@6.0.3':
+ dependencies:
+ '@types/http-cache-semantics': 4.0.4
+ '@types/keyv': 3.1.4
+ '@types/node': 22.18.8
+ '@types/responselike': 1.0.3
+
+ '@types/cors@2.8.19':
+ dependencies:
+ '@types/node': 24.6.2
+
+ '@types/estree@1.0.8': {}
+
+ '@types/http-cache-semantics@4.0.4': {}
+
+ '@types/keyv@3.1.4':
+ dependencies:
+ '@types/node': 22.18.8
+
+ '@types/node@22.18.8':
+ dependencies:
+ undici-types: 6.21.0
+
+ '@types/node@24.6.2':
+ dependencies:
+ undici-types: 7.13.0
+
+ '@types/responselike@1.0.3':
+ dependencies:
+ '@types/node': 22.18.8
+
+ '@types/web-bluetooth@0.0.20': {}
+
+ '@types/web-bluetooth@0.0.21': {}
+
+ '@types/yauzl@2.10.3':
+ dependencies:
+ '@types/node': 22.18.8
+ optional: true
+
+ '@vee-validate/zod@4.15.1(vue@3.5.22)(zod@3.25.76)':
+ dependencies:
+ type-fest: 4.41.0
+ vee-validate: 4.15.1(vue@3.5.22)
+ zod: 3.25.76
+ transitivePeerDependencies:
+ - vue
+
+ '@vitejs/plugin-vue@6.0.1(vite@7.1.7(@types/node@24.6.2)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@2.8.1))(vue@3.5.22)':
+ dependencies:
+ '@rolldown/pluginutils': 1.0.0-beta.29
+ vite: 7.1.7(@types/node@24.6.2)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@2.8.1)
+ vue: 3.5.22
+
+ '@volar/language-core@2.4.23':
+ dependencies:
+ '@volar/source-map': 2.4.23
+
+ '@volar/source-map@2.4.23': {}
+
+ '@vue-macros/common@3.0.0-beta.16(vue@3.5.22)':
+ dependencies:
+ '@vue/compiler-sfc': 3.5.22
+ ast-kit: 2.1.2
+ local-pkg: 1.1.2
+ magic-string-ast: 1.0.2
+ unplugin-utils: 0.2.5
+ optionalDependencies:
+ vue: 3.5.22
+
+ '@vue/babel-helper-vue-transform-on@1.5.0': {}
+
+ '@vue/babel-plugin-jsx@1.5.0(@babel/core@7.28.4)':
+ dependencies:
+ '@babel/helper-module-imports': 7.27.1
+ '@babel/helper-plugin-utils': 7.27.1
+ '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.4)
+ '@babel/template': 7.27.2
+ '@babel/traverse': 7.28.4
+ '@babel/types': 7.28.4
+ '@vue/babel-helper-vue-transform-on': 1.5.0
+ '@vue/babel-plugin-resolve-type': 1.5.0(@babel/core@7.28.4)
+ '@vue/shared': 3.5.22
+ optionalDependencies:
+ '@babel/core': 7.28.4
+ transitivePeerDependencies:
+ - supports-color
+
+ '@vue/babel-plugin-resolve-type@1.5.0(@babel/core@7.28.4)':
+ dependencies:
+ '@babel/code-frame': 7.27.1
+ '@babel/core': 7.28.4
+ '@babel/helper-module-imports': 7.27.1
+ '@babel/helper-plugin-utils': 7.27.1
+ '@babel/parser': 7.28.4
+ '@vue/compiler-sfc': 3.5.22
+ transitivePeerDependencies:
+ - supports-color
+
+ '@vue/compiler-core@3.5.22':
+ dependencies:
+ '@babel/parser': 7.28.4
+ '@vue/shared': 3.5.22
+ entities: 4.5.0
+ estree-walker: 2.0.2
+ source-map-js: 1.2.1
+
+ '@vue/compiler-dom@3.5.22':
+ dependencies:
+ '@vue/compiler-core': 3.5.22
+ '@vue/shared': 3.5.22
+
+ '@vue/compiler-sfc@3.5.22':
+ dependencies:
+ '@babel/parser': 7.28.4
+ '@vue/compiler-core': 3.5.22
+ '@vue/compiler-dom': 3.5.22
+ '@vue/compiler-ssr': 3.5.22
+ '@vue/shared': 3.5.22
+ estree-walker: 2.0.2
+ magic-string: 0.30.19
+ postcss: 8.5.6
+ source-map-js: 1.2.1
+
+ '@vue/compiler-ssr@3.5.22':
+ dependencies:
+ '@vue/compiler-dom': 3.5.22
+ '@vue/shared': 3.5.22
+
+ '@vue/devtools-api@6.6.4': {}
+
+ '@vue/devtools-api@7.7.7':
+ dependencies:
+ '@vue/devtools-kit': 7.7.7
+
+ '@vue/devtools-core@8.0.2(vite@7.1.7(@types/node@24.6.2)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@2.8.1))(vue@3.5.22)':
+ dependencies:
+ '@vue/devtools-kit': 8.0.2
+ '@vue/devtools-shared': 8.0.2
+ mitt: 3.0.1
+ nanoid: 5.1.6
+ pathe: 2.0.3
+ vite-hot-client: 2.1.0(vite@7.1.7(@types/node@24.6.2)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@2.8.1))
+ vue: 3.5.22
+ transitivePeerDependencies:
+ - vite
+
+ '@vue/devtools-electron@8.0.2(vite@7.1.7(@types/node@24.6.2)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@2.8.1))(vue@3.5.22)':
+ dependencies:
+ '@vue/devtools-core': 8.0.2(vite@7.1.7(@types/node@24.6.2)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@2.8.1))(vue@3.5.22)
+ '@vue/devtools-kit': 8.0.2
+ '@vue/devtools-shared': 8.0.2
+ electron: 36.9.3
+ execa: 9.6.0
+ h3: 1.15.4
+ pathe: 2.0.3
+ socket.io: 4.8.1
+ socket.io-client: 4.8.1
+ transitivePeerDependencies:
+ - bufferutil
+ - supports-color
+ - utf-8-validate
+ - vite
+ - vue
+
+ '@vue/devtools-kit@7.7.7':
+ dependencies:
+ '@vue/devtools-shared': 7.7.7
+ birpc: 2.6.1
+ hookable: 5.5.3
+ mitt: 3.0.1
+ perfect-debounce: 1.0.0
+ speakingurl: 14.0.1
+ superjson: 2.2.2
+
+ '@vue/devtools-kit@8.0.2':
+ dependencies:
+ '@vue/devtools-shared': 8.0.2
+ birpc: 2.6.1
+ hookable: 5.5.3
+ mitt: 3.0.1
+ perfect-debounce: 2.0.0
+ speakingurl: 14.0.1
+ superjson: 2.2.2
+
+ '@vue/devtools-shared@7.7.7':
+ dependencies:
+ rfdc: 1.4.1
+
+ '@vue/devtools-shared@8.0.2':
+ dependencies:
+ rfdc: 1.4.1
+
+ '@vue/devtools@8.0.2(vite@7.1.7(@types/node@24.6.2)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@2.8.1))(vue@3.5.22)':
+ dependencies:
+ '@vue/devtools-electron': 8.0.2(vite@7.1.7(@types/node@24.6.2)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@2.8.1))(vue@3.5.22)
+ '@vue/devtools-kit': 8.0.2
+ transitivePeerDependencies:
+ - bufferutil
+ - supports-color
+ - utf-8-validate
+ - vite
+ - vue
+
+ '@vue/language-core@3.1.0':
+ dependencies:
+ '@volar/language-core': 2.4.23
+ '@vue/compiler-dom': 3.5.22
+ '@vue/shared': 3.5.22
+ alien-signals: 3.0.0
+ muggle-string: 0.4.1
+ path-browserify: 1.0.1
+ picomatch: 4.0.3
+
+ '@vue/reactivity@3.5.22':
+ dependencies:
+ '@vue/shared': 3.5.22
+
+ '@vue/runtime-core@3.5.22':
+ dependencies:
+ '@vue/reactivity': 3.5.22
+ '@vue/shared': 3.5.22
+
+ '@vue/runtime-dom@3.5.22':
+ dependencies:
+ '@vue/reactivity': 3.5.22
+ '@vue/runtime-core': 3.5.22
+ '@vue/shared': 3.5.22
+ csstype: 3.1.3
+
+ '@vue/server-renderer@3.5.22(vue@3.5.22)':
+ dependencies:
+ '@vue/compiler-ssr': 3.5.22
+ '@vue/shared': 3.5.22
+ vue: 3.5.22
+
+ '@vue/shared@3.5.22': {}
+
+ '@vueuse/core@10.11.1(vue@3.5.22)':
+ dependencies:
+ '@types/web-bluetooth': 0.0.20
+ '@vueuse/metadata': 10.11.1
+ '@vueuse/shared': 10.11.1(vue@3.5.22)
+ vue-demi: 0.14.10(vue@3.5.22)
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - vue
+
+ '@vueuse/core@12.8.2':
+ dependencies:
+ '@types/web-bluetooth': 0.0.21
+ '@vueuse/metadata': 12.8.2
+ '@vueuse/shared': 12.8.2
+ vue: 3.5.22
+ transitivePeerDependencies:
+ - typescript
+
+ '@vueuse/core@13.9.0(vue@3.5.22)':
+ dependencies:
+ '@types/web-bluetooth': 0.0.21
+ '@vueuse/metadata': 13.9.0
+ '@vueuse/shared': 13.9.0(vue@3.5.22)
+ vue: 3.5.22
+
+ '@vueuse/metadata@10.11.1': {}
+
+ '@vueuse/metadata@12.8.2': {}
+
+ '@vueuse/metadata@13.9.0': {}
+
+ '@vueuse/shared@10.11.1(vue@3.5.22)':
+ dependencies:
+ vue-demi: 0.14.10(vue@3.5.22)
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - vue
+
+ '@vueuse/shared@12.8.2':
+ dependencies:
+ vue: 3.5.22
+ transitivePeerDependencies:
+ - typescript
+
+ '@vueuse/shared@13.9.0(vue@3.5.22)':
+ dependencies:
+ vue: 3.5.22
+
+ accepts@1.3.8:
+ dependencies:
+ mime-types: 2.1.35
+ negotiator: 0.6.3
+
+ acorn@8.15.0: {}
+
+ alien-signals@3.0.0: {}
+
+ ansis@4.2.0: {}
+
+ aria-hidden@1.2.6:
+ dependencies:
+ tslib: 2.8.1
+
+ ast-kit@2.1.2:
+ dependencies:
+ '@babel/parser': 7.28.4
+ pathe: 2.0.3
+
+ ast-walker-scope@0.8.2:
+ dependencies:
+ '@babel/parser': 7.28.4
+ ast-kit: 2.1.2
+
+ asynckit@0.4.0: {}
+
+ axios@1.12.2:
+ dependencies:
+ follow-redirects: 1.15.11
+ form-data: 4.0.4
+ proxy-from-env: 1.1.0
+ transitivePeerDependencies:
+ - debug
+
+ base64id@2.0.0: {}
+
+ baseline-browser-mapping@2.8.10: {}
+
+ birpc@2.6.1: {}
+
+ boolean@3.2.0:
+ optional: true
+
+ browserslist@4.26.3:
+ dependencies:
+ baseline-browser-mapping: 2.8.10
+ caniuse-lite: 1.0.30001746
+ electron-to-chromium: 1.5.228
+ node-releases: 2.0.21
+ update-browserslist-db: 1.1.3(browserslist@4.26.3)
+
+ buffer-crc32@0.2.13: {}
+
+ bundle-name@4.1.0:
+ dependencies:
+ run-applescript: 7.1.0
+
+ cacheable-lookup@5.0.4: {}
+
+ cacheable-request@7.0.4:
+ dependencies:
+ clone-response: 1.0.3
+ get-stream: 5.2.0
+ http-cache-semantics: 4.2.0
+ keyv: 4.5.4
+ lowercase-keys: 2.0.0
+ normalize-url: 6.1.0
+ responselike: 2.0.1
+
+ call-bind-apply-helpers@1.0.2:
+ dependencies:
+ es-errors: 1.3.0
+ function-bind: 1.1.2
+
+ caniuse-lite@1.0.30001746: {}
+
+ chokidar@4.0.3:
+ dependencies:
+ readdirp: 4.1.2
+
+ chownr@3.0.0: {}
+
+ class-variance-authority@0.7.1:
+ dependencies:
+ clsx: 2.1.1
+
+ clone-response@1.0.3:
+ dependencies:
+ mimic-response: 1.0.1
+
+ clsx@2.1.1: {}
+
+ combined-stream@1.0.8:
+ dependencies:
+ delayed-stream: 1.0.0
+
+ confbox@0.1.8: {}
+
+ confbox@0.2.2: {}
+
+ convert-source-map@2.0.0: {}
+
+ cookie-es@1.2.2: {}
+
+ cookie@0.7.2: {}
+
+ copy-anything@3.0.5:
+ dependencies:
+ is-what: 4.1.16
+
+ cors@2.8.5:
+ dependencies:
+ object-assign: 4.1.1
+ vary: 1.1.2
+
+ cross-spawn@7.0.6:
+ dependencies:
+ path-key: 3.1.1
+ shebang-command: 2.0.0
+ which: 2.0.2
+
+ crossws@0.3.5:
+ dependencies:
+ uncrypto: 0.1.3
+
+ cssesc@3.0.0: {}
+
+ csstype@3.1.3: {}
+
+ debug@4.3.7:
+ dependencies:
+ ms: 2.1.3
+
+ debug@4.4.3:
+ dependencies:
+ ms: 2.1.3
+
+ decompress-response@6.0.0:
+ dependencies:
+ mimic-response: 3.1.0
+
+ default-browser-id@5.0.0: {}
+
+ default-browser@5.2.1:
+ dependencies:
+ bundle-name: 4.1.0
+ default-browser-id: 5.0.0
+
+ defer-to-connect@2.0.1: {}
+
+ define-data-property@1.1.4:
+ dependencies:
+ es-define-property: 1.0.1
+ es-errors: 1.3.0
+ gopd: 1.2.0
+ optional: true
+
+ define-lazy-prop@3.0.0: {}
+
+ define-properties@1.2.1:
+ dependencies:
+ define-data-property: 1.1.4
+ has-property-descriptors: 1.0.2
+ object-keys: 1.1.1
+ optional: true
+
+ defu@6.1.4: {}
+
+ delayed-stream@1.0.0: {}
+
+ destr@2.0.5: {}
+
+ detect-libc@2.1.1: {}
+
+ detect-node@2.1.0:
+ optional: true
+
+ dunder-proto@1.0.1:
+ dependencies:
+ call-bind-apply-helpers: 1.0.2
+ es-errors: 1.3.0
+ gopd: 1.2.0
+
+ electron-to-chromium@1.5.228: {}
+
+ electron@36.9.3:
+ dependencies:
+ '@electron/get': 2.0.3
+ '@types/node': 22.18.8
+ extract-zip: 2.0.1
+ transitivePeerDependencies:
+ - supports-color
+
+ end-of-stream@1.4.5:
+ dependencies:
+ once: 1.4.0
+
+ engine.io-client@6.6.3:
+ dependencies:
+ '@socket.io/component-emitter': 3.1.2
+ debug: 4.3.7
+ engine.io-parser: 5.2.3
+ ws: 8.17.1
+ xmlhttprequest-ssl: 2.1.2
+ transitivePeerDependencies:
+ - bufferutil
+ - supports-color
+ - utf-8-validate
+
+ engine.io-parser@5.2.3: {}
+
+ engine.io@6.6.4:
+ dependencies:
+ '@types/cors': 2.8.19
+ '@types/node': 24.6.2
+ accepts: 1.3.8
+ base64id: 2.0.0
+ cookie: 0.7.2
+ cors: 2.8.5
+ debug: 4.3.7
+ engine.io-parser: 5.2.3
+ ws: 8.17.1
+ transitivePeerDependencies:
+ - bufferutil
+ - supports-color
+ - utf-8-validate
+
+ enhanced-resolve@5.18.3:
+ dependencies:
+ graceful-fs: 4.2.11
+ tapable: 2.2.3
+
+ entities@4.5.0: {}
+
+ env-paths@2.2.1: {}
+
+ error-stack-parser-es@1.0.5: {}
+
+ 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
+
+ es6-error@4.1.1:
+ optional: true
+
+ esbuild@0.25.10:
+ optionalDependencies:
+ '@esbuild/aix-ppc64': 0.25.10
+ '@esbuild/android-arm': 0.25.10
+ '@esbuild/android-arm64': 0.25.10
+ '@esbuild/android-x64': 0.25.10
+ '@esbuild/darwin-arm64': 0.25.10
+ '@esbuild/darwin-x64': 0.25.10
+ '@esbuild/freebsd-arm64': 0.25.10
+ '@esbuild/freebsd-x64': 0.25.10
+ '@esbuild/linux-arm': 0.25.10
+ '@esbuild/linux-arm64': 0.25.10
+ '@esbuild/linux-ia32': 0.25.10
+ '@esbuild/linux-loong64': 0.25.10
+ '@esbuild/linux-mips64el': 0.25.10
+ '@esbuild/linux-ppc64': 0.25.10
+ '@esbuild/linux-riscv64': 0.25.10
+ '@esbuild/linux-s390x': 0.25.10
+ '@esbuild/linux-x64': 0.25.10
+ '@esbuild/netbsd-arm64': 0.25.10
+ '@esbuild/netbsd-x64': 0.25.10
+ '@esbuild/openbsd-arm64': 0.25.10
+ '@esbuild/openbsd-x64': 0.25.10
+ '@esbuild/openharmony-arm64': 0.25.10
+ '@esbuild/sunos-x64': 0.25.10
+ '@esbuild/win32-arm64': 0.25.10
+ '@esbuild/win32-ia32': 0.25.10
+ '@esbuild/win32-x64': 0.25.10
+
+ escalade@3.2.0: {}
+
+ escape-string-regexp@4.0.0:
+ optional: true
+
+ estree-walker@2.0.2: {}
+
+ execa@9.6.0:
+ dependencies:
+ '@sindresorhus/merge-streams': 4.0.0
+ cross-spawn: 7.0.6
+ figures: 6.1.0
+ get-stream: 9.0.1
+ human-signals: 8.0.1
+ is-plain-obj: 4.1.0
+ is-stream: 4.0.1
+ npm-run-path: 6.0.0
+ pretty-ms: 9.3.0
+ signal-exit: 4.1.0
+ strip-final-newline: 4.0.0
+ yoctocolors: 2.1.2
+
+ exsolve@1.0.7: {}
+
+ extract-zip@2.0.1:
+ dependencies:
+ debug: 4.4.3
+ get-stream: 5.2.0
+ yauzl: 2.10.0
+ optionalDependencies:
+ '@types/yauzl': 2.10.3
+ transitivePeerDependencies:
+ - supports-color
+
+ fast-deep-equal@3.1.3: {}
+
+ fd-slicer@1.1.0:
+ dependencies:
+ pend: 1.2.0
+
+ fdir@6.5.0(picomatch@4.0.3):
+ optionalDependencies:
+ picomatch: 4.0.3
+
+ figures@6.1.0:
+ dependencies:
+ is-unicode-supported: 2.1.0
+
+ follow-redirects@1.15.11: {}
+
+ form-data@4.0.4:
+ 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
+
+ fs-extra@8.1.0:
+ dependencies:
+ graceful-fs: 4.2.11
+ jsonfile: 4.0.0
+ universalify: 0.1.2
+
+ fsevents@2.3.3:
+ optional: true
+
+ function-bind@1.1.2: {}
+
+ gensync@1.0.0-beta.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
+
+ get-stream@5.2.0:
+ dependencies:
+ pump: 3.0.3
+
+ get-stream@9.0.1:
+ dependencies:
+ '@sec-ant/readable-stream': 0.4.1
+ is-stream: 4.0.1
+
+ global-agent@3.0.0:
+ dependencies:
+ boolean: 3.2.0
+ es6-error: 4.1.1
+ matcher: 3.0.0
+ roarr: 2.15.4
+ semver: 7.7.2
+ serialize-error: 7.0.1
+ optional: true
+
+ globalthis@1.0.4:
+ dependencies:
+ define-properties: 1.2.1
+ gopd: 1.2.0
+ optional: true
+
+ gopd@1.2.0: {}
+
+ got@11.8.6:
+ dependencies:
+ '@sindresorhus/is': 4.6.0
+ '@szmarczak/http-timer': 4.0.6
+ '@types/cacheable-request': 6.0.3
+ '@types/responselike': 1.0.3
+ cacheable-lookup: 5.0.4
+ cacheable-request: 7.0.4
+ decompress-response: 6.0.0
+ http2-wrapper: 1.0.3
+ lowercase-keys: 2.0.0
+ p-cancelable: 2.1.1
+ responselike: 2.0.1
+
+ graceful-fs@4.2.11: {}
+
+ h3@1.15.4:
+ dependencies:
+ cookie-es: 1.2.2
+ crossws: 0.3.5
+ defu: 6.1.4
+ destr: 2.0.5
+ iron-webcrypto: 1.2.1
+ node-mock-http: 1.0.3
+ radix3: 1.1.2
+ ufo: 1.6.1
+ uncrypto: 0.1.3
+
+ has-property-descriptors@1.0.2:
+ dependencies:
+ es-define-property: 1.0.1
+ optional: true
+
+ 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
+
+ hookable@5.5.3: {}
+
+ http-cache-semantics@4.2.0: {}
+
+ http2-wrapper@1.0.3:
+ dependencies:
+ quick-lru: 5.1.1
+ resolve-alpn: 1.2.1
+
+ human-signals@8.0.1: {}
+
+ iron-webcrypto@1.2.1: {}
+
+ is-docker@3.0.0: {}
+
+ is-inside-container@1.0.0:
+ dependencies:
+ is-docker: 3.0.0
+
+ is-plain-obj@4.1.0: {}
+
+ is-stream@4.0.1: {}
+
+ is-unicode-supported@2.1.0: {}
+
+ is-what@4.1.16: {}
+
+ is-wsl@3.1.0:
+ dependencies:
+ is-inside-container: 1.0.0
+
+ isexe@2.0.0: {}
+
+ jiti@2.6.1: {}
+
+ js-tokens@4.0.0: {}
+
+ jsesc@3.1.0: {}
+
+ json-buffer@3.0.1: {}
+
+ json-stringify-safe@5.0.1:
+ optional: true
+
+ json5@2.2.3: {}
+
+ jsonfile@4.0.0:
+ optionalDependencies:
+ graceful-fs: 4.2.11
+
+ keyv@4.5.4:
+ dependencies:
+ json-buffer: 3.0.1
+
+ kolorist@1.8.0: {}
+
+ lightningcss-darwin-arm64@1.30.1:
+ optional: true
+
+ lightningcss-darwin-x64@1.30.1:
+ optional: true
+
+ lightningcss-freebsd-x64@1.30.1:
+ optional: true
+
+ lightningcss-linux-arm-gnueabihf@1.30.1:
+ optional: true
+
+ lightningcss-linux-arm64-gnu@1.30.1:
+ optional: true
+
+ lightningcss-linux-arm64-musl@1.30.1:
+ optional: true
+
+ lightningcss-linux-x64-gnu@1.30.1:
+ optional: true
+
+ lightningcss-linux-x64-musl@1.30.1:
+ optional: true
+
+ lightningcss-win32-arm64-msvc@1.30.1:
+ optional: true
+
+ lightningcss-win32-x64-msvc@1.30.1:
+ optional: true
+
+ lightningcss@1.30.1:
+ dependencies:
+ detect-libc: 2.1.1
+ optionalDependencies:
+ lightningcss-darwin-arm64: 1.30.1
+ lightningcss-darwin-x64: 1.30.1
+ lightningcss-freebsd-x64: 1.30.1
+ lightningcss-linux-arm-gnueabihf: 1.30.1
+ lightningcss-linux-arm64-gnu: 1.30.1
+ lightningcss-linux-arm64-musl: 1.30.1
+ lightningcss-linux-x64-gnu: 1.30.1
+ lightningcss-linux-x64-musl: 1.30.1
+ lightningcss-win32-arm64-msvc: 1.30.1
+ lightningcss-win32-x64-msvc: 1.30.1
+
+ local-pkg@1.1.2:
+ dependencies:
+ mlly: 1.8.0
+ pkg-types: 2.3.0
+ quansync: 0.2.11
+
+ lowercase-keys@2.0.0: {}
+
+ lru-cache@5.1.1:
+ dependencies:
+ yallist: 3.1.1
+
+ lucide-react@0.544.0(react@19.2.0):
+ dependencies:
+ react: 19.2.0
+
+ lucide-vue-next@0.544.0(vue@3.5.22):
+ dependencies:
+ vue: 3.5.22
+
+ magic-string-ast@1.0.2:
+ dependencies:
+ magic-string: 0.30.19
+
+ magic-string@0.30.19:
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.5.5
+
+ marked@16.3.0: {}
+
+ matcher@3.0.0:
+ dependencies:
+ escape-string-regexp: 4.0.0
+ optional: true
+
+ math-intrinsics@1.1.0: {}
+
+ mime-db@1.52.0: {}
+
+ mime-types@2.1.35:
+ dependencies:
+ mime-db: 1.52.0
+
+ mimic-response@1.0.1: {}
+
+ mimic-response@3.1.0: {}
+
+ minipass@7.1.2: {}
+
+ minizlib@3.1.0:
+ dependencies:
+ minipass: 7.1.2
+
+ mitt@3.0.1: {}
+
+ mlly@1.8.0:
+ dependencies:
+ acorn: 8.15.0
+ pathe: 2.0.3
+ pkg-types: 1.3.1
+ ufo: 1.6.1
+
+ mrmime@2.0.1: {}
+
+ ms@2.1.3: {}
+
+ muggle-string@0.4.1: {}
+
+ nanoid@3.3.11: {}
+
+ nanoid@5.1.6: {}
+
+ negotiator@0.6.3: {}
+
+ node-mock-http@1.0.3: {}
+
+ node-releases@2.0.21: {}
+
+ normalize-url@6.1.0: {}
+
+ npm-run-path@6.0.0:
+ dependencies:
+ path-key: 4.0.0
+ unicorn-magic: 0.3.0
+
+ object-assign@4.1.1: {}
+
+ object-keys@1.1.1:
+ optional: true
+
+ ohash@2.0.11: {}
+
+ once@1.4.0:
+ dependencies:
+ wrappy: 1.0.2
+
+ open@10.2.0:
+ dependencies:
+ default-browser: 5.2.1
+ define-lazy-prop: 3.0.0
+ is-inside-container: 1.0.0
+ wsl-utils: 0.1.0
+
+ p-cancelable@2.1.1: {}
+
+ parse-ms@4.0.0: {}
+
+ path-browserify@1.0.1: {}
+
+ path-key@3.1.1: {}
+
+ path-key@4.0.0: {}
+
+ pathe@2.0.3: {}
+
+ pend@1.2.0: {}
+
+ perfect-debounce@1.0.0: {}
+
+ perfect-debounce@2.0.0: {}
+
+ picocolors@1.1.1: {}
+
+ picomatch@4.0.3: {}
+
+ pinia@3.0.3(vue@3.5.22):
+ dependencies:
+ '@vue/devtools-api': 7.7.7
+ vue: 3.5.22
+
+ pkg-types@1.3.1:
+ dependencies:
+ confbox: 0.1.8
+ mlly: 1.8.0
+ pathe: 2.0.3
+
+ pkg-types@2.3.0:
+ dependencies:
+ confbox: 0.2.2
+ exsolve: 1.0.7
+ pathe: 2.0.3
+
+ postcss-selector-parser@6.0.10:
+ dependencies:
+ cssesc: 3.0.0
+ util-deprecate: 1.0.2
+
+ postcss@8.5.6:
+ dependencies:
+ nanoid: 3.3.11
+ picocolors: 1.1.1
+ source-map-js: 1.2.1
+
+ pretty-ms@9.3.0:
+ dependencies:
+ parse-ms: 4.0.0
+
+ progress@2.0.3: {}
+
+ proxy-from-env@1.1.0: {}
+
+ pump@3.0.3:
+ dependencies:
+ end-of-stream: 1.4.5
+ once: 1.4.0
+
+ quansync@0.2.11: {}
+
+ quick-lru@5.1.1: {}
+
+ radix-vue@1.9.17(vue@3.5.22):
+ dependencies:
+ '@floating-ui/dom': 1.7.4
+ '@floating-ui/vue': 1.1.9(vue@3.5.22)
+ '@internationalized/date': 3.9.0
+ '@internationalized/number': 3.6.5
+ '@tanstack/vue-virtual': 3.13.12(vue@3.5.22)
+ '@vueuse/core': 10.11.1(vue@3.5.22)
+ '@vueuse/shared': 10.11.1(vue@3.5.22)
+ aria-hidden: 1.2.6
+ defu: 6.1.4
+ fast-deep-equal: 3.1.3
+ nanoid: 5.1.6
+ vue: 3.5.22
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+
+ radix3@1.1.2: {}
+
+ react@19.2.0: {}
+
+ readdirp@4.1.2: {}
+
+ reka-ui@2.5.1(vue@3.5.22):
+ dependencies:
+ '@floating-ui/dom': 1.7.4
+ '@floating-ui/vue': 1.1.9(vue@3.5.22)
+ '@internationalized/date': 3.9.0
+ '@internationalized/number': 3.6.5
+ '@tanstack/vue-virtual': 3.13.12(vue@3.5.22)
+ '@vueuse/core': 12.8.2
+ '@vueuse/shared': 12.8.2
+ aria-hidden: 1.2.6
+ defu: 6.1.4
+ ohash: 2.0.11
+ vue: 3.5.22
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - typescript
+
+ resolve-alpn@1.2.1: {}
+
+ responselike@2.0.1:
+ dependencies:
+ lowercase-keys: 2.0.0
+
+ rfdc@1.4.1: {}
+
+ roarr@2.15.4:
+ dependencies:
+ boolean: 3.2.0
+ detect-node: 2.1.0
+ globalthis: 1.0.4
+ json-stringify-safe: 5.0.1
+ semver-compare: 1.0.0
+ sprintf-js: 1.1.3
+ optional: true
+
+ rollup@4.52.3:
+ dependencies:
+ '@types/estree': 1.0.8
+ optionalDependencies:
+ '@rollup/rollup-android-arm-eabi': 4.52.3
+ '@rollup/rollup-android-arm64': 4.52.3
+ '@rollup/rollup-darwin-arm64': 4.52.3
+ '@rollup/rollup-darwin-x64': 4.52.3
+ '@rollup/rollup-freebsd-arm64': 4.52.3
+ '@rollup/rollup-freebsd-x64': 4.52.3
+ '@rollup/rollup-linux-arm-gnueabihf': 4.52.3
+ '@rollup/rollup-linux-arm-musleabihf': 4.52.3
+ '@rollup/rollup-linux-arm64-gnu': 4.52.3
+ '@rollup/rollup-linux-arm64-musl': 4.52.3
+ '@rollup/rollup-linux-loong64-gnu': 4.52.3
+ '@rollup/rollup-linux-ppc64-gnu': 4.52.3
+ '@rollup/rollup-linux-riscv64-gnu': 4.52.3
+ '@rollup/rollup-linux-riscv64-musl': 4.52.3
+ '@rollup/rollup-linux-s390x-gnu': 4.52.3
+ '@rollup/rollup-linux-x64-gnu': 4.52.3
+ '@rollup/rollup-linux-x64-musl': 4.52.3
+ '@rollup/rollup-openharmony-arm64': 4.52.3
+ '@rollup/rollup-win32-arm64-msvc': 4.52.3
+ '@rollup/rollup-win32-ia32-msvc': 4.52.3
+ '@rollup/rollup-win32-x64-gnu': 4.52.3
+ '@rollup/rollup-win32-x64-msvc': 4.52.3
+ fsevents: 2.3.3
+
+ run-applescript@7.1.0: {}
+
+ scule@1.3.0: {}
+
+ semver-compare@1.0.0:
+ optional: true
+
+ semver@6.3.1: {}
+
+ semver@7.7.2:
+ optional: true
+
+ serialize-error@7.0.1:
+ dependencies:
+ type-fest: 0.13.1
+ optional: true
+
+ shebang-command@2.0.0:
+ dependencies:
+ shebang-regex: 3.0.0
+
+ shebang-regex@3.0.0: {}
+
+ signal-exit@4.1.0: {}
+
+ sirv@3.0.2:
+ dependencies:
+ '@polka/url': 1.0.0-next.29
+ mrmime: 2.0.1
+ totalist: 3.0.1
+
+ socket.io-adapter@2.5.5:
+ dependencies:
+ debug: 4.3.7
+ ws: 8.17.1
+ transitivePeerDependencies:
+ - bufferutil
+ - supports-color
+ - utf-8-validate
+
+ socket.io-client@4.8.1:
+ dependencies:
+ '@socket.io/component-emitter': 3.1.2
+ debug: 4.3.7
+ engine.io-client: 6.6.3
+ socket.io-parser: 4.2.4
+ transitivePeerDependencies:
+ - bufferutil
+ - supports-color
+ - utf-8-validate
+
+ socket.io-parser@4.2.4:
+ dependencies:
+ '@socket.io/component-emitter': 3.1.2
+ debug: 4.3.7
+ transitivePeerDependencies:
+ - supports-color
+
+ socket.io@4.8.1:
+ dependencies:
+ accepts: 1.3.8
+ base64id: 2.0.0
+ cors: 2.8.5
+ debug: 4.3.7
+ engine.io: 6.6.4
+ socket.io-adapter: 2.5.5
+ socket.io-parser: 4.2.4
+ transitivePeerDependencies:
+ - bufferutil
+ - supports-color
+ - utf-8-validate
+
+ source-map-js@1.2.1: {}
+
+ speakingurl@14.0.1: {}
+
+ sprintf-js@1.1.3:
+ optional: true
+
+ strip-final-newline@4.0.0: {}
+
+ sumchecker@3.0.1:
+ dependencies:
+ debug: 4.4.3
+ transitivePeerDependencies:
+ - supports-color
+
+ superjson@2.2.2:
+ dependencies:
+ copy-anything: 3.0.5
+
+ tailwind-merge@3.3.1: {}
+
+ tailwindcss@4.1.14: {}
+
+ tapable@2.2.3: {}
+
+ tar@7.5.1:
+ dependencies:
+ '@isaacs/fs-minipass': 4.0.1
+ chownr: 3.0.0
+ minipass: 7.1.2
+ minizlib: 3.1.0
+ yallist: 5.0.0
+
+ tinyglobby@0.2.15:
+ dependencies:
+ fdir: 6.5.0(picomatch@4.0.3)
+ picomatch: 4.0.3
+
+ totalist@3.0.1: {}
+
+ tslib@2.8.1: {}
+
+ tw-animate-css@1.4.0: {}
+
+ type-fest@0.13.1:
+ optional: true
+
+ type-fest@4.41.0: {}
+
+ ufo@1.6.1: {}
+
+ uncrypto@0.1.3: {}
+
+ undici-types@6.21.0: {}
+
+ undici-types@7.13.0: {}
+
+ unicorn-magic@0.3.0: {}
+
+ universalify@0.1.2: {}
+
+ unplugin-utils@0.2.5:
+ dependencies:
+ pathe: 2.0.3
+ picomatch: 4.0.3
+
+ unplugin-utils@0.3.0:
+ dependencies:
+ pathe: 2.0.3
+ picomatch: 4.0.3
+
+ unplugin-vue-router@0.15.0(@vue/compiler-sfc@3.5.22)(vue-router@4.5.1(vue@3.5.22))(vue@3.5.22):
+ dependencies:
+ '@vue-macros/common': 3.0.0-beta.16(vue@3.5.22)
+ '@vue/compiler-sfc': 3.5.22
+ '@vue/language-core': 3.1.0
+ ast-walker-scope: 0.8.2
+ chokidar: 4.0.3
+ json5: 2.2.3
+ local-pkg: 1.1.2
+ magic-string: 0.30.19
+ mlly: 1.8.0
+ muggle-string: 0.4.1
+ pathe: 2.0.3
+ picomatch: 4.0.3
+ scule: 1.3.0
+ tinyglobby: 0.2.15
+ unplugin: 2.3.10
+ unplugin-utils: 0.2.5
+ yaml: 2.8.1
+ optionalDependencies:
+ vue-router: 4.5.1(vue@3.5.22)
+ transitivePeerDependencies:
+ - typescript
+ - vue
+
+ unplugin@2.3.10:
+ dependencies:
+ '@jridgewell/remapping': 2.3.5
+ acorn: 8.15.0
+ picomatch: 4.0.3
+ webpack-virtual-modules: 0.6.2
+
+ update-browserslist-db@1.1.3(browserslist@4.26.3):
+ dependencies:
+ browserslist: 4.26.3
+ escalade: 3.2.0
+ picocolors: 1.1.1
+
+ util-deprecate@1.0.2: {}
+
+ vary@1.1.2: {}
+
+ vee-validate@4.15.1(vue@3.5.22):
+ dependencies:
+ '@vue/devtools-api': 7.7.7
+ type-fest: 4.41.0
+ vue: 3.5.22
+
+ vite-dev-rpc@1.1.0(vite@7.1.7(@types/node@24.6.2)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@2.8.1)):
+ dependencies:
+ birpc: 2.6.1
+ vite: 7.1.7(@types/node@24.6.2)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@2.8.1)
+ vite-hot-client: 2.1.0(vite@7.1.7(@types/node@24.6.2)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@2.8.1))
+
+ vite-hot-client@2.1.0(vite@7.1.7(@types/node@24.6.2)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@2.8.1)):
+ dependencies:
+ vite: 7.1.7(@types/node@24.6.2)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@2.8.1)
+
+ vite-plugin-inspect@11.3.3(vite@7.1.7(@types/node@24.6.2)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@2.8.1)):
+ dependencies:
+ ansis: 4.2.0
+ debug: 4.4.3
+ error-stack-parser-es: 1.0.5
+ ohash: 2.0.11
+ open: 10.2.0
+ perfect-debounce: 2.0.0
+ sirv: 3.0.2
+ unplugin-utils: 0.3.0
+ vite: 7.1.7(@types/node@24.6.2)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@2.8.1)
+ vite-dev-rpc: 1.1.0(vite@7.1.7(@types/node@24.6.2)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@2.8.1))
+ transitivePeerDependencies:
+ - supports-color
+
+ vite-plugin-vue-devtools@8.0.2(vite@7.1.7(@types/node@24.6.2)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@2.8.1))(vue@3.5.22):
+ dependencies:
+ '@vue/devtools-core': 8.0.2(vite@7.1.7(@types/node@24.6.2)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@2.8.1))(vue@3.5.22)
+ '@vue/devtools-kit': 8.0.2
+ '@vue/devtools-shared': 8.0.2
+ execa: 9.6.0
+ sirv: 3.0.2
+ vite: 7.1.7(@types/node@24.6.2)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@2.8.1)
+ vite-plugin-inspect: 11.3.3(vite@7.1.7(@types/node@24.6.2)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@2.8.1))
+ vite-plugin-vue-inspector: 5.3.2(vite@7.1.7(@types/node@24.6.2)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@2.8.1))
+ transitivePeerDependencies:
+ - '@nuxt/kit'
+ - supports-color
+ - vue
+
+ vite-plugin-vue-inspector@5.3.2(vite@7.1.7(@types/node@24.6.2)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@2.8.1)):
+ dependencies:
+ '@babel/core': 7.28.4
+ '@babel/plugin-proposal-decorators': 7.28.0(@babel/core@7.28.4)
+ '@babel/plugin-syntax-import-attributes': 7.27.1(@babel/core@7.28.4)
+ '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.28.4)
+ '@babel/plugin-transform-typescript': 7.28.0(@babel/core@7.28.4)
+ '@vue/babel-plugin-jsx': 1.5.0(@babel/core@7.28.4)
+ '@vue/compiler-dom': 3.5.22
+ kolorist: 1.8.0
+ magic-string: 0.30.19
+ vite: 7.1.7(@types/node@24.6.2)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@2.8.1)
+ transitivePeerDependencies:
+ - supports-color
+
+ vite@7.1.7(@types/node@24.6.2)(jiti@2.6.1)(lightningcss@1.30.1)(yaml@2.8.1):
+ dependencies:
+ esbuild: 0.25.10
+ fdir: 6.5.0(picomatch@4.0.3)
+ picomatch: 4.0.3
+ postcss: 8.5.6
+ rollup: 4.52.3
+ tinyglobby: 0.2.15
+ optionalDependencies:
+ '@types/node': 24.6.2
+ fsevents: 2.3.3
+ jiti: 2.6.1
+ lightningcss: 1.30.1
+ yaml: 2.8.1
+
+ vue-demi@0.14.10(vue@3.5.22):
+ dependencies:
+ vue: 3.5.22
+
+ vue-router@4.5.1(vue@3.5.22):
+ dependencies:
+ '@vue/devtools-api': 6.6.4
+ vue: 3.5.22
+
+ vue-sonner@2.0.9: {}
+
+ vue@3.5.22:
+ dependencies:
+ '@vue/compiler-dom': 3.5.22
+ '@vue/compiler-sfc': 3.5.22
+ '@vue/runtime-dom': 3.5.22
+ '@vue/server-renderer': 3.5.22(vue@3.5.22)
+ '@vue/shared': 3.5.22
+
+ webpack-virtual-modules@0.6.2: {}
+
+ which@2.0.2:
+ dependencies:
+ isexe: 2.0.0
+
+ wrappy@1.0.2: {}
+
+ ws@8.17.1: {}
+
+ wsl-utils@0.1.0:
+ dependencies:
+ is-wsl: 3.1.0
+
+ xmlhttprequest-ssl@2.1.2: {}
+
+ yallist@3.1.1: {}
+
+ yallist@5.0.0: {}
+
+ yaml@2.8.1: {}
+
+ yauzl@2.10.0:
+ dependencies:
+ buffer-crc32: 0.2.13
+ fd-slicer: 1.1.0
+
+ yoctocolors@2.1.2: {}
+
+ zod@3.25.76: {}
diff --git a/public/vite.svg b/public/vite.svg
new file mode 100644
index 0000000..e7b8dfb
--- /dev/null
+++ b/public/vite.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/App.vue b/src/App.vue
new file mode 100644
index 0000000..0270f57
--- /dev/null
+++ b/src/App.vue
@@ -0,0 +1,10 @@
+
+
+
+
+
+
diff --git a/src/assets/vue.svg b/src/assets/vue.svg
new file mode 100644
index 0000000..770e9d3
--- /dev/null
+++ b/src/assets/vue.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/components/AppCard.vue b/src/components/AppCard.vue
new file mode 100644
index 0000000..39acfb6
--- /dev/null
+++ b/src/components/AppCard.vue
@@ -0,0 +1,296 @@
+
+
+
+
+
+
+ 加载中...
+
+
+
+
+ 错误
+ {{ error }}
+
+
+
+
+
+
+
(e.target.style.display = 'none')"
+ />
+
+
{{ app.name }}
+
+ {{ app.description }}
+
+
+ {{ app.owner?.display_name || app.owner?.username }}
+
+
+
+
+
+
+
+
+
+
+
+
+
(e.target.style.display = 'none')"
+ />
+
+ {{ app.name }}
+
+ {{ app.description }}
+
+
+
+
+
+
+
+
开发者
+
{{ app.owner?.display_name || app.owner?.username }}
+
+
+
+
+
+
+
+
+
+
+ 无法加载 README 文件
+
+
+
+
diff --git a/src/components/DeviceRegisterDialog.vue b/src/components/DeviceRegisterDialog.vue
new file mode 100644
index 0000000..be9e136
--- /dev/null
+++ b/src/components/DeviceRegisterDialog.vue
@@ -0,0 +1,400 @@
+
+
+
+ !val && (props.required ? isOpen = true : handleClose())">
+
+
+ 设备管理
+
+ 加载账户设备或注册新设备
+
+
+
+
+
+
+
+
请先注册或加载设备
+
+ 您需要注册或加载一个设备才能继续使用。
+
+
+
+
+
+
+
+
+
+
+ 加载设备
+
+
+
+ 注册设备
+
+
+
+
+
+
+
请先登录以查看您的设备列表
+
+ 登录账户
+
+
+
+
+
+
+
您的账户暂未绑定任何设备
+
+
+ 注册新设备
+
+
+
+
+
+
+
+
+ {{ device.name || '未命名设备' }}
+
+
+ {{ device.uuid }}
+
+
+ 创建时间: {{ new Date(device.createdAt).toLocaleString('zh-CN') }}
+
+
+
+ 加载
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 设备名称
+
+
+
+
+
+
+
+
+
+
+ 绑定到账户
+
+
+ {{ accountStore.isAuthenticated
+ ? `将此设备绑定到账户 ${accountStore.userName},绑定后可在其他设备上快速加载`
+ : '登录后可以将设备绑定到您的账户'
+ }}
+
+
+
+
+
+
+
提示:
+
+ UUID将保存到本地浏览器存储
+ 设备名称将帮助您快速识别不同的设备
+ 绑定后可在任何设备上通过账户加载
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/EditDeviceNameDialog.vue b/src/components/EditDeviceNameDialog.vue
new file mode 100644
index 0000000..76d34e4
--- /dev/null
+++ b/src/components/EditDeviceNameDialog.vue
@@ -0,0 +1,136 @@
+
+
+
+
+
+
+
+
+
+ 编辑设备名称
+
+
+
+ 为设备设置一个易于识别的名称
+
+
+
+
+
+
+
+ 取消
+
+
+ {{ isSubmitting ? '更新中...' : '确认' }}
+
+
+
+
+
diff --git a/src/components/HelloWorld.vue b/src/components/HelloWorld.vue
new file mode 100644
index 0000000..b58e52b
--- /dev/null
+++ b/src/components/HelloWorld.vue
@@ -0,0 +1,41 @@
+
+
+
+ {{ msg }}
+
+
+
count is {{ count }}
+
+ Edit
+ components/HelloWorld.vue
to test HMR
+
+
+
+
+ Check out
+ create-vue , the official Vue + Vite starter
+
+
+ Learn more about IDE Support for Vue in the
+ Vue Docs Scaling up Guide .
+
+ Click on the Vite and Vue logos to learn more
+
+
+
diff --git a/src/components/LoginDialog.vue b/src/components/LoginDialog.vue
new file mode 100644
index 0000000..b106ed1
--- /dev/null
+++ b/src/components/LoginDialog.vue
@@ -0,0 +1,220 @@
+
+
+
+
+
+
+ 账户登录
+
+ 选择一个OAuth提供者进行登录
+
+
+
+
+ 正在加载登录方式...
+
+
+
+
+
+
+
{{ provider.name }}
+
{{ provider.description }}
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/components/PasswordInput.vue b/src/components/PasswordInput.vue
new file mode 100644
index 0000000..55e5657
--- /dev/null
+++ b/src/components/PasswordInput.vue
@@ -0,0 +1,262 @@
+
+
+
+
+
+
+
+ {{ label }}
+ *
+
+
+
+
+
+
+ 密码提示
+
+
+
+
+
+
+
+
+
密码提示
+
{{ passwordHint }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ passwordHint }}
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/components/ResetDevicePasswordDialog.vue b/src/components/ResetDevicePasswordDialog.vue
new file mode 100644
index 0000000..e7ef977
--- /dev/null
+++ b/src/components/ResetDevicePasswordDialog.vue
@@ -0,0 +1,274 @@
+
+
+
+
+
+
+ 重置设备密码
+
+ 为设备 {{ deviceName || deviceUuid }} 设置新密码
+
+
+
+
+
+
+ 您已登录绑定的账户,可以直接重置密码而无需输入当前密码
+
+
+
+
+
+
+
+
+
+ 删除密码
+
+
+ 设置提示
+
+
+
+
+ 取消
+
+
+ {{ isSubmitting ? '重置中...' : '确认重置' }}
+
+
+
+
+
+
+
+
+
+
+ 确认删除密码
+
+ 确定要删除设备 "{{ deviceName || deviceUuid }}" 的密码吗?删除后任何人都可以访问该设备。
+
+
+
+ 取消
+
+ {{ isSubmitting ? '删除中...' : '确认删除' }}
+
+
+
+
+
+
+
+
+
+ 设置密码提示
+
+ 为设备 {{ deviceName || deviceUuid }} 设置密码提示
+
+
+
+
+
+
+
+ 取消
+
+
+ {{ isSettingHint ? '设置中...' : '确认设置' }}
+
+
+
+
+
diff --git a/src/components/ui/alert-dialog/AlertDialog.vue b/src/components/ui/alert-dialog/AlertDialog.vue
new file mode 100644
index 0000000..266f5c7
--- /dev/null
+++ b/src/components/ui/alert-dialog/AlertDialog.vue
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/alert-dialog/AlertDialogAction.vue b/src/components/ui/alert-dialog/AlertDialogAction.vue
new file mode 100644
index 0000000..98526b9
--- /dev/null
+++ b/src/components/ui/alert-dialog/AlertDialogAction.vue
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/alert-dialog/AlertDialogCancel.vue b/src/components/ui/alert-dialog/AlertDialogCancel.vue
new file mode 100644
index 0000000..1c7fd6d
--- /dev/null
+++ b/src/components/ui/alert-dialog/AlertDialogCancel.vue
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/alert-dialog/AlertDialogContent.vue b/src/components/ui/alert-dialog/AlertDialogContent.vue
new file mode 100644
index 0000000..54237cf
--- /dev/null
+++ b/src/components/ui/alert-dialog/AlertDialogContent.vue
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/ui/alert-dialog/AlertDialogDescription.vue b/src/components/ui/alert-dialog/AlertDialogDescription.vue
new file mode 100644
index 0000000..6617af9
--- /dev/null
+++ b/src/components/ui/alert-dialog/AlertDialogDescription.vue
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/alert-dialog/AlertDialogFooter.vue b/src/components/ui/alert-dialog/AlertDialogFooter.vue
new file mode 100644
index 0000000..c216b25
--- /dev/null
+++ b/src/components/ui/alert-dialog/AlertDialogFooter.vue
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/alert-dialog/AlertDialogHeader.vue b/src/components/ui/alert-dialog/AlertDialogHeader.vue
new file mode 100644
index 0000000..00c5aaf
--- /dev/null
+++ b/src/components/ui/alert-dialog/AlertDialogHeader.vue
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/alert-dialog/AlertDialogTitle.vue b/src/components/ui/alert-dialog/AlertDialogTitle.vue
new file mode 100644
index 0000000..5c48c2d
--- /dev/null
+++ b/src/components/ui/alert-dialog/AlertDialogTitle.vue
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/alert-dialog/AlertDialogTrigger.vue b/src/components/ui/alert-dialog/AlertDialogTrigger.vue
new file mode 100644
index 0000000..2d546bd
--- /dev/null
+++ b/src/components/ui/alert-dialog/AlertDialogTrigger.vue
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/alert-dialog/index.js b/src/components/ui/alert-dialog/index.js
new file mode 100644
index 0000000..c48e47b
--- /dev/null
+++ b/src/components/ui/alert-dialog/index.js
@@ -0,0 +1,9 @@
+export { default as AlertDialog } from "./AlertDialog.vue";
+export { default as AlertDialogAction } from "./AlertDialogAction.vue";
+export { default as AlertDialogCancel } from "./AlertDialogCancel.vue";
+export { default as AlertDialogContent } from "./AlertDialogContent.vue";
+export { default as AlertDialogDescription } from "./AlertDialogDescription.vue";
+export { default as AlertDialogFooter } from "./AlertDialogFooter.vue";
+export { default as AlertDialogHeader } from "./AlertDialogHeader.vue";
+export { default as AlertDialogTitle } from "./AlertDialogTitle.vue";
+export { default as AlertDialogTrigger } from "./AlertDialogTrigger.vue";
diff --git a/src/components/ui/badge/Badge.vue b/src/components/ui/badge/Badge.vue
new file mode 100644
index 0000000..c050809
--- /dev/null
+++ b/src/components/ui/badge/Badge.vue
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/badge/index.js b/src/components/ui/badge/index.js
new file mode 100644
index 0000000..447cf8e
--- /dev/null
+++ b/src/components/ui/badge/index.js
@@ -0,0 +1,24 @@
+import { cva } from "class-variance-authority";
+
+export { default as Badge } from "./Badge.vue";
+
+export const badgeVariants = cva(
+ "inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-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 transition-[color,box-shadow] overflow-hidden",
+ {
+ variants: {
+ variant: {
+ default:
+ "border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
+ secondary:
+ "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
+ destructive:
+ "border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
+ outline:
+ "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
+ },
+ },
+ defaultVariants: {
+ variant: "default",
+ },
+ },
+);
diff --git a/src/components/ui/button/Button.vue b/src/components/ui/button/Button.vue
new file mode 100644
index 0000000..8abe477
--- /dev/null
+++ b/src/components/ui/button/Button.vue
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/button/index.js b/src/components/ui/button/index.js
new file mode 100644
index 0000000..83eb0ed
--- /dev/null
+++ b/src/components/ui/button/index.js
@@ -0,0 +1,34 @@
+import { cva } from "class-variance-authority";
+
+export { default as Button } from "./Button.vue";
+
+export const buttonVariants = cva(
+ "inline-flex 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 shadow-xs hover:bg-primary/90",
+ destructive:
+ "bg-destructive text-white shadow-xs 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 shadow-xs 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",
+ },
+ },
+ defaultVariants: {
+ variant: "default",
+ size: "default",
+ },
+ },
+);
diff --git a/src/components/ui/card/Card.vue b/src/components/ui/card/Card.vue
new file mode 100644
index 0000000..16920e4
--- /dev/null
+++ b/src/components/ui/card/Card.vue
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/card/CardAction.vue b/src/components/ui/card/CardAction.vue
new file mode 100644
index 0000000..4c13362
--- /dev/null
+++ b/src/components/ui/card/CardAction.vue
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/card/CardContent.vue b/src/components/ui/card/CardContent.vue
new file mode 100644
index 0000000..f54f541
--- /dev/null
+++ b/src/components/ui/card/CardContent.vue
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/card/CardDescription.vue b/src/components/ui/card/CardDescription.vue
new file mode 100644
index 0000000..199875d
--- /dev/null
+++ b/src/components/ui/card/CardDescription.vue
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/card/CardFooter.vue b/src/components/ui/card/CardFooter.vue
new file mode 100644
index 0000000..a28c159
--- /dev/null
+++ b/src/components/ui/card/CardFooter.vue
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/card/CardHeader.vue b/src/components/ui/card/CardHeader.vue
new file mode 100644
index 0000000..cc387d1
--- /dev/null
+++ b/src/components/ui/card/CardHeader.vue
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/card/CardTitle.vue b/src/components/ui/card/CardTitle.vue
new file mode 100644
index 0000000..bb88bf0
--- /dev/null
+++ b/src/components/ui/card/CardTitle.vue
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/card/index.js b/src/components/ui/card/index.js
new file mode 100644
index 0000000..409685b
--- /dev/null
+++ b/src/components/ui/card/index.js
@@ -0,0 +1,7 @@
+export { default as Card } from "./Card.vue";
+export { default as CardAction } from "./CardAction.vue";
+export { default as CardContent } from "./CardContent.vue";
+export { default as CardDescription } from "./CardDescription.vue";
+export { default as CardFooter } from "./CardFooter.vue";
+export { default as CardHeader } from "./CardHeader.vue";
+export { default as CardTitle } from "./CardTitle.vue";
diff --git a/src/components/ui/checkbox/Checkbox.vue b/src/components/ui/checkbox/Checkbox.vue
new file mode 100644
index 0000000..32519de
--- /dev/null
+++ b/src/components/ui/checkbox/Checkbox.vue
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/ui/checkbox/index.js b/src/components/ui/checkbox/index.js
new file mode 100644
index 0000000..75be342
--- /dev/null
+++ b/src/components/ui/checkbox/index.js
@@ -0,0 +1 @@
+export { default as Checkbox } from "./Checkbox.vue";
diff --git a/src/components/ui/dialog/Dialog.vue b/src/components/ui/dialog/Dialog.vue
new file mode 100644
index 0000000..c261c6f
--- /dev/null
+++ b/src/components/ui/dialog/Dialog.vue
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/dialog/DialogClose.vue b/src/components/ui/dialog/DialogClose.vue
new file mode 100644
index 0000000..80f6f53
--- /dev/null
+++ b/src/components/ui/dialog/DialogClose.vue
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/dialog/DialogContent.vue b/src/components/ui/dialog/DialogContent.vue
new file mode 100644
index 0000000..50befa5
--- /dev/null
+++ b/src/components/ui/dialog/DialogContent.vue
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+ Close
+
+
+
+
diff --git a/src/components/ui/dialog/DialogDescription.vue b/src/components/ui/dialog/DialogDescription.vue
new file mode 100644
index 0000000..b981e8e
--- /dev/null
+++ b/src/components/ui/dialog/DialogDescription.vue
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/dialog/DialogFooter.vue b/src/components/ui/dialog/DialogFooter.vue
new file mode 100644
index 0000000..eee552a
--- /dev/null
+++ b/src/components/ui/dialog/DialogFooter.vue
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/dialog/DialogHeader.vue b/src/components/ui/dialog/DialogHeader.vue
new file mode 100644
index 0000000..91194b0
--- /dev/null
+++ b/src/components/ui/dialog/DialogHeader.vue
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/dialog/DialogOverlay.vue b/src/components/ui/dialog/DialogOverlay.vue
new file mode 100644
index 0000000..e47c602
--- /dev/null
+++ b/src/components/ui/dialog/DialogOverlay.vue
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/dialog/DialogScrollContent.vue b/src/components/ui/dialog/DialogScrollContent.vue
new file mode 100644
index 0000000..95cbf42
--- /dev/null
+++ b/src/components/ui/dialog/DialogScrollContent.vue
@@ -0,0 +1,71 @@
+
+
+
+
+
+ {
+ const originalEvent = event.detail.originalEvent;
+ const target = originalEvent.target;
+ if (
+ originalEvent.offsetX > target.clientWidth ||
+ originalEvent.offsetY > target.clientHeight
+ ) {
+ event.preventDefault();
+ }
+ }
+ "
+ >
+
+
+
+
+ Close
+
+
+
+
+
diff --git a/src/components/ui/dialog/DialogTitle.vue b/src/components/ui/dialog/DialogTitle.vue
new file mode 100644
index 0000000..49cda6f
--- /dev/null
+++ b/src/components/ui/dialog/DialogTitle.vue
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/dialog/DialogTrigger.vue b/src/components/ui/dialog/DialogTrigger.vue
new file mode 100644
index 0000000..2938e30
--- /dev/null
+++ b/src/components/ui/dialog/DialogTrigger.vue
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/dialog/index.js b/src/components/ui/dialog/index.js
new file mode 100644
index 0000000..6c411de
--- /dev/null
+++ b/src/components/ui/dialog/index.js
@@ -0,0 +1,10 @@
+export { default as Dialog } from "./Dialog.vue";
+export { default as DialogClose } from "./DialogClose.vue";
+export { default as DialogContent } from "./DialogContent.vue";
+export { default as DialogDescription } from "./DialogDescription.vue";
+export { default as DialogFooter } from "./DialogFooter.vue";
+export { default as DialogHeader } from "./DialogHeader.vue";
+export { default as DialogOverlay } from "./DialogOverlay.vue";
+export { default as DialogScrollContent } from "./DialogScrollContent.vue";
+export { default as DialogTitle } from "./DialogTitle.vue";
+export { default as DialogTrigger } from "./DialogTrigger.vue";
diff --git a/src/components/ui/dropdown-menu/DropdownItem.vue b/src/components/ui/dropdown-menu/DropdownItem.vue
new file mode 100644
index 0000000..48e8abf
--- /dev/null
+++ b/src/components/ui/dropdown-menu/DropdownItem.vue
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/components/ui/dropdown-menu/DropdownMenu.vue b/src/components/ui/dropdown-menu/DropdownMenu.vue
new file mode 100644
index 0000000..86333fb
--- /dev/null
+++ b/src/components/ui/dropdown-menu/DropdownMenu.vue
@@ -0,0 +1,62 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/src/components/ui/input/Input.vue b/src/components/ui/input/Input.vue
new file mode 100644
index 0000000..dc16a12
--- /dev/null
+++ b/src/components/ui/input/Input.vue
@@ -0,0 +1,32 @@
+
+
+
+
+
diff --git a/src/components/ui/input/index.js b/src/components/ui/input/index.js
new file mode 100644
index 0000000..110f046
--- /dev/null
+++ b/src/components/ui/input/index.js
@@ -0,0 +1 @@
+export { default as Input } from "./Input.vue";
diff --git a/src/components/ui/label/Label.vue b/src/components/ui/label/Label.vue
new file mode 100644
index 0000000..b20aec0
--- /dev/null
+++ b/src/components/ui/label/Label.vue
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/label/index.js b/src/components/ui/label/index.js
new file mode 100644
index 0000000..38eaa35
--- /dev/null
+++ b/src/components/ui/label/index.js
@@ -0,0 +1 @@
+export { default as Label } from "./Label.vue";
diff --git a/src/components/ui/select/Select.vue b/src/components/ui/select/Select.vue
new file mode 100644
index 0000000..b2cab62
--- /dev/null
+++ b/src/components/ui/select/Select.vue
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/select/SelectContent.vue b/src/components/ui/select/SelectContent.vue
new file mode 100644
index 0000000..459a179
--- /dev/null
+++ b/src/components/ui/select/SelectContent.vue
@@ -0,0 +1,81 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/ui/select/SelectGroup.vue b/src/components/ui/select/SelectGroup.vue
new file mode 100644
index 0000000..eecc39b
--- /dev/null
+++ b/src/components/ui/select/SelectGroup.vue
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/select/SelectItem.vue b/src/components/ui/select/SelectItem.vue
new file mode 100644
index 0000000..18edeca
--- /dev/null
+++ b/src/components/ui/select/SelectItem.vue
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/ui/select/SelectItemText.vue b/src/components/ui/select/SelectItemText.vue
new file mode 100644
index 0000000..eb87548
--- /dev/null
+++ b/src/components/ui/select/SelectItemText.vue
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/select/SelectLabel.vue b/src/components/ui/select/SelectLabel.vue
new file mode 100644
index 0000000..adb66ad
--- /dev/null
+++ b/src/components/ui/select/SelectLabel.vue
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/select/SelectScrollDownButton.vue b/src/components/ui/select/SelectScrollDownButton.vue
new file mode 100644
index 0000000..6932136
--- /dev/null
+++ b/src/components/ui/select/SelectScrollDownButton.vue
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/components/ui/select/SelectScrollUpButton.vue b/src/components/ui/select/SelectScrollUpButton.vue
new file mode 100644
index 0000000..c7a493f
--- /dev/null
+++ b/src/components/ui/select/SelectScrollUpButton.vue
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/components/ui/select/SelectSeparator.vue b/src/components/ui/select/SelectSeparator.vue
new file mode 100644
index 0000000..34f2f59
--- /dev/null
+++ b/src/components/ui/select/SelectSeparator.vue
@@ -0,0 +1,21 @@
+
+
+
+
+
diff --git a/src/components/ui/select/SelectTrigger.vue b/src/components/ui/select/SelectTrigger.vue
new file mode 100644
index 0000000..4bd93a8
--- /dev/null
+++ b/src/components/ui/select/SelectTrigger.vue
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/ui/select/SelectValue.vue b/src/components/ui/select/SelectValue.vue
new file mode 100644
index 0000000..db9807f
--- /dev/null
+++ b/src/components/ui/select/SelectValue.vue
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/select/index.js b/src/components/ui/select/index.js
new file mode 100644
index 0000000..d911c4e
--- /dev/null
+++ b/src/components/ui/select/index.js
@@ -0,0 +1,11 @@
+export { default as Select } from "./Select.vue";
+export { default as SelectContent } from "./SelectContent.vue";
+export { default as SelectGroup } from "./SelectGroup.vue";
+export { default as SelectItem } from "./SelectItem.vue";
+export { default as SelectItemText } from "./SelectItemText.vue";
+export { default as SelectLabel } from "./SelectLabel.vue";
+export { default as SelectScrollDownButton } from "./SelectScrollDownButton.vue";
+export { default as SelectScrollUpButton } from "./SelectScrollUpButton.vue";
+export { default as SelectSeparator } from "./SelectSeparator.vue";
+export { default as SelectTrigger } from "./SelectTrigger.vue";
+export { default as SelectValue } from "./SelectValue.vue";
diff --git a/src/components/ui/separator/Separator.vue b/src/components/ui/separator/Separator.vue
new file mode 100644
index 0000000..680a1d2
--- /dev/null
+++ b/src/components/ui/separator/Separator.vue
@@ -0,0 +1,28 @@
+
+
+
+
+
diff --git a/src/components/ui/separator/index.js b/src/components/ui/separator/index.js
new file mode 100644
index 0000000..aae7f1a
--- /dev/null
+++ b/src/components/ui/separator/index.js
@@ -0,0 +1 @@
+export { default as Separator } from "./Separator.vue";
diff --git a/src/components/ui/sonner/Sonner.vue b/src/components/ui/sonner/Sonner.vue
new file mode 100644
index 0000000..8802e9a
--- /dev/null
+++ b/src/components/ui/sonner/Sonner.vue
@@ -0,0 +1,39 @@
+
+
+
+
+
diff --git a/src/components/ui/sonner/index.js b/src/components/ui/sonner/index.js
new file mode 100644
index 0000000..39a59dd
--- /dev/null
+++ b/src/components/ui/sonner/index.js
@@ -0,0 +1 @@
+export { default as Toaster } from "./Sonner.vue";
diff --git a/src/components/ui/table/Table.vue b/src/components/ui/table/Table.vue
new file mode 100644
index 0000000..71bd0a9
--- /dev/null
+++ b/src/components/ui/table/Table.vue
@@ -0,0 +1,18 @@
+
+
+
+
+
diff --git a/src/components/ui/table/TableBody.vue b/src/components/ui/table/TableBody.vue
new file mode 100644
index 0000000..3cfac53
--- /dev/null
+++ b/src/components/ui/table/TableBody.vue
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/table/TableCaption.vue b/src/components/ui/table/TableCaption.vue
new file mode 100644
index 0000000..2a4488e
--- /dev/null
+++ b/src/components/ui/table/TableCaption.vue
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/table/TableCell.vue b/src/components/ui/table/TableCell.vue
new file mode 100644
index 0000000..aa0faef
--- /dev/null
+++ b/src/components/ui/table/TableCell.vue
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/table/TableEmpty.vue b/src/components/ui/table/TableEmpty.vue
new file mode 100644
index 0000000..0a94d54
--- /dev/null
+++ b/src/components/ui/table/TableEmpty.vue
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/ui/table/TableFooter.vue b/src/components/ui/table/TableFooter.vue
new file mode 100644
index 0000000..89c5ac1
--- /dev/null
+++ b/src/components/ui/table/TableFooter.vue
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/table/TableHead.vue b/src/components/ui/table/TableHead.vue
new file mode 100644
index 0000000..1e8dad9
--- /dev/null
+++ b/src/components/ui/table/TableHead.vue
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/table/TableHeader.vue b/src/components/ui/table/TableHeader.vue
new file mode 100644
index 0000000..616e4dc
--- /dev/null
+++ b/src/components/ui/table/TableHeader.vue
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/table/TableRow.vue b/src/components/ui/table/TableRow.vue
new file mode 100644
index 0000000..85f521c
--- /dev/null
+++ b/src/components/ui/table/TableRow.vue
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/table/index.js b/src/components/ui/table/index.js
new file mode 100644
index 0000000..0afab4c
--- /dev/null
+++ b/src/components/ui/table/index.js
@@ -0,0 +1,9 @@
+export { default as Table } from "./Table.vue";
+export { default as TableBody } from "./TableBody.vue";
+export { default as TableCaption } from "./TableCaption.vue";
+export { default as TableCell } from "./TableCell.vue";
+export { default as TableEmpty } from "./TableEmpty.vue";
+export { default as TableFooter } from "./TableFooter.vue";
+export { default as TableHead } from "./TableHead.vue";
+export { default as TableHeader } from "./TableHeader.vue";
+export { default as TableRow } from "./TableRow.vue";
diff --git a/src/components/ui/table/utils.js b/src/components/ui/table/utils.js
new file mode 100644
index 0000000..ee61875
--- /dev/null
+++ b/src/components/ui/table/utils.js
@@ -0,0 +1,7 @@
+import { isFunction } from "@tanstack/vue-table";
+
+export function valueUpdater(updaterOrValue, ref) {
+ ref.value = isFunction(updaterOrValue)
+ ? updaterOrValue(ref.value)
+ : updaterOrValue;
+}
diff --git a/src/components/ui/tabs/Tabs.vue b/src/components/ui/tabs/Tabs.vue
new file mode 100644
index 0000000..31ba139
--- /dev/null
+++ b/src/components/ui/tabs/Tabs.vue
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/tabs/TabsContent.vue b/src/components/ui/tabs/TabsContent.vue
new file mode 100644
index 0000000..b9331fd
--- /dev/null
+++ b/src/components/ui/tabs/TabsContent.vue
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/tabs/TabsList.vue b/src/components/ui/tabs/TabsList.vue
new file mode 100644
index 0000000..791ab3d
--- /dev/null
+++ b/src/components/ui/tabs/TabsList.vue
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/tabs/TabsTrigger.vue b/src/components/ui/tabs/TabsTrigger.vue
new file mode 100644
index 0000000..03e10df
--- /dev/null
+++ b/src/components/ui/tabs/TabsTrigger.vue
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/tabs/index.js b/src/components/ui/tabs/index.js
new file mode 100644
index 0000000..3b3741b
--- /dev/null
+++ b/src/components/ui/tabs/index.js
@@ -0,0 +1,4 @@
+export { default as Tabs } from "./Tabs.vue";
+export { default as TabsContent } from "./TabsContent.vue";
+export { default as TabsList } from "./TabsList.vue";
+export { default as TabsTrigger } from "./TabsTrigger.vue";
diff --git a/src/composables/useOAuthCallback.js b/src/composables/useOAuthCallback.js
new file mode 100644
index 0000000..f01d598
--- /dev/null
+++ b/src/composables/useOAuthCallback.js
@@ -0,0 +1,126 @@
+import { onMounted, onUnmounted } from 'vue'
+import { useRoute, useRouter } from 'vue-router'
+import { useAccountStore } from '@/stores/account'
+import { toast } from 'vue-sonner'
+
+/**
+ * 处理OAuth回调
+ * 检查URL参数中是否有OAuth回调信息
+ */
+export function useOAuthCallback() {
+ const route = useRoute()
+ const router = useRouter()
+ const accountStore = useAccountStore()
+
+ const handleOAuthCallback = async () => {
+ const { token, provider, success, error } = route.query
+
+ // 检查是否是OAuth回调
+ if (!success && !error) {
+ return
+ }
+
+ // 处理成功回调
+ if (success === 'true' && token) {
+ try {
+ // 保存token到localStorage
+ localStorage.setItem('auth_token', token)
+ localStorage.setItem('auth_provider', provider)
+
+ // 登录到store
+ await accountStore.login(token)
+
+ // 显示成功提示
+ toast.success('登录成功', {
+ description: `已通过 ${provider} 登录`
+ })
+
+ // 清除URL参数
+ router.replace({ query: {} })
+
+ // 触发storage事件,通知其他窗口
+ window.dispatchEvent(new StorageEvent('storage', {
+ key: 'auth_token',
+ newValue: token,
+ url: window.location.href
+ }))
+
+ // 如果是在新窗口中打开的OAuth回调,自动关闭窗口
+ if (window.opener) {
+ // 通知父窗口登录成功
+ window.opener.postMessage({
+ type: 'oauth_success',
+ token,
+ provider
+ }, window.location.origin)
+
+ // 延迟关闭窗口,确保消息已发送
+ setTimeout(() => {
+ window.close()
+ }, 1000)
+ }
+
+ } catch (err) {
+ toast.error('登录失败', {
+ description: err.message || '处理登录信息时出错'
+ })
+ }
+ }
+
+ // 处理错误回调
+ if (success === 'false' || error) {
+ const errorMessages = {
+ 'invalid_state': 'State验证失败,可能存在安全风险',
+ 'access_denied': '用户拒绝了授权请求',
+ 'temporarily_unavailable': '服务暂时不可用,请稍后重试'
+ }
+
+ const errorMsg = errorMessages[error] || error || '登录过程中出现错误'
+
+ toast.error('登录失败', {
+ description: errorMsg
+ })
+
+ // 清除URL参数
+ router.replace({ query: {} })
+
+ // 如果是在新窗口中打开的OAuth回调,自动关闭窗口
+ if (window.opener) {
+ // 通知父窗口登录失败
+ window.opener.postMessage({
+ type: 'oauth_error',
+ error: errorMsg
+ }, window.location.origin)
+
+ // 延迟关闭窗口
+ setTimeout(() => {
+ window.close()
+ }, 1000)
+ }
+ }
+ }
+
+ onMounted(() => {
+ handleOAuthCallback()
+ })
+
+ // 监听storage事件,处理其他标签页的登录
+ const handleStorageChange = (e) => {
+ if (e.key === 'auth_token' && e.newValue) {
+ // 其他标签页已登录,刷新当前页面的状态
+ accountStore.login(e.newValue)
+ }
+ }
+
+ onMounted(() => {
+ window.addEventListener('storage', handleStorageChange)
+ })
+
+ onUnmounted(() => {
+ window.removeEventListener('storage', handleStorageChange)
+ })
+
+ return {
+ handleOAuthCallback
+ }
+}
\ No newline at end of file
diff --git a/src/lib/api.js b/src/lib/api.js
new file mode 100644
index 0000000..cc03606
--- /dev/null
+++ b/src/lib/api.js
@@ -0,0 +1,533 @@
+const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:3030'
+const SITE_KEY = import.meta.env.VITE_SITE_KEY || ''
+
+class ApiClient {
+ constructor(baseUrl, siteKey) {
+ this.baseUrl = baseUrl
+ this.siteKey = siteKey
+ }
+
+ async fetch(endpoint, options = {}) {
+ const headers = {
+ 'Content-Type': 'application/json',
+ 'x-site-key': this.siteKey,
+ ...options.headers,
+ }
+
+ const response = await fetch(`${this.baseUrl}${endpoint}`, {
+ ...options,
+ headers,
+ })
+
+ if (!response.ok) {
+ const error = await response.json().catch(() => ({ message: 'Unknown error' }))
+ throw new Error(error.message || `HTTP ${response.status}`)
+ }
+
+ if (response.status === 204) {
+ return {}
+ }
+
+ return response.json()
+ }
+
+ // 带认证的fetch
+ async authenticatedFetch(endpoint, options = {}, token = null) {
+ const headers = {
+ ...options.headers,
+ }
+
+ // 如果提供了token,添加Authorization头
+ if (token) {
+ headers['Authorization'] = `Bearer ${token}`
+ }
+
+ return this.fetch(endpoint, {
+ ...options,
+ headers,
+ })
+ }
+
+ // 应用相关 API
+ async getApps(params = {}) {
+ const query = new URLSearchParams(params).toString()
+ return this.fetch(`/apps${query ? `?${query}` : ''}`)
+ }
+
+ async getApp(appId) {
+ return this.fetch(`/apps/info/${appId}`)
+ }
+
+ async getAppInstallations(appId, deviceUuid, params = {}) {
+ const query = new URLSearchParams(params).toString()
+ return this.fetch(`/apps/info/${appId}/device-installations${query ? `?${query}` : ''}`, {
+ headers: {
+ 'x-device-uuid': deviceUuid,
+ },
+ })
+ }
+
+ // Token 管理 API
+ async getDeviceTokens(deviceUuid, options = {}) {
+ const params = new URLSearchParams({
+ uuid: deviceUuid,
+ });
+
+ return this.fetch(`/apps/tokens?${params}`);
+ }
+
+ async revokeToken(targetToken, authOptions = {}) {
+ const { deviceUuid, password, usePathParam = true, bearerToken } = authOptions;
+
+ if (usePathParam) {
+ // 使用路径参数方式 (推荐)
+ const headers = {};
+
+ if (bearerToken) {
+ headers['Authorization'] = `Bearer ${bearerToken}`;
+ } else if (deviceUuid) {
+ headers['x-device-uuid'] = deviceUuid;
+ if (password) {
+ headers['x-device-password'] = password;
+ }
+ }
+
+ return this.fetch(`/apps/tokens/${targetToken}`, {
+ method: 'DELETE',
+ headers,
+ });
+ } else {
+ // 使用查询参数方式 (向后兼容)
+ const params = new URLSearchParams({ token: targetToken });
+ const headers = {};
+
+ if (bearerToken) {
+ headers['Authorization'] = `Bearer ${bearerToken}`;
+ } else if (deviceUuid) {
+ headers['x-device-uuid'] = deviceUuid;
+ if (password) {
+ headers['x-device-password'] = password;
+ }
+ }
+
+ return this.fetch(`/apps/tokens?${params}`, {
+ method: 'DELETE',
+ headers,
+ });
+ }
+ }
+
+ // 应用安装接口 (对应后端的 /apps/devices/:uuid/install/:appId)
+ async authorizeApp(appId, deviceUuid, options = {}) {
+ const { password, note, token } = options;
+
+ const headers = {
+ 'x-device-uuid': deviceUuid,
+ };
+
+
+ if (token) {
+ headers['Authorization'] = `Bearer ${token}`;
+ }
+
+ // 使用新的安装接口
+ return this.fetch(`/apps/devices/${deviceUuid}/install/${appId}?password=${password}`, {
+ method: 'POST',
+ headers,
+ body: JSON.stringify({ note: note || '应用授权' }),
+ });
+ }
+
+ // 设备级别的应用卸载,使用新的 uninstall 接口
+ async revokeDeviceToken(deviceUuid, installId, password = null, token = null) {
+ const params = new URLSearchParams({ uuid: deviceUuid });
+ const headers = {};
+
+ if (password) {
+ params.set('password', password);
+ }
+
+ if (token) {
+ headers['Authorization'] = `Bearer ${token}`;
+ }
+
+ return this.fetch(`/apps/devices/${deviceUuid}/uninstall/${installId}?${params}`, {
+ method: 'DELETE',
+ headers,
+ });
+ }
+
+ // 设备密码管理 API
+ async setDevicePassword(deviceUuid, data, token = null) {
+ const { newPassword, currentPassword, passwordHint } = data;
+
+ // 检查设备是否已设置密码
+ const deviceInfo = await this.getDeviceInfo(deviceUuid);
+ const hasPassword = deviceInfo.hasPassword;
+
+ if (hasPassword) {
+ // 使用PUT修改密码
+ const params = new URLSearchParams();
+ params.set('uuid', deviceUuid);
+ params.set('newPassword', newPassword);
+ if (currentPassword) {
+ params.set('currentPassword', currentPassword);
+ }
+ if (passwordHint !== undefined) {
+ params.set('passwordHint', passwordHint);
+ }
+
+ const headers = {};
+ if (token) {
+ headers['Authorization'] = `Bearer ${token}`;
+ }
+
+ return this.fetch(`/devices/${deviceUuid}/password?${params}`, {
+ method: 'PUT',
+ headers,
+ });
+ } else {
+ // 使用POST初次设置密码
+ const params = new URLSearchParams();
+ params.set('newPassword', newPassword);
+ if (passwordHint !== undefined) {
+ params.set('passwordHint', passwordHint);
+ }
+
+ return this.fetch(`/devices/${deviceUuid}/password?${params}`, {
+ method: 'POST',
+ });
+ }
+ }
+
+ async deleteDevicePassword(deviceUuid, password, token = null) {
+ const params = new URLSearchParams({ uuid: deviceUuid });
+ const headers = {};
+
+ // 如果提供了账户token,使用JWT认证
+ if (token) {
+ headers['Authorization'] = `Bearer ${token}`;
+ } else if (password) {
+ params.set('password', password);
+ }
+
+ return this.fetch(`/devices/${deviceUuid}/password?${params}`, {
+ method: 'DELETE',
+ headers,
+ });
+ }
+
+ async setDevicePasswordHint(deviceUuid, hint, password = null, token = null) {
+ return this.authenticatedFetch(`/devices/${deviceUuid}/password-hint`, {
+ method: 'PUT',
+ body: JSON.stringify({ hint, password }),
+ }, token)
+ }
+
+ async getDevicePasswordHint(deviceUuid) {
+ return this.fetch(`/devices/${deviceUuid}/password-hint`)
+ }
+
+ // 设备授权相关 API
+ async bindDeviceCode(deviceCode, token) {
+ return this.fetch('/auth/device/bind', {
+ method: 'POST',
+ body: JSON.stringify({ device_code: deviceCode, token }),
+ })
+ }
+
+ async getDeviceCodeStatus(deviceCode) {
+ return this.fetch(`/auth/device/status?device_code=${deviceCode}`)
+ }
+
+ // KV 存储管理 API
+ async listKVItems(token, params = {}) {
+ const query = new URLSearchParams(params).toString()
+ return this.fetch(`/kv${query ? `?${query}` : ''}`, {
+ headers: { 'x-app-token': token }
+ })
+ }
+
+ async getKVItem(token, key) {
+ return this.fetch(`/kv/${encodeURIComponent(key)}`, {
+ headers: { 'x-app-token': token }
+ })
+ }
+
+ async setKVItem(token, key, value) {
+ return this.fetch(`/kv/${encodeURIComponent(key)}`, {
+ method: 'POST',
+ headers: { 'x-app-token': token },
+ body: JSON.stringify(value),
+ })
+ }
+
+ async deleteKVItem(token, key) {
+ return this.fetch(`/kv/${encodeURIComponent(key)}`, {
+ method: 'DELETE',
+ headers: { 'x-app-token': token }
+ })
+ }
+
+ async getKVKeys(token, pattern = '*') {
+ return this.fetch(`/kv/_keys?pattern=${encodeURIComponent(pattern)}`, {
+ headers: { 'x-app-token': token }
+ })
+ }
+
+ // 设备信息 API
+ async getDeviceInfo(deviceUuid) {
+ return this.fetch(`/devices/${deviceUuid}`)
+ }
+
+ // 获取设备应用列表 API (公开接口,无需认证)
+ async getDeviceApps(deviceUuid) {
+ return this.fetch(`/apps/devices/${deviceUuid}/apps`)
+ }
+
+ // 密码提示管理 API
+ async getPasswordHint(deviceUuid) {
+ try {
+ const response = await this.fetch(`/devices/${deviceUuid}`)
+ return { hint: response.device?.passwordHint || '' }
+ } catch (error) {
+ // 如果接口不存在,返回空提示
+ return { hint: '' }
+ }
+ }
+
+ async setPasswordHint(deviceUuid, hint, password) {
+ try {
+ return await this.fetch(`/devices/${deviceUuid}/password-hint?password=${encodeURIComponent(password)}`, {
+ method: 'PUT',
+ headers: {
+ 'x-device-uuid': deviceUuid,
+ },
+ body: JSON.stringify({ passwordHint: hint }),
+ })
+ } catch (error) {
+ // 如果接口不存在,忽略错误
+ console.log('Password hint API not available')
+ return { success: false }
+ }
+ }
+
+ // 账户相关 API
+ async getOAuthProviders() {
+ return this.fetch('/accounts/oauth/providers')
+ }
+
+ async getAccountProfile(token) {
+ return this.fetch('/accounts/profile', {
+ headers: { 'Authorization': `Bearer ${token}` }
+ })
+ }
+
+ async getAccountDevices(token) {
+ return this.fetch('/accounts/devices', {
+ headers: { 'Authorization': `Bearer ${token}` }
+ })
+ }
+
+ async bindDevice(token, deviceUuid) {
+ return this.fetch('/accounts/devices/bind', {
+ method: 'POST',
+ headers: { 'Authorization': `Bearer ${token}` },
+ body: JSON.stringify({ uuid: deviceUuid }),
+ })
+ }
+
+ async unbindDevice(token, deviceUuid) {
+ return this.fetch('/accounts/devices/unbind', {
+ method: 'POST',
+ headers: { 'Authorization': `Bearer ${token}` },
+ body: JSON.stringify({ uuid: deviceUuid }),
+ })
+ }
+
+ async getDeviceAccount(deviceUuid) {
+ return this.fetch(`/accounts/device/${deviceUuid}/account`)
+ }
+
+ // 绑定设备到当前账户
+ async bindDeviceToAccount(token, deviceUuid) {
+ return this.authenticatedFetch('/accounts/devices/bind', {
+ method: 'POST',
+ body: JSON.stringify({ uuid: deviceUuid }),
+ }, token)
+ }
+
+ // 解绑设备
+ async unbindDeviceFromAccount(token, deviceUuid) {
+ return this.authenticatedFetch('/accounts/devices/unbind', {
+ method: 'POST',
+ body: JSON.stringify({ uuid: deviceUuid }),
+ }, token)
+ }
+
+ // 批量解绑设备
+ async batchUnbindDevices(token, deviceUuids) {
+ return this.authenticatedFetch('/accounts/devices/unbind', {
+ method: 'POST',
+ body: JSON.stringify({ uuids: deviceUuids }),
+ }, token)
+ }
+
+ // 设备名称管理 API
+ async setDeviceName(deviceUuid, name, password = null, token = null) {
+ const headers = {
+ 'x-device-uuid': deviceUuid,
+ };
+ if (token) {
+ headers['Authorization'] = `Bearer ${token}`;
+ }
+ if (password) {
+ headers['x-device-password'] = password;
+ }
+
+ return this.fetch(`/devices/${deviceUuid}/name`, {
+ method: 'PUT',
+ headers,
+ body: JSON.stringify({ name }),
+ });
+ }
+
+ // 修改设备密码 API
+ async updateDevicePassword(deviceUuid, currentPassword, newPassword, passwordHint = null, token = null) {
+ const headers = {
+ 'x-device-uuid': deviceUuid,
+ };
+
+ // 如果提供了账户token,使用JWT认证(账户拥有者无需当前密码)
+ if (token) {
+ headers['Authorization'] = `Bearer ${token}`;
+ } else if (currentPassword) {
+ headers['x-device-password'] = currentPassword;
+ }
+
+ const body = { newPassword, passwordHint };
+ // 只有在非账户拥有者时才需要发送当前密码
+ if (!token && currentPassword) {
+ body.currentPassword = currentPassword;
+ }
+
+ return this.fetch(`/devices/${deviceUuid}/password`, {
+ method: 'PUT',
+ headers,
+ body: JSON.stringify(body),
+ });
+ }
+
+ // 验证设备密码 API
+ async verifyDevicePassword(deviceUuid, password) {
+ return this.fetch(`/devices/${deviceUuid}`, {
+ method: 'GET',
+ headers: {
+ 'x-device-uuid': deviceUuid,
+ 'x-device-password': password,
+ },
+ });
+ }
+
+ // 设备注册 API
+ async registerDevice(uuid, deviceName, token = null) {
+ return this.authenticatedFetch('/devices', {
+ method: 'POST',
+ body: JSON.stringify({ uuid, deviceName }),
+ }, token)
+ }
+
+ // 账户拥有者重置设备密码 API
+ async resetDevicePasswordAsOwner(deviceUuid, newPassword, passwordHint = null, token) {
+ return this.fetch(`/devices/${deviceUuid}/password`, {
+ method: 'PUT',
+ headers: {
+ 'Authorization': `Bearer ${token}`,
+ 'x-device-uuid': deviceUuid,
+ },
+ body: JSON.stringify({ newPassword, passwordHint }),
+ });
+ }
+
+ // 兼容性方法 - 保持旧的API调用方式
+ async getTokens(deviceUuid, options = {}) {
+ return this.getDeviceTokens(deviceUuid, options);
+ }
+
+ async deleteToken(targetToken, deviceUuid = null) {
+ // 向后兼容的删除方法
+ return this.revokeToken(targetToken, { deviceUuid, usePathParam: true });
+ }
+
+ // 便捷方法:使用设备UUID和密码删除token
+ async revokeTokenByDevice(targetToken, deviceUuid, password = null) {
+ return this.revokeToken(targetToken, {
+ deviceUuid,
+ password,
+ usePathParam: true
+ });
+ }
+
+ // 便捷方法:使用账户token删除token
+ async revokeTokenByAccount(targetToken, bearerToken) {
+ return this.revokeToken(targetToken, {
+ bearerToken,
+ usePathParam: true
+ });
+ }
+
+ // 便捷方法:应用自撤销
+ async revokeOwnToken(targetToken) {
+ return this.fetch(`/apps/tokens/${targetToken}`, {
+ method: 'DELETE',
+ headers: {
+ 'x-app-token': targetToken,
+ },
+ });
+ }
+
+ // 新的便捷方法
+ async getTokensWithAuth(authType, authValue, options = {}) {
+ const headers = {};
+ const params = new URLSearchParams(options);
+
+ switch (authType) {
+ case 'uuid':
+ headers['x-device-uuid'] = authValue;
+ params.set('uuid', authValue);
+ break;
+ case 'token':
+ headers['x-app-token'] = authValue;
+ break;
+ case 'bearer':
+ headers['Authorization'] = `Bearer ${authValue}`;
+ break;
+ }
+
+ return this.fetch(`/apps/tokens?${params}`, { headers });
+ }
+
+ async revokeTokenWithAuth(targetToken, authType, authValue) {
+ const headers = {};
+ const params = new URLSearchParams({ token: targetToken });
+
+ switch (authType) {
+ case 'uuid':
+ headers['x-device-uuid'] = authValue;
+ break;
+ case 'token':
+ headers['x-app-token'] = authValue;
+ break;
+ case 'bearer':
+ headers['Authorization'] = `Bearer ${authValue}`;
+ break;
+ }
+
+ return this.fetch(`/apps/tokens?${params}`, {
+ method: 'DELETE',
+ headers,
+ });
+ }
+}
+
+export const apiClient = new ApiClient(API_BASE_URL, SITE_KEY)
diff --git a/src/lib/axios.js b/src/lib/axios.js
new file mode 100644
index 0000000..67a6b02
--- /dev/null
+++ b/src/lib/axios.js
@@ -0,0 +1,37 @@
+import axios from 'axios'
+
+const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:3030'
+const SITE_KEY = import.meta.env.VITE_SITE_KEY || ''
+
+// 创建 axios 实例
+const axiosInstance = axios.create({
+ baseURL: API_BASE_URL,
+ timeout: 30000,
+ headers: {
+ 'Content-Type': 'application/json',
+ 'x-site-key': SITE_KEY,
+ },
+})
+
+// 请求拦截器
+axiosInstance.interceptors.request.use(
+ (config) => {
+ return config
+ },
+ (error) => {
+ return Promise.reject(error)
+ }
+)
+
+// 响应拦截器
+axiosInstance.interceptors.response.use(
+ (response) => {
+ return response.data
+ },
+ (error) => {
+ const message = error.response?.data?.message || error.message || 'Unknown error'
+ return Promise.reject(new Error(message))
+ }
+)
+
+export default axiosInstance
diff --git a/src/lib/deviceStore.js b/src/lib/deviceStore.js
new file mode 100644
index 0000000..7877e02
--- /dev/null
+++ b/src/lib/deviceStore.js
@@ -0,0 +1,191 @@
+// 生成 UUID v4
+export function generateUUID() {
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
+ const r = Math.random() * 16 | 0
+ const v = c === 'x' ? r : (r & 0x3 | 0x8)
+ return v.toString(16)
+ })
+}
+
+// 设备 UUID 管理 - 使用多种缓存策略确保UUID不丢失
+export const deviceStore = {
+ // 存储键名
+ STORAGE_KEY: 'device_uuid',
+ BACKUP_KEY: 'device_uuid_backup',
+ SESSION_KEY: 'device_uuid_session',
+
+ // 获取当前设备 UUID(从多个存储位置尝试读取)
+ getDeviceUuid() {
+ // 1. 首先从 localStorage 获取
+ let uuid = localStorage.getItem(this.STORAGE_KEY)
+
+ // 2. 如果没有,尝试从备份位置获取
+ if (!uuid) {
+ uuid = localStorage.getItem(this.BACKUP_KEY)
+ if (uuid) {
+ // 恢复到主存储位置
+ this.setDeviceUuid(uuid)
+ }
+ }
+
+ // 3. 如果还没有,尝试从 sessionStorage 获取
+ if (!uuid) {
+ uuid = sessionStorage.getItem(this.SESSION_KEY)
+ if (uuid) {
+ // 恢复到主存储位置
+ this.setDeviceUuid(uuid)
+ }
+ }
+
+ // 4. 如果还没有,尝试从 cookie 获取(如果有的话)
+ if (!uuid) {
+ uuid = this.getFromCookie()
+ if (uuid) {
+ // 恢复到所有存储位置
+ this.setDeviceUuid(uuid)
+ }
+ }
+
+ return uuid
+ },
+
+ // 设置设备 UUID(同时存储到多个位置)
+ setDeviceUuid(uuid) {
+ // 1. 存储到 localStorage 主位置
+ localStorage.setItem(this.STORAGE_KEY, uuid)
+
+ // 2. 存储到备份位置
+ localStorage.setItem(this.BACKUP_KEY, uuid)
+
+ // 3. 存储到 sessionStorage
+ sessionStorage.setItem(this.SESSION_KEY, uuid)
+
+ // 4. 存储到 cookie(设置较长的过期时间)
+ this.saveToCookie(uuid)
+
+ // 5. 尝试存储到 IndexedDB(异步)
+ this.saveToIndexedDB(uuid)
+ },
+
+ // 生成并保存新的设备 UUID
+ generateAndSave() {
+ const uuid = generateUUID()
+ this.setDeviceUuid(uuid)
+ return uuid
+ },
+
+ // 获取或生成设备 UUID
+ getOrGenerate() {
+ let uuid = this.getDeviceUuid()
+ if (!uuid) {
+ uuid = this.generateAndSave()
+ } else {
+ // 确保UUID被保存到所有位置
+ this.setDeviceUuid(uuid)
+ }
+ return uuid
+ },
+
+ // 清除设备 UUID(从所有存储位置清除)
+ clear() {
+ localStorage.removeItem(this.STORAGE_KEY)
+ localStorage.removeItem(this.BACKUP_KEY)
+ sessionStorage.removeItem(this.SESSION_KEY)
+ this.clearCookie()
+ this.clearIndexedDB()
+ },
+
+ // Cookie 操作
+ saveToCookie(uuid) {
+ try {
+ const expires = new Date()
+ expires.setFullYear(expires.getFullYear() + 10) // 10年过期
+ document.cookie = `device_uuid=${uuid}; expires=${expires.toUTCString()}; path=/; SameSite=Strict`
+ } catch (e) {
+ console.log('Failed to save UUID to cookie:', e)
+ }
+ },
+
+ getFromCookie() {
+ try {
+ const match = document.cookie.match(/(?:^|; )device_uuid=([^;]*)/)
+ return match ? match[1] : null
+ } catch (e) {
+ console.log('Failed to get UUID from cookie:', e)
+ return null
+ }
+ },
+
+ clearCookie() {
+ try {
+ document.cookie = 'device_uuid=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;'
+ } catch (e) {
+ console.log('Failed to clear UUID cookie:', e)
+ }
+ },
+
+ // IndexedDB 操作(异步,作为额外的备份)
+ async saveToIndexedDB(uuid) {
+ try {
+ const db = await this.openDB()
+ const transaction = db.transaction(['device'], 'readwrite')
+ const store = transaction.objectStore('device')
+ await store.put({ id: 'uuid', value: uuid })
+ } catch (e) {
+ console.log('Failed to save UUID to IndexedDB:', e)
+ }
+ },
+
+ async getFromIndexedDB() {
+ try {
+ const db = await this.openDB()
+ const transaction = db.transaction(['device'], 'readonly')
+ const store = transaction.objectStore('device')
+ const result = await store.get('uuid')
+ return result?.value || null
+ } catch (e) {
+ console.log('Failed to get UUID from IndexedDB:', e)
+ return null
+ }
+ },
+
+ async clearIndexedDB() {
+ try {
+ const db = await this.openDB()
+ const transaction = db.transaction(['device'], 'readwrite')
+ const store = transaction.objectStore('device')
+ await store.delete('uuid')
+ } catch (e) {
+ console.log('Failed to clear UUID from IndexedDB:', e)
+ }
+ },
+
+ openDB() {
+ return new Promise((resolve, reject) => {
+ const request = indexedDB.open('ClassworksKV', 1)
+
+ request.onerror = () => reject(request.error)
+ request.onsuccess = () => resolve(request.result)
+
+ request.onupgradeneeded = (event) => {
+ const db = event.target.result
+ if (!db.objectStoreNames.contains('device')) {
+ db.createObjectStore('device', { keyPath: 'id' })
+ }
+ }
+ })
+ },
+
+ // 尝试从 IndexedDB 恢复 UUID(在初始化时调用)
+ async tryRestoreFromIndexedDB() {
+ const uuid = await this.getFromIndexedDB()
+ if (uuid && !this.getDeviceUuid()) {
+ this.setDeviceUuid(uuid)
+ }
+ }
+}
+
+// 在页面加载时尝试从 IndexedDB 恢复
+if (typeof window !== 'undefined') {
+ deviceStore.tryRestoreFromIndexedDB()
+}
diff --git a/src/lib/tokenStore.js b/src/lib/tokenStore.js
new file mode 100644
index 0000000..7d6e469
--- /dev/null
+++ b/src/lib/tokenStore.js
@@ -0,0 +1,66 @@
+// 生成随机设备码
+export function generateDeviceCode() {
+ const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
+ const segments = []
+
+ for (let i = 0; i < 4; i++) {
+ let segment = ''
+ for (let j = 0; j < 4; j++) {
+ segment += chars[Math.floor(Math.random() * chars.length)]
+ }
+ segments.push(segment)
+ }
+
+ return segments.join('-')
+}
+
+// Token 管理
+export const tokenStore = {
+ // 获取所有 token
+ getTokens() {
+ const tokens = localStorage.getItem('kv_tokens')
+ return tokens ? JSON.parse(tokens) : []
+ },
+
+ // 添加 token
+ addToken(token, appName = '') {
+ const tokens = this.getTokens()
+ const newToken = {
+ id: Date.now().toString(),
+ token,
+ appName,
+ deviceCode: generateDeviceCode(),
+ createdAt: new Date().toISOString(),
+ lastUsed: new Date().toISOString()
+ }
+ tokens.push(newToken)
+ localStorage.setItem('kv_tokens', JSON.stringify(tokens))
+ return newToken
+ },
+
+ // 删除 token
+ removeToken(id) {
+ const tokens = this.getTokens().filter(t => t.id !== id)
+ localStorage.setItem('kv_tokens', JSON.stringify(tokens))
+ },
+
+ // 更新 token
+ updateToken(id, updates) {
+ const tokens = this.getTokens().map(t =>
+ t.id === id ? { ...t, ...updates } : t
+ )
+ localStorage.setItem('kv_tokens', JSON.stringify(tokens))
+ },
+
+ // 获取当前活跃的 token
+ getActiveToken() {
+ const activeId = localStorage.getItem('kv_active_token')
+ if (!activeId) return null
+ return this.getTokens().find(t => t.id === activeId)
+ },
+
+ // 设置活跃 token
+ setActiveToken(id) {
+ localStorage.setItem('kv_active_token', id)
+ }
+}
diff --git a/src/lib/utils.js b/src/lib/utils.js
new file mode 100644
index 0000000..b20bf01
--- /dev/null
+++ b/src/lib/utils.js
@@ -0,0 +1,6 @@
+import { clsx } from "clsx";
+import { twMerge } from "tailwind-merge"
+
+export function cn(...inputs) {
+ return twMerge(clsx(inputs));
+}
diff --git a/src/main.js b/src/main.js
new file mode 100644
index 0000000..7389876
--- /dev/null
+++ b/src/main.js
@@ -0,0 +1,45 @@
+import { createApp } from 'vue'
+import { createRouter, createWebHistory } from 'vue-router'
+import { createPinia } from 'pinia'
+import { routes } from 'vue-router/auto-routes'
+import { tokenStore } from './lib/tokenStore'
+import { deviceStore } from './lib/deviceStore'
+import './style.css'
+import App from './App.vue'
+
+// 检查 URL 参数中的 uuid 并设置到本地存储
+const urlParams = new URLSearchParams(window.location.search)
+const urlUuid = urlParams.get('uuid')
+if (urlUuid) {
+ deviceStore.setDeviceUuid(urlUuid)
+ // 清除 URL 中的 uuid 参数
+ urlParams.delete('uuid')
+ const newUrl = urlParams.toString()
+ ? `${window.location.pathname}?${urlParams.toString()}`
+ : window.location.pathname
+ window.history.replaceState({}, '', newUrl)
+}
+
+const pinia = createPinia()
+
+const router = createRouter({
+ history: createWebHistory(),
+ routes,
+})
+
+// Navigation guard for authentication
+router.beforeEach((to, _from, next) => {
+ const requiresAuth = to.meta?.requiresAuth
+ const activeToken = tokenStore.getActiveToken()
+
+ if (requiresAuth && !activeToken) {
+ next({ path: '/' })
+ } else {
+ next()
+ }
+})
+
+const app = createApp(App)
+app.use(pinia)
+app.use(router)
+app.mount('#app')
diff --git a/src/pages/authorize.vue b/src/pages/authorize.vue
new file mode 100644
index 0000000..2526087
--- /dev/null
+++ b/src/pages/authorize.vue
@@ -0,0 +1,493 @@
+
+
+
+
+
+
+
+
+
+ 应用授权
+
+
+ 授权应用访问您的 KV 存储
+
+
+
+
+
+
+
+
+
+
+
+ 设备 UUID
+
+
+
+
+
+
+
+
+ {{ deviceUuid }}
+
+
+
+ 已保护
+
+
+
+
+
+
+ 已绑定至: {{ deviceAccount.name }}
+
+
+
+
+
+
+
+ {{ isDeviceCodeMode ? '设备代码模式' : '回调模式' }}
+
+
+
+
+
+
+
+ 设备代码
+
+
+
+
+
+
+
+
+ 备注(可选)
+
+
+
+
+
+
+
+
+
+
+ 确认授权
+
+
+
+
+ 返回管理页面
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
授权成功!
+
+
+ 设备代码已绑定,您可以继续使用 CLI 工具
+
+
+ 应用已成功授权
+
+
+
+
+
+
+ 返回管理页面
+
+
+
+
+
+
+
+
+
+
+
授权失败
+
{{ errorMessage }}
+
+
+
+
+
+ 重试
+
+
+ 返回管理页面
+
+
+
+
+
+
+
+
+
+
授权说明
+
+
+ 点击"确认授权"后,应用将获得访问您 KV 存储的权限。CLI 工具将自动完成授权流程。
+
+
+ 点击"确认授权"后,应用将获得访问您 KV 存储的权限。
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pages/device-management.vue b/src/pages/device-management.vue
new file mode 100644
index 0000000..ca35341
--- /dev/null
+++ b/src/pages/device-management.vue
@@ -0,0 +1,276 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ accountStore.userName }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 暂无绑定设备
+ 您可以在主页面注册并绑定新设备
+
+ 返回主页
+
+
+
+
+
+
+
+
+ 共 {{ devices.length }} 个设备
+
+
+
+
+
+
+
+
+
+ {{ device.name || '未命名设备' }}
+
+
+ {{ device.uuid }}
+
+
+
+
+
+
+
+ 创建时间: {{ formatDate(device.createdAt) }}
+
+
+
+
+
+ 重命名
+
+
+
+ 重置密码
+
+
+
+
+
+ 解绑设备
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 确认解绑设备
+
+ 确定要解绑设备 "{{ currentDevice?.name || currentDevice?.uuid }}" 吗?
+ 此操作无法撤销。
+
+
+
+ 取消
+
+ 确认解绑
+
+
+
+
+
+
diff --git a/src/pages/index.vue b/src/pages/index.vue
new file mode 100644
index 0000000..1ae2d8d
--- /dev/null
+++ b/src/pages/index.vue
@@ -0,0 +1,861 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Classworks KV
+
+
云原生键值数据库
+
+
+
+
+
+
+
+
+
+
+ {{ accountStore.userName }}
+
+
+
+
+
+
+ 设备管理
+
+
+
+ 高级设置
+
+
+
+ 退出登录
+
+
+
+
+
+ 登录
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ deviceInfo?.name || '设备标识' }}
+
+
+
+
+
+
您的唯一设备标识符
+
+
+
+
+
+
+ {{ hasPassword ? '已设密码保护' : '未设密码' }}
+
+
+
+
+
+ {{ deviceInfo.account.name }}
+
+
+
+ 绑定到账户
+
+ 高级设置
+
+
+
+
+
+
+
+
+
+
+ {{ deviceUuid }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ groupedByApp.length }}
+
应用数
+
+
+
{{ tokens.length }}
+
令牌数
+
+
+
+ {{ hasPassword ? '安全' : '未设置' }}
+
+
安全状态
+
+
+
+
+
+
+
+
+
密码提示
+
{{ passwordHint }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 暂无授权应用
+ 点击上方按钮授权您的第一个应用
+
+
+ 授权应用
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ token.token }}
+
+
+
+
+
+
+
+
+ {{ token.note }}
+
+
+
+
+
+ {{ formatDate(token.installedAt) }}
+
+
+
+ 撤销
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 授权新应用
+
+ 为应用生成新的访问令牌
+
+
+
+
+ 应用 ID
+
+
+
+ 备注(可选)
+
+
+
+
+
+
+ 取消
+
+
+ 授权
+
+
+
+
+
+
+
+
+
+ 撤销授权
+
+ 确定要撤销此令牌的授权吗?此操作无法撤销。{{selectedToken}}
+
+
+
+
+
+ 应用:
+ {{ getAppName(selectedToken.appId) }}
+
+
+ 令牌:
+ {{ selectedToken.token.slice(0, 16) }}...
+
+
+
+
+
+
+
+
+
+
+ 已登录账户,无需输入密码
+
+
+
+ 设备未设置密码
+
+
+
+ 需要验证设备密码
+
+
+
+
+
+ 取消
+
+
+ 确认撤销
+
+
+
+
+
+
+
+
+
+ {{ hasPassword ? '修改密码' : '设置密码' }}
+
+ {{ hasPassword ? '输入当前密码和新密码' : '为设备设置密码以增强安全性' }}
+
+
+
+
+
+
+
+
+
账户已登录
+
您已登录绑定的账户,无需输入当前密码
+
+
+
+
+
+
+
+ 取消
+
+
+ 确认
+
+
+
+
+
+
+
+
{
+ if (!val && deviceRequired.value) {
+ showRegisterDialog.value = true
+ }
+ }"
+ />
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/pages/kv-manager.vue b/src/pages/kv-manager.vue
new file mode 100644
index 0000000..ca8713e
--- /dev/null
+++ b/src/pages/kv-manager.vue
@@ -0,0 +1,615 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
加载中...
+
+
+
{{ error }}
+
+
+
+
+
+
+ 键名
+ 值
+ 操作
+
+
+
+
+ {{ key }}
+
+ 加载中...
+
+
{{ formatValue(values[key]) }}
+
+ 查看
+
+
+ 编辑
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ editingKey ? '编辑键值' : '添加键值' }}
+
+ 键名
+
+
+
+ 值(JSON 格式)
+
+
+
{{ dialogError }}
+
+ 取消
+ 保存
+
+
+
+
+
+
+
+
+
diff --git a/src/pages/password-manager.vue b/src/pages/password-manager.vue
new file mode 100644
index 0000000..67d07be
--- /dev/null
+++ b/src/pages/password-manager.vue
@@ -0,0 +1,615 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ successMessage }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 密码状态
+ 当前设备的密码保护状态
+
+
+
+
+
+ {{ hasPassword ? '已设置密码' : '未设置密码' }}
+
+
+
+
+
+
+
+ 设备 UUID
+ {{ deviceUuid }}
+
+
+
+
+
+
+
+
密码提示
+
{{ passwordHint }}
+
+
+
+
+
+
+
+
+ 设置密码
+
+
+
+
+ 修改密码
+
+
+
+
+ {{ passwordHint ? '修改提示' : '设置提示' }}
+
+
+
+
+ 删除密码
+
+
+
+
+
+
+
+
设备管理
+
+
+
+
+
+
+ 重置设备
+
+
+ 重置或换新设备标识。此操作无法撤销,您将失去当前设备的所有授权。
+
+
+
+
+
+
+
+
+
警告:此操作不可逆
+
+ 重置设备后,您将获得全新的设备标识,现有的所有授权将被撤销,无法恢复。
+
+
+
+
+
+
+
+ 重置设备
+
+
+
+
+
+
+
+
+
+
+
+ {{ hasPassword ? '修改密码' : '设置密码' }}
+
+ {{ hasPassword ? '请输入当前密码和新密码' : '为您的设备设置一个安全的密码' }}
+
+
+
+
+
+
+
+ 取消
+
+
+ {{ isLoading ? '处理中...' : (hasPassword ? '修改密码' : '设置密码') }}
+
+
+
+
+
+
+
+
+
+ 删除密码
+
+ 删除密码后,您的设备将不再受密码保护。此操作无法撤销。
+
+
+
+
+
+
+
+
+
警告
+
删除密码后,任何拥有您设备 UUID 的人都可以管理您的授权应用。
+
+
+
+
+
+
+
+
+
+ 取消
+
+
+ {{ isLoading ? '删除中...' : '确认删除' }}
+
+
+
+
+
+
+
+
+
+ {{ passwordHint ? '修改密码提示' : '设置密码提示' }}
+
+ 密码提示可以帮助您在忘记密码时回忆起密码
+
+
+
+
+
+
当前提示
+
{{ passwordHint }}
+
+
+
+
新的密码提示
+
+
+ 提示不应包含密码本身,而是能帮助您回忆密码的信息
+
+
+
+
+
+
+
+
+ 取消
+
+
+ {{ isLoading ? '保存中...' : '保存提示' }}
+
+
+
+
+
+
+
showResetDeviceDialog = val"
+ />
+
+
+
+
+
\ No newline at end of file
diff --git a/src/stores/account.js b/src/stores/account.js
new file mode 100644
index 0000000..3aed301
--- /dev/null
+++ b/src/stores/account.js
@@ -0,0 +1,116 @@
+import { defineStore } from 'pinia'
+import { ref, computed } from 'vue'
+import { apiClient } from '@/lib/api'
+
+export const useAccountStore = defineStore('account', () => {
+ // 状态
+ const token = ref(localStorage.getItem('auth_token') || null)
+ const profile = ref(null)
+ const devices = ref([])
+ const loading = ref(false)
+
+ // 计算属性
+ const isAuthenticated = computed(() => !!token.value)
+ const userName = computed(() => profile.value?.name || '')
+ const userAvatar = computed(() => profile.value?.avatarUrl || '')
+
+ // 方法
+ const setToken = (newToken) => {
+ token.value = newToken
+ if (newToken) {
+ localStorage.setItem('auth_token', newToken)
+ } else {
+ localStorage.removeItem('auth_token')
+ localStorage.removeItem('auth_provider')
+ }
+ }
+
+ const loadProfile = async () => {
+ if (!token.value) return
+
+ loading.value = true
+ try {
+ const response = await apiClient.getAccountProfile(token.value)
+ profile.value = response.data
+ } catch (error) {
+ console.error('Failed to load profile:', error)
+ // Token可能无效,清除
+ if (error.message.includes('401')) {
+ logout()
+ }
+ } finally {
+ loading.value = false
+ }
+ }
+
+ const loadDevices = async () => {
+ if (!token.value) return
+
+ try {
+ const response = await apiClient.getAccountDevices(token.value)
+ devices.value = response.data || []
+ return devices.value
+ } catch (error) {
+ console.error('Failed to load devices:', error)
+ return []
+ }
+ }
+
+ const bindDevice = async (deviceUuid) => {
+ if (!token.value) throw new Error('未登录')
+
+ const response = await apiClient.bindDevice(token.value, deviceUuid)
+ // 重新加载设备列表
+ await loadDevices()
+ return response
+ }
+
+ const unbindDevice = async (deviceUuid) => {
+ if (!token.value) throw new Error('未登录')
+
+ const response = await apiClient.unbindDevice(token.value, deviceUuid)
+ // 重新加载设备列表
+ await loadDevices()
+ return response
+ }
+
+ const login = async (authToken) => {
+ setToken(authToken)
+ await loadProfile()
+ await loadDevices()
+ }
+
+ const logout = () => {
+ token.value = null
+ profile.value = null
+ devices.value = []
+ localStorage.removeItem('auth_token')
+ localStorage.removeItem('auth_provider')
+ }
+
+ // 初始化时加载用户信息
+ if (token.value) {
+ loadProfile()
+ loadDevices()
+ }
+
+ return {
+ // 状态
+ token,
+ profile,
+ devices,
+ loading,
+ // 计算属性
+ isAuthenticated,
+ userName,
+ userAvatar,
+ // 方法
+ setToken,
+ loadProfile,
+ loadDevices,
+ bindDevice,
+ unbindDevice,
+ login,
+ logout,
+ }
+})
\ No newline at end of file
diff --git a/src/style.css b/src/style.css
new file mode 100644
index 0000000..1949175
--- /dev/null
+++ b/src/style.css
@@ -0,0 +1,124 @@
+@import "tailwindcss";
+@plugin "@tailwindcss/typography";
+@import "tw-animate-css";
+
+@custom-variant dark (&:is(.dark *));
+
+@theme inline {
+ --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-destructive-foreground: var(--destructive-foreground);
+ --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);
+ --radius-sm: calc(var(--radius) - 4px);
+ --radius-md: calc(var(--radius) - 2px);
+ --radius-lg: var(--radius);
+ --radius-xl: calc(var(--radius) + 4px);
+ --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 {
+ --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);
+ --destructive-foreground: 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);
+ --radius: 0.625rem;
+ --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.145 0 0);
+ --card-foreground: oklch(0.985 0 0);
+ --popover: oklch(0.145 0 0);
+ --popover-foreground: oklch(0.985 0 0);
+ --primary: oklch(0.985 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.396 0.141 25.723);
+ --destructive-foreground: oklch(0.637 0.237 25.331);
+ --border: oklch(0.269 0 0);
+ --input: oklch(0.269 0 0);
+ --ring: oklch(0.439 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(0.269 0 0);
+ --sidebar-ring: oklch(0.439 0 0);
+}
+
+@layer base {
+ * {
+ @apply border-border outline-ring/50;
+ }
+ body {
+ @apply bg-background text-foreground;
+ }
+}
diff --git a/vite.config.js b/vite.config.js
new file mode 100644
index 0000000..98f70fd
--- /dev/null
+++ b/vite.config.js
@@ -0,0 +1,26 @@
+import path from "path"
+import { fileURLToPath, URL } from 'node:url'
+import tailwindcss from "@tailwindcss/vite"
+import vue from '@vitejs/plugin-vue'
+import { defineConfig } from 'vite'
+import VueRouter from 'unplugin-vue-router/vite'
+import vueDevTools from 'vite-plugin-vue-devtools'
+
+
+// https://vite.dev/config/
+export default defineConfig({
+ plugins: [
+ VueRouter({
+ routesFolder: 'src/pages',
+ dts: false,
+ }),
+ vue(),
+ tailwindcss(),
+ vueDevTools(),
+ ],
+ resolve: {
+ alias: {
+ "@": fileURLToPath(new URL('./src', import.meta.url)),
+ },
+ },
+})