import { useState, useCallback, useMemo, useRef, type UIEvent } from "react"; import ReactMarkdown from "react-markdown"; import remarkGfm from "remark-gfm"; import { FileEdit, Eye, WrapText } from "lucide-react"; interface FileEditorProps { content: string; onChange: (content: string) => void; readOnly?: boolean; filePath?: string; showLineNumbers?: boolean; } function isMarkdownFile(filePath?: string): boolean { if (!filePath) return false; const lowerPath = filePath.toLowerCase(); return lowerPath.endsWith(".md") || lowerPath.endsWith(".markdown") || lowerPath.endsWith(".mdx"); } export function FileEditor({ content, onChange, readOnly, filePath, showLineNumbers = false }: FileEditorProps) { const [showPreview, setShowPreview] = useState(false); const [wordWrap, setWordWrap] = useState(true); const lineNumbersRef = useRef(null); const isMarkdown = isMarkdownFile(filePath); // For markdown files in readOnly mode, default to preview const effectiveShowPreview = isMarkdown && (readOnly ? true : showPreview); const shouldRenderLineNumbers = showLineNumbers && !readOnly && !effectiveShowPreview; const lineCount = useMemo(() => { if (!shouldRenderLineNumbers) { return 0; } return content.split("\n").length; }, [content, shouldRenderLineNumbers]); const handleEditClick = useCallback(() => { setShowPreview(false); }, []); const handlePreviewClick = useCallback(() => { setShowPreview(true); }, []); const handleWordWrapToggle = useCallback(() => { setWordWrap((prev) => !prev); }, []); const handleTextareaScroll = useCallback((event: UIEvent) => { if (!lineNumbersRef.current) { return; } lineNumbersRef.current.scrollTop = event.currentTarget.scrollTop; }, []); return (
{isMarkdown ? (
{!readOnly && ( )}
{!readOnly && ( )}
) : ( !readOnly && (
) )} {effectiveShowPreview ? (
{content}
) : (
{shouldRenderLineNumbers && ( )}