From c6a3d8add014ddfe08c62b3ccb1b01dbc47495f5 Mon Sep 17 00:00:00 2001
From: Nate Sesti <sestinj@gmail.com>
Date: Thu, 17 Aug 2023 22:19:55 -0700
Subject: feat: :sparkles: edit previous inputs

---
 .../src/components/UserInputContainer.tsx          | 147 ++++++++++++++++++---
 1 file changed, 128 insertions(+), 19 deletions(-)

(limited to 'extension/react-app/src/components/UserInputContainer.tsx')

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>
-- 
cgit v1.2.3-70-g09d2

