@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
JavaScript
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 })] }));
}