import React, { useRef, useEffect } from "react"; import { EditorView, basicSetup } from "codemirror"; import { json } from "@codemirror/lang-json"; import { oneDark } from "@codemirror/theme-one-dark"; import { EditorState } from "@codemirror/state"; import { placeholder } from "@codemirror/view"; interface JsonEditorProps { value: string; onChange: (value: string) => void; placeholder?: string; darkMode?: boolean; rows?: number; } const JsonEditor: React.FC = ({ value, onChange, placeholder: placeholderText = "", darkMode = false, rows = 12, }) => { const editorRef = useRef(null); const viewRef = useRef(null); useEffect(() => { if (!editorRef.current) return; // 创建编辑器扩展 const minHeightPx = Math.max(1, rows) * 18; // 降低最小高度以减少抖动 const sizingTheme = EditorView.theme({ "&": { minHeight: `${minHeightPx}px` }, ".cm-scroller": { overflow: "auto" }, ".cm-content": { fontFamily: "ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace", fontSize: "14px", }, }); const extensions = [ basicSetup, json(), placeholder(placeholderText || ""), sizingTheme, EditorView.updateListener.of((update) => { if (update.docChanged) { const newValue = update.state.doc.toString(); onChange(newValue); } }), ]; // 如果启用深色模式,添加深色主题 if (darkMode) { extensions.push(oneDark); } // 创建初始状态 const state = EditorState.create({ doc: value, extensions, }); // 创建编辑器视图 const view = new EditorView({ state, parent: editorRef.current, }); viewRef.current = view; // 清理函数 return () => { view.destroy(); viewRef.current = null; }; }, [darkMode, rows]); // 依赖项中不包含 onChange 和 placeholder,避免不必要的重建 // 当 value 从外部改变时更新编辑器内容 useEffect(() => { if (viewRef.current && viewRef.current.state.doc.toString() !== value) { const transaction = viewRef.current.state.update({ changes: { from: 0, to: viewRef.current.state.doc.length, insert: value, }, }); viewRef.current.dispatch(transaction); } }, [value]); return
; }; export default JsonEditor;