import { useEffect, useRef, useState } from "react"; import { Link } from "react-router-dom"; import type { PageSummary } from "@ledger/shared"; import { Icon } from "./Icon"; type Space = { id: string; name: string; key: string; visibility: string; }; export function CommandSearch({ open, onClose, onSearch, spaces, results, isLoading }: { open: boolean; onClose: () => void; onSearch: (query: string) => void; spaces: Space[]; results: PageSummary[]; isLoading: boolean; }) { const [query, setQuery] = useState(""); const inputRef = useRef(null); useEffect(() => { if (!open) { setQuery(""); return; } inputRef.current?.focus(); }, [open]); useEffect(() => { if (!open) { return; } const timeout = window.setTimeout(() => { onSearch(query); }, 180); return () => window.clearTimeout(timeout); }, [open, onSearch, query]); useEffect(() => { function handleKeyDown(event: KeyboardEvent) { if (event.key === "Escape") { onClose(); } } if (open) { window.addEventListener("keydown", handleKeyDown); } return () => window.removeEventListener("keydown", handleKeyDown); }, [onClose, open]); const grouped = results.reduce>((acc, result) => { acc[result.spaceId] = acc[result.spaceId] ?? []; acc[result.spaceId].push(result); return acc; }, {}); const spaceNameFor = (spaceId: string) => spaces.find((space) => space.id === spaceId)?.name ?? "Collection"; return ( <>
setQuery(event.target.value)} placeholder="Search docs, pages, and answers" aria-label="Search" />
{isLoading ?

Searching...

: null} {!isLoading && query.trim() && results.length === 0 ? (

No results found.

) : null} {!isLoading && !query.trim() ? (

Search by title or article content. Try a page name, keyword, or process.

) : null} {Object.entries(grouped).map(([spaceId, items]) => (
{spaceNameFor(spaceId)}
{items.map((result) => (
{result.title}

{result.excerpt ?? "Open this article to read more."}

{spaceNameFor(spaceId)} / {result.slug}
))}
))}
); }