From c91b28cf10a2142d67387a7700601365fb65d057 Mon Sep 17 00:00:00 2001 From: byeong Date: Mon, 6 Jul 2026 14:51:58 +0900 Subject: [PATCH] =?UTF-8?q?feat:=2008-ImageCarousel=20=EA=B3=BC=EC=A0=9C?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20(=EC=B5=9C=EB=B3=91=EC=B0=AC)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 08-ImageCarousel/chan-byeong/index.tsx | 105 +++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 08-ImageCarousel/chan-byeong/index.tsx diff --git a/08-ImageCarousel/chan-byeong/index.tsx b/08-ImageCarousel/chan-byeong/index.tsx new file mode 100644 index 0000000..a53dba1 --- /dev/null +++ b/08-ImageCarousel/chan-byeong/index.tsx @@ -0,0 +1,105 @@ +import { useState } from "react"; + +export default function ImageCarousel({ + images, +}: Readonly<{ + images: ReadonlyArray<{ src: string; alt: string }>; +}>) { + const [currentIndex, setCurrentIndex] = useState(1); + const [isTransition, setIsTransition] = useState(true); + const clonedImage = formatImageArr(images); + + const handlePrev = () => { + setIsTransition(true); + setCurrentIndex((prev) => prev - 1); + }; + + const handleNext = () => { + setIsTransition(true); + setCurrentIndex((prev) => prev + 1); + }; + + const handleTransitionEnd = () => { + setIsTransition(false); + if (currentIndex === 0) { + setCurrentIndex(clonedImage.length - 2); + } else if (currentIndex === clonedImage.length - 1) { + setCurrentIndex(1); + } + }; + + return ( +
+ +
+
+ {clonedImage.map(({ alt, src }) => ( + {alt} + ))} +
+
+ + +
+ ); +} + +function formatImageArr(images: ReadonlyArray<{ src: string; alt: string }>) { + const clone = [images[images.length - 1], ...images, images[0]]; + return clone; +}