()
| 19 | ) |
| 20 | |
| 21 | const App = () => { |
| 22 | const parentRef = React.useRef<HTMLDivElement>(null) |
| 23 | |
| 24 | const activeStickyIndexRef = React.useRef(0) |
| 25 | |
| 26 | const stickyIndexes = React.useMemo( |
| 27 | () => groups.map((gn) => findIndex(rows, (n) => n === gn)), |
| 28 | [], |
| 29 | ) |
| 30 | |
| 31 | const isSticky = (index: number) => stickyIndexes.includes(index) |
| 32 | |
| 33 | const isActiveSticky = (index: number) => |
| 34 | activeStickyIndexRef.current === index |
| 35 | |
| 36 | const rowVirtualizer = useVirtualizer({ |
| 37 | count: rows.length, |
| 38 | estimateSize: () => 50, |
| 39 | getScrollElement: () => parentRef.current, |
| 40 | rangeExtractor: React.useCallback( |
| 41 | (range: Range) => { |
| 42 | activeStickyIndexRef.current = |
| 43 | [...stickyIndexes] |
| 44 | .reverse() |
| 45 | .find((index) => range.startIndex >= index) ?? 0 |
| 46 | |
| 47 | const next = new Set([ |
| 48 | activeStickyIndexRef.current, |
| 49 | ...defaultRangeExtractor(range), |
| 50 | ]) |
| 51 | |
| 52 | return [...next].sort((a, b) => a - b) |
| 53 | }, |
| 54 | [stickyIndexes], |
| 55 | ), |
| 56 | }) |
| 57 | |
| 58 | return ( |
| 59 | <div> |
| 60 | <div |
| 61 | ref={parentRef} |
| 62 | className="List" |
| 63 | style={{ |
| 64 | height: `300px`, |
| 65 | width: `400px`, |
| 66 | overflow: 'auto', |
| 67 | }} |
| 68 | > |
| 69 | <div |
| 70 | style={{ |
| 71 | height: `${rowVirtualizer.getTotalSize()}px`, |
| 72 | width: '100%', |
| 73 | position: 'relative', |
| 74 | }} |
| 75 | > |
| 76 | {rowVirtualizer.getVirtualItems().map((virtualRow) => ( |
| 77 | <div |
| 78 | key={virtualRow.index} |
nothing calls this directly
no test coverage detected