Skip to content
Source
Sign inSign up
Open History to see the last commit

ThreadSearchMatch.tsx

51 lines1.6 KB

1import {
2 findSearchTokenRanges,
3 splitSearchText,
4 type SearchMatchHint,
5 type SearchRange,
6} from "@t3tools/shared/paletteSearch";
7​
8/** `text` with each range in semibold foreground. */
9function HighlightedSearchText(props: { text: string; ranges: ReadonlyArray<SearchRange> }) {
10 if (props.ranges.length === 0) return props.text;
11 return splitSearchText(props.text, props.ranges).map((part) =>
12 part.highlighted ? (
13 <mark className="bg-transparent font-semibold text-foreground" key={part.start}>
14 {part.text}
15 </mark>
16 ) : (
17 part.text
18 ),
19 );
21​
22/** Why a row matched when its title does not show it: the field and its match. */
23export function SearchMatchHintLine(props: { hint: SearchMatchHint }) {
24 return (
25 <span className="truncate text-xs text-muted-foreground/85">
26 <span className="text-muted-foreground/70">{props.hint.label}:</span>{" "}
27 <HighlightedSearchText text={props.hint.text} ranges={props.hint.ranges} />
28 </span>
29 );
31​
32export function ThreadSearchMatchExcerpt(props: {
33 match: {
34 readonly source: "user" | "assistant";
35 readonly snippet: string;
36 readonly query: string;
37 };
38}) {
39 const isUser = props.match.source === "user";
40 return (
41 <span className="truncate text-xs text-muted-foreground/85">
42 <span className={isUser ? "text-info-foreground" : "text-success-foreground"}>
43 {isUser ? "You:" : "Agent:"}
44 </span>{" "}
45 <HighlightedSearchText
46 text={props.match.snippet}
47 ranges={findSearchTokenRanges(props.match.snippet, props.match.query)}
48 />
49 </span>
50 );