Neah/components/email/RichEmailEditor.tsx
2025-04-27 10:25:20 +02:00

132 lines
3.6 KiB
TypeScript

'use client';
import React, { useEffect, useRef, useState } from 'react';
import 'quill/dist/quill.snow.css';
import { sanitizeHtml } from '@/lib/utils/email-formatter';
interface RichEmailEditorProps {
initialContent: string;
onChange: (content: string) => void;
placeholder?: string;
minHeight?: string;
maxHeight?: string;
}
const RichEmailEditor: React.FC<RichEmailEditorProps> = ({
initialContent,
onChange,
placeholder = 'Write your message here...',
minHeight = '200px',
maxHeight = 'calc(100vh - 400px)',
}) => {
const editorRef = useRef<HTMLDivElement>(null);
const quillRef = useRef<any>(null);
const [isReady, setIsReady] = useState(false);
// Initialize Quill editor when component mounts
useEffect(() => {
// Import Quill dynamically (client-side only)
const initializeQuill = async () => {
if (!editorRef.current) return;
const Quill = (await import('quill')).default;
// Define custom formats/modules as needed for email
const emailToolbarOptions = [
['bold', 'italic', 'underline', 'strike'],
[{ 'color': [] }, { 'background': [] }],
[{ 'list': 'ordered'}, { 'list': 'bullet' }],
[{ 'indent': '-1'}, { 'indent': '+1' }],
[{ 'align': [] }],
['link'],
['clean'],
];
// Create new Quill instance with the DOM element
const editorElement = editorRef.current;
quillRef.current = new Quill(editorElement, {
modules: {
toolbar: emailToolbarOptions
},
placeholder: placeholder,
theme: 'snow',
});
// Set initial content (sanitized)
if (initialContent) {
quillRef.current.clipboard.dangerouslyPasteHTML(sanitizeHtml(initialContent));
}
// Add change listener
quillRef.current.on('text-change', () => {
const html = quillRef.current.root.innerHTML;
onChange(html);
});
setIsReady(true);
};
initializeQuill();
// Clean up on unmount
return () => {
if (quillRef.current) {
// Clean up any event listeners or resources
quillRef.current.off('text-change');
}
};
}, []);
// Update content from props if changed externally
useEffect(() => {
if (quillRef.current && isReady) {
const currentContent = quillRef.current.root.innerHTML;
if (initialContent !== currentContent) {
quillRef.current.clipboard.dangerouslyPasteHTML(sanitizeHtml(initialContent));
}
}
}, [initialContent, isReady]);
return (
<div className="rich-email-editor-container">
{/* Quill container */}
<div
ref={editorRef}
className="quill-editor"
style={{
height: 'auto',
minHeight: minHeight,
maxHeight: maxHeight
}}
/>
{/* Loading indicator */}
{!isReady && (
<div className="flex items-center justify-center py-8">
<div className="h-6 w-6 animate-spin rounded-full border-2 border-primary border-t-transparent"></div>
</div>
)}
{/* Custom styles for email context */}
<style jsx>{`
.rich-email-editor-container {
display: flex;
flex-direction: column;
width: 100%;
border-radius: 6px;
overflow: hidden;
flex: 1;
}
.quill-editor {
width: 100%;
flex: 1;
}
/* Hide the editor until it's ready */
.quill-editor ${!isReady ? '{ display: none; }' : ''}
`}</style>
</div>
);
};
export default RichEmailEditor;