1/** Save the row at the current offset; a virtualizer's cached visible range can lag a fling. */
2export function resolveWorkGroupScrollAnchor(state: {
3 readonly data: ReadonlyArray<{ readonly id: string }>;
4 readonly scroll: number;
5 readonly positionAtIndex: (index: number) => number | undefined;
6}) {
7 if (state.data.length === 0 || !Number.isFinite(state.scroll)) return undefined;
8 const scrollOffset = Math.max(0, state.scroll);
9 let low = 0;
10 let high = state.data.length - 1;
11 let index = 0;
12 let rowTop = state.positionAtIndex(0);
13 if (rowTop === undefined || !Number.isFinite(rowTop)) return undefined;
14
15 while (low <= high) {
16 const middle = Math.floor((low + high) / 2);
17 const top = state.positionAtIndex(middle);
18 if (top === undefined || !Number.isFinite(top)) return undefined;
19 if (top <= scrollOffset) {
20 index = middle;
21 rowTop = top;
22 low = middle + 1;
23 } else {
24 high = middle - 1;
25 }
26 }
27
28 return {
29 rowId: state.data[index]!.id,
30 offsetWithinRow: Math.max(0, scrollOffset - rowTop),
31 scrollOffset,
32 };
33}