diff --git a/bun.lock b/bun.lock index 1231b0fe..d02ee205 100644 --- a/bun.lock +++ b/bun.lock @@ -5,7 +5,7 @@ "": { "name": "betterseqtaplus", "dependencies": { - "@bedframe/core": "^0.0.46", + "@bedframe/core": "^0.1.0", "@codemirror/autocomplete": "^6.18.6", "@codemirror/commands": "^6.8.0", "@codemirror/lang-css": "^6.3.1", @@ -13,7 +13,7 @@ "@codemirror/search": "^6.5.10", "@codemirror/state": "^6.5.2", "@codemirror/view": "^6.36.4", - "@sveltejs/vite-plugin-svelte": "^5.0.3", + "@sveltejs/vite-plugin-svelte": "^7.0.0", "@tailwindcss/forms": "^0.5.10", "@tsconfig/svelte": "^5.0.4", "@types/chrome": "^0.1.4", @@ -52,17 +52,17 @@ "react-dom": "17", "rss-parser": "^3.13.0", "sortablejs": "^1.15.6", - "svelte": "^5.22.6", + "svelte": "^5.46.4", "typescript": "^5.8.2", "uuid": "^11.1.0", - "vite": "^6.2.1", + "vite": "^8.0.5", "webextension-polyfill": "^0.12.0", }, "devDependencies": { "@babel/plugin-transform-runtime": "^7.26.9", "@babel/runtime": "^7.26.9", - "@bedframe/cli": "^0.0.95", - "@crxjs/vite-plugin": "^2.2.0", + "@bedframe/cli": "^0.1.2", + "@crxjs/vite-plugin": "^2.4.0", "@types/mime-types": "^3.0.1", "@types/react": "^19.0.10", "@types/react-dom": "^19.0.4", @@ -127,9 +127,9 @@ "@babel/types": ["@babel/types@7.28.2", "", { "dependencies": { "@babel/helper-string-parser": "7.27.1", "@babel/helper-validator-identifier": "7.27.1" } }, "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ=="], - "@bedframe/cli": ["@bedframe/cli@0.0.95", "", { "dependencies": { "@bedframe/core": "0.0.46", "commander": "14.0.0", "execa": "9.6.0", "kolorist": "1.8.0", "listr": "0.14.3", "nanospinner": "1.2.2", "node-fetch": "3.3.2", "pkg-install": "1.0.0", "prompts": "2.4.2", "vite": "6.3.5" }, "peerDependencies": { "concurrently": "8.2.2" }, "bin": { "bedframe": "dist/bedframe.js", "create-bedframe": "dist/create-bedframe.js" } }, "sha512-WSb0HhHCfH7/tS5dDC/HL/VgKrIFGLmI0OesmcwQntrJdHVirtjrDVjcTFG3lC3LB5Ax85P1CY50Gy5aDNc0sQ=="], + "@bedframe/cli": ["@bedframe/cli@0.1.2", "", { "dependencies": { "@bedframe/core": "0.1.0", "commander": "^14.0.2", "execa": "^9.6.1", "kolorist": "^1.8.0", "listr": "^0.14.3", "nanospinner": "^1.2.2", "node-fetch": "^3.3.2", "pkg-install": "^1.0.0", "prompts": "^2.4.2", "vite": "^6.4.1" }, "peerDependencies": { "concurrently": "^8.2.1" }, "bin": { "bedframe": "dist/bedframe.js", "create-bedframe": "dist/create-bedframe.js" } }, "sha512-nu0VSfGLhY9f62w+fDRQi2YnfoY9c6u28ZlJ8rH6f57ItLo5TNrZetfw37fYNnh8yK2RSAWU7+6KCkdVm0Fokg=="], - "@bedframe/core": ["@bedframe/core@0.0.46", "", { "dependencies": { "@crxjs/vite-plugin": "2.0.2" }, "peerDependencies": { "vite-plugin-dts": "3.9.1", "vite-plugin-externalize-deps": "0.7.0", "vitest": "0.34.6" } }, "sha512-cOshFUrBksWnVQ08chunlvAetwhuytkX7NdH6blNNylYzsgCaLGBbCJ2EZ0d18kimFVNZoODrc+812if5dio/w=="], + "@bedframe/core": ["@bedframe/core@0.1.0", "", { "dependencies": { "@crxjs/vite-plugin": "2.3.0" }, "peerDependencies": { "vite-plugin-dts": "^3.7.0", "vite-plugin-externalize-deps": "^0.7.0", "vitest": "^0.34.6" } }, "sha512-bM9vuYG67m9lVTui966AmkoxPPdEHEDOKKjzAWV/Ymgur818fRhMMpblx3+PLs8kTCek1m79fjYKoE8PhqJ22g=="], "@codemirror/autocomplete": ["@codemirror/autocomplete@6.18.6", "", { "dependencies": { "@codemirror/language": "6.11.3", "@codemirror/state": "6.5.2", "@codemirror/view": "6.38.1", "@lezer/common": "1.2.3" } }, "sha512-PHHBXFomUs5DF+9tCOM/UoW6XQ4R44lLNNhRaW9PKPTU0D7lIjRg3ElxaJnTwsl/oHiR93WSXDBrekhoUGCPtg=="], @@ -147,7 +147,13 @@ "@codemirror/view": ["@codemirror/view@6.38.1", "", { "dependencies": { "@codemirror/state": "6.5.2", "crelt": "1.0.6", "style-mod": "4.1.2", "w3c-keyname": "2.2.8" } }, "sha512-RmTOkE7hRU3OVREqFVITWHz6ocgBjv08GoePscAakgVQfciA3SGCEk7mb9IzwW61cKKmlTpHXG6DUE5Ubx+MGQ=="], - "@crxjs/vite-plugin": ["@crxjs/vite-plugin@2.2.0", "", { "dependencies": { "@rollup/pluginutils": "4.2.1", "@webcomponents/custom-elements": "1.6.0", "acorn-walk": "8.3.4", "cheerio": "1.1.2", "convert-source-map": "1.9.0", "debug": "4.4.1", "es-module-lexer": "0.10.5", "fast-glob": "3.3.3", "fs-extra": "10.1.0", "jsesc": "3.1.0", "magic-string": "0.30.18", "pathe": "2.0.3", "picocolors": "1.1.1", "react-refresh": "0.13.0", "rollup": "2.79.2", "rxjs": "7.5.7" } }, "sha512-HpT1GLbUQy42nlpN4sGzFgulacBraMM778s8Q+oPo4cb26DwO9tTwdndlvAS8fe6vEProFXvbdt37objp/0IQA=="], + "@crxjs/vite-plugin": ["@crxjs/vite-plugin@2.4.0", "", { "dependencies": { "@rollup/pluginutils": "^4.1.2", "@webcomponents/custom-elements": "^1.5.0", "acorn-walk": "^8.2.0", "convert-source-map": "^1.7.0", "debug": "^4.3.3", "es-module-lexer": "^0.10.0", "fast-glob": "^3.2.11", "fs-extra": "^10.0.1", "jsesc": "^3.0.2", "magic-string": "^0.30.12", "node-html-parser": "^7.0.2", "pathe": "^2.0.1", "picocolors": "^1.1.1", "react-refresh": "^0.13.0", "rollup": "2.79.2", "rxjs": "7.5.7" }, "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-bDLdq0W2V1SkMQDJjrcYyjK9/uKtdl4joT7GRImcootCjZdKRiRYt+cv9z8tJoU/tK3o1lX48LTqN7JMsk5AQg=="], + + "@emnapi/core": ["@emnapi/core@1.9.2", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" } }, "sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA=="], + + "@emnapi/runtime": ["@emnapi/runtime@1.9.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw=="], + + "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w=="], "@epic-web/invariant": ["@epic-web/invariant@1.0.0", "", {}, "sha512-lrTPqgvfFQtR/eY/qkIzp98OGdNJu0m5ji3q/nJI8v3SXkRKEnWiOxMmbvcSoAIzv/cGiuvRy57k4suKQSAdwA=="], @@ -293,12 +299,16 @@ "@napi-rs/canvas-win32-x64-msvc": ["@napi-rs/canvas-win32-x64-msvc@0.1.89", "", { "os": "win32", "cpu": "x64" }, "sha512-WMej0LZrIqIncQcx0JHaMXlnAG7sncwJh7obs/GBgp0xF9qABjwoRwIooMWCZkSansapKGNUHhamY6qEnFN7gA=="], + "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.4", "", { "dependencies": { "@tybys/wasm-util": "^0.10.1" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" } }, "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow=="], + "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "1.2.0" } }, "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.19.1" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], + "@oxc-project/types": ["@oxc-project/types@0.124.0", "", {}, "sha512-VBFWMTBvHxS11Z5Lvlr3IWgrwhMTXV+Md+EQF0Xf60+wAdsGFTBx7X7K/hP4pi8N7dcm1RvcHwDxZ16Qx8keUg=="], + "@parcel/watcher": ["@parcel/watcher@2.5.1", "", { "dependencies": { "detect-libc": "1.0.3", "is-glob": "4.0.3", "micromatch": "4.0.8", "node-addon-api": "7.1.1" }, "optionalDependencies": { "@parcel/watcher-android-arm64": "2.5.1", "@parcel/watcher-darwin-arm64": "2.5.1", "@parcel/watcher-darwin-x64": "2.5.1", "@parcel/watcher-freebsd-x64": "2.5.1", "@parcel/watcher-linux-arm-glibc": "2.5.1", "@parcel/watcher-linux-arm-musl": "2.5.1", "@parcel/watcher-linux-arm64-glibc": "2.5.1", "@parcel/watcher-linux-arm64-musl": "2.5.1", "@parcel/watcher-linux-x64-glibc": "2.5.1", "@parcel/watcher-linux-x64-musl": "2.5.1", "@parcel/watcher-win32-arm64": "2.5.1", "@parcel/watcher-win32-ia32": "2.5.1", "@parcel/watcher-win32-x64": "2.5.1" } }, "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg=="], "@parcel/watcher-android-arm64": ["@parcel/watcher-android-arm64@2.5.1", "", { "os": "android", "cpu": "arm64" }, "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA=="], @@ -349,6 +359,38 @@ "@protobufjs/utf8": ["@protobufjs/utf8@1.1.0", "", {}, "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw=="], + "@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.0.0-rc.15", "", { "os": "android", "cpu": "arm64" }, "sha512-YYe6aWruPZDtHNpwu7+qAHEMbQ/yRl6atqb/AhznLTnD3UY99Q1jE7ihLSahNWkF4EqRPVC4SiR4O0UkLK02tA=="], + + "@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.0-rc.15", "", { "os": "darwin", "cpu": "arm64" }, "sha512-oArR/ig8wNTPYsXL+Mzhs0oxhxfuHRfG7Ikw7jXsw8mYOtk71W0OkF2VEVh699pdmzjPQsTjlD1JIOoHkLP1Fg=="], + + "@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.0.0-rc.15", "", { "os": "darwin", "cpu": "x64" }, "sha512-YzeVqOqjPYvUbJSWJ4EDL8ahbmsIXQpgL3JVipmN+MX0XnXMeWomLN3Fb+nwCmP/jfyqte5I3XRSm7OfQrbyxw=="], + + "@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.0.0-rc.15", "", { "os": "freebsd", "cpu": "x64" }, "sha512-9Erhx956jeQ0nNTyif1+QWAXDRD38ZNjr//bSHrt6wDwB+QkAfl2q6Mn1k6OBPerznjRmbM10lgRb1Pli4xZPw=="], + + "@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.15", "", { "os": "linux", "cpu": "arm" }, "sha512-cVwk0w8QbZJGTnP/AHQBs5yNwmpgGYStL88t4UIaqcvYJWBfS0s3oqVLZPwsPU6M0zlW4GqjP0Zq5MnAGwFeGA=="], + + "@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.0.0-rc.15", "", { "os": "linux", "cpu": "arm64" }, "sha512-eBZ/u8iAK9SoHGanqe/jrPnY0JvBN6iXbVOsbO38mbz+ZJsaobExAm1Iu+rxa4S1l2FjG0qEZn4Rc6X8n+9M+w=="], + + "@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.0.0-rc.15", "", { "os": "linux", "cpu": "arm64" }, "sha512-ZvRYMGrAklV9PEkgt4LQM6MjQX2P58HPAuecwYObY2DhS2t35R0I810bKi0wmaYORt6m/2Sm+Z+nFgb0WhXNcQ=="], + + "@rolldown/binding-linux-ppc64-gnu": ["@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.15", "", { "os": "linux", "cpu": "ppc64" }, "sha512-VDpgGBzgfg5hLg+uBpCLoFG5kVvEyafmfxGUV0UHLcL5irxAK7PKNeC2MwClgk6ZAiNhmo9FLhRYgvMmedLtnQ=="], + + "@rolldown/binding-linux-s390x-gnu": ["@rolldown/binding-linux-s390x-gnu@1.0.0-rc.15", "", { "os": "linux", "cpu": "s390x" }, "sha512-y1uXY3qQWCzcPgRJATPSOUP4tCemh4uBdY7e3EZbVwCJTY3gLJWnQABgeUetvED+bt1FQ01OeZwvhLS2bpNrAQ=="], + + "@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.0.0-rc.15", "", { "os": "linux", "cpu": "x64" }, "sha512-023bTPBod7J3Y/4fzAN6QtpkSABR0rigtrwaP+qSEabUh5zf6ELr9Nc7GujaROuPY3uwdSIXWrvhn1KxOvurWA=="], + + "@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.0.0-rc.15", "", { "os": "linux", "cpu": "x64" }, "sha512-witB2O0/hU4CgfOOKUoeFgQ4GktPi1eEbAhaLAIpgD6+ZnhcPkUtPsoKKHRzmOoWPZue46IThdSgdo4XneOLYw=="], + + "@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.0.0-rc.15", "", { "os": "none", "cpu": "arm64" }, "sha512-UCL68NJ0Ud5zRipXZE9dF5PmirzJE4E4BCIOOssEnM7wLDsxjc6Qb0sGDxTNRTP53I6MZpygyCpY8Aa8sPfKPg=="], + + "@rolldown/binding-wasm32-wasi": ["@rolldown/binding-wasm32-wasi@1.0.0-rc.15", "", { "dependencies": { "@emnapi/core": "1.9.2", "@emnapi/runtime": "1.9.2", "@napi-rs/wasm-runtime": "^1.1.3" }, "cpu": "none" }, "sha512-ApLruZq/ig+nhaE7OJm4lDjayUnOHVUa77zGeqnqZ9pn0ovdVbbNPerVibLXDmWeUZXjIYIT8V3xkT58Rm9u5Q=="], + + "@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.0.0-rc.15", "", { "os": "win32", "cpu": "arm64" }, "sha512-KmoUoU7HnN+Si5YWJigfTws1jz1bKBYDQKdbLspz0UaqjjFkddHsqorgiW1mxcAj88lYUE6NC/zJNwT+SloqtA=="], + + "@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.0.0-rc.15", "", { "os": "win32", "cpu": "x64" }, "sha512-3P2A8L+x75qavWLe/Dll3EYBJLQmtkJN8rfh+U/eR3MqMgL/h98PhYI+JFfXuDPgPeCB7iZAKiqii5vqOvnA0g=="], + + "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-rc.15", "", {}, "sha512-UromN0peaE53IaBRe9W7CjrZgXl90fqGpK+mIZbA3qSTeYqg3pqpROBdIPvOG3F5ereDHNwoHBI2e50n1BDr1g=="], + "@rollup/pluginutils": ["@rollup/pluginutils@4.2.1", "", { "dependencies": { "estree-walker": "2.0.2", "picomatch": "2.3.1" } }, "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ=="], "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.49.0", "", { "os": "android", "cpu": "arm" }, "sha512-rlKIeL854Ed0e09QGYFlmDNbka6I3EQFw7iZuugQjMb11KMpJCLPFL4ZPbMfaEhLADEL1yx0oujGkBQ7+qW3eA=="], @@ -409,14 +451,14 @@ "@sveltejs/acorn-typescript": ["@sveltejs/acorn-typescript@1.0.5", "", { "peerDependencies": { "acorn": "8.15.0" } }, "sha512-IwQk4yfwLdibDlrXVE04jTZYlLnwsTT2PIOQQGNLWfjavGifnk1JD1LcZjZaBTRcxZu2FfPfNLOE04DSu9lqtQ=="], - "@sveltejs/vite-plugin-svelte": ["@sveltejs/vite-plugin-svelte@5.1.1", "", { "dependencies": { "@sveltejs/vite-plugin-svelte-inspector": "4.0.1", "debug": "4.4.1", "deepmerge": "4.3.1", "kleur": "4.1.5", "magic-string": "0.30.18", "vitefu": "1.1.1" }, "peerDependencies": { "svelte": "5.38.6", "vite": "6.3.5" } }, "sha512-Y1Cs7hhTc+a5E9Va/xwKlAJoariQyHY+5zBgCZg4PFWNYQ1nMN9sjK1zhw1gK69DuqVP++sht/1GZg1aRwmAXQ=="], - - "@sveltejs/vite-plugin-svelte-inspector": ["@sveltejs/vite-plugin-svelte-inspector@4.0.1", "", { "dependencies": { "debug": "4.4.1" }, "peerDependencies": { "@sveltejs/vite-plugin-svelte": "5.1.1", "svelte": "5.38.6", "vite": "6.3.5" } }, "sha512-J/Nmb2Q2y7mck2hyCX4ckVHcR5tu2J+MtBEQqpDrrgELZ2uvraQcK/ioCV61AqkdXFgriksOKIceDcQmqnGhVw=="], + "@sveltejs/vite-plugin-svelte": ["@sveltejs/vite-plugin-svelte@7.0.0", "", { "dependencies": { "deepmerge": "^4.3.1", "magic-string": "^0.30.21", "obug": "^2.1.0", "vitefu": "^1.1.2" }, "peerDependencies": { "svelte": "^5.46.4", "vite": "^8.0.0-beta.7 || ^8.0.0" } }, "sha512-ILXmxC7HAsnkK2eslgPetrqqW1BKSL7LktsFgqzNj83MaivMGZzluWq32m25j2mDOjmSKX7GGWahePhuEs7P/g=="], "@tailwindcss/forms": ["@tailwindcss/forms@0.5.10", "", { "dependencies": { "mini-svg-data-uri": "1.4.4" }, "peerDependencies": { "tailwindcss": "3.4.17" } }, "sha512-utI1ONF6uf/pPNO68kmN1b8rEwNXv3czukalo8VtJH8ksIkZXr3Q3VYudZLkCsDd4Wku120uF02hYK25XGPorw=="], "@tsconfig/svelte": ["@tsconfig/svelte@5.0.5", "", {}, "sha512-48fAnUjKye38FvMiNOj0J9I/4XlQQiZlpe9xaNPfe8vy2Y1hFBt8g1yqf2EGjVvHavo4jf2lC+TQyENCr4BJBQ=="], + "@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="], + "@types/argparse": ["@types/argparse@1.0.38", "", {}, "sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA=="], "@types/chai": ["@types/chai@4.3.20", "", {}, "sha512-/pC9HAB5I/xMlc5FP77qjCnI16ChlJfW0tGa0IUcFn38VJrTV6DeZ60NU5KZBtaOZqjdpwTWohz5HU1RrhiYxQ=="], @@ -527,7 +569,7 @@ "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], - "aria-query": ["aria-query@5.3.2", "", {}, "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw=="], + "aria-query": ["aria-query@5.3.1", "", {}, "sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g=="], "assertion-error": ["assertion-error@1.1.0", "", {}, "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw=="], @@ -631,7 +673,7 @@ "colors-named-hex": ["colors-named-hex@1.0.2", "", {}, "sha512-k6kq1e1pUCQvSVwIaGFq2l0LrkAPQZWyeuZn1Z8nOiYSEZiKoFj4qx690h2Kd34DFl9Me0gKS6MUwAMBJj8nuA=="], - "commander": ["commander@14.0.0", "", {}, "sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA=="], + "commander": ["commander@14.0.3", "", {}, "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw=="], "complex.js": ["complex.js@2.4.2", "", {}, "sha512-qtx7HRhPGSCBtGiST4/WGHuW+zeaND/6Ld+db6PbrulIB1i2Ev/2UPiqcmpQNPSyfBKraC0EOvOKCB5dGZKt3g=="], @@ -693,6 +735,8 @@ "detect-libc": ["detect-libc@1.0.3", "", { "bin": { "detect-libc": "./bin/detect-libc.js" } }, "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg=="], + "devalue": ["devalue@5.7.1", "", {}, "sha512-MUbZ586EgQqdRnC4yDrlod3BEdyvE4TapGYHMW2CiaW+KkkFmWEFqBUaLltEZCGi0iFXCEjRF0OjF0DV2QHjOA=="], + "didyoumean": ["didyoumean@1.2.2", "", {}, "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw=="], "diff-sequences": ["diff-sequences@29.6.3", "", {}, "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q=="], @@ -773,7 +817,7 @@ "esquery": ["esquery@1.6.0", "", { "dependencies": { "estraverse": "5.3.0" } }, "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg=="], - "esrap": ["esrap@2.1.0", "", { "dependencies": { "@jridgewell/sourcemap-codec": "1.5.5" } }, "sha512-yzmPNpl7TBbMRC5Lj2JlJZNPml0tzqoqP5B1JXycNUwtqma9AKCO0M2wHrdgsHcy1WRW7S9rJknAMtByg3usgA=="], + "esrap": ["esrap@2.2.5", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" }, "peerDependencies": { "@typescript-eslint/types": "^8.2.0" }, "optionalPeers": ["@typescript-eslint/types"] }, "sha512-/yLB1538mag+dn0wsePTe8C0rDIjUOaJpMs2McodSzmM2msWcZsBSdRtg6HOBt0A/r82BN+Md3pgwSc/uWt2Ig=="], "esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "5.3.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="], @@ -787,7 +831,7 @@ "events": ["events@3.3.0", "", {}, "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q=="], - "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.1", "human-signals": "8.0.1", "is-plain-obj": "4.1.0", "is-stream": "4.0.1", "npm-run-path": "6.0.0", "pretty-ms": "9.2.0", "signal-exit": "4.1.0", "strip-final-newline": "4.0.0", "yoctocolors": "2.1.2" } }, "sha512-jpWzZ1ZhwUmeWRhS7Qv3mhpOhLfwI+uAX4e5fOcXqwMR7EcJ0pj2kV1CVzHVMX/LphnKWD3LObjZCoJ71lKpHw=="], + "execa": ["execa@9.6.1", "", { "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-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA=="], "expand-template": ["expand-template@2.0.3", "", {}, "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg=="], @@ -995,6 +1039,30 @@ "lie": ["lie@3.1.1", "", { "dependencies": { "immediate": "3.0.6" } }, "sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw=="], + "lightningcss": ["lightningcss@1.32.0", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "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" } }, "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ=="], + + "lightningcss-android-arm64": ["lightningcss-android-arm64@1.32.0", "", { "os": "android", "cpu": "arm64" }, "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg=="], + + "lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.32.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ=="], + + "lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.32.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w=="], + + "lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.32.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig=="], + + "lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.32.0", "", { "os": "linux", "cpu": "arm" }, "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw=="], + + "lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.32.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ=="], + + "lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.32.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg=="], + + "lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.32.0", "", { "os": "linux", "cpu": "x64" }, "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA=="], + + "lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.32.0", "", { "os": "linux", "cpu": "x64" }, "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg=="], + + "lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.32.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw=="], + + "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.32.0", "", { "os": "win32", "cpu": "x64" }, "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q=="], + "lilconfig": ["lilconfig@3.1.3", "", {}, "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw=="], "lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="], @@ -1125,6 +1193,8 @@ "node-fetch-native": ["node-fetch-native@1.6.7", "", {}, "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q=="], + "node-html-parser": ["node-html-parser@7.1.0", "", { "dependencies": { "css-select": "^5.1.0", "he": "1.2.0" } }, "sha512-iJo8b2uYGT40Y8BTyy5ufL6IVbN8rbm/1QK2xffXU/1a/v3AAa0d1YAoqBNYqaS4R/HajkWIpIfdE6KcyFh1AQ=="], + "node-releases": ["node-releases@2.0.19", "", {}, "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw=="], "normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="], @@ -1143,6 +1213,8 @@ "object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="], + "obug": ["obug@2.1.1", "", {}, "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ=="], + "ofetch": ["ofetch@1.5.1", "", { "dependencies": { "destr": "^2.0.5", "node-fetch-native": "^1.6.7", "ufo": "^1.6.1" } }, "sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA=="], "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1.0.2" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="], @@ -1293,6 +1365,8 @@ "rfdc": ["rfdc@1.4.1", "", {}, "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="], + "rolldown": ["rolldown@1.0.0-rc.15", "", { "dependencies": { "@oxc-project/types": "=0.124.0", "@rolldown/pluginutils": "1.0.0-rc.15" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.0-rc.15", "@rolldown/binding-darwin-arm64": "1.0.0-rc.15", "@rolldown/binding-darwin-x64": "1.0.0-rc.15", "@rolldown/binding-freebsd-x64": "1.0.0-rc.15", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.15", "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.15", "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.15", "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.15", "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.15", "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.15", "@rolldown/binding-linux-x64-musl": "1.0.0-rc.15", "@rolldown/binding-openharmony-arm64": "1.0.0-rc.15", "@rolldown/binding-wasm32-wasi": "1.0.0-rc.15", "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.15", "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.15" }, "bin": { "rolldown": "bin/cli.mjs" } }, "sha512-Ff31guA5zT6WjnGp0SXw76X6hzGRk/OQq2hE+1lcDe+lJdHSgnSX6nK3erbONHyCbpSj9a9E+uX/OvytZoWp2g=="], + "rollup": ["rollup@2.79.2", "", { "optionalDependencies": { "fsevents": "2.3.3" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ=="], "rss-parser": ["rss-parser@3.13.0", "", { "dependencies": { "entities": "2.2.0", "xml2js": "0.5.0" } }, "sha512-7jWUBV5yGN3rqMMj7CZufl/291QAhvrrGpDNE4k/02ZchL0npisiYYqULF71jCEKoIiHvK/Q2e6IkDwPziT7+w=="], @@ -1397,7 +1471,7 @@ "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="], - "svelte": ["svelte@5.38.6", "", { "dependencies": { "@jridgewell/remapping": "2.3.5", "@jridgewell/sourcemap-codec": "1.5.5", "@sveltejs/acorn-typescript": "1.0.5", "@types/estree": "1.0.8", "acorn": "8.15.0", "aria-query": "5.3.2", "axobject-query": "4.1.0", "clsx": "2.1.1", "esm-env": "1.2.2", "esrap": "2.1.0", "is-reference": "3.0.3", "locate-character": "3.0.0", "magic-string": "0.30.18", "zimmerframe": "1.1.2" } }, "sha512-ltBPlkvqk3bgCK7/N323atUpP3O3Y+DrGV4dcULrsSn4fZaaNnOmdplNznwfdWclAgvSr5rxjtzn/zJhRm6TKg=="], + "svelte": ["svelte@5.55.4", "", { "dependencies": { "@jridgewell/remapping": "^2.3.4", "@jridgewell/sourcemap-codec": "^1.5.0", "@sveltejs/acorn-typescript": "^1.0.5", "@types/estree": "^1.0.5", "@types/trusted-types": "^2.0.7", "acorn": "^8.12.1", "aria-query": "5.3.1", "axobject-query": "^4.1.0", "clsx": "^2.1.1", "devalue": "^5.6.4", "esm-env": "^1.2.1", "esrap": "^2.2.4", "is-reference": "^3.0.3", "locate-character": "^3.0.0", "magic-string": "^0.30.11", "zimmerframe": "^1.1.2" } }, "sha512-q8DFohk6vUswSng95IZb9nzWJnbINZsK7OiM1snAa3qCjJBL0ZQpvMyAaVXjUukdM75J/m8UE8xwqat8Ors/zQ=="], "symbol-observable": ["symbol-observable@1.2.0", "", {}, "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ=="], @@ -1423,7 +1497,7 @@ "tinycolor2": ["tinycolor2@1.4.2", "", {}, "sha512-vJhccZPs965sV/L2sU4oRQVAos0pQXwsvTLkWYdqJ+a8Q5kPFzJTuOFwy7UniPli44NKQGAglksjvOcpo95aZA=="], - "tinyglobby": ["tinyglobby@0.2.14", "", { "dependencies": { "fdir": "6.5.0", "picomatch": "4.0.3" } }, "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ=="], + "tinyglobby": ["tinyglobby@0.2.16", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg=="], "tinypool": ["tinypool@0.7.0", "", {}, "sha512-zSYNUlYSMhJ6Zdou4cJwo/p7w5nmAH17GRfU/ui3ctvjXFErXXkruT4MWW6poDeXgCaIBlGLrfU6TbTXxyGMww=="], @@ -1477,7 +1551,7 @@ "validator": ["validator@13.15.15", "", {}, "sha512-BgWVbCI72aIQy937xbawcs+hrVaN/CZ2UwutgaJ36hGqRrLNM+f5LUT/YPRbo8IV/ASeFzXszezV+y2+rq3l8A=="], - "vite": ["vite@6.3.5", "", { "dependencies": { "esbuild": "0.25.9", "fdir": "6.5.0", "picomatch": "4.0.3", "postcss": "8.5.6", "rollup": "4.49.0", "tinyglobby": "0.2.14" }, "optionalDependencies": { "@types/node": "24.3.0", "fsevents": "2.3.3", "jiti": "1.21.7", "sass": "1.91.0", "yaml": "2.8.1" }, "bin": { "vite": "bin/vite.js" } }, "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ=="], + "vite": ["vite@8.0.8", "", { "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", "postcss": "^8.5.8", "rolldown": "1.0.0-rc.15", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.1.0", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-dbU7/iLVa8KZALJyLOBOQ88nOXtNG8vxKuOT4I2mD+Ya70KPceF4IAmDsmU0h1Qsn5bPrvsY9HJstCRh3hG6Uw=="], "vite-node": ["vite-node@0.34.6", "", { "dependencies": { "cac": "6.7.14", "debug": "4.4.1", "mlly": "1.8.0", "pathe": "1.1.2", "picocolors": "1.1.1", "vite": "5.4.19" }, "bin": { "vite-node": "vite-node.mjs" } }, "sha512-nlBMJ9x6n7/Amaz6F3zJ97EBwR2FkzhBRxF5e+jE6LA3yi6Wtc2lyTij1OnDMIr34v5g/tVQtsVAzhT0jc5ygA=="], @@ -1485,7 +1559,7 @@ "vite-plugin-externalize-deps": ["vite-plugin-externalize-deps@0.7.0", "", { "peerDependencies": { "vite": "6.3.5" } }, "sha512-do2gPrR79Tm8UKcqsw3RTAtN4YO8GkVRBckWdJWINZ3Qdp3KN9S1oyUZxKszTB/iyg4zdOUweLOeBI8t86QVow=="], - "vitefu": ["vitefu@1.1.1", "", { "optionalDependencies": { "vite": "6.3.5" } }, "sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ=="], + "vitefu": ["vitefu@1.1.3", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" }, "optionalPeers": ["vite"] }, "sha512-ub4okH7Z5KLjb6hDyjqrGXqWtWvoYdU3IGm/NorpgHncKoLTCfRIbvlhBm7r0YstIaQRYlp4yEbFqDcKSzXSSg=="], "vitest": ["vitest@0.34.6", "", { "dependencies": { "@types/chai": "4.3.20", "@types/chai-subset": "1.3.6", "@types/node": "24.3.0", "@vitest/expect": "0.34.6", "@vitest/runner": "0.34.6", "@vitest/snapshot": "0.34.6", "@vitest/spy": "0.34.6", "@vitest/utils": "0.34.6", "acorn": "8.15.0", "acorn-walk": "8.3.4", "cac": "6.7.14", "chai": "4.5.0", "debug": "4.4.1", "local-pkg": "0.4.3", "magic-string": "0.30.18", "pathe": "1.1.2", "picocolors": "1.1.1", "std-env": "3.9.0", "strip-literal": "1.3.0", "tinybench": "2.9.0", "tinypool": "0.7.0", "vite": "5.4.19", "vite-node": "0.34.6", "why-is-node-running": "2.3.0" }, "bin": { "vitest": "vitest.mjs" } }, "sha512-+5CALsOvbNKnS+ZHMXtuUC7nL8/7F1F2DnHGjSsszX8zCjWSSviphCb/NuS9Nzf4Q03KyyDRBAXhF/8lffME4Q=="], @@ -1555,7 +1629,9 @@ "@babel/plugin-transform-runtime/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], - "@bedframe/core/@crxjs/vite-plugin": ["@crxjs/vite-plugin@2.0.2", "", { "dependencies": { "@rollup/pluginutils": "4.2.1", "@webcomponents/custom-elements": "1.6.0", "acorn-walk": "8.3.4", "cheerio": "1.1.2", "convert-source-map": "1.9.0", "debug": "4.4.1", "es-module-lexer": "0.10.5", "fast-glob": "3.3.3", "fs-extra": "10.1.0", "jsesc": "3.1.0", "magic-string": "0.30.18", "pathe": "2.0.3", "picocolors": "1.1.1", "react-refresh": "0.13.0", "rollup": "2.79.2", "rxjs": "7.5.7" } }, "sha512-BeaVEkCTmna2tzl5DL9nw1kxll1IpIFZ+wbl2+iILz4fNJy1xRD6c1nF8w8/CvrWUuPYTFTpyX9K+A30ISDXHA=="], + "@bedframe/cli/vite": ["vite@6.4.2", "", { "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": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-2N/55r4JDJ4gdrCvGgINMy+HH3iRpNIz8K6SFwVsA+JbQScLiC+clmAxBgwiSPgcG9U15QmvqCGWzMbqda5zGQ=="], + + "@bedframe/core/@crxjs/vite-plugin": ["@crxjs/vite-plugin@2.3.0", "", { "dependencies": { "@rollup/pluginutils": "^4.1.2", "@webcomponents/custom-elements": "^1.5.0", "acorn-walk": "^8.2.0", "cheerio": "^1.0.0-rc.10", "convert-source-map": "^1.7.0", "debug": "^4.3.3", "es-module-lexer": "^0.10.0", "fast-glob": "^3.2.11", "fs-extra": "^10.0.1", "jsesc": "^3.0.2", "magic-string": "^0.30.12", "pathe": "^2.0.1", "picocolors": "^1.1.1", "react-refresh": "^0.13.0", "rollup": "2.79.2", "rxjs": "7.5.7" } }, "sha512-+0CNVGS4bB30OoaF1vUsHVwWU1Lm7MxI0XWY9Fd/Ob+ZVTZgEFNqJ1ZC69IVwQsoYhY0sMQLvpLWiFIuDz8htg=="], "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], @@ -1591,6 +1667,8 @@ "@samverschueren/stream-to-observable/rxjs": ["rxjs@6.6.7", "", { "dependencies": { "tslib": "1.14.1" } }, "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ=="], + "@sveltejs/vite-plugin-svelte/magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], + "@vitest/runner/pathe": ["pathe@1.1.2", "", {}, "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ=="], "@vitest/snapshot/pathe": ["pathe@1.1.2", "", {}, "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ=="], @@ -1621,6 +1699,8 @@ "concurrently/yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "8.0.1", "escalade": "3.2.0", "get-caller-file": "2.0.5", "require-directory": "2.1.1", "string-width": "4.2.3", "y18n": "5.0.8", "yargs-parser": "21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="], + "dependency-cruiser/commander": ["commander@14.0.0", "", {}, "sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA=="], + "dom-serializer/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], "eslint/ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "3.1.3", "fast-json-stable-stringify": "2.1.0", "json-schema-traverse": "0.4.1", "uri-js": "4.4.1" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="], @@ -1633,6 +1713,8 @@ "htmlparser2/entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="], + "lightningcss/detect-libc": ["detect-libc@2.0.4", "", {}, "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA=="], + "listr/is-stream": ["is-stream@1.1.0", "", {}, "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ=="], "listr/rxjs": ["rxjs@6.6.7", "", { "dependencies": { "tslib": "1.14.1" } }, "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ=="], @@ -1715,9 +1797,13 @@ "tailwindcss/chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "3.1.3", "braces": "3.0.3", "glob-parent": "5.1.2", "is-binary-path": "2.1.0", "is-glob": "4.0.3", "normalize-path": "3.0.0", "readdirp": "3.6.0" }, "optionalDependencies": { "fsevents": "2.3.3" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="], + "tinyglobby/picomatch": ["picomatch@4.0.4", "", {}, "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A=="], + "uri-js/punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], - "vite/rollup": ["rollup@4.49.0", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.49.0", "@rollup/rollup-android-arm64": "4.49.0", "@rollup/rollup-darwin-arm64": "4.49.0", "@rollup/rollup-darwin-x64": "4.49.0", "@rollup/rollup-freebsd-arm64": "4.49.0", "@rollup/rollup-freebsd-x64": "4.49.0", "@rollup/rollup-linux-arm-gnueabihf": "4.49.0", "@rollup/rollup-linux-arm-musleabihf": "4.49.0", "@rollup/rollup-linux-arm64-gnu": "4.49.0", "@rollup/rollup-linux-arm64-musl": "4.49.0", "@rollup/rollup-linux-loongarch64-gnu": "4.49.0", "@rollup/rollup-linux-ppc64-gnu": "4.49.0", "@rollup/rollup-linux-riscv64-gnu": "4.49.0", "@rollup/rollup-linux-riscv64-musl": "4.49.0", "@rollup/rollup-linux-s390x-gnu": "4.49.0", "@rollup/rollup-linux-x64-gnu": "4.49.0", "@rollup/rollup-linux-x64-musl": "4.49.0", "@rollup/rollup-win32-arm64-msvc": "4.49.0", "@rollup/rollup-win32-ia32-msvc": "4.49.0", "@rollup/rollup-win32-x64-msvc": "4.49.0", "fsevents": "2.3.3" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-3IVq0cGJ6H7fKXXEdVt+RcYvRCt8beYY9K1760wGQwSAHZcS9eot1zDG5axUbcp/kWRi5zKIIDX8MoKv/TzvZA=="], + "vite/picomatch": ["picomatch@4.0.4", "", {}, "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A=="], + + "vite/postcss": ["postcss@8.5.10", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ=="], "vite-node/pathe": ["pathe@1.1.2", "", {}, "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ=="], @@ -1725,6 +1811,8 @@ "vite-plugin-dts/@rollup/pluginutils": ["@rollup/pluginutils@5.2.0", "", { "dependencies": { "@types/estree": "1.0.8", "estree-walker": "2.0.2", "picomatch": "4.0.3" }, "optionalDependencies": { "rollup": "4.49.0" } }, "sha512-qWJ2ZTbmumwiLFomfzTyt5Kng4hwPi9rwCYN4SHb6eaRU1KNO4ccxINHr/VhH4GgPlt1XfSTLX2LBTme8ne4Zw=="], + "vite-plugin-dts/vite": ["vite@6.3.5", "", { "dependencies": { "esbuild": "0.25.9", "fdir": "6.5.0", "picomatch": "4.0.3", "postcss": "8.5.6", "rollup": "4.49.0", "tinyglobby": "0.2.14" }, "optionalDependencies": { "@types/node": "24.3.0", "fsevents": "2.3.3", "jiti": "1.21.7", "sass": "1.91.0", "yaml": "2.8.1" }, "bin": { "vite": "bin/vite.js" } }, "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ=="], + "vitest/pathe": ["pathe@1.1.2", "", {}, "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ=="], "vitest/vite": ["vite@5.4.19", "", { "dependencies": { "esbuild": "0.21.5", "postcss": "8.5.6", "rollup": "4.49.0" }, "optionalDependencies": { "@types/node": "24.3.0", "fsevents": "2.3.3", "sass": "1.91.0" }, "bin": { "vite": "bin/vite.js" } }, "sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA=="], @@ -1741,6 +1829,14 @@ "z-schema/commander": ["commander@9.5.0", "", {}, "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ=="], + "@bedframe/cli/vite/picomatch": ["picomatch@4.0.4", "", {}, "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A=="], + + "@bedframe/cli/vite/postcss": ["postcss@8.5.10", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ=="], + + "@bedframe/cli/vite/rollup": ["rollup@4.49.0", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.49.0", "@rollup/rollup-android-arm64": "4.49.0", "@rollup/rollup-darwin-arm64": "4.49.0", "@rollup/rollup-darwin-x64": "4.49.0", "@rollup/rollup-freebsd-arm64": "4.49.0", "@rollup/rollup-freebsd-x64": "4.49.0", "@rollup/rollup-linux-arm-gnueabihf": "4.49.0", "@rollup/rollup-linux-arm-musleabihf": "4.49.0", "@rollup/rollup-linux-arm64-gnu": "4.49.0", "@rollup/rollup-linux-arm64-musl": "4.49.0", "@rollup/rollup-linux-loongarch64-gnu": "4.49.0", "@rollup/rollup-linux-ppc64-gnu": "4.49.0", "@rollup/rollup-linux-riscv64-gnu": "4.49.0", "@rollup/rollup-linux-riscv64-musl": "4.49.0", "@rollup/rollup-linux-s390x-gnu": "4.49.0", "@rollup/rollup-linux-x64-gnu": "4.49.0", "@rollup/rollup-linux-x64-musl": "4.49.0", "@rollup/rollup-win32-arm64-msvc": "4.49.0", "@rollup/rollup-win32-ia32-msvc": "4.49.0", "@rollup/rollup-win32-x64-msvc": "4.49.0", "fsevents": "2.3.3" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-3IVq0cGJ6H7fKXXEdVt+RcYvRCt8beYY9K1760wGQwSAHZcS9eot1zDG5axUbcp/kWRi5zKIIDX8MoKv/TzvZA=="], + + "@bedframe/core/@crxjs/vite-plugin/magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], + "@eslint/eslintrc/ajv/json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], "@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], @@ -1865,6 +1961,10 @@ "vite-plugin-dts/@rollup/pluginutils/rollup": ["rollup@4.49.0", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.49.0", "@rollup/rollup-android-arm64": "4.49.0", "@rollup/rollup-darwin-arm64": "4.49.0", "@rollup/rollup-darwin-x64": "4.49.0", "@rollup/rollup-freebsd-arm64": "4.49.0", "@rollup/rollup-freebsd-x64": "4.49.0", "@rollup/rollup-linux-arm-gnueabihf": "4.49.0", "@rollup/rollup-linux-arm-musleabihf": "4.49.0", "@rollup/rollup-linux-arm64-gnu": "4.49.0", "@rollup/rollup-linux-arm64-musl": "4.49.0", "@rollup/rollup-linux-loongarch64-gnu": "4.49.0", "@rollup/rollup-linux-ppc64-gnu": "4.49.0", "@rollup/rollup-linux-riscv64-gnu": "4.49.0", "@rollup/rollup-linux-riscv64-musl": "4.49.0", "@rollup/rollup-linux-s390x-gnu": "4.49.0", "@rollup/rollup-linux-x64-gnu": "4.49.0", "@rollup/rollup-linux-x64-musl": "4.49.0", "@rollup/rollup-win32-arm64-msvc": "4.49.0", "@rollup/rollup-win32-ia32-msvc": "4.49.0", "@rollup/rollup-win32-x64-msvc": "4.49.0", "fsevents": "2.3.3" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-3IVq0cGJ6H7fKXXEdVt+RcYvRCt8beYY9K1760wGQwSAHZcS9eot1zDG5axUbcp/kWRi5zKIIDX8MoKv/TzvZA=="], + "vite-plugin-dts/vite/rollup": ["rollup@4.49.0", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.49.0", "@rollup/rollup-android-arm64": "4.49.0", "@rollup/rollup-darwin-arm64": "4.49.0", "@rollup/rollup-darwin-x64": "4.49.0", "@rollup/rollup-freebsd-arm64": "4.49.0", "@rollup/rollup-freebsd-x64": "4.49.0", "@rollup/rollup-linux-arm-gnueabihf": "4.49.0", "@rollup/rollup-linux-arm-musleabihf": "4.49.0", "@rollup/rollup-linux-arm64-gnu": "4.49.0", "@rollup/rollup-linux-arm64-musl": "4.49.0", "@rollup/rollup-linux-loongarch64-gnu": "4.49.0", "@rollup/rollup-linux-ppc64-gnu": "4.49.0", "@rollup/rollup-linux-riscv64-gnu": "4.49.0", "@rollup/rollup-linux-riscv64-musl": "4.49.0", "@rollup/rollup-linux-s390x-gnu": "4.49.0", "@rollup/rollup-linux-x64-gnu": "4.49.0", "@rollup/rollup-linux-x64-musl": "4.49.0", "@rollup/rollup-win32-arm64-msvc": "4.49.0", "@rollup/rollup-win32-ia32-msvc": "4.49.0", "@rollup/rollup-win32-x64-msvc": "4.49.0", "fsevents": "2.3.3" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-3IVq0cGJ6H7fKXXEdVt+RcYvRCt8beYY9K1760wGQwSAHZcS9eot1zDG5axUbcp/kWRi5zKIIDX8MoKv/TzvZA=="], + + "vite-plugin-dts/vite/tinyglobby": ["tinyglobby@0.2.14", "", { "dependencies": { "fdir": "6.5.0", "picomatch": "4.0.3" } }, "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ=="], + "vitest/vite/esbuild": ["esbuild@0.21.5", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.21.5", "@esbuild/android-arm": "0.21.5", "@esbuild/android-arm64": "0.21.5", "@esbuild/android-x64": "0.21.5", "@esbuild/darwin-arm64": "0.21.5", "@esbuild/darwin-x64": "0.21.5", "@esbuild/freebsd-arm64": "0.21.5", "@esbuild/freebsd-x64": "0.21.5", "@esbuild/linux-arm": "0.21.5", "@esbuild/linux-arm64": "0.21.5", "@esbuild/linux-ia32": "0.21.5", "@esbuild/linux-loong64": "0.21.5", "@esbuild/linux-mips64el": "0.21.5", "@esbuild/linux-ppc64": "0.21.5", "@esbuild/linux-riscv64": "0.21.5", "@esbuild/linux-s390x": "0.21.5", "@esbuild/linux-x64": "0.21.5", "@esbuild/netbsd-x64": "0.21.5", "@esbuild/openbsd-x64": "0.21.5", "@esbuild/sunos-x64": "0.21.5", "@esbuild/win32-arm64": "0.21.5", "@esbuild/win32-ia32": "0.21.5", "@esbuild/win32-x64": "0.21.5" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw=="], "vitest/vite/rollup": ["rollup@4.49.0", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.49.0", "@rollup/rollup-android-arm64": "4.49.0", "@rollup/rollup-darwin-arm64": "4.49.0", "@rollup/rollup-darwin-x64": "4.49.0", "@rollup/rollup-freebsd-arm64": "4.49.0", "@rollup/rollup-freebsd-x64": "4.49.0", "@rollup/rollup-linux-arm-gnueabihf": "4.49.0", "@rollup/rollup-linux-arm-musleabihf": "4.49.0", "@rollup/rollup-linux-arm64-gnu": "4.49.0", "@rollup/rollup-linux-arm64-musl": "4.49.0", "@rollup/rollup-linux-loongarch64-gnu": "4.49.0", "@rollup/rollup-linux-ppc64-gnu": "4.49.0", "@rollup/rollup-linux-riscv64-gnu": "4.49.0", "@rollup/rollup-linux-riscv64-musl": "4.49.0", "@rollup/rollup-linux-s390x-gnu": "4.49.0", "@rollup/rollup-linux-x64-gnu": "4.49.0", "@rollup/rollup-linux-x64-musl": "4.49.0", "@rollup/rollup-win32-arm64-msvc": "4.49.0", "@rollup/rollup-win32-ia32-msvc": "4.49.0", "@rollup/rollup-win32-x64-msvc": "4.49.0", "fsevents": "2.3.3" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-3IVq0cGJ6H7fKXXEdVt+RcYvRCt8beYY9K1760wGQwSAHZcS9eot1zDG5axUbcp/kWRi5zKIIDX8MoKv/TzvZA=="], diff --git a/src/plugins/built-in/assessmentsAverage/index.ts b/src/plugins/built-in/assessmentsAverage/index.ts index ed7140f1..b3438ea6 100644 --- a/src/plugins/built-in/assessmentsAverage/index.ts +++ b/src/plugins/built-in/assessmentsAverage/index.ts @@ -7,11 +7,11 @@ import { import { type Plugin } from "@/plugins/core/types"; import stringToHTML from "@/seqta/utils/stringToHTML"; import { waitForElm } from "@/seqta/utils/waitForElm"; -import ReactFiber from "@/seqta/utils/ReactFiber.ts"; import { clearStuck, getClassByPattern, initStorage, + injectWeightingsTab, letterToNumber, parseAssessments, processAssessments, @@ -20,6 +20,7 @@ import { interface weightingsStorage { weightings: Record; assessments: Record; + weightingOverrides: Record; } const settings = defineSettings({ @@ -37,6 +38,8 @@ class AssessmentsAveragePluginClass extends BasePlugin { const instance = new AssessmentsAveragePluginClass(); +let overrideListenerController: AbortController | null = null; + const assessmentsAveragePlugin: Plugin = { id: "assessments-average", name: "Assessment Averages", @@ -58,143 +61,149 @@ const assessmentsAveragePlugin: Plugin = { ); await parseAssessments(api); - - const sampleAssessmentItem = document.querySelector( - "[class*='AssessmentItem__AssessmentItem___']", + await renderSubjectAverage(api); + overrideListenerController?.abort(); + overrideListenerController = new AbortController(); + document.addEventListener( + "betterseqta:overrideChanged", + () => renderSubjectAverage(api), + { signal: overrideListenerController.signal }, ); - if (!sampleAssessmentItem) return; - - const assessmentItemClass = - Array.from(sampleAssessmentItem.classList).find((c) => - c.startsWith("AssessmentItem__AssessmentItem___"), - ) || ""; - - const metaContainerClass = getClassByPattern( - sampleAssessmentItem, - "AssessmentItem__metaContainer___", - ); - const metaClass = getClassByPattern( - sampleAssessmentItem, - "AssessmentItem__meta___", - ); - const simpleResultClass = getClassByPattern( - sampleAssessmentItem, - "AssessmentItem__simpleResult___", - ); - const titleClass = getClassByPattern( - sampleAssessmentItem, - "AssessmentItem__title___", - ); - - const thermoscoreElement = document.querySelector( - "[class*='Thermoscore__Thermoscore___']", - ); - if (!thermoscoreElement) return; - - const thermoscoreClass = - Array.from(thermoscoreElement.classList).find((c) => - c.startsWith("Thermoscore__Thermoscore___"), - ) || ""; - const fillClass = getClassByPattern( - thermoscoreElement, - "Thermoscore__fill___", - ); - const textClass = getClassByPattern( - thermoscoreElement, - "Thermoscore__text___", - ); - - const assessmentsList = document.querySelector( - "#main > .assessmentsWrapper .assessments [class*='AssessmentList__items___']", - ); - if (!assessmentsList) return; - - const state = await ReactFiber.find( - "[class*='AssessmentList__items___']", - ).getState(); - const marks = state["marks"]; - if (!marks || !marks.length) return; - - const assessmentItems = Array.from( - assessmentsList.querySelectorAll( - `[class*='AssessmentItem__AssessmentItem___']`, - ), - ).filter( - (item) => - !item - .querySelector(`[class*='AssessmentItem__title___']`) - ?.textContent?.includes("Subject Average"), - ); - - const { weightedTotal, totalWeight, hasInaccurateWeighting, count } = - await processAssessments(api, assessmentItems); - - if (!count || totalWeight === 0) return; - - const avg = weightedTotal / totalWeight; - const rounded = Math.ceil(avg / 5) * 5; - const numberToLetter = Object.entries(letterToNumber).reduce( - (acc, [k, v]) => { - acc[v] = k; - return acc; - }, - {} as Record, - ); - - const letterAvg = numberToLetter[rounded] ?? "N/A"; - const display = api.settings.lettergrade - ? letterAvg - : `${avg.toFixed(2)}%`; - - const existing = assessmentsList.querySelector( - `[class*='AssessmentItem__title___']`, - ); - if (existing?.textContent === "Subject Average") return; - - let warningHTML = ""; - if (hasInaccurateWeighting) { - warningHTML = /* html */ ` -
- ⚠ Some weightings unavailable -
- `; - } - - assessmentsList.insertBefore( - stringToHTML(/* html */ ` -
-
-
-
-
Subject Average
- ${warningHTML} -
-
-
-
-
-
${display}
-
-
-
- `).firstChild!, - assessmentsList.firstChild, - ); - - applySubjectColourToOverallResult(); - - const observer = new MutationObserver(() => { - applySubjectColourToOverallResult(); - }); const wrapper = document.querySelector(".assessmentsWrapper"); if (wrapper) { + const observer = new MutationObserver(() => { + applySubjectColourToOverallResult(); + }); observer.observe(wrapper, { childList: true, subtree: true }); setTimeout(() => observer.disconnect(), 10000); } }); + api.seqta.onMount("[class*='SelectedAssessment__']", () => { + injectWeightingsTab(api); + }); }, }; +let renderInFlight = false; +async function renderSubjectAverage(api: any) { + if (renderInFlight) return; + renderInFlight = true; + + try { + const assessmentsList = document.querySelector( + "#main > .assessmentsWrapper .assessments [class*='AssessmentList__items___']", + ); + if (!assessmentsList) return; + + // Remove existing subject average before re-rendering + Array.from( + assessmentsList.querySelectorAll(`[class*='AssessmentItem__title___']`), + ) + .find((el) => el.textContent === "Subject Average") + ?.closest("[class*='AssessmentItem__AssessmentItem___']") + ?.remove(); + + const sampleAssessmentItem = document.querySelector( + "[class*='AssessmentItem__AssessmentItem___']", + ); + if (!sampleAssessmentItem) return; + const assessmentItemClass = + Array.from(sampleAssessmentItem.classList).find((c) => + c.startsWith("AssessmentItem__AssessmentItem___"), + ) || ""; + const metaContainerClass = getClassByPattern( + sampleAssessmentItem, + "AssessmentItem__metaContainer___", + ); + const metaClass = getClassByPattern( + sampleAssessmentItem, + "AssessmentItem__meta___", + ); + const simpleResultClass = getClassByPattern( + sampleAssessmentItem, + "AssessmentItem__simpleResult___", + ); + const titleClass = getClassByPattern( + sampleAssessmentItem, + "AssessmentItem__title___", + ); + + const assessmentItems = Array.from( + assessmentsList.querySelectorAll( + `[class*='AssessmentItem__AssessmentItem___']`, + ), + ).filter( + (item) => + !item + .querySelector(`[class*='AssessmentItem__title___']`) + ?.textContent?.includes("Subject Average"), + ); + + const { weightedTotal, totalWeight, hasInaccurateWeighting, count } = + await processAssessments(api, assessmentItems); + if (!count || totalWeight === 0) return; + + const thermoscoreElement = document.querySelector( + "[class*='Thermoscore__Thermoscore___']", + ); + if (!thermoscoreElement) return; + const thermoscoreClass = + Array.from(thermoscoreElement.classList).find((c) => + c.startsWith("Thermoscore__Thermoscore___"), + ) || ""; + const fillClass = getClassByPattern( + thermoscoreElement, + "Thermoscore__fill___", + ); + const textClass = getClassByPattern( + thermoscoreElement, + "Thermoscore__text___", + ); + + const avg = weightedTotal / totalWeight; + const rounded = Math.ceil(avg / 5) * 5; + const numberToLetter = Object.entries(letterToNumber).reduce( + (acc, [k, v]) => { + acc[v] = k; + return acc; + }, + {} as Record, + ); + const letterAvg = numberToLetter[rounded] ?? "N/A"; + const display = api.settings.lettergrade ? letterAvg : `${avg.toFixed(2)}%`; + let warningHTML = ""; + if (hasInaccurateWeighting) { + warningHTML = /* html */ ` +
+ ⚠ Some weightings unavailable +
+ `; + } + assessmentsList.insertBefore( + stringToHTML(/* html */ ` +
+
+
+
+
Subject Average
+ ${warningHTML} +
+
+
+
+
+
${display}
+
+
+
+ `).firstChild!, + assessmentsList.firstChild, + ); + applySubjectColourToOverallResult(); + } finally { + renderInFlight = false; + } +} function applySubjectColourToOverallResult() { const selectedAssessmentItem = document.querySelector( "[class*='AssessmentItem__AssessmentItem___'][class*='selected___']", diff --git a/src/plugins/built-in/assessmentsAverage/utils.ts b/src/plugins/built-in/assessmentsAverage/utils.ts index d833cc98..bf7514a6 100644 --- a/src/plugins/built-in/assessmentsAverage/utils.ts +++ b/src/plugins/built-in/assessmentsAverage/utils.ts @@ -17,6 +17,9 @@ export async function initStorage(api: any) { if (!api.storage.assessments) { api.storage.assessments = {}; } + if (!api.storage.weightingOverrides) { + api.storage.weightingOverrides = {}; + } } export function clearStuck(api: any) { @@ -79,52 +82,84 @@ function createWeightLabel( assessmentItem: Element, weighting: string | undefined, ) { - const statsContainer = assessmentItem.querySelector( - `[class*='AssessmentItem__stats___']`, - ) as HTMLElement; + let statsContainer = assessmentItem.querySelector( + `[class*='AssessmentItem__stats___'], .betterseqta-stats-container`, + ) as HTMLElement | null; - if ( - !statsContainer || - statsContainer.querySelector(".betterseqta-weight-label") - ) - return; + if (!statsContainer) { + const statsClass = getClassByPattern(document, "AssessmentItem__stats___"); + statsContainer = document.createElement("div"); + statsContainer.className = statsClass; + statsContainer.classList.add("betterseqta-stats-container"); + const thermoscore = assessmentItem.querySelector(`[class*='Thermoscore__Thermoscore___']`); + if (thermoscore) { + thermoscore.insertAdjacentElement("afterend", statsContainer); + } else { + assessmentItem.appendChild(statsContainer); + } + } - const label = statsContainer.querySelector( - `[class*='Label__Label___']`, - ) as HTMLElement; - - if (!label) return; - - const weightLabel = label.cloneNode(true) as HTMLElement; - weightLabel.classList.add("betterseqta-weight-label"); - - const innerTextDiv = weightLabel.querySelector( - `[class*='Label__innerText___']`, + const hasNativeLabel = !!statsContainer.querySelector( + `[class*='Label__Label___']:not(.betterseqta-weight-label)`, ); + statsContainer.style.justifyContent = hasNativeLabel + ? "space-between" + : "flex-end"; + + const displayText = + weighting && weighting !== "processing" && weighting !== "N/A" + ? `${Number(weighting) % 1 === 0 ? Number(weighting) : weighting}%` + : "N/A"; + + const existingLabel = statsContainer.querySelector( + ".betterseqta-weight-label", + ) as HTMLElement | null; + + if (existingLabel) { + const textNodes = Array.from(existingLabel.childNodes).filter( + (node) => node.nodeType === Node.TEXT_NODE, + ); + if (textNodes.length) textNodes[0].textContent = displayText; + return; + } + + statsContainer.style.display = "flex"; + statsContainer.style.alignItems = "center"; + statsContainer.style.width = "100%"; + + // Try to clone an existing label from the stats container first, + // fall back to building from scratch if none exists + const existingNativeLabel = statsContainer.querySelector( + `[class*='Label__Label___']`, + ) as HTMLElement | null; + + const weightLabel = existingNativeLabel + ? (existingNativeLabel.cloneNode(true) as HTMLElement) + : (() => { + const labelClass = getClassByPattern(document, "Label__Label___"); + const innerTextClass = getClassByPattern(document, "Label__innerText___"); + const el = document.createElement("label"); + el.className = labelClass; + el.innerHTML = `
Weight
`; + return el; + })(); + + weightLabel.classList.add("betterseqta-weight-label"); + weightLabel.style.flex = "none"; + weightLabel.style.width = "fit-content"; + + const innerTextDiv = weightLabel.querySelector(`[class*='Label__innerText___']`); if (innerTextDiv) innerTextDiv.textContent = "Weight"; const textNodes = Array.from(weightLabel.childNodes).filter( (node) => node.nodeType === Node.TEXT_NODE, ); - if (textNodes.length) { - textNodes[0].textContent = - weighting && weighting !== "processing" - ? `${Number(weighting) % 1 === 0 ? Number(weighting) : weighting}%` - : "N/A"; + textNodes[0].textContent = displayText; + } else { + weightLabel.appendChild(document.createTextNode(displayText)); } - // Stack weight under Max/native stats — absolute right:0 overlapped the max column (#414). - statsContainer.style.display = "flex"; - statsContainer.style.flexDirection = "column"; - statsContainer.style.alignItems = "flex-end"; - statsContainer.style.gap = "2px"; - statsContainer.style.justifyContent = "center"; - - weightLabel.style.position = "relative"; - weightLabel.style.inset = "unset"; - weightLabel.style.transform = "none"; - statsContainer.appendChild(weightLabel); } @@ -228,7 +263,8 @@ async function fetchPDFAsArrayBuffer(url: string): Promise { export async function extractPDFText(url: string): Promise { try { if (isFirefox) { - const { lib: pdfLibUrl, worker: pdfWorkerUrl } = getPdfjsPageContextUrls(); + const { lib: pdfLibUrl, worker: pdfWorkerUrl } = + getPdfjsPageContextUrls(); const escJsSingleQuoted = (s: string) => s.replace(/\\/g, "\\\\").replace(/'/g, "\\'"); const pdfLibInj = escJsSingleQuoted(pdfLibUrl); @@ -519,7 +555,11 @@ export async function parseAssessments(api: any) { "[class*='AssessmentList__items___']", ).getState(); - const marks = state["marks"]; + const marks = [ + ...(state["marks"] ?? []), + ...(state["upcoming"] ?? []), + ...(state["pending"] ?? []), + ]; if (!marks) return; await Promise.all(marks.map((mark: any) => handleWeightings(mark, api))); @@ -532,15 +572,6 @@ export async function processAssessments(api: any, assessmentItems: Element[]) { let count = 0; for (const assessmentItem of assessmentItems) { - const gradeElement = assessmentItem.querySelector( - `[class*='Thermoscore__text___']`, - ); - - if (!gradeElement) continue; - - const grade = parseGrade(gradeElement.textContent || ""); - if (grade <= 0) continue; - const titleEl = assessmentItem.querySelector( `[class*='AssessmentItem__title___']`, ); @@ -550,12 +581,23 @@ export async function processAssessments(api: any, assessmentItems: Element[]) { if (!title) continue; const assessmentID = api.storage.assessments?.[title]; - const weighting = assessmentID + const autoWeighting = assessmentID ? api.storage.weightings?.[assessmentID] : undefined; + const override = assessmentID + ? api.storage.weightingOverrides?.[assessmentID] + : undefined; + const weighting = override ?? autoWeighting; createWeightLabel(assessmentItem, weighting); + const gradeElement = assessmentItem.querySelector( + `[class*='Thermoscore__text___']`, + ); + if (!gradeElement) continue; + const grade = parseGrade(gradeElement.textContent || ""); + if (grade <= 0) continue; + if ( weighting === null || weighting === undefined || @@ -563,8 +605,7 @@ export async function processAssessments(api: any, assessmentItems: Element[]) { weighting === "processing" ) { hasInaccurateWeighting = true; - weightedTotal += grade; - totalWeight += 1; + continue } else { const weight = parseFloat(weighting); @@ -587,3 +628,271 @@ export async function processAssessments(api: any, assessmentItems: Element[]) { count, }; } + +function resolveTabSetClasses(): Record { + const patterns = [ + "TabSet__tabsheet___", + "TabSet__hidden___", + "TabSet__selected___", + "TabSet__disappearToLeft___", + "TabSet__disappearToRight___", + "TabSet__appearFromRight___", + "TabSet__appearFromLeft___", + ]; + + const resolved: Record = {}; + + // First pass: scan live DOM elements (fast, covers currently-applied classes) + const allClasses = Array.from( + document.querySelectorAll('[class*="TabSet__"]'), + ).flatMap((el) => Array.from(el.classList)); + + for (const pattern of patterns) { + const found = allClasses.find((c) => c.startsWith(pattern)); + if (found) resolved[pattern] = found; + } + + // Second pass: scan stylesheets for any classes not yet in the DOM + // (e.g. animation classes that haven't been applied yet) + const missing = patterns.filter((p) => !resolved[p]); + if (missing.length > 0) { + try { + for (const sheet of Array.from(document.styleSheets)) { + if (missing.every((p) => resolved[p])) break; + try { + for (const rule of Array.from(sheet.cssRules ?? [])) { + if (!(rule instanceof CSSStyleRule)) continue; + const selectorClasses = + rule.selectorText.match(/\.([\w-]+)/g) ?? []; + for (const pattern of missing) { + if (!resolved[pattern]) { + const match = selectorClasses.find((c) => + c.slice(1).startsWith(pattern), + ); + if (match) resolved[pattern] = match.slice(1); + } + } + } + } catch { + // Cross-origin stylesheet + } + } + } catch {} + } + + // Fallback: use the base pattern as-is so the function doesn't crash, + // though styles won't apply if the hash is truly unknown. + for (const pattern of patterns) { + if (!resolved[pattern]) resolved[pattern] = pattern; + } + + return resolved; +} + +function buildWeightingsTabContent(api: any, sheet: HTMLElement) { + const titleEl = document.querySelector( + "[class*='AssessmentItem__AssessmentItem___'][class*='selected___'] [class*='AssessmentItem__title___']", + ); + const title = titleEl?.textContent?.trim(); + const assessmentID = title ? api.storage.assessments?.[title] : undefined; + + const rawWeight = assessmentID + ? api.storage.weightings?.[assessmentID] + : undefined; + + const weightingUnavailable = rawWeight === "N/A"; + + const autoWeight = + rawWeight && rawWeight !== "processing" && rawWeight !== "N/A" + ? rawWeight + : undefined; + + const override = assessmentID + ? api.storage.weightingOverrides?.[assessmentID] + : undefined; + + const statusNote = !assessmentID + ? "" + : rawWeight === "processing" + ? "Weighting is still being detected." + : weightingUnavailable + ? "No weighting was found in the marksheet. Set one manually." + : "Overrides the auto-detected value."; + + sheet.innerHTML = ` + +
+

Weighting Override

+

+ Set the weighting for this assessment. + ${statusNote} +

+
+ + ${autoWeight != null ? `${autoWeight}%` : "none"} +
+
+ + +
+
+ +
+ ${!assessmentID ? `

Assessment not yet indexed — try refreshing.

` : ""} +
+ `; + + if (!assessmentID) return; + + const input = sheet.querySelector( + "#betterseqta-weight-override", + ) as HTMLInputElement; + const statusEl = sheet.querySelector( + ".betterseqta-save-status", + ) as HTMLElement; + + const save = () => { + const raw = input.value.trim(); + if (raw === "") { + const { [assessmentID]: _, ...rest } = api.storage.weightingOverrides; + api.storage.weightingOverrides = rest; + } else { + const val = parseFloat(raw); + if (isNaN(val) || val < 0) { + input.style.borderColor = "rgba(255,80,80,0.6)"; + statusEl.textContent = "Invalid. Must be 0 or greater"; + statusEl.style.color = "rgba(255,80,80,0.8)"; + return; + } + input.style.borderColor = "rgba(128,128,128,0.3)"; + api.storage.weightingOverrides = { + ...api.storage.weightingOverrides, + [assessmentID]: String(val), + }; + } + statusEl.textContent = "Saved"; + statusEl.style.color = ""; + setTimeout(() => (statusEl.textContent = ""), 2000); + document.dispatchEvent(new CustomEvent("betterseqta:overrideChanged")); + }; + + input.addEventListener("blur", save); + input.addEventListener("keydown", (e) => { + if (e.key === "Enter") { + input.blur(); + save(); + } + }); + input.addEventListener("input", () => { + input.style.borderColor = "rgba(128,128,128,0.3)"; + if (statusEl.textContent === "Invalid. Must be 0 or greater.") + statusEl.textContent = ""; + }); +} + +export function injectWeightingsTab(api: any) { + const tabList = document.querySelector( + '[class*="TabSet__tabs___"]', + ) as HTMLElement; + const container = document.querySelector( + '[class*="TabSet__tabContainer___"]', + ) as HTMLElement; + if (!tabList || !container) return; + if (tabList.querySelector(".betterseqta-weightings-tab")) return; + + const cls = resolveTabSetClasses(); + + const prefix = (tabList.querySelector("li") as HTMLElement).id.replace( + /-tab-\d+$/, + "", + ); + const newIndex = tabList.querySelectorAll("li").length; + + const newTab = document.createElement("li"); + newTab.id = `${prefix}-tab-${newIndex}`; + newTab.className = ""; + newTab.setAttribute("aria-selected", "false"); + newTab.setAttribute("aria-controls", `${prefix}-tabsheet-${newIndex}`); + newTab.classList.add("betterseqta-weightings-tab"); + newTab.textContent = "Weightings"; + tabList.appendChild(newTab); + + const newSheet = document.createElement("div"); + newSheet.id = `${prefix}-tabsheet-${newIndex}`; + newSheet.setAttribute("aria-labelledby", `${prefix}-tab-${newIndex}`); + newSheet.className = [ + cls["TabSet__tabsheet___"], + cls["TabSet__hidden___"], + cls["TabSet__disappearToRight___"], + ].join(" "); + container.appendChild(newSheet); + + let populated = false; + newTab.addEventListener("click", () => { + if (!populated) { + buildWeightingsTabContent(api, newSheet); + populated = true; + } + }); + + const allTabs = Array.from(tabList.querySelectorAll("li")); + const allSheets = Array.from( + container.querySelectorAll('[class*="tabsheet"]'), + ); + + allTabs.forEach((tab, i) => { + tab.addEventListener("click", () => { + const currentIndex = allTabs.findIndex((t) => + t.className.includes("TabSet__selected___"), + ); + if (i === currentIndex) return; + const goingRight = i > currentIndex; + + allTabs.forEach((t) => { + t.className = ""; + t.setAttribute("aria-selected", "false"); + }); + + allSheets[currentIndex].className = [ + cls["TabSet__tabsheet___"], + cls["TabSet__hidden___"], + goingRight + ? cls["TabSet__disappearToLeft___"] + : cls["TabSet__disappearToRight___"], + ].join(" "); + + allSheets[i].className = [ + cls["TabSet__tabsheet___"], + cls["TabSet__selected___"], + goingRight + ? cls["TabSet__appearFromRight___"] + : cls["TabSet__appearFromLeft___"], + ].join(" "); + + tab.className = cls["TabSet__selected___"]; + tab.setAttribute("aria-selected", "true"); + }); + }); +} diff --git a/src/plugins/built-in/assessmentsOverview/api.ts b/src/plugins/built-in/assessmentsOverview/api.ts index 3b1d32fd..38df693c 100644 --- a/src/plugins/built-in/assessmentsOverview/api.ts +++ b/src/plugins/built-in/assessmentsOverview/api.ts @@ -28,17 +28,9 @@ async function fetchJSON(url: string, body: any) { async function loadSubjects() { const res = await fetchJSON("/seqta/student/load/subjects?", {}); - const activeGroup = res.payload.find((s: any) => s.active === 1); - const activeYear = activeGroup?.year; - const allSubjects = res.payload - .filter((s: any) => s.year === activeYear) + return res.payload + .filter((s: any) => s.active === 1) .flatMap((s: any) => s.subjects); - const seen = new Set(); - return allSubjects.filter((s: Subject) => { - if (seen.has(s.code)) return false; - seen.add(s.code); - return true; - }); } async function loadPrefs(student: number) { diff --git a/src/plugins/built-in/messageFolders/index.ts b/src/plugins/built-in/messageFolders/index.ts index e8170e86..a3e9161e 100644 --- a/src/plugins/built-in/messageFolders/index.ts +++ b/src/plugins/built-in/messageFolders/index.ts @@ -22,6 +22,7 @@ interface Folder { id: string; name: string; color: string; + emoji: string; } interface MessageFoldersStorage { @@ -34,12 +35,33 @@ const FOLDER_COLORS = [ "#8b5cf6", "#ec4899", "#14b8a6", "#f97316", ]; +const FOLDER_HEROICONS = [ + ``, + ``, + ``, + ``, + ``, + ``, + ``, + ``, + ``, + ``, + ``, + ``, + ``, + ``, + ``, + ``, +]; + const FOLDER_ICON_SVG = ``; const PLUS_SVG = ``; const CHECK_SVG_WHITE = ``; const CLOSE_SVG = ``; const EDIT_SVG = ``; const TRASH_SVG = ``; +const CHEVRON_SVG = ``; +const DRAG_SVG = ``; function generateId(): string { return Date.now().toString(36) + Math.random().toString(36).slice(2, 7); @@ -49,7 +71,7 @@ const messageFoldersPlugin: Plugin void) | null = null; + let foldedSection: HTMLElement | null = null; const unregisters: Array<{ unregister: () => void }> = []; - // ── Storage accessors ── - const getFolders = (): Folder[] => api.storage.folders ?? []; const getAssignments = (): Record => api.storage.messageAssignments ?? {}; @@ -94,6 +115,18 @@ const messageFoldersPlugin: Plugin { + const assignments = getAssignments(); + if (!assignments[folderId]) assignments[folderId] = []; + const idx = assignments[folderId].indexOf(messageId); + if (add && idx < 0) { + assignments[folderId].push(messageId); + } else if (!add && idx >= 0) { + assignments[folderId].splice(idx, 1); + } + saveAssignments(assignments); + }; + const toggleMessageInFolder = (messageId: string, folderId: string) => { const assignments = getAssignments(); if (!assignments[folderId]) assignments[folderId] = []; @@ -129,16 +162,28 @@ const messageFoldersPlugin: Plugin { + const selectedMsg = document.querySelector("[class*='MessageList__selected___']"); + return selectedMsg?.getAttribute("data-message") ?? null; + }; - const showConfirmModal = ( - title: string, - message: string, - onConfirm: () => void, - ) => { + const getMessageIdFromEvent = (target: HTMLElement): string | null => { + const li = target.closest("li[data-message]"); + return li?.getAttribute("data-message") ?? null; + }; + + const getAllVisibleMessageIds = (): string[] => { + const ids: string[] = []; + document.querySelectorAll("[class*='MessageList__MessageList___'] ol > li[data-message]").forEach((li) => { + const id = li.getAttribute("data-message"); + if (id) ids.push(id); + }); + return ids; + }; + + const showConfirmModal = (title: string, message: string, onConfirm: () => void) => { const overlay = document.createElement("div"); overlay.className = "bsplus-modal-overlay"; - const modal = document.createElement("div"); modal.className = "bsplus-modal"; modal.innerHTML = ` @@ -150,16 +195,13 @@ const messageFoldersPlugin: Plugin `; overlay.appendChild(modal); - const remove = () => { overlay.remove(); document.removeEventListener("keydown", onKey); }; - const onKey = (e: KeyboardEvent) => { if (e.key === "Escape") remove(); }; - overlay.addEventListener("click", (e) => { if (e.target === overlay) remove(); }); @@ -168,36 +210,42 @@ const messageFoldersPlugin: Plugin { const sidebar = document.querySelector("[class*='Viewer__sidebar___']"); if (!sidebar) return; - const ol = sidebar.querySelector("ol"); if (!ol) return; - let section = ol.querySelector(".bsplus-folders-section"); + let section = ol.querySelector(".bsplus-folders-section") as HTMLElement; if (!section) { section = document.createElement("div"); section.className = "bsplus-folders-section"; ol.appendChild(section); } + foldedSection = section; const folders = getFolders(); - const existingInput = section.querySelector(".bsplus-folder-input"); - const existingColors = section.querySelector(".bsplus-folder-colors"); - section.innerHTML = ""; - // Header const header = document.createElement("div"); header.className = "bsplus-folders-header"; + header.dataset.folded = "false"; + + const collapseBtn = document.createElement("button"); + collapseBtn.className = "bsplus-folders-collapse"; + collapseBtn.innerHTML = CHEVRON_SVG; + collapseBtn.title = "Collapse"; + collapseBtn.addEventListener("click", (e) => { + e.stopPropagation(); + const isFolded = collapseBtn.classList.toggle("bsplus-folded"); + section.classList.toggle("bsplus-section-folded", isFolded); + collapseBtn.title = isFolded ? "Expand" : "Collapse"; + }); + header.appendChild(collapseBtn); const label = document.createElement("span"); label.textContent = "Folders"; @@ -214,9 +262,8 @@ const messageFoldersPlugin: Plugin All Messages @@ -226,20 +273,34 @@ const messageFoldersPlugin: Plugin { + applyFolderFilter(); + applyBadges(); + }, 100); }); section.appendChild(allItem); - // Folder items for (const folder of folders) { const item = document.createElement("div"); item.className = `bsplus-folder-item${activeFolderId === folder.id ? " bsplus-folder-active" : ""}`; item.dataset.folderId = folder.id; + item.draggable = true; + + const dragHandle = document.createElement("div"); + dragHandle.className = "bsplus-folder-drag"; + dragHandle.innerHTML = DRAG_SVG; + item.appendChild(dragHandle); const dot = document.createElement("div"); dot.className = "bsplus-folder-dot"; dot.style.background = folder.color; item.appendChild(dot); + const iconSpan = document.createElement("span"); + iconSpan.className = "bsplus-folder-icon"; + iconSpan.innerHTML = folder.emoji || FOLDER_HEROICONS[0]; + item.appendChild(iconSpan); + const name = document.createElement("span"); name.className = "bsplus-folder-name"; name.textContent = folder.name; @@ -264,21 +325,17 @@ const messageFoldersPlugin: Plugin { e.stopPropagation(); - showConfirmModal( - "Delete folder", - `Remove "${folder.name}"? Messages won't be deleted.`, - () => { - const folders = getFolders().filter((f) => f.id !== folder.id); - saveFolders(folders); - const assignments = getAssignments(); - delete assignments[folder.id]; - saveAssignments(assignments); - if (activeFolderId === folder.id) activeFolderId = null; - applyFolderFilter(); - applyBadges(); - renderSidebarFolders(); - }, - ); + showConfirmModal("Delete folder", `Remove "${folder.name}"? Messages won't be deleted.`, () => { + const folders = getFolders().filter((f) => f.id !== folder.id); + saveFolders(folders); + const assignments = getAssignments(); + delete assignments[folder.id]; + saveAssignments(assignments); + if (activeFolderId === folder.id) activeFolderId = null; + applyFolderFilter(); + applyBadges(); + renderSidebarFolders(); + }); }); actions.appendChild(deleteBtn); @@ -295,15 +352,89 @@ const messageFoldersPlugin: Plugin { + applyFolderFilter(); + applyBadges(); + }, 100); + }); + + item.addEventListener("dragstart", (e) => { + e.dataTransfer?.setData("text/plain", `reorder:${folder.id}`); + item.classList.add("bsplus-dragging"); + }); + item.addEventListener("dragend", () => { + item.classList.remove("bsplus-dragging"); + document.querySelectorAll(".bsplus-folder-item").forEach((el) => el.classList.remove("bsplus-drag-over")); + }); + item.addEventListener("dragover", (e) => { + e.preventDefault(); + const data = e.dataTransfer?.getData("text/plain") || ""; + if (data.startsWith("reorder:") && !data.includes(folder.id)) { + item.classList.add("bsplus-drag-over"); + } + }); + item.addEventListener("dragleave", () => { + item.classList.remove("bsplus-drag-over"); + }); + item.addEventListener("drop", (e) => { + e.preventDefault(); + item.classList.remove("bsplus-drag-over"); + const data = e.dataTransfer?.getData("text/plain") || ""; + if (data.startsWith("reorder:")) { + const draggedId = data.replace("reorder:", ""); + const folders = getFolders(); + const draggedIdx = folders.findIndex((f) => f.id === draggedId); + const targetIdx = folders.findIndex((f) => f.id === folder.id); + if (draggedIdx >= 0 && targetIdx >= 0 && draggedIdx !== targetIdx) { + const [removed] = folders.splice(draggedIdx, 1); + folders.splice(targetIdx, 0, removed); + saveFolders(folders); + renderSidebarFolders(); + } + } }); section.appendChild(item); } - // Restore input if it was open - if (existingInput || existingColors) { - // Don't restore – let user re-trigger - } + section.addEventListener("dragover", (e) => { + e.preventDefault(); + }); + section.addEventListener("drop", (e) => { + e.preventDefault(); + const data = e.dataTransfer?.getData("text/plain") || ""; + if (data.startsWith("msg:")) { + const messageId = data.replace("msg:", ""); + const folderId = (e.target as HTMLElement).closest("[data-folder-id]")?.getAttribute("data-folder-id"); + if (messageId && folderId) { + assignMessageToFolder(messageId, folderId, true); + applyBadges(); + applyFolderFilter(); + renderSidebarFolders(); + } + } + }); + + attachDragListeners(); + }; + + const attachDragListeners = () => { + document.querySelectorAll("[class*='MessageList__MessageList___'] ol > li[data-message]").forEach((li) => { + if (li.getAttribute("data-bsplus-drag") === "true") return; + li.setAttribute("data-bsplus-drag", "true"); + li.draggable = true; + li.addEventListener("dragstart", (e) => { + const id = li.getAttribute("data-message"); + if (id) { + e.dataTransfer?.setData("text/plain", `msg:${id}`); + li.classList.add("bsplus-msg-dragging"); + } + }); + li.addEventListener("dragend", () => { + li.classList.remove("bsplus-msg-dragging"); + document.querySelectorAll(".bsplus-folder-item").forEach((el) => el.classList.remove("bsplus-drag-over")); + }); + }); }; const showNewFolderInput = (container: Element, editFolder?: Folder) => { @@ -312,16 +443,34 @@ const messageFoldersPlugin: Plugin { + e.stopPropagation(); + const picker = container.querySelector(".bsplus-icon-picker") as HTMLElement | null; + if (picker) { + picker.remove(); + return; + } + showIconPicker(container, (iconSvg) => { + selectedIcon = iconSvg; + iconBtn.innerHTML = iconSvg; + }); + }); + const confirmBtn = document.createElement("button"); confirmBtn.className = "bsplus-folder-input-confirm"; confirmBtn.innerHTML = CHECK_SVG_WHITE; @@ -330,11 +479,11 @@ const messageFoldersPlugin: Plugin { const name = input.value.trim(); if (!name) return; - if (editFolder) { const folders = getFolders().map((f) => - f.id === editFolder.id ? { ...f, name, color: selectedColor } : f, + f.id === editFolder.id ? { ...f, name, color: selectedColor, emoji: selectedIcon } : f, ); saveFolders(folders); } else { - const folder: Folder = { id: generateId(), name, color: selectedColor }; + const folder: Folder = { id: generateId(), name, color: selectedColor, emoji: selectedIcon }; saveFolders([...getFolders(), folder]); } applyBadges(); @@ -386,23 +534,38 @@ const messageFoldersPlugin: Plugin input.focus()); }; + const showIconPicker = (container: Element, onSelect: (iconSvg: string) => void) => { + const existing = container.querySelector(".bsplus-icon-picker"); + if (existing) existing.remove(); + + const picker = document.createElement("div"); + picker.className = "bsplus-icon-picker"; + for (const icon of FOLDER_HEROICONS) { + const btn = document.createElement("button"); + btn.className = "bsplus-icon-opt"; + btn.innerHTML = icon; + btn.addEventListener("click", (e) => { + e.stopPropagation(); + onSelect(icon); + picker.remove(); + }); + picker.appendChild(btn); + } + container.appendChild(picker); + }; + const showEditFolderInput = (container: Element, folder: Folder) => { showNewFolderInput(container, folder); }; - // ── Intercept native sidebar clicks to clear folder filter ── - const attachNativeSidebarListeners = () => { const sidebar = document.querySelector("[class*='Viewer__sidebar___']"); if (!sidebar) return; - const ol = sidebar.querySelector("ol"); if (!ol) return; - ol.addEventListener("click", (e) => { const target = e.target as HTMLElement; if (target.closest(".bsplus-folders-section")) return; - const li = target.closest("li"); if (li && ol.contains(li)) { if (activeFolderId !== null) { @@ -415,47 +578,22 @@ const messageFoldersPlugin: Plugin { - if (actionsBar.querySelector(".bsplus-folder-btn")) return; - - const wrapper = document.createElement("div"); - wrapper.className = "bsplus-folder-btn"; - wrapper.style.position = "relative"; - wrapper.style.display = "inline-block"; - - const btn = document.createElement("button"); - const btnClasses = actionsBar.querySelector("button")?.className ?? ""; - btn.className = btnClasses; - btn.title = "Add to folder"; - btn.innerHTML = FOLDER_ICON_SVG; - - btn.addEventListener("click", (e) => { - e.preventDefault(); - e.stopPropagation(); - closeDropdown(); - - const selectedMsg = document.querySelector("[class*='MessageList__selected___']"); - const messageId = selectedMsg?.getAttribute("data-message"); - if (!messageId) return; - - showFolderDropdown(wrapper, messageId); - }); - - wrapper.appendChild(btn); - - const moreMenu = actionsBar.querySelector("[class*='MenuButton__Menu___']"); - if (moreMenu) { - actionsBar.insertBefore(wrapper, moreMenu); - } else { - actionsBar.appendChild(wrapper); + const closeDropdown = () => { + if (openDropdown) { + openDropdown.remove(); + openDropdown = null; + } + if (dropdownCloseHandler) { + document.removeEventListener("click", dropdownCloseHandler, true); + dropdownCloseHandler = null; } }; const showFolderDropdown = (anchor: HTMLElement, messageId: string) => { + closeDropdown(); const dropdown = document.createElement("div"); dropdown.className = "bsplus-folder-dropdown"; + dropdown.dataset.msgId = messageId; const folders = getFolders(); const currentFolderIds = getMessageFolderIds(messageId); @@ -470,6 +608,7 @@ const messageFoldersPlugin: Plugin { e.stopPropagation(); + e.preventDefault(); toggleMessageInFolder(messageId, folder.id); - const nowChecked = getMessageFolderIds(messageId).includes(folder.id); item.classList.toggle("bsplus-checked", nowChecked); check.style.borderColor = nowChecked ? folder.color : ""; check.style.background = nowChecked ? folder.color : ""; - applyBadges(); applyFolderFilter(); renderSidebarFolders(); @@ -519,22 +662,105 @@ const messageFoldersPlugin: Plugin { - if (openDropdown) { - openDropdown.remove(); - openDropdown = null; - } - if (dropdownCloseHandler) { - document.removeEventListener("click", dropdownCloseHandler, true); - dropdownCloseHandler = null; + const injectFolderButton = (actionsBar: Element) => { + if (actionsBar.querySelector(".bsplus-folder-btn")) return; + const wrapper = document.createElement("div"); + wrapper.className = "bsplus-folder-btn"; + wrapper.style.position = "relative"; + wrapper.style.display = "inline-block"; + const btn = document.createElement("button"); + const btnClasses = actionsBar.querySelector("button")?.className ?? ""; + btn.className = btnClasses; + btn.title = "Add to folder"; + btn.innerHTML = FOLDER_ICON_SVG; + btn.addEventListener("click", (e) => { + e.preventDefault(); + e.stopPropagation(); + const selectedMsg = document.querySelector("[class*='MessageList__selected___']"); + const messageId = selectedMsg?.getAttribute("data-message"); + if (!messageId) return; + showFolderDropdown(wrapper, messageId); + }); + wrapper.appendChild(btn); + const moreMenu = actionsBar.querySelector("[class*='MenuButton__Menu___']"); + if (moreMenu) { + actionsBar.insertBefore(wrapper, moreMenu); + } else { + actionsBar.appendChild(wrapper); } }; - // ── Message badges ── + const showContextMenu = (e: MouseEvent, messageId: string) => { + e.preventDefault(); + e.stopPropagation(); + closeDropdown(); + const existing = document.querySelector(".bsplus-context-menu"); + if (existing) existing.remove(); + + const menu = document.createElement("div"); + menu.className = "bsplus-context-menu"; + menu.style.left = `${e.clientX}px`; + menu.style.top = `${e.clientY}px`; + + const title = document.createElement("div"); + title.className = "bsplus-context-title"; + title.textContent = "Add to folder"; + menu.appendChild(title); + + const folders = getFolders(); + const currentFolderIds = getMessageFolderIds(messageId); + + if (folders.length === 0) { + const empty = document.createElement("div"); + empty.className = "bsplus-context-empty"; + empty.textContent = "No folders"; + menu.appendChild(empty); + } else { + for (const folder of folders) { + const isChecked = currentFolderIds.includes(folder.id); + const item = document.createElement("button"); + item.className = `bsplus-context-item${isChecked ? " bsplus-context-checked" : ""}`; + const dot = document.createElement("div"); + dot.className = "bsplus-folder-dot"; + dot.style.background = folder.color; + const iconSpan = document.createElement("span"); + iconSpan.className = "bsplus-folder-icon"; + iconSpan.innerHTML = folder.emoji || FOLDER_HEROICONS[0]; + const name = document.createElement("span"); + name.textContent = folder.name; + item.appendChild(dot); + item.appendChild(iconSpan); + item.appendChild(name); + if (isChecked) { + const check = document.createElement("span"); + check.className = "bsplus-context-checkmark"; + check.textContent = "\u2713"; + item.appendChild(check); + } + item.addEventListener("click", (e) => { + e.stopPropagation(); + toggleMessageInFolder(messageId, folder.id); + applyBadges(); + applyFolderFilter(); + renderSidebarFolders(); + menu.remove(); + }); + menu.appendChild(item); + } + } + + document.body.appendChild(menu); + const closeMenu = (ev: MouseEvent) => { + if (!menu.contains(ev.target as Node)) { + menu.remove(); + document.removeEventListener("click", closeMenu); + } + }; + setTimeout(() => document.addEventListener("click", closeMenu), 0); + }; const applyBadges = () => { const messageItems = document.querySelectorAll("[class*='MessageList__MessageList___'] ol > li[data-message]"); - if (!shouldShowBadgesInList()) { for (const li of messageItems) { const subject = li.querySelector("[class*='MessageList__subject___']"); @@ -546,26 +772,20 @@ const messageFoldersPlugin: Plugin f.id === fId); @@ -591,7 +810,7 @@ const messageFoldersPlugin: Plugin${folder.emoji}` : ""}${folder.name}`; badge.title = `Filter by "${folder.name}"`; badge.addEventListener("click", (e) => { e.stopPropagation(); @@ -605,12 +824,9 @@ const messageFoldersPlugin: Plugin { const messageItems = document.querySelectorAll("[class*='MessageList__MessageList___'] ol > li[data-message]"); const moreBtn = document.querySelector("[class*='MessageList__MessageList___'] ol > button"); - if (activeFolderId === null) { if (api.settings.hideFolderedMessagesInAll) { for (const li of messageItems) { @@ -629,9 +845,7 @@ const messageFoldersPlugin: Plugin { const messageList = document.querySelector("[class*='MessageList__MessageList___'] ol"); if (!messageList || messageListObserver) return; - messageListObserver = new MutationObserver(() => { applyBadges(); applyFolderFilter(); + attachDragListeners(); + attachContextMenuListeners(); }); messageListObserver.observe(messageList, { childList: true, subtree: false }); }; + const attachContextMenuListeners = () => { + document.querySelectorAll("[class*='MessageList__MessageList___'] ol > li[data-message]").forEach((li) => { + if (li.getAttribute("data-bsplus-ctx") === "true") return; + li.setAttribute("data-bsplus-ctx", "true"); + li.addEventListener("contextmenu", (e) => { + const msgId = li.getAttribute("data-message"); + if (msgId) { + showContextMenu(e, msgId); + } + }); + }); + }; + const setupActionsObserver = () => { if (actionsObserver) return; - const target = document.querySelector("[class*='Viewer__Viewer___']") ?? document.querySelector("div.messages"); if (!target) return; - actionsObserver = new MutationObserver(() => { const actionsBar = document.querySelector("[class*='Message__actions___']"); if (actionsBar && !actionsBar.querySelector(".bsplus-folder-btn")) { @@ -671,28 +895,19 @@ const messageFoldersPlugin: Plugin { await waitForElm("[class*='Viewer__sidebar___'] ol", true, 50, 100); - renderSidebarFolders(); attachNativeSidebarListeners(); - await waitForElm("[class*='MessageList__MessageList___'] ol", true, 50, 100); applyBadges(); applyFolderFilter(); setupMessageListObserver(); - - // The actions bar only exists when a message is selected/open, - // so we observe the whole viewer for it to appear dynamically setupActionsObserver(); - - // If a message is already selected, inject immediately + attachDragListeners(); + attachContextMenuListeners(); const actionsBar = document.querySelector("[class*='Message__actions___']"); if (actionsBar) injectFolderButton(actionsBar); - - // Re-observe the sidebar for SEQTA re-renders const sidebar = document.querySelector("[class*='Viewer__sidebar___']"); if (sidebar && !sidebarObserver) { sidebarObserver = new MutationObserver(() => { @@ -706,11 +921,8 @@ const messageFoldersPlugin: Plugin { applyBadges(); @@ -732,6 +944,7 @@ const messageFoldersPlugin: Plugin el.remove()); document.querySelectorAll(".bsplus-folder-btn").forEach((el) => el.remove()); document.querySelectorAll(".bsplus-msg-badges").forEach((el) => el.remove()); + document.querySelectorAll(".bsplus-context-menu").forEach((el) => el.remove()); document.querySelectorAll("[class*='MessageList__subject___']").forEach((subject) => { if (subject.querySelector(".bsplus-subject-text")) { restoreSubjectPlain(subject); @@ -741,6 +954,7 @@ const messageFoldersPlugin: Plugin el.remove()); + }; }, }; diff --git a/src/plugins/built-in/messageFolders/styles.css b/src/plugins/built-in/messageFolders/styles.css index e239a883..6b99b126 100644 --- a/src/plugins/built-in/messageFolders/styles.css +++ b/src/plugins/built-in/messageFolders/styles.css @@ -3,12 +3,21 @@ border-top: 1px solid var(--background-secondary, rgba(128, 128, 128, 0.2)); margin-top: 4px; padding-top: 4px; + transition: opacity .2s; +} + +.bsplus-folders-section.bsplus-section-folded .bsplus-folder-item, +.bsplus-folders-section.bsplus-section-folded .bsplus-folder-input, +.bsplus-folders-section.bsplus-section-folded .bsplus-folder-colors, +.bsplus-folders-section.bsplus-section-folded .bsplus-emoji-picker, +.bsplus-folders-section.bsplus-section-folded .bsplus-all-msgs { + display: none !important; } .bsplus-folders-header { display: flex; align-items: center; - justify-content: space-between; + gap: 4px; padding: 6px 12px 2px; user-select: none; } @@ -20,6 +29,33 @@ letter-spacing: 0.5px; color: var(--text-primary, #666); opacity: 0.5; + flex: 1; +} + +.bsplus-folders-collapse { + display: flex !important; + align-items: center !important; + justify-content: center !important; + width: 18px !important; + height: 18px !important; + min-width: 0 !important; + border: none !important; + background: transparent !important; + opacity: 0.4; + cursor: pointer; + border-radius: 4px !important; + padding: 0 !important; + margin: 0 !important; + transition: all .2s; +} + +.bsplus-folders-collapse:hover { + opacity: 0.8; + background: var(--background-secondary, rgba(128, 128, 128, 0.1)) !important; +} + +.bsplus-folders-collapse.bsplus-folded svg { + transform: rotate(-90deg); } .bsplus-folders-add-btn { @@ -51,12 +87,21 @@ align-items: center; padding: 6px 12px; cursor: pointer; - transition: background 0.15s ease; + transition: background 0.15s ease, opacity 0.2s; position: relative; - gap: 8px; + gap: 6px; user-select: none; } +.bsplus-folder-item.bsplus-dragging { + opacity: 0.4; +} + +.bsplus-folder-item.bsplus-drag-over { + background: var(--better-main, #007bff22) !important; + border-radius: 4px; +} + .bsplus-folder-item:hover { background: var(--theme-offset-bg-more, rgba(128, 128, 128, 0.08)); } @@ -76,6 +121,18 @@ border-radius: 0 2px 2px 0; } +.bsplus-folder-drag { + display: flex; + align-items: center; + opacity: 0; + transition: opacity .15s; + margin-right: -4px; +} + +.bsplus-folder-item:hover .bsplus-folder-drag { + opacity: 0.5; +} + .bsplus-folder-dot { width: 8px; height: 8px; @@ -83,6 +140,23 @@ flex-shrink: 0; } +.bsplus-folder-icon { + display: inline-flex; + align-items: center; + justify-content: center; + width: 16px; + height: 16px; + flex-shrink: 0; + color: var(--text-primary, #333); +} + +.bsplus-folder-icon svg { + width: 16px; + height: 16px; + stroke: currentColor; + fill: none; +} + .bsplus-folder-name { font-size: 13px; color: var(--text-primary, #333); @@ -97,6 +171,8 @@ color: var(--text-primary, #999); opacity: 0.5; flex-shrink: 0; + min-width: 16px; + text-align: right; } .bsplus-folder-actions { @@ -158,6 +234,35 @@ box-shadow: 0 0 0 2px rgba(0, 123, 255, 0.2); } +.bsplus-folder-icon-btn { + display: flex !important; + align-items: center !important; + justify-content: center !important; + width: 28px !important; + height: 28px !important; + min-width: 0 !important; + border: 1px solid var(--background-secondary, #ccc) !important; + border-radius: 6px !important; + background: var(--background-secondary, #f5f5f5) !important; + cursor: pointer; + padding: 0 !important; + margin: 0 !important; + transition: all .15s; + color: var(--text-primary, #333); +} + +.bsplus-folder-icon-btn:hover { + transform: scale(1.1); + background: var(--theme-offset-bg-more, rgba(128, 128, 128, 0.1)) !important; +} + +.bsplus-folder-icon-btn svg { + width: 18px; + height: 18px; + stroke: currentColor; + fill: none; +} + .bsplus-folder-input-confirm, .bsplus-folder-input-cancel { display: flex !important; @@ -192,6 +297,43 @@ background: var(--background-secondary, rgba(128, 128, 128, 0.1)) !important; } +/* ── Icon picker ── */ +.bsplus-icon-picker { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: 4px; + padding: 4px 12px 6px; + max-width: 140px; +} + +.bsplus-icon-opt { + display: flex !important; + align-items: center !important; + justify-content: center !important; + width: 28px !important; + height: 28px !important; + min-width: 0 !important; + border: none !important; + border-radius: 6px !important; + background: transparent !important; + cursor: pointer; + padding: 0 !important; + transition: all .15s; + color: var(--text-primary, #333); +} + +.bsplus-icon-opt svg { + width: 18px; + height: 18px; + stroke: currentColor; + fill: none; +} + +.bsplus-icon-opt:hover { + transform: scale(1.3); + background: var(--theme-offset-bg-more, rgba(128, 128, 128, 0.1)) !important; +} + /* ── Color picker row ── */ .bsplus-folder-colors { display: grid; @@ -322,14 +464,113 @@ opacity: 0.5; } -/* ── Let primary column use available space instead of being clipped ── */ +/* ── Context menu ── */ +.bsplus-context-menu { + position: fixed; + min-width: 160px; + background: var(--background-primary, #fff) !important; + border: 1px solid var(--background-secondary, #e0e0e0) !important; + border-radius: 8px; + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15); + z-index: 2147483646; + overflow: hidden; + animation: bsplus-dropdown-in 0.12s ease-out; + padding: 4px 0; +} + +.bsplus-context-title { + padding: 6px 12px 4px; + font-size: 11px; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.5px; + color: var(--text-primary, #999) !important; + opacity: 0.5; + user-select: none; +} + +.bsplus-context-item:hover { + background: var(--theme-offset-bg-more, rgba(128, 128, 128, 0.08)) !important; +} + +.bsplus-context-item span { + flex: 1; +} + +.bsplus-context-checkmark { + color: var(--better-main, #007bff) !important; + font-weight: bold; + flex: 0 !important; +} + +.bsplus-context-item { + display: flex !important; + align-items: center !important; + justify-content: flex-start !important; + gap: 8px; + padding: 7px 12px !important; + font-size: 13px; + cursor: pointer; + border: none !important; + background: transparent !important; + width: 100%; + text-align: left !important; + color: var(--text-primary, #333) !important; + transition: background .1s; + font-family: inherit; +} + +.bsplus-context-item .bsplus-folder-icon { + color: var(--text-primary, #333) !important; + width: 16px; + height: 16px; +} + +.bsplus-context-item .bsplus-folder-icon svg { + width: 16px; + height: 16px; + stroke: currentColor; + fill: none; +} + +.bsplus-context-item:hover { + background: var(--theme-offset-bg-more, rgba(128, 128, 128, 0.08)); +} + +.bsplus-context-item span { + flex: 1; +} + +.bsplus-context-checkmark { + color: var(--better-main, #007bff) !important; + font-weight: bold; + flex: 0 !important; +} + +.bsplus-context-empty { + padding: 12px; + text-align: center; + font-size: 12px; + color: var(--text-primary, #999); + opacity: 0.5; +} + +/* ── Drag feedback ── */ +.bsplus-msg-dragging { + opacity: 0.4; +} + +[class*='MessageList__MessageList___'] ol > li[data-message] { + transition: opacity .15s; +} + +/* ── Layout fixes ── */ [class*='MessageList__primary___'] { flex: 1 1 0% !important; min-width: 0 !important; overflow: hidden !important; } -/* ── Make subject line a flex row so badges sit inline ── */ [class*='MessageList__subject___'] { display: flex !important; align-items: center; @@ -338,7 +579,6 @@ overflow: hidden !important; } -/* ── Subject text truncates to make room for badges ── */ .bsplus-subject-text { overflow: hidden; text-overflow: ellipsis; @@ -347,7 +587,6 @@ flex: 1 1 auto; } -/* ── Shrink the secondary column to its content ── */ [class*='MessageList__secondary___'] { flex: 0 0 auto !important; width: auto !important; @@ -355,7 +594,6 @@ max-width: 200px !important; } -/* ── Constrain the flags/attachment icon column ── */ [class*='MessageList__flags___'] { width: 24px !important; min-width: 0 !important; @@ -391,7 +629,7 @@ transform: scale(1.05); } -/* ── Folder filtering (hide messages not in active folder) ── */ +/* ── Folder filtering ── */ .bsplus-folder-hidden { display: none !important; } @@ -489,3 +727,5 @@ transform: translateY(-1px); box-shadow: 0 4px 12px rgba(229, 62, 62, 0.35); } + + diff --git a/src/seqta/utils/Loaders/LoadHomePage.ts b/src/seqta/utils/Loaders/LoadHomePage.ts index e590e097..dcbd553d 100644 --- a/src/seqta/utils/Loaders/LoadHomePage.ts +++ b/src/seqta/utils/Loaders/LoadHomePage.ts @@ -113,16 +113,7 @@ export async function loadHomePage() { callHomeTimetable(TodayFormatted, true); const activeClass = classes.find((c: any) => c.hasOwnProperty("active")); - const activeYear = activeClass?.year; - const allSubjectsInYear = classes - .filter((c: any) => c.year === activeYear) - .flatMap((c: any) => c.subjects || []); - const seen = new Set(); - const activeSubjects = allSubjectsInYear.filter((s: any) => { - if (seen.has(s.code)) return false; - seen.add(s.code); - return true; - }); + const activeSubjects = activeClass?.subjects || []; const activeSubjectCodes = activeSubjects.map((s: any) => s.code); const currentAssessments = assessments .filter((a: any) => activeSubjectCodes.includes(a.code)) diff --git a/src/seqta/utils/Openers/OpenWhatsNewPopup.ts b/src/seqta/utils/Openers/OpenWhatsNewPopup.ts index 19e5b86f..6160f6e5 100644 --- a/src/seqta/utils/Openers/OpenWhatsNewPopup.ts +++ b/src/seqta/utils/Openers/OpenWhatsNewPopup.ts @@ -34,13 +34,16 @@ export function OpenWhatsNewPopup(onDismissed?: () => void) { const text = stringToHTML(/* html */ `
+

3.6.5 - Assessment weighting override & fixes

+
  • Added the ability to override/add weightings to assessments (on assessment page).
  • +
  • Fixed the display of weightings that could not automatically be discovered.
  • +
  • Fixed the formatting of the weighting tag that was broken due to a SEQTA update.
  • -

    3.6.4 - DM Folders, Theme falvours and fixes, Upcoming Assements improvement

    +

    3.6.4 - Theme flavours and fixes, Upcoming Assements improvement

  • Added advanced colour adjustments variables for theme customisation.
  • Improved logic for upcoming assements dashlet to improve compatibility.
  • BS Cloud can now automatically download themes from other devices.
  • -
  • Added theme flavour's for multiple colour variations of the same theme.
  • -
  • Added custom message folder, customizable in settings.
  • +
  • Added theme flavours for multiple colour variations of the same theme.
  • 3.6.3 - Assessment overview fix

  • Fixed assessments overview failing to load.