diff --git a/bun.lockb b/bun.lockb deleted file mode 100644 index 6c9089d..0000000 Binary files a/bun.lockb and /dev/null differ diff --git a/package-lock.json b/package-lock.json index 59b6973..8f4fbc1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,14 +1,13 @@ { "name": "nx-working", - "version": "1.0.0", + "version": "3.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "nx-working", - "version": "1.0.0", + "version": "3.0.0", "dependencies": { - "@rollup/rollup-win32-x64-msvc": "^4.27.3", "clsx": "^2.1.0", "fuse.js": "^7.0.0", "lucide-react": "^0.344.0", @@ -56,13 +55,12 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", - "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.25.7.tgz", + "integrity": "sha512-0xZJFNE5XMpENsgfHYTw8FbX4kv53mFLn2i3XPoq69LyhYSCBJtitaHx9QnsVTrsogI4Z3+HtEfZ2/GFPOtf5g==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.25.9", - "js-tokens": "^4.0.0", + "@babel/highlight": "^7.25.7", "picocolors": "^1.0.0" }, "engines": { @@ -70,30 +68,30 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.2.tgz", - "integrity": "sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.7.tgz", + "integrity": "sha512-9ickoLz+hcXCeh7jrcin+/SLWm+GkxE2kTvoYyp38p4WkdFXfQJxDFGWp/YHjiKLPx06z2A7W8XKuqbReXDzsw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.0.tgz", - "integrity": "sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.7.tgz", + "integrity": "sha512-yJ474Zv3cwiSOO9nXJuqzvwEeM+chDuQ8GJirw+pZ91sCGCyOZ3dJkVE09fTV0VEVzXyLWhh3G/AolYTPX7Mow==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.26.0", - "@babel/generator": "^7.26.0", - "@babel/helper-compilation-targets": "^7.25.9", - "@babel/helper-module-transforms": "^7.26.0", - "@babel/helpers": "^7.26.0", - "@babel/parser": "^7.26.0", - "@babel/template": "^7.25.9", - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.26.0", + "@babel/code-frame": "^7.25.7", + "@babel/generator": "^7.25.7", + "@babel/helper-compilation-targets": "^7.25.7", + "@babel/helper-module-transforms": "^7.25.7", + "@babel/helpers": "^7.25.7", + "@babel/parser": "^7.25.7", + "@babel/template": "^7.25.7", + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -109,13 +107,12 @@ } }, "node_modules/@babel/generator": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.2.tgz", - "integrity": "sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.7.tgz", + "integrity": "sha512-5Dqpl5fyV9pIAD62yK9P7fcA768uVPUyrQmqpqstHWgMma4feF1x/oFysBCVZLY5wJ2GkMUCdsNDnGZrPoR6rA==", "dev": true, "dependencies": { - "@babel/parser": "^7.26.2", - "@babel/types": "^7.26.0", + "@babel/types": "^7.25.7", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" @@ -125,13 +122,13 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz", - "integrity": "sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.7.tgz", + "integrity": "sha512-DniTEax0sv6isaw6qSQSfV4gVRNtw2rte8HHM45t9ZR0xILaufBRNkpMifCRiAPyvL4ACD6v0gfCwCmtOQaV4A==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.25.9", - "@babel/helper-validator-option": "^7.25.9", + "@babel/compat-data": "^7.25.7", + "@babel/helper-validator-option": "^7.25.7", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" @@ -141,27 +138,28 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", - "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.7.tgz", + "integrity": "sha512-o0xCgpNmRohmnoWKQ0Ij8IdddjyBFE4T2kagL/x6M3+4zUgc+4qTOUBoNe4XxDskt1HPKO007ZPiMgLDq2s7Kw==", "dev": true, "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", - "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.7.tgz", + "integrity": "sha512-k/6f8dKG3yDz/qCwSM+RKovjMix563SLxQFo0UhRNo239SP6n9u5/eLtKD6EAjwta2JHJ49CsD8pms2HdNiMMQ==", "dev": true, "dependencies": { - "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9", - "@babel/traverse": "^7.25.9" + "@babel/helper-module-imports": "^7.25.7", + "@babel/helper-simple-access": "^7.25.7", + "@babel/helper-validator-identifier": "^7.25.7", + "@babel/traverse": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -171,61 +169,89 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz", - "integrity": "sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.7.tgz", + "integrity": "sha512-eaPZai0PiqCi09pPs3pAFfl/zYgGaE6IdXtYvmf0qlcDTd3WCtO7JWCcRd64e0EQrcYgiHibEZnOGsSY4QSgaw==", "dev": true, "engines": { "node": ">=6.9.0" } }, + "node_modules/@babel/helper-simple-access": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.25.7.tgz", + "integrity": "sha512-FPGAkJmyoChQeM+ruBGIDyrT2tKfZJO8NcxdC+CWNJi7N8/rZpSxK7yvBJ5O/nF1gfu5KzN7VKG3YVSLFfRSxQ==", + "dev": true, + "dependencies": { + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-string-parser": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", - "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.7.tgz", + "integrity": "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", - "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.7.tgz", + "integrity": "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", - "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.7.tgz", + "integrity": "sha512-ytbPLsm+GjArDYXJ8Ydr1c/KJuutjF2besPNbIZnZ6MKUxi/uTA22t2ymmA4WFjZFpjiAMO0xuuJPqK2nvDVfQ==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.0.tgz", - "integrity": "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.7.tgz", + "integrity": "sha512-Sv6pASx7Esm38KQpF/U/OXLwPPrdGHNKoeblRxgZRLXnAtnkEe4ptJPDtAZM7fBLadbc1Q07kQpSiGQ0Jg6tRA==", + "dev": true, + "dependencies": { + "@babel/template": "^7.25.7", + "@babel/types": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.25.7.tgz", + "integrity": "sha512-iYyACpW3iW8Fw+ZybQK+drQre+ns/tKpXbNESfrhNnPLIklLbXr7MYJ6gPEd0iETGLOK+SxMjVvKb/ffmk+FEw==", "dev": true, "dependencies": { - "@babel/template": "^7.25.9", - "@babel/types": "^7.26.0" + "@babel/helper-validator-identifier": "^7.25.7", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.2.tgz", - "integrity": "sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.7.tgz", + "integrity": "sha512-aZn7ETtQsjjGG5HruveUK06cU3Hljuhd9Iojm4M8WWv3wLE6OkE5PWbDUkItmMgegmccaITudyuW5RPYrYlgWw==", "dev": true, "dependencies": { - "@babel/types": "^7.26.0" + "@babel/types": "^7.25.7" }, "bin": { "parser": "bin/babel-parser.js" @@ -235,12 +261,12 @@ } }, "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.25.9.tgz", - "integrity": "sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.25.7.tgz", + "integrity": "sha512-JD9MUnLbPL0WdVK8AWC7F7tTG2OS6u/AKKnsK+NdRhUiVdnzyR1S3kKQCaRLOiaULvUiqK6Z4JQE635VgtCFeg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -250,12 +276,12 @@ } }, "node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.25.9.tgz", - "integrity": "sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.25.7.tgz", + "integrity": "sha512-S/JXG/KrbIY06iyJPKfxr0qRxnhNOdkNXYBl/rmwgDd72cQLH9tEGkDm/yJPGvcSIUoikzfjMios9i+xT/uv9w==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.25.7" }, "engines": { "node": ">=6.9.0" @@ -265,30 +291,30 @@ } }, "node_modules/@babel/template": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", - "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.7.tgz", + "integrity": "sha512-wRwtAgI3bAS+JGU2upWNL9lSlDcRCqD05BZ1n3X2ONLH1WilFP6O1otQjeMK/1g0pvYcXC7b/qVUB1keofjtZA==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.25.9", - "@babel/parser": "^7.25.9", - "@babel/types": "^7.25.9" + "@babel/code-frame": "^7.25.7", + "@babel/parser": "^7.25.7", + "@babel/types": "^7.25.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", - "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.7.tgz", + "integrity": "sha512-jatJPT1Zjqvh/1FyJs6qAHL+Dzb7sTb+xr7Q+gM1b+1oBsMsQQ4FkVKb6dFlJvLlVssqkRzV05Jzervt9yhnzg==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.25.9", - "@babel/generator": "^7.25.9", - "@babel/parser": "^7.25.9", - "@babel/template": "^7.25.9", - "@babel/types": "^7.25.9", + "@babel/code-frame": "^7.25.7", + "@babel/generator": "^7.25.7", + "@babel/parser": "^7.25.7", + "@babel/template": "^7.25.7", + "@babel/types": "^7.25.7", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -296,273 +322,27 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/types": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz", - "integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", - "cpu": [ - "riscv64" - ], + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true, - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=12" + "node": ">=4" } }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", - "cpu": [ - "s390x" - ], + "node_modules/@babel/types": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.7.tgz", + "integrity": "sha512-vwIVdXG+j+FOpkwqHRcBgHLYNL7XMkufrlaFvL9o6Ai9sJn9+PdyIL5qa0XzTZw084c+u9LOls53eoZWP/W5WQ==", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/helper-string-parser": "^7.25.7", + "@babel/helper-validator-identifier": "^7.25.7", + "to-fast-properties": "^2.0.0" + }, "engines": { - "node": ">=12" + "node": ">=6.9.0" } }, "node_modules/@esbuild/linux-x64": { @@ -581,102 +361,6 @@ "node": ">=12" } }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -712,254 +396,85 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "optional": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.27.3.tgz", - "integrity": "sha512-EzxVSkIvCFxUd4Mgm4xR9YXrcp976qVaHnqom/Tgm+vU79k4vV4eYTjmRvGfeoW8m9LVcsAy/lGjcgVegKEhLQ==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.27.3.tgz", - "integrity": "sha512-LJc5pDf1wjlt9o/Giaw9Ofl+k/vLUaYsE2zeQGH85giX2F+wn/Cg8b3c5CDP3qmVmeO5NzwVUzQQxwZvC2eQKw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.27.3.tgz", - "integrity": "sha512-OuRysZ1Mt7wpWJ+aYKblVbJWtVn3Cy52h8nLuNSzTqSesYw1EuN6wKp5NW/4eSre3mp12gqFRXOKTcN3AI3LqA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.27.3.tgz", - "integrity": "sha512-xW//zjJMlJs2sOrCmXdB4d0uiilZsOdlGQIC/jjmMWT47lkLLoB1nsNhPUcnoqyi5YR6I4h+FjBpILxbEy8JRg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.27.3.tgz", - "integrity": "sha512-58E0tIcwZ+12nK1WiLzHOD8I0d0kdrY/+o7yFVPRHuVGY3twBwzwDdTIBGRxLmyjciMYl1B/U515GJy+yn46qw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.27.3.tgz", - "integrity": "sha512-78fohrpcVwTLxg1ZzBMlwEimoAJmY6B+5TsyAZ3Vok7YabRBUvjYTsRXPTjGEvv/mfgVBepbW28OlMEz4w8wGA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.27.3.tgz", - "integrity": "sha512-h2Ay79YFXyQi+QZKo3ISZDyKaVD7uUvukEHTOft7kh00WF9mxAaxZsNs3o/eukbeKuH35jBvQqrT61fzKfAB/Q==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] + "dev": true, + "engines": { + "node": ">=6.0.0" + } }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.27.3.tgz", - "integrity": "sha512-Sv2GWmrJfRY57urktVLQ0VKZjNZGogVtASAgosDZ1aUB+ykPxSi3X1nWORL5Jk0sTIIwQiPH7iE3BMi9zGWfkg==", - "cpu": [ - "arm" - ], + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "dev": true, - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": ">=6.0.0" + } }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.27.3.tgz", - "integrity": "sha512-FPoJBLsPW2bDNWjSrwNuTPUt30VnfM8GPGRoLCYKZpPx0xiIEdFip3dH6CqgoT0RnoGXptaNziM0WlKgBc+OWQ==", - "cpu": [ - "arm64" - ], + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, - "optional": true, - "os": [ - "linux" - ] + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.27.3.tgz", - "integrity": "sha512-TKxiOvBorYq4sUpA0JT+Fkh+l+G9DScnG5Dqx7wiiqVMiRSkzTclP35pE6eQQYjP4Gc8yEkJGea6rz4qyWhp3g==", - "cpu": [ - "arm64" - ], + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, - "optional": true, - "os": [ - "linux" - ] + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.27.3.tgz", - "integrity": "sha512-v2M/mPvVUKVOKITa0oCFksnQQ/TqGrT+yD0184/cWHIu0LoIuYHwox0Pm3ccXEz8cEQDLk6FPKd1CCm+PlsISw==", - "cpu": [ - "ppc64" - ], + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": ">= 8" + } }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.27.3.tgz", - "integrity": "sha512-LdrI4Yocb1a/tFVkzmOE5WyYRgEBOyEhWYJe4gsDWDiwnjYKjNs7PS6SGlTDB7maOHF4kxevsuNBl2iOcj3b4A==", - "cpu": [ - "riscv64" - ], + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, - "optional": true, - "os": [ - "linux" - ] + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.27.3.tgz", - "integrity": "sha512-d4wVu6SXij/jyiwPvI6C4KxdGzuZOvJ6y9VfrcleHTwo68fl8vZC5ZYHsCVPUi4tndCfMlFniWgwonQ5CUpQcA==", - "cpu": [ - "s390x" - ], + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", "dev": true, "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": ">=14" + } }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.27.3.tgz", - "integrity": "sha512-/6bn6pp1fsCGEY5n3yajmzZQAh+mW4QPItbiWxs69zskBzJuheb3tNynEjL+mKOsUSFK11X4LYF2BwwXnzWleA==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.0.tgz", + "integrity": "sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==", "cpu": [ "x64" ], @@ -970,9 +485,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.27.3.tgz", - "integrity": "sha512-nBXOfJds8OzUT1qUreT/en3eyOXd2EH5b0wr2bVB5999qHdGKkzGzIyKYaKj02lXk6wpN71ltLIaQpu58YFBoQ==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.0.tgz", + "integrity": "sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ==", "cpu": [ "x64" ], @@ -982,43 +497,6 @@ "linux" ] }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.27.3.tgz", - "integrity": "sha512-ogfbEVQgIZOz5WPWXF2HVb6En+kWzScuxJo/WdQTqEgeyGkaa2ui5sQav9Zkr7bnNCLK48uxmmK0TySm22eiuw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.27.3.tgz", - "integrity": "sha512-ecE36ZBMLINqiTtSNQ1vzWc5pXLQHlf/oqGp/bSbi7iedcjcNb6QbCBNG73Euyy2C+l/fn8qKWEwxr+0SSfs3w==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.27.3.tgz", - "integrity": "sha512-vliZLrDmYKyaUoMzEbMTg2JkerfBjn03KmAw9CykO0Zzkzoyd7o3iZNam/TpyWNjNT+Cz2iO3P9Smv2wgrR+Eg==", - "cpu": [ - "x64" - ], - "os": [ - "win32" - ] - }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -1066,6 +544,17 @@ "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", "dev": true }, + "node_modules/@types/node": { + "version": "20.12.14", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.14.tgz", + "integrity": "sha512-scnD59RpYD91xngrQQLGkE+6UrHUPzeKZWhhjBSa3HSkwjbQc38+q3RoIVEwxQGRw3M+j5hpNAM+lgV3cVormg==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, "node_modules/@types/prop-types": { "version": "15.7.13", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz", @@ -1073,9 +562,9 @@ "devOptional": true }, "node_modules/@types/react": { - "version": "18.3.12", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.12.tgz", - "integrity": "sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==", + "version": "18.3.11", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.11.tgz", + "integrity": "sha512-r6QZ069rFTjrEYgFdOck1gK7FLVsgJE7tTz0pQBczlBNUhBNk0MQH4UbnFSwjpQLMkLzgqvBBa+qGpLje16eTQ==", "devOptional": true, "dependencies": { "@types/prop-types": "*", @@ -1083,18 +572,18 @@ } }, "node_modules/@types/react-dom": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.1.tgz", - "integrity": "sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==", + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", + "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", "dev": true, "dependencies": { "@types/react": "*" } }, "node_modules/@vitejs/plugin-react": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.3.3.tgz", - "integrity": "sha512-NooDe9GpHGqNns1i8XDERg0Vsg5SSYRhRxxyTGogUdkdNt47jal+fbuYi+Yfq6pzRCKXyoPcWisfxE6RIM3GKA==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.3.2.tgz", + "integrity": "sha512-hieu+o05v4glEBucTcKMK3dlES0OeJlD9YVOAPraVMOInBCwzumaIFiUjr4bHK7NPgnAHgiskUoceKercrN8vg==", "dev": true, "dependencies": { "@babel/core": "^7.25.2", @@ -1123,15 +612,15 @@ } }, "node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, - "engines": { - "node": ">=12" + "dependencies": { + "color-convert": "^1.9.0" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "engines": { + "node": ">=4" } }, "node_modules/any-promise": { @@ -1214,15 +703,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, "node_modules/braces": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", @@ -1236,9 +716,9 @@ } }, "node_modules/browserslist": { - "version": "4.24.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", - "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.0.tgz", + "integrity": "sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A==", "dev": true, "funding": [ { @@ -1255,10 +735,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001669", - "electron-to-chromium": "^1.5.41", + "caniuse-lite": "^1.0.30001663", + "electron-to-chromium": "^1.5.28", "node-releases": "^2.0.18", - "update-browserslist-db": "^1.1.1" + "update-browserslist-db": "^1.1.0" }, "bin": { "browserslist": "cli.js" @@ -1277,9 +757,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001682", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001682.tgz", - "integrity": "sha512-rJFwz3yRO6NU6Y8aEJKPzS4fngOE8j05pd33FW5Uk9v9b5StWNhGFeVpogwS2FFl78wNDGW5NsVvlwySPEDU5w==", + "version": "1.0.30001667", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001667.tgz", + "integrity": "sha512-7LTwJjcRkzKFmtqGsibMeuXmvFDfZq/nzIjnmgCGzKKRVzjD72selLDK1oPF/Oxzmt4fNcPvTDvGqSDG4tCALw==", "dev": true, "funding": [ { @@ -1296,6 +776,20 @@ } ] }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", @@ -1341,21 +835,18 @@ } }, "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" + "color-name": "1.1.3" } }, "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, "node_modules/commander": { @@ -1374,9 +865,9 @@ "dev": true }, "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, "dependencies": { "path-key": "^3.1.0", @@ -1441,9 +932,9 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.5.63", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.63.tgz", - "integrity": "sha512-ddeXKuY9BHo/mw145axlyWjlJ1UBt4WK3AlvkT7W2AbqfRQoacVoRUCF6wL3uIx/8wT9oLKXzI+rFqHHscByaA==", + "version": "1.5.33", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.33.tgz", + "integrity": "sha512-+cYTcFB1QqD4j4LegwLfpCNxifb6dDFUAwk6RsLusCwIaZI6or2f+q8rs5tTB2YC53HhOlIbEaqHMAAC8IOIwA==", "dev": true }, "node_modules/emoji-regex": { @@ -1499,6 +990,15 @@ "node": ">=6" } }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", @@ -1577,20 +1077,6 @@ "url": "https://github.com/sponsors/rawify" } }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -1649,10 +1135,34 @@ "node": ">=10.13.0" } }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "node_modules/glob/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, "engines": { "node": ">=4" @@ -1860,21 +1370,6 @@ "node": ">=8.6" } }, - "node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/minipass": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", @@ -2016,9 +1511,9 @@ } }, "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", + "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", "dev": true }, "node_modules/picomatch": { @@ -2052,9 +1547,9 @@ } }, "node_modules/postcss": { - "version": "8.4.49", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", - "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", + "version": "8.4.47", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", + "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", "dev": true, "funding": [ { @@ -2072,7 +1567,7 @@ ], "dependencies": { "nanoid": "^3.3.7", - "picocolors": "^1.1.1", + "picocolors": "^1.1.0", "source-map-js": "^1.2.1" }, "engines": { @@ -2334,9 +1829,9 @@ } }, "node_modules/rollup": { - "version": "4.27.3", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.27.3.tgz", - "integrity": "sha512-SLsCOnlmGt9VoZ9Ek8yBK8tAdmPHeppkw+Xa7yDlCEhDTvwYei03JlWo1fdc7YTfLZ4tD8riJCUyAgTbszk1fQ==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.0.tgz", + "integrity": "sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg==", "dev": true, "dependencies": { "@types/estree": "1.0.6" @@ -2349,24 +1844,22 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.27.3", - "@rollup/rollup-android-arm64": "4.27.3", - "@rollup/rollup-darwin-arm64": "4.27.3", - "@rollup/rollup-darwin-x64": "4.27.3", - "@rollup/rollup-freebsd-arm64": "4.27.3", - "@rollup/rollup-freebsd-x64": "4.27.3", - "@rollup/rollup-linux-arm-gnueabihf": "4.27.3", - "@rollup/rollup-linux-arm-musleabihf": "4.27.3", - "@rollup/rollup-linux-arm64-gnu": "4.27.3", - "@rollup/rollup-linux-arm64-musl": "4.27.3", - "@rollup/rollup-linux-powerpc64le-gnu": "4.27.3", - "@rollup/rollup-linux-riscv64-gnu": "4.27.3", - "@rollup/rollup-linux-s390x-gnu": "4.27.3", - "@rollup/rollup-linux-x64-gnu": "4.27.3", - "@rollup/rollup-linux-x64-musl": "4.27.3", - "@rollup/rollup-win32-arm64-msvc": "4.27.3", - "@rollup/rollup-win32-ia32-msvc": "4.27.3", - "@rollup/rollup-win32-x64-msvc": "4.27.3", + "@rollup/rollup-android-arm-eabi": "4.24.0", + "@rollup/rollup-android-arm64": "4.24.0", + "@rollup/rollup-darwin-arm64": "4.24.0", + "@rollup/rollup-darwin-x64": "4.24.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.24.0", + "@rollup/rollup-linux-arm-musleabihf": "4.24.0", + "@rollup/rollup-linux-arm64-gnu": "4.24.0", + "@rollup/rollup-linux-arm64-musl": "4.24.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.24.0", + "@rollup/rollup-linux-riscv64-gnu": "4.24.0", + "@rollup/rollup-linux-s390x-gnu": "4.24.0", + "@rollup/rollup-linux-x64-gnu": "4.24.0", + "@rollup/rollup-linux-x64-musl": "4.24.0", + "@rollup/rollup-win32-arm64-msvc": "4.24.0", + "@rollup/rollup-win32-ia32-msvc": "4.24.0", + "@rollup/rollup-win32-x64-msvc": "4.24.0", "fsevents": "~2.3.2" } }, @@ -2570,6 +2063,18 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", @@ -2583,33 +2088,33 @@ } }, "node_modules/tailwindcss": { - "version": "3.4.15", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.15.tgz", - "integrity": "sha512-r4MeXnfBmSOuKUWmXe6h2CcyfzJCEk4F0pptO5jlnYSIViUkVmsawj80N5h2lO3gwcmSb4n3PuN+e+GC1Guylw==", + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.13.tgz", + "integrity": "sha512-KqjHOJKogOUt5Bs752ykCeiwvi0fKVkr5oqsFNt/8px/tA8scFPIlkygsf6jXrfCqGHz7VflA6+yytWuM+XhFw==", "dev": true, "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", - "chokidar": "^3.6.0", + "chokidar": "^3.5.3", "didyoumean": "^1.2.2", "dlv": "^1.1.3", - "fast-glob": "^3.3.2", + "fast-glob": "^3.3.0", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", - "jiti": "^1.21.6", + "jiti": "^1.21.0", "lilconfig": "^2.1.0", - "micromatch": "^4.0.8", + "micromatch": "^4.0.5", "normalize-path": "^3.0.0", "object-hash": "^3.0.0", - "picocolors": "^1.1.1", - "postcss": "^8.4.47", + "picocolors": "^1.0.0", + "postcss": "^8.4.23", "postcss-import": "^15.1.0", "postcss-js": "^4.0.1", - "postcss-load-config": "^4.0.2", - "postcss-nested": "^6.2.0", - "postcss-selector-parser": "^6.1.2", - "resolve": "^1.22.8", - "sucrase": "^3.35.0" + "postcss-load-config": "^4.0.1", + "postcss-nested": "^6.0.1", + "postcss-selector-parser": "^6.0.11", + "resolve": "^1.22.2", + "sucrase": "^3.32.0" }, "bin": { "tailwind": "lib/cli.js", @@ -2640,6 +2145,15 @@ "node": ">=0.8" } }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -2671,6 +2185,14 @@ "node": ">=14.17" } }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true, + "optional": true, + "peer": true + }, "node_modules/update-browserslist-db": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", @@ -2716,9 +2238,9 @@ "dev": true }, "node_modules/vite": { - "version": "5.4.11", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.11.tgz", - "integrity": "sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==", + "version": "5.4.8", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.8.tgz", + "integrity": "sha512-FqrItQ4DT1NC4zCUqMB4c4AZORMKIa0m8/URVCZ77OZ/QSNeJ54bU1vrFADbDsuwfIPcgknRkmqakQcgnL4GiQ==", "dev": true, "dependencies": { "esbuild": "^0.21.3", @@ -2848,6 +2370,24 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/wrap-ansi-cjs/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -2880,6 +2420,18 @@ "node": ">=8" } }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", @@ -2887,9 +2439,9 @@ "dev": true }, "node_modules/yaml": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.1.tgz", - "integrity": "sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", + "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", "dev": true, "bin": { "yaml": "bin.mjs" diff --git a/package.json b/package.json index 1e27d5f..8c6f8f2 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "nx-working", "private": true, - "version": "1.0.0", + "version": "3.0.0", "type": "module", "scripts": { "dev": "vite", @@ -9,7 +9,6 @@ "preview": "vite preview" }, "dependencies": { - "@rollup/rollup-win32-x64-msvc": "^4.27.3", "clsx": "^2.1.0", "fuse.js": "^7.0.0", "lucide-react": "^0.344.0", diff --git a/src/App.tsx b/src/App.tsx index 25f701d..98f4c9b 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -2,12 +2,13 @@ import { useEffect, useState } from 'react'; import { ContentItem } from './types'; import { ContentTable } from './components/ContentTable'; import { TabNavigation } from './components/TabNavigation'; -import { StatsCard } from './components/StatsCard'; import { Header } from './components/Header'; import { SearchBar } from './components/SearchBar'; import { logger } from './utils/logger'; import { useSearch } from './hooks/useSearch'; import { useUserPreferences } from './store/userPreferences'; +import { sortByReleaseDate } from './utils/sorting'; +import { isValidDate } from './utils/dates'; interface WorkingJsonItem { "Game Name": string; @@ -19,96 +20,30 @@ interface WorkingJson { [key: string]: WorkingJsonItem; } -interface VersionsJson { - [titleId: string]: { - [version: string]: string; - }; -} - -function parseDate(dateStr: string | undefined): number { - if (!dateStr) return 0; - try { - const date = new Date(dateStr); - return isNaN(date.getTime()) ? 0 : date.getTime(); - } catch { - return 0; - } -} - -function getUpdateReleaseDate(titleId: string, version: string, versionsJson: VersionsJson): string | undefined { - const baseId = titleId.slice(0, -3) + '000'; - const versionInfo = versionsJson[baseId]; - - if (versionInfo) { - const versionParts = version.split('.').map(Number); - let versionNumber = 65536; - - if (versionParts.length >= 3) { - versionNumber = versionParts[0] * 65536 + versionParts[1] * 256 + versionParts[2]; - } - - return versionInfo[versionNumber.toString()]; - } - - return undefined; -} - -function processUpdates(baseId: string, versionsJson: VersionsJson): ContentItem[] { - const updates: ContentItem[] = []; - const versionInfo = versionsJson[baseId]; - - if (versionInfo) { - const updateId = baseId.slice(0, -3) + '800'; - - Object.entries(versionInfo).forEach(([versionNumber, releaseDate]) => { - const version = parseInt(versionNumber); - const major = Math.floor(version / 65536); - const minor = Math.floor((version % 65536) / 256); - const patch = version % 256; - - updates.push({ - id: updateId, - uniqueId: `${updateId}_${version}`, - type: 'update', - version: `${major}.${minor}.${patch}`, - releaseDate, - name: undefined, - size: undefined - }); - }); - } - - return updates; -} - -function sortByReleaseDate(items: ContentItem[]): ContentItem[] { - return [...items].sort((a, b) => { - const dateA = parseDate(a.releaseDate); - const dateB = parseDate(b.releaseDate); - - // Always put items without dates at the end - if (!dateA && !dateB) return 0; - if (!dateA) return 1; - if (!dateB) return -1; - - // Sort by date - if (dateA !== dateB) { - return dateB - dateA; // Descending order - } - - // If dates are equal, sort by name as secondary criteria - const nameA = a.name || 'Unknown Title'; - const nameB = b.name || 'Unknown Title'; - return nameA.localeCompare(nameB); - }); -} - export default function App() { - const { isDark, setDarkMode, itemsPerPage, lastActiveTab, setLastActiveTab, dataSources } = useUserPreferences(); + const { isDark, setDarkMode, itemsPerPage, lastActiveTab, setLastActiveTab } = useUserPreferences(); const [items, setItems] = useState([]); const [loading, setLoading] = useState(true); const [currentPage, setCurrentPage] = useState(1); - const { query, setQuery, results, sortField, sortDirection, toggleSort } = useSearch(items); + const { + nameQuery, + setNameQuery, + tidQuery, + setTidQuery, + results, + sortField, + sortDirection, + toggleSort + } = useSearch(items); + + useEffect(() => { + const root = document.documentElement; + if (isDark) { + root.classList.add('dark'); + } else { + root.classList.remove('dark'); + } + }, [isDark]); useEffect(() => { const loadData = async () => { @@ -116,12 +51,10 @@ export default function App() { setLoading(true); logger.info('Starting data load'); - // Fetch all data sources in parallel - const [workingResponse, titlesResponse, workingJsonResponse, versionsResponse] = await Promise.all([ - fetch(dataSources.workingContent), - fetch(dataSources.titlesDb), - fetch('https://raw.githubusercontent.com/ghost-land/NX-Missing/refs/heads/main/data/working.json'), - fetch('https://raw.githubusercontent.com/blawar/titledb/refs/heads/master/versions.json') + const [workingResponse, titlesResponse, workingJsonResponse] = await Promise.all([ + fetch('https://raw.githubusercontent.com/ghost-land/NX-Missing/refs/heads/main/data/working.txt'), + fetch('https://raw.githubusercontent.com/ghost-land/NX-Missing/refs/heads/main/data/titles_db.txt'), + fetch('https://raw.githubusercontent.com/ghost-land/NX-Missing/refs/heads/main/data/working.json') ]); const [workingText, titlesText] = await Promise.all([ @@ -129,10 +62,7 @@ export default function App() { titlesResponse.text() ]); - const [workingJson, versionsJson]: [WorkingJson, VersionsJson] = await Promise.all([ - workingJsonResponse.json(), - versionsResponse.json() - ]); + const workingJson: WorkingJson = await workingJsonResponse.json(); // Process titles database const titlesMap = new Map(titlesText.trim().split('\n').map(line => { @@ -140,19 +70,9 @@ export default function App() { return [id, { date, name, size: parseInt(size) }]; })); - // Process working content + // Process all items from working.txt const processedItems = new Map(); - const baseTitleIds = new Set(); - - // First pass: collect base title IDs and process working.txt entries - workingText.trim().split('\n').forEach(line => { - const [id] = line.split('|'); - if (id.endsWith('000')) { - baseTitleIds.add(id); - } - }); - // Second pass: process all content including updates from versions.json workingText.trim().split('\n').forEach(line => { const [id, version] = line.split('|'); const type = id.endsWith('800') ? 'update' as const : @@ -162,36 +82,19 @@ export default function App() { const titleInfo = titlesMap.get(id); const jsonInfo = workingJson[id]; - // Get release date based on content type - let releaseDate = titleInfo?.date; - if (type === 'update' && version) { - releaseDate = getUpdateReleaseDate(id, version, versionsJson) || releaseDate; - } - if (!processedItems.has(uniqueId)) { processedItems.set(uniqueId, { id, uniqueId, type, version: version || jsonInfo?.Version, - name: titleInfo?.name || jsonInfo?.["Game Name"] || 'Unknown Title', + name: jsonInfo?.["Game Name"] || titleInfo?.name || 'Unknown Title', size: titleInfo?.size || jsonInfo?.Size, - releaseDate + releaseDate: type === 'base' ? titleInfo?.date : undefined }); } }); - // Add all updates from versions.json - baseTitleIds.forEach(baseId => { - const updates = processUpdates(baseId, versionsJson); - updates.forEach(update => { - if (!processedItems.has(update.uniqueId)) { - processedItems.set(update.uniqueId, update); - } - }); - }); - - // Convert to array and sort by release date const sortedItems = sortByReleaseDate(Array.from(processedItems.values())); setItems(sortedItems); @@ -201,8 +104,8 @@ export default function App() { baseCount: sortedItems.filter(item => item.type === 'base').length, updateCount: sortedItems.filter(item => item.type === 'update').length, dlcCount: sortedItems.filter(item => item.type === 'dlc').length, - withDatesCount: sortedItems.filter(item => item.releaseDate).length, - withoutDatesCount: sortedItems.filter(item => !item.releaseDate).length + withDatesCount: sortedItems.filter(item => isValidDate(item.releaseDate)).length, + withoutDatesCount: sortedItems.filter(item => !isValidDate(item.releaseDate)).length }); } catch (error) { logger.error('Failed to load content data', { @@ -214,15 +117,18 @@ export default function App() { }; loadData(); - }, [dataSources]); + }, []); - useEffect(() => { - if (isDark) { - document.documentElement.classList.add('dark'); - } else { - document.documentElement.classList.remove('dark'); - } - }, [isDark]); + if (loading) { + return ( +
+
+
+

Loading games...

+
+
+ ); + } const filteredItems = results.filter(item => item.type === lastActiveTab); const totalPages = Math.ceil(filteredItems.length / itemsPerPage); @@ -237,47 +143,38 @@ export default function App() { dlc: items.filter(item => item.type === 'dlc').length }; - if (loading) { - return ( -
-
-
-

Loading games...

-
-
- ); - } - return (
setDarkMode(!isDark)} />
- setLastActiveTab('base')} - /> - setLastActiveTab('update')} - /> - setLastActiveTab('dlc')} - /> +
+

Base Games

+

+ {counts.base.toLocaleString()} +

+
+
+

Updates

+

+ {counts.update.toLocaleString()} +

+
+
+

DLCs

+

+ {counts.dlc.toLocaleString()} +

+
item.type === lastActiveTab).length} /> diff --git a/src/components/ContentTable.tsx b/src/components/ContentTable.tsx index 7ebfde9..74a4e9f 100644 --- a/src/components/ContentTable.tsx +++ b/src/components/ContentTable.tsx @@ -52,36 +52,43 @@ export function ContentTable({ ); }; - const renderSortHeader = (field: SortField, label: string) => ( - - - - ); + const renderSortHeader = (field: SortField, label: string, showForType?: 'base' | 'update' | 'dlc') => { + // Si showForType est spécifié et que tous les éléments ne sont pas de ce type, masquer la colonne + const shouldShow = !showForType || items.every(item => item.type === showForType); + if (!shouldShow) return null; + + return ( + + + + ); + }; + + // Vérifier si nous affichons des jeux de base + const showingBaseGames = items.length > 0 && items[0].type === 'base'; return (
@@ -95,7 +102,7 @@ export function ContentTable({ {renderSortHeader('id', 'Title ID')} {renderSortHeader('name', 'Name')} {renderSortHeader('size', 'Size')} - {renderSortHeader('releaseDate', 'Release Date')} + {showingBaseGames && renderSortHeader('releaseDate', 'Release Date', 'base')} Related Content @@ -105,7 +112,7 @@ export function ContentTable({ {items.map((item) => ( handleDetails(item.id)} className="group hover:bg-muted/50 active:bg-muted transition-colors cursor-pointer" > @@ -142,11 +149,13 @@ export function ContentTable({ {formatFileSize(item.size)}
- -
- {formatDate(item.releaseDate)} -
- + {showingBaseGames && ( + +
+ {formatDate(item.releaseDate)} +
+ + )} {getContentBadges(item.id)} diff --git a/src/components/ErrorLog.tsx b/src/components/ErrorLog.tsx index ed21a1f..45303af 100644 --- a/src/components/ErrorLog.tsx +++ b/src/components/ErrorLog.tsx @@ -1,11 +1,22 @@ import { useState, type ReactNode } from 'react'; -import { AlertTriangle, X } from 'lucide-react'; -import { logger, type LogEntry, type LogDetails } from '../utils/logger'; +import { AlertTriangle, X, FileText, AlertCircle, Info } from 'lucide-react'; +import { logger, type LogEntry, type LogDetails, type LogLevel } from '../utils/logger'; interface ErrorLogProps { onClose: () => void; } +function LogIcon({ level }: { level: LogLevel }) { + switch (level) { + case 'error': + return ; + case 'warn': + return ; + default: + return ; + } +} + function formatLogDetails(details: LogDetails): ReactNode { try { return ( @@ -34,28 +45,66 @@ export function ErrorLog({ onClose }: ErrorLogProps) {

Application Logs

- +
+ + +
-
+
+ +
{logs.length === 0 ? ( -

No logs to display

+
+ +

No logs to display

+
) : (
{logs.map((log: LogEntry, index) => ( @@ -63,21 +112,24 @@ export function ErrorLog({ onClose }: ErrorLogProps) { key={index} className={`p-3 rounded-lg border ${ log.level === 'error' - ? 'bg-red-500/10 border-red-500/20 text-red-500' + ? 'bg-red-500/10 border-red-500/20' : log.level === 'warn' - ? 'bg-yellow-500/10 border-yellow-500/20 text-yellow-500' - : 'bg-blue-500/10 border-blue-500/20 text-blue-500' + ? 'bg-yellow-500/10 border-yellow-500/20' + : 'bg-blue-500/10 border-blue-500/20' }`} >
- - {log.level.toUpperCase()} - - +
+ + + {log.level.toUpperCase()} + +
+ {new Date(log.timestamp).toLocaleString()}
-

{log.message}

+

{log.message}

{log.details && formatLogDetails(log.details)}
))} diff --git a/src/components/GameDetails.tsx b/src/components/GameDetails.tsx index 33ee0e9..bbbb90a 100644 --- a/src/components/GameDetails.tsx +++ b/src/components/GameDetails.tsx @@ -35,11 +35,6 @@ function ContentList({ items, maxVisible = 5, type }: ContentListProps) { Size: {formatFileSize(item.size)}

)} - {item.releaseDate && ( -

- Released: {formatDate(item.releaseDate)} -

- )}
))} {hasMore && ( diff --git a/src/components/Header.tsx b/src/components/Header.tsx index 809afea..1f7cb22 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -1,4 +1,4 @@ -import { useState } from 'react'; +import { useState, useEffect } from 'react'; import { Database, AlertTriangle, Sun, Moon, Settings as SettingsIcon } from 'lucide-react'; import { ErrorLog } from './ErrorLog'; import { Settings } from './Settings'; @@ -13,7 +13,21 @@ export function Header({ onToggleTheme }: HeaderProps) { const [showErrorLog, setShowErrorLog] = useState(false); const [showSettings, setShowSettings] = useState(false); const { isDark, showLogs } = useUserPreferences(); - const errorCount = logger.getErrorLogs().length; + const [errorCount, setErrorCount] = useState(0); + const [totalLogs, setTotalLogs] = useState(0); + + useEffect(() => { + const updateCounts = () => { + const errors = logger.getErrorLogs(); + const all = logger.getLogs(); + setErrorCount(errors.length); + setTotalLogs(all.length); + }; + + updateCounts(); + const interval = setInterval(updateCounts, 1000); + return () => clearInterval(interval); + }, []); return (
@@ -23,14 +37,23 @@ export function Header({ onToggleTheme }: HeaderProps) {

NX Working Content Tracker

-
- {showLogs && ( +
+ {showLogs && totalLogs > 0 && ( )} @@ -58,18 +81,10 @@ export function Header({ onToggleTheme }: HeaderProps) { href="https://github.com/ghost-land/NX-Working" target="_blank" rel="noopener noreferrer" - className="flex items-center space-x-2 px-3 py-1.5 rounded-lg hover:bg-muted transition-colors" + className="hidden sm:flex items-center space-x-2 px-3 py-1.5 rounded-lg hover:bg-muted transition-colors" > - - + + View on GitHub diff --git a/src/components/SearchBar.tsx b/src/components/SearchBar.tsx index 44f30d9..8d9ae90 100644 --- a/src/components/SearchBar.tsx +++ b/src/components/SearchBar.tsx @@ -1,43 +1,94 @@ import { Search, X } from 'lucide-react'; interface SearchBarProps { - value: string; - onChange: (value: string) => void; + nameQuery: string; + tidQuery: string; + onNameChange: (value: string) => void; + onTidChange: (value: string) => void; resultCount?: number; totalCount?: number; } -export function SearchBar({ value, onChange, resultCount, totalCount }: SearchBarProps) { +export function SearchBar({ + nameQuery, + tidQuery, + onNameChange, + onTidChange, + resultCount, + totalCount +}: SearchBarProps) { return ( -
-
- -
- onChange(e.target.value)} - className="block w-full pl-10 pr-24 py-3 bg-card border border-border rounded-lg - text-foreground placeholder-muted-foreground - focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent - hover:border-primary/50 transition-all duration-200" - placeholder="Search by Title ID or Name..." - /> -
- {resultCount !== undefined && totalCount !== undefined && ( - - {resultCount.toLocaleString()} / {totalCount.toLocaleString()} - +
+ {/* Name search */} +
+
+ +
+ onNameChange(e.target.value)} + className={` + block w-full pl-10 pr-10 py-3 bg-card border border-border rounded-lg + text-foreground placeholder-muted-foreground + focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent + hover:border-primary/50 transition-all duration-200 + ${nameQuery ? 'ring-2 ring-primary' : ''} + `} + placeholder="Search by name..." + /> + {nameQuery && ( + )} - {value && ( +
+ + {/* Title ID search */} +
+
+ +
+ { + const newValue = e.target.value.toUpperCase(); + if (newValue === '' || /^[0-9A-F]*$/.test(newValue)) { + onTidChange(newValue); + } + }} + maxLength={16} + className={` + block w-full pl-10 pr-10 py-3 bg-card border border-border rounded-lg + text-foreground placeholder-muted-foreground font-mono uppercase + focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent + hover:border-primary/50 transition-all duration-200 + ${tidQuery ? 'ring-2 ring-primary' : ''} + `} + placeholder="Search by Title ID..." + /> + {tidQuery && ( )}
+ + {/* Results counter */} + {resultCount !== undefined && totalCount !== undefined && ( +
+ + {resultCount.toLocaleString()} / {totalCount.toLocaleString()} + +
+ )}
); } \ No newline at end of file diff --git a/src/components/Settings.tsx b/src/components/Settings.tsx index a7eb591..7f895c9 100644 --- a/src/components/Settings.tsx +++ b/src/components/Settings.tsx @@ -11,8 +11,10 @@ export function Settings({ onClose }: SettingsProps) { const { itemsPerPage, setItemsPerPage, - searchPrecision, - setSearchPrecision, + namePrecision, + setNamePrecision, + tidPrecision, + setTidPrecision, showLogs, setShowLogs, showVersionHistory, @@ -28,10 +30,6 @@ export function Settings({ onClose }: SettingsProps) { resetDataSources } = useUserPreferences(); - const handlePrecisionChange = (value: string) => { - setSearchPrecision(parseFloat(value)); - }; - return (
@@ -43,13 +41,55 @@ export function Settings({ onClose }: SettingsProps) {
+ {/* Search Settings */} +
+

Search Settings

+ +
+ + setNamePrecision(parseFloat(e.target.value))} + className="w-full accent-primary" + /> +
+ Exact Match + Fuzzy Match +
+
+ +
+ + setTidPrecision(parseFloat(e.target.value))} + className="w-full accent-primary" + /> +
+ Exact Match + Partial Match +
+
+
+ {/* Display Settings */}

Display Settings

@@ -61,7 +101,7 @@ export function Settings({ onClose }: SettingsProps) {
+
+ + +
+ +
+ + +
+
- - {/* Search Settings */} -
-

Search Settings

-
- handlePrecisionChange(e.target.value)} - className="w-full accent-primary" - /> -
- Exact Match - Fuzzy Match -
-
- {searchPrecision <= 0.3 ? ( - "High precision: Requires almost exact matches" - ) : searchPrecision <= 0.6 ? ( - "Medium precision: Allows some typos and variations" - ) : ( - "Low precision: Very forgiving, finds similar matches" - )} -
-
-
- - {/* Feature Toggles */} -
-

Features

- -
-
- - -
- -
- - -
- -
- - -
+
@@ -230,7 +226,7 @@ export function Settings({ onClose }: SettingsProps) { type="url" value={dataSources.workingContent} onChange={(e) => setDataSource('workingContent', e.target.value)} - className="w-full bg-muted border border-border rounded-lg px-3 py-2 text-sm hover:border-primary/50 transition-colors" + className="w-full bg-muted border border-border rounded-lg px-3 py-2 text-sm" placeholder="Enter URL for working.txt" />
@@ -243,7 +239,7 @@ export function Settings({ onClose }: SettingsProps) { type="url" value={dataSources.titlesDb} onChange={(e) => setDataSource('titlesDb', e.target.value)} - className="w-full bg-muted border border-border rounded-lg px-3 py-2 text-sm hover:border-primary/50 transition-colors" + className="w-full bg-muted border border-border rounded-lg px-3 py-2 text-sm" placeholder="Enter URL for titles_db.txt" />
@@ -256,14 +252,6 @@ export function Settings({ onClose }: SettingsProps) { Reset to Defaults
- -
-

⚠️ Warning

-

- Modifying these URLs may affect the application's functionality. - Only change them if you know what you're doing. -

-
)} diff --git a/src/components/StatsCard.tsx b/src/components/StatsCard.tsx index 4a5392c..9d6cef8 100644 --- a/src/components/StatsCard.tsx +++ b/src/components/StatsCard.tsx @@ -1,28 +1,15 @@ -import { type MouseEventHandler } from 'react'; - interface StatsCardProps { title: string; count: number; - isActive?: boolean; - onClick?: MouseEventHandler; } -export function StatsCard({ title, count, isActive = false, onClick }: StatsCardProps) { +export function StatsCard({ title, count }: StatsCardProps) { return ( - +
); } \ No newline at end of file diff --git a/src/components/TabNavigation.tsx b/src/components/TabNavigation.tsx index 65565b2..35cdc82 100644 --- a/src/components/TabNavigation.tsx +++ b/src/components/TabNavigation.tsx @@ -3,9 +3,9 @@ import { Database, Download, Package } from 'lucide-react'; export function TabNavigation({ activeTab, onTabChange, counts }: TabNavigationProps) { const tabs = [ - { id: 'base' as const, name: 'Base Games', icon: Database, count: counts?.base ?? 0 }, - { id: 'update' as const, name: 'Updates', icon: Download, count: counts?.update ?? 0 }, - { id: 'dlc' as const, name: 'DLC', icon: Package, count: counts?.dlc ?? 0 }, + { id: 'base' as const, name: 'Base Games', icon: Database, count: counts.base }, + { id: 'update' as const, name: 'Updates', icon: Download, count: counts.update }, + { id: 'dlc' as const, name: 'DLC', icon: Package, count: counts.dlc }, ]; return ( @@ -19,21 +19,13 @@ export function TabNavigation({ activeTab, onTabChange, counts }: TabNavigationP flex-1 flex items-center justify-center py-3 px-4 rounded-md text-sm font-medium transition-all ${activeTab === id ? 'bg-primary text-primary-foreground shadow-sm' - : 'text-muted-foreground hover:text-foreground hover:bg-muted' + : 'text-muted-foreground hover:text-foreground hover:bg-muted/50' } `} > {name} - - {count.toLocaleString()} - + ({count.toLocaleString()}) ))} diff --git a/src/constants/dates.ts b/src/constants/dates.ts new file mode 100644 index 0000000..ba7d0b3 --- /dev/null +++ b/src/constants/dates.ts @@ -0,0 +1,20 @@ +export const DATE_FORMATS = [ + { + // ISO format: YYYY-MM-DD + pattern: /^(\d{4})-(\d{2})-(\d{2})(?:T|\s|$)/, + parse: (match: RegExpMatchArray) => new Date( + parseInt(match[1]), + parseInt(match[2]) - 1, + parseInt(match[3]) + ) + }, + { + // Compact format: YYYYMMDD + pattern: /^(\d{4})(\d{2})(\d{2})/, + parse: (match: RegExpMatchArray) => new Date( + parseInt(match[1]), + parseInt(match[2]) - 1, + parseInt(match[3]) + ) + } +]; \ No newline at end of file diff --git a/src/hooks/useSearch.ts b/src/hooks/useSearch.ts index 6a4d0d0..8ed6b52 100644 --- a/src/hooks/useSearch.ts +++ b/src/hooks/useSearch.ts @@ -1,129 +1,82 @@ import { useMemo, useState, useCallback } from 'react'; import Fuse from 'fuse.js'; -import { ContentItem, SearchOptions, SortField, SortDirection } from '../types'; +import { ContentItem, SortField, SortDirection } from '../types'; import { useUserPreferences } from '../store/userPreferences'; +import { sortItems } from '../utils/sorting'; -const getSearchOptions = (precision: number): SearchOptions => ({ - threshold: precision, - distance: Math.floor(100 * (1 + precision)), - minMatchCharLength: Math.max(2, Math.floor(4 * (1 - precision))), -}); - -function parseDate(dateStr: string | undefined): number { - if (!dateStr) return 0; - try { - const date = new Date(dateStr); - return isNaN(date.getTime()) ? 0 : date.getTime(); - } catch { - return 0; - } -} - -function sortItems(items: ContentItem[], field: SortField, direction: SortDirection): ContentItem[] { - return [...items].sort((a, b) => { - let comparison = 0; - - switch (field) { - case 'id': - comparison = (a.id || '').localeCompare(b.id || ''); - break; - - case 'name': { - const nameA = a.name || 'Unknown Title'; - const nameB = b.name || 'Unknown Title'; - - // Always put Unknown at the end regardless of sort direction - if (nameA === 'Unknown Title' && nameB !== 'Unknown Title') return 1; - if (nameB === 'Unknown Title' && nameA !== 'Unknown Title') return -1; - - comparison = nameA.localeCompare(nameB); - break; - } - - case 'releaseDate': { - const dateA = parseDate(a.releaseDate); - const dateB = parseDate(b.releaseDate); - - // Always put items without dates at the end - if (!dateA && !dateB) return 0; - if (!dateA) return 1; - if (!dateB) return 1; - - // Sort by date - if (dateA !== dateB) { - comparison = dateA - dateB; - } else { - // If dates are equal, sort by name as secondary criteria - const nameA = a.name || 'Unknown Title'; - const nameB = b.name || 'Unknown Title'; - comparison = nameA.localeCompare(nameB); - } - break; - } - - case 'size': { - const sizeA = a.size || 0; - const sizeB = b.size || 0; - - // Always put items without size at the end - if (sizeA === 0 && sizeB !== 0) return 1; - if (sizeB === 0 && sizeA !== 0) return -1; - - comparison = sizeA - sizeB; - break; - } - } - - return direction === 'asc' ? comparison : -comparison; - }); +function getSearchOptions(precision: number) { + return { + threshold: Math.max(0.1, 1 - precision), // Invert precision for better control + distance: Math.floor(30 * (1 - precision)), + minMatchCharLength: Math.max(2, Math.floor(4 * precision)), + location: 0, + ignoreLocation: false, + findAllMatches: true, + includeMatches: true, + useExtendedSearch: false, + isCaseSensitive: false, + tokenize: true, + matchAllTokens: false, + }; } export function useSearch(items: ContentItem[]) { - const [query, setQuery] = useState(''); - const [sortField, setSortField] = useState('releaseDate'); - const [sortDirection, setSortDirection] = useState('desc'); - const { searchPrecision } = useUserPreferences(); - - const searchOptions = useMemo(() => getSearchOptions(searchPrecision), [searchPrecision]); - + const [nameQuery, setNameQuery] = useState(''); + const [tidQuery, setTidQuery] = useState(''); + const [sortField, setSortField] = useState('name'); + const [sortDirection, setSortDirection] = useState('asc'); + const { namePrecision } = useUserPreferences(); + const fuse = useMemo(() => new Fuse(items, { - keys: [ - { name: 'id', weight: 2 }, - { name: 'name', weight: 1 } - ], - ...searchOptions, - shouldSort: false, - includeScore: true, - ignoreLocation: true, - useExtendedSearch: true, - getFn: (obj, path) => { - const value = obj[path as keyof ContentItem]; - return value?.toString() || ''; + keys: ['name'], + ...getSearchOptions(namePrecision) + }), [items, namePrecision]); + + const search = useCallback(() => { + let results = items; + + // Apply TID filter (exact match, case-insensitive) + if (tidQuery) { + const normalizedTid = tidQuery.toLowerCase(); + results = results.filter(item => + item.id.toLowerCase().includes(normalizedTid) + ); } - }), [items, searchOptions]); - - const search = useCallback((searchQuery: string) => { - if (!searchQuery) return items; - return fuse.search(searchQuery).map(result => result.item); - }, [fuse, items]); - const toggleSort = useCallback((field: SortField) => { - if (field === sortField) { - setSortDirection(current => current === 'asc' ? 'desc' : 'asc'); - } else { - setSortField(field); - setSortDirection('desc'); + // Apply name filter + if (nameQuery.trim()) { + const fuseResults = fuse.search(nameQuery); + const matchedItems = fuseResults.map(result => result.item); + + // If we already filtered by TID, intersect the results + if (tidQuery) { + const matchedIds = new Set(matchedItems.map(item => item.id)); + results = results.filter(item => matchedIds.has(item.id)); + } else { + results = matchedItems; + } } + + return results; + }, [fuse, items, nameQuery, tidQuery]); + + const toggleSort = useCallback((field: SortField) => { + setSortField(field); + setSortDirection(current => + field === sortField ? (current === 'asc' ? 'desc' : 'asc') : 'asc' + ); }, [sortField]); const results = useMemo(() => { - const searchResults = search(query); + const searchResults = search(); return sortItems(searchResults, sortField, sortDirection); - }, [search, query, sortField, sortDirection]); + }, [search, sortField, sortDirection]); return { - query, - setQuery, + nameQuery, + setNameQuery, + tidQuery, + setTidQuery, results, sortField, sortDirection, diff --git a/src/index.css b/src/index.css index a6ac67d..f1dd947 100644 --- a/src/index.css +++ b/src/index.css @@ -3,39 +3,39 @@ @tailwind utilities; :root { + color-scheme: light; --background: 255 255 255; --foreground: 15 23 42; - --muted: 241 245 249; --muted-foreground: 100 116 139; - --card: 255 255 255; --card-foreground: 15 23 42; - --border: 226 232 240; - --primary: 37 99 235; --primary-foreground: 255 255 255; } :root[class~="dark"] { + color-scheme: dark; --background: 15 23 42; --foreground: 226 232 240; - --muted: 30 41 59; --muted-foreground: 148 163 184; - --card: 30 41 59; --card-foreground: 226 232 240; - --border: 51 65 85; - --primary: 59 130 246; --primary-foreground: 255 255 255; } -body { - @apply antialiased bg-background text-foreground; +@layer base { + * { + @apply border-border; + } + body { + @apply bg-background text-foreground antialiased; + font-feature-settings: "rlig" 1, "calt" 1; + } } .icon-container { @@ -45,4 +45,63 @@ body { .icon-container img { @apply absolute inset-0 w-full h-full object-cover rounded-lg; aspect-ratio: 1/1; +} + +/* Mobile optimizations */ +@media (max-width: 640px) { + .icon-container { + @apply w-12 h-12; + } + + .content-table th, + .content-table td { + @apply px-2 py-2 text-sm; + } + + .content-table th:not(:first-child):not(:last-child), + .content-table td:not(:first-child):not(:last-child) { + @apply hidden; + } + + .pagination-controls { + @apply flex-col space-y-2; + } + + .pagination-controls select { + @apply w-full; + } + + .search-bar { + @apply flex-col space-y-2; + } + + .search-bar input { + @apply w-full; + } + + .stats-grid { + @apply grid-cols-1 gap-2; + } +} + +/* Tablet optimizations */ +@media (min-width: 641px) and (max-width: 1024px) { + .icon-container { + @apply w-14 h-14; + } + + .content-table th, + .content-table td { + @apply px-3 py-3; + } + + .stats-grid { + @apply grid-cols-2 gap-3; + } +} + +/* Ensure content is always visible */ +.overflow-container { + @apply overflow-x-auto -mx-4 px-4; + -webkit-overflow-scrolling: touch; } \ No newline at end of file diff --git a/src/store/userPreferences.ts b/src/store/userPreferences.ts index 6e79b61..3965fc2 100644 --- a/src/store/userPreferences.ts +++ b/src/store/userPreferences.ts @@ -1,101 +1,83 @@ import { create } from 'zustand'; -import { persist, createJSONStorage } from 'zustand/middleware'; - -interface DataSources { - workingContent: string; - titlesDb: string; -} +import { persist } from 'zustand/middleware'; interface UserPreferences { isDark: boolean; itemsPerPage: number; lastActiveTab: 'base' | 'update' | 'dlc'; - searchPrecision: number; + namePrecision: number; + tidPrecision: number; showLogs: boolean; showVersionHistory: boolean; autoRefreshInterval: number | null; maxDlcDisplay: number; maxUpdateDisplay: number; - dataSources: DataSources; + dataSources: { + workingContent: string; + titlesDb: string; + }; setDarkMode: (isDark: boolean) => void; setItemsPerPage: (count: number) => void; setLastActiveTab: (tab: 'base' | 'update' | 'dlc') => void; - setSearchPrecision: (precision: number) => void; + setNamePrecision: (precision: number) => void; + setTidPrecision: (precision: number) => void; setShowLogs: (show: boolean) => void; setShowVersionHistory: (show: boolean) => void; setAutoRefreshInterval: (interval: number | null) => void; setMaxDlcDisplay: (count: number) => void; setMaxUpdateDisplay: (count: number) => void; - setDataSource: (key: keyof DataSources, url: string) => void; + setDataSource: (key: 'workingContent' | 'titlesDb', url: string) => void; resetDataSources: () => void; } -const DEFAULT_DATA_SOURCES: DataSources = { +const DEFAULT_DATA_SOURCES = { workingContent: 'https://raw.githubusercontent.com/ghost-land/NX-Missing/refs/heads/main/data/working.txt', titlesDb: 'https://raw.githubusercontent.com/ghost-land/NX-Missing/refs/heads/main/data/titles_db.txt' }; -const initialState = { - isDark: window.matchMedia('(prefers-color-scheme: dark)').matches, - itemsPerPage: 25, - lastActiveTab: 'base' as const, - searchPrecision: 0.4, - showLogs: false, - showVersionHistory: true, - autoRefreshInterval: null, - maxDlcDisplay: 5, - maxUpdateDisplay: 5, - dataSources: DEFAULT_DATA_SOURCES, -}; - export const useUserPreferences = create()( persist( (set) => ({ - ...initialState, + isDark: window.matchMedia('(prefers-color-scheme: dark)').matches, + itemsPerPage: 25, + lastActiveTab: 'base', + namePrecision: 0.7, // Higher precision for name search + tidPrecision: 0.1, // Exact match for TID search + showLogs: true, // Show logs by default + showVersionHistory: true, + autoRefreshInterval: null, + maxDlcDisplay: 5, + maxUpdateDisplay: 5, + dataSources: DEFAULT_DATA_SOURCES, setDarkMode: (isDark) => set({ isDark }), setItemsPerPage: (itemsPerPage) => set({ itemsPerPage }), setLastActiveTab: (lastActiveTab) => set({ lastActiveTab }), - setSearchPrecision: (searchPrecision) => set({ searchPrecision }), + setNamePrecision: (namePrecision) => set({ namePrecision }), + setTidPrecision: (tidPrecision) => set({ tidPrecision }), setShowLogs: (showLogs) => set({ showLogs }), setShowVersionHistory: (showVersionHistory) => set({ showVersionHistory }), setAutoRefreshInterval: (autoRefreshInterval) => set({ autoRefreshInterval }), setMaxDlcDisplay: (maxDlcDisplay) => set({ maxDlcDisplay }), setMaxUpdateDisplay: (maxUpdateDisplay) => set({ maxUpdateDisplay }), setDataSource: (key, url) => set(state => ({ - dataSources: { - ...state.dataSources, - [key]: url - } + dataSources: { ...state.dataSources, [key]: url } })), resetDataSources: () => set({ dataSources: DEFAULT_DATA_SOURCES }), }), { name: 'nx-working-preferences', - version: 5, - storage: createJSONStorage(() => localStorage), - partialize: (state) => ({ - isDark: state.isDark, - itemsPerPage: state.itemsPerPage, - lastActiveTab: state.lastActiveTab, - searchPrecision: state.searchPrecision, - showLogs: state.showLogs, - showVersionHistory: state.showVersionHistory, - autoRefreshInterval: state.autoRefreshInterval, - maxDlcDisplay: state.maxDlcDisplay, - maxUpdateDisplay: state.maxUpdateDisplay, - dataSources: state.dataSources, - }), - migrate: (persistedState: any, version) => { - if (version < 5) { + version: 4, + migrate: (persistedState: any, version: number) => { + if (version < 4) { return { - ...initialState, ...persistedState, - maxDlcDisplay: 5, - maxUpdateDisplay: 5, + tidPrecision: 0.1, + namePrecision: 0.7, + showLogs: true }; } - return persistedState as UserPreferences; - }, + return persistedState; + } } ) ); \ No newline at end of file diff --git a/src/utils/dates.ts b/src/utils/dates.ts new file mode 100644 index 0000000..633bf86 --- /dev/null +++ b/src/utils/dates.ts @@ -0,0 +1,43 @@ +export function parseDate(dateStr: string | undefined): number { + if (!dateStr) return 0; + + try { + const date = new Date(dateStr); + return isNaN(date.getTime()) ? 0 : date.getTime(); + } catch { + return 0; + } +} + +export function formatDate(dateStr: string | undefined): string { + if (!dateStr) return 'Unknown'; + + try { + const date = new Date(dateStr); + if (isNaN(date.getTime())) return 'Unknown'; + + return new Intl.DateTimeFormat('en-US', { + year: 'numeric', + month: 'long', + day: 'numeric' + }).format(date); + } catch { + return 'Unknown'; + } +} + +export function isValidDate(dateStr: string | undefined): boolean { + if (!dateStr) return false; + + try { + const date = new Date(dateStr); + if (isNaN(date.getTime())) return false; + + // Ensure date is between 2000 and current year + 2 + const year = date.getFullYear(); + const currentYear = new Date().getFullYear(); + return year >= 2000 && year <= currentYear + 2; + } catch { + return false; + } +} \ No newline at end of file diff --git a/src/utils/formatters.ts b/src/utils/formatters.ts index 7c1ec7c..0abb6ed 100644 --- a/src/utils/formatters.ts +++ b/src/utils/formatters.ts @@ -19,12 +19,16 @@ export function formatFileSize(bytes?: number): string { return `${size.toFixed(2)} ${units[unitIndex]}`; } -export function formatDate(dateString?: string): string { - if (!dateString) return 'Unknown'; +export function formatDate(dateStr?: string): string { + if (!dateStr || !/^\d{4}-\d{2}-\d{2}/.test(dateStr)) { + return 'Unknown'; + } try { - const date = new Date(dateString); - if (isNaN(date.getTime())) return 'Unknown'; + const date = new Date(dateStr); + if (isNaN(date.getTime())) { + return 'Unknown'; + } return new Intl.DateTimeFormat('en-US', { year: 'numeric', diff --git a/src/utils/sorting.ts b/src/utils/sorting.ts new file mode 100644 index 0000000..d134ee5 --- /dev/null +++ b/src/utils/sorting.ts @@ -0,0 +1,119 @@ +import { ContentItem, SortField, SortDirection } from '../types'; + +function isValidDate(dateStr?: string): boolean { + if (!dateStr) return false; + const date = new Date(dateStr); + return !isNaN(date.getTime()); +} + +function getDateValue(item: ContentItem): number { + if (!item.releaseDate || !isValidDate(item.releaseDate)) return 0; + return new Date(item.releaseDate).getTime(); +} + +function compareItems(a: ContentItem, b: ContentItem, field: SortField): number { + switch (field) { + case 'releaseDate': { + // Only sort base games by release date + if (a.type !== 'base' || b.type !== 'base') { + return a.id.localeCompare(b.id); + } + + const dateA = getDateValue(a); + const dateB = getDateValue(b); + + // Both unknown dates - sort by ID + if (dateA === 0 && dateB === 0) { + return a.id.localeCompare(b.id); + } + + // Unknown dates go to the end + if (dateA === 0) return 1; + if (dateB === 0) return -1; + + // Sort by date, then by name if dates are equal + return dateA === dateB + ? (a.name || '').localeCompare(b.name || '') + : dateB - dateA; + } + + case 'name': { + const nameA = a.name || 'Unknown Title'; + const nameB = b.name || 'Unknown Title'; + + // Always put Unknown Title at the end + if (nameA === 'Unknown Title' && nameB !== 'Unknown Title') return 1; + if (nameB === 'Unknown Title' && nameA !== 'Unknown Title') return -1; + + return nameA.localeCompare(nameB); + } + + case 'size': { + const sizeA = a.size || 0; + const sizeB = b.size || 0; + + // Items without size go to the end + if (sizeA === 0 && sizeB !== 0) return 1; + if (sizeB === 0 && sizeA !== 0) return -1; + + return sizeB - sizeA; + } + + case 'id': + default: + return a.id.localeCompare(b.id); + } +} + +export function sortItems(items: ContentItem[], field: SortField, direction: SortDirection): ContentItem[] { + const sorted = [...items].sort((a, b) => { + const comparison = compareItems(a, b, field); + return direction === 'asc' ? comparison : -comparison; + }); + + // For release date sorting, ensure unknown dates are always at the end + if (field === 'releaseDate') { + const withDates = sorted.filter(item => isValidDate(item.releaseDate)); + const withoutDates = sorted.filter(item => !isValidDate(item.releaseDate)); + return direction === 'asc' + ? [...withDates, ...withoutDates] + : [...withDates, ...withoutDates]; + } + + return sorted; +} + +export function sortByReleaseDate(items: ContentItem[]): ContentItem[] { + // Separate items into base games with dates, base games without dates, and others + const baseWithDates = items.filter(item => + item.type === 'base' && isValidDate(item.releaseDate) + ); + const baseWithoutDates = items.filter(item => + item.type === 'base' && !isValidDate(item.releaseDate) + ); + const nonBaseItems = items.filter(item => item.type !== 'base'); + + // Sort base games with dates by date + const sortedBaseWithDates = baseWithDates.sort((a, b) => { + const dateA = getDateValue(a); + const dateB = getDateValue(b); + return dateA === dateB + ? (a.name || '').localeCompare(b.name || '') + : dateB - dateA; + }); + + // Sort other items by ID + const sortedBaseWithoutDates = baseWithoutDates.sort((a, b) => + a.id.localeCompare(b.id) + ); + const sortedNonBaseItems = nonBaseItems.sort((a, b) => + a.id.localeCompare(b.id) + ); + + // Combine all sorted arrays + return [ + ...sortedBaseWithDates, + ...sortedBaseWithoutDates, + ...sortedNonBaseItems + ]; +} \ No newline at end of file diff --git a/src/utils/updates.ts b/src/utils/updates.ts new file mode 100644 index 0000000..0265e3d --- /dev/null +++ b/src/utils/updates.ts @@ -0,0 +1 @@ +// File should be deleted entirely as it's no longer needed \ No newline at end of file diff --git a/src/utils/versions.ts b/src/utils/versions.ts new file mode 100644 index 0000000..0265e3d --- /dev/null +++ b/src/utils/versions.ts @@ -0,0 +1 @@ +// File should be deleted entirely as it's no longer needed \ No newline at end of file diff --git a/tailwind.config.js b/tailwind.config.js index 2f73add..fd83148 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -18,6 +18,12 @@ export default { primary: 'rgb(var(--primary) / )', 'primary-foreground': 'rgb(var(--primary-foreground) / )', }, + screens: { + 'xs': '475px', + }, + maxWidth: { + '8xl': '88rem', + }, }, }, plugins: [],