import { useEffect, useState } from 'react' import type { FormEvent } from 'react' import { Link2Icon, Trash2Icon, XIcon } from 'lucide-react' import { buildLinkRel, normalizeHref } from '../../utils/link' export type LinkModalValue = { href: string newTab: boolean nofollow: boolean } type LinkModalProps = { /** مقادیر اولیه — از لینک فعال زیر نشانگر یا خالی برای لینک تازه */ initial: LinkModalValue /** ویرایش لینک موجود (دکمه «حذف لینک» نمایش داده می‌شود) */ editing: boolean onApply: (value: LinkModalValue) => void onRemove: () => void onClose: () => void } const FIELD_CLASS = 'mt-2 w-full border border-ivory/15 bg-char px-3 py-2 text-sm font-light text-ivory placeholder:text-ivory/30 focus:border-copper focus:outline-none' /** مدت انیمیشن ورود/خروج — با duration-300 کلاس‌ها هماهنگ است */ const TRANSITION_MS = 300 /** * مودال ثبت و ویرایش لینک — انیمیشن نرم fade و scale با کلاس‌های Tailwind. * ورود با یک فریم تاخیر (تا کلاس‌های بسته اعمال شوند) و خروج پیش از بستن مودال اجرا می‌شود. * جایگزین پنجره پیش‌فرض مرورگر برای لینک شده است. */ export function LinkModal({ initial, editing, onApply, onRemove, onClose }: LinkModalProps) { const [href, setHref] = useState(initial.href) const [newTab, setNewTab] = useState(initial.newTab) const [nofollow, setNofollow] = useState(initial.nofollow) const [error, setError] = useState('') const [visible, setVisible] = useState(false) const [closing, setClosing] = useState(false) // انیمیشن ورود: ابتدا حالت بسته رندر می‌شود، سپس به حالت باز می‌رود useEffect(() => { const frame = window.requestAnimationFrame(() => setVisible(true)) return () => window.cancelAnimationFrame(frame) }, []) /** بستن نرم: اول انیمیشن خروج کامل می‌شود، بعد عملیات و unmount */ const closeWith = (action?: () => void) => { if (closing) return setClosing(true) setVisible(false) window.setTimeout(() => { action?.() onClose() }, TRANSITION_MS) } const submit = (event: FormEvent) => { event.preventDefault() const normalized = normalizeHref(href) if (!normalized) { setError('نشانی معتبر نیست — نمونه: https://example.com یا /contact') return } closeWith(() => onApply({ href: normalized, newTab, nofollow })) } const relPreview = buildLinkRel({ newTab, nofollow }) return (
{/* پس‌زمینه تار — fade نرم */}
closeWith()} aria-hidden="true" /> {/* کارت مودال — fade + scale نرم */}

{/* نشانی */} { setHref(event.target.value) if (error) setError('') }} placeholder="https://example.com" className={FIELD_CLASS} /> {error && (

{error}

)} {/* باز شدن در تب جدید */} {/* نوع لینک از نظر سئو */}
انتقال اعتبار سئو (rel)
{[ { key: 'dofollow', label: 'Dofollow', hint: 'اعتبار سئو به مقصد منتقل می‌شود', value: false }, { key: 'nofollow', label: 'Nofollow', hint: 'گوگل این لینک را دنبال نکند', value: true }, ].map((option) => ( ))}
{relPreview && (

rel="{relPreview}"

)} {/* دکمه‌ها */}
{editing ? ( ) : ( )}
) }