UNPKG

react-bootstrap

Version:

Bootstrap 3 components build with React

301 lines (241 loc) 8.69 kB
'use strict'; var _extends = require('babel-runtime/helpers/extends')['default']; var _interopRequireDefault = require('babel-runtime/helpers/interop-require-default')['default']; exports.__esModule = true; var _react = require('react'); var _react2 = _interopRequireDefault(_react); var _classnames = require('classnames'); var _classnames2 = _interopRequireDefault(_classnames); var _BootstrapMixin = require('./BootstrapMixin'); var _BootstrapMixin2 = _interopRequireDefault(_BootstrapMixin); var _utilsValidComponentChildren = require('./utils/ValidComponentChildren'); var _utilsValidComponentChildren2 = _interopRequireDefault(_utilsValidComponentChildren); var _Glyphicon = require('./Glyphicon'); var _Glyphicon2 = _interopRequireDefault(_Glyphicon); var Carousel = _react2['default'].createClass({ displayName: 'Carousel', mixins: [_BootstrapMixin2['default']], propTypes: { slide: _react2['default'].PropTypes.bool, indicators: _react2['default'].PropTypes.bool, interval: _react2['default'].PropTypes.number, controls: _react2['default'].PropTypes.bool, pauseOnHover: _react2['default'].PropTypes.bool, wrap: _react2['default'].PropTypes.bool, onSelect: _react2['default'].PropTypes.func, onSlideEnd: _react2['default'].PropTypes.func, activeIndex: _react2['default'].PropTypes.number, defaultActiveIndex: _react2['default'].PropTypes.number, direction: _react2['default'].PropTypes.oneOf(['prev', 'next']), prevIcon: _react2['default'].PropTypes.node, nextIcon: _react2['default'].PropTypes.node }, getDefaultProps: function getDefaultProps() { return { slide: true, interval: 5000, pauseOnHover: true, wrap: true, indicators: true, controls: true, prevIcon: _react2['default'].createElement(_Glyphicon2['default'], { glyph: "chevron-left" }), nextIcon: _react2['default'].createElement(_Glyphicon2['default'], { glyph: "chevron-right" }) }; }, getInitialState: function getInitialState() { return { activeIndex: this.props.defaultActiveIndex == null ? 0 : this.props.defaultActiveIndex, previousActiveIndex: null, direction: null }; }, getDirection: function getDirection(prevIndex, index) { if (prevIndex === index) { return null; } return prevIndex > index ? 'prev' : 'next'; }, componentWillReceiveProps: function componentWillReceiveProps(nextProps) { var activeIndex = this.getActiveIndex(); if (nextProps.activeIndex != null && nextProps.activeIndex !== activeIndex) { clearTimeout(this.timeout); this.setState({ previousActiveIndex: activeIndex, direction: nextProps.direction != null ? nextProps.direction : this.getDirection(activeIndex, nextProps.activeIndex) }); } }, componentDidMount: function componentDidMount() { this.waitForNext(); }, componentWillUnmount: function componentWillUnmount() { clearTimeout(this.timeout); }, next: function next(e) { if (e) { e.preventDefault(); } var index = this.getActiveIndex() + 1; var count = _utilsValidComponentChildren2['default'].numberOf(this.props.children); if (index > count - 1) { if (!this.props.wrap) { return; } index = 0; } this.handleSelect(index, 'next'); }, prev: function prev(e) { if (e) { e.preventDefault(); } var index = this.getActiveIndex() - 1; if (index < 0) { if (!this.props.wrap) { return; } index = _utilsValidComponentChildren2['default'].numberOf(this.props.children) - 1; } this.handleSelect(index, 'prev'); }, pause: function pause() { this.isPaused = true; clearTimeout(this.timeout); }, play: function play() { this.isPaused = false; this.waitForNext(); }, waitForNext: function waitForNext() { if (!this.isPaused && this.props.slide && this.props.interval && this.props.activeIndex == null) { this.timeout = setTimeout(this.next, this.props.interval); } }, handleMouseOver: function handleMouseOver() { if (this.props.pauseOnHover) { this.pause(); } }, handleMouseOut: function handleMouseOut() { if (this.isPaused) { this.play(); } }, render: function render() { var classes = { carousel: true, slide: this.props.slide }; return _react2['default'].createElement( 'div', _extends({}, this.props, { className: _classnames2['default'](this.props.className, classes), onMouseOver: this.handleMouseOver, onMouseOut: this.handleMouseOut }), this.props.indicators ? this.renderIndicators() : null, _react2['default'].createElement( 'div', { className: "carousel-inner", ref: "inner" }, _utilsValidComponentChildren2['default'].map(this.props.children, this.renderItem) ), this.props.controls ? this.renderControls() : null ); }, renderPrev: function renderPrev() { return _react2['default'].createElement( 'a', { className: "left carousel-control", href: "#prev", key: 0, onClick: this.prev }, this.props.prevIcon ); }, renderNext: function renderNext() { return _react2['default'].createElement( 'a', { className: "right carousel-control", href: "#next", key: 1, onClick: this.next }, this.props.nextIcon ); }, renderControls: function renderControls() { if (!this.props.wrap) { var activeIndex = this.getActiveIndex(); var count = _utilsValidComponentChildren2['default'].numberOf(this.props.children); return [activeIndex !== 0 ? this.renderPrev() : null, activeIndex !== count - 1 ? this.renderNext() : null]; } return [this.renderPrev(), this.renderNext()]; }, renderIndicator: function renderIndicator(child, index) { var className = index === this.getActiveIndex() ? 'active' : null; return _react2['default'].createElement('li', { key: index, className: className, onClick: this.handleSelect.bind(this, index, null) }); }, renderIndicators: function renderIndicators() { var indicators = []; _utilsValidComponentChildren2['default'].forEach(this.props.children, function (child, index) { indicators.push(this.renderIndicator(child, index), // Force whitespace between indicator elements, bootstrap // requires this for correct spacing of elements. ' '); }, this); return _react2['default'].createElement( 'ol', { className: "carousel-indicators" }, indicators ); }, getActiveIndex: function getActiveIndex() { return this.props.activeIndex != null ? this.props.activeIndex : this.state.activeIndex; }, handleItemAnimateOutEnd: function handleItemAnimateOutEnd() { this.setState({ previousActiveIndex: null, direction: null }, function () { this.waitForNext(); if (this.props.onSlideEnd) { this.props.onSlideEnd(); } }); }, renderItem: function renderItem(child, index) { var activeIndex = this.getActiveIndex(); var isActive = index === activeIndex; var isPreviousActive = this.state.previousActiveIndex != null && this.state.previousActiveIndex === index && this.props.slide; return _react.cloneElement(child, { active: isActive, ref: child.ref, key: child.key ? child.key : index, index: index, animateOut: isPreviousActive, animateIn: isActive && this.state.previousActiveIndex != null && this.props.slide, direction: this.state.direction, onAnimateOutEnd: isPreviousActive ? this.handleItemAnimateOutEnd : null }); }, handleSelect: function handleSelect(index, direction) { clearTimeout(this.timeout); if (this.isMounted()) { var previousActiveIndex = this.getActiveIndex(); direction = direction || this.getDirection(previousActiveIndex, index); if (this.props.onSelect) { this.props.onSelect(index, direction); } if (this.props.activeIndex == null && index !== previousActiveIndex) { if (this.state.previousActiveIndex != null) { // If currently animating don't activate the new index. // TODO: look into queuing this canceled call and // animating after the current animation has ended. return; } this.setState({ activeIndex: index, previousActiveIndex: previousActiveIndex, direction: direction }); } } } }); exports['default'] = Carousel; module.exports = exports['default'];