import { useEffect, useRef, useState } from 'react' import { NodeViewWrapper } from '@tiptap/react' import type { NodeViewProps } from '@tiptap/react' import { PlusIcon, XIcon } from 'lucide-react' type ImageAttrs = { src: string alt: string | null title: string | null caption: string | null } const DELETE_BUTTON_CLASS = 'flex h-7 w-7 shrink-0 items-center justify-center border border-red-400/50 bg-ink/85 text-red-300 backdrop-blur-sm transition-colors duration-150 hover:bg-red-500/20' const INLINE_FIELD_CLASS = 'w-full border border-ivory/15 bg-ink px-3 py-1.5 text-xs font-light text-ivory placeholder:text-ivory/30 focus:border-copper focus:outline-none' const ADD_CAPTION_CLASS = 'mt-1.5 inline-flex items-center gap-1.5 border border-dashed border-ivory/25 px-3 py-1 text-[11px] font-light text-ivory/50 transition-colors duration-150 hover:border-copper hover:text-copper' /** * نمایش تصویر مقاله در ویرایشگر — دقیقاً با همان ساختار خروجی سایت: *
کپشن
* * ویرایش کاملاً درون‌خطی است (بدون پاپ‌اور/مودال): * - هر تصویر یک «جعبه توضیح/کپشن» همراه خود دارد و متن آن در figcaption ذخیره می‌شود. * - دکمه X کپشن را کامل حذف می‌کند: صفت کپشن به مقدار پیش‌فرض برمی‌گردد و عنصر * figcaption با ورودی‌اش از DOM ویرایشگر (و از خروجی ذخیره‌شده) حذف می‌شود؛ * فقط تصویر می‌ماند و «افزودن کپشن» دوباره جعبه را باز می‌کند. * - ویرایش Alt در ویرایشگر وجود ندارد؛ Alt هنگام درج از نام فایل ثبت می‌شود. * - دکمه X روی تصویر کل تصویر را حذف می‌کند. */ export function ImageNodeView({ node, updateAttributes, deleteNode, selected }: NodeViewProps) { const { src, alt, title, caption } = node.attrs as ImageAttrs const hasCaption = Boolean((caption ?? '').trim()) const [captionOpen, setCaptionOpen] = useState(true) const captionInputRef = useRef(null) const focusOnOpen = useRef(false) const showCaption = captionOpen || hasCaption // فقط وقتی کاربر «افزودن کپشن» را می‌زند ورودی فوکوس می‌گیرد (نه هنگام بارگذاری مقاله) useEffect(() => { if (!focusOnOpen.current) return focusOnOpen.current = false captionInputRef.current?.focus() }, [captionOpen]) /** حذف کامل کپشن: عنصر figcaption و ورودی‌اش از DOM ویرایشگر بیرون می‌رود */ const removeCaption = () => { updateAttributes({ caption: '' }) setCaptionOpen(false) } const addCaption = () => { focusOnOpen.current = true setCaptionOpen(true) } return (
{alt {/* حذف کل تصویر */} {showCaption ? (
updateAttributes({ caption: event.target.value })} placeholder="توضیح تصویر (کپشن)…" aria-label="کپشن تصویر" className={INLINE_FIELD_CLASS} /> {/* حذف کامل کپشن — تصویر دست‌نخورده می‌ماند */}
) : ( )}
) }