Skip to content

Commit 04caac0

Browse files
committed
feat: add virtualize utility
1 parent 0ef81fa commit 04caac0

File tree

4 files changed

+502
-0
lines changed

4 files changed

+502
-0
lines changed

src/utils/virtualize.d.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
export interface VirtualizeConfig {
2+
/** Full array of items to virtualize */
3+
items: any[];
4+
/** Height of each item in pixels */
5+
itemHeight: number;
6+
/** Visible container height in pixels */
7+
containerHeight: number;
8+
/** Current scroll position */
9+
scrollTop: number;
10+
/** Extra items to render above/below viewport (default: 3) */
11+
overscan?: number;
12+
/** Cap maximum rendered items */
13+
maxItems?: number;
14+
/** Minimum items before virtualization activates (default: 100) */
15+
threshold?: number;
16+
}
17+
18+
export interface VirtualizeResult<T = any> {
19+
/** Items to render in the current viewport */
20+
visibleItems: T[];
21+
/** Index of first visible item */
22+
startIndex: number;
23+
/** Index after last visible item */
24+
endIndex: number;
25+
/** Y offset for positioning visible items */
26+
offsetY: number;
27+
/** Total height of all items */
28+
totalHeight: number;
29+
/** Whether virtualization is active */
30+
isVirtualized: boolean;
31+
}
32+
33+
export function virtualize<T = any>(
34+
config: VirtualizeConfig,
35+
): VirtualizeResult<T>;

src/utils/virtualize.js

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/**
2+
* Virtualizes a list to render only visible items for performance.
3+
*
4+
* @param {Object} config
5+
* @param {Array} config.items - Full array of items to virtualize
6+
* @param {number} config.itemHeight - Height of each item in pixels
7+
* @param {number} config.containerHeight - Visible container height in pixels
8+
* @param {number} config.scrollTop - Current scroll position
9+
* @param {number} [config.overscan=3] - Extra items to render above/below viewport
10+
* @param {number} [config.maxItems] - Cap maximum rendered items
11+
* @param {number} [config.threshold=100] - Minimum items before virtualization activates
12+
*
13+
* @returns {{
14+
* visibleItems: Array,
15+
* startIndex: number,
16+
* endIndex: number,
17+
* offsetY: number,
18+
* totalHeight: number,
19+
* isVirtualized: boolean
20+
* }}
21+
*/
22+
export function virtualize({
23+
items,
24+
itemHeight,
25+
containerHeight,
26+
scrollTop,
27+
overscan = 3,
28+
maxItems = undefined,
29+
threshold = 100,
30+
}) {
31+
// Auto-disable if below threshold
32+
if (items.length < threshold) {
33+
return {
34+
visibleItems: items,
35+
startIndex: 0,
36+
endIndex: items.length,
37+
offsetY: 0,
38+
totalHeight: items.length * itemHeight,
39+
isVirtualized: false,
40+
};
41+
}
42+
43+
const totalHeight = items.length * itemHeight;
44+
45+
// Calculate visible range
46+
const startIndex = Math.max(0, Math.floor(scrollTop / itemHeight) - overscan);
47+
let endIndex = Math.min(
48+
items.length,
49+
Math.ceil((scrollTop + containerHeight) / itemHeight) + overscan,
50+
);
51+
52+
// Apply maxItems cap if specified
53+
if (maxItems && endIndex - startIndex > maxItems) {
54+
endIndex = startIndex + maxItems;
55+
}
56+
57+
const offsetY = startIndex * itemHeight;
58+
59+
return {
60+
visibleItems: items.slice(startIndex, endIndex),
61+
startIndex,
62+
endIndex,
63+
offsetY,
64+
totalHeight,
65+
isVirtualized: true,
66+
};
67+
}

0 commit comments

Comments
 (0)