export default (domRef, { initialScroll = null, inaccuracy = 0, runScroll = defaultRunScroll, } = {}) => { const wasScrolled = useRef(null); const isScrolled = useCallback( () => Math.ceil(domRef.current.scrollTop) >= maxScrollTop(domRef.current) - inaccuracy, [inaccuracy], ); useLayoutEffect(() => { const onScroll = () => { wasScrolled.current = isScrolled(); }; domRef.current.addEventListener('scroll', onScroll); return () => domRef.current.removeEventListener('scroll', onScroll); }, []); const scroll = useCallback((position) => { invariant(domRef.current !== null, `Trying to scroll to the bottom, but no element was found. Did you call this scrollBottom before the component with this hook finished mounting?`); const offset = position === Infinity ? maxScrollTop(domRef.current) : position; runScroll(domRef.current, offset); }, [runScroll]); const scrollBottom = useCallback(() => { scroll(Infinity); }, [scroll]); const stayScrolled = useCallback(() => { if (wasScrolled.current) scrollBottom(); return wasScrolled.current; }, [scrollBottom]); useLayoutEffect(() => { if (initialScroll !== null) { scroll(initialScroll); } wasScrolled.current = isScrolled(); }, []); return { scroll, stayScrolled, scrollBottom, isScrolled, }; };
function FocusOnMountMenuItem(props) { const listItemRef = React.useRef(null); React.useLayoutEffect(() => { listItemRef.current.focus(); }, []); return <MenuItem {...props} ref={listItemRef} tabIndex={0} />; }
const About = ({ aboutData }) => { const aboutContainerRef = useRef(null) useLayoutEffect(() => { const aboutContainer = aboutContainerRef.current const viewportHeight = Math.max( document.documentElement.clientHeight, window.innerHeight || 0, ) const aboutHeight = aboutContainer.clientHeight const offsetTop = aboutContainer.offsetTop const offsetBottom = viewportHeight - (offsetTop + aboutHeight) const validMargin = ((offsetTop + aboutHeight) / 100) * 20 if (offsetBottom > 0 && offsetBottom < validMargin) { const newPadding = (offsetBottom - 40) / 2 aboutContainer.style.padding = `${newPadding}px 0` } }, []) return ( <Container ref={aboutContainerRef}> {aboutData.map((paragraph, i) => ( <p key={i}>{paragraph}</p> ))} </Container> ) }
function useBodyScrollLock() { useLayoutEffect(() => { const originalOverflow = window.getComputedStyle(document.body).overflow console.log('originalOverflow:', originalOverflow) document.body.style.overflow = 'hidden'; // unlock the DOM on unmounting DishForm, destroy the effects return function cleanup() { document.body.style.overflow = originalOverflow; } // this ===> }, []) to ensure function is only run on mount }, []) }
export function Nevergreen({initalise, loaded, isFullScreen, children, clickToShowMenu, fullScreenRequested, enableFullScreen, checkForNewVersion}) { const fullScreenTimer = useRef() const disableFullScreen = throttle(() => { clearTimeout(fullScreenTimer.current) if (isFullScreen) { enableFullScreen(false) } if (fullScreenRequested) { fullScreenTimer.current = setTimeout(() => enableFullScreen(true), THREE_SECONDS) } }, ONE_SECOND, {trailing: false}) const checkVersion = useMemo(() => () => loaded && checkForNewVersion(version, window.location.hostname), [loaded]) useEffect(() => { initalise() }, []) useLayoutEffect(() => { enableFullScreen(fullScreenRequested) if (!fullScreenRequested) { clearTimeout(fullScreenTimer.current) } }, [fullScreenRequested]) useTimer(checkVersion, TWENTY_FOUR_HOURS) const disableFullScreenOn = clickToShowMenu ? {onClick: disableFullScreen} : {onMouseMove: disableFullScreen} return ( <> {loaded && <KeyboardShortcuts/>} <div className={styles.nevergreen} aria-busy={!loaded} tabIndex='-1' {...disableFullScreenOn}> <Header fullScreen={isFullScreen}/> <NotificationContainer/> {loaded && <main className={styles.main}>{children}</main>} <Footer fullScreen={isFullScreen}/> </div> </> ) }