@@ -21,6 +21,83 @@ function roundRectDown(rect) {
21
21
} ;
22
22
}
23
23
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
+
24
101
export default function useVisibilitySensor (
25
102
nodeRef ,
26
103
{
@@ -52,78 +129,21 @@ export default function useVisibilitySensor(
52
129
const visibilityCheck = useCallback (
53
130
( ) => {
54
131
const el = nodeRef && nodeRef . current ;
55
- let rect ;
56
- let containmentRect ;
57
-
58
132
// if the component has rendered to null, dont update visibility
59
133
if ( ! el ) {
60
134
return ;
61
135
}
62
136
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
+ ) ;
127
147
128
148
// notify the parent when the value changes
129
149
if ( isVisible !== nextIsVisible ) {
0 commit comments