import React, { useRef, useEffect, useState, useCallback } from 'react' function exec(cmd, value = null) { try { return document.execCommand(cmd, false, value) } catch (_) { return false } } /** Selection speichern, bevor Toolbar-Klicks sie zerstört (mousedown + preventDefault allein reicht nicht überall). */ function saveSelectionInside(editorEl) { const sel = window.getSelection() if (!sel || sel.rangeCount === 0 || !editorEl) return null try { const range = sel.getRangeAt(0) if (!editorEl.contains(range.commonAncestorContainer)) return null return range.cloneRange() } catch { return null } } function restoreSelection(range) { if (!range) return try { const sel = window.getSelection() sel.removeAllRanges() sel.addRange(range) } catch { /* noop */ } } /** Browser: formatBlock erwartet oft Tag in Großschreibung. */ function formatBlock(tag) { const t = String(tag).toUpperCase() if (!exec('formatBlock', t)) { exec('formatBlock', tag.toLowerCase()) } } function normalText() { exec('removeFormat') formatBlock('p') } /** * Leichter WYSIWYG (contenteditable). Wert kommt von außen zuverlässig ins DOM (Edit-Modus). */ export default function RichTextEditor({ value, onChange, placeholder, minHeight = '140px' }) { const ref = useRef(null) const [focused, setFocused] = useState(false) useEffect(() => { const el = ref.current if (!el || focused) return const next = value ?? '' if (el.innerHTML !== next) { el.innerHTML = next } }, [value, focused]) const sync = useCallback(() => { if (!ref.current) return onChange(ref.current.innerHTML) }, [onChange]) const run = (fn) => (e) => { e.preventDefault() e.stopPropagation() const el = ref.current if (!el) return const saved = saveSelectionInside(el) el.focus() restoreSelection(saved) try { document.execCommand('styleWithCSS', false, false) } catch { /* optional */ } fn() sync() } const onLink = (e) => { e.preventDefault() e.stopPropagation() const el = ref.current if (!el) return const saved = saveSelectionInside(el) el.focus() restoreSelection(saved) const url = window.prompt('Link-URL (https://…)') if (url) { exec('createLink', url) sync() } } return (