{(search.loading || search.error) && (
{search.loading ? (
<>
{" "}
{search.symbol
? formatMessage(tx("Searching for usages of '{symbol}'"), { symbol: search.symbol })
: tx("Searching for usages")}
…
>
) : (
{search.error}
)}
)}
}>
key={`${search.id}:${accessOptions.read}:${accessOptions.write}`}
aria-label="Usages"
handleRef={tree}
roots={roots}
getKey={(n) => n.key}
getLabel={(n) =>
n.kind === "summary"
? tx("Found usages")
: n.kind === "file"
? basename(n.group.path)
: n.usage.text.trim()
}
getChildren={getChildren}
isExpandable={(n) => n.kind !== "usage"}
isOccurrence={(n) => n.kind === "usage" && !excluded.has(n.key)}
expanded={expanded}
onExpandedChange={(next) =>
setCollapsed({
id: search.id,
keys: new Set([SUMMARY_KEY, ...files.map((f) => f.key)].filter((k) => !next.has(k))),
})
}
renderNode={renderNode}
multiSelect={false}
onSelectionChange={(_sel, node) => setLead(node)}
onContextMenu={(n, _sel, e) => {
if (!n) return;
showContextMenu(e, [
{
id: "exclude",
label: isExcluded(n) ? "Include" : "Exclude",
shortcut: "⌫",
run: () => {
setLead(n);
const next = toggleExcludedUsages(excluded, nodeUsages(n, files));
useExcluded.setState((s) => ({ byTab: { ...s.byTab, [search.id]: next } }));
},
},
]);
}}
onActivate={(n) => {
const u = n.kind === "usage" ? n.usage : n.kind === "file" ? n.group.usages[0] : undefined;
if (u) openUsage(u, true);
}}
empty={
!search.loading && !search.error ? (
{total ? tx("No usages match the access filters") : No usages found}
) : undefined
}
/>