import React, { useState, useEffect, useRef, useLayoutEffect } from "react"; import { css, cx } from "emotion"; import { useHistory } from "react-router-dom"; import { ReactComponent as Logo } from "../assets/logo.svg"; import { ReactComponent as Right } from "../assets/arrow-right.svg"; import { getTimeout } from "../util"; import Menu from "./Menu"; import useMediaQuery from "../util/useMediaQuery"; const flash = css` span& { width: 5.6rem; height: 5.6rem; top: -0.2rem; left: -0.05rem; opacity: 1; } `; const [timer, clear] = getTimeout(); const Container: React.FunctionComponent<{ children: (string | React.DetailedReactHTMLElement | React.ReactElement)[]; hideNav?: boolean; arrowReversed?: boolean; next?: string; className?: string; }> = ({ children: _children, hideNav = false, arrowReversed = false, next, className, ...props }) => { const history = useHistory(); const mobile = useMediaQuery("(max-width: 50rem)"); const logoContainer = useRef(null); const logo = useRef(null); const highlightCircle = useRef(null); const containerChild = useRef(null); const nextBtn = useRef(null); const [showMenu, setShowMenu] = useState(false); const children = React.Children.map( _children, (child: string | React.DetailedReactHTMLElement | React.ReactElement) => !child || typeof child === "string" ? child : React.cloneElement(child, { style: { opacity: 0, transform: "translateY(3rem)", transition: "all 300ms" }, }), ); useEffect(() => { // scroll back to top when new page is loaded window.scrollTo({ top: 0 }); if (highlightCircle.current) { highlightCircle.current.classList.add(flash); timer(() => highlightCircle.current && highlightCircle.current.classList.remove(flash), 1500); } if (nextBtn.current) { nextBtn.current.style.width = "4rem"; timer(() => nextBtn.current && (nextBtn.current.style.right = "10vw"), 300); } if (containerChild.current) { const containerChildren = [...containerChild.current.children] as ( | HTMLElement | SVGElement )[]; containerChildren.forEach((child, idx) => { timer(() => { child.style.removeProperty("opacity"); child.style.removeProperty("transform"); }, 100 * idx); }); timer(() => { document.body.style.maxHeight = "auto"; document.body.style.overflow = "auto"; }, containerChildren.length * 100); } // cleanup return clear; }, []); const handleResize = () => { if (containerChild.current && logoContainer.current) logoContainer.current.style.left = `${containerChild.current.getBoundingClientRect().x}px`; }; useEffect(() => { window.addEventListener("resize", handleResize); // cleanup return () => window.removeEventListener("resize", handleResize); }, []); // on first render useLayoutEffect(handleResize, []); const handleNext: React.MouseEventHandler = e => { if (containerChild.current) { ([...containerChild.current.children] as (HTMLElement | SVGElement)[]).forEach(child => { child.style.marginBottom = "2rem"; child.style.opacity = "0"; }); } document.body.style.maxHeight = "100vh"; document.body.style.overflow = "hidden"; e.currentTarget.style.width = "0"; timer(() => next && history.push(next), 300); }; return (
{!hideNav && ( )} {next && ( )}
* { margin-bottom: 2rem; } `, className, )} ref={containerChild} {...props}> {children}
); }; export default Container;