zarm
Version:
基于 React 的移动端UI库
346 lines (284 loc) • 11.4 kB
JavaScript
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;
;