@@ -7,8 +7,10 @@ type Props = {
7
7
* Default: false
8
8
*/
9
9
initialVisible ?: boolean
10
- /** An estimate of the element's height */
11
- defaultHeight ?: number
10
+ /** An estimate of the element's virtualized axis size (e.g. height for vertical scroll) */
11
+ defaultSize ?: number
12
+ /** Default = 'vertical' */
13
+ direction ?: 'vertical' | 'horizontal'
12
14
/** How far outside the viewport in pixels should elements be considered visible? */
13
15
visibleOffset ?: number
14
16
/** Should the element stay rendered after it becomes visible? */
@@ -25,7 +27,8 @@ type Props = {
25
27
26
28
const RenderIfVisible = ( {
27
29
initialVisible = false ,
28
- defaultHeight = 300 ,
30
+ defaultSize = 300 ,
31
+ direction = 'vertical' ,
29
32
visibleOffset = 1000 ,
30
33
stayRendered = false ,
31
34
root = null ,
@@ -37,7 +40,7 @@ const RenderIfVisible = ({
37
40
} : Props ) => {
38
41
const [ isVisible , setIsVisible ] = useState < boolean > ( initialVisible )
39
42
const wasVisible = useRef < boolean > ( initialVisible )
40
- const placeholderHeight = useRef < number > ( defaultHeight )
43
+ const placeholderSize = useRef < number > ( defaultSize )
41
44
const intersectionRef = useRef < HTMLDivElement > ( null )
42
45
43
46
// Set visibility with intersection observer
@@ -46,9 +49,12 @@ const RenderIfVisible = ({
46
49
const localRef = intersectionRef . current
47
50
const observer = new IntersectionObserver (
48
51
( entries ) => {
49
- // Before switching off `isVisible`, set the height of the placeholder
52
+ // Before switching off `isVisible`, set the size of the placeholder
50
53
if ( ! entries [ 0 ] . isIntersecting ) {
51
- placeholderHeight . current = localRef ! . offsetHeight
54
+ placeholderSize . current =
55
+ direction === 'vertical'
56
+ ? localRef ! . offsetHeight
57
+ : localRef ! . offsetWidth
52
58
}
53
59
if ( typeof window !== undefined && window . requestIdleCallback ) {
54
60
window . requestIdleCallback (
@@ -61,7 +67,13 @@ const RenderIfVisible = ({
61
67
setIsVisible ( entries [ 0 ] . isIntersecting )
62
68
}
63
69
} ,
64
- { root, rootMargin : `${ visibleOffset } px 0px ${ visibleOffset } px 0px` }
70
+ {
71
+ root,
72
+ rootMargin :
73
+ direction === 'vertical'
74
+ ? `${ visibleOffset } px 0px ${ visibleOffset } px 0px`
75
+ : `0px ${ visibleOffset } px 0px ${ visibleOffset } px` ,
76
+ }
65
77
)
66
78
67
79
observer . observe ( localRef )
@@ -72,15 +84,18 @@ const RenderIfVisible = ({
72
84
}
73
85
}
74
86
return ( ) => { }
75
- } , [ ] )
87
+ } , [ direction ] )
76
88
77
89
useEffect ( ( ) => {
78
90
if ( isVisible ) {
79
91
wasVisible . current = true
80
92
}
81
93
} , [ isVisible ] )
82
94
83
- const placeholderStyle = { height : placeholderHeight . current }
95
+ const placeholderStyle =
96
+ direction === 'vertical'
97
+ ? { height : placeholderSize . current }
98
+ : { width : placeholderSize . current }
84
99
const rootClasses = useMemo (
85
100
( ) => `renderIfVisible ${ rootElementClass } ` ,
86
101
[ rootElementClass ]
@@ -91,14 +106,15 @@ const RenderIfVisible = ({
91
106
)
92
107
93
108
return React . createElement ( rootElement , {
94
- children : isVisible || ( stayRendered && wasVisible . current ) ? (
95
- < > { children } </ >
96
- ) : (
97
- React . createElement ( placeholderElement , {
98
- className : placeholderClasses ,
99
- style : placeholderStyle ,
100
- } )
101
- ) ,
109
+ children :
110
+ isVisible || ( stayRendered && wasVisible . current ) ? (
111
+ < > { children } </ >
112
+ ) : (
113
+ React . createElement ( placeholderElement , {
114
+ className : placeholderClasses ,
115
+ style : placeholderStyle ,
116
+ } )
117
+ ) ,
102
118
ref : intersectionRef ,
103
119
className : rootClasses ,
104
120
} )
0 commit comments