## 🚀 Feature: Inline Code Editor This PR adds a comprehensive inline code editing experience to the DyadWrite component. ### ✨ What's New - **Inline Monaco Editor**: Edit code directly within the component using Monaco Editor - **Cancel/Revert**: Cancel changes and revert to original code state - **Language Detection**: Automatic syntax highlighting based on file extensions - **Theme Support**: Proper dark/light mode theming integration https://github.com/user-attachments/assets/c44ab622-6b86-403c-904d-3f327f9719e8 <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Adds an inline Monaco-based code editor to DyadWrite so users can edit code blocks in place, then save or cancel changes. Saves stream edits back to the chat as a dyad-edit block. - **New Features** - Inline editor with Edit, Save, and Cancel; preserves original code and auto-expands when editing. - Language detection from file extension and dark/light theme support. - Save streams edits via useStreamChat as <dyad-edit path="...">...</dyad-edit> tied to the selected chat. - Non-edit view still uses CodeHighlight; visibility toggle and in-progress state respected. - **Refactors** - ChatMessage now uses DyadMarkdownParser instead of VanillaMarkdownParser. <!-- End of auto-generated description by cubic. -->
This commit is contained in:
committed by
GitHub
parent
8c3fdb0ad0
commit
2edd122d9b
@@ -7,9 +7,14 @@ import {
|
||||
Pencil,
|
||||
Loader,
|
||||
CircleX,
|
||||
Edit,
|
||||
X,
|
||||
} from "lucide-react";
|
||||
import { CodeHighlight } from "./CodeHighlight";
|
||||
import { CustomTagState } from "./stateTypes";
|
||||
import { FileEditor } from "../preview_panel/FileEditor";
|
||||
import { useAtomValue } from "jotai";
|
||||
import { selectedAppIdAtom } from "@/atoms/appAtoms";
|
||||
|
||||
interface DyadWriteProps {
|
||||
children?: ReactNode;
|
||||
@@ -30,9 +35,20 @@ export const DyadWrite: React.FC<DyadWriteProps> = ({
|
||||
const path = pathProp || node?.properties?.path || "";
|
||||
const description = descriptionProp || node?.properties?.description || "";
|
||||
const state = node?.properties?.state as CustomTagState;
|
||||
const inProgress = state === "pending";
|
||||
const aborted = state === "aborted";
|
||||
|
||||
const aborted = state === "aborted";
|
||||
const appId = useAtomValue(selectedAppIdAtom);
|
||||
const [isEditing, setIsEditing] = useState(false);
|
||||
const inProgress = state === "pending";
|
||||
|
||||
const handleCancel = () => {
|
||||
setIsEditing(false);
|
||||
};
|
||||
|
||||
const handleEdit = () => {
|
||||
setIsEditing(true);
|
||||
setIsContentVisible(true);
|
||||
};
|
||||
// Extract filename from path
|
||||
const fileName = path ? path.split("/").pop() : "";
|
||||
|
||||
@@ -69,6 +85,35 @@ export const DyadWrite: React.FC<DyadWriteProps> = ({
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-center">
|
||||
{!inProgress && (
|
||||
<>
|
||||
{isEditing ? (
|
||||
<>
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
handleCancel();
|
||||
}}
|
||||
className="flex items-center gap-1 text-xs text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200 px-2 py-1 rounded cursor-pointer"
|
||||
>
|
||||
<X size={14} />
|
||||
Cancel
|
||||
</button>
|
||||
</>
|
||||
) : (
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
handleEdit();
|
||||
}}
|
||||
className="flex items-center gap-1 text-xs text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200 px-2 py-1 rounded cursor-pointer"
|
||||
>
|
||||
<Edit size={14} />
|
||||
Edit
|
||||
</button>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{isContentVisible ? (
|
||||
<ChevronsDownUp
|
||||
size={20}
|
||||
@@ -98,9 +143,15 @@ export const DyadWrite: React.FC<DyadWriteProps> = ({
|
||||
className="text-xs cursor-text"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<CodeHighlight className="language-typescript">
|
||||
{children}
|
||||
</CodeHighlight>
|
||||
{isEditing ? (
|
||||
<div className="h-96 min-h-96 border border-gray-200 dark:border-gray-700 rounded overflow-hidden">
|
||||
<FileEditor appId={appId ?? null} filePath={path} />
|
||||
</div>
|
||||
) : (
|
||||
<CodeHighlight className="language-typescript">
|
||||
{children}
|
||||
</CodeHighlight>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user