Skip to content

Commit 7834241

Browse files
committed
Add option to observe horizontal intersection
1 parent 418e4c3 commit 7834241

File tree

1 file changed

+33
-17
lines changed

1 file changed

+33
-17
lines changed

src/render-if-visible.tsx

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@ type Props = {
77
* Default: false
88
*/
99
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'
1214
/** How far outside the viewport in pixels should elements be considered visible? */
1315
visibleOffset?: number
1416
/** Should the element stay rendered after it becomes visible? */
@@ -25,7 +27,8 @@ type Props = {
2527

2628
const RenderIfVisible = ({
2729
initialVisible = false,
28-
defaultHeight = 300,
30+
defaultSize = 300,
31+
direction = 'vertical',
2932
visibleOffset = 1000,
3033
stayRendered = false,
3134
root = null,
@@ -37,7 +40,7 @@ const RenderIfVisible = ({
3740
}: Props) => {
3841
const [isVisible, setIsVisible] = useState<boolean>(initialVisible)
3942
const wasVisible = useRef<boolean>(initialVisible)
40-
const placeholderHeight = useRef<number>(defaultHeight)
43+
const placeholderSize = useRef<number>(defaultSize)
4144
const intersectionRef = useRef<HTMLDivElement>(null)
4245

4346
// Set visibility with intersection observer
@@ -46,9 +49,12 @@ const RenderIfVisible = ({
4649
const localRef = intersectionRef.current
4750
const observer = new IntersectionObserver(
4851
(entries) => {
49-
// Before switching off `isVisible`, set the height of the placeholder
52+
// Before switching off `isVisible`, set the size of the placeholder
5053
if (!entries[0].isIntersecting) {
51-
placeholderHeight.current = localRef!.offsetHeight
54+
placeholderSize.current =
55+
direction === 'vertical'
56+
? localRef!.offsetHeight
57+
: localRef!.offsetWidth
5258
}
5359
if (typeof window !== undefined && window.requestIdleCallback) {
5460
window.requestIdleCallback(
@@ -61,7 +67,13 @@ const RenderIfVisible = ({
6167
setIsVisible(entries[0].isIntersecting)
6268
}
6369
},
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+
}
6577
)
6678

6779
observer.observe(localRef)
@@ -72,15 +84,18 @@ const RenderIfVisible = ({
7284
}
7385
}
7486
return () => {}
75-
}, [])
87+
}, [direction])
7688

7789
useEffect(() => {
7890
if (isVisible) {
7991
wasVisible.current = true
8092
}
8193
}, [isVisible])
8294

83-
const placeholderStyle = { height: placeholderHeight.current }
95+
const placeholderStyle =
96+
direction === 'vertical'
97+
? { height: placeholderSize.current }
98+
: { width: placeholderSize.current }
8499
const rootClasses = useMemo(
85100
() => `renderIfVisible ${rootElementClass}`,
86101
[rootElementClass]
@@ -91,14 +106,15 @@ const RenderIfVisible = ({
91106
)
92107

93108
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+
),
102118
ref: intersectionRef,
103119
className: rootClasses,
104120
})

0 commit comments

Comments
 (0)