import { forwardRef, useEffect, useImperativeHandle } from 'react'; import { EditorContent, useEditor } from '@tiptap/react'; import StarterKit from '@tiptap/starter-kit'; import Link from '@tiptap/extension-link'; import Placeholder from '@tiptap/extension-placeholder'; import Image from '@tiptap/extension-image'; import { Button, Stack } from '@mui/material'; export type RichEditorHandle = { insertImage: (src: string, alt?: string) => void; insertHtmlAtCursor: (html: string) => void; }; type Props = { value: string; onChange: (html: string) => void; placeholder?: string; }; const RichEditor = forwardRef(({ value, onChange, placeholder }, ref) => { const editor = useEditor({ extensions: [ StarterKit, Link.configure({ openOnClick: true }), Placeholder.configure({ placeholder: placeholder ?? 'Write something…' }), Image.configure({ inline: false, allowBase64: false }), ], content: value ?? '', onUpdate: ({ editor }) => onChange(editor.getHTML()), editorProps: { attributes: { class: 'tiptap-content' } }, }); useImperativeHandle(ref, () => ({ insertImage: (src: string, alt?: string) => { if (!editor) return; editor.chain().focus().setImage({ src, alt }).run(); }, insertHtmlAtCursor: (html: string) => { if (!editor) return; editor.chain().focus().insertContent(html).run(); }, }), [editor]); useEffect(() => { if (editor && value !== editor.getHTML()) { editor.commands.setContent(value ?? '', { emitUpdate: false }); } }, [value, editor]); return (
); }); export default RichEditor;