UNPKG

8.49 kBJavaScriptView Raw
1import _assertThisInitialized from "@babel/runtime/helpers/esm/assertThisInitialized";
2import _inheritsLoose from "@babel/runtime/helpers/esm/inheritsLoose";
3import React from 'react';
4import PropTypes from 'prop-types';
5import classNames from 'classnames';
6import CarouselItem from './CarouselItem';
7import { mapToCssModules } from './utils';
8
9var Carousel =
10/*#__PURE__*/
11function (_React$Component) {
12 _inheritsLoose(Carousel, _React$Component);
13
14 function Carousel(props) {
15 var _this;
16
17 _this = _React$Component.call(this, props) || this;
18 _this.handleKeyPress = _this.handleKeyPress.bind(_assertThisInitialized(_this));
19 _this.renderItems = _this.renderItems.bind(_assertThisInitialized(_this));
20 _this.hoverStart = _this.hoverStart.bind(_assertThisInitialized(_this));
21 _this.hoverEnd = _this.hoverEnd.bind(_assertThisInitialized(_this));
22 _this.state = {
23 direction: 'right',
24 indicatorClicked: false
25 };
26 return _this;
27 }
28
29 var _proto = Carousel.prototype;
30
31 _proto.getChildContext = function getChildContext() {
32 return {
33 direction: this.state.direction
34 };
35 };
36
37 _proto.componentDidMount = function componentDidMount() {
38 // Set up the cycle
39 if (this.props.ride === 'carousel') {
40 this.setInterval();
41 } // TODO: move this to the specific carousel like bootstrap. Currently it will trigger ALL carousels on the page.
42
43
44 document.addEventListener('keyup', this.handleKeyPress);
45 };
46
47 _proto.componentWillReceiveProps = function componentWillReceiveProps(nextProps) {
48 this.setInterval(nextProps); // Calculate the direction to turn
49
50 if (this.props.activeIndex + 1 === nextProps.activeIndex) {
51 this.setState({
52 direction: 'right'
53 });
54 } else if (this.props.activeIndex - 1 === nextProps.activeIndex) {
55 this.setState({
56 direction: 'left'
57 });
58 } else if (this.props.activeIndex > nextProps.activeIndex) {
59 this.setState({
60 direction: this.state.indicatorClicked ? 'left' : 'right'
61 });
62 } else if (this.props.activeIndex !== nextProps.activeIndex) {
63 this.setState({
64 direction: this.state.indicatorClicked ? 'right' : 'left'
65 });
66 }
67
68 this.setState({
69 indicatorClicked: false
70 });
71 };
72
73 _proto.componentWillUnmount = function componentWillUnmount() {
74 this.clearInterval();
75 document.removeEventListener('keyup', this.handleKeyPress);
76 };
77
78 _proto.setInterval = function (_setInterval) {
79 function setInterval() {
80 return _setInterval.apply(this, arguments);
81 }
82
83 setInterval.toString = function () {
84 return _setInterval.toString();
85 };
86
87 return setInterval;
88 }(function (props) {
89 if (props === void 0) {
90 props = this.props;
91 }
92
93 // make sure not to have multiple intervals going...
94 this.clearInterval();
95
96 if (props.interval) {
97 this.cycleInterval = setInterval(function () {
98 props.next();
99 }, parseInt(props.interval, 10));
100 }
101 });
102
103 _proto.clearInterval = function (_clearInterval) {
104 function clearInterval() {
105 return _clearInterval.apply(this, arguments);
106 }
107
108 clearInterval.toString = function () {
109 return _clearInterval.toString();
110 };
111
112 return clearInterval;
113 }(function () {
114 clearInterval(this.cycleInterval);
115 });
116
117 _proto.hoverStart = function hoverStart() {
118 if (this.props.pause === 'hover') {
119 this.clearInterval();
120 }
121
122 if (this.props.mouseEnter) {
123 var _this$props;
124
125 (_this$props = this.props).mouseEnter.apply(_this$props, arguments);
126 }
127 };
128
129 _proto.hoverEnd = function hoverEnd() {
130 if (this.props.pause === 'hover') {
131 this.setInterval();
132 }
133
134 if (this.props.mouseLeave) {
135 var _this$props2;
136
137 (_this$props2 = this.props).mouseLeave.apply(_this$props2, arguments);
138 }
139 };
140
141 _proto.handleKeyPress = function handleKeyPress(evt) {
142 if (this.props.keyboard) {
143 if (evt.keyCode === 37) {
144 this.props.previous();
145 } else if (evt.keyCode === 39) {
146 this.props.next();
147 }
148 }
149 };
150
151 _proto.renderItems = function renderItems(carouselItems, className) {
152 var _this2 = this;
153
154 var slide = this.props.slide;
155 return React.createElement("div", {
156 className: className
157 }, carouselItems.map(function (item, index) {
158 var isIn = index === _this2.props.activeIndex;
159 return React.cloneElement(item, {
160 in: isIn,
161 slide: slide
162 });
163 }));
164 };
165
166 _proto.render = function render() {
167 var _this3 = this;
168
169 var _this$props3 = this.props,
170 cssModule = _this$props3.cssModule,
171 slide = _this$props3.slide,
172 className = _this$props3.className;
173 var outerClasses = mapToCssModules(classNames(className, 'carousel', slide && 'slide'), cssModule);
174 var innerClasses = mapToCssModules(classNames('carousel-inner'), cssModule); // filter out booleans, null, or undefined
175
176 var children = this.props.children.filter(function (child) {
177 return child !== null && child !== undefined && typeof child !== 'boolean';
178 });
179 var slidesOnly = children.every(function (child) {
180 return child.type === CarouselItem;
181 }); // Rendering only slides
182
183 if (slidesOnly) {
184 return React.createElement("div", {
185 className: outerClasses,
186 onMouseEnter: this.hoverStart,
187 onMouseLeave: this.hoverEnd
188 }, this.renderItems(children, innerClasses));
189 } // Rendering slides and controls
190
191
192 if (children[0] instanceof Array) {
193 var _carouselItems = children[0];
194 var _controlLeft = children[1];
195 var _controlRight = children[2];
196 return React.createElement("div", {
197 className: outerClasses,
198 onMouseEnter: this.hoverStart,
199 onMouseLeave: this.hoverEnd
200 }, this.renderItems(_carouselItems, innerClasses), _controlLeft, _controlRight);
201 } // Rendering indicators, slides and controls
202
203
204 var indicators = children[0];
205
206 var wrappedOnClick = function wrappedOnClick(e) {
207 if (typeof indicators.props.onClickHandler === 'function') {
208 _this3.setState({
209 indicatorClicked: true
210 }, function () {
211 return indicators.props.onClickHandler(e);
212 });
213 }
214 };
215
216 var wrappedIndicators = React.cloneElement(indicators, {
217 onClickHandler: wrappedOnClick
218 });
219 var carouselItems = children[1];
220 var controlLeft = children[2];
221 var controlRight = children[3];
222 return React.createElement("div", {
223 className: outerClasses,
224 onMouseEnter: this.hoverStart,
225 onMouseLeave: this.hoverEnd
226 }, wrappedIndicators, this.renderItems(carouselItems, innerClasses), controlLeft, controlRight);
227 };
228
229 return Carousel;
230}(React.Component);
231
232Carousel.propTypes = {
233 // the current active slide of the carousel
234 activeIndex: PropTypes.number,
235 // a function which should advance the carousel to the next slide (via activeIndex)
236 next: PropTypes.func.isRequired,
237 // a function which should advance the carousel to the previous slide (via activeIndex)
238 previous: PropTypes.func.isRequired,
239 // controls if the left and right arrow keys should control the carousel
240 keyboard: PropTypes.bool,
241
242 /* If set to "hover", pauses the cycling of the carousel on mouseenter and resumes the cycling of the carousel on
243 * mouseleave. If set to false, hovering over the carousel won't pause it. (default: "hover")
244 */
245 pause: PropTypes.oneOf(['hover', false]),
246 // Autoplays the carousel after the user manually cycles the first item. If "carousel", autoplays the carousel on load.
247 // This is how bootstrap defines it... I would prefer a bool named autoplay or something...
248 ride: PropTypes.oneOf(['carousel']),
249 // the interval at which the carousel automatically cycles (default: 5000)
250 // eslint-disable-next-line react/no-unused-prop-types
251 interval: PropTypes.oneOfType([PropTypes.number, PropTypes.string, PropTypes.bool]),
252 children: PropTypes.array,
253 // called when the mouse enters the Carousel
254 mouseEnter: PropTypes.func,
255 // called when the mouse exits the Carousel
256 mouseLeave: PropTypes.func,
257 // controls whether the slide animation on the Carousel works or not
258 slide: PropTypes.bool,
259 cssModule: PropTypes.object,
260 className: PropTypes.string
261};
262Carousel.defaultProps = {
263 interval: 5000,
264 pause: 'hover',
265 keyboard: true,
266 slide: true
267};
268Carousel.childContextTypes = {
269 direction: PropTypes.string
270};
271export default Carousel;
\No newline at end of file