UNPKG

rc-infinite-carousel

Version:

A lightweight and customizable infinite carousel component for React. Perfect for displaying images, logos, testimonials, or any other content with smooth transitions and flexible configuration options.

76 lines (73 loc) 3.52 kB
import * as React from 'react'; import { useState, useRef, useLayoutEffect, useCallback, useEffect } from 'react'; const Carousel = ({ data, renderItem, animationDuration = 10, direction = "LEFT", showMask = false, pauseOnHover = false, onSlideClick, ariaLabel, role, }) => { const [dimensions, setDimensions] = useState({ height: 0, width: 0, }); const [visibleSlides, setVisibleSlides] = useState(0); const [isPaused, setIsPaused] = useState(false); const tempRef = useRef(null); const carouselRef = useRef(null); // Set dimensions of the first slide useLayoutEffect(() => { if (tempRef.current) { const firstSlide = tempRef.current.children[0]; if (firstSlide) { const { offsetHeight, offsetWidth } = firstSlide; setDimensions({ height: offsetHeight, width: offsetWidth }); } } }, [data]); // Calculate the number of visible slides based on container width const calculateVisibleSlides = useCallback(() => { if (carouselRef.current) { const containerWidth = carouselRef.current.offsetWidth; if (dimensions.width === 0) return; const visible = Math.floor(containerWidth / dimensions.width); setVisibleSlides(visible); } }, [dimensions.width]); // Recalculate visible slides when dimensions or data change useLayoutEffect(() => { calculateVisibleSlides(); }, [dimensions, data, calculateVisibleSlides]); // Handle window resize events to recalculate visible slides useEffect(() => { const handleResize = () => { calculateVisibleSlides(); }; const debounceResize = debounce(handleResize, 100); window.addEventListener("resize", debounceResize); return () => { window.removeEventListener("resize", debounceResize); }; }, [calculateVisibleSlides]); // Debounce function to limit the rate of function execution const debounce = (func, wait) => { let timeout; return () => { clearTimeout(timeout); timeout = setTimeout(func, wait); }; }; return (React.createElement(React.Fragment, null, React.createElement("div", { style: { position: "absolute", visibility: "hidden", pointerEvents: "none", }, ref: tempRef }, renderItem({ item: data[0], index: 0 })), React.createElement("div", { className: `carousel ${showMask ? "with-mask" : ""}`, ref: carouselRef, "data-reverse": direction === "RIGHT", style: { "--slide-items": data.length, "--slide-width": `${dimensions.width}px`, "--slide-height": `${dimensions.height}px`, "--visible-slides": visibleSlides, "--animation-duration": `${animationDuration}s`, }, onMouseEnter: () => pauseOnHover && setIsPaused(true), onMouseLeave: () => pauseOnHover && setIsPaused(false), "aria-label": ariaLabel, role: role }, React.createElement("div", null, data.map((item, index) => (React.createElement("div", { key: index, className: "slide", style: { "--slide-index": index + 1, animationPlayState: isPaused ? "paused" : "running", }, onClick: () => onSlideClick?.(item, index) }, renderItem({ item, index })))))))); }; export { Carousel as default };