backpack-ui
Version:
Lonely Planet's Components
488 lines (393 loc) • 14.5 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _extends2 = require("babel-runtime/helpers/extends");
var _extends3 = _interopRequireDefault(_extends2);
var _getPrototypeOf = require("babel-runtime/core-js/object/get-prototype-of");
var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck");
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
var _createClass2 = require("babel-runtime/helpers/createClass");
var _createClass3 = _interopRequireDefault(_createClass2);
var _possibleConstructorReturn2 = require("babel-runtime/helpers/possibleConstructorReturn");
var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
var _inherits2 = require("babel-runtime/helpers/inherits");
var _inherits3 = _interopRequireDefault(_inherits2);
var _defineProperty2 = require("babel-runtime/helpers/defineProperty");
var _defineProperty3 = _interopRequireDefault(_defineProperty2);
var _2, _3;
var _react = require("react");
var _react2 = _interopRequireDefault(_react);
var _propTypes = require("prop-types");
var _propTypes2 = _interopRequireDefault(_propTypes);
var _radium = require("radium");
var _radium2 = _interopRequireDefault(_radium);
var _iconButton = require("../iconButton");
var _iconButton2 = _interopRequireDefault(_iconButton);
var _mq = require("../../styles/mq");
var _mq2 = _interopRequireDefault(_mq);
var _timing = require("../../styles/timing");
var _timing2 = _interopRequireDefault(_timing);
var _zIndex = require("../../styles/zIndex");
var _zIndex2 = _interopRequireDefault(_zIndex);
var _propTypes3 = require("../../utils/propTypes");
var _propTypes4 = _interopRequireDefault(_propTypes3);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var styles = {
container: {
position: "relative"
},
slider: {
default: {
overflow: "hidden",
overflowX: "hidden",
overflowY: "hidden"
},
draggable: {
overflow: "initial",
overflowX: "visible",
overflowY: "hidden"
}
},
children: {
default: {
overflow: "hidden",
overflowX: "hidden",
overflowY: "hidden",
position: "relative",
whiteSpace: "nowrap"
},
defaultCellSpacing: (0, _defineProperty3.default)({
marginRight: "-20px"
}, "@media (max-width: " + _mq2.default.max["480"] + ")", {
marginRight: "-12px"
}),
draggable: {
overflow: "initial",
overflowX: "scroll",
overflowY: "hidden",
WebkitOverflowScrolling: "touch"
}
},
child: {
default: {
display: "inline-block",
left: 0,
position: "relative",
top: 0,
transition: "transform " + _timing2.default.default + " ease-out",
verticalAlign: "top",
whiteSpace: "normal",
width: "25%"
},
defaultCellSpacing: (0, _defineProperty3.default)({
paddingRight: "20px"
}, "@media (max-width: " + _mq2.default.max["480"] + ")", {
paddingRight: "12px"
}),
1: {
width: "100%"
},
2: (0, _defineProperty3.default)({
width: "50%"
}, "@media (max-width: " + _mq2.default.max["360"] + ")", {
width: "100%"
}),
3: (_2 = {
width: "33.333%"
}, (0, _defineProperty3.default)(_2, "@media (max-width: " + _mq2.default.max["720"] + ")", {
width: "50%"
}), (0, _defineProperty3.default)(_2, "@media (max-width: " + _mq2.default.max["360"] + ")", {
width: "100%"
}), _2),
4: (_3 = {
width: "25%"
}, (0, _defineProperty3.default)(_3, "@media (max-width: " + _mq2.default.max["960"] + ")", {
width: "33.333%"
}), (0, _defineProperty3.default)(_3, "@media (max-width: " + _mq2.default.max["720"] + ")", {
width: "50%"
}), (0, _defineProperty3.default)(_3, "@media (max-width: " + _mq2.default.max["360"] + ")", {
width: "100%"
}), _3)
},
arrowContainer: {
display: "flex",
flexDirection: "column",
height: "100%",
justifyContent: "center",
position: "absolute",
top: 0,
transition: "opacity " + _timing2.default.fast,
width: 0,
zIndex: _zIndex2.default.default
},
arrow: {
default: {
cursor: "inherit",
fontSize: "9px",
height: "4.4444em",
position: "relative",
width: "4.4444em"
},
next: {
right: "2.2222em"
},
prev: {
left: "-2.2222em"
}
}
};
var VideoSlider = function (_React$Component) {
(0, _inherits3.default)(VideoSlider, _React$Component);
function VideoSlider(props) {
(0, _classCallCheck3.default)(this, VideoSlider);
var _this = (0, _possibleConstructorReturn3.default)(this, (VideoSlider.__proto__ || (0, _getPrototypeOf2.default)(VideoSlider)).call(this, props));
_this.onWindowResize = function () {
// We rewind to avoid visual glitch where cards aren't evenly spaced.
// This also forces the component to re-evaluate which arrows should be
// shown when media-query breakpoints are hit.
_this.setState({ index: 0 });
};
_this.onMouseEnter = function () {
_this.hovering = true;
};
_this.onMouseLeave = function () {
_this.hovering = false;
};
_this.onAutoplayInterval = function () {
if (!_this.props.pauseOnHover || !_this.hovering) {
_this.next();
}
};
_this.onClickPrevArrow = function () {
_this.prev();
};
_this.onClickNextArrow = function () {
_this.next();
};
_this.getFrameCount = function () {
var responsiveSlidesToShow = _this.getResponsiveSlidesToShow();
return Math.ceil(_react2.default.Children.count(_this.props.children) / responsiveSlidesToShow);
};
_this.getResponsiveSlidesToShow = function () {
var _this$props = _this.props,
mqSlidesToShow = _this$props.mqSlidesToShow,
slidesToShow = _this$props.slidesToShow;
if (slidesToShow) {
return slidesToShow;
}
var width = typeof window === "undefined" ? null : window.innerWidth;
// TODO: Use window.matchMedia
if (width === null || width > 960) {
return mqSlidesToShow;
} else if (width > 720) {
return mqSlidesToShow < 3 ? mqSlidesToShow : 3;
} else if (width > 360) {
return mqSlidesToShow < 2 ? mqSlidesToShow : 2;
}
return 1;
};
_this.setAutoplayInterval = function () {
var _this$props2 = _this.props,
autoplay = _this$props2.autoplay,
autoplaySpeed = _this$props2.autoplaySpeed,
draggable = _this$props2.draggable;
clearInterval(_this.autoplayIntervalId);
if (autoplay && !draggable) {
_this.autoplayIntervalId = setInterval(_this.onAutoplayInterval.bind(_this), autoplaySpeed);
}
};
_this.prev = function () {
var infinite = _this.props.infinite;
var index = _this.state.index;
var frameCount = _this.getFrameCount();
var endValue = infinite ? frameCount - 1 : index;
var prevIndex = index - 1 < 0 ? endValue : index - 1;
_this.setState({
index: prevIndex
});
};
_this.next = function () {
var infinite = _this.props.infinite;
var index = _this.state.index;
var frameCount = _this.getFrameCount();
var endValue = infinite ? 0 : index;
var nextIndex = index + 1 >= frameCount ? endValue : index + 1;
_this.setState({
index: nextIndex
});
};
_this.scroller = null;
_this.state = {
index: 0
};
_this.autoplayIntervalId = null;
_this.hovering = false;
return _this;
}
(0, _createClass3.default)(VideoSlider, [{
key: "componentDidMount",
value: function componentDidMount() {
this.setAutoplayInterval();
if (typeof window !== "undefined") {
window.addEventListener("resize", this.onWindowResize);
}
}
}, {
key: "componentWillReceiveProps",
value: function componentWillReceiveProps(nextProps) {
if (nextProps.draggable !== this.props.draggable) {
// Issue: Setting scrollLeft doesn't always bring the slider back
// to where we'd like (there is like a 20 pixel offset sometimes),
// but this is simply here for convenience anyway, so leaving for now.
this.scroller.scrollLeft = 0;
this.setState({ index: 0 });
}
if (this.props.slidesToShow !== nextProps.slidesToShow) {
// We rewind in this case to avoid situations where the new "current frame"
// wouldn't have any children in it (specifically, if slidesToShow went
// from a low number to a high number and the user was on the last frame
// in the slider at the time)
this.setState({ index: 0 });
}
if (nextProps.draggable) {
clearInterval(this.autoplayIntervalId);
}
}
}, {
key: "componentDidUpdate",
value: function componentDidUpdate(prevProps) {
var shouldSetAutoplayInterval = prevProps.draggable && !this.props.draggable || this.props.autoplay !== prevProps.autoplay || this.props.autoplaySpeed !== prevProps.autoplaySpeed;
if (shouldSetAutoplayInterval) {
this.setAutoplayInterval();
}
}
}, {
key: "componentWillUnmount",
value: function componentWillUnmount() {
clearInterval(this.autoplayIntervalId);
if (typeof window !== "undefined") {
window.removeEventListener("resize", this.onWindowResize);
}
}
}, {
key: "render",
value: function render() {
var _this2 = this;
var _props = this.props,
children = _props.children,
mqSlidesToShow = _props.mqSlidesToShow,
slidesToShow = _props.slidesToShow,
cellSpacing = _props.cellSpacing,
infinite = _props.infinite,
draggable = _props.draggable,
arrows = _props.arrows,
arrowProps = _props.arrowProps,
childStyle = _props.childStyle,
style = _props.style;
var index = this.state.index;
var frameCount = this.getFrameCount();
var showNextArrow = infinite || index !== frameCount - 1;
var showPrevArrow = infinite || index !== 0;
var translateXAmount = "-" + index * 100 * this.getResponsiveSlidesToShow() + "%";
return _react2.default.createElement(
"div",
{
className: "VideoSlider" + (draggable ? " VideoSlider-draggable" : ""),
onMouseEnter: this.onMouseEnter,
onMouseLeave: this.onMouseLeave,
style: [styles.container, style]
},
draggable && _react2.default.createElement(_radium.Style, {
scopeSelector: ".VideoSlider-draggable",
rules: {
"::-webkit-scrollbar": {
display: "none"
}
}
}),
arrows && !draggable && _react2.default.createElement(
"div",
{
style: [styles.arrowContainer, { left: 0 }, { opacity: showPrevArrow ? 1 : 0 }]
},
_react2.default.createElement(_iconButton2.default, (0, _extends3.default)({
shadow: true
}, arrowProps, {
iconName: "ChevronLeft",
label: "Previous",
onClick: this.onClickPrevArrow,
style: [styles.arrow.default, styles.arrow.prev, { cursor: showPrevArrow ? "pointer" : "default" }, arrowProps.style]
}))
),
arrows && !draggable && _react2.default.createElement(
"div",
{
style: [styles.arrowContainer, { right: 0 }, { opacity: showNextArrow ? 1 : 0 }]
},
_react2.default.createElement(_iconButton2.default, (0, _extends3.default)({
shadow: true
}, arrowProps, {
iconName: "ChevronRight",
label: "Next",
onClick: this.onClickNextArrow,
style: [styles.arrow.default, styles.arrow.next, { cursor: showNextArrow ? "pointer" : "default" }, arrowProps.style]
}))
),
_react2.default.createElement(
"div",
{
style: [styles.slider.default, draggable && styles.slider.draggable]
},
_react2.default.createElement(
"div",
{
ref: function ref(_ref) {
_this2.scroller = _ref;
},
style: [styles.children.default, draggable && styles.children.draggable, typeof cellSpacing === "number" && { marginRight: "-" + cellSpacing + "px" }, typeof cellSpacing !== "number" && styles.children.defaultCellSpacing]
},
_react2.default.Children.map(children, function (child, i) {
return _react2.default.createElement(
"div",
{
key: i,
style: [styles.child.default, typeof slidesToShow === "number" && { width: 100 / slidesToShow + "%" }, typeof slidesToShow !== "number" && styles.child[mqSlidesToShow], typeof cellSpacing === "number" && { paddingRight: cellSpacing + "px" }, typeof cellSpacing !== "number" && styles.child.defaultCellSpacing, childStyle, { transform: "translateX(" + translateXAmount + ")" }]
},
child
);
})
)
)
);
}
}]);
return VideoSlider;
}(_react2.default.Component);
VideoSlider.propTypes = {
children: _propTypes2.default.arrayOf(_propTypes2.default.element).isRequired,
mqSlidesToShow: _propTypes2.default.oneOf([1, 2, 3, 4]).isRequired,
slidesToShow: _propTypes2.default.number,
cellSpacing: _propTypes2.default.number,
arrows: _propTypes2.default.bool,
arrowProps: _propTypes2.default.shape((0, _extends3.default)({}, _iconButton2.default.propTypes, {
iconName: _propTypes2.default.string,
label: _propTypes2.default.string
})),
infinite: _propTypes2.default.bool,
draggable: _propTypes2.default.bool,
autoplay: _propTypes2.default.bool,
autoplaySpeed: _propTypes2.default.number,
pauseOnHover: _propTypes2.default.bool,
childStyle: _propTypes4.default.style,
style: _propTypes4.default.style
};
VideoSlider.defaultProps = {
mqSlidesToShow: 4,
autoplaySpeed: 5000,
pauseOnHover: true,
arrows: true,
arrowProps: {}
};
exports.default = (0, _radium2.default)(VideoSlider);