1import type { ThreadFindStart } from "./threadFind";
2import { collectThreadFindRanges } from "./threadFindHighlights";
3
4/** Anchor to the first row being read, skipping occurrences above its viewport. */
5export function readThreadFindPosition(
6 container: HTMLElement,
7 query: string,
8 resolveEntry: (rowId: string) => string | undefined,
9 contentInsetEndAdjustment: number,
10): ThreadFindStart | undefined {
11 const viewport = container.getBoundingClientRect();
12 for (const row of container.querySelectorAll<HTMLElement>("[data-timeline-row-id]")) {
13 const rect = row.getBoundingClientRect();
14 if (rect.bottom <= viewport.top || rect.top >= viewport.bottom - contentInsetEndAdjustment)
15 continue;
16 const rowId = row.dataset.timelineRowId;
17 const entryId = rowId ? resolveEntry(rowId) : undefined;
18 if (!entryId) continue;
19 const matches = collectThreadFindRanges(row, query);
20 const next = matches.find((match) => match.range.getBoundingClientRect().bottom > viewport.top);
21 return { entryId, occurrence: next?.occurrence ?? matches.length };
22 }
23 return undefined;
24}