"use client"; import React, { useState, useEffect, memo, useMemo, useCallback } from "react"; import ContentThumbnailTemplate from "./ContentThumbnailTemplate"; const RelatedArticles = memo( ({ relatedPosts, currentPostSlug, slugOrder = [] }) => { // Memoize filtered posts to prevent unnecessary re-computations const filteredPosts = useMemo( () => relatedPosts.filter((post) => post.slug !== currentPostSlug), [relatedPosts, currentPostSlug], ); const [currentIndex, setCurrentIndex] = useState(0); const [progress, setProgress] = useState(0); const [isMobile, setIsMobile] = useState(true); // Memoize the mouse down handler to prevent unnecessary re-renders const handleMouseDown = useCallback((e) => { const slider = e.currentTarget; const startX = e.pageX - slider.offsetLeft; const scrollLeft = slider.scrollLeft; const handleMouseMove = (e) => { const x = e.pageX - slider.offsetLeft; const walk = (x - startX) * 2; slider.scrollLeft = scrollLeft - walk; }; const handleMouseUp = () => { document.removeEventListener("mousemove", handleMouseMove); document.removeEventListener("mouseup", handleMouseUp); }; document.addEventListener("mousemove", handleMouseMove); document.addEventListener("mouseup", handleMouseUp); }, []); // Memoize transform style to prevent unnecessary recalculations const transformStyle = useMemo( () => ({ transform: isMobile ? `translateX(calc(50% - 130px - ${currentIndex * 260}px))` : "none", scrollBehavior: !isMobile ? "smooth" : "auto", }), [isMobile, currentIndex], ); // Memoize progress bar style calculation const getProgressStyle = useCallback( (index) => ({ width: index === currentIndex ? `${progress}%` : index < currentIndex ? "100%" : "0%", }), [currentIndex, progress], ); // Check if we're on mobile (below lg breakpoint) useEffect(() => { const checkScreenSize = () => { setIsMobile(window.innerWidth < 1024); // lg breakpoint is 1024px }; checkScreenSize(); window.addEventListener("resize", checkScreenSize); return () => window.removeEventListener("resize", checkScreenSize); }, []); // Auto-advance every 3 seconds (only on mobile) useEffect(() => { if (filteredPosts.length <= 1 || !isMobile) return; const interval = setInterval(() => { setProgress(0); setCurrentIndex((prev) => (prev + 1) % filteredPosts.length); }, 3000); return () => clearInterval(interval); }, [filteredPosts.length, isMobile]); // Progress animation (only on mobile) useEffect(() => { if (filteredPosts.length <= 1 || !isMobile) return; const progressInterval = setInterval(() => { setProgress((prev) => { if (prev >= 100) { return 0; } return prev + 1; }); }, 30); // 30ms intervals for smooth animation return () => clearInterval(progressInterval); }, [currentIndex, filteredPosts.length, isMobile]); if (filteredPosts.length === 0) { return null; } return (

Related Articles

{/* Horizontal Articles Row - Carousel on mobile, Scrollable slider on desktop */}
{filteredPosts.map((relatedPost, index) => (
))}
{/* Progress bars - only show on mobile */} {isMobile && (
{filteredPosts.map((relatedPost, index) => (
))}
)}
); }, ); RelatedArticles.displayName = "RelatedArticles"; export default RelatedArticles;