Skip to content

Commit 4f23c9c

Browse files
committed
improve readability and maintainability
1 parent 228ea74 commit 4f23c9c

File tree

1 file changed

+87
-67
lines changed

1 file changed

+87
-67
lines changed

lib/use-visibility-sensor.js

+87-67
Original file line numberDiff line numberDiff line change
@@ -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+
24101
export 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

Comments
 (0)