import { useEditor, EditorContent } from '@tiptap/react'; import StarterKit from '@tiptap/starter-kit'; import Link from '@tiptap/extension-link'; import Underline from '@tiptap/extension-underline'; import TextAlign from '@tiptap/extension-text-align'; import { TextStyle } from '@tiptap/extension-text-style'; import Color from '@tiptap/extension-color'; import Image from '@tiptap/extension-image'; import { Bold, Italic, Underline as UnderlineIcon, List, ListOrdered, AlignLeft, AlignCenter, AlignRight, Link as LinkIcon, Unlink, } from 'lucide-react'; import { useTranslation } from 'react-i18next'; interface RichTextEditorProps { content: string; onChange: (html: string) => void; placeholder?: string; } export function RichTextEditor({ content, onChange, placeholder }: RichTextEditorProps) { const { t } = useTranslation(); const editor = useEditor({ extensions: [ StarterKit.configure({ heading: false, codeBlock: false, code: false, }), Underline, Link.configure({ openOnClick: false, HTMLAttributes: { target: '_blank', rel: 'noopener noreferrer', }, }), TextAlign.configure({ types: ['paragraph'], }), TextStyle, Color, Image.configure({ HTMLAttributes: { style: 'max-width: 100%; height: auto;', }, }), ], content, onUpdate: ({ editor }) => { onChange(editor.getHTML()); }, editorProps: { attributes: { class: 'prose prose-invert prose-sm max-w-none focus:outline-none min-h-[120px] px-3 py-2', placeholder: placeholder || '', }, }, }); if (!editor) { return null; } const ToolbarButton = ({ onClick, isActive = false, children, title, }: { onClick: () => void; isActive?: boolean; children: React.ReactNode; title: string; }) => ( ); const setLink = () => { const url = window.prompt('Enter URL:'); if (url) { editor.chain().focus().setLink({ href: url }).run(); } }; return (
{/* Toolbar */}
editor.chain().focus().toggleBold().run()} isActive={editor.isActive('bold')} title={t('richTextEditor.bold')} > editor.chain().focus().toggleItalic().run()} isActive={editor.isActive('italic')} title={t('richTextEditor.italic')} > editor.chain().focus().toggleUnderline().run()} isActive={editor.isActive('underline')} title={t('richTextEditor.underline')} >
editor.chain().focus().toggleBulletList().run()} isActive={editor.isActive('bulletList')} title={t('richTextEditor.bulletList')} > editor.chain().focus().toggleOrderedList().run()} isActive={editor.isActive('orderedList')} title={t('richTextEditor.numberedList')} >
editor.chain().focus().setTextAlign('left').run()} isActive={editor.isActive({ textAlign: 'left' })} title={t('richTextEditor.alignLeft')} > editor.chain().focus().setTextAlign('center').run()} isActive={editor.isActive({ textAlign: 'center' })} title={t('richTextEditor.alignCenter')} > editor.chain().focus().setTextAlign('right').run()} isActive={editor.isActive({ textAlign: 'right' })} title={t('richTextEditor.alignRight')} >
{editor.isActive('link') && ( editor.chain().focus().unsetLink().run()} title={t('richTextEditor.removeLink')} > )}
{/* Editor */}
); }