UNPKG

@coreui/react-pro

Version:

UI Components Library for React.js

174 lines (170 loc) 7.38 kB
'use strict'; var tslib_es6 = require('../../node_modules/tslib/tslib.es6.js'); var React = require('react'); var PropTypes = require('prop-types'); var index = require('../../_virtual/index.js'); var isRTL = require('../../utils/isRTL.js'); var isInViewport = require('../../utils/isInViewport.js'); var swipe = require('../../utils/swipe.js'); require('@popperjs/core'); var useForkedRef = require('../../hooks/useForkedRef.js'); var CCarouselContext = require('./CCarouselContext.js'); const CCarousel = React.forwardRef((_a, ref) => { var { children, activeIndex = 0, className, controls, dark, indicators, interval = 5000, onSlid, onSlide, pause = 'hover', touch = true, transition, wrap = true } = _a, rest = tslib_es6.__rest(_a, ["children", "activeIndex", "className", "controls", "dark", "indicators", "interval", "onSlid", "onSlide", "pause", "touch", "transition", "wrap"]); const carouselRef = React.useRef(null); const forkedRef = useForkedRef.useForkedRef(ref, carouselRef); const data = React.useRef({}).current; const handleControlClickRef = React.useRef(() => undefined); const [active, setActive] = React.useState(activeIndex); const [animating, setAnimating] = React.useState(false); const [customInterval, setCustomInterval] = React.useState(); const [direction, setDirection] = React.useState('next'); const [itemsNumber, setItemsNumber] = React.useState(0); const [visible, setVisible] = React.useState(); React.useEffect(() => { setItemsNumber(React.Children.toArray(children).length); }, [children]); React.useEffect(() => { if (visible) { cycle(); } }, [visible]); React.useEffect(() => { if (animating) { onSlide === null || onSlide === void 0 ? void 0 : onSlide(active, direction); } else { cycle(); onSlid === null || onSlid === void 0 ? void 0 : onSlid(active, direction); } }, [animating]); React.useEffect(() => { window.addEventListener('scroll', handleScroll); return () => { window.removeEventListener('scroll', handleScroll); }; }, []); React.useEffect(() => { if (!touch || !carouselRef.current) { return; } const swipe$1 = new swipe.default(carouselRef.current, { onLeft: () => handleControlClickRef.current(isRTL.default(carouselRef.current) ? 'prev' : 'next'), onRight: () => handleControlClickRef.current(isRTL.default(carouselRef.current) ? 'next' : 'prev'), }); return () => swipe$1.dispose(); }, [touch]); React.useEffect(() => { return () => clearCycleTimeout(); }, []); const clearCycleTimeout = () => { if (data.timeout) { clearTimeout(data.timeout); data.timeout = null; } }; const cycle = () => { clearCycleTimeout(); if (!wrap && active === itemsNumber - 1) { return; } if (typeof interval === 'number') { data.timeout = setTimeout(() => nextItemWhenVisible(), typeof customInterval === 'number' ? customInterval : interval); } }; const _pause = () => pause && clearCycleTimeout(); const nextItemWhenVisible = () => { // Don't call next when the page isn't visible // or the carousel or its parent isn't visible if (!document.hidden && carouselRef.current && isInViewport.default(carouselRef.current)) { if (animating) { return; } handleControlClick('next'); } }; const handleControlClick = (direction) => { if (animating) { return; } setDirection(direction); if (direction === 'next') { setActive(active === itemsNumber - 1 ? 0 : active + 1); } else { setActive(active === 0 ? itemsNumber - 1 : active - 1); } }; handleControlClickRef.current = handleControlClick; const handleIndicatorClick = (index) => { if (active === index) { return; } if (active < index) { setDirection('next'); setActive(index); return; } if (active > index) { setDirection('prev'); setActive(index); } }; const handleScroll = () => { if (!document.hidden && carouselRef.current && isInViewport.default(carouselRef.current)) { setVisible(true); } else { setVisible(false); } }; return (React.createElement("div", Object.assign({ className: index.default('carousel slide', { 'carousel-fade': transition === 'crossfade', }, className) }, (dark && { 'data-coreui-theme': 'dark' }), { onMouseEnter: _pause, onMouseLeave: cycle }, rest, { ref: forkedRef }), React.createElement(CCarouselContext.CCarouselContext.Provider, { value: { setAnimating, setCustomInterval, } }, indicators && (React.createElement("div", { className: "carousel-indicators" }, Array.from({ length: itemsNumber }, (_, i) => i).map((index$1) => { return (React.createElement("button", Object.assign({ key: `indicator${index$1}`, onClick: () => { if (!animating) { handleIndicatorClick(index$1); } }, className: index.default({ active: active === index$1, }), "data-coreui-target": "" }, (active === index$1 && { 'aria-current': true }), { "aria-label": `Slide ${index$1 + 1}` }))); }))), React.createElement("div", { className: "carousel-inner" }, React.Children.map(children, (child, index) => { if (React.isValidElement(child)) { return React.cloneElement(child, { active: active === index, direction: direction, key: index, }); } return; })), controls && (React.createElement(React.Fragment, null, React.createElement("button", { className: "carousel-control-prev", onClick: () => handleControlClick('prev') }, React.createElement("span", { className: `carousel-control-prev-icon`, "aria-label": "prev" })), React.createElement("button", { className: "carousel-control-next", onClick: () => handleControlClick('next') }, React.createElement("span", { className: `carousel-control-next-icon`, "aria-label": "next" }))))))); }); CCarousel.propTypes = { activeIndex: PropTypes.number, children: PropTypes.node, className: PropTypes.string, controls: PropTypes.bool, dark: PropTypes.bool, indicators: PropTypes.bool, interval: PropTypes.oneOfType([PropTypes.bool, PropTypes.number]), onSlid: PropTypes.func, onSlide: PropTypes.func, pause: PropTypes.oneOf([false, 'hover']), touch: PropTypes.bool, transition: PropTypes.oneOf(['slide', 'crossfade']), wrap: PropTypes.bool, }; CCarousel.displayName = 'CCarousel'; exports.CCarousel = CCarousel; //# sourceMappingURL=CCarousel.js.map