"use client" // @-tagging (ADR-063) -- delt UI mellom innleggs-komposereren // (round-messages.tsx) og kommentar-komposereren (post-engagement.tsx). // Selve logikken (offset-regning, tekst-diffing) er bevisst flyttet ut i // lib/mentions.ts og enhetstestet der -- denne fila er ren presentasjon // og DOM-/fokushåndtering. import type React from "react" import Link from "next/link" import { useEffect, useRef, useState } from "react" import { cn } from "@/lib/utils" import { adjustTagsForEdit, detectActiveMention, fetchTaggablePeople, insertMention, segmentTaggedText, type Tag, type TaggablePerson, } from "@/lib/mentions" type MentionTextareaProps = { roundId: string value: string tags: Tag[] onChange: (value: string, tags: Tag[]) => void placeholder?: string rows?: number id?: string className?: string autoFocus?: boolean // Videresendes KUN når dropdownen ikke er åpen -- Enter/piltaster skal // styre forslagslisten når den vises, ikke utløse f.eks. avsenderens // egen Cmd/Ctrl+Enter-innsending samtidig (post-engagement.tsx). onKeyDownWhenClosed?: (e: React.KeyboardEvent) => void } export function MentionTextarea({ roundId, value, tags, onChange, placeholder, rows = 3, id, className, autoFocus, onKeyDownWhenClosed, }: MentionTextareaProps) { const textareaRef = useRef(null) const [mention, setMention] = useState<{ start: number; query: string } | null>(null) const [suggestions, setSuggestions] = useState([]) const [loadingSuggestions, setLoadingSuggestions] = useState(false) const [highlighted, setHighlighted] = useState(0) // Markørposisjonen som stod da @-forsøket sist ble oppdatert -- trengs // for å vite hvor SLUTTEN av "@søketekst" er ved faktisk innsetting // (markøren kan ha rukket å flytte seg videre siden selve deteksjonen). const cursorAtDetectionRef = useRef(0) const pendingCursorRef = useRef(null) const open = mention !== null // Debouncet henting av kandidater -- kun mens dropdownen faktisk er åpen. useEffect(() => { if (!open) { setSuggestions([]) return } let cancelled = false setLoadingSuggestions(true) const handle = setTimeout(async () => { const people = await fetchTaggablePeople(roundId, mention.query) if (!cancelled) { setSuggestions(people) setHighlighted(0) setLoadingSuggestions(false) } }, 200) return () => { cancelled = true clearTimeout(handle) } // eslint-disable-next-line react-hooks/exhaustive-deps -- kun query/roundId skal trigge ny henting }, [open, mention?.query, roundId]) // Sett markøren riktig sted ETTER at React har rendret den nye, // lengre/kortere verdien -- kan ikke gjøres synkront i onChange, siden //