UNPKG

@daimo/pay

Version:

Seamless crypto payments. Onboard users from any chain, any coin into your app with one click.

130 lines (127 loc) 6.8 kB
import { jsx, jsxs, Fragment } from 'react/jsx-runtime'; import { useState, useRef, useEffect } from 'react'; import { Slider, ImageContainer, ImageContainerInner, Slides, Slide, MobileImageContainer, Dots, Dot } from './styles.js'; import { MotionConfig, AnimatePresence } from 'framer-motion'; import useLocales from '../../../hooks/useLocales.js'; import { usePayContext } from '../../../hooks/usePayContext.js'; import Button from '../../Common/Button/index.js'; import FitText from '../../Common/FitText/index.js'; import { OrDivider } from '../../Common/Modal/index.js'; import { ModalH1, ModalBody, PageContent, ModalContent } from '../../Common/Modal/styles.js'; import { SlideOne, SlideTwo, SlideThree } from './graphics.js'; const About = () => { const locales = useLocales({ //CONNECTORNAME: connector.name, }); const context = usePayContext(); const ctaUrl = context.options?.ethereumOnboardingUrl ?? locales.aboutScreen_ctaUrl; const [ready, setReady] = useState(true); const [slider, setSlider] = useState(0); const interacted = useRef(false); const scrollPos = useRef(0); const animationEase = [0.16, 1, 0.3, 1]; const animationDuration = 600; let interval; useEffect(() => { return () => clearInterval(interval); }, []); // eslint-disable-line react-hooks/exhaustive-deps const isSwipe = () => { if (sliderRef.current) { const { overflow } = getComputedStyle(sliderRef.current); return overflow !== "visible"; } return false; }; const gotoSlide = (index) => { setReady(false); if (isSwipe()) { scrollToSlide(index); } else { setSlider(index); } }; const scrollToSlide = (index) => { if (sliderRef.current) { const { offsetWidth: width } = sliderRef.current; sliderRef.current.scrollLeft = width * index; setTimeout(() => setSlider(index), 100); } }; // This event should not fire on mobile const onScroll = () => { if (!sliderRef.current) return; const { offsetWidth: width, scrollLeft: x } = sliderRef.current; const prevScroll = scrollPos.current; scrollPos.current = x; // Limit when the slider should be set after swipe const threshold = 4; if (prevScroll - x > -threshold && prevScroll - x < threshold) { const currentSlide = Math.round(x / width); setSlider(currentSlide); } }; const onTouchMove = () => { didInteract(); }; const onTouchEnd = () => { const { offsetWidth: width, scrollLeft: x } = sliderRef.current; const currentSlide = Math.round(x / width); setSlider(currentSlide); }; const didInteract = () => { interacted.current = true; clearTimeout(interval); }; const sliderRef = useRef(null); useEffect(() => { const slider = sliderRef.current; if (slider == null) return; slider.addEventListener("scroll", onScroll); slider.addEventListener("touchmove", onTouchMove); slider.addEventListener("touchend", onTouchEnd); return () => { slider.removeEventListener("scroll", onScroll); slider.removeEventListener("touchmove", onTouchMove); slider.removeEventListener("touchend", onTouchEnd); }; }, [sliderRef.current]); // eslint-disable-line react-hooks/exhaustive-deps const graphics = [ jsx(SlideOne, { layoutId: "graphicCircle", duration: animationDuration, ease: animationEase }, "slideOne"), jsx(SlideTwo, { layoutId: "graphicCircle", duration: animationDuration, ease: animationEase }, "slideTwo"), jsx(SlideThree, { layoutId: "graphicCircle", duration: animationDuration, ease: animationEase }, "slideThree"), ]; const mobileGraphics = [ jsx(SlideOne, { duration: animationDuration, ease: animationEase }, "slideOne"), jsx(SlideTwo, { duration: animationDuration, ease: animationEase }, "slideTwo"), jsx(SlideThree, { duration: animationDuration, ease: animationEase }, "slideThree"), ]; // Adjust height of ModalBody to fit content based on language const slideHeight = (() => { switch (context.options?.language) { case "en-US": case "zh-CN": return 64; default: return 84; } })(); const slides = [ jsxs(Fragment, { children: [jsx(ModalH1, { style: { height: 24 }, "$small": true, children: jsx(FitText, { children: locales.aboutScreen_a_h1 }) }), jsx(ModalBody, { style: { height: slideHeight }, children: jsx(FitText, { children: locales.aboutScreen_a_p }) })] }), jsxs(Fragment, { children: [jsx(ModalH1, { style: { height: 24 }, "$small": true, children: jsx(FitText, { children: locales.aboutScreen_b_h1 }) }), jsx(ModalBody, { style: { height: slideHeight }, children: jsx(FitText, { children: locales.aboutScreen_b_p }) })] }), jsxs(Fragment, { children: [jsx(ModalH1, { style: { height: 24 }, "$small": true, children: jsx(FitText, { children: locales.aboutScreen_c_h1 }) }), jsx(ModalBody, { style: { height: slideHeight }, children: jsx(FitText, { children: locales.aboutScreen_c_p }) })] }), ]; return (jsxs(PageContent, { children: [jsxs(Slider, { children: [jsx(ImageContainer, { children: jsx(MotionConfig, { transition: { duration: animationDuration / 1000, ease: animationEase, }, children: jsx(AnimatePresence, { initial: false, onExitComplete: () => setReady(true), children: graphics.map((g, i) => slider === i && (jsx(ImageContainerInner, { style: { position: "absolute" }, children: g }, i))) }) }) }), jsx(Slides, { ref: sliderRef, children: jsx(AnimatePresence, { children: slides.map((s, i) => (jsxs(Slide, { "$active": slider === i, children: [jsx(MobileImageContainer, { children: jsx(MotionConfig, { transition: { duration: 0, }, children: jsx(ImageContainerInner, { children: mobileGraphics[i] }) }) }), jsx(ModalContent, { style: { gap: 8, paddingBottom: 0 }, children: s })] }, i))) }) })] }), jsx(OrDivider, { children: jsx(Dots, { children: slides.map((s, i) => (jsx(Dot, { "$active": slider === i, onClick: () => { didInteract(); gotoSlide(i); } }, i))) }) }), jsx(Button, { href: ctaUrl, arrow: true, children: locales.aboutScreen_ctaText })] })); }; export { About as default }; //# sourceMappingURL=index.js.map