UNPKG

story-az-card-kit

Version:

A flexible and customizable story card component with multiple layouts

153 lines (137 loc) 4.01 kB
import React, { useState, useRef, useEffect } from 'react'; import PropTypes from 'prop-types'; import StoryCard from '../components/StoryCard'; const CarouselCard = ({ stories = [], theme = 'default', onCardClick, className = '', autoPlay = false, autoPlayInterval = 3000, showArrows = true, showDots = true, children, ...props }) => { const [currentIndex, setCurrentIndex] = useState(0); const [isAutoPlaying, setIsAutoPlaying] = useState(autoPlay); const carouselRef = useRef(null); const intervalRef = useRef(null); useEffect(() => { if (isAutoPlaying && autoPlay) { intervalRef.current = setInterval(() => { setCurrentIndex((prev) => (prev + 1) % stories.length); }, autoPlayInterval); } return () => { if (intervalRef.current) { clearInterval(intervalRef.current); } }; }, [isAutoPlaying, autoPlay, autoPlayInterval, stories.length]); const goToSlide = (index) => { setCurrentIndex(index); }; const goToPrevious = () => { setCurrentIndex((prev) => (prev - 1 + stories.length) % stories.length); }; const goToNext = () => { setCurrentIndex((prev) => (prev + 1) % stories.length); }; const handleMouseEnter = () => { if (autoPlay) { setIsAutoPlaying(false); if (intervalRef.current) { clearInterval(intervalRef.current); } } }; const handleMouseLeave = () => { if (autoPlay) { setIsAutoPlaying(true); } }; const carouselClass = 'story-card-carousel'; const carouselClasses = [ carouselClass, className ].filter(Boolean).join(' '); return ( <div ref={carouselRef} className={carouselClasses} onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave} {...props} > <div className="story-card-carousel__container"> <div className="story-card-carousel__track" style={{ transform: `translateX(-${currentIndex * 100}%)` }} > {stories.map((story, index) => ( <div key={index} className="story-card-carousel__slide"> <StoryCard {...story} theme={theme} onClick={onCardClick ? (e, data) => onCardClick(e, data, index) : undefined} /> </div> ))} </div> </div> {showArrows && stories.length > 1 && ( <> <button className="story-card-carousel__arrow story-card-carousel__arrow--prev" onClick={goToPrevious} aria-label="Previous slide" ></button> <button className="story-card-carousel__arrow story-card-carousel__arrow--next" onClick={goToNext} aria-label="Next slide" ></button> </> )} {showDots && stories.length > 1 && ( <div className="story-card-carousel__dots"> {stories.map((_, index) => ( <button key={index} className={`story-card-carousel__dot ${index === currentIndex ? 'story-card-carousel__dot--active' : ''}`} onClick={() => goToSlide(index)} aria-label={`Go to slide ${index + 1}`} /> ))} </div> )} {children} </div> ); }; CarouselCard.propTypes = { stories: PropTypes.arrayOf(PropTypes.shape({ title: PropTypes.string, description: PropTypes.string, image: PropTypes.string, author: PropTypes.string, date: PropTypes.string, tags: PropTypes.arrayOf(PropTypes.string) })), theme: PropTypes.oneOf(['default', 'dark', 'minimal', 'elegant', 'modern']), onCardClick: PropTypes.func, className: PropTypes.string, autoPlay: PropTypes.bool, autoPlayInterval: PropTypes.number, showArrows: PropTypes.bool, showDots: PropTypes.bool, children: PropTypes.node }; export default CarouselCard;