UNPKG

@meetdhanani/react-image-carousel

Version:

A modern React Image Carousel component with smooth transitions and touch support

369 lines (349 loc) 31.3 kB
import React, { useState, useRef, useMemo, useEffect, useCallback } from 'react'; /****************************************************************************** Copyright (c) Microsoft Corporation. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ***************************************************************************** */ /* global Reflect, Promise, SuppressedError, Symbol, Iterator */ function __awaiter(thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); } function __generator(thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype); return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (g && (g = 0, op[0] && (_ = 0)), _) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } } function __spreadArray(to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); } typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { var e = new Error(message); return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; }; function styleInject(css, ref) { if ( ref === void 0 ) ref = {}; var insertAt = ref.insertAt; if (typeof document === 'undefined') { return; } var head = document.head || document.getElementsByTagName('head')[0]; var style = document.createElement('style'); style.type = 'text/css'; if (insertAt === 'top') { if (head.firstChild) { head.insertBefore(style, head.firstChild); } else { head.appendChild(style); } } else { head.appendChild(style); } if (style.styleSheet) { style.styleSheet.cssText = css; } else { style.appendChild(document.createTextNode(css)); } } var css_248z = ".image-carousel {\n position: relative;\n width: 800px; /* Default fixed width */\n height: 400px; /* Default fixed height */\n overflow: hidden;\n touch-action: pan-y pinch-zoom;\n background: #f5f5f5;\n border-radius: 8px;\n box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\n}\n\n/* Allow size override through className */\n.image-carousel.full-width {\n width: 100%;\n}\n\n.image-carousel.full-height {\n height: 100%;\n}\n\n.carousel-container {\n display: flex;\n width: 100%;\n height: 100%;\n position: relative;\n}\n\n.carousel-slide {\n flex: 0 0 100%;\n width: 100%;\n height: 100%;\n position: relative;\n}\n\n.carousel-slide img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n display: block;\n opacity: 0;\n transition: opacity 0.3s ease-in-out;\n}\n\n.carousel-slide img.loaded {\n opacity: 1;\n}\n\n/* Arrow Styles */\n.carousel-arrow {\n position: absolute;\n top: 50%;\n transform: translateY(-50%);\n background: rgba(255, 255, 255, 0.9);\n color: #333;\n border: none;\n width: 40px;\n height: 40px;\n border-radius: 50%;\n cursor: pointer;\n font-size: 20px;\n z-index: 1;\n transition: all 0.3s ease;\n display: flex;\n align-items: center;\n justify-content: center;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n}\n\n.carousel-arrow:hover:not(:disabled) {\n background: #fff;\n transform: translateY(-50%) scale(1.1);\n box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);\n}\n\n.carousel-arrow:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n transform: translateY(-50%) scale(0.95);\n background: rgba(255, 255, 255, 0.5);\n box-shadow: none;\n}\n\n/* Add a visual indicator for disabled state */\n.carousel-arrow:disabled::after {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n border-radius: 50%;\n background: rgba(0, 0, 0, 0.1);\n pointer-events: none;\n}\n\n.carousel-arrow.prev {\n left: 16px;\n}\n\n.carousel-arrow.next {\n right: 16px;\n}\n\n/* Arrow Style Variants */\n.arrow-minimal {\n background: transparent;\n box-shadow: none;\n color: #fff;\n text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);\n}\n\n.arrow-minimal:hover:not(:disabled) {\n background: transparent;\n transform: translateY(-50%) scale(1.1);\n text-shadow: 0 4px 8px rgba(0, 0, 0, 0.5);\n}\n\n.arrow-rounded {\n background: rgba(255, 255, 255, 0.95);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);\n}\n\n.arrow-rounded:hover:not(:disabled) {\n background: #fff;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);\n}\n\n.arrow-minimal:disabled {\n background: transparent;\n color: rgba(255, 255, 255, 0.3);\n text-shadow: none;\n}\n\n.arrow-rounded:disabled {\n background: rgba(255, 255, 255, 0.5);\n box-shadow: none;\n}\n\n/* Dots Styles */\n.carousel-dots {\n position: absolute;\n bottom: 20px;\n left: 50%;\n transform: translateX(-50%);\n display: flex;\n gap: 8px;\n z-index: 1;\n padding: 8px 16px;\n background: rgba(0, 0, 0, 0.3);\n border-radius: 20px;\n backdrop-filter: blur(4px);\n}\n\n.dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: rgba(255, 255, 255, 0.5);\n border: none;\n cursor: pointer;\n padding: 0;\n transition: all 0.3s ease;\n}\n\n.dot:hover {\n background: rgba(255, 255, 255, 0.8);\n transform: scale(1.2);\n}\n\n.dot.active {\n background: #fff;\n transform: scale(1.2);\n}\n\n/* Dot Style Variants */\n.dot-minimal .dot {\n width: 6px;\n height: 6px;\n background: rgba(255, 255, 255, 0.3);\n}\n\n.dot-minimal .dot.active {\n background: rgba(255, 255, 255, 0.8);\n}\n\n.dot-square .dot {\n border-radius: 2px;\n width: 8px;\n height: 8px;\n}\n\n.dot-square .dot.active {\n background: #007bff;\n}\n\n/* Responsive adjustments */\n@media (max-width: 768px) {\n .image-carousel {\n width: 100%;\n height: 300px;\n }\n\n .carousel-arrow {\n width: 36px;\n height: 36px;\n font-size: 18px;\n }\n\n .carousel-dots {\n bottom: 16px;\n padding: 6px 12px;\n }\n\n .dot {\n width: 6px;\n height: 6px;\n }\n}\n\n/* Loading state */\n.carousel-slide.loading {\n background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);\n background-size: 200% 100%;\n animation: loading 1.5s infinite;\n}\n\n@keyframes loading {\n 0% {\n background-position: 200% 0;\n }\n 100% {\n background-position: -200% 0;\n }\n}\n\n/* Loading Placeholder Styles */\n.carousel-loading-placeholder {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n display: flex;\n justify-content: center;\n align-items: center;\n z-index: 1;\n}\n\n.carousel-loading-spinner {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 1rem;\n}\n\n.carousel-loading-spinner .spinner {\n width: 40px;\n height: 40px;\n border: 4px solid rgba(255, 255, 255, 0.3);\n border-radius: 50%;\n border-top-color: #fff;\n animation: spin 1s ease-in-out infinite;\n}\n\n.carousel-loading-spinner span {\n color: #666;\n font-size: 14px;\n}\n\n@keyframes spin {\n to {\n transform: rotate(360deg);\n }\n}\n\n/* Modern Arrow Styles */\n.carousel-arrow.arrow-modern {\n background: rgba(255, 255, 255, 0.9);\n border-radius: 50%;\n width: 40px;\n height: 40px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);\n transition: all 0.3s ease;\n font-size: 18px;\n color: #333;\n}\n\n.carousel-arrow.arrow-modern:hover {\n background: #fff;\n transform: scale(1.1);\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);\n}\n\n.carousel-arrow.arrow-floating {\n background: transparent;\n border: none;\n color: #fff;\n font-size: 24px;\n text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);\n transition: all 0.3s ease;\n}\n\n.carousel-arrow.arrow-floating:hover {\n transform: translateY(-2px);\n text-shadow: 0 4px 8px rgba(0, 0, 0, 0.4);\n}\n\n.carousel-arrow.arrow-outline {\n background: transparent;\n border: 2px solid #fff;\n border-radius: 50%;\n width: 40px;\n height: 40px;\n color: #fff;\n transition: all 0.3s ease;\n}\n\n.carousel-arrow.arrow-outline:hover {\n background: rgba(255, 255, 255, 0.1);\n transform: scale(1.1);\n}\n\n.carousel-arrow.arrow-gradient {\n background: linear-gradient(135deg, #6e8efb, #a777e3);\n border: none;\n border-radius: 50%;\n width: 40px;\n height: 40px;\n color: #fff;\n transition: all 0.3s ease;\n}\n\n.carousel-arrow.arrow-gradient:hover {\n background: linear-gradient(135deg, #5d7ef9, #9666e3);\n transform: scale(1.1);\n}\n\n/* Modern Dot Styles */\n.carousel-dots.dot-line .dot {\n width: 30px;\n height: 3px;\n border-radius: 0;\n background: rgba(255, 255, 255, 0.5);\n transition: all 0.3s ease;\n}\n\n.carousel-dots.dot-line .dot.active {\n background: #fff;\n width: 40px;\n}\n\n.carousel-dots.dot-pill .dot {\n width: 20px;\n height: 6px;\n border-radius: 3px;\n background: rgba(255, 255, 255, 0.5);\n transition: all 0.3s ease;\n}\n\n.carousel-dots.dot-pill .dot.active {\n background: #fff;\n width: 30px;\n}\n\n.carousel-dots.dot-circle .dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: rgba(255, 255, 255, 0.5);\n transition: all 0.3s ease;\n}\n\n.carousel-dots.dot-circle .dot.active {\n background: #fff;\n transform: scale(1.2);\n}\n\n.carousel-dots.dot-pulse .dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: rgba(255, 255, 255, 0.5);\n transition: all 0.3s ease;\n}\n\n.carousel-dots.dot-pulse .dot.active {\n background: #fff;\n animation: pulse 1.5s infinite;\n}\n\n.carousel-dots.dot-bar .dot {\n width: 40px;\n height: 3px;\n border-radius: 0;\n background: rgba(255, 255, 255, 0.3);\n transition: all 0.3s ease;\n}\n\n.carousel-dots.dot-bar .dot.active {\n background: #fff;\n box-shadow: 0 0 10px rgba(255, 255, 255, 0.5);\n}\n\n/* Transition Styles */\n/* Smooth transition (default) */\n.transition-smooth .carousel-slide {\n transition: transform 0.5s ease-in-out;\n}\n\n/* Instant transition */\n.transition-instant .carousel-slide {\n transition: none;\n}\n\n/* Slide transition */\n.transition-slide .carousel-slide {\n transition: transform 0.5s ease-in-out;\n}\n\n/* Jump transition */\n.transition-jump .carousel-slide {\n transition: opacity 0.5s ease-in-out;\n}\n\n/* Fade transition */\n.transition-fade .carousel-slide {\n position: absolute;\n width: 100%;\n height: 100%;\n opacity: 0;\n transition: opacity 0.5s ease-in-out;\n}\n\n.transition-fade .carousel-slide.active {\n opacity: 1;\n position: relative;\n}\n\n/* Zoom transition */\n.transition-zoom .carousel-slide {\n position: absolute;\n width: 100%;\n height: 100%;\n opacity: 0;\n transform: scale(0.95);\n transition: all 0.5s ease-in-out;\n}\n\n.transition-zoom .carousel-slide.active {\n opacity: 1;\n transform: scale(1);\n position: relative;\n}\n\n/* Flip transition */\n.transition-flip {\n perspective: 1000px;\n}\n\n.transition-flip .carousel-slide {\n position: absolute;\n width: 100%;\n height: 100%;\n transform-style: preserve-3d;\n backface-visibility: hidden;\n transition: transform 0.6s ease-in-out;\n}\n\n.transition-flip .carousel-slide.active {\n transform: rotateY(0deg);\n position: relative;\n}\n\n.transition-flip .carousel-slide:not(.active) {\n transform: rotateY(180deg);\n}\n\n/* Infinite transition */\n.transition-infinite .carousel-slide {\n transition: transform 0.5s ease-in-out;\n}\n\n/* Update container styles for different transitions */\n.transition-fade .carousel-container,\n.transition-zoom .carousel-container,\n.transition-flip .carousel-container {\n position: relative;\n overflow: hidden;\n}\n\n/* Ensure proper stacking for absolute positioned slides */\n.carousel-slide {\n flex: 0 0 100%;\n width: 100%;\n height: 100%;\n position: relative;\n}\n\n.carousel-slide img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n display: block;\n opacity: 0;\n transition: opacity 0.3s ease-in-out;\n}\n\n.carousel-slide img.loaded {\n opacity: 1;\n}\n\n@keyframes pulse {\n 0% {\n transform: scale(1);\n opacity: 1;\n }\n 50% {\n transform: scale(1.5);\n opacity: 0.5;\n }\n 100% {\n transform: scale(1);\n opacity: 1;\n }\n}\n\n/* Responsive adjustments for new styles */\n@media (max-width: 768px) {\n .carousel-arrow.arrow-modern,\n .carousel-arrow.arrow-outline,\n .carousel-arrow.arrow-gradient {\n width: 35px;\n height: 35px;\n font-size: 16px;\n }\n\n .carousel-dots.dot-line .dot {\n width: 25px;\n }\n\n .carousel-dots.dot-line .dot.active {\n width: 35px;\n }\n\n .carousel-dots.dot-pill .dot {\n width: 15px;\n }\n\n .carousel-dots.dot-pill .dot.active {\n width: 25px;\n }\n} "; styleInject(css_248z); var Navigation = function (props) { var currentIndex = props.currentIndex, totalSlides = props.totalSlides, onPrevious = props.onPrevious, onNext = props.onNext, onDotClick = props.onDotClick, showArrows = props.showArrows, showDots = props.showDots, arrowStyle = props.arrowStyle, dotStyle = props.dotStyle, arrowClassName = props.arrowClassName, dotClassName = props.dotClassName, infinite = props.infinite, infiniteTransition = props.infiniteTransition; var isNavigationDisabled = function (direction) { if (infinite) return false; if (direction === 'prev') { return currentIndex === 0; } else { return currentIndex === totalSlides - 1; } }; return (React.createElement(React.Fragment, null, showArrows && (React.createElement(React.Fragment, null, React.createElement("button", { className: "carousel-arrow prev arrow-".concat(arrowStyle, " ").concat(arrowClassName), onClick: onPrevious, "aria-label": "Previous slide", disabled: isNavigationDisabled('prev') }, "\u276E"), React.createElement("button", { className: "carousel-arrow next arrow-".concat(arrowStyle, " ").concat(arrowClassName), onClick: onNext, "aria-label": "Next slide", disabled: isNavigationDisabled('next') }, "\u276F"))), showDots && (React.createElement("div", { className: "carousel-dots dot-".concat(dotStyle, " ").concat(dotClassName), role: "tablist", "aria-label": "Slides" }, Array.from({ length: totalSlides }).map(function (_, index) { return (React.createElement("button", { key: index, className: "dot ".concat(index === currentIndex ? 'active' : ''), onClick: function () { return onDotClick(infiniteTransition === 'infinite' ? index + 1 : index); }, role: "tab", "aria-selected": index === currentIndex, "aria-label": "Go to slide ".concat(index + 1) })); }))))); }; var Slide = function (props) { var image = props.image, index = props.index, isActive = props.isActive, className = props.className, loadedImages = props.loadedImages, getRealIndex = props.getRealIndex; return (React.createElement("div", { className: "carousel-slide ".concat(className), role: "group", "aria-roledescription": "slide", "aria-label": "".concat(getRealIndex(index) + 1), "aria-hidden": !isActive }, React.createElement("img", { src: image, alt: "Slide ".concat(getRealIndex(index) + 1), style: { opacity: loadedImages.has(image) ? 1 : 0 } }))); }; var LoadingPlaceholder = function (props) { var placeholderColor = props.placeholderColor, loadingPlaceholder = props.loadingPlaceholder; return (React.createElement("div", { className: "carousel-loading-placeholder", style: { backgroundColor: placeholderColor } }, loadingPlaceholder || (React.createElement("div", { className: "carousel-loading-spinner" }, React.createElement("div", { className: "spinner" }), React.createElement("span", null, "Loading images..."))))); }; var ImageCarousel = function (props) { var images = props.images, _a = props.autoPlay, autoPlay = _a === void 0 ? true : _a, _b = props.interval, interval = _b === void 0 ? 3000 : _b, _c = props.showArrows, showArrows = _c === void 0 ? true : _c, _d = props.showDots, showDots = _d === void 0 ? true : _d, _e = props.className, className = _e === void 0 ? '' : _e, _f = props.transitionDuration, transitionDuration = _f === void 0 ? 500 : _f, _g = props.swipeThreshold, swipeThreshold = _g === void 0 ? 50 : _g, _h = props.arrowStyle, arrowStyle = _h === void 0 ? 'default' : _h, _j = props.dotStyle, dotStyle = _j === void 0 ? 'default' : _j, _k = props.transitionStyle, transitionStyle = _k === void 0 ? 'smooth' : _k, _l = props.containerClassName, containerClassName = _l === void 0 ? '' : _l, _m = props.slideClassName, slideClassName = _m === void 0 ? '' : _m, _o = props.arrowClassName, arrowClassName = _o === void 0 ? '' : _o, _p = props.dotClassName, dotClassName = _p === void 0 ? '' : _p, onSlideChange = props.onSlideChange, _q = props.pauseOnHover, pauseOnHover = _q === void 0 ? false : _q, _r = props.infinite, infinite = _r === void 0 ? true : _r, _s = props.infiniteTransition, infiniteTransition = _s === void 0 ? 'smooth' : _s, _t = props.showLoadingPlaceholder, showLoadingPlaceholder = _t === void 0 ? true : _t, loadingPlaceholder = props.loadingPlaceholder, _u = props.placeholderColor, placeholderColor = _u === void 0 ? '#f0f0f0' : _u, onImagesLoaded = props.onImagesLoaded; var _v = useState(1), currentIndex = _v[0], setCurrentIndex = _v[1]; var _w = useState(null), touchStart = _w[0], setTouchStart = _w[1]; var _x = useState(null), touchEnd = _x[0], setTouchEnd = _x[1]; var _y = useState(false), isPaused = _y[0], setIsPaused = _y[1]; var _z = useState(false), isTransitioning = _z[0], setIsTransitioning = _z[1]; var _0 = useState(true), isLoading = _0[0], setIsLoading = _0[1]; var _1 = useState(new Set()), loadedImages = _1[0], setLoadedImages = _1[1]; var carouselRef = useRef(null); var slides = useMemo(function () { if (infiniteTransition === 'infinite') { return __spreadArray(__spreadArray([images[images.length - 1]], images, true), [images[0]], false); } return images; }, [images, infiniteTransition]); useEffect(function () { var loadImages = function () { return __awaiter(void 0, void 0, void 0, function () { var loadPromises, error_1; return __generator(this, function (_a) { switch (_a.label) { case 0: loadPromises = images.map(function (src) { return new Promise(function (resolve, reject) { var img = new Image(); img.onload = function () { setLoadedImages(function (prev) { return new Set(Array.from(prev).concat(src)); }); resolve(src); }; img.onerror = reject; img.src = src; }); }); _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); return [4 /*yield*/, Promise.all(loadPromises)]; case 2: _a.sent(); setIsLoading(false); onImagesLoaded === null || onImagesLoaded === void 0 ? void 0 : onImagesLoaded(); return [3 /*break*/, 4]; case 3: error_1 = _a.sent(); console.error('Error loading images:', error_1); setIsLoading(false); return [3 /*break*/, 4]; case 4: return [2 /*return*/]; } }); }); }; loadImages(); }, [images, onImagesLoaded]); var getRealIndex = useCallback(function (index) { if (infiniteTransition === 'infinite') { if (index === 0) return images.length - 1; if (index === images.length + 1) return 0; return index - 1; } return index; }, [images.length, infiniteTransition]); var goToSlide = useCallback(function (index) { if (isTransitioning) return; setIsTransitioning(true); setCurrentIndex(index); onSlideChange === null || onSlideChange === void 0 ? void 0 : onSlideChange(index % images.length); setTimeout(function () { setIsTransitioning(false); if (infiniteTransition === 'infinite') { if (index === 0) { setCurrentIndex(images.length); } else if (index === images.length + 1) { setCurrentIndex(1); } } }, transitionDuration); }, [onSlideChange, transitionDuration, isTransitioning, images.length, infiniteTransition]); var goToPrevious = useCallback(function () { var _a, _b; if (!infinite && currentIndex === 0) return; if (infinite && currentIndex === 0) { if (infiniteTransition === 'instant') { goToSlide(images.length - 1); } else if (infiniteTransition === 'slide') { var container_1 = (_a = carouselRef.current) === null || _a === void 0 ? void 0 : _a.querySelector('.carousel-container'); if (container_1) { container_1.style.transition = 'none'; container_1.style.transform = "translateX(-".concat((images.length + 1) * 100, "%)"); requestAnimationFrame(function () { container_1.style.transition = "transform ".concat(transitionDuration, "ms ease-in-out"); goToSlide(images.length - 1); }); } } else if (infiniteTransition === 'jump') { var container_2 = (_b = carouselRef.current) === null || _b === void 0 ? void 0 : _b.querySelector('.carousel-container'); if (container_2) { container_2.style.transition = "opacity ".concat(transitionDuration, "ms ease-in-out"); container_2.style.opacity = '0'; setTimeout(function () { goToSlide(images.length - 1); container_2.style.opacity = '1'; }, transitionDuration / 2); } } else if (infiniteTransition === 'infinite') { goToSlide(currentIndex - 1); } else { goToSlide(images.length - 1); } } else { goToSlide(currentIndex - 1); } }, [currentIndex, images.length, infinite, goToSlide, infiniteTransition, transitionDuration]); var goToNext = useCallback(function () { var _a, _b; if (!infinite && currentIndex === images.length - 1) return; if (infinite && currentIndex === images.length - 1) { if (infiniteTransition === 'instant') { goToSlide(0); } else if (infiniteTransition === 'slide') { var container_3 = (_a = carouselRef.current) === null || _a === void 0 ? void 0 : _a.querySelector('.carousel-container'); if (container_3) { container_3.style.transition = 'none'; container_3.style.transform = "translateX(0)"; requestAnimationFrame(function () { container_3.style.transition = "transform ".concat(transitionDuration, "ms ease-in-out"); goToSlide(0); }); } } else if (infiniteTransition === 'jump') { var container_4 = (_b = carouselRef.current) === null || _b === void 0 ? void 0 : _b.querySelector('.carousel-container'); if (container_4) { container_4.style.transition = "opacity ".concat(transitionDuration, "ms ease-in-out"); container_4.style.opacity = '0'; setTimeout(function () { goToSlide(0); container_4.style.opacity = '1'; }, transitionDuration / 2); } } else if (infiniteTransition === 'infinite') { goToSlide(currentIndex + 1); } else { goToSlide(0); } } else { goToSlide(currentIndex + 1); } }, [currentIndex, images.length, infinite, goToSlide, infiniteTransition, transitionDuration]); useEffect(function () { var timer; if (autoPlay && !isPaused) { timer = setInterval(goToNext, interval); } return function () { if (timer) clearInterval(timer); }; }, [autoPlay, interval, goToNext, isPaused]); var handleTouchStart = useCallback(function (e) { setTouchStart(e.touches[0].clientX); }, []); var handleTouchMove = useCallback(function (e) { setTouchEnd(e.touches[0].clientX); }, []); var handleTouchEnd = useCallback(function () { if (!touchStart || !touchEnd) return; var distance = touchStart - touchEnd; var isLeftSwipe = distance > swipeThreshold; var isRightSwipe = distance < -swipeThreshold; if (isLeftSwipe) { goToNext(); } else if (isRightSwipe) { goToPrevious(); } }, [touchStart, touchEnd, goToNext, goToPrevious, swipeThreshold]); var handleMouseEnter = useCallback(function () { if (pauseOnHover) { setIsPaused(true); } }, [pauseOnHover]); var handleMouseLeave = useCallback(function () { if (pauseOnHover) { setIsPaused(false); } }, [pauseOnHover]); var getTransitionStyle = useCallback(function () { switch (transitionStyle) { case 'fade': case 'zoom': case 'flip': return { transform: 'none', transition: isTransitioning ? "all ".concat(transitionDuration, "ms ease-in-out") : 'none', opacity: isLoading ? 0 : 1, }; default: return { transform: "translateX(-".concat(currentIndex * 100, "%)"), transition: isTransitioning ? "transform ".concat(transitionDuration, "ms ease-in-out") : 'none', opacity: isLoading ? 0 : 1, }; } }, [currentIndex, transitionStyle, isTransitioning, transitionDuration, isLoading]); var getSlideClassName = useCallback(function (index) { var baseClass = "carousel-slide ".concat(slideClassName); if (transitionStyle === 'fade' || transitionStyle === 'zoom' || transitionStyle === 'flip') { return "".concat(baseClass, " ").concat(index === currentIndex ? 'active' : ''); } return baseClass; }, [slideClassName, transitionStyle, currentIndex]); return (React.createElement("div", { ref: carouselRef, className: "image-carousel ".concat(className), onTouchStart: handleTouchStart, onTouchMove: handleTouchMove, onTouchEnd: handleTouchEnd, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, role: "region", "aria-roledescription": "carousel", "aria-label": "Image carousel" }, isLoading && showLoadingPlaceholder && (React.createElement(LoadingPlaceholder, { placeholderColor: placeholderColor, loadingPlaceholder: loadingPlaceholder })), React.createElement("div", { className: "carousel-container ".concat(containerClassName, " transition-").concat(transitionStyle), style: getTransitionStyle(), role: "presentation" }, slides.map(function (image, index) { return (React.createElement(Slide, { key: index, image: image, index: index, isActive: index === currentIndex, className: getSlideClassName(index), loadedImages: loadedImages, getRealIndex: getRealIndex })); })), React.createElement(Navigation, { currentIndex: getRealIndex(currentIndex), totalSlides: images.length, onPrevious: goToPrevious, onNext: goToNext, onDotClick: goToSlide, showArrows: showArrows, showDots: showDots, arrowStyle: arrowStyle, dotStyle: dotStyle, arrowClassName: arrowClassName, dotClassName: dotClassName, infinite: infinite, infiniteTransition: infiniteTransition }))); }; export { ImageCarousel };