Skip to content

Commit

Permalink
proper md editor
Browse files Browse the repository at this point in the history
  • Loading branch information
bracesproul committed Oct 8, 2024
1 parent 20c9bb1 commit 7a6fea3
Show file tree
Hide file tree
Showing 8 changed files with 111 additions and 68 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"lucide-react": "^0.441.0",
"next": "14.2.7",
"react": "^18",
"react-contenteditable": "^3.3.7",
"react-dom": "^18",
"react-json-view": "^1.21.3",
"react-markdown": "^9.0.1",
Expand Down
2 changes: 1 addition & 1 deletion src/app/api/[..._path]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ async function handleRequest(req: NextRequest, method: string) {
options.body = await req.text();
}

const apiUrl = process.env.LANGGRAPH_API_URL ?? "http://localhost:57515";
const apiUrl = process.env.LANGGRAPH_API_URL ?? "http://localhost:51356";
const res = await fetch(`${apiUrl}/${path}${queryString}`, options);

const headers = new Headers({
Expand Down
1 change: 0 additions & 1 deletion src/components/LangSmithLinkToolUI.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ export const useLangSmithLinkToolUI = () =>
useAssistantToolUI({
toolName: "langsmith_tool_ui",
render: useCallback((input) => {

return (
<TooltipIconButton
tooltip="View in LangSmith"
Expand Down
57 changes: 37 additions & 20 deletions src/components/artifacts/ArtifactRenderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { v4 as uuidv4 } from "uuid";
import { useState, useEffect, useCallback, useRef } from "react";
import { Button } from "../ui/button";
import { Input } from "../ui/input";
import { CircleArrowUp } from "lucide-react";
import { CircleArrowUp, Eye, PencilLine } from "lucide-react";
import { cn } from "@/lib/utils";
import { Artifact, ProgrammingLanguageOptions } from "@/types";
import { GraphInput } from "@/hooks/useGraph";
Expand Down Expand Up @@ -45,6 +45,7 @@ export function ArtifactRenderer(props: ArtifactRendererProps) {
const [isInputVisible, setIsInputVisible] = useState(false);
const [isSelectionActive, setIsSelectionActive] = useState(false);
const [inputValue, setInputValue] = useState("");
const [isEditing, setIsEditing] = useState(false);

const handleMouseUp = useCallback(() => {
const selection = window.getSelection();
Expand Down Expand Up @@ -232,37 +233,53 @@ export function ArtifactRenderer(props: ArtifactRendererProps) {

return (
<div className="relative w-full h-full overflow-auto">
<div className="pl-[6px] pt-3 flex flex-row gap-4 items-center justify-start">
<TooltipIconButton
tooltip="Close canvas"
variant="ghost"
className="w-[36px] h-[36px]"
delayDuration={400}
onClick={() => props.setSelectedArtifactById(undefined)}
>
<X />
</TooltipIconButton>
<h1 className="text-xl font-medium">{props.artifact.title}</h1>
<div className="flex flex-row items-center justify-between">
<div className="pl-[6px] pt-3 flex flex-row gap-4 items-center justify-start">
<TooltipIconButton
tooltip="Close canvas"
variant="ghost"
className="w-[36px] h-[36px]"
delayDuration={400}
onClick={() => props.setSelectedArtifactById(undefined)}
>
<X />
</TooltipIconButton>
<h1 className="text-xl font-medium">{props.artifact.title}</h1>
</div>
{props.artifact.type === "text" ? (
<div className="pr-[6px] pt-3 flex flex-row gap-4 items-center justify-end">
<TooltipIconButton
tooltip={isEditing ? "Preview" : "Edit"}
variant="ghost"
className="transition-colors w-fit h-fit"
delayDuration={400}
onClick={() => setIsEditing((v) => !v)}
>
{isEditing ? <Eye className="w-6 h-6" /> : <PencilLine />}
</TooltipIconButton>
</div>
) : null}
</div>

<div
ref={contentRef}
className={cn(
"flex justify-center h-full",
props.artifact.type === "code" ? "pt-[10px]" : "pt-[10%]"
props.artifact.type === "code" ? "pt-[10px]" : "pt-[0px]"
)}
>
<div
className={cn(
"relative",
props.artifact.type === "code"
? "min-w-full min-h-full"
: "w-full min-h-full px-4"
"relative min-h-full",
props.artifact.type === "code" ? "min-w-full" : "w-full px-4"
)}
>
<div ref={markdownRef}>
<div className="h-[85%]" ref={markdownRef}>
{props.artifact.type === "text" ? (
<TextRenderer artifact={props.artifact} />
<TextRenderer
isEditing={isEditing}
setIsEditing={setIsEditing}
artifact={props.artifact}
/>
) : null}
{props.artifact.type === "code" ? (
<CodeRenderer editorRef={editorRef} artifact={props.artifact} />
Expand Down
20 changes: 0 additions & 20 deletions src/components/artifacts/CodeRenderer.module.css
Original file line number Diff line number Diff line change
@@ -1,23 +1,3 @@
/* .codeMirrorCustom :global(.cm-focused) {
outline: none !important;
}
.codeMirrorCustom :global(.cm-editor) {
border: none !important;
}
.codeMirrorCustom :global(.cm-focused) {
outline: none !important;
}
.codeMirrorCustom :global(.cm-editor) {
border: none !important;
}
.codeMirrorCustom :global(.cm-gutters) {
border-right: none !important;
} */

.codeMirrorCustom {
height: 100vh !important;
overflow: hidden;
Expand Down
35 changes: 35 additions & 0 deletions src/components/artifacts/TextRenderer.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
.mdEditorCustom {
height: 100% !important;
overflow: hidden;
}

.mdEditorCustom :global(.w-md-editor) {
height: 100% !important;
border: none !important;
}

.mdEditorCustom :global(.w-md-editor-content) {
height: 100% !important;
}

.mdEditorCustom :global(.w-md-editor-text),
.mdEditorCustom :global(.w-md-editor-text-pre),
.mdEditorCustom :global(.w-md-editor-text-input) {
min-height: 100% !important;
height: 100% !important;
}

.mdEditorCustom :global(.w-md-editor-preview) {
box-shadow: none !important;
border-left: 1px solid #e0e0e0;
}

.mdEditorCustom :global(.w-md-editor-toolbar) {
border-bottom: none !important;
}

/* Force full height for text area */
.fullHeightTextArea :global(.w-md-editor-text-input) {
min-height: 100vh !important;
height: 100% !important;
}
53 changes: 28 additions & 25 deletions src/components/artifacts/TextRenderer.tsx
Original file line number Diff line number Diff line change
@@ -1,39 +1,42 @@
import { Artifact } from "@/types";
import MDEditor from "@uiw/react-md-editor";
import { useCallback, useEffect, useState } from "react";
import { Dispatch, SetStateAction, useEffect, useRef, useState } from "react";

export interface TextRendererProps {
artifact: Artifact;
}
import styles from "./TextRenderer.module.css";

export function TextRenderer(props: TextRendererProps) {
export function TextRenderer({
artifact,
isEditing,
setIsEditing,
}: {
artifact: Artifact;
isEditing: boolean;
setIsEditing: Dispatch<SetStateAction<boolean>>;
}) {
const [value, setValue] = useState("");
const hasSetInitial = useRef(false);

useEffect(() => {
setValue(props.artifact.content);
}, [props.artifact.content]);

const handleEdit = useCallback((event: React.FormEvent<HTMLDivElement>) => {
const newValue = event.currentTarget.innerText;
setValue(newValue);
}, []);
if (!hasSetInitial.current) {
if (artifact.title === "Quickstart text") {
setIsEditing(true);
} else {
setValue(artifact.content);
}
hasSetInitial.current = true;
}
}, [artifact.content]);

return (
<div
className="w-full h-full"
contentEditable
onInput={handleEdit}
suppressContentEditableWarning
>
<div className="w-full h-full mt-2 flex flex-col border-[1px] border-gray-200 rounded-2xl overflow-hidden">
<MDEditor
value={value}
preview="preview"
preview={isEditing ? "edit" : "preview"}
hideToolbar
previewOptions={{
components: {
p: "div",
},
}}
visibleDragbar={false}
value={value}
onChange={(v) => setValue(v || "")}
className={`min-h-full border-none ${styles.mdEditorCustom} ${styles.fullHeightTextArea}`}
height="100%"
/>
</div>
);
Expand Down
10 changes: 9 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4601,7 +4601,7 @@ promise@^7.1.1:
dependencies:
asap "~2.0.3"

prop-types@^15.8.1:
prop-types@^15.7.1, prop-types@^15.8.1:
version "15.8.1"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
Expand Down Expand Up @@ -4647,6 +4647,14 @@ react-base16-styling@^0.6.0:
lodash.flow "^3.3.0"
pure-color "^1.2.0"

react-contenteditable@^3.3.7:
version "3.3.7"
resolved "https://registry.yarnpkg.com/react-contenteditable/-/react-contenteditable-3.3.7.tgz#18dd1f281841ba2c2b306e2d28278bc31b7929ed"
integrity sha512-GA9NbC0DkDdpN3iGvib/OMHWTJzDX2cfkgy5Tt98JJAbA3kLnyrNbBIpsSpPpq7T8d3scD39DHP+j8mAM7BIfQ==
dependencies:
fast-deep-equal "^3.1.3"
prop-types "^15.7.1"

react-dom@^18:
version "18.3.1"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.3.1.tgz#c2265d79511b57d479b3dd3fdfa51536494c5cb4"
Expand Down

0 comments on commit 7a6fea3

Please sign in to comment.