"use strict"; var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard"); var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); exports.__esModule = true; exports.default = void 0; var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var _objectWithoutPropertiesLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutPropertiesLoose")); var _inheritsLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/inheritsLoose")); var _classnames = _interopRequireDefault(require("classnames")); var _style = _interopRequireDefault(require("dom-helpers/style")); var _transition = _interopRequireDefault(require("dom-helpers/transition")); var _react = _interopRequireWildcard(require("react")); var _uncontrollable = require("uncontrollable"); var _CarouselCaption = _interopRequireDefault(require("./CarouselCaption")); var _CarouselItem = _interopRequireDefault(require("./CarouselItem")); var _SafeAnchor = _interopRequireDefault(require("./SafeAnchor")); var _ElementChildren = require("./utils/ElementChildren"); var _triggerBrowserReflow = _interopRequireDefault(require("./utils/triggerBrowserReflow")); var _ThemeProvider = require("./ThemeProvider"); var countChildren = function countChildren(c) { return _react.default.Children.toArray(c).filter(_react.default.isValidElement).length; }; var SWIPE_THRESHOLD = 40; // TODO: `slide` should be `animate`. var defaultProps = { slide: true, fade: false, interval: 5000, keyboard: true, pauseOnHover: true, wrap: true, indicators: true, controls: true, activeIndex: 0, prevIcon: _react.default.createElement("span", { "aria-hidden": "true", className: "carousel-control-prev-icon" }), prevLabel: 'Previous', nextIcon: _react.default.createElement("span", { "aria-hidden": "true", className: "carousel-control-next-icon" }), nextLabel: 'Next', touch: true }; var Carousel = /*#__PURE__*/ function (_React$Component) { (0, _inheritsLoose2.default)(Carousel, _React$Component); function Carousel() { var _this; for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _this = _React$Component.call.apply(_React$Component, [this].concat(args)) || this; _this.state = { prevClasses: '', currentClasses: 'active', touchStartX: 0 }; _this.isUnmounted = false; _this.carousel = _react.default.createRef(); _this.handleTouchStart = function (e) { _this.setState({ touchStartX: e.changedTouches[0].screenX }); }; _this.handleTouchEnd = function (e) { // If the swipe is under the threshold, don't do anything. if (Math.abs(e.changedTouches[0].screenX - _this.state.touchStartX) < SWIPE_THRESHOLD) return; if (e.changedTouches[0].screenX < _this.state.touchStartX) { // Swiping left to navigate to next item. _this.handleNext(e); } else { // Swiping right to navigate to previous item. _this.handlePrev(e); } }; _this.handleSlideEnd = function () { var pendingIndex = _this._pendingIndex; _this._isSliding = false; _this._pendingIndex = null; if (pendingIndex != null) _this.to(pendingIndex);else _this.cycle(); }; _this.handleMouseOut = function () { _this.cycle(); }; _this.handleMouseOver = function () { if (_this.props.pauseOnHover) _this.pause(); }; _this.handleKeyDown = function (event) { if (/input|textarea/i.test(event.target.tagName)) return; switch (event.key) { case 'ArrowLeft': event.preventDefault(); _this.handlePrev(event); break; case 'ArrowRight': event.preventDefault(); _this.handleNext(event); break; default: break; } }; _this.handleNextWhenVisible = function () { if (!_this.isUnmounted && !document.hidden && (0, _style.default)(_this.carousel.current, 'visibility') !== 'hidden') { _this.handleNext(); } }; _this.handleNext = function (e) { if (_this._isSliding) return; var _this$props = _this.props, wrap = _this$props.wrap, activeIndex = _this$props.activeIndex; var index = activeIndex + 1; var count = countChildren(_this.props.children); if (index > count - 1) { if (!wrap) return; index = 0; } _this.select(index, e, 'next'); }; _this.handlePrev = function (e) { if (_this._isSliding) return; var _this$props2 = _this.props, wrap = _this$props2.wrap, activeIndex = _this$props2.activeIndex; var index = activeIndex - 1; if (index < 0) { if (!wrap) return; index = countChildren(_this.props.children) - 1; } _this.select(index, e, 'prev'); }; return _this; } var _proto = Carousel.prototype; _proto.componentDidMount = function componentDidMount() { this.cycle(); }; Carousel.getDerivedStateFromProps = function getDerivedStateFromProps(nextProps, _ref) { var previousActiveIndex = _ref.activeIndex; if (nextProps.activeIndex !== previousActiveIndex) { var lastPossibleIndex = countChildren(nextProps.children) - 1; var nextIndex = Math.max(0, Math.min(nextProps.activeIndex, lastPossibleIndex)); var direction; if (nextIndex === 0 && previousActiveIndex >= lastPossibleIndex || previousActiveIndex <= nextIndex) { direction = 'next'; } else { direction = 'prev'; } return { direction: direction, previousActiveIndex: previousActiveIndex, activeIndex: nextIndex }; } return null; }; _proto.componentDidUpdate = function componentDidUpdate(_, prevState) { var _this2 = this; var _this$props3 = this.props, bsPrefix = _this$props3.bsPrefix, slide = _this$props3.slide, onSlideEnd = _this$props3.onSlideEnd; if (!slide || this.state.activeIndex === prevState.activeIndex || this._isSliding) return; var _this$state = this.state, activeIndex = _this$state.activeIndex, direction = _this$state.direction; var orderClassName, directionalClassName; if (direction === 'next') { orderClassName = bsPrefix + "-item-next"; directionalClassName = bsPrefix + "-item-left"; } else if (direction === 'prev') { orderClassName = bsPrefix + "-item-prev"; directionalClassName = bsPrefix + "-item-right"; } this._isSliding = true; this.pause(); // eslint-disable-next-line react/no-did-update-set-state this.safeSetState({ prevClasses: 'active', currentClasses: orderClassName }, function () { var items = _this2.carousel.current.children; var nextElement = items[activeIndex]; (0, _triggerBrowserReflow.default)(nextElement); _this2.safeSetState({ prevClasses: (0, _classnames.default)('active', directionalClassName), currentClasses: (0, _classnames.default)(orderClassName, directionalClassName) }, function () { return _transition.default.end(nextElement, function () { _this2.safeSetState({ prevClasses: '', currentClasses: 'active' }, _this2.handleSlideEnd); if (onSlideEnd) { onSlideEnd(); } }); }); }); }; _proto.componentWillUnmount = function componentWillUnmount() { clearTimeout(this.timeout); this.isUnmounted = true; }; _proto.safeSetState = function safeSetState(state, cb) { var _this3 = this; if (this.isUnmounted) return; this.setState(state, function () { return !_this3.isUnmounted && cb(); }); } // This might be a public API. ; _proto.pause = function pause() { this._isPaused = true; clearInterval(this._interval); this._interval = null; }; _proto.cycle = function cycle() { this._isPaused = false; clearInterval(this._interval); this._interval = null; if (this.props.interval && !this._isPaused) { this._interval = setInterval(document.visibilityState ? this.handleNextWhenVisible : this.handleNext, this.props.interval); } }; _proto.to = function to(index, event) { var children = this.props.children; if (index < 0 || index > countChildren(children) - 1) { return; } if (this._isSliding) { this._pendingIndex = index; return; } this.select(index, event); }; _proto.select = function select(index, event, direction) { var _this4 = this; clearTimeout(this.selectThrottle); if (event && event.persist) event.persist(); // The timeout throttles fast clicks, in order to give any pending state // a chance to update and propagate back through props this.selectThrottle = setTimeout(function () { clearTimeout(_this4.timeout); var _this4$props = _this4.props, activeIndex = _this4$props.activeIndex, onSelect = _this4$props.onSelect; if (index === activeIndex || _this4._isSliding || _this4.isUnmounted) return; onSelect(index, direction || (index < activeIndex ? 'prev' : 'next'), event); }, 50); }; _proto.renderControls = function renderControls(properties) { var bsPrefix = this.props.bsPrefix; var wrap = properties.wrap, children = properties.children, activeIndex = properties.activeIndex, prevIcon = properties.prevIcon, nextIcon = properties.nextIcon, prevLabel = properties.prevLabel, nextLabel = properties.nextLabel; var count = countChildren(children); return [(wrap || activeIndex !== 0) && _react.default.createElement(_SafeAnchor.default, { key: "prev", className: bsPrefix + "-control-prev", onClick: this.handlePrev }, prevIcon, prevLabel && _react.default.createElement("span", { className: "sr-only" }, prevLabel)), (wrap || activeIndex !== count - 1) && _react.default.createElement(_SafeAnchor.default, { key: "next", className: bsPrefix + "-control-next", onClick: this.handleNext }, nextIcon, nextLabel && _react.default.createElement("span", { className: "sr-only" }, nextLabel))]; }; _proto.renderIndicators = function renderIndicators(children, activeIndex) { var _this5 = this; var bsPrefix = this.props.bsPrefix; var indicators = []; (0, _ElementChildren.forEach)(children, function (child, index) { indicators.push(_react.default.createElement("li", { key: index, className: index === activeIndex ? 'active' : null, onClick: function onClick(e) { return _this5.to(index, e); } }), // Force whitespace between indicator elements. Bootstrap requires // this for correct spacing of elements. ' '); }); return _react.default.createElement("ol", { className: bsPrefix + "-indicators" }, indicators); }; _proto.render = function render() { var _this$props4 = this.props, _this$props4$as = _this$props4.as, Component = _this$props4$as === void 0 ? 'div' : _this$props4$as, bsPrefix = _this$props4.bsPrefix, slide = _this$props4.slide, fade = _this$props4.fade, indicators = _this$props4.indicators, controls = _this$props4.controls, wrap = _this$props4.wrap, touch = _this$props4.touch, prevIcon = _this$props4.prevIcon, prevLabel = _this$props4.prevLabel, nextIcon = _this$props4.nextIcon, nextLabel = _this$props4.nextLabel, className = _this$props4.className, children = _this$props4.children, keyboard = _this$props4.keyboard, _5 = _this$props4.activeIndex, _4 = _this$props4.pauseOnHover, _3 = _this$props4.interval, _2 = _this$props4.onSelect, _1 = _this$props4.onSlideEnd, props = (0, _objectWithoutPropertiesLoose2.default)(_this$props4, ["as", "bsPrefix", "slide", "fade", "indicators", "controls", "wrap", "touch", "prevIcon", "prevLabel", "nextIcon", "nextLabel", "className", "children", "keyboard", "activeIndex", "pauseOnHover", "interval", "onSelect", "onSlideEnd"]); var _this$state2 = this.state, activeIndex = _this$state2.activeIndex, previousActiveIndex = _this$state2.previousActiveIndex, prevClasses = _this$state2.prevClasses, currentClasses = _this$state2.currentClasses; return (// eslint-disable-next-line jsx-a11y/no-static-element-interactions _react.default.createElement(Component, (0, _extends2.default)({ onTouchStart: touch ? this.handleTouchStart : undefined, onTouchEnd: touch ? this.handleTouchEnd : undefined }, props, { className: (0, _classnames.default)(className, bsPrefix, slide && 'slide', fade && bsPrefix + "-fade"), onKeyDown: keyboard ? this.handleKeyDown : undefined, onMouseOver: this.handleMouseOver, onMouseOut: this.handleMouseOut }), indicators && this.renderIndicators(children, activeIndex), _react.default.createElement("div", { className: bsPrefix + "-inner", ref: this.carousel }, (0, _ElementChildren.map)(children, function (child, index) { var current = index === activeIndex; var previous = index === previousActiveIndex; return (0, _react.cloneElement)(child, { className: (0, _classnames.default)(child.props.className, bsPrefix + "-item", current && currentClasses, previous && prevClasses) }); })), controls && this.renderControls({ wrap: wrap, children: children, activeIndex: activeIndex, prevIcon: prevIcon, prevLabel: prevLabel, nextIcon: nextIcon, nextLabel: nextLabel })) ); }; return Carousel; }(_react.default.Component); Carousel.defaultProps = defaultProps; var DecoratedCarousel = (0, _ThemeProvider.createBootstrapComponent)((0, _uncontrollable.uncontrollable)(Carousel, { activeIndex: 'onSelect' }), 'carousel'); DecoratedCarousel.Caption = _CarouselCaption.default; DecoratedCarousel.Item = _CarouselItem.default; var _default = DecoratedCarousel; exports.default = _default; module.exports = exports["default"];