@coreui/react-pro
Version:
UI Components Library for React.js
174 lines (170 loc) • 7.38 kB
JavaScript
;
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