UNPKG

@coin-voyage/paykit

Version:

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

150 lines (149 loc) 7.65 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { Fragment, useCallback, useEffect, useMemo, useRef, useState } from "react"; import { Dot, Dots, ImageContainer, ImageContainerInner, MobileImageContainer, Slide, Slider, Slides } from "./styles"; import { ModalBody, ModalContent, ModalH1, PageContent } from "../../ui/Modal/styles"; import { AnimatePresence, MotionConfig } from "framer-motion"; import useLocales from "../../../hooks/useLocales"; import usePayContext from "../../contexts/pay/index"; import Button from "../../ui/Button/index"; import { OrDivider } from "../../ui/Divider/OrDivider"; import FitText from "../../ui/FitText/index"; import { SlideOne, SlideThree, SlideTwo } from "./graphics"; const ANIMATION_EASE = [0.16, 1, 0.3, 1]; const ANIMATION_DURATION = 600; const AUTOPLAY_DELAY = 5100; const SLIDE_COUNT = 3; export default function About() { const locales = useLocales({ //CONNECTORNAME: connector.name, }); const context = usePayContext(); const ctaUrl = locales.aboutScreen_ctaUrl; const [slider, setSlider] = useState(0); const interacted = useRef(false); const scrollPos = useRef(0); const sliderRef = useRef(null); const timeoutRef = useRef(null); const isSwipe = useCallback(() => { if (sliderRef.current) { const { overflow } = getComputedStyle(sliderRef.current); return overflow !== "visible"; } return false; }, []); const scrollToSlide = useCallback((index) => { if (sliderRef.current) { const { offsetWidth: width } = sliderRef.current; sliderRef.current.scrollLeft = width * index; setTimeout(() => setSlider(index), 100); } }, []); const gotoSlide = useCallback((index) => { if (isSwipe()) { scrollToSlide(index); } else { setSlider(index); } }, [isSwipe, scrollToSlide]); const didInteract = useCallback(() => { interacted.current = true; if (timeoutRef.current) { clearTimeout(timeoutRef.current); timeoutRef.current = null; } }, []); const scheduleNextRef = useRef(() => { }); const scheduleNext = useCallback(() => { if (interacted.current) return; setSlider((prev) => { const next = (prev + 1) % SLIDE_COUNT; if (isSwipe()) { scrollToSlide(next); } return next; }); timeoutRef.current = setTimeout(() => scheduleNextRef.current(), AUTOPLAY_DELAY); }, [isSwipe, scrollToSlide]); useEffect(() => { scheduleNextRef.current = scheduleNext; }, [scheduleNext]); useEffect(() => { timeoutRef.current = setTimeout(() => scheduleNextRef.current(), AUTOPLAY_DELAY); return () => { if (timeoutRef.current) { clearTimeout(timeoutRef.current); timeoutRef.current = null; } }; }, []); useEffect(() => { const sr = sliderRef.current; if (!sr) return; const onScroll = () => { if (!sliderRef.current) return; const { offsetWidth: width, scrollLeft: x } = sliderRef.current; const prevScroll = scrollPos.current; scrollPos.current = x; const threshold = 4; if (prevScroll - x > -threshold && prevScroll - x < threshold) { const currentSlide = Math.round(x / width); setSlider(currentSlide); } }; const onTouchMove = () => { didInteract(); }; const onTouchEnd = () => { if (!sliderRef.current) return; const { offsetWidth: width, scrollLeft: x } = sliderRef.current; const currentSlide = Math.round(x / width); setSlider(currentSlide); }; sr.addEventListener("scroll", onScroll); sr.addEventListener("touchmove", onTouchMove); sr.addEventListener("touchend", onTouchEnd); return () => { sr.removeEventListener("scroll", onScroll); sr.removeEventListener("touchmove", onTouchMove); sr.removeEventListener("touchend", onTouchEnd); }; }, [didInteract]); const graphics = useMemo(() => [ _jsx(SlideOne, { layoutId: "graphicCircle", duration: ANIMATION_DURATION, ease: ANIMATION_EASE }, "slide-1"), _jsx(SlideTwo, { layoutId: "graphicCircle", duration: ANIMATION_DURATION, ease: ANIMATION_EASE }, "slide-2"), _jsx(SlideThree, { layoutId: "graphicCircle", duration: ANIMATION_DURATION, ease: ANIMATION_EASE }, "slide-3"), ], []); const mobileGraphics = useMemo(() => [ _jsx(SlideOne, { duration: ANIMATION_DURATION, ease: ANIMATION_EASE }, "slide-1"), _jsx(SlideTwo, { duration: ANIMATION_DURATION, ease: ANIMATION_EASE }, "slide-2"), _jsx(SlideThree, { duration: ANIMATION_DURATION, ease: ANIMATION_EASE }, "slide-3"), ], []); const slideHeight = useMemo(() => { switch (context.options?.language) { case "en-US": case "zh-CN": return 64; default: return 84; } }, [context.options?.language]); const slides = useMemo(() => [ _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 }) })] }, "aboutScreen_a"), _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 }) })] }, "aboutScreen_b"), _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 }) })] }, "aboutScreen_c"), ], [locales, slideHeight]); return (_jsxs(PageContent, { children: [_jsxs(Slider, { children: [_jsx(ImageContainer, { children: _jsx(MotionConfig, { transition: { duration: ANIMATION_DURATION / 1000, ease: ANIMATION_EASE, }, children: _jsx(AnimatePresence, { initial: false, 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 })] })); }