test-iki-mini-app
Version:
ứng dựng bán hàng trên mini app z a l o
105 lines (91 loc) • 3.04 kB
JSX
import { useSwipeable } from "react-swipeable";
import React, { useState, useEffect } from "react";
import "../../style/carousel.css";
import { useAppStore } from "../../store/appStore";
const NEXT = "next";
const PREV = "prev";
const getOrder = (index, pos, numItems) => {
return index - pos < 0 ? numItems - Math.abs(index - pos) : index - pos;
};
export const Carousel = ({ children }) => {
const numItems = React.Children.count(children);
const [sliding, setSliding] = useState(false);
const [direction, setDirection] = useState("");
const [pos, setPos] = useState(0);
const { appTheme } = useAppStore((state) => state);
const { color_main_1 } = appTheme;
const slideNext = () => {
setSliding(true);
setDirection(NEXT);
setPos(pos === numItems - 1 ? 0 : pos + 1);
setTimeout(stopSliding, 50);
};
useEffect(() => {
const interval = setInterval(slideNext, 3000);
return () => clearInterval(interval);
}, [pos]);
const slidePrev = () => {
setSliding(true);
setDirection(PREV);
setPos(pos === 0 ? numItems - 1 : pos - 1);
setTimeout(stopSliding, 50);
};
const stopSliding = () => setSliding(false);
const slide = (direction) => {
if (direction === NEXT) {
slideNext();
} else {
slidePrev();
}
};
const handlePageClick = (pageIndex) => {
setSliding(true);
setDirection(pageIndex > pos ? NEXT : PREV);
setPos(pageIndex);
setTimeout(stopSliding, 50);
};
const pages = Array.from({ length: numItems }, (_, index) => ({
index,
active: index === pos,
}));
const handlers = useSwipeable({
onSwipedLeft: () => slide(NEXT),
onSwipedRight: () => slide(PREV),
swipeDuration: 1000,
preventScrollOnSwipe: true,
trackMouse: true,
// onSwiped: (eventData) => console.log("User Swiped!", eventData),
// onSwiping: () => console.log("swiping"),
// onSwipedUp: () => console.log("up"),
touchEventOptions: { passive: false },
});
return (
<div {...handlers} style={{ touchAction: "pan-y" }} className="relative">
<div className="wrapper w-full overflow-hidden pr-[16px]">
<div
className={`carousel-container ${direction} ${sliding && "sliding"} flex gap-[16px]`}
>
{React.Children.map(children, (child, index) => (
<div
className="carousel-slot"
style={{ order: getOrder(index, pos, numItems) }}
key={index}
>
{child}
</div>
))}
</div>
</div>
<div className="pagination flex justify-center w-fit absolute bottom-[10px] right-[50%] translate-x-[50%]">
{pages.map((page) => (
<span
key={page.index}
className={`w-[6px] h-[6px] rounded-full bg-[#fff] mx-[5px] cursor-pointer`}
onClick={() => handlePageClick(page.index)}
style={{backgroundColor: page.active ? color_main_1 : "#fff"}}
/>
))}
</div>
</div>
);
};