UNPKG

react-responsive-3d-carousel

Version:
936 lines (914 loc) 37.7 kB
import { jsxs, jsx } from 'react/jsx-runtime'; import { useEffect, useMemo, useRef, createContext, useState, 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 */ var __assign = function() { __assign = Object.assign || function __assign(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { var e = new Error(message); return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; }; var CSS_VARIABLE = { CONTAINER_WIDTH: '--container-width', CONTAINER_HEIGHT: '--container-height', ITEM_WIDTH: '--item-width', }; var useAutoPlay = function (autoplay, interval, slideNext, pauseRef) { /** * Auto play the carousel */ useEffect(function () { if (!autoplay) return; var timer = window.setInterval(function () { if (pauseRef.current) return; slideNext(); }, interval); return function () { clearInterval(timer); }; }, [autoplay, interval, slideNext]); }; var useFocus = function (containerRef, autoFocus, slideWithKeyboard, slideNext, slidePrev) { /** * Auto-focus the container element when autoFocus is true. */ useEffect(function () { var container = containerRef.current; if (!container) return; if (autoFocus) container.focus(); }, [autoFocus]); /** * Set up keydown event listener for keyboard navigation. */ useEffect(function () { if (slideWithKeyboard === 'none') return; var container = containerRef.current; if (!container) return; var handleKeyDown = function (e) { if (container !== document.activeElement) return; switch (e.key) { case 'ArrowLeft': if (slideWithKeyboard === 'horizontal' || slideWithKeyboard === 'both') { slidePrev(); } break; case 'ArrowRight': if (slideWithKeyboard === 'horizontal' || slideWithKeyboard === 'both') { slideNext(); } break; case 'ArrowUp': if (slideWithKeyboard === 'vertical' || slideWithKeyboard === 'both') { slidePrev(); } break; case 'ArrowDown': if (slideWithKeyboard === 'vertical' || slideWithKeyboard === 'both') { slideNext(); } break; } }; window.addEventListener('keydown', handleKeyDown); return function () { window.removeEventListener('keydown', handleKeyDown); }; }, [slideWithKeyboard, slideNext, slidePrev]); }; var DEFAULT_TWO_CAROUSEL_INDEX_TRANSFORM = { default: { translate: { x: 0, y: 0, z: -1, }, rotate: { x: 0, y: 0, z: 0, }, offset: { x: 0, y: 0, z: 0, }, }, 0: { translate: { x: 0, y: 0, z: 0, }, rotate: { x: 0, y: 0, z: 0, }, offset: { x: 0, y: 0, z: 0, }, }, }; var DEFAULT_THREE_CAROUSEL_INDEX_TRANSFORM = { default: { translate: { x: 0, y: 0, z: -1, }, rotate: { x: 0, y: 0, z: 0, }, offset: { x: 0, y: 0, z: 0, }, }, '-1': { translate: { x: -0.5, y: 0, z: 0, }, rotate: { x: 0, y: 40, z: 0, }, offset: { x: 0.5 * Math.cos(40 * (Math.PI / 180)), y: 0, z: -1 * Math.sin(30 * (Math.PI / 180)), }, }, 0: { translate: { x: 0, y: 0, z: 0, }, rotate: { x: 0, y: 0, z: 0, }, offset: { x: 0, y: 0, z: 0, }, }, 1: { translate: { x: 0.5, y: 0, z: 0, }, rotate: { x: 0, y: -40, z: 0, }, offset: { x: -0.5 * Math.cos(40 * (Math.PI / 180)), y: 0, z: -1 * Math.sin(30 * (Math.PI / 180)), }, }, }; var DEFAULT_FIVE_CAROUSEL_INDEX_TRANSFORM = { default: { translate: { x: 0, y: 0, z: -1, }, rotate: { x: 0, y: 0, z: 0, }, offset: { x: 0, y: 0, z: 0, }, }, '-2': { translate: { x: -0.5, y: 0, z: 0, }, rotate: { x: 0, y: 40, z: 0, }, offset: { x: 0.5 * Math.cos(40 * (Math.PI / 180)), y: 0, z: -1 * Math.sin(40 * (Math.PI / 180)), }, }, '-1': { translate: { x: -0.25, y: 0, z: 0, }, rotate: { x: 0, y: 20, z: 0, }, offset: { x: 0.25 * Math.cos(40 * (Math.PI / 180)), y: 0, z: -0.5 * Math.sin(40 * (Math.PI / 180)), }, }, 0: { translate: { x: 0, y: 0, z: 0, }, rotate: { x: 0, y: 0, z: 0, }, offset: { x: 0, y: 0, z: 0, }, }, 1: { translate: { x: 0.25, y: 0, z: 0, }, rotate: { x: 0, y: -20, z: 0, }, offset: { x: -0.25 * Math.cos(40 * (Math.PI / 180)), y: 0, z: -0.5 * Math.sin(40 * (Math.PI / 180)), }, }, 2: { translate: { x: 0.5, y: 0, z: 0, }, rotate: { x: 0, y: -40, z: 0, }, offset: { x: -0.5 * Math.cos(40 * (Math.PI / 180)), y: 0, z: -1 * Math.sin(40 * (Math.PI / 180)), }, }, }; var round = function (num, decimal) { return Math.round(num * Math.pow(10, decimal)) / Math.pow(10, decimal); }; /** * Adjust default carousel layout info based on the default option values */ var adjustDefaultCarouselLayoutInfo = function (info, defaultOption) { var _a, _b, _c; var adjustedInfo = {}; var widthFactor = (_a = defaultOption === null || defaultOption === void 0 ? void 0 : defaultOption.widthFactor) !== null && _a !== void 0 ? _a : 1; var depthFactor = (_b = defaultOption === null || defaultOption === void 0 ? void 0 : defaultOption.depthFactor) !== null && _b !== void 0 ? _b : 1; var angleFactor = (_c = defaultOption === null || defaultOption === void 0 ? void 0 : defaultOption.angleFactor) !== null && _c !== void 0 ? _c : 1; Object.entries(info).forEach(function (_a) { var key = _a[0], itemInfo = _a[1]; var adjustedTranslate = { x: round(itemInfo.translate.x * widthFactor, 3), // it's always number : constant/layout.ts y: itemInfo.translate.y, z: round(itemInfo.translate.z * widthFactor, 3), // it's always number : constant/layout.ts }; var adjustedRotate = { x: round(itemInfo.rotate.x * angleFactor, 3), y: round(itemInfo.rotate.y * angleFactor, 3), z: round(itemInfo.rotate.z * angleFactor, 3), }; var adjustedOffset = { x: round(itemInfo.offset.x * widthFactor, 3), // it's always number : constant/layout.ts y: itemInfo.offset.y, z: round(itemInfo.offset.z * depthFactor, 3), // it's always number : constant/layout.ts }; adjustedInfo[key] = { translate: adjustedTranslate, rotate: adjustedRotate, offset: adjustedOffset, }; }); return adjustedInfo; }; /** * Get default carousel layout info based on the length of items */ var getDefaultCarouselLayoutInfo = function (length, defaultOption) { // Get default layout info based on 'defaultOption.numOfSlides' if (defaultOption && 'numOfSlides' in defaultOption) { if (defaultOption.numOfSlides === 2) { return adjustDefaultCarouselLayoutInfo(DEFAULT_TWO_CAROUSEL_INDEX_TRANSFORM, defaultOption); } else if (defaultOption.numOfSlides === 3) { return adjustDefaultCarouselLayoutInfo(DEFAULT_THREE_CAROUSEL_INDEX_TRANSFORM, defaultOption); } else if (defaultOption.numOfSlides === 5) { return adjustDefaultCarouselLayoutInfo(DEFAULT_FIVE_CAROUSEL_INDEX_TRANSFORM, defaultOption); } } // Get default layout info based on the length of items if (length < 3) { return adjustDefaultCarouselLayoutInfo(DEFAULT_TWO_CAROUSEL_INDEX_TRANSFORM, defaultOption); } else if (length < 5) { return adjustDefaultCarouselLayoutInfo(DEFAULT_THREE_CAROUSEL_INDEX_TRANSFORM, defaultOption); } else { return adjustDefaultCarouselLayoutInfo(DEFAULT_FIVE_CAROUSEL_INDEX_TRANSFORM, defaultOption); } }; /** * Transform layout info to CSS style */ var transformLayoutInfoToStyle = function (info, align) { var width = info.width, height = info.height, translate = info.translate, rotate = info.rotate, offset = info.offset; // Transform width var newWidth = typeof width === 'number' ? "calc(".concat(width, " * var(").concat(CSS_VARIABLE.CONTAINER_WIDTH, "))") : (width !== null && width !== void 0 ? width : 'auto'); // Transform height var newHeight = typeof height === 'number' ? "calc(".concat(height, " * var(").concat(CSS_VARIABLE.CONTAINER_HEIGHT, "))") : (height !== null && height !== void 0 ? height : 'auto'); // Set init initTranslateY depend on the align var initTranslateY; switch (align) { case 'top': initTranslateY = 0; break; case 'bottom': initTranslateY = -100; break; case 'center': initTranslateY = -50; break; } // Transform rotate var magnitude = Math.sqrt(Math.pow(rotate.x, 2) + Math.pow(rotate.y, 2) + Math.pow(rotate.z, 2)); var nx = magnitude ? rotate.x / magnitude : 0; var ny = magnitude ? rotate.y / magnitude : 0; var nz = magnitude ? rotate.z / magnitude : 0; // Transform translate var translateX = typeof translate.x === 'number' ? "".concat(translate.x, " * var(").concat(CSS_VARIABLE.CONTAINER_WIDTH, ")") : translate.x; var translateY = typeof translate.y === 'number' ? "".concat(translate.y, " * var(").concat(CSS_VARIABLE.CONTAINER_HEIGHT, ")") : translate.y; var translateZ = typeof translate.z === 'number' ? "".concat(translate.z, " * var(").concat(CSS_VARIABLE.CONTAINER_WIDTH, ")") : translate.z; // Transform offset var offsetX = typeof offset.x === 'number' ? "".concat(offset.x, " * 100%") : offset.x; var offsetY = typeof offset.y === 'number' ? "".concat(offset.y, " * 100%") : offset.y; var offsetZ = typeof offset.z === 'number' ? "".concat(offset.z, " * var(").concat(CSS_VARIABLE.ITEM_WIDTH, ")") : offset.z; return { width: newWidth, height: newHeight, transform: "translate(-50%, ".concat(initTranslateY, "%) \n translate3d(calc(").concat(translateX, " + ").concat(offsetX, "), calc(").concat(translateY, " + ").concat(offsetY, "), calc(").concat(translateZ, " + ").concat(offsetZ, ")) \n rotate3d(").concat(nx, ", ").concat(ny, ", ").concat(nz, ", calc(").concat(magnitude, "deg)"), }; }; /** * Transform carousel layout info to CSS style */ var transformCarouselLayoutInfoToStyle = function (info, align) { var style = {}; for (var key in info) { style[key] = transformLayoutInfoToStyle(info[key], align); } return style; }; var useLayout = function (items, htmlItemsRef, align, width, height, aspectRatio, layout, curIndex, defaultOption) { /** * Memoize the layout styles from layout info */ var layoutStyle = useMemo(function () { var layoutInfo = layout === 'default' ? getDefaultCarouselLayoutInfo(items.length, defaultOption) : layout; return transformCarouselLayoutInfoToStyle(layoutInfo, align); }, [items, align, layout, defaultOption]); /** * Apply the calculated layout styles to each item on every render. */ useEffect(function () { var htmlItems = htmlItemsRef.current; var applyStyle = function (item, style) { item.style.width = style.width === 'auto' ? width : style.width; item.style.height = style.height === 'auto' ? height : style.height; item.style.transform = style.transform; // Toggle item width class if (item.style.width !== 'auto' || (item.style.height !== 'auto' && aspectRatio !== 'auto')) { item.classList.add('fixed-width'); } else { item.classList.remove('fixed-width'); } // Toggle item height class if (item.style.height !== 'auto' || (item.style.width !== 'auto' && aspectRatio !== 'auto')) { item.classList.add('fixed-height'); } else { item.classList.remove('fixed-height'); } }; htmlItems.forEach(function (item, i) { // Check the simple-calculated index first var primaryIdx = i - curIndex; if (layoutStyle[primaryIdx]) { applyStyle(item, layoutStyle[primaryIdx]); return; } // Check the other side of the carousel var secondaryIdx = primaryIdx + (primaryIdx > 0 ? -items.length : items.length); if (layoutStyle[secondaryIdx]) { applyStyle(item, layoutStyle[secondaryIdx]); return; } // If there's no layout info for the index, apply the default layout applyStyle(item, layoutStyle.default); }); }, [items, width, height, aspectRatio, layoutStyle, curIndex]); }; var useSize = function (items, htmlItemsRef, listRef, width, curIndex) { /** * Set the width of each item as a CSS variable on every render. */ useEffect(function () { var htmlItems = htmlItemsRef.current; htmlItems.forEach(function (item) { item.style.setProperty(CSS_VARIABLE.ITEM_WIDTH, "".concat(item.offsetWidth, "px")); }); }, [items, width, curIndex]); /** * Set the width and height of the Carousel list as a CSS variable * Use ResizeObserver if available; otherwise, falls back to window resize event. */ useEffect(function () { var list = listRef.current; if (!list) return; var handleResize = function () { list.style.setProperty(CSS_VARIABLE.CONTAINER_WIDTH, "".concat(list.offsetWidth, "px")); list.style.setProperty(CSS_VARIABLE.CONTAINER_HEIGHT, "".concat(list.offsetHeight, "px")); }; handleResize(); // Initial call var resizeObserver = 'ResizeObserver' in window ? new ResizeObserver(handleResize) : null; if (resizeObserver) { resizeObserver.observe(list); } else { window.addEventListener('resize', handleResize); } return function () { if (resizeObserver) { resizeObserver.disconnect(); } else { window.removeEventListener('resize', handleResize); } }; }, []); }; var MIN_SWIPE_DISTANCE = 30; // Minimum distance in pixels to consider a swipe var useSwipe = function (_a) { var containerRef = _a.containerRef, swipeable = _a.swipeable, swipeDirection = _a.swipeDirection, slideNext = _a.slideNext, slidePrev = _a.slidePrev, onSwipeStart = _a.onSwipeStart, onSwipeEnd = _a.onSwipeEnd, onSwipeMove = _a.onSwipeMove; // Ref to track if a swipe is currently in progress var isSwiping = useRef(false); /** * Handle swipe gestures on a container element */ useEffect(function () { if (!swipeable) return; var container = containerRef.current; if (!container) return; var startX = 0; var startY = 0; var handleSwipeStart = function (event) { isSwiping.current = true; startX = event.touches[0].clientX; startY = event.touches[0].clientY; onSwipeStart && onSwipeStart(event); }; var handleSwipeMove = function (event) { if (!isSwiping.current) return; onSwipeMove && onSwipeMove(event); }; var handleSwipeEnd = function (event) { if (!isSwiping.current) return; isSwiping.current = false; onSwipeEnd && onSwipeEnd(event); var endX = event.changedTouches[0].clientX; var endY = event.changedTouches[0].clientY; var deltaX = endX - startX; var deltaY = endY - startY; var absDeltaX = Math.abs(deltaX); var absDeltaY = Math.abs(deltaY); var absDelta = Math.sqrt(Math.pow(absDeltaX, 2) + Math.pow(absDeltaY, 2)); if (absDelta < MIN_SWIPE_DISTANCE) return; if (swipeDirection === 'horizontal' && absDeltaX > absDeltaY) { event.preventDefault(); if (deltaX > 0) { slidePrev(); } else { slideNext(); } } else if (swipeDirection === 'vertical' && absDeltaY > absDeltaX) { event.preventDefault(); if (deltaY > 0) { slidePrev(); } else { slideNext(); } } }; container.addEventListener('touchstart', handleSwipeStart, { passive: true, }); container.addEventListener('touchmove', handleSwipeMove, { passive: true, }); container.addEventListener('touchend', handleSwipeEnd); return function () { container.removeEventListener('touchstart', handleSwipeStart); container.removeEventListener('touchmove', handleSwipeMove); container.removeEventListener('touchend', handleSwipeEnd); }; }, [ swipeable, swipeDirection, slideNext, slidePrev, onSwipeStart, onSwipeEnd, onSwipeMove, ]); return { isSwiping: isSwiping }; }; var Arrows = function (_a) { var _b = _a.width, width = _b === void 0 ? '3rem' : _b, _c = _a.height, height = _c === void 0 ? '5rem' : _c, _d = _a.color, color = _d === void 0 ? '#ffffff' : _d, _e = _a.hoverColor, hoverColor = _e === void 0 ? '#888888' : _e, _f = _a.shadow, shadow = _f === void 0 ? '0 0.05rem 0.1rem rgba(0, 0, 0, 0.3)' : _f, _g = _a.nextArrowTranslate, nextArrowTranslate = _g === void 0 ? ['0px', '0px'] : _g, _h = _a.prevArrowTranslate, prevArrowTranslate = _h === void 0 ? ['0px', '0px'] : _h, onClickNext = _a.onClickNext, onClickPrev = _a.onClickPrev, nextIcon = _a.nextIcon, prevIcon = _a.prevIcon; var handleClickPrev = function (e) { e.stopPropagation(); onClickPrev && onClickPrev(e); }; var handleClickNext = function (e) { e.stopPropagation(); onClickNext && onClickNext(e); }; var arrowsStyle = { '--arrow-width': width, '--arrow-height': height, '--arrow-drop-shadow': shadow, '--arrow-color': color, '--arrow-hover-color': hoverColor, }; return (jsxs("div", { className: "react-responsive-3d-carousel__arrows", style: arrowsStyle, children: [jsx("button", { type: "button", onClick: handleClickPrev, "aria-label": "previous slide", style: { transform: "translateY(-50%) translate(".concat(prevArrowTranslate[0], ", ").concat(prevArrowTranslate[1], ")"), }, children: prevIcon || jsx(LeftCaretIcon, {}) }), jsx("button", { type: "button", onClick: handleClickNext, "aria-label": "next slide", style: { transform: "translateY(-50%) translate(".concat(nextArrowTranslate[0], ", ").concat(nextArrowTranslate[1], ")"), }, children: nextIcon || jsx(RightCaretIcon, {}) })] })); }; var LeftCaretIcon = function () { return (jsx("svg", { width: "24", height: "24", viewBox: "0 0 24 24", preserveAspectRatio: "none", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsx("polyline", { points: "15 18 9 12 15 6" }) })); }; var RightCaretIcon = function () { return (jsx("svg", { width: "24", height: "24", viewBox: "0 0 24 24", preserveAspectRatio: "none", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: jsx("polyline", { points: "9 18 15 12 9 6" }) })); }; Arrows.displayName = 'Arrows'; var Indicators = function (_a) { var length = _a.length, curIndex = _a.curIndex, _b = _a.color, color = _b === void 0 ? '#ffffff' : _b, _c = _a.width, width = _c === void 0 ? '0.7rem' : _c, _d = _a.height, height = _d === void 0 ? '0.7rem' : _d, _e = _a.gap, gap = _e === void 0 ? '1.5rem' : _e, _f = _a.activeColor, activeColor = _f === void 0 ? '#888888' : _f, _g = _a.shadow, shadow = _g === void 0 ? '0 0.05rem 0.1rem rgba(0, 0, 0, 0.5)' : _g, _h = _a.translate, translate = _h === void 0 ? ['0px', '0px'] : _h, indicatorIcon = _a.indicatorIcon, onClick = _a.onClick; var handleClick = function (e, index) { e.stopPropagation(); onClick && onClick(e, index); }; var indicatorsStyle = { gap: gap, transform: "translate(".concat(translate[0], ", ").concat(translate[1], ")"), '--indicator-width': width, '--indicator-height': height, '--indicator-color': color, '--indicator-active-color': activeColor, '--indicator-shadow': shadow, }; return (jsx("ul", { className: "react-responsive-3d-carousel__indicators", style: indicatorsStyle, children: Array.from({ length: length }, function (_, i) { return (jsx("li", { onClick: function (e) { return handleClick(e, i); }, "aria-label": "slide item ".concat(i + 1), className: i === curIndex ? 'active' : '', children: indicatorIcon ? indicatorIcon : jsx(CircleIcon, {}) }, i)); }) })); }; var CircleIcon = function () { return (jsx("svg", { preserveAspectRatio: "none", width: "24", height: "24", viewBox: "0 0 24 24", fill: "currentColor", children: jsx("circle", { cx: "12", cy: "12", r: "10" }) })); }; Indicators.displayName = 'Indicators'; var Status = function (_a) { var length = _a.length, curIndex = _a.curIndex, _b = _a.color, color = _b === void 0 ? '#ffffff' : _b, _c = _a.fontSize, fontSize = _c === void 0 ? '1rem' : _c, _d = _a.fontWeight, fontWeight = _d === void 0 ? '600' : _d, _e = _a.shadow, shadow = _e === void 0 ? '0 0.05rem 0.1rem rgba(0, 0, 0, 0.5)' : _e, _f = _a.translate, translate = _f === void 0 ? ['0px', '0px'] : _f; var statusStyle = { color: color, fontSize: fontSize, fontWeight: fontWeight, textShadow: shadow, transform: "translate(".concat(translate[0], ", ").concat(translate[1], ")"), }; return (jsx("p", { className: "react-responsive-3d-carousel__status", "aria-label": "".concat(curIndex + 1, " of ").concat(length), style: statusStyle, children: "".concat(curIndex + 1, " / ").concat(length) })); }; Status.displayName = 'Status'; var CarouselContext = createContext({ curIndex: 0, setCurIndex: function (_) { }, slideNext: function () { }, slidePrev: function () { }, }); var Carousel = function (_a) { var children = _a.children, _b = _a.ariaLabel, ariaLabel = _b === void 0 ? '3d carousel' : _b, items = _a.items, _c = _a.startIndex, startIndex = _c === void 0 ? 0 : _c, /** Container */ _d = _a.containerHeight, /** Container */ containerHeight = _d === void 0 ? 'auto' : _d, _e = _a.containerWidth, containerWidth = _e === void 0 ? '100%' : _e, _f = _a.containerPadding, containerPadding = _f === void 0 ? '1rem' : _f, /** Carousel 2D */ _g = _a.width, /** Carousel 2D */ strNumWidth = _g === void 0 ? '400px' : _g, _h = _a.height, strNumHeight = _h === void 0 ? '300px' : _h, _j = _a.aspectRatio, aspectRatio = _j === void 0 ? 'auto' : _j, _k = _a.align, align = _k === void 0 ? 'center' : _k, _l = _a.boxShadow, boxShadow = _l === void 0 ? '0 0.1rem 0.5rem rgba(0, 0, 0, 0.5)' : _l, /** Carousel 3D */ _m = _a.perspective, /** Carousel 3D */ perspective = _m === void 0 ? 1 : _m, _o = _a.perspectiveOrigin, perspectiveOrigin = _o === void 0 ? 'center' : _o, _p = _a.layout, layout = _p === void 0 ? 'default' : _p, defaultOption = _a.defaultOption, /** Carousel Transition */ _q = _a.sizeDuration, /** Carousel Transition */ sizeDuration = _q === void 0 ? 1000 : _q, _r = _a.sizeTimingFn, sizeTimingFn = _r === void 0 ? 'ease-in-out' : _r, _s = _a.transformDuration, transformDuration = _s === void 0 ? 1000 : _s, _t = _a.transformTimingFn, transformTimingFn = _t === void 0 ? 'ease-in-out' : _t, /** Carousel Interaction */ _u = _a.focusOnSelect, /** Carousel Interaction */ focusOnSelect = _u === void 0 ? true : _u, _v = _a.pauseOnHover, pauseOnHover = _v === void 0 ? true : _v, _w = _a.pauseOnTransition, pauseOnTransition = _w === void 0 ? 'both' : _w, /** Carousel Callback */ onClickItem = _a.onClickItem, onChange = _a.onChange, /** Carousel Play */ _x = _a.autoPlay, /** Carousel Play */ autoPlay = _x === void 0 ? true : _x, _y = _a.interval, interval = _y === void 0 ? 3000 : _y, _z = _a.infiniteLoop, infiniteLoop = _z === void 0 ? true : _z, /** Carousel Focus */ _0 = _a.autoFocus, /** Carousel Focus */ autoFocus = _0 === void 0 ? false : _0, _1 = _a.slideWithKeyboard, slideWithKeyboard = _1 === void 0 ? 'both' : _1, /** Carousel Swipe */ _2 = _a.swipeable, /** Carousel Swipe */ swipeable = _2 === void 0 ? true : _2, _3 = _a.swipeDirection, swipeDirection = _3 === void 0 ? 'horizontal' : _3, onSwipeStart = _a.onSwipeStart, onSwipeEnd = _a.onSwipeEnd, onSwipeMove = _a.onSwipeMove, /* Status */ _4 = _a.showStatus, /* Status */ showStatus = _4 === void 0 ? true : _4, status = _a.status, /* Arrows */ _5 = _a.showArrows, /* Arrows */ showArrows = _5 === void 0 ? true : _5, arrows = _a.arrows, /* Indicators */ _6 = _a.showIndicators, /* Indicators */ showIndicators = _6 === void 0 ? true : _6, indicators = _a.indicators; var containerRef = useRef(null); // The carousel container element var listRef = useRef(null); // The carousel list element var pauseRef = useRef(false); // Flag to pause carousel auto play var transitionRef = useRef({ size: false, transform: false }); // Flag to prevent multiple transitions var _7 = useState(startIndex), curIndex = _7[0], setCurIndex = _7[1]; // Current center carousel's index // Transform number or string type width and height to string type var width = useMemo(function () { return typeof strNumWidth === 'number' ? "calc(".concat(strNumWidth, " * var(").concat(CSS_VARIABLE.CONTAINER_WIDTH, "))") : strNumWidth; }, [strNumWidth]); var height = useMemo(function () { return typeof strNumHeight === 'number' ? "calc(".concat(strNumHeight, " * var(").concat(CSS_VARIABLE.CONTAINER_HEIGHT, "))") : strNumHeight; }, [strNumHeight]); var htmlItemsRef = useRef([]); /** * Memoize renderedItems */ useEffect(function () { var container = containerRef.current; if (!container) return; htmlItemsRef.current = Array.from(container.getElementsByClassName('react-responsive-3d-carousel__item')); }, [items]); /** * Transition flags */ useEffect(function () { var sizeDurationOffset = sizeDuration - 100; var transformDurationOffset = transformDuration - 100; if (sizeDurationOffset > 0) transitionRef.current.size = true; if (transformDurationOffset > 0) transitionRef.current.transform = true; var sizeTimeoutId = setTimeout(function () { transitionRef.current.size = false; }, sizeDurationOffset); var transformTimeoutId = setTimeout(function () { transitionRef.current.transform = false; }, transformDurationOffset); return function () { clearTimeout(sizeTimeoutId); clearTimeout(transformTimeoutId); }; }, [curIndex, sizeDuration, transformDuration]); /** * Slide to the previous carousel item */ var slidePrev = useCallback(function () { if ((pauseOnTransition === 'size' || pauseOnTransition === 'both') && transitionRef.current.size) { return; } if ((pauseOnTransition === 'transform' || pauseOnTransition === 'both') && transitionRef.current.transform) { return; } setCurIndex(function (curIndex) { if (!infiniteLoop && curIndex === 0) return curIndex; return (curIndex - 1 + items.length) % items.length; }); }, [items, infiniteLoop, setCurIndex, pauseOnTransition]); /** * Slide to the next carousel item */ var slideNext = useCallback(function () { if ((pauseOnTransition === 'size' || pauseOnTransition === 'both') && transitionRef.current.size) { return; } if ((pauseOnTransition === 'transform' || pauseOnTransition === 'both') && transitionRef.current.transform) { return; } setCurIndex(function (curIndex) { if (!infiniteLoop && curIndex === items.length - 1) return curIndex; return (curIndex + 1) % items.length; }); }, [items, infiniteLoop, setCurIndex, pauseOnTransition]); /** * Sync curIndex with startIndex, if startIndex is changed */ useEffect(function () { setCurIndex(startIndex); }, [startIndex]); /** * Adjust curIndex if it's out of range */ useEffect(function () { if (curIndex < 0) setCurIndex(0); else if (items.length - 1 < curIndex) setCurIndex(items.length - 1); }, [items, curIndex]); /** * Callback function for onChange */ var isFlag = useRef(false); // Flag to prevent calling onChange on the first render useEffect(function () { if (!isFlag.current) { isFlag.current = true; return; } onChange && onChange(curIndex, items[curIndex]); }, [curIndex, onChange]); // Auto play useAutoPlay(autoPlay, interval, slideNext, pauseRef); // Set width of the list and items as CSS variables useSize(items, htmlItemsRef, listRef, width, curIndex); // Carousel layout style useLayout(items, htmlItemsRef, align, width, height, aspectRatio, layout, curIndex, defaultOption); // Swipe feature useSwipe({ containerRef: containerRef, swipeable: swipeable, swipeDirection: swipeDirection, slideNext: slideNext, slidePrev: slidePrev, onSwipeStart: onSwipeStart, onSwipeEnd: onSwipeEnd, onSwipeMove: onSwipeMove, }); // Focus and keyboard navigation useFocus(containerRef, autoFocus, slideWithKeyboard, slideNext, slidePrev); /** * Handler functions */ var handleClickItem = function (e, index) { focusOnSelect && setCurIndex(index); onClickItem && onClickItem(e, index, items[curIndex], curIndex === index); }; var handleMouseEnterItem = function () { pauseOnHover && (pauseRef.current = true); }; var handleMouseLeaveItem = function () { pauseOnHover && (pauseRef.current = false); }; var handleClickNextArrow = function (e) { slideNext(); (arrows === null || arrows === void 0 ? void 0 : arrows.onClickNext) && arrows.onClickNext(e); }; var handleClickPrevArrow = function (e) { slidePrev(); (arrows === null || arrows === void 0 ? void 0 : arrows.onClickPrev) && arrows.onClickPrev(e); }; var handleClickIndicator = function (e, index) { setCurIndex(index); (indicators === null || indicators === void 0 ? void 0 : indicators.onClick) && indicators.onClick(e, index); }; /** * Styles */ var containerStyle = { width: containerWidth, height: containerHeight, padding: containerPadding, }; var listStyle = { perspective: typeof perspective === 'number' ? "calc(".concat(perspective, " * var(").concat(CSS_VARIABLE.CONTAINER_WIDTH, "))") : perspective, perspectiveOrigin: perspectiveOrigin, height: containerHeight === 'auto' ? 'auto' : '100%', }; var itemStyle = { width: width, height: height, aspectRatio: aspectRatio, transition: "transform ".concat(transformDuration, "ms ").concat(transformTimingFn, ", width ").concat(sizeDuration, "ms ").concat(sizeTimingFn, ", height ").concat(sizeDuration, "ms ").concat(sizeTimingFn), cursor: focusOnSelect ? 'pointer' : 'initial', top: align === 'top' ? '0%' : align === 'bottom' ? '100%' : '50%', boxShadow: boxShadow, }; return (jsx(CarouselContext.Provider, { value: { curIndex: curIndex, setCurIndex: setCurIndex, slideNext: slideNext, slidePrev: slidePrev }, children: jsxs("div", { className: "react-responsive-3d-carousel", "aria-label": ariaLabel, tabIndex: slideWithKeyboard !== 'none' ? 0 : undefined, style: containerStyle, ref: containerRef, children: [jsxs("ul", { className: "react-responsive-3d-carousel__list", style: listStyle, ref: listRef, children: [jsx("div", { className: "react-responsive-3d-carousel__dummy", style: __assign(__assign({}, itemStyle), { visibility: 'hidden' }) }), items.map(function (item, index) { return (jsx("li", { className: "react-responsive-3d-carousel__item \n ".concat((width !== 'auto' || (height !== 'auto' && aspectRatio !== 'auto')) ? 'fixed-width' : '', " \n ").concat((height !== 'auto' || (width !== 'auto' && aspectRatio !== 'auto')) ? 'fixed-height' : ''), onClick: function (e) { return handleClickItem(e, index); }, style: itemStyle, onMouseEnter: handleMouseEnterItem, onMouseLeave: handleMouseLeaveItem, children: item }, index)); }), children] }), showStatus && (jsx("div", { className: "react-responsive-3d-carousel__status-container", children: jsx(Status, __assign({ length: items.length, curIndex: curIndex }, status)) })), showArrows && (jsx("div", { className: "react-responsive-3d-carousel__arrows-container", children: jsx(Arrows, __assign({ onClickNext: handleClickNextArrow, onClickPrev: handleClickPrevArrow }, arrows)) })), showIndicators && (jsx("div", { className: "react-responsive-3d-carousel__indicators-container", children: jsx(Indicators, __assign({ length: items.length, curIndex: curIndex, onClick: handleClickIndicator }, indicators)) }))] }) })); }; export { Arrows, Carousel, CarouselContext, Indicators, Status };