import { useEditor, EditorContent } from '@tiptap/react'; import StarterKit from '@tiptap/starter-kit'; import Link from '@tiptap/extension-link'; import Image from '@tiptap/extension-image'; import Placeholder from '@tiptap/extension-placeholder'; import { Button } from '@/components/ui/button'; import { Bold, Italic, List, ListOrdered, Quote, Link as LinkIcon, Image as ImageIcon, Heading1, Heading2, Undo, Redo } from 'lucide-react'; import { cn } from '@/lib/utils'; import { useCallback, useEffect } from 'react'; import { supabase } from '@/integrations/supabase/client'; import { toast } from '@/hooks/use-toast'; interface RichTextEditorProps { content: string; onChange: (html: string) => void; placeholder?: string; className?: string; } export function RichTextEditor({ content, onChange, placeholder = 'Tulis konten...', className }: RichTextEditorProps) { const editor = useEditor({ extensions: [ StarterKit, Link.configure({ openOnClick: false, HTMLAttributes: { class: 'text-primary underline', }, }), Image.configure({ HTMLAttributes: { class: 'max-w-full h-auto rounded-md', }, }), Placeholder.configure({ placeholder, }), ], content, onUpdate: ({ editor }) => { onChange(editor.getHTML()); }, }); // Sync content when it changes externally (e.g., when editing different items) useEffect(() => { if (editor && content !== editor.getHTML()) { editor.commands.setContent(content || ''); } }, [content, editor]); const addLink = useCallback(() => { if (!editor) return; const url = window.prompt('Masukkan URL:'); if (url) { editor.chain().focus().extendMarkRange('link').setLink({ href: url }).run(); } }, [editor]); const handleImageUpload = useCallback(async (e: React.ChangeEvent) => { const file = e.target.files?.[0]; if (!file || !editor) return; // For now, convert to base64 data URL since storage bucket may not be configured // In production, you would upload to Supabase Storage const reader = new FileReader(); reader.onload = () => { const dataUrl = reader.result as string; editor.chain().focus().setImage({ src: dataUrl }).run(); }; reader.readAsDataURL(file); }, [editor]); const handlePaste = useCallback(async (e: React.ClipboardEvent) => { const items = e.clipboardData?.items; if (!items || !editor) return; for (const item of Array.from(items)) { if (item.type.startsWith('image/')) { e.preventDefault(); const file = item.getAsFile(); if (!file) continue; const reader = new FileReader(); reader.onload = () => { const dataUrl = reader.result as string; editor.chain().focus().setImage({ src: dataUrl }).run(); }; reader.readAsDataURL(file); break; } } }, [editor]); if (!editor) return null; return (
); }