summaryrefslogtreecommitdiff
path: root/extension/react-app/src/components/UserInputContainer.tsx
diff options
context:
space:
mode:
authorNate Sesti <sestinj@gmail.com>2023-08-17 22:19:55 -0700
committerNate Sesti <sestinj@gmail.com>2023-08-17 22:19:55 -0700
commitc6a3d8add014ddfe08c62b3ccb1b01dbc47495f5 (patch)
tree0bb5bb11cf185a575df520908078d310775f4a7c /extension/react-app/src/components/UserInputContainer.tsx
parent98047dc32a5bfa525eff7089b2ac020ce761f9a9 (diff)
downloadsncontinue-c6a3d8add014ddfe08c62b3ccb1b01dbc47495f5.tar.gz
sncontinue-c6a3d8add014ddfe08c62b3ccb1b01dbc47495f5.tar.bz2
sncontinue-c6a3d8add014ddfe08c62b3ccb1b01dbc47495f5.zip
feat: :sparkles: edit previous inputs
Diffstat (limited to 'extension/react-app/src/components/UserInputContainer.tsx')
-rw-r--r--extension/react-app/src/components/UserInputContainer.tsx147
1 files changed, 128 insertions, 19 deletions
diff --git a/extension/react-app/src/components/UserInputContainer.tsx b/extension/react-app/src/components/UserInputContainer.tsx
index 90cd549b..9784a615 100644
--- a/extension/react-app/src/components/UserInputContainer.tsx
+++ b/extension/react-app/src/components/UserInputContainer.tsx
@@ -1,16 +1,24 @@
-import React, { useState } from "react";
+import React, { useContext, useEffect, useRef, useState } from "react";
import ReactMarkdown from "react-markdown";
import styled from "styled-components";
-import { defaultBorderRadius, secondaryDark, vscBackground } from ".";
+import {
+ defaultBorderRadius,
+ secondaryDark,
+ vscBackground,
+ vscForeground,
+} from ".";
import HeaderButtonWithText from "./HeaderButtonWithText";
-import { XMarkIcon } from "@heroicons/react/24/outline";
+import { XMarkIcon, PencilIcon, CheckIcon } from "@heroicons/react/24/outline";
import { HistoryNode } from "../../../schema/HistoryNode";
import StyledMarkdownPreview from "./StyledMarkdownPreview";
+import { GUIClientContext } from "../App";
+import { text } from "stream/consumers";
interface UserInputContainerProps {
onDelete: () => void;
children: string;
historyNode: HistoryNode;
+ index: number;
}
const StyledDiv = styled.div`
@@ -40,8 +48,69 @@ const StyledPre = styled.pre`
font-size: 13px;
`;
+const TextArea = styled.textarea`
+ margin: 8px;
+ margin-right: 22px;
+ padding: 8px;
+ white-space: pre-wrap;
+ word-wrap: break-word;
+ font-family: "Lexend", sans-serif;
+ font-size: 13px;
+ width: 100%;
+ border-radius: ${defaultBorderRadius};
+ height: 100%;
+ border: none;
+ background-color: ${vscBackground};
+ resize: none;
+ outline: none;
+ border: none;
+ color: ${vscForeground};
+
+ &:focus {
+ border: none;
+ outline: none;
+ }
+`;
+
const UserInputContainer = (props: UserInputContainerProps) => {
const [isHovered, setIsHovered] = useState(false);
+ const [isEditing, setIsEditing] = useState(false);
+
+ const textAreaRef = useRef<HTMLTextAreaElement>(null);
+ const client = useContext(GUIClientContext);
+
+ useEffect(() => {
+ if (isEditing) {
+ textAreaRef.current?.focus();
+ // Select all text
+ textAreaRef.current?.setSelectionRange(
+ 0,
+ textAreaRef.current.value.length
+ );
+ }
+ }, [isEditing]);
+
+ useEffect(() => {
+ const handleKeyDown = (event: KeyboardEvent) => {
+ if (event.key === "Escape") {
+ setIsEditing(false);
+ }
+ };
+ document.addEventListener("keydown", handleKeyDown);
+ return () => {
+ document.removeEventListener("keydown", handleKeyDown);
+ };
+ }, []);
+
+ const doneEditing = (e: any) => {
+ if (!textAreaRef.current?.value) {
+ return;
+ }
+ client?.editStepAtIndex(textAreaRef.current.value, props.index);
+ setIsEditing(false);
+ e.stopPropagation();
+ };
+
return (
<StyledDiv
onMouseEnter={() => {
@@ -51,24 +120,64 @@ const UserInputContainer = (props: UserInputContainerProps) => {
setIsHovered(false);
}}
>
- {/* <StyledMarkdownPreview
- light={true}
- source={props.children}
- className="mr-6"
- /> */}
- <StyledPre className="mr-6">{props.children}</StyledPre>
+ {isEditing ? (
+ <TextArea
+ ref={textAreaRef}
+ onKeyDown={(e) => {
+ if (e.key === "Enter" && !e.shiftKey) {
+ e.preventDefault();
+ doneEditing(e);
+ }
+ }}
+ defaultValue={props.children}
+ />
+ ) : (
+ <StyledPre
+ onClick={() => {
+ setIsEditing(true);
+ }}
+ className="mr-6 cursor-text w-full"
+ >
+ {props.children}
+ </StyledPre>
+ )}
{/* <ReactMarkdown children={props.children} className="w-fit mr-10" /> */}
<DeleteButtonDiv>
- {isHovered && (
- <HeaderButtonWithText
- onClick={(e) => {
- props.onDelete();
- e.stopPropagation();
- }}
- text="Delete"
- >
- <XMarkIcon width="1.4em" height="1.4em" />
- </HeaderButtonWithText>
+ {(isHovered || isEditing) && (
+ <div className="flex">
+ {isEditing ? (
+ <HeaderButtonWithText
+ onClick={(e) => {
+ doneEditing(e);
+ }}
+ text="Done"
+ >
+ <CheckIcon width="1.4em" height="1.4em" />
+ </HeaderButtonWithText>
+ ) : (
+ <>
+ <HeaderButtonWithText
+ onClick={(e) => {
+ setIsEditing((prev) => !prev);
+ e.stopPropagation();
+ }}
+ text="Edit"
+ >
+ <PencilIcon width="1.4em" height="1.4em" />
+ </HeaderButtonWithText>
+
+ <HeaderButtonWithText
+ onClick={(e) => {
+ props.onDelete();
+ e.stopPropagation();
+ }}
+ text="Delete"
+ >
+ <XMarkIcon width="1.4em" height="1.4em" />
+ </HeaderButtonWithText>
+ </>
+ )}
+ </div>
)}
</DeleteButtonDiv>
</StyledDiv>