import { useEffect, useRef, useState } from 'react' import './App.css' import EditorJS, { OutputData } from '@editorjs/editorjs' class EditorJSWrapper { private editor: EditorJS | null = null; private holder: HTMLDivElement | null = null; private onChange!: (data: OutputData) => void; private static instance: EditorJSWrapper | null = null; private currentData: OutputData = { time: Date.now(), blocks: [], version: '2.28.2' }; constructor(onChange: (data: OutputData) => void) { if (EditorJSWrapper.instance) { return EditorJSWrapper.instance; } this.onChange = onChange; EditorJSWrapper.instance = this; } initialize(holder: HTMLDivElement) { if (this.editor || !holder) return; // Ensure any existing instance is destroyed first if (EditorJSWrapper.instance?.editor) { void EditorJSWrapper.instance.destroy(); } this.holder = holder; try { this.editor = new EditorJS({ holder: holder, placeholder: 'Start writing...', data: this.currentData, onChange: async () => { await this.syncState(); } }); } catch (error) { console.error('Error initializing editor:', error); } } private async syncState() { if (!this.editor) return; try { this.currentData = await this.editor.save(); this.onChange(this.currentData); } catch (err) { console.error('Error syncing state:', err); } } async addBlock(text: string) { if (!this.editor) return; try { await this.editor.blocks.insert('paragraph', { text }); await this.syncState(); } catch (err) { console.error('Error adding block:', err); } } async clear() { if (!this.editor) return; try { await this.editor.clear(); this.currentData = { time: Date.now(), blocks: [], version: '2.28.2' }; this.onChange(this.currentData); } catch (err) { console.error('Error clearing editor:', err); } } async getData(): Promise { return this.currentData; } async destroy() { try { if (this.editor && typeof this.editor.destroy === 'function') { await this.editor.destroy(); this.editor = null; this.holder = null; this.currentData = { time: Date.now(), blocks: [], version: '2.28.2' }; EditorJSWrapper.instance = null; } } catch (error: unknown) { console.error('Error destroying editor:', error); } } } function App() { const [editorData, setEditorData] = useState(null); const [inputText, setInputText] = useState(""); const [editor] = useState(() => new EditorJSWrapper((data) => setEditorData(data))); const inputRef = useRef(null); const editorRef = useRef(null); useEffect(() => { if (editorRef.current) { editor.initialize(editorRef.current); } return () => { const cleanup = async () => { await editor.destroy(); }; void cleanup(); }; }, [editor]); const handleAdd = async () => { if (!inputText.trim()) return; await editor.addBlock(inputText); setInputText(""); setTimeout(() => { inputRef.current?.focus(); }, 0); }; const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); void handleAdd(); }; return (
setInputText(e.target.value)} placeholder="Enter text..." />
) } export default App function OutputComponent({ data }: { data: OutputData | null }) { return (
        {data ? JSON.stringify(data, null, 2) : 'Output content will go here'}
      
) }