import { useState, useEffect } from 'react'; import Editor, { OnMount } from '@monaco-editor/react'; import styles from './CodeEditor.module.css'; export interface CodeEditorProps { value: string; onChange: (value: string) => void; language?: string; rows?: number; error?: boolean; } function useMonacoTheme() { const [theme, setTheme] = useState(() => document.documentElement.getAttribute('data-theme') === 'dark' ? 'vs-dark' : 'vs-light' ); useEffect(() => { const observer = new MutationObserver(() => { setTheme( document.documentElement.getAttribute('data-theme') === 'dark' ? 'vs-dark' : 'vs-light' ); }); observer.observe(document.documentElement, { attributes: true, attributeFilter: ['data-theme'], }); return () => observer.disconnect(); }, []); return theme; } export function CodeEditor({ value, onChange, language = 'javascript', rows = 6, error = false, }: CodeEditorProps) { const theme = useMonacoTheme(); const [focused, setFocused] = useState(false); const height = rows * 20 + 16; const handleMount: OnMount = (editor) => { editor.onDidFocusEditorWidget(() => setFocused(true)); editor.onDidBlurEditorWidget(() => setFocused(false)); }; return (
onChange(v ?? '')} onMount={handleMount} options={{ minimap: { enabled: false }, scrollBeyondLastLine: false, fontSize: 14, lineHeight: 20, wordWrap: 'on', padding: { top: 8, bottom: 8 }, folding: false, renderLineHighlight: 'line', scrollbar: { vertical: 'auto', horizontal: 'hidden' }, automaticLayout: true, }} />
); }