import React, { useState, useRef, useEffect } from "react"; import ReactMarkdown from "react-markdown"; import remarkGfm from "remark-gfm"; import { EditorState } from "@codemirror/state"; import { EditorView, keymap, lineNumbers, highlightActiveLine, drawSelection } from "@codemirror/view"; import { markdown } from "@codemirror/lang-markdown"; import { languages } from "@codemirror/language-data"; import { syntaxHighlighting, defaultHighlightStyle } from "@codemirror/language"; import { defaultKeymap, history, historyKeymap } from "@codemirror/commands"; import { oneDark } from "@codemirror/theme-one-dark"; import type { Phase } from "../types"; interface DocumentPaneProps { content: string; onChange: (content: string) => void; phase: Phase; disabled: boolean; showOnboarding?: boolean; theme: "dark" | "light"; } function MarkdownEditor({ content, onChange, disabled, theme, }: { content: string; onChange: (content: string) => void; disabled: boolean; theme: "dark" | "light"; }) { const editorRef = useRef(null); const viewRef = useRef(null); useEffect(() => { if (!editorRef.current) return; const updateListener = EditorView.updateListener.of((update) => { if (update.docChanged) { onChange(update.state.doc.toString()); } }); const state = EditorState.create({ doc: content, extensions: [ lineNumbers(), highlightActiveLine(), drawSelection(), history(), keymap.of([...defaultKeymap, ...historyKeymap]), markdown({ codeLanguages: languages }), theme === "dark" ? oneDark : syntaxHighlighting(defaultHighlightStyle), updateListener, EditorView.editable.of(!disabled), EditorView.lineWrapping, EditorView.theme({ "&": { height: "100%", fontSize: "14px", }, ".cm-scroller": { overflow: "auto", fontFamily: '"SF Mono", Monaco, "Cascadia Code", monospace', }, ".cm-content": { padding: "16px 0", }, ".cm-line": { padding: "0 16px", }, }), ], }); const view = new EditorView({ state, parent: editorRef.current, }); viewRef.current = view; return () => { view.destroy(); viewRef.current = null; }; }, [disabled, theme]); // Update content when it changes externally useEffect(() => { const view = viewRef.current; if (!view) return; const currentContent = view.state.doc.toString(); if (content !== currentContent) { view.dispatch({ changes: { from: 0, to: currentContent.length, insert: content, }, }); } }, [content]); return
; } export function DocumentPane({ content, onChange, phase, disabled, showOnboarding, theme, }: DocumentPaneProps) { const [isEditing, setIsEditing] = useState(false); // Always exit edit mode when the pane becomes read-only. useEffect(() => { if (disabled) setIsEditing(false); }, [disabled]); if (showOnboarding) { return (
Welcome to Claude Flow

Claude Flow

A structured workflow for AI-assisted coding:{" "} Research → Plan → Implement.

Setup

Export your Anthropic API key:

            export ANTHROPIC_API_KEY=your-key-here
          

Get one at{" "} platform.claude.com

Getting Started

  1. Add a project — Select a codebase folder
  2. Create a session — Start a new task
  3. Describe your work — Tell Claude what you want to build

Workflow

Research: Claude analyzes your codebase and writes findings to research.md. Add notes like{" "} // REVIEW: check this — click Review{" "} when done.

Plan: Claude drafts an implementation plan in{" "} plan.md with code snippets and a TODO list. Iterate the same way.

Implement: Claude executes the plan, marking tasks complete as it goes.

Iterate on research and plan docs as long as you want. Click{" "} Submit when happy to move to the next phase.

); } if (phase === "implement") { return (
plan.md Implementing...
{content}
); } const filename = phase === "research" ? "research.md" : "plan.md"; return (
{filename} {disabled ? ( Read-only ) : ( )}
{isEditing ? ( ) : (
!disabled && setIsEditing(true)} > {content ? ( {content} ) : (

Document will appear here after Claude generates it...

)}
)}
); }