"use client"; import { Agent } from "@atproto/api"; import { Input } from "components/Input"; import { Combobox, ComboboxResult } from "components/Combobox"; import { useRef, useState } from "react"; import { useDebouncedEffect } from "src/hooks/useDebouncedEffect"; import { DotLoader } from "components/utils/DotLoader"; import { theme } from "tailwind.config"; import { AtmosphereAccount } from "components/Icons/AtmosphereAccount"; type ActorSuggestion = { handle: string; did: string; displayName?: string; avatar?: string; }; export const HandleInput = (props: { autoFocus?: boolean; action?: React.ReactNode; className?: string; large?: boolean; loading?: boolean; onSubmit?: (handle: string) => void; }) => { let [handleValue, setHandleValue] = useState(""); let [suggestions, setSuggestions] = useState([]); let [dropdownOpen, setDropdownOpen] = useState(false); let [highlighted, setHighlighted] = useState(undefined); let requestIdRef = useRef(0); useDebouncedEffect( async () => { if (!handleValue) { setSuggestions([]); setDropdownOpen(false); return; } const requestId = ++requestIdRef.current; const agent = new Agent("https://public.api.bsky.app"); const result = await agent.searchActorsTypeahead({ q: handleValue, limit: 8, }); if (requestId !== requestIdRef.current) return; const actors = result.data.actors.map((actor) => ({ handle: actor.handle, did: actor.did, displayName: actor.displayName, avatar: actor.avatar, })); setSuggestions(actors); setDropdownOpen(actors.length > 0); }, 300, [handleValue], ); const handleSelect = (handle?: string) => { const selected = handle ?? handleValue; if (!selected) return; setHandleValue(selected); setDropdownOpen(false); setSuggestions([]); setHighlighted(undefined); props.onSubmit?.(selected); }; const handles = suggestions.map((s) => s.handle); return ( { if (!open) { setDropdownOpen(false); setHighlighted(undefined); } }} results={handles} highlighted={highlighted} setHighlighted={setHighlighted} onSelect={() => handleSelect(highlighted)} zIndex={60} sideOffset={4} className="w-(--radix-popover-trigger-width)!" trigger={
setHandleValue(e.target.value)} onClick={(e) => e.stopPropagation()} onPointerDown={(e) => e.stopPropagation()} autoComplete="off" disabled={props.loading} /> {props.loading ? ( ) : props.onSubmit ? ( ) : ( props.action )}
} > {suggestions.map((actor) => ( handleSelect(actor.handle)} className=" flex-row! gap-2! leading-snug text-sm" > {actor.avatar ? ( ) : (
)}
{actor.displayName || actor.handle}
{actor.displayName && (
@{actor.handle}
)}
))} ); };