You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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