diff options
| author | Nate Sesti <33237525+sestinj@users.noreply.github.com> | 2023-06-12 21:36:11 -0700 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-06-12 21:36:11 -0700 | 
| commit | 297511b5e3ba67e3c37e5cb4c038186093da6a95 (patch) | |
| tree | c850a433c3a7d594fdeabf11cabd505bb5388d40 /extension/react-app/src/components | |
| parent | 52ffaa321ee24d2a930ac4e6ff083aaa37be79e8 (diff) | |
| parent | 01cfbc179a33c99d55acdc989dbafd554db16a92 (diff) | |
| download | sncontinue-297511b5e3ba67e3c37e5cb4c038186093da6a95.tar.gz sncontinue-297511b5e3ba67e3c37e5cb4c038186093da6a95.tar.bz2 sncontinue-297511b5e3ba67e3c37e5cb4c038186093da6a95.zip | |
Merge pull request #76 from continuedev/superset-of-chat
Superset of chat
Diffstat (limited to 'extension/react-app/src/components')
| -rw-r--r-- | extension/react-app/src/components/CodeBlock.tsx | 1 | ||||
| -rw-r--r-- | extension/react-app/src/components/ComboBox.tsx | 146 | ||||
| -rw-r--r-- | extension/react-app/src/components/StepContainer.tsx | 67 | ||||
| -rw-r--r-- | extension/react-app/src/components/index.ts | 18 | 
4 files changed, 209 insertions, 23 deletions
| diff --git a/extension/react-app/src/components/CodeBlock.tsx b/extension/react-app/src/components/CodeBlock.tsx index e0336554..eedae3fb 100644 --- a/extension/react-app/src/components/CodeBlock.tsx +++ b/extension/react-app/src/components/CodeBlock.tsx @@ -11,6 +11,7 @@ const StyledPre = styled.pre`    border: 1px solid gray;    border-radius: ${defaultBorderRadius};    background-color: ${vscBackground}; +  padding: 8px;  `;  const StyledCode = styled.code` diff --git a/extension/react-app/src/components/ComboBox.tsx b/extension/react-app/src/components/ComboBox.tsx new file mode 100644 index 00000000..1b7c60e6 --- /dev/null +++ b/extension/react-app/src/components/ComboBox.tsx @@ -0,0 +1,146 @@ +import React, { useCallback } from "react"; +import { useCombobox } from "downshift"; +import styled from "styled-components"; +import { +  buttonColor, +  defaultBorderRadius, +  secondaryDark, +  vscBackground, +} from "."; + +const mainInputFontSize = 16; +const MainTextInput = styled.input` +  padding: 8px; +  font-size: ${mainInputFontSize}px; +  border-radius: ${defaultBorderRadius}; +  border: 1px solid #ccc; +  margin: 8px auto; +  width: 100%; +  background-color: ${vscBackground}; +  color: white; +  outline: 1px solid orange; +`; + +const UlMaxHeight = 200; +const Ul = styled.ul<{ +  hidden: boolean; +  showAbove: boolean; +  ulHeightPixels: number; +}>` +  ${(props) => +    props.showAbove +      ? `transform: translateY(-${props.ulHeightPixels + 8}px);` +      : `transform: translateY(${2 * mainInputFontSize}px);`} +  position: absolute; +  background: ${vscBackground}; +  background-color: ${secondaryDark}; +  color: white; +  font-family: "Fira Code", monospace; +  max-height: ${UlMaxHeight}px; +  overflow: scroll; +  padding: 0; +  ${({ hidden }) => hidden && "display: none;"} +  border-radius: ${defaultBorderRadius}; +  overflow: hidden; +  border: 0.5px solid gray; +`; + +const Li = styled.li<{ +  highlighted: boolean; +  selected: boolean; +  isLastItem: boolean; +}>` +  ${({ highlighted }) => highlighted && "background: #aa0000;"} +  ${({ selected }) => selected && "font-weight: bold;"} +    padding: 0.5rem 0.75rem; +  display: flex; +  flex-direction: column; +  ${({ isLastItem }) => isLastItem && "border-bottom: 1px solid gray;"} +  border-top: 1px solid gray; +  cursor: pointer; +`; + +interface ComboBoxProps { +  items: { name: string; description: string }[]; +  onInputValueChange: (inputValue: string) => void; +  disabled?: boolean; +  onEnter?: (e: React.KeyboardEvent<HTMLInputElement>) => void; +} + +const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => { +  const [items, setItems] = React.useState(props.items); +  const { +    isOpen, +    getToggleButtonProps, +    getLabelProps, +    getMenuProps, +    getInputProps, +    highlightedIndex, +    getItemProps, +    selectedItem, +    setInputValue, +  } = useCombobox({ +    onInputValueChange({ inputValue }) { +      if (!inputValue) return; +      props.onInputValueChange(inputValue); +      setItems( +        props.items.filter((item) => +          item.name.toLowerCase().startsWith(inputValue.toLowerCase()) +        ) +      ); +    }, +    items, +    itemToString(item) { +      return item ? item.name : ""; +    }, +  }); + +  const divRef = React.useRef<HTMLDivElement>(null); +  const ulRef = React.useRef<HTMLUListElement>(null); +  const showAbove = () => { +    return (divRef.current?.getBoundingClientRect().top || 0) > UlMaxHeight; +  }; + +  return ( +    <div className="flex px-2" ref={divRef} hidden={!isOpen}> +      <MainTextInput +        disabled={props.disabled} +        placeholder="Ask anything:" +        {...getInputProps({ +          onKeyDown: (event) => { +            if (event.key === "Enter" && (!isOpen || items.length === 0)) { +              // Prevent Downshift's default 'Enter' behavior. +              (event.nativeEvent as any).preventDownshiftDefault = true; +              if (props.onEnter) props.onEnter(event); +              setInputValue(""); +            } +          }, +          ref: ref as any, +        })} +      /> +      <Ul +        {...getMenuProps({ +          ref: ulRef, +        })} +        showAbove={showAbove()} +        ulHeightPixels={ulRef.current?.getBoundingClientRect().height || 0} +      > +        {isOpen && +          items.map((item, index) => ( +            <Li +              key={`${item.name}${index}`} +              {...getItemProps({ item, index })} +              highlighted={highlightedIndex === index} +              selected={selectedItem === item} +            > +              <span> +                {item.name}: {item.description} +              </span> +            </Li> +          ))} +      </Ul> +    </div> +  ); +}); + +export default ComboBox; diff --git a/extension/react-app/src/components/StepContainer.tsx b/extension/react-app/src/components/StepContainer.tsx index 3408053b..ca142b06 100644 --- a/extension/react-app/src/components/StepContainer.tsx +++ b/extension/react-app/src/components/StepContainer.tsx @@ -7,6 +7,7 @@ import {    vscBackground,    GradientBorder,    vscBackgroundTransparent, +  HeaderButton,  } from ".";  import { RangeInFile, FileEdit } from "../../../src/client";  import CodeBlock from "./CodeBlock"; @@ -15,7 +16,7 @@ import SubContainer from "./SubContainer";  import {    ChevronDown,    ChevronRight, -  Backward, +  XMark,    ArrowPath,  } from "@styled-icons/heroicons-outline";  import { HistoryNode } from "../../../schema/HistoryNode"; @@ -31,6 +32,7 @@ interface StepContainerProps {    onRefinement: (input: string) => void;    onUserInput: (input: string) => void;    onRetry: () => void; +  onDelete: () => void;    open?: boolean;  } @@ -54,8 +56,10 @@ const HeaderDiv = styled.div<{ error: boolean }>`    background-color: ${(props) =>      props.error ? "#522" : vscBackgroundTransparent};    display: grid; -  grid-template-columns: 1fr auto; +  grid-template-columns: 1fr auto auto; +  grid-gap: 8px;    align-items: center; +  padding-right: 8px;  `;  const ContentDiv = styled.div` @@ -64,26 +68,21 @@ const ContentDiv = styled.div`    background-color: ${vscBackground};  `; -const HeaderButton = styled.button` -  background-color: transparent; -  border: 1px solid white; -  border-radius: ${defaultBorderRadius}; -  padding: 2px; -  cursor: pointer; -  color: white; - -  &:hover { -    background-color: white; -    color: black; -  } -`; -  const OnHoverDiv = styled.div`    text-align: center;    padding: 10px;    animation: ${appear} 0.3s ease-in-out;  `; +const MarkdownPre = styled.pre` +  background-color: ${secondaryDark}; +  padding: 10px; +  border-radius: ${defaultBorderRadius}; +  border: 0.5px solid white; +`; + +const MarkdownCode = styled.code``; +  function StepContainer(props: StepContainerProps) {    const [open, setOpen] = useState(      typeof props.open === "undefined" ? true : props.open @@ -152,18 +151,28 @@ function StepContainer(props: StepContainerProps) {                <Backward size="1.6em" onClick={props.onReverse}></Backward>              </HeaderButton> */} -            {props.historyNode.observation?.error ? ( +            <>                <HeaderButton                  onClick={(e) => {                    e.stopPropagation(); -                  props.onRetry(); +                  props.onDelete();                  }}                > -                <ArrowPath size="1.6em" onClick={props.onRetry}></ArrowPath> +                <XMark size="1.6em" onClick={props.onDelete} />                </HeaderButton> -            ) : ( -              <></> -            )} +              {props.historyNode.observation?.error ? ( +                <HeaderButton +                  onClick={(e) => { +                    e.stopPropagation(); +                    props.onRetry(); +                  }} +                > +                  <ArrowPath size="1.6em" onClick={props.onRetry} /> +                </HeaderButton> +              ) : ( +                <></> +              )} +            </>            </HeaderDiv>          </GradientBorder>          <ContentDiv hidden={!open}> @@ -182,7 +191,19 @@ function StepContainer(props: StepContainerProps) {                {props.historyNode.observation.error as string}              </pre>            ) : ( -            <ReactMarkdown key={1} className="overflow-scroll"> +            <ReactMarkdown +              key={1} +              className="overflow-scroll" +              components={{ +                pre: ({ node, ...props }) => { +                  return ( +                    <CodeBlock +                      children={props.children[0] as string} +                    ></CodeBlock> +                  ); +                }, +              }} +            >                {props.historyNode.step.description as any}              </ReactMarkdown>            )} diff --git a/extension/react-app/src/components/index.ts b/extension/react-app/src/components/index.ts index 4966f3e8..525989af 100644 --- a/extension/react-app/src/components/index.ts +++ b/extension/react-app/src/components/index.ts @@ -143,3 +143,21 @@ export const appear = keyframes`          transform: translateY(0px);      }  `; + +export const HeaderButton = styled.button` +  background-color: transparent; +  border: 1px solid white; +  border-radius: ${defaultBorderRadius}; +  cursor: pointer; +  color: white; + +  &:hover { +    background-color: white; +    color: black; +  } +  display: flex; +  align-items: center; +  justify-content: center; +  gap: 4px; +  padding: 1px; +`; | 
