-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdemo.tsx
121 lines (106 loc) · 3.97 KB
/
demo.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import React, { useEffect, useRef, useState } from "react";
import ReactDOM from "react-dom/client";
import { useVirtualOverflowY, virtualOverflowCalcVisibleRect } from "..";
import { virtualOverflowUtils } from "../utils";
import { VirtualListY } from "../fixed-list-y";
import { VirtualGrid } from "../fixed-grid";
const itemsLine = Array.from({ length: 300 }).map((_, i) => `item ${i}`);
const itemsGrid = Array.from({ length: 300 }).map((_, iy) => Array.from({ length: 300 }).map((_, ix) => `item ${ix} ${iy}`));
function ListWithHookExample() {
const [items, setItems] = useState([] as string[]);
const containerRef = useRef<HTMLDivElement>(undefined!);
const infoRef = useRef<HTMLDivElement>(undefined!);
const itemHeight = 40;
const { renderedItems, updateViewRect, itemSlice } = useVirtualOverflowY({
containerRef,
itemHeight,
itemsLengthY: items.length,
overscanItemsCount: 3,
calcVisibleRect: virtualOverflowUtils.calcVisibleRectOverflowed,
renderItem: (itemIndex, offsetTop, item = items[itemIndex]) => (
<div style={{ position: 'absolute', top: `${offsetTop}px` }} key={item}>
<div style={{ height: '40px' }}>{item}</div>
</div>
),
});
useEffect(() => {
// in case of animated containers
// setInterval(() => updateViewRect(), 8);
setInterval(() => {
const visibleRect = virtualOverflowCalcVisibleRect(containerRef.current);
infoRef.current.innerText = `Visible rect of content:\n\n${JSON.stringify(visibleRect, null, 2)}`;
}, 24);
}, []);
useEffect(() => {
if (itemSlice.topStartIndex + itemSlice.lengthY >= items.length - 4) {
// load more
setItems(prev => [...prev, ...itemsLine]);
}
}, [itemSlice.topStartIndex, itemSlice.lengthY]);
return (
<>
<div ref={infoRef} style={{ position: 'fixed', top: 0, right: 0, paddingRight: '40px', width: '200px' }}></div>
<div style={{ overflowY: 'scroll', height: '300px', background: 'lightgreen' }}>
<div ref={containerRef} style={{ position: 'relative', height: `${itemHeight * items.length}px` }}>
{renderedItems}
</div>
</div>
</>
);
}
function VerticalListExample() {
const items = itemsLine;
return (
<div style={{ overflowY: 'scroll', height: '300px', background: 'lightgreen' }}>
<VirtualListY
items={items}
itemHeight={40}
itemKey={x => x}
renderItem={item => <div style={{ height: '40px' }}>{item}</div>}
/>
</div>
);
}
function GridExample() {
const items = itemsGrid;
return (
<div style={{ overflowY: 'scroll', height: '300px', background: 'lightgreen' }}>
<VirtualGrid
items={items}
columnsNum={300}
itemWidth={40}
itemHeight={80}
itemKey={x => x}
overscanItemsCount={3}
renderItem={item => <div style={{ width: '40px', height: '80px' }}>{item}</div>}
/>
</div>
);
}
function App() {
return (
<div>
<div style={{
height: '700px', fontSize: '60px',
color: 'black'
}}>Scroll me down</div>
<div style={{ overflowY: 'scroll', height: '600px', background: 'blue' }}>
<div style={{
height: '700px', fontSize: '60px',
color: 'white'
}}>
Scroll me down
</div>
<ListWithHookExample />
</div>
<div style={{ height: '700px' }}></div>
</div>
);
}
const rootElement = document.getElementById("demo")!;
const root = ReactDOM.createRoot(rootElement);
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);