+ {/* Hidden file input for image selection */}
+
+
+ {/* Title area */}
+
+ updateNoteTitle(activeNote.id, e.target.value)}
+ />
+
+
+ {/* Editor.js Holder */}
+
+
+ {/* Plus trigger button — always mounted, visibility controlled via refs (prevents flickering) */}
+ {createPortal(
+
,
+ document.body
+ )}
+
+ {/* Block Insertion Panel */}
+ {showInsertPanel && (
+
{ setShowInsertPanel(false); setSlashBlockIndex(null); }}
+ containerRef={containerRef}
+ />
+ )}
+
+ );
+});
+
+export default EditorJsEditor;
diff --git a/src/components/notes/NoteEditor.tsx b/src/components/notes/NoteEditor.tsx
index 2a1217e..ed0a2a7 100644
--- a/src/components/notes/NoteEditor.tsx
+++ b/src/components/notes/NoteEditor.tsx
@@ -1,268 +1,25 @@
-import React, { useCallback, useEffect, useRef, useState } from 'react';
-import { useEditor, EditorContent } from '@tiptap/react';
-import StarterKit from '@tiptap/starter-kit';
-import Underline from '@tiptap/extension-underline';
-import Image from '@tiptap/extension-image';
-import Placeholder from '@tiptap/extension-placeholder';
+import React from 'react';
import { useAppStore } from '../../store/useAppStore';
-import { useSpeechToText } from '../../hooks/useSpeechToText';
-
+import TiptapEditor from './TiptapEditor';
+import EditorJsEditor from './EditorJsEditor';
+
+/**
+ * NoteEditor Switcher
+ * Conditionally renders TiptapEditor or EditorJsEditor based on the active note's editorType.
+ * This component owns zero editor logic — it simply delegates to the correct editor.
+ */
const NoteEditor: React.FC = React.memo(() => {
- const { activeNoteId, updateNoteTitle, t, design, language } = useAppStore();
+ const activeNoteId = useAppStore((state) => state.activeNoteId);
const activeNote = useAppStore((state) => state.notes.find(n => n.id === activeNoteId));
- const fileInputRef = useRef