nuorder-carousel
Version:
React Responsive Carousel
372 lines (302 loc) • 14.3 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _react = require('react');
var _react2 = _interopRequireDefault(_react);
var _reactDom = require('react-dom');
var _reactDom2 = _interopRequireDefault(_reactDom);
var _propTypes = require('prop-types');
var _propTypes2 = _interopRequireDefault(_propTypes);
var _cssClasses = require('../cssClasses');
var _cssClasses2 = _interopRequireDefault(_cssClasses);
var _dimensions = require('../dimensions');
var _CSSTranslate = require('../CSSTranslate');
var _CSSTranslate2 = _interopRequireDefault(_CSSTranslate);
var _reactEasySwipe = require('react-easy-swipe');
var _reactEasySwipe2 = _interopRequireDefault(_reactEasySwipe);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
var Thumbs = function (_Component) {
_inherits(Thumbs, _Component);
function Thumbs(props) {
_classCallCheck(this, Thumbs);
var _this = _possibleConstructorReturn(this, (Thumbs.__proto__ || Object.getPrototypeOf(Thumbs)).call(this, props));
_this.updateSizes = function () {
if (!_this.state.initialized) {
return;
}
var total = _this.props.children.length;
_this.wrapperSize = _this.itemsWrapper.clientWidth;
_this.itemSize = (0, _dimensions.outerWidth)(_this.refs.thumb0);
_this.visibleItems = Math.floor(_this.wrapperSize / _this.itemSize);
_this.lastPosition = total - _this.visibleItems;
_this.showArrows = _this.visibleItems < total;
};
_this.setMountState = function () {
_this.setState({ hasMount: true });
_this.updateSizes();
};
_this.handleClickItem = function (index, item) {
var handler = _this.props.onSelectItem;
if (typeof handler === 'function') {
handler(index, item);
}
};
_this.onSwipeStart = function () {
_this.setState({
swiping: true
});
};
_this.onSwipeEnd = function () {
_this.setState({
swiping: false
});
};
_this.onSwipeMove = function (deltaX) {
var leftBoundry = 0;
var list = _reactDom2.default.findDOMNode(_this.itemList);
var wrapperSize = list.clientWidth;
var visibleItems = Math.floor(wrapperSize / _this.itemSize);
var currentPosition = -_this.state.firstItem * _this.itemSize;
var lastLeftBoundry = -_this.visibleItems * _this.itemSize;
// prevent user from swiping left out of boundaries
if (currentPosition === leftBoundry && deltaX > 0) {
deltaX = 0;
}
// prevent user from swiping right out of boundaries
if (currentPosition === lastLeftBoundry && deltaX < 0) {
deltaX = 0;
}
var position = currentPosition + 100 / (wrapperSize / deltaX) + '%';
// if 3d isn't available we will use left to move
['WebkitTransform', 'MozTransform', 'MsTransform', 'OTransform', 'transform', 'msTransform'].forEach(function (prop) {
list.style[prop] = (0, _CSSTranslate2.default)(position, _this.props.axis);
});
};
_this.slideRight = function (positions) {
_this.moveTo(_this.state.firstItem - (typeof positions === 'Number' ? positions : 1));
};
_this.slideLeft = function (positions) {
_this.moveTo(_this.state.firstItem + (typeof positions === 'Number' ? positions : 1));
};
_this.moveTo = function (position) {
// position can't be lower than 0
position = position < 0 ? 0 : position;
// position can't be higher than last postion
position = position >= _this.lastPosition ? _this.lastPosition : position;
_this.setState({
firstItem: position,
// if it's not a slider, we don't need to set position here
selectedItem: _this.state.selectedItem
});
};
_this.state = {
initialized: false,
selectedItem: props.selectedItem,
hasMount: false,
firstItem: _this.getFirstItem(props.selectedItem),
images: []
};
return _this;
}
_createClass(Thumbs, [{
key: 'componentDidMount',
value: function componentDidMount(nextProps) {
if (!this.props.children) {
return;
}
this.setupThumbs();
}
}, {
key: 'componentWillReceiveProps',
value: function componentWillReceiveProps(props, state) {
if (props.selectedItem !== this.state.selectedItem) {
this.setState({
selectedItem: props.selectedItem,
firstItem: this.getFirstItem(props.selectedItem)
});
}
}
}, {
key: 'componentDidUpdate',
value: function componentDidUpdate(prevProps) {
if (!prevProps.children && this.props.children && !this.state.initialized) {
this.setupThumbs();
}
}
}, {
key: 'componentWillUnmount',
value: function componentWillUnmount() {
this.destroyThumbs();
}
}, {
key: 'setupThumbs',
value: function setupThumbs() {
// as the widths are calculated, we need to resize
// the carousel when the window is resized
window.addEventListener("resize", this.updateSizes);
// issue #2 - image loading smaller
window.addEventListener("DOMContentLoaded", this.updateSizes);
var images = this.getImages();
if (!images) {
return;
}
this.setState({
initialized: true,
images: images
});
// when the component is rendered we need to calculate
// the container size to adjust the responsive behaviour
this.updateSizes();
}
}, {
key: 'destroyThumbs',
value: function destroyThumbs() {
// removing listeners
window.removeEventListener("resize", this.updateSizes);
window.removeEventListener("DOMContentLoaded", this.updateSizes);
}
}, {
key: 'getImages',
value: function getImages() {
var images = _react2.default.Children.map(this.props.children, function (item, index) {
var img = item;
// if the item is not an image, try to find the first image in the item's children.
if (item.type !== "img") {
img = _react2.default.Children.toArray(item.props.children).filter(function (children) {
return children.type === "img";
})[0];
}
if (!img || img.length === 0) {
return null;
}
return img;
});
if (images.filter(function (image) {
return image !== null;
}).length === 0) {
console.warn('No images found! Can\'t build the thumb list without images. If you don\'t need thumbs, set showThumbs={false} in the Carousel. Note that it\'s not possible to get images rendered inside custom components. More info at https://github.com/leandrowd/react-responsive-carousel/blob/master/TROUBLESHOOTING.md');
return null;
}
return images;
}
}, {
key: 'getFirstItem',
value: function getFirstItem(selectedItem) {
if (!this.showArrows) {
return 0;
}
var firstItem = selectedItem;
if (selectedItem >= this.lastPosition) {
firstItem = this.lastPosition;
}
if (selectedItem < this.state.firstItem + this.visibleItems) {
firstItem = this.state.firstItem;
}
if (selectedItem < this.state.firstItem) {
firstItem = selectedItem;
}
return firstItem;
}
}, {
key: 'renderItems',
value: function renderItems() {
var _this2 = this;
return this.state.images.map(function (img, index) {
var itemClass = _cssClasses2.default.ITEM(false, index === _this2.state.selectedItem && _this2.state.hasMount);
var thumbProps = {
key: index,
ref: 'thumb' + index,
className: itemClass,
onClick: _this2.handleClickItem.bind(_this2, index, _this2.props.children[index])
};
if (index === 0) {
img = _react2.default.cloneElement(img, {
onLoad: _this2.setMountState
});
}
return _react2.default.createElement(
'li',
thumbProps,
img
);
});
}
}, {
key: 'render',
value: function render() {
var _this3 = this;
if (!this.props.children || this.state.images.length === 0) {
return null;
}
// show left arrow?
var hasPrev = this.showArrows && this.state.firstItem > 0;
// show right arrow
var hasNext = this.showArrows && this.state.firstItem < this.lastPosition;
// obj to hold the transformations and styles
var itemListStyles = {};
var currentPosition = -this.state.firstItem * this.itemSize + 'px';
var transformProp = (0, _CSSTranslate2.default)(currentPosition, this.props.axis);
var transitionTime = this.props.transitionTime + 'ms';
itemListStyles = {
'WebkitTransform': transformProp,
'MozTransform': transformProp,
'MsTransform': transformProp,
'OTransform': transformProp,
'transform': transformProp,
'msTransform': transformProp,
'WebkitTransitionDuration': transitionTime,
'MozTransitionDuration': transitionTime,
'MsTransitionDuration': transitionTime,
'OTransitionDuration': transitionTime,
'transitionDuration': transitionTime,
'msTransitionDuration': transitionTime
};
return _react2.default.createElement(
'div',
{ className: _cssClasses2.default.CAROUSEL(false) },
_react2.default.createElement(
'div',
{ className: _cssClasses2.default.WRAPPER(false), ref: function ref(node) {
return _this3.itemsWrapper = node;
} },
_react2.default.createElement('button', { type: 'button', className: _cssClasses2.default.ARROW_PREV(!hasPrev), onClick: this.slideRight }),
_react2.default.createElement(
_reactEasySwipe2.default,
{ tagName: 'ul',
selectedItem: this.state.selectedItem,
className: _cssClasses2.default.SLIDER(false, this.state.swiping),
onSwipeLeft: this.slideLeft,
onSwipeRight: this.slideRight,
onSwipeMove: this.onSwipeMove,
onSwipeStart: this.onSwipeStart,
onSwipeEnd: this.onSwipeEnd,
style: itemListStyles,
ref: function ref(node) {
return _this3.itemList = node;
} },
this.renderItems()
),
_react2.default.createElement('button', { type: 'button', className: _cssClasses2.default.ARROW_NEXT(!hasNext), onClick: this.slideLeft })
)
);
}
}]);
return Thumbs;
}(_react.Component);
Thumbs.displayName = 'Thumbs';
Thumbs.propsTypes = {
children: _propTypes2.default.element.isRequired,
transitionTime: _propTypes2.default.number,
selectedItem: _propTypes2.default.number
};
Thumbs.defaultProps = {
selectedItem: 0,
transitionTime: 350,
axis: 'horizontal'
};
exports.default = Thumbs;