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.
 
 
 
 

393 lines
13 KiB

  1. "use strict";
  2. var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");
  3. var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
  4. exports.__esModule = true;
  5. exports.default = void 0;
  6. var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
  7. var _objectWithoutPropertiesLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutPropertiesLoose"));
  8. var _useEventCallback = _interopRequireDefault(require("@restart/hooks/useEventCallback"));
  9. var _useUpdateEffect = _interopRequireDefault(require("@restart/hooks/useUpdateEffect"));
  10. var _useTimeout = _interopRequireDefault(require("@restart/hooks/useTimeout"));
  11. var _classnames = _interopRequireDefault(require("classnames"));
  12. var _transitionEnd = _interopRequireDefault(require("dom-helpers/transitionEnd"));
  13. var _Transition = _interopRequireDefault(require("react-transition-group/Transition"));
  14. var _react = _interopRequireWildcard(require("react"));
  15. var _uncontrollable = require("uncontrollable");
  16. var _CarouselCaption = _interopRequireDefault(require("./CarouselCaption"));
  17. var _CarouselItem = _interopRequireDefault(require("./CarouselItem"));
  18. var _ElementChildren = require("./ElementChildren");
  19. var _SafeAnchor = _interopRequireDefault(require("./SafeAnchor"));
  20. var _ThemeProvider = require("./ThemeProvider");
  21. var _triggerBrowserReflow = _interopRequireDefault(require("./triggerBrowserReflow"));
  22. var SWIPE_THRESHOLD = 40;
  23. var defaultProps = {
  24. slide: true,
  25. fade: false,
  26. controls: true,
  27. indicators: true,
  28. defaultActiveIndex: 0,
  29. interval: 5000,
  30. keyboard: true,
  31. pause: 'hover',
  32. wrap: true,
  33. touch: true,
  34. prevIcon: /*#__PURE__*/_react.default.createElement("span", {
  35. "aria-hidden": "true",
  36. className: "carousel-control-prev-icon"
  37. }),
  38. prevLabel: 'Previous',
  39. nextIcon: /*#__PURE__*/_react.default.createElement("span", {
  40. "aria-hidden": "true",
  41. className: "carousel-control-next-icon"
  42. }),
  43. nextLabel: 'Next'
  44. };
  45. function isVisible(element) {
  46. if (!element || !element.style || !element.parentNode || !element.parentNode.style) {
  47. return false;
  48. }
  49. var elementStyle = getComputedStyle(element);
  50. return elementStyle.display !== 'none' && elementStyle.visibility !== 'hidden' && getComputedStyle(element.parentNode).display !== 'none';
  51. }
  52. var Carousel = _react.default.forwardRef(function (uncontrolledProps, ref) {
  53. var _useUncontrolled = (0, _uncontrollable.useUncontrolled)(uncontrolledProps, {
  54. activeIndex: 'onSelect'
  55. }),
  56. _useUncontrolled$as = _useUncontrolled.as,
  57. Component = _useUncontrolled$as === void 0 ? 'div' : _useUncontrolled$as,
  58. bsPrefix = _useUncontrolled.bsPrefix,
  59. slide = _useUncontrolled.slide,
  60. fade = _useUncontrolled.fade,
  61. controls = _useUncontrolled.controls,
  62. indicators = _useUncontrolled.indicators,
  63. activeIndex = _useUncontrolled.activeIndex,
  64. onSelect = _useUncontrolled.onSelect,
  65. onSlide = _useUncontrolled.onSlide,
  66. onSlid = _useUncontrolled.onSlid,
  67. interval = _useUncontrolled.interval,
  68. keyboard = _useUncontrolled.keyboard,
  69. onKeyDown = _useUncontrolled.onKeyDown,
  70. pause = _useUncontrolled.pause,
  71. onMouseOver = _useUncontrolled.onMouseOver,
  72. onMouseOut = _useUncontrolled.onMouseOut,
  73. wrap = _useUncontrolled.wrap,
  74. touch = _useUncontrolled.touch,
  75. onTouchStart = _useUncontrolled.onTouchStart,
  76. onTouchMove = _useUncontrolled.onTouchMove,
  77. onTouchEnd = _useUncontrolled.onTouchEnd,
  78. prevIcon = _useUncontrolled.prevIcon,
  79. prevLabel = _useUncontrolled.prevLabel,
  80. nextIcon = _useUncontrolled.nextIcon,
  81. nextLabel = _useUncontrolled.nextLabel,
  82. className = _useUncontrolled.className,
  83. children = _useUncontrolled.children,
  84. props = (0, _objectWithoutPropertiesLoose2.default)(_useUncontrolled, ["as", "bsPrefix", "slide", "fade", "controls", "indicators", "activeIndex", "onSelect", "onSlide", "onSlid", "interval", "keyboard", "onKeyDown", "pause", "onMouseOver", "onMouseOut", "wrap", "touch", "onTouchStart", "onTouchMove", "onTouchEnd", "prevIcon", "prevLabel", "nextIcon", "nextLabel", "className", "children"]);
  85. var prefix = (0, _ThemeProvider.useBootstrapPrefix)(bsPrefix, 'carousel');
  86. var nextDirectionRef = (0, _react.useRef)(null);
  87. var _useState = (0, _react.useState)('next'),
  88. direction = _useState[0],
  89. setDirection = _useState[1];
  90. var _useState2 = (0, _react.useState)(false),
  91. isSliding = _useState2[0],
  92. setIsSliding = _useState2[1];
  93. var _useState3 = (0, _react.useState)(activeIndex),
  94. renderedActiveIndex = _useState3[0],
  95. setRenderedActiveIndex = _useState3[1];
  96. if (!isSliding && activeIndex !== renderedActiveIndex) {
  97. if (nextDirectionRef.current) {
  98. setDirection(nextDirectionRef.current);
  99. nextDirectionRef.current = null;
  100. } else {
  101. setDirection(activeIndex > renderedActiveIndex ? 'next' : 'prev');
  102. }
  103. if (slide) {
  104. setIsSliding(true);
  105. }
  106. setRenderedActiveIndex(activeIndex);
  107. }
  108. var numChildren = _react.default.Children.toArray(children).filter(_react.default.isValidElement).length;
  109. var prev = (0, _react.useCallback)(function (event) {
  110. if (isSliding) {
  111. return;
  112. }
  113. var nextActiveIndex = renderedActiveIndex - 1;
  114. if (nextActiveIndex < 0) {
  115. if (!wrap) {
  116. return;
  117. }
  118. nextActiveIndex = numChildren - 1;
  119. }
  120. nextDirectionRef.current = 'prev';
  121. onSelect(nextActiveIndex, event);
  122. }, [isSliding, renderedActiveIndex, onSelect, wrap, numChildren]); // This is used in the setInterval, so it should not invalidate.
  123. var next = (0, _useEventCallback.default)(function (event) {
  124. if (isSliding) {
  125. return;
  126. }
  127. var nextActiveIndex = renderedActiveIndex + 1;
  128. if (nextActiveIndex >= numChildren) {
  129. if (!wrap) {
  130. return;
  131. }
  132. nextActiveIndex = 0;
  133. }
  134. nextDirectionRef.current = 'next';
  135. onSelect(nextActiveIndex, event);
  136. });
  137. var elementRef = (0, _react.useRef)();
  138. (0, _react.useImperativeHandle)(ref, function () {
  139. return {
  140. element: elementRef.current,
  141. prev: prev,
  142. next: next
  143. };
  144. }); // This is used in the setInterval, so it should not invalidate.
  145. var nextWhenVisible = (0, _useEventCallback.default)(function () {
  146. if (!document.hidden && isVisible(elementRef.current)) {
  147. next();
  148. }
  149. });
  150. var slideDirection = direction === 'next' ? 'left' : 'right';
  151. (0, _useUpdateEffect.default)(function () {
  152. if (slide) {
  153. // These callbacks will be handled by the <Transition> callbacks.
  154. return;
  155. }
  156. if (onSlide) {
  157. onSlide(renderedActiveIndex, slideDirection);
  158. }
  159. if (onSlid) {
  160. onSlid(renderedActiveIndex, slideDirection);
  161. }
  162. }, [renderedActiveIndex]);
  163. var orderClassName = prefix + "-item-" + direction;
  164. var directionalClassName = prefix + "-item-" + slideDirection;
  165. var handleEnter = (0, _react.useCallback)(function (node) {
  166. (0, _triggerBrowserReflow.default)(node);
  167. if (onSlide) {
  168. onSlide(renderedActiveIndex, slideDirection);
  169. }
  170. }, [onSlide, renderedActiveIndex, slideDirection]);
  171. var handleEntered = (0, _react.useCallback)(function () {
  172. setIsSliding(false);
  173. if (onSlid) {
  174. onSlid(renderedActiveIndex, slideDirection);
  175. }
  176. }, [onSlid, renderedActiveIndex, slideDirection]);
  177. var handleKeyDown = (0, _react.useCallback)(function (event) {
  178. if (keyboard && !/input|textarea/i.test(event.target.tagName)) {
  179. switch (event.key) {
  180. case 'ArrowLeft':
  181. event.preventDefault();
  182. prev(event);
  183. return;
  184. case 'ArrowRight':
  185. event.preventDefault();
  186. next(event);
  187. return;
  188. default:
  189. }
  190. }
  191. if (onKeyDown) {
  192. onKeyDown(event);
  193. }
  194. }, [keyboard, onKeyDown, prev, next]);
  195. var _useState4 = (0, _react.useState)(false),
  196. pausedOnHover = _useState4[0],
  197. setPausedOnHover = _useState4[1];
  198. var handleMouseOver = (0, _react.useCallback)(function (event) {
  199. if (pause === 'hover') {
  200. setPausedOnHover(true);
  201. }
  202. if (onMouseOver) {
  203. onMouseOver(event);
  204. }
  205. }, [pause, onMouseOver]);
  206. var handleMouseOut = (0, _react.useCallback)(function (event) {
  207. setPausedOnHover(false);
  208. if (onMouseOut) {
  209. onMouseOut(event);
  210. }
  211. }, [onMouseOut]);
  212. var touchStartXRef = (0, _react.useRef)(0);
  213. var touchDeltaXRef = (0, _react.useRef)(0);
  214. var _useState5 = (0, _react.useState)(false),
  215. pausedOnTouch = _useState5[0],
  216. setPausedOnTouch = _useState5[1];
  217. var touchUnpauseTimeout = (0, _useTimeout.default)();
  218. var handleTouchStart = (0, _react.useCallback)(function (event) {
  219. touchStartXRef.current = event.touches[0].clientX;
  220. touchDeltaXRef.current = 0;
  221. if (touch) {
  222. setPausedOnTouch(true);
  223. }
  224. if (onTouchStart) {
  225. onTouchStart(event);
  226. }
  227. }, [touch, onTouchStart]);
  228. var handleTouchMove = (0, _react.useCallback)(function (event) {
  229. if (event.touches && event.touches.length > 1) {
  230. touchDeltaXRef.current = 0;
  231. } else {
  232. touchDeltaXRef.current = event.touches[0].clientX - touchStartXRef.current;
  233. }
  234. if (onTouchMove) {
  235. onTouchMove(event);
  236. }
  237. }, [onTouchMove]);
  238. var handleTouchEnd = (0, _react.useCallback)(function (event) {
  239. if (touch) {
  240. var touchDeltaX = touchDeltaXRef.current;
  241. if (Math.abs(touchDeltaX) <= SWIPE_THRESHOLD) {
  242. return;
  243. }
  244. if (touchDeltaX > 0) {
  245. prev(event);
  246. } else {
  247. next(event);
  248. }
  249. }
  250. touchUnpauseTimeout.set(function () {
  251. setPausedOnTouch(false);
  252. }, interval);
  253. if (onTouchEnd) {
  254. onTouchEnd(event);
  255. }
  256. }, [touch, prev, next, touchUnpauseTimeout, interval, onTouchEnd]);
  257. var shouldPlay = interval != null && !pausedOnHover && !pausedOnTouch && !isSliding;
  258. var intervalHandleRef = (0, _react.useRef)();
  259. (0, _react.useEffect)(function () {
  260. if (!shouldPlay) {
  261. return undefined;
  262. }
  263. intervalHandleRef.current = setInterval(document.visibilityState ? nextWhenVisible : next, interval);
  264. return function () {
  265. clearInterval(intervalHandleRef.current);
  266. };
  267. }, [shouldPlay, next, interval, nextWhenVisible]);
  268. var indicatorOnClicks = (0, _react.useMemo)(function () {
  269. return indicators && Array.from({
  270. length: numChildren
  271. }, function (_, index) {
  272. return function (event) {
  273. onSelect(index, event);
  274. };
  275. });
  276. }, [indicators, numChildren, onSelect]);
  277. return /*#__PURE__*/_react.default.createElement(Component, (0, _extends2.default)({
  278. ref: elementRef
  279. }, props, {
  280. onKeyDown: handleKeyDown,
  281. onMouseOver: handleMouseOver,
  282. onMouseOut: handleMouseOut,
  283. onTouchStart: handleTouchStart,
  284. onTouchMove: handleTouchMove,
  285. onTouchEnd: handleTouchEnd,
  286. className: (0, _classnames.default)(className, prefix, slide && 'slide', fade && prefix + "-fade")
  287. }), indicators && /*#__PURE__*/_react.default.createElement("ol", {
  288. className: prefix + "-indicators"
  289. }, (0, _ElementChildren.map)(children, function (child, index) {
  290. return /*#__PURE__*/_react.default.createElement("li", {
  291. key: index,
  292. className: index === renderedActiveIndex ? 'active' : null,
  293. onClick: indicatorOnClicks[index]
  294. });
  295. })), /*#__PURE__*/_react.default.createElement("div", {
  296. className: prefix + "-inner"
  297. }, (0, _ElementChildren.map)(children, function (child, index) {
  298. var isActive = index === renderedActiveIndex;
  299. return slide ? /*#__PURE__*/_react.default.createElement(_Transition.default, {
  300. in: isActive,
  301. onEnter: isActive ? handleEnter : null,
  302. onEntered: isActive ? handleEntered : null,
  303. addEndListener: _transitionEnd.default
  304. }, function (status) {
  305. return _react.default.cloneElement(child, {
  306. className: (0, _classnames.default)(child.props.className, isActive && status !== 'entered' && orderClassName, (status === 'entered' || status === 'exiting') && 'active', (status === 'entering' || status === 'exiting') && directionalClassName)
  307. });
  308. }) : _react.default.cloneElement(child, {
  309. className: (0, _classnames.default)(child.props.className, isActive && 'active')
  310. });
  311. })), controls && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, (wrap || activeIndex !== 0) && /*#__PURE__*/_react.default.createElement(_SafeAnchor.default, {
  312. className: prefix + "-control-prev",
  313. onClick: prev
  314. }, prevIcon, prevLabel && /*#__PURE__*/_react.default.createElement("span", {
  315. className: "sr-only"
  316. }, prevLabel)), (wrap || activeIndex !== numChildren - 1) && /*#__PURE__*/_react.default.createElement(_SafeAnchor.default, {
  317. className: prefix + "-control-next",
  318. onClick: next
  319. }, nextIcon, nextLabel && /*#__PURE__*/_react.default.createElement("span", {
  320. className: "sr-only"
  321. }, nextLabel))));
  322. });
  323. Carousel.displayName = 'Carousel';
  324. Carousel.defaultProps = defaultProps;
  325. Carousel.Caption = _CarouselCaption.default;
  326. Carousel.Item = _CarouselItem.default;
  327. var _default = Carousel;
  328. exports.default = _default;
  329. module.exports = exports["default"];