import React, { useRef, useState, useEffect } from 'react'; import { Bold, Italic, Underline, List, ListOrdered, Link, Code, Type, Eraser, AlignLeft, AlignCenter, AlignRight, Braces } from 'lucide-react'; interface Props { value: string; onChange: (value: string) => void; placeholder?: string; className?: string; } const RichTextEditor: React.FC = ({ value, onChange, placeholder, className = '' }) => { const [isSourceMode, setIsSourceMode] = useState(false); const contentRef = useRef(null); const selectionRef = useRef(null); // Sync value to contentEditable div useEffect(() => { if (contentRef.current && !isSourceMode) { if (document.activeElement !== contentRef.current) { if (contentRef.current.innerHTML !== value) { contentRef.current.innerHTML = value; } } } }, [value, isSourceMode]); const saveSelection = () => { const sel = window.getSelection(); if (sel && sel.rangeCount > 0) { const range = sel.getRangeAt(0); // Ensure the selection is actually inside our editor if (contentRef.current && contentRef.current.contains(range.commonAncestorContainer)) { selectionRef.current = range; } } }; const restoreSelection = () => { if (contentRef.current) { contentRef.current.focus(); if (selectionRef.current) { const sel = window.getSelection(); if (sel) { sel.removeAllRanges(); sel.addRange(selectionRef.current); } } else { // Fallback: move cursor to the end if no selection saved const range = document.createRange(); range.selectNodeContents(contentRef.current); range.collapse(false); const sel = window.getSelection(); sel?.removeAllRanges(); sel?.addRange(range); } } }; const execCommand = (command: string, value: string | undefined = undefined) => { restoreSelection(); document.execCommand(command, false, value); handleInput(); }; const handleInput = () => { if (contentRef.current) { onChange(contentRef.current.innerHTML); saveSelection(); } }; const insertVariable = (e: React.MouseEvent) => { e.preventDefault(); // Prevent default button behavior e.stopPropagation(); const varName = prompt("Inserisci nome variabile (senza parentesi):", "nome_variabile"); if (varName) { if (isSourceMode) { alert("Passa alla modalità Visuale per usare l'inseritore, oppure scrivi {{nome}} manualmente."); } else { restoreSelection(); const text = `{{${varName}}}`; // Try standard command first, fallback to range manipulation const success = document.execCommand('insertText', false, text); if (!success) { const sel = window.getSelection(); if (sel && sel.rangeCount > 0) { const range = sel.getRangeAt(0); range.deleteContents(); const textNode = document.createTextNode(text); range.insertNode(textNode); // Move cursor after inserted text range.setStartAfter(textNode); range.setEndAfter(textNode); sel.removeAllRanges(); sel.addRange(range); } } handleInput(); } } }; const ToolbarButton = ({ icon: Icon, command, arg, active = false, title }: { icon: any, command?: string, arg?: string, active?: boolean, title: string }) => ( ); return (
{/* Toolbar */}
{!isSourceMode && ( <>
)}
{/* Editor Area */}
{isSourceMode ? (