"use client"; import { useEditor, EditorContent } from "@tiptap/react"; import StarterKit from "@tiptap/starter-kit"; import Placeholder from "@tiptap/extension-placeholder"; import Underline from "@tiptap/extension-underline"; import Highlight from "@tiptap/extension-highlight"; import TextAlign from "@tiptap/extension-text-align"; import Link from "@tiptap/extension-link"; import { Button } from "@/components/ui/button"; import { Separator } from "@/components/ui/separator"; import { Bold, Italic, UnderlineIcon, Strikethrough, Highlighter, Heading1, Heading2, Heading3, List, ListOrdered, Quote, Code, Code2, AlignLeft, AlignCenter, AlignRight, Minus, Undo2, Redo2, Link2, Link2Off, } from "lucide-react"; import { useCallback, useEffect } from "react"; interface Props { value?: string; onChange: (html: string) => void; placeholder?: string; minHeight?: string; } export function TiptapEditor({ value = "", onChange, placeholder = "Write your post content here…", minHeight = "320px", }: Props) { const editor = useEditor({ immediatelyRender: false, extensions: [ StarterKit.configure({ bulletList: { keepMarks: true, keepAttributes: false }, orderedList: { keepMarks: true, keepAttributes: false }, }), Underline, Highlight.configure({ multicolor: false }), TextAlign.configure({ types: ["heading", "paragraph"] }), Placeholder.configure({ placeholder }), Link.configure({ openOnClick: false, HTMLAttributes: { class: "text-primary underline underline-offset-2" }, }), ], content: value, onUpdate: ({ editor }) => { onChange(editor.getHTML()); }, }); // Sync external value changes (e.g. when edit form opens with existing content) useEffect(() => { if (!editor) return; const current = editor.getHTML(); if (value !== current) { editor.commands.setContent(value || "", { emitUpdate: false }); } }, [value, editor]); const setLink = useCallback(() => { if (!editor) return; const prev = editor.getAttributes("link").href as string | undefined; const url = window.prompt("URL", prev ?? "https://"); if (url === null) return; // cancelled if (url === "") { editor.chain().focus().extendMarkRange("link").unsetLink().run(); } else { editor.chain().focus().extendMarkRange("link").setLink({ href: url }).run(); } }, [editor]); if (!editor) return null; const btn = (active: boolean) => `h-7 w-7 p-0 ${active ? "bg-muted text-foreground" : "text-muted-foreground hover:text-foreground hover:bg-muted/60"}`; return (