From 95363a5b52f3bf73531ac76b00178fa79ca97661 Mon Sep 17 00:00:00 2001
From: Nate Sesti <33237525+sestinj@users.noreply.github.com>
Date: Thu, 28 Sep 2023 01:02:52 -0700
Subject: Past input (#513)

* feat: :construction: use ComboBox in place of UserInputContainer

* feat: :construction: adding context to previous inputs steps

* feat: :sparkles: preview context items on click

* feat: :construction: more work on context items ui

* style: :construction: working out the details of ctx item buttons

* feat: :sparkles: getting the final details

* fix: :bug: fix height of ctx items bar

* fix: :bug: last couple of details

* fix: :bug: pass model param through to hf inference api

* fix: :loud_sound: better logging for timeout

* feat: :sparkles: option to set the meilisearch url

* fix: :bug: fix height of past inputs
---
 extension/react-app/src/components/PillButton.tsx | 257 +++++++++++++---------
 1 file changed, 148 insertions(+), 109 deletions(-)

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

diff --git a/extension/react-app/src/components/PillButton.tsx b/extension/react-app/src/components/PillButton.tsx
index fb685a82..063572b5 100644
--- a/extension/react-app/src/components/PillButton.tsx
+++ b/extension/react-app/src/components/PillButton.tsx
@@ -1,23 +1,23 @@
-import { useContext, useEffect, useState } from "react";
+import { useContext, useEffect, useRef, useState } from "react";
 import styled from "styled-components";
 import {
   StyledTooltip,
   defaultBorderRadius,
   lightGray,
   secondaryDark,
-  vscBackground,
   vscForeground,
 } from ".";
 import {
   TrashIcon,
   PaintBrushIcon,
   ExclamationTriangleIcon,
+  EyeIcon,
 } from "@heroicons/react/24/outline";
 import { GUIClientContext } from "../App";
 import { useDispatch } from "react-redux";
-import { setBottomMessage } from "../redux/slices/uiStateSlice";
 import { ContextItem } from "../../../schema/FullState";
 import { getFontSize } from "../util";
+import HeaderButtonWithText from "./HeaderButtonWithText";
 
 const Button = styled.button<{ fontSize?: number }>`
   border: none;
@@ -80,7 +80,13 @@ interface PillButtonProps {
   editingAny: boolean;
   index: number;
   areMultipleItems?: boolean;
-  onDelete?: () => void;
+  onDelete?: (index?: number) => void;
+  onClick?: (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;
+  stepIndex?: number;
+  previewing?: boolean;
+  toggleViewContent?: () => void;
+  onBlur?: () => void;
+  focusing?: boolean;
 }
 
 interface StyledButtonProps {
@@ -88,6 +94,14 @@ interface StyledButtonProps {
   editing?: boolean;
 }
 
+const Container = styled.div<{ previewing?: boolean }>`
+  border-radius: ${defaultBorderRadius};
+  background-color: ${secondaryDark};
+  display: flex;
+  align-items: center;
+  justify-content: center;
+`;
+
 const StyledButton = styled(Button)<StyledButtonProps>`
   position: relative;
   border-color: ${(props) => props.borderColor || "transparent"};
@@ -96,12 +110,34 @@ const StyledButton = styled(Button)<StyledButtonProps>`
 
   &:focus {
     outline: none;
-    border-color: ${lightGray};
-    border-width: 1px;
-    border-style: solid;
+    /* border-color: ${lightGray}; */
+    text-decoration: underline;
+  }
+`;
+
+const HoverableInsidePillButton = styled(HeaderButtonWithText)<{
+  color: string;
+}>`
+  &:hover {
+    background-color: ${(props) => props.color};
   }
 `;
 
+const ClickableInsidePillButton = styled(HeaderButtonWithText)<{
+  color: string;
+  selected: boolean;
+}>`
+  ${(props) =>
+    props.selected &&
+    `
+    background-color: ${props.color};
+    
+    &:hover {
+      background-color: ${props.color};
+    }
+  `}
+`;
+
 const PillButton = (props: PillButtonProps) => {
   const [isHovered, setIsHovered] = useState(false);
   const client = useContext(GUIClientContext);
@@ -116,122 +152,125 @@ const PillButton = (props: PillButtonProps) => {
     }
   }, [props.editing, props.item]);
 
