import { useEffect, useRef } from 'react' import { EditorContent, useEditor } from '@tiptap/react' import StarterKit from '@tiptap/starter-kit' import TextAlign from '@tiptap/extension-text-align' import Underline from '@tiptap/extension-underline' export function RichTextEditor({ onChange, value }) { const lastSyncedHtmlRef = useRef(value || '') const applyingExternalContentRef = useRef(false) const tiptapEditor = useEditor({ extensions: [ StarterKit, Underline, TextAlign.configure({ types: ['heading', 'paragraph'], }), ], content: value || '', editorProps: { attributes: { class: 'report-rich-surface min-h-[560px] px-4 py-3 text-sm leading-6 text-[#e5e5e5] outline-none', }, }, shouldRerenderOnTransaction: false, onUpdate: ({ editor: currentEditor }) => { if (applyingExternalContentRef.current) return const nextHtml = currentEditor.getHTML() lastSyncedHtmlRef.current = nextHtml onChange(nextHtml) }, }) useEffect(() => { if (!tiptapEditor) return const nextValue = value || '' if (lastSyncedHtmlRef.current === nextValue) return if (tiptapEditor.getHTML() === nextValue) { lastSyncedHtmlRef.current = nextValue return } applyingExternalContentRef.current = true try { tiptapEditor.commands.setContent(nextValue, { emitUpdate: false }) } finally { applyingExternalContentRef.current = false } lastSyncedHtmlRef.current = nextValue }, [tiptapEditor, value]) const blockFormat = tiptapEditor?.isActive('heading', { level: 2 }) ? 'h2' : tiptapEditor?.isActive('heading', { level: 3 }) ? 'h3' : 'p' return (