@onesy/ui-react
Version:
UI for React
81 lines (77 loc) • 2.67 kB
JavaScript
import React from 'react';
import { hash, isEnvironment } from '@onesy/utils';
const useVisible = props => {
const {
element,
visibleDefault,
options,
addClasses,
classes = {
in: 'onesy-visible'
},
addStyles,
styles
} = props;
const [response, setResponse] = React.useState({
visible: visibleDefault !== undefined ? visibleDefault : false
});
const [root, setRoot] = React.useState();
const refs = {
root: React.useRef(root),
response: React.useRef(response),
addClasses: React.useRef(addClasses),
classes: React.useRef(classes),
addStyles: React.useRef(addStyles),
styles: React.useRef(styles)
};
refs.root.current = root;
refs.response.current = response;
refs.addClasses.current = addClasses;
refs.classes.current = classes;
refs.addStyles.current = addStyles;
refs.styles.current = styles;
// Root
React.useEffect(() => {
const rootNew = element;
setRoot(rootNew);
refs.root.current = rootNew;
}, [element]);
const method = entries => {
entries.forEach(entry => {
const properties = ['boundingClientRect', 'intersectionRatio', 'intersectionRect', 'isIntersecting', 'isVisible', 'rootBounds', 'target', 'time'];
const responseNew = {
visible: !!entry.isIntersecting,
percentage: entry.intersectionRatio
};
properties.forEach(property => responseNew[property] = entry[property]);
const target = entry.target;
// classes
if (refs.addClasses.current) {
const visibleClass = refs.classes.current?.in || 'onesy-visible';
if (responseNew.visible) target.classList.add(visibleClass);else target.classList.remove(visibleClass);
}
// styles
if (refs.addStyles.current) {
const visibleStyles = refs.styles.current?.in || {};
const notVisibleStyles = refs.styles.current?.out || {};
if (responseNew.visible) Object.keys(visibleStyles).forEach(item => target.style[item] = visibleStyles[item]);else Object.keys(notVisibleStyles).forEach(item_0 => target.style[item_0] = notVisibleStyles[item_0]);
}
setResponse(responseNew);
});
};
React.useEffect(() => {
if (!(isEnvironment('browser') && 'IntersectionObserver' in window)) return;
// Add new observer listener
const observer = new IntersectionObserver(method, options);
if (root) {
observer.observe(root);
}
return () => {
// Clean up
observer.disconnect();
};
}, [root, options?.root, options?.rootMargin, hash(options?.threshold)]);
return response;
};
useVisible.displayName = 'onesy-UseVisible';
export default useVisible;