import { ChevronLeft, ChevronRight } from 'lucide-react'; import { useEffect, useRef, useState } from 'react'; // Components import { Button } from '../Button/Button'; import { CardArticle } from '../CardArticle/CardArticle'; import { Heading } from '../Heading/Heading'; import { Paragraph } from '../Paragraph/Paragraph'; // Styles & Types import * as styles from './PostCarousel.styles'; import { PostCarouselProps } from './PostCarousel.types'; export default function PostCarousel({ posts, title = 'Latest Posts' }: PostCarouselProps) { const [currentIndex, setCurrentIndex] = useState(0); const [visibleCount, setVisibleCount] = useState(3); const containerRef = useRef(null); const carouselRef = useRef(null); const [announcement, setAnnouncement] = useState(''); // Resize Logic (Detect How Many Cards to Show) useEffect(() => { const updateVisibleCount = () => { if (!containerRef.current) return; const width = containerRef.current.offsetWidth; let newCount = width < 640 ? 1 : width < 1024 ? 2 : 3; setVisibleCount(newCount); setCurrentIndex((prevIndex) => Math.min(prevIndex, Math.max(0, posts.length - newCount))); }; let resizeTimer: ReturnType; const handleResize = () => { clearTimeout(resizeTimer); resizeTimer = setTimeout(updateVisibleCount, 100); }; updateVisibleCount(); window.addEventListener('resize', handleResize); return () => { window.removeEventListener('resize', handleResize); clearTimeout(resizeTimer); }; }, [posts.length]); // Navigation Logic const goToPrevious = () => { if (currentIndex === 0) return; setCurrentIndex((prevIndex) => Math.max(0, prevIndex - visibleCount)); }; const goToNext = () => { if (currentIndex + visibleCount >= posts.length) return; setCurrentIndex((prevIndex) => Math.min(posts.length - visibleCount, prevIndex + visibleCount)); }; // Announce Navigation for Screen Readers useEffect(() => { setAnnouncement( `Showing posts ${currentIndex + 1} to ${Math.min(currentIndex + visibleCount, posts.length)} of ${posts.length}`, ); }, [ currentIndex, visibleCount, posts.length, ]); return (
{title && ( {title} )} {/* Screen reader announcement */}
{announcement}
{/* Main Carousel Container */}
0 ? '5%' : '0%'}))`, }} aria-live="polite" > {posts.map((post) => (
= currentIndex + visibleCount} // ✅ post.key is now correctly used as a number >
))}
{/* Navigation Controls */}
Showing {currentIndex + 1}-{Math.min(currentIndex + visibleCount, posts.length)} of {posts.length} posts
); }