UNPKG

@onesy/ui-react

Version:
81 lines (77 loc) 2.67 kB
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;