444 lines
14 KiB
JavaScript
444 lines
14 KiB
JavaScript
"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 _css = _interopRequireDefault(require("dom-helpers/css"));
|
|
|
|
var _transitionEnd = _interopRequireDefault(require("dom-helpers/transitionEnd"));
|
|
|
|
var _react = _interopRequireWildcard(require("react"));
|
|
|
|
var _uncontrollable = require("uncontrollable");
|
|
|
|
var _CarouselCaption = _interopRequireDefault(require("./CarouselCaption"));
|
|
|
|
var _CarouselItem = _interopRequireDefault(require("./CarouselItem"));
|
|
|
|
var _ElementChildren = require("./ElementChildren");
|
|
|
|
var _SafeAnchor = _interopRequireDefault(require("./SafeAnchor"));
|
|
|
|
var _ThemeProvider = require("./ThemeProvider");
|
|
|
|
var _triggerBrowserReflow = _interopRequireDefault(require("./triggerBrowserReflow"));
|
|
|
|
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, _css.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 (0, _transitionEnd.default)(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, 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"]; |