diff --git a/package-lock.json b/package-lock.json index 8b148ef..e75fa21 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,18 @@ { "name": "ciphertalk", - "version": "2.2.7", + "version": "2.2.13", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "ciphertalk", - "version": "2.2.7", + "version": "2.2.13", "hasInstallScript": true, "license": "CC-BY-NC-SA-4.0", "dependencies": { + "@emotion/react": "^11.14.0", + "@emotion/styled": "^11.14.1", + "@mui/material": "^7.3.9", "@types/dompurify": "^3.0.5", "@types/marked": "^5.0.2", "@types/react-virtualized-auto-sizer": "^1.0.4", @@ -65,7 +68,6 @@ "version": "7.29.0", "resolved": "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.29.0.tgz", "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-validator-identifier": "^7.28.5", @@ -131,7 +133,6 @@ "version": "7.29.1", "resolved": "https://registry.npmmirror.com/@babel/generator/-/generator-7.29.1.tgz", "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/parser": "^7.29.0", @@ -175,7 +176,6 @@ "version": "7.28.0", "resolved": "https://registry.npmmirror.com/@babel/helper-globals/-/helper-globals-7.28.0.tgz", "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -185,7 +185,6 @@ "version": "7.28.6", "resolved": "https://registry.npmmirror.com/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/traverse": "^7.28.6", @@ -227,7 +226,6 @@ "version": "7.27.1", "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -237,7 +235,6 @@ "version": "7.28.5", "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -271,7 +268,6 @@ "version": "7.29.0", "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.29.0.tgz", "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", - "dev": true, "license": "MIT", "dependencies": { "@babel/types": "^7.29.0" @@ -315,11 +311,19 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/runtime": { + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.28.6.tgz", + "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/template": { "version": "7.28.6", "resolved": "https://registry.npmmirror.com/@babel/template/-/template-7.28.6.tgz", "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.28.6", @@ -334,7 +338,6 @@ "version": "7.29.0", "resolved": "https://registry.npmmirror.com/@babel/traverse/-/traverse-7.29.0.tgz", "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.29.0", @@ -353,7 +356,6 @@ "version": "7.29.0", "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.29.0.tgz", "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.27.1", @@ -741,6 +743,167 @@ "license": "0BSD", "optional": true }, + "node_modules/@emotion/babel-plugin": { + "version": "11.13.5", + "resolved": "https://registry.npmmirror.com/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz", + "integrity": "sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@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.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/babel-plugin/node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmmirror.com/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "license": "MIT" + }, + "node_modules/@emotion/babel-plugin/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@emotion/cache": { + "version": "11.14.0", + "resolved": "https://registry.npmmirror.com/@emotion/cache/-/cache-11.14.0.tgz", + "integrity": "sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==", + "license": "MIT", + "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" + } + }, + "node_modules/@emotion/hash": { + "version": "0.9.2", + "resolved": "https://registry.npmmirror.com/@emotion/hash/-/hash-0.9.2.tgz", + "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==", + "license": "MIT" + }, + "node_modules/@emotion/is-prop-valid": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/@emotion/is-prop-valid/-/is-prop-valid-1.4.0.tgz", + "integrity": "sha512-QgD4fyscGcbbKwJmqNvUMSE02OsHUa+lAWKdEUIJKgqe5IwRSKd7+KhibEWdaKwgjLj0DRSHA9biAIqGBk05lw==", + "license": "MIT", + "dependencies": { + "@emotion/memoize": "^0.9.0" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.9.0", + "resolved": "https://registry.npmmirror.com/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==", + "license": "MIT" + }, + "node_modules/@emotion/react": { + "version": "11.14.0", + "resolved": "https://registry.npmmirror.com/@emotion/react/-/react-11.14.0.tgz", + "integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@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.1" + }, + "peerDependencies": { + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/serialize": { + "version": "1.3.3", + "resolved": "https://registry.npmmirror.com/@emotion/serialize/-/serialize-1.3.3.tgz", + "integrity": "sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==", + "license": "MIT", + "dependencies": { + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/unitless": "^0.10.0", + "@emotion/utils": "^1.4.2", + "csstype": "^3.0.2" + } + }, + "node_modules/@emotion/sheet": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/@emotion/sheet/-/sheet-1.4.0.tgz", + "integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==", + "license": "MIT" + }, + "node_modules/@emotion/styled": { + "version": "11.14.1", + "resolved": "https://registry.npmmirror.com/@emotion/styled/-/styled-11.14.1.tgz", + "integrity": "sha512-qEEJt42DuToa3gurlH4Qqc1kVpNq8wO8cJtDzU46TjlzWjDlsVyevtYCRijVq3SrHsROS+gVQ8Fnea108GnKzw==", + "license": "MIT", + "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" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/unitless": { + "version": "0.10.0", + "resolved": "https://registry.npmmirror.com/@emotion/unitless/-/unitless-0.10.0.tgz", + "integrity": "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==", + "license": "MIT" + }, + "node_modules/@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.2.0.tgz", + "integrity": "sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==", + "license": "MIT", + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@emotion/utils": { + "version": "1.4.2", + "resolved": "https://registry.npmmirror.com/@emotion/utils/-/utils-1.4.2.tgz", + "integrity": "sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==", + "license": "MIT" + }, + "node_modules/@emotion/weak-memoize": { + "version": "0.4.0", + "resolved": "https://registry.npmmirror.com/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz", + "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==", + "license": "MIT" + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.25.12", "resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", @@ -1707,7 +1870,6 @@ "version": "0.3.13", "resolved": "https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", @@ -1729,7 +1891,6 @@ "version": "3.1.2", "resolved": "https://registry.npmmirror.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.0.0" @@ -1739,14 +1900,12 @@ "version": "1.5.5", "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.31", "resolved": "https://registry.npmmirror.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -1831,6 +1990,213 @@ "node": ">= 10.0.0" } }, + "node_modules/@mui/core-downloads-tracker": { + "version": "7.3.9", + "resolved": "https://registry.npmmirror.com/@mui/core-downloads-tracker/-/core-downloads-tracker-7.3.9.tgz", + "integrity": "sha512-MOkOCTfbMJwLshlBCKJ59V2F/uaLYfmKnN76kksj6jlGUVdI25A9Hzs08m+zjBRdLv+sK7Rqdsefe8X7h/6PCw==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + } + }, + "node_modules/@mui/material": { + "version": "7.3.9", + "resolved": "https://registry.npmmirror.com/@mui/material/-/material-7.3.9.tgz", + "integrity": "sha512-I8yO3t4T0y7bvDiR1qhIN6iBWZOTBfVOnmLlM7K6h3dx5YX2a7rnkuXzc2UkZaqhxY9NgTnEbdPlokR1RxCNRQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.6", + "@mui/core-downloads-tracker": "^7.3.9", + "@mui/system": "^7.3.9", + "@mui/types": "^7.4.12", + "@mui/utils": "^7.3.9", + "@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" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@mui/material-pigment-css": "^7.3.9", + "@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" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@mui/material-pigment-css": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/private-theming": { + "version": "7.3.9", + "resolved": "https://registry.npmmirror.com/@mui/private-theming/-/private-theming-7.3.9.tgz", + "integrity": "sha512-ErIyRQvsiQEq7Yvcvfw9UDHngaqjMy9P3JDPnRAaKG5qhpl2C4tX/W1S4zJvpu+feihmZJStjIyvnv6KDbIrlw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.6", + "@mui/utils": "^7.3.9", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/styled-engine": { + "version": "7.3.9", + "resolved": "https://registry.npmmirror.com/@mui/styled-engine/-/styled-engine-7.3.9.tgz", + "integrity": "sha512-JqujWt5bX4okjUPGpVof/7pvgClqh7HvIbsIBIOOlCh2u3wG/Bwp4+E1bc1dXSwkrkp9WUAoNdI5HEC+5HKvMw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.6", + "@emotion/cache": "^11.14.0", + "@emotion/serialize": "^1.3.3", + "@emotion/sheet": "^1.4.0", + "csstype": "^3.2.3", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.4.1", + "@emotion/styled": "^11.3.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + } + } + }, + "node_modules/@mui/system": { + "version": "7.3.9", + "resolved": "https://registry.npmmirror.com/@mui/system/-/system-7.3.9.tgz", + "integrity": "sha512-aL1q9am8XpRrSabv9qWf5RHhJICJql34wnrc1nz0MuOglPRYF/liN+c8VqZdTvUn9qg+ZjRVbKf4sJVFfIDtmg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.6", + "@mui/private-theming": "^7.3.9", + "@mui/styled-engine": "^7.3.9", + "@mui/types": "^7.4.12", + "@mui/utils": "^7.3.9", + "clsx": "^2.1.1", + "csstype": "^3.2.3", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "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" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/types": { + "version": "7.4.12", + "resolved": "https://registry.npmmirror.com/@mui/types/-/types-7.4.12.tgz", + "integrity": "sha512-iKNAF2u9PzSIj40CjvKJWxFXJo122jXVdrmdh0hMYd+FR+NuJMkr/L88XwWLCRiJ5P1j+uyac25+Kp6YC4hu6w==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.6" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/utils": { + "version": "7.3.9", + "resolved": "https://registry.npmmirror.com/@mui/utils/-/utils-7.3.9.tgz", + "integrity": "sha512-U6SdZaGbfb65fqTsH3V5oJdFj9uYwyLE2WVuNvmbggTSDBb8QHrFsqY8BN3taK9t3yJ8/BPHD/kNvLNyjwM7Yw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.6", + "@mui/types": "^7.4.12", + "@types/prop-types": "^15.7.15", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-is": "^19.2.3" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@npmcli/agent": { "version": "3.0.0", "resolved": "https://registry.npmmirror.com/@npmcli/agent/-/agent-3.0.0.tgz", @@ -2212,6 +2578,16 @@ "node": ">=14" } }, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmmirror.com/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, "node_modules/@rolldown/pluginutils": { "version": "1.0.0-beta.27", "resolved": "https://registry.npmmirror.com/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz", @@ -2758,6 +3134,12 @@ "form-data": "^4.0.4" } }, + "node_modules/@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmmirror.com/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", + "license": "MIT" + }, "node_modules/@types/plist": { "version": "3.0.5", "resolved": "https://registry.npmmirror.com/@types/plist/-/plist-3.0.5.tgz", @@ -2770,6 +3152,12 @@ "xmlbuilder": ">=11.0.1" } }, + "node_modules/@types/prop-types": { + "version": "15.7.15", + "resolved": "https://registry.npmmirror.com/@types/prop-types/-/prop-types-15.7.15.tgz", + "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", + "license": "MIT" + }, "node_modules/@types/react": { "version": "19.2.14", "resolved": "https://registry.npmmirror.com/@types/react/-/react-19.2.14.tgz", @@ -2789,6 +3177,15 @@ "@types/react": "^19.2.0" } }, + "node_modules/@types/react-transition-group": { + "version": "4.4.12", + "resolved": "https://registry.npmmirror.com/@types/react-transition-group/-/react-transition-group-4.4.12.tgz", + "integrity": "sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*" + } + }, "node_modules/@types/react-virtualized-auto-sizer": { "version": "1.0.4", "resolved": "https://registry.npmmirror.com/@types/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.4.tgz", @@ -3773,6 +4170,21 @@ "when-exit": "^2.1.4" } }, + "node_modules/babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + } + }, "node_modules/balanced-match": { "version": "4.0.2", "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-4.0.2.tgz", @@ -4293,6 +4705,15 @@ "node": ">= 0.4" } }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/caniuse-lite": { "version": "1.0.30001770", "resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001770.tgz", @@ -4491,6 +4912,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/codepage": { "version": "1.15.0", "resolved": "https://registry.npmmirror.com/codepage/-/codepage-1.15.0.tgz", @@ -4875,6 +5305,31 @@ "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", "license": "MIT" }, + "node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmmirror.com/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "license": "MIT", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cosmiconfig/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmmirror.com/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, "node_modules/crc": { "version": "3.8.0", "resolved": "https://registry.npmmirror.com/crc/-/crc-3.8.0.tgz", @@ -5224,6 +5679,16 @@ "node": ">=8" } }, + "node_modules/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmmirror.com/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, "node_modules/dom-to-image-more": { "version": "3.7.2", "resolved": "https://registry.npmmirror.com/dom-to-image-more/-/dom-to-image-more-3.7.2.tgz", @@ -5682,6 +6147,15 @@ "dev": true, "license": "MIT" }, + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmmirror.com/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, "node_modules/es-define-property": { "version": "1.0.1", "resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.1.tgz", @@ -5998,6 +6472,12 @@ "node": ">=10" } }, + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", + "license": "MIT" + }, "node_modules/foreground-child": { "version": "3.3.1", "resolved": "https://registry.npmmirror.com/foreground-child/-/foreground-child-3.3.1.tgz", @@ -6441,6 +6921,21 @@ "node": ">= 0.4" } }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmmirror.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "license": "BSD-3-Clause", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/hoist-non-react-statics/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmmirror.com/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT" + }, "node_modules/hosted-git-info": { "version": "4.1.0", "resolved": "https://registry.npmmirror.com/hosted-git-info/-/hosted-git-info-4.1.0.tgz", @@ -6623,6 +7118,22 @@ "dev": true, "license": "MIT" }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmmirror.com/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmmirror.com/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -6684,6 +7195,12 @@ "node": ">= 12" } }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "license": "MIT" + }, "node_modules/is-ci": { "version": "3.0.1", "resolved": "https://registry.npmmirror.com/is-ci/-/is-ci-3.0.1.tgz", @@ -6697,6 +7214,21 @@ "is-ci": "bin.js" } }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmmirror.com/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz", @@ -6832,7 +7364,6 @@ "version": "4.0.0", "resolved": "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, "license": "MIT" }, "node_modules/js-yaml": { @@ -6851,7 +7382,6 @@ "version": "3.1.0", "resolved": "https://registry.npmmirror.com/jsesc/-/jsesc-3.1.0.tgz", "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "dev": true, "license": "MIT", "bin": { "jsesc": "bin/jsesc" @@ -6867,6 +7397,12 @@ "dev": true, "license": "MIT" }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmmirror.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "license": "MIT" + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -7036,6 +7572,12 @@ "immediate": "~3.0.5" } }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmmirror.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "license": "MIT" + }, "node_modules/lodash": { "version": "4.17.23", "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.23.tgz", @@ -7113,6 +7655,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, "node_modules/lowercase-keys": { "version": "2.0.0", "resolved": "https://registry.npmmirror.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz", @@ -7688,6 +8242,15 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmmirror.com/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-keys": { "version": "1.1.1", "resolved": "https://registry.npmmirror.com/object-keys/-/object-keys-1.1.1.tgz", @@ -7866,11 +8429,41 @@ "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", "license": "(MIT AND Zlib)" }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/parse-cache-control": { "version": "1.0.1", "resolved": "https://registry.npmmirror.com/parse-cache-control/-/parse-cache-control-1.0.1.tgz", "integrity": "sha512-60zvsJReQPX5/QP0Kzfd/VrpjScIQ7SHBW6bFCYfEP+fp0Eppr1SHhIO5nd1PjZtvclzSzES9D/p5nFJurwfWg==" }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmmirror.com/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmmirror.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -7891,6 +8484,12 @@ "node": ">=8" } }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmmirror.com/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "license": "MIT" + }, "node_modules/path-scurry": { "version": "1.11.1", "resolved": "https://registry.npmmirror.com/path-scurry/-/path-scurry-1.11.1.tgz", @@ -7915,6 +8514,15 @@ "dev": true, "license": "ISC" }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/pe-library": { "version": "0.4.1", "resolved": "https://registry.npmmirror.com/pe-library/-/pe-library-0.4.1.tgz", @@ -7941,7 +8549,6 @@ "version": "1.1.1", "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, "license": "ISC" }, "node_modules/picomatch": { @@ -8095,6 +8702,23 @@ "node": ">=10" } }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmmirror.com/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/prop-types/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmmirror.com/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT" + }, "node_modules/pump": { "version": "3.0.3", "resolved": "https://registry.npmmirror.com/pump/-/pump-3.0.3.tgz", @@ -8164,6 +8788,12 @@ "react": "^19.2.4" } }, + "node_modules/react-is": { + "version": "19.2.4", + "resolved": "https://registry.npmmirror.com/react-is/-/react-is-19.2.4.tgz", + "integrity": "sha512-W+EWGn2v0ApPKgKKCy/7s7WHXkboGcsrXE+2joLyVxkbyVQfO3MUEaUQDHoSmb8TFFrSKYa9mw64WZHNHSDzYA==", + "license": "MIT" + }, "node_modules/react-refresh": { "version": "0.17.0", "resolved": "https://registry.npmmirror.com/react-refresh/-/react-refresh-0.17.0.tgz", @@ -8212,6 +8842,22 @@ "react-dom": ">=18" } }, + "node_modules/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmmirror.com/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "license": "BSD-3-Clause", + "dependencies": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": ">=16.6.0", + "react-dom": ">=16.6.0" + } + }, "node_modules/react-virtualized-auto-sizer": { "version": "2.0.3", "resolved": "https://registry.npmmirror.com/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-2.0.3.tgz", @@ -8354,6 +9000,26 @@ "url": "https://github.com/sponsors/jet2jet" } }, + "node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmmirror.com/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/resolve-alpn": { "version": "1.2.1", "resolved": "https://registry.npmmirror.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz", @@ -8361,6 +9027,15 @@ "dev": true, "license": "MIT" }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/responselike": { "version": "2.0.1", "resolved": "https://registry.npmmirror.com/responselike/-/responselike-2.0.1.tgz", @@ -9064,6 +9739,12 @@ "integrity": "sha512-zOh9jPYI+xrNOyisSelgym4tolKTJCQd5GBhK0+0xJvcYDcwlOoxF/rnFKQ2KRZknXSG9jWAp66fwP6AxN9STg==", "license": "MIT" }, + "node_modules/stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==", + "license": "MIT" + }, "node_modules/sumchecker": { "version": "3.0.1", "resolved": "https://registry.npmmirror.com/sumchecker/-/sumchecker-3.0.1.tgz", @@ -9090,6 +9771,18 @@ "node": ">=8" } }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/tar": { "version": "7.5.9", "resolved": "https://registry.npmmirror.com/tar/-/tar-7.5.9.tgz", diff --git a/package.json b/package.json index e9d4850..f0a4982 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,9 @@ "tuisong": "node scripts/push-release.js" }, "dependencies": { + "@emotion/react": "^11.14.0", + "@emotion/styled": "^11.14.1", + "@mui/material": "^7.3.9", "@types/dompurify": "^3.0.5", "@types/marked": "^5.0.2", "@types/react-virtualized-auto-sizer": "^1.0.4", @@ -162,4 +165,4 @@ "resources/**/*" ] } -} \ No newline at end of file +} diff --git a/src/App.scss b/src/App.scss index da02ba7..ee57a59 100644 --- a/src/App.scss +++ b/src/App.scss @@ -5,22 +5,6 @@ background: var(--bg-primary); } -.main-layout { - flex: 1; - display: flex; - overflow: hidden; -} - -.content { - flex: 1; - overflow: auto; - padding: 24px 24px 0 24px; // 移除底部 padding - - &.no-overflow { - overflow: hidden; // 数据管理页面禁用外层滚动 - } -} - // 更新提示悬浮卡片 .update-toast { position: fixed; diff --git a/src/App.tsx b/src/App.tsx index 7a55c5c..b8cfd53 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,5 +1,6 @@ import { useEffect, useState } from 'react' import { Routes, Route, useNavigate, useLocation } from 'react-router-dom' +import Box from '@mui/material/Box' import TitleBar from './components/TitleBar' import Sidebar from './components/Sidebar' import RouteGuard from './components/RouteGuard' @@ -459,6 +460,8 @@ function App() { } // 主窗口 - 完整布局 + const disableContentOverflow = ['/data-management', '/settings', '/open-api'].includes(location.pathname) + return (
@@ -481,10 +484,25 @@ function App() {
)} -
+ -
@@ -499,8 +517,8 @@ function App() { } /> -
-
+ + {downloadProgress !== null && (
diff --git a/src/components/Sidebar.scss b/src/components/Sidebar.scss deleted file mode 100644 index f43c052..0000000 --- a/src/components/Sidebar.scss +++ /dev/null @@ -1,126 +0,0 @@ -.sidebar { - width: 200px; - background: var(--bg-secondary); - border-right: 1px solid var(--border-color); - display: flex; - flex-direction: column; - padding: 16px 0; - transition: width 0.25s ease; - position: relative; - z-index: 100; - - &.collapsed { - width: 64px; - - .nav-menu { - padding: 0 8px; - } - - .nav-label, - .collapse-label { - display: none; - } - - .nav-item { - justify-content: center; - padding: 10px; - gap: 0; - } - - .collapse-btn { - justify-content: center; - padding: 10px; - gap: 0; - } - } -} - -.nav-menu { - flex: 1; - display: flex; - flex-direction: column; - gap: 4px; - padding: 0 8px; -} - -.nav-item { - display: flex; - align-items: center; - gap: 12px; - padding: 10px 16px; - border-radius: 9999px; - color: var(--text-secondary); - text-decoration: none; - transition: all 0.2s ease; - white-space: nowrap; - border: none; - background: transparent; - cursor: pointer; - font-family: inherit; - width: 100%; - - &:hover { - background: var(--bg-tertiary); - color: var(--text-primary); - } - - &.active { - background: var(--primary); - color: white; - } -} - -.nav-icon { - display: flex; - align-items: center; - justify-content: center; - width: 20px; - height: 20px; - flex-shrink: 0; -} - -.nav-label { - font-size: 14px; - font-weight: 500; -} - -.sidebar-footer { - padding: 12px 8px 0 8px; - border-top: 1px solid var(--border-color); - margin-top: 8px; - display: flex; - flex-direction: column; - gap: 4px; -} - -.collapse-btn { - display: flex; - align-items: center; - justify-content: flex-start; - gap: 12px; - width: 100%; - padding: 10px 16px; - border: none; - background: transparent; - color: var(--text-secondary); - cursor: pointer; - border-radius: 9999px; - transition: all 0.2s ease; - margin-top: 4px; - font-family: inherit; - - svg { - width: 20px; - height: 20px; - } - - &:hover { - background: var(--bg-tertiary); - color: var(--text-primary); - } - - .collapse-label { - font-size: 14px; - font-weight: 500; - } -} diff --git a/src/components/Sidebar.tsx b/src/components/Sidebar.tsx index f72d8ba..27fcbbd 100644 --- a/src/components/Sidebar.tsx +++ b/src/components/Sidebar.tsx @@ -1,11 +1,48 @@ -import { useState } from 'react' +import { useState, type ReactElement } from 'react' import { NavLink, useLocation } from 'react-router-dom' +import Avatar from '@mui/material/Avatar' +import Box from '@mui/material/Box' +import Divider from '@mui/material/Divider' +import Drawer from '@mui/material/Drawer' +import List from '@mui/material/List' +import ListItem from '@mui/material/ListItem' +import ListItemButton from '@mui/material/ListItemButton' +import ListItemIcon from '@mui/material/ListItemIcon' +import Tooltip from '@mui/material/Tooltip' +import Typography from '@mui/material/Typography' import { Home, MessageSquare, BarChart3, Users, FileText, Database, Settings, SquareChevronLeft, SquareChevronRight, Download, Aperture, Network } from 'lucide-react' -import './Sidebar.scss' +import { useAppStore } from '../stores/appStore' + +const DRAWER_WIDTH = 220 +const COLLAPSED_DRAWER_WIDTH = 72 + +type RouteItem = { + key: string + label: string + icon: ReactElement + type: 'route' + path: string +} + +type ActionItem = { + key: string + label: string + icon: ReactElement + type: 'action' + onClick: () => void +} + +type NavItemConfig = RouteItem | ActionItem function Sidebar() { const location = useLocation() + const userInfo = useAppStore(state => state.userInfo) const [collapsed, setCollapsed] = useState(false) + const drawerWidth = collapsed ? COLLAPSED_DRAWER_WIDTH : DRAWER_WIDTH + const userDisplayName = userInfo?.nickName?.trim() || userInfo?.alias?.trim() || '未连接用户' + const userInitial = userDisplayName.slice(0, 1).toUpperCase() + const widthTransition = '220ms cubic-bezier(0.4, 0, 0.2, 1)' + const fadeTransition = '140ms ease' const isActive = (path: string) => { return location.pathname === path @@ -35,122 +72,282 @@ function Sidebar() { } } + const navItems: NavItemConfig[] = [ + { key: 'home', label: '首页', icon: , type: 'route', path: '/home' }, + { key: 'chat', label: '聊天查看', icon: , type: 'action', onClick: openChatWindow }, + { key: 'moments', label: '朋友圈', icon: , type: 'action', onClick: openMomentsWindow }, + { key: 'analytics', label: '私聊分析', icon: , type: 'route', path: '/analytics' }, + { key: 'group-analytics', label: '群聊分析', icon: , type: 'action', onClick: openGroupAnalyticsWindow }, + { key: 'annual-report', label: '年度报告', icon: , type: 'route', path: '/annual-report' }, + { key: 'export', label: '导出数据', icon: , type: 'route', path: '/export' }, + { key: 'data-management', label: '数据管理', icon: , type: 'route', path: '/data-management' }, + { key: 'open-api', label: '开放接口', icon: , type: 'route', path: '/open-api' }, + ] + + const navItemSx = { + minHeight: 44, + width: collapsed ? 44 : '100%', + mx: collapsed ? 'auto' : 0, + px: 1.25, + py: 1, + borderRadius: collapsed ? '50%' : '9999px', + justifyContent: 'center', + color: 'var(--text-secondary)', + transition: `width 220ms cubic-bezier(0.4, 0, 0.2, 1), margin 220ms cubic-bezier(0.4, 0, 0.2, 1), border-radius 220ms cubic-bezier(0.4, 0, 0.2, 1), background-color 0.2s ease, color 0.2s ease`, + '&:hover': { + backgroundColor: 'var(--bg-tertiary)', + color: 'var(--text-primary)', + }, + '&.Mui-selected': { + backgroundColor: 'var(--primary)', + color: '#ffffff', + }, + '&.Mui-selected:hover': { + backgroundColor: 'var(--primary-hover)', + }, + } + + const navItemIconSx = { + minWidth: 24, + width: 24, + color: 'inherit', + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + flexShrink: 0, + } + + const railContentSx = { + display: 'flex', + alignItems: 'center', + overflow: 'hidden', + width: collapsed ? '24px' : '100%', + transition: `width ${widthTransition}`, + } + + const profileContentSx = { + display: 'flex', + alignItems: 'center', + overflow: 'hidden', + width: collapsed ? '36px' : '100%', + transition: `width ${widthTransition}`, + } + + const createLabelSx = (maxWidth: number) => ({ + minWidth: 0, + overflow: 'hidden', + whiteSpace: 'nowrap', + maxWidth: collapsed ? '0px' : `${maxWidth}px`, + opacity: collapsed ? 0 : 1, + transform: collapsed ? 'translateX(-8px)' : 'translateX(0)', + marginLeft: collapsed ? '0px' : '12px', + transition: [ + `max-width ${widthTransition}`, + `opacity ${fadeTransition}`, + `transform ${widthTransition}`, + `margin-left ${widthTransition}`, + ].join(', '), + }) + + const renderNavItem = (item: NavItemConfig) => { + const selected = item.type === 'route' ? isActive(item.path) : false + const button = ( + + + + {item.icon} + + + + {item.label} + + + + + ) + + return ( + + + {button} + + + ) + } + return ( - + + + setCollapsed(!collapsed)} + sx={navItemSx} + > + + + {collapsed ? : } + + + + {collapsed ? '展开' : '收回'} + + + + + + + + + + ) } diff --git a/src/pages/OpenApiPage.tsx b/src/pages/OpenApiPage.tsx index e9e514e..757f206 100644 --- a/src/pages/OpenApiPage.tsx +++ b/src/pages/OpenApiPage.tsx @@ -1,37 +1,412 @@ -import { useEffect, useState } from 'react' +import { useEffect, useState, type ReactNode } from 'react' +import { + Alert, + Box, + Button, + Card, + CardContent, + CardHeader, + Chip, + CircularProgress, + Container, + IconButton, + InputAdornment, + Snackbar, + Stack, + Switch, + TextField, + Tooltip, + Typography, +} from '@mui/material' +import { ChevronDown, ChevronUp, Copy, Eye, EyeOff, FileText, RefreshCw, RotateCcw, Save, Sparkles } from 'lucide-react' import * as configService from '../services/config' -import { Save, RefreshCw, RotateCcw, Eye, EyeOff, Sparkles, Copy, FileText, AlertCircle } from 'lucide-react' import { useTitleBarStore } from '../stores/titleBarStore' -import './SettingsPage.scss' + +const HTTP_API_DOC_URL = 'https://ciphertalk.apifox.cn/' + +type ToastState = { + text: string + success: boolean +} + +type HttpApiStatus = { + running: boolean + host: string + port: number + enabled: boolean + startedAt: string + uptimeMs: number + tokenConfigured: boolean + tokenPreview: string + baseUrl: string + endpoints: Array<{ method: string; path: string; desc: string }> + lastError: string +} + +type StatusMetricCardProps = { + label: string + value: ReactNode + helper?: string +} + +const LARGE_RADIUS = '28px' +const MEDIUM_RADIUS = '24px' +const SMALL_RADIUS = '20px' + +const monoSx = { + fontFamily: 'var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace)', +} + +const cardSx = { + borderRadius: LARGE_RADIUS, + border: 'none', + bgcolor: 'transparent', + backdropFilter: 'none', + boxShadow: 'none', + overflow: 'visible', +} + +const sectionHeaderSx = { + px: { xs: 0.5, md: 1 }, + pt: 0, + pb: 1.5, +} + +const sectionContentSx = { + px: { xs: 0.5, md: 1 }, + pt: 0, + '&:last-child': { + pb: 0, + }, +} + +const pillButtonSx = { + borderRadius: '999px', + px: 2.25, + minHeight: 44, + textTransform: 'none', + fontWeight: 600, +} + +const primaryButtonSx = { + ...pillButtonSx, + color: '#fff', + background: 'var(--primary-gradient)', + boxShadow: '0 10px 28px var(--primary-light)', + '&:hover': { + background: 'var(--primary-gradient)', + filter: 'brightness(0.98)', + boxShadow: '0 12px 30px var(--primary-light)', + }, + '&.Mui-disabled': { + color: 'var(--text-tertiary)', + background: 'var(--bg-tertiary)', + boxShadow: 'none', + }, +} + +const secondaryButtonSx = { + ...pillButtonSx, + color: 'var(--text-primary)', + borderColor: 'var(--border-color)', + backgroundColor: 'var(--bg-secondary)', + '&:hover': { + borderColor: 'var(--primary)', + backgroundColor: 'var(--primary-light)', + }, + '&.Mui-disabled': { + color: 'var(--text-tertiary)', + borderColor: 'var(--border-color)', + backgroundColor: 'transparent', + }, +} + +const inlineIconButtonSx = { + color: 'var(--text-secondary)', + bgcolor: 'transparent', + borderRadius: '999px', + '&:hover': { + color: 'var(--text-primary)', + bgcolor: 'var(--primary-light)', + }, +} + +const codePillSx = { + ...monoSx, + display: 'inline-flex', + alignItems: 'center', + px: 1, + py: 0.5, + borderRadius: '999px', + fontSize: 12, + bgcolor: 'var(--bg-tertiary)', + border: '1px solid var(--border-color)', + color: 'var(--text-primary)', +} + +const panelSx = { + p: 2.25, + borderRadius: MEDIUM_RADIUS, + border: '1px solid var(--border-color)', + bgcolor: 'var(--bg-secondary)', + boxShadow: '0 6px 18px rgba(0, 0, 0, 0.03)', +} + +const textFieldSx = { + '& .MuiInputLabel-root': { + color: 'var(--text-secondary)', + }, + '& .MuiInputLabel-root.Mui-focused': { + color: 'var(--primary)', + }, + '& .MuiOutlinedInput-root': { + height: 42, + borderRadius: '999px', + color: 'var(--text-primary)', + backgroundColor: 'var(--bg-secondary)', + overflow: 'hidden', + alignItems: 'stretch', + pr: 0, + '& fieldset': { + borderColor: 'var(--border-color)', + }, + '&:hover fieldset': { + borderColor: 'var(--primary)', + }, + '&.Mui-focused': { + boxShadow: '0 0 0 4px var(--primary-light)', + }, + '&.Mui-focused fieldset': { + borderColor: 'var(--primary)', + borderWidth: 1, + }, + }, + '& .MuiInputBase-input': { + paddingTop: '10px', + paddingBottom: '10px', + paddingLeft: '16px', + paddingRight: '12px', + color: 'var(--text-primary)', + }, + '& input[type=number]': { + appearance: 'textfield', + }, + '& input[type=number]::-webkit-outer-spin-button, & input[type=number]::-webkit-inner-spin-button': { + WebkitAppearance: 'none', + margin: 0, + }, + '& .MuiInputAdornment-root': { + margin: 0, + alignSelf: 'stretch', + maxHeight: 'none', + height: '100%', + }, + '& .MuiFormHelperText-root': { + marginLeft: 1.5, + marginTop: 0.75, + color: 'var(--text-tertiary)', + }, + '& .MuiFormHelperText-root.Mui-error': { + color: 'var(--danger)', + }, +} + +const endpointCardSx = { + p: 2.25, + borderRadius: MEDIUM_RADIUS, + border: '1px solid var(--border-color)', + bgcolor: 'var(--bg-secondary)', + boxShadow: '0 6px 18px rgba(0, 0, 0, 0.03)', +} + +const endpointPathSx = { + ...codePillSx, + px: 1.4, + py: 0.85, + fontSize: 13, +} + +const tertiaryButtonSx = { + borderRadius: '999px', + minHeight: 34, + px: 1.5, + textTransform: 'none', + color: 'var(--text-secondary)', + borderColor: 'var(--border-color)', + backgroundColor: 'transparent', + '&:hover': { + borderColor: 'var(--primary)', + color: 'var(--primary)', + backgroundColor: 'var(--primary-light)', + }, +} + +const stepperButtonSx = { + width: '100%', + flex: 1, + minWidth: 0, + borderRadius: 0, + color: 'var(--text-secondary)', + backgroundColor: 'transparent', + '& + &': { + borderTop: '1px solid var(--border-color)', + }, + '&:hover': { + color: 'var(--primary)', + bgcolor: 'var(--primary-light)', + }, +} + +const switchSx = { + '& .MuiSwitch-switchBase.Mui-checked': { + color: 'var(--primary)', + }, + '& .MuiSwitch-switchBase.Mui-checked + .MuiSwitch-track': { + backgroundColor: 'var(--primary)', + opacity: 1, + }, + '& .MuiSwitch-track': { + borderRadius: '999px', + backgroundColor: 'var(--text-tertiary)', + opacity: 0.35, + }, +} + +const getChipSx = (tone: 'primary' | 'neutral' | 'danger' = 'neutral') => { + if (tone === 'primary') { + return { + borderRadius: '999px', + border: '1px solid var(--primary)', + color: 'var(--primary)', + backgroundColor: 'var(--primary-light)', + fontWeight: 700, + } + } + + if (tone === 'danger') { + return { + borderRadius: '999px', + border: '1px solid rgba(220, 53, 69, 0.24)', + color: 'var(--danger)', + backgroundColor: 'rgba(220, 53, 69, 0.08)', + fontWeight: 700, + } + } + + return { + borderRadius: '999px', + border: '1px solid var(--border-color)', + color: 'var(--text-secondary)', + backgroundColor: 'var(--bg-secondary)', + fontWeight: 700, + } +} + +const getAlertSx = (tone: 'primary' | 'neutral' | 'danger' = 'primary') => ({ + borderRadius: MEDIUM_RADIUS, + border: '1px solid', + borderColor: tone === 'danger' ? 'rgba(220, 53, 69, 0.24)' : 'var(--border-color)', + bgcolor: tone === 'danger' + ? 'rgba(220, 53, 69, 0.08)' + : tone === 'primary' + ? 'var(--primary-light)' + : 'var(--bg-secondary)', + color: 'var(--text-primary)', + '& .MuiAlert-icon': { + color: tone === 'danger' ? 'var(--danger)' : 'var(--primary)', + }, +}) + +function formatDuration(durationMs: number) { + if (!durationMs || durationMs <= 0) { + return '0 秒' + } + + const totalSeconds = Math.floor(durationMs / 1000) + const days = Math.floor(totalSeconds / 86400) + const hours = Math.floor((totalSeconds % 86400) / 3600) + const minutes = Math.floor((totalSeconds % 3600) / 60) + const seconds = totalSeconds % 60 + + const parts = [ + days > 0 ? `${days} 天` : null, + hours > 0 ? `${hours} 小时` : null, + minutes > 0 ? `${minutes} 分钟` : null, + seconds > 0 ? `${seconds} 秒` : null, + ].filter(Boolean) + + return parts.slice(0, 3).join(' ') +} + +function createRandomToken() { + if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') { + return `ct_${crypto.randomUUID().replace(/-/g, '')}` + } + + const randomPart = Math.random().toString(36).slice(2) + const randomPart2 = Math.random().toString(36).slice(2) + return `ct_${Date.now().toString(36)}_${randomPart}${randomPart2}` +} + +function getEndpointUrl(baseUrl: string, path: string) { + if (path === '/v1' || path === '/v1/') { + return baseUrl + } + + return `${baseUrl}${path.replace(/^\/v1/, '')}` +} + +function StatusMetricCard({ label, value, helper }: StatusMetricCardProps) { + return ( + + + + + {label} + + {helper && ( + + {helper} + + )} + + + {typeof value === 'string' + ? ( + + {value} + + ) + : value} + + + + ) +} function OpenApiPage() { - const HTTP_API_DOC_URL = 'https://ciphertalk.apifox.cn/' - - const [message, setMessage] = useState<{ text: string; success: boolean } | null>(null) + const [message, setMessage] = useState(null) const [httpApiEnabled, setHttpApiEnabled] = useState(false) const [httpApiPort, setHttpApiPort] = useState(5031) const [httpApiToken, setHttpApiToken] = useState('') const [showHttpApiToken, setShowHttpApiToken] = useState(false) - const [httpApiStatus, setHttpApiStatus] = useState<{ - running: boolean - host: string - port: number - enabled: boolean - startedAt: string - uptimeMs: number - tokenConfigured: boolean - tokenPreview: string - baseUrl: string - endpoints: Array<{ method: string; path: string; desc: string }> - lastError: string - } | null>(null) + const [httpApiStatus, setHttpApiStatus] = useState(null) const [isSavingHttpApi, setIsSavingHttpApi] = useState(false) const [isRefreshingHttpApi, setIsRefreshingHttpApi] = useState(false) const [nowTs, setNowTs] = useState(Date.now()) + const setTitleBarContent = useTitleBarStore(state => state.setRightContent) + const showMessage = (text: string, success: boolean) => { setMessage({ text, success }) - setTimeout(() => setMessage(null), 3000) } const copyText = async (text: string, successText: string) => { @@ -43,18 +418,13 @@ function OpenApiPage() { } } - const createRandomToken = () => { - const randomPart = Math.random().toString(36).slice(2) - const randomPart2 = Math.random().toString(36).slice(2) - return `ct_${Date.now().toString(36)}_${randomPart}${randomPart2}` - } - useEffect(() => { const load = async () => { try { const enabled = await configService.getHttpApiEnabled() const port = await configService.getHttpApiPort() const token = await configService.getHttpApiToken() + setHttpApiEnabled(enabled) setHttpApiPort(port) setHttpApiToken(token) @@ -63,37 +433,46 @@ function OpenApiPage() { if (statusResult.success && statusResult.status) { setHttpApiStatus(statusResult.status) } - } catch (e) { - showMessage(`加载开放接口配置失败: ${e}`, false) + } catch (error) { + showMessage(`加载开放接口配置失败: ${error}`, false) } } + load() }, []) useEffect(() => { - if (!httpApiStatus?.running) return + if (!httpApiStatus?.running) { + return + } + const timer = window.setInterval(() => setNowTs(Date.now()), 1000) return () => window.clearInterval(timer) }, [httpApiStatus?.running]) - const setTitleBarContent = useTitleBarStore(state => state.setRightContent) - useEffect(() => { setTitleBarContent( - + 接口文档 + ) + return () => setTitleBarContent(null) }, [setTitleBarContent]) const refreshHttpApiStatus = async () => { setIsRefreshingHttpApi(true) + try { const result = await window.electronAPI.httpApi.getStatus() if (result.success && result.status) { @@ -103,20 +482,28 @@ function OpenApiPage() { } else { showMessage(result.error || '获取接口状态失败', false) } - } catch (e) { - showMessage(`获取接口状态失败: ${e}`, false) + } catch (error) { + showMessage(`获取接口状态失败: ${error}`, false) } finally { setIsRefreshingHttpApi(false) } } + const isPortInvalid = !Number.isInteger(httpApiPort) || httpApiPort < 1 || httpApiPort > 65535 + const handleSaveHttpApiSettings = async () => { + if (isPortInvalid) { + showMessage('监听端口需在 1 到 65535 之间', false) + return + } + setIsSavingHttpApi(true) + try { const result = await window.electronAPI.httpApi.applySettings({ enabled: httpApiEnabled, port: httpApiPort, - token: httpApiToken + token: httpApiToken, }) if (result.success && result.status) { @@ -129,8 +516,8 @@ function OpenApiPage() { } else { showMessage(result.error || '保存开放接口配置失败', false) } - } catch (e) { - showMessage(`保存开放接口配置失败: ${e}`, false) + } catch (error) { + showMessage(`保存开放接口配置失败: ${error}`, false) } finally { setIsSavingHttpApi(false) } @@ -138,6 +525,7 @@ function OpenApiPage() { const handleRestartHttpApi = async () => { setIsRefreshingHttpApi(true) + try { const result = await window.electronAPI.httpApi.restart() if (result.success && result.status) { @@ -146,8 +534,8 @@ function OpenApiPage() { } else { showMessage(result.error || '接口服务重启失败', false) } - } catch (e) { - showMessage(`接口服务重启失败: ${e}`, false) + } catch (error) { + showMessage(`接口服务重启失败: ${error}`, false) } finally { setIsRefreshingHttpApi(false) } @@ -158,174 +546,536 @@ function OpenApiPage() { const uptime = status?.running && startedAtMs > 0 ? Math.max(0, nowTs - startedAtMs) : (status?.uptimeMs ?? 0) - const uptimeText = uptime > 0 ? `${Math.floor(uptime / 1000)} 秒` : '0 秒' + const uptimeText = formatDuration(uptime) + const fallbackBaseUrl = `http://127.0.0.1:${isPortInvalid ? 5031 : httpApiPort}/v1` + const baseUrl = status?.baseUrl || fallbackBaseUrl return ( -
- {message &&
{message.text}
} - -
-
-
-

开放接口(HTTP API)

-
用于给外部工具调用,默认仅监听本机地址 `127.0.0.1`。
- -
-
-
-
-
启用 HTTP API
-
关闭后将停止监听端口,不再对外提供接口。
-
- -
-
-
+ 开放接口 + + + 用于给外部工具调用,默认仅监听本机地址 + 127.0.0.1 + ,正式接口统一使用 + /v1 + 前缀。 + + -
- - 建议保持默认 5031,范围 1-65535 - setHttpApiPort(Number(e.target.value || 5031))} + + + + + + + + + {httpApiEnabled + ? 'HTTP API 已处于启用配置。修改端口或密钥后,需要点击“保存并应用”同步到本地服务。' + : 'HTTP API 当前关闭。保存并应用后才会开始监听端口,对外提供接口。'} + + + + -
+ + + + + + + 启用 HTTP API + + + 关闭后会停止监听端口,不再接受外部请求。 + + -
- - 令牌预设说明:留空表示不鉴权;设置后,`/v1/status` 等接口必须携带 `Authorization: Bearer <token>`。 -
- setHttpApiToken(e.target.value)} - placeholder="留空表示不启用令牌鉴权" - /> -
- - -
-
-
+ { + const nextPort = Number(event.target.value) + setHttpApiPort(Number.isNaN(nextPort) ? 0 : nextPort) + }} + error={isPortInvalid} + helperText={isPortInvalid ? '端口必须在 1 到 65535 之间' : '建议保持默认 5031'} + inputProps={{ min: 1, max: 65535, inputMode: 'numeric' }} + InputProps={{ + endAdornment: ( + + + setHttpApiPort((p) => Math.min(65535, (p && p > 0 ? p : 5031) + 1))} + disabled={httpApiPort >= 65535} + sx={{ ...stepperButtonSx, p: 0, minHeight: 0 }} + > + + + setHttpApiPort((p) => Math.max(1, (p && p > 0 ? p : 5031) - 1))} + disabled={httpApiPort <= 1} + sx={{ ...stepperButtonSx, p: 0, minHeight: 0 }} + > + + + + + ), + }} + /> -
- - - -
-
+ setHttpApiToken(event.target.value)} + placeholder="留空表示不启用令牌鉴权" + helperText="设置后,请使用 Authorization: Bearer 调用受保护接口。" + InputProps={{ + endAdornment: ( + + + + + setShowHttpApiToken((value) => !value)} + sx={inlineIconButtonSx} + > + {showHttpApiToken ? : } + + -
+ + setHttpApiToken(createRandomToken())} + sx={inlineIconButtonSx} + > + + + -
-

接口状态与信息

+ {httpApiToken && ( + + copyText(httpApiToken, '访问密钥已复制')} + sx={inlineIconButtonSx} + > + + + + )} + + + + ), + }} + /> + - {status ? ( - <> -
-
-
运行状态
-
{status.running ? '运行中' : '未运行'}
-
-
-
监听地址
-
{status.host}:{status.port}
-
-
-
运行时长
-
{uptimeText}
-
-
-
鉴权状态
-
{status.tokenConfigured ? '已启用' : '未启用'}
-
-
+ + -
- -
- -
- -
-
-
+ -
- -
- -
- {status.tokenConfigured && ( - - )} -
-
-
+ +
+ + + - {status.lastError && ( -
- -

最近错误:{status.lastError}

-
+ + + + {status ? ( + + + + + + copyText(baseUrl, '基础地址已复制')} + sx={inlineIconButtonSx} + > + + + + + + ), + }} + /> + + + + + copyText(httpApiToken, '访问密钥已复制')} + sx={inlineIconButtonSx} + > + + + + + + ) + : undefined, + }} + /> + + + + } + /> + } + /> + {status.host}:{status.port}} + /> + + } + /> + + + {status.lastError && ( + + 最近错误:{status.lastError} + + )} + + ) : ( + + 尚未读取到接口状态,请点击“刷新状态”。 + )} - - ) : ( -

尚未读取到接口状态,请点击“刷新状态”。

+
+
+ + {status && ( + + + + + {status.endpoints.map((endpoint) => { + const endpointUrl = getEndpointUrl(baseUrl, endpoint.path) + + return ( + + + + + + + {endpoint.desc} + + + {endpoint.path} + + + + {endpointUrl} + + + + + + + ) + })} + + + )} -
-
-
-
+ + + + + setMessage(null)} + anchorOrigin={{ vertical: 'top', horizontal: 'center' }} + > + setMessage(null)} + severity={message?.success ? 'success' : 'error'} + variant="filled" + sx={{ + width: '100%', + borderRadius: '999px', + color: '#fff', + background: message?.success + ? 'var(--primary-gradient)' + : 'var(--danger)', + boxShadow: message?.success + ? '0 12px 32px var(--primary-light)' + : '0 12px 32px rgba(220, 53, 69, 0.2)', + }} + > + {message?.text} + + + ) } diff --git a/src/pages/SettingsPage.scss b/src/pages/SettingsPage.scss index 099c27d..a58dfa4 100644 --- a/src/pages/SettingsPage.scss +++ b/src/pages/SettingsPage.scss @@ -3,8 +3,8 @@ .settings-page { display: flex; flex-direction: column; - height: calc(100% + 48px); - margin: -24px; + height: calc(100% + 24px); + margin: -24px 0 0; position: relative; overflow: hidden; @@ -3312,3 +3312,4 @@ to { inset 0 -2px 10px rgba(0, 0, 0, 0.15); } } +