Dashboard sipadu mbip
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.

Carousel.js 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  1. import _extends from "@babel/runtime/helpers/esm/extends";
  2. import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
  3. import _inheritsLoose from "@babel/runtime/helpers/esm/inheritsLoose";
  4. import classNames from 'classnames';
  5. import styles from 'dom-helpers/style';
  6. import transition from 'dom-helpers/transition';
  7. import React, { cloneElement } from 'react';
  8. import { uncontrollable } from 'uncontrollable';
  9. import CarouselCaption from './CarouselCaption';
  10. import CarouselItem from './CarouselItem';
  11. import SafeAnchor from './SafeAnchor';
  12. import { map, forEach } from './utils/ElementChildren';
  13. import triggerBrowserReflow from './utils/triggerBrowserReflow';
  14. import { createBootstrapComponent } from './ThemeProvider';
  15. var countChildren = function countChildren(c) {
  16. return React.Children.toArray(c).filter(React.isValidElement).length;
  17. };
  18. var SWIPE_THRESHOLD = 40; // TODO: `slide` should be `animate`.
  19. var defaultProps = {
  20. slide: true,
  21. fade: false,
  22. interval: 5000,
  23. keyboard: true,
  24. pauseOnHover: true,
  25. wrap: true,
  26. indicators: true,
  27. controls: true,
  28. activeIndex: 0,
  29. prevIcon: React.createElement("span", {
  30. "aria-hidden": "true",
  31. className: "carousel-control-prev-icon"
  32. }),
  33. prevLabel: 'Previous',
  34. nextIcon: React.createElement("span", {
  35. "aria-hidden": "true",
  36. className: "carousel-control-next-icon"
  37. }),
  38. nextLabel: 'Next',
  39. touch: true
  40. };
  41. var Carousel =
  42. /*#__PURE__*/
  43. function (_React$Component) {
  44. _inheritsLoose(Carousel, _React$Component);
  45. function Carousel() {
  46. var _this;
  47. for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
  48. args[_key] = arguments[_key];
  49. }
  50. _this = _React$Component.call.apply(_React$Component, [this].concat(args)) || this;
  51. _this.state = {
  52. prevClasses: '',
  53. currentClasses: 'active',
  54. touchStartX: 0
  55. };
  56. _this.isUnmounted = false;
  57. _this.carousel = React.createRef();
  58. _this.handleTouchStart = function (e) {
  59. _this.setState({
  60. touchStartX: e.changedTouches[0].screenX
  61. });
  62. };
  63. _this.handleTouchEnd = function (e) {
  64. // If the swipe is under the threshold, don't do anything.
  65. if (Math.abs(e.changedTouches[0].screenX - _this.state.touchStartX) < SWIPE_THRESHOLD) return;
  66. if (e.changedTouches[0].screenX < _this.state.touchStartX) {
  67. // Swiping left to navigate to next item.
  68. _this.handleNext(e);
  69. } else {
  70. // Swiping right to navigate to previous item.
  71. _this.handlePrev(e);
  72. }
  73. };
  74. _this.handleSlideEnd = function () {
  75. var pendingIndex = _this._pendingIndex;
  76. _this._isSliding = false;
  77. _this._pendingIndex = null;
  78. if (pendingIndex != null) _this.to(pendingIndex);else _this.cycle();
  79. };
  80. _this.handleMouseOut = function () {
  81. _this.cycle();
  82. };
  83. _this.handleMouseOver = function () {
  84. if (_this.props.pauseOnHover) _this.pause();
  85. };
  86. _this.handleKeyDown = function (event) {
  87. if (/input|textarea/i.test(event.target.tagName)) return;
  88. switch (event.key) {
  89. case 'ArrowLeft':
  90. event.preventDefault();
  91. _this.handlePrev(event);
  92. break;
  93. case 'ArrowRight':
  94. event.preventDefault();
  95. _this.handleNext(event);
  96. break;
  97. default:
  98. break;
  99. }
  100. };
  101. _this.handleNextWhenVisible = function () {
  102. if (!_this.isUnmounted && !document.hidden && styles(_this.carousel.current, 'visibility') !== 'hidden') {
  103. _this.handleNext();
  104. }
  105. };
  106. _this.handleNext = function (e) {
  107. if (_this._isSliding) return;
  108. var _this$props = _this.props,
  109. wrap = _this$props.wrap,
  110. activeIndex = _this$props.activeIndex;
  111. var index = activeIndex + 1;
  112. var count = countChildren(_this.props.children);
  113. if (index > count - 1) {
  114. if (!wrap) return;
  115. index = 0;
  116. }
  117. _this.select(index, e, 'next');
  118. };
  119. _this.handlePrev = function (e) {
  120. if (_this._isSliding) return;
  121. var _this$props2 = _this.props,
  122. wrap = _this$props2.wrap,
  123. activeIndex = _this$props2.activeIndex;
  124. var index = activeIndex - 1;
  125. if (index < 0) {
  126. if (!wrap) return;
  127. index = countChildren(_this.props.children) - 1;
  128. }
  129. _this.select(index, e, 'prev');
  130. };
  131. return _this;
  132. }
  133. var _proto = Carousel.prototype;
  134. _proto.componentDidMount = function componentDidMount() {
  135. this.cycle();
  136. };
  137. Carousel.getDerivedStateFromProps = function getDerivedStateFromProps(nextProps, _ref) {
  138. var previousActiveIndex = _ref.activeIndex;
  139. if (nextProps.activeIndex !== previousActiveIndex) {
  140. var lastPossibleIndex = countChildren(nextProps.children) - 1;
  141. var nextIndex = Math.max(0, Math.min(nextProps.activeIndex, lastPossibleIndex));
  142. var direction;
  143. if (nextIndex === 0 && previousActiveIndex >= lastPossibleIndex || previousActiveIndex <= nextIndex) {
  144. direction = 'next';
  145. } else {
  146. direction = 'prev';
  147. }
  148. return {
  149. direction: direction,
  150. previousActiveIndex: previousActiveIndex,
  151. activeIndex: nextIndex
  152. };
  153. }
  154. return null;
  155. };
  156. _proto.componentDidUpdate = function componentDidUpdate(_, prevState) {
  157. var _this2 = this;
  158. var _this$props3 = this.props,
  159. bsPrefix = _this$props3.bsPrefix,
  160. slide = _this$props3.slide,
  161. onSlideEnd = _this$props3.onSlideEnd;
  162. if (!slide || this.state.activeIndex === prevState.activeIndex || this._isSliding) return;
  163. var _this$state = this.state,
  164. activeIndex = _this$state.activeIndex,
  165. direction = _this$state.direction;
  166. var orderClassName, directionalClassName;
  167. if (direction === 'next') {
  168. orderClassName = bsPrefix + "-item-next";
  169. directionalClassName = bsPrefix + "-item-left";
  170. } else if (direction === 'prev') {
  171. orderClassName = bsPrefix + "-item-prev";
  172. directionalClassName = bsPrefix + "-item-right";
  173. }
  174. this._isSliding = true;
  175. this.pause(); // eslint-disable-next-line react/no-did-update-set-state
  176. this.safeSetState({
  177. prevClasses: 'active',
  178. currentClasses: orderClassName
  179. }, function () {
  180. var items = _this2.carousel.current.children;
  181. var nextElement = items[activeIndex];
  182. triggerBrowserReflow(nextElement);
  183. _this2.safeSetState({
  184. prevClasses: classNames('active', directionalClassName),
  185. currentClasses: classNames(orderClassName, directionalClassName)
  186. }, function () {
  187. return transition.end(nextElement, function () {
  188. _this2.safeSetState({
  189. prevClasses: '',
  190. currentClasses: 'active'
  191. }, _this2.handleSlideEnd);
  192. if (onSlideEnd) {
  193. onSlideEnd();
  194. }
  195. });
  196. });
  197. });
  198. };
  199. _proto.componentWillUnmount = function componentWillUnmount() {
  200. clearTimeout(this.timeout);
  201. this.isUnmounted = true;
  202. };
  203. _proto.safeSetState = function safeSetState(state, cb) {
  204. var _this3 = this;
  205. if (this.isUnmounted) return;
  206. this.setState(state, function () {
  207. return !_this3.isUnmounted && cb();
  208. });
  209. } // This might be a public API.
  210. ;
  211. _proto.pause = function pause() {
  212. this._isPaused = true;
  213. clearInterval(this._interval);
  214. this._interval = null;
  215. };
  216. _proto.cycle = function cycle() {
  217. this._isPaused = false;
  218. clearInterval(this._interval);
  219. this._interval = null;
  220. if (this.props.interval && !this._isPaused) {
  221. this._interval = setInterval(document.visibilityState ? this.handleNextWhenVisible : this.handleNext, this.props.interval);
  222. }
  223. };
  224. _proto.to = function to(index, event) {
  225. var children = this.props.children;
  226. if (index < 0 || index > countChildren(children) - 1) {
  227. return;
  228. }
  229. if (this._isSliding) {
  230. this._pendingIndex = index;
  231. return;
  232. }
  233. this.select(index, event);
  234. };
  235. _proto.select = function select(index, event, direction) {
  236. var _this4 = this;
  237. clearTimeout(this.selectThrottle);
  238. if (event && event.persist) event.persist(); // The timeout throttles fast clicks, in order to give any pending state
  239. // a chance to update and propagate back through props
  240. this.selectThrottle = setTimeout(function () {
  241. clearTimeout(_this4.timeout);
  242. var _this4$props = _this4.props,
  243. activeIndex = _this4$props.activeIndex,
  244. onSelect = _this4$props.onSelect;
  245. if (index === activeIndex || _this4._isSliding || _this4.isUnmounted) return;
  246. onSelect(index, direction || (index < activeIndex ? 'prev' : 'next'), event);
  247. }, 50);
  248. };
  249. _proto.renderControls = function renderControls(properties) {
  250. var bsPrefix = this.props.bsPrefix;
  251. var wrap = properties.wrap,
  252. children = properties.children,
  253. activeIndex = properties.activeIndex,
  254. prevIcon = properties.prevIcon,
  255. nextIcon = properties.nextIcon,
  256. prevLabel = properties.prevLabel,
  257. nextLabel = properties.nextLabel;
  258. var count = countChildren(children);
  259. return [(wrap || activeIndex !== 0) && React.createElement(SafeAnchor, {
  260. key: "prev",
  261. className: bsPrefix + "-control-prev",
  262. onClick: this.handlePrev
  263. }, prevIcon, prevLabel && React.createElement("span", {
  264. className: "sr-only"
  265. }, prevLabel)), (wrap || activeIndex !== count - 1) && React.createElement(SafeAnchor, {
  266. key: "next",
  267. className: bsPrefix + "-control-next",
  268. onClick: this.handleNext
  269. }, nextIcon, nextLabel && React.createElement("span", {
  270. className: "sr-only"
  271. }, nextLabel))];
  272. };
  273. _proto.renderIndicators = function renderIndicators(children, activeIndex) {
  274. var _this5 = this;
  275. var bsPrefix = this.props.bsPrefix;
  276. var indicators = [];
  277. forEach(children, function (child, index) {
  278. indicators.push(React.createElement("li", {
  279. key: index,
  280. className: index === activeIndex ? 'active' : null,
  281. onClick: function onClick(e) {
  282. return _this5.to(index, e);
  283. }
  284. }), // Force whitespace between indicator elements. Bootstrap requires
  285. // this for correct spacing of elements.
  286. ' ');
  287. });
  288. return React.createElement("ol", {
  289. className: bsPrefix + "-indicators"
  290. }, indicators);
  291. };
  292. _proto.render = function render() {
  293. var _this$props4 = this.props,
  294. _this$props4$as = _this$props4.as,
  295. Component = _this$props4$as === void 0 ? 'div' : _this$props4$as,
  296. bsPrefix = _this$props4.bsPrefix,
  297. slide = _this$props4.slide,
  298. fade = _this$props4.fade,
  299. indicators = _this$props4.indicators,
  300. controls = _this$props4.controls,
  301. wrap = _this$props4.wrap,
  302. touch = _this$props4.touch,
  303. prevIcon = _this$props4.prevIcon,
  304. prevLabel = _this$props4.prevLabel,
  305. nextIcon = _this$props4.nextIcon,
  306. nextLabel = _this$props4.nextLabel,
  307. className = _this$props4.className,
  308. children = _this$props4.children,
  309. keyboard = _this$props4.keyboard,
  310. _5 = _this$props4.activeIndex,
  311. _4 = _this$props4.pauseOnHover,
  312. _3 = _this$props4.interval,
  313. _2 = _this$props4.onSelect,
  314. _1 = _this$props4.onSlideEnd,
  315. props = _objectWithoutPropertiesLoose(_this$props4, ["as", "bsPrefix", "slide", "fade", "indicators", "controls", "wrap", "touch", "prevIcon", "prevLabel", "nextIcon", "nextLabel", "className", "children", "keyboard", "activeIndex", "pauseOnHover", "interval", "onSelect", "onSlideEnd"]);
  316. var _this$state2 = this.state,
  317. activeIndex = _this$state2.activeIndex,
  318. previousActiveIndex = _this$state2.previousActiveIndex,
  319. prevClasses = _this$state2.prevClasses,
  320. currentClasses = _this$state2.currentClasses;
  321. return (// eslint-disable-next-line jsx-a11y/no-static-element-interactions
  322. React.createElement(Component, _extends({
  323. onTouchStart: touch ? this.handleTouchStart : undefined,
  324. onTouchEnd: touch ? this.handleTouchEnd : undefined
  325. }, props, {
  326. className: classNames(className, bsPrefix, slide && 'slide', fade && bsPrefix + "-fade"),
  327. onKeyDown: keyboard ? this.handleKeyDown : undefined,
  328. onMouseOver: this.handleMouseOver,
  329. onMouseOut: this.handleMouseOut
  330. }), indicators && this.renderIndicators(children, activeIndex), React.createElement("div", {
  331. className: bsPrefix + "-inner",
  332. ref: this.carousel
  333. }, map(children, function (child, index) {
  334. var current = index === activeIndex;
  335. var previous = index === previousActiveIndex;
  336. return cloneElement(child, {
  337. className: classNames(child.props.className, bsPrefix + "-item", current && currentClasses, previous && prevClasses)
  338. });
  339. })), controls && this.renderControls({
  340. wrap: wrap,
  341. children: children,
  342. activeIndex: activeIndex,
  343. prevIcon: prevIcon,
  344. prevLabel: prevLabel,
  345. nextIcon: nextIcon,
  346. nextLabel: nextLabel
  347. }))
  348. );
  349. };
  350. return Carousel;
  351. }(React.Component);
  352. Carousel.defaultProps = defaultProps;
  353. var DecoratedCarousel = createBootstrapComponent(uncontrollable(Carousel, {
  354. activeIndex: 'onSelect'
  355. }), 'carousel');
  356. DecoratedCarousel.Caption = CarouselCaption;
  357. DecoratedCarousel.Item = CarouselItem;
  358. export default DecoratedCarousel;