-  const dispatch = useDispatch();
+  const pillContainerRef = useRef<HTMLDivElement>(null);
+  const buttonRef = useRef<HTMLButtonElement>(null);
 
   return (
     <div style={{ position: "relative" }}>
-      <StyledButton
-        fontSize={getFontSize()}
-        borderColor={props.editing ? (warning ? "red" : undefined) : undefined}
-        onMouseEnter={() => {
-          setIsHovered(true);
-          if (props.onHover) {
-            props.onHover(true);
+      <Container previewing={props.previewing} ref={pillContainerRef}>
+        <StyledButton
+          fontSize={getFontSize()}
+          borderColor={
+            props.editing ? (warning ? "red" : undefined) : undefined
           }
-        }}
-        onMouseLeave={() => {
-          setIsHovered(false);
-          if (props.onHover) {
-            props.onHover(false);
-          }
-        }}
-        className="pill-button"
-        onKeyDown={(e) => {
-          if (e.key === "Backspace") {
-            props.onDelete?.();
-          }
-        }}
-      >
-        {isHovered && (
-          <GridDiv
-            style={{
-              gridTemplateColumns:
-                props.item.editable &&
-                props.areMultipleItems &&
-                props.editingAny
-                  ? "1fr 1fr"
-                  : "1fr",
-              backgroundColor: vscBackground,
-            }}
-          >
-            {props.editingAny &&
-              props.item.editable &&
-              props.areMultipleItems && (
-                <ButtonDiv
-                  data-tooltip-id={`edit-${props.index}`}
-                  backgroundColor={"#8800aa55"}
-                  onClick={() => {
-                    client?.setEditingAtIds([
-                      props.item.description.id.item_id,
-                    ]);
-                  }}
-                >
-                  <PaintBrushIcon style={{ margin: "auto" }} width="1.6em" />
-                </ButtonDiv>
-              )}
-
-            <StyledTooltip id={`pin-${props.index}`}>
-              Edit this range
-            </StyledTooltip>
-            <ButtonDiv
-              data-tooltip-id={`delete-${props.index}`}
-              backgroundColor={"#cc000055"}
+          ref={buttonRef}
+          onMouseEnter={() => {
+            setIsHovered(true);
+            if (props.onHover) {
+              props.onHover(true);
+            }
+          }}
+          onMouseLeave={() => {
+            setIsHovered(false);
+            if (props.onHover) {
+              props.onHover(false);
+            }
+          }}
+          className={`pill-button-${props.stepIndex || "main"}`}
+          onKeyDown={(e) => {
+            if (e.key === "Backspace") {
+              props.onDelete?.(props.stepIndex);
+            } else if (e.key === "v") {
+              props.toggleViewContent?.();
+            } else if (e.key === "e") {
+              client?.setEditingAtIds([props.item.description.id.item_id]);
+            }
+          }}
+          onClick={(e) => {
+            props.onClick?.(e);
+          }}
+          onBlur={(e) => {
+            if (!pillContainerRef.current?.contains(e.relatedTarget as any)) {
+              props.onBlur?.();
+            } else {
+              e.preventDefault();
+              buttonRef.current?.focus();
+            }
+          }}
+        >
+          <span className={isHovered ? "underline" : ""}>
+            {props.item.description.name}
+          </span>
+        </StyledButton>
+        {((props.focusing && props.item.editable && props.editingAny) ||
+          props.editing) && (
+          <>
+            <ClickableInsidePillButton
+              data-tooltip-id={`circle-div-${props.item.description.name}`}
+              text={
+                props.editing ? "Editing this range" : "Edit this range (e)"
+              }
               onClick={() => {
-                client?.deleteContextWithIds([props.item.description.id]);
-                dispatch(setBottomMessage(undefined));
+                if (!props.editing) {
+                  client?.setEditingAtIds([props.item.description.id.item_id]);
+                }
               }}
+              tabIndex={-1}
+              color="#f0f4"
+              selected={props.editing}
             >
-              <TrashIcon style={{ margin: "auto" }} width="1.6em" />
-            </ButtonDiv>
-          </GridDiv>
+              <PaintBrushIcon width="1.4em" height="1.4em" />
+            </ClickableInsidePillButton>
+            <StyledTooltip id={`circle-div-${props.item.description.name}`}>
+              Editing this range
+            </StyledTooltip>
+          </>
+        )}
+        {(props.focusing || props.previewing) && (
+          <ClickableInsidePillButton
+            text="View (v)"
+            onClick={() => props.toggleViewContent?.()}
+            tabIndex={-1}
+            color="#ff04"
+            selected={props.previewing || false}
+          >
+            <EyeIcon width="1.4em" height="1.4em" />
+          </ClickableInsidePillButton>
+        )}
+        {props.focusing && (
+          <HoverableInsidePillButton
+            text="Delete (⌫)"
+            onClick={() => props.onDelete?.(props.stepIndex)}
+            tabIndex={-1}
+            color="#f004"
+          >
+            <TrashIcon width="1.4em" height="1.4em" />
+          </HoverableInsidePillButton>
         )}
-        {props.item.description.name}
-      </StyledButton>
+      </Container>
       <StyledTooltip id={`edit-${props.index}`}>
         {props.item.editing
           ? "Editing this section (with entire file as context)"
           : "Edit this section"}
       </StyledTooltip>
       <StyledTooltip id={`delete-${props.index}`}>Delete</StyledTooltip>
-      {props.editing &&
-        (warning ? (
-          <>
-            <CircleDiv
-              data-tooltip-id={`circle-div-${props.item.description.name}`}
-              className="z-10"
-            >
-              <ExclamationTriangleIcon
-                style={{ margin: "auto" }}
-                width="1.0em"
-                strokeWidth={2}
-              />
-            </CircleDiv>
-            <StyledTooltip id={`circle-div-${props.item.description.name}`}>
-              {warning}
-            </StyledTooltip>
-          </>
-        ) : (
-          <>
-            <CircleDiv
-              data-tooltip-id={`circle-div-${props.item.description.name}`}
-              style={{
-                backgroundColor: "#8800aa55",
-                border: `0.5px solid ${lightGray}`,
-                padding: "1px",
-                zIndex: 1,
-              }}
-            >
-              <PaintBrushIcon
-                style={{ margin: "auto" }}
-                width="1.0em"
-                strokeWidth={2}
-              />
-            </CircleDiv>
-            <StyledTooltip id={`circle-div-${props.item.description.name}`}>
-              Editing this range
-            </StyledTooltip>
-          </>
-        ))}
+      {props.editing && warning && (
+        <>
+          <CircleDiv
+            data-tooltip-id={`circle-div-${props.item.description.name}`}
+            className="z-10"
+          >
+            <ExclamationTriangleIcon
+              style={{ margin: "auto" }}
+              width="1.0em"
+              strokeWidth={2}
+            />
+          </CircleDiv>
+          <StyledTooltip id={`circle-div-${props.item.description.name}`}>
+            {warning}
+          </StyledTooltip>
+        </>
+      )}
     </div>
   );
 };
-- 
cgit v1.2.3-70-g09d2

