From 816a6c7cd3ccd26dd73dbc2bbf1389839ae41f9d Mon Sep 17 00:00:00 2001 From: Steve Ayers Date: Tue, 1 Oct 2024 10:52:43 -0400 Subject: [PATCH] Merge Signed-off-by: Steve Ayers --- package-lock.json | 152 ++++++++++---------- src/components/eliza-demo/index.tsx | 51 ++++--- src/components/eliza-demo/styles.module.css | 72 ---------- src/components/home/examples.module.css | 41 ------ src/components/home/examples.tsx | 21 +-- src/components/terminal/index.tsx | 15 ++ src/components/terminal/styles.module.css | 119 +++++++++++++++ src/components/terminal/terminal.tsx | 144 +++++++++++++++++++ swizzling.md | 14 -- tsconfig.json | 3 +- 10 files changed, 390 insertions(+), 242 deletions(-) delete mode 100644 src/components/eliza-demo/styles.module.css create mode 100644 src/components/terminal/index.tsx create mode 100644 src/components/terminal/styles.module.css create mode 100644 src/components/terminal/terminal.tsx diff --git a/package-lock.json b/package-lock.json index 7015f132..4c040257 100644 --- a/package-lock.json +++ b/package-lock.json @@ -175,9 +175,9 @@ } }, "node_modules/@algolia/client-common": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.6.1.tgz", - "integrity": "sha512-4MGqXqiAyqsUJw+KamKWZO2Gxn9iMpc05vC0vy8+iQRjKRZEDB1a+3Da6CnkWzXa162pJb7a/chDAAKA9rye8A==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.7.0.tgz", + "integrity": "sha512-hrYlN9yNQukmNj8bBlw9PCXi9jmRQqNUXaG6MXH1aDabjO6YD1WPVqTvaELbIBgTbDJzCn0R2owms0uaxQkjUg==", "license": "MIT", "peer": true, "engines": { @@ -206,16 +206,16 @@ } }, "node_modules/@algolia/client-search": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.6.1.tgz", - "integrity": "sha512-HloeR0Ef29vf2yJc1lhjw1OYial3YgB0f3TQaqqMlSnM/IkAw9TnX1IOYLurnI91apMKggFpA9t8lRp7TGEKEg==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.7.0.tgz", + "integrity": "sha512-0Frfjt4oxvVP2qsTQAjwdaG5SvJ3TbHBkBrS6M7cG5RDrgHqOrhBnBGCFT+YO3CeNK54r+d57oB1VcD2F1lHuQ==", "license": "MIT", "peer": true, "dependencies": { - "@algolia/client-common": "5.6.1", - "@algolia/requester-browser-xhr": "5.6.1", - "@algolia/requester-fetch": "5.6.1", - "@algolia/requester-node-http": "5.6.1" + "@algolia/client-common": "5.7.0", + "@algolia/requester-browser-xhr": "5.7.0", + "@algolia/requester-fetch": "5.7.0", + "@algolia/requester-node-http": "5.7.0" }, "engines": { "node": ">= 14.0.0" @@ -301,13 +301,13 @@ } }, "node_modules/@algolia/requester-browser-xhr": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.6.1.tgz", - "integrity": "sha512-tY1RW60sGF9sMpxbd8j53IqLLwnkNhrAarVhFfNZzDZNvI8WyzG78W5ZD/SFvtkgNPPSav3T/3LpBT8xBpzbGw==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.7.0.tgz", + "integrity": "sha512-ohtIp+lyTGM3agrHyedC3w7ijfdUvSN6wmGuKqUezrNzd0nCkFoLW0OINlyv1ODrTEVnL8PAM/Zqubjafxd/Ww==", "license": "MIT", "peer": true, "dependencies": { - "@algolia/client-common": "5.6.1" + "@algolia/client-common": "5.7.0" }, "engines": { "node": ">= 14.0.0" @@ -320,26 +320,26 @@ "license": "MIT" }, "node_modules/@algolia/requester-fetch": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.6.1.tgz", - "integrity": "sha512-4TvR5IodrH+o+ji4ka+VBufWY0GfHr43nFqnDTStabtjspfo4rlcV16x534vvnbfp694oBxrz0SO/Ny8VemvXg==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.7.0.tgz", + "integrity": "sha512-Eg8cBhNg2QNnDDldyK77aXvg3wIc5qnpCDCAJXQ2oaqZwwvvYaTgnP1ofznNG6+klri4Fk1YAaC9wyDBhByWIA==", "license": "MIT", "peer": true, "dependencies": { - "@algolia/client-common": "5.6.1" + "@algolia/client-common": "5.7.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/requester-node-http": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.6.1.tgz", - "integrity": "sha512-K7tlss87aq6UnWnU8+fPIe+Is9Mvyqwzysp6Ty/HpQ7YNKUU7opgkMOVKxzTwt3fm40NfNX4ENvVKHoYABL6vw==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.7.0.tgz", + "integrity": "sha512-8BDssYEkcp1co06KtHO9b37H+5zVM/h+5kyesJb2C2EHFO3kgzLHWl/JyXOVtYlKQBkmdObYOI0s6JaXRy2yQA==", "license": "MIT", "peer": true, "dependencies": { - "@algolia/client-common": "5.6.1" + "@algolia/client-common": "5.7.0" }, "engines": { "node": ">= 14.0.0" @@ -4259,17 +4259,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.7.0.tgz", - "integrity": "sha512-RIHOoznhA3CCfSTFiB6kBGLQtB/sox+pJ6jeFu6FxJvqL8qRxq/FfGO/UhsGgQM9oGdXkV4xUgli+dt26biB6A==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.8.0.tgz", + "integrity": "sha512-wORFWjU30B2WJ/aXBfOm1LX9v9nyt9D3jsSOxC3cCaTQGCW5k4jNpmjFv3U7p/7s4yvdjHzwtv2Sd2dOyhjS0A==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.7.0", - "@typescript-eslint/type-utils": "8.7.0", - "@typescript-eslint/utils": "8.7.0", - "@typescript-eslint/visitor-keys": "8.7.0", + "@typescript-eslint/scope-manager": "8.8.0", + "@typescript-eslint/type-utils": "8.8.0", + "@typescript-eslint/utils": "8.8.0", + "@typescript-eslint/visitor-keys": "8.8.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -4293,16 +4293,16 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.7.0.tgz", - "integrity": "sha512-ZbdUdwsl2X/s3CiyAu3gOlfQzpbuG3nTWKPoIvAu1pu5r8viiJvv2NPN2AqArL35NCYtw/lrPPfM4gxrMLNLPw==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.8.0.tgz", + "integrity": "sha512-QE2MgfOTem00qrlPgyByaCHay9yb1+9BjnMFnSFkUKQfu7adBXDTnCAivURnuPPAG/qiB+kzKkZKmKfaMT0zVg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.7.0", - "@typescript-eslint/types": "8.7.0", - "@typescript-eslint/typescript-estree": "8.7.0" + "@typescript-eslint/scope-manager": "8.8.0", + "@typescript-eslint/types": "8.8.0", + "@typescript-eslint/typescript-estree": "8.8.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4316,16 +4316,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.7.0.tgz", - "integrity": "sha512-lN0btVpj2unxHlNYLI//BQ7nzbMJYBVQX5+pbNXvGYazdlgYonMn4AhhHifQ+J4fGRYA/m1DjaQjx+fDetqBOQ==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.8.0.tgz", + "integrity": "sha512-uEFUsgR+tl8GmzmLjRqz+VrDv4eoaMqMXW7ruXfgThaAShO9JTciKpEsB+TvnfFfbg5IpujgMXVV36gOJRLtZg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/scope-manager": "8.7.0", - "@typescript-eslint/types": "8.7.0", - "@typescript-eslint/typescript-estree": "8.7.0", - "@typescript-eslint/visitor-keys": "8.7.0", + "@typescript-eslint/scope-manager": "8.8.0", + "@typescript-eslint/types": "8.8.0", + "@typescript-eslint/typescript-estree": "8.8.0", + "@typescript-eslint/visitor-keys": "8.8.0", "debug": "^4.3.4" }, "engines": { @@ -4345,14 +4345,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.7.0.tgz", - "integrity": "sha512-87rC0k3ZlDOuz82zzXRtQ7Akv3GKhHs0ti4YcbAJtaomllXoSO8hi7Ix3ccEvCd824dy9aIX+j3d2UMAfCtVpg==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.8.0.tgz", + "integrity": "sha512-EL8eaGC6gx3jDd8GwEFEV091210U97J0jeEHrAYvIYosmEGet4wJ+g0SYmLu+oRiAwbSA5AVrt6DxLHfdd+bUg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.7.0", - "@typescript-eslint/visitor-keys": "8.7.0" + "@typescript-eslint/types": "8.8.0", + "@typescript-eslint/visitor-keys": "8.8.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4363,14 +4363,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.7.0.tgz", - "integrity": "sha512-tl0N0Mj3hMSkEYhLkjREp54OSb/FI6qyCzfiiclvJvOqre6hsZTGSnHtmFLDU8TIM62G7ygEa1bI08lcuRwEnQ==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.8.0.tgz", + "integrity": "sha512-IKwJSS7bCqyCeG4NVGxnOP6lLT9Okc3Zj8hLO96bpMkJab+10HIfJbMouLrlpyOr3yrQ1cA413YPFiGd1mW9/Q==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.7.0", - "@typescript-eslint/utils": "8.7.0", + "@typescript-eslint/typescript-estree": "8.8.0", + "@typescript-eslint/utils": "8.8.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -4388,16 +4388,16 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.7.0.tgz", - "integrity": "sha512-ZbdUdwsl2X/s3CiyAu3gOlfQzpbuG3nTWKPoIvAu1pu5r8viiJvv2NPN2AqArL35NCYtw/lrPPfM4gxrMLNLPw==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.8.0.tgz", + "integrity": "sha512-QE2MgfOTem00qrlPgyByaCHay9yb1+9BjnMFnSFkUKQfu7adBXDTnCAivURnuPPAG/qiB+kzKkZKmKfaMT0zVg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.7.0", - "@typescript-eslint/types": "8.7.0", - "@typescript-eslint/typescript-estree": "8.7.0" + "@typescript-eslint/scope-manager": "8.8.0", + "@typescript-eslint/types": "8.8.0", + "@typescript-eslint/typescript-estree": "8.8.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4411,9 +4411,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.7.0.tgz", - "integrity": "sha512-LLt4BLHFwSfASHSF2K29SZ+ZCsbQOM+LuarPjRUuHm+Qd09hSe3GCeaQbcCr+Mik+0QFRmep/FyZBO6fJ64U3w==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.8.0.tgz", + "integrity": "sha512-QJwc50hRCgBd/k12sTykOJbESe1RrzmX6COk8Y525C9l7oweZ+1lw9JiU56im7Amm8swlz00DRIlxMYLizr2Vw==", "dev": true, "license": "MIT", "engines": { @@ -4425,14 +4425,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.7.0.tgz", - "integrity": "sha512-MC8nmcGHsmfAKxwnluTQpNqceniT8SteVwd2voYlmiSWGOtjvGXdPl17dYu2797GVscK30Z04WRM28CrKS9WOg==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.8.0.tgz", + "integrity": "sha512-ZaMJwc/0ckLz5DaAZ+pNLmHv8AMVGtfWxZe/x2JVEkD5LnmhWiQMMcYT7IY7gkdJuzJ9P14fRy28lUrlDSWYdw==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "8.7.0", - "@typescript-eslint/visitor-keys": "8.7.0", + "@typescript-eslint/types": "8.8.0", + "@typescript-eslint/visitor-keys": "8.8.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -4559,13 +4559,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.7.0.tgz", - "integrity": "sha512-b1tx0orFCCh/THWPQa2ZwWzvOeyzzp36vkJYOpVg0u8UVOIsfVrnuC9FqAw9gRKn+rG2VmWQ/zDJZzkxUnj/XQ==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.8.0.tgz", + "integrity": "sha512-8mq51Lx6Hpmd7HnA2fcHQo3YgfX1qbccxQOgZcb4tvasu//zXRaA1j5ZRFeCw/VRAdFi4mRM9DnZw0Nu0Q2d1g==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.7.0", + "@typescript-eslint/types": "8.8.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -7176,9 +7176,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.29", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.29.tgz", - "integrity": "sha512-PF8n2AlIhCKXQ+gTpiJi0VhcHDb69kYX4MtCiivctc2QD3XuNZ/XIOlbGzt7WAjjEev0TtaH6Cu3arZExm5DOw==", + "version": "1.5.30", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.30.tgz", + "integrity": "sha512-sXI35EBN4lYxzc/pIGorlymYNzDBOqkSlVRe6MkgBsW/hW1tpC/HDJ2fjG7XnjakzfLEuvdmux0Mjs6jHq4UOA==", "license": "ISC" }, "node_modules/emoji-regex": { @@ -7597,9 +7597,9 @@ } }, "node_modules/eslint-plugin-react": { - "version": "7.37.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.0.tgz", - "integrity": "sha512-IHBePmfWH5lKhJnJ7WB1V+v/GolbB0rjS8XYVCSQCZKaQCAUhMoVoOEn1Ef8Z8Wf0a7l8KTJvuZg5/e4qrZ6nA==", + "version": "7.37.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.1.tgz", + "integrity": "sha512-xwTnwDqzbDRA8uJ7BMxPs/EXRB3i8ZfnOIp8BsxEQkT0nHPp+WWceqGgo6rKb9ctNi8GJLDT4Go5HAWELa/WMg==", "dev": true, "license": "MIT", "dependencies": { diff --git a/src/components/eliza-demo/index.tsx b/src/components/eliza-demo/index.tsx index 3ae5b759..6c362523 100644 --- a/src/components/eliza-demo/index.tsx +++ b/src/components/eliza-demo/index.tsx @@ -13,11 +13,10 @@ // limitations under the License. import { ElizaService } from "@buf/connectrpc_eliza.connectrpc_es/connectrpc/eliza/v1/eliza_connect"; -import React, { useCallback, useEffect, useRef } from "react"; +import React, { useCallback, useState } from "react"; import { createPromiseClient } from "@connectrpc/connect"; import { createConnectTransport } from "@connectrpc/connect-web"; -import styles from "./styles.module.css"; -import { TerminalHeader } from "../home/examples"; +import { Terminal, Message } from "../terminal"; const host = "https://demo.connectrpc.com"; @@ -27,29 +26,43 @@ const transport = createConnectTransport({ const elizaServicePromiseClient = createPromiseClient(ElizaService, transport); -export const ElizaDemo: React.FC<{ focusOnMount?: boolean }> = ({ - focusOnMount = false, -}) => { - const callbackRef = useRef(false); - useEffect(() => { - if (callbackRef.current) { - return; - } - callbackRef.current = true; - }, []); +interface DemoProps { + focusOnMount?: boolean; +} + +export const ElizaDemo: React.FC = ({ focusOnMount = false }) => { + const [conversation, setConversation] = useState([ + { + sender: "user", + text: "Meet Eliza, our psychotherapist", + }, + { + sender: "eliza", + text: "Hello, how are you feeling?", + }, + ]); const handleCommand = useCallback( - async (str: string) => { + async (inputText: string) => { const response = await elizaServicePromiseClient.say({ - sentence: str, + sentence: inputText, }); + const updated = [ + { sender: "user", text: inputText } as Message, + { sender: "eliza", text: response.sentence } as Message, + ]; + const updatedConvo = [...conversation, ...updated]; + setConversation(updatedConvo); + return; }, - [elizaServicePromiseClient], + [elizaServicePromiseClient, conversation], ); return ( -
focus()}> - Connect-Web -
+ ); }; diff --git a/src/components/eliza-demo/styles.module.css b/src/components/eliza-demo/styles.module.css deleted file mode 100644 index b7b1ba44..00000000 --- a/src/components/eliza-demo/styles.module.css +++ /dev/null @@ -1,72 +0,0 @@ -.container > :global(.crt-terminal) { - font-family: var(--ifm-font-family-monospace); - background: #f4f5fe; - color: black; - padding-left: 40px; - padding-right: 40px; - border-radius: 2px; - box-shadow: none; - text-shadow: none; - /* 0 0 1px #42dffb, 0 0 4px #42dffb;*/ - border: none; -} - -.container > :global(.crt-terminal) ::selection { - color: black; - background: white; -} - -.container :global(.crt-cursor-symbol) { - background-color: black; -} - -.container :global(.crt-scanner) { - background: linear-gradient( - 180deg, - transparent 0, - #fffcfc 85%, - #42dffb 0, - transparent - ); -} - -.container :global(.crt-terminal__overflow-container)::-webkit-scrollbar-thumb { - border-color: white; - background-color: white; -} - -.elizaResponse { - color: var(--buf-ink-blue-02); - padding: 0 20px !important; -} - -.container { - height: 240px; - position: relative; -} - -.container :global(.crt-command-line) { - padding: 10px 0; -} - -.fakeBrowserBar { - background-color: var(--buf-grey-01); - border-radius: 4px; - width: 50%; - padding: 4px 10px; - display: flex; - color: var(--buf-ink-blue-03); - gap: 6px; -} - -.prefix { - color: var(--buf-grey-03); -} - -@media screen and (max-width: 966px) { - .container > :global(.crt-terminal) { - padding-left: 20px; - padding-right: 20px; - font-size: 14px; - } -} diff --git a/src/components/home/examples.module.css b/src/components/home/examples.module.css index f52f552d..ee3d6f3d 100644 --- a/src/components/home/examples.module.css +++ b/src/components/home/examples.module.css @@ -58,47 +58,6 @@ align-items: center; } -.terminalHeaderWrapper { - display: flex; - border-bottom: 1px solid #cbcbde; - height: 40px; - justify-content: flex-start; - align-items: center; - padding-left: 14px; - padding-right: 14px; - background-color: #f4f5fe; - width: 100%; - border-top-left-radius: 2px; - border-top-right-radius: 2px; -} - -.terminalHeaderFakeButtons { - display: flex; - gap: 8px; - position: absolute; -} - -.terminalHeaderFakeButton { - width: 12px; - height: 12px; - border-radius: 50%; - border: 1px solid #cbcbde; -} - -.terminalHeaderText { - color: #9699b6; - font-family: var(--buf-mono-font); - text-transform: uppercase; - font-weight: 400; - font-size: 14px; - line-height: 18px; - text-align: center; - letter-spacing: 0.08em; - flex: 1 1 auto; - display: flex; - justify-content: center; -} - .codeFooter { padding-top: var(--ifm-pre-padding); padding-right: var(--ifm-pre-padding); diff --git a/src/components/home/examples.tsx b/src/components/home/examples.tsx index 551f17f5..bfe4cd96 100644 --- a/src/components/home/examples.tsx +++ b/src/components/home/examples.tsx @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +import React, { useEffect, useState } from "react"; import clsx from "clsx"; -import React, { PropsWithChildren, useEffect, useState } from "react"; import classes from "./examples.module.css"; import codeBlockStyles from "@site/src/theme/CodeBlock/styles.module.css"; import { @@ -32,6 +32,7 @@ import { Highlight } from "prism-react-renderer"; import Translate, { translate } from "@docusaurus/Translate"; import Tooltip from "../tooltip"; import { ElizaDemo } from "../eliza-demo"; +import { TerminalHeader } from "../terminal"; const plainHttpTerminalContent = ` $ curl \\ @@ -315,21 +316,3 @@ function CodeBlock({ ); } - -type TerminalHeaderProps = { - children: React.ReactNode; -}; -export const TerminalHeader: React.FC = ({ - children, -}: PropsWithChildren) => { - return ( -
-
-
-
-
-
-
{children}
-
- ); -}; diff --git a/src/components/terminal/index.tsx b/src/components/terminal/index.tsx new file mode 100644 index 00000000..68605595 --- /dev/null +++ b/src/components/terminal/index.tsx @@ -0,0 +1,15 @@ +// Copyright 2022-2023 The Connect Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +export * from "./terminal"; diff --git a/src/components/terminal/styles.module.css b/src/components/terminal/styles.module.css new file mode 100644 index 00000000..76d8a0e8 --- /dev/null +++ b/src/components/terminal/styles.module.css @@ -0,0 +1,119 @@ +.terminalHeaderWrapper { + display: flex; + border-bottom: 1px solid #cbcbde; + height: 40px; + justify-content: flex-start; + align-items: center; + padding-left: 14px; + padding-right: 14px; + background-color: #f4f5fe; + width: 100%; + border-top-left-radius: 2px; + border-top-right-radius: 2px; +} + +.terminalHeaderFakeButtons { + display: flex; + gap: 8px; + position: absolute; +} + +.terminalHeaderFakeButton { + width: 12px; + height: 12px; + border-radius: 50%; + border: 1px solid #cbcbde; +} + +.terminalHeaderText { + color: #9699b6; + font-family: var(--buf-mono-font); + text-transform: uppercase; + font-weight: 400; + font-size: 14px; + line-height: 18px; + text-align: center; + letter-spacing: 0.08em; + flex: 1 1 auto; + display: flex; + justify-content: center; +} + +.terminalContainer { + font-family: var(--ifm-font-family-monospace); + background: #f4f5fe; + color: black; + box-shadow: none; + text-shadow: none; + height: 300px; + margin-bottom: 15px; +} +.terminal { + padding: 25px 40px; +} +.terminalContainer p { + margin: 0; + padding: 5px 0; +} +.terminalBody { + color: black; + padding: 20px; + background: #f4f5fe; + height: 100%; +} +.terminalOverflow { + overflow: auto; + height: 100%; +} +.inputElement { + opacity: 0; + position: absolute; +} +.spacer::after { + margin-right: 7px; + content: ">"; +} +.prompt { + margin-top: 7px; + display: flex; + flex: 1 1 auto; + width: 100%; + align-items: center; +} +.elizaText { + color: var(--buf-ink-blue-02); + white-space: nowrap; + overflow: hidden; + width: 100%; + animation: linearwipe 500ms steps(60, end); +} +.elizaText .spacer { + visibility: hidden; +} +.userText { + font-weight: 400; + color: black; +} +.blinkingCursor { + height: 20px; + width: 10px; + background-color: #111010; + animation: blink 1s step-start 0s infinite; + -webkit-animation: 1s blink step-end infinite; + -moz-animation: 1s blink step-end infinite; + -ms-animation: 1s blink step-end infinite; + -o-animation: 1s blink step-end infinite; + animation: 1s blink step-end infinite; +} + +@keyframes blink { + 50% { + opacity: 0; + } +} + +@keyframes linearwipe { + from { + width: 0; + } +} diff --git a/src/components/terminal/terminal.tsx b/src/components/terminal/terminal.tsx new file mode 100644 index 00000000..2f9e1f64 --- /dev/null +++ b/src/components/terminal/terminal.tsx @@ -0,0 +1,144 @@ +// Copyright 2022-2023 The Connect Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import React, { + ChangeEvent, + KeyboardEvent, + PropsWithChildren, + useEffect, + useRef, + useState, +} from "react"; +import clsx from "clsx"; +import styles from "./styles.module.css"; + +interface TerminalProps { + conversation: Message[]; + handleCommand: (str: string) => Promise; + focusOnMount: boolean; +} + +export interface Message { + text: string; + sender: "eliza" | "user"; +} + +type TerminalHeaderProps = { + children: React.ReactNode; +}; +export const TerminalHeader: React.FC = ({ + children, +}: PropsWithChildren) => { + return ( +
+
+
+
+
+
+
{children}
+
+ ); +}; + +export const Terminal: React.FC = ({ + conversation, + handleCommand, + focusOnMount = false, +}) => { + const [inputText, setInputText] = useState(""); + + // Ref for the terminal scroll container + const terminalRef = useRef(null); + // Ref for the hidden input + const inputRef = useRef(null); + + // Focuses the hidden input + const handleTerminalFocus = () => { + inputRef.current.focus(); + }; + + // Handler for typing into the terminal into the hidden input element + const handleInputChange = (e: ChangeEvent) => { + setInputText(e.target.value); + }; + + // Handler for pressing Enter key + const handleKeyPress = async (event: KeyboardEvent) => { + if (event.key === "Enter") { + await handleCommand(inputText); + setInputText(""); + } + }; + + // If focusOnMount is true, focus the terminal input when the component mounts + useEffect(() => { + if (focusOnMount) { + handleTerminalFocus(); + } + }, []); + + useEffect(() => { + // If the terminal scroll container has a scroll visibile, scroll to the bottom + if (terminalRef.current.scrollHeight > terminalRef.current.clientHeight) { + terminalRef.current?.scrollTo(0, terminalRef.current?.scrollHeight); + } + }, [conversation]); + + return ( +
+ Connect-Web +
+
+ {conversation.map((msg, i) => { + const key = `text${i}`; + if (msg.sender === "user") { + return ( +

+ + {msg.text} +

+ ); + } + return ( +

+ Eliza: {msg.text} +

+ ); + })} +
+ + + {inputText.split("").map((letter, i) => { + return ( + + {/* If the current letter is a space, then add a Unicode space */} + {letter === " " ? "\u00A0" : letter} + + ); + })} +
+
+
+
+
+ ); +}; diff --git a/swizzling.md b/swizzling.md index b50cfd77..6862ff64 100644 --- a/swizzling.md +++ b/swizzling.md @@ -34,20 +34,6 @@ components in [`src/theme`](./src/theme) and fully custom components in - All text for the front page is defined in [`src/components/home/text.tsx`](./src/components/home/text.tsx) -## Vendored libraries - -We've vendored out `crt-terminal` in order to fix a focus issue on mount. We -have added the prop `focusOnMount` to the `Terminal` component. - -In order to rebuild the package: - -```bash -cd src/vendor/crt-terminal -npm install -npm run build -rm -rf node_modules -``` - [docusaurus]: https://docusaurus.io [swizzling]: https://docusaurus.io/docs/swizzling diff --git a/tsconfig.json b/tsconfig.json index a8cb11c5..68af32db 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,6 +3,7 @@ "extends": "@tsconfig/docusaurus/tsconfig.json", "compilerOptions": { "jsx": "react", - "baseUrl": "." + "baseUrl": ".", + "esModuleInterop": true } }