diff --git a/bun.lock b/bun.lock new file mode 100644 index 0000000..20ea76e --- /dev/null +++ b/bun.lock @@ -0,0 +1,832 @@ +{ + "lockfileVersion": 1, + "configVersion": 0, + "workspaces": { + "": { + "name": "offstyles-web", + "dependencies": { + "@headlessui/vue": "^1.7.23", + "@tailwindcss/vite": "^4.1.11", + "gl-matrix": "^3.4.4", + "tailwindcss": "^4.1.11", + "vite-plugin-wasm": "^3.5.0", + "vue": "^3.5.13", + "vue-router": "^4.5.0", + }, + "devDependencies": { + "@tsconfig/node22": "^22.0.1", + "@types/node": "^22.14.0", + "@vitejs/plugin-vue": "^5.2.3", + "@vue/eslint-config-typescript": "^14.5.0", + "@vue/tsconfig": "^0.7.0", + "eslint": "^9.22.0", + "eslint-plugin-vue": "~10.0.0", + "jiti": "^2.4.2", + "npm-run-all2": "^7.0.2", + "typescript": "~5.8.0", + "vite": "^6.2.4", + "vite-plugin-vue-devtools": "^7.7.2", + "vue-tsc": "^2.2.8", + }, + }, + }, + "packages": { + "@ampproject/remapping": ["@ampproject/remapping@2.3.0", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw=="], + + "@antfu/utils": ["@antfu/utils@0.7.10", "", {}, "sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww=="], + + "@babel/code-frame": ["@babel/code-frame@7.27.1", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg=="], + + "@babel/compat-data": ["@babel/compat-data@7.27.5", "", {}, "sha512-KiRAp/VoJaWkkte84TvUd9qjdbZAdiqyvMxrGl1N6vzFogKmaLgoM3L1kgtLicp2HP5fBJS8JrZKLVIZGVJAVg=="], + + "@babel/core": ["@babel/core@7.27.4", "", { "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.27.3", "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-module-transforms": "^7.27.3", "@babel/helpers": "^7.27.4", "@babel/parser": "^7.27.4", "@babel/template": "^7.27.2", "@babel/traverse": "^7.27.4", "@babel/types": "^7.27.3", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-bXYxrXFubeYdvB0NhD/NBB3Qi6aZeV20GOWVI47t2dkecCEoneR4NPVcb7abpXDEvejgrUfFtG6vG/zxAKmg+g=="], + + "@babel/generator": ["@babel/generator@7.27.5", "", { "dependencies": { "@babel/parser": "^7.27.5", "@babel/types": "^7.27.3", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" } }, "sha512-ZGhA37l0e/g2s1Cnzdix0O3aLYm66eF8aufiVteOgnwxgnRP8GoyMj7VWsgWnQbVKXyge7hqrFh2K2TQM6t1Hw=="], + + "@babel/helper-annotate-as-pure": ["@babel/helper-annotate-as-pure@7.27.3", "", { "dependencies": { "@babel/types": "^7.27.3" } }, "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg=="], + + "@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.27.2", "", { "dependencies": { "@babel/compat-data": "^7.27.2", "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ=="], + + "@babel/helper-create-class-features-plugin": ["@babel/helper-create-class-features-plugin@7.27.1", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.1", "@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/helper-skip-transparent-expression-wrappers": "^7.27.1", "@babel/traverse": "^7.27.1", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-QwGAmuvM17btKU5VqXfb+Giw4JcN0hjuufz3DYnpeVDvZLAObloM77bhMXiqry3Iio+Ai4phVRDwl6WU10+r5A=="], + + "@babel/helper-member-expression-to-functions": ["@babel/helper-member-expression-to-functions@7.27.1", "", { "dependencies": { "@babel/traverse": "^7.27.1", "@babel/types": "^7.27.1" } }, "sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA=="], + + "@babel/helper-module-imports": ["@babel/helper-module-imports@7.27.1", "", { "dependencies": { "@babel/traverse": "^7.27.1", "@babel/types": "^7.27.1" } }, "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w=="], + + "@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.27.3", "", { "dependencies": { "@babel/helper-module-imports": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1", "@babel/traverse": "^7.27.3" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg=="], + + "@babel/helper-optimise-call-expression": ["@babel/helper-optimise-call-expression@7.27.1", "", { "dependencies": { "@babel/types": "^7.27.1" } }, "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw=="], + + "@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.27.1", "", {}, "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw=="], + + "@babel/helper-replace-supers": ["@babel/helper-replace-supers@7.27.1", "", { "dependencies": { "@babel/helper-member-expression-to-functions": "^7.27.1", "@babel/helper-optimise-call-expression": "^7.27.1", "@babel/traverse": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA=="], + + "@babel/helper-skip-transparent-expression-wrappers": ["@babel/helper-skip-transparent-expression-wrappers@7.27.1", "", { "dependencies": { "@babel/traverse": "^7.27.1", "@babel/types": "^7.27.1" } }, "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg=="], + + "@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], + + "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.27.1", "", {}, "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="], + + "@babel/helper-validator-option": ["@babel/helper-validator-option@7.27.1", "", {}, "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg=="], + + "@babel/helpers": ["@babel/helpers@7.27.6", "", { "dependencies": { "@babel/template": "^7.27.2", "@babel/types": "^7.27.6" } }, "sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug=="], + + "@babel/parser": ["@babel/parser@7.27.5", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": { "parser": "bin/babel-parser.js" } }, "sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg=="], + + "@babel/plugin-proposal-decorators": ["@babel/plugin-proposal-decorators@7.27.1", "", { "dependencies": { "@babel/helper-create-class-features-plugin": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1", "@babel/plugin-syntax-decorators": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-DTxe4LBPrtFdsWzgpmbBKevg3e9PBy+dXRt19kSbucbZvL2uqtdqwwpluL1jfxYE0wIDTFp1nTy/q6gNLsxXrg=="], + + "@babel/plugin-syntax-decorators": ["@babel/plugin-syntax-decorators@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-YMq8Z87Lhl8EGkmb0MwYkt36QnxC+fzCgrl66ereamPlYToRpIk5nUjKUY3QKLWq8mwUB1BgbeXcTJhZOCDg5A=="], + + "@babel/plugin-syntax-import-attributes": ["@babel/plugin-syntax-import-attributes@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww=="], + + "@babel/plugin-syntax-import-meta": ["@babel/plugin-syntax-import-meta@7.10.4", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g=="], + + "@babel/plugin-syntax-jsx": ["@babel/plugin-syntax-jsx@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w=="], + + "@babel/plugin-syntax-typescript": ["@babel/plugin-syntax-typescript@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ=="], + + "@babel/plugin-transform-typescript": ["@babel/plugin-transform-typescript@7.27.1", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.1", "@babel/helper-create-class-features-plugin": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", "@babel/plugin-syntax-typescript": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-Q5sT5+O4QUebHdbwKedFBEwRLb02zJ7r4A5Gg2hUoLuU3FjdMcyqcywqUrLCaDsFCxzokf7u9kuy7qz51YUuAg=="], + + "@babel/template": ["@babel/template@7.27.2", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/parser": "^7.27.2", "@babel/types": "^7.27.1" } }, "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw=="], + + "@babel/traverse": ["@babel/traverse@7.27.4", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.27.3", "@babel/parser": "^7.27.4", "@babel/template": "^7.27.2", "@babel/types": "^7.27.3", "debug": "^4.3.1", "globals": "^11.1.0" } }, "sha512-oNcu2QbHqts9BtOWJosOVJapWjBDSxGCpFvikNR5TGDYDQf3JwpIoMzIKrvfoti93cLfPJEG4tH9SPVeyCGgdA=="], + + "@babel/types": ["@babel/types@7.27.6", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q=="], + + "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.5", "", { "os": "aix", "cpu": "ppc64" }, "sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA=="], + + "@esbuild/android-arm": ["@esbuild/android-arm@0.25.5", "", { "os": "android", "cpu": "arm" }, "sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA=="], + + "@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.5", "", { "os": "android", "cpu": "arm64" }, "sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg=="], + + "@esbuild/android-x64": ["@esbuild/android-x64@0.25.5", "", { "os": "android", "cpu": "x64" }, "sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw=="], + + "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ=="], + + "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ=="], + + "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.5", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw=="], + + "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.5", "", { "os": "freebsd", "cpu": "x64" }, "sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw=="], + + "@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.5", "", { "os": "linux", "cpu": "arm" }, "sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw=="], + + "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg=="], + + "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.5", "", { "os": "linux", "cpu": "ia32" }, "sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA=="], + + "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.5", "", { "os": "linux", "cpu": "none" }, "sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg=="], + + "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.5", "", { "os": "linux", "cpu": "none" }, "sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg=="], + + "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.5", "", { "os": "linux", "cpu": "ppc64" }, "sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ=="], + + "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.5", "", { "os": "linux", "cpu": "none" }, "sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA=="], + + "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.5", "", { "os": "linux", "cpu": "s390x" }, "sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ=="], + + "@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.5", "", { "os": "linux", "cpu": "x64" }, "sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw=="], + + "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.5", "", { "os": "none", "cpu": "arm64" }, "sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw=="], + + "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.5", "", { "os": "none", "cpu": "x64" }, "sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ=="], + + "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.5", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw=="], + + "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.5", "", { "os": "openbsd", "cpu": "x64" }, "sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg=="], + + "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.5", "", { "os": "sunos", "cpu": "x64" }, "sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA=="], + + "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw=="], + + "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ=="], + + "@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.5", "", { "os": "win32", "cpu": "x64" }, "sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g=="], + + "@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.7.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw=="], + + "@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.1", "", {}, "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ=="], + + "@eslint/config-array": ["@eslint/config-array@0.20.1", "", { "dependencies": { "@eslint/object-schema": "^2.1.6", "debug": "^4.3.1", "minimatch": "^3.1.2" } }, "sha512-OL0RJzC/CBzli0DrrR31qzj6d6i6Mm3HByuhflhl4LOBiWxN+3i6/t/ZQQNii4tjksXi8r2CRW1wMpWA2ULUEw=="], + + "@eslint/config-helpers": ["@eslint/config-helpers@0.2.3", "", {}, "sha512-u180qk2Um1le4yf0ruXH3PYFeEZeYC3p/4wCTKrr2U1CmGdzGi3KtY0nuPDH48UJxlKCC5RDzbcbh4X0XlqgHg=="], + + "@eslint/core": ["@eslint/core@0.14.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg=="], + + "@eslint/eslintrc": ["@eslint/eslintrc@3.3.1", "", { "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" } }, "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ=="], + + "@eslint/js": ["@eslint/js@9.29.0", "", {}, "sha512-3PIF4cBw/y+1u2EazflInpV+lYsSG0aByVIQzAgb1m1MhHFSbqTyNqtBKHgWf/9Ykud+DhILS9EGkmekVhbKoQ=="], + + "@eslint/object-schema": ["@eslint/object-schema@2.1.6", "", {}, "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA=="], + + "@eslint/plugin-kit": ["@eslint/plugin-kit@0.3.2", "", { "dependencies": { "@eslint/core": "^0.15.0", "levn": "^0.4.1" } }, "sha512-4SaFZCNfJqvk/kenHpI8xvN42DMaoycy4PzKc5otHxRswww1kAt82OlBuwRVLofCACCTZEcla2Ydxv8scMXaTg=="], + + "@headlessui/vue": ["@headlessui/vue@1.7.23", "", { "dependencies": { "@tanstack/vue-virtual": "^3.0.0-beta.60" }, "peerDependencies": { "vue": "^3.2.0" } }, "sha512-JzdCNqurrtuu0YW6QaDtR2PIYCKPUWq28csDyMvN4zmGccmE7lz40Is6hc3LA4HFeCI7sekZ/PQMTNmn9I/4Wg=="], + + "@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="], + + "@humanfs/node": ["@humanfs/node@0.16.6", "", { "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.3.0" } }, "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw=="], + + "@humanwhocodes/module-importer": ["@humanwhocodes/module-importer@1.0.1", "", {}, "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="], + + "@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="], + + "@isaacs/fs-minipass": ["@isaacs/fs-minipass@4.0.1", "", { "dependencies": { "minipass": "^7.0.4" } }, "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w=="], + + "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.8", "", { "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA=="], + + "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="], + + "@jridgewell/set-array": ["@jridgewell/set-array@1.2.1", "", {}, "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A=="], + + "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.0", "", {}, "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="], + + "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.25", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ=="], + + "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], + + "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="], + + "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], + + "@polka/url": ["@polka/url@1.0.0-next.29", "", {}, "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww=="], + + "@rollup/pluginutils": ["@rollup/pluginutils@5.1.4", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" } }, "sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ=="], + + "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.43.0", "", { "os": "android", "cpu": "arm" }, "sha512-Krjy9awJl6rKbruhQDgivNbD1WuLb8xAclM4IR4cN5pHGAs2oIMMQJEiC3IC/9TZJ+QZkmZhlMO/6MBGxPidpw=="], + + "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.43.0", "", { "os": "android", "cpu": "arm64" }, "sha512-ss4YJwRt5I63454Rpj+mXCXicakdFmKnUNxr1dLK+5rv5FJgAxnN7s31a5VchRYxCFWdmnDWKd0wbAdTr0J5EA=="], + + "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.43.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-eKoL8ykZ7zz8MjgBenEF2OoTNFAPFz1/lyJ5UmmFSz5jW+7XbH1+MAgCVHy72aG59rbuQLcJeiMrP8qP5d/N0A=="], + + "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.43.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-SYwXJgaBYW33Wi/q4ubN+ldWC4DzQY62S4Ll2dgfr/dbPoF50dlQwEaEHSKrQdSjC6oIe1WgzosoaNoHCdNuMg=="], + + "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.43.0", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-SV+U5sSo0yujrjzBF7/YidieK2iF6E7MdF6EbYxNz94lA+R0wKl3SiixGyG/9Klab6uNBIqsN7j4Y/Fya7wAjQ=="], + + "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.43.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-J7uCsiV13L/VOeHJBo5SjasKiGxJ0g+nQTrBkAsmQBIdil3KhPnSE9GnRon4ejX1XDdsmK/l30IYLiAaQEO0Cg=="], + + "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.43.0", "", { "os": "linux", "cpu": "arm" }, "sha512-gTJ/JnnjCMc15uwB10TTATBEhK9meBIY+gXP4s0sHD1zHOaIh4Dmy1X9wup18IiY9tTNk5gJc4yx9ctj/fjrIw=="], + + "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.43.0", "", { "os": "linux", "cpu": "arm" }, "sha512-ZJ3gZynL1LDSIvRfz0qXtTNs56n5DI2Mq+WACWZ7yGHFUEirHBRt7fyIk0NsCKhmRhn7WAcjgSkSVVxKlPNFFw=="], + + "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.43.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-8FnkipasmOOSSlfucGYEu58U8cxEdhziKjPD2FIa0ONVMxvl/hmONtX/7y4vGjdUhjcTHlKlDhw3H9t98fPvyA=="], + + "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.43.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-KPPyAdlcIZ6S9C3S2cndXDkV0Bb1OSMsX0Eelr2Bay4EsF9yi9u9uzc9RniK3mcUGCLhWY9oLr6er80P5DE6XA=="], + + "@rollup/rollup-linux-loongarch64-gnu": ["@rollup/rollup-linux-loongarch64-gnu@4.43.0", "", { "os": "linux", "cpu": "none" }, "sha512-HPGDIH0/ZzAZjvtlXj6g+KDQ9ZMHfSP553za7o2Odegb/BEfwJcR0Sw0RLNpQ9nC6Gy8s+3mSS9xjZ0n3rhcYg=="], + + "@rollup/rollup-linux-powerpc64le-gnu": ["@rollup/rollup-linux-powerpc64le-gnu@4.43.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-gEmwbOws4U4GLAJDhhtSPWPXUzDfMRedT3hFMyRAvM9Mrnj+dJIFIeL7otsv2WF3D7GrV0GIewW0y28dOYWkmw=="], + + "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.43.0", "", { "os": "linux", "cpu": "none" }, "sha512-XXKvo2e+wFtXZF/9xoWohHg+MuRnvO29TI5Hqe9xwN5uN8NKUYy7tXUG3EZAlfchufNCTHNGjEx7uN78KsBo0g=="], + + "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.43.0", "", { "os": "linux", "cpu": "none" }, "sha512-ruf3hPWhjw6uDFsOAzmbNIvlXFXlBQ4nk57Sec8E8rUxs/AI4HD6xmiiasOOx/3QxS2f5eQMKTAwk7KHwpzr/Q=="], + + "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.43.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-QmNIAqDiEMEvFV15rsSnjoSmO0+eJLoKRD9EAa9rrYNwO/XRCtOGM3A5A0X+wmG+XRrw9Fxdsw+LnyYiZWWcVw=="], + + "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.43.0", "", { "os": "linux", "cpu": "x64" }, "sha512-jAHr/S0iiBtFyzjhOkAics/2SrXE092qyqEg96e90L3t9Op8OTzS6+IX0Fy5wCt2+KqeHAkti+eitV0wvblEoQ=="], + + "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.43.0", "", { "os": "linux", "cpu": "x64" }, "sha512-3yATWgdeXyuHtBhrLt98w+5fKurdqvs8B53LaoKD7P7H7FKOONLsBVMNl9ghPQZQuYcceV5CDyPfyfGpMWD9mQ=="], + + "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.43.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-wVzXp2qDSCOpcBCT5WRWLmpJRIzv23valvcTwMHEobkjippNf+C3ys/+wf07poPkeNix0paTNemB2XrHr2TnGw=="], + + "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.43.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-fYCTEyzf8d+7diCw8b+asvWDCLMjsCEA8alvtAutqJOJp/wL5hs1rWSqJ1vkjgW0L2NB4bsYJrpKkiIPRR9dvw=="], + + "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.43.0", "", { "os": "win32", "cpu": "x64" }, "sha512-SnGhLiE5rlK0ofq8kzuDkM0g7FN1s5VYY+YSMTibP7CqShxCQvqtNxTARS4xX4PFJfHjG0ZQYX9iGzI3FQh5Aw=="], + + "@sec-ant/readable-stream": ["@sec-ant/readable-stream@0.4.1", "", {}, "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg=="], + + "@sindresorhus/merge-streams": ["@sindresorhus/merge-streams@4.0.0", "", {}, "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ=="], + + "@tailwindcss/node": ["@tailwindcss/node@4.1.11", "", { "dependencies": { "@ampproject/remapping": "^2.3.0", "enhanced-resolve": "^5.18.1", "jiti": "^2.4.2", "lightningcss": "1.30.1", "magic-string": "^0.30.17", "source-map-js": "^1.2.1", "tailwindcss": "4.1.11" } }, "sha512-yzhzuGRmv5QyU9qLNg4GTlYI6STedBWRE7NjxP45CsFYYq9taI0zJXZBMqIC/c8fViNLhmrbpSFS57EoxUmD6Q=="], + + "@tailwindcss/oxide": ["@tailwindcss/oxide@4.1.11", "", { "dependencies": { "detect-libc": "^2.0.4", "tar": "^7.4.3" }, "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.1.11", "@tailwindcss/oxide-darwin-arm64": "4.1.11", "@tailwindcss/oxide-darwin-x64": "4.1.11", "@tailwindcss/oxide-freebsd-x64": "4.1.11", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.11", "@tailwindcss/oxide-linux-arm64-gnu": "4.1.11", "@tailwindcss/oxide-linux-arm64-musl": "4.1.11", "@tailwindcss/oxide-linux-x64-gnu": "4.1.11", "@tailwindcss/oxide-linux-x64-musl": "4.1.11", "@tailwindcss/oxide-wasm32-wasi": "4.1.11", "@tailwindcss/oxide-win32-arm64-msvc": "4.1.11", "@tailwindcss/oxide-win32-x64-msvc": "4.1.11" } }, "sha512-Q69XzrtAhuyfHo+5/HMgr1lAiPP/G40OMFAnws7xcFEYqcypZmdW8eGXaOUIeOl1dzPJBPENXgbjsOyhg2nkrg=="], + + "@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.1.11", "", { "os": "android", "cpu": "arm64" }, "sha512-3IfFuATVRUMZZprEIx9OGDjG3Ou3jG4xQzNTvjDoKmU9JdmoCohQJ83MYd0GPnQIu89YoJqvMM0G3uqLRFtetg=="], + + "@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.1.11", "", { "os": "darwin", "cpu": "arm64" }, "sha512-ESgStEOEsyg8J5YcMb1xl8WFOXfeBmrhAwGsFxxB2CxY9evy63+AtpbDLAyRkJnxLy2WsD1qF13E97uQyP1lfQ=="], + + "@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.1.11", "", { "os": "darwin", "cpu": "x64" }, "sha512-EgnK8kRchgmgzG6jE10UQNaH9Mwi2n+yw1jWmof9Vyg2lpKNX2ioe7CJdf9M5f8V9uaQxInenZkOxnTVL3fhAw=="], + + "@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.1.11", "", { "os": "freebsd", "cpu": "x64" }, "sha512-xdqKtbpHs7pQhIKmqVpxStnY1skuNh4CtbcyOHeX1YBE0hArj2romsFGb6yUmzkq/6M24nkxDqU8GYrKrz+UcA=="], + + "@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.1.11", "", { "os": "linux", "cpu": "arm" }, "sha512-ryHQK2eyDYYMwB5wZL46uoxz2zzDZsFBwfjssgB7pzytAeCCa6glsiJGjhTEddq/4OsIjsLNMAiMlHNYnkEEeg=="], + + "@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.1.11", "", { "os": "linux", "cpu": "arm64" }, "sha512-mYwqheq4BXF83j/w75ewkPJmPZIqqP1nhoghS9D57CLjsh3Nfq0m4ftTotRYtGnZd3eCztgbSPJ9QhfC91gDZQ=="], + + "@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.1.11", "", { "os": "linux", "cpu": "arm64" }, "sha512-m/NVRFNGlEHJrNVk3O6I9ggVuNjXHIPoD6bqay/pubtYC9QIdAMpS+cswZQPBLvVvEF6GtSNONbDkZrjWZXYNQ=="], + + "@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.1.11", "", { "os": "linux", "cpu": "x64" }, "sha512-YW6sblI7xukSD2TdbbaeQVDysIm/UPJtObHJHKxDEcW2exAtY47j52f8jZXkqE1krdnkhCMGqP3dbniu1Te2Fg=="], + + "@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.1.11", "", { "os": "linux", "cpu": "x64" }, "sha512-e3C/RRhGunWYNC3aSF7exsQkdXzQ/M+aYuZHKnw4U7KQwTJotnWsGOIVih0s2qQzmEzOFIJ3+xt7iq67K/p56Q=="], + + "@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.1.11", "", { "cpu": "none" }, "sha512-Xo1+/GU0JEN/C/dvcammKHzeM6NqKovG+6921MR6oadee5XPBaKOumrJCXvopJ/Qb5TH7LX/UAywbqrP4lax0g=="], + + "@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.1.11", "", { "os": "win32", "cpu": "arm64" }, "sha512-UgKYx5PwEKrac3GPNPf6HVMNhUIGuUh4wlDFR2jYYdkX6pL/rn73zTq/4pzUm8fOjAn5L8zDeHp9iXmUGOXZ+w=="], + + "@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.1.11", "", { "os": "win32", "cpu": "x64" }, "sha512-YfHoggn1j0LK7wR82TOucWc5LDCguHnoS879idHekmmiR7g9HUtMw9MI0NHatS28u/Xlkfi9w5RJWgz2Dl+5Qg=="], + + "@tailwindcss/vite": ["@tailwindcss/vite@4.1.11", "", { "dependencies": { "@tailwindcss/node": "4.1.11", "@tailwindcss/oxide": "4.1.11", "tailwindcss": "4.1.11" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7" } }, "sha512-RHYhrR3hku0MJFRV+fN2gNbDNEh3dwKvY8XJvTxCSXeMOsCRSr+uKvDWQcbizrHgjML6ZmTE5OwMrl5wKcujCw=="], + + "@tanstack/virtual-core": ["@tanstack/virtual-core@3.13.10", "", {}, "sha512-sPEDhXREou5HyZYqSWIqdU580rsF6FGeN7vpzijmP3KTiOGjOMZASz4Y6+QKjiFQwhWrR58OP8izYaNGVxvViA=="], + + "@tanstack/vue-virtual": ["@tanstack/vue-virtual@3.13.10", "", { "dependencies": { "@tanstack/virtual-core": "3.13.10" }, "peerDependencies": { "vue": "^2.7.0 || ^3.0.0" } }, "sha512-1UZmUiMNyKxQ1JFPtO3rfRmK7IuLYwfj/foPC7FVWj6yHand4ry5joFh8LQ1Ckm7Dfe/08cv6LKZNc4WYj7hxQ=="], + + "@tsconfig/node22": ["@tsconfig/node22@22.0.2", "", {}, "sha512-Kmwj4u8sDRDrMYRoN9FDEcXD8UpBSaPQQ24Gz+Gamqfm7xxn+GBR7ge/Z7pK8OXNGyUzbSwJj+TH6B+DS/epyA=="], + + "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], + + "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], + + "@types/node": ["@types/node@22.15.31", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-jnVe5ULKl6tijxUhvQeNbQG/84fHfg+yMak02cT8QVhBx/F05rAVxCGBYYTh2EKz22D6JF5ktXuNwdx7b9iEGw=="], + + "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.34.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.34.0", "@typescript-eslint/type-utils": "8.34.0", "@typescript-eslint/utils": "8.34.0", "@typescript-eslint/visitor-keys": "8.34.0", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.34.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-QXwAlHlbcAwNlEEMKQS2RCgJsgXrTJdjXT08xEgbPFa2yYQgVjBymxP5DrfrE7X7iodSzd9qBUHUycdyVJTW1w=="], + + "@typescript-eslint/parser": ["@typescript-eslint/parser@8.34.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.34.0", "@typescript-eslint/types": "8.34.0", "@typescript-eslint/typescript-estree": "8.34.0", "@typescript-eslint/visitor-keys": "8.34.0", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-vxXJV1hVFx3IXz/oy2sICsJukaBrtDEQSBiV48/YIV5KWjX1dO+bcIr/kCPrW6weKXvsaGKFNlwH0v2eYdRRbA=="], + + "@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.34.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.34.0", "@typescript-eslint/types": "^8.34.0", "debug": "^4.3.4" }, "peerDependencies": { "typescript": ">=4.8.4 <5.9.0" } }, "sha512-iEgDALRf970/B2YExmtPMPF54NenZUf4xpL3wsCRx/lgjz6ul/l13R81ozP/ZNuXfnLCS+oPmG7JIxfdNYKELw=="], + + "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.34.0", "", { "dependencies": { "@typescript-eslint/types": "8.34.0", "@typescript-eslint/visitor-keys": "8.34.0" } }, "sha512-9Ac0X8WiLykl0aj1oYQNcLZjHgBojT6cW68yAgZ19letYu+Hxd0rE0veI1XznSSst1X5lwnxhPbVdwjDRIomRw=="], + + "@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.34.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <5.9.0" } }, "sha512-+W9VYHKFIzA5cBeooqQxqNriAP0QeQ7xTiDuIOr71hzgffm3EL2hxwWBIIj4GuofIbKxGNarpKqIq6Q6YrShOA=="], + + "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.34.0", "", { "dependencies": { "@typescript-eslint/typescript-estree": "8.34.0", "@typescript-eslint/utils": "8.34.0", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-n7zSmOcUVhcRYC75W2pnPpbO1iwhJY3NLoHEtbJwJSNlVAZuwqu05zY3f3s2SDWWDSo9FdN5szqc73DCtDObAg=="], + + "@typescript-eslint/types": ["@typescript-eslint/types@8.34.0", "", {}, "sha512-9V24k/paICYPniajHfJ4cuAWETnt7Ssy+R0Rbcqo5sSFr3QEZ/8TSoUi9XeXVBGXCaLtwTOKSLGcInCAvyZeMA=="], + + "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.34.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.34.0", "@typescript-eslint/tsconfig-utils": "8.34.0", "@typescript-eslint/types": "8.34.0", "@typescript-eslint/visitor-keys": "8.34.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "typescript": ">=4.8.4 <5.9.0" } }, "sha512-rOi4KZxI7E0+BMqG7emPSK1bB4RICCpF7QD3KCLXn9ZvWoESsOMlHyZPAHyG04ujVplPaHbmEvs34m+wjgtVtg=="], + + "@typescript-eslint/utils": ["@typescript-eslint/utils@8.34.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", "@typescript-eslint/scope-manager": "8.34.0", "@typescript-eslint/types": "8.34.0", "@typescript-eslint/typescript-estree": "8.34.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-8L4tWatGchV9A1cKbjaavS6mwYwp39jql8xUmIIKJdm+qiaeHy5KMKlBrf30akXAWBzn2SqKsNOtSENWUwg7XQ=="], + + "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.34.0", "", { "dependencies": { "@typescript-eslint/types": "8.34.0", "eslint-visitor-keys": "^4.2.0" } }, "sha512-qHV7pW7E85A0x6qyrFn+O+q1k1p3tQCsqIZ1KZ5ESLXY57aTvUd3/a4rdPTeXisvhXn2VQG0VSKUqs8KHF2zcA=="], + + "@vitejs/plugin-vue": ["@vitejs/plugin-vue@5.2.4", "", { "peerDependencies": { "vite": "^5.0.0 || ^6.0.0", "vue": "^3.2.25" } }, "sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA=="], + + "@volar/language-core": ["@volar/language-core@2.4.14", "", { "dependencies": { "@volar/source-map": "2.4.14" } }, "sha512-X6beusV0DvuVseaOEy7GoagS4rYHgDHnTrdOj5jeUb49fW5ceQyP9Ej5rBhqgz2wJggl+2fDbbojq1XKaxDi6w=="], + + "@volar/source-map": ["@volar/source-map@2.4.14", "", {}, "sha512-5TeKKMh7Sfxo8021cJfmBzcjfY1SsXsPMMjMvjY7ivesdnybqqS+GxGAoXHAOUawQTwtdUxgP65Im+dEmvWtYQ=="], + + "@volar/typescript": ["@volar/typescript@2.4.14", "", { "dependencies": { "@volar/language-core": "2.4.14", "path-browserify": "^1.0.1", "vscode-uri": "^3.0.8" } }, "sha512-p8Z6f/bZM3/HyCdRNFZOEEzts51uV8WHeN8Tnfnm2EBv6FDB2TQLzfVx7aJvnl8ofKAOnS64B2O8bImBFaauRw=="], + + "@vue/babel-helper-vue-transform-on": ["@vue/babel-helper-vue-transform-on@1.4.0", "", {}, "sha512-mCokbouEQ/ocRce/FpKCRItGo+013tHg7tixg3DUNS+6bmIchPt66012kBMm476vyEIJPafrvOf4E5OYj3shSw=="], + + "@vue/babel-plugin-jsx": ["@vue/babel-plugin-jsx@1.4.0", "", { "dependencies": { "@babel/helper-module-imports": "^7.25.9", "@babel/helper-plugin-utils": "^7.26.5", "@babel/plugin-syntax-jsx": "^7.25.9", "@babel/template": "^7.26.9", "@babel/traverse": "^7.26.9", "@babel/types": "^7.26.9", "@vue/babel-helper-vue-transform-on": "1.4.0", "@vue/babel-plugin-resolve-type": "1.4.0", "@vue/shared": "^3.5.13" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-9zAHmwgMWlaN6qRKdrg1uKsBKHvnUU+Py+MOCTuYZBoZsopa90Di10QRjB+YPnVss0BZbG/H5XFwJY1fTxJWhA=="], + + "@vue/babel-plugin-resolve-type": ["@vue/babel-plugin-resolve-type@1.4.0", "", { "dependencies": { "@babel/code-frame": "^7.26.2", "@babel/helper-module-imports": "^7.25.9", "@babel/helper-plugin-utils": "^7.26.5", "@babel/parser": "^7.26.9", "@vue/compiler-sfc": "^3.5.13" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-4xqDRRbQQEWHQyjlYSgZsWj44KfiF6D+ktCuXyZ8EnVDYV3pztmXJDf1HveAjUAXxAnR8daCQT51RneWWxtTyQ=="], + + "@vue/compiler-core": ["@vue/compiler-core@3.5.16", "", { "dependencies": { "@babel/parser": "^7.27.2", "@vue/shared": "3.5.16", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" } }, "sha512-AOQS2eaQOaaZQoL1u+2rCJIKDruNXVBZSiUD3chnUrsoX5ZTQMaCvXlWNIfxBJuU15r1o7+mpo5223KVtIhAgQ=="], + + "@vue/compiler-dom": ["@vue/compiler-dom@3.5.16", "", { "dependencies": { "@vue/compiler-core": "3.5.16", "@vue/shared": "3.5.16" } }, "sha512-SSJIhBr/teipXiXjmWOVWLnxjNGo65Oj/8wTEQz0nqwQeP75jWZ0n4sF24Zxoht1cuJoWopwj0J0exYwCJ0dCQ=="], + + "@vue/compiler-sfc": ["@vue/compiler-sfc@3.5.16", "", { "dependencies": { "@babel/parser": "^7.27.2", "@vue/compiler-core": "3.5.16", "@vue/compiler-dom": "3.5.16", "@vue/compiler-ssr": "3.5.16", "@vue/shared": "3.5.16", "estree-walker": "^2.0.2", "magic-string": "^0.30.17", "postcss": "^8.5.3", "source-map-js": "^1.2.1" } }, "sha512-rQR6VSFNpiinDy/DVUE0vHoIDUF++6p910cgcZoaAUm3POxgNOOdS/xgoll3rNdKYTYPnnbARDCZOyZ+QSe6Pw=="], + + "@vue/compiler-ssr": ["@vue/compiler-ssr@3.5.16", "", { "dependencies": { "@vue/compiler-dom": "3.5.16", "@vue/shared": "3.5.16" } }, "sha512-d2V7kfxbdsjrDSGlJE7my1ZzCXViEcqN6w14DOsDrUCHEA6vbnVCpRFfrc4ryCP/lCKzX2eS1YtnLE/BuC9f/A=="], + + "@vue/compiler-vue2": ["@vue/compiler-vue2@2.7.16", "", { "dependencies": { "de-indent": "^1.0.2", "he": "^1.2.0" } }, "sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A=="], + + "@vue/devtools-api": ["@vue/devtools-api@6.6.4", "", {}, "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g=="], + + "@vue/devtools-core": ["@vue/devtools-core@7.7.6", "", { "dependencies": { "@vue/devtools-kit": "^7.7.6", "@vue/devtools-shared": "^7.7.6", "mitt": "^3.0.1", "nanoid": "^5.1.0", "pathe": "^2.0.3", "vite-hot-client": "^2.0.4" }, "peerDependencies": { "vue": "^3.0.0" } }, "sha512-ghVX3zjKPtSHu94Xs03giRIeIWlb9M+gvDRVpIZ/cRIxKHdW6HE/sm1PT3rUYS3aV92CazirT93ne+7IOvGUWg=="], + + "@vue/devtools-kit": ["@vue/devtools-kit@7.7.6", "", { "dependencies": { "@vue/devtools-shared": "^7.7.6", "birpc": "^2.3.0", "hookable": "^5.5.3", "mitt": "^3.0.1", "perfect-debounce": "^1.0.0", "speakingurl": "^14.0.1", "superjson": "^2.2.2" } }, "sha512-geu7ds7tem2Y7Wz+WgbnbZ6T5eadOvozHZ23Atk/8tksHMFOFylKi1xgGlQlVn0wlkEf4hu+vd5ctj1G4kFtwA=="], + + "@vue/devtools-shared": ["@vue/devtools-shared@7.7.6", "", { "dependencies": { "rfdc": "^1.4.1" } }, "sha512-yFEgJZ/WblEsojQQceuyK6FzpFDx4kqrz2ohInxNj5/DnhoX023upTv4OD6lNPLAA5LLkbwPVb10o/7b+Y4FVA=="], + + "@vue/eslint-config-typescript": ["@vue/eslint-config-typescript@14.5.0", "", { "dependencies": { "@typescript-eslint/utils": "^8.26.0", "fast-glob": "^3.3.3", "typescript-eslint": "^8.26.0", "vue-eslint-parser": "^10.1.1" }, "peerDependencies": { "eslint": "^9.10.0", "eslint-plugin-vue": "^9.28.0 || ^10.0.0", "typescript": ">=4.8.4" } }, "sha512-5oPOyuwkw++AP5gHDh5YFmST50dPfWOcm3/W7Nbh42IK5O3H74ytWAw0TrCRTaBoD/02khnWXuZf1Bz1xflavQ=="], + + "@vue/language-core": ["@vue/language-core@2.2.10", "", { "dependencies": { "@volar/language-core": "~2.4.11", "@vue/compiler-dom": "^3.5.0", "@vue/compiler-vue2": "^2.7.16", "@vue/shared": "^3.5.0", "alien-signals": "^1.0.3", "minimatch": "^9.0.3", "muggle-string": "^0.4.1", "path-browserify": "^1.0.1" }, "peerDependencies": { "typescript": "*" } }, "sha512-+yNoYx6XIKuAO8Mqh1vGytu8jkFEOH5C8iOv3i8Z/65A7x9iAOXA97Q+PqZ3nlm2lxf5rOJuIGI/wDtx/riNYw=="], + + "@vue/reactivity": ["@vue/reactivity@3.5.16", "", { "dependencies": { "@vue/shared": "3.5.16" } }, "sha512-FG5Q5ee/kxhIm1p2bykPpPwqiUBV3kFySsHEQha5BJvjXdZTUfmya7wP7zC39dFuZAcf/PD5S4Lni55vGLMhvA=="], + + "@vue/runtime-core": ["@vue/runtime-core@3.5.16", "", { "dependencies": { "@vue/reactivity": "3.5.16", "@vue/shared": "3.5.16" } }, "sha512-bw5Ykq6+JFHYxrQa7Tjr+VSzw7Dj4ldR/udyBZbq73fCdJmyy5MPIFR9IX/M5Qs+TtTjuyUTCnmK3lWWwpAcFQ=="], + + "@vue/runtime-dom": ["@vue/runtime-dom@3.5.16", "", { "dependencies": { "@vue/reactivity": "3.5.16", "@vue/runtime-core": "3.5.16", "@vue/shared": "3.5.16", "csstype": "^3.1.3" } }, "sha512-T1qqYJsG2xMGhImRUV9y/RseB9d0eCYZQ4CWca9ztCuiPj/XWNNN+lkNBuzVbia5z4/cgxdL28NoQCvC0Xcfww=="], + + "@vue/server-renderer": ["@vue/server-renderer@3.5.16", "", { "dependencies": { "@vue/compiler-ssr": "3.5.16", "@vue/shared": "3.5.16" }, "peerDependencies": { "vue": "3.5.16" } }, "sha512-BrX0qLiv/WugguGsnQUJiYOE0Fe5mZTwi6b7X/ybGB0vfrPH9z0gD/Y6WOR1sGCgX4gc25L1RYS5eYQKDMoNIg=="], + + "@vue/shared": ["@vue/shared@3.5.16", "", {}, "sha512-c/0fWy3Jw6Z8L9FmTyYfkpM5zklnqqa9+a6dz3DvONRKW2NEbh46BP0FHuLFSWi2TnQEtp91Z6zOWNrU6QiyPg=="], + + "@vue/tsconfig": ["@vue/tsconfig@0.7.0", "", { "peerDependencies": { "typescript": "5.x", "vue": "^3.4.0" } }, "sha512-ku2uNz5MaZ9IerPPUyOHzyjhXoX2kVJaVf7hL315DC17vS6IiZRmmCPfggNbU16QTvM80+uYYy3eYJB59WCtvg=="], + + "acorn": ["acorn@8.15.0", "", { "bin": "bin/acorn" }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], + + "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="], + + "ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="], + + "alien-signals": ["alien-signals@1.0.13", "", {}, "sha512-OGj9yyTnJEttvzhTUWuscOvtqxq5vrhF7vL9oS0xJ2mK0ItPYP1/y+vCFebfxoEyAz0++1AIwJ5CMr+Fk3nDmg=="], + + "ansi-styles": ["ansi-styles@6.2.1", "", {}, "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="], + + "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], + + "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + + "birpc": ["birpc@2.4.0", "", {}, "sha512-5IdNxTyhXHv2UlgnPHQ0h+5ypVmkrYHzL8QT+DwFZ//2N/oNV8Ch+BCRmTJ3x6/z9Axo/cXYBc9eprsUVK/Jsg=="], + + "boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="], + + "brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], + + "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], + + "browserslist": ["browserslist@4.25.0", "", { "dependencies": { "caniuse-lite": "^1.0.30001718", "electron-to-chromium": "^1.5.160", "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.3" }, "bin": "cli.js" }, "sha512-PJ8gYKeS5e/whHBh8xrwYK+dAvEj7JXtz6uTucnMRB8OiGTsKccFekoRrjajPBHV8oOY+2tI4uxeceSimKwMFA=="], + + "bundle-name": ["bundle-name@4.1.0", "", { "dependencies": { "run-applescript": "^7.0.0" } }, "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q=="], + + "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="], + + "caniuse-lite": ["caniuse-lite@1.0.30001723", "", {}, "sha512-1R/elMjtehrFejxwmexeXAtae5UO9iSyFn6G/I806CYC/BLyyBk1EPhrKBkWhy6wM6Xnm47dSJQec+tLJ39WHw=="], + + "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], + + "chownr": ["chownr@3.0.0", "", {}, "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g=="], + + "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], + + "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], + + "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="], + + "convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="], + + "copy-anything": ["copy-anything@3.0.5", "", { "dependencies": { "is-what": "^4.1.8" } }, "sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w=="], + + "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], + + "cssesc": ["cssesc@3.0.0", "", { "bin": "bin/cssesc" }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="], + + "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="], + + "de-indent": ["de-indent@1.0.2", "", {}, "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg=="], + + "debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], + + "deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="], + + "default-browser": ["default-browser@5.2.1", "", { "dependencies": { "bundle-name": "^4.1.0", "default-browser-id": "^5.0.0" } }, "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg=="], + + "default-browser-id": ["default-browser-id@5.0.0", "", {}, "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA=="], + + "define-lazy-prop": ["define-lazy-prop@3.0.0", "", {}, "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg=="], + + "detect-libc": ["detect-libc@2.0.4", "", {}, "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA=="], + + "electron-to-chromium": ["electron-to-chromium@1.5.167", "", {}, "sha512-LxcRvnYO5ez2bMOFpbuuVuAI5QNeY1ncVytE/KXaL6ZNfzX1yPlAO0nSOyIHx2fVAuUprMqPs/TdVhUFZy7SIQ=="], + + "enhanced-resolve": ["enhanced-resolve@5.18.3", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww=="], + + "entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], + + "error-stack-parser-es": ["error-stack-parser-es@0.1.5", "", {}, "sha512-xHku1X40RO+fO8yJ8Wh2f2rZWVjqyhb1zgq1yZ8aZRQkv6OOKhKWRUaht3eSCUbAOBaKIgM+ykwFLE+QUxgGeg=="], + + "esbuild": ["esbuild@0.25.5", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.5", "@esbuild/android-arm": "0.25.5", "@esbuild/android-arm64": "0.25.5", "@esbuild/android-x64": "0.25.5", "@esbuild/darwin-arm64": "0.25.5", "@esbuild/darwin-x64": "0.25.5", "@esbuild/freebsd-arm64": "0.25.5", "@esbuild/freebsd-x64": "0.25.5", "@esbuild/linux-arm": "0.25.5", "@esbuild/linux-arm64": "0.25.5", "@esbuild/linux-ia32": "0.25.5", "@esbuild/linux-loong64": "0.25.5", "@esbuild/linux-mips64el": "0.25.5", "@esbuild/linux-ppc64": "0.25.5", "@esbuild/linux-riscv64": "0.25.5", "@esbuild/linux-s390x": "0.25.5", "@esbuild/linux-x64": "0.25.5", "@esbuild/netbsd-arm64": "0.25.5", "@esbuild/netbsd-x64": "0.25.5", "@esbuild/openbsd-arm64": "0.25.5", "@esbuild/openbsd-x64": "0.25.5", "@esbuild/sunos-x64": "0.25.5", "@esbuild/win32-arm64": "0.25.5", "@esbuild/win32-ia32": "0.25.5", "@esbuild/win32-x64": "0.25.5" }, "bin": "bin/esbuild" }, "sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ=="], + + "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], + + "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], + + "eslint": ["eslint@9.29.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.20.1", "@eslint/config-helpers": "^0.2.1", "@eslint/core": "^0.14.0", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "9.29.0", "@eslint/plugin-kit": "^0.3.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.4.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "bin": "bin/eslint.js" }, "sha512-GsGizj2Y1rCWDu6XoEekL3RLilp0voSePurjZIkxL3wlm5o5EC9VpgaP7lrCvjnkuLvzFBQWB3vWB3K5KQTveQ=="], + + "eslint-plugin-vue": ["eslint-plugin-vue@10.0.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "natural-compare": "^1.4.0", "nth-check": "^2.1.1", "postcss-selector-parser": "^6.0.15", "semver": "^7.6.3", "xml-name-validator": "^4.0.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "vue-eslint-parser": "^10.0.0" } }, "sha512-A5dRYc3eQ5i2rJFBW8J6F69ur/H7YfYg+5SCg6v829FU0BhM4fUTrRVR2d4MdZgzw0ioJEk6otYHEAnoGFqO4A=="], + + "eslint-scope": ["eslint-scope@8.4.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg=="], + + "eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="], + + "espree": ["espree@10.4.0", "", { "dependencies": { "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.1" } }, "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ=="], + + "esquery": ["esquery@1.6.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg=="], + + "esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="], + + "estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="], + + "estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="], + + "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="], + + "execa": ["execa@9.6.0", "", { "dependencies": { "@sindresorhus/merge-streams": "^4.0.0", "cross-spawn": "^7.0.6", "figures": "^6.1.0", "get-stream": "^9.0.0", "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.2.0", "signal-exit": "^4.1.0", "strip-final-newline": "^4.0.0", "yoctocolors": "^2.1.1" } }, "sha512-jpWzZ1ZhwUmeWRhS7Qv3mhpOhLfwI+uAX4e5fOcXqwMR7EcJ0pj2kV1CVzHVMX/LphnKWD3LObjZCoJ71lKpHw=="], + + "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], + + "fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="], + + "fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="], + + "fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="], + + "fastq": ["fastq@1.19.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ=="], + + "fdir": ["fdir@6.4.6", "", { "peerDependencies": { "picomatch": "^3 || ^4" } }, "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w=="], + + "figures": ["figures@6.1.0", "", { "dependencies": { "is-unicode-supported": "^2.0.0" } }, "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg=="], + + "file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="], + + "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], + + "find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="], + + "flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="], + + "flatted": ["flatted@3.3.3", "", {}, "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="], + + "fs-extra": ["fs-extra@11.3.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew=="], + + "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], + + "gensync": ["gensync@1.0.0-beta.2", "", {}, "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="], + + "get-stream": ["get-stream@9.0.1", "", { "dependencies": { "@sec-ant/readable-stream": "^0.4.1", "is-stream": "^4.0.1" } }, "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA=="], + + "gl-matrix": ["gl-matrix@3.4.4", "", {}, "sha512-latSnyDNt/8zYUB6VIJ6PCh2jBjJX6gnDsoCZ7LyW7GkqrD51EWwa9qCoGixj8YqBtETQK/xY7OmpTF8xz1DdQ=="], + + "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], + + "globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="], + + "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], + + "graphemer": ["graphemer@1.4.0", "", {}, "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag=="], + + "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], + + "he": ["he@1.2.0", "", { "bin": "bin/he" }, "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="], + + "hookable": ["hookable@5.5.3", "", {}, "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ=="], + + "human-signals": ["human-signals@8.0.1", "", {}, "sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ=="], + + "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], + + "import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="], + + "imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="], + + "is-docker": ["is-docker@3.0.0", "", { "bin": "cli.js" }, "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ=="], + + "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], + + "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], + + "is-inside-container": ["is-inside-container@1.0.0", "", { "dependencies": { "is-docker": "^3.0.0" }, "bin": "cli.js" }, "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA=="], + + "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], + + "is-plain-obj": ["is-plain-obj@4.1.0", "", {}, "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg=="], + + "is-stream": ["is-stream@4.0.1", "", {}, "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A=="], + + "is-unicode-supported": ["is-unicode-supported@2.1.0", "", {}, "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ=="], + + "is-what": ["is-what@4.1.16", "", {}, "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A=="], + + "is-wsl": ["is-wsl@3.1.0", "", { "dependencies": { "is-inside-container": "^1.0.0" } }, "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw=="], + + "isexe": ["isexe@3.1.1", "", {}, "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ=="], + + "jiti": ["jiti@2.4.2", "", { "bin": "lib/jiti-cli.mjs" }, "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A=="], + + "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], + + "js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": "bin/js-yaml.js" }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="], + + "jsesc": ["jsesc@3.1.0", "", { "bin": "bin/jsesc" }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="], + + "json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="], + + "json-parse-even-better-errors": ["json-parse-even-better-errors@4.0.0", "", {}, "sha512-lR4MXjGNgkJc7tkQ97kb2nuEMnNCyU//XYVH0MKTGcXEiSudQ5MKGKen3C5QubYy0vmq+JGitUg92uuywGEwIA=="], + + "json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], + + "json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="], + + "json5": ["json5@2.2.3", "", { "bin": "lib/cli.js" }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="], + + "jsonfile": ["jsonfile@6.1.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ=="], + + "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="], + + "kolorist": ["kolorist@1.8.0", "", {}, "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ=="], + + "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="], + + "lightningcss": ["lightningcss@1.30.1", "", { "dependencies": { "detect-libc": "^2.0.3" }, "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" } }, "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg=="], + + "lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.30.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ=="], + + "lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.30.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA=="], + + "lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.30.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig=="], + + "lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.30.1", "", { "os": "linux", "cpu": "arm" }, "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q=="], + + "lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.30.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw=="], + + "lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.30.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ=="], + + "lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.30.1", "", { "os": "linux", "cpu": "x64" }, "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw=="], + + "lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.30.1", "", { "os": "linux", "cpu": "x64" }, "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ=="], + + "lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.30.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA=="], + + "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.30.1", "", { "os": "win32", "cpu": "x64" }, "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg=="], + + "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="], + + "lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="], + + "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="], + + "lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="], + + "magic-string": ["magic-string@0.30.17", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA=="], + + "memorystream": ["memorystream@0.3.1", "", {}, "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw=="], + + "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], + + "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], + + "minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], + + "minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="], + + "minizlib": ["minizlib@3.0.2", "", { "dependencies": { "minipass": "^7.1.2" } }, "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA=="], + + "mitt": ["mitt@3.0.1", "", {}, "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw=="], + + "mkdirp": ["mkdirp@3.0.1", "", { "bin": "dist/cjs/src/bin.js" }, "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg=="], + + "mrmime": ["mrmime@2.0.1", "", {}, "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ=="], + + "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + + "muggle-string": ["muggle-string@0.4.1", "", {}, "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ=="], + + "nanoid": ["nanoid@3.3.11", "", { "bin": "bin/nanoid.cjs" }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], + + "natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="], + + "node-releases": ["node-releases@2.0.19", "", {}, "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw=="], + + "npm-normalize-package-bin": ["npm-normalize-package-bin@4.0.0", "", {}, "sha512-TZKxPvItzai9kN9H/TkmCtx/ZN/hvr3vUycjlfmH0ootY9yFBzNOpiXAdIn1Iteqsvk4lQn6B5PTrt+n6h8k/w=="], + + "npm-run-all2": ["npm-run-all2@7.0.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "cross-spawn": "^7.0.6", "memorystream": "^0.3.1", "minimatch": "^9.0.0", "pidtree": "^0.6.0", "read-package-json-fast": "^4.0.0", "shell-quote": "^1.7.3", "which": "^5.0.0" }, "bin": { "npm-run-all": "bin/npm-run-all/index.js", "npm-run-all2": "bin/npm-run-all/index.js", "run-p": "bin/run-p/index.js", "run-s": "bin/run-s/index.js" } }, "sha512-7tXR+r9hzRNOPNTvXegM+QzCuMjzUIIq66VDunL6j60O4RrExx32XUhlrS7UK4VcdGw5/Wxzb3kfNcFix9JKDA=="], + + "npm-run-path": ["npm-run-path@6.0.0", "", { "dependencies": { "path-key": "^4.0.0", "unicorn-magic": "^0.3.0" } }, "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA=="], + + "nth-check": ["nth-check@2.1.1", "", { "dependencies": { "boolbase": "^1.0.0" } }, "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w=="], + + "open": ["open@10.1.2", "", { "dependencies": { "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", "is-inside-container": "^1.0.0", "is-wsl": "^3.1.0" } }, "sha512-cxN6aIDPz6rm8hbebcP7vrQNhvRcveZoJU72Y7vskh4oIm+BZwBECnx5nTmrlres1Qapvx27Qo1Auukpf8PKXw=="], + + "optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="], + + "p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="], + + "p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="], + + "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="], + + "parse-ms": ["parse-ms@4.0.0", "", {}, "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw=="], + + "path-browserify": ["path-browserify@1.0.1", "", {}, "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g=="], + + "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], + + "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], + + "pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], + + "perfect-debounce": ["perfect-debounce@1.0.0", "", {}, "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA=="], + + "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], + + "picomatch": ["picomatch@4.0.2", "", {}, "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg=="], + + "pidtree": ["pidtree@0.6.0", "", { "bin": "bin/pidtree.js" }, "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g=="], + + "postcss": ["postcss@8.5.5", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-d/jtm+rdNT8tpXuHY5MMtcbJFBkhXE6593XVR9UoGCH8jSFGci7jGvMGH5RYd5PBJW+00NZQt6gf7CbagJCrhg=="], + + "postcss-selector-parser": ["postcss-selector-parser@6.1.2", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg=="], + + "prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="], + + "pretty-ms": ["pretty-ms@9.2.0", "", { "dependencies": { "parse-ms": "^4.0.0" } }, "sha512-4yf0QO/sllf/1zbZWYnvWw3NxCQwLXKzIj0G849LSufP15BXKM0rbD2Z3wVnkMfjdn/CB0Dpp444gYAACdsplg=="], + + "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], + + "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], + + "read-package-json-fast": ["read-package-json-fast@4.0.0", "", { "dependencies": { "json-parse-even-better-errors": "^4.0.0", "npm-normalize-package-bin": "^4.0.0" } }, "sha512-qpt8EwugBWDw2cgE2W+/3oxC+KTez2uSVR8JU9Q36TXPAGCaozfQUs59v4j4GFpWTaw0i6hAZSvOmu1J0uOEUg=="], + + "resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], + + "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="], + + "rfdc": ["rfdc@1.4.1", "", {}, "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="], + + "rollup": ["rollup@4.43.0", "", { "dependencies": { "@types/estree": "1.0.7" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.43.0", "@rollup/rollup-android-arm64": "4.43.0", "@rollup/rollup-darwin-arm64": "4.43.0", "@rollup/rollup-darwin-x64": "4.43.0", "@rollup/rollup-freebsd-arm64": "4.43.0", "@rollup/rollup-freebsd-x64": "4.43.0", "@rollup/rollup-linux-arm-gnueabihf": "4.43.0", "@rollup/rollup-linux-arm-musleabihf": "4.43.0", "@rollup/rollup-linux-arm64-gnu": "4.43.0", "@rollup/rollup-linux-arm64-musl": "4.43.0", "@rollup/rollup-linux-loongarch64-gnu": "4.43.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.43.0", "@rollup/rollup-linux-riscv64-gnu": "4.43.0", "@rollup/rollup-linux-riscv64-musl": "4.43.0", "@rollup/rollup-linux-s390x-gnu": "4.43.0", "@rollup/rollup-linux-x64-gnu": "4.43.0", "@rollup/rollup-linux-x64-musl": "4.43.0", "@rollup/rollup-win32-arm64-msvc": "4.43.0", "@rollup/rollup-win32-ia32-msvc": "4.43.0", "@rollup/rollup-win32-x64-msvc": "4.43.0", "fsevents": "~2.3.2" }, "bin": "dist/bin/rollup" }, "sha512-wdN2Kd3Twh8MAEOEJZsuxuLKCsBEo4PVNLK6tQWAn10VhsVewQLzcucMgLolRlhFybGxfclbPeEYBaP6RvUFGg=="], + + "run-applescript": ["run-applescript@7.0.0", "", {}, "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A=="], + + "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], + + "semver": ["semver@7.7.2", "", { "bin": "bin/semver.js" }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="], + + "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], + + "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], + + "shell-quote": ["shell-quote@1.8.3", "", {}, "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw=="], + + "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], + + "sirv": ["sirv@3.0.1", "", { "dependencies": { "@polka/url": "^1.0.0-next.24", "mrmime": "^2.0.0", "totalist": "^3.0.0" } }, "sha512-FoqMu0NCGBLCcAkS1qA+XJIQTR6/JHfQXl+uGteNCQ76T91DMUjPa9xfmeqMY3z80nLSg9yQmNjK0Px6RWsH/A=="], + + "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], + + "speakingurl": ["speakingurl@14.0.1", "", {}, "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ=="], + + "strip-final-newline": ["strip-final-newline@4.0.0", "", {}, "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw=="], + + "strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="], + + "superjson": ["superjson@2.2.2", "", { "dependencies": { "copy-anything": "^3.0.2" } }, "sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q=="], + + "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], + + "tailwindcss": ["tailwindcss@4.1.11", "", {}, "sha512-2E9TBm6MDD/xKYe+dvJZAmg3yxIEDNRc0jwlNyDg/4Fil2QcSLjFKGVff0lAf1jjeaArlG/M75Ey/EYr/OJtBA=="], + + "tapable": ["tapable@2.2.2", "", {}, "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg=="], + + "tar": ["tar@7.4.3", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.0.1", "mkdirp": "^3.0.1", "yallist": "^5.0.0" } }, "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw=="], + + "tinyglobby": ["tinyglobby@0.2.14", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ=="], + + "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], + + "totalist": ["totalist@3.0.1", "", {}, "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ=="], + + "ts-api-utils": ["ts-api-utils@2.1.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ=="], + + "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="], + + "typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="], + + "typescript-eslint": ["typescript-eslint@8.34.0", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.34.0", "@typescript-eslint/parser": "8.34.0", "@typescript-eslint/utils": "8.34.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-MRpfN7uYjTrTGigFCt8sRyNqJFhjN0WwZecldaqhWm+wy0gaRt8Edb/3cuUy0zdq2opJWT6iXINKAtewnDOltQ=="], + + "undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], + + "unicorn-magic": ["unicorn-magic@0.3.0", "", {}, "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA=="], + + "universalify": ["universalify@2.0.1", "", {}, "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="], + + "update-browserslist-db": ["update-browserslist-db@1.1.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": "cli.js" }, "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw=="], + + "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], + + "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], + + "vite": ["vite@6.3.5", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": "bin/vite.js" }, "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ=="], + + "vite-hot-client": ["vite-hot-client@2.0.4", "", { "peerDependencies": { "vite": "^2.6.0 || ^3.0.0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0" } }, "sha512-W9LOGAyGMrbGArYJN4LBCdOC5+Zwh7dHvOHC0KmGKkJhsOzaKbpo/jEjpPKVHIW0/jBWj8RZG0NUxfgA8BxgAg=="], + + "vite-plugin-inspect": ["vite-plugin-inspect@0.8.9", "", { "dependencies": { "@antfu/utils": "^0.7.10", "@rollup/pluginutils": "^5.1.3", "debug": "^4.3.7", "error-stack-parser-es": "^0.1.5", "fs-extra": "^11.2.0", "open": "^10.1.0", "perfect-debounce": "^1.0.0", "picocolors": "^1.1.1", "sirv": "^3.0.0" }, "peerDependencies": { "vite": "^3.1.0 || ^4.0.0 || ^5.0.0-0 || ^6.0.1" } }, "sha512-22/8qn+LYonzibb1VeFZmISdVao5kC22jmEKm24vfFE8siEn47EpVcCLYMv6iKOYMJfjSvSJfueOwcFCkUnV3A=="], + + "vite-plugin-vue-devtools": ["vite-plugin-vue-devtools@7.7.6", "", { "dependencies": { "@vue/devtools-core": "^7.7.6", "@vue/devtools-kit": "^7.7.6", "@vue/devtools-shared": "^7.7.6", "execa": "^9.5.2", "sirv": "^3.0.1", "vite-plugin-inspect": "0.8.9", "vite-plugin-vue-inspector": "^5.3.1" }, "peerDependencies": { "vite": "^3.1.0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.0-0" } }, "sha512-L7nPVM5a7lgit/Z+36iwoqHOaP3wxqVi1UvaDJwGCfblS9Y6vNqf32ILlzJVH9c47aHu90BhDXeZc+rgzHRHcw=="], + + "vite-plugin-vue-inspector": ["vite-plugin-vue-inspector@5.3.1", "", { "dependencies": { "@babel/core": "^7.23.0", "@babel/plugin-proposal-decorators": "^7.23.0", "@babel/plugin-syntax-import-attributes": "^7.22.5", "@babel/plugin-syntax-import-meta": "^7.10.4", "@babel/plugin-transform-typescript": "^7.22.15", "@vue/babel-plugin-jsx": "^1.1.5", "@vue/compiler-dom": "^3.3.4", "kolorist": "^1.8.0", "magic-string": "^0.30.4" }, "peerDependencies": { "vite": "^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.0-0" } }, "sha512-cBk172kZKTdvGpJuzCCLg8lJ909wopwsu3Ve9FsL1XsnLBiRT9U3MePcqrgGHgCX2ZgkqZmAGR8taxw+TV6s7A=="], + + "vite-plugin-wasm": ["vite-plugin-wasm@3.5.0", "", { "peerDependencies": { "vite": "^2 || ^3 || ^4 || ^5 || ^6 || ^7" } }, "sha512-X5VWgCnqiQEGb+omhlBVsvTfxikKtoOgAzQ95+BZ8gQ+VfMHIjSHr0wyvXFQCa0eKQ0fKyaL0kWcEnYqBac4lQ=="], + + "vscode-uri": ["vscode-uri@3.1.0", "", {}, "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ=="], + + "vue": ["vue@3.5.16", "", { "dependencies": { "@vue/compiler-dom": "3.5.16", "@vue/compiler-sfc": "3.5.16", "@vue/runtime-dom": "3.5.16", "@vue/server-renderer": "3.5.16", "@vue/shared": "3.5.16" }, "peerDependencies": { "typescript": "*" } }, "sha512-rjOV2ecxMd5SiAmof2xzh2WxntRcigkX/He4YFJ6WdRvVUrbt6DxC1Iujh10XLl8xCDRDtGKMeO3D+pRQ1PP9w=="], + + "vue-eslint-parser": ["vue-eslint-parser@10.1.3", "", { "dependencies": { "debug": "^4.4.0", "eslint-scope": "^8.2.0", "eslint-visitor-keys": "^4.2.0", "espree": "^10.3.0", "esquery": "^1.6.0", "lodash": "^4.17.21", "semver": "^7.6.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0" } }, "sha512-dbCBnd2e02dYWsXoqX5yKUZlOt+ExIpq7hmHKPb5ZqKcjf++Eo0hMseFTZMLKThrUk61m+Uv6A2YSBve6ZvuDQ=="], + + "vue-router": ["vue-router@4.5.1", "", { "dependencies": { "@vue/devtools-api": "^6.6.4" }, "peerDependencies": { "vue": "^3.2.0" } }, "sha512-ogAF3P97NPm8fJsE4by9dwSYtDwXIY1nFY9T6DyQnGHd1E2Da94w9JIolpe42LJGIl0DwOHBi8TcRPlPGwbTtw=="], + + "vue-tsc": ["vue-tsc@2.2.10", "", { "dependencies": { "@volar/typescript": "~2.4.11", "@vue/language-core": "2.2.10" }, "peerDependencies": { "typescript": ">=5.0.0" }, "bin": "bin/vue-tsc.js" }, "sha512-jWZ1xSaNbabEV3whpIDMbjVSVawjAyW+x1n3JeGQo7S0uv2n9F/JMgWW90tGWNFRKya4YwKMZgCtr0vRAM7DeQ=="], + + "which": ["which@5.0.0", "", { "dependencies": { "isexe": "^3.1.1" }, "bin": { "node-which": "bin/which.js" } }, "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ=="], + + "word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="], + + "xml-name-validator": ["xml-name-validator@4.0.0", "", {}, "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw=="], + + "yallist": ["yallist@5.0.0", "", {}, "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="], + + "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], + + "yoctocolors": ["yoctocolors@2.1.1", "", {}, "sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ=="], + + "@babel/core/semver": ["semver@6.3.1", "", { "bin": "bin/semver.js" }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + + "@babel/helper-compilation-targets/semver": ["semver@6.3.1", "", { "bin": "bin/semver.js" }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + + "@babel/helper-create-class-features-plugin/semver": ["semver@6.3.1", "", { "bin": "bin/semver.js" }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + + "@babel/traverse/globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="], + + "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], + + "@eslint/config-array/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], + + "@eslint/eslintrc/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], + + "@eslint/plugin-kit/@eslint/core": ["@eslint/core@0.15.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-b7ePw78tEWWkpgZCDYkbqDOP8dmM6qe+AOC6iuJqlq1R/0ahMAeH3qynpnqKFGkMltrp44ohV4ubGyvLX28tzw=="], + + "@humanfs/node/@humanwhocodes/retry": ["@humanwhocodes/retry@0.3.1", "", {}, "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA=="], + + "@rollup/pluginutils/picomatch": ["picomatch@4.0.2", "", {}, "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg=="], + + "@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], + + "@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + + "@typescript-eslint/visitor-keys/eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="], + + "@vue/devtools-core/nanoid": ["nanoid@5.1.5", "", { "bin": "bin/nanoid.js" }, "sha512-Ir/+ZpE9fDsNH0hQ3C68uyThDXzYcim2EqcZ8zn8Chtt1iylPT9xXJB0kPCnqzgcEGikO9RxSrh63MsmVCU7Fw=="], + + "@vue/language-core/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + + "chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], + + "cross-spawn/which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], + + "espree/eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="], + + "fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + + "lru-cache/yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="], + + "micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + + "npm-run-all2/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + + "npm-run-path/path-key": ["path-key@4.0.0", "", {}, "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ=="], + + "rollup/@types/estree": ["@types/estree@1.0.7", "", {}, "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ=="], + + "tinyglobby/fdir": ["fdir@6.4.6", "", { "peerDependencies": { "picomatch": "^3 || ^4" } }, "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w=="], + + "tinyglobby/picomatch": ["picomatch@4.0.2", "", {}, "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg=="], + + "vue-eslint-parser/eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="], + + "@eslint/config-array/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], + + "@eslint/eslintrc/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], + + "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], + + "@vue/language-core/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], + + "cross-spawn/which/isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], + + "npm-run-all2/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], + } +} diff --git a/package-lock.json b/package-lock.json index 23d2458..3d14235 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,9 @@ "dependencies": { "@headlessui/vue": "^1.7.23", "@tailwindcss/vite": "^4.1.11", + "gl-matrix": "^3.4.4", "tailwindcss": "^4.1.11", + "vite-plugin-wasm": "^3.5.0", "vue": "^3.5.13", "vue-router": "^4.5.0" }, @@ -930,10 +932,11 @@ } }, "node_modules/@eslint/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -996,10 +999,11 @@ } }, "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -1029,12 +1033,13 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.2.tgz", - "integrity": "sha512-4SaFZCNfJqvk/kenHpI8xvN42DMaoycy4PzKc5otHxRswww1kAt82OlBuwRVLofCACCTZEcla2Ydxv8scMXaTg==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz", + "integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.15.0", + "@eslint/core": "^0.15.2", "levn": "^0.4.1" }, "engines": { @@ -1042,10 +1047,11 @@ } }, "node_modules/@eslint/plugin-kit/node_modules/@eslint/core": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.0.tgz", - "integrity": "sha512-b7ePw78tEWWkpgZCDYkbqDOP8dmM6qe+AOC6iuJqlq1R/0ahMAeH3qynpnqKFGkMltrp44ohV4ubGyvLX28tzw==", + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz", + "integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@types/json-schema": "^7.0.15" }, @@ -1258,240 +1264,325 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.43.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.43.0.tgz", - "integrity": "sha512-Krjy9awJl6rKbruhQDgivNbD1WuLb8xAclM4IR4cN5pHGAs2oIMMQJEiC3IC/9TZJ+QZkmZhlMO/6MBGxPidpw==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz", + "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==", "cpu": [ "arm" ], + "license": "MIT", "optional": true, "os": [ "android" ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.43.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.43.0.tgz", - "integrity": "sha512-ss4YJwRt5I63454Rpj+mXCXicakdFmKnUNxr1dLK+5rv5FJgAxnN7s31a5VchRYxCFWdmnDWKd0wbAdTr0J5EA==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz", + "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==", "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "android" ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.43.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.43.0.tgz", - "integrity": "sha512-eKoL8ykZ7zz8MjgBenEF2OoTNFAPFz1/lyJ5UmmFSz5jW+7XbH1+MAgCVHy72aG59rbuQLcJeiMrP8qP5d/N0A==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz", + "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==", "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "darwin" ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.43.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.43.0.tgz", - "integrity": "sha512-SYwXJgaBYW33Wi/q4ubN+ldWC4DzQY62S4Ll2dgfr/dbPoF50dlQwEaEHSKrQdSjC6oIe1WgzosoaNoHCdNuMg==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz", + "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "darwin" ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.43.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.43.0.tgz", - "integrity": "sha512-SV+U5sSo0yujrjzBF7/YidieK2iF6E7MdF6EbYxNz94lA+R0wKl3SiixGyG/9Klab6uNBIqsN7j4Y/Fya7wAjQ==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz", + "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==", "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "freebsd" ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.43.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.43.0.tgz", - "integrity": "sha512-J7uCsiV13L/VOeHJBo5SjasKiGxJ0g+nQTrBkAsmQBIdil3KhPnSE9GnRon4ejX1XDdsmK/l30IYLiAaQEO0Cg==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz", + "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "freebsd" ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.43.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.43.0.tgz", - "integrity": "sha512-gTJ/JnnjCMc15uwB10TTATBEhK9meBIY+gXP4s0sHD1zHOaIh4Dmy1X9wup18IiY9tTNk5gJc4yx9ctj/fjrIw==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz", + "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==", "cpu": [ "arm" ], + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.43.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.43.0.tgz", - "integrity": "sha512-ZJ3gZynL1LDSIvRfz0qXtTNs56n5DI2Mq+WACWZ7yGHFUEirHBRt7fyIk0NsCKhmRhn7WAcjgSkSVVxKlPNFFw==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz", + "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==", "cpu": [ "arm" ], + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.43.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.43.0.tgz", - "integrity": "sha512-8FnkipasmOOSSlfucGYEu58U8cxEdhziKjPD2FIa0ONVMxvl/hmONtX/7y4vGjdUhjcTHlKlDhw3H9t98fPvyA==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz", + "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==", "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.43.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.43.0.tgz", - "integrity": "sha512-KPPyAdlcIZ6S9C3S2cndXDkV0Bb1OSMsX0Eelr2Bay4EsF9yi9u9uzc9RniK3mcUGCLhWY9oLr6er80P5DE6XA==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz", + "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==", "cpu": [ "arm64" ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz", + "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==", + "cpu": [ + "loong64" + ], + "license": "MIT", "optional": true, "os": [ "linux" ] }, - "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.43.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.43.0.tgz", - "integrity": "sha512-HPGDIH0/ZzAZjvtlXj6g+KDQ9ZMHfSP553za7o2Odegb/BEfwJcR0Sw0RLNpQ9nC6Gy8s+3mSS9xjZ0n3rhcYg==", + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz", + "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==", "cpu": [ "loong64" ], + "license": "MIT", "optional": true, "os": [ "linux" ] }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.43.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.43.0.tgz", - "integrity": "sha512-gEmwbOws4U4GLAJDhhtSPWPXUzDfMRedT3hFMyRAvM9Mrnj+dJIFIeL7otsv2WF3D7GrV0GIewW0y28dOYWkmw==", + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz", + "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==", "cpu": [ "ppc64" ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz", + "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==", + "cpu": [ + "ppc64" + ], + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.43.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.43.0.tgz", - "integrity": "sha512-XXKvo2e+wFtXZF/9xoWohHg+MuRnvO29TI5Hqe9xwN5uN8NKUYy7tXUG3EZAlfchufNCTHNGjEx7uN78KsBo0g==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz", + "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==", "cpu": [ "riscv64" ], + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.43.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.43.0.tgz", - "integrity": "sha512-ruf3hPWhjw6uDFsOAzmbNIvlXFXlBQ4nk57Sec8E8rUxs/AI4HD6xmiiasOOx/3QxS2f5eQMKTAwk7KHwpzr/Q==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz", + "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==", "cpu": [ "riscv64" ], + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.43.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.43.0.tgz", - "integrity": "sha512-QmNIAqDiEMEvFV15rsSnjoSmO0+eJLoKRD9EAa9rrYNwO/XRCtOGM3A5A0X+wmG+XRrw9Fxdsw+LnyYiZWWcVw==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz", + "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==", "cpu": [ "s390x" ], + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.43.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.43.0.tgz", - "integrity": "sha512-jAHr/S0iiBtFyzjhOkAics/2SrXE092qyqEg96e90L3t9Op8OTzS6+IX0Fy5wCt2+KqeHAkti+eitV0wvblEoQ==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz", + "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.43.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.43.0.tgz", - "integrity": "sha512-3yATWgdeXyuHtBhrLt98w+5fKurdqvs8B53LaoKD7P7H7FKOONLsBVMNl9ghPQZQuYcceV5CDyPfyfGpMWD9mQ==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz", + "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "linux" ] }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz", + "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz", + "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.43.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.43.0.tgz", - "integrity": "sha512-wVzXp2qDSCOpcBCT5WRWLmpJRIzv23valvcTwMHEobkjippNf+C3ys/+wf07poPkeNix0paTNemB2XrHr2TnGw==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz", + "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==", "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "win32" ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.43.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.43.0.tgz", - "integrity": "sha512-fYCTEyzf8d+7diCw8b+asvWDCLMjsCEA8alvtAutqJOJp/wL5hs1rWSqJ1vkjgW0L2NB4bsYJrpKkiIPRR9dvw==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz", + "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==", "cpu": [ "ia32" ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz", + "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==", + "cpu": [ + "x64" + ], + "license": "MIT", "optional": true, "os": [ "win32" ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.43.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.43.0.tgz", - "integrity": "sha512-SnGhLiE5rlK0ofq8kzuDkM0g7FN1s5VYY+YSMTibP7CqShxCQvqtNxTARS4xX4PFJfHjG0ZQYX9iGzI3FQh5Aw==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz", + "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "win32" @@ -1795,8 +1886,7 @@ "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 + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==" }, "node_modules/@types/json-schema": { "version": "7.0.15", @@ -2388,10 +2478,11 @@ } }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -2955,10 +3046,11 @@ } }, "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -3249,6 +3341,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/gl-matrix": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-3.4.4.tgz", + "integrity": "sha512-latSnyDNt/8zYUB6VIJ6PCh2jBjJX6gnDsoCZ7LyW7GkqrD51EWwa9qCoGixj8YqBtETQK/xY7OmpTF8xz1DdQ==", + "license": "MIT" + }, "node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -3498,10 +3596,11 @@ "dev": true }, "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -3833,10 +3932,11 @@ } }, "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", + "dev": true, + "license": "MIT" }, "node_modules/lodash.merge": { "version": "4.6.2", @@ -3893,12 +3993,13 @@ } }, "node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", "dev": true, + "license": "ISC", "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^2.0.2" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -3916,9 +4017,10 @@ } }, "node_modules/minizlib": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz", - "integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", + "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", + "license": "MIT", "dependencies": { "minipass": "^7.1.2" }, @@ -3932,20 +4034,6 @@ "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", "dev": true }, - "node_modules/mkdirp": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", - "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", - "bin": { - "mkdirp": "dist/cjs/src/bin.js" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/mrmime": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", @@ -4393,11 +4481,12 @@ "dev": true }, "node_modules/rollup": { - "version": "4.43.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.43.0.tgz", - "integrity": "sha512-wdN2Kd3Twh8MAEOEJZsuxuLKCsBEo4PVNLK6tQWAn10VhsVewQLzcucMgLolRlhFybGxfclbPeEYBaP6RvUFGg==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz", + "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==", + "license": "MIT", "dependencies": { - "@types/estree": "1.0.7" + "@types/estree": "1.0.8" }, "bin": { "rollup": "dist/bin/rollup" @@ -4407,34 +4496,34 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.43.0", - "@rollup/rollup-android-arm64": "4.43.0", - "@rollup/rollup-darwin-arm64": "4.43.0", - "@rollup/rollup-darwin-x64": "4.43.0", - "@rollup/rollup-freebsd-arm64": "4.43.0", - "@rollup/rollup-freebsd-x64": "4.43.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.43.0", - "@rollup/rollup-linux-arm-musleabihf": "4.43.0", - "@rollup/rollup-linux-arm64-gnu": "4.43.0", - "@rollup/rollup-linux-arm64-musl": "4.43.0", - "@rollup/rollup-linux-loongarch64-gnu": "4.43.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.43.0", - "@rollup/rollup-linux-riscv64-gnu": "4.43.0", - "@rollup/rollup-linux-riscv64-musl": "4.43.0", - "@rollup/rollup-linux-s390x-gnu": "4.43.0", - "@rollup/rollup-linux-x64-gnu": "4.43.0", - "@rollup/rollup-linux-x64-musl": "4.43.0", - "@rollup/rollup-win32-arm64-msvc": "4.43.0", - "@rollup/rollup-win32-ia32-msvc": "4.43.0", - "@rollup/rollup-win32-x64-msvc": "4.43.0", + "@rollup/rollup-android-arm-eabi": "4.59.0", + "@rollup/rollup-android-arm64": "4.59.0", + "@rollup/rollup-darwin-arm64": "4.59.0", + "@rollup/rollup-darwin-x64": "4.59.0", + "@rollup/rollup-freebsd-arm64": "4.59.0", + "@rollup/rollup-freebsd-x64": "4.59.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", + "@rollup/rollup-linux-arm-musleabihf": "4.59.0", + "@rollup/rollup-linux-arm64-gnu": "4.59.0", + "@rollup/rollup-linux-arm64-musl": "4.59.0", + "@rollup/rollup-linux-loong64-gnu": "4.59.0", + "@rollup/rollup-linux-loong64-musl": "4.59.0", + "@rollup/rollup-linux-ppc64-gnu": "4.59.0", + "@rollup/rollup-linux-ppc64-musl": "4.59.0", + "@rollup/rollup-linux-riscv64-gnu": "4.59.0", + "@rollup/rollup-linux-riscv64-musl": "4.59.0", + "@rollup/rollup-linux-s390x-gnu": "4.59.0", + "@rollup/rollup-linux-x64-gnu": "4.59.0", + "@rollup/rollup-linux-x64-musl": "4.59.0", + "@rollup/rollup-openbsd-x64": "4.59.0", + "@rollup/rollup-openharmony-arm64": "4.59.0", + "@rollup/rollup-win32-arm64-msvc": "4.59.0", + "@rollup/rollup-win32-ia32-msvc": "4.59.0", + "@rollup/rollup-win32-x64-gnu": "4.59.0", + "@rollup/rollup-win32-x64-msvc": "4.59.0", "fsevents": "~2.3.2" } }, - "node_modules/rollup/node_modules/@types/estree": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", - "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==" - }, "node_modules/run-applescript": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", @@ -4620,15 +4709,15 @@ } }, "node_modules/tar": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", - "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", + "version": "7.5.11", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.11.tgz", + "integrity": "sha512-ChjMH33/KetonMTAtpYdgUFr0tbz69Fp2v7zWxQfYZX4g5ZN2nOBXm1R2xyA+lMIKrLKIoKAwFj93jE/avX9cQ==", + "license": "BlueOak-1.0.0", "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", - "minizlib": "^3.0.1", - "mkdirp": "^3.0.1", + "minizlib": "^3.1.0", "yallist": "^5.0.0" }, "engines": { @@ -4835,9 +4924,10 @@ "dev": true }, "node_modules/vite": { - "version": "6.3.5", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz", - "integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz", + "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", + "license": "MIT", "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", @@ -4991,6 +5081,15 @@ "vite": "^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.0-0" } }, + "node_modules/vite-plugin-wasm": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/vite-plugin-wasm/-/vite-plugin-wasm-3.5.0.tgz", + "integrity": "sha512-X5VWgCnqiQEGb+omhlBVsvTfxikKtoOgAzQ95+BZ8gQ+VfMHIjSHr0wyvXFQCa0eKQ0fKyaL0kWcEnYqBac4lQ==", + "license": "MIT", + "peerDependencies": { + "vite": "^2 || ^3 || ^4 || ^5 || ^6 || ^7" + } + }, "node_modules/vite/node_modules/fdir": { "version": "6.4.6", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", diff --git a/package.json b/package.json index 7f9773f..fb49eff 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,9 @@ "dependencies": { "@headlessui/vue": "^1.7.23", "@tailwindcss/vite": "^4.1.11", + "gl-matrix": "^3.4.4", "tailwindcss": "^4.1.11", + "vite-plugin-wasm": "^3.5.0", "vue": "^3.5.13", "vue-router": "^4.5.0" }, diff --git a/src/api/offstylesApi.ts b/src/api/offstylesApi.ts index cd72677..89a9de1 100644 --- a/src/api/offstylesApi.ts +++ b/src/api/offstylesApi.ts @@ -1,8 +1,8 @@ -import { Style } from '@/types/Style'; -import Api from './api'; -import type { Time } from '@/types/Time'; -import type { User } from '@/types/User'; -import type { RecentModAction, ModerationTargetFilter } from '@/types/moderation'; +import { Style } from "@/types/Style"; +import Api from "./api"; +import type { Time } from "@/types/Time"; +import type { User } from "@/types/User"; +import type { RecentModAction, ModerationTargetFilter } from "@/types/moderation"; // Add new interfaces based on the API spec export interface RankAwareRecord extends Time { @@ -73,54 +73,72 @@ export interface ServerKeyInfo { } class OffstylesApi extends Api { - static offstylesApiUrl = import.meta.env.DEV ? 'http://127.0.0.1:8000/api' : 'https://offstyles.tommyy.dev/api'; + static offstylesApiUrl = import.meta.env.DEV ? "/api" : "https://offstyles.tommyy.dev/api"; // Fixed method signature to require style parameter - static async getTimesByMap(mapName: string, style: number = Style.normal, steamid?: string, limit: number = 50, page: number = 1): Promise { + static async getTimesByMap( + mapName: string, + style: number = Style.normal, + steamid?: string, + limit: number = 50, + page: number = 1, + ): Promise { const params = new URLSearchParams({ map: mapName, style: style.toString(), limit: limit.toString(), - page: page.toString() + page: page.toString(), }); if (steamid) { - params.append('steamid', steamid); + params.append("steamid", steamid); } this.url = `${this.offstylesApiUrl}/map?${params.toString()}`; return await this.fetchFromUrl(); } - static async getTimesByPlayer(steamID: string, map?: string, style: number = Style.all, limit: number = 50, page: number = 1, best: boolean = false): Promise { + static async getTimesByPlayer( + steamID: string, + map?: string, + style: number = Style.all, + limit: number = 50, + page: number = 1, + best: boolean = false, + ): Promise { const params = new URLSearchParams({ steamid: steamID, limit: limit.toString(), page: page.toString(), - best: best.toString() + best: best.toString(), }); if (map) { - params.append('map', map); + params.append("map", map); } if (style !== undefined && style !== Style.all) { - params.append('style', style.toString()); + params.append("style", style.toString()); } this.url = `${this.offstylesApiUrl}/times?${params.toString()}`; return await this.fetchFromUrl(); } - static async getRecentTimes(style: number = Style.all, limit: number = 15, page: number = 1, wr: boolean = true): Promise { + static async getRecentTimes( + style: number = Style.all, + limit: number = 15, + page: number = 1, + wr: boolean = true, + ): Promise { const params = new URLSearchParams({ limit: limit.toString(), page: page.toString(), - wr: wr.toString() + wr: wr.toString(), }); if (style !== undefined && style !== Style.all) { - params.append('style', style.toString()); + params.append("style", style.toString()); } this.url = `${this.offstylesApiUrl}/recent?${params.toString()}`; @@ -130,7 +148,7 @@ class OffstylesApi extends Api { // New methods based on the API spec static async getMapsForAutoComplete(text: string): Promise { const params = new URLSearchParams({ - text: text + text: text, }); this.url = `${this.offstylesApiUrl}/autocomplete_maps?${params.toString()}`; @@ -139,7 +157,7 @@ class OffstylesApi extends Api { static async getPlayersForAutoComplete(text: string): Promise<[string, string][]> { const params = new URLSearchParams({ - text: text + text: text, }); this.url = `${this.offstylesApiUrl}/autocomplete_players?${params.toString()}`; @@ -148,7 +166,7 @@ class OffstylesApi extends Api { static async getSingleTime(id: string): Promise { const params = new URLSearchParams({ - id: id + id: id, }); this.url = `${this.offstylesApiUrl}/time?${params.toString()}`; @@ -162,11 +180,11 @@ class OffstylesApi extends Api { static async downloadReplay(id: string): Promise { const params = new URLSearchParams({ - id: id + id: id, }); const response = await fetch(`${this.offstylesApiUrl}/replay?${params.toString()}`, { - credentials: 'include' // Include cookies for session authentication + credentials: "include", // Include cookies for session authentication }); if (!response.ok) { @@ -183,19 +201,23 @@ class OffstylesApi extends Api { } // Moderation methods (require authentication) - static async moderatePlayer(steamId: string, action: 'ban' | 'unban', reason: string): Promise { + static async moderatePlayer( + steamId: string, + action: "ban" | "unban", + reason: string, + ): Promise { const params = new URLSearchParams({ id: steamId, - action: action + action: action, }); const response = await fetch(`${this.offstylesApiUrl}/moderate_player?${params.toString()}`, { - method: 'POST', + method: "POST", headers: { - 'Content-Type': 'text/plain', + "Content-Type": "text/plain", }, body: reason, - credentials: 'include' // Include cookies for session authentication + credentials: "include", // Include cookies for session authentication }); if (!response.ok) { @@ -209,24 +231,32 @@ class OffstylesApi extends Api { } } - static async moderateRecord(recordId: string, action: 'invalidate' | 'revalidate', reason: string): Promise { + static async moderateRecord( + recordId: string, + action: "invalidate" | "revalidate", + reason: string, + ): Promise { return this.moderateRecords([recordId], action, reason); } - // Bulk moderation method for multiple records - static async moderateRecords(recordIds: string[], action: 'invalidate' | 'revalidate', reason: string): Promise { + // Bulk moderation method for multiple records + static async moderateRecords( + recordIds: string[], + action: "invalidate" | "revalidate", + reason: string, + ): Promise { const params = new URLSearchParams({ action: action, - ids: recordIds.join(',') // Comma-separated values for the ids parameter + ids: recordIds.join(","), // Comma-separated values for the ids parameter }); const response = await fetch(`${this.offstylesApiUrl}/moderate_record?${params.toString()}`, { - method: 'POST', + method: "POST", headers: { - 'Content-Type': 'text/plain', + "Content-Type": "text/plain", }, body: reason, - credentials: 'include' // Include cookies for session authentication + credentials: "include", // Include cookies for session authentication }); if (!response.ok) { @@ -243,7 +273,7 @@ class OffstylesApi extends Api { // Get user profile data static async getUserProfile(steamId: string): Promise { const params = new URLSearchParams({ - steamid: steamId + steamid: steamId, }); const response = await fetch(`${this.offstylesApiUrl}/profile?${params.toString()}`); @@ -265,7 +295,7 @@ class OffstylesApi extends Api { static async getCurrentUser(): Promise { try { const response = await fetch(`${this.offstylesApiUrl}/profile`, { - credentials: 'include' // Include cookies for session authentication + credentials: "include", // Include cookies for session authentication }); if (response.ok) { @@ -274,7 +304,7 @@ class OffstylesApi extends Api { return null; // Not authenticated or user not found } } catch (error) { - console.error('Error fetching current user:', error); + console.error("Error fetching current user:", error); return null; } } @@ -290,11 +320,11 @@ class OffstylesApi extends Api { // Get moderation logs static async getModerationLogs(id: string): Promise { const params = new URLSearchParams({ - id: id + id: id, }); const response = await fetch(`${this.offstylesApiUrl}/mod_logs?${params.toString()}`, { - credentials: 'include' // Include cookies for session authentication + credentials: "include", // Include cookies for session authentication }); if (!response.ok) { @@ -322,27 +352,27 @@ class OffstylesApi extends Api { name: string, owner: string | undefined, servers: ServerInfo[], - permissions?: number + permissions?: number, ): Promise { const params = new URLSearchParams(); if (permissions !== undefined) { - params.append('permissions', permissions.toString()); + params.append("permissions", permissions.toString()); } const serverData = { name: name, owner: owner || null, - servers: servers + servers: servers, }; const response = await fetch(`${this.offstylesApiUrl}/admin/create_key?${params.toString()}`, { - method: 'POST', + method: "POST", headers: { - 'Content-Type': 'application/json', + "Content-Type": "application/json", }, body: JSON.stringify(serverData), - credentials: 'include' + credentials: "include", }); if (!response.ok) { @@ -362,16 +392,16 @@ class OffstylesApi extends Api { // Admin methods (require admin permissions) static async createApiKey(server: string, permissions?: number): Promise { const params = new URLSearchParams({ - server: server + server: server, }); if (permissions !== undefined) { - params.append('permissions', permissions.toString()); + params.append("permissions", permissions.toString()); } const response = await fetch(`${this.offstylesApiUrl}/admin/create_key?${params.toString()}`, { - method: 'POST', - credentials: 'include' // Include cookies for session authentication + method: "POST", + credentials: "include", // Include cookies for session authentication }); if (!response.ok) { @@ -390,12 +420,12 @@ class OffstylesApi extends Api { static async updateApiKey(server: string, permissions: number): Promise { const params = new URLSearchParams({ server: server, - permissions: permissions.toString() + permissions: permissions.toString(), }); const response = await fetch(`${this.offstylesApiUrl}/update_key?${params.toString()}`, { - method: 'POST', - credentials: 'include' // Include cookies for session authentication + method: "POST", + credentials: "include", // Include cookies for session authentication }); if (!response.ok) { @@ -413,11 +443,11 @@ class OffstylesApi extends Api { static async getServerKeyInfo(serverName: string): Promise { const params = new URLSearchParams({ - name: serverName + name: serverName, }); const response = await fetch(`${this.offstylesApiUrl}/server_key?${params.toString()}`, { - credentials: 'include' // Include cookies for session authentication + credentials: "include", // Include cookies for session authentication }); if (!response.ok) { @@ -435,12 +465,12 @@ class OffstylesApi extends Api { static async deleteApiKey(serverName: string): Promise { const params = new URLSearchParams({ - name: serverName + name: serverName, }); const response = await fetch(`${this.offstylesApiUrl}/delete_key?${params.toString()}`, { - method: 'DELETE', - credentials: 'include' // Include cookies for session authentication + method: "DELETE", + credentials: "include", // Include cookies for session authentication }); if (!response.ok) { @@ -458,15 +488,17 @@ class OffstylesApi extends Api { return responseText === "true"; } - static async getRecentModerationLogs(filter?: ModerationTargetFilter): Promise { + static async getRecentModerationLogs( + filter?: ModerationTargetFilter, + ): Promise { const params = new URLSearchParams(); if (filter) { - params.append('filter', filter); + params.append("filter", filter); } const response = await fetch(`${this.offstylesApiUrl}/mod_logs_recent?${params.toString()}`, { - credentials: 'include' // Include cookies for session authentication + credentials: "include", // Include cookies for session authentication }); if (!response.ok) { @@ -483,20 +515,24 @@ class OffstylesApi extends Api { } // Reverse moderator actions - static async reverseModerationActions(moderatorSteamId: string, timeframeHours: number, reason: string): Promise { + static async reverseModerationActions( + moderatorSteamId: string, + timeframeHours: number, + reason: string, + ): Promise { const data = { moderator_steam_id: moderatorSteamId, timeframe_hours: timeframeHours, - reason: reason + reason: reason, }; const response = await fetch(`${this.offstylesApiUrl}/reverse_moderator_actions`, { - method: 'POST', + method: "POST", headers: { - 'Content-Type': 'application/json', + "Content-Type": "application/json", }, body: JSON.stringify(data), - credentials: 'include' // Include cookies for session authentication + credentials: "include", // Include cookies for session authentication }); if (!response.ok) { @@ -515,17 +551,20 @@ class OffstylesApi extends Api { // New server management methods static async addServerSubserver(targetId: string, servers: ServerInfo[]): Promise { const params = new URLSearchParams({ - target: targetId + target: targetId, }); - const response = await fetch(`${this.offstylesApiUrl}/servers/subservers/add?${params.toString()}`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', + const response = await fetch( + `${this.offstylesApiUrl}/servers/subservers/add?${params.toString()}`, + { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(servers), + credentials: "include", }, - body: JSON.stringify(servers), - credentials: 'include' - }); + ); if (!response.ok) { const errorText = await response.text(); @@ -540,19 +579,25 @@ class OffstylesApi extends Api { return await response.json(); } - static async removeServerSubserver(targetId: string, servers: ServerInfo[]): Promise { + static async removeServerSubserver( + targetId: string, + servers: ServerInfo[], + ): Promise { const params = new URLSearchParams({ - target: targetId + target: targetId, }); - const response = await fetch(`${this.offstylesApiUrl}/servers/subservers/remove?${params.toString()}`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', + const response = await fetch( + `${this.offstylesApiUrl}/servers/subservers/remove?${params.toString()}`, + { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(servers), + credentials: "include", }, - body: JSON.stringify(servers), - credentials: 'include' - }); + ); if (!response.ok) { const errorText = await response.text(); @@ -567,19 +612,25 @@ class OffstylesApi extends Api { return await response.json(); } - static async updateServerSubservers(targetId: string, servers: ServerInfo[]): Promise { + static async updateServerSubservers( + targetId: string, + servers: ServerInfo[], + ): Promise { const params = new URLSearchParams({ - target: targetId + target: targetId, }); - const response = await fetch(`${this.offstylesApiUrl}/servers/subservers/update?${params.toString()}`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', + const response = await fetch( + `${this.offstylesApiUrl}/servers/subservers/update?${params.toString()}`, + { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(servers), + credentials: "include", }, - body: JSON.stringify(servers), - credentials: 'include' - }); + ); if (!response.ok) { const errorText = await response.text(); @@ -597,12 +648,12 @@ class OffstylesApi extends Api { static async updateServerName(targetId: string, name: string): Promise { const params = new URLSearchParams({ target: targetId, - name: name + name: name, }); const response = await fetch(`${this.offstylesApiUrl}/servers/name?${params.toString()}`, { - method: 'POST', - credentials: 'include' + method: "POST", + credentials: "include", }); if (!response.ok) { @@ -618,15 +669,18 @@ class OffstylesApi extends Api { return await response.json(); } - static async updateServerOwner(targetId: string, ownerSteamId: string): Promise { + static async updateServerOwner( + targetId: string, + ownerSteamId: string, + ): Promise { const params = new URLSearchParams({ target: targetId, - owner: ownerSteamId + owner: ownerSteamId, }); const response = await fetch(`${this.offstylesApiUrl}/servers/owner?${params.toString()}`, { - method: 'POST', - credentials: 'include' + method: "POST", + credentials: "include", }); if (!response.ok) { diff --git a/src/replay-viewer/LoadingModal.vue b/src/replay-viewer/LoadingModal.vue new file mode 100644 index 0000000..b1935c1 --- /dev/null +++ b/src/replay-viewer/LoadingModal.vue @@ -0,0 +1,72 @@ + + + + + diff --git a/src/replay-viewer/ReplayViewerOverlay.vue b/src/replay-viewer/ReplayViewerOverlay.vue new file mode 100644 index 0000000..9d6c9d7 --- /dev/null +++ b/src/replay-viewer/ReplayViewerOverlay.vue @@ -0,0 +1,497 @@ + + + diff --git a/src/replay-viewer/ViewerControls.vue b/src/replay-viewer/ViewerControls.vue new file mode 100644 index 0000000..891bfaa --- /dev/null +++ b/src/replay-viewer/ViewerControls.vue @@ -0,0 +1,245 @@ + + + + + diff --git a/src/replay-viewer/ViewerHUD.vue b/src/replay-viewer/ViewerHUD.vue new file mode 100644 index 0000000..4caac7b --- /dev/null +++ b/src/replay-viewer/ViewerHUD.vue @@ -0,0 +1,120 @@ + + + + + diff --git a/src/replay-viewer/camera.ts b/src/replay-viewer/camera.ts new file mode 100644 index 0000000..c0bb357 --- /dev/null +++ b/src/replay-viewer/camera.ts @@ -0,0 +1,145 @@ +import { mat4, vec3 } from 'gl-matrix'; +import type { PlaybackState } from './playback'; + +export class Camera { + readonly viewMatrix = mat4.create(); + private freecam = false; + + // Freecam state + private pos = vec3.fromValues(0, 0, 0); + private yaw = 0; + private pitch = 0; + private keys: Record = {}; + private speed = 800; + private sensitivity = 0.002; + private canvas: HTMLCanvasElement; + + private onKeyDown: (e: KeyboardEvent) => void; + private onKeyUp: (e: KeyboardEvent) => void; + private onMouseMove: (e: MouseEvent) => void; + + constructor(canvas: HTMLCanvasElement) { + this.canvas = canvas; + + this.onKeyDown = (e: KeyboardEvent) => { + this.keys[e.key.toLowerCase()] = true; + }; + this.onKeyUp = (e: KeyboardEvent) => { + this.keys[e.key.toLowerCase()] = false; + }; + this.onMouseMove = (e: MouseEvent) => { + if (!this.freecam || !document.pointerLockElement) return; + this.yaw -= e.movementX * this.sensitivity; + this.pitch -= e.movementY * this.sensitivity; + this.pitch = Math.max(-Math.PI / 2 + 0.01, Math.min(Math.PI / 2 - 0.01, this.pitch)); + }; + + document.addEventListener('keydown', this.onKeyDown); + document.addEventListener('keyup', this.onKeyUp); + canvas.addEventListener('mousemove', this.onMouseMove); + canvas.addEventListener('click', () => { + if (this.freecam && !document.pointerLockElement) { + canvas.requestPointerLock(); + } + }); + } + + get isFreecam(): boolean { + return this.freecam; + } + + toggleFreecam(): void { + this.freecam = !this.freecam; + if (this.freecam) { + this.canvas.requestPointerLock(); + } else { + document.exitPointerLock(); + } + } + + forceFreecam(): void { + this.freecam = true; + } + + getPosition(): Float32Array { + return new Float32Array([this.pos[0], this.pos[1], this.pos[2]]); + } + + update(dt: number, state: PlaybackState): void { + if (this.freecam) { + this.updateFreecam(dt); + } else { + this.updateFollowCam(state); + } + } + + private updateFollowCam(state: PlaybackState): void { + const px = state.position[0]; + const py = state.position[1]; + const pz = state.position[2] + state.eyeHeight; + + // Source Engine angles: yaw is angles[1], pitch is angles[0] + const yaw = state.angles[1] * Math.PI / 180; + const pitch = -state.angles[0] * Math.PI / 180; + + const cosPitch = Math.cos(pitch); + const fx = Math.cos(yaw) * cosPitch; + const fy = Math.sin(yaw) * cosPitch; + const fz = Math.sin(pitch); + + mat4.lookAt( + this.viewMatrix, + [px, py, pz], + [px + fx, py + fy, pz + fz], + [0, 0, 1], + ); + } + + private updateFreecam(dt: number): void { + const spd = this.keys['shift'] ? this.speed * 3 : this.speed; + + const cosPitch = Math.cos(this.pitch); + const fx = Math.cos(this.yaw) * cosPitch; + const fy = Math.sin(this.yaw) * cosPitch; + const fz = Math.sin(this.pitch); + + // Right vector (perpendicular to forward in XY plane) + const rx = Math.cos(this.yaw - Math.PI / 2); + const ry = Math.sin(this.yaw - Math.PI / 2); + + if (this.keys['w']) { + this.pos[0] += fx * spd * dt; + this.pos[1] += fy * spd * dt; + this.pos[2] += fz * spd * dt; + } + if (this.keys['s']) { + this.pos[0] -= fx * spd * dt; + this.pos[1] -= fy * spd * dt; + this.pos[2] -= fz * spd * dt; + } + if (this.keys['a']) { + this.pos[0] -= rx * spd * dt; + this.pos[1] -= ry * spd * dt; + } + if (this.keys['d']) { + this.pos[0] += rx * spd * dt; + this.pos[1] += ry * spd * dt; + } + + mat4.lookAt( + this.viewMatrix, + this.pos as unknown as vec3, + [this.pos[0] + fx, this.pos[1] + fy, this.pos[2] + fz], + [0, 0, 1], + ); + } + + dispose(): void { + document.removeEventListener('keydown', this.onKeyDown); + document.removeEventListener('keyup', this.onKeyUp); + this.canvas.removeEventListener('mousemove', this.onMouseMove); + if (document.pointerLockElement === this.canvas) { + document.exitPointerLock(); + } + } +} diff --git a/src/replay-viewer/fetchWithProgress.ts b/src/replay-viewer/fetchWithProgress.ts new file mode 100644 index 0000000..85ecfe5 --- /dev/null +++ b/src/replay-viewer/fetchWithProgress.ts @@ -0,0 +1,42 @@ +export async function fetchWithProgress( + url: string, + onProgress: (received: number, total: number | null) => void, + credentials: RequestCredentials = 'same-origin', +): Promise { + const response = await fetch(url, { credentials }); + if (!response.ok) { + throw new Error(`Failed to fetch ${url}: ${response.status} ${response.statusText}`); + } + + // If no body stream available, fall back to simple arrayBuffer + if (!response.body) { + onProgress(0, null); + return response.arrayBuffer(); + } + + const contentLength = response.headers.get('content-length'); + const total = contentLength ? parseInt(contentLength, 10) : null; + + // Always use streaming reader so progress updates even without Content-Length + const reader = response.body.getReader(); + const chunks: Uint8Array[] = []; + let received = 0; + + onProgress(0, total); + + while (true) { + const { done, value } = await reader.read(); + if (done) break; + chunks.push(value); + received += value.length; + onProgress(received, total); + } + + const result = new Uint8Array(received); + let offset = 0; + for (const chunk of chunks) { + result.set(chunk, offset); + offset += chunk.length; + } + return result.buffer; +} diff --git a/src/replay-viewer/math.ts b/src/replay-viewer/math.ts new file mode 100644 index 0000000..4aab518 --- /dev/null +++ b/src/replay-viewer/math.ts @@ -0,0 +1,43 @@ +export function deltaAngle(a: number, b: number): number { + return (b - a) - Math.floor((b - a + 180) / 360) * 360; +} + +export function hermiteValue(p0: number, p1: number, p2: number, p3: number, t: number): number { + const m0 = (p2 - p0) * 0.5; + const m1 = (p3 - p1) * 0.5; + const t2 = t * t; + const t3 = t * t * t; + return (2 * t3 - 3 * t2 + 1) * p1 + (t3 - 2 * t2 + t) * m0 + + (-2 * t3 + 3 * t2) * p2 + (t3 - t2) * m1; +} + +export function hermitePosition( + p0: Float32Array, p1: Float32Array, p2: Float32Array, p3: Float32Array, + t: number, out: Float32Array +): void { + out[0] = hermiteValue(p0[0], p1[0], p2[0], p3[0], t); + out[1] = hermiteValue(p0[1], p1[1], p2[1], p3[1], t); + out[2] = hermiteValue(p0[2], p1[2], p2[2], p3[2], t); +} + +export function hermiteAngles( + a0: Float32Array, a1: Float32Array, a2: Float32Array, a3: Float32Array, + t: number, out: Float32Array +): void { + // Pitch + out[0] = hermiteValue( + a1[0] + deltaAngle(a1[0], a0[0]), + a1[0], + a1[0] + deltaAngle(a1[0], a2[0]), + a1[0] + deltaAngle(a1[0], a3[0]), + t + ); + // Yaw + out[1] = hermiteValue( + a1[1] + deltaAngle(a1[1], a0[1]), + a1[1], + a1[1] + deltaAngle(a1[1], a2[1]), + a1[1] + deltaAngle(a1[1], a3[1]), + t + ); +} diff --git a/src/replay-viewer/playback.ts b/src/replay-viewer/playback.ts new file mode 100644 index 0000000..e6ea603 --- /dev/null +++ b/src/replay-viewer/playback.ts @@ -0,0 +1,211 @@ +import { hermitePosition, hermiteAngles, hermiteValue } from './math'; + +// Button flags +export const IN_JUMP = 1 << 1; +export const IN_DUCK = 1 << 2; +export const IN_FORWARD = 1 << 3; +export const IN_BACK = 1 << 4; +export const IN_MOVELEFT = 1 << 9; +export const IN_MOVERIGHT = 1 << 10; + +// Entity flags +export const FL_DUCKING = 1 << 1; + +export interface PlaybackState { + tick: number; + position: Float32Array; // [x, y, z] + angles: Float32Array; // [pitch, yaw] + buttons: number; + flags: number; + eyeHeight: number; + speed: number; + isPlaying: boolean; + playbackRate: number; + totalTicks: number; + tickRate: number; + time: number; +} + +export class PlaybackEngine { + private positions: Float32Array; + private angles: Float32Array; + private buttons: Int32Array; + private flags: Int32Array; + private tickCount: number; + readonly tickRate: number; + readonly replayTime: number; + + tick = 0; + isPlaying = true; + playbackRate = 1.0; + private spareTime = 0; + private pauseTicks = 100; + + // Temp buffers for interpolation + private tempPos = [new Float32Array(3), new Float32Array(3), new Float32Array(3), new Float32Array(3)]; + private tempAng = [new Float32Array(2), new Float32Array(2), new Float32Array(2), new Float32Array(2)]; + + // Output state + readonly state: PlaybackState; + + constructor( + positions: Float32Array, + angles: Float32Array, + buttons: Int32Array, + flags: Int32Array, + tickCount: number, + tickRate: number, + replayTime: number, + ) { + this.positions = positions; + this.angles = angles; + this.buttons = buttons; + this.flags = flags; + this.tickCount = tickCount; + this.tickRate = tickRate; + this.replayTime = replayTime; + + this.state = { + tick: 0, + position: new Float32Array(3), + angles: new Float32Array(2), + buttons: 0, + flags: 0, + eyeHeight: 64, + speed: 0, + isPlaying: true, + playbackRate: 1.0, + totalTicks: tickCount, + tickRate, + time: replayTime, + }; + } + + private clampTick(tick: number): number { + return Math.max(0, Math.min(tick, this.tickCount - 1)); + } + + private getTickPos(tick: number, out: Float32Array): void { + const t = this.clampTick(tick); + const off = t * 3; + out[0] = this.positions[off]; + out[1] = this.positions[off + 1]; + out[2] = this.positions[off + 2]; + } + + private getTickAngles(tick: number, out: Float32Array): void { + const t = this.clampTick(tick); + const off = t * 2; + out[0] = this.angles[off]; + out[1] = this.angles[off + 1]; + } + + private getTickFlags(tick: number): number { + return this.flags[this.clampTick(tick)]; + } + + private getTickButtons(tick: number): number { + return this.buttons[this.clampTick(tick)]; + } + + private getEyeHeight(flags: number): number { + return (flags & FL_DUCKING) !== 0 ? 46 : 64; + } + + setTick(tick: number): void { + this.tick = tick; + this.spareTime = 0; + } + + setPlaying(isPlaying: boolean): void { + this.isPlaying = isPlaying; + if (!isPlaying) { + this.spareTime = 0; + } + } + + togglePlaying(): void { + this.setPlaying(!this.isPlaying); + } + + setPlaybackRate(rate: number): void { + this.playbackRate = rate; + } + + update(dt: number): void { + const tickPeriod = 1.0 / this.tickRate; + + if (this.isPlaying) { + this.spareTime += dt * this.playbackRate; + + while (this.spareTime > tickPeriod) { + this.spareTime -= tickPeriod; + this.tick += 1; + if (this.tick > this.tickCount + this.pauseTicks * 2) { + this.tick = -this.pauseTicks; + } + } + + while (this.spareTime < 0) { + this.spareTime += tickPeriod; + this.tick -= 1; + if (this.tick < -this.pauseTicks * 2) { + this.tick = this.tickCount + this.pauseTicks; + } + } + } else { + this.spareTime = 0; + } + + const clamped = this.clampTick(this.tick); + const curFlags = this.getTickFlags(this.tick); + const curButtons = this.getTickButtons(this.tick); + let eyeHeight = this.getEyeHeight(curFlags); + + // Get base position/angles + this.getTickPos(this.tick, this.state.position); + this.getTickAngles(this.tick, this.state.angles); + + // Hermite interpolation + if (this.spareTime >= 0 && this.spareTime <= tickPeriod) { + const t = this.spareTime / tickPeriod; + + this.getTickPos(this.tick - 1, this.tempPos[0]); + this.getTickPos(this.tick, this.tempPos[1]); + this.getTickPos(this.tick + 1, this.tempPos[2]); + this.getTickPos(this.tick + 2, this.tempPos[3]); + + this.getTickAngles(this.tick - 1, this.tempAng[0]); + this.getTickAngles(this.tick, this.tempAng[1]); + this.getTickAngles(this.tick + 1, this.tempAng[2]); + this.getTickAngles(this.tick + 2, this.tempAng[3]); + + hermitePosition(this.tempPos[0], this.tempPos[1], this.tempPos[2], this.tempPos[3], t, this.state.position); + hermiteAngles(this.tempAng[0], this.tempAng[1], this.tempAng[2], this.tempAng[3], t, this.state.angles); + + eyeHeight = hermiteValue( + this.getEyeHeight(this.getTickFlags(this.tick - 1)), + this.getEyeHeight(curFlags), + this.getEyeHeight(this.getTickFlags(this.tick + 1)), + this.getEyeHeight(this.getTickFlags(this.tick + 2)), + t, + ); + } + + // Compute speed (horizontal velocity between ticks) + const prevTick = this.clampTick(clamped - 1); + const p0 = prevTick * 3; + const p1 = clamped * 3; + const dx = this.positions[p1] - this.positions[p0]; + const dy = this.positions[p1 + 1] - this.positions[p0 + 1]; + const speed = Math.sqrt(dx * dx + dy * dy) * this.tickRate; + + this.state.tick = clamped; + this.state.buttons = curButtons; + this.state.flags = curFlags; + this.state.eyeHeight = eyeHeight; + this.state.speed = speed; + this.state.isPlaying = this.isPlaying; + this.state.playbackRate = this.playbackRate; + } +} diff --git a/src/replay-viewer/renderer.ts b/src/replay-viewer/renderer.ts new file mode 100644 index 0000000..5a15dde --- /dev/null +++ b/src/replay-viewer/renderer.ts @@ -0,0 +1,833 @@ +import { mat4 } from 'gl-matrix'; +import type { BspMesh } from './wasm/bhop_replay_viewer_wasm'; + +// Vertex stride: 14 floats = [x, y, z, nx, ny, nz, lm_u, lm_v, tex_u, tex_v, atlas_min_u, atlas_min_v, atlas_scale_u, atlas_scale_v] +const STRIDE = 14 * 4; // 56 bytes + +const MAP_VERT = ` +attribute vec3 aPosition; +attribute vec3 aNormal; +attribute vec2 aLightmapUV; +attribute vec2 aTexUV; +attribute vec2 aAtlasMin; +attribute vec2 aAtlasScale; +uniform mat4 uProjection; +uniform mat4 uView; +uniform vec3 uCameraPos; +varying vec3 vNormal; +varying vec2 vLightmapUV; +varying vec2 vTexUV; +varying vec2 vAtlasMin; +varying vec2 vAtlasScale; +varying float vDist; +void main() { + vNormal = aNormal; + vLightmapUV = aLightmapUV; + vTexUV = aTexUV; + vAtlasMin = aAtlasMin; + vAtlasScale = aAtlasScale; + vDist = length(aPosition - uCameraPos); + gl_Position = uProjection * uView * vec4(aPosition, 1.0); +} +`; + +const MAP_FRAG = ` +#extension GL_OES_standard_derivatives : enable +#extension GL_EXT_shader_texture_lod : enable +precision mediump float; +varying vec3 vNormal; +varying vec2 vLightmapUV; +varying vec2 vTexUV; +varying vec2 vAtlasMin; +varying vec2 vAtlasScale; +varying float vDist; +uniform sampler2D uLightmap; +uniform sampler2D uTexture; +uniform vec2 uAtlasSize; +uniform float uDebugMode; +uniform float uAlphaOverride; +uniform float uTime; +uniform float uIsWater; + +const float RGBM_SCALE = 6.0; +const float MAX_SAFE_TEXELS = 8.0; // must match TEX_PAD in bsp.rs + +void main() { + vec3 n = normalize(vNormal); + if (!gl_FrontFacing) n = -n; + + // Sample base texture with per-pixel tiling + float hasTex = step(0.001, vAtlasScale.x + vAtlasScale.y); + + vec2 baseTexUV = vTexUV; + if (uIsWater > 0.5) { + baseTexUV += vec2(uTime * 0.05, uTime * 0.05); + } + + // Missing texture: classic Source Engine black & purple checkerboard + if (hasTex < 0.5) { + vec2 checker = floor(baseTexUV * 2.0); + float c = mod(checker.x + checker.y, 2.0); + vec3 missingColor = mix(vec3(0.0), vec3(0.498, 0.0, 0.498), c); + + // Apply lightmap if available + if (uDebugMode < 0.5) { + vec4 lmSample = texture2D(uLightmap, vLightmapUV); + vec3 lightColor = lmSample.rgb * lmSample.a * RGBM_SCALE; + float hasLM = step(0.001, vLightmapUV.x + vLightmapUV.y); + vec3 light = mix(vec3(1.0), lightColor, hasLM); + + // Unlit fallback + if (hasLM < 0.5) { + vec3 lightDir = normalize(vec3(0.5, 0.8, 1.0)); + float ndotl = max(dot(n, lightDir), 0.0); + float ambient = 0.5; + light = vec3(1.0) * (ambient + (1.0 - ambient) * ndotl); + } + + vec3 lit = pow(missingColor, vec3(2.2)) * light; + missingColor = pow(lit, vec3(1.0 / 2.2)); + } + + gl_FragColor = vec4(missingColor, uAlphaOverride); + return; + } + + vec2 rawDdx = dFdx(baseTexUV) * vAtlasScale; + vec2 rawDdy = dFdy(baseTexUV) * vAtlasScale; + + // Clamp gradients so mip level never exceeds padding coverage + float maxGrad = MAX_SAFE_TEXELS / max(uAtlasSize.x, uAtlasSize.y); + float gradLen = max(length(rawDdx), length(rawDdy)); + if (gradLen > maxGrad) { + float s = maxGrad / gradLen; + rawDdx *= s; + rawDdy *= s; + } + + vec2 tiledUV = fract(baseTexUV); + vec2 atlasUV = vAtlasMin + tiledUV * vAtlasScale; + vec4 texColor = texture2DGradEXT(uTexture, atlasUV, rawDdx, rawDdy); + + // Alpha test: discard nearly transparent fragments (cutout textures like fences, grates) + float alpha = mix(1.0, texColor.a, hasTex); + if (alpha < 0.1) discard; + + // Debug mode 1: raw texture only (no lightmap, no gamma) + if (uDebugMode > 0.5) { + gl_FragColor = vec4(texColor.rgb, alpha * uAlphaOverride); + return; + } + + // Linearize base texture (sRGB -> linear) before combining with lightmap + vec3 texLinear = pow(texColor.rgb, vec3(2.2)); + vec3 albedo = texLinear; + + // Extract flag (negative U = prop) and absolute UV + float isProp = step(vLightmapUV.x, -0.00005); + vec2 realLmUV = vec2(abs(vLightmapUV.x), vLightmapUV.y); + + // Sample lightmap (RGBM encoded, already linear) + vec4 lmSample = texture2D(uLightmap, realLmUV); + vec3 lightColor = lmSample.rgb * lmSample.a * RGBM_SCALE; + + float hasLM = step(0.001, realLmUV.x + realLmUV.y); + vec3 light = mix(vec3(1.0), lightColor, hasLM); + + // Apply fake directional lighting for props or unlit geometry + if (isProp > 0.5 || hasLM < 0.5) { + vec3 lightDir = normalize(vec3(0.5, 0.8, 1.0)); + float ndotl = max(dot(n, lightDir), 0.0); + float ambient = 0.5; + vec3 baseLight = isProp > 0.5 ? lightColor : vec3(1.0); + light = baseLight * (ambient + (1.0 - ambient) * ndotl); + } + + vec3 color = albedo * light; + color = pow(color, vec3(1.0 / 2.2)); + + gl_FragColor = vec4(color, alpha * uAlphaOverride); +} +`; + +const PLAYER_VERT = ` +attribute vec3 aPosition; +uniform mat4 uProjection; +uniform mat4 uView; +uniform mat4 uModel; +void main() { + gl_Position = uProjection * uView * uModel * vec4(aPosition, 1.0); +} +`; + +const PLAYER_FRAG = ` +precision mediump float; +void main() { + gl_FragColor = vec4(0.3, 0.65, 0.4, 1.0); +} +`; + +const SKY_VERT = ` +attribute vec3 aPosition; +attribute vec2 aUV; +uniform mat4 uProjection; +uniform mat4 uViewRotation; +varying vec2 vUV; +void main() { + vUV = aUV; + gl_Position = uProjection * uViewRotation * vec4(aPosition, 1.0); +} +`; + +const SKY_FRAG = ` +precision mediump float; +varying vec2 vUV; +uniform sampler2D uSkybox; +void main() { + gl_FragColor = texture2D(uSkybox, vUV); +} +`; + +// Depth-only shader for sky face occlusion +const DEPTH_VERT = ` +attribute vec3 aPosition; +uniform mat4 uProjection; +uniform mat4 uView; +void main() { + gl_Position = uProjection * uView * vec4(aPosition, 1.0); +} +`; + +const DEPTH_FRAG = ` +precision mediump float; +void main() { + gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0); +} +`; + +// Build 6 skybox quads matching noclip.website's exact vertex positions. +// Atlas layout: 3 columns x 2 rows +// Row 0: ft(0), bk(1), lf(2) +// Row 1: rt(3), up(4), dn(5) +function createSkyboxQuads(): { vertices: Float32Array; indices: Uint16Array } { + const S = 100; + const eps = 1.0 / 512.0; + + const faces: Array<{ verts: number[][]; localUVs: number[][]; faceIdx: number }> = [ + { // ft (faceIdx 0) + verts: [[S,-S,-S], [S,-S,S], [-S,-S,S], [-S,-S,-S]], + localUVs: [[0,1], [0,0], [1,0], [1,1]], + faceIdx: 0, + }, + { // bk (faceIdx 1) + verts: [[-S,S,-S], [-S,S,S], [S,S,S], [S,S,-S]], + localUVs: [[0,1], [0,0], [1,0], [1,1]], + faceIdx: 1, + }, + { // lf (faceIdx 2) + verts: [[-S,-S,-S], [-S,-S,S], [-S,S,S], [-S,S,-S]], + localUVs: [[0,1], [0,0], [1,0], [1,1]], + faceIdx: 2, + }, + { // rt (faceIdx 3) + verts: [[S,S,-S], [S,S,S], [S,-S,S], [S,-S,-S]], + localUVs: [[0,1], [0,0], [1,0], [1,1]], + faceIdx: 3, + }, + { // up (faceIdx 4) + verts: [[S,S,S], [-S,S,S], [-S,-S,S], [S,-S,S]], + localUVs: [[0,1], [0,0], [1,0], [1,1]], + faceIdx: 4, + }, + { // dn (faceIdx 5) + verts: [[-S,S,-S], [S,S,-S], [S,-S,-S], [-S,-S,-S]], + localUVs: [[0,1], [0,0], [1,0], [1,1]], + faceIdx: 5, + }, + ]; + + const vertData: number[] = []; + const idxs: number[] = []; + + for (const face of faces) { + const col = face.faceIdx % 3; + const row = Math.floor(face.faceIdx / 3); + const base = vertData.length / 5; + + for (let i = 0; i < 4; i++) { + const [lu, lv] = face.localUVs[i]; + const cu = Math.max(eps, Math.min(1 - eps, lu)); + const cv = Math.max(eps, Math.min(1 - eps, lv)); + const atlasU = col / 3 + cu / 3; + const atlasV = row / 2 + cv / 2; + vertData.push(face.verts[i][0], face.verts[i][1], face.verts[i][2], atlasU, atlasV); + } + + idxs.push(base, base + 1, base + 2); + idxs.push(base, base + 2, base + 3); + } + + return { vertices: new Float32Array(vertData), indices: new Uint16Array(idxs) }; +} + +function compileShader(gl: WebGLRenderingContext, type: number, source: string): WebGLShader { + const shader = gl.createShader(type)!; + gl.shaderSource(shader, source); + gl.compileShader(shader); + if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { + const info = gl.getShaderInfoLog(shader); + gl.deleteShader(shader); + throw new Error('Shader compile error: ' + info); + } + return shader; +} + +function createProgram(gl: WebGLRenderingContext, vert: string, frag: string): WebGLProgram { + const vs = compileShader(gl, gl.VERTEX_SHADER, vert); + const fs = compileShader(gl, gl.FRAGMENT_SHADER, frag); + const prog = gl.createProgram()!; + gl.attachShader(prog, vs); + gl.attachShader(prog, fs); + gl.linkProgram(prog); + if (!gl.getProgramParameter(prog, gl.LINK_STATUS)) { + const info = gl.getProgramInfoLog(prog); + throw new Error('Program link error: ' + info); + } + return prog; +} + +function createCubeData(): { vertices: Float32Array; indices: Uint16Array } { + const s = 8; + const h = 36; + const v = [ + -s, -s, 0, s, -s, 0, s, s, 0, -s, s, 0, + -s, -s, h, s, -s, h, s, s, h, -s, s, h, + ]; + const i = [ + 0,1,2, 0,2,3, 4,6,5, 4,7,6, 0,4,5, 0,5,1, + 2,6,7, 2,7,3, 0,3,7, 0,7,4, 1,5,6, 1,6,2, + ]; + return { vertices: new Float32Array(v), indices: new Uint16Array(i) }; +} + +interface ModelDrawRange { + indexStart: number; + indexCount: number; + cluster: number; +} + +export class Renderer { + private gl: WebGLRenderingContext; + private mapProgram: WebGLProgram; + private playerProgram: WebGLProgram; + private mapVBO: WebGLBuffer; + private mapIBO: WebGLBuffer; + private indexCount = 0; + private playerVBO: WebGLBuffer; + private playerIBO: WebGLBuffer; + private playerIndexCount: number; + private lightmapTexture: WebGLTexture | null = null; + private baseTexture: WebGLTexture | null = null; + private anisoExt: any = null; + private maxAnisotropy = 1; + + // Map uniforms + private uProjection: WebGLUniformLocation; + private uView: WebGLUniformLocation; + private uLightmap: WebGLUniformLocation; + private uTexture: WebGLUniformLocation; + private uAtlasSize: WebGLUniformLocation; + private uDebugMode: WebGLUniformLocation; + private uAlphaOverride: WebGLUniformLocation; + private uCameraPos: WebGLUniformLocation; + + private uTime: WebGLUniformLocation; + private uIsWater: WebGLUniformLocation; + + private atlasWidth = 0; + private atlasHeight = 0; + public debugTexMode = false; + + // Player uniforms + private puProjection: WebGLUniformLocation; + private puView: WebGLUniformLocation; + private puModel: WebGLUniformLocation; + + // Skybox + private skyboxProgram: WebGLProgram | null = null; + private skyboxVBO: WebGLBuffer | null = null; + private skyboxIBO: WebGLBuffer | null = null; + private skyboxTexture: WebGLTexture | null = null; + private skyboxIndexCount = 0; + private suProjection: WebGLUniformLocation | null = null; + private suViewRot: WebGLUniformLocation | null = null; + private suSkybox: WebGLUniformLocation | null = null; + + // Sky depth faces (occlusion) + private depthProgram: WebGLProgram | null = null; + private skyDepthVBO: WebGLBuffer | null = null; + private skyDepthIBO: WebGLBuffer | null = null; + private skyDepthIndexCount = 0; + private dpProjection: WebGLUniformLocation | null = null; + private dpView: WebGLUniformLocation | null = null; + + // PVS + private bspMesh: BspMesh | null = null; + private modelDrawRanges: ModelDrawRange[] = []; + private waterDrawRanges: ModelDrawRange[] = []; + + // Animated textures + private animTextures: { atlasX: number; atlasY: number; width: number; height: number; frameCount: number; fps: number; dataOffset: number; currentFrame: number }[] = []; + private animFrameData: Uint8Array | null = null; + + readonly projMatrix = mat4.create(); + private playerModelMatrix = mat4.create(); + + // Attribute locations (cached) + private aPos = -1; + private aNorm = -1; + private aLmUV = -1; + private aTexUV = -1; + private aAtlasMin = -1; + private aAtlasScale = -1; + + constructor(private canvas: HTMLCanvasElement) { + const gl = canvas.getContext('webgl', { antialias: true, alpha: false })!; + if (!gl) throw new Error('WebGL not supported'); + this.gl = gl; + + gl.getExtension('OES_element_index_uint'); + gl.getExtension('OES_standard_derivatives'); + gl.getExtension('EXT_shader_texture_lod'); + this.anisoExt = gl.getExtension('EXT_texture_filter_anisotropic') + || gl.getExtension('WEBKIT_EXT_texture_filter_anisotropic') + || gl.getExtension('MOZ_EXT_texture_filter_anisotropic'); + if (this.anisoExt) { + this.maxAnisotropy = gl.getParameter(this.anisoExt.MAX_TEXTURE_MAX_ANISOTROPY_EXT); + } + gl.enable(gl.DEPTH_TEST); + gl.disable(gl.CULL_FACE); + gl.clearColor(0.1, 0.1, 0.18, 1.0); + + // Map shader + this.mapProgram = createProgram(gl, MAP_VERT, MAP_FRAG); + this.uProjection = gl.getUniformLocation(this.mapProgram, 'uProjection')!; + this.uView = gl.getUniformLocation(this.mapProgram, 'uView')!; + this.uLightmap = gl.getUniformLocation(this.mapProgram, 'uLightmap')!; + this.uTexture = gl.getUniformLocation(this.mapProgram, 'uTexture')!; + this.uAtlasSize = gl.getUniformLocation(this.mapProgram, 'uAtlasSize')!; + this.uDebugMode = gl.getUniformLocation(this.mapProgram, 'uDebugMode')!; + this.uAlphaOverride = gl.getUniformLocation(this.mapProgram, 'uAlphaOverride')!; + this.uCameraPos = gl.getUniformLocation(this.mapProgram, 'uCameraPos')!; + + this.uTime = gl.getUniformLocation(this.mapProgram, 'uTime')!; + this.uIsWater = gl.getUniformLocation(this.mapProgram, 'uIsWater')!; + + // Cache attribute locations + this.aPos = gl.getAttribLocation(this.mapProgram, 'aPosition'); + this.aNorm = gl.getAttribLocation(this.mapProgram, 'aNormal'); + this.aLmUV = gl.getAttribLocation(this.mapProgram, 'aLightmapUV'); + this.aTexUV = gl.getAttribLocation(this.mapProgram, 'aTexUV'); + this.aAtlasMin = gl.getAttribLocation(this.mapProgram, 'aAtlasMin'); + this.aAtlasScale = gl.getAttribLocation(this.mapProgram, 'aAtlasScale'); + + // Player shader + this.playerProgram = createProgram(gl, PLAYER_VERT, PLAYER_FRAG); + this.puProjection = gl.getUniformLocation(this.playerProgram, 'uProjection')!; + this.puView = gl.getUniformLocation(this.playerProgram, 'uView')!; + this.puModel = gl.getUniformLocation(this.playerProgram, 'uModel')!; + + // Buffers + this.mapVBO = gl.createBuffer()!; + this.mapIBO = gl.createBuffer()!; + + const cube = createCubeData(); + this.playerVBO = gl.createBuffer()!; + gl.bindBuffer(gl.ARRAY_BUFFER, this.playerVBO); + gl.bufferData(gl.ARRAY_BUFFER, cube.vertices, gl.STATIC_DRAW); + this.playerIBO = gl.createBuffer()!; + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.playerIBO); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, cube.indices, gl.STATIC_DRAW); + this.playerIndexCount = cube.indices.length; + } + + uploadMap(vertices: Float32Array, indices: Uint32Array): void { + const gl = this.gl; + gl.bindBuffer(gl.ARRAY_BUFFER, this.mapVBO); + gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW); + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.mapIBO); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW); + this.indexCount = indices.length; + } + + setPVS(mesh: BspMesh): void { + this.bspMesh = mesh; + const drawData = mesh.model_draw_data(); + const count = mesh.model_draw_count(); + this.modelDrawRanges = []; + for (let i = 0; i < count; i++) { + this.modelDrawRanges.push({ + indexStart: drawData[i * 3], + indexCount: drawData[i * 3 + 1], + cluster: drawData[i * 3 + 2], + }); + } + // Water draw ranges (rendered separately with transparency) + const waterData = mesh.water_draw_data(); + const waterCount = mesh.water_draw_count(); + this.waterDrawRanges = []; + for (let i = 0; i < waterCount; i++) { + this.waterDrawRanges.push({ + indexStart: waterData[i * 3], + indexCount: waterData[i * 3 + 1], + cluster: waterData[i * 3 + 2], + }); + } + } + + setupAnimatedTextures(info: Float32Array, frameData: Uint8Array): void { + this.animFrameData = frameData; + this.animTextures = []; + const ENTRY_SIZE = 7; + const count = info.length / ENTRY_SIZE; + let computedOffset = 0; + for (let i = 0; i < count; i++) { + const off = i * ENTRY_SIZE; + const width = info[off + 2]; + const height = info[off + 3]; + const frameCount = info[off + 4]; + this.animTextures.push({ + atlasX: info[off], + atlasY: info[off + 1], + width, + height, + frameCount, + fps: info[off + 5], + dataOffset: computedOffset, + currentFrame: -1, + }); + computedOffset += width * height * 4 * frameCount; + } + } + + updateAnimations(time: number): void { + if (!this.animFrameData || this.animTextures.length === 0) return; + const gl = this.gl; + gl.activeTexture(gl.TEXTURE1); + gl.bindTexture(gl.TEXTURE_2D, this.baseTexture); + let updated = 0; + for (const anim of this.animTextures) { + const frame = Math.floor(time * anim.fps) % anim.frameCount; + if (frame === anim.currentFrame) continue; + anim.currentFrame = frame; + const frameBytes = anim.width * anim.height * 4; + const offset = anim.dataOffset + frame * frameBytes; + const pixels = new Uint8Array(this.animFrameData.buffer, this.animFrameData.byteOffset + offset, frameBytes); + gl.texSubImage2D(gl.TEXTURE_2D, 0, anim.atlasX, anim.atlasY, anim.width, anim.height, gl.RGBA, gl.UNSIGNED_BYTE, pixels); + updated++; + } + if (updated > 0) { + gl.generateMipmap(gl.TEXTURE_2D); + } + } + + uploadLightmap(data: Uint8Array, width: number, height: number): void { + const gl = this.gl; + this.lightmapTexture = gl.createTexture()!; + gl.bindTexture(gl.TEXTURE_2D, this.lightmapTexture); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, data); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + } + + uploadTextureAtlas(data: Uint8Array, width: number, height: number): void { + const gl = this.gl; + this.atlasWidth = width; + this.atlasHeight = height; + this.baseTexture = gl.createTexture()!; + gl.bindTexture(gl.TEXTURE_2D, this.baseTexture); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, data); + gl.generateMipmap(gl.TEXTURE_2D); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + if (this.anisoExt) { + gl.texParameterf(gl.TEXTURE_2D, this.anisoExt.TEXTURE_MAX_ANISOTROPY_EXT, this.maxAnisotropy); + } + } + + /** Patch a region of the texture atlas (for external texture loading). Caller must include tiling padding. */ + patchTextureAtlas(x: number, y: number, width: number, height: number, data: Uint8Array): void { + const gl = this.gl; + gl.bindTexture(gl.TEXTURE_2D, this.baseTexture); + gl.texSubImage2D(gl.TEXTURE_2D, 0, x, y, width, height, gl.RGBA, gl.UNSIGNED_BYTE, data); + gl.generateMipmap(gl.TEXTURE_2D); + } + + uploadSkybox(data: Uint8Array, faceSize: number): void { + const gl = this.gl; + + // Build skybox shader + geometry + this.skyboxProgram = createProgram(gl, SKY_VERT, SKY_FRAG); + this.suProjection = gl.getUniformLocation(this.skyboxProgram, 'uProjection'); + this.suViewRot = gl.getUniformLocation(this.skyboxProgram, 'uViewRotation'); + this.suSkybox = gl.getUniformLocation(this.skyboxProgram, 'uSkybox'); + + const quads = createSkyboxQuads(); + this.skyboxVBO = gl.createBuffer()!; + gl.bindBuffer(gl.ARRAY_BUFFER, this.skyboxVBO); + gl.bufferData(gl.ARRAY_BUFFER, quads.vertices, gl.STATIC_DRAW); + this.skyboxIBO = gl.createBuffer()!; + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.skyboxIBO); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, quads.indices, gl.STATIC_DRAW); + this.skyboxIndexCount = quads.indices.length; + + // Build 3x2 atlas from 6 concatenated face images + const atlasW = faceSize * 3; + const atlasH = faceSize * 2; + const faceBytes = faceSize * faceSize * 4; + const atlas = new Uint8Array(atlasW * atlasH * 4); + for (let fi = 0; fi < 6; fi++) { + const col = fi % 3; + const row = Math.floor(fi / 3); + const ox = col * faceSize; + const oy = row * faceSize; + const srcOff = fi * faceBytes; + for (let y = 0; y < faceSize; y++) { + const srcRow = srcOff + y * faceSize * 4; + const dstRow = ((oy + y) * atlasW + ox) * 4; + atlas.set(data.subarray(srcRow, srcRow + faceSize * 4), dstRow); + } + } + + this.skyboxTexture = gl.createTexture()!; + gl.bindTexture(gl.TEXTURE_2D, this.skyboxTexture); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, atlasW, atlasH, 0, gl.RGBA, gl.UNSIGNED_BYTE, atlas); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + } + + uploadSkyDepth(vertices: Float32Array, indices: Uint32Array): void { + const gl = this.gl; + this.depthProgram = createProgram(gl, DEPTH_VERT, DEPTH_FRAG); + this.dpProjection = gl.getUniformLocation(this.depthProgram, 'uProjection'); + this.dpView = gl.getUniformLocation(this.depthProgram, 'uView'); + + this.skyDepthVBO = gl.createBuffer()!; + gl.bindBuffer(gl.ARRAY_BUFFER, this.skyDepthVBO); + gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW); + + this.skyDepthIBO = gl.createBuffer()!; + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.skyDepthIBO); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW); + + this.skyDepthIndexCount = indices.length; + } + + resize(): void { + const canvas = this.canvas; + const dpr = window.devicePixelRatio || 1; + const w = canvas.clientWidth * dpr; + const h = canvas.clientHeight * dpr; + if (canvas.width !== w || canvas.height !== h) { + canvas.width = w; + canvas.height = h; + } + this.gl.viewport(0, 0, canvas.width, canvas.height); + mat4.perspective(this.projMatrix, 80 * Math.PI / 180, w / h, 1, 65536); + } + + render(viewMatrix: mat4, playerPos: Float32Array, showPlayer: boolean = true): void { + const gl = this.gl; + this.resize(); + + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + + // Draw skybox first (depth test OFF so it fills background) + if (this.skyboxTexture && this.skyboxProgram) { + gl.disable(gl.DEPTH_TEST); + gl.depthMask(false); + gl.useProgram(this.skyboxProgram); + gl.uniformMatrix4fv(this.suProjection, false, this.projMatrix); + + // View matrix with translation removed (rotation only) + const viewRot = mat4.clone(viewMatrix); + viewRot[12] = 0; viewRot[13] = 0; viewRot[14] = 0; + gl.uniformMatrix4fv(this.suViewRot, false, viewRot); + + gl.activeTexture(gl.TEXTURE2); + gl.bindTexture(gl.TEXTURE_2D, this.skyboxTexture); + gl.uniform1i(this.suSkybox, 2); + + // Stride: 5 floats (pos3 + uv2) = 20 bytes + gl.bindBuffer(gl.ARRAY_BUFFER, this.skyboxVBO!); + const sPos = gl.getAttribLocation(this.skyboxProgram, 'aPosition'); + const sUV = gl.getAttribLocation(this.skyboxProgram, 'aUV'); + gl.enableVertexAttribArray(sPos); + gl.vertexAttribPointer(sPos, 3, gl.FLOAT, false, 20, 0); + gl.enableVertexAttribArray(sUV); + gl.vertexAttribPointer(sUV, 2, gl.FLOAT, false, 20, 12); + + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.skyboxIBO!); + gl.drawElements(gl.TRIANGLES, this.skyboxIndexCount, gl.UNSIGNED_SHORT, 0); + + gl.disableVertexAttribArray(sPos); + gl.disableVertexAttribArray(sUV); + gl.depthMask(true); + gl.enable(gl.DEPTH_TEST); + } + + // Draw sky faces depth-only (occlusion barrier so geometry behind sky isn't visible) + if (this.depthProgram && this.skyDepthIndexCount > 0) { + gl.useProgram(this.depthProgram); + gl.uniformMatrix4fv(this.dpProjection, false, this.projMatrix); + gl.uniformMatrix4fv(this.dpView, false, viewMatrix); + gl.colorMask(false, false, false, false); + + gl.bindBuffer(gl.ARRAY_BUFFER, this.skyDepthVBO!); + const dpPos = gl.getAttribLocation(this.depthProgram, 'aPosition'); + gl.enableVertexAttribArray(dpPos); + gl.vertexAttribPointer(dpPos, 3, gl.FLOAT, false, 12, 0); + + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.skyDepthIBO!); + gl.drawElements(gl.TRIANGLES, this.skyDepthIndexCount, gl.UNSIGNED_INT, 0); + + gl.disableVertexAttribArray(dpPos); + gl.colorMask(true, true, true, true); + } + + if (this.indexCount === 0) return; + + // Enable alpha blending for transparent textures (fences, grates, glass, etc.) + gl.enable(gl.BLEND); + gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); + + // Draw map + gl.useProgram(this.mapProgram); + gl.uniformMatrix4fv(this.uProjection, false, this.projMatrix); + gl.uniformMatrix4fv(this.uView, false, viewMatrix); + gl.uniform3f(this.uCameraPos, playerPos[0], playerPos[1], playerPos[2]); + gl.uniform1f(this.uTime, performance.now() / 1000.0); + + // Bind lightmap on unit 0 + gl.activeTexture(gl.TEXTURE0); + gl.bindTexture(gl.TEXTURE_2D, this.lightmapTexture); + gl.uniform1i(this.uLightmap, 0); + + // Bind texture atlas on unit 1 + gl.activeTexture(gl.TEXTURE1); + gl.bindTexture(gl.TEXTURE_2D, this.baseTexture); + gl.uniform1i(this.uTexture, 1); + gl.uniform2f(this.uAtlasSize, this.atlasWidth, this.atlasHeight); + gl.uniform1f(this.uDebugMode, this.debugTexMode ? 1.0 : 0.0); + gl.uniform1f(this.uAlphaOverride, 1.0); + + gl.bindBuffer(gl.ARRAY_BUFFER, this.mapVBO); + gl.enableVertexAttribArray(this.aPos); + gl.vertexAttribPointer(this.aPos, 3, gl.FLOAT, false, STRIDE, 0); + gl.enableVertexAttribArray(this.aNorm); + gl.vertexAttribPointer(this.aNorm, 3, gl.FLOAT, false, STRIDE, 12); + gl.enableVertexAttribArray(this.aLmUV); + gl.vertexAttribPointer(this.aLmUV, 2, gl.FLOAT, false, STRIDE, 24); + gl.enableVertexAttribArray(this.aTexUV); + gl.vertexAttribPointer(this.aTexUV, 2, gl.FLOAT, false, STRIDE, 32); + gl.enableVertexAttribArray(this.aAtlasMin); + gl.vertexAttribPointer(this.aAtlasMin, 2, gl.FLOAT, false, STRIDE, 40); + gl.enableVertexAttribArray(this.aAtlasScale); + gl.vertexAttribPointer(this.aAtlasScale, 2, gl.FLOAT, false, STRIDE, 48); + + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.mapIBO); + + // PVS-based per-cluster draw calls (opaque geometry) + if (this.bspMesh && this.modelDrawRanges.length > 0) { + gl.uniform1f(this.uIsWater, 0.0); + const camCluster = this.bspMesh.find_cluster(playerPos[0], playerPos[1], playerPos[2]); + for (let i = 0; i < this.modelDrawRanges.length; i++) { + const m = this.modelDrawRanges[i]; + if (m.indexCount === 0) continue; + // cluster -1 = unknown, always draw; otherwise PVS check + if (m.cluster < 0 || this.bspMesh.is_cluster_visible(camCluster, m.cluster)) { + gl.drawElements(gl.TRIANGLES, m.indexCount, gl.UNSIGNED_INT, m.indexStart * 4); + } + } + + // Water pass: render with transparency, no depth write + if (this.waterDrawRanges.length > 0) { + gl.depthMask(false); + gl.uniform1f(this.uAlphaOverride, 0.6); + gl.uniform1f(this.uIsWater, 1.0); + for (let i = 0; i < this.waterDrawRanges.length; i++) { + const m = this.waterDrawRanges[i]; + if (m.indexCount === 0) continue; + if (m.cluster < 0 || this.bspMesh.is_cluster_visible(camCluster, m.cluster)) { + gl.drawElements(gl.TRIANGLES, m.indexCount, gl.UNSIGNED_INT, m.indexStart * 4); + } + } + gl.depthMask(true); + gl.uniform1f(this.uAlphaOverride, 1.0); + gl.uniform1f(this.uIsWater, 0.0); + } + } else { + gl.uniform1f(this.uIsWater, 0.0); + gl.drawElements(gl.TRIANGLES, this.indexCount, gl.UNSIGNED_INT, 0); + } + + gl.disableVertexAttribArray(this.aNorm); + gl.disableVertexAttribArray(this.aLmUV); + gl.disableVertexAttribArray(this.aTexUV); + gl.disableVertexAttribArray(this.aAtlasMin); + gl.disableVertexAttribArray(this.aAtlasScale); + + // Disable blending for subsequent draws (player cube, etc.) + gl.disable(gl.BLEND); + + // Draw player cube (only in freecam) + if (showPlayer) { + gl.useProgram(this.playerProgram); + gl.uniformMatrix4fv(this.puProjection, false, this.projMatrix); + gl.uniformMatrix4fv(this.puView, false, viewMatrix); + + mat4.identity(this.playerModelMatrix); + mat4.translate(this.playerModelMatrix, this.playerModelMatrix, [ + playerPos[0], playerPos[1], playerPos[2], + ]); + gl.uniformMatrix4fv(this.puModel, false, this.playerModelMatrix); + + gl.bindBuffer(gl.ARRAY_BUFFER, this.playerVBO); + const pPos = gl.getAttribLocation(this.playerProgram, 'aPosition'); + gl.enableVertexAttribArray(pPos); + gl.vertexAttribPointer(pPos, 3, gl.FLOAT, false, 12, 0); + + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.playerIBO); + gl.drawElements(gl.TRIANGLES, this.playerIndexCount, gl.UNSIGNED_SHORT, 0); + + gl.disableVertexAttribArray(pPos); + } + } + + dispose(): void { + const gl = this.gl; + gl.deleteBuffer(this.mapVBO); + gl.deleteBuffer(this.mapIBO); + gl.deleteBuffer(this.playerVBO); + gl.deleteBuffer(this.playerIBO); + if (this.lightmapTexture) gl.deleteTexture(this.lightmapTexture); + if (this.baseTexture) gl.deleteTexture(this.baseTexture); + if (this.skyboxTexture) gl.deleteTexture(this.skyboxTexture); + if (this.skyboxVBO) gl.deleteBuffer(this.skyboxVBO); + if (this.skyboxIBO) gl.deleteBuffer(this.skyboxIBO); + if (this.skyDepthVBO) gl.deleteBuffer(this.skyDepthVBO); + if (this.skyDepthIBO) gl.deleteBuffer(this.skyDepthIBO); + gl.deleteProgram(this.mapProgram); + gl.deleteProgram(this.playerProgram); + if (this.skyboxProgram) gl.deleteProgram(this.skyboxProgram); + if (this.depthProgram) gl.deleteProgram(this.depthProgram); + const ext = gl.getExtension('WEBGL_lose_context'); + if (ext) ext.loseContext(); + } +} diff --git a/src/replay-viewer/wasm/bhop_replay_viewer_wasm.d.ts b/src/replay-viewer/wasm/bhop_replay_viewer_wasm.d.ts new file mode 100644 index 0000000..e5dc791 --- /dev/null +++ b/src/replay-viewer/wasm/bhop_replay_viewer_wasm.d.ts @@ -0,0 +1,191 @@ +/* tslint:disable */ +/* eslint-disable */ + +export class BspMesh { + private constructor(); + free(): void; + [Symbol.dispose](): void; + /** + * Animated texture frame data (all frames for all animated textures, concatenated) + */ + animated_frame_data(): Uint8Array; + /** + * Animated texture metadata: [atlas_x, atlas_y, width, height, frame_count, fps, data_byte_offset] per texture + */ + animated_texture_info(): Float32Array; + /** + * Find the cluster for a world position (for camera PVS lookup) + */ + find_cluster(x: number, y: number, z: number): number; + has_sky_faces(): boolean; + has_skybox(): boolean; + index_count(): number; + index_data(): Uint32Array; + /** + * Check if cluster `to` is visible from cluster `from` + */ + is_cluster_visible(from: number, to: number): boolean; + lightmap_atlas_data(): Uint8Array; + lightmap_height(): number; + lightmap_width(): number; + /** + * JSON array of missing prop model paths: ["models/props/foo.mdl", ...] + */ + missing_props(): string; + /** + * Number of drawable models (call before model_draw_data) + */ + model_draw_count(): number; + /** + * Returns per-model draw info as flat array: [index_start, index_count, cluster] * N + */ + model_draw_data(): Int32Array; + sky_index_data(): Uint32Array; + /** + * Sky face positions [x,y,z] for depth-only rendering + */ + sky_vertex_data(): Float32Array; + skybox_data(): Uint8Array; + skybox_face_size(): number; + texture_atlas_data(): Uint8Array; + texture_atlas_height(): number; + texture_atlas_width(): number; + /** + * JSON array of unresolved texture info: [{name, atlas_x, atlas_y, width, height, pad}, ...] + */ + unresolved_textures(): string; + vertex_count(): number; + /** + * Move vertex data out (avoids clone). Field becomes empty after call. + */ + vertex_data(): Float32Array; + /** + * Number of water draw ranges (call before water_draw_data) + */ + water_draw_count(): number; + /** + * Water draw ranges: same format as model_draw_data but for water faces + */ + water_draw_data(): Int32Array; +} + +export class ReplayData { + private constructor(); + free(): void; + [Symbol.dispose](): void; + angles(): Float32Array; + buttons_array(): Int32Array; + flags_array(): Int32Array; + map_name(): string; + positions(): Float32Array; + preframes(): number; + tick_count(): number; + tick_rate(): number; + time(): number; +} + +/** + * Decode a VTF file, downscale to target dimensions, apply color tint, create tiled version with padding. + * Returns RGBA data of size (target_w + 2*pad) × (target_h + 2*pad) × 4, ready for texSubImage2D. + * When force_opaque is true, all alpha values are set to 255 (most Source textures use alpha + * for specular masks etc., not actual transparency). + */ +export function decode_and_tile_vtf(vtf_data: Uint8Array, target_w: number, target_h: number, color_r: number, color_g: number, color_b: number, force_opaque: boolean): Uint8Array | undefined; + +export function decompress_bz2(data: Uint8Array): Uint8Array; + +export function init(): void; + +export function parse_bsp(data: Uint8Array): BspMesh; + +/** + * Parse a BSP with extra files injected (e.g. prop models from VPK). + * `extras_json` is a JSON array of `{"path":"models/foo.mdl","offset":0,"length":1234}`. + * `extras_data` is all the file contents concatenated. + */ +export function parse_bsp_with_extras(data: Uint8Array, extras_json: string, extras_data: Uint8Array): BspMesh; + +export function parse_replay(data: Uint8Array): ReplayData; + +/** + * Parse a VMT file and return JSON: {"basetexture":"...", "color":[r,g,b], "fps":0, "is_water":false} + */ +export function parse_vmt_data(data: Uint8Array): string | undefined; + +export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module; + +export interface InitOutput { + readonly memory: WebAssembly.Memory; + readonly __wbg_bspmesh_free: (a: number, b: number) => void; + readonly bspmesh_animated_frame_data: (a: number) => [number, number]; + readonly bspmesh_animated_texture_info: (a: number) => [number, number]; + readonly bspmesh_find_cluster: (a: number, b: number, c: number, d: number) => number; + readonly bspmesh_has_sky_faces: (a: number) => number; + readonly bspmesh_has_skybox: (a: number) => number; + readonly bspmesh_index_count: (a: number) => number; + readonly bspmesh_index_data: (a: number) => [number, number]; + readonly bspmesh_is_cluster_visible: (a: number, b: number, c: number) => number; + readonly bspmesh_lightmap_atlas_data: (a: number) => [number, number]; + readonly bspmesh_lightmap_height: (a: number) => number; + readonly bspmesh_lightmap_width: (a: number) => number; + readonly bspmesh_missing_props: (a: number) => [number, number]; + readonly bspmesh_model_draw_count: (a: number) => number; + readonly bspmesh_model_draw_data: (a: number) => [number, number]; + readonly bspmesh_sky_index_data: (a: number) => [number, number]; + readonly bspmesh_sky_vertex_data: (a: number) => [number, number]; + readonly bspmesh_skybox_data: (a: number) => [number, number]; + readonly bspmesh_skybox_face_size: (a: number) => number; + readonly bspmesh_texture_atlas_data: (a: number) => [number, number]; + readonly bspmesh_texture_atlas_height: (a: number) => number; + readonly bspmesh_texture_atlas_width: (a: number) => number; + readonly bspmesh_unresolved_textures: (a: number) => [number, number]; + readonly bspmesh_vertex_count: (a: number) => number; + readonly bspmesh_vertex_data: (a: number) => [number, number]; + readonly bspmesh_water_draw_count: (a: number) => number; + readonly bspmesh_water_draw_data: (a: number) => [number, number]; + readonly parse_bsp: (a: number, b: number) => [number, number, number]; + readonly parse_bsp_with_extras: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number, number]; + readonly __wbg_replaydata_free: (a: number, b: number) => void; + readonly parse_replay: (a: number, b: number) => [number, number, number]; + readonly replaydata_angles: (a: number) => [number, number]; + readonly replaydata_buttons_array: (a: number) => [number, number]; + readonly replaydata_flags_array: (a: number) => [number, number]; + readonly replaydata_map_name: (a: number) => [number, number]; + readonly replaydata_positions: (a: number) => [number, number]; + readonly replaydata_preframes: (a: number) => number; + readonly replaydata_tick_count: (a: number) => number; + readonly replaydata_tick_rate: (a: number) => number; + readonly replaydata_time: (a: number) => number; + readonly decode_and_tile_vtf: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number) => [number, number]; + readonly init: () => void; + readonly parse_vmt_data: (a: number, b: number) => [number, number]; + readonly decompress_bz2: (a: number, b: number) => [number, number, number, number]; + readonly __wbindgen_free: (a: number, b: number, c: number) => void; + readonly __wbindgen_malloc: (a: number, b: number) => number; + readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number; + readonly __wbindgen_externrefs: WebAssembly.Table; + readonly __externref_table_dealloc: (a: number) => void; + readonly __wbindgen_start: () => void; +} + +export type SyncInitInput = BufferSource | WebAssembly.Module; + +/** + * Instantiates the given `module`, which can either be bytes or + * a precompiled `WebAssembly.Module`. + * + * @param {{ module: SyncInitInput }} module - Passing `SyncInitInput` directly is deprecated. + * + * @returns {InitOutput} + */ +export function initSync(module: { module: SyncInitInput } | SyncInitInput): InitOutput; + +/** + * If `module_or_path` is {RequestInfo} or {URL}, makes a request and + * for everything else, calls `WebAssembly.instantiate` directly. + * + * @param {{ module_or_path: InitInput | Promise }} module_or_path - Passing `InitInput` directly is deprecated. + * + * @returns {Promise} + */ +export default function __wbg_init (module_or_path?: { module_or_path: InitInput | Promise } | InitInput | Promise): Promise; diff --git a/src/replay-viewer/wasm/bhop_replay_viewer_wasm.js b/src/replay-viewer/wasm/bhop_replay_viewer_wasm.js new file mode 100644 index 0000000..1f2fcde --- /dev/null +++ b/src/replay-viewer/wasm/bhop_replay_viewer_wasm.js @@ -0,0 +1,779 @@ +/* @ts-self-types="./bhop_replay_viewer_wasm.d.ts" */ + +export class BspMesh { + static __wrap(ptr) { + ptr = ptr >>> 0; + const obj = Object.create(BspMesh.prototype); + obj.__wbg_ptr = ptr; + BspMeshFinalization.register(obj, obj.__wbg_ptr, obj); + return obj; + } + __destroy_into_raw() { + const ptr = this.__wbg_ptr; + this.__wbg_ptr = 0; + BspMeshFinalization.unregister(this); + return ptr; + } + free() { + const ptr = this.__destroy_into_raw(); + wasm.__wbg_bspmesh_free(ptr, 0); + } + /** + * Animated texture frame data (all frames for all animated textures, concatenated) + * @returns {Uint8Array} + */ + animated_frame_data() { + const ret = wasm.bspmesh_animated_frame_data(this.__wbg_ptr); + var v1 = getArrayU8FromWasm0(ret[0], ret[1]).slice(); + wasm.__wbindgen_free(ret[0], ret[1] * 1, 1); + return v1; + } + /** + * Animated texture metadata: [atlas_x, atlas_y, width, height, frame_count, fps, data_byte_offset] per texture + * @returns {Float32Array} + */ + animated_texture_info() { + const ret = wasm.bspmesh_animated_texture_info(this.__wbg_ptr); + var v1 = getArrayF32FromWasm0(ret[0], ret[1]).slice(); + wasm.__wbindgen_free(ret[0], ret[1] * 4, 4); + return v1; + } + /** + * Find the cluster for a world position (for camera PVS lookup) + * @param {number} x + * @param {number} y + * @param {number} z + * @returns {number} + */ + find_cluster(x, y, z) { + const ret = wasm.bspmesh_find_cluster(this.__wbg_ptr, x, y, z); + return ret; + } + /** + * @returns {boolean} + */ + has_sky_faces() { + const ret = wasm.bspmesh_has_sky_faces(this.__wbg_ptr); + return ret !== 0; + } + /** + * @returns {boolean} + */ + has_skybox() { + const ret = wasm.bspmesh_has_skybox(this.__wbg_ptr); + return ret !== 0; + } + /** + * @returns {number} + */ + index_count() { + const ret = wasm.bspmesh_index_count(this.__wbg_ptr); + return ret >>> 0; + } + /** + * @returns {Uint32Array} + */ + index_data() { + const ret = wasm.bspmesh_index_data(this.__wbg_ptr); + var v1 = getArrayU32FromWasm0(ret[0], ret[1]).slice(); + wasm.__wbindgen_free(ret[0], ret[1] * 4, 4); + return v1; + } + /** + * Check if cluster `to` is visible from cluster `from` + * @param {number} from + * @param {number} to + * @returns {boolean} + */ + is_cluster_visible(from, to) { + const ret = wasm.bspmesh_is_cluster_visible(this.__wbg_ptr, from, to); + return ret !== 0; + } + /** + * @returns {Uint8Array} + */ + lightmap_atlas_data() { + const ret = wasm.bspmesh_lightmap_atlas_data(this.__wbg_ptr); + var v1 = getArrayU8FromWasm0(ret[0], ret[1]).slice(); + wasm.__wbindgen_free(ret[0], ret[1] * 1, 1); + return v1; + } + /** + * @returns {number} + */ + lightmap_height() { + const ret = wasm.bspmesh_lightmap_height(this.__wbg_ptr); + return ret >>> 0; + } + /** + * @returns {number} + */ + lightmap_width() { + const ret = wasm.bspmesh_lightmap_width(this.__wbg_ptr); + return ret >>> 0; + } + /** + * JSON array of missing prop model paths: ["models/props/foo.mdl", ...] + * @returns {string} + */ + missing_props() { + let deferred1_0; + let deferred1_1; + try { + const ret = wasm.bspmesh_missing_props(this.__wbg_ptr); + deferred1_0 = ret[0]; + deferred1_1 = ret[1]; + return getStringFromWasm0(ret[0], ret[1]); + } finally { + wasm.__wbindgen_free(deferred1_0, deferred1_1, 1); + } + } + /** + * Number of drawable models (call before model_draw_data) + * @returns {number} + */ + model_draw_count() { + const ret = wasm.bspmesh_model_draw_count(this.__wbg_ptr); + return ret >>> 0; + } + /** + * Returns per-model draw info as flat array: [index_start, index_count, cluster] * N + * @returns {Int32Array} + */ + model_draw_data() { + const ret = wasm.bspmesh_model_draw_data(this.__wbg_ptr); + var v1 = getArrayI32FromWasm0(ret[0], ret[1]).slice(); + wasm.__wbindgen_free(ret[0], ret[1] * 4, 4); + return v1; + } + /** + * @returns {Uint32Array} + */ + sky_index_data() { + const ret = wasm.bspmesh_sky_index_data(this.__wbg_ptr); + var v1 = getArrayU32FromWasm0(ret[0], ret[1]).slice(); + wasm.__wbindgen_free(ret[0], ret[1] * 4, 4); + return v1; + } + /** + * Sky face positions [x,y,z] for depth-only rendering + * @returns {Float32Array} + */ + sky_vertex_data() { + const ret = wasm.bspmesh_sky_vertex_data(this.__wbg_ptr); + var v1 = getArrayF32FromWasm0(ret[0], ret[1]).slice(); + wasm.__wbindgen_free(ret[0], ret[1] * 4, 4); + return v1; + } + /** + * @returns {Uint8Array} + */ + skybox_data() { + const ret = wasm.bspmesh_skybox_data(this.__wbg_ptr); + var v1 = getArrayU8FromWasm0(ret[0], ret[1]).slice(); + wasm.__wbindgen_free(ret[0], ret[1] * 1, 1); + return v1; + } + /** + * @returns {number} + */ + skybox_face_size() { + const ret = wasm.bspmesh_skybox_face_size(this.__wbg_ptr); + return ret >>> 0; + } + /** + * @returns {Uint8Array} + */ + texture_atlas_data() { + const ret = wasm.bspmesh_texture_atlas_data(this.__wbg_ptr); + var v1 = getArrayU8FromWasm0(ret[0], ret[1]).slice(); + wasm.__wbindgen_free(ret[0], ret[1] * 1, 1); + return v1; + } + /** + * @returns {number} + */ + texture_atlas_height() { + const ret = wasm.bspmesh_texture_atlas_height(this.__wbg_ptr); + return ret >>> 0; + } + /** + * @returns {number} + */ + texture_atlas_width() { + const ret = wasm.bspmesh_texture_atlas_width(this.__wbg_ptr); + return ret >>> 0; + } + /** + * JSON array of unresolved texture info: [{name, atlas_x, atlas_y, width, height, pad}, ...] + * @returns {string} + */ + unresolved_textures() { + let deferred1_0; + let deferred1_1; + try { + const ret = wasm.bspmesh_unresolved_textures(this.__wbg_ptr); + deferred1_0 = ret[0]; + deferred1_1 = ret[1]; + return getStringFromWasm0(ret[0], ret[1]); + } finally { + wasm.__wbindgen_free(deferred1_0, deferred1_1, 1); + } + } + /** + * @returns {number} + */ + vertex_count() { + const ret = wasm.bspmesh_vertex_count(this.__wbg_ptr); + return ret >>> 0; + } + /** + * Move vertex data out (avoids clone). Field becomes empty after call. + * @returns {Float32Array} + */ + vertex_data() { + const ret = wasm.bspmesh_vertex_data(this.__wbg_ptr); + var v1 = getArrayF32FromWasm0(ret[0], ret[1]).slice(); + wasm.__wbindgen_free(ret[0], ret[1] * 4, 4); + return v1; + } + /** + * Number of water draw ranges (call before water_draw_data) + * @returns {number} + */ + water_draw_count() { + const ret = wasm.bspmesh_water_draw_count(this.__wbg_ptr); + return ret >>> 0; + } + /** + * Water draw ranges: same format as model_draw_data but for water faces + * @returns {Int32Array} + */ + water_draw_data() { + const ret = wasm.bspmesh_water_draw_data(this.__wbg_ptr); + var v1 = getArrayI32FromWasm0(ret[0], ret[1]).slice(); + wasm.__wbindgen_free(ret[0], ret[1] * 4, 4); + return v1; + } +} +if (Symbol.dispose) BspMesh.prototype[Symbol.dispose] = BspMesh.prototype.free; + +export class ReplayData { + static __wrap(ptr) { + ptr = ptr >>> 0; + const obj = Object.create(ReplayData.prototype); + obj.__wbg_ptr = ptr; + ReplayDataFinalization.register(obj, obj.__wbg_ptr, obj); + return obj; + } + __destroy_into_raw() { + const ptr = this.__wbg_ptr; + this.__wbg_ptr = 0; + ReplayDataFinalization.unregister(this); + return ptr; + } + free() { + const ptr = this.__destroy_into_raw(); + wasm.__wbg_replaydata_free(ptr, 0); + } + /** + * @returns {Float32Array} + */ + angles() { + const ret = wasm.replaydata_angles(this.__wbg_ptr); + var v1 = getArrayF32FromWasm0(ret[0], ret[1]).slice(); + wasm.__wbindgen_free(ret[0], ret[1] * 4, 4); + return v1; + } + /** + * @returns {Int32Array} + */ + buttons_array() { + const ret = wasm.replaydata_buttons_array(this.__wbg_ptr); + var v1 = getArrayI32FromWasm0(ret[0], ret[1]).slice(); + wasm.__wbindgen_free(ret[0], ret[1] * 4, 4); + return v1; + } + /** + * @returns {Int32Array} + */ + flags_array() { + const ret = wasm.replaydata_flags_array(this.__wbg_ptr); + var v1 = getArrayI32FromWasm0(ret[0], ret[1]).slice(); + wasm.__wbindgen_free(ret[0], ret[1] * 4, 4); + return v1; + } + /** + * @returns {string} + */ + map_name() { + let deferred1_0; + let deferred1_1; + try { + const ret = wasm.replaydata_map_name(this.__wbg_ptr); + deferred1_0 = ret[0]; + deferred1_1 = ret[1]; + return getStringFromWasm0(ret[0], ret[1]); + } finally { + wasm.__wbindgen_free(deferred1_0, deferred1_1, 1); + } + } + /** + * @returns {Float32Array} + */ + positions() { + const ret = wasm.replaydata_positions(this.__wbg_ptr); + var v1 = getArrayF32FromWasm0(ret[0], ret[1]).slice(); + wasm.__wbindgen_free(ret[0], ret[1] * 4, 4); + return v1; + } + /** + * @returns {number} + */ + preframes() { + const ret = wasm.replaydata_preframes(this.__wbg_ptr); + return ret; + } + /** + * @returns {number} + */ + tick_count() { + const ret = wasm.replaydata_tick_count(this.__wbg_ptr); + return ret >>> 0; + } + /** + * @returns {number} + */ + tick_rate() { + const ret = wasm.replaydata_tick_rate(this.__wbg_ptr); + return ret >>> 0; + } + /** + * @returns {number} + */ + time() { + const ret = wasm.replaydata_time(this.__wbg_ptr); + return ret; + } +} +if (Symbol.dispose) ReplayData.prototype[Symbol.dispose] = ReplayData.prototype.free; + +/** + * Decode a VTF file, downscale to target dimensions, apply color tint, create tiled version with padding. + * Returns RGBA data of size (target_w + 2*pad) × (target_h + 2*pad) × 4, ready for texSubImage2D. + * When force_opaque is true, all alpha values are set to 255 (most Source textures use alpha + * for specular masks etc., not actual transparency). + * @param {Uint8Array} vtf_data + * @param {number} target_w + * @param {number} target_h + * @param {number} color_r + * @param {number} color_g + * @param {number} color_b + * @param {boolean} force_opaque + * @returns {Uint8Array | undefined} + */ +export function decode_and_tile_vtf(vtf_data, target_w, target_h, color_r, color_g, color_b, force_opaque) { + const ptr0 = passArray8ToWasm0(vtf_data, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.decode_and_tile_vtf(ptr0, len0, target_w, target_h, color_r, color_g, color_b, force_opaque); + let v2; + if (ret[0] !== 0) { + v2 = getArrayU8FromWasm0(ret[0], ret[1]).slice(); + wasm.__wbindgen_free(ret[0], ret[1] * 1, 1); + } + return v2; +} + +/** + * @param {Uint8Array} data + * @returns {Uint8Array} + */ +export function decompress_bz2(data) { + const ptr0 = passArray8ToWasm0(data, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.decompress_bz2(ptr0, len0); + if (ret[3]) { + throw takeFromExternrefTable0(ret[2]); + } + var v2 = getArrayU8FromWasm0(ret[0], ret[1]).slice(); + wasm.__wbindgen_free(ret[0], ret[1] * 1, 1); + return v2; +} + +export function init() { + wasm.init(); +} + +/** + * @param {Uint8Array} data + * @returns {BspMesh} + */ +export function parse_bsp(data) { + const ptr0 = passArray8ToWasm0(data, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.parse_bsp(ptr0, len0); + if (ret[2]) { + throw takeFromExternrefTable0(ret[1]); + } + return BspMesh.__wrap(ret[0]); +} + +/** + * Parse a BSP with extra files injected (e.g. prop models from VPK). + * `extras_json` is a JSON array of `{"path":"models/foo.mdl","offset":0,"length":1234}`. + * `extras_data` is all the file contents concatenated. + * @param {Uint8Array} data + * @param {string} extras_json + * @param {Uint8Array} extras_data + * @returns {BspMesh} + */ +export function parse_bsp_with_extras(data, extras_json, extras_data) { + const ptr0 = passArray8ToWasm0(data, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passStringToWasm0(extras_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + const ptr2 = passArray8ToWasm0(extras_data, wasm.__wbindgen_malloc); + const len2 = WASM_VECTOR_LEN; + const ret = wasm.parse_bsp_with_extras(ptr0, len0, ptr1, len1, ptr2, len2); + if (ret[2]) { + throw takeFromExternrefTable0(ret[1]); + } + return BspMesh.__wrap(ret[0]); +} + +/** + * @param {Uint8Array} data + * @returns {ReplayData} + */ +export function parse_replay(data) { + const ptr0 = passArray8ToWasm0(data, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.parse_replay(ptr0, len0); + if (ret[2]) { + throw takeFromExternrefTable0(ret[1]); + } + return ReplayData.__wrap(ret[0]); +} + +/** + * Parse a VMT file and return JSON: {"basetexture":"...", "color":[r,g,b], "fps":0, "is_water":false} + * @param {Uint8Array} data + * @returns {string | undefined} + */ +export function parse_vmt_data(data) { + const ptr0 = passArray8ToWasm0(data, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.parse_vmt_data(ptr0, len0); + let v2; + if (ret[0] !== 0) { + v2 = getStringFromWasm0(ret[0], ret[1]).slice(); + wasm.__wbindgen_free(ret[0], ret[1] * 1, 1); + } + return v2; +} + +function __wbg_get_imports() { + const import0 = { + __proto__: null, + __wbg_Error_83742b46f01ce22d: function(arg0, arg1) { + const ret = Error(getStringFromWasm0(arg0, arg1)); + return ret; + }, + __wbg___wbindgen_throw_6ddd609b62940d55: function(arg0, arg1) { + throw new Error(getStringFromWasm0(arg0, arg1)); + }, + __wbg_error_a6fa202b58aa1cd3: function(arg0, arg1) { + let deferred0_0; + let deferred0_1; + try { + deferred0_0 = arg0; + deferred0_1 = arg1; + console.error(getStringFromWasm0(arg0, arg1)); + } finally { + wasm.__wbindgen_free(deferred0_0, deferred0_1, 1); + } + }, + __wbg_log_524eedafa26daa59: function(arg0) { + console.log(arg0); + }, + __wbg_log_89f0432d129e5e26: function(arg0, arg1) { + console.log(getStringFromWasm0(arg0, arg1)); + }, + __wbg_new_227d7c05414eb861: function() { + const ret = new Error(); + return ret; + }, + __wbg_stack_3b0d974bbf31e44f: function(arg0, arg1) { + const ret = arg1.stack; + const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true); + getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true); + }, + __wbindgen_cast_0000000000000001: function(arg0, arg1) { + // Cast intrinsic for `Ref(String) -> Externref`. + const ret = getStringFromWasm0(arg0, arg1); + return ret; + }, + __wbindgen_init_externref_table: function() { + const table = wasm.__wbindgen_externrefs; + const offset = table.grow(4); + table.set(0, undefined); + table.set(offset + 0, undefined); + table.set(offset + 1, null); + table.set(offset + 2, true); + table.set(offset + 3, false); + }, + }; + return { + __proto__: null, + "./bhop_replay_viewer_wasm_bg.js": import0, + }; +} + +const BspMeshFinalization = (typeof FinalizationRegistry === 'undefined') + ? { register: () => {}, unregister: () => {} } + : new FinalizationRegistry(ptr => wasm.__wbg_bspmesh_free(ptr >>> 0, 1)); +const ReplayDataFinalization = (typeof FinalizationRegistry === 'undefined') + ? { register: () => {}, unregister: () => {} } + : new FinalizationRegistry(ptr => wasm.__wbg_replaydata_free(ptr >>> 0, 1)); + +function getArrayF32FromWasm0(ptr, len) { + ptr = ptr >>> 0; + return getFloat32ArrayMemory0().subarray(ptr / 4, ptr / 4 + len); +} + +function getArrayI32FromWasm0(ptr, len) { + ptr = ptr >>> 0; + return getInt32ArrayMemory0().subarray(ptr / 4, ptr / 4 + len); +} + +function getArrayU32FromWasm0(ptr, len) { + ptr = ptr >>> 0; + return getUint32ArrayMemory0().subarray(ptr / 4, ptr / 4 + len); +} + +function getArrayU8FromWasm0(ptr, len) { + ptr = ptr >>> 0; + return getUint8ArrayMemory0().subarray(ptr / 1, ptr / 1 + len); +} + +let cachedDataViewMemory0 = null; +function getDataViewMemory0() { + if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || (cachedDataViewMemory0.buffer.detached === undefined && cachedDataViewMemory0.buffer !== wasm.memory.buffer)) { + cachedDataViewMemory0 = new DataView(wasm.memory.buffer); + } + return cachedDataViewMemory0; +} + +let cachedFloat32ArrayMemory0 = null; +function getFloat32ArrayMemory0() { + if (cachedFloat32ArrayMemory0 === null || cachedFloat32ArrayMemory0.byteLength === 0) { + cachedFloat32ArrayMemory0 = new Float32Array(wasm.memory.buffer); + } + return cachedFloat32ArrayMemory0; +} + +let cachedInt32ArrayMemory0 = null; +function getInt32ArrayMemory0() { + if (cachedInt32ArrayMemory0 === null || cachedInt32ArrayMemory0.byteLength === 0) { + cachedInt32ArrayMemory0 = new Int32Array(wasm.memory.buffer); + } + return cachedInt32ArrayMemory0; +} + +function getStringFromWasm0(ptr, len) { + ptr = ptr >>> 0; + return decodeText(ptr, len); +} + +let cachedUint32ArrayMemory0 = null; +function getUint32ArrayMemory0() { + if (cachedUint32ArrayMemory0 === null || cachedUint32ArrayMemory0.byteLength === 0) { + cachedUint32ArrayMemory0 = new Uint32Array(wasm.memory.buffer); + } + return cachedUint32ArrayMemory0; +} + +let cachedUint8ArrayMemory0 = null; +function getUint8ArrayMemory0() { + if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) { + cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer); + } + return cachedUint8ArrayMemory0; +} + +function passArray8ToWasm0(arg, malloc) { + const ptr = malloc(arg.length * 1, 1) >>> 0; + getUint8ArrayMemory0().set(arg, ptr / 1); + WASM_VECTOR_LEN = arg.length; + return ptr; +} + +function passStringToWasm0(arg, malloc, realloc) { + if (realloc === undefined) { + const buf = cachedTextEncoder.encode(arg); + const ptr = malloc(buf.length, 1) >>> 0; + getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf); + WASM_VECTOR_LEN = buf.length; + return ptr; + } + + let len = arg.length; + let ptr = malloc(len, 1) >>> 0; + + const mem = getUint8ArrayMemory0(); + + let offset = 0; + + for (; offset < len; offset++) { + const code = arg.charCodeAt(offset); + if (code > 0x7F) break; + mem[ptr + offset] = code; + } + if (offset !== len) { + if (offset !== 0) { + arg = arg.slice(offset); + } + ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0; + const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len); + const ret = cachedTextEncoder.encodeInto(arg, view); + + offset += ret.written; + ptr = realloc(ptr, len, offset, 1) >>> 0; + } + + WASM_VECTOR_LEN = offset; + return ptr; +} + +function takeFromExternrefTable0(idx) { + const value = wasm.__wbindgen_externrefs.get(idx); + wasm.__externref_table_dealloc(idx); + return value; +} + +let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }); +cachedTextDecoder.decode(); +const MAX_SAFARI_DECODE_BYTES = 2146435072; +let numBytesDecoded = 0; +function decodeText(ptr, len) { + numBytesDecoded += len; + if (numBytesDecoded >= MAX_SAFARI_DECODE_BYTES) { + cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }); + cachedTextDecoder.decode(); + numBytesDecoded = len; + } + return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len)); +} + +const cachedTextEncoder = new TextEncoder(); + +if (!('encodeInto' in cachedTextEncoder)) { + cachedTextEncoder.encodeInto = function (arg, view) { + const buf = cachedTextEncoder.encode(arg); + view.set(buf); + return { + read: arg.length, + written: buf.length + }; + }; +} + +let WASM_VECTOR_LEN = 0; + +let wasmModule, wasm; +function __wbg_finalize_init(instance, module) { + wasm = instance.exports; + wasmModule = module; + cachedDataViewMemory0 = null; + cachedFloat32ArrayMemory0 = null; + cachedInt32ArrayMemory0 = null; + cachedUint32ArrayMemory0 = null; + cachedUint8ArrayMemory0 = null; + wasm.__wbindgen_start(); + return wasm; +} + +async function __wbg_load(module, imports) { + if (typeof Response === 'function' && module instanceof Response) { + if (typeof WebAssembly.instantiateStreaming === 'function') { + try { + return await WebAssembly.instantiateStreaming(module, imports); + } catch (e) { + const validResponse = module.ok && expectedResponseType(module.type); + + if (validResponse && module.headers.get('Content-Type') !== 'application/wasm') { + console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e); + + } else { throw e; } + } + } + + const bytes = await module.arrayBuffer(); + return await WebAssembly.instantiate(bytes, imports); + } else { + const instance = await WebAssembly.instantiate(module, imports); + + if (instance instanceof WebAssembly.Instance) { + return { instance, module }; + } else { + return instance; + } + } + + function expectedResponseType(type) { + switch (type) { + case 'basic': case 'cors': case 'default': return true; + } + return false; + } +} + +function initSync(module) { + if (wasm !== undefined) return wasm; + + + if (module !== undefined) { + if (Object.getPrototypeOf(module) === Object.prototype) { + ({module} = module) + } else { + console.warn('using deprecated parameters for `initSync()`; pass a single object instead') + } + } + + const imports = __wbg_get_imports(); + if (!(module instanceof WebAssembly.Module)) { + module = new WebAssembly.Module(module); + } + const instance = new WebAssembly.Instance(module, imports); + return __wbg_finalize_init(instance, module); +} + +async function __wbg_init(module_or_path) { + if (wasm !== undefined) return wasm; + + + if (module_or_path !== undefined) { + if (Object.getPrototypeOf(module_or_path) === Object.prototype) { + ({module_or_path} = module_or_path) + } else { + console.warn('using deprecated parameters for the initialization function; pass a single object instead') + } + } + + if (module_or_path === undefined) { + module_or_path = new URL('bhop_replay_viewer_wasm_bg.wasm', import.meta.url); + } + const imports = __wbg_get_imports(); + + if (typeof module_or_path === 'string' || (typeof Request === 'function' && module_or_path instanceof Request) || (typeof URL === 'function' && module_or_path instanceof URL)) { + module_or_path = fetch(module_or_path); + } + + const { instance, module } = await __wbg_load(await module_or_path, imports); + + return __wbg_finalize_init(instance, module); +} + +export { initSync, __wbg_init as default }; diff --git a/src/replay-viewer/wasm/bhop_replay_viewer_wasm_bg.wasm b/src/replay-viewer/wasm/bhop_replay_viewer_wasm_bg.wasm new file mode 100644 index 0000000..5e5f956 Binary files /dev/null and b/src/replay-viewer/wasm/bhop_replay_viewer_wasm_bg.wasm differ diff --git a/src/replay-viewer/wasm/bhop_replay_viewer_wasm_bg.wasm.d.ts b/src/replay-viewer/wasm/bhop_replay_viewer_wasm_bg.wasm.d.ts new file mode 100644 index 0000000..a6ce27b --- /dev/null +++ b/src/replay-viewer/wasm/bhop_replay_viewer_wasm_bg.wasm.d.ts @@ -0,0 +1,53 @@ +/* tslint:disable */ +/* eslint-disable */ +export const memory: WebAssembly.Memory; +export const __wbg_bspmesh_free: (a: number, b: number) => void; +export const bspmesh_animated_frame_data: (a: number) => [number, number]; +export const bspmesh_animated_texture_info: (a: number) => [number, number]; +export const bspmesh_find_cluster: (a: number, b: number, c: number, d: number) => number; +export const bspmesh_has_sky_faces: (a: number) => number; +export const bspmesh_has_skybox: (a: number) => number; +export const bspmesh_index_count: (a: number) => number; +export const bspmesh_index_data: (a: number) => [number, number]; +export const bspmesh_is_cluster_visible: (a: number, b: number, c: number) => number; +export const bspmesh_lightmap_atlas_data: (a: number) => [number, number]; +export const bspmesh_lightmap_height: (a: number) => number; +export const bspmesh_lightmap_width: (a: number) => number; +export const bspmesh_missing_props: (a: number) => [number, number]; +export const bspmesh_model_draw_count: (a: number) => number; +export const bspmesh_model_draw_data: (a: number) => [number, number]; +export const bspmesh_sky_index_data: (a: number) => [number, number]; +export const bspmesh_sky_vertex_data: (a: number) => [number, number]; +export const bspmesh_skybox_data: (a: number) => [number, number]; +export const bspmesh_skybox_face_size: (a: number) => number; +export const bspmesh_texture_atlas_data: (a: number) => [number, number]; +export const bspmesh_texture_atlas_height: (a: number) => number; +export const bspmesh_texture_atlas_width: (a: number) => number; +export const bspmesh_unresolved_textures: (a: number) => [number, number]; +export const bspmesh_vertex_count: (a: number) => number; +export const bspmesh_vertex_data: (a: number) => [number, number]; +export const bspmesh_water_draw_count: (a: number) => number; +export const bspmesh_water_draw_data: (a: number) => [number, number]; +export const parse_bsp: (a: number, b: number) => [number, number, number]; +export const parse_bsp_with_extras: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number, number]; +export const __wbg_replaydata_free: (a: number, b: number) => void; +export const parse_replay: (a: number, b: number) => [number, number, number]; +export const replaydata_angles: (a: number) => [number, number]; +export const replaydata_buttons_array: (a: number) => [number, number]; +export const replaydata_flags_array: (a: number) => [number, number]; +export const replaydata_map_name: (a: number) => [number, number]; +export const replaydata_positions: (a: number) => [number, number]; +export const replaydata_preframes: (a: number) => number; +export const replaydata_tick_count: (a: number) => number; +export const replaydata_tick_rate: (a: number) => number; +export const replaydata_time: (a: number) => number; +export const decode_and_tile_vtf: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number) => [number, number]; +export const init: () => void; +export const parse_vmt_data: (a: number, b: number) => [number, number]; +export const decompress_bz2: (a: number, b: number) => [number, number, number, number]; +export const __wbindgen_free: (a: number, b: number, c: number) => void; +export const __wbindgen_malloc: (a: number, b: number) => number; +export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number; +export const __wbindgen_externrefs: WebAssembly.Table; +export const __externref_table_dealloc: (a: number) => void; +export const __wbindgen_start: () => void; diff --git a/src/replay-viewer/wasm/package.json b/src/replay-viewer/wasm/package.json new file mode 100644 index 0000000..42a6f70 --- /dev/null +++ b/src/replay-viewer/wasm/package.json @@ -0,0 +1,15 @@ +{ + "name": "bhop-replay-viewer-wasm", + "type": "module", + "version": "0.1.0", + "files": [ + "bhop_replay_viewer_wasm_bg.wasm", + "bhop_replay_viewer_wasm.js", + "bhop_replay_viewer_wasm.d.ts" + ], + "main": "bhop_replay_viewer_wasm.js", + "types": "bhop_replay_viewer_wasm.d.ts", + "sideEffects": [ + "./snippets/*" + ] +} \ No newline at end of file diff --git a/src/views/IndividualRecordView.vue b/src/views/IndividualRecordView.vue index 9d6be04..2e22d4f 100644 --- a/src/views/IndividualRecordView.vue +++ b/src/views/IndividualRecordView.vue @@ -9,6 +9,7 @@ import styleFormat from '@/utils/styleFormat'; import { useRouter } from 'vue-router'; import { useAuth } from '@/stores/auth'; + import ReplayViewerOverlay from '@/replay-viewer/ReplayViewerOverlay.vue'; const props = defineProps<{ id: string @@ -19,6 +20,7 @@ const isLoading: Ref = ref(false); const record: Ref = ref(null); const error: Ref = ref(null); + const showReplayViewer: Ref = ref(false); const playerUrl = computed(() => { return record.value ? `/players/${record.value.steamid}` : null; @@ -214,24 +216,30 @@
-
- + -
- + No Replay Available @@ -240,5 +248,14 @@
+ + + \ No newline at end of file diff --git a/vite.config.ts b/vite.config.ts index 975d368..0bc14d3 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -4,6 +4,7 @@ import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import vueDevTools from 'vite-plugin-vue-devtools' import tailwindcss from '@tailwindcss/vite' +import wasm from 'vite-plugin-wasm' // https://vite.dev/config/ export default defineConfig({ @@ -12,6 +13,7 @@ export default defineConfig({ vue(), vueDevTools(), tailwindcss(), + wasm(), ], resolve: { alias: { @@ -25,11 +27,17 @@ export default defineConfig({ target: 'https://offstyles.tommyy.dev', changeOrigin: true, secure: true, - configure: (proxy, options) => { - proxy.on('proxyReq', (proxyReq, req, res) => { - // Forward cookies to maintain session - if (req.headers.cookie) { - proxyReq.setHeader('Cookie', req.headers.cookie); + cookieDomainRewrite: 'localhost', + configure: (proxy) => { + // Rewrite response cookies so they work on http://localhost + proxy.on('proxyRes', (proxyRes) => { + const setCookie = proxyRes.headers['set-cookie']; + if (setCookie) { + proxyRes.headers['set-cookie'] = setCookie.map((cookie: string) => + cookie + .replace(/;\s*Secure/gi, '') + .replace(/;\s*SameSite=\w+/gi, '; SameSite=Lax') + ); } }); }