diff --git a/.github/workflows/version-bump.yml b/.github/workflows/version-bump.yml
index 11cf6e06..33414486 100644
--- a/.github/workflows/version-bump.yml
+++ b/.github/workflows/version-bump.yml
@@ -58,23 +58,30 @@ jobs:
MINOR="${VERSION_PARTS[1]}"
PATCH="${VERSION_PARTS[2]}"
- # Bump version based on type
- case "${{ github.event.inputs.bump_type }}" in
- major)
- MAJOR=$((MAJOR + 1))
- MINOR=0
- PATCH=0
- ;;
- minor)
- MINOR=$((MINOR + 1))
- PATCH=0
- ;;
- patch)
- PATCH=$((PATCH + 1))
- ;;
- esac
-
- NEW_VERSION="${MAJOR}.${MINOR}.${PATCH}"
+ # If requesting a pre-release and current is already a pre-release, keep base version
+ # Otherwise, bump the version based on type
+ if [ -n "${{ github.event.inputs.pre_release }}" ] && [ "$IS_PRERELEASE" = "true" ]; then
+ # Keep existing base version for iterative betas (7.6.0-beta.1 -> 7.6.0-beta.2)
+ NEW_VERSION="$BASE_VERSION"
+ else
+ # Bump version based on type
+ case "${{ github.event.inputs.bump_type }}" in
+ major)
+ MAJOR=$((MAJOR + 1))
+ MINOR=0
+ PATCH=0
+ ;;
+ minor)
+ MINOR=$((MINOR + 1))
+ PATCH=0
+ ;;
+ patch)
+ PATCH=$((PATCH + 1))
+ ;;
+ esac
+
+ NEW_VERSION="${MAJOR}.${MINOR}.${PATCH}"
+ fi
# Add pre-release label if specified
if [ -n "${{ github.event.inputs.pre_release }}" ]; then
diff --git a/bun.lock b/bun.lock
index 3219a5f8..c029e655 100644
--- a/bun.lock
+++ b/bun.lock
@@ -1,6 +1,5 @@
{
"lockfileVersion": 1,
- "configVersion": 0,
"workspaces": {
"": {
"name": "mue",
@@ -9,46 +8,40 @@
"@dnd-kit/sortable": "^10.0.0",
"@dnd-kit/utilities": "^3.2.2",
"@eartharoid/i18n": "1.2.1",
- "@emotion/react": "^11.14.0",
- "@emotion/styled": "^11.14.1",
"@floating-ui/react-dom": "2.1.6",
"@fontsource/lexend-deca": "5.0.14",
"@fontsource/montserrat": "5.0.19",
- "@mui/material": "7.3.7",
- "@sentry/react": "^10.22.0",
- "embla-carousel-autoplay": "8.6.0",
- "embla-carousel-react": "8.6.0",
+ "@sentry/react": "^10.36.0",
"fast-blurhash": "^1.1.4",
"image-conversion": "^2.1.1",
- "mue": "file:",
- "react": "^19",
+ "react": "^19.2.3",
"react-best-gradient-color-picker": "^3.0.14",
"react-clock": "6.0.0",
- "react-dom": "^19",
+ "react-dom": "^19.2.3",
"react-icons": "^5.5.0",
"react-modal": "3.16.3",
"react-toastify": "11.0.5",
- "use-debounce": "^10.0.6",
+ "use-debounce": "^10.1.0",
},
"devDependencies": {
- "@commitlint/cli": "^20.1.0",
- "@commitlint/config-conventional": "^20.0.0",
+ "@commitlint/cli": "^20.3.1",
+ "@commitlint/config-conventional": "^20.3.1",
"@eartharoid/deep-merge": "^0.0.2",
- "@eslint/js": "^9",
- "@vitejs/plugin-react-swc": "^4",
+ "@eslint/js": "^9.39.2",
+ "@vitejs/plugin-react-swc": "^4.2.2",
"adm-zip": "0.5.16",
- "eslint": "^9",
+ "eslint": "^9.39.2",
"eslint-config-prettier": "^10.1.8",
- "eslint-plugin-jsx-a11y": "^6",
- "eslint-plugin-react": "^7",
- "eslint-plugin-react-hooks": "^7",
+ "eslint-plugin-jsx-a11y": "^6.10.2",
+ "eslint-plugin-react": "^7.37.5",
+ "eslint-plugin-react-hooks": "^7.0.1",
"husky": "^9.1.7",
- "prettier": "^3.6.2",
- "sass": "^1.93.2",
+ "prettier": "^3.8.1",
+ "sass": "^1.97.3",
"stylelint": "^17.0.0",
"stylelint-config-standard-scss": "^17.0.0",
"stylelint-scss": "^7.0.0",
- "vite": "^7",
+ "vite": "^7.3.1",
"vite-plugin-progress": "^0.0.7",
},
},
@@ -66,7 +59,7 @@
"@babel/helper-globals": ["@babel/helper-globals@7.28.0", "", {}, "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw=="],
- "@babel/helper-module-imports": ["@babel/helper-module-imports@7.25.7", "", { "dependencies": { "@babel/traverse": "7.25.7", "@babel/types": "7.25.8" } }, "sha512-o0xCgpNmRohmnoWKQ0Ij8IdddjyBFE4T2kagL/x6M3+4zUgc+4qTOUBoNe4XxDskt1HPKO007ZPiMgLDq2s7Kw=="],
+ "@babel/helper-module-imports": ["@babel/helper-module-imports@7.27.1", "", { "dependencies": { "@babel/traverse": "^7.27.1", "@babel/types": "^7.27.1" } }, "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w=="],
"@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.28.3", "", { "dependencies": { "@babel/helper-module-imports": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1", "@babel/traverse": "^7.28.3" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw=="],
@@ -82,8 +75,6 @@
"@babel/parser": ["@babel/parser@7.25.8", "", { "dependencies": { "@babel/types": "7.25.8" }, "bin": "./bin/babel-parser.js" }, "sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ=="],
- "@babel/runtime": ["@babel/runtime@7.26.0", "", { "dependencies": { "regenerator-runtime": "0.14.1" } }, "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw=="],
-
"@babel/template": ["@babel/template@7.27.2", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/parser": "^7.27.2", "@babel/types": "^7.27.1" } }, "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw=="],
"@babel/traverse": ["@babel/traverse@7.28.5", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.5", "@babel/helper-globals": "^7.28.0", "@babel/parser": "^7.28.5", "@babel/template": "^7.27.2", "@babel/types": "^7.28.5", "debug": "^4.3.1" } }, "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ=="],
@@ -152,32 +143,6 @@
"@eartharoid/i18n": ["@eartharoid/i18n@1.2.1", "", {}, "sha512-nMQdHrGgpw+vNL5DbivELW2K3KAUGaMvTjjmFsEPf8mUW8+LAgRjvfFn2gkJq1mnlD6HoqUaHqEL4YpWr2T5MA=="],
- "@emotion/babel-plugin": ["@emotion/babel-plugin@11.13.5", "", { "dependencies": { "@babel/helper-module-imports": "7.25.7", "@babel/runtime": "7.26.0", "@emotion/hash": "0.9.2", "@emotion/memoize": "0.9.0", "@emotion/serialize": "1.3.3", "babel-plugin-macros": "3.1.0", "convert-source-map": "1.9.0", "escape-string-regexp": "4.0.0", "find-root": "1.1.0", "source-map": "0.5.7", "stylis": "4.2.0" } }, "sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ=="],
-
- "@emotion/cache": ["@emotion/cache@11.14.0", "", { "dependencies": { "@emotion/memoize": "0.9.0", "@emotion/sheet": "1.4.0", "@emotion/utils": "1.4.2", "@emotion/weak-memoize": "0.4.0", "stylis": "4.2.0" } }, "sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA=="],
-
- "@emotion/hash": ["@emotion/hash@0.9.2", "", {}, "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g=="],
-
- "@emotion/is-prop-valid": ["@emotion/is-prop-valid@1.3.1", "", { "dependencies": { "@emotion/memoize": "0.9.0" } }, "sha512-/ACwoqx7XQi9knQs/G0qKvv5teDMhD7bXYns9N/wM8ah8iNb8jZ2uNO0YOgiq2o2poIvVtJS2YALasQuMSQ7Kw=="],
-
- "@emotion/memoize": ["@emotion/memoize@0.9.0", "", {}, "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ=="],
-
- "@emotion/react": ["@emotion/react@11.14.0", "", { "dependencies": { "@babel/runtime": "7.26.0", "@emotion/babel-plugin": "11.13.5", "@emotion/cache": "11.14.0", "@emotion/serialize": "1.3.3", "@emotion/use-insertion-effect-with-fallbacks": "1.2.0", "@emotion/utils": "1.4.2", "@emotion/weak-memoize": "0.4.0", "hoist-non-react-statics": "3.3.2" }, "optionalDependencies": { "@types/react": "18.3.11" }, "peerDependencies": { "react": "18.3.1" } }, "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA=="],
-
- "@emotion/serialize": ["@emotion/serialize@1.3.3", "", { "dependencies": { "@emotion/hash": "0.9.2", "@emotion/memoize": "0.9.0", "@emotion/unitless": "0.10.0", "@emotion/utils": "1.4.2", "csstype": "3.1.3" } }, "sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA=="],
-
- "@emotion/sheet": ["@emotion/sheet@1.4.0", "", {}, "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg=="],
-
- "@emotion/styled": ["@emotion/styled@11.14.1", "", { "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.13.5", "@emotion/is-prop-valid": "^1.3.0", "@emotion/serialize": "^1.3.3", "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", "@emotion/utils": "^1.4.2" }, "peerDependencies": { "@emotion/react": "^11.0.0-rc.0", "react": ">=16.8.0" } }, "sha512-qEEJt42DuToa3gurlH4Qqc1kVpNq8wO8cJtDzU46TjlzWjDlsVyevtYCRijVq3SrHsROS+gVQ8Fnea108GnKzw=="],
-
- "@emotion/unitless": ["@emotion/unitless@0.10.0", "", {}, "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg=="],
-
- "@emotion/use-insertion-effect-with-fallbacks": ["@emotion/use-insertion-effect-with-fallbacks@1.2.0", "", { "peerDependencies": { "react": "18.3.1" } }, "sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg=="],
-
- "@emotion/utils": ["@emotion/utils@1.4.2", "", {}, "sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA=="],
-
- "@emotion/weak-memoize": ["@emotion/weak-memoize@0.4.0", "", {}, "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg=="],
-
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw=="],
"@esbuild/android-arm": ["@esbuild/android-arm@0.27.2", "", { "os": "android", "cpu": "arm" }, "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA=="],
@@ -274,8 +239,6 @@
"@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
- "@jridgewell/set-array": ["@jridgewell/set-array@1.2.1", "", {}, "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A=="],
-
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.0", "", {}, "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="],
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
@@ -284,20 +247,6 @@
"@keyv/serialize": ["@keyv/serialize@1.1.1", "", {}, "sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA=="],
- "@mui/core-downloads-tracker": ["@mui/core-downloads-tracker@7.3.7", "", {}, "sha512-8jWwS6FweMkpyRkrJooamUGe1CQfO1yJ+lM43IyUJbrhHW/ObES+6ry4vfGi8EKaldHL3t3BG1bcLcERuJPcjg=="],
-
- "@mui/material": ["@mui/material@7.3.7", "", { "dependencies": { "@babel/runtime": "^7.28.4", "@mui/core-downloads-tracker": "^7.3.7", "@mui/system": "^7.3.7", "@mui/types": "^7.4.10", "@mui/utils": "^7.3.7", "@popperjs/core": "^2.11.8", "@types/react-transition-group": "^4.4.12", "clsx": "^2.1.1", "csstype": "^3.2.3", "prop-types": "^15.8.1", "react-is": "^19.2.3", "react-transition-group": "^4.4.5" }, "peerDependencies": { "@emotion/react": "^11.5.0", "@emotion/styled": "^11.3.0", "@mui/material-pigment-css": "^7.3.7", "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", "react": "^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/react", "@emotion/styled", "@mui/material-pigment-css", "@types/react"] }, "sha512-6bdIxqzeOtBAj2wAsfhWCYyMKPLkRO9u/2o5yexcL0C3APqyy91iGSWgT3H7hg+zR2XgE61+WAu12wXPON8b6A=="],
-
- "@mui/private-theming": ["@mui/private-theming@7.3.7", "", { "dependencies": { "@babel/runtime": "^7.28.4", "@mui/utils": "^7.3.7", "prop-types": "^15.8.1" }, "peerDependencies": { "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", "react": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-w7r1+CYhG0syCAQUWAuV5zSaU2/67WA9JXUderdb7DzCIJdp/5RmJv6L85wRjgKCMsxFF0Kfn0kPgPbPgw/jdw=="],
-
- "@mui/styled-engine": ["@mui/styled-engine@7.3.7", "", { "dependencies": { "@babel/runtime": "^7.28.4", "@emotion/cache": "^11.14.0", "@emotion/serialize": "^1.3.3", "@emotion/sheet": "^1.4.0", "csstype": "^3.2.3", "prop-types": "^15.8.1" }, "peerDependencies": { "@emotion/react": "^11.4.1", "@emotion/styled": "^11.3.0", "react": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/react", "@emotion/styled"] }, "sha512-y/QkNXv6cF6dZ5APztd/dFWfQ6LHKPx3skyYO38YhQD4+Cxd6sFAL3Z38WMSSC8LQz145Mpp3CcLrSCLKPwYAg=="],
-
- "@mui/system": ["@mui/system@7.3.7", "", { "dependencies": { "@babel/runtime": "^7.28.4", "@mui/private-theming": "^7.3.7", "@mui/styled-engine": "^7.3.7", "@mui/types": "^7.4.10", "@mui/utils": "^7.3.7", "clsx": "^2.1.1", "csstype": "^3.2.3", "prop-types": "^15.8.1" }, "peerDependencies": { "@emotion/react": "^11.5.0", "@emotion/styled": "^11.3.0", "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", "react": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/react", "@emotion/styled", "@types/react"] }, "sha512-DovL3k+FBRKnhmatzUMyO5bKkhMLlQ9L7Qw5qHrre3m8zCZmE+31NDVBFfqrbrA7sq681qaEIHdkWD5nmiAjyQ=="],
-
- "@mui/types": ["@mui/types@7.4.10", "", { "dependencies": { "@babel/runtime": "^7.28.4" }, "peerDependencies": { "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-0+4mSjknSu218GW3isRqoxKRTOrTLd/vHi/7UC4+wZcUrOAqD9kRk7UQRL1mcrzqRoe7s3UT6rsRpbLkW5mHpQ=="],
-
- "@mui/utils": ["@mui/utils@7.3.7", "", { "dependencies": { "@babel/runtime": "^7.28.4", "@mui/types": "^7.4.10", "@types/prop-types": "^15.7.15", "clsx": "^2.1.1", "prop-types": "^15.8.1", "react-is": "^19.2.3" }, "peerDependencies": { "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", "react": "^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-+YjnjMRnyeTkWnspzoxRdiSOgkrcpTikhNPoxOZW0APXx+urHtUoXJ9lbtCZRCA5a4dg5gSbd19alL1DvRs5fg=="],
-
"@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "1.2.0" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="],
"@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="],
@@ -332,8 +281,6 @@
"@parcel/watcher-win32-x64": ["@parcel/watcher-win32-x64@2.5.1", "", { "os": "win32", "cpu": "x64" }, "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA=="],
- "@popperjs/core": ["@popperjs/core@2.11.8", "", {}, "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A=="],
-
"@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-beta.47", "", {}, "sha512-8QagwMH3kNCuzD8EWL8R2YPW5e4OrHNSAHRFDdmFqEwEaD/KcNKjVoumo+gP2vW5eKB2UPbM6vTYiGZX0ixLnw=="],
"@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.52.5", "", { "os": "android", "cpu": "arm" }, "sha512-8c1vW4ocv3UOMp9K+gToY5zL2XiiVw3k7f1ksf4yO1FlDFQ1C2u72iACFnSOceJFsWskc2WZNqeRhFRPzv+wtQ=="],
@@ -430,14 +377,10 @@
"@types/node": ["@types/node@10.17.60", "", {}, "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw=="],
- "@types/parse-json": ["@types/parse-json@4.0.2", "", {}, "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw=="],
-
"@types/prop-types": ["@types/prop-types@15.7.14", "", {}, "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ=="],
"@types/react": ["@types/react@18.3.11", "", { "dependencies": { "@types/prop-types": "15.7.14", "csstype": "3.1.3" } }, "sha512-r6QZ069rFTjrEYgFdOck1gK7FLVsgJE7tTz0pQBczlBNUhBNk0MQH4UbnFSwjpQLMkLzgqvBBa+qGpLje16eTQ=="],
- "@types/react-transition-group": ["@types/react-transition-group@4.4.12", "", { "peerDependencies": { "@types/react": "18.3.11" } }, "sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w=="],
-
"@vitejs/plugin-react-swc": ["@vitejs/plugin-react-swc@4.2.2", "", { "dependencies": { "@rolldown/pluginutils": "1.0.0-beta.47", "@swc/core": "^1.13.5" }, "peerDependencies": { "vite": "^4 || ^5 || ^6 || ^7" } }, "sha512-x+rE6tsxq/gxrEJN3Nv3dIV60lFflPj94c90b+NNo6n1QV1QQUTLoL0MpaOVasUZ0zqVBn7ead1B5ecx1JAGfA=="],
"@wojtekmaj/date-utils": ["@wojtekmaj/date-utils@2.0.2", "", {}, "sha512-Do66mSlSNifFFuo3l9gNKfRMSFi26CRuQMsDJuuKO/ekrDWuTTtE4ZQxoFCUOG+NgxnpSeBq/k5TY8ZseEzLpA=="],
@@ -486,8 +429,6 @@
"axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="],
- "babel-plugin-macros": ["babel-plugin-macros@3.1.0", "", { "dependencies": { "@babel/runtime": "7.27.0", "cosmiconfig": "7.1.0", "resolve": "1.22.8" } }, "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg=="],
-
"balanced-match": ["balanced-match@3.0.1", "", {}, "sha512-vjtV3hiLqYDNRoiAv0zC4QaGAMPomEoq83PRmYIofPswwZurCeWR5LByXm7SyoL0Zh5+2z0+HC7jG8gSZJUh0w=="],
"base64-arraybuffer": ["base64-arraybuffer@1.0.2", "", {}, "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ=="],
@@ -552,7 +493,7 @@
"cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="],
- "csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="],
+ "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
"damerau-levenshtein": ["damerau-levenshtein@1.0.8", "", {}, "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA=="],
@@ -576,22 +517,12 @@
"doctrine": ["doctrine@2.1.0", "", { "dependencies": { "esutils": "2.0.3" } }, "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw=="],
- "dom-helpers": ["dom-helpers@5.2.1", "", { "dependencies": { "@babel/runtime": "7.27.0", "csstype": "3.1.3" } }, "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA=="],
-
"dot-prop": ["dot-prop@5.3.0", "", { "dependencies": { "is-obj": "2.0.0" } }, "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q=="],
"dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
"electron-to-chromium": ["electron-to-chromium@1.5.244", "", {}, "sha512-OszpBN7xZX4vWMPJwB9illkN/znA8M36GQqQxi6MNy9axWxhOfJyZZJtSLQCpEFLHP2xK33BiWx9aIuIEXVCcw=="],
- "embla-carousel": ["embla-carousel@8.6.0", "", {}, "sha512-SjWyZBHJPbqxHOzckOfo8lHisEaJWmwd23XppYFYVh10bU66/Pn5tkVkbkCMZVdbUE5eTCI2nD8OyIP4Z+uwkA=="],
-
- "embla-carousel-autoplay": ["embla-carousel-autoplay@8.6.0", "", { "peerDependencies": { "embla-carousel": "8.6.0" } }, "sha512-OBu5G3nwaSXkZCo1A6LTaFMZ8EpkYbwIaH+bPqdBnDGQ2fh4+NbzjXjs2SktoPNKCtflfVMc75njaDHOYXcrsA=="],
-
- "embla-carousel-react": ["embla-carousel-react@8.6.0", "", { "dependencies": { "embla-carousel": "8.6.0", "embla-carousel-reactive-utils": "8.6.0" }, "peerDependencies": { "react": "18.3.1" } }, "sha512-0/PjqU7geVmo6F734pmPqpyHqiM99olvyecY7zdweCw+6tKEXnrE90pBiBbMMU8s5tICemzpQ3hi5EpxzGW+JA=="],
-
- "embla-carousel-reactive-utils": ["embla-carousel-reactive-utils@8.6.0", "", { "peerDependencies": { "embla-carousel": "8.6.0" } }, "sha512-fMVUDUEx0/uIEDM0Mz3dHznDhfX+znCCDCeIophYb1QGVM7YThSWX+wz11zlYwWFOr74b4QLGg0hrGPJeG2s4A=="],
-
"emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="],
"env-paths": ["env-paths@2.2.1", "", {}, "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A=="],
@@ -668,8 +599,6 @@
"fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="],
- "find-root": ["find-root@1.1.0", "", {}, "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng=="],
-
"find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "6.0.0", "path-exists": "4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="],
"flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="],
@@ -740,8 +669,6 @@
"hermes-parser": ["hermes-parser@0.25.1", "", { "dependencies": { "hermes-estree": "0.25.1" } }, "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA=="],
- "hoist-non-react-statics": ["hoist-non-react-statics@3.3.2", "", { "dependencies": { "react-is": "16.13.1" } }, "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw=="],
-
"hookified": ["hookified@1.15.0", "", {}, "sha512-51w+ZZGt7Zw5q7rM3nC4t3aLn/xvKDETsXqMczndvwyVQhAHfUmUuFBRFcos8Iyebtk7OAE9dL26wFNzZVVOkw=="],
"html-tags": ["html-tags@5.1.0", "", {}, "sha512-n6l5uca7/y5joxZ3LUePhzmBFUJ+U2YWzhMa8XUTecSeSlQiZdF5XAd/Q3/WUl0VsXgUwWi8I7CNIwdI5WN1SQ=="],
@@ -920,8 +847,6 @@
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
- "mue": ["mue@root:", {}],
-
"nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
"natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="],
@@ -964,8 +889,6 @@
"path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="],
- "path-type": ["path-type@4.0.0", "", {}, "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw=="],
-
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
"picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
@@ -1012,7 +935,7 @@
"react-icons": ["react-icons@5.5.0", "", { "peerDependencies": { "react": "*" } }, "sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw=="],
- "react-is": ["react-is@19.2.3", "", {}, "sha512-qJNJfu81ByyabuG7hPFEbXqNcWSU3+eVus+KJs+0ncpGfMyYdvSmxiJxbWR65lYi1I+/0HBcliO029gc4F+PnA=="],
+ "react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="],
"react-lifecycles-compat": ["react-lifecycles-compat@3.0.4", "", {}, "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="],
@@ -1020,14 +943,10 @@
"react-toastify": ["react-toastify@11.0.5", "", { "dependencies": { "clsx": "2.1.1" }, "peerDependencies": { "react": "18.3.1", "react-dom": "18.3.1" } }, "sha512-EpqHBGvnSTtHYhCPLxML05NLY2ZX0JURbAdNYa6BUkk+amz4wbKBQvoKQAB0ardvSarUBuY4Q4s1sluAzZwkmA=="],
- "react-transition-group": ["react-transition-group@4.4.5", "", { "dependencies": { "@babel/runtime": "7.27.0", "dom-helpers": "5.2.1", "loose-envify": "1.4.0", "prop-types": "15.8.1" }, "peerDependencies": { "react": "18.3.1", "react-dom": "18.3.1" } }, "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g=="],
-
"readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="],
"reflect.getprototypeof": ["reflect.getprototypeof@1.0.10", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.9", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.7", "get-proto": "^1.0.1", "which-builtin-type": "^1.2.1" } }, "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw=="],
- "regenerator-runtime": ["regenerator-runtime@0.14.1", "", {}, "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="],
-
"regexp.prototype.flags": ["regexp.prototype.flags@1.5.4", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-errors": "^1.3.0", "get-proto": "^1.0.1", "gopd": "^1.2.0", "set-function-name": "^2.0.2" } }, "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA=="],
"require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="],
@@ -1080,8 +999,6 @@
"slice-ansi": ["slice-ansi@4.0.0", "", { "dependencies": { "ansi-styles": "4.3.0", "astral-regex": "2.0.0", "is-fullwidth-code-point": "3.0.0" } }, "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ=="],
- "source-map": ["source-map@0.5.7", "", {}, "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ=="],
-
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
"split2": ["split2@4.2.0", "", {}, "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg=="],
@@ -1118,8 +1035,6 @@
"stylelint-scss": ["stylelint-scss@7.0.0", "", { "dependencies": { "css-tree": "^3.0.1", "is-plain-object": "^5.0.0", "known-css-properties": "^0.37.0", "mdn-data": "^2.25.0", "postcss-media-query-parser": "^0.2.3", "postcss-resolve-nested-selector": "^0.1.6", "postcss-selector-parser": "^7.1.1", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "stylelint": "^16.8.2 || ^17.0.0" } }, "sha512-H88kCC+6Vtzj76NsC8rv6x/LW8slBzIbyeSjsKVlS+4qaEJoDrcJR4L+8JdrR2ORdTscrBzYWiiT2jq6leYR1Q=="],
- "stylis": ["stylis@4.2.0", "", {}, "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw=="],
-
"supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
"supports-hyperlinks": ["supports-hyperlinks@4.4.0", "", { "dependencies": { "has-flag": "^5.0.1", "supports-color": "^10.2.2" } }, "sha512-UKbpT93hN5Nr9go5UY7bopIB9YQlMz9nm/ct4IXt/irb5YRkn9WaqrOBJGZ5Pwvsd5FQzSVeYlGdXoCAPQZrPg=="],
@@ -1218,12 +1133,6 @@
"@babel/generator/@babel/parser": ["@babel/parser@7.28.5", "", { "dependencies": { "@babel/types": "^7.28.5" }, "bin": "./bin/babel-parser.js" }, "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ=="],
- "@babel/helper-module-imports/@babel/traverse": ["@babel/traverse@7.25.7", "", { "dependencies": { "@babel/code-frame": "7.25.7", "@babel/generator": "7.25.7", "@babel/parser": "7.25.8", "@babel/template": "7.25.7", "@babel/types": "7.25.8", "debug": "4.3.7", "globals": "11.12.0" } }, "sha512-jatJPT1Zjqvh/1FyJs6qAHL+Dzb7sTb+xr7Q+gM1b+1oBsMsQQ4FkVKb6dFlJvLlVssqkRzV05Jzervt9yhnzg=="],
-
- "@babel/helper-module-imports/@babel/types": ["@babel/types@7.25.8", "", { "dependencies": { "@babel/helper-string-parser": "7.25.7", "@babel/helper-validator-identifier": "7.25.7", "to-fast-properties": "2.0.0" } }, "sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg=="],
-
- "@babel/helper-module-transforms/@babel/helper-module-imports": ["@babel/helper-module-imports@7.27.1", "", { "dependencies": { "@babel/traverse": "^7.27.1", "@babel/types": "^7.27.1" } }, "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w=="],
-
"@babel/highlight/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.7", "", {}, "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg=="],
"@babel/highlight/chalk": ["chalk@2.4.2", "", { "dependencies": { "ansi-styles": "3.2.1", "escape-string-regexp": "1.0.5", "supports-color": "5.5.0" } }, "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="],
@@ -1250,42 +1159,14 @@
"@commitlint/types/chalk": ["chalk@5.3.0", "", {}, "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w=="],
- "@emotion/babel-plugin/convert-source-map": ["convert-source-map@1.9.0", "", {}, "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A=="],
-
- "@emotion/serialize/csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
-
- "@emotion/styled/@babel/runtime": ["@babel/runtime@7.28.4", "", {}, "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ=="],
-
"@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="],
"@keyv/bigmap/keyv": ["keyv@5.6.0", "", { "dependencies": { "@keyv/serialize": "^1.1.1" } }, "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw=="],
- "@mui/material/@babel/runtime": ["@babel/runtime@7.28.4", "", {}, "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ=="],
-
- "@mui/private-theming/@babel/runtime": ["@babel/runtime@7.28.4", "", {}, "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ=="],
-
- "@mui/styled-engine/@babel/runtime": ["@babel/runtime@7.28.4", "", {}, "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ=="],
-
- "@mui/system/@babel/runtime": ["@babel/runtime@7.28.4", "", {}, "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ=="],
-
- "@mui/types/@babel/runtime": ["@babel/runtime@7.28.4", "", {}, "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ=="],
-
- "@mui/utils/@babel/runtime": ["@babel/runtime@7.28.4", "", {}, "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ=="],
-
- "@mui/utils/@types/prop-types": ["@types/prop-types@15.7.15", "", {}, "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw=="],
-
"@types/conventional-commits-parser/@types/node": ["@types/node@22.7.5", "", { "dependencies": { "undici-types": "6.19.8" } }, "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ=="],
- "@types/react/csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
-
"acorn-jsx/acorn": ["acorn@8.12.1", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg=="],
- "babel-plugin-macros/@babel/runtime": ["@babel/runtime@7.27.0", "", { "dependencies": { "regenerator-runtime": "0.14.1" } }, "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw=="],
-
- "babel-plugin-macros/cosmiconfig": ["cosmiconfig@7.1.0", "", { "dependencies": { "@types/parse-json": "4.0.2", "import-fresh": "3.3.0", "parse-json": "5.2.0", "path-type": "4.0.0", "yaml": "1.10.2" } }, "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA=="],
-
- "babel-plugin-macros/resolve": ["resolve@1.22.8", "", { "dependencies": { "is-core-module": "2.15.1", "path-parse": "1.0.7", "supports-preserve-symlinks-flag": "1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw=="],
-
"brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
"cacheable/keyv": ["keyv@5.6.0", "", { "dependencies": { "@keyv/serialize": "^1.1.1" } }, "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw=="],
@@ -1304,10 +1185,6 @@
"define-data-property/gopd": ["gopd@1.0.1", "", { "dependencies": { "get-intrinsic": "1.2.4" } }, "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA=="],
- "dom-helpers/@babel/runtime": ["@babel/runtime@7.27.0", "", { "dependencies": { "regenerator-runtime": "0.14.1" } }, "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw=="],
-
- "dom-helpers/csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
-
"es-abstract/es-set-tostringtag": ["es-set-tostringtag@2.0.3", "", { "dependencies": { "get-intrinsic": "1.2.4", "has-tostringtag": "1.0.2", "hasown": "2.0.2" } }, "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ=="],
"es-abstract/gopd": ["gopd@1.0.1", "", { "dependencies": { "get-intrinsic": "1.2.4" } }, "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA=="],
@@ -1352,8 +1229,6 @@
"has-tostringtag/has-symbols": ["has-symbols@1.0.3", "", {}, "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A=="],
- "hoist-non-react-statics/react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="],
-
"import-fresh/resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="],
"is-symbol/has-symbols": ["has-symbols@1.0.3", "", {}, "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A=="],
@@ -1384,10 +1259,6 @@
"postcss-scss/postcss": ["postcss@8.4.49", "", { "dependencies": { "nanoid": "3.3.8", "picocolors": "1.1.1", "source-map-js": "1.2.1" } }, "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA=="],
- "prop-types/react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="],
-
- "react-transition-group/@babel/runtime": ["@babel/runtime@7.27.0", "", { "dependencies": { "regenerator-runtime": "0.14.1" } }, "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw=="],
-
"reflect.getprototypeof/call-bind": ["call-bind@1.0.8", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", "get-intrinsic": "^1.2.4", "set-function-length": "^1.2.2" } }, "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww=="],
"reflect.getprototypeof/es-abstract": ["es-abstract@1.24.1", "", { "dependencies": { "array-buffer-byte-length": "^1.0.2", "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "data-view-buffer": "^1.0.2", "data-view-byte-length": "^1.0.2", "data-view-byte-offset": "^1.0.1", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "es-set-tostringtag": "^2.1.0", "es-to-primitive": "^1.3.0", "function.prototype.name": "^1.1.8", "get-intrinsic": "^1.3.0", "get-proto": "^1.0.1", "get-symbol-description": "^1.1.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "internal-slot": "^1.1.0", "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", "is-data-view": "^1.0.2", "is-negative-zero": "^2.0.3", "is-regex": "^1.2.1", "is-set": "^2.0.3", "is-shared-array-buffer": "^1.0.4", "is-string": "^1.1.1", "is-typed-array": "^1.1.15", "is-weakref": "^1.1.1", "math-intrinsics": "^1.1.0", "object-inspect": "^1.13.4", "object-keys": "^1.1.1", "object.assign": "^4.1.7", "own-keys": "^1.0.1", "regexp.prototype.flags": "^1.5.4", "safe-array-concat": "^1.1.3", "safe-push-apply": "^1.0.0", "safe-regex-test": "^1.1.0", "set-proto": "^1.0.0", "stop-iteration-iterator": "^1.1.0", "string.prototype.trim": "^1.2.10", "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", "typed-array-buffer": "^1.0.3", "typed-array-byte-length": "^1.0.3", "typed-array-byte-offset": "^1.0.4", "typed-array-length": "^1.0.7", "unbox-primitive": "^1.1.0", "which-typed-array": "^1.1.19" } }, "sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw=="],
@@ -1480,20 +1351,6 @@
"yargs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "8.0.0", "is-fullwidth-code-point": "3.0.0", "strip-ansi": "6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
- "@babel/helper-module-imports/@babel/traverse/@babel/code-frame": ["@babel/code-frame@7.25.7", "", { "dependencies": { "@babel/highlight": "7.25.7", "picocolors": "1.1.1" } }, "sha512-0xZJFNE5XMpENsgfHYTw8FbX4kv53mFLn2i3XPoq69LyhYSCBJtitaHx9QnsVTrsogI4Z3+HtEfZ2/GFPOtf5g=="],
-
- "@babel/helper-module-imports/@babel/traverse/@babel/generator": ["@babel/generator@7.25.7", "", { "dependencies": { "@babel/types": "7.25.8", "@jridgewell/gen-mapping": "0.3.5", "@jridgewell/trace-mapping": "0.3.25", "jsesc": "3.0.2" } }, "sha512-5Dqpl5fyV9pIAD62yK9P7fcA768uVPUyrQmqpqstHWgMma4feF1x/oFysBCVZLY5wJ2GkMUCdsNDnGZrPoR6rA=="],
-
- "@babel/helper-module-imports/@babel/traverse/@babel/template": ["@babel/template@7.25.7", "", { "dependencies": { "@babel/code-frame": "7.25.7", "@babel/parser": "7.25.8", "@babel/types": "7.25.8" } }, "sha512-wRwtAgI3bAS+JGU2upWNL9lSlDcRCqD05BZ1n3X2ONLH1WilFP6O1otQjeMK/1g0pvYcXC7b/qVUB1keofjtZA=="],
-
- "@babel/helper-module-imports/@babel/traverse/debug": ["debug@4.3.7", "", { "dependencies": { "ms": "2.1.3" } }, "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ=="],
-
- "@babel/helper-module-imports/@babel/traverse/globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="],
-
- "@babel/helper-module-imports/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.25.7", "", {}, "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g=="],
-
- "@babel/helper-module-imports/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.7", "", {}, "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg=="],
-
"@babel/highlight/chalk/ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "1.9.3" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="],
"@babel/highlight/chalk/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="],
@@ -1838,10 +1695,6 @@
"yargs/string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
- "@babel/helper-module-imports/@babel/traverse/@babel/generator/@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.5", "", { "dependencies": { "@jridgewell/set-array": "1.2.1", "@jridgewell/sourcemap-codec": "1.5.0", "@jridgewell/trace-mapping": "0.3.25" } }, "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg=="],
-
- "@babel/helper-module-imports/@babel/traverse/@babel/generator/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.25", "", { "dependencies": { "@jridgewell/resolve-uri": "3.1.2", "@jridgewell/sourcemap-codec": "1.5.0" } }, "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ=="],
-
"@babel/highlight/chalk/ansi-styles/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="],
"@babel/highlight/chalk/supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="],
diff --git a/manifest/chrome.json b/manifest/chrome.json
index c97cd76d..82864c1e 100644
--- a/manifest/chrome.json
+++ b/manifest/chrome.json
@@ -4,7 +4,7 @@
"default_locale": "en",
"name": "__MSG_name__",
"description": "__MSG_description__",
- "version": "7.5.0",
+ "version": "7.6.0",
"homepage_url": "https://muetab.com",
"permissions": ["search"],
"action": {
diff --git a/manifest/firefox.json b/manifest/firefox.json
index 4119f002..d036efc7 100644
--- a/manifest/firefox.json
+++ b/manifest/firefox.json
@@ -2,7 +2,7 @@
"manifest_version": 3,
"name": "Mue",
"description": "Fast, open and free-to-use new tab page for modern browsers.",
- "version": "7.5.0",
+ "version": "7.6.0",
"homepage_url": "https://muetab.com",
"action": {
"default_icon": "icons/128x128.png"
diff --git a/package.json b/package.json
index 0a0b7d6b..f7b6906a 100644
--- a/package.json
+++ b/package.json
@@ -9,7 +9,7 @@
"homepage": "https://muetab.com",
"bugs": "https://github.com/mue/mue/issues/new?assignees=&labels=bug&template=bug-report.md&title=%5BBUG%5D",
"license": "BSD-3-Clause",
- "version": "7.5.0",
+ "version": "7.6.0",
"type": "module",
"packageManager": "bun@1.3.1",
"engines": {
@@ -21,18 +21,12 @@
"@dnd-kit/sortable": "^10.0.0",
"@dnd-kit/utilities": "^3.2.2",
"@eartharoid/i18n": "1.2.1",
- "@emotion/react": "^11.14.0",
- "@emotion/styled": "^11.14.1",
"@floating-ui/react-dom": "2.1.6",
"@fontsource/lexend-deca": "5.0.14",
"@fontsource/montserrat": "5.0.19",
- "@mui/material": "7.3.7",
"@sentry/react": "^10.36.0",
- "embla-carousel-autoplay": "8.6.0",
- "embla-carousel-react": "8.6.0",
"fast-blurhash": "^1.1.4",
"image-conversion": "^2.1.1",
- "mue": "file:",
"react": "^19.2.3",
"react-best-gradient-color-picker": "^3.0.14",
"react-clock": "6.0.0",
diff --git a/safari/Mue Extension/Resources/manifest.json b/safari/Mue Extension/Resources/manifest.json
index 1821da96..2afad899 100644
--- a/safari/Mue Extension/Resources/manifest.json
+++ b/safari/Mue Extension/Resources/manifest.json
@@ -4,7 +4,7 @@
"default_locale": "en",
"name": "__MSG_name__",
"description": "__MSG_description__",
- "version": "7.5.0",
+ "version": "7.6.0",
"homepage_url": "https://muetab.com",
"permissions": ["search"],
"chrome_url_overrides": {
diff --git a/safari/Mue.xcodeproj/project.pbxproj b/safari/Mue.xcodeproj/project.pbxproj
index c0b4e9ae..bbe452c0 100644
--- a/safari/Mue.xcodeproj/project.pbxproj
+++ b/safari/Mue.xcodeproj/project.pbxproj
@@ -255,7 +255,7 @@
"@executable_path/../../../../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.14;
- MARKETING_VERSION = 7.5.0;
+ MARKETING_VERSION = 7.6.0;
OTHER_LDFLAGS = (
"-framework",
SafariServices,
@@ -289,7 +289,7 @@
"@executable_path/../../../../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.14;
- MARKETING_VERSION = 7.5.0;
+ MARKETING_VERSION = 7.6.0;
OTHER_LDFLAGS = (
"-framework",
SafariServices,
@@ -445,7 +445,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
- MARKETING_VERSION = 7.5.0;
+ MARKETING_VERSION = 7.6.0;
OTHER_LDFLAGS = (
"-framework",
SafariServices,
@@ -486,7 +486,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
- MARKETING_VERSION = 7.5.0;
+ MARKETING_VERSION = 7.6.0;
OTHER_LDFLAGS = (
"-framework",
SafariServices,
diff --git a/src/components/Elements/AddModal/AddModal.jsx b/src/components/Elements/AddModal/AddModal.jsx
index fa97493d..4f68e975 100644
--- a/src/components/Elements/AddModal/AddModal.jsx
+++ b/src/components/Elements/AddModal/AddModal.jsx
@@ -1,7 +1,6 @@
import variables from 'config/variables';
import { useState, memo } from 'react';
-import { TextareaAutosize } from '@mui/material';
import { MdAddLink, MdClose } from 'react-icons/md';
import { Tooltip } from 'components/Elements';
import { Button } from 'components/Elements';
@@ -26,22 +25,24 @@ function AddModal({ urlError, iconError, addLink, closeModal, edit, editData, ed
-
setName(e.target.value.replace(/(\r\n|\n|\r)/gm, ''))}
style={{ gridColumn: 'span 2' }}
/>
- setUrl(e.target.value.replace(/(\r\n|\n|\r)/gm, ''))}
/>
- setIcon(e.target.value.replace(/(\r\n|\n|\r)/gm, ''))}
diff --git a/src/components/Elements/MainModal/scss/index.scss b/src/components/Elements/MainModal/scss/index.scss
index 609ef95f..03a274c8 100644
--- a/src/components/Elements/MainModal/scss/index.scss
+++ b/src/components/Elements/MainModal/scss/index.scss
@@ -206,7 +206,7 @@ h5 {
}
.languageSettings {
- margin-bottom: 15px;
+ padding-bottom: 50px;
.MuiFormGroup-root {
gap: 5px;
diff --git a/src/components/Elements/MainModal/scss/marketplace/_main.scss b/src/components/Elements/MainModal/scss/marketplace/_main.scss
index 27eec856..f9b3c8d0 100644
--- a/src/components/Elements/MainModal/scss/marketplace/_main.scss
+++ b/src/components/Elements/MainModal/scss/marketplace/_main.scss
@@ -21,7 +21,7 @@
.items {
display: grid;
- grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
+ grid-template-columns: repeat(auto-fill, minmax(250px, 280px));
grid-gap: 1.5rem;
margin-top: 15px;
margin-bottom: 30px;
@@ -62,6 +62,20 @@
width: 60px !important;
border-radius: 12px;
transition: 0.5s;
+
+ &.item-icon-text {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 20px;
+ font-weight: 600;
+ letter-spacing: 1px;
+
+ @include themed {
+ background-color: t($modal-sidebarActive);
+ color: t($color);
+ }
+ }
}
.card-details {
@@ -113,6 +127,28 @@
}
}
+ .item-uninstall-btn {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 28px;
+ height: 28px;
+ border-radius: 50%;
+ border: none;
+ background-color: rgba(0, 0, 0, 0.5);
+ cursor: pointer;
+ transition: background-color 0.2s ease;
+
+ svg {
+ color: white;
+ font-size: 18px;
+ }
+
+ &:hover {
+ background-color: rgba(220, 50, 50, 0.9);
+ }
+ }
+
.item-installed-badge {
position: absolute;
top: 12px;
@@ -135,9 +171,33 @@
}
}
+ .item-sideload-badge {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 28px;
+ height: 28px;
+ border-radius: 50%;
+ background-color: rgba(100, 100, 100, 0.9);
+ cursor: help;
+
+ svg {
+ color: white;
+ font-size: 16px;
+ }
+ }
+
&:hover .item-installed-badge {
transform: scale(1.05);
}
+
+ &.item-sideloaded {
+ cursor: default;
+
+ &:hover {
+ transform: none;
+ }
+ }
}
}
diff --git a/src/components/Form/Settings/Checkbox/Checkbox.jsx b/src/components/Form/Settings/Checkbox/Checkbox.jsx
index 22d65564..76deb876 100644
--- a/src/components/Form/Settings/Checkbox/Checkbox.jsx
+++ b/src/components/Form/Settings/Checkbox/Checkbox.jsx
@@ -1,9 +1,11 @@
import variables from 'config/variables';
import { memo, useState, useCallback } from 'react';
-import { Checkbox as CheckboxUI, FormControlLabel } from '@mui/material';
+import { MdCheck } from 'react-icons/md';
import EventBus from 'utils/eventbus';
+import './Checkbox.scss';
+
const Checkbox = memo((props) => {
const [checked, setChecked] = useState(localStorage.getItem(props.name) === 'true');
@@ -18,7 +20,7 @@ const Checkbox = memo((props) => {
variables.stats.postEvent(
'setting',
- `${props.name} ${checked ? 'enabled' : 'disabled'}`,
+ `${props.name} ${value ? 'enabled' : 'disabled'}`,
);
if (props.element) {
@@ -31,20 +33,30 @@ const Checkbox = memo((props) => {
EventBus.emit('refresh', props.category);
}, [checked, props]);
+ const handleKeyDown = useCallback((e) => {
+ if ((e.key === ' ' || e.key === 'Enter') && !props.disabled) {
+ e.preventDefault();
+ handleChange();
+ }
+ }, [handleChange, props.disabled]);
+
return (
-
- }
- label={props.text}
- />
+
+
{props.text}
+
+
+ {checked && }
+
+
);
});
diff --git a/src/components/Form/Settings/Checkbox/Checkbox.scss b/src/components/Form/Settings/Checkbox/Checkbox.scss
new file mode 100644
index 00000000..5755d111
--- /dev/null
+++ b/src/components/Form/Settings/Checkbox/Checkbox.scss
@@ -0,0 +1,118 @@
+@use 'scss/variables' as *;
+@use 'scss/mixins' as *;
+
+@include keyframes(checkScale) {
+ 0% {
+ transform: scale(0);
+ opacity: 0;
+ }
+
+ 50% {
+ transform: scale(1.1);
+ }
+
+ 100% {
+ transform: scale(1);
+ opacity: 1;
+ }
+}
+
+.checkbox-wrapper {
+ position: relative;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ width: 100%;
+ cursor: pointer;
+ padding: 8px 0;
+
+ &.disabled {
+ opacity: 0.5;
+ cursor: not-allowed;
+ }
+
+ &:hover:not(.disabled) .checkbox-label {
+ @include themed {
+ color: t($link);
+ }
+ }
+
+ .checkbox-label {
+ flex: 1;
+ transition: color 0.2s ease;
+ pointer-events: none;
+
+ @include themed {
+ color: t($color);
+ }
+ }
+
+ .checkbox-box {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 24px;
+ height: 24px;
+ border-radius: 6px;
+ transition: all 0.2s ease;
+ cursor: pointer;
+ flex-shrink: 0;
+ pointer-events: none;
+
+ @include themed {
+ border: 2px solid t($modal-sidebarActive);
+ background: t($modal-sidebar);
+ color: t($color);
+
+ &:hover:not(.disabled) {
+ border-color: t($color);
+ transform: scale(1.05);
+ }
+ }
+
+ &:active:not(.disabled) {
+ transform: scale(0.95);
+
+ @include themed {
+ box-shadow: 0 0 0 4px rgba(255, 92, 37, 0.1);
+ }
+ }
+
+ &.checked {
+ @include themed {
+ background: t($link);
+ border-color: t($link);
+ }
+
+ svg {
+ @include animation(checkScale 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55));
+ }
+ }
+
+ svg {
+ font-size: 18px;
+ color: white;
+ }
+ }
+
+ .checkbox-input {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ opacity: 0;
+ cursor: pointer;
+ margin: 0;
+
+ &:focus-visible + .checkbox-box {
+ @include themed {
+ box-shadow: 0 0 0 3px t($link);
+ }
+ }
+
+ &:disabled {
+ cursor: not-allowed;
+ }
+ }
+}
diff --git a/src/components/Form/Settings/ChipSelect/ChipSelect.jsx b/src/components/Form/Settings/ChipSelect/ChipSelect.jsx
index f4cb8b1a..0bb1815c 100644
--- a/src/components/Form/Settings/ChipSelect/ChipSelect.jsx
+++ b/src/components/Form/Settings/ChipSelect/ChipSelect.jsx
@@ -1,12 +1,7 @@
-import { useState, memo } from 'react';
+import { useState, memo, useRef, useEffect } from 'react';
+import { MdExpandMore, MdClose } from 'react-icons/md';
-import Box from '@mui/material/Box';
-import OutlinedInput from '@mui/material/OutlinedInput';
-import InputLabel from '@mui/material/InputLabel';
-import MenuItem from '@mui/material/MenuItem';
-import FormControl from '@mui/material/FormControl';
-import Select from '@mui/material/Select';
-import Chip from '@mui/material/Chip';
+import './ChipSelect.scss';
function ChipSelect({ label, options, onChange }) {
let start = (localStorage.getItem('apiCategories') || '').split(',');
@@ -14,47 +9,88 @@ function ChipSelect({ label, options, onChange }) {
start = [];
}
- const [optionsSelected, setoptionsSelected] = useState(start);
+ const [optionsSelected, setOptionsSelected] = useState(start);
+ const [isOpen, setIsOpen] = useState(false);
+ const containerRef = useRef(null);
- const handleChange = (event) => {
- const {
- target: { value },
- } = event;
- setoptionsSelected(typeof value === 'string' ? value.split(',') : value);
- localStorage.setItem('apiCategories', value);
+ useEffect(() => {
+ const handleClickOutside = (event) => {
+ if (containerRef.current && !containerRef.current.contains(event.target)) {
+ setIsOpen(false);
+ }
+ };
+
+ document.addEventListener('mousedown', handleClickOutside);
+ return () => document.removeEventListener('mousedown', handleClickOutside);
+ }, []);
+
+ const handleToggle = (optionName) => {
+ let newSelected;
+ if (optionsSelected.includes(optionName)) {
+ newSelected = optionsSelected.filter((item) => item !== optionName);
+ } else {
+ newSelected = [...optionsSelected, optionName];
+ }
+
+ setOptionsSelected(newSelected);
+ localStorage.setItem('apiCategories', newSelected.join(','));
- // Call parent onChange if provided
if (onChange) {
- onChange(value);
+ onChange(newSelected);
}
};
+ const handleRemoveChip = (e, optionName) => {
+ e.stopPropagation();
+ handleToggle(optionName);
+ };
+
return (
-
- {label}
- }
- renderValue={(optionsSelected) => (
-
- {optionsSelected.map((value) => (
-
- ))}
-
- )}
- >
- {options.map((option) => (
-
- ))}
-
-
+
+ {label &&
}
+
setIsOpen(!isOpen)}>
+
+ {optionsSelected.length === 0 ? (
+
Select options...
+ ) : (
+
+ {optionsSelected.map((value) => (
+
+ {value.charAt(0).toUpperCase() + value.slice(1)}
+
+
+ ))}
+
+ )}
+
+
+
+ {isOpen && (
+
+ {options.map((option) => (
+
handleToggle(option.name)}
+ >
+
+ {optionsSelected.includes(option.name) && '✓'}
+
+
+ {option.name.charAt(0).toUpperCase() + option.name.slice(1)}
+ {option.count && ` (${option.count})`}
+
+
+ ))}
+
+ )}
+
);
}
diff --git a/src/components/Form/Settings/ChipSelect/ChipSelect.scss b/src/components/Form/Settings/ChipSelect/ChipSelect.scss
new file mode 100644
index 00000000..31bb4009
--- /dev/null
+++ b/src/components/Form/Settings/ChipSelect/ChipSelect.scss
@@ -0,0 +1,178 @@
+@use 'scss/variables' as *;
+
+.chipSelect {
+ position: relative;
+ width: 300px;
+ margin-top: 10px;
+
+ .chipSelect-label {
+ display: block;
+ margin-bottom: 8px;
+ font-size: 12px;
+ font-weight: 500;
+ text-transform: uppercase;
+ letter-spacing: 0.5px;
+
+ @include themed {
+ color: t($subColor);
+ }
+ }
+
+ .chipSelect-control {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ min-height: 56px;
+ padding: 8px 12px;
+ cursor: pointer;
+ transition: 0.2s ease;
+
+ @include themed {
+ background: t($modal-sidebar);
+ border: 1px solid t($modal-sidebarActive);
+ border-radius: t($borderRadius);
+ color: t($color);
+
+ &:hover {
+ border-color: t($color);
+ }
+ }
+ }
+
+ .chipSelect-value {
+ flex: 1;
+ min-width: 0;
+ }
+
+ .chipSelect-placeholder {
+ @include themed {
+ color: t($subColor);
+ }
+ }
+
+ .chipSelect-chips {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 6px;
+ }
+
+ .chipSelect-chip {
+ display: inline-flex;
+ align-items: center;
+ gap: 4px;
+ padding: 4px 8px;
+ font-size: 13px;
+ text-transform: capitalize;
+
+ @include themed {
+ background: t($modal-sidebarActive);
+ border-radius: calc(t($borderRadius) / 2);
+ color: t($color);
+ }
+
+ .chipSelect-chip-remove {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 2px;
+ margin-left: 2px;
+ border: none;
+ background: transparent;
+ cursor: pointer;
+ border-radius: 50%;
+ transition: 0.2s ease;
+
+ @include themed {
+ color: t($subColor);
+
+ &:hover {
+ background: rgba(255, 255, 255, 0.1);
+ color: t($color);
+ }
+ }
+
+ svg {
+ font-size: 14px;
+ }
+ }
+ }
+
+ .chipSelect-arrow {
+ flex-shrink: 0;
+ font-size: 24px;
+ transition: transform 0.2s ease;
+
+ @include themed {
+ color: t($subColor);
+ }
+
+ &.open {
+ transform: rotate(180deg);
+ }
+ }
+
+ .chipSelect-dropdown {
+ position: absolute;
+ top: calc(100% + 4px);
+ left: 0;
+ right: 0;
+ max-height: 250px;
+ overflow-y: auto;
+ z-index: 100;
+
+ @include themed {
+ background: t($modal-background);
+ border: 1px solid t($modal-sidebarActive);
+ border-radius: t($borderRadius);
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
+ }
+ }
+
+ .chipSelect-option {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ padding: 12px 16px;
+ cursor: pointer;
+ transition: 0.2s ease;
+
+ @include themed {
+ color: t($color);
+
+ &:hover {
+ background: t($modal-sidebarActive);
+ }
+
+ &.selected {
+ background: t($modal-sidebar);
+ }
+ }
+
+ .chipSelect-option-checkbox {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 20px;
+ height: 20px;
+ font-size: 12px;
+ font-weight: bold;
+
+ @include themed {
+ border: 2px solid t($modal-sidebarActive);
+ border-radius: 4px;
+ color: t($color);
+ }
+ }
+
+ &.selected .chipSelect-option-checkbox {
+ @include themed {
+ background: t($modal-sidebarActive);
+ border-color: t($color);
+ }
+ }
+
+ .chipSelect-option-label {
+ flex: 1;
+ }
+ }
+}
diff --git a/src/components/Form/Settings/Dropdown/Dropdown.jsx b/src/components/Form/Settings/Dropdown/Dropdown.jsx
index ac4eebfb..d4585d45 100644
--- a/src/components/Form/Settings/Dropdown/Dropdown.jsx
+++ b/src/components/Form/Settings/Dropdown/Dropdown.jsx
@@ -1,69 +1,165 @@
import variables from 'config/variables';
-import { memo, useState, useCallback, useRef } from 'react';
-import { InputLabel, MenuItem, FormControl, Select } from '@mui/material';
+import { memo, useState, useCallback, useRef, useEffect } from 'react';
+import { MdExpandMore, MdCheck, MdRefresh } from 'react-icons/md';
+import { toast } from 'react-toastify';
import EventBus from 'utils/eventbus';
+import './Dropdown.scss';
+
const Dropdown = memo((props) => {
const [value, setValue] = useState(
- localStorage.getItem(props.name) || props.items[0].value,
+ localStorage.getItem(props.name) || props.items[0]?.value,
);
- const dropdown = useRef();
+ const [isOpen, setIsOpen] = useState(false);
+ const [focusedIndex, setFocusedIndex] = useState(-1);
+ const containerRef = useRef(null);
+ const optionsRef = useRef([]);
- const onChange = useCallback((e) => {
- const newValue = e.target.value;
-
- if (newValue === variables.getMessage('modals.main.loading')) {
- return;
- }
-
- variables.stats.postEvent('setting', `${props.name} from ${value} to ${newValue}`);
-
- setValue(newValue);
-
- if (!props.noSetting) {
- localStorage.setItem(props.name, newValue);
- localStorage.setItem(props.name2, props.value2);
- }
-
- if (props.onChange) {
- props.onChange(newValue);
- }
-
- if (props.element) {
- if (!document.querySelector(props.element)) {
- document.querySelector('.reminder-info').style.display = 'flex';
- return localStorage.setItem('showReminder', true);
+ useEffect(() => {
+ const handleClickOutside = (event) => {
+ if (containerRef.current && !containerRef.current.contains(event.target)) {
+ setIsOpen(false);
+ setFocusedIndex(-1);
}
- }
+ };
- EventBus.emit('refresh', props.category);
- }, [value, props]);
+ document.addEventListener('mousedown', handleClickOutside);
+ return () => document.removeEventListener('mousedown', handleClickOutside);
+ }, []);
+
+ const onChange = useCallback(
+ (newValue) => {
+ if (newValue === variables.getMessage('modals.main.loading')) {
+ return;
+ }
+
+ variables.stats.postEvent('setting', `${props.name} from ${value} to ${newValue}`);
+
+ setValue(newValue);
+ setIsOpen(false);
+ setFocusedIndex(-1);
+
+ if (!props.noSetting) {
+ localStorage.setItem(props.name, newValue);
+ localStorage.setItem(props.name2, props.value2);
+ }
+
+ if (props.onChange) {
+ props.onChange(newValue);
+ }
+
+ if (props.element) {
+ if (!document.querySelector(props.element)) {
+ document.querySelector('.reminder-info').style.display = 'flex';
+ return localStorage.setItem('showReminder', true);
+ }
+ }
+
+ EventBus.emit('refresh', props.category);
+ },
+ [value, props],
+ );
+
+ const handleKeyDown = useCallback(
+ (e) => {
+ if (props.disabled) return;
+
+ switch (e.key) {
+ case 'Enter':
+ case ' ':
+ e.preventDefault();
+ setIsOpen(!isOpen);
+ break;
+ case 'Escape':
+ setIsOpen(false);
+ setFocusedIndex(-1);
+ break;
+ case 'ArrowDown':
+ e.preventDefault();
+ if (!isOpen) {
+ setIsOpen(true);
+ } else {
+ setFocusedIndex((prev) => (prev < props.items.filter((i) => i !== null).length - 1 ? prev + 1 : prev));
+ }
+ break;
+ case 'ArrowUp':
+ e.preventDefault();
+ if (isOpen) {
+ setFocusedIndex((prev) => (prev > 0 ? prev - 1 : prev));
+ }
+ break;
+ }
+ },
+ [isOpen, props.items, props.disabled],
+ );
+
+ const handleOptionKeyDown = useCallback(
+ (e, item) => {
+ if (e.key === 'Enter' || e.key === ' ') {
+ e.preventDefault();
+ onChange(item.value);
+ }
+ },
+ [onChange],
+ );
+
+ const resetItem = useCallback(() => {
+ const defaultValue = props.default || props.items[0]?.value;
+ onChange(defaultValue);
+ toast(variables.getMessage('toasts.reset'));
+ }, [onChange, props.default, props.items]);
const id = 'dropdown' + props.name;
const label = props.label || '';
+ const selectedItem = props.items.find((item) => item?.value === value);
return (
-
- {label}
-
);
});
diff --git a/src/components/Form/Settings/Dropdown/Dropdown.scss b/src/components/Form/Settings/Dropdown/Dropdown.scss
new file mode 100644
index 00000000..637fad37
--- /dev/null
+++ b/src/components/Form/Settings/Dropdown/Dropdown.scss
@@ -0,0 +1,218 @@
+@use 'scss/variables' as *;
+@use 'scss/mixins' as *;
+
+@include keyframes(dropdownSlideIn) {
+ 0% {
+ opacity: 0;
+ transform: translateY(-10px);
+ }
+
+ 100% {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
+
+.dropdown {
+ position: relative;
+ width: 300px;
+ margin-top: 10px;
+ gap: 8px;
+ display: flex;
+ flex-flow: column;
+
+
+ &.disabled {
+ opacity: 0.5;
+ cursor: not-allowed;
+ pointer-events: none;
+ }
+
+ .dropdown-header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-bottom: 8px;
+ }
+
+ .dropdown-label {
+ font-size: 12px;
+ font-weight: 500;
+ text-transform: uppercase;
+ letter-spacing: 0.5px;
+
+ @include themed {
+ color: t($subColor);
+ }
+ }
+
+ .dropdown-reset {
+ display: flex;
+ align-items: center;
+ gap: 5px;
+ cursor: pointer;
+ font-size: 12px;
+ font-weight: 500;
+ text-transform: uppercase;
+ letter-spacing: 0.5px;
+
+ @include themed {
+ color: t($link);
+ }
+
+ &:hover {
+ opacity: 0.8;
+ }
+
+ svg {
+ font-size: 12px;
+ }
+ }
+
+ .dropdown-control {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ height: 56px;
+ padding: 0 16px;
+ cursor: pointer;
+ transition: all 0.2s ease;
+ outline: none;
+
+ @include themed {
+ background: t($modal-sidebar);
+ border: 1px solid t($modal-sidebarActive);
+ border-radius: t($borderRadius);
+ color: t($color);
+
+ &:hover {
+ border-color: t($color);
+ }
+ }
+
+ &:focus-visible {
+ outline: none;
+
+ @include themed {
+ border-color: t($link);
+ box-shadow: 0 0 0 3px t($link);
+ }
+ }
+ }
+
+ .dropdown-value {
+ flex: 1;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ transition: color 0.2s ease;
+ }
+
+ .dropdown-arrow {
+ flex-shrink: 0;
+ font-size: 24px;
+ transition: transform 0.2s ease;
+
+ @include themed {
+ color: t($subColor);
+ }
+
+ &.open {
+ transform: rotate(180deg);
+ }
+ }
+
+ .dropdown-menu {
+ position: absolute;
+ top: calc(100% + 4px);
+ left: 0;
+ right: 0;
+ max-height: 250px;
+ overflow-y: auto;
+ z-index: 9999;
+ @include animation(dropdownSlideIn 0.2s ease-out);
+
+ @include themed {
+ background: t($modal-background);
+ border: 1px solid t($modal-sidebarActive);
+ border-radius: t($borderRadius);
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
+ }
+
+ &::-webkit-scrollbar {
+ width: 6px;
+ }
+
+ &::-webkit-scrollbar-track {
+ @include themed {
+ background: t($modal-sidebar);
+ }
+ }
+
+ &::-webkit-scrollbar-thumb {
+ @include themed {
+ background: t($modal-sidebarActive);
+ border-radius: 3px;
+ }
+
+ &:hover {
+ @include themed {
+ background: t($color);
+ }
+ }
+ }
+ }
+
+ .dropdown-option {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 8px;
+ padding: 12px 16px;
+ cursor: pointer;
+ transition: all 0.15s ease;
+ outline: none;
+
+ @include themed {
+ color: t($color);
+
+ &:hover {
+ background: t($modal-sidebarActive);
+ padding-left: 20px;
+ }
+
+ &.selected {
+ background: t($modal-sidebar);
+ font-weight: 500;
+ }
+
+ &.focused {
+ background: t($modal-sidebarActive);
+ border-left: 2px solid t($link);
+ }
+ }
+
+ .dropdown-option-text {
+ flex: 1;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+
+ .dropdown-option-check {
+ flex-shrink: 0;
+ font-size: 14px;
+ width: 20px;
+ height: 20px;
+ border-radius: 50%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+
+ @include themed {
+ background: t($link);
+ color: white;
+ }
+ }
+ }
+}
diff --git a/src/components/Form/Settings/Radio/Radio.jsx b/src/components/Form/Settings/Radio/Radio.jsx
index cf5fa311..b1a96969 100644
--- a/src/components/Form/Settings/Radio/Radio.jsx
+++ b/src/components/Form/Settings/Radio/Radio.jsx
@@ -1,85 +1,88 @@
import variables from 'config/variables';
import { memo, useState, useCallback } from 'react';
import { useTranslation } from 'contexts/TranslationContext';
-import {
- Radio as RadioUI,
- RadioGroup,
- FormControlLabel,
- FormControl,
- FormLabel,
-} from '@mui/material';
import EventBus from 'utils/eventbus';
+import './Radio.scss';
+
const Radio = memo((props) => {
const { changeLanguage } = useTranslation();
const [value, setValue] = useState(localStorage.getItem(props.name));
- const handleChange = useCallback(async (e) => {
- const newValue = e.target.value;
+ const handleChange = useCallback(
+ async (newValue) => {
+ if (newValue === 'loading') {
+ return;
+ }
- if (newValue === 'loading') {
- return;
- }
+ if (props.name === 'language') {
+ changeLanguage(newValue);
+ setValue(newValue);
- if (props.name === 'language') {
- // Use context to change language directly - no EventBus needed
- changeLanguage(newValue);
+ variables.stats.postEvent('setting', `${props.name} from ${value} to ${newValue}`);
+
+ if (props.onChange) {
+ props.onChange(newValue);
+ }
+
+ EventBus.emit('refresh', props.category);
+ return;
+ }
+
+ localStorage.setItem(props.name, newValue);
setValue(newValue);
- variables.stats.postEvent('setting', `${props.name} from ${value} to ${newValue}`);
-
if (props.onChange) {
props.onChange(newValue);
}
- EventBus.emit('refresh', props.category);
- return;
- }
+ variables.stats.postEvent('setting', `${props.name} from ${value} to ${newValue}`);
- localStorage.setItem(props.name, newValue);
- setValue(newValue);
-
- if (props.onChange) {
- props.onChange(newValue);
- }
-
- variables.stats.postEvent('setting', `${props.name} from ${value} to ${newValue}`);
-
- if (props.element) {
- if (!document.querySelector(props.element)) {
- document.querySelector('.reminder-info').style.display = 'flex';
- return localStorage.setItem('showReminder', true);
+ if (props.element) {
+ if (!document.querySelector(props.element)) {
+ document.querySelector('.reminder-info').style.display = 'flex';
+ return localStorage.setItem('showReminder', true);
+ }
}
- }
- EventBus.emit('refresh', props.category);
- }, [value, props, changeLanguage]);
+ EventBus.emit('refresh', props.category);
+ },
+ [value, props, changeLanguage],
+ );
return (
-
-
- {props.title}
-
-
+
+ {props.title && (
+
+ )}
+
{props.options.map((option) => (
-
}
- label={option.name}
+
+ className={`radio-option ${value === option.value ? 'selected' : ''} ${option.disabled || props.disabled ? 'disabled' : ''}`}
+ >
+
{option.name}
+
handleChange(option.value)}
+ disabled={option.disabled || props.disabled || false}
+ className="radio-input"
+ aria-label={option.name}
+ tabIndex={0}
+ />
+
+ {value === option.value &&
}
+
+
))}
-
-
+
+
);
});
diff --git a/src/components/Form/Settings/Radio/Radio.scss b/src/components/Form/Settings/Radio/Radio.scss
new file mode 100644
index 00000000..2bd09236
--- /dev/null
+++ b/src/components/Form/Settings/Radio/Radio.scss
@@ -0,0 +1,159 @@
+@use 'scss/variables' as *;
+@use 'scss/mixins' as *;
+
+@include keyframes(radioDotScale) {
+ 0% {
+ transform: scale(0);
+ opacity: 0;
+ }
+
+ 50% {
+ transform: scale(1.2);
+ }
+
+ 100% {
+ transform: scale(1);
+ opacity: 1;
+ }
+}
+
+.radio-group {
+ width: 100%;
+ margin-top: 10px;
+
+ .radio-title {
+ font-weight: bold;
+ font-size: 1.17rem;
+ margin-bottom: 12px;
+ display: block;
+
+ @include themed {
+ color: t($color);
+ }
+ }
+
+ .radio-title-small {
+ font-weight: bold;
+ font-size: 1rem;
+ margin-bottom: 10px;
+ display: block;
+
+ @include themed {
+ color: t($color);
+ }
+ }
+
+ .radio-options {
+ display: flex;
+ flex-direction: column;
+ gap: 10px;
+ }
+
+ .radio-option {
+ position: relative;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ cursor: pointer;
+ padding: 16px 20px;
+ transition: all 0.2s ease;
+
+ @include themed {
+ background: t($modal-sidebar);
+ border-radius: t($borderRadius);
+ box-shadow: 0 0 0 1px t($modal-sidebarActive);
+
+ &:hover:not(.disabled) {
+ background: t($modal-secondaryColour);
+ transform: translateY(-1px);
+ }
+ }
+
+ &:active:not(.disabled) {
+ transform: translateY(0);
+ }
+
+ &.selected .radio-circle {
+ @include themed {
+ border-color: t($link);
+ }
+ }
+
+ &.disabled {
+ opacity: 0.5;
+ cursor: not-allowed;
+ pointer-events: none;
+ }
+ }
+
+ .radio-label {
+ flex: 1;
+ font-size: 15px;
+ pointer-events: none;
+
+ @include themed {
+ color: t($color);
+ }
+ }
+
+ .radio-circle {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 22px;
+ height: 22px;
+ border-radius: 50%;
+ transition: all 0.2s ease;
+ cursor: pointer;
+ flex-shrink: 0;
+ margin-left: 20px;
+ pointer-events: none;
+
+ @include themed {
+ border: 2px solid t($modal-sidebarActive);
+ background: t($modal-secondaryColour);
+ }
+
+ &:hover:not(.disabled) {
+ transform: scale(1.1);
+ }
+
+ &:active:not(.disabled) {
+ @include themed {
+ box-shadow: 0 0 0 4px rgba(255, 92, 37, 0.1);
+ }
+ }
+ }
+
+ .radio-dot {
+ width: 12px;
+ height: 12px;
+ border-radius: 50%;
+ @include animation(radioDotScale 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55));
+
+ @include themed {
+ background: t($link);
+ }
+ }
+
+ .radio-input {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ opacity: 0;
+ cursor: pointer;
+ margin: 0;
+
+ &:focus-visible + .radio-circle {
+ @include themed {
+ box-shadow: 0 0 0 3px t($link);
+ }
+ }
+
+ &:disabled {
+ cursor: not-allowed;
+ }
+ }
+}
diff --git a/src/components/Form/Settings/SearchInput/SearchInput.jsx b/src/components/Form/Settings/SearchInput/SearchInput.jsx
new file mode 100644
index 00000000..ba2cebb2
--- /dev/null
+++ b/src/components/Form/Settings/SearchInput/SearchInput.jsx
@@ -0,0 +1,23 @@
+import { memo } from 'react';
+import { MdSearch } from 'react-icons/md';
+
+import './SearchInput.scss';
+
+const SearchInput = memo(({ value, onChange, placeholder, fullWidth }) => {
+ return (
+
+
+
+
+ );
+});
+
+SearchInput.displayName = 'SearchInput';
+
+export { SearchInput as default, SearchInput };
diff --git a/src/components/Form/Settings/SearchInput/SearchInput.scss b/src/components/Form/Settings/SearchInput/SearchInput.scss
new file mode 100644
index 00000000..123e25cb
--- /dev/null
+++ b/src/components/Form/Settings/SearchInput/SearchInput.scss
@@ -0,0 +1,48 @@
+@use 'scss/variables' as *;
+
+.search-input-container {
+ position: relative;
+ display: flex;
+ align-items: center;
+ width: 250px;
+
+ &.full-width {
+ width: 100%;
+ }
+
+ .search-input-icon {
+ position: absolute;
+ left: 16px;
+ font-size: 20px;
+ pointer-events: none;
+
+ @include themed {
+ color: t($subColor);
+ }
+ }
+
+ .search-input-field {
+ width: 100%;
+ height: 48px;
+ padding: 0 16px 0 44px;
+ font-size: 15px;
+ outline: none;
+ transition: 0.2s ease;
+
+ @include themed {
+ background: t($modal-sidebar);
+ border: 1px solid t($modal-sidebarActive);
+ border-radius: 24px;
+ color: t($color);
+
+ &:hover,
+ &:focus {
+ border-color: t($color);
+ }
+
+ &::placeholder {
+ color: t($subColor);
+ }
+ }
+ }
+}
diff --git a/src/components/Form/Settings/SearchInput/index.jsx b/src/components/Form/Settings/SearchInput/index.jsx
new file mode 100644
index 00000000..c068bf43
--- /dev/null
+++ b/src/components/Form/Settings/SearchInput/index.jsx
@@ -0,0 +1 @@
+export * from './SearchInput';
diff --git a/src/components/Form/Settings/Slider/Slider.jsx b/src/components/Form/Settings/Slider/Slider.jsx
index 4c88badb..49e42329 100644
--- a/src/components/Form/Settings/Slider/Slider.jsx
+++ b/src/components/Form/Settings/Slider/Slider.jsx
@@ -1,23 +1,20 @@
import variables from 'config/variables';
-import { memo, useState, useCallback } from 'react';
+import { memo, useState, useCallback, useRef } from 'react';
import { toast } from 'react-toastify';
-import { Slider } from '@mui/material';
import { MdRefresh } from 'react-icons/md';
import EventBus from 'utils/eventbus';
+import './Slider.scss';
+
const SliderComponent = memo((props) => {
const [value, setValue] = useState(localStorage.getItem(props.name) || props.default);
+ const animationRef = useRef(null);
- const handleChange = useCallback((e, text) => {
- let newValue = e.target.value;
- newValue = Number(newValue);
-
- if (text) {
- if (newValue === '') {
- setValue(0);
- return;
- }
+ const handleChange = useCallback(
+ (e) => {
+ let newValue = e.target.value;
+ newValue = Number(newValue);
if (newValue > props.max) {
newValue = props.max;
@@ -26,52 +23,104 @@ const SliderComponent = memo((props) => {
if (newValue < props.min) {
newValue = props.min;
}
- }
- localStorage.setItem(props.name, newValue);
- setValue(newValue);
+ localStorage.setItem(props.name, newValue);
+ setValue(newValue);
- if (props.element) {
- if (!document.querySelector(props.element)) {
- document.querySelector('.reminder-info').style.display = 'flex';
- return localStorage.setItem('showReminder', true);
+ if (props.element) {
+ if (!document.querySelector(props.element)) {
+ document.querySelector('.reminder-info').style.display = 'flex';
+ return localStorage.setItem('showReminder', true);
+ }
}
- }
- EventBus.emit('refresh', props.category);
- }, [props]);
+ EventBus.emit('refresh', props.category);
+ },
+ [props],
+ );
const resetItem = useCallback(() => {
- handleChange({
- target: {
- value: props.default || '',
- },
- });
+ if (animationRef.current) {
+ cancelAnimationFrame(animationRef.current);
+ }
+
+ const startValue = Number(value);
+ const endValue = Number(props.default || 0);
+ const duration = 300; // milliseconds
+ const startTime = performance.now();
+
+ const animate = (currentTime) => {
+ const elapsed = currentTime - startTime;
+ const progress = Math.min(elapsed / duration, 1);
+
+ // Easing function for smooth animation
+ const easeOutCubic = 1 - Math.pow(1 - progress, 3);
+
+ const currentValue = startValue + (endValue - startValue) * easeOutCubic;
+ const roundedValue = Math.round(currentValue / (Number(props.step) || 1)) * (Number(props.step) || 1);
+
+ localStorage.setItem(props.name, roundedValue);
+ setValue(roundedValue);
+
+ if (progress < 1) {
+ animationRef.current = requestAnimationFrame(animate);
+ } else {
+ // Ensure we end exactly at the target value
+ localStorage.setItem(props.name, endValue);
+ setValue(endValue);
+ EventBus.emit('refresh', props.category);
+ }
+ };
+
+ animationRef.current = requestAnimationFrame(animate);
toast(variables.getMessage('toasts.reset'));
- }, [handleChange, props.default]);
+ }, [value, props]);
+
+ const percentage =
+ ((Number(value) - Number(props.min)) / (Number(props.max) - Number(props.min))) * 100;
return (
- <>
-
- {props.title}
- {Number(value)}
-
+
+
+ {Number(value)}
+
{variables.getMessage('modals.main.settings.buttons.reset')}
-
- `${value}`}
- marks={props.marks || []}
- />
- >
+
+
+
+ {props.marks && props.marks.length > 0 && (
+
+ {props.marks.map((mark) => (
+
+ {mark.label}
+
+ ))}
+
+ )}
+
+
);
});
diff --git a/src/components/Form/Settings/Slider/Slider.scss b/src/components/Form/Settings/Slider/Slider.scss
new file mode 100644
index 00000000..252bf342
--- /dev/null
+++ b/src/components/Form/Settings/Slider/Slider.scss
@@ -0,0 +1,174 @@
+@use 'scss/variables' as *;
+
+.slider-container {
+ width: 300px;
+ margin-bottom: 30px;
+
+ .slider-header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-bottom: 12px;
+ }
+
+ .slider-value {
+ font-size: 16px;
+ font-weight: 600;
+
+ @include themed {
+ color: t($color);
+ }
+ }
+
+ .slider-reset {
+ display: flex;
+ align-items: center;
+ gap: 5px;
+ cursor: pointer;
+ font-size: 12px;
+ font-weight: 500;
+ text-transform: uppercase;
+ letter-spacing: 0.5px;
+
+ @include themed {
+ color: t($link);
+ }
+
+ &:hover {
+ opacity: 0.8;
+ }
+
+ svg {
+ font-size: 12px;
+ }
+ }
+
+ .slider-wrapper {
+ position: relative;
+ width: 100%;
+ }
+
+ .slider-input {
+ -webkit-appearance: none;
+ appearance: none;
+ width: 100%;
+ height: 6px;
+ border-radius: 3px;
+ outline: none;
+ cursor: pointer;
+ transition: background 0.3s ease;
+
+ @include themed {
+ background: linear-gradient(
+ to right,
+ t($link) 0%,
+ t($link) var(--slider-percentage),
+ t($modal-sidebarActive) var(--slider-percentage),
+ t($modal-sidebarActive) 100%
+ );
+ }
+
+ &::-webkit-slider-thumb {
+ -webkit-appearance: none;
+ appearance: none;
+ width: 20px;
+ height: 20px;
+ border-radius: 50%;
+ cursor: pointer;
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
+
+ @include themed {
+ background: t($color);
+ border: 2px solid t($link);
+ }
+
+ &:hover {
+ transform: scale(1.1);
+ box-shadow: 0 3px 8px rgba(0, 0, 0, 0.3);
+ }
+ }
+
+ &::-moz-range-thumb {
+ width: 20px;
+ height: 20px;
+ border-radius: 50%;
+ cursor: pointer;
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
+ border: none;
+
+ @include themed {
+ background: t($color);
+ border: 2px solid t($link);
+ }
+
+ &:hover {
+ transform: scale(1.1);
+ box-shadow: 0 3px 8px rgba(0, 0, 0, 0.3);
+ }
+ }
+
+ &:focus-visible {
+ outline: none;
+
+ &::-webkit-slider-thumb {
+ @include themed {
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2), 0 0 0 3px t($link);
+ }
+
+ transform: scale(1.15);
+ }
+
+ &::-moz-range-thumb {
+ @include themed {
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2), 0 0 0 3px t($link);
+ }
+
+ transform: scale(1.15);
+ }
+ }
+
+ &:active:not(:disabled) {
+ &::-webkit-slider-thumb {
+ transform: scale(1.2);
+ }
+
+ &::-moz-range-thumb {
+ transform: scale(1.2);
+ }
+ }
+
+ &:disabled {
+ opacity: 0.5;
+ cursor: not-allowed;
+
+ &::-webkit-slider-thumb {
+ cursor: not-allowed;
+ transform: scale(1) !important;
+ }
+
+ &::-moz-range-thumb {
+ cursor: not-allowed;
+ transform: scale(1) !important;
+ }
+ }
+ }
+
+ .slider-marks {
+ position: relative;
+ width: 100%;
+ height: 20px;
+ margin-top: 8px;
+
+ .slider-mark {
+ position: absolute;
+ transform: translateX(-50%);
+ font-size: 12px;
+
+ @include themed {
+ color: t($subColor);
+ }
+ }
+ }
+}
diff --git a/src/components/Form/Settings/Switch/Switch.jsx b/src/components/Form/Settings/Switch/Switch.jsx
index 841ca65e..56e9cfdd 100644
--- a/src/components/Form/Settings/Switch/Switch.jsx
+++ b/src/components/Form/Settings/Switch/Switch.jsx
@@ -1,9 +1,10 @@
import variables from 'config/variables';
import { memo, useState, useCallback } from 'react';
-import { Switch as SwitchUI, FormControlLabel } from '@mui/material';
import EventBus from 'utils/eventbus';
+import './Switch.scss';
+
const Switch = memo((props) => {
const [checked, setChecked] = useState(localStorage.getItem(props.name) === 'true');
@@ -32,18 +33,20 @@ const Switch = memo((props) => {
}, [checked, props]);
return (
-
- }
- label={props.header ? '' : props.text}
- labelPlacement="start"
- />
+
+ {!props.header &&
{props.text}}
+
+
+
);
});
diff --git a/src/components/Form/Settings/Switch/Switch.scss b/src/components/Form/Settings/Switch/Switch.scss
new file mode 100644
index 00000000..2a7bf5d3
--- /dev/null
+++ b/src/components/Form/Settings/Switch/Switch.scss
@@ -0,0 +1,63 @@
+@use 'scss/variables' as *;
+
+.switch-wrapper {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ width: 100%;
+ cursor: pointer;
+ padding: 8px 0;
+
+ .switch-label {
+ flex: 1;
+
+ @include themed {
+ color: t($color);
+ }
+ }
+
+ .switch-track {
+ position: relative;
+ width: 52px;
+ height: 32px;
+ border-radius: 16px;
+ cursor: pointer;
+ transition: 0.2s ease;
+ flex-shrink: 0;
+
+ @include themed {
+ background: t($modal-sidebarActive);
+ }
+
+ &.checked {
+ @include themed {
+ background: t($link);
+ }
+
+ .switch-thumb {
+ transform: translateX(20px);
+ }
+ }
+ }
+
+ .switch-thumb {
+ position: absolute;
+ top: 4px;
+ left: 4px;
+ width: 24px;
+ height: 24px;
+ border-radius: 50%;
+ transition: 0.2s ease;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
+
+ @include themed {
+ background: t($color);
+ }
+ }
+
+ .switch-input {
+ position: absolute;
+ opacity: 0;
+ pointer-events: none;
+ }
+}
diff --git a/src/components/Form/Settings/Text/Text.jsx b/src/components/Form/Settings/Text/Text.jsx
index 11efbef0..6e53d729 100644
--- a/src/components/Form/Settings/Text/Text.jsx
+++ b/src/components/Form/Settings/Text/Text.jsx
@@ -1,79 +1,95 @@
import variables from 'config/variables';
import { memo, useState, useCallback } from 'react';
import { toast } from 'react-toastify';
-import { TextField } from '@mui/material';
import { MdRefresh } from 'react-icons/md';
import EventBus from 'utils/eventbus';
+import './Text.scss';
+
const Text = memo((props) => {
- const [value, setValue] = useState(localStorage.getItem(props.name) || '');
+ const { name, upperCaseFirst, element, category, onChange, title, textarea, customcss, placeholder } = props;
+ const defaultValue = props.default;
+ const [value, setValue] = useState(localStorage.getItem(name) || '');
- const handleChange = useCallback((e) => {
- let { value } = e.target;
+ const handleChange = useCallback(
+ (e) => {
+ let newValue = e.target.value;
- // Alex wanted font to work with montserrat and Montserrat, so I made it work
- if (props.upperCaseFirst === true) {
- value = value.charAt(0).toUpperCase() + value.slice(1);
- }
-
- localStorage.setItem(props.name, value);
- setValue(value);
-
- // Call parent onChange if provided
- if (props.onChange) {
- props.onChange(value);
- }
-
- if (props.element) {
- if (!document.querySelector(props.element)) {
- document.querySelector('.reminder-info').style.display = 'flex';
- return localStorage.setItem('showReminder', true);
+ if (upperCaseFirst === true) {
+ newValue = newValue.charAt(0).toUpperCase() + newValue.slice(1);
}
- }
- EventBus.emit('refresh', props.category);
- }, [props.name, props.upperCaseFirst, props.element, props.category, props.onChange]);
+ localStorage.setItem(name, newValue);
+ setValue(newValue);
+
+ if (onChange) {
+ onChange(newValue);
+ }
+
+ if (element) {
+ if (!document.querySelector(element)) {
+ document.querySelector('.reminder-info').style.display = 'flex';
+ return localStorage.setItem('showReminder', true);
+ }
+ }
+
+ EventBus.emit('refresh', category);
+ },
+ [name, upperCaseFirst, element, category, onChange],
+ );
const resetItem = useCallback(() => {
handleChange({
target: {
- value: props.default || '',
+ value: defaultValue || '',
},
});
toast(variables.getMessage('toasts.reset'));
- }, [handleChange, props.default]);
+ }, [handleChange, defaultValue]);
return (
- <>
- {props.textarea === true ? (
-
+
+ {textarea === true ? (
+
+ {title && (
+
+
+
+
+ {variables.getMessage('modals.main.settings.buttons.reset')}
+
+
+ )}
+
+
) : (
-
+
+ {title && (
+
+
+
+
+ {variables.getMessage('modals.main.settings.buttons.reset')}
+
+
+ )}
+
+
)}
-
-
- {variables.getMessage('modals.main.settings.buttons.reset')}
-
- >
+
);
});
diff --git a/src/components/Form/Settings/Text/Text.scss b/src/components/Form/Settings/Text/Text.scss
new file mode 100644
index 00000000..eb44c009
--- /dev/null
+++ b/src/components/Form/Settings/Text/Text.scss
@@ -0,0 +1,110 @@
+@use 'scss/variables' as *;
+
+.text-field-container {
+ display: flex;
+ flex-direction: column;
+ width: 300px;
+ margin-top: 10px;
+}
+
+.text-field {
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+
+ .text-field-header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-bottom: 8px;
+ }
+
+ .text-field-label {
+ font-size: 12px;
+ font-weight: 500;
+ text-transform: uppercase;
+ letter-spacing: 0.5px;
+
+ @include themed {
+ color: t($subColor);
+ }
+ }
+
+ .text-field-reset {
+ display: flex;
+ align-items: center;
+ gap: 5px;
+ cursor: pointer;
+ font-size: 12px;
+ font-weight: 500;
+ text-transform: uppercase;
+ letter-spacing: 0.5px;
+
+ @include themed {
+ color: t($link);
+ }
+
+ &:hover {
+ opacity: 0.8;
+ }
+
+ svg {
+ font-size: 12px;
+ }
+ }
+
+ .text-field-input {
+ height: 56px;
+ padding: 0 16px;
+ font-size: 16px;
+ outline: none;
+ transition: 0.2s ease;
+
+ @include themed {
+ background: t($modal-sidebar);
+ border: 1px solid t($modal-sidebarActive);
+ border-radius: t($borderRadius);
+ color: t($color);
+
+ &:hover,
+ &:focus {
+ border-color: t($color);
+ }
+
+ &::placeholder {
+ color: t($subColor);
+ }
+ }
+ }
+
+ .text-field-textarea {
+ padding: 16px;
+ font-size: 16px;
+ outline: none;
+ resize: vertical;
+ min-height: 100px;
+ transition: 0.2s ease;
+
+ @include themed {
+ background: t($modal-sidebar);
+ border: 1px solid t($modal-sidebarActive);
+ border-radius: t($borderRadius);
+ color: t($color);
+
+ &:hover,
+ &:focus {
+ border-color: t($color);
+ }
+
+ &::placeholder {
+ color: t($subColor);
+ }
+ }
+ }
+
+ &.customcss .text-field-textarea {
+ font-family: Consolas, 'Andale Mono WT', 'Andale Mono', 'Lucida Console',
+ 'Lucida Sans Typewriter', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Liberation Mono',
+ 'Nimbus Mono L', Monaco, 'Courier New', Courier, monospace !important;
+ }
+}
diff --git a/src/components/Form/Settings/Textarea/Textarea.jsx b/src/components/Form/Settings/Textarea/Textarea.jsx
new file mode 100644
index 00000000..e60312e1
--- /dev/null
+++ b/src/components/Form/Settings/Textarea/Textarea.jsx
@@ -0,0 +1,57 @@
+import { memo, useRef, useEffect, useCallback } from 'react';
+
+import './Textarea.scss';
+
+const Textarea = memo(({ value, onChange, placeholder, minRows = 1, maxRows, className, style, readOnly }) => {
+ const textareaRef = useRef(null);
+
+ const adjustHeight = useCallback(() => {
+ const textarea = textareaRef.current;
+ if (!textarea) return;
+
+ // Reset height to auto to get the correct scrollHeight
+ textarea.style.height = 'auto';
+
+ // Calculate line height
+ const computedStyle = window.getComputedStyle(textarea);
+ const lineHeight = parseInt(computedStyle.lineHeight) || 24;
+ const paddingTop = parseInt(computedStyle.paddingTop) || 0;
+ const paddingBottom = parseInt(computedStyle.paddingBottom) || 0;
+
+ // Calculate min and max heights
+ const minHeight = (minRows * lineHeight) + paddingTop + paddingBottom;
+ const maxHeight = maxRows ? (maxRows * lineHeight) + paddingTop + paddingBottom : Infinity;
+
+ // Set the height based on content, clamped between min and max
+ const newHeight = Math.min(Math.max(textarea.scrollHeight, minHeight), maxHeight);
+ textarea.style.height = `${newHeight}px`;
+ }, [minRows, maxRows]);
+
+ useEffect(() => {
+ adjustHeight();
+ }, [value, adjustHeight]);
+
+ // Adjust on mount and window resize
+ useEffect(() => {
+ adjustHeight();
+ window.addEventListener('resize', adjustHeight);
+ return () => window.removeEventListener('resize', adjustHeight);
+ }, [adjustHeight]);
+
+ return (
+
+ );
+});
+
+Textarea.displayName = 'Textarea';
+
+export { Textarea as default, Textarea };
diff --git a/src/components/Form/Settings/Textarea/Textarea.scss b/src/components/Form/Settings/Textarea/Textarea.scss
new file mode 100644
index 00000000..4d49584d
--- /dev/null
+++ b/src/components/Form/Settings/Textarea/Textarea.scss
@@ -0,0 +1,34 @@
+@use 'scss/variables' as *;
+
+.textarea-autosize {
+ width: 100%;
+ padding: 12px 16px;
+ font-size: 15px;
+ line-height: 24px;
+ outline: none;
+ resize: none;
+ overflow: hidden;
+ transition: 0.2s ease;
+ font-family: inherit;
+
+ @include themed {
+ background: t($modal-sidebar);
+ border: 1px solid t($modal-sidebarActive);
+ border-radius: t($borderRadius);
+ color: t($color);
+
+ &:hover,
+ &:focus {
+ border-color: t($color);
+ }
+
+ &::placeholder {
+ color: t($subColor);
+ }
+ }
+
+ &[readonly] {
+ opacity: 0.6;
+ cursor: not-allowed;
+ }
+}
diff --git a/src/components/Form/Settings/Textarea/index.jsx b/src/components/Form/Settings/Textarea/index.jsx
new file mode 100644
index 00000000..6449a419
--- /dev/null
+++ b/src/components/Form/Settings/Textarea/index.jsx
@@ -0,0 +1 @@
+export * from './Textarea';
diff --git a/src/components/Form/Settings/index.jsx b/src/components/Form/Settings/index.jsx
index 75eddedb..e3179fc6 100644
--- a/src/components/Form/Settings/index.jsx
+++ b/src/components/Form/Settings/index.jsx
@@ -3,6 +3,8 @@ export * from './ChipSelect';
export * from './Dropdown';
export * from './FileUpload';
export * from './Radio';
+export * from './SearchInput';
export * from './Slider';
export * from './Switch';
export * from './Text';
+export * from './Textarea';
diff --git a/src/config/constants.js b/src/config/constants.js
index e4793f61..52c44a77 100644
--- a/src/config/constants.js
+++ b/src/config/constants.js
@@ -25,4 +25,4 @@ export const EMAIL = 'hello@muetab.com';
export const TWITTER_HANDLE = 'getmue';
export const DISCORD_SERVER = 'zv8C9F8';
-export const VERSION = '7.5.0';
+export const VERSION = '7.6.0';
diff --git a/src/features/greeting/options/GreetingOptions.jsx b/src/features/greeting/options/GreetingOptions.jsx
index bf1e5beb..dceb037b 100644
--- a/src/features/greeting/options/GreetingOptions.jsx
+++ b/src/features/greeting/options/GreetingOptions.jsx
@@ -10,7 +10,6 @@ import {
Section,
} from 'components/Layout/Settings';
import { Checkbox, Switch, Text } from 'components/Form/Settings';
-import { TextareaAutosize } from '@mui/material';
import { Button } from 'components/Elements';
import { toast } from 'react-toastify';
@@ -192,15 +191,15 @@ const GreetingOptions = ({ currentSubSection, onSubSectionChange, sectionName })
{variables.getMessage(`${GREETING_SECTION}.event_name`)}
- {
const updatedEvent = { ...event, name: e.target.value };
updateEvent(index, updatedEvent);
}}
- varient="outlined"
- style={{ padding: '0' }}
/>
diff --git a/src/features/marketplace/components/Items/Items.jsx b/src/features/marketplace/components/Items/Items.jsx
index 93fa0383..f6a1a5ed 100644
--- a/src/features/marketplace/components/Items/Items.jsx
+++ b/src/features/marketplace/components/Items/Items.jsx
@@ -1,9 +1,16 @@
import variables from 'config/variables';
import React, { memo, useState, useMemo } from 'react';
-import { MdAutoFixHigh, MdOutlineArrowForward, MdOutlineOpenInNew, MdCheckCircle } from 'react-icons/md';
+import {
+ MdAutoFixHigh,
+ MdOutlineArrowForward,
+ MdOutlineOpenInNew,
+ MdCheckCircle,
+ MdOutlineUploadFile,
+ MdClose,
+} from 'react-icons/md';
import placeholderIcon from 'assets/icons/marketplace-placeholder.png';
-import { Button } from 'components/Elements';
+import { Button, Tooltip } from 'components/Elements';
import Dropdown from '../../../../components/Form/Settings/Dropdown/Dropdown';
function filterItems(item, filter, categoryFilter) {
@@ -28,7 +35,29 @@ function filterItems(item, filter, categoryFilter) {
return textMatch && item.type === categoryMap[categoryFilter];
}
-function ItemCard({ item, toggleFunction, type, onCollection, isCurator, isInstalled }) {
+function getInitials(name) {
+ if (!name) return '??';
+ const words = name.split(' ');
+ if (words.length === 1) {
+ return name.substring(0, 2).toUpperCase();
+ }
+ return words
+ .slice(0, 2)
+ .map((word) => word[0])
+ .join('')
+ .toUpperCase();
+}
+
+function getTypeTranslationKey(type) {
+ const typeMap = {
+ photos: 'photo_packs',
+ quotes: 'quote_packs',
+ settings: 'preset_settings',
+ };
+ return typeMap[type] || type;
+}
+
+function ItemCard({ item, toggleFunction, type, onCollection, isCurator, isInstalled, isAdded, onUninstall }) {
item._onCollection = onCollection;
// Convert hex color to RGB for gradient with opacity
@@ -73,28 +102,62 @@ function ItemCard({ item, toggleFunction, type, onCollection, isCurator, isInsta
};
};
+ const isSideloaded = item.sideload === true;
+
return (
toggleFunction(item)}
+ className={`item ${isSideloaded ? 'item-sideloaded' : ''}`}
+ onClick={isSideloaded ? undefined : () => toggleFunction(item)}
key={item.name}
style={getGradientStyle()}
>
- {isInstalled && item.colour && (
+ {isAdded && onUninstall && (
+
+
+
+ )}
+ {isSideloaded && (
+
+
+
+
+
+ )}
+ {isInstalled && item.colour && !isSideloaded && (
)}
-

{
- e.target.onerror = null;
- e.target.src = placeholderIcon;
- }}
- />
+ {item.icon_url ? (
+

{
+ e.target.onerror = null;
+ e.target.src = placeholderIcon;
+ }}
+ />
+ ) : (
+
+ {getInitials(item.display_name || item.name)}
+
+ )}
{item.display_name || item.name}
{!isCurator ? (
@@ -106,17 +169,14 @@ function ItemCard({ item, toggleFunction, type, onCollection, isCurator, isInsta
)}
- {type === 'all' && !onCollection ? (
+ {item.type && (
- {variables.getMessage('modals.main.marketplace.' + item.type)}
+ {variables.getMessage('modals.main.marketplace.' + getTypeTranslationKey(item.type))}
- ) : null}
-
- {/* {item.in_collections && item.in_collections.length > 0 && !onCollection ? (
-
- {item.in_collections[0]}
-
- ) : null} */}
+ )}
+ {item.in_collections && item.in_collections.length > 0 && !onCollection && (
+ {item.in_collections[0]}
+ )}
@@ -136,6 +196,8 @@ function Items({
showCreateYourOwn,
filterOptions = false,
onSortChange,
+ isAdded = false,
+ onUninstall,
}) {
const [selectedCategory, setSelectedCategory] = useState('all');
const [sortType, setSortType] = useState(localStorage.getItem('sortMarketplace') || 'a-z');
@@ -239,6 +301,8 @@ function Items({
type={type}
onCollection={onCollection}
isInstalled={installedNames.has(item.name)}
+ isAdded={isAdded}
+ onUninstall={onUninstall}
key={index}
/>
))}
diff --git a/src/features/marketplace/views/Added.jsx b/src/features/marketplace/views/Added.jsx
index 908455e3..7a210c78 100644
--- a/src/features/marketplace/views/Added.jsx
+++ b/src/features/marketplace/views/Added.jsx
@@ -84,27 +84,24 @@ const Added = memo(() => {
const sortAddons = useCallback((value, sendEvent) => {
const installedItems = JSON.parse(localStorage.getItem('installed'));
-
+
switch (value) {
case 'newest':
installedItems.reverse();
break;
- case 'oldest':
- break;
case 'a-z':
installedItems.sort((a, b) => {
- if (a.display_name < b.display_name) {
- return -1;
- }
- if (a.display_name > b.display_name) {
- return 1;
- }
- return 0;
+ const nameA = (a.display_name || a.name || '').toLowerCase();
+ const nameB = (b.display_name || b.name || '').toLowerCase();
+ return nameA.localeCompare(nameB);
});
break;
- case 'z-a':
- installedItems.sort();
- installedItems.reverse();
+ case 'recently-updated':
+ installedItems.sort((a, b) => {
+ const dateA = a.updated_at ? new Date(a.updated_at) : new Date(0);
+ const dateB = b.updated_at ? new Date(b.updated_at) : new Date(0);
+ return dateB - dateA;
+ });
break;
default:
break;
@@ -154,6 +151,12 @@ const Added = memo(() => {
setInstalled([]);
}, [installed]);
+ const handleUninstall = useCallback((type, name) => {
+ uninstall(type, name);
+ toast(variables.getMessage('toasts.uninstalled'));
+ setInstalled(JSON.parse(localStorage.getItem('installed')));
+ }, []);
+
useEffect(() => {
sortAddons(localStorage.getItem('sortAddons'), false);
}, []); // eslint-disable-line react-hooks/exhaustive-deps
@@ -243,9 +246,8 @@ const Added = memo(() => {
onChange={(value) => sortAddons(value)}
items={[
{ value: 'newest', text: variables.getMessage('modals.main.addons.sort.newest') },
- { value: 'oldest', text: variables.getMessage('modals.main.addons.sort.oldest') },
{ value: 'a-z', text: variables.getMessage('modals.main.addons.sort.a_z') },
- { value: 'z-a', text: variables.getMessage('modals.main.addons.sort.z_a') },
+ { value: 'recently-updated', text: 'Recently Updated' },
]}
/>
{
filter=""
toggleFunction={(input) => toggle('item', input)}
showCreateYourOwn={false}
+ onUninstall={handleUninstall}
/>
>
);
diff --git a/src/features/message/options/MessageOptions.jsx b/src/features/message/options/MessageOptions.jsx
index f2784cd7..fbad7f00 100644
--- a/src/features/message/options/MessageOptions.jsx
+++ b/src/features/message/options/MessageOptions.jsx
@@ -2,9 +2,9 @@ import variables from 'config/variables';
import { useState } from 'react';
import { MdCancel, MdAdd, MdOutlineTextsms } from 'react-icons/md';
import { toast } from 'react-toastify';
-import { TextareaAutosize } from '@mui/material';
import { Header, Row, Content, Action, PreferencesWrapper } from 'components/Layout/Settings';
+import { Textarea } from 'components/Form/Settings';
import { Button } from 'components/Elements';
import EventBus from 'utils/eventbus';
@@ -82,14 +82,13 @@ const MessageOptions = () => {
{variables.getMessage(`${MESSAGE_SECTION}.title`)}
- message(e, true, index)}
- varient="outlined"
- style={{ padding: '0' }}
+ minRows={2}
/>
diff --git a/src/features/misc/modals/Modals.jsx b/src/features/misc/modals/Modals.jsx
index 67c4128f..261e260d 100644
--- a/src/features/misc/modals/Modals.jsx
+++ b/src/features/misc/modals/Modals.jsx
@@ -8,9 +8,45 @@ import Preview from '../../helpers/preview/Preview';
import EventBus from 'utils/eventbus';
import { parseDeepLink, shouldAutoOpenModal, updateHash } from 'utils/deepLinking';
+import { install } from 'utils/marketplace';
import Welcome from 'features/welcome/Welcome';
+const DEFAULT_PACK_ID = '0c8a5bdebd13';
+
+const isDefaultPackInstalled = () => {
+ const installed = JSON.parse(localStorage.getItem('installed') || '[]');
+ return installed.some((item) => item.id === DEFAULT_PACK_ID);
+};
+
+const isDefaultPackUninstalled = () => {
+ const uninstalledPacks = JSON.parse(localStorage.getItem('uninstalledPacks') || '[]');
+ return uninstalledPacks.includes(DEFAULT_PACK_ID);
+};
+
+const tryInstallDefaultPack = async () => {
+ // Don't install if offline mode, already installed, or explicitly uninstalled
+ if (
+ localStorage.getItem('offlineMode') === 'true' ||
+ isDefaultPackInstalled() ||
+ isDefaultPackUninstalled()
+ ) {
+ return false;
+ }
+
+ try {
+ const response = await fetch(
+ `${variables.constants.API_URL}/marketplace/item/${DEFAULT_PACK_ID}`,
+ );
+ const { data } = await response.json();
+ install(data.type, data, false, true);
+ return true;
+ } catch (e) {
+ console.error('Failed to install default pack:', e);
+ return false;
+ }
+};
+
const Modals = () => {
const [mainModal, setMainModal] = useState(false);
const [updateModal, setUpdateModal] = useState(false);
@@ -60,6 +96,15 @@ const Modals = () => {
localStorage.setItem('showReminder', false);
}
+ // Try to install default pack if it wasn't installed during welcome (e.g., no internet)
+ if (localStorage.getItem('showWelcome') !== 'true') {
+ tryInstallDefaultPack().then((installed) => {
+ if (installed) {
+ EventBus.emit('refresh', 'quote');
+ }
+ });
+ }
+
// Listen for EventBus modal open requests
const handleModalOpen = (data) => {
if (data === 'openMainModal') {
@@ -76,9 +121,12 @@ const Modals = () => {
};
}, []);
- const closeWelcome = () => {
+ const closeWelcome = async () => {
localStorage.setItem('showWelcome', false);
setWelcomeModal(false);
+
+ await tryInstallDefaultPack();
+
EventBus.emit('refresh', 'widgetsWelcomeDone');
EventBus.emit('refresh', 'widgets');
EventBus.emit('refresh', 'backgroundwelcome');
diff --git a/src/features/misc/sections/Experimental.jsx b/src/features/misc/sections/Experimental.jsx
index 88e6e965..6a41c53e 100644
--- a/src/features/misc/sections/Experimental.jsx
+++ b/src/features/misc/sections/Experimental.jsx
@@ -2,7 +2,6 @@ import variables from 'config/variables';
import { useState, memo } from 'react';
import { Checkbox, Slider } from 'components/Form/Settings';
import { Button } from 'components/Elements';
-import { TextField } from '@mui/material';
import { toast } from 'react-toastify';
import EventBus from 'utils/eventbus';
@@ -39,22 +38,26 @@ function ExperimentalOptions() {
element=".other"
/>
Send Event
- setEventType(e.target.value)}
- spellCheck={false}
- varient="outlined"
- InputLabelProps={{ shrink: true }}
- />
- setEventName(e.target.value)}
- spellCheck={false}
- varient="outlined"
- InputLabelProps={{ shrink: true }}
- />
+
+
+ setEventType(e.target.value)}
+ spellCheck={false}
+ />
+
+
+
+ setEventName(e.target.value)}
+ spellCheck={false}
+ />
+
diff --git a/src/features/navbar/components/Todo.jsx b/src/features/navbar/components/Todo.jsx
index 4614dbb0..da94b8e8 100644
--- a/src/features/navbar/components/Todo.jsx
+++ b/src/features/navbar/components/Todo.jsx
@@ -9,11 +9,10 @@ import {
MdPlaylistAdd,
MdOutlineDragIndicator,
MdPlaylistRemove,
+ MdCheck,
} from 'react-icons/md';
-import TextareaAutosize from '@mui/material/TextareaAutosize';
import { Tooltip } from 'components/Elements';
-
-import Checkbox from '@mui/material/Checkbox';
+import { Textarea } from 'components/Form/Settings';
import { shift, useFloating } from '@floating-ui/react-dom';
import {
DndContext,
@@ -210,15 +209,18 @@ function Todo({ todoRef, floatRef, position, xPosition, yPosition }) {
{({ attributes, listeners }) => (
- updateTodo('done', index)}
- />
-
+ {todoItem.done && }
+
+