UNPKG

@nutui/nutui-react

Version:

京东风格的轻量级移动端 React 组件库,支持一套代码生成 H5 和小程序

271 lines (270 loc) 11.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "Swiper", { enumerable: true, get: function() { return Swiper; } }); var _interop_require_default = require("@swc/helpers/_/_interop_require_default"); var _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard"); var _define_property = require("@swc/helpers/_/_define_property"); var _object_spread = require("@swc/helpers/_/_object_spread"); var _sliced_to_array = require("@swc/helpers/_/_sliced_to_array"); var _react = /*#__PURE__*/ _interop_require_wildcard._(require("react")); var _react1 = require("@use-gesture/react"); var _web = require("@react-spring/web"); var _classnames = /*#__PURE__*/ _interop_require_default._(require("classnames")); var _indicator = /*#__PURE__*/ _interop_require_default._(require("../indicator")); var _userefstate = require("../../hooks/use-ref-state"); var _default = require("./effects/default"); var _focus = require("./effects/focus"); var defaultProps = { direction: 'horizontal', indicator: false, loop: false, duration: 3000, autoPlay: false, defaultValue: 0, touchable: true, effect: undefined }; var Swiper = /*#__PURE__*/ _react.default.forwardRef(function(props, ref) { var boundIndex = function boundIndex(current) { var min = 0; var max = count - 1; if (current === max && !loop && props.slideSize) { var slideSize = props.slideSize; var swiperSize = getSwiperSize(); var ratio = (swiperSize - slideSize) / slideSize; return bound(current, min, max - ratio); } return current; }; var classPrefix = 'nut-swiper'; var _$_object_spread = (0, _object_spread._)({}, defaultProps, props), children = _$_object_spread.children, direction = _$_object_spread.direction, indicator = _$_object_spread.indicator, loop = _$_object_spread.loop, effect = _$_object_spread.effect, autoPlay = _$_object_spread.autoPlay, touchable = _$_object_spread.touchable, defaultValue = _$_object_spread.defaultValue, duration = _$_object_spread.duration, style = _$_object_spread.style, className = _$_object_spread.className; var isVertical = direction === 'vertical'; var count = (0, _react.useMemo)(function() { var c = 0; _react.default.Children.map(children, function(child, index) { c += 1; }); return c; }, [ children ]); var getSlideSize = function getSlideSize() { if (props.slideSize) return props.slideSize; if (stageRef.current) { if (isVertical) return stageRef.current.offsetHeight; return stageRef.current.offsetWidth; } return 0; }; var getSwiperSize = function getSwiperSize() { if (swiperRef.current) { if (isVertical) return swiperRef.current.offsetHeight; return swiperRef.current.offsetWidth; } return 0; }; var bound = function bound(v, min, max) { if (min !== undefined) { v = Math.max(v, min); } if (max !== undefined) { v = Math.min(v, max); } return v; }; var timeoutRef = (0, _react.useRef)(null); var _useState = (0, _sliced_to_array._)((0, _react.useState)(false), 2), dragging = _useState[0], setDragging = _useState[1]; var _useRefState = (0, _sliced_to_array._)((0, _userefstate.useRefState)(defaultValue), 2), current = _useRefState[0], setCurrent = _useRefState[1]; var stageRef = (0, _react.useRef)(null); var swiperRef = (0, _react.useRef)(null); var _useSpring = (0, _sliced_to_array._)((0, _web.useSpring)(function() { return { x: !isVertical ? current.current * 100 * -1 : 0, y: isVertical ? current.current * 100 * -1 : 0, s: 0, reset: function reset() {}, config: { tension: 200, friction: 30 } }; }), 2), springs = _useSpring[0], api = _useSpring[1]; (0, _react.useEffect)(function() { var _obj; api.start((_obj = {}, (0, _define_property._)(_obj, isVertical ? 'y' : 'x', boundIndex(current.current) * -1 * 100), (0, _define_property._)(_obj, "immediate", true), _obj)); }, [ swiperRef.current ]); var swiperDirection = (0, _react.useRef)(1); var _useList = (0, _sliced_to_array._)((0, _focus.useList)(effect, count, current), 2), transforms = _useList[0], setTransforms = _useList[1]; // 自动播放 var runTimeSwiper = function runTimeSwiper1() { var durationNumber = typeof duration === 'string' ? parseInt(duration) : duration; var d = typeof autoPlay === 'number' ? autoPlay : durationNumber; timeoutRef.current = window.setTimeout(function() { next(); runTimeSwiper(); }, d); }; (0, _react.useEffect)(function() { if (!autoPlay || dragging) return; runTimeSwiper(); return function() { if (timeoutRef.current) window.clearTimeout(timeoutRef.current); }; }, [ autoPlay, duration, dragging, count ]); var to = function to(index) { var immediate = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : false; var _props_onChange; var targetIndex = bound(index, 0, count - 1); if (loop) { var cycleIndex = index % count; targetIndex = cycleIndex < 0 ? cycleIndex + count : cycleIndex; } setCurrent(targetIndex); (_props_onChange = props.onChange) === null || _props_onChange === void 0 ? void 0 : _props_onChange.call(props, targetIndex); if (effect) { (0, _focus.updateTransform)(transforms, setTransforms, effect, targetIndex); } var _obj; api.start((_obj = {}, (0, _define_property._)(_obj, isVertical ? 'y' : 'x', (loop ? -index : boundIndex(targetIndex) * -1) * 100), (0, _define_property._)(_obj, "s", 0), (0, _define_property._)(_obj, "immediate", immediate), _obj)); }; var getSpringsAxis = function getSpringsAxis() { return springs[isVertical ? 'y' : 'x']; }; var next = function next() { to(Math.round(-getSpringsAxis().get() / 100) + 1); }; var prev = function prev() { to(Math.round(-getSpringsAxis().get() / 100) - 1); }; _react.default.useImperativeHandle(ref, function() { return { to: to, next: next, prev: prev }; }); var bind = (0, _react1.useDrag)(function(state) { var axis = Number(isVertical); var slideSize = getSlideSize(); var offset = state.offset[axis]; setDragging(!!state.dragging); var distance = state.distance[axis]; swiperDirection.current = state.direction[axis]; if (state.last) { // 计算位置 var swipeDirection = state.direction[axis]; var velocity = state.velocity[axis]; var minIndex = Math.floor(offset / slideSize); var maxIndex = minIndex + 1; var index = Math.round((offset + velocity * 2000 * swipeDirection) / slideSize); to(bound(index, minIndex, maxIndex)); } else { var _obj; // 实时移动,换算百分比 api.start((_obj = {}, (0, _define_property._)(_obj, isVertical ? 'y' : 'x', -(offset / slideSize * 100)), (0, _define_property._)(_obj, "s", distance / slideSize), (0, _define_property._)(_obj, "immediate", true), _obj)); } }, { enabled: touchable, transform: function transform(param) { var _param = (0, _sliced_to_array._)(param, 2), x = _param[0], y = _param[1]; return [ -x, -y ]; }, from: function from() { // 由百分比转换到像素 var slideSize = getSlideSize(); var x = springs.x.get() / 100 * slideSize; var y = springs.y.get() / 100 * slideSize; return [ -x, -y ]; }, bounds: function bounds() { if (loop) return {}; var slideSize = getSlideSize(); if (isVertical) { return { top: 0, bottom: (count - 1) * slideSize }; } return { left: 0, right: (count - 1) * slideSize }; }, rubberband: true, triggerAllEvents: true, preventScroll: isVertical, axis: isVertical ? 'y' : 'x', pointer: { touch: true } }); var renderIndicator = function renderIndicator() { if (/*#__PURE__*/ _react.default.isValidElement(indicator)) return indicator; if (!indicator) return null; var _obj; return /*#__PURE__*/ _react.default.createElement("div", { className: (0, _classnames.default)((_obj = {}, (0, _define_property._)(_obj, "".concat(classPrefix, "-indicator"), true), (0, _define_property._)(_obj, "".concat(classPrefix, "-indicator-vertical"), isVertical), (0, _define_property._)(_obj, "".concat(classPrefix, "-indicator-horizontal"), !isVertical), _obj)) }, /*#__PURE__*/ _react.default.createElement(_indicator.default, { current: (0, _userefstate.getRefValue)(current), total: count, direction: direction })); }; var renderEffect = function renderEffect() { if (!effect) return (0, _default.defaultEffect)({ children: children, getSpringsAxis: getSpringsAxis, loop: loop, count: count, isVertical: isVertical }); if (effect && effect.name === 'focus') { return (0, _focus.focusEffect)({ children: children, springs: springs, loop: loop, count: count, isVertical: isVertical, effect: effect, current: current, swiperDirection: swiperDirection, dragging: dragging, transforms: transforms }); } }; var renderSlides = function renderSlides() { var _obj; return /*#__PURE__*/ _react.default.createElement("div", { ref: stageRef, className: (0, _classnames.default)("".concat(classPrefix, "-inner"), (_obj = {}, (0, _define_property._)(_obj, "".concat(classPrefix, "-inner-vertical"), isVertical), (0, _define_property._)(_obj, "".concat(classPrefix, "-inner-horizontal"), !isVertical), _obj)), style: (0, _object_spread._)({}, props.slideSize ? (0, _define_property._)({}, isVertical ? 'height' : 'width', "".concat(props.slideSize, "px")) : {}) }, renderEffect()); }; return /*#__PURE__*/ _react.default.createElement("div", (0, _object_spread._)({ className: (0, _classnames.default)(classPrefix, "".concat(classPrefix, "-canmove-").concat(direction), className), style: style, ref: swiperRef }, bind()), renderSlides(), renderIndicator()); }); Swiper.displayName = 'NutSwiper';