import * as React from "react" import { Command } from "cmdk" import { useTranslate } from "@workspace/i18n" import { Button } from "@workspace/ui/components/button" import { ScrollArea } from "@workspace/ui/components/scroll-area" import { CornerDownLeftIcon, FileTextIcon, LoaderCircleIcon, } from "@workspace/ui/components/icon" import { splitHighlightSegments } from "./highlight" import { searchMessages } from "./messages" import type { SearchResultGroup, SearchResultItem } from "./types" export interface SearchResultsProps { groups: readonly SearchResultGroup[] hasMore: boolean isLoadingMore: boolean onLoadMore: VoidFunction onSelect: (item: SearchResultItem) => void query: string } export function SearchResults({ groups, hasMore, isLoadingMore, onLoadMore, onSelect, query, }: SearchResultsProps) { const t = useTranslate() return ( {groups.map((group) => { if (group.items.length === 0) return null return ( {group.icon} {group.label} {t(searchMessages.resultCount, { count: group.total ?? group.items.length, })} } > {group.items.map((item) => ( ))} ) })} {hasMore && (
)}
) } function SearchResultRow({ item, onSelect, query, }: { item: SearchResultItem onSelect: (item: SearchResultItem) => void query: string }) { const t = useTranslate() const value = [ item.id, item.title, item.description, ...(item.meta ?? []), ...(item.keywords ?? []), ] .filter(Boolean) .join(" ") return ( onSelect(item)} className="group/search-result flex items-center gap-3 rounded-xl border border-border/55 bg-background p-3 shadow-xs transition-colors hover:bg-muted" aria-label={t(searchMessages.selectResult, { title: item.title })} > {item.description && ( )} {item.meta?.map((line) => ( ))} ) } function ResultMedia({ item }: { item: SearchResultItem }) { if (item.image) { return ( {item.image.alt ) } return ( {item.icon ?? } ) } function HighlightedText({ text, query }: { text: string; query: string }) { let offset = 0 return splitHighlightSegments(text, query).map((segment) => { const key = `${offset}:${segment.highlighted ? "highlight" : "text"}` offset += segment.text.length return segment.highlighted ? ( {segment.text} ) : ( {segment.text} ) }) }