@@ -21,6 +21,83 @@ function roundRectDown(rect) {
2121 } ;
2222}
2323
24+ function getContainmentRect ( containment , offset ) {
25+ let containmentRect ;
26+ if ( containment ) {
27+ const containmentDOMRect = containment . getBoundingClientRect ( ) ;
28+ containmentRect = {
29+ top : containmentDOMRect . top ,
30+ left : containmentDOMRect . left ,
31+ bottom : containmentDOMRect . bottom ,
32+ right : containmentDOMRect . right
33+ } ;
34+ } else {
35+ containmentRect = {
36+ top : 0 ,
37+ left : 0 ,
38+ bottom : window . innerHeight || document . documentElement . clientHeight ,
39+ right : window . innerWidth || document . documentElement . clientWidth
40+ } ;
41+ }
42+ // Check if visibility is wanted via offset?
43+ const hasValidOffset = typeof offset === "object" ;
44+ if ( hasValidOffset ) {
45+ containmentRect . top += offset . top || 0 ;
46+ containmentRect . left += offset . left || 0 ;
47+ containmentRect . bottom -= offset . bottom || 0 ;
48+ containmentRect . right -= offset . right || 0 ;
49+ }
50+
51+ return containmentRect ;
52+ }
53+
54+ function getVisibilityRect ( rect , containmentRect ) {
55+ return {
56+ top : rect . top >= containmentRect . top ,
57+ left : rect . left >= containmentRect . left ,
58+ bottom : rect . bottom <= containmentRect . bottom ,
59+ right : rect . right <= containmentRect . right
60+ } ;
61+ }
62+
63+ function checkIsVisible (
64+ rect ,
65+ containmentRect ,
66+ visibilityRect ,
67+ partialVisibility ,
68+ minTopValue
69+ ) {
70+ // https://github.com/joshwnj/react-visibility-sensor/pull/114
71+ const hasSize = rect . height > 0 && rect . width > 0 ;
72+ const isVisible =
73+ hasSize &&
74+ visibilityRect . top &&
75+ visibilityRect . left &&
76+ visibilityRect . bottom &&
77+ visibilityRect . right ;
78+
79+ // check for partial visibility
80+ if ( hasSize && partialVisibility ) {
81+ let partialVisible =
82+ rect . top <= containmentRect . bottom &&
83+ rect . bottom >= containmentRect . top &&
84+ rect . left <= containmentRect . right &&
85+ rect . right >= containmentRect . left ;
86+
87+ // account for partial visibility on a single edge
88+ if ( typeof partialVisibility === "string" ) {
89+ partialVisible = visibilityRect [ partialVisibility ] ;
90+ }
91+
92+ // if we have minimum top visibility set by props, lets check, if it meets the passed value
93+ // so if for instance element is at least 200px in viewport, then show it.
94+ return minTopValue
95+ ? partialVisible && rect . top <= containmentRect . bottom - minTopValue
96+ : partialVisible ;
97+ }
98+ return isVisible ;
99+ }
100+
24101export default function useVisibilitySensor (
25102 nodeRef ,
26103 {
@@ -52,78 +129,21 @@ export default function useVisibilitySensor(
52129 const visibilityCheck = useCallback (
53130 ( ) => {
54131 const el = nodeRef && nodeRef . current ;
55- let rect ;
56- let containmentRect ;
57-
58132 // if the component has rendered to null, dont update visibility
59133 if ( ! el ) {
60134 return ;
61135 }
62136
63- rect = normalizeRect ( roundRectDown ( el . getBoundingClientRect ( ) ) ) ;
64-
65- if ( containment ) {
66- const containmentDOMRect = containment . getBoundingClientRect ( ) ;
67- containmentRect = {
68- top : containmentDOMRect . top ,
69- left : containmentDOMRect . left ,
70- bottom : containmentDOMRect . bottom ,
71- right : containmentDOMRect . right
72- } ;
73- } else {
74- containmentRect = {
75- top : 0 ,
76- left : 0 ,
77- bottom : window . innerHeight || document . documentElement . clientHeight ,
78- right : window . innerWidth || document . documentElement . clientWidth
79- } ;
80- }
81-
82- // Check if visibility is wanted via offset?
83- const hasValidOffset = typeof offset === "object" ;
84- if ( hasValidOffset ) {
85- containmentRect . top += offset . top || 0 ;
86- containmentRect . left += offset . left || 0 ;
87- containmentRect . bottom -= offset . bottom || 0 ;
88- containmentRect . right -= offset . right || 0 ;
89- }
90-
91- const nextVisibilityRect = {
92- top : rect . top >= containmentRect . top ,
93- left : rect . left >= containmentRect . left ,
94- bottom : rect . bottom <= containmentRect . bottom ,
95- right : rect . right <= containmentRect . right
96- } ;
97-
98- // https://github.com/joshwnj/react-visibility-sensor/pull/114
99- const hasSize = rect . height > 0 && rect . width > 0 ;
100-
101- let nextIsVisible =
102- hasSize &&
103- nextVisibilityRect . top &&
104- nextVisibilityRect . left &&
105- nextVisibilityRect . bottom &&
106- nextVisibilityRect . right ;
107-
108- // check for partial visibility
109- if ( hasSize && partialVisibility ) {
110- let partialVisible =
111- rect . top <= containmentRect . bottom &&
112- rect . bottom >= containmentRect . top &&
113- rect . left <= containmentRect . right &&
114- rect . right >= containmentRect . left ;
115-
116- // account for partial visibility on a single edge
117- if ( typeof partialVisibility === "string" ) {
118- partialVisible = nextVisibilityRect [ partialVisibility ] ;
119- }
120-
121- // if we have minimum top visibility set by props, lets check, if it meets the passed value
122- // so if for instance element is at least 200px in viewport, then show it.
123- nextIsVisible = minTopValue
124- ? partialVisible && rect . top <= containmentRect . bottom - minTopValue
125- : partialVisible ;
126- }
137+ const rect = normalizeRect ( roundRectDown ( el . getBoundingClientRect ( ) ) ) ;
138+ const containmentRect = getContainmentRect ( containment , offset ) ;
139+ const nextVisibilityRect = getVisibilityRect ( rect , containmentRect ) ;
140+ const nextIsVisible = checkIsVisible (
141+ rect ,
142+ containmentRect ,
143+ nextVisibilityRect ,
144+ partialVisibility ,
145+ minTopValue
146+ ) ;
127147
128148 // notify the parent when the value changes
129149 if ( isVisible !== nextIsVisible ) {
0 commit comments