import React, { useEffect, useRef } from 'react'; import { EditorView, basicSetup } from 'codemirror'; import { markdown } from '@codemirror/lang-markdown'; import { oneDark } from '@codemirror/theme-one-dark'; import { MarkdownToolbar } from './markdown-toolbar'; interface CodeEditorProps { value: string; onChange: (value: string) => void; placeholder?: string; supportMarkdown?: boolean; // Keep for backward compatibility but always use markdown } export function CodeEditor({ value, onChange, placeholder }: CodeEditorProps) { const editorRef = useRef(null); const viewRef = useRef(null); // Handle markdown insertions from toolbar const handleInsert = (before: string, after: string = '') => { if (!viewRef.current) return; const view = viewRef.current; const selection = view.state.selection.main; const selectedText = view.state.doc.sliceString(selection.from, selection.to); // Insert the markdown syntax const newText = before + selectedText + after; view.dispatch({ changes: { from: selection.from, to: selection.to, insert: newText }, selection: { anchor: selection.from + before.length + selectedText.length } }); // Focus back to editor view.focus(); }; // Initialize editor once useEffect(() => { if (!editorRef.current) return; const view = new EditorView({ doc: value, extensions: [ basicSetup, markdown(), oneDark, EditorView.updateListener.of((update) => { if (update.docChanged) { const content = update.state.doc.toString(); onChange(content); } }), ], parent: editorRef.current, }); viewRef.current = view; return () => { view.destroy(); }; }, []); // Only run once on mount // Update editor when value prop changes from external source useEffect(() => { if (viewRef.current && value !== viewRef.current.state.doc.toString()) { viewRef.current.dispatch({ changes: { from: 0, to: viewRef.current.state.doc.length, insert: value, }, }); } }, [value]); return (

💡 Use the toolbar above or type markdown directly: **bold**, ## headings, [card]...[/card], [button]...[/button]

); }