diff --git a/frontend/package-lock.json b/frontend/package-lock.json index bfc24c17f..f19cbab4d 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -9,12 +9,12 @@ "version": "1.0.0", "license": "GPL-3", "dependencies": { - "@mantine/core": "^6.0.21", - "@mantine/dropzone": "^6.0.21", - "@mantine/form": "^6.0.21", - "@mantine/hooks": "^6.0.21", - "@mantine/modals": "^6.0.21", - "@mantine/notifications": "^6.0.21", + "@mantine/core": "^7.10.1", + "@mantine/dropzone": "^7.10.1", + "@mantine/form": "^7.10.1", + "@mantine/hooks": "^7.10.1", + "@mantine/modals": "^7.10.1", + "@mantine/notifications": "^7.10.1", "axios": "^1.6.8", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -49,6 +49,8 @@ "husky": "^9.0.11", "jsdom": "^24.0.0", "lodash": "^4.17.21", + "postcss-preset-mantine": "^1.14.4", + "postcss-simple-vars": "^7.0.1", "prettier": "^3.2.5", "prettier-plugin-organize-imports": "^3.2.4", "pretty-quick": "^4.0.0", @@ -94,6 +96,7 @@ "version": "7.24.2", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", + "dev": true, "dependencies": { "@babel/highlight": "^7.24.2", "picocolors": "^1.0.0" @@ -335,6 +338,7 @@ "version": "7.24.3", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz", "integrity": "sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==", + "dev": true, "dependencies": { "@babel/types": "^7.24.0" }, @@ -456,6 +460,7 @@ "version": "7.24.1", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz", "integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==", + "dev": true, "engines": { "node": ">=6.9.0" } @@ -464,6 +469,7 @@ "version": "7.22.20", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "dev": true, "engines": { "node": ">=6.9.0" } @@ -509,6 +515,7 @@ "version": "7.24.2", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.2.tgz", "integrity": "sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==", + "dev": true, "dependencies": { "@babel/helper-validator-identifier": "^7.22.20", "chalk": "^2.4.2", @@ -523,6 +530,7 @@ "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, "dependencies": { "color-convert": "^1.9.0" }, @@ -534,6 +542,7 @@ "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", @@ -547,6 +556,7 @@ "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.3" } @@ -554,12 +564,14 @@ "node_modules/@babel/highlight/node_modules/color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true }, "node_modules/@babel/highlight/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" } @@ -568,6 +580,7 @@ "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" } @@ -576,6 +589,7 @@ "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" }, @@ -2193,6 +2207,7 @@ "version": "7.24.0", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", + "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.23.4", "@babel/helper-validator-identifier": "^7.22.20", @@ -2208,120 +2223,6 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, - "node_modules/@emotion/babel-plugin": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz", - "integrity": "sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==", - "peer": true, - "dependencies": { - "@babel/helper-module-imports": "^7.16.7", - "@babel/runtime": "^7.18.3", - "@emotion/hash": "^0.9.1", - "@emotion/memoize": "^0.8.1", - "@emotion/serialize": "^1.1.2", - "babel-plugin-macros": "^3.1.0", - "convert-source-map": "^1.5.0", - "escape-string-regexp": "^4.0.0", - "find-root": "^1.1.0", - "source-map": "^0.5.7", - "stylis": "4.2.0" - } - }, - "node_modules/@emotion/cache": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.11.0.tgz", - "integrity": "sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==", - "peer": true, - "dependencies": { - "@emotion/memoize": "^0.8.1", - "@emotion/sheet": "^1.2.2", - "@emotion/utils": "^1.2.1", - "@emotion/weak-memoize": "^0.3.1", - "stylis": "4.2.0" - } - }, - "node_modules/@emotion/hash": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", - "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==", - "peer": true - }, - "node_modules/@emotion/memoize": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", - "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==", - "peer": true - }, - "node_modules/@emotion/react": { - "version": "11.11.4", - "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.4.tgz", - "integrity": "sha512-t8AjMlF0gHpvvxk5mAtCqR4vmxiGHCeJBaQO6gncUSdklELOgtwjerNY2yuJNfwnc6vi16U/+uMF+afIawJ9iw==", - "peer": true, - "dependencies": { - "@babel/runtime": "^7.18.3", - "@emotion/babel-plugin": "^11.11.0", - "@emotion/cache": "^11.11.0", - "@emotion/serialize": "^1.1.3", - "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", - "@emotion/utils": "^1.2.1", - "@emotion/weak-memoize": "^0.3.1", - "hoist-non-react-statics": "^3.3.1" - }, - "peerDependencies": { - "react": ">=16.8.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@emotion/serialize": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.4.tgz", - "integrity": "sha512-RIN04MBT8g+FnDwgvIUi8czvr1LU1alUMI05LekWB5DGyTm8cCBMCRpq3GqaiyEDRptEXOyXnvZ58GZYu4kBxQ==", - "peer": true, - "dependencies": { - "@emotion/hash": "^0.9.1", - "@emotion/memoize": "^0.8.1", - "@emotion/unitless": "^0.8.1", - "@emotion/utils": "^1.2.1", - "csstype": "^3.0.2" - } - }, - "node_modules/@emotion/sheet": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.2.tgz", - "integrity": "sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==", - "peer": true - }, - "node_modules/@emotion/unitless": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", - "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==", - "peer": true - }, - "node_modules/@emotion/use-insertion-effect-with-fallbacks": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz", - "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==", - "peer": true, - "peerDependencies": { - "react": ">=16.8.0" - } - }, - "node_modules/@emotion/utils": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz", - "integrity": "sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==", - "peer": true - }, - "node_modules/@emotion/weak-memoize": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz", - "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==", - "peer": true - }, "node_modules/@esbuild/aix-ppc64": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", @@ -2791,13 +2692,13 @@ } }, "node_modules/@floating-ui/react": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.19.2.tgz", - "integrity": "sha512-JyNk4A0Ezirq8FlXECvRtQOX/iBe5Ize0W/pLkrZjfHW9GUV7Xnq6zm6fyZuQzaHHqEnVizmvlA96e1/CkZv+w==", + "version": "0.26.12", + "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.12.tgz", + "integrity": "sha512-D09o62HrWdIkstF2kGekIKAC0/N/Dl6wo3CQsnLcOmO3LkW6Ik8uIb3kw8JYkwxNCcg+uJ2bpWUiIijTBep05w==", "dependencies": { - "@floating-ui/react-dom": "^1.3.0", - "aria-hidden": "^1.1.3", - "tabbable": "^6.0.1" + "@floating-ui/react-dom": "^2.0.0", + "@floating-ui/utils": "^0.2.0", + "tabbable": "^6.0.0" }, "peerDependencies": { "react": ">=16.8.0", @@ -2805,11 +2706,11 @@ } }, "node_modules/@floating-ui/react-dom": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-1.3.0.tgz", - "integrity": "sha512-htwHm67Ji5E/pROEAr7f8IKFShuiCKHwUC/UY4vC3I5jiSvGFAYnSYiZO5MlGmads+QqvUkR9ANHEguGrDv72g==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.0.8.tgz", + "integrity": "sha512-HOdqOt3R3OGeTKidaLvJKcgg75S6tibQ3Tif4eyd91QnIJWr0NLvoXFpJA/j8HqkFSL68GDca9AuyWEHlhyClw==", "dependencies": { - "@floating-ui/dom": "^1.2.1" + "@floating-ui/dom": "^1.6.1" }, "peerDependencies": { "react": ">=16.8.0", @@ -3034,120 +2935,107 @@ } }, "node_modules/@mantine/core": { - "version": "6.0.21", - "resolved": "https://registry.npmjs.org/@mantine/core/-/core-6.0.21.tgz", - "integrity": "sha512-Kx4RrRfv0I+cOCIcsq/UA2aWcYLyXgW3aluAuW870OdXnbII6qg7RW28D+r9D76SHPxWFKwIKwmcucAG08Divg==", + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@mantine/core/-/core-7.10.1.tgz", + "integrity": "sha512-l9ypojKN3PjwO1CSLIsqxi7mA25+7w+xc71Q+JuCCREI0tuGwkZsKbIOpuTATIJOjPh8ycLiW7QxX1LYsRTq6w==", + "license": "MIT", "dependencies": { - "@floating-ui/react": "^0.19.1", - "@mantine/styles": "6.0.21", - "@mantine/utils": "6.0.21", - "@radix-ui/react-scroll-area": "1.0.2", - "react-remove-scroll": "^2.5.5", - "react-textarea-autosize": "8.3.4" + "@floating-ui/react": "^0.26.9", + "clsx": "^2.1.1", + "react-number-format": "^5.3.1", + "react-remove-scroll": "^2.5.7", + "react-textarea-autosize": "8.5.3", + "type-fest": "^4.12.0" }, "peerDependencies": { - "@mantine/hooks": "6.0.21", - "react": ">=16.8.0", - "react-dom": ">=16.8.0" + "@mantine/hooks": "7.10.1", + "react": "^18.2.0", + "react-dom": "^18.2.0" + } + }, + "node_modules/@mantine/core/node_modules/type-fest": { + "version": "4.15.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.15.0.tgz", + "integrity": "sha512-tB9lu0pQpX5KJq54g+oHOLumOx+pMep4RaM6liXh2PKmVRFF+/vAtUP0ZaJ0kOySfVNjF6doBWPHhBhISKdlIA==", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/@mantine/dropzone": { - "version": "6.0.21", - "resolved": "https://registry.npmjs.org/@mantine/dropzone/-/dropzone-6.0.21.tgz", - "integrity": "sha512-v63tL4x7R1CvBNnxJVaVPhBVnQcfROQvyOV0xK/v0ZGNAzFxjJoiCRMGdlBjxnEawM0dRhNs/46ItpBgjQIr6g==", + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@mantine/dropzone/-/dropzone-7.10.1.tgz", + "integrity": "sha512-WzOLwMf8RJtakivPzSYBy3ZLuCtsZEbkJpAXNmM5PdsA8s9MKmY3jYA1MuZis1/NStAGm1d4twofH1KjGCMphg==", + "license": "MIT", "dependencies": { - "@mantine/utils": "6.0.21", - "react-dropzone": "14.2.3" + "react-dropzone-esm": "15.0.1" }, "peerDependencies": { - "@mantine/core": "6.0.21", - "@mantine/hooks": "6.0.21", - "react": ">=16.8.0", - "react-dom": ">=16.8.0" + "@mantine/core": "7.10.1", + "@mantine/hooks": "7.10.1", + "react": "^18.2.0", + "react-dom": "^18.2.0" } }, "node_modules/@mantine/form": { - "version": "6.0.21", - "resolved": "https://registry.npmjs.org/@mantine/form/-/form-6.0.21.tgz", - "integrity": "sha512-d4tlxyZic7MSDnaPx/WliCX1sRFDkUd2nxx4MxxO2T4OSek0YDqTlSBCxeoveu60P+vrQQN5rbbsVsaOJBe4SQ==", + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@mantine/form/-/form-7.10.1.tgz", + "integrity": "sha512-mZwzg4GEWKEDKEIZu9FmSpGFzYYhFD2YArVOXUM0MMciUqX7yxSCon1PaPJxrV8ldc6FE+JLVI2+G2KVxJ3ZXA==", + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", - "klona": "^2.0.5" + "klona": "^2.0.6" }, "peerDependencies": { - "react": ">=16.8.0" + "react": "^18.2.0" } }, "node_modules/@mantine/hooks": { - "version": "6.0.21", - "resolved": "https://registry.npmjs.org/@mantine/hooks/-/hooks-6.0.21.tgz", - "integrity": "sha512-sYwt5wai25W6VnqHbS5eamey30/HD5dNXaZuaVEAJ2i2bBv8C0cCiczygMDpAFiSYdXoSMRr/SZ2CrrPTzeNew==", + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@mantine/hooks/-/hooks-7.10.1.tgz", + "integrity": "sha512-0EH9WBWUdtQLGU3Ak+csQ77EtUxI6pPNfwZdRJQWcaA3f8SFOLo9h9CGxiikFExerhvuCeUlaTf3s+TB9Op/rw==", + "license": "MIT", "peerDependencies": { - "react": ">=16.8.0" + "react": "^18.2.0" } }, "node_modules/@mantine/modals": { - "version": "6.0.21", - "resolved": "https://registry.npmjs.org/@mantine/modals/-/modals-6.0.21.tgz", - "integrity": "sha512-Gx2D/ZHMUuYF197JKMWey4K9FeGP9rxYp4lmAEXUrjXiST2fEhLZOdiD75KuOHXd1/sYAU9NcNRo9wXrlF/gUA==", - "dependencies": { - "@mantine/utils": "6.0.21" - }, + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@mantine/modals/-/modals-7.10.1.tgz", + "integrity": "sha512-2riQSNpVV7f0baizlqcggz9hx9/+y6SQTnW3zEkl/RIkuyK9dpeMFUG6M+M8ntwP79b7x9n7Em9PMWxRbgi28A==", + "license": "MIT", "peerDependencies": { - "@mantine/core": "6.0.21", - "@mantine/hooks": "6.0.21", - "react": ">=16.8.0", - "react-dom": ">=16.8.0" + "@mantine/core": "7.10.1", + "@mantine/hooks": "7.10.1", + "react": "^18.2.0", + "react-dom": "^18.2.0" } }, "node_modules/@mantine/notifications": { - "version": "6.0.21", - "resolved": "https://registry.npmjs.org/@mantine/notifications/-/notifications-6.0.21.tgz", - "integrity": "sha512-qsrqxuJHK8b67sf9Pfk+xyhvpf9jMsivW8vchfnJfjv7yz1lLvezjytMFp4fMDoYhjHnDPOEc/YFockK4muhOw==", + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@mantine/notifications/-/notifications-7.10.1.tgz", + "integrity": "sha512-cx3JR3BJzEzH6t2EF1ysrWVY/rdJk0WbSBQo/qFamJd2sbU+8XAHriI8Cx6hNo7uRGCwd8VGAj7Cf3aWK2VC5A==", + "license": "MIT", "dependencies": { - "@mantine/utils": "6.0.21", - "react-transition-group": "4.4.2" + "@mantine/store": "7.10.1", + "react-transition-group": "4.4.5" }, "peerDependencies": { - "@mantine/core": "6.0.21", - "@mantine/hooks": "6.0.21", - "react": ">=16.8.0", - "react-dom": ">=16.8.0" - } - }, - "node_modules/@mantine/styles": { - "version": "6.0.21", - "resolved": "https://registry.npmjs.org/@mantine/styles/-/styles-6.0.21.tgz", - "integrity": "sha512-PVtL7XHUiD/B5/kZ/QvZOZZQQOj12QcRs3Q6nPoqaoPcOX5+S7bMZLMH0iLtcGq5OODYk0uxlvuJkOZGoPj8Mg==", - "dependencies": { - "clsx": "1.1.1", - "csstype": "3.0.9" - }, - "peerDependencies": { - "@emotion/react": ">=11.9.0", - "react": ">=16.8.0", - "react-dom": ">=16.8.0" - } - }, - "node_modules/@mantine/styles/node_modules/clsx": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz", - "integrity": "sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==", - "engines": { - "node": ">=6" + "@mantine/core": "7.10.1", + "@mantine/hooks": "7.10.1", + "react": "^18.2.0", + "react-dom": "^18.2.0" } }, - "node_modules/@mantine/styles/node_modules/csstype": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.9.tgz", - "integrity": "sha512-rpw6JPxK6Rfg1zLOYCSwle2GFOOsnjmDYDaBwEcwoOg4qlsIVCN789VkBZDJAGi4T07gI4YSutR43t9Zz4Lzuw==" - }, - "node_modules/@mantine/utils": { - "version": "6.0.21", - "resolved": "https://registry.npmjs.org/@mantine/utils/-/utils-6.0.21.tgz", - "integrity": "sha512-33RVDRop5jiWFao3HKd3Yp7A9mEq4HAJxJPTuYm1NkdqX6aTKOQK7wT8v8itVodBp+sb4cJK6ZVdD1UurK/txQ==", + "node_modules/@mantine/store": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@mantine/store/-/store-7.10.1.tgz", + "integrity": "sha512-KrGBsSoMsfrYeLxPwf5rFv0s2Nl/4wf+AaF/U1SpQrMgPI8vYokPXx52Wp3jCmlo12NCZnCIG+/6YHAdTWH1qQ==", + "license": "MIT", "peerDependencies": { - "react": ">=16.8.0" + "react": "^18.2.0" } }, "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { @@ -3222,137 +3110,6 @@ "integrity": "sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==", "dev": true }, - "node_modules/@radix-ui/number": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.0.0.tgz", - "integrity": "sha512-Ofwh/1HX69ZfJRiRBMTy7rgjAzHmwe4kW9C9Y99HTRUcYLUuVT0KESFj15rPjRgKJs20GPq8Bm5aEDJ8DuA3vA==", - "dependencies": { - "@babel/runtime": "^7.13.10" - } - }, - "node_modules/@radix-ui/primitive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.0.0.tgz", - "integrity": "sha512-3e7rn8FDMin4CgeL7Z/49smCA3rFYY3Ha2rUQ7HRWFadS5iCRw08ZgVT1LaNTCNqgvrUiyczLflrVrF0SRQtNA==", - "dependencies": { - "@babel/runtime": "^7.13.10" - } - }, - "node_modules/@radix-ui/react-compose-refs": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.0.tgz", - "integrity": "sha512-0KaSv6sx787/hK3eF53iOkiSLwAGlFMx5lotrqD2pTjB18KbybKoEIgkNZTKC60YECDQTKGTRcDBILwZVqVKvA==", - "dependencies": { - "@babel/runtime": "^7.13.10" - }, - "peerDependencies": { - "react": "^16.8 || ^17.0 || ^18.0" - } - }, - "node_modules/@radix-ui/react-context": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.0.0.tgz", - "integrity": "sha512-1pVM9RfOQ+n/N5PJK33kRSKsr1glNxomxONs5c49MliinBY6Yw2Q995qfBUUo0/Mbg05B/sGA0gkgPI7kmSHBg==", - "dependencies": { - "@babel/runtime": "^7.13.10" - }, - "peerDependencies": { - "react": "^16.8 || ^17.0 || ^18.0" - } - }, - "node_modules/@radix-ui/react-direction": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.0.0.tgz", - "integrity": "sha512-2HV05lGUgYcA6xgLQ4BKPDmtL+QbIZYH5fCOTAOOcJ5O0QbWS3i9lKaurLzliYUDhORI2Qr3pyjhJh44lKA3rQ==", - "dependencies": { - "@babel/runtime": "^7.13.10" - }, - "peerDependencies": { - "react": "^16.8 || ^17.0 || ^18.0" - } - }, - "node_modules/@radix-ui/react-presence": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.0.0.tgz", - "integrity": "sha512-A+6XEvN01NfVWiKu38ybawfHsBjWum42MRPnEuqPsBZ4eV7e/7K321B5VgYMPv3Xx5An6o1/l9ZuDBgmcmWK3w==", - "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-compose-refs": "1.0.0", - "@radix-ui/react-use-layout-effect": "1.0.0" - }, - "peerDependencies": { - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" - } - }, - "node_modules/@radix-ui/react-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-1.0.1.tgz", - "integrity": "sha512-fHbmislWVkZaIdeF6GZxF0A/NH/3BjrGIYj+Ae6eTmTCr7EB0RQAAVEiqsXK6p3/JcRqVSBQoceZroj30Jj3XA==", - "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-slot": "1.0.1" - }, - "peerDependencies": { - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" - } - }, - "node_modules/@radix-ui/react-scroll-area": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.0.2.tgz", - "integrity": "sha512-k8VseTxI26kcKJaX0HPwkvlNBPTs56JRdYzcZ/vzrNUkDlvXBy8sMc7WvCpYzZkHgb+hd72VW9MqkqecGtuNgg==", - "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/number": "1.0.0", - "@radix-ui/primitive": "1.0.0", - "@radix-ui/react-compose-refs": "1.0.0", - "@radix-ui/react-context": "1.0.0", - "@radix-ui/react-direction": "1.0.0", - "@radix-ui/react-presence": "1.0.0", - "@radix-ui/react-primitive": "1.0.1", - "@radix-ui/react-use-callback-ref": "1.0.0", - "@radix-ui/react-use-layout-effect": "1.0.0" - }, - "peerDependencies": { - "react": "^16.8 || ^17.0 || ^18.0", - "react-dom": "^16.8 || ^17.0 || ^18.0" - } - }, - "node_modules/@radix-ui/react-slot": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.1.tgz", - "integrity": "sha512-avutXAFL1ehGvAXtPquu0YK5oz6ctS474iM3vNGQIkswrVhdrS52e3uoMQBzZhNRAIE0jBnUyXWNmSjGHhCFcw==", - "dependencies": { - "@babel/runtime": "^7.13.10", - "@radix-ui/react-compose-refs": "1.0.0" - }, - "peerDependencies": { - "react": "^16.8 || ^17.0 || ^18.0" - } - }, - "node_modules/@radix-ui/react-use-callback-ref": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.0.tgz", - "integrity": "sha512-GZtyzoHz95Rhs6S63D2t/eqvdFCm7I+yHMLVQheKM7nBD8mbZIt+ct1jz4536MDnaOGKIxynJ8eHTkVGVVkoTg==", - "dependencies": { - "@babel/runtime": "^7.13.10" - }, - "peerDependencies": { - "react": "^16.8 || ^17.0 || ^18.0" - } - }, - "node_modules/@radix-ui/react-use-layout-effect": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.0.0.tgz", - "integrity": "sha512-6Tpkq+R6LOlmQb1R5NNETLG0B4YP0wc+klfXafpUCj6JGyaUc8il7/kUZ7m59rGbXGczE9Bs+iz2qloqsZBduQ==", - "dependencies": { - "@babel/runtime": "^7.13.10" - }, - "peerDependencies": { - "react": "^16.8 || ^17.0 || ^18.0" - } - }, "node_modules/@remix-run/router": { "version": "1.15.3", "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.15.3.tgz", @@ -3899,7 +3656,8 @@ "node_modules/@types/parse-json": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", - "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==" + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", + "dev": true }, "node_modules/@types/prop-types": { "version": "15.7.12", @@ -4640,17 +4398,6 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, - "node_modules/aria-hidden": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.4.tgz", - "integrity": "sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==", - "dependencies": { - "tslib": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/aria-query": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", @@ -4848,14 +4595,6 @@ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, - "node_modules/attr-accept": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/attr-accept/-/attr-accept-2.2.2.tgz", - "integrity": "sha512-7prDjvt9HmqiZ0cl5CRjtS84sEyhsHP2coDkaZKRKVfCDo9s7iw7ChVmar78Gu9pC4SoR/28wFu/G5JJhTnqEg==", - "engines": { - "node": ">=4" - } - }, "node_modules/available-typed-arrays": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", @@ -4903,6 +4642,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "dev": true, "dependencies": { "@babel/runtime": "^7.12.5", "cosmiconfig": "^7.0.0", @@ -5107,10 +4847,20 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, "engines": { "node": ">=6" } }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/caniuse-lite": { "version": "1.0.30001607", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001607.tgz", @@ -5229,10 +4979,10 @@ } }, "node_modules/clsx": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.0.tgz", - "integrity": "sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==", - "dev": true, + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", "engines": { "node": ">=6" } @@ -5286,12 +5036,6 @@ "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==", "dev": true }, - "node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "peer": true - }, "node_modules/core-js-compat": { "version": "3.36.1", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.36.1.tgz", @@ -5309,6 +5053,7 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "dev": true, "dependencies": { "@types/parse-json": "^4.0.0", "import-fresh": "^3.2.1", @@ -5324,6 +5069,7 @@ "version": "1.10.2", "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, "engines": { "node": ">= 6" } @@ -5348,6 +5094,18 @@ "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", "dev": true }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/cssstyle": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.0.1.tgz", @@ -5779,6 +5537,7 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, "dependencies": { "is-arrayish": "^0.2.1" } @@ -5992,6 +5751,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, "engines": { "node": ">=10" }, @@ -6606,17 +6366,6 @@ "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/file-selector": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/file-selector/-/file-selector-0.6.0.tgz", - "integrity": "sha512-QlZ5yJC0VxHxQQsQhXvBaC7VRJ2uaxTf+Tfpu4Z/OcVQJVpZO+DGU0rkoVW5ce2SccxugvpBJoMvUs59iILYdw==", - "dependencies": { - "tslib": "^2.4.0" - }, - "engines": { - "node": ">= 12" - } - }, "node_modules/fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -6629,12 +6378,6 @@ "node": ">=8" } }, - "node_modules/find-root": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", - "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", - "peer": true - }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -6758,6 +6501,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -7035,6 +6779,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, "dependencies": { "function-bind": "^1.1.2" }, @@ -7042,15 +6787,6 @@ "node": ">= 0.4" } }, - "node_modules/hoist-non-react-statics": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", - "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", - "peer": true, - "dependencies": { - "react-is": "^16.7.0" - } - }, "node_modules/html-encoding-sniffer": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", @@ -7150,6 +6886,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -7243,7 +6980,8 @@ "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true }, "node_modules/is-async-function": { "version": "2.0.0", @@ -7316,6 +7054,7 @@ "version": "2.13.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dev": true, "dependencies": { "hasown": "^2.0.0" }, @@ -7934,7 +7673,8 @@ "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true }, "node_modules/json-schema-traverse": { "version": "0.4.1", @@ -8053,7 +7793,8 @@ "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true }, "node_modules/local-pkg": { "version": "0.5.0", @@ -8621,6 +8362,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, "dependencies": { "callsites": "^3.0.0" }, @@ -8632,6 +8374,7 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", @@ -8686,12 +8429,14 @@ "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, "engines": { "node": ">=8" } @@ -8714,7 +8459,8 @@ "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true }, "node_modules/picomatch": { "version": "2.3.1", @@ -8776,6 +8522,108 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/postcss-js": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "dev": true, + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-mixins": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/postcss-mixins/-/postcss-mixins-9.0.4.tgz", + "integrity": "sha512-XVq5jwQJDRu5M1XGkdpgASqLk37OqkH4JCFDXl/Dn7janOJjCTEKL+36cnRVy7bMtoBzALfO7bV7nTIsFnUWLA==", + "dev": true, + "dependencies": { + "fast-glob": "^3.2.11", + "postcss-js": "^4.0.0", + "postcss-simple-vars": "^7.0.0", + "sugarss": "^4.0.1" + }, + "engines": { + "node": ">=14.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-nested": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz", + "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.11" + }, + "engines": { + "node": ">=12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-preset-mantine": { + "version": "1.14.4", + "resolved": "https://registry.npmjs.org/postcss-preset-mantine/-/postcss-preset-mantine-1.14.4.tgz", + "integrity": "sha512-T1K3MVhU1hA9mJWfqoGvMcK5WKcHpVi4JUX6AYTbESvp78WneB/KFONUi+eXDG9Lpw62W/KNxEYl1ic3Dpm88w==", + "dev": true, + "dependencies": { + "postcss-mixins": "^9.0.4", + "postcss-nested": "^6.0.1" + }, + "peerDependencies": { + "postcss": ">=8.0.0" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.16", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.16.tgz", + "integrity": "sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-simple-vars": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/postcss-simple-vars/-/postcss-simple-vars-7.0.1.tgz", + "integrity": "sha512-5GLLXaS8qmzHMOjVxqkk1TZPf1jMqesiI7qLhnlyERalG0sMbHIbJqrcnrpmZdKCLglHnRHoEBB61RtGTsj++A==", + "dev": true, + "engines": { + "node": ">=14.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.2.1" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -8967,13 +8815,11 @@ "react": "^18.2.0" } }, - "node_modules/react-dropzone": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/react-dropzone/-/react-dropzone-14.2.3.tgz", - "integrity": "sha512-O3om8I+PkFKbxCukfIR3QAGftYXDZfOE2N1mr/7qebQJHs7U+/RSL/9xomJNpRg9kM5h9soQSdf0Gc7OHF5Fug==", + "node_modules/react-dropzone-esm": { + "version": "15.0.1", + "resolved": "https://registry.npmjs.org/react-dropzone-esm/-/react-dropzone-esm-15.0.1.tgz", + "integrity": "sha512-RdeGpqwHnoV/IlDFpQji7t7pTtlC2O1i/Br0LWkRZ9hYtLyce814S71h5NolnCZXsIN5wrZId6+8eQj2EBnEzg==", "dependencies": { - "attr-accept": "^2.2.2", - "file-selector": "^0.6.0", "prop-types": "^15.8.1" }, "engines": { @@ -8988,6 +8834,18 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "node_modules/react-number-format": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/react-number-format/-/react-number-format-5.3.4.tgz", + "integrity": "sha512-2hHN5mbLuCDUx19bv0Q8wet67QqYK6xmtLQeY5xx+h7UXiMmRtaCwqko4mMPoKXLc6xAzwRrutg8XbTRlsfjRg==", + "dependencies": { + "prop-types": "^15.7.2" + }, + "peerDependencies": { + "react": "^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/react-query": { "version": "3.39.3", "resolved": "https://registry.npmjs.org/react-query/-/react-query-3.39.3.tgz", @@ -9112,22 +8970,6 @@ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, - "node_modules/react-smooth/node_modules/react-transition-group": { - "version": "4.4.5", - "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", - "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.5.5", - "dom-helpers": "^5.0.1", - "loose-envify": "^1.4.0", - "prop-types": "^15.6.2" - }, - "peerDependencies": { - "react": ">=16.6.0", - "react-dom": ">=16.6.0" - } - }, "node_modules/react-style-singleton": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz", @@ -9164,11 +9006,11 @@ } }, "node_modules/react-textarea-autosize": { - "version": "8.3.4", - "resolved": "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-8.3.4.tgz", - "integrity": "sha512-CdtmP8Dc19xL8/R6sWvtknD/eCXkQr30dtvC4VmGInhRsfF8X/ihXCq6+9l9qbxmKRiq407/7z5fxE7cVWQNgQ==", + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-8.5.3.tgz", + "integrity": "sha512-XT1024o2pqCuZSuBt9FwHlaDeNtVrtCXu0Rnz88t1jUGheCLa3PhjE1GH8Ctm2axEtvdCl5SUHYschyQ0L5QHQ==", "dependencies": { - "@babel/runtime": "^7.10.2", + "@babel/runtime": "^7.20.13", "use-composed-ref": "^1.3.0", "use-latest": "^1.2.1" }, @@ -9180,9 +9022,9 @@ } }, "node_modules/react-transition-group": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.2.tgz", - "integrity": "sha512-/RNYfRAMlZwDSr6z4zNKV6xu53/e2BuaBbGhbyYIXTrmgu/bGHzmqOs7mJSJBHy9Ud+ApHx3QjrkKSp1pxvlFg==", + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", "dependencies": { "@babel/runtime": "^7.5.5", "dom-helpers": "^5.0.1", @@ -9375,6 +9217,7 @@ "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", @@ -9391,6 +9234,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, "engines": { "node": ">=4" } @@ -9701,15 +9545,6 @@ "node": ">=10.0.0" } }, - "node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/source-map-js": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", @@ -9905,11 +9740,21 @@ "integrity": "sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==", "dev": true }, - "node_modules/stylis": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", - "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==", - "peer": true + "node_modules/sugarss": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/sugarss/-/sugarss-4.0.1.tgz", + "integrity": "sha512-WCjS5NfuVJjkQzK10s8WOBY+hhDxxNt/N6ZaGwxFZ+wN3/lKKFSaaKUNecULcTTvE4urLcKaZFQD8vO0mOZujw==", + "dev": true, + "engines": { + "node": ">=12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.3.3" + } }, "node_modules/supports-color": { "version": "7.2.0", @@ -9927,6 +9772,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, "engines": { "node": ">= 0.4" }, @@ -9999,6 +9845,7 @@ "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" } @@ -10432,6 +10279,12 @@ } } }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, "node_modules/v8-to-istanbul": { "version": "9.2.0", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index eadb26496..971065e4d 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -13,12 +13,12 @@ }, "private": true, "dependencies": { - "@mantine/core": "^6.0.21", - "@mantine/dropzone": "^6.0.21", - "@mantine/form": "^6.0.21", - "@mantine/hooks": "^6.0.21", - "@mantine/modals": "^6.0.21", - "@mantine/notifications": "^6.0.21", + "@mantine/core": "^7.10.1", + "@mantine/dropzone": "^7.10.1", + "@mantine/form": "^7.10.1", + "@mantine/hooks": "^7.10.1", + "@mantine/modals": "^7.10.1", + "@mantine/notifications": "^7.10.1", "axios": "^1.6.8", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -53,6 +53,8 @@ "husky": "^9.0.11", "jsdom": "^24.0.0", "lodash": "^4.17.21", + "postcss-preset-mantine": "^1.14.4", + "postcss-simple-vars": "^7.0.1", "prettier": "^3.2.5", "prettier-plugin-organize-imports": "^3.2.4", "pretty-quick": "^4.0.0", diff --git a/frontend/postcss.config.cjs b/frontend/postcss.config.cjs new file mode 100644 index 000000000..e817f567b --- /dev/null +++ b/frontend/postcss.config.cjs @@ -0,0 +1,14 @@ +module.exports = { + plugins: { + "postcss-preset-mantine": {}, + "postcss-simple-vars": { + variables: { + "mantine-breakpoint-xs": "36em", + "mantine-breakpoint-sm": "48em", + "mantine-breakpoint-md": "62em", + "mantine-breakpoint-lg": "75em", + "mantine-breakpoint-xl": "88em", + }, + }, + }, +}; diff --git a/frontend/src/App/Header.module.scss b/frontend/src/App/Header.module.scss new file mode 100644 index 000000000..85b3661a9 --- /dev/null +++ b/frontend/src/App/Header.module.scss @@ -0,0 +1,9 @@ +.header { + @include light { + color: var(--mantine-color-gray-0); + } + + @include dark { + color: var(--mantine-color-dark-0); + } +} diff --git a/frontend/src/App/Header.tsx b/frontend/src/App/Header.tsx index c15071045..6bb47f5b1 100644 --- a/frontend/src/App/Header.tsx +++ b/frontend/src/App/Header.tsx @@ -1,6 +1,5 @@ import { useSystem, useSystemSettings } from "@/apis/hooks"; import { Action, Search } from "@/components"; -import { Layout } from "@/constants"; import { useNavbar } from "@/contexts/Navbar"; import { useIsOnline } from "@/contexts/Online"; import { Environment, useGotoHomepage } from "@/utilities"; @@ -12,27 +11,16 @@ import { import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { Anchor, + AppShell, Avatar, Badge, Burger, Divider, Group, - Header, - MediaQuery, Menu, - createStyles, } from "@mantine/core"; import { FunctionComponent } from "react"; - -const useStyles = createStyles((theme) => { - const headerBackgroundColor = - theme.colorScheme === "light" ? theme.colors.gray[0] : theme.colors.dark[4]; - return { - header: { - backgroundColor: headerBackgroundColor, - }, - }; -}); +import styles from "./Header.module.scss"; const AppHeader: FunctionComponent = () => { const { data: settings } = useSystemSettings(); @@ -47,39 +35,28 @@ const AppHeader: FunctionComponent = () => { const goHome = useGotoHomepage(); - const { classes } = useStyles(); - return ( -
- - - - - - - - - show(!showed)} - size="sm" - > - + + + + + + + show(!showed)} + size="sm" + hiddenFrom="sm" + > Bazarr - + @@ -95,13 +72,13 @@ const AppHeader: FunctionComponent = () => { } + leftSection={} onClick={() => restart()} > Restart } + leftSection={} onClick={() => shutdown()} > Shutdown @@ -114,7 +91,7 @@ const AppHeader: FunctionComponent = () => { -
+ ); }; diff --git a/frontend/src/App/Navbar.module.scss b/frontend/src/App/Navbar.module.scss new file mode 100644 index 000000000..ddb444e4d --- /dev/null +++ b/frontend/src/App/Navbar.module.scss @@ -0,0 +1,56 @@ +.anchor { + border-color: var(--mantine-color-gray-5); + text-decoration: none; + + @include dark { + border-color: var(--mantine-color-dark-5); + } + + &.active { + border-left: 2px solid $color-brand-4; + background-color: var(--mantine-color-gray-1); + + @include dark { + border-left: 2px solid $color-brand-8; + background-color: var(--mantine-color-dark-8); + } + } + + &.hover { + background-color: var(--mantine-color-gray-0); + + @include dark { + background-color: var(--mantine-color-dark-7); + } + } +} + +.badge { + margin-left: auto; + text-decoration: none; + box-shadow: var(--mantine-shadow-xs); +} + +.icon { + width: 1.4rem; + margin-right: var(--mantine-spacing-xs); +} + +.nav { + background-color: var(--mantine-color-gray-2); + + @include dark { + background-color: var(--mantine-color-dark-8); + } +} + +.text { + display: inline-flex; + align-items: center; + width: 100%; + color: var(--mantine-color-gray-8); + + @include dark { + color: var(--mantine-color-gray-5); + } +} diff --git a/frontend/src/App/Navbar.tsx b/frontend/src/App/Navbar.tsx index c626dc257..8254f2fc0 100644 --- a/frontend/src/App/Navbar.tsx +++ b/frontend/src/App/Navbar.tsx @@ -1,5 +1,4 @@ import { Action } from "@/components"; -import { Layout } from "@/constants"; import { useNavbar } from "@/contexts/Navbar"; import { useRouteItems } from "@/Router"; import { CustomRouteObject, Route } from "@/Router/type"; @@ -14,19 +13,19 @@ import { import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { Anchor, + AppShell, Badge, Collapse, - createStyles, Divider, Group, - Navbar as MantineNavbar, Stack, Text, + useComputedColorScheme, useMantineColorScheme, } from "@mantine/core"; import { useHover } from "@mantine/hooks"; import clsx from "clsx"; -import { +import React, { createContext, FunctionComponent, useContext, @@ -35,6 +34,7 @@ import { useState, } from "react"; import { matchPath, NavLink, RouteObject, useLocation } from "react-router-dom"; +import styles from "./Navbar.module.scss"; const Selection = createContext<{ selection: string | null; @@ -97,11 +97,12 @@ function useIsActive(parent: string, route: RouteObject) { } const AppNavbar: FunctionComponent = () => { - const { showed } = useNavbar(); const [selection, select] = useState(null); - const { colorScheme, toggleColorScheme } = useMantineColorScheme(); - const dark = colorScheme === "dark"; + const { toggleColorScheme } = useMantineColorScheme(); + const computedColorScheme = useComputedColorScheme("light"); + + const dark = computedColorScheme === "dark"; const routes = useRouteItems(); @@ -111,23 +112,10 @@ const AppNavbar: FunctionComponent = () => { }, [pathname]); return ( - + ); }; @@ -186,7 +174,7 @@ const RouteItem: FunctionComponent<{ if (children !== undefined) { const elements = ( - + {children.map((child, idx) => ( + { - const borderColor = - theme.colorScheme === "light" ? theme.colors.gray[5] : theme.colors.dark[4]; - - const activeBorderColor = - theme.colorScheme === "light" - ? theme.colors.brand[4] - : theme.colors.brand[8]; - - const activeBackgroundColor = - theme.colorScheme === "light" ? theme.colors.gray[1] : theme.colors.dark[8]; - - const hoverBackgroundColor = - theme.colorScheme === "light" ? theme.colors.gray[0] : theme.colors.dark[7]; - - const textColor = - theme.colorScheme === "light" ? theme.colors.gray[8] : theme.colors.gray[5]; - - return { - text: { - display: "inline-flex", - alignItems: "center", - width: "100%", - color: textColor, - }, - anchor: { - textDecoration: "none", - borderLeft: `2px solid ${borderColor}`, - }, - active: { - backgroundColor: activeBackgroundColor, - borderLeft: `2px solid ${activeBorderColor}`, - boxShadow: theme.shadows.xs, - }, - hover: { - backgroundColor: hoverBackgroundColor, - }, - icon: { width: "1.4rem", marginRight: theme.spacing.xs }, - badge: { - marginLeft: "auto", - textDecoration: "none", - boxShadow: theme.shadows.xs, - color: textColor, - }, - }; -}); - interface NavbarItemProps { name: string; link: string; @@ -308,8 +249,6 @@ const NavbarItem: FunctionComponent = ({ onClick, primary = false, }) => { - const { classes } = useStyles(); - const { show } = useNavbar(); const { ref, hovered } = useHover(); @@ -335,9 +274,9 @@ const NavbarItem: FunctionComponent = ({ }} className={({ isActive }) => clsx( - clsx(classes.anchor, { - [classes.active]: isActive, - [classes.hover]: hovered, + clsx(styles.anchor, { + [styles.active]: isActive, + [styles.hover]: hovered, }), ) } @@ -347,18 +286,19 @@ const NavbarItem: FunctionComponent = ({ inline p="xs" size="sm" - weight={primary ? "bold" : "normal"} - className={classes.text} + fw={primary ? "bold" : "normal"} + className={styles.text} + span > {icon && ( )} {name} - {shouldHideBadge === false && ( - + {!shouldHideBadge && ( + {badge} )} diff --git a/frontend/src/App/ThemeLoader.tsx b/frontend/src/App/ThemeLoader.tsx new file mode 100644 index 000000000..2bc7e4005 --- /dev/null +++ b/frontend/src/App/ThemeLoader.tsx @@ -0,0 +1,39 @@ +import { useCallback, useEffect, useState } from "react"; +import { MantineColorScheme, useMantineColorScheme } from "@mantine/core"; +import { useSystemSettings } from "@/apis/hooks"; + +const ThemeProvider = () => { + const [localScheme, setLocalScheme] = useState( + null, + ); + const { setColorScheme } = useMantineColorScheme(); + + const settings = useSystemSettings(); + + const settingsColorScheme = settings.data?.general + .theme as MantineColorScheme; + + const setScheme = useCallback( + (colorScheme: MantineColorScheme) => { + setColorScheme(colorScheme); + }, + [setColorScheme], + ); + + useEffect(() => { + if (!settingsColorScheme) { + return; + } + + if (localScheme === settingsColorScheme) { + return; + } + + setScheme(settingsColorScheme); + setLocalScheme(settingsColorScheme); + }, [settingsColorScheme, setScheme, localScheme]); + + return <>; +}; + +export default ThemeProvider; diff --git a/frontend/src/App/ThemeProvider.tsx b/frontend/src/App/ThemeProvider.tsx new file mode 100644 index 000000000..d3a39cdb0 --- /dev/null +++ b/frontend/src/App/ThemeProvider.tsx @@ -0,0 +1,61 @@ +import { + ActionIcon, + AppShell, + Badge, + Button, + createTheme, + MantineProvider, +} from "@mantine/core"; +import { FunctionComponent, PropsWithChildren } from "react"; +import ThemeLoader from "@/App/ThemeLoader"; +import "@mantine/core/styles.layer.css"; +import "@mantine/notifications/styles.layer.css"; +import styleVars from "@/assets/_variables.module.scss"; +import buttonClasses from "@/assets/button.module.scss"; +import actionIconClasses from "@/assets/action_icon.module.scss"; +import appShellClasses from "@/assets/app_shell.module.scss"; +import badgeClasses from "@/assets/badge.module.scss"; + +const themeProvider = createTheme({ + fontFamily: "Roboto, open sans, Helvetica Neue, Helvetica, Arial, sans-serif", + colors: { + brand: [ + styleVars.colorBrand0, + styleVars.colorBrand1, + styleVars.colorBrand2, + styleVars.colorBrand3, + styleVars.colorBrand4, + styleVars.colorBrand5, + styleVars.colorBrand6, + styleVars.colorBrand7, + styleVars.colorBrand8, + styleVars.colorBrand9, + ], + }, + primaryColor: "brand", + components: { + ActionIcon: ActionIcon.extend({ + classNames: actionIconClasses, + }), + AppShell: AppShell.extend({ + classNames: appShellClasses, + }), + Badge: Badge.extend({ + classNames: badgeClasses, + }), + Button: Button.extend({ + classNames: buttonClasses, + }), + }, +}); + +const ThemeProvider: FunctionComponent = ({ children }) => { + return ( + + + {children} + + ); +}; + +export default ThemeProvider; diff --git a/frontend/src/App/index.tsx b/frontend/src/App/index.tsx index 4e09a97da..1b27734f4 100644 --- a/frontend/src/App/index.tsx +++ b/frontend/src/App/index.tsx @@ -1,7 +1,6 @@ import AppNavbar from "@/App/Navbar"; import { RouterNames } from "@/Router/RouterNames"; import ErrorBoundary from "@/components/ErrorBoundary"; -import { Layout } from "@/constants"; import NavbarProvider from "@/contexts/Navbar"; import OnlineProvider from "@/contexts/Online"; import { notification } from "@/modules/task"; @@ -13,6 +12,7 @@ import { showNotification } from "@mantine/notifications"; import { FunctionComponent, useEffect, useState } from "react"; import { Outlet, useNavigate } from "react-router-dom"; import AppHeader from "./Header"; +import styleVars from "@/assets/_variables.module.scss"; const App: FunctionComponent = () => { const navigate = useNavigate(); @@ -55,13 +55,19 @@ const App: FunctionComponent = () => { } - navbar={} + navbar={{ + width: styleVars.navBarWidth, + breakpoint: "sm", + collapsed: { mobile: !navbar }, + }} + header={{ height: { base: styleVars.headerHeight } }} padding={0} - fixed > - + + + + + diff --git a/frontend/src/App/theme.tsx b/frontend/src/App/theme.tsx deleted file mode 100644 index 947b4f7a8..000000000 --- a/frontend/src/App/theme.tsx +++ /dev/null @@ -1,87 +0,0 @@ -import { useSystemSettings } from "@/apis/hooks"; -import { - ColorScheme, - ColorSchemeProvider, - createEmotionCache, - MantineProvider, - MantineThemeOverride, -} from "@mantine/core"; -import { useColorScheme } from "@mantine/hooks"; -import { - FunctionComponent, - PropsWithChildren, - useCallback, - useEffect, - useState, -} from "react"; - -const theme: MantineThemeOverride = { - fontFamily: "Roboto, open sans, Helvetica Neue, Helvetica, Arial, sans-serif", - colors: { - brand: [ - "#F8F0FC", - "#F3D9FA", - "#EEBEFA", - "#E599F7", - "#DA77F2", - "#CC5DE8", - "#BE4BDB", - "#AE3EC9", - "#9C36B5", - "#862E9C", - ], - }, - primaryColor: "brand", -}; - -function useAutoColorScheme() { - const settings = useSystemSettings(); - const settingsColorScheme = settings.data?.general.theme; - - let preferredColorScheme: ColorScheme = useColorScheme(); - switch (settingsColorScheme) { - case "light": - preferredColorScheme = "light" as ColorScheme; - break; - case "dark": - preferredColorScheme = "dark" as ColorScheme; - break; - } - - const [colorScheme, setColorScheme] = useState(preferredColorScheme); - - // automatically switch dark/light theme - useEffect(() => { - setColorScheme(preferredColorScheme); - }, [preferredColorScheme]); - - const toggleColorScheme = useCallback((value?: ColorScheme) => { - setColorScheme((scheme) => value || (scheme === "dark" ? "light" : "dark")); - }, []); - - return { colorScheme, setColorScheme, toggleColorScheme }; -} - -const emotionCache = createEmotionCache({ key: "bazarr" }); - -const ThemeProvider: FunctionComponent = ({ children }) => { - const { colorScheme, toggleColorScheme } = useAutoColorScheme(); - - return ( - - - {children} - - - ); -}; - -export default ThemeProvider; diff --git a/frontend/src/Router/index.tsx b/frontend/src/Router/index.tsx index 335cf2d75..efed2edb2 100644 --- a/frontend/src/Router/index.tsx +++ b/frontend/src/Router/index.tsx @@ -53,7 +53,9 @@ import Redirector from "./Redirector"; import { RouterNames } from "./RouterNames"; import { CustomRouteObject } from "./type"; -const HistoryStats = lazy(() => import("@/pages/History/Statistics")); +const HistoryStats = lazy( + () => import("@/pages/History/Statistics/HistoryStats"), +); const SystemStatusView = lazy(() => import("@/pages/System/Status")); function useRoutes(): CustomRouteObject[] { diff --git a/frontend/src/assets/_bazarr.scss b/frontend/src/assets/_bazarr.scss new file mode 100644 index 000000000..6c23aac1a --- /dev/null +++ b/frontend/src/assets/_bazarr.scss @@ -0,0 +1,40 @@ +$color-brand-0: #f8f0fc; +$color-brand-1: #f3d9fa; +$color-brand-2: #eebefa; +$color-brand-3: #e599f7; +$color-brand-4: #da77f2; +$color-brand-5: #cc5de8; +$color-brand-6: #be4bdb; +$color-brand-7: #ae3ec9; +$color-brand-8: #9c36b5; +$color-brand-9: #862e9c; + +$header-height: 64px; + +:global { + .table-long-break { + overflow-wrap: anywhere; + } + + .table-primary { + display: inline-block; + + font-size: var(--mantine-font-size-sm); + + @include smaller-than($mantine-breakpoint-sm) { + min-width: 12rem; + } + } + + .table-no-wrap { + white-space: nowrap; + } + + .table-select { + display: inline-block; + + @include smaller-than($mantine-breakpoint-sm) { + min-width: 10rem; + } + } +} diff --git a/frontend/src/assets/_mantine.scss b/frontend/src/assets/_mantine.scss new file mode 100644 index 000000000..93412c636 --- /dev/null +++ b/frontend/src/assets/_mantine.scss @@ -0,0 +1,61 @@ +@use "sass:math"; + +$mantine-breakpoint-xs: "36em"; +$mantine-breakpoint-sm: "48em"; +$mantine-breakpoint-md: "62em"; +$mantine-breakpoint-lg: "75em"; +$mantine-breakpoint-xl: "88em"; + +@function rem($value) { + @return #{math.div(math.div($value, $value * 0 + 1), 16)}rem; +} + +@mixin light { + [data-mantine-color-scheme="light"] & { + @content; + } +} + +@mixin dark { + [data-mantine-color-scheme="dark"] & { + @content; + } +} + +@mixin hover { + @media (hover: hover) { + &:hover { + @content; + } + } + + @media (hover: none) { + &:active { + @content; + } + } +} + +@mixin smaller-than($breakpoint) { + @media (max-width: $breakpoint) { + @content; + } +} + +@mixin larger-than($breakpoint) { + @media (min-width: $breakpoint) { + @content; + } +} + +@mixin rtl { + [dir="rtl"] & { + @content; + } +} + +@mixin ltr { + [dir="ltr"] & { + @content; + } +} diff --git a/frontend/src/assets/_variables.module.scss b/frontend/src/assets/_variables.module.scss new file mode 100644 index 000000000..262d285b2 --- /dev/null +++ b/frontend/src/assets/_variables.module.scss @@ -0,0 +1,18 @@ +$navbar-width: 200; + +:export { + colorBrand0: $color-brand-0; + colorBrand1: $color-brand-1; + colorBrand2: $color-brand-2; + colorBrand3: $color-brand-3; + colorBrand4: $color-brand-4; + colorBrand5: $color-brand-5; + colorBrand6: $color-brand-6; + colorBrand7: $color-brand-7; + colorBrand8: $color-brand-8; + colorBrand9: $color-brand-9; + + headerHeight: $header-height; + + navBarWidth: $navbar-width; +} diff --git a/frontend/src/assets/action_icon.module.scss b/frontend/src/assets/action_icon.module.scss new file mode 100644 index 000000000..c4bf2eefa --- /dev/null +++ b/frontend/src/assets/action_icon.module.scss @@ -0,0 +1,14 @@ +@layer mantine { + .root { + &[data-variant="light"] { + color: var(--mantine-color-dark-0); + } + + @include light { + &[data-variant="light"] { + background-color: var(--mantine-color-gray-1); + color: var(--mantine-color-dark-2); + } + } + } +} diff --git a/frontend/src/assets/app_shell.module.scss b/frontend/src/assets/app_shell.module.scss new file mode 100644 index 000000000..b027c771a --- /dev/null +++ b/frontend/src/assets/app_shell.module.scss @@ -0,0 +1,5 @@ +.main { + @include dark { + background-color: rgb(26, 27, 30); + } +} diff --git a/frontend/src/assets/badge.module.scss b/frontend/src/assets/badge.module.scss new file mode 100644 index 000000000..830da2927 --- /dev/null +++ b/frontend/src/assets/badge.module.scss @@ -0,0 +1,8 @@ +.root { + background-color: var(--mantine-color-grape-light); + + @include light { + color: var(--mantine-color-dark-filled); + background-color: var(--mantine-color-grape-light); + } +} diff --git a/frontend/src/assets/button.module.scss b/frontend/src/assets/button.module.scss new file mode 100644 index 000000000..4ef306883 --- /dev/null +++ b/frontend/src/assets/button.module.scss @@ -0,0 +1,12 @@ +@layer mantine { + .root { + @include dark { + color: var(--mantine-color-dark-0); + } + + &[data-variant="danger"] { + background-color: var(--mantine-color-red-9); + color: var(--mantine-color-red-0); + } + } +} diff --git a/frontend/src/components/Search.module.scss b/frontend/src/components/Search.module.scss new file mode 100644 index 000000000..2c42098eb --- /dev/null +++ b/frontend/src/components/Search.module.scss @@ -0,0 +1,9 @@ +.result { + @include light { + color: var(--mantine-color-dark-8); + } + + @include dark { + color: var(--mantine-color-gray-1); + } +} diff --git a/frontend/src/components/Search.tsx b/frontend/src/components/Search.tsx index bc4a9f8d3..75341e0a8 100644 --- a/frontend/src/components/Search.tsx +++ b/frontend/src/components/Search.tsx @@ -5,11 +5,12 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { Anchor, Autocomplete, - createStyles, - SelectItemProps, + ComboboxItem, + OptionsFilter, } from "@mantine/core"; -import { forwardRef, FunctionComponent, useMemo, useState } from "react"; +import { FunctionComponent, useMemo, useState } from "react"; import { Link } from "react-router-dom"; +import styles from "./Search.module.scss"; type SearchResultItem = { value: string; @@ -41,36 +42,35 @@ function useSearch(query: string) { ); } -const useStyles = createStyles((theme) => { - return { - result: { - color: - theme.colorScheme === "light" - ? theme.colors.dark[8] - : theme.colors.gray[1], - }, - }; -}); - -type ResultCompProps = SelectItemProps & SearchResultItem; - -const ResultComponent = forwardRef( - ({ link, value }, ref) => { - const styles = useStyles(); +const optionsFilter: OptionsFilter = ({ options, search }) => { + const lowercaseSearch = search.toLowerCase(); + const trimmedSearch = search.trim(); + return (options as ComboboxItem[]).filter((option) => { return ( - - {value} - + option.value.toLowerCase().includes(lowercaseSearch) || + option.value + .normalize("NFD") + .replace(/[\u0300-\u036f]/g, "") + .toLowerCase() + .includes(trimmedSearch) ); - }, -); + }); +}; + +const ResultComponent = ({ name, link }: { name: string; link: string }) => { + return ( + + {name} + + ); +}; const Search: FunctionComponent = () => { const [query, setQuery] = useState(""); @@ -79,22 +79,22 @@ const Search: FunctionComponent = () => { return ( } - itemComponent={ResultComponent} + leftSection={} + renderOption={(input) => ( + a.value === input.option.value)?.link || "/" + } + /> + )} placeholder="Search" size="sm" data={results} value={query} onChange={setQuery} onBlur={() => setQuery("")} - filter={(value, item) => - item.value.toLowerCase().includes(value.toLowerCase().trim()) || - item.value - .normalize("NFD") - .replace(/[\u0300-\u036f]/g, "") - .toLowerCase() - .includes(value.trim()) - } + filter={optionsFilter} > ); }; diff --git a/frontend/src/components/StateIcon.tsx b/frontend/src/components/StateIcon.tsx index f9683f63a..73700a679 100644 --- a/frontend/src/components/StateIcon.tsx +++ b/frontend/src/components/StateIcon.tsx @@ -31,7 +31,7 @@ const StateIcon: FunctionComponent = ({ return ; } else { return ( - + @@ -48,9 +48,9 @@ const StateIcon: FunctionComponent = ({ - - - + + + @@ -59,8 +59,8 @@ const StateIcon: FunctionComponent = ({ ))} - - + + diff --git a/frontend/src/components/SubtitleToolsMenu.tsx b/frontend/src/components/SubtitleToolsMenu.tsx index e36a1e9e1..bdadb5cb4 100644 --- a/frontend/src/components/SubtitleToolsMenu.tsx +++ b/frontend/src/components/SubtitleToolsMenu.tsx @@ -148,7 +148,7 @@ const SubtitleToolsMenu: FunctionComponent = ({ } + leftSection={} onClick={() => { if (tool.modal) { modals.openContextModal(tool.modal, { selections }); @@ -164,7 +164,7 @@ const SubtitleToolsMenu: FunctionComponent = ({ Actions } + leftSection={} onClick={() => { onAction?.("search"); }} @@ -174,7 +174,7 @@ const SubtitleToolsMenu: FunctionComponent = ({ } + leftSection={} onClick={() => { modals.openConfirmModal({ title: "The following subtitles will be deleted", diff --git a/frontend/src/components/bazarr/AudioList.tsx b/frontend/src/components/bazarr/AudioList.tsx index ac9cce743..b73f71331 100644 --- a/frontend/src/components/bazarr/AudioList.tsx +++ b/frontend/src/components/bazarr/AudioList.tsx @@ -13,7 +13,7 @@ const AudioList: FunctionComponent = ({ ...group }) => { return ( - + {audios.map((audio, idx) => ( {audio.name} diff --git a/frontend/src/components/bazarr/Language.test.tsx b/frontend/src/components/bazarr/Language.test.tsx index 9e0e0fab8..e4e3b42b8 100644 --- a/frontend/src/components/bazarr/Language.test.tsx +++ b/frontend/src/components/bazarr/Language.test.tsx @@ -1,4 +1,4 @@ -import { rawRender, screen } from "@/tests"; +import { render, screen } from "@/tests"; import { describe, it } from "vitest"; import { Language } from "."; @@ -9,13 +9,13 @@ describe("Language text", () => { }; it("should show short text", () => { - rawRender(); + render(); expect(screen.getByText(testLanguage.code2)).toBeDefined(); }); it("should show long text", () => { - rawRender(); + render(); expect(screen.getByText(testLanguage.name)).toBeDefined(); }); @@ -23,7 +23,7 @@ describe("Language text", () => { const testLanguageWithHi: Language.Info = { ...testLanguage, hi: true }; it("should show short text with HI", () => { - rawRender(); + render(); const expectedText = `${testLanguageWithHi.code2}:HI`; @@ -31,7 +31,7 @@ describe("Language text", () => { }); it("should show long text with HI", () => { - rawRender(); + render(); const expectedText = `${testLanguageWithHi.name} HI`; @@ -44,7 +44,7 @@ describe("Language text", () => { }; it("should show short text with Forced", () => { - rawRender(); + render(); const expectedText = `${testLanguageWithHi.code2}:Forced`; @@ -52,9 +52,7 @@ describe("Language text", () => { }); it("should show long text with Forced", () => { - rawRender( - , - ); + render(); const expectedText = `${testLanguageWithHi.name} Forced`; @@ -75,7 +73,7 @@ describe("Language list", () => { ]; it("should show all languages", () => { - rawRender(); + render(); elements.forEach((value) => { expect(screen.getByText(value.name)).toBeDefined(); diff --git a/frontend/src/components/bazarr/Language.tsx b/frontend/src/components/bazarr/Language.tsx index e5627c82e..ba1a884e6 100644 --- a/frontend/src/components/bazarr/Language.tsx +++ b/frontend/src/components/bazarr/Language.tsx @@ -49,7 +49,7 @@ type LanguageListProps = { const LanguageList: FunctionComponent = ({ value }) => { return ( - + {value.map((v) => ( {v.name} ))} diff --git a/frontend/src/components/forms/FrameRateForm.tsx b/frontend/src/components/forms/FrameRateForm.tsx index 7e7eca24c..aa1723183 100644 --- a/frontend/src/components/forms/FrameRateForm.tsx +++ b/frontend/src/components/forms/FrameRateForm.tsx @@ -55,15 +55,17 @@ const FrameRateForm: FunctionComponent = ({ selections, onSubmit }) => { })} > - + diff --git a/frontend/src/components/forms/ItemEditForm.tsx b/frontend/src/components/forms/ItemEditForm.tsx index 9f3856d54..64f87fb36 100644 --- a/frontend/src/components/forms/ItemEditForm.tsx +++ b/frontend/src/components/forms/ItemEditForm.tsx @@ -80,7 +80,7 @@ const ItemEditForm: FunctionComponent = ({ label="Languages Profile" > - + diff --git a/frontend/src/components/forms/ProfileEditForm.module.scss b/frontend/src/components/forms/ProfileEditForm.module.scss new file mode 100644 index 000000000..d98b850ff --- /dev/null +++ b/frontend/src/components/forms/ProfileEditForm.module.scss @@ -0,0 +1,5 @@ +.content { + @include smaller-than($mantine-breakpoint-md) { + padding: 0; + } +} diff --git a/frontend/src/components/forms/ProfileEditForm.tsx b/frontend/src/components/forms/ProfileEditForm.tsx index eecacd73e..93f09d8b8 100644 --- a/frontend/src/components/forms/ProfileEditForm.tsx +++ b/frontend/src/components/forms/ProfileEditForm.tsx @@ -1,6 +1,5 @@ import { Action, Selector, SelectorOption, SimpleTable } from "@/components"; import { useModals, withModal } from "@/modules/modals"; -import { useTableStyles } from "@/styles"; import { useArrayAction, useSelectorOptions } from "@/utilities"; import { LOG } from "@/utilities/console"; import FormUtils from "@/utilities/form"; @@ -19,6 +18,7 @@ import { useForm } from "@mantine/form"; import { FunctionComponent, useCallback, useMemo } from "react"; import { Column } from "react-table"; import ChipInput from "../inputs/ChipInput"; +import styles from "./ProfileEditForm.module.scss"; export const anyCutoff = 65535; @@ -162,12 +162,10 @@ const ProfileEditForm: FunctionComponent = ({ [code], ); - const { classes } = useTableStyles(); - return ( { if (value) { @@ -260,13 +258,7 @@ const ProfileEditForm: FunctionComponent = ({ multiple chevronPosition="right" defaultValue={["Languages"]} - styles={(theme) => ({ - content: { - [theme.fn.smallerThan("md")]: { - padding: 0, - }, - }, - })} + className={styles.content} > @@ -275,7 +267,7 @@ const ProfileEditForm: FunctionComponent = ({ columns={columns} data={form.values.items} > - { - return { - wrapper: { - overflowWrap: "anywhere", - }, - }; -}); - const SeriesUploadForm: FunctionComponent = ({ series, files, onComplete, }) => { const modals = useModals(); - const { classes } = useStyles(); const episodes = useEpisodesBySeriesId(series.sonarrSeriesId); const episodeOptions = useSelectorOptions( episodes.data ?? [], @@ -225,8 +214,7 @@ const SeriesUploadForm: FunctionComponent = ({ id: "filename", accessor: "file", Cell: ({ value: { name } }) => { - const { classes } = useTableStyles(); - return {name}; + return {name}; }, }, { @@ -283,11 +271,10 @@ const SeriesUploadForm: FunctionComponent = ({ ), accessor: "language", Cell: ({ row: { original, index }, value }) => { - const { classes } = useTableStyles(); return ( { action.mutate(index, { ...original, language: item }); @@ -301,12 +288,11 @@ const SeriesUploadForm: FunctionComponent = ({ Header: "Episode", accessor: "episode", Cell: ({ value, row }) => { - const { classes } = useTableStyles(); return ( { action.mutate(row.index, { ...row.original, episode: item }); @@ -368,7 +354,7 @@ const SeriesUploadForm: FunctionComponent = ({ modals.closeSelf(); })} > - + diff --git a/frontend/src/components/forms/SyncSubtitleForm.tsx b/frontend/src/components/forms/SyncSubtitleForm.tsx index b5136fc85..c2e4ae9a5 100644 --- a/frontend/src/components/forms/SyncSubtitleForm.tsx +++ b/frontend/src/components/forms/SyncSubtitleForm.tsx @@ -14,10 +14,15 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { Alert, Button, Checkbox, Divider, Stack, Text } from "@mantine/core"; import { useForm } from "@mantine/form"; import { FunctionComponent } from "react"; -import { Selector, SelectorOption } from "../inputs"; +import { GroupedSelector, Selector } from "../inputs"; const TaskName = "Syncing Subtitle"; +interface SelectOptions { + group: string; + items: { value: string; label: string }[]; +} + function useReferencedSubtitles( mediaType: "episode" | "movie", mediaId: number, @@ -37,15 +42,21 @@ function useReferencedSubtitles( const mediaData = mediaType === "episode" ? episodeData : movieData; - const subtitles: { group: string; value: string; label: string }[] = []; + const subtitles: SelectOptions[] = []; if (!mediaData.data) { return []; } else { if (mediaData.data.audio_tracks.length > 0) { + const embeddedAudioGroup: SelectOptions = { + group: "Embedded audio tracks", + items: [], + }; + + subtitles.push(embeddedAudioGroup); + mediaData.data.audio_tracks.forEach((item) => { - subtitles.push({ - group: "Embedded audio tracks", + embeddedAudioGroup.items.push({ value: item.stream, label: `${item.name || item.language} (${item.stream})`, }); @@ -53,9 +64,15 @@ function useReferencedSubtitles( } if (mediaData.data.embedded_subtitles_tracks.length > 0) { + const embeddedSubtitlesTrackGroup: SelectOptions = { + group: "Embedded subtitles tracks", + items: [], + }; + + subtitles.push(embeddedSubtitlesTrackGroup); + mediaData.data.embedded_subtitles_tracks.forEach((item) => { - subtitles.push({ - group: "Embedded subtitles tracks", + embeddedSubtitlesTrackGroup.items.push({ value: item.stream, label: `${item.name || item.language} (${item.stream})`, }); @@ -63,10 +80,16 @@ function useReferencedSubtitles( } if (mediaData.data.external_subtitles_tracks.length > 0) { + const externalSubtitlesFilesGroup: SelectOptions = { + group: "External Subtitles files", + items: [], + }; + + subtitles.push(externalSubtitlesFilesGroup); + mediaData.data.external_subtitles_tracks.forEach((item) => { if (item) { - subtitles.push({ - group: "External Subtitles files", + externalSubtitlesFilesGroup.items.push({ value: item.path, label: item.name, }); @@ -105,7 +128,7 @@ const SyncSubtitleForm: FunctionComponent = ({ const mediaId = selections[0].id; const subtitlesPath = selections[0].path; - const subtitles: SelectorOption[] = useReferencedSubtitles( + const subtitles: SelectOptions[] = useReferencedSubtitles( mediaType, mediaId, subtitlesPath, @@ -145,14 +168,14 @@ const SyncSubtitleForm: FunctionComponent = ({ > {selections.length} subtitles selected - + > = ({ selections, onSubmit }) => { })} > - +