Files
deer-flow/frontend/src/components/workspace/code-editor.tsx
2026-01-31 21:46:31 +08:00

115 lines
3.0 KiB
TypeScript

"use client";
import { css } from "@codemirror/lang-css";
import { html } from "@codemirror/lang-html";
import { javascript } from "@codemirror/lang-javascript";
import { json } from "@codemirror/lang-json";
import { markdown, markdownLanguage } from "@codemirror/lang-markdown";
import { python } from "@codemirror/lang-python";
import { languages } from "@codemirror/language-data";
import { basicLightInit } from "@uiw/codemirror-theme-basic";
import { monokaiInit } from "@uiw/codemirror-theme-monokai";
import CodeMirror from "@uiw/react-codemirror";
import { useTheme } from "next-themes";
import { useMemo } from "react";
import { Textarea } from "@/components/ui/textarea";
import { cn } from "@/lib/utils";
import { useThread } from "./messages/context";
const customDarkTheme = monokaiInit({
settings: {
background: "transparent",
gutterBackground: "transparent",
gutterForeground: "#555",
gutterActiveForeground: "#fff",
fontSize: "var(--text-sm)",
},
});
const customLightTheme = basicLightInit({
settings: {
background: "transparent",
fontSize: "var(--text-sm)",
},
});
export function CodeEditor({
className,
placeholder,
value,
readonly,
disabled,
autoFocus,
settings,
}: {
className?: string;
placeholder?: string;
value: string;
readonly?: boolean;
disabled?: boolean;
autoFocus?: boolean;
settings?: unknown;
}) {
const {
thread: { isLoading },
} = useThread();
const { resolvedTheme } = useTheme();
const extensions = useMemo(() => {
return [
css(),
html(),
javascript({}),
json(),
markdown({
base: markdownLanguage,
codeLanguages: languages,
}),
python(),
];
}, []);
return (
<div
className={cn(
"flex cursor-text flex-col overflow-hidden rounded-md",
className,
)}
>
{isLoading ? (
<Textarea
className={cn(
"h-full overflow-auto font-mono [&_.cm-editor]:h-full [&_.cm-focused]:outline-none!",
"resize-none p-4! [&_.cm-line]:px-2! [&_.cm-line]:py-0!",
"border-none",
)}
readOnly
value={value}
/>
) : (
<CodeMirror
readOnly={readonly ?? disabled}
placeholder={placeholder}
className={cn(
"h-full overflow-auto font-mono [&_.cm-editor]:h-full [&_.cm-focused]:outline-none!",
"px-2 py-0! [&_.cm-line]:px-2! [&_.cm-line]:py-0!",
)}
theme={resolvedTheme === "dark" ? customDarkTheme : customLightTheme}
extensions={extensions}
basicSetup={{
foldGutter:
(settings as { foldGutter?: boolean })?.foldGutter ?? false,
highlightActiveLine: false,
highlightActiveLineGutter: false,
lineNumbers:
(settings as { lineNumbers?: boolean })?.lineNumbers ?? false,
}}
autoFocus={autoFocus}
value={value}
/>
)}
</div>
);
}