commit 5674ce116ec6378b9bc4052570969207e038730d Author: yinsx Date: Fri Jan 23 15:23:04 2026 +0800 1 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8d032d5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/ +/dist/ +nul \ No newline at end of file diff --git a/ScreenShot_2026-01-22_174129_211.png b/ScreenShot_2026-01-22_174129_211.png new file mode 100644 index 0000000..d5de95e Binary files /dev/null and b/ScreenShot_2026-01-22_174129_211.png differ diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..8d032d5 --- /dev/null +++ b/app/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/ +/dist/ +nul \ No newline at end of file diff --git a/app/index.html b/app/index.html new file mode 100644 index 0000000..dbabf45 --- /dev/null +++ b/app/index.html @@ -0,0 +1,13 @@ + + + + + + + iTab Clone + + +
+ + + diff --git a/app/package-lock.json b/app/package-lock.json new file mode 100644 index 0000000..6c3f50b --- /dev/null +++ b/app/package-lock.json @@ -0,0 +1,1882 @@ +{ + "name": "itab-clone", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "itab-clone", + "version": "0.0.0", + "dependencies": { + "muuri": "^0.9.5", + "pinia": "^2.1.7", + "vue": "^3.3.11" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^4.5.2", + "sass": "^1.69.7", + "typescript": "^5.2.2", + "vite": "^5.0.8", + "vue-tsc": "^1.8.25" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.6.tgz", + "integrity": "sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.6" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.6.tgz", + "integrity": "sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@parcel/watcher": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.4.tgz", + "integrity": "sha512-WYa2tUVV5HiArWPB3ydlOc4R2ivq0IDrlqhMi3l7mVsFEXNcTfxYFPIHXHXIh/ca/y/V5N4E1zecyxdIBjYnkQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "detect-libc": "^2.0.3", + "is-glob": "^4.0.3", + "node-addon-api": "^7.0.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.5.4", + "@parcel/watcher-darwin-arm64": "2.5.4", + "@parcel/watcher-darwin-x64": "2.5.4", + "@parcel/watcher-freebsd-x64": "2.5.4", + "@parcel/watcher-linux-arm-glibc": "2.5.4", + "@parcel/watcher-linux-arm-musl": "2.5.4", + "@parcel/watcher-linux-arm64-glibc": "2.5.4", + "@parcel/watcher-linux-arm64-musl": "2.5.4", + "@parcel/watcher-linux-x64-glibc": "2.5.4", + "@parcel/watcher-linux-x64-musl": "2.5.4", + "@parcel/watcher-win32-arm64": "2.5.4", + "@parcel/watcher-win32-ia32": "2.5.4", + "@parcel/watcher-win32-x64": "2.5.4" + } + }, + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.4.tgz", + "integrity": "sha512-hoh0vx4v+b3BNI7Cjoy2/B0ARqcwVNrzN/n7DLq9ZB4I3lrsvhrkCViJyfTj/Qi5xM9YFiH4AmHGK6pgH1ss7g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-arm64": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.4.tgz", + "integrity": "sha512-kphKy377pZiWpAOyTgQYPE5/XEKVMaj6VUjKT5VkNyUJlr2qZAn8gIc7CPzx+kbhvqHDT9d7EqdOqRXT6vk0zw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.4.tgz", + "integrity": "sha512-UKaQFhCtNJW1A9YyVz3Ju7ydf6QgrpNQfRZ35wNKUhTQ3dxJ/3MULXN5JN/0Z80V/KUBDGa3RZaKq1EQT2a2gg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.4.tgz", + "integrity": "sha512-Dib0Wv3Ow/m2/ttvLdeI2DBXloO7t3Z0oCp4bAb2aqyqOjKPPGrg10pMJJAQ7tt8P4V2rwYwywkDhUia/FgS+Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.4.tgz", + "integrity": "sha512-I5Vb769pdf7Q7Sf4KNy8Pogl/URRCKu9ImMmnVKYayhynuyGYMzuI4UOWnegQNa2sGpsPSbzDsqbHNMyeyPCgw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-musl": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.4.tgz", + "integrity": "sha512-kGO8RPvVrcAotV4QcWh8kZuHr9bXi9a3bSZw7kFarYR0+fGliU7hd/zevhjw8fnvIKG3J9EO5G6sXNGCSNMYPQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.4.tgz", + "integrity": "sha512-KU75aooXhqGFY2W5/p8DYYHt4hrjHZod8AhcGAmhzPn/etTa+lYCDB2b1sJy3sWJ8ahFVTdy+EbqSBvMx3iFlw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.4.tgz", + "integrity": "sha512-Qx8uNiIekVutnzbVdrgSanM+cbpDD3boB1f8vMtnuG5Zau4/bdDbXyKwIn0ToqFhIuob73bcxV9NwRm04/hzHQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.4.tgz", + "integrity": "sha512-UYBQvhYmgAv61LNUn24qGQdjtycFBKSK3EXr72DbJqX9aaLbtCOO8+1SkKhD/GNiJ97ExgcHBrukcYhVjrnogA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.4.tgz", + "integrity": "sha512-YoRWCVgxv8akZrMhdyVi6/TyoeeMkQ0PGGOf2E4omODrvd1wxniXP+DBynKoHryStks7l+fDAMUBRzqNHrVOpg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.4.tgz", + "integrity": "sha512-iby+D/YNXWkiQNYcIhg8P5hSjzXEHaQrk2SLrWOUD7VeC4Ohu0WQvmV+HDJokZVJ2UjJ4AGXW3bx7Lls9Ln4TQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-ia32": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.4.tgz", + "integrity": "sha512-vQN+KIReG0a2ZDpVv8cgddlf67J8hk1WfZMMP7sMeZmJRSmEax5xNDNWKdgqSe2brOKTQQAs3aCCUal2qBHAyg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.4.tgz", + "integrity": "sha512-3A6efb6BOKwyw7yk9ro2vus2YTt2nvcd56AuzxdMiVOxL9umDyN5PKkKfZ/gZ9row41SjVmTVQNWQhaRRGpOKw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.56.0.tgz", + "integrity": "sha512-LNKIPA5k8PF1+jAFomGe3qN3bbIgJe/IlpDBwuVjrDKrJhVWywgnJvflMt/zkbVNLFtF1+94SljYQS6e99klnw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.56.0.tgz", + "integrity": "sha512-lfbVUbelYqXlYiU/HApNMJzT1E87UPGvzveGg2h0ktUNlOCxKlWuJ9jtfvs1sKHdwU4fzY7Pl8sAl49/XaEk6Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.56.0.tgz", + "integrity": "sha512-EgxD1ocWfhoD6xSOeEEwyE7tDvwTgZc8Bss7wCWe+uc7wO8G34HHCUH+Q6cHqJubxIAnQzAsyUsClt0yFLu06w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.56.0.tgz", + "integrity": "sha512-1vXe1vcMOssb/hOF8iv52A7feWW2xnu+c8BV4t1F//m9QVLTfNVpEdja5ia762j/UEJe2Z1jAmEqZAK42tVW3g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.56.0.tgz", + "integrity": "sha512-bof7fbIlvqsyv/DtaXSck4VYQ9lPtoWNFCB/JY4snlFuJREXfZnm+Ej6yaCHfQvofJDXLDMTVxWscVSuQvVWUQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.56.0.tgz", + "integrity": "sha512-KNa6lYHloW+7lTEkYGa37fpvPq+NKG/EHKM8+G/g9WDU7ls4sMqbVRV78J6LdNuVaeeK5WB9/9VAFbKxcbXKYg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.56.0.tgz", + "integrity": "sha512-E8jKK87uOvLrrLN28jnAAAChNq5LeCd2mGgZF+fGF5D507WlG/Noct3lP/QzQ6MrqJ5BCKNwI9ipADB6jyiq2A==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.56.0.tgz", + "integrity": "sha512-jQosa5FMYF5Z6prEpTCCmzCXz6eKr/tCBssSmQGEeozA9tkRUty/5Vx06ibaOP9RCrW1Pvb8yp3gvZhHwTDsJw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.56.0.tgz", + "integrity": "sha512-uQVoKkrC1KGEV6udrdVahASIsaF8h7iLG0U0W+Xn14ucFwi6uS539PsAr24IEF9/FoDtzMeeJXJIBo5RkbNWvQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.56.0.tgz", + "integrity": "sha512-vLZ1yJKLxhQLFKTs42RwTwa6zkGln+bnXc8ueFGMYmBTLfNu58sl5/eXyxRa2RarTkJbXl8TKPgfS6V5ijNqEA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.56.0.tgz", + "integrity": "sha512-FWfHOCub564kSE3xJQLLIC/hbKqHSVxy8vY75/YHHzWvbJL7aYJkdgwD/xGfUlL5UV2SB7otapLrcCj2xnF1dg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.56.0.tgz", + "integrity": "sha512-z1EkujxIh7nbrKL1lmIpqFTc/sr0u8Uk0zK/qIEFldbt6EDKWFk/pxFq3gYj4Bjn3aa9eEhYRlL3H8ZbPT1xvA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.56.0.tgz", + "integrity": "sha512-iNFTluqgdoQC7AIE8Q34R3AuPrJGJirj5wMUErxj22deOcY7XwZRaqYmB6ZKFHoVGqRcRd0mqO+845jAibKCkw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.56.0.tgz", + "integrity": "sha512-MtMeFVlD2LIKjp2sE2xM2slq3Zxf9zwVuw0jemsxvh1QOpHSsSzfNOTH9uYW9i1MXFxUSMmLpeVeUzoNOKBaWg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.56.0.tgz", + "integrity": "sha512-in+v6wiHdzzVhYKXIk5U74dEZHdKN9KH0Q4ANHOTvyXPG41bajYRsy7a8TPKbYPl34hU7PP7hMVHRvv/5aCSew==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.56.0.tgz", + "integrity": "sha512-yni2raKHB8m9NQpI9fPVwN754mn6dHQSbDTwxdr9SE0ks38DTjLMMBjrwvB5+mXrX+C0npX0CVeCUcvvvD8CNQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.56.0.tgz", + "integrity": "sha512-zhLLJx9nQPu7wezbxt2ut+CI4YlXi68ndEve16tPc/iwoylWS9B3FxpLS2PkmfYgDQtosah07Mj9E0khc3Y+vQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.56.0.tgz", + "integrity": "sha512-MVC6UDp16ZSH7x4rtuJPAEoE1RwS8N4oK9DLHy3FTEdFoUTCFVzMfJl/BVJ330C+hx8FfprA5Wqx4FhZXkj2Kw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.56.0.tgz", + "integrity": "sha512-ZhGH1eA4Qv0lxaV00azCIS1ChedK0V32952Md3FtnxSqZTBTd6tgil4nZT5cU8B+SIw3PFYkvyR4FKo2oyZIHA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.56.0.tgz", + "integrity": "sha512-O16XcmyDeFI9879pEcmtWvD/2nyxR9mF7Gs44lf1vGGx8Vg2DRNx11aVXBEqOQhWb92WN4z7fW/q4+2NYzCbBA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.56.0.tgz", + "integrity": "sha512-LhN/Reh+7F3RCgQIRbgw8ZMwUwyqJM+8pXNT6IIJAqm2IdKkzpCh/V9EdgOMBKuebIrzswqy4ATlrDgiOwbRcQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.56.0.tgz", + "integrity": "sha512-kbFsOObXp3LBULg1d3JIUQMa9Kv4UitDmpS+k0tinPBz3watcUiV2/LUDMMucA6pZO3WGE27P7DsfaN54l9ing==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.56.0.tgz", + "integrity": "sha512-vSSgny54D6P4vf2izbtFm/TcWYedw7f8eBrOiGGecyHyQB9q4Kqentjaj8hToe+995nob/Wv48pDqL5a62EWtg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.56.0.tgz", + "integrity": "sha512-FeCnkPCTHQJFbiGG49KjV5YGW/8b9rrXAM2Mz2kiIoktq2qsJxRD5giEMEOD2lPdgs72upzefaUvS+nc8E3UzQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.56.0.tgz", + "integrity": "sha512-H8AE9Ur/t0+1VXujj90w0HrSOuv0Nq9r1vSZF2t5km20NTfosQsGGUXDaKdQZzwuLts7IyL1fYT4hM95TI9c4g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vitejs/plugin-vue": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-4.6.2.tgz", + "integrity": "sha512-kqf7SGFoG+80aZG6Pf+gsZIVvGSCKE98JbiWqcCV9cThtg91Jav0yvYFC9Zb+jKetNGF6ZKeoaxgZfND21fWKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.0.0 || ^5.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@volar/language-core": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-1.11.1.tgz", + "integrity": "sha512-dOcNn3i9GgZAcJt43wuaEykSluAuOkQgzni1cuxLxTV0nJKanQztp7FxyswdRILaKH+P2XZMPRp2S4MV/pElCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/source-map": "1.11.1" + } + }, + "node_modules/@volar/source-map": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-1.11.1.tgz", + "integrity": "sha512-hJnOnwZ4+WT5iupLRnuzbULZ42L7BWWPMmruzwtLhJfpDVoZLjNBxHDi2sY2bgZXCKlpU5XcsMFoYrsQmPhfZg==", + "dev": true, + "license": "MIT", + "dependencies": { + "muggle-string": "^0.3.1" + } + }, + "node_modules/@volar/typescript": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-1.11.1.tgz", + "integrity": "sha512-iU+t2mas/4lYierSnoFOeRFQUhAEMgsFuQxoxvwn5EdQopw43j+J27a4lt9LMInx1gLJBC6qL14WYGlgymaSMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "1.11.1", + "path-browserify": "^1.0.1" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.5.27", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.27.tgz", + "integrity": "sha512-gnSBQjZA+//qDZen+6a2EdHqJ68Z7uybrMf3SPjEGgG4dicklwDVmMC1AeIHxtLVPT7sn6sH1KOO+tS6gwOUeQ==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.5", + "@vue/shared": "3.5.27", + "entities": "^7.0.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.27", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.27.tgz", + "integrity": "sha512-oAFea8dZgCtVVVTEC7fv3T5CbZW9BxpFzGGxC79xakTr6ooeEqmRuvQydIiDAkglZEAd09LgVf1RoDnL54fu5w==", + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.5.27", + "@vue/shared": "3.5.27" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.5.27", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.27.tgz", + "integrity": "sha512-sHZu9QyDPeDmN/MRoshhggVOWE5WlGFStKFwu8G52swATgSny27hJRWteKDSUUzUH+wp+bmeNbhJnEAel/auUQ==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.5", + "@vue/compiler-core": "3.5.27", + "@vue/compiler-dom": "3.5.27", + "@vue/compiler-ssr": "3.5.27", + "@vue/shared": "3.5.27", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.21", + "postcss": "^8.5.6", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.27", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.27.tgz", + "integrity": "sha512-Sj7h+JHt512fV1cTxKlYhg7qxBvack+BGncSpH+8vnN+KN95iPIcqB5rsbblX40XorP+ilO7VIKlkuu3Xq2vjw==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.27", + "@vue/shared": "3.5.27" + } + }, + "node_modules/@vue/devtools-api": { + "version": "6.6.4", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz", + "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", + "license": "MIT" + }, + "node_modules/@vue/language-core": { + "version": "1.8.27", + "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-1.8.27.tgz", + "integrity": "sha512-L8Kc27VdQserNaCUNiSFdDl9LWT24ly8Hpwf1ECy3aFb9m6bDhBGQYOujDm21N7EW3moKIOKEanQwe1q5BK+mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "~1.11.1", + "@volar/source-map": "~1.11.1", + "@vue/compiler-dom": "^3.3.0", + "@vue/shared": "^3.3.0", + "computeds": "^0.0.1", + "minimatch": "^9.0.3", + "muggle-string": "^0.3.1", + "path-browserify": "^1.0.1", + "vue-template-compiler": "^2.7.14" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@vue/reactivity": { + "version": "3.5.27", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.27.tgz", + "integrity": "sha512-vvorxn2KXfJ0nBEnj4GYshSgsyMNFnIQah/wczXlsNXt+ijhugmW+PpJ2cNPe4V6jpnBcs0MhCODKllWG+nvoQ==", + "license": "MIT", + "dependencies": { + "@vue/shared": "3.5.27" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.5.27", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.27.tgz", + "integrity": "sha512-fxVuX/fzgzeMPn/CLQecWeDIFNt3gQVhxM0rW02Tvp/YmZfXQgcTXlakq7IMutuZ/+Ogbn+K0oct9J3JZfyk3A==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.27", + "@vue/shared": "3.5.27" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.27", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.27.tgz", + "integrity": "sha512-/QnLslQgYqSJ5aUmb5F0z0caZPGHRB8LEAQ1s81vHFM5CBfnun63rxhvE/scVb/j3TbBuoZwkJyiLCkBluMpeg==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.27", + "@vue/runtime-core": "3.5.27", + "@vue/shared": "3.5.27", + "csstype": "^3.2.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.5.27", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.27.tgz", + "integrity": "sha512-qOz/5thjeP1vAFc4+BY3Nr6wxyLhpeQgAE/8dDtKo6a6xdk+L4W46HDZgNmLOBUDEkFXV3G7pRiUqxjX0/2zWA==", + "license": "MIT", + "dependencies": { + "@vue/compiler-ssr": "3.5.27", + "@vue/shared": "3.5.27" + }, + "peerDependencies": { + "vue": "3.5.27" + } + }, + "node_modules/@vue/shared": { + "version": "3.5.27", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.27.tgz", + "integrity": "sha512-dXr/3CgqXsJkZ0n9F3I4elY8wM9jMJpP3pvRG52r6m0tu/MsAFIe6JpXVGeNMd/D9F4hQynWT8Rfuj0bdm9kFQ==", + "license": "MIT" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/computeds": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/computeds/-/computeds-0.0.1.tgz", + "integrity": "sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "license": "MIT" + }, + "node_modules/de-indent": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", + "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==", + "dev": true, + "license": "MIT" + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/entities": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "license": "MIT" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "license": "MIT", + "bin": { + "he": "bin/he" + } + }, + "node_modules/immutable": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.4.tgz", + "integrity": "sha512-p6u1bG3YSnINT5RQmx/yRZBpenIl30kVxkTLDyHLIMk0gict704Q9n+thfDI7lTRm9vXdDYutVzXhzcThxTnXA==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/muggle-string": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.3.1.tgz", + "integrity": "sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==", + "dev": true, + "license": "MIT" + }, + "node_modules/muuri": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/muuri/-/muuri-0.9.5.tgz", + "integrity": "sha512-nJL9/Pd5IaIXGAVunBs/LLQ+v6tPkvlqCYrlauWESgkVFr+F+CRf8HnayRh4AqiQ1S/PIEN39fhJSe4L5rLlxg==", + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pinia": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.3.1.tgz", + "integrity": "sha512-khUlZSwt9xXCaTbbxFYBKDc/bWAGWJjOgvxETwkTN7KRm66EeT1ZdZj6i2ceh9sP2Pzqsbc704r2yngBrxBVug==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^6.6.3", + "vue-demi": "^0.14.10" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "typescript": ">=4.4.4", + "vue": "^2.7.0 || ^3.5.11" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/rollup": { + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.56.0.tgz", + "integrity": "sha512-9FwVqlgUHzbXtDg9RCMgodF3Ua4Na6Gau+Sdt9vyCN4RhHfVKX2DCHy3BjMLTDd47ITDhYAnTwGulWTblJSDLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.56.0", + "@rollup/rollup-android-arm64": "4.56.0", + "@rollup/rollup-darwin-arm64": "4.56.0", + "@rollup/rollup-darwin-x64": "4.56.0", + "@rollup/rollup-freebsd-arm64": "4.56.0", + "@rollup/rollup-freebsd-x64": "4.56.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.56.0", + "@rollup/rollup-linux-arm-musleabihf": "4.56.0", + "@rollup/rollup-linux-arm64-gnu": "4.56.0", + "@rollup/rollup-linux-arm64-musl": "4.56.0", + "@rollup/rollup-linux-loong64-gnu": "4.56.0", + "@rollup/rollup-linux-loong64-musl": "4.56.0", + "@rollup/rollup-linux-ppc64-gnu": "4.56.0", + "@rollup/rollup-linux-ppc64-musl": "4.56.0", + "@rollup/rollup-linux-riscv64-gnu": "4.56.0", + "@rollup/rollup-linux-riscv64-musl": "4.56.0", + "@rollup/rollup-linux-s390x-gnu": "4.56.0", + "@rollup/rollup-linux-x64-gnu": "4.56.0", + "@rollup/rollup-linux-x64-musl": "4.56.0", + "@rollup/rollup-openbsd-x64": "4.56.0", + "@rollup/rollup-openharmony-arm64": "4.56.0", + "@rollup/rollup-win32-arm64-msvc": "4.56.0", + "@rollup/rollup-win32-ia32-msvc": "4.56.0", + "@rollup/rollup-win32-x64-gnu": "4.56.0", + "@rollup/rollup-win32-x64-msvc": "4.56.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/sass": { + "version": "1.97.3", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.97.3.tgz", + "integrity": "sha512-fDz1zJpd5GycprAbu4Q2PV/RprsRtKC/0z82z0JLgdytmcq0+ujJbJ/09bPGDxCLkKY3Np5cRAOcWiVkLXJURg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chokidar": "^4.0.0", + "immutable": "^5.0.2", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=14.0.0" + }, + "optionalDependencies": { + "@parcel/watcher": "^2.4.1" + } + }, + "node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/vite": { + "version": "5.4.21", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", + "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vue": { + "version": "3.5.27", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.27.tgz", + "integrity": "sha512-aJ/UtoEyFySPBGarREmN4z6qNKpbEguYHMmXSiOGk69czc+zhs0NF6tEFrY8TZKAl8N/LYAkd4JHVd5E/AsSmw==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.27", + "@vue/compiler-sfc": "3.5.27", + "@vue/runtime-dom": "3.5.27", + "@vue/server-renderer": "3.5.27", + "@vue/shared": "3.5.27" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/vue-demi": { + "version": "0.14.10", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz", + "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/vue-template-compiler": { + "version": "2.7.16", + "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.7.16.tgz", + "integrity": "sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "de-indent": "^1.0.2", + "he": "^1.2.0" + } + }, + "node_modules/vue-tsc": { + "version": "1.8.27", + "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-1.8.27.tgz", + "integrity": "sha512-WesKCAZCRAbmmhuGl3+VrdWItEvfoFIPXOvUJkjULi+x+6G/Dy69yO3TBRJDr9eUlmsNAwVmxsNZxvHKzbkKdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/typescript": "~1.11.1", + "@vue/language-core": "1.8.27", + "semver": "^7.5.4" + }, + "bin": { + "vue-tsc": "bin/vue-tsc.js" + }, + "peerDependencies": { + "typescript": "*" + } + } + } +} diff --git a/app/package.json b/app/package.json new file mode 100644 index 0000000..651f184 --- /dev/null +++ b/app/package.json @@ -0,0 +1,23 @@ +{ + "name": "itab-clone", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vue-tsc && vite build", + "preview": "vite preview" + }, + "dependencies": { + "muuri": "^0.9.5", + "pinia": "^2.1.7", + "vue": "^3.3.11" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^4.5.2", + "sass": "^1.69.7", + "typescript": "^5.2.2", + "vite": "^5.0.8", + "vue-tsc": "^1.8.25" + } +} diff --git a/app/src/App.vue b/app/src/App.vue new file mode 100644 index 0000000..1ef6ee0 --- /dev/null +++ b/app/src/App.vue @@ -0,0 +1,22 @@ + + + + + diff --git a/app/src/components/GridCanvas/index.vue b/app/src/components/GridCanvas/index.vue new file mode 100644 index 0000000..58d97c4 --- /dev/null +++ b/app/src/components/GridCanvas/index.vue @@ -0,0 +1,343 @@ + + + + + diff --git a/app/src/components/IconCard/index.vue b/app/src/components/IconCard/index.vue new file mode 100644 index 0000000..ad7a6fa --- /dev/null +++ b/app/src/components/IconCard/index.vue @@ -0,0 +1,88 @@ + + + + + diff --git a/app/src/components/MainContent/index.vue b/app/src/components/MainContent/index.vue new file mode 100644 index 0000000..9411977 --- /dev/null +++ b/app/src/components/MainContent/index.vue @@ -0,0 +1,40 @@ + + + + + diff --git a/app/src/components/TheClock/index.vue b/app/src/components/TheClock/index.vue new file mode 100644 index 0000000..d5c08af --- /dev/null +++ b/app/src/components/TheClock/index.vue @@ -0,0 +1,58 @@ + + + + + diff --git a/app/src/components/TheContextMenu/index.vue b/app/src/components/TheContextMenu/index.vue new file mode 100644 index 0000000..d5dd828 --- /dev/null +++ b/app/src/components/TheContextMenu/index.vue @@ -0,0 +1,163 @@ + + + + + diff --git a/app/src/components/TheSearchBar/index.vue b/app/src/components/TheSearchBar/index.vue new file mode 100644 index 0000000..17d96ff --- /dev/null +++ b/app/src/components/TheSearchBar/index.vue @@ -0,0 +1,63 @@ + + + + + diff --git a/app/src/components/TheSidebar/index.vue b/app/src/components/TheSidebar/index.vue new file mode 100644 index 0000000..37c1afb --- /dev/null +++ b/app/src/components/TheSidebar/index.vue @@ -0,0 +1,139 @@ + + + + + diff --git a/app/src/components/WidgetCard/index.vue b/app/src/components/WidgetCard/index.vue new file mode 100644 index 0000000..c058d3e --- /dev/null +++ b/app/src/components/WidgetCard/index.vue @@ -0,0 +1,76 @@ + + + + + diff --git a/app/src/components/widgets/CalendarWidget.vue b/app/src/components/widgets/CalendarWidget.vue new file mode 100644 index 0000000..a19cafa --- /dev/null +++ b/app/src/components/widgets/CalendarWidget.vue @@ -0,0 +1,42 @@ + + + diff --git a/app/src/components/widgets/CountdownWidget.vue b/app/src/components/widgets/CountdownWidget.vue new file mode 100644 index 0000000..83682fc --- /dev/null +++ b/app/src/components/widgets/CountdownWidget.vue @@ -0,0 +1,39 @@ + + + diff --git a/app/src/components/widgets/HotSearchWidget.vue b/app/src/components/widgets/HotSearchWidget.vue new file mode 100644 index 0000000..cf9f856 --- /dev/null +++ b/app/src/components/widgets/HotSearchWidget.vue @@ -0,0 +1,56 @@ + + + + + diff --git a/app/src/config/layout.ts b/app/src/config/layout.ts new file mode 100644 index 0000000..eda8f04 --- /dev/null +++ b/app/src/config/layout.ts @@ -0,0 +1,171 @@ +export const layoutConfig = { + // Muuri 网格系统尺寸。 + grid: { + // 1x1 单元格宽高(像素)。 + cellSize: 106, + // 单元格间距(像素)。 + gap: 16, + }, + // 左侧栏布局。 + sidebar: { + // 侧栏宽度(像素)。 + width: 68, + // 侧栏上下内边距(像素)。 + paddingY: 20, + // 头像占位尺寸(像素)。 + profileSize: 40, + // 头像下方间距(像素)。 + profileMarginBottom: 30, + // 导航项正方形尺寸(像素)。 + navItemSize: 44, + // 导航项间距(像素)。 + navGap: 16, + // 激活指示条水平偏移(可为负)。 + activeIndicatorOffset: -8, + // 激活指示条宽度(像素)。 + activeIndicatorWidth: 4, + // 激活指示条高度(像素)。 + activeIndicatorHeight: 20, + // “新增”按钮额外上边距(像素)。 + addItemMarginTop: 10, + }, + // 主内容区边界。 + content: { + // 最大宽度(像素)。 + maxWidth: 1400, + // 内容区内边距(像素)。 + padding: 40, + }, + // 搜索栏尺寸。 + searchBar: { + // 最大宽度(像素)。 + maxWidth: 560, + // 高度(像素)。 + height: 52, + // 水平内边距(像素)。 + paddingX: 16, + // 搜索栏下方间距(像素)。 + marginBottom: 40, + }, + // 图标卡片尺寸与字体。 + icon: { + // 图标方块尺寸(像素)。 + size: 72, + // 图标首字母字体大小(像素)。 + fontSize: 28, + // 卡片内边距(像素)。 + padding: 8, + // 标签字体大小(像素)。 + labelFontSize: 13, + // 图标与标签间距(像素)。 + labelMarginTop: 8, + }, + // 组件卡片尺寸与字体。 + widget: { + // 内容区内边距(像素)。 + contentPadding: 16, + // 标签字体大小(像素)。 + labelFontSize: 13, + // 标签上下内边距(像素)。 + labelPaddingY: 8, + }, + // 时钟尺寸。 + clock: { + // 时间字体大小(像素)。 + timeFontSize: 82, + // 日期字体大小(像素)。 + dateFontSize: 16, + // 时钟下方间距(像素)。 + marginBottom: 30, + // 字母间距(像素)。 + letterSpacing: 2, + // 日期上方间距(像素)。 + dateMarginTop: 8, + }, + // 右键菜单尺寸。 + contextMenu: { + // 菜单宽度(像素)。 + width: 180, + // 菜单内边距(像素)。 + padding: 8, + // 菜单项上下内边距(像素)。 + itemPaddingY: 10, + // 菜单项左右内边距(像素)。 + itemPaddingX: 16, + // 图标尺寸(像素)。 + iconSize: 16, + // 图标与文字间距(像素)。 + iconMarginRight: 12, + // 布局区块上下内边距(像素)。 + layoutSectionPaddingY: 6, + // 布局区块左右内边距(像素)。 + layoutSectionPaddingX: 12, + // 布局标题下方间距(像素)。 + layoutTitleMarginBottom: 8, + // 布局选项间距(像素)。 + layoutOptionsGap: 6, + // 布局选项胶囊宽度(像素)。 + layoutOptionWidth: 40, + // 布局选项上下内边距(像素)。 + layoutOptionPaddingY: 4, + }, +} as const; + +// 设置根元素上的像素级样式变量。 +const setPx = (root: HTMLElement, name: string, value: number) => { + root.style.setProperty(name, `${value}px`); +}; + +// 将布局配置写入全局样式变量,供样式使用。 +export const applyLayoutConfig = (root: HTMLElement = document.documentElement) => { + setPx(root, '--grid-cell-size', layoutConfig.grid.cellSize); + setPx(root, '--grid-gap', layoutConfig.grid.gap); + + setPx(root, '--sidebar-width', layoutConfig.sidebar.width); + setPx(root, '--sidebar-padding-y', layoutConfig.sidebar.paddingY); + setPx(root, '--sidebar-profile-size', layoutConfig.sidebar.profileSize); + setPx(root, '--sidebar-profile-margin-bottom', layoutConfig.sidebar.profileMarginBottom); + setPx(root, '--sidebar-nav-item-size', layoutConfig.sidebar.navItemSize); + setPx(root, '--sidebar-nav-gap', layoutConfig.sidebar.navGap); + setPx(root, '--sidebar-active-indicator-offset', layoutConfig.sidebar.activeIndicatorOffset); + setPx(root, '--sidebar-active-indicator-width', layoutConfig.sidebar.activeIndicatorWidth); + setPx(root, '--sidebar-active-indicator-height', layoutConfig.sidebar.activeIndicatorHeight); + setPx(root, '--sidebar-add-margin-top', layoutConfig.sidebar.addItemMarginTop); + + setPx(root, '--content-max-width', layoutConfig.content.maxWidth); + setPx(root, '--content-padding', layoutConfig.content.padding); + + setPx(root, '--search-max-width', layoutConfig.searchBar.maxWidth); + setPx(root, '--search-height', layoutConfig.searchBar.height); + setPx(root, '--search-padding-x', layoutConfig.searchBar.paddingX); + setPx(root, '--search-margin-bottom', layoutConfig.searchBar.marginBottom); + + setPx(root, '--icon-size', layoutConfig.icon.size); + setPx(root, '--icon-font-size', layoutConfig.icon.fontSize); + setPx(root, '--icon-card-padding', layoutConfig.icon.padding); + setPx(root, '--icon-label-font-size', layoutConfig.icon.labelFontSize); + setPx(root, '--icon-label-margin-top', layoutConfig.icon.labelMarginTop); + + setPx(root, '--widget-content-padding', layoutConfig.widget.contentPadding); + setPx(root, '--widget-label-font-size', layoutConfig.widget.labelFontSize); + setPx(root, '--widget-label-padding-y', layoutConfig.widget.labelPaddingY); + + setPx(root, '--clock-time-font-size', layoutConfig.clock.timeFontSize); + setPx(root, '--clock-date-font-size', layoutConfig.clock.dateFontSize); + setPx(root, '--clock-margin-bottom', layoutConfig.clock.marginBottom); + setPx(root, '--clock-letter-spacing', layoutConfig.clock.letterSpacing); + setPx(root, '--clock-date-margin-top', layoutConfig.clock.dateMarginTop); + + setPx(root, '--context-menu-width', layoutConfig.contextMenu.width); + setPx(root, '--context-menu-padding', layoutConfig.contextMenu.padding); + setPx(root, '--context-menu-item-padding-y', layoutConfig.contextMenu.itemPaddingY); + setPx(root, '--context-menu-item-padding-x', layoutConfig.contextMenu.itemPaddingX); + setPx(root, '--context-menu-icon-size', layoutConfig.contextMenu.iconSize); + setPx(root, '--context-menu-icon-margin-right', layoutConfig.contextMenu.iconMarginRight); + setPx(root, '--context-menu-layout-section-padding-y', layoutConfig.contextMenu.layoutSectionPaddingY); + setPx(root, '--context-menu-layout-section-padding-x', layoutConfig.contextMenu.layoutSectionPaddingX); + setPx(root, '--context-menu-layout-title-margin-bottom', layoutConfig.contextMenu.layoutTitleMarginBottom); + setPx(root, '--context-menu-layout-options-gap', layoutConfig.contextMenu.layoutOptionsGap); + setPx(root, '--context-menu-layout-option-width', layoutConfig.contextMenu.layoutOptionWidth); + setPx(root, '--context-menu-layout-option-padding-y', layoutConfig.contextMenu.layoutOptionPaddingY); +}; diff --git a/app/src/config/theme.ts b/app/src/config/theme.ts new file mode 100644 index 0000000..192cf06 --- /dev/null +++ b/app/src/config/theme.ts @@ -0,0 +1,26 @@ +export const themeConfig = { + // 圆角配置,统一控制卡片与胶囊样式。 + radius: { + // 小圆角(像素)。 + sm: 8, + // 中圆角(像素)。 + md: 16, + // 大圆角(像素)。 + lg: 24, + // 胶囊圆角(像素)。 + pill: 20, + }, +} as const; + +// 设置根元素上的像素级样式变量。 +const setPx = (root: HTMLElement, name: string, value: number) => { + root.style.setProperty(name, `${value}px`); +}; + +// 将主题配置写入全局样式变量,供样式使用。 +export const applyThemeConfig = (root: HTMLElement = document.documentElement) => { + setPx(root, '--radius-sm', themeConfig.radius.sm); + setPx(root, '--radius-md', themeConfig.radius.md); + setPx(root, '--radius-lg', themeConfig.radius.lg); + setPx(root, '--radius-pill', themeConfig.radius.pill); +}; diff --git a/app/src/main.ts b/app/src/main.ts new file mode 100644 index 0000000..7e07e4b --- /dev/null +++ b/app/src/main.ts @@ -0,0 +1,17 @@ +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import './styles/global.scss' +import App from './App.vue' +import { applyLayoutConfig } from './config/layout' +import { applyThemeConfig } from './config/theme' +import { disableDefaultBehaviors } from './utils/disableDefaultBehaviors' + +// 在挂载前应用配置,确保样式变量已就绪。 +applyThemeConfig() +applyLayoutConfig() +disableDefaultBehaviors() + +const app = createApp(App) + +app.use(createPinia()) +app.mount('#app') diff --git a/app/src/store/useLayoutStore.ts b/app/src/store/useLayoutStore.ts new file mode 100644 index 0000000..82a5861 --- /dev/null +++ b/app/src/store/useLayoutStore.ts @@ -0,0 +1,103 @@ +import { defineStore } from 'pinia'; + +// 模拟数据(来自截图参考) +interface Icon { + id: string; + name: string; + url: string; + img?: string; // 可选:用于图片图标(如徽标) + bgColor?: string; // 可选:纯色背景 +} + +interface DragState { + isDragging: boolean; + itemId: string | null; + itemType: 'icon' | 'widget' | null; + startX: number; + startY: number; + currentX: number; + currentY: number; +} + +interface LayoutState { + icons: Icon[]; + dragState: DragState; +} + +const defaultIcons: Icon[] = [ + { id: '1', name: '淘宝', url: 'https://taobao.com', bgColor: '#ff4f00' }, + { id: '2', name: '京东商城', url: 'https://jd.com', bgColor: '#e4393c' }, + { id: '3', name: '百度', url: 'https://baidu.com', bgColor: '#3388ff' }, + { id: '4', name: '备忘录', url: '#', bgColor: '#f9ca24' }, + { id: '5', name: '爱奇艺', url: 'https://iqiyi.com', bgColor: '#00be06' }, + { id: '6', name: '文件夹', url: '#', bgColor: '#4285f4' }, + { id: '7', name: '抖音', url: 'https://douyin.com', bgColor: '#222' }, + { id: '8', name: '小浣熊', url: '#', bgColor: '#f0932b' }, + { id: '9', name: 'AiPPT', url: '#', bgColor: '#d63031' }, + { id: '10', name: '电影日历', url: '#', bgColor: 'transparent', img: 'https://example.com/movie_poster.png' }, // 图片示例 + { id: '11', name: '稿定设计', url: '#', bgColor: '#00aaff' }, + { id: '12', name: '壁纸', url: '#', bgColor: '#1dd1a1' }, + { id: '13', 'name': '即梦AI', url: '#', bgColor: '#6c5ce7' }, + { id: '14', name: '码上掘金', url: '#', bgColor: '#1e80ff' }, + { id: '15', name: '扩展管理', url: '#', bgColor: '#7f8c8d' }, + { id: '16', name: '书签管理', url: '#', bgColor: '#f1c40f' }, +]; + +const savedIcons = localStorage.getItem('itab_icons'); + +export const useLayoutStore = defineStore('layout', { + state: (): LayoutState => ({ + icons: savedIcons ? JSON.parse(savedIcons) : defaultIcons, + dragState: { + isDragging: false, + itemId: null, + itemType: null, + startX: 0, + startY: 0, + currentX: 0, + currentY: 0, + } + }), + actions: { + reorderIcons(draggedId: string, targetId: string) { + const draggedIndex = this.icons.findIndex(p => p.id === draggedId); + const targetIndex = this.icons.findIndex(p => p.id === targetId); + + if (draggedIndex !== -1 && targetIndex !== -1) { + // 直接交换 + const draggedItem = this.icons[draggedIndex]; + this.icons[draggedIndex] = this.icons[targetIndex]; + this.icons[targetIndex] = draggedItem; + + // 持久化顺序 + localStorage.setItem('itab_icons', JSON.stringify(this.icons)); + } + }, + setIconOrder(orderIds: string[]) { + const ordered: Icon[] = []; + const seen = new Set(); + for (const id of orderIds) { + const icon = this.icons.find(item => item.id === id); + if (icon) { + ordered.push(icon); + seen.add(icon.id); + } + } + for (const icon of this.icons) { + if (!seen.has(icon.id)) { + ordered.push(icon); + } + } + this.icons = ordered; + localStorage.setItem('itab_icons', JSON.stringify(this.icons)); + }, + deleteIcon(itemId: string) { + const index = this.icons.findIndex(p => p.id === itemId); + if (index !== -1) { + this.icons.splice(index, 1); + // 持久化顺序 + localStorage.setItem('itab_icons', JSON.stringify(this.icons)); + } + }, + } +}); diff --git a/app/src/store/useUIStore.ts b/app/src/store/useUIStore.ts new file mode 100644 index 0000000..6a41c6e --- /dev/null +++ b/app/src/store/useUIStore.ts @@ -0,0 +1,40 @@ +import { defineStore } from 'pinia'; + +interface ContextMenuState { + isOpen: boolean; + x: number; + y: number; + itemId: string | null; + itemType?: 'icon' | 'widget'; +} + +interface UIState { + contextMenu: ContextMenuState; +} + +export const useUIStore = defineStore('ui', { + state: (): UIState => ({ + contextMenu: { + isOpen: false, + x: 0, + y: 0, + itemId: null, + itemType: 'icon', + } + }), + actions: { + openContextMenu(x: number, y: number, itemId: string, itemType: 'icon' | 'widget') { + this.contextMenu = { + isOpen: true, + x, + y, + itemId, + itemType, + }; + }, + closeContextMenu() { + this.contextMenu.isOpen = false; + this.contextMenu.itemId = null; + }, + }, +}); diff --git a/app/src/store/useWidgetsStore.ts b/app/src/store/useWidgetsStore.ts new file mode 100644 index 0000000..bb5e12e --- /dev/null +++ b/app/src/store/useWidgetsStore.ts @@ -0,0 +1,88 @@ +import { defineStore } from 'pinia'; + +// 组件数据结构 +type WidgetSize = '1x1' | '1x2' | '2x1' | '2x2' | '2x4'; +interface Widget { + id: string; + component: string; // 渲染的组件名 + size: WidgetSize; // 组件尺寸 + gridPosition: { x: number; y: number }; // 网格位置 + data?: any; // 组件数据 +} + +interface WidgetsState { + widgets: Widget[]; +} + +const defaultWidgets: Widget[] = [ + { + id: 'widget-1', + component: 'CalendarWidget', + size: '1x1', + gridPosition: { x: 0, y: 0 } + }, + { + id: 'widget-2', + component: 'HotSearchWidget', + size: '2x1', + gridPosition: { x: 1, y: 0 }, + data: { + tabs: ['百度', '微博', '抖音'], + items: [ + { title: '茅台确认“马茅”包装少写一撇', value: '780.9万' }, + { title: '双休不应成为奢侈品', value: '771.2万' }, + { title: '突破8100亿元这场双向奔赴很燃', value: '761.8万' }, + { title: '第一个2万亿经济大区要来了', value: '752.2万' } + ] + } + }, + { + id: 'widget-3', + component: 'CountdownWidget', + size: '2x1', + gridPosition: { x: 0, y: 1 } + } +]; + +const savedWidgets = localStorage.getItem('itab_widgets'); + +// 模拟数据(来自截图参考) +export const useWidgetsStore = defineStore('widgets', { + state: (): WidgetsState => ({ + widgets: savedWidgets ? JSON.parse(savedWidgets) : defaultWidgets, + }), + actions: { + updateWidgetSize(widgetId: string, newSize: WidgetSize) { + const widget = this.widgets.find(w => w.id === widgetId); + if (widget) { + widget.size = newSize; + localStorage.setItem('itab_widgets', JSON.stringify(this.widgets)); + } + }, + updateWidgetPosition(widgetId: string, x: number, y: number) { + const widget = this.widgets.find(w => w.id === widgetId); + if (widget) { + widget.gridPosition = { x, y }; + localStorage.setItem('itab_widgets', JSON.stringify(this.widgets)); + } + }, + setWidgetOrder(orderIds: string[]) { + const ordered: Widget[] = []; + const seen = new Set(); + for (const id of orderIds) { + const widget = this.widgets.find(item => item.id === id); + if (widget) { + ordered.push(widget); + seen.add(widget.id); + } + } + for (const widget of this.widgets) { + if (!seen.has(widget.id)) { + ordered.push(widget); + } + } + this.widgets = ordered; + localStorage.setItem('itab_widgets', JSON.stringify(this.widgets)); + } + } +}); diff --git a/app/src/styles/global.scss b/app/src/styles/global.scss new file mode 100644 index 0000000..d249e56 --- /dev/null +++ b/app/src/styles/global.scss @@ -0,0 +1,49 @@ +@import './tokens.scss'; + +// 样式重置 +*, +*::before, +*::after { + box-sizing: border-box; + margin: 0; + padding: 0; +} + +// 全局样式 +html, body { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; + color: $color-text-primary; + background-color: $color-background; + overscroll-behavior: none; +} + +body { + width: 100vw; + height: 100vh; + overflow: hidden; +} + +#app { + width: 100%; + height: 100%; + background: radial-gradient(ellipse at bottom, #1b2735 0%, #090a0f 100%); +} + +// 滚动条样式 +::-webkit-scrollbar { + width: 6px; + height: 6px; +} + +::-webkit-scrollbar-track { + background: transparent; +} + +::-webkit-scrollbar-thumb { + background: rgba(255, 255, 255, 0.2); + border-radius: 3px; +} + +::-webkit-scrollbar-thumb:hover { + background: rgba(255, 255, 255, 0.3); +} diff --git a/app/src/styles/tokens.scss b/app/src/styles/tokens.scss new file mode 100644 index 0000000..00e5a56 --- /dev/null +++ b/app/src/styles/tokens.scss @@ -0,0 +1,38 @@ +// 样式变量定义 + +// 颜色 +$color-background: #121212; +$color-text-primary: #ffffff; +$color-text-secondary: #a9a9a9; +$color-accent: #ff9500; + +// 表面颜色(用于卡片、弹窗等) +$color-surface-1: rgba(30, 30, 30, 0.7); +$color-surface-2: rgba(45, 45, 45, 0.7); + +// 毛玻璃效果(云母/亚克力) +$backdrop-filter-blur: 16px; +$backdrop-filter-saturation: 180%; + +// 几何尺寸 +$border-radius-small: var(--radius-sm); +$border-radius-medium: var(--radius-md); +$border-radius-large: var(--radius-lg); +$grid-gap: var(--grid-gap); + +// 阴影(轻拟物) +$shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(0, 0, 0, 0.06); +$shadow-md: 0 4px 6px rgba(0, 0, 0, 0.1), 0 2px 4px rgba(0, 0, 0, 0.06); +$shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.1), 0 4px 6px rgba(0, 0, 0, 0.07); + +// 动画 +$motion-duration-sm: 0.2s; +$motion-duration-md: 0.3s; +$motion-easing-standard: cubic-bezier(0.4, 0, 0.2, 1); + +// 层级 +$z-index-base: 0; +$z-index-content: 1; +$z-index-sidebar: 100; +$z-index-modal: 200; +$z-index-menu: 300; diff --git a/app/src/types/muuri.d.ts b/app/src/types/muuri.d.ts new file mode 100644 index 0000000..f96c8df --- /dev/null +++ b/app/src/types/muuri.d.ts @@ -0,0 +1 @@ +declare module 'muuri'; diff --git a/app/src/utils/disableDefaultBehaviors.ts b/app/src/utils/disableDefaultBehaviors.ts new file mode 100644 index 0000000..157acfb --- /dev/null +++ b/app/src/utils/disableDefaultBehaviors.ts @@ -0,0 +1,36 @@ +// 禁用浏览器默认交互(右键菜单、文本选择、拖拽)。 + +const isEditableTarget = (target: EventTarget | null) => { + if (!(target instanceof HTMLElement)) return false; + if (target.isContentEditable) return true; + const tag = target.tagName.toLowerCase(); + return tag === 'input' || tag === 'textarea' || tag === 'select'; +}; + +export const disableDefaultBehaviors = () => { + document.addEventListener( + 'contextmenu', + (event) => { + event.preventDefault(); + }, + { capture: true } + ); + + document.addEventListener( + 'selectstart', + (event) => { + if (isEditableTarget(event.target)) return; + event.preventDefault(); + }, + { capture: true } + ); + + document.addEventListener( + 'dragstart', + (event) => { + if (isEditableTarget(event.target)) return; + event.preventDefault(); + }, + { capture: true } + ); +}; diff --git a/app/tsconfig.json b/app/tsconfig.json new file mode 100644 index 0000000..fd6f0ce --- /dev/null +++ b/app/tsconfig.json @@ -0,0 +1,31 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "module": "ESNext", + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "preserve", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + + /* Aliases */ + "baseUrl": ".", + "paths": { + "@/*": ["src/*"] + } + }, + "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"], + "references": [{ "path": "./tsconfig.node.json" }] +} diff --git a/app/tsconfig.node.json b/app/tsconfig.node.json new file mode 100644 index 0000000..42872c5 --- /dev/null +++ b/app/tsconfig.node.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/app/vite.config.ts b/app/vite.config.ts new file mode 100644 index 0000000..cf60ce1 --- /dev/null +++ b/app/vite.config.ts @@ -0,0 +1,13 @@ +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import path from 'path' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [vue()], + resolve: { + alias: { + '@': path.resolve(__dirname, './src'), + }, + }, +}) diff --git a/wechat_2026-01-22_152229_725.png b/wechat_2026-01-22_152229_725.png new file mode 100644 index 0000000..fed7c90 Binary files /dev/null and b/wechat_2026-01-22_152229_725.png differ diff --git a/wechat_2026-01-22_173911_794.png b/wechat_2026-01-22_173911_794.png new file mode 100644 index 0000000..4df4d59 Binary files /dev/null and b/wechat_2026-01-22_173911_794.png differ diff --git a/产品设计.md b/产品设计.md new file mode 100644 index 0000000..598b414 --- /dev/null +++ b/产品设计.md @@ -0,0 +1,223 @@ +# Prompt:itab 风格“逻辑型交互”完整多端项目(Extension + Web + Mobile H5)架构与 UI 交互实现方案(SCSS) +> 技术栈:Vite + Vue3 + TypeScript + Pinia + SCSS +> 目标:交互完整、符合 itab 这类“逻辑型工作台”的使用习惯;UI/交互都能跑通(后端接口先 mock),支持插件 New Tab + Web 预览 + 移动端 H5。 +> 风格:iOS 扁平化 + 轻拟物(圆角/阴影/磨砂)+ 丝滑动画 +> 规范:统一样式放全局 SCSS,组件目录 `ComponentName/index.vue + index.scss` +> 补充:Icon/Widget 下方都有 label(单行省略,Icon 必须可重命名) + +--- + +## 0) 你必须理解“符合 itab 的逻辑型交互”是什么意思(必须按此实现) +itab 类产品的核心不是“能拖就行”,而是**工作台逻辑**:用户进入新标签页后,第一时间完成“搜索/打开网站/查看信息/快速编辑”,交互必须满足: +1) **默认浏览模式是“可用态”**:点击即打开、滚动即查看;不会因为可拖拽导致误触。 +2) **编辑模式是“布局态”**:所有拖拽、尺寸、删除、批量操作只发生在编辑模式,且有明显工具条与控件。 +3) **行为一致**:空白处/元素处右键菜单内容合理分层;同一入口在桌面与移动端有等价替代(右键=长按)。 +4) **轻干扰但明确反馈**:toast、状态条、占位符、落位动画都要“轻”,不要吓人但要清晰。 +5) **数据先本地后同步**:首屏永远本地秒开;同步/登录只影响“增强能力”,不阻断使用。 +6) **组件是“卡片 + label”**:label 是信息结构的一部分(命名/识别),不是装饰;重命名入口必须自然(右键/设置/编辑态)。 + +--- + +## 强约束(必须遵守) +1) 三端同源代码:Web/Extension/Mobile H5 共用同一套 Vue3 + Pinia 业务代码;通过 build target/adapter 区分环境。 +2) Web 可直接预览:无需插件即可体验完整 UI/交互。 +3) Pinia 必须作为核心状态管理:避免 props 风暴。业务状态/交互状态/弹窗菜单状态必须进 store。 +4) 禁止第三方拖拽/网格库:不得使用 react-grid-layout、gridstack、interact.js;网格拖拽必须原生:Pointer Events + rAF + transform + 自研 push-down/compact。 +5) 仅鼠标/触控交互:不需要键盘辅助。 +6) 元素规则固定: + - Icon:固定 `1×1`,可移动/编辑/删除/锁定;不可缩放。 + - Widget:尺寸只能切换:`1×1, 1×2, 2×1, 2×2, 2×4`(离散)。 +7) 每个元素都有 label:单行省略;Icon 必须支持重命名(Widget 可选)。 +8) 组件封装目录强制:`ComponentName/index.vue + index.scss`。 +9) 统一样式:全局 SCSS(`global.scss`)集中 token,组件局部 SCSS 只能引用 token。 +10) 丝滑动画:必须给出统一动效体系,所有交互动效使用同一套 motion token。 + +--- + +# 你需要输出的 Markdown 文档结构(必须严格按顺序) + +## 1. 产品与交互总览(itab 逻辑型) +- 用户进入新标签页的 3 个主任务路径(例如:搜索→打开;快速访问→打开;查看组件→轻操作) +- “浏览模式/编辑模式”的设计原则与对用户心智的解释 +- 一致性原则:桌面/移动端等价交互映射(右键=长按) + +## 2. 信息架构 IA(页面/面板/弹窗/菜单:必须完整) +必须列出所有入口并写: +- 触发方式(按钮/右键/长按/侧边栏) +- 承载容器(面板/弹窗/抽屉/路由页) +- 关闭方式(点击遮罩、返回、关闭按钮) +- 与主页面的关系(是否阻断、是否保留状态) + +至少包含: +- 主页面(搜索栏 + 网格 + 侧边栏) +- 侧边栏面板:账号、组件库、设置、主题/壁纸、同步中心、帮助/关于 +- 弹窗:登录、添加/编辑 Icon、Widget 设置、导入导出、确认删除 +- 菜单:空白右键、Icon 右键、Widget 右键(移动端长按 ActionSheet) +- Onboarding 新手引导(首次进入) + +## 3. 关键交互规范(必须写到“照着就能实现”,并符合 itab 逻辑) +### 3.1 浏览模式(默认态) +必须定义: +- 点击 Icon:打开链接(新标签/当前标签策略写清,可在设置里切换) +- 点击 Widget:进入 widget 的“轻交互”(如滚动、按钮刷新、查看详情);不触发拖拽 +- 点击 label:默认与点击卡片一致(或只选中,不打开——你必须选一个并解释为啥更像 itab) +- hover/pressed 反馈:阴影、缩放、光泽(轻拟物) +- 空白处点击:取消选中、关闭菜单 + +### 3.2 编辑模式(布局态) +必须定义: +- 进入/退出入口(顶部工具条/侧边栏开关/右键菜单) +- 编辑模式视觉: + - 网格底纹 + - 卡片工具按钮(锁定/删除/设置/尺寸) + - 选中态描边 +- 编辑模式操作: + - 拖拽移动(只允许从手柄触发,label 不触发拖拽) + - Widget 尺寸切换(五档 size picker) + - 多元素管理(至少支持:批量删除 或 批量锁定 任选其一;若不做必须说明原因) +- 编辑模式退出后:自动保存布局,toast 提示(轻提示) + +### 3.3 右键菜单(itab 逻辑:层级清晰、动作合理) +必须分别定义: +1) 空白处右键菜单 +2) Icon 右键菜单 +3) Widget 右键菜单 +对每一项写:名称/图标/动作/是否二级菜单/是否需要确认。 + +必须包含与 itab 逻辑一致的动作集合(可微调但要齐全): +- 空白:添加 Icon、添加 Widget、进入/退出编辑模式、主题/壁纸、布局设置(compact/网格密度)、导入导出、同步中心、帮助/关于 +- Icon:打开、在新标签打开(或设置项控制)、编辑(含重命名)、更换图标、复制链接、删除、锁定/解锁 +- Widget:刷新、设置、尺寸(五档二级菜单)、复制配置(mock)、删除、锁定/解锁 + +移动端替代: +- 长按空白/元素 → ActionSheet(同菜单项结构) + +### 3.4 侧边栏(工作台逻辑:主入口集合) +必须定义: +- 桌面侧边栏开合(overlay + 磨砂背景) +- 分区:账号区(头像/登录态)、快捷区(编辑/同步/主题)、面板区(组件库/设置/主题/同步) +- 面板切换动效与状态保留(切换后保留滚动位置与筛选条件) +- 与编辑模式联动:进入编辑模式时自动打开“组件库/布局设置”面板(或保持上次面板——你必须选一个并解释) + +移动端: +- 侧边栏替代形态(建议全屏面板或底部抽屉),写清返回逻辑与层级管理 + +### 3.5 Label(逻辑型识别与管理) +必须定义: +- label 视觉:单行省略、对齐、间距(使用全局 label token) +- label 的交互: + - 浏览模式:点击 label 的行为(与卡片一致 or 仅选中) + - 编辑模式:label 不触发拖拽;重命名入口(至少 Icon) +- label 与布局关系: + - 网格占用只算卡片(w×h),label 是视觉附属 + - 像素渲染要加固定 labelHeight,避免视觉重叠(写公式) + +--- + +## 4. 工程架构(Vite + Vue3 + TS + Pinia,多端同源) +### 4.1 Monorepo 目录结构(必须可落地) +给出目录树并解释职责,要求包含: +- apps/web、apps/extension、apps/mobile(可选) +- packages/core、ui、engine、widgets、shared +- 每个模块的职责边界与依赖方向(禁止环依赖) + +### 4.2 组件文件组织(必须符合你的封装规范) +- 每个组件一个文件夹:`ComponentName/index.vue` + `index.scss` +- UI 基础组件与业务组件放置规则 +- 示例:Sidebar/ContextMenu/GridCanvas/IconTile/WidgetCard/Label + +--- + +## 5. Pinia 设计(避免 props 风暴,必须非常具体) +### 5.1 Store 拆分与字段(必须给清单) +至少包含: +- useLayoutStore:items、layoutsByBreakpoint、editMode、selectedId、dragState、compactEnabled、gridConfig +- useUIStore:sidebarOpen、activePanel、dialogs、toasts、contextMenuState、actionSheetState(移动端)、overlayStack +- useAuthStore:user、token(mock)、status +- useSettingsStore:theme、wallpaper、searchEngine、openLinkBehavior、gridDensity、motionLevel(可选) +- useWidgetsStore:registry、instances、schemas、mockData +- useSyncStore:syncState(mock)、lastSyncAt、conflictFlag +- useOnboardingStore:hasSeen、steps、currentStep + +必须写: +- 哪些组件只通过 store 取数据(容器组件) +- 哪些组件允许 props(纯展示) +- 如何避免 store 间耦合:通过 services/adapters 作为协调层 + +--- + +## 6. UI 风格与全局 SCSS(必须能“一处改全局”) +### 6.1 global.scss 结构与 tokens(必须详细) +- tokens.scss:SCSS 变量 + :root CSS variables 映射(推荐双层) +- reset/base/utilities/components +- 必须列出 token 分类与命名规则(颜色/圆角/阴影/动效/间距/层级/label) + +### 6.2 通用组件样式(必须给示例) +- Card、Button、Menu、Drawer、Modal、Toast、Label 的通用 class 示例(引用 token) +- pressed/hover 状态的阴影与轻缩放 +- 磨砂背景 class(带降级) + +--- + +## 7. 动效体系(必须体现“丝滑”与一致性) +- motion token:duration/easing +- 菜单/抽屉/弹窗/落位动画统一规则 +- 拖拽落位动画:松手后卡片过渡到最终位置(transform 过渡) +- 避免卡顿策略:只动 transform/opacity/box-shadow + +--- + +## 8. 网格布局引擎(原生算法,必须给伪代码) +必须包含并解释: +- collides(a,b) +- clampRect(rect, cols) +- resolvePushDown(target, items, cols):队列迭代 + 固定排序 + icon 优先被推挤 +- compactIcons(items, cols):icon-only compact(可配置) +- findFirstFit(size, items, cols, startY) +并写清: +- 拖动中:transform + placeholder +- 松手 commit:resolve + compact + save + 落位动画 +- labelHeight 的像素渲染处理公式 + +--- + +## 9. Mock 与持久化(IndexedDB) +- 表:layout/settings/user/widgetsData/onboarding +- 迁移:version + migrations +- mock 登录、mock 同步、mock widget 刷新、模拟网络失败开关 +- 导入导出 JSON(包含 label) + +--- + +## 10. 逐功能实现清单(必须覆盖 itab 常见功能) +用“功能 → UI 入口 → 交互流程 → store 字段变化 → 组件列表”形式写清: +- 搜索(引擎切换、输入框动效、建议 mock) +- Icon 管理(添加/编辑/重命名/更换图标/删除/锁定) +- Widget 管理(添加/设置/刷新/尺寸切换/删除/锁定) +- 主题/壁纸(选择、预览、应用、随机切换 mock) +- 设置(布局设置、打开链接行为、动效强度、隐私) +- 同步中心(mock) +- Onboarding 引导(高亮与遮罩) +- Toast/错误态/空态 + +--- + +## 11. 验收标准(至少 35 条,必须体现“符合 itab 逻辑型交互”) +必须覆盖: +- 默认浏览模式不误触拖拽,点击即打开/查看 +- 编辑模式才可拖拽与改尺寸,退出自动保存 +- 右键菜单/长按菜单结构合理、定位正确、动效顺滑 +- 侧边栏作为“主入口集合”逻辑清晰 +- label 显示与重命名流程自然(至少 Icon) +- 全局 SCSS 改 token 可全局换肤(圆角/阴影/颜色/动效) +- Web 可预览、Extension 可运行、H5 交互等价(右键=长按) +- 性能:TTI、拖拽帧率、commit 耗时可观测(本地开发面板) + +--- + +## 输出要求(必须) +- 输出必须是 Markdown +- 不要空话:给参数(cols/rowHeight/gap/snap阈值/labelHeight/动画时长) +- Pinia 设计要清晰,避免 props 风暴 +- 拖拽网格必须自研原生算法 +- 登录/同步/刷新均 mock,但 UI/交互要完整可实现