mirror of
https://github.com/OpenHands/OpenHands.git
synced 2026-03-22 13:47:19 +08:00
style(code editor): improved UI / UX for code editor (#826)
* style(): improved code edito ui / ux * fix(): fix build issue and use cn fn * theme variable updated to tailwind neutral gray * fix(): fix conflicts * fix lint errors --------- Co-authored-by: Jim Su <jimsu@protonmail.com>
This commit is contained in:
178
frontend/package-lock.json
generated
178
frontend/package-lock.json
generated
@@ -12,16 +12,10 @@
|
||||
"@nextui-org/react": "^2.2.10",
|
||||
"@react-types/shared": "^3.22.1",
|
||||
"@reduxjs/toolkit": "^2.2.2",
|
||||
"@testing-library/jest-dom": "^6.4.2",
|
||||
"@testing-library/react": "^13.4.0",
|
||||
"@testing-library/user-event": "^13.5.0",
|
||||
"@types/node": "^18.0.0 ",
|
||||
"@types/react": "^18.2.66",
|
||||
"@types/react-dom": "^18.2.22",
|
||||
"@types/react-syntax-highlighter": "^15.5.11",
|
||||
"@typescript-eslint/eslint-plugin": "^7.4.0",
|
||||
"@vitejs/plugin-react": "^4.2.1",
|
||||
"@xterm/xterm": "^5.4.0",
|
||||
"clsx": "^2.1.0",
|
||||
"eslint-config-airbnb-typescript": "^18.0.0",
|
||||
"framer-motion": "^11.0.24",
|
||||
"i18next": "^23.10.1",
|
||||
"i18next-browser-languagedetector": "^7.2.1",
|
||||
@@ -2712,6 +2706,14 @@
|
||||
"tailwind-variants": ">=0.1.13"
|
||||
}
|
||||
},
|
||||
"node_modules/@nextui-org/system-rsc/node_modules/clsx": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz",
|
||||
"integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@nextui-org/table": {
|
||||
"version": "2.0.28",
|
||||
"resolved": "https://registry.npmjs.org/@nextui-org/table/-/table-2.0.28.tgz",
|
||||
@@ -3246,14 +3248,6 @@
|
||||
"react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@react-aria/focus/node_modules/clsx": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.0.tgz",
|
||||
"integrity": "sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@react-aria/form": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@react-aria/form/-/form-3.0.3.tgz",
|
||||
@@ -3643,14 +3637,6 @@
|
||||
"react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@react-aria/utils/node_modules/clsx": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.0.tgz",
|
||||
"integrity": "sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@react-aria/visually-hidden": {
|
||||
"version": "3.8.10",
|
||||
"resolved": "https://registry.npmjs.org/@react-aria/visually-hidden/-/visually-hidden-3.8.10.tgz",
|
||||
@@ -4211,9 +4197,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm-eabi": {
|
||||
"version": "4.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.14.0.tgz",
|
||||
"integrity": "sha512-jwXtxYbRt1V+CdQSy6Z+uZti7JF5irRKF8hlKfEnF/xJpcNGuuiZMBvuoYM+x9sr9iWGnzrlM0+9hvQ1kgkf1w==",
|
||||
"version": "4.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.14.1.tgz",
|
||||
"integrity": "sha512-fH8/o8nSUek8ceQnT7K4EQbSiV7jgkHq81m9lWZFIXjJ7lJzpWXbQFpT/Zh6OZYnpFykvzC3fbEvEAFZu03dPA==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
@@ -4223,9 +4209,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm64": {
|
||||
"version": "4.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.14.0.tgz",
|
||||
"integrity": "sha512-fI9nduZhCccjzlsA/OuAwtFGWocxA4gqXGTLvOyiF8d+8o0fZUeSztixkYjcGq1fGZY3Tkq4yRvHPFxU+jdZ9Q==",
|
||||
"version": "4.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.14.1.tgz",
|
||||
"integrity": "sha512-Y/9OHLjzkunF+KGEoJr3heiD5X9OLa8sbT1lm0NYeKyaM3oMhhQFvPB0bNZYJwlq93j8Z6wSxh9+cyKQaxS7PQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -4235,9 +4221,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-arm64": {
|
||||
"version": "4.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.14.0.tgz",
|
||||
"integrity": "sha512-BcnSPRM76/cD2gQC+rQNGBN6GStBs2pl/FpweW8JYuz5J/IEa0Fr4AtrPv766DB/6b2MZ/AfSIOSGw3nEIP8SA==",
|
||||
"version": "4.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.14.1.tgz",
|
||||
"integrity": "sha512-+kecg3FY84WadgcuSVm6llrABOdQAEbNdnpi5X3UwWiFVhZIZvKgGrF7kmLguvxHNQy+UuRV66cLVl3S+Rkt+Q==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -4247,9 +4233,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-x64": {
|
||||
"version": "4.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.14.0.tgz",
|
||||
"integrity": "sha512-LDyFB9GRolGN7XI6955aFeI3wCdCUszFWumWU0deHA8VpR3nWRrjG6GtGjBrQxQKFevnUTHKCfPR4IvrW3kCgQ==",
|
||||
"version": "4.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.14.1.tgz",
|
||||
"integrity": "sha512-2pYRzEjVqq2TB/UNv47BV/8vQiXkFGVmPFwJb+1E0IFFZbIX8/jo1olxqqMbo6xCXf8kabANhp5bzCij2tFLUA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -4259,9 +4245,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
||||
"version": "4.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.14.0.tgz",
|
||||
"integrity": "sha512-ygrGVhQP47mRh0AAD0zl6QqCbNsf0eTo+vgwkY6LunBcg0f2Jv365GXlDUECIyoXp1kKwL5WW6rsO429DBY/bA==",
|
||||
"version": "4.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.14.1.tgz",
|
||||
"integrity": "sha512-mS6wQ6Do6/wmrF9aTFVpIJ3/IDXhg1EZcQFYHZLHqw6AzMBjTHWnCG35HxSqUNphh0EHqSM6wRTT8HsL1C0x5g==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
@@ -4271,9 +4257,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
||||
"version": "4.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.14.0.tgz",
|
||||
"integrity": "sha512-x+uJ6MAYRlHGe9wi4HQjxpaKHPM3d3JjqqCkeC5gpnnI6OWovLdXTpfa8trjxPLnWKyBsSi5kne+146GAxFt4A==",
|
||||
"version": "4.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.14.1.tgz",
|
||||
"integrity": "sha512-p9rGKYkHdFMzhckOTFubfxgyIO1vw//7IIjBBRVzyZebWlzRLeNhqxuSaZ7kCEKVkm/kuC9fVRW9HkC/zNRG2w==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -4283,9 +4269,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
||||
"version": "4.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.14.0.tgz",
|
||||
"integrity": "sha512-nrRw8ZTQKg6+Lttwqo6a2VxR9tOroa2m91XbdQ2sUUzHoedXlsyvY1fN4xWdqz8PKmf4orDwejxXHjh7YBGUCA==",
|
||||
"version": "4.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.14.1.tgz",
|
||||
"integrity": "sha512-nDY6Yz5xS/Y4M2i9JLQd3Rofh5OR8Bn8qe3Mv/qCVpHFlwtZSBYSPaU4mrGazWkXrdQ98GB//H0BirGR/SKFSw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -4295,9 +4281,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
|
||||
"version": "4.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.14.0.tgz",
|
||||
"integrity": "sha512-xV0d5jDb4aFu84XKr+lcUJ9y3qpIWhttO3Qev97z8DKLXR62LC3cXT/bMZXrjLF9X+P5oSmJTzAhqwUbY96PnA==",
|
||||
"version": "4.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.14.1.tgz",
|
||||
"integrity": "sha512-im7HE4VBL+aDswvcmfx88Mp1soqL9OBsdDBU8NqDEYtkri0qV0THhQsvZtZeNNlLeCUQ16PZyv7cqutjDF35qw==",
|
||||
"cpu": [
|
||||
"ppc64le"
|
||||
],
|
||||
@@ -4307,9 +4293,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
||||
"version": "4.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.14.0.tgz",
|
||||
"integrity": "sha512-SDDhBQwZX6LPRoPYjAZWyL27LbcBo7WdBFWJi5PI9RPCzU8ijzkQn7tt8NXiXRiFMJCVpkuMkBf4OxSxVMizAw==",
|
||||
"version": "4.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.14.1.tgz",
|
||||
"integrity": "sha512-RWdiHuAxWmzPJgaHJdpvUUlDz8sdQz4P2uv367T2JocdDa98iRw2UjIJ4QxSyt077mXZT2X6pKfT2iYtVEvOFw==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
@@ -4319,9 +4305,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-s390x-gnu": {
|
||||
"version": "4.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.14.0.tgz",
|
||||
"integrity": "sha512-RxB/qez8zIDshNJDufYlTT0ZTVut5eCpAZ3bdXDU9yTxBzui3KhbGjROK2OYTTor7alM7XBhssgoO3CZ0XD3qA==",
|
||||
"version": "4.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.14.1.tgz",
|
||||
"integrity": "sha512-VMgaGQ5zRX6ZqV/fas65/sUGc9cPmsntq2FiGmayW9KMNfWVG/j0BAqImvU4KTeOOgYSf1F+k6at1UfNONuNjA==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
@@ -4331,9 +4317,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
||||
"version": "4.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.14.0.tgz",
|
||||
"integrity": "sha512-C6y6z2eCNCfhZxT9u+jAM2Fup89ZjiG5pIzZIDycs1IwESviLxwkQcFRGLjnDrP+PT+v5i4YFvlcfAs+LnreXg==",
|
||||
"version": "4.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.14.1.tgz",
|
||||
"integrity": "sha512-9Q7DGjZN+hTdJomaQ3Iub4m6VPu1r94bmK2z3UeWP3dGUecRC54tmVu9vKHTm1bOt3ASoYtEz6JSRLFzrysKlA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -4343,9 +4329,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-musl": {
|
||||
"version": "4.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.14.0.tgz",
|
||||
"integrity": "sha512-i0QwbHYfnOMYsBEyjxcwGu5SMIi9sImDVjDg087hpzXqhBSosxkE7gyIYFHgfFl4mr7RrXksIBZ4DoLoP4FhJg==",
|
||||
"version": "4.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.14.1.tgz",
|
||||
"integrity": "sha512-JNEG/Ti55413SsreTguSx0LOVKX902OfXIKVg+TCXO6Gjans/k9O6ww9q3oLGjNDaTLxM+IHFMeXy/0RXL5R/g==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -4355,9 +4341,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
||||
"version": "4.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.14.0.tgz",
|
||||
"integrity": "sha512-Fq52EYb0riNHLBTAcL0cun+rRwyZ10S9vKzhGKKgeD+XbwunszSY0rVMco5KbOsTlwovP2rTOkiII/fQ4ih/zQ==",
|
||||
"version": "4.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.14.1.tgz",
|
||||
"integrity": "sha512-ryS22I9y0mumlLNwDFYZRDFLwWh3aKaC72CWjFcFvxK0U6v/mOkM5Up1bTbCRAhv3kEIwW2ajROegCIQViUCeA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -4367,9 +4353,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
||||
"version": "4.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.14.0.tgz",
|
||||
"integrity": "sha512-e/PBHxPdJ00O9p5Ui43+vixSgVf4NlLsmV6QneGERJ3lnjIua/kim6PRFe3iDueT1rQcgSkYP8ZBBXa/h4iPvw==",
|
||||
"version": "4.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.14.1.tgz",
|
||||
"integrity": "sha512-TdloItiGk+T0mTxKx7Hp279xy30LspMso+GzQvV2maYePMAWdmrzqSNZhUpPj3CGw12aGj57I026PgLCTu8CGg==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
@@ -4379,9 +4365,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
||||
"version": "4.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.14.0.tgz",
|
||||
"integrity": "sha512-aGg7iToJjdklmxlUlJh/PaPNa4PmqHfyRMLunbL3eaMO0gp656+q1zOKkpJ/CVe9CryJv6tAN1HDoR8cNGzkag==",
|
||||
"version": "4.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.14.1.tgz",
|
||||
"integrity": "sha512-wQGI+LY/Py20zdUPq+XCem7JcPOyzIJBm3dli+56DJsQOHbnXZFEwgmnC6el1TPAfC8lBT3m+z69RmLykNUbew==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -5681,9 +5667,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001606",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001606.tgz",
|
||||
"integrity": "sha512-LPbwnW4vfpJId225pwjZJOgX1m9sGfbw/RKJvw/t0QhYOOaTXHvkjVGFGPpvwEzufrjvTlsULnVTxdy4/6cqkg==",
|
||||
"version": "1.0.30001607",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001607.tgz",
|
||||
"integrity": "sha512-WcvhVRjXLKFB/kmOFVwELtMxyhq3iM/MvmXcyCe2PNf166c39mptscOc/45TTS96n2gpNV2z7+NakArTWZCQ3w==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
@@ -5904,9 +5890,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/clsx": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz",
|
||||
"integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==",
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.0.tgz",
|
||||
"integrity": "sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
@@ -9671,9 +9657,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/jose": {
|
||||
"version": "5.2.3",
|
||||
"resolved": "https://registry.npmjs.org/jose/-/jose-5.2.3.tgz",
|
||||
"integrity": "sha512-KUXdbctm1uHVL8BYhnyHkgp3zDX5KW8ZhAKVFEfUbU2P8Alpzjb+48hHvjOdQIyPshoblhzsuqOwEEAbtHVirA==",
|
||||
"version": "5.2.4",
|
||||
"resolved": "https://registry.npmjs.org/jose/-/jose-5.2.4.tgz",
|
||||
"integrity": "sha512-6ScbIk2WWCeXkmzF6bRPmEuaqy1m8SbsRFMa/FLrSCkGIhj8OLVG/IH+XHVmNMx/KUo8cVWEE6oKR4dJ+S0Rkg==",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/panva"
|
||||
}
|
||||
@@ -11721,9 +11707,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/rollup": {
|
||||
"version": "4.14.0",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.14.0.tgz",
|
||||
"integrity": "sha512-Qe7w62TyawbDzB4yt32R0+AbIo6m1/sqO7UPzFS8Z/ksL5mrfhA0v4CavfdmFav3D+ub4QeAgsGEe84DoWe/nQ==",
|
||||
"version": "4.14.1",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.14.1.tgz",
|
||||
"integrity": "sha512-4LnHSdd3QK2pa1J6dFbfm1HN0D7vSK/ZuZTsdyUAlA6Rr1yTouUTL13HaDOGJVgby461AhrNGBS7sCGXXtT+SA==",
|
||||
"dependencies": {
|
||||
"@types/estree": "1.0.5"
|
||||
},
|
||||
@@ -11735,21 +11721,21 @@
|
||||
"npm": ">=8.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@rollup/rollup-android-arm-eabi": "4.14.0",
|
||||
"@rollup/rollup-android-arm64": "4.14.0",
|
||||
"@rollup/rollup-darwin-arm64": "4.14.0",
|
||||
"@rollup/rollup-darwin-x64": "4.14.0",
|
||||
"@rollup/rollup-linux-arm-gnueabihf": "4.14.0",
|
||||
"@rollup/rollup-linux-arm64-gnu": "4.14.0",
|
||||
"@rollup/rollup-linux-arm64-musl": "4.14.0",
|
||||
"@rollup/rollup-linux-powerpc64le-gnu": "4.14.0",
|
||||
"@rollup/rollup-linux-riscv64-gnu": "4.14.0",
|
||||
"@rollup/rollup-linux-s390x-gnu": "4.14.0",
|
||||
"@rollup/rollup-linux-x64-gnu": "4.14.0",
|
||||
"@rollup/rollup-linux-x64-musl": "4.14.0",
|
||||
"@rollup/rollup-win32-arm64-msvc": "4.14.0",
|
||||
"@rollup/rollup-win32-ia32-msvc": "4.14.0",
|
||||
"@rollup/rollup-win32-x64-msvc": "4.14.0",
|
||||
"@rollup/rollup-android-arm-eabi": "4.14.1",
|
||||
"@rollup/rollup-android-arm64": "4.14.1",
|
||||
"@rollup/rollup-darwin-arm64": "4.14.1",
|
||||
"@rollup/rollup-darwin-x64": "4.14.1",
|
||||
"@rollup/rollup-linux-arm-gnueabihf": "4.14.1",
|
||||
"@rollup/rollup-linux-arm64-gnu": "4.14.1",
|
||||
"@rollup/rollup-linux-arm64-musl": "4.14.1",
|
||||
"@rollup/rollup-linux-powerpc64le-gnu": "4.14.1",
|
||||
"@rollup/rollup-linux-riscv64-gnu": "4.14.1",
|
||||
"@rollup/rollup-linux-s390x-gnu": "4.14.1",
|
||||
"@rollup/rollup-linux-x64-gnu": "4.14.1",
|
||||
"@rollup/rollup-linux-x64-musl": "4.14.1",
|
||||
"@rollup/rollup-win32-arm64-msvc": "4.14.1",
|
||||
"@rollup/rollup-win32-ia32-msvc": "4.14.1",
|
||||
"@rollup/rollup-win32-x64-msvc": "4.14.1",
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -13,17 +13,19 @@
|
||||
"@reduxjs/toolkit": "^2.2.2",
|
||||
"@vitejs/plugin-react": "^4.2.1",
|
||||
"@xterm/xterm": "^5.4.0",
|
||||
"clsx": "^2.1.0",
|
||||
"eslint-config-airbnb-typescript": "^18.0.0",
|
||||
"framer-motion": "^11.0.24",
|
||||
"jose": "^5.2.3",
|
||||
"i18next": "^23.10.1",
|
||||
"i18next-browser-languagedetector": "^7.2.1",
|
||||
"i18next-http-backend": "^2.5.0",
|
||||
"jose": "^5.2.3",
|
||||
"monaco-editor": "^0.47.0",
|
||||
"react": "^18.2.0",
|
||||
"react-accessible-treeview": "^2.8.3",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-icons": "^5.0.1",
|
||||
"react-i18next": "^14.1.0",
|
||||
"react-icons": "^5.0.1",
|
||||
"react-redux": "^9.1.0",
|
||||
"react-syntax-highlighter": "^15.5.0",
|
||||
"tailwind-merge": "^2.2.2",
|
||||
|
||||
@@ -19,7 +19,7 @@ interface Props {
|
||||
|
||||
function LeftNav({ setSettingOpen }: Props): JSX.Element {
|
||||
return (
|
||||
<div className="flex flex-col h-full p-4 bg-bg-dark w-16 items-center shrink-0">
|
||||
<div className="flex flex-col h-full p-4 bg-neutral-900 w-16 items-center shrink-0">
|
||||
<div
|
||||
className="mt-auto cursor-pointer hover:opacity-80"
|
||||
onClick={() => setSettingOpen(true)}
|
||||
@@ -69,18 +69,18 @@ function App(): JSX.Element {
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex h-screen bg-bg-dark text-white">
|
||||
<div className="flex h-screen bg-neutral-900 text-white">
|
||||
<LeftNav setSettingOpen={setSettingOpen} />
|
||||
<div className="flex flex-col grow gap-3 py-3 pr-3">
|
||||
<div className="flex gap-3 grow min-h-0">
|
||||
<div className="w-[500px] shrink-0 rounded-xl overflow-hidden border border-border">
|
||||
<div className="w-[500px] shrink-0 rounded-xl overflow-hidden border border-neutral-600">
|
||||
<ChatInterface />
|
||||
</div>
|
||||
<div className="flex flex-col flex-1 overflow-hidden rounded-xl bg-bg-workspace border border-border">
|
||||
<div className="flex flex-col flex-1 overflow-hidden rounded-xl bg-neutral-800 border border-neutral-600">
|
||||
<Workspace />
|
||||
</div>
|
||||
</div>
|
||||
<div className="h-72 shrink-0 bg-bg-workspace rounded-xl border border-border flex flex-col">
|
||||
<div className="h-72 shrink-0 bg-neutral-800 rounded-xl border border-neutral-600 flex flex-col">
|
||||
<Terminal key="terminal" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -13,7 +13,7 @@ function Browser(): JSX.Element {
|
||||
: `data:image/png;base64,${screenshotSrc || ""}`;
|
||||
|
||||
return (
|
||||
<div className="h-full m-2 bg-bg-workspace mockup-browser">
|
||||
<div className="h-full m-2 bg-neutral-700 mockup-browser">
|
||||
<div className="mockup-browser-toolbar">
|
||||
<div className="input">{url}</div>
|
||||
</div>
|
||||
|
||||
@@ -139,8 +139,8 @@ function ChatInterface(): JSX.Element {
|
||||
const { initialized } = useSelector((state: RootState) => state.task);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col h-full p-0 bg-bg-workspace">
|
||||
<div className="border-b border-border text-lg px-4 py-2">Chat</div>
|
||||
<div className="flex flex-col h-full p-0 bg-neutral-800">
|
||||
<div className="border-b border-neutral-600 text-sm px-4 py-2">Chat</div>
|
||||
{initialized ? <MessageList /> : <InitializingStatus />}
|
||||
<Input />
|
||||
</div>
|
||||
|
||||
@@ -1,166 +1,17 @@
|
||||
import Editor, { Monaco } from "@monaco-editor/react";
|
||||
import type { editor } from "monaco-editor";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import TreeView, { flattenTree } from "react-accessible-treeview";
|
||||
import { DiJavascript } from "react-icons/di";
|
||||
import {
|
||||
FaCss3,
|
||||
FaFile,
|
||||
FaFolder,
|
||||
FaFolderOpen,
|
||||
FaHtml5,
|
||||
FaList,
|
||||
FaMarkdown,
|
||||
FaNpm,
|
||||
FaPython,
|
||||
} from "react-icons/fa";
|
||||
import { VscClose, VscListTree, VscRefresh } from "react-icons/vsc";
|
||||
import React, { useState } from "react";
|
||||
import { Tabs, Tab } from "@nextui-org/react";
|
||||
import { useSelector } from "react-redux";
|
||||
import { getWorkspace, selectFile } from "../services/fileService";
|
||||
import { setCode, updateWorkspace } from "../state/codeSlice";
|
||||
import store, { RootState } from "../store";
|
||||
|
||||
interface FileIconProps {
|
||||
filename: string;
|
||||
}
|
||||
|
||||
function FileIcon({ filename }: FileIconProps): JSX.Element | null {
|
||||
const extension = filename.slice(filename.lastIndexOf(".") + 1);
|
||||
switch (extension) {
|
||||
case "js":
|
||||
return <DiJavascript />;
|
||||
case "ts":
|
||||
return <DiJavascript />;
|
||||
case "py":
|
||||
return <FaPython />;
|
||||
case "css":
|
||||
return <FaCss3 />;
|
||||
case "json":
|
||||
return <FaList />;
|
||||
case "npmignore":
|
||||
return <FaNpm />;
|
||||
case "html":
|
||||
return <FaHtml5 />;
|
||||
case "md":
|
||||
return <FaMarkdown />;
|
||||
default:
|
||||
return <FaFile />;
|
||||
}
|
||||
}
|
||||
|
||||
interface FolderIconProps {
|
||||
isOpen: boolean;
|
||||
}
|
||||
|
||||
function FolderIcon({ isOpen }: FolderIconProps): JSX.Element {
|
||||
return isOpen ? (
|
||||
<FaFolderOpen color="D9D3D0" className="icon" />
|
||||
) : (
|
||||
<FaFolder color="D9D3D0" className="icon" />
|
||||
);
|
||||
}
|
||||
|
||||
function Files(): JSX.Element | null {
|
||||
const workspaceFolder = useSelector(
|
||||
(state: RootState) => state.code.workspaceFolder,
|
||||
);
|
||||
const selectedIds = useSelector((state: RootState) => state.code.selectedIds);
|
||||
const [explorerOpen, setExplorerOpen] = useState(true);
|
||||
const workspaceTree = flattenTree(workspaceFolder);
|
||||
|
||||
useEffect(() => {
|
||||
getWorkspace().then((file) => store.dispatch(updateWorkspace(file)));
|
||||
}, []);
|
||||
|
||||
if (workspaceTree.length <= 1) {
|
||||
return null;
|
||||
}
|
||||
if (!explorerOpen) {
|
||||
return (
|
||||
<div className="h-full bg-bg-workspace border-r-1 flex flex-col">
|
||||
<div className="flex gap-1 border-b-1 p-1 justify-end">
|
||||
<VscListTree
|
||||
className="cursor-pointer"
|
||||
onClick={() => setExplorerOpen(true)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div className="min-w-[250px] h-full bg-bg-workspace border-r-1 flex flex-col">
|
||||
<div className="flex gap-1 border-b-1 p-1 justify-end">
|
||||
<VscRefresh
|
||||
onClick={() =>
|
||||
getWorkspace().then((file) => store.dispatch(updateWorkspace(file)))
|
||||
}
|
||||
className="cursor-pointer"
|
||||
/>
|
||||
<VscClose
|
||||
className="cursor-pointer"
|
||||
onClick={() => setExplorerOpen(false)}
|
||||
/>
|
||||
</div>
|
||||
<div className="w-full overflow-x-auto h-full py-2">
|
||||
<TreeView
|
||||
className="font-mono text-sm"
|
||||
data={workspaceTree}
|
||||
selectedIds={selectedIds}
|
||||
expandedIds={workspaceTree.map((node) => node.id)}
|
||||
onNodeSelect={(node) => {
|
||||
if (!node.isBranch) {
|
||||
let fullPath = node.element.name;
|
||||
let currentNode = workspaceTree.find(
|
||||
(file) => file.id === node.element.id,
|
||||
);
|
||||
while (currentNode !== undefined && currentNode.parent) {
|
||||
currentNode = workspaceTree.find(
|
||||
(file) => file.id === node.element.parent,
|
||||
);
|
||||
fullPath = `${currentNode!.name}/${fullPath}`;
|
||||
}
|
||||
selectFile(fullPath).then((code) => {
|
||||
store.dispatch(setCode(code));
|
||||
});
|
||||
}
|
||||
}}
|
||||
// eslint-disable-next-line react/no-unstable-nested-components
|
||||
nodeRenderer={({
|
||||
element,
|
||||
isBranch,
|
||||
isExpanded,
|
||||
getNodeProps,
|
||||
level,
|
||||
}) => (
|
||||
<div
|
||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||
{...getNodeProps()}
|
||||
style={{ paddingLeft: 20 * (level - 1) }}
|
||||
className="cursor-pointer nowrap flex items-center gap-2 aria-selected:bg-slate-500 hover:bg-slate-700"
|
||||
>
|
||||
<div className="shrink-0">
|
||||
{isBranch ? (
|
||||
<FolderIcon isOpen={isExpanded} />
|
||||
) : (
|
||||
<FileIcon filename={element.name} />
|
||||
)}
|
||||
</div>
|
||||
{element.name}
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
import { RootState } from "../store";
|
||||
import Files from "./Files";
|
||||
import { cn } from "../utils/utils";
|
||||
|
||||
function CodeEditor(): JSX.Element {
|
||||
const [selectedFileName, setSelectedFileName] = useState("welcome");
|
||||
const [explorerOpen, setExplorerOpen] = useState(true);
|
||||
const code = useSelector((state: RootState) => state.code.code);
|
||||
|
||||
const bgColor = getComputedStyle(document.documentElement)
|
||||
.getPropertyValue("--bg-workspace")
|
||||
.trim();
|
||||
|
||||
const handleEditorDidMount = (
|
||||
editor: editor.IStandaloneCodeEditor,
|
||||
monaco: Monaco,
|
||||
@@ -171,7 +22,7 @@ function CodeEditor(): JSX.Element {
|
||||
inherit: true,
|
||||
rules: [],
|
||||
colors: {
|
||||
"editor.background": bgColor,
|
||||
"editor.background": "#171717",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -180,16 +31,50 @@ function CodeEditor(): JSX.Element {
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="w-full h-full bg-bg-workspace flex">
|
||||
<Files />
|
||||
<Editor
|
||||
height="95%"
|
||||
theme="vs-dark"
|
||||
defaultLanguage="python"
|
||||
defaultValue="# Welcome to OpenDevin!"
|
||||
value={code}
|
||||
onMount={handleEditorDidMount}
|
||||
/>
|
||||
<div
|
||||
className={`${cn(
|
||||
explorerOpen ? "grid-cols-[250px_auto]" : "grid-cols-[50px_auto]",
|
||||
)} grid h-full bg-neutral-900 transition-all duration-500 ease-in-out`}
|
||||
>
|
||||
<div>
|
||||
<Files
|
||||
setSelectedFileName={setSelectedFileName}
|
||||
setExplorerOpen={setExplorerOpen}
|
||||
explorerOpen={explorerOpen}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Tabs
|
||||
disableCursorAnimation
|
||||
classNames={{
|
||||
tabList:
|
||||
"w-full relative rounded-none bg-neutral-900 p-0 border-r border-divider",
|
||||
cursor: "w-full bg-neutral-600 rounded-none",
|
||||
tab: "max-w-fit px-4 h-[36px]",
|
||||
tabContent: "group-data-[selected=true]:text-neutral-50 ",
|
||||
}}
|
||||
aria-label="Options"
|
||||
>
|
||||
<Tab
|
||||
key={
|
||||
selectedFileName === ""
|
||||
? "Welcome"
|
||||
: selectedFileName.toLocaleLowerCase()
|
||||
}
|
||||
title={!selectedFileName ? "Welcome" : selectedFileName}
|
||||
>
|
||||
<div>
|
||||
<Editor
|
||||
height="100vh"
|
||||
defaultLanguage="python"
|
||||
defaultValue="# Welcome to OpenDevin!"
|
||||
value={code}
|
||||
onMount={handleEditorDidMount}
|
||||
/>
|
||||
</div>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
41
frontend/src/components/FileIcons.tsx
Normal file
41
frontend/src/components/FileIcons.tsx
Normal file
@@ -0,0 +1,41 @@
|
||||
import React from "react";
|
||||
import { DiJavascript } from "react-icons/di";
|
||||
import {
|
||||
FaCss3,
|
||||
FaFile,
|
||||
FaHtml5,
|
||||
FaList,
|
||||
FaMarkdown,
|
||||
FaNpm,
|
||||
FaPython,
|
||||
} from "react-icons/fa";
|
||||
|
||||
interface FileIconProps {
|
||||
filename: string;
|
||||
}
|
||||
|
||||
function FileIcon({ filename }: FileIconProps): JSX.Element | null {
|
||||
const extension = filename.slice(filename.lastIndexOf(".") + 1);
|
||||
switch (extension) {
|
||||
case "js":
|
||||
return <DiJavascript />;
|
||||
case "ts":
|
||||
return <DiJavascript />;
|
||||
case "py":
|
||||
return <FaPython />;
|
||||
case "css":
|
||||
return <FaCss3 />;
|
||||
case "json":
|
||||
return <FaList />;
|
||||
case "npmignore":
|
||||
return <FaNpm />;
|
||||
case "html":
|
||||
return <FaHtml5 />;
|
||||
case "md":
|
||||
return <FaMarkdown />;
|
||||
default:
|
||||
return <FaFile />;
|
||||
}
|
||||
}
|
||||
|
||||
export default FileIcon;
|
||||
175
frontend/src/components/Files.tsx
Normal file
175
frontend/src/components/Files.tsx
Normal file
@@ -0,0 +1,175 @@
|
||||
import React, { useEffect } from "react";
|
||||
import TreeView, { flattenTree } from "react-accessible-treeview";
|
||||
import { AiOutlineFolder } from "react-icons/ai";
|
||||
import { Accordion, AccordionItem, Button } from "@nextui-org/react";
|
||||
import {
|
||||
TbLayoutSidebarLeftCollapseFilled,
|
||||
TbLayoutSidebarRightCollapseFilled,
|
||||
} from "react-icons/tb";
|
||||
|
||||
import { IoIosArrowDown } from "react-icons/io";
|
||||
import { VscRefresh } from "react-icons/vsc";
|
||||
import { useSelector } from "react-redux";
|
||||
import { getWorkspace, selectFile } from "../services/fileService";
|
||||
import { setCode, updateWorkspace } from "../state/codeSlice";
|
||||
import store, { RootState } from "../store";
|
||||
import FolderIcon from "./FolderIcon";
|
||||
import FileIcon from "./FileIcons";
|
||||
|
||||
interface FilesProps {
|
||||
setSelectedFileName: React.Dispatch<React.SetStateAction<string>>;
|
||||
setExplorerOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
explorerOpen: boolean;
|
||||
}
|
||||
|
||||
function Files({
|
||||
setSelectedFileName,
|
||||
setExplorerOpen,
|
||||
explorerOpen,
|
||||
}: FilesProps): JSX.Element {
|
||||
const workspaceFolder = useSelector(
|
||||
(state: RootState) => state.code.workspaceFolder,
|
||||
);
|
||||
|
||||
const selectedIds = useSelector((state: RootState) => state.code.selectedIds);
|
||||
const workspaceTree = flattenTree(workspaceFolder);
|
||||
|
||||
useEffect(() => {
|
||||
getWorkspace().then((file) => store.dispatch(updateWorkspace(file)));
|
||||
}, []);
|
||||
|
||||
if (workspaceTree.length <= 1) {
|
||||
<div className="h-full bg-neutral-700 border-neutral-600 items-center border-r-1 flex flex-col">
|
||||
<div>No workspace found</div>
|
||||
</div>;
|
||||
}
|
||||
|
||||
if (!explorerOpen) {
|
||||
return (
|
||||
<div className="h-full bg-neutral-800 border-neutral-600 items-center border-r-1 flex flex-col">
|
||||
<div className="flex mt-2 p-1 justify-end">
|
||||
<TbLayoutSidebarRightCollapseFilled
|
||||
className="cursor-pointer"
|
||||
onClick={() => setExplorerOpen(true)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div className="bg-neutral-800 h-full border-r-1 border-r-neutral-600 flex flex-col">
|
||||
<div className="flex p-2 items-center justify-between ">
|
||||
<Accordion className="px-0" defaultExpandedKeys={["1"]} isCompact>
|
||||
<AccordionItem
|
||||
classNames={{
|
||||
title: "editor-accordion-title",
|
||||
content: "editor-accordion-content",
|
||||
}}
|
||||
hideIndicator
|
||||
key="1"
|
||||
aria-label={workspaceFolder.name}
|
||||
title={
|
||||
<div className="group flex items-center justify-between ">
|
||||
<span className="text-neutral-400">{workspaceFolder.name}</span>
|
||||
<div className="opacity-0 translate-y-[10px] transition-all ease-in-out group-hover:opacity-100 transform group-hover:-translate-y-0 ">
|
||||
<Button
|
||||
type="button"
|
||||
style={{
|
||||
width: "24px",
|
||||
height: "24px",
|
||||
}}
|
||||
variant="flat"
|
||||
onClick={() =>
|
||||
getWorkspace().then((file) =>
|
||||
store.dispatch(updateWorkspace(file)),
|
||||
)
|
||||
}
|
||||
className="cursor-pointer text-[12px] bg-neutral-800"
|
||||
isIconOnly
|
||||
aria-label="Refresh"
|
||||
>
|
||||
<VscRefresh />
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
style={{
|
||||
width: "24px",
|
||||
height: "24px",
|
||||
}}
|
||||
variant="flat"
|
||||
onClick={() => setExplorerOpen(false)}
|
||||
className="cursor-pointer text-[12px] bg-neutral-800"
|
||||
isIconOnly
|
||||
aria-label="Refresh"
|
||||
>
|
||||
<TbLayoutSidebarLeftCollapseFilled />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
className="editor-accordion"
|
||||
startContent={
|
||||
<div className="flex items-center gap-1">
|
||||
<IoIosArrowDown className="text-neutral-400" />
|
||||
<AiOutlineFolder className="text-neutral-400" />
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<div className="w-full overflow-x-auto h-full py-2">
|
||||
<TreeView
|
||||
className="font-mono text-sm text-neutral-400"
|
||||
data={workspaceTree}
|
||||
selectedIds={selectedIds}
|
||||
expandedIds={workspaceTree.map((node) => node.id)}
|
||||
onNodeSelect={(node) => {
|
||||
if (!node.isBranch) {
|
||||
let fullPath = node.element.name;
|
||||
setSelectedFileName(fullPath);
|
||||
let currentNode = workspaceTree.find(
|
||||
(file) => file.id === node.element.id,
|
||||
);
|
||||
while (currentNode !== undefined && currentNode.parent) {
|
||||
currentNode = workspaceTree.find(
|
||||
(file) => file.id === node.element.parent,
|
||||
);
|
||||
fullPath = `${currentNode!.name}/${fullPath}`;
|
||||
}
|
||||
selectFile(fullPath).then((code) => {
|
||||
store.dispatch(setCode(code));
|
||||
});
|
||||
}
|
||||
}}
|
||||
// eslint-disable-next-line react/no-unstable-nested-components
|
||||
nodeRenderer={({
|
||||
element,
|
||||
isBranch,
|
||||
isExpanded,
|
||||
getNodeProps,
|
||||
level,
|
||||
}) => (
|
||||
<div
|
||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||
{...getNodeProps()}
|
||||
style={{ paddingLeft: 20 * (level - 1) }}
|
||||
className="cursor-pointer rounded-[5px] p-1 nowrap flex items-center gap-2 aria-selected:bg-neutral-600 aria-selected:text-neutral-50 hover:text-neutral-50"
|
||||
>
|
||||
<div className="shrink-0 pl-5">
|
||||
{isBranch ? (
|
||||
<FolderIcon isOpen={isExpanded} />
|
||||
) : (
|
||||
<FileIcon filename={element.name} />
|
||||
)}
|
||||
</div>
|
||||
{element.name}
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</AccordionItem>
|
||||
</Accordion>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Files;
|
||||
16
frontend/src/components/FolderIcon.tsx
Normal file
16
frontend/src/components/FolderIcon.tsx
Normal file
@@ -0,0 +1,16 @@
|
||||
import React from "react";
|
||||
import { FaFolder, FaFolderOpen } from "react-icons/fa";
|
||||
|
||||
interface FolderIconProps {
|
||||
isOpen: boolean;
|
||||
}
|
||||
|
||||
function FolderIcon({ isOpen }: FolderIconProps): JSX.Element {
|
||||
return isOpen ? (
|
||||
<FaFolderOpen color="D9D3D0" className="icon" />
|
||||
) : (
|
||||
<FaFolder color="D9D3D0" className="icon" />
|
||||
);
|
||||
}
|
||||
|
||||
export default FolderIcon;
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from "react";
|
||||
|
||||
function Planner(): JSX.Element {
|
||||
return <div className="h-full w-full bg-bg-workspace">Coming soon...</div>;
|
||||
return <div className="h-full w-full bg-neutral-700">Coming soon...</div>;
|
||||
}
|
||||
|
||||
export default Planner;
|
||||
|
||||
@@ -52,10 +52,6 @@ function Terminal(): JSX.Element {
|
||||
const { commands } = useSelector((state: RootState) => state.cmd);
|
||||
|
||||
useEffect(() => {
|
||||
const bgColor = getComputedStyle(document.documentElement)
|
||||
.getPropertyValue("--bg-workspace")
|
||||
.trim();
|
||||
|
||||
const terminal = new XtermTerminal({
|
||||
// This value is set to the appropriate value by the
|
||||
// `fitAddon.fit()` call below.
|
||||
@@ -66,7 +62,7 @@ function Terminal(): JSX.Element {
|
||||
fontFamily: "Menlo, Monaco, 'Courier New', monospace",
|
||||
fontSize: 14,
|
||||
theme: {
|
||||
background: bgColor,
|
||||
background: "#262626",
|
||||
},
|
||||
});
|
||||
terminal.write("$ ");
|
||||
@@ -104,7 +100,9 @@ function Terminal(): JSX.Element {
|
||||
|
||||
return (
|
||||
<div className="flex flex-col h-full">
|
||||
<div className="px-4 py-2 text-lg border-b border-border">Terminal</div>
|
||||
<div className="px-4 py-2 text-sm border-b border-neutral-600">
|
||||
Terminal
|
||||
</div>
|
||||
<div className="grow p-2 flex min-h-0">
|
||||
<div ref={terminalRef} className="h-full w-full" />
|
||||
</div>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Tab, Tabs } from "@nextui-org/react";
|
||||
import React, { useMemo, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { FaCode } from "react-icons/fa6";
|
||||
import { IoIosGlobe } from "react-icons/io";
|
||||
import Calendar from "../assets/calendar";
|
||||
import Earth from "../assets/earth";
|
||||
import Pencil from "../assets/pencil";
|
||||
import { I18nKey } from "../i18n/declaration";
|
||||
import { AllTabs, TabOption, TabType } from "../types/TabOption";
|
||||
import Browser from "./Browser";
|
||||
@@ -23,12 +23,12 @@ function Workspace() {
|
||||
},
|
||||
[TabOption.CODE]: {
|
||||
name: t(I18nKey.WORKSPACE$CODE_EDITOR_TAB_LABEL),
|
||||
icon: <Pencil />,
|
||||
icon: <FaCode size={18} />,
|
||||
component: <CodeEditor key="code" />,
|
||||
},
|
||||
[TabOption.BROWSER]: {
|
||||
name: t(I18nKey.WORKSPACE$BROWSER_TAB_LABEL),
|
||||
icon: <Earth />,
|
||||
icon: <IoIosGlobe size={18} />,
|
||||
component: <Browser key="browser" />,
|
||||
},
|
||||
}),
|
||||
@@ -39,9 +39,17 @@ function Workspace() {
|
||||
<>
|
||||
<div
|
||||
role="tablist"
|
||||
className="tabs tabs-bordered tabs-lg border-b border-border"
|
||||
className="tabs tabs-bordered tabs-lg border-b border-neutral-600"
|
||||
>
|
||||
<Tabs
|
||||
disableCursorAnimation
|
||||
classNames={{
|
||||
tabList:
|
||||
"w-full relative rounded-none bg-neutral-800 p-0 border-divider gap-0 h-[36px]",
|
||||
cursor: "w-full bg-neutral-800 rounded-none",
|
||||
tab: " rounded-none border-neutral-600 border-r-[1px] border-r",
|
||||
tabContent: "group-data-[selected=true]:text-neutral-50",
|
||||
}}
|
||||
variant="light"
|
||||
size="lg"
|
||||
onSelectionChange={(v) => {
|
||||
@@ -52,7 +60,7 @@ function Workspace() {
|
||||
<Tab
|
||||
key={tab}
|
||||
title={
|
||||
<div className="flex items-center space-x-2">
|
||||
<div className="flex items-center space-x-2 justify-center text-xs">
|
||||
{tabData[tab].icon}
|
||||
<span>{tabData[tab].name}</span>
|
||||
</div>
|
||||
@@ -63,7 +71,7 @@ function Workspace() {
|
||||
</div>
|
||||
{Object.keys(tabData).map((tab) => (
|
||||
<div
|
||||
className="h-full w-full p-4 bg-bg-workspace"
|
||||
className="h-full w-full bg-neutral-800"
|
||||
key={tab}
|
||||
hidden={activeTab !== tab}
|
||||
>
|
||||
|
||||
@@ -4,7 +4,12 @@
|
||||
--bg-input: #393939;
|
||||
--bg-workspace: #1f2228;
|
||||
--border: #3c3c4a;
|
||||
background-color: var(--bg-dark) !important;
|
||||
--text-editor-base: #9099AC;
|
||||
--text-editor-active:#C4CBDA;
|
||||
--bg-editor-sidebar: #24272E;
|
||||
--bg-editor-active: #31343D;
|
||||
--border-editor-sidebar: #3C3C4A;
|
||||
background-color: var(--neutral-900) !important;
|
||||
}
|
||||
|
||||
body {
|
||||
@@ -20,3 +25,22 @@ code {
|
||||
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
|
||||
monospace;
|
||||
}
|
||||
|
||||
.editor-accordion h2 > button{
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.editor-accordion-title {
|
||||
color: var(--bg-neutral-400) !important;
|
||||
}
|
||||
|
||||
.editor-accordion-content {
|
||||
padding-top: 0 !important;
|
||||
padding-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.editor-accordion-content ul {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
6
frontend/src/utils/utils.ts
Normal file
6
frontend/src/utils/utils.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import { type ClassValue, clsx } from "clsx";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs));
|
||||
}
|
||||
@@ -5,17 +5,6 @@ export default {
|
||||
"./src/**/*.{js,ts,jsx,tsx}",
|
||||
"./node_modules/@nextui-org/theme/dist/**/*.{js,ts,jsx,tsx}",
|
||||
],
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
"bg-dark": "var(--bg-dark)",
|
||||
"bg-light": "var(--bg-light)",
|
||||
"bg-input": "var(--bg-input)",
|
||||
"bg-workspace": "var(--bg-workspace)",
|
||||
border: "var(--border)",
|
||||
},
|
||||
},
|
||||
},
|
||||
darkMode: "class",
|
||||
plugins: [
|
||||
nextui({
|
||||
|
||||
Reference in New Issue
Block a user