diff --git a/app/package-lock.json b/app/package-lock.json
index 19d4988..6c8cf54 100644
--- a/app/package-lock.json
+++ b/app/package-lock.json
@@ -8,9 +8,7 @@
"name": "app",
"version": "0.1.0",
"dependencies": {
- "@emotion/react": "^11.11.0",
- "@emotion/styled": "^11.11.0",
- "@mui/base": "^5.0.0-beta.40",
+ "@microlink/react-json-view": "^1.26.1",
"@mui/icons-material": "^5.15.14",
"@mui/material": "^5.15.14",
"@testing-library/jest-dom": "^5.17.0",
@@ -37,6 +35,7 @@
"eslint": "^8.57.1",
"eslint-config-prettier": "^10.0.2",
"prettier": "3.5.3",
+ "source-map-explorer": "^2.5.3",
"typescript-eslint": "^8.26.0"
}
},
@@ -2310,6 +2309,8 @@
"version": "11.11.0",
"resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz",
"integrity": "sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==",
+ "optional": true,
+ "peer": true,
"dependencies": {
"@babel/helper-module-imports": "^7.16.7",
"@babel/runtime": "^7.18.3",
@@ -2327,12 +2328,16 @@
"node_modules/@emotion/babel-plugin/node_modules/convert-source-map": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
- "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A=="
+ "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==",
+ "optional": true,
+ "peer": true
},
"node_modules/@emotion/babel-plugin/node_modules/escape-string-regexp": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "optional": true,
+ "peer": true,
"engines": {
"node": ">=10"
},
@@ -2344,6 +2349,8 @@
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
"integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
+ "optional": true,
+ "peer": true,
"engines": {
"node": ">=0.10.0"
}
@@ -2363,12 +2370,16 @@
"node_modules/@emotion/hash": {
"version": "0.9.1",
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz",
- "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ=="
+ "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==",
+ "optional": true,
+ "peer": true
},
"node_modules/@emotion/is-prop-valid": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz",
"integrity": "sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==",
+ "optional": true,
+ "peer": true,
"dependencies": {
"@emotion/memoize": "^0.8.1"
}
@@ -2382,6 +2393,8 @@
"version": "11.11.4",
"resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.4.tgz",
"integrity": "sha512-t8AjMlF0gHpvvxk5mAtCqR4vmxiGHCeJBaQO6gncUSdklELOgtwjerNY2yuJNfwnc6vi16U/+uMF+afIawJ9iw==",
+ "optional": true,
+ "peer": true,
"dependencies": {
"@babel/runtime": "^7.18.3",
"@emotion/babel-plugin": "^11.11.0",
@@ -2405,6 +2418,8 @@
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.3.tgz",
"integrity": "sha512-iD4D6QVZFDhcbH0RAG1uVu1CwVLMWUkCvAqqlewO/rxf8+87yIBAlt4+AxMiiKPLs5hFc0owNk/sLLAOROw3cA==",
+ "optional": true,
+ "peer": true,
"dependencies": {
"@emotion/hash": "^0.9.1",
"@emotion/memoize": "^0.8.1",
@@ -2422,6 +2437,8 @@
"version": "11.11.0",
"resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.11.0.tgz",
"integrity": "sha512-hM5Nnvu9P3midq5aaXj4I+lnSfNi7Pmd4EWk1fOZ3pxookaQTNew6bp4JaCBYM4HVFZF9g7UjJmsUmC2JlxOng==",
+ "optional": true,
+ "peer": true,
"dependencies": {
"@babel/runtime": "^7.18.3",
"@emotion/babel-plugin": "^11.11.0",
@@ -2443,12 +2460,16 @@
"node_modules/@emotion/unitless": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz",
- "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ=="
+ "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==",
+ "optional": true,
+ "peer": true
},
"node_modules/@emotion/use-insertion-effect-with-fallbacks": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz",
"integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==",
+ "optional": true,
+ "peer": true,
"peerDependencies": {
"react": ">=16.8.0"
}
@@ -3432,6 +3453,23 @@
"resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz",
"integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A=="
},
+ "node_modules/@microlink/react-json-view": {
+ "version": "1.26.1",
+ "resolved": "https://registry.npmjs.org/@microlink/react-json-view/-/react-json-view-1.26.1.tgz",
+ "integrity": "sha512-2H5QCYdZlJi+oN4YBiUYPPFTNh/KLCN9i9yz8NwmSkRqXSRXYtEVIRffc9L34jdopKGK/tK21SeuzXVJHQLkfQ==",
+ "dependencies": {
+ "react-base16-styling": "~0.9.0",
+ "react-lifecycles-compat": "~3.0.4",
+ "react-textarea-autosize": "~8.5.7"
+ },
+ "engines": {
+ "node": ">=17"
+ },
+ "peerDependencies": {
+ "react": ">= 15",
+ "react-dom": ">= 15"
+ }
+ },
"node_modules/@mui/base": {
"version": "5.0.0-beta.40",
"resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.40.tgz",
@@ -4500,6 +4538,11 @@
"@babel/types": "^7.20.7"
}
},
+ "node_modules/@types/base16": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/@types/base16/-/base16-1.0.5.tgz",
+ "integrity": "sha512-OzOWrTluG9cwqidEzC/Q6FAmIPcnZfm8BFRlIx0+UIUqnuAmi5OS88O0RpT3Yz6qdmqObvUhasrbNsCofE4W9A=="
+ },
"node_modules/@types/body-parser": {
"version": "1.19.5",
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz",
@@ -4669,6 +4712,11 @@
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
"integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ=="
},
+ "node_modules/@types/lodash": {
+ "version": "4.17.16",
+ "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.16.tgz",
+ "integrity": "sha512-HX7Em5NYQAXKW+1T+FiuG27NGwzJfCX3s1GjOa7ujxZa52kjJLOr4FUxT+giF6Tgxv1e+/czV/iTtBw27WTU9g=="
+ },
"node_modules/@types/mdast": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz",
@@ -6070,6 +6118,11 @@
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
},
+ "node_modules/base16": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/base16/-/base16-1.0.0.tgz",
+ "integrity": "sha512-pNdYkNPiJUnEhnfXV56+sQy8+AaPcG3POZAUnwr4EeqCUZFz4u2PePbo3e5Gj4ziYPCWGUZT9RHisvJKnwFuBQ=="
+ },
"node_modules/batch": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
@@ -6247,6 +6300,18 @@
"node-int64": "^0.4.0"
}
},
+ "node_modules/btoa": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/btoa/-/btoa-1.2.1.tgz",
+ "integrity": "sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==",
+ "dev": true,
+ "bin": {
+ "btoa": "bin/btoa.js"
+ },
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
"node_modules/buffer-from": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
@@ -6559,6 +6624,15 @@
"resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz",
"integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q=="
},
+ "node_modules/color": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz",
+ "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==",
+ "dependencies": {
+ "color-convert": "^1.9.3",
+ "color-string": "^1.6.0"
+ }
+ },
"node_modules/color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
@@ -6572,6 +6646,15 @@
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
},
+ "node_modules/color-string": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
+ "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
+ "dependencies": {
+ "color-name": "^1.0.0",
+ "simple-swizzle": "^0.2.2"
+ }
+ },
"node_modules/colord": {
"version": "2.9.3",
"resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz",
@@ -8997,7 +9080,9 @@
"node_modules/find-root": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz",
- "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng=="
+ "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==",
+ "optional": true,
+ "peer": true
},
"node_modules/find-up": {
"version": "5.0.0",
@@ -9705,6 +9790,8 @@
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
"integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
+ "optional": true,
+ "peer": true,
"dependencies": {
"react-is": "^16.7.0"
}
@@ -9712,7 +9799,9 @@
"node_modules/hoist-non-react-statics/node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
- "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
+ "optional": true,
+ "peer": true
},
"node_modules/hoopy": {
"version": "0.1.4",
@@ -13027,6 +13116,11 @@
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
+ "node_modules/lodash.curry": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.curry/-/lodash.curry-4.1.1.tgz",
+ "integrity": "sha512-/u14pXGviLaweY5JI0IUzgzF2J6Ne8INyzAZjImcryjgkZ+ebruBxy2/JaOOkTqScddcYtakjhSaeemV8lR0tA=="
+ },
"node_modules/lodash.debounce": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
@@ -16155,6 +16249,20 @@
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
"integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
},
+ "node_modules/react-base16-styling": {
+ "version": "0.9.1",
+ "resolved": "https://registry.npmjs.org/react-base16-styling/-/react-base16-styling-0.9.1.tgz",
+ "integrity": "sha512-1s0CY1zRBOQ5M3T61wetEpvQmsYSNtWEcdYzyZNxKa8t7oDvaOn9d21xrGezGAHFWLM7SHcktPuPTrvoqxSfKw==",
+ "dependencies": {
+ "@babel/runtime": "^7.16.7",
+ "@types/base16": "^1.0.2",
+ "@types/lodash": "^4.14.178",
+ "base16": "^1.0.0",
+ "color": "^3.2.1",
+ "csstype": "^3.0.10",
+ "lodash.curry": "^4.1.1"
+ }
+ },
"node_modules/react-dev-utils": {
"version": "12.0.1",
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz",
@@ -16294,6 +16402,11 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
},
+ "node_modules/react-lifecycles-compat": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
+ "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
+ },
"node_modules/react-markdown": {
"version": "10.0.1",
"resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-10.0.1.tgz",
@@ -16430,6 +16543,22 @@
}
}
},
+ "node_modules/react-textarea-autosize": {
+ "version": "8.5.9",
+ "resolved": "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-8.5.9.tgz",
+ "integrity": "sha512-U1DGlIQN5AwgjTyOEnI1oCcMuEr1pv1qOtklB2l4nyMGbHzWrI0eFsYK0zos2YWqAolJyG0IWJaqWmWj5ETh0A==",
+ "dependencies": {
+ "@babel/runtime": "^7.20.13",
+ "use-composed-ref": "^1.3.0",
+ "use-latest": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
"node_modules/react-transition-group": {
"version": "4.4.5",
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
@@ -17320,6 +17449,19 @@
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
},
+ "node_modules/simple-swizzle": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
+ "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==",
+ "dependencies": {
+ "is-arrayish": "^0.3.1"
+ }
+ },
+ "node_modules/simple-swizzle/node_modules/is-arrayish": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
+ "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="
+ },
"node_modules/sisteransi": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
@@ -17356,6 +17498,125 @@
"node": ">= 8"
}
},
+ "node_modules/source-map-explorer": {
+ "version": "2.5.3",
+ "resolved": "https://registry.npmjs.org/source-map-explorer/-/source-map-explorer-2.5.3.tgz",
+ "integrity": "sha512-qfUGs7UHsOBE5p/lGfQdaAj/5U/GWYBw2imEpD6UQNkqElYonkow8t+HBL1qqIl3CuGZx7n8/CQo4x1HwSHhsg==",
+ "dev": true,
+ "dependencies": {
+ "btoa": "^1.2.1",
+ "chalk": "^4.1.0",
+ "convert-source-map": "^1.7.0",
+ "ejs": "^3.1.5",
+ "escape-html": "^1.0.3",
+ "glob": "^7.1.6",
+ "gzip-size": "^6.0.0",
+ "lodash": "^4.17.20",
+ "open": "^7.3.1",
+ "source-map": "^0.7.4",
+ "temp": "^0.9.4",
+ "yargs": "^16.2.0"
+ },
+ "bin": {
+ "sme": "bin/cli.js",
+ "source-map-explorer": "bin/cli.js"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/source-map-explorer/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/source-map-explorer/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/source-map-explorer/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/source-map-explorer/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/source-map-explorer/node_modules/convert-source-map": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
+ "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==",
+ "dev": true
+ },
+ "node_modules/source-map-explorer/node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/source-map-explorer/node_modules/open": {
+ "version": "7.4.2",
+ "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz",
+ "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==",
+ "dev": true,
+ "dependencies": {
+ "is-docker": "^2.0.0",
+ "is-wsl": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/source-map-explorer/node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/source-map-js": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz",
@@ -18126,6 +18387,19 @@
"node": ">=6"
}
},
+ "node_modules/temp": {
+ "version": "0.9.4",
+ "resolved": "https://registry.npmjs.org/temp/-/temp-0.9.4.tgz",
+ "integrity": "sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==",
+ "dev": true,
+ "dependencies": {
+ "mkdirp": "^0.5.1",
+ "rimraf": "~2.6.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
"node_modules/temp-dir": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz",
@@ -18134,6 +18408,19 @@
"node": ">=8"
}
},
+ "node_modules/temp/node_modules/rimraf": {
+ "version": "2.6.3",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
+ "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
+ "deprecated": "Rimraf versions prior to v4 are no longer supported",
+ "dev": true,
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ }
+ },
"node_modules/tempy": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/tempy/-/tempy-0.6.0.tgz",
@@ -19043,6 +19330,48 @@
"requires-port": "^1.0.0"
}
},
+ "node_modules/use-composed-ref": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/use-composed-ref/-/use-composed-ref-1.4.0.tgz",
+ "integrity": "sha512-djviaxuOOh7wkj0paeO1Q/4wMZ8Zrnag5H6yBvzN7AKKe8beOaED9SF5/ByLqsku8NP4zQqsvM2u3ew/tJK8/w==",
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/use-isomorphic-layout-effect": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.2.0.tgz",
+ "integrity": "sha512-q6ayo8DWoPZT0VdG4u3D3uxcgONP3Mevx2i2b0434cwWBoL+aelL1DzkXI6w3PhTZzUeR2kaVlZn70iCiseP6w==",
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/use-latest": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/use-latest/-/use-latest-1.3.0.tgz",
+ "integrity": "sha512-mhg3xdm9NaM8q+gLT8KryJPnRFOz1/5XPBhmDEVZK1webPzDjrPk7f/mbpeLqTgB9msytYWANxgALOCJKnLvcQ==",
+ "dependencies": {
+ "use-isomorphic-layout-effect": "^1.1.1"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
"node_modules/usehooks-ts": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/usehooks-ts/-/usehooks-ts-3.0.2.tgz",
diff --git a/app/package.json b/app/package.json
index 5243aff..d16b347 100644
--- a/app/package.json
+++ b/app/package.json
@@ -3,9 +3,7 @@
"version": "0.1.0",
"private": true,
"dependencies": {
- "@emotion/react": "^11.11.0",
- "@emotion/styled": "^11.11.0",
- "@mui/base": "^5.0.0-beta.40",
+ "@microlink/react-json-view": "^1.26.1",
"@mui/icons-material": "^5.15.14",
"@mui/material": "^5.15.14",
"@testing-library/jest-dom": "^5.17.0",
@@ -32,6 +30,7 @@
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
+ "analyze": "source-map-explorer 'build/static/js/*.js'",
"format": "npx prettier . --write",
"format-check": "npx prettier ."
},
@@ -58,6 +57,7 @@
"eslint": "^8.57.1",
"eslint-config-prettier": "^10.0.2",
"prettier": "3.5.3",
+ "source-map-explorer": "^2.5.3",
"typescript-eslint": "^8.26.0"
},
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
diff --git a/app/public/index.html b/app/public/index.html
index aa069f2..e65acb3 100644
--- a/app/public/index.html
+++ b/app/public/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/app/src/App.css b/app/src/App.css
index ba2ab37..3704068 100644
--- a/app/src/App.css
+++ b/app/src/App.css
@@ -11,7 +11,7 @@
}
.app-toolbar {
- background-color: #181818 !important;
+ background-color: #181818;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
}
@@ -46,28 +46,28 @@ body {
/* Button overrides */
.MuiButton-containedPrimary {
- background-color: #0d47a1 !important;
- color: #ffffff !important;
+ background-color: #0d47a1;
+ color: #ffffff;
}
.MuiButton-containedPrimary:hover {
- background-color: #1565c0 !important;
+ background-color: #1565c0;
}
.MuiButton-containedSecondary {
- background-color: #00f58c !important;
- color: #111111 !important;
+ background-color: #00f58c;
+ color: #111111;
}
.MuiButton-containedSecondary:hover {
- background-color: #2dffa0 !important;
+ background-color: #2dffa0;
}
.MuiButton-containedWarning {
- background-color: #bf360c !important;
- color: #ffffff !important;
+ background-color: #bf360c;
+ color: #ffffff;
}
.MuiButton-containedWarning:hover {
- background-color: #e64a19 !important;
+ background-color: #e64a19;
}
diff --git a/app/src/App.tsx b/app/src/App.tsx
index 2ae08a6..e0d3179 100644
--- a/app/src/App.tsx
+++ b/app/src/App.tsx
@@ -1,13 +1,11 @@
import React, { ReactNode } from "react";
-import AppBar from "@mui/material/AppBar/AppBar";
-import Toolbar from "@mui/material/Toolbar/Toolbar";
+import { ThemeProvider } from "@mui/material/styles";
+import { AppBar, Toolbar, Box } from "@mui/material";
import { useNavigate } from "react-router-dom";
import UserButton from "./features/toolbar/components/UserButton";
import { useIsMobile } from "./features/toolbar/hooks/useIsMobile";
import SearchBar from "./features/toolbar/components/SearchBar";
-import "./App.css";
-
-export const FUEL_GREEN = "#00f58c";
+import theme from "./theme/theme";
interface AppProps {
children?: ReactNode;
@@ -18,20 +16,61 @@ function App({ children }: AppProps) {
const isMobile = useIsMobile();
return (
-
-
-
- navigate("/")}>
- forc.pub
-
-
- {!isMobile && }
-
-
- {isMobile && }
-
-
{children}
-
+
+
+
+
+ navigate("/")}
+ sx={{
+ flexGrow: 1,
+ display: "block",
+ color: theme.palette.primary.main,
+ fontSize: "24px",
+ fontFamily: "monospace",
+ cursor: "pointer",
+ fontWeight: "bold",
+ transition: "color 0.2s ease-in-out",
+ "&:hover": {
+ color: theme.palette.primary.light,
+ },
+ }}
+ >
+ forc.pub
+
+ {!isMobile && }
+
+
+ {isMobile && }
+
+
+ {children}
+
+
+
);
}
diff --git a/app/src/features/dahboard/components/PackageDashboard.css b/app/src/features/dahboard/components/PackageDashboard.css
deleted file mode 100644
index f24dcd1..0000000
--- a/app/src/features/dahboard/components/PackageDashboard.css
+++ /dev/null
@@ -1,58 +0,0 @@
-/* Dark mode styling for Package Dashboard */
-.dashboard-container {
- margin-top: 24px;
-}
-
-.section-title {
- border-bottom: 2px solid #90caf9 !important;
- padding-bottom: 8px !important;
- color: #ffffff !important;
- font-weight: 500 !important;
-}
-
-.package-card {
- margin-bottom: 16px;
- border-radius: 8px;
- box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3) !important;
- cursor: pointer;
- transition:
- transform 0.2s,
- background-color 0.2s;
- background-color: #2a2a2a !important;
- border: 1px solid #333 !important;
-}
-
-.package-card-hover {
- background-color: #383838 !important;
- transform: translateY(-2px);
- box-shadow: 0 6px 12px rgba(0, 0, 0, 0.4) !important;
-}
-
-.card-content {
- display: flex;
- align-items: center;
- justify-content: space-between;
- background-color: transparent !important;
-}
-
-.package-name {
- color: #90caf9 !important;
- margin-bottom: 8px !important;
-}
-
-.package-timestamp {
- color: #b0b0b0 !important;
- font-size: 0.85rem !important;
-}
-
-.package-description {
- color: #e0e0e0 !important;
- margin-top: 8px !important;
-}
-
-.arrow-icon {
- color: #90caf9 !important;
- margin-left: 16px;
- align-self: center;
- font-size: 1.2rem !important;
-}
diff --git a/app/src/features/dashboard/components/PackageDashboard.css b/app/src/features/dashboard/components/PackageDashboard.css
new file mode 100644
index 0000000..03a9333
--- /dev/null
+++ b/app/src/features/dashboard/components/PackageDashboard.css
@@ -0,0 +1,58 @@
+/* Dark mode styling for Package Dashboard */
+.dashboard-container {
+ margin-top: 24px;
+}
+
+.section-title {
+ border-bottom: 2px solid #90caf9;
+ padding-bottom: 8px;
+ color: #ffffff;
+ font-weight: 500;
+}
+
+.package-card {
+ margin-bottom: 16px;
+ border-radius: 8px;
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
+ cursor: pointer;
+ transition:
+ transform 0.2s,
+ background-color 0.2s;
+ background-color: #2a2a2a;
+ border: 1px solid #333;
+}
+
+.package-card-hover {
+ background-color: #383838;
+ transform: translateY(-2px);
+ box-shadow: 0 6px 12px rgba(0, 0, 0, 0.4);
+}
+
+.card-content {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ background-color: transparent;
+}
+
+.package-name {
+ color: #90caf9;
+ margin-bottom: 8px;
+}
+
+.package-timestamp {
+ color: #b0b0b0;
+ font-size: 0.85rem;
+}
+
+.package-description {
+ color: #e0e0e0;
+ margin-top: 8px;
+}
+
+.arrow-icon {
+ color: #90caf9;
+ margin-left: 16px;
+ align-self: center;
+ font-size: 1.2rem;
+}
diff --git a/app/src/features/dahboard/components/PackageDashboard.tsx b/app/src/features/dashboard/components/PackageDashboard.tsx
similarity index 100%
rename from app/src/features/dahboard/components/PackageDashboard.tsx
rename to app/src/features/dashboard/components/PackageDashboard.tsx
diff --git a/app/src/features/dahboard/hooks/useFetchRecentPackages.ts b/app/src/features/dashboard/hooks/useFetchRecentPackages.ts
similarity index 100%
rename from app/src/features/dahboard/hooks/useFetchRecentPackages.ts
rename to app/src/features/dashboard/hooks/useFetchRecentPackages.ts
diff --git a/app/src/features/detail/components/AbiContent.tsx b/app/src/features/detail/components/AbiContent.tsx
new file mode 100644
index 0000000..ec4d33f
--- /dev/null
+++ b/app/src/features/detail/components/AbiContent.tsx
@@ -0,0 +1,109 @@
+import React, { useState } from "react";
+import { useAbiContent } from "../hooks/useAbiContent";
+import {
+ CircularProgress,
+ Alert,
+ Box,
+ IconButton,
+ Tooltip,
+ Snackbar,
+} from "@mui/material";
+import ReactJsonView from "@microlink/react-json-view";
+import ContentCopyIcon from "@mui/icons-material/ContentCopy";
+import CheckIcon from "@mui/icons-material/Check";
+
+interface AbiContentProps {
+ abiUrl: string;
+}
+
+export const AbiContent: React.FC = ({ abiUrl }) => {
+ const { abiContent, loading, error } = useAbiContent(abiUrl);
+ const [copied, setCopied] = useState(false);
+
+ const handleCopy = async () => {
+ try {
+ await navigator.clipboard.writeText(JSON.stringify(abiContent, null, 2));
+ setCopied(true);
+ setTimeout(() => setCopied(false), 2000);
+ } catch (err) {
+ console.error("Failed to copy:", err);
+ }
+ };
+
+ if (loading) {
+ return (
+
+
+
+ );
+ }
+
+ if (error) {
+ return (
+
+ Failed to load ABI content: {error.message}
+
+ );
+ }
+
+ if (!abiContent) {
+ return null;
+ }
+
+ return (
+
+
+
+
+
+ {copied ? : }
+
+
+
+
+
+
+
+
+
+ );
+};
diff --git a/app/src/features/detail/components/PackageDetail.css b/app/src/features/detail/components/PackageDetail.css
index b61ce12..03d03c4 100644
--- a/app/src/features/detail/components/PackageDetail.css
+++ b/app/src/features/detail/components/PackageDetail.css
@@ -8,27 +8,27 @@
/* Ensure all MUI components in package detail follow dark theme */
.package-detail-container .MuiPaper-root {
- background-color: #2a2a2a !important;
- color: #e0e0e0 !important;
+ background-color: #2a2a2a;
+ color: #e0e0e0;
}
.package-detail-container .MuiCard-root {
- background-color: #2a2a2a !important;
- color: #e0e0e0 !important;
- border: 1px solid #333 !important;
+ background-color: #2a2a2a;
+ color: #e0e0e0;
+ border: 1px solid #333;
}
.package-detail-container .MuiButton-contained {
- background-color: #0d47a1 !important;
- color: #ffffff !important;
+ background-color: #0d47a1;
+ color: #ffffff;
}
.package-detail-container .MuiButton-contained:hover {
- background-color: #1565c0 !important;
+ background-color: #1565c0;
}
.package-detail-container .MuiDivider-root {
- background-color: #444 !important;
+ background-color: #444;
}
/* Make sure all text in the cards is light */
@@ -37,6 +37,7 @@
margin-top: 0;
padding-top: 24px;
max-width: 1100px;
+ overflow: auto;
}
.package-header {
@@ -66,7 +67,7 @@
}
.package-tab {
- color: #e0e0e0 !important;
+ color: #e0e0e0;
opacity: 0.8;
text-transform: none;
min-width: 120px;
@@ -77,18 +78,18 @@
.package-tab:hover {
opacity: 1;
- color: #ffffff !important;
+ color: #ffffff;
}
/* Style for the active tab */
.package-tabs .Mui-selected {
- color: #ffffff !important;
+ color: #ffffff;
opacity: 1;
}
/* Style for the tab indicator (the line under the active tab) */
.package-tabs .MuiTabs-indicator {
- background-color: #2196f3 !important;
+ background-color: #2196f3;
height: 3px;
}
@@ -96,36 +97,36 @@
margin-bottom: 16px;
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
- background-color: #2a2a2a !important;
- border: 1px solid #333 !important;
- color: #e0e0e0 !important;
+ background-color: #2a2a2a;
+ border: 1px solid #333;
+ color: #e0e0e0;
}
/* Override MUI styles for dark mode */
.card-dark .MuiPaper-root {
- background-color: #2a2a2a !important;
- color: #e0e0e0 !important;
+ background-color: #2a2a2a;
+ color: #e0e0e0;
}
.card-dark .MuiCardContent-root {
- background-color: #2a2a2a !important;
+ background-color: #2a2a2a;
}
.card-dark .MuiTypography-root {
- color: #e0e0e0 !important;
+ color: #e0e0e0;
}
.card-dark .MuiDivider-root {
- background-color: #444 !important;
+ background-color: #444;
}
.card-dark .MuiListItemText-secondary {
- color: #b0b0b0 !important;
+ color: #b0b0b0;
}
.card-dark .MuiChip-root {
- background-color: #3a3a3a !important;
- color: #e0e0e0 !important;
+ background-color: #3a3a3a;
+ color: #e0e0e0;
}
.card-content {
@@ -134,6 +135,7 @@
word-wrap: break-word;
display: flex;
flex-direction: column;
+ max-height: calc(100vh - 300px);
}
.card-title {
@@ -223,27 +225,27 @@
}
.alert-dark {
- background-color: rgba(30, 70, 100, 0.2) !important;
- color: #90caf9 !important;
- border-color: #2a5d8a !important;
+ background-color: rgba(30, 70, 100, 0.2);
+ color: #90caf9;
+ border-color: #2a5d8a;
}
.alert-dark .MuiAlert-icon {
- color: #90caf9 !important;
+ color: #90caf9;
}
.package-detail-container .MuiAlert-root {
- background-color: rgba(30, 70, 100, 0.2) !important;
- color: #90caf9 !important;
- border-color: #2a5d8a !important;
+ background-color: rgba(30, 70, 100, 0.2);
+ color: #90caf9;
+ border-color: #2a5d8a;
}
.package-detail-container .MuiAlert-root .MuiAlert-icon {
- color: #90caf9 !important;
+ color: #90caf9;
}
.package-detail-container .MuiAlert-root .MuiAlert-message {
- color: #90caf9 !important;
+ color: #90caf9;
}
.download-section {
@@ -270,9 +272,7 @@
}
.abi-download {
- margin-top: 16px;
- padding-top: 16px;
- border-top: 1px solid #444;
+ margin: 8px 0 0px;
}
.link-light {
@@ -320,7 +320,7 @@
}
.section-divider {
- margin: 16px 0 !important;
+ margin: 16px 0;
}
.sidebar-link-item {
diff --git a/app/src/features/detail/components/PackageDetail.tsx b/app/src/features/detail/components/PackageDetail.tsx
index 6138553..cf9183b 100644
--- a/app/src/features/detail/components/PackageDetail.tsx
+++ b/app/src/features/detail/components/PackageDetail.tsx
@@ -19,14 +19,31 @@ import usePackageDetail from "../hooks/usePackageDetail";
import ReactMarkdown from "react-markdown";
import "./PackageDetail.css";
import PackageSidebar from "./PackageSidebar";
+import { AbiContent } from "./AbiContent";
+
+type TabNames =
+ | "Readme"
+ | "Versions"
+ | "Dependencies"
+ | "Dependents"
+ | "Code"
+ | "ABI";
+const TABS: TabNames[] = [
+ "Readme",
+ "Versions",
+ "Dependencies",
+ "Dependents",
+ "Code",
+ "ABI",
+];
const PackageDetail: React.FC = () => {
const { name, version } = useParams<{ name: string; version?: string }>();
- const [activeTab, setActiveTab] = useState(0);
+ const [activeTab, setActiveTab] = useState(TABS[0]);
const { data, loading, error } = usePackageDetail(name!, version);
const handleTabChange = (event: React.SyntheticEvent, newValue: number) => {
- setActiveTab(newValue);
+ setActiveTab(TABS[newValue]);
};
if (loading) {
@@ -89,7 +106,7 @@ const PackageDetail: React.FC = () => {
)}
{
+ {data.abiIpfsUrl && }
{/* Main Content - Left Side (changes with tabs) */}
{/* Readme Tab */}
- {activeTab === 0 && renderReadmeTab()}
+ {activeTab === TABS[0] && renderReadmeTab()}
{/* Versions Tab */}
- {activeTab === 1 && (
+ {activeTab === TABS[1] && (
@@ -131,7 +149,7 @@ const PackageDetail: React.FC = () => {
)}
{/* Dependencies Tab */}
- {activeTab === 2 && (
+ {activeTab === TABS[2] && (
@@ -151,7 +169,7 @@ const PackageDetail: React.FC = () => {
)}
{/* Dependents Tab */}
- {activeTab === 3 && (
+ {activeTab === TABS[3] && (
@@ -171,17 +189,13 @@ const PackageDetail: React.FC = () => {
)}
{/* Code Tab */}
- {activeTab === 4 && (
+ {activeTab === TABS[4] && (
Source Code
-
- Browse the source code for {data.name}@{data.version}.
-
-
{
- Full source code including dependencies
+ Package source code
IPFS: {data.sourceCodeIpfsUrl.split("/").pop()}
+
- {data.abiIpfsUrl && (
+
+ Source code browser feature is coming soon.
+
+
+
+
+ )}
+ {/* ABI Tab */}
+ {activeTab === TABS[5] && (
+
+
+
+ Application Binary Interface (ABI)
+
+
+ {data.abiIpfsUrl && (
+ <>
+
{
rel="noopener noreferrer"
className="link-light"
>
- Download ABI (.json)
+ }
+ >
+ Download ABI (.json)
+
- )}
-
-
-
- Source code browser feature is coming soon.
-
-
+
+
+ >
+ )}
)}
diff --git a/app/src/features/detail/components/PackageSidebar.css b/app/src/features/detail/components/PackageSidebar.css
index 2a49aca..069770b 100644
--- a/app/src/features/detail/components/PackageSidebar.css
+++ b/app/src/features/detail/components/PackageSidebar.css
@@ -1,11 +1,11 @@
/* Dark mode styles for Package Sidebar */
.sidebar-card {
margin-top: 0;
- background-color: #2a2a2a !important;
- color: #e0e0e0 !important;
- border: none !important;
- border-radius: 12px !important;
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2) !important;
+ background-color: #2a2a2a;
+ color: #e0e0e0;
+ border: none;
+ border-radius: 12px;
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}
.sidebar-card .MuiCardContent-root {
@@ -29,38 +29,38 @@
.sidebar-section-heading {
text-transform: uppercase;
letter-spacing: 0.5px;
- font-size: 0.9rem !important;
- color: #aaa !important;
- font-weight: 500 !important;
- margin-top: 10px !important;
- margin-bottom: 8px !important;
- border: none !important;
- padding: 0 !important;
- background: none !important;
- position: relative !important;
- display: block !important;
+ font-size: 0.9rem;
+ color: #aaa;
+ font-weight: 500;
+ margin-top: 10px;
+ margin-bottom: 8px;
+ border: none;
+ padding: 0;
+ background: none;
+ position: relative;
+ display: block;
}
/* Explicitly ensure no decorations or pseudo-elements */
.sidebar-section-heading:after,
.sidebar-section-heading:before {
- content: none !important;
- display: none !important;
- border: none !important;
- height: 0 !important;
- width: 0 !important;
- position: static !important;
+ content: none;
+ display: none;
+ border: none;
+ height: 0;
+ width: 0;
+ position: static;
}
/* Explicitly remove any dividers or borders */
.sidebar-card .MuiDivider-root {
- display: none !important;
+ display: none;
}
.sidebar-link-item {
margin-bottom: 16px;
padding-bottom: 16px;
- border-bottom: none !important;
+ border-bottom: none;
}
.sidebar-list {
@@ -78,17 +78,17 @@
}
.link-light {
- color: #c0c0c0 !important;
- text-decoration: none !important;
+ color: #c0c0c0;
+ text-decoration: none;
word-break: break-word;
opacity: 0.9;
transition: all 0.2s ease;
}
.link-light:hover {
- color: #ffffff !important;
+ color: #ffffff;
opacity: 1;
- text-decoration: underline !important;
+ text-decoration: underline;
}
.link-block {
@@ -99,15 +99,15 @@
/* Override MUI styles for dark mode */
.sidebar-card .MuiTypography-root {
- color: #e0e0e0 !important;
+ color: #e0e0e0;
}
.sidebar-card .MuiAlert-root {
- background-color: rgba(60, 60, 60, 0.2) !important;
- color: #e0e0e0 !important;
- border: none !important;
+ background-color: rgba(60, 60, 60, 0.2);
+ color: #e0e0e0;
+ border: none;
}
.sidebar-card .MuiAlert-icon {
- color: #e0e0e0 !important;
+ color: #e0e0e0;
}
diff --git a/app/src/features/detail/hooks/useAbiContent.ts b/app/src/features/detail/hooks/useAbiContent.ts
new file mode 100644
index 0000000..23d6c5e
--- /dev/null
+++ b/app/src/features/detail/hooks/useAbiContent.ts
@@ -0,0 +1,37 @@
+import { useState, useEffect } from "react";
+
+interface UseAbiContentResult {
+ abiContent: any;
+ loading: boolean;
+ error: Error | null;
+}
+
+export const useAbiContent = (abiUrl: string | null): UseAbiContentResult => {
+ const [abiContent, setAbiContent] = useState(null);
+ const [loading, setLoading] = useState(false);
+ const [error, setError] = useState(null);
+
+ useEffect(() => {
+ const fetchAbi = async () => {
+ if (!abiUrl) return;
+
+ setLoading(true);
+ try {
+ const response = await fetch(abiUrl);
+ if (!response.ok) {
+ throw new Error(`HTTP error! status: ${response.status}`);
+ }
+ const data = await response.json();
+ setAbiContent(data);
+ } catch (e) {
+ setError(e instanceof Error ? e : new Error("Failed to fetch ABI"));
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ fetchAbi();
+ }, [abiUrl]);
+
+ return { abiContent, loading, error };
+};
diff --git a/app/src/features/tokens/components/CopyableToken.css b/app/src/features/tokens/components/CopyableToken.css
index d6458c4..08aa925 100644
--- a/app/src/features/tokens/components/CopyableToken.css
+++ b/app/src/features/tokens/components/CopyableToken.css
@@ -30,12 +30,12 @@
}
.copy-button {
- color: #e0e0e0 !important;
+ color: #e0e0e0;
}
.copy-button:hover {
- color: #ffffff !important;
- background-color: rgba(255, 255, 255, 0.1) !important;
+ color: #ffffff;
+ background-color: rgba(255, 255, 255, 0.1);
}
.copy-button svg {
diff --git a/app/src/features/toolbar/components/SearchBar.css b/app/src/features/toolbar/components/SearchBar.css
index 0763aaa..be676d0 100644
--- a/app/src/features/toolbar/components/SearchBar.css
+++ b/app/src/features/toolbar/components/SearchBar.css
@@ -18,7 +18,6 @@
height: 100%;
background-color: #333333;
color: #e0e0e0;
- border-radius: 4px;
padding: 2px 4px;
}
@@ -27,17 +26,18 @@
.search-input:-moz-placeholder,
.search-input::-moz-placeholder,
.search-input:-ms-input-placeholder {
- color: #c0c0c0 !important;
- opacity: 1 !important;
+ color: #c0c0c0;
+ opacity: 1;
}
/* Target the actual input element within MUI Input */
.search-input input::placeholder {
- color: #c0c0c0 !important;
- opacity: 1 !important;
+ color: #c0c0c0;
+ opacity: 1;
}
.search-icon {
color: #c0c0c0;
margin-left: 10px;
+ margin-right: 10px;
}
diff --git a/app/src/features/toolbar/components/SearchBar.tsx b/app/src/features/toolbar/components/SearchBar.tsx
index 16ca205..78f6324 100644
--- a/app/src/features/toolbar/components/SearchBar.tsx
+++ b/app/src/features/toolbar/components/SearchBar.tsx
@@ -30,7 +30,7 @@ function SearchBar() {
className="search-input"
startAdornment={
-
+
}
placeholder="Search packages and plugins"
diff --git a/app/src/features/toolbar/components/UserButton.css b/app/src/features/toolbar/components/UserButton.css
index eae32bc..44bcf59 100644
--- a/app/src/features/toolbar/components/UserButton.css
+++ b/app/src/features/toolbar/components/UserButton.css
@@ -16,23 +16,23 @@
}
.user-button:hover {
- background-color: rgba(255, 255, 255, 0.1) !important;
+ background-color: rgba(255, 255, 255, 0.1);
}
/* Menu styling */
.menu-paper {
- background-color: #2a2a2a !important;
- color: #e0e0e0 !important;
- border: 1px solid #444 !important;
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3) !important;
+ background-color: #2a2a2a;
+ color: #e0e0e0;
+ border: 1px solid #444;
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
}
.menu-item {
- color: #e0e0e0 !important;
+ color: #e0e0e0;
}
.menu-item:hover {
- background-color: #3a3a3a !important;
+ background-color: #3a3a3a;
}
/* Login button styling */
@@ -40,11 +40,11 @@
transition: all 0.2s ease;
display: flex;
align-items: center;
- color: #e0e0e0 !important;
+ color: #e0e0e0;
}
.login-button:hover {
- background-color: rgba(255, 255, 255, 0.1) !important;
+ background-color: rgba(255, 255, 255, 0.1);
}
.login-icon {
@@ -55,3 +55,8 @@
margin-left: 10px;
color: #e0e0e0;
}
+
+.button-wrapper {
+ text-wrap: nowrap;
+ color: inherit;
+}
diff --git a/app/src/features/toolbar/components/UserButton.tsx b/app/src/features/toolbar/components/UserButton.tsx
index f981864..64a1a27 100644
--- a/app/src/features/toolbar/components/UserButton.tsx
+++ b/app/src/features/toolbar/components/UserButton.tsx
@@ -1,7 +1,6 @@
import React, { useCallback } from "react";
import Lock from "@mui/icons-material/Lock";
import Button from "@mui/material/Button/Button";
-import styled from "@emotion/styled";
import Menu from "@mui/material/Menu/Menu";
import MenuItem from "@mui/material/MenuItem/MenuItem";
import { useNavigate } from "react-router-dom";
@@ -12,11 +11,6 @@ import "./UserButton.css";
export const GITHUB_CLIENT_ID = "Iv1.ebdf596c6c548759";
-const StyledWrapper = styled.div`
- text-wrap: nowrap;
- color: inherit;
-`;
-
function UserButton() {
const navigate = useNavigate();
const [user, logout] = useGithubAuth();
@@ -48,7 +42,7 @@ function UserButton() {
if (user) {
return (
-
+
);
}
return (
-
+
>
-
+
);
}
diff --git a/app/src/pages/ApiTokens.css b/app/src/pages/ApiTokens.css
index 1fa1304..c9f1bf5 100644
--- a/app/src/pages/ApiTokens.css
+++ b/app/src/pages/ApiTokens.css
@@ -37,15 +37,6 @@
margin: 0;
}
-.new-token-button {
- background-color: #0d47a1 !important;
- color: #ffffff !important;
-}
-
-.new-token-button:hover {
- background-color: #1565c0 !important;
-}
-
.tokens-list-container {
display: flex;
flex-direction: column;
@@ -73,35 +64,35 @@
}
.token-name-field {
- min-width: 50% !important;
+ min-width: 50%;
}
/* Override MUI styles for dark mode */
.api-tokens-container .MuiFilledInput-root {
- background-color: #2a2a2a !important;
+ background-color: #2a2a2a;
}
.api-tokens-container .MuiInputBase-input {
- color: #e0e0e0 !important;
+ color: #e0e0e0;
}
.api-tokens-container .MuiInputLabel-root {
- color: #b0b0b0 !important;
+ color: #b0b0b0;
}
.api-tokens-container .MuiFormLabel-root.Mui-focused {
- color: #90caf9 !important;
+ color: #90caf9;
}
.api-tokens-container .MuiFilledInput-underline:after {
- border-bottom-color: #90caf9 !important;
+ border-bottom-color: #90caf9;
}
.generate-button {
- background-color: #0d47a1 !important;
- color: #ffffff !important;
+ background-color: #0d47a1;
+ color: #ffffff;
}
.generate-button:hover {
- background-color: #1565c0 !important;
+ background-color: #1565c0;
}
diff --git a/app/src/pages/ApiTokens.tsx b/app/src/pages/ApiTokens.tsx
index f27c308..d51b497 100644
--- a/app/src/pages/ApiTokens.tsx
+++ b/app/src/pages/ApiTokens.tsx
@@ -24,6 +24,7 @@ function ApiTokens() {
/>