1 Commits

Author SHA1 Message Date
Sebastian 1c6c0837b3 chore(deps): update dependency jsdom to v30
Build Test / test (pull_request) Successful in 33s
JS Unit Tests / test (pull_request) Successful in 43s
PHP Integration Tests / Integration Tests (pull_request) Failing after 1m9s
PHP Unit Tests / test (pull_request) Successful in 1m12s
2026-07-29 03:02:50 +00:00
10 changed files with 270 additions and 1079 deletions
+265 -313
View File
@@ -9,73 +9,52 @@
"version": "1.0.0",
"dependencies": {
"pinia": "^4.0.0",
"vue": "^3.5.13",
"vuetify": "^4.0.0"
"vue": "^3.5.13"
},
"devDependencies": {
"@tsconfig/node24": "^24.0.0",
"@types/node": "^24.0.0",
"@vitejs/plugin-vue": "^6.0.1",
"@vitest/coverage-v8": "^4.1.6",
"@vue/tsconfig": "^0.9.0",
"jsdom": "^29.1.1",
"jsdom": "^30.0.0",
"typescript": "~6.0.0",
"vite": "^8.0.0",
"vitest": "^4.1.6",
"vue-tsc": "^3.0.5"
"vitest": "^4.1.6"
}
},
"node_modules/@asamuzakjp/css-color": {
"version": "5.1.11",
"resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-5.1.11.tgz",
"integrity": "sha512-KVw6qIiCTUQhByfTd78h2yD1/00waTmm9uy/R7Ck/ctUyAPj+AEDLkQIdJW0T8+qGgj3j5bpNKK7Q3G+LedJWg==",
"version": "6.0.5",
"resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-6.0.5.tgz",
"integrity": "sha512-mbhpPMmnw/kwW19aRNmSUl1QzLbdGo1SCuE49BT98MNwqF6zaHb3o2owssFc/PEO/4t2UjqtCNwocuDtJornzA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@asamuzakjp/generational-cache": "^1.0.1",
"@csstools/css-calc": "^3.2.0",
"@csstools/css-color-parser": "^4.1.0",
"@csstools/css-calc": "^3.2.1",
"@csstools/css-color-parser": "^4.1.9",
"@csstools/css-parser-algorithms": "^4.0.0",
"@csstools/css-tokenizer": "^4.0.0"
"@csstools/css-tokenizer": "^4.0.0",
"lru-cache": "^11.5.2"
},
"engines": {
"node": "^20.19.0 || ^22.12.0 || >=24.0.0"
"node": "^22.13.0 || >=24.0.0"
}
},
"node_modules/@asamuzakjp/dom-selector": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-7.1.1.tgz",
"integrity": "sha512-67RZDnYRc8H/8MLDgQCDE//zoqVFwajkepHZgmXrbwybzXOEwOWGPYGmALYl9J2DOLfFPPs6kKCqmbzV895hTQ==",
"version": "8.3.0",
"resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-8.3.0.tgz",
"integrity": "sha512-UJLfKXBhrc8i1vH2eJXuYQMwlsLKWFw3O+CPqXSuVEiikeAim3UgrfWX0k4tA/X8cRFM8iZ7OaqBokFGbYusdg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@asamuzakjp/generational-cache": "^1.0.1",
"@asamuzakjp/nwsapi": "^2.3.9",
"bidi-js": "^1.0.3",
"css-tree": "^3.2.1",
"is-potential-custom-element-name": "^1.0.1"
"is-potential-custom-element-name": "^1.0.1",
"lru-cache": "^11.5.2"
},
"engines": {
"node": "^20.19.0 || ^22.12.0 || >=24.0.0"
"node": "^22.13.0 || >=24.0.0"
}
},
"node_modules/@asamuzakjp/generational-cache": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@asamuzakjp/generational-cache/-/generational-cache-1.0.1.tgz",
"integrity": "sha512-wajfB8KqzMCN2KGNFdLkReeHncd0AslUSrvHVvvYWuU8ghncRJoA50kT3zP9MVL0+9g4/67H+cdvBskj9THPzg==",
"dev": true,
"license": "MIT",
"engines": {
"node": "^20.19.0 || ^22.12.0 || >=24.0.0"
}
},
"node_modules/@asamuzakjp/nwsapi": {
"version": "2.3.9",
"resolved": "https://registry.npmjs.org/@asamuzakjp/nwsapi/-/nwsapi-2.3.9.tgz",
"integrity": "sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==",
"dev": true,
"license": "MIT"
},
"node_modules/@babel/helper-string-parser": {
"version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz",
@@ -285,6 +264,40 @@
"node": ">=20.19.0"
}
},
"node_modules/@emnapi/core": {
"version": "1.11.1",
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.1.tgz",
"integrity": "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==",
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
"@emnapi/wasi-threads": "1.2.2",
"tslib": "^2.4.0"
}
},
"node_modules/@emnapi/runtime": {
"version": "1.11.1",
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.1.tgz",
"integrity": "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==",
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
"tslib": "^2.4.0"
}
},
"node_modules/@emnapi/wasi-threads": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.2.tgz",
"integrity": "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==",
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
"tslib": "^2.4.0"
}
},
"node_modules/@exodus/bytes": {
"version": "1.15.1",
"resolved": "https://registry.npmjs.org/@exodus/bytes/-/bytes-1.15.1.tgz",
@@ -330,10 +343,29 @@
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
"node_modules/@napi-rs/wasm-runtime": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.6.tgz",
"integrity": "sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==",
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
"@tybys/wasm-util": "^0.10.3"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/Brooooooklyn"
},
"peerDependencies": {
"@emnapi/core": "^1.7.1",
"@emnapi/runtime": "^1.7.1"
}
},
"node_modules/@oxc-project/types": {
"version": "0.144.0",
"resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.144.0.tgz",
"integrity": "sha512-nuhZIOLuI6TFQ32I/WnUx+SCPY7SdSKwgnFHydAuoS1+Z4BRcaP+RRJmGzl9lw+0OFF7UmaESf7KQRXaNLHypg==",
"version": "0.139.0",
"resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.139.0.tgz",
"integrity": "sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw==",
"dev": true,
"license": "MIT",
"funding": {
@@ -341,9 +373,9 @@
}
},
"node_modules/@rolldown/binding-android-arm64": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.4.tgz",
"integrity": "sha512-jHC2cnyKz5xU2fhECtFl8OZ83cYNt13GZQD+0uMJ/X3o+ijmd56okHhTUwxVSHPx1IRVIJEZ1/1pPzeLCU6XKA==",
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.1.5.tgz",
"integrity": "sha512-lZg8fqIv2v7FF237bwMgzGZEJvGL79/s5knJ/i6FmsGF4XXlzccZ4jb+TrFIxtSSxFtIpdsgrPZeMk1I9AFcyQ==",
"cpu": [
"arm64"
],
@@ -358,9 +390,9 @@
}
},
"node_modules/@rolldown/binding-darwin-arm64": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.4.tgz",
"integrity": "sha512-Dc5mPD8F5F/FS8i01syd7FTF6yB2fVthH/TRkjwJkzUK6EpoxHtqvZQP5Zwq80/5z19TWYHIg1KOHboCgVx/aQ==",
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.1.5.tgz",
"integrity": "sha512-51Bnx9pNiMRKSUNtBfySkNJ9vMU9Hh3I1ozDd6gyPPYzaXCfnptUcEZxXGYFn+ul2dtcMUiqGR1Yai2K10uoTw==",
"cpu": [
"arm64"
],
@@ -375,9 +407,9 @@
}
},
"node_modules/@rolldown/binding-darwin-x64": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.4.tgz",
"integrity": "sha512-fpDm4oBo6SqLvWUYCmFhdde3U9KH2fRNNMeAnAPAIwxRL345xutL0EtEUcuoxsoazdJGv/MuDBQHlCDrtbvqOg==",
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.1.5.tgz",
"integrity": "sha512-Tm+gbfC0aHu1tBA/JvKQh32S0K6YgCHkiAF4/W6xX0K0RmNuc94VeK419dJoE65R5aRxmo+noZQSWrAMF6yb6g==",
"cpu": [
"x64"
],
@@ -392,9 +424,9 @@
}
},
"node_modules/@rolldown/binding-freebsd-x64": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.4.tgz",
"integrity": "sha512-rSJoreDE/HoIzoaib6MTp5jQtCTdMHKIvItAKT/ImS6Y6Ww76oUaeMyp4Vc/fAgd/ehji068IxetHXAnqUwN9A==",
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.1.5.tgz",
"integrity": "sha512-JMzDKCCXq93YccG5gz3hvOs1oXRKAf0XYpfOS88e+wZrC8Iugj6j68867vrYZkvpDDpKn/KoKORThmchMpF6TA==",
"cpu": [
"x64"
],
@@ -409,9 +441,9 @@
}
},
"node_modules/@rolldown/binding-linux-arm-gnueabihf": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.4.tgz",
"integrity": "sha512-/jm8OGHgn7oGaJu3i/qZI9spUGcJ+y/lk43ttQ/iO1tOd9NissG6o97bighBCiL+BKRngmcDuR6ikfwYdJmVuQ==",
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.1.5.tgz",
"integrity": "sha512-uML21j2K5TfPGutKxub+M+nLjZIrWjXQ5Grx4lCe/nimTj9B4L63zHpjXLl4y0L3mcm2htEQIb06oCG/szerNw==",
"cpu": [
"arm"
],
@@ -426,9 +458,9 @@
}
},
"node_modules/@rolldown/binding-linux-arm64-gnu": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.4.tgz",
"integrity": "sha512-tIP06BeD9EqvECBrPZ+sqdPlYrT+aYaAiu1wYziVx5elRK/ftm33JxVDy2bXGbr6J0CrtirCkR87/X5a2euEng==",
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.1.5.tgz",
"integrity": "sha512-navSiuTMogvnQoZoM/v+l3ZWo50/NTwSHSzheABx/RCnmUPaKwq9qSo4Br2OYRs21+Fz8uFqITZM3H4opOB0/Q==",
"cpu": [
"arm64"
],
@@ -443,9 +475,9 @@
}
},
"node_modules/@rolldown/binding-linux-arm64-musl": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.4.tgz",
"integrity": "sha512-Ql1Q0EQqVThvn9VAVlwNzsUvbSFtCMGjLpRRi4pk5i7NZZ4n5ISiLMjHYtus4VQ2PvkSw24zyaCVsiS+sXPj1w==",
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.1.5.tgz",
"integrity": "sha512-lAryqH7IteztmCXQXk0etKj4wBQ7Gx5S6LjKhsgp9zb8I5bsuvU/2llH1hDQcjsFeqIsovMVN339/8pUDDBXxA==",
"cpu": [
"arm64"
],
@@ -460,9 +492,9 @@
}
},
"node_modules/@rolldown/binding-linux-ppc64-gnu": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.4.tgz",
"integrity": "sha512-GjbjXD4XXfN19D0LZNbmiCBUoDiRACsYHr0yaIbbn8aFsXjHZifcYqu/W5Er5X2X990WjHXFrxarn5chzItorQ==",
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.1.5.tgz",
"integrity": "sha512-fsK/sNBnxzBlL4O1JNrZakVQxPspqpED5dLtNsZS9oOKmtSpdNIzxH2kkol5HYTWJN47sE20ztMJPxfZ89qGOg==",
"cpu": [
"ppc64"
],
@@ -477,9 +509,9 @@
}
},
"node_modules/@rolldown/binding-linux-s390x-gnu": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.4.tgz",
"integrity": "sha512-p5WR0NOwaRmJ/B1b6IjEFLLivwEsf3PrdBIhRbhTCQisbo2SvHHpG4ELB/+FgQNnB88LTOF86upmJmbvZdQ2lw==",
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.1.5.tgz",
"integrity": "sha512-gLYb4BIadlfTOYT5gO503n8zQjXflgzpD0FcyKh0Mzx3rqCZKnHoJWV9xe1KXUJ5lx2JfcSHr/mhzS0PC/McAA==",
"cpu": [
"s390x"
],
@@ -494,9 +526,9 @@
}
},
"node_modules/@rolldown/binding-linux-x64-gnu": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.4.tgz",
"integrity": "sha512-4/GyVjmhR+Tc6HLJvwc1sOhPqAZtySiSMesOZyX6JQ5XBxoTDEMKQzvo07NIK6nTon/SivlZqvhzvuVBNQhObQ==",
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.1.5.tgz",
"integrity": "sha512-FjcpEKUyJygHgs1o50VYNvkt5+7Le/VEdYt0AkRpkL33MnyQfwr8l5mXwMmfmTbyMPr5vJLC+8/Gd9gXnwU1QQ==",
"cpu": [
"x64"
],
@@ -511,9 +543,9 @@
}
},
"node_modules/@rolldown/binding-linux-x64-musl": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.4.tgz",
"integrity": "sha512-l9eeLsCNvPpmSXUej0etw/J1eqV0Jj1D5G/xG6YTijmE6dkv6E2QezgWbTfQk63v952DPqrjOCoiqxq7Bw0YUQ==",
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.1.5.tgz",
"integrity": "sha512-Me+PfPI2TMeOQk0gYWfLQZtTktrmzbr8cDboqX83XKc7UrgAi55gF+2dUkWdxd19n55Essp2yeca+O9N5rBxHg==",
"cpu": [
"x64"
],
@@ -528,9 +560,9 @@
}
},
"node_modules/@rolldown/binding-openharmony-arm64": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.4.tgz",
"integrity": "sha512-e0F355MSTMm3+UOqtV3L24gFUp2N5m1f8L/7d56deik6va+AXdrt9F8LbzGpeWGWRbZEDq4m8NVnJDeBtf9DZg==",
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.1.5.tgz",
"integrity": "sha512-yc5WrLzXks6zCQfn9Oxr8pORKyl/pF+QjHmW/Qx3qu0oyrrNC+y2JLTU1E2rcWYAmzlnqngWXHQjy51VzW70Vw==",
"cpu": [
"arm64"
],
@@ -544,10 +576,29 @@
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@rolldown/binding-wasm32-wasi": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.1.5.tgz",
"integrity": "sha512-VbQGPX2b4r48TAMIM2cjgluIM1HYutm4pcTEJsle7iEP7sB1dFqtPLBVbdLAZCxy1txCcPxf4QFf4v8uvltPqA==",
"cpu": [
"wasm32"
],
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
"@emnapi/core": "1.11.1",
"@emnapi/runtime": "1.11.1",
"@napi-rs/wasm-runtime": "^1.1.6"
},
"engines": {
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@rolldown/binding-win32-arm64-msvc": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.4.tgz",
"integrity": "sha512-AWLi0uBRYh6QlE7OKhiz+phZC0qwtij2QZmhmOdsLdFn64m7oMpooE9ICE3lhm9xMb4SpDo2WbHcxX1iFLFtqw==",
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.1.5.tgz",
"integrity": "sha512-gHv82k63z4qpV5+Q1y/12KrK0ltWBukVDI8nZcbT7Tt/ZlOIVwppazneq0F93oDxTo3IgAMEDIoQh3E2n6mVsw==",
"cpu": [
"arm64"
],
@@ -562,9 +613,9 @@
}
},
"node_modules/@rolldown/binding-win32-x64-msvc": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.4.tgz",
"integrity": "sha512-UwSDJOg3dqCAejWdxclJjCsh3Qq4vLYMDxmyHqo1btz3stK2VqgwNd3mm5tuIwzSlGIQ/1H9Hr+Zn09mrezNqQ==",
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.1.5.tgz",
"integrity": "sha512-tTZuDBPw85tEN5PQi1pnEBzDy0Z49HtScLAbD5t6hyeU92A95pRWaSMw1GZZi/RwgSgUIl0xrSlXIT/9QzvYSA==",
"cpu": [
"x64"
],
@@ -599,6 +650,17 @@
"dev": true,
"license": "MIT"
},
"node_modules/@tybys/wasm-util": {
"version": "0.10.3",
"resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.3.tgz",
"integrity": "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==",
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
"tslib": "^2.4.0"
}
},
"node_modules/@types/chai": {
"version": "5.2.3",
"resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz",
@@ -634,23 +696,6 @@
"undici-types": "~7.18.0"
}
},
"node_modules/@vitejs/plugin-vue": {
"version": "6.0.8",
"resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.8.tgz",
"integrity": "sha512-0ZjgOg7oO6farnNGup7yvoM/YXZV84OZxHAwtflItNa/6zzQyVb5LNxyea3FEKEX2XlagIKzrlH7wwxkKgtiew==",
"dev": true,
"license": "MIT",
"dependencies": {
"@rolldown/pluginutils": "^1.0.1"
},
"engines": {
"node": "^20.19.0 || >=22.12.0"
},
"peerDependencies": {
"vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0",
"vue": "^3.2.25"
}
},
"node_modules/@vitest/coverage-v8": {
"version": "4.1.10",
"resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.1.10.tgz",
@@ -805,35 +850,6 @@
"url": "https://opencollective.com/vitest"
}
},
"node_modules/@volar/language-core": {
"version": "2.4.28",
"resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.28.tgz",
"integrity": "sha512-w4qhIJ8ZSitgLAkVay6AbcnC7gP3glYM3fYwKV3srj8m494E3xtrCv6E+bWviiK/8hs6e6t1ij1s2Endql7vzQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@volar/source-map": "2.4.28"
}
},
"node_modules/@volar/source-map": {
"version": "2.4.28",
"resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.28.tgz",
"integrity": "sha512-yX2BDBqJkRXfKw8my8VarTyjv48QwxdJtvRgUpNE5erCsgEUdI2DsLbpa+rOQVAJYshY99szEcRDmyHbF10ggQ==",
"dev": true,
"license": "MIT"
},
"node_modules/@volar/typescript": {
"version": "2.4.28",
"resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.28.tgz",
"integrity": "sha512-Ja6yvWrbis2QtN4ClAKreeUZPVYMARDYZl9LMEv1iQ1QdepB6wn0jTRxA9MftYmYa4DQ4k/DaSZpFPUfxl8giw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@volar/language-core": "2.4.28",
"path-browserify": "^1.0.1",
"vscode-uri": "^3.0.8"
}
},
"node_modules/@vue/compiler-core": {
"version": "3.5.40",
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.40.tgz",
@@ -914,22 +930,6 @@
"license": "MIT",
"peer": true
},
"node_modules/@vue/language-core": {
"version": "3.3.9",
"resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-3.3.9.tgz",
"integrity": "sha512-in/68oAa4BCtVY6n/nkuhLIkV8DHYd2UivedJ6cMZ6UYtlq9jaoaSNUBHYCVO44z3nKg7MdE5OBoHKt5SxeBKQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@volar/language-core": "2.4.28",
"@vue/compiler-dom": "^3.5.0",
"@vue/shared": "^3.5.0",
"alien-signals": "^3.2.1",
"muggle-string": "^0.4.1",
"path-browserify": "^1.0.1",
"picomatch": "^4.0.4"
}
},
"node_modules/@vue/reactivity": {
"version": "3.5.40",
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.40.tgz",
@@ -997,13 +997,6 @@
}
}
},
"node_modules/alien-signals": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/alien-signals/-/alien-signals-3.2.1.tgz",
"integrity": "sha512-I8FjmltrfnDFoZedi5CG8DghVYNhzb/Ijluz7tCSJH0xpd0484Kowhbb1XDYOxfJpU1p5wnM2X54dA+IfGyD1g==",
"dev": true,
"license": "MIT"
},
"node_modules/assertion-error": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz",
@@ -1283,39 +1276,39 @@
"license": "MIT"
},
"node_modules/jsdom": {
"version": "29.1.1",
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-29.1.1.tgz",
"integrity": "sha512-ECi4Fi2f7BdJtUKTflYRTiaMxIB0O6zfR1fX0GXpUrf6flp8QIYn1UT20YQqdSOfk2dfkCwS8LAFoJDEppNK5Q==",
"version": "30.0.0",
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-30.0.0.tgz",
"integrity": "sha512-JQHfRGmmKmaZoUAvIgff5jjG/0SzTQlGz8c7t72KzBzo8ZULEjAjnYE0sNwBOUA4QtWwYE2xoYitg8NFsmiYxA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@asamuzakjp/css-color": "^5.1.11",
"@asamuzakjp/dom-selector": "^7.1.1",
"@asamuzakjp/css-color": "^6.0.5",
"@asamuzakjp/dom-selector": "^8.2.5",
"@bramus/specificity": "^2.4.2",
"@csstools/css-syntax-patches-for-csstree": "^1.1.3",
"@exodus/bytes": "^1.15.0",
"@csstools/css-syntax-patches-for-csstree": "^1.1.6",
"@exodus/bytes": "^1.15.1",
"css-tree": "^3.2.1",
"data-urls": "^7.0.0",
"decimal.js": "^10.6.0",
"html-encoding-sniffer": "^6.0.0",
"is-potential-custom-element-name": "^1.0.1",
"lru-cache": "^11.3.5",
"lru-cache": "^11.5.2",
"parse5": "^8.0.1",
"saxes": "^6.0.0",
"symbol-tree": "^3.2.4",
"tough-cookie": "^6.0.1",
"undici": "^7.25.0",
"tough-cookie": "^6.0.2",
"undici": "^8.7.0",
"w3c-xmlserializer": "^5.0.0",
"webidl-conversions": "^8.0.1",
"whatwg-mimetype": "^5.0.0",
"whatwg-url": "^16.0.1",
"whatwg-url": "^17.1.0",
"xml-name-validator": "^5.0.0"
},
"engines": {
"node": "^20.19.0 || ^22.13.0 || >=24.0.0"
"node": "^22.22.2 || ^24.15.0 || >=26.0.0"
},
"peerDependencies": {
"canvas": "^3.0.0"
"canvas": "^3.2.3"
},
"peerDependenciesMeta": {
"canvas": {
@@ -1323,10 +1316,25 @@
}
}
},
"node_modules/jsdom/node_modules/whatwg-url": {
"version": "17.1.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-17.1.0.tgz",
"integrity": "sha512-3GeworPmc2ZfEEHP7lEbUfBX/L75wdEsi0rLNhXcXxnoN5jyq0SL5gCy06SGW2cyTIZdTvWIDQNQoza++vKeaw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@exodus/bytes": "^1.15.1",
"tr46": "^6.0.0",
"webidl-conversions": "^8.0.1"
},
"engines": {
"node": "^22.14.0 || >=24.0.0"
}
},
"node_modules/lightningcss": {
"version": "1.33.0",
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.33.0.tgz",
"integrity": "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==",
"version": "1.32.0",
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz",
"integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==",
"dev": true,
"license": "MPL-2.0",
"dependencies": {
@@ -1340,23 +1348,23 @@
"url": "https://opencollective.com/parcel"
},
"optionalDependencies": {
"lightningcss-android-arm64": "1.33.0",
"lightningcss-darwin-arm64": "1.33.0",
"lightningcss-darwin-x64": "1.33.0",
"lightningcss-freebsd-x64": "1.33.0",
"lightningcss-linux-arm-gnueabihf": "1.33.0",
"lightningcss-linux-arm64-gnu": "1.33.0",
"lightningcss-linux-arm64-musl": "1.33.0",
"lightningcss-linux-x64-gnu": "1.33.0",
"lightningcss-linux-x64-musl": "1.33.0",
"lightningcss-win32-arm64-msvc": "1.33.0",
"lightningcss-win32-x64-msvc": "1.33.0"
"lightningcss-android-arm64": "1.32.0",
"lightningcss-darwin-arm64": "1.32.0",
"lightningcss-darwin-x64": "1.32.0",
"lightningcss-freebsd-x64": "1.32.0",
"lightningcss-linux-arm-gnueabihf": "1.32.0",
"lightningcss-linux-arm64-gnu": "1.32.0",
"lightningcss-linux-arm64-musl": "1.32.0",
"lightningcss-linux-x64-gnu": "1.32.0",
"lightningcss-linux-x64-musl": "1.32.0",
"lightningcss-win32-arm64-msvc": "1.32.0",
"lightningcss-win32-x64-msvc": "1.32.0"
}
},
"node_modules/lightningcss-android-arm64": {
"version": "1.33.0",
"resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.33.0.tgz",
"integrity": "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==",
"version": "1.32.0",
"resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz",
"integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==",
"cpu": [
"arm64"
],
@@ -1375,9 +1383,9 @@
}
},
"node_modules/lightningcss-darwin-arm64": {
"version": "1.33.0",
"resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.33.0.tgz",
"integrity": "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==",
"version": "1.32.0",
"resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz",
"integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==",
"cpu": [
"arm64"
],
@@ -1396,9 +1404,9 @@
}
},
"node_modules/lightningcss-darwin-x64": {
"version": "1.33.0",
"resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.33.0.tgz",
"integrity": "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==",
"version": "1.32.0",
"resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz",
"integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==",
"cpu": [
"x64"
],
@@ -1417,9 +1425,9 @@
}
},
"node_modules/lightningcss-freebsd-x64": {
"version": "1.33.0",
"resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.33.0.tgz",
"integrity": "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==",
"version": "1.32.0",
"resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz",
"integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==",
"cpu": [
"x64"
],
@@ -1438,9 +1446,9 @@
}
},
"node_modules/lightningcss-linux-arm-gnueabihf": {
"version": "1.33.0",
"resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.33.0.tgz",
"integrity": "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==",
"version": "1.32.0",
"resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz",
"integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==",
"cpu": [
"arm"
],
@@ -1459,9 +1467,9 @@
}
},
"node_modules/lightningcss-linux-arm64-gnu": {
"version": "1.33.0",
"resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.33.0.tgz",
"integrity": "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==",
"version": "1.32.0",
"resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz",
"integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==",
"cpu": [
"arm64"
],
@@ -1480,9 +1488,9 @@
}
},
"node_modules/lightningcss-linux-arm64-musl": {
"version": "1.33.0",
"resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.33.0.tgz",
"integrity": "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==",
"version": "1.32.0",
"resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz",
"integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==",
"cpu": [
"arm64"
],
@@ -1501,9 +1509,9 @@
}
},
"node_modules/lightningcss-linux-x64-gnu": {
"version": "1.33.0",
"resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.33.0.tgz",
"integrity": "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==",
"version": "1.32.0",
"resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz",
"integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==",
"cpu": [
"x64"
],
@@ -1522,9 +1530,9 @@
}
},
"node_modules/lightningcss-linux-x64-musl": {
"version": "1.33.0",
"resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.33.0.tgz",
"integrity": "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==",
"version": "1.32.0",
"resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz",
"integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==",
"cpu": [
"x64"
],
@@ -1543,9 +1551,9 @@
}
},
"node_modules/lightningcss-win32-arm64-msvc": {
"version": "1.33.0",
"resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.33.0.tgz",
"integrity": "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==",
"version": "1.32.0",
"resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz",
"integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==",
"cpu": [
"arm64"
],
@@ -1564,9 +1572,9 @@
}
},
"node_modules/lightningcss-win32-x64-msvc": {
"version": "1.33.0",
"resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.33.0.tgz",
"integrity": "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==",
"version": "1.32.0",
"resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz",
"integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==",
"cpu": [
"x64"
],
@@ -1638,17 +1646,10 @@
"dev": true,
"license": "CC0-1.0"
},
"node_modules/muggle-string": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.4.1.tgz",
"integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==",
"dev": true,
"license": "MIT"
},
"node_modules/nanoid": {
"version": "3.3.18",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz",
"integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==",
"version": "3.3.12",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz",
"integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==",
"funding": [
{
"type": "github",
@@ -1709,13 +1710,6 @@
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/path-browserify": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz",
"integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==",
"dev": true,
"license": "MIT"
},
"node_modules/pathe": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
@@ -1775,9 +1769,9 @@
}
},
"node_modules/postcss": {
"version": "8.5.26",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz",
"integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==",
"version": "8.5.19",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.19.tgz",
"integrity": "sha512-Mz8SaolMd8nB+G13WkORcxQKHZ/NE4xXevtkJHVuG+guo9/wYKlIMTKAqGdEmYOXR2ijPjTYNHssizdaVSUNdQ==",
"funding": [
{
"type": "opencollective",
@@ -1794,7 +1788,7 @@
],
"license": "MIT",
"dependencies": {
"nanoid": "^3.3.17",
"nanoid": "^3.3.12",
"picocolors": "^1.1.1",
"source-map-js": "^1.2.1"
},
@@ -1823,13 +1817,13 @@
}
},
"node_modules/rolldown": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.4.tgz",
"integrity": "sha512-rSr7irW0K7QRWzjdJXqZowkcRdDtjRduh43rBltnVKd0VFq839l1lJoDvGJb6gl7+4rTTCrPWu+YfujUL8Ug7w==",
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.1.5.tgz",
"integrity": "sha512-t9z29cJjXf/vxQ8dyhCSpt6H6aSwHTk8cT5I3iy6SMXuFpk5mB6PL6XfC8PCwrPTx93udwKUm9HRteAlTGBLiA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@oxc-project/types": "=0.144.0",
"@oxc-project/types": "=0.139.0",
"@rolldown/pluginutils": "^1.0.0"
},
"bin": {
@@ -1839,20 +1833,21 @@
"node": "^20.19.0 || >=22.12.0"
},
"optionalDependencies": {
"@rolldown/binding-android-arm64": "1.2.4",
"@rolldown/binding-darwin-arm64": "1.2.4",
"@rolldown/binding-darwin-x64": "1.2.4",
"@rolldown/binding-freebsd-x64": "1.2.4",
"@rolldown/binding-linux-arm-gnueabihf": "1.2.4",
"@rolldown/binding-linux-arm64-gnu": "1.2.4",
"@rolldown/binding-linux-arm64-musl": "1.2.4",
"@rolldown/binding-linux-ppc64-gnu": "1.2.4",
"@rolldown/binding-linux-s390x-gnu": "1.2.4",
"@rolldown/binding-linux-x64-gnu": "1.2.4",
"@rolldown/binding-linux-x64-musl": "1.2.4",
"@rolldown/binding-openharmony-arm64": "1.2.4",
"@rolldown/binding-win32-arm64-msvc": "1.2.4",
"@rolldown/binding-win32-x64-msvc": "1.2.4"
"@rolldown/binding-android-arm64": "1.1.5",
"@rolldown/binding-darwin-arm64": "1.1.5",
"@rolldown/binding-darwin-x64": "1.1.5",
"@rolldown/binding-freebsd-x64": "1.1.5",
"@rolldown/binding-linux-arm-gnueabihf": "1.1.5",
"@rolldown/binding-linux-arm64-gnu": "1.1.5",
"@rolldown/binding-linux-arm64-musl": "1.1.5",
"@rolldown/binding-linux-ppc64-gnu": "1.1.5",
"@rolldown/binding-linux-s390x-gnu": "1.1.5",
"@rolldown/binding-linux-x64-gnu": "1.1.5",
"@rolldown/binding-linux-x64-musl": "1.1.5",
"@rolldown/binding-openharmony-arm64": "1.1.5",
"@rolldown/binding-wasm32-wasi": "1.1.5",
"@rolldown/binding-win32-arm64-msvc": "1.1.5",
"@rolldown/binding-win32-x64-msvc": "1.1.5"
}
},
"node_modules/saxes": {
@@ -2021,6 +2016,14 @@
"node": ">=20"
}
},
"node_modules/tslib": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
"dev": true,
"license": "0BSD",
"optional": true
},
"node_modules/typescript": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz",
@@ -2036,13 +2039,13 @@
}
},
"node_modules/undici": {
"version": "7.28.0",
"resolved": "https://registry.npmjs.org/undici/-/undici-7.28.0.tgz",
"integrity": "sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA==",
"version": "8.9.0",
"resolved": "https://registry.npmjs.org/undici/-/undici-8.9.0.tgz",
"integrity": "sha512-aWZpUj7XoGonMClx4gdDRfgBjqeA+F473aDmROQQbM9n6PRfK/u1q/a0X4wMTgcHfT8H6fpbt98PFuDUwFg2YA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=20.18.1"
"node": ">=22.19.0"
}
},
"node_modules/undici-types": {
@@ -2053,16 +2056,16 @@
"license": "MIT"
},
"node_modules/vite": {
"version": "8.2.1",
"resolved": "https://registry.npmjs.org/vite/-/vite-8.2.1.tgz",
"integrity": "sha512-EU/eS7BH3XROHh2YnBefjM6DBKA6ZeMZEYQbj7NLWg5wHYlhB8B/Mayd5XsgWq+NFYccDOTemRpdETWR6Ka/lw==",
"version": "8.1.5",
"resolved": "https://registry.npmjs.org/vite/-/vite-8.1.5.tgz",
"integrity": "sha512-7ULLwsCdYx/nRyrpiEwvqb5TFHrMVZyBt+rg/OAXT7rgj/z+DtTDyKFeLAdDkubDVDKD8jOsndmy7m55XcfUsw==",
"dev": true,
"license": "MIT",
"dependencies": {
"lightningcss": "^1.33.0",
"lightningcss": "^1.32.0",
"picomatch": "^4.0.5",
"postcss": "^8.5.25",
"rolldown": "~1.2.1",
"postcss": "^8.5.17",
"rolldown": "~1.1.5",
"tinyglobby": "^0.2.17"
},
"bin": {
@@ -2079,7 +2082,7 @@
},
"peerDependencies": {
"@types/node": "^20.19.0 || >=22.12.0",
"@vitejs/devtools": "^0.4.0",
"@vitejs/devtools": "^0.3.0",
"esbuild": "^0.27.0 || ^0.28.0",
"jiti": ">=1.21.0",
"less": "^4.0.0",
@@ -2220,13 +2223,6 @@
}
}
},
"node_modules/vscode-uri": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz",
"integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==",
"dev": true,
"license": "MIT"
},
"node_modules/vue": {
"version": "3.5.40",
"resolved": "https://registry.npmjs.org/vue/-/vue-3.5.40.tgz",
@@ -2248,50 +2244,6 @@
}
}
},
"node_modules/vue-tsc": {
"version": "3.3.9",
"resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-3.3.9.tgz",
"integrity": "sha512-TS3Y1ux/IRoE8OCP2PpACAeOseuIs0UvWrcr7u+w3PmfY+SlCfEf8zjrBgnQksHUgLpthi5vHlffcQTQTdPBZA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@volar/typescript": "2.4.28",
"@vue/language-core": "3.3.9"
},
"bin": {
"vue-tsc": "bin/vue-tsc.js"
},
"peerDependencies": {
"typescript": ">=5.0.0"
}
},
"node_modules/vuetify": {
"version": "4.1.9",
"resolved": "https://registry.npmjs.org/vuetify/-/vuetify-4.1.9.tgz",
"integrity": "sha512-2NlpUiSwkUAGxKmkKwoRCst3IJF6EPP7msNJd+VxFjcAN9xCG+RFODzsfXfO2ypl9aSj3T/PJ65BBjQeTGgFKA==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/johnleider"
},
"peerDependencies": {
"typescript": ">=4.7",
"vite-plugin-vuetify": ">=2.1.0",
"vue": "^3.5.0 || ^3.6.0-0",
"webpack-plugin-vuetify": ">=3.1.0"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
},
"vite-plugin-vuetify": {
"optional": true
},
"webpack-plugin-vuetify": {
"optional": true
}
}
},
"node_modules/w3c-xmlserializer": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz",
+2 -5
View File
@@ -15,19 +15,16 @@
},
"dependencies": {
"pinia": "^4.0.0",
"vue": "^3.5.13",
"vuetify": "^4.0.0"
"vue": "^3.5.13"
},
"devDependencies": {
"@tsconfig/node24": "^24.0.0",
"@types/node": "^24.0.0",
"@vitejs/plugin-vue": "^6.0.1",
"@vue/tsconfig": "^0.9.0",
"typescript": "~6.0.0",
"vite": "^8.0.0",
"vue-tsc": "^3.0.5",
"@vitest/coverage-v8": "^4.1.6",
"jsdom": "^29.1.1",
"jsdom": "^30.0.0",
"vitest": "^4.1.6"
}
}
-228
View File
@@ -1,228 +0,0 @@
<script setup lang="ts">
import { computed, ref, watch } from 'vue'
import { useDocumentManager, useDocumentSelection } from '@/composables'
import { CollectionObject } from '@/models/collection'
import { EntityObject } from '@/models/entity'
import { formatSize, getFileIcon } from '@/utils/fileHelpers'
export interface DocumentSelection {
kind: 'entity' | 'collection'
identifier: string
name: string
mimeType?: string
size?: number
}
const PROVIDER_ID = 'default'
const SERVICE_ID = 'personal'
const LARGE_FILE_WARNING_BYTES = 25 * 1024 * 1024
const props = withDefaults(defineProps<{
modelValue: boolean
selectable?: ('entity' | 'collection')[]
}>(), {
selectable: () => ['entity'],
})
const emit = defineEmits<{
'update:modelValue': [value: boolean]
select: [items: DocumentSelection[]]
}>()
const allowEntities = computed(() => props.selectable.includes('entity'))
const allowCollections = computed(() => props.selectable.includes('collection'))
const documentManager = useDocumentManager({
providerId: PROVIDER_ID,
serviceId: SERVICE_ID,
})
const selection = useDocumentSelection({
multiple: true,
allowFolders: allowCollections.value,
allowFiles: allowEntities.value,
})
const initialized = ref(false)
watch(() => props.modelValue, async (isOpen) => {
if (!isOpen) {
return
}
selection.clear()
if (!initialized.value) {
await documentManager.initialize()
initialized.value = true
}
await documentManager.navigateToRoot()
})
function nodeId(node: CollectionObject | EntityObject): string {
return String(node.identifier ?? '')
}
function nodeLabel(node: CollectionObject | EntityObject): string {
return node.properties.label || nodeId(node)
}
const breadcrumbs = computed(() => [
{ id: documentManager.ROOT_ID, label: 'Home' },
...documentManager.breadcrumbs.value.map(node => ({ id: nodeId(node), label: nodeLabel(node) })),
])
async function navigateToBreadcrumb(id: string) {
selection.clear()
await documentManager.navigateTo(id === documentManager.ROOT_ID ? null : id)
}
async function openFolder(folder: CollectionObject) {
selection.clear()
await documentManager.navigateTo(nodeId(folder))
}
function toggleFolderSelection(folder: CollectionObject, event: Event) {
event.stopPropagation()
selection.toggle(folder)
}
function toggleEntity(entity: EntityObject) {
selection.toggle(entity)
}
const hasLargeSelection = computed(() =>
selection.selectedEntities.value.some(entity => entity.properties.size > LARGE_FILE_WARNING_BYTES),
)
function entityIdentifier(entity: EntityObject): string {
return `${entity.provider}:${entity.service}:${entity.collection}:${entity.identifier}`
}
function collectionIdentifier(collection: CollectionObject): string {
return `${collection.provider}:${collection.service}:${collection.identifier}`
}
function toSelection(node: CollectionObject | EntityObject): DocumentSelection {
if (node instanceof EntityObject) {
return {
kind: 'entity',
identifier: entityIdentifier(node),
name: nodeLabel(node),
mimeType: node.properties.mime || 'application/octet-stream',
size: node.properties.size,
}
}
return {
kind: 'collection',
identifier: collectionIdentifier(node),
name: nodeLabel(node),
}
}
function handleClose() {
emit('update:modelValue', false)
}
function handleConfirm() {
const items = selection.selectedNodeArray.value.map(toSelection)
if (items.length === 0) {
return
}
emit('select', items)
selection.clear()
emit('update:modelValue', false)
}
</script>
<template>
<v-dialog :model-value="modelValue" @update:model-value="emit('update:modelValue', $event)" max-width="560">
<v-card>
<v-card-title class="d-flex align-center">
<v-icon class="mr-2">mdi-folder-search-outline</v-icon>
Select Documents
</v-card-title>
<v-card-text>
<v-breadcrumbs :items="breadcrumbs" density="compact" class="px-0 mb-2">
<template #item="{ item }">
<v-breadcrumbs-item :disabled="item.id === breadcrumbs[breadcrumbs.length - 1]?.id" @click="navigateToBreadcrumb(item.id)">
{{ item.label }}
</v-breadcrumbs-item>
</template>
</v-breadcrumbs>
<v-progress-linear v-if="documentManager.isLoading.value" indeterminate color="primary" class="mb-2" />
<div class="selector-list">
<v-list v-if="documentManager.currentCollections.value.length > 0 || documentManager.currentEntities.value.length > 0" density="compact">
<v-list-item
v-for="folder in documentManager.currentCollections.value"
:key="nodeId(folder)"
:title="nodeLabel(folder)"
@click="openFolder(folder)"
>
<template #prepend>
<v-checkbox-btn
v-if="allowCollections"
:model-value="selection.isSelected(nodeId(folder))"
class="mr-2"
@click="toggleFolderSelection(folder, $event)"
/>
<v-icon>mdi-folder</v-icon>
</template>
<template #append>
<v-icon size="small">mdi-chevron-right</v-icon>
</template>
</v-list-item>
<v-list-item
v-for="entity in documentManager.currentEntities.value"
:key="nodeId(entity)"
:title="nodeLabel(entity)"
:subtitle="formatSize(entity.properties.size)"
:disabled="!allowEntities"
@click="allowEntities && toggleEntity(entity)"
>
<template #prepend>
<v-checkbox-btn v-if="allowEntities" :model-value="selection.isSelected(nodeId(entity))" class="mr-2" />
<v-icon>{{ getFileIcon(entity) }}</v-icon>
</template>
</v-list-item>
</v-list>
<div v-else-if="!documentManager.isLoading.value" class="text-center py-8 text-medium-emphasis">
<v-icon size="40" class="mb-2">mdi-folder-open-outline</v-icon>
<div>This folder is empty</div>
</div>
</div>
<v-alert v-if="hasLargeSelection" type="warning" variant="tonal" density="compact" class="mt-3">
One or more selected files are larger than 25 MB and may take a moment to process.
</v-alert>
</v-card-text>
<v-card-actions>
<span class="text-caption text-medium-emphasis ml-2">
{{ selection.count.value }} selected
</span>
<v-spacer />
<v-btn variant="text" @click="handleClose">Cancel</v-btn>
<v-btn color="primary" variant="elevated" :disabled="!selection.hasSelection.value" @click="handleConfirm">
Select
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<style scoped>
.selector-list {
max-height: 360px;
overflow-y: auto;
border: 1px solid rgb(var(--v-border-color));
border-radius: 8px;
}
</style>
-9
View File
@@ -1,9 +0,0 @@
/**
* Central export point for Documents Manager composables
*/
export { useDocumentManager } from './useDocumentManager'
export { useDocumentSelection } from './useDocumentSelection'
export type { UseDocumentManagerOptions } from './useDocumentManager'
export type { UseDocumentSelectionOptions } from './useDocumentSelection'
-295
View File
@@ -1,295 +0,0 @@
/**
* File Manager composable for convenient file/folder operations
* Provides reactive access to file manager state and actions
*/
import { computed, ref, unref } from 'vue'
import type { Ref, ComputedRef } from 'vue'
import { useProvidersStore } from '@/stores/providersStore'
import { useServicesStore } from '@/stores/servicesStore'
import { useNodesStore, ROOT_ID } from '@/stores/nodesStore'
import type { ListFilter, ListSort, ListRange } from '@/types/common'
import type { DocumentInterface } from '@/types/document'
import { CollectionObject } from '@/models/collection'
import { EntityObject } from '@/models/entity'
// Base URL for file manager transfer endpoints
const TRANSFER_BASE_URL = '/m/documents_manager'
export interface UseDocumentManagerOptions {
providerId: string | Ref<string> | ComputedRef<string>
serviceId: string | Ref<string> | ComputedRef<string>
autoFetch?: boolean
}
export function useDocumentManager(options: UseDocumentManagerOptions) {
const providersStore = useProvidersStore()
const servicesStore = useServicesStore()
const nodesStore = useNodesStore()
const { providerId, serviceId, autoFetch = false } = options
const currentProviderId = () => unref(providerId)
const currentServiceId = () => unref(serviceId)
// Current location (folder being viewed)
const currentLocation: Ref<string> = ref(ROOT_ID)
// Loading/error state
const isLoading = computed(() => nodesStore.transceiving)
const error = computed(() => nodesStore.error)
// Provider and service
const provider = computed(() => providersStore.provider(currentProviderId()))
const service = computed(() => servicesStore.service(currentProviderId(), currentServiceId()))
const rootId = computed(() => ROOT_ID)
// Current children
const currentChildren = computed(() =>
nodesStore.getChildren(currentProviderId(), currentServiceId(), currentLocation.value)
)
const currentCollections: ComputedRef<CollectionObject[]> = computed(() =>
nodesStore.getChildCollections(currentProviderId(), currentServiceId(), currentLocation.value)
)
const currentEntities: ComputedRef<EntityObject[]> = computed(() =>
nodesStore.getChildEntities(currentProviderId(), currentServiceId(), currentLocation.value)
)
// Breadcrumb path
const breadcrumbs = computed(() => {
if (currentLocation.value === ROOT_ID) {
return []
}
return nodesStore.getPath(currentProviderId(), currentServiceId(), currentLocation.value)
})
// Is at root?
const isAtRoot = computed(() => currentLocation.value === ROOT_ID)
// Navigate to a folder
const navigateTo = async (collectionId: string | null) => {
currentLocation.value = collectionId || ROOT_ID
await refresh()
}
// Navigate up one level
const navigateUp = async () => {
if (currentLocation.value === ROOT_ID) {
return
}
const currentNode = nodesStore.getNode(currentProviderId(), currentServiceId(), currentLocation.value)
if (currentNode) {
await navigateTo(currentNode.collection ? String(currentNode.collection) : ROOT_ID)
}
}
// Navigate to root
const navigateToRoot = async () => {
await navigateTo(ROOT_ID)
}
// Refresh current location
const refresh = async (
filter?: ListFilter,
sort?: ListSort,
range?: ListRange
) => {
await nodesStore.fetchNodes(
currentProviderId(),
currentServiceId(),
currentLocation.value === ROOT_ID ? ROOT_ID : currentLocation.value,
filter,
sort,
range
)
}
// Create a new folder
const createFolder = async (label: string): Promise<CollectionObject> => {
return await nodesStore.createCollection(
currentProviderId(),
currentServiceId(),
currentLocation.value === ROOT_ID ? ROOT_ID : currentLocation.value,
{ label, owner: '' }
)
}
// Create a new file
const createFile = async (
label: string,
mime: string = 'application/octet-stream'
): Promise<EntityObject> => {
const properties: DocumentInterface = {
'@type': 'documents.properties',
urid: null,
size: 0,
label,
mime,
format: null,
encoding: null,
}
return await nodesStore.createEntity(
currentProviderId(),
currentServiceId(),
currentLocation.value === ROOT_ID ? ROOT_ID : currentLocation.value,
properties
)
}
// Rename a node
const renameNode = async (nodeId: string, newLabel: string) => {
const node = nodesStore.getNode(currentProviderId(), currentServiceId(), nodeId)
if (!node) {
throw new Error('Node not found')
}
if (node instanceof CollectionObject) {
return await nodesStore.updateCollection(currentProviderId(), currentServiceId(), nodeId, {
label: newLabel,
owner: node.properties.owner,
})
} else {
const properties: DocumentInterface = {
'@type': 'documents.properties',
urid: node.properties.urid,
size: node.properties.size,
label: newLabel,
mime: node.properties.mime,
format: node.properties.format,
encoding: node.properties.encoding,
}
return await nodesStore.updateEntity(currentProviderId(), currentServiceId(), node.collection, nodeId, properties)
}
}
// Delete a node
const deleteNode = async (nodeId: string): Promise<boolean> => {
const node = nodesStore.getNode(currentProviderId(), currentServiceId(), nodeId)
if (!node) {
throw new Error('Node not found')
}
if (node instanceof CollectionObject) {
return await nodesStore.deleteCollection(currentProviderId(), currentServiceId(), nodeId)
} else {
return await nodesStore.deleteEntity(currentProviderId(), currentServiceId(), node.collection, nodeId)
}
}
// Read file content
const readFile = async (entityId: string): Promise<string | null> => {
const node = nodesStore.getNode(currentProviderId(), currentServiceId(), entityId)
if (!node || !(node instanceof EntityObject)) {
throw new Error('Entity not found')
}
return await nodesStore.readEntity(currentProviderId(), currentServiceId(), node.collection || ROOT_ID, entityId)
}
// Write file content
const writeFile = async (entityId: string, content: string): Promise<number> => {
const node = nodesStore.getNode(currentProviderId(), currentServiceId(), entityId)
if (!node || !(node instanceof EntityObject)) {
throw new Error('Entity not found')
}
return await nodesStore.writeEntity(currentProviderId(), currentServiceId(), node.collection, entityId, content)
}
// Get a URL suitable for inline viewing (img src / video src)
const getEntityUrl = (entityId: string, collectionId?: string | null): string => {
const collection = collectionId ?? currentLocation.value
return `${TRANSFER_BASE_URL}/download/entity/${encodeURIComponent(currentProviderId())}/${encodeURIComponent(currentServiceId())}/${encodeURIComponent(collection)}/${encodeURIComponent(entityId)}`
}
// Download a single file
const downloadEntity = (entityId: string, collectionId?: string | null): void => {
const collection = collectionId ?? currentLocation.value
// Use path parameters: /download/entity/{provider}/{service}/{collection}/{identifier}
const url = `${TRANSFER_BASE_URL}/download/entity/${encodeURIComponent(currentProviderId())}/${encodeURIComponent(currentServiceId())}/${encodeURIComponent(collection)}/${encodeURIComponent(entityId)}`
// Trigger download by opening URL (browser handles it)
window.open(url, '_blank')
}
const downloadCollection = (collectionId: string): void => {
// Use path parameters: /download/collection/{provider}/{service}/{identifier}
const url = `${TRANSFER_BASE_URL}/download/collection/${encodeURIComponent(currentProviderId())}/${encodeURIComponent(currentServiceId())}/${encodeURIComponent(collectionId)}`
window.open(url, '_blank')
}
const downloadArchive = (ids: string[], name: string = 'download', collectionId?: string | null): void => {
const collection = collectionId ?? currentLocation.value
const params = new URLSearchParams({
provider: currentProviderId(),
service: currentServiceId(),
})
ids.forEach(id => params.append('ids[]', id))
if (name) {
params.append('name', name)
}
if (collection && collection !== ROOT_ID) {
params.append('collection', collection)
}
const url = `${TRANSFER_BASE_URL}/download/archive?${params.toString()}`
window.open(url, '_blank')
}
// Initialize - fetch providers, services, and initial nodes if autoFetch
const initialize = async () => {
await providersStore.list([currentProviderId()])
await servicesStore.list()
if (autoFetch) {
await refresh()
}
}
return {
// State
currentLocation,
isLoading,
error,
// Provider/Service
provider,
service,
rootId,
// Current view
currentChildren,
currentCollections,
currentEntities,
breadcrumbs,
isAtRoot,
// Navigation
navigateTo,
navigateUp,
navigateToRoot,
refresh,
// Operations
createFolder,
createFile,
renameNode,
deleteNode,
readFile,
writeFile,
getEntityUrl,
downloadEntity,
downloadCollection,
downloadArchive,
// Initialize
initialize,
// Constants
ROOT_ID,
}
}
export default useDocumentManager
-135
View File
@@ -1,135 +0,0 @@
/**
* File selection composable
* Provides reactive selection management for file manager
*/
import { ref, computed } from 'vue'
import type { Ref, ComputedRef } from 'vue'
import { CollectionObject } from '@/models/collection'
import { EntityObject } from '@/models/entity'
type NodeRecord = CollectionObject | EntityObject
export interface UseDocumentSelectionOptions {
multiple?: boolean
allowFolders?: boolean
allowFiles?: boolean
}
export function useDocumentSelection(options: UseDocumentSelectionOptions = {}) {
const {
multiple = true,
allowFolders = true,
allowFiles = true,
} = options
const selectedIds: Ref<Set<string>> = ref(new Set())
const selectedNodes: Ref<Map<string, NodeRecord>> = ref(new Map())
const count: ComputedRef<number> = computed(() => selectedIds.value.size)
const hasSelection: ComputedRef<boolean> = computed(() => selectedIds.value.size > 0)
const selectedIdArray: ComputedRef<string[]> = computed(() => Array.from(selectedIds.value))
const selectedNodeArray: ComputedRef<NodeRecord[]> = computed(() => Array.from(selectedNodes.value.values()))
const selectedCollections: ComputedRef<CollectionObject[]> = computed(() =>
selectedNodeArray.value.filter((node): node is CollectionObject => node instanceof CollectionObject),
)
const selectedEntities: ComputedRef<EntityObject[]> = computed(() =>
selectedNodeArray.value.filter((node): node is EntityObject => node instanceof EntityObject),
)
const isSelected = (nodeId: string): boolean => selectedIds.value.has(nodeId)
const isTypeAllowed = (node: NodeRecord): boolean => {
if (node instanceof CollectionObject && !allowFolders) return false
if (node instanceof EntityObject && !allowFiles) return false
return true
}
const select = (node: NodeRecord) => {
if (!isTypeAllowed(node)) return
if (!multiple) {
selectedIds.value.clear()
selectedNodes.value.clear()
}
const nodeId = String(node.identifier)
selectedIds.value.add(nodeId)
selectedNodes.value.set(nodeId, node)
}
const deselect = (nodeId: string) => {
selectedIds.value.delete(nodeId)
selectedNodes.value.delete(nodeId)
}
const toggle = (node: NodeRecord) => {
const nodeId = String(node.identifier)
if (isSelected(nodeId)) {
deselect(nodeId)
return
}
select(node)
}
const selectMultiple = (nodes: NodeRecord[]) => {
if (!multiple) {
const lastNode = nodes[nodes.length - 1]
if (lastNode && isTypeAllowed(lastNode)) {
selectedIds.value.clear()
selectedNodes.value.clear()
const nodeId = String(lastNode.identifier)
selectedIds.value.add(nodeId)
selectedNodes.value.set(nodeId, lastNode)
}
return
}
for (const node of nodes) {
if (isTypeAllowed(node)) {
const nodeId = String(node.identifier)
selectedIds.value.add(nodeId)
selectedNodes.value.set(nodeId, node)
}
}
}
const selectAll = (nodes: NodeRecord[]) => {
if (!multiple) return
selectMultiple(nodes)
}
const clear = () => {
selectedIds.value.clear()
selectedNodes.value.clear()
}
const setSelection = (nodes: NodeRecord[]) => {
clear()
selectMultiple(nodes)
}
return {
selectedIds,
selectedNodes,
count,
hasSelection,
selectedIdArray,
selectedNodeArray,
selectedCollections,
selectedEntities,
isSelected,
select,
deselect,
toggle,
selectMultiple,
selectAll,
clear,
setSelection,
}
}
export default useDocumentSelection
-14
View File
@@ -1,14 +0,0 @@
import type { ModuleIntegrations } from "@KTXC/types/moduleTypes";
const integrations: ModuleIntegrations = {
documents_selector: [
{
id: 'dialog',
label: 'Document Selector Dialog',
priority: 10,
component: () => import('./components/DocumentSelectorDialog.vue'),
},
],
};
export default integrations;
+2 -8
View File
@@ -2,20 +2,14 @@
* Documents Manager Module Boot
*/
import integrations from '@/integrations'
console.log('[Documents Manager] Booting module...')
console.log('[Documents Manager] Module booted successfully...')
// CSS filename is injected by the vite plugin at build time
export const css = ['__CSS_FILENAME_PLACEHOLDER__']
export { integrations }
// CSS will be injected by build process
//export const css = ['__CSS_FILENAME_PLACEHOLDER__']
// Export services, stores and models for external use
export * from '@/services'
export * from '@/stores'
export * from '@/models'
export * from '@/composables'
export * from '@/utils/fileHelpers'
-71
View File
@@ -1,71 +0,0 @@
import { EntityObject } from '@/models/entity'
/**
* Get the appropriate icon for a file based on its MIME type
*/
export function getFileIcon(entity: EntityObject): string {
const mime = entity.properties.mime || ''
if (!mime) return 'mdi-file'
if (mime.startsWith('image/')) return 'mdi-file-image'
if (mime.startsWith('video/')) return 'mdi-file-video'
if (mime.startsWith('audio/')) return 'mdi-file-music'
if (mime.startsWith('text/')) return 'mdi-file-document'
if (mime === 'application/pdf') return 'mdi-file-pdf-box'
if (mime.includes('zip') || mime.includes('tar') || mime.includes('compressed')) return 'mdi-folder-zip'
if (mime.includes('word') || mime.includes('document')) return 'mdi-file-word'
if (mime.includes('excel') || mime.includes('spreadsheet')) return 'mdi-file-excel'
if (mime.includes('powerpoint') || mime.includes('presentation')) return 'mdi-file-powerpoint'
return 'mdi-file'
}
/**
* Format file size in human readable format
*/
export function formatSize(bytes: number): string {
const safeBytes = Number.isFinite(bytes) ? bytes : 0
if (safeBytes === 0) return '0 B'
const k = 1024
const sizes = ['B', 'KB', 'MB', 'GB', 'TB']
const i = Math.floor(Math.log(safeBytes) / Math.log(k))
return parseFloat((safeBytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
}
/**
* Format date string to localized format
*/
export function formatDate(value: Date | string | null | undefined): string {
if (!value) return '—'
const date = value instanceof Date ? value : new Date(value)
if (Number.isNaN(date.getTime())) return '—'
return date.toLocaleDateString('en-US', {
year: 'numeric',
month: 'short',
day: 'numeric',
})
}
/**
* Get upload status icon
*/
export function getUploadStatusIcon(status: string): string {
switch (status) {
case 'pending': return 'mdi-clock-outline'
case 'uploading': return 'mdi-loading mdi-spin'
case 'completed': return 'mdi-check-circle'
case 'error': return 'mdi-alert-circle'
default: return 'mdi-file'
}
}
/**
* Get upload status color
*/
export function getUploadStatusColor(status: string): string {
switch (status) {
case 'pending': return 'grey'
case 'uploading': return 'primary'
case 'completed': return 'success'
case 'error': return 'error'
default: return 'grey'
}
}
+1 -1
View File
@@ -15,5 +15,5 @@
"@KTXC/*": ["../../core/src/*"]
}
},
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"]
"include": ["src/**/*.ts", "src/**/*.tsx"]
}