import { useEffect, useRef, useState } from 'react' import type { CSSProperties, ElementType, KeyboardEvent } from 'react' import { useAdmin } from '../../admin/AdminContext' type InlineEditProps = { value: string /** ذخیره async — در صورت خطا، متن به مقدار قبلی برمی‌گردد */ onSave: (value: string) => Promise | boolean | void as?: ElementType /** چندخطی: Enter خط جدید می‌گذارد و فقط blur ذخیره می‌کند */ multiline?: boolean className?: string style?: CSSProperties 'aria-label'?: string } /** * ویرایش درجا متن — در حالت عادی دقیقاً همان HTML قبلی را رندر می‌کند * (بدون هیچ تغییر چیدمان) و فقط در Edit Mode برای ادمین قابل ویرایش می‌شود. */ export function InlineEdit({ value, onSave, as: Tag = 'span', multiline = false, className = '', style, ...rest }: InlineEditProps) { const { isAuthenticated, isEditMode } = useAdmin() const editing = isAuthenticated && isEditMode const ref = useRef(null) const [focused, setFocused] = useState(false) // همگام‌سازی متن فقط وقتی المان در حال ویرایش نیست (پرش نشانگر رخ ندهد) useEffect(() => { const el = ref.current if (el && !focused && el.innerText !== value) el.innerText = value }, [value, focused]) if (!editing) { return ( {value} ) } const commit = async () => { const el = ref.current if (!el) return setFocused(false) const next = el.innerText.replace(/\u00a0/g, ' ') if (next === value) return el.innerText = value // بازگشت فوری به مقدار فعلی؛ در صورت موفقیت، به‌روزرسانی خوش‌بینانه متن تازه می‌آید await onSave(next) } const onKeyDown = (e: KeyboardEvent) => { if (!multiline && e.key === 'Enter') { e.preventDefault() ;(e.currentTarget as HTMLElement).blur() } if (e.key === 'Escape') { if (ref.current) ref.current.innerText = value ;(e.currentTarget as HTMLElement).blur() } } return ( setFocused(true)} onBlur={commit} onKeyDown={onKeyDown} > {value} ) }