'use client'; import React, { useState, useEffect, useRef, forwardRef, useImperativeHandle } from 'react'; import { processContentWithDirection } from '@/lib/utils/text-direction'; import { getDOMPurify } from '@/lib/utils/dom-purify-config'; interface RichTextEditorProps { /** Initial HTML content */ initialContent?: string; /** Callback when content changes */ onChange?: (html: string) => void; /** Additional CSS class names */ className?: string; /** Editor placeholder text */ placeholder?: string; /** Whether the editor is read-only */ readOnly?: boolean; /** Minimum height of the editor */ minHeight?: string; /** Initial text direction */ initialDirection?: 'ltr' | 'rtl'; } // Get DOMPurify from our centralized configuration const DOMPurify = getDOMPurify(); /** * Unified rich text editor component with proper RTL support * Handles email composition with appropriate text direction detection */ const RichTextEditor = forwardRef(({ initialContent = '', onChange, className = '', placeholder = 'Write your message...', readOnly = false, minHeight = '200px', initialDirection }, ref) => { const internalEditorRef = useRef(null); // Process initial content to get its direction const processedInitialContent = processContentWithDirection(initialContent); // Set initial direction either from prop or detected from content const [direction, setDirection] = useState<'ltr' | 'rtl'>( initialDirection || processedInitialContent.direction ); // Forward the ref to parent components useImperativeHandle(ref, () => internalEditorRef.current as HTMLDivElement); // Initialize editor with clean content useEffect(() => { if (internalEditorRef.current) { // Using centralized processing for initial content const { html: cleanContent } = processContentWithDirection(initialContent); internalEditorRef.current.innerHTML = cleanContent || ''; // Set initial direction internalEditorRef.current.setAttribute('dir', direction); // Focus editor if not read-only if (!readOnly) { setTimeout(() => { internalEditorRef.current?.focus(); }, 100); } } }, [initialContent, direction, readOnly]); // Handle content changes and detect direction changes const handleInput = (e: React.FormEvent) => { const newContent = e.currentTarget.innerHTML; // Notify parent of changes if (onChange && newContent !== initialContent) { onChange(newContent); } // Only perform direction detection periodically to avoid constant recalculation // Get the text content for direction detection const newTextContent = e.currentTarget.innerText; if (newTextContent.length > 5 && newTextContent.length % 10 === 0) { // Process the content to determine direction const { direction: newDirection } = processContentWithDirection(newTextContent); if (newDirection !== direction) { setDirection(newDirection); e.currentTarget.setAttribute('dir', newDirection); } } }; return (
); }); RichTextEditor.displayName = 'RichTextEditor'; export default RichTextEditor;