-
-
Notifications
You must be signed in to change notification settings - Fork 55
/
VList.tsx
120 lines (114 loc) · 2.47 KB
/
VList.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
import { ReactElement, forwardRef, useRef } from "react";
import { ViewportComponentAttributes } from "./types";
import {
Virtualizer,
VirtualizerHandle,
VirtualizerProps,
} from "./Virtualizer";
/**
* Methods of {@link VList}.
*/
export interface VListHandle extends VirtualizerHandle {}
/**
* Props of {@link VList}.
*/
export interface VListProps
extends Pick<
VirtualizerProps,
| "children"
| "count"
| "overscan"
| "itemSize"
| "shift"
| "horizontal"
| "cache"
| "ssrCount"
| "item"
| "onScroll"
| "onScrollEnd"
| "onRangeChange"
>,
ViewportComponentAttributes {
/**
* If true, items are aligned to the end of the list when total size of items are smaller than viewport size. It's useful for chat like app.
*/
reverse?: boolean;
}
/**
* Virtualized list component. See {@link VListProps} and {@link VListHandle}.
*/
export const VList = forwardRef<VListHandle, VListProps>(
(
{
children,
count,
overscan,
itemSize,
shift,
horizontal,
reverse,
cache,
ssrCount,
item,
onScroll,
onScrollEnd,
onRangeChange,
style,
...attrs
},
ref
): ReactElement => {
const scrollRef = useRef<HTMLDivElement>(null);
const shouldReverse = reverse && !horizontal;
let element = (
<Virtualizer
ref={ref}
scrollRef={shouldReverse ? scrollRef : undefined}
count={count}
overscan={overscan}
itemSize={itemSize}
shift={shift}
horizontal={horizontal}
cache={cache}
ssrCount={ssrCount}
item={item}
onScroll={onScroll}
onScrollEnd={onScrollEnd}
onRangeChange={onRangeChange}
>
{children}
</Virtualizer>
);
if (shouldReverse) {
element = (
<div
style={{
visibility: "hidden",
display: "flex",
flexDirection: "column",
justifyContent: "flex-end",
minHeight: "100%",
}}
>
{element}
</div>
);
}
return (
<div
ref={scrollRef}
{...attrs}
style={{
display: horizontal ? "inline-block" : "block",
[horizontal ? "overflowX" : "overflowY"]: "auto",
contain: "strict",
width: "100%",
height: "100%",
...style,
}}
>
{element}
</div>
);
}
);