PullIn
uses useState
Find a definition in the codebase by name (findDefinitions: its letters in order) and pull it into the scratch
file (onPick, its name).
import { findDefinitions } from "#codebase/tcmts/studio"; import { useEffect, useState } from "react"; import { Button, Dialog, DialogTrigger, Input, ListBox, ListBoxItem, Popover, SearchField, } from "react-aria-components"; export function PullIn({ onPick }: { onPick: (name: string) => void }) { const [q, setQ] = useState(""); const [found, setFound] = useState<{ path: string; kind: string; signature: string }[]>([]); useEffect(() => { let live = true; const t = setTimeout(async () => { const r = await findDefinitions(q).catch(() => []); if (live) setFound(r); }, 150); return () => { live = false; clearTimeout(t); }; }, [q]); return ( <DialogTrigger onOpenChange={(open) => !open && setQ("")}> <Button className="btn">Pull in…</Button> <Popover className="menu-pop pullpop" placement="bottom end" offset={6}> <Dialog className="getit-body" aria-label="Pull a definition into this file"> {({ close }) => ( <> <SearchField aria-label="A definition's name" value={q} onChange={setQ} autoFocus> <Input className="field" placeholder="A definition's name" /> </SearchField> {found.length > 0 ? ( <ListBox className="menu pulllist" aria-label="Definitions" items={found.map((f) => ({ id: f.path, ...f }))} onAction={(k) => { close(); onPick(String(k)); }} > {(f) => ( <ListBoxItem id={f.id} className="opt" textValue={f.path}> <span className="mono">{f.path}</span> <span className="muted sig">{f.kind === "type" ? "type" : f.signature}</span> </ListBoxItem> )} </ListBox> ) : ( <p className="muted"> {q.trim() ? "No definition is named like that." : "Its name, or letters of it in order."} </p> )} </> )} </Dialog> </Popover> </DialogTrigger> ); }