UNPKG

zarm

Version:

基于 React 的移动端UI库

346 lines (284 loc) 11.4 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _typeof = require("@babel/runtime/helpers/typeof"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray")); var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); var _react = _interopRequireWildcard(require("react")); var _bem = require("@zarm-design/bem"); var _react2 = require("@use-gesture/react"); var _events = _interopRequireDefault(require("../utils/events")); var _configProvider = require("../config-provider"); var _dom = require("../utils/dom"); function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) { if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } } return n.default = e, t && t.set(e, n), n; } var Carousel = /*#__PURE__*/(0, _react.forwardRef)(function (props, ref) { var _React$useContext = _react.default.useContext(_configProvider.ConfigContext), prefixCls = _React$useContext.prefixCls; var bem = (0, _bem.createBEM)('carousel', { prefixCls: prefixCls }); var className = props.className, height = props.height, style = props.style, children = props.children, direction = props.direction, loop = props.loop, onChangeEnd = props.onChangeEnd, onChange = props.onChange, autoPlay = props.autoPlay, autoPlayIntervalTime = props.autoPlayIntervalTime, swipeable = props.swipeable, animationDuration = props.animationDuration, propActiveIndex = props.activeIndex, showPagination = props.showPagination, moveDistanceRatio = props.moveDistanceRatio, moveTimeSpan = props.moveTimeSpan; var stateRef = (0, _react.useRef)({ activeIndex: propActiveIndex, activeIndexChanged: false }); var _useState = (0, _react.useState)(stateRef.current.activeIndex), _useState2 = (0, _slicedToArray2.default)(_useState, 2), activeIndexState = _useState2[0], setActiveIndexState = _useState2[1]; var updateRef = (0, _react.useRef)(function (state) { stateRef.current = state; setActiveIndexState(state.activeIndex); }); var isVertical = direction === 'vertical'; var carouselRef = ref || /*#__PURE__*/_react.default.createRef(); var carouselItemsRef = (0, _react.useRef)(null); var translateXRef = (0, _react.useRef)(0); var translateYRef = (0, _react.useRef)(0); var count = (0, _react.useMemo)(function () { return _react.Children.count(children); }, [children]); // 处理节点(首尾拼接) var carouselItems = (0, _react.useMemo)(function () { if (children == null || children.length === 0) { return; } // 增加头尾拼接节点 var itemList = (0, _toConsumableArray2.default)(children); var firstItem = itemList[0]; var lastItem = itemList[itemList.length - 1]; if (loop) { itemList.push(firstItem); itemList.unshift(lastItem); } // 节点追加后重排key var newItems = _react.default.Children.map(itemList, function (element, index) { return /*#__PURE__*/(0, _react.cloneElement)(element, { key: index, className: bem('item', [element.props.className]) }); }); return newItems; }, [children]); // 执行过渡动画 var doTransition = (0, _react.useCallback)(function (offset, animationDurationNum) { var dom = carouselItemsRef.current; var x = 0; var y = 0; if (!isVertical) { x = offset.x; } else { y = offset.y; } dom.style.transitionDuration = "".concat(animationDurationNum, "ms"); dom.style.transform = "translate3d(".concat(x, "px, ").concat(y, "px, 0)"); }, [isVertical]); var onMoving = (0, _react.useRef)(false); var transitionEnd = (0, _react.useCallback)(function () { onMoving.current = false; var _stateRef$current = stateRef.current, activeIndex = _stateRef$current.activeIndex, activeIndexChanged = _stateRef$current.activeIndexChanged; var dom = carouselItemsRef.current; var index = loop ? activeIndex + 1 : activeIndex; var size = (0, _dom.getBoundingClientRect)(dom); translateXRef.current = -size.width * index; translateYRef.current = -size.height * index; doTransition({ x: translateXRef.current, y: translateYRef.current }, 0); if (activeIndexChanged) { onChangeEnd === null || onChangeEnd === void 0 ? void 0 : onChangeEnd(activeIndex); } }, [loop, doTransition, onChangeEnd]); // 移动到指定编号 var onMoveTo = (0, _react.useCallback)(function (index, animationDurationNum) { var dom = carouselItemsRef.current; var previousIndex = stateRef.current.activeIndex; var activeIndexChanged = previousIndex !== index; var num = loop ? 1 : 0; var size = (0, _dom.getBoundingClientRect)(dom); translateXRef.current = -size.width * (index + num); translateYRef.current = -size.height * (index + num); doTransition({ x: translateXRef.current, y: translateYRef.current }, animationDurationNum); if (index > count - 1) { index = 0; } else if (index < 0) { index = count - 1; } updateRef.current({ activeIndex: index, activeIndexChanged: activeIndexChanged }); if (activeIndexChanged) { onChange === null || onChange === void 0 ? void 0 : onChange(index); } }, [children, doTransition, loop, onChange]); // 滑动到指定编号 var _onSlideTo = (0, _react.useCallback)(function (index) { onMoveTo(index, animationDuration); }, [onMoveTo, animationDuration]); // 静默跳到指定编号 var _onJumpTo = (0, _react.useCallback)(function (index) { onMoveTo(index, 0); }, [onMoveTo]); // 更新窗口变化的位置偏移 var resize = (0, _react.useCallback)(function () { _onJumpTo(stateRef.current.activeIndex); }, [_onJumpTo]); var intervalRef = (0, _react.useRef)(); var bind = (0, _react2.useDrag)(function (state) { var activeIndex = stateRef.current.activeIndex; if (onMoving.current) { if (activeIndex <= 0) { _onJumpTo(0); } else if (activeIndex >= count - 1) { _onJumpTo(count - 1); } onMoving.current = false; } if (!state.intentional) { return false; } ; intervalRef.current && window.clearInterval(intervalRef.current); var offset = state.offset, elapsedTime = state.elapsedTime; var _offset = (0, _slicedToArray2.default)(offset, 2), offsetX = _offset[0], offsetY = _offset[1]; var index = isVertical ? 1 : 0; if (!offset[index]) { return false; } var action = !isVertical && offsetX > 0 || isVertical && offsetY > 0 ? 'prev' : 'next'; if (!loop && (action === 'prev' && activeIndex <= 0 || action === 'next' && activeIndex >= count - 1)) { return false; } if (state.last) { var dom = carouselItemsRef.current; var size = (0, _dom.getBoundingClientRect)(dom); var ratio = !isVertical ? Math.abs(offsetX / size.width) : Math.abs(offsetY / size.height); // 判断滑动临界点 // 1.滑动距离超过0,且滑动距离和父容器长度之比超过moveDistanceRatio // 2.滑动释放时间差低于moveTimeSpan if (ratio >= moveDistanceRatio || elapsedTime <= moveTimeSpan) { activeIndex = action === 'next' ? activeIndex + 1 : activeIndex - 1; } if (loop && (activeIndex >= count - 1 || activeIndex <= 1)) { onMoving.current = true; } _onSlideTo(activeIndex); return false; } doTransition({ x: translateXRef.current + offset[0], y: translateYRef.current + offset[1] }, 0); }, { from: function from() { return [0, 0]; }, enabled: swipeable, axis: isVertical ? 'y' : 'x', pointer: { touch: true }, preventScroll: !isVertical, triggerAllEvents: true }); (0, _react.useEffect)(function () { if (!autoPlay || count <= 1) return; intervalRef.current = window.setInterval(function () { !onMoving.current && _onSlideTo(stateRef.current.activeIndex + 1); }, autoPlayIntervalTime); return function () { window.clearInterval(intervalRef.current); }; }, [autoPlay, autoPlayIntervalTime, loop, _onSlideTo, stateRef.current.activeIndex]); (0, _react.useEffect)(function () { // 监听窗口变化 _events.default.on(window, 'resize', resize); // 设置起始位置编号 _onJumpTo(propActiveIndex); return function () { // 移除监听窗口变化 _events.default.off(window, 'resize', resize); }; }, [_onJumpTo, _onSlideTo, propActiveIndex, resize, transitionEnd]); (0, _react.useImperativeHandle)(carouselRef, function () { return { onJumpTo: function onJumpTo(index) { _onJumpTo(index); }, onSlideTo: function onSlideTo(index) { _onSlideTo(index); } }; }); var pagination = (0, _react.useMemo)(function () { if (!showPagination) return null; var paginationItems = _react.Children.map(children, function (_child, index) { return /*#__PURE__*/_react.default.createElement("div", { key: "pagination-".concat(+index), className: bem('pagination__item', [{ active: index === activeIndexState }]), onClick: function onClick() { return _onSlideTo(index); } }); }); return /*#__PURE__*/_react.default.createElement("div", { className: bem('pagination') }, paginationItems); }, [showPagination, children, activeIndexState]); var cls = bem([{ horizontal: !isVertical, vertical: isVertical }, className]); var itemsStyle = {}; if (isVertical) { itemsStyle.height = height; } return /*#__PURE__*/_react.default.createElement("div", (0, _extends2.default)({ className: cls, style: style, ref: carouselRef }, bind()), /*#__PURE__*/_react.default.createElement("div", { ref: carouselItemsRef, className: bem('items'), onTransitionEnd: transitionEnd, style: itemsStyle }, carouselItems), pagination); }); Carousel.displayName = 'Carousel'; Carousel.defaultProps = { direction: 'horizontal', height: 160, loop: false, activeIndex: 0, animationDuration: 500, swipeable: true, autoPlay: false, autoPlayIntervalTime: 3000, moveDistanceRatio: 0.5, moveTimeSpan: 300, showPagination: true }; var _default = Carousel; exports.default = _default;