@nutui/nutui-react-taro
Version:
京东风格的轻量级移动端 React 组件库,支持一套代码生成 H5 和小程序
251 lines (250 loc) • 12.7 kB
JavaScript
import { _ as _async_to_generator } from "@swc/helpers/_/_async_to_generator";
import { _ as _define_property } from "@swc/helpers/_/_define_property";
import { _ as _sliced_to_array } from "@swc/helpers/_/_sliced_to_array";
import { _ as _ts_generator } from "@swc/helpers/_/_ts_generator";
import React, { useState, useEffect, useRef, useImperativeHandle } from "react";
import classNames from "classnames";
import { View } from "@tarojs/components";
import { useTouch } from "../../hooks/use-touch";
import { passiveSupported } from "../../utils/supports-passive";
import { web } from "../../utils/taro/platform";
import { preventDefault } from "../../utils";
import { momentum, useStyles } from "./utils";
import { useUuid } from "../../hooks/use-uuid";
import { getRectInMultiPlatform } from "../../utils/taro/get-rect";
var InternalPickerRoller = function(props, ref) {
var _props_keyIndex = props.keyIndex, keyIndex = _props_keyIndex === void 0 ? 0 : _props_keyIndex, _props_options = props.options, options = _props_options === void 0 ? [] : _props_options, _props_threeDimensional = props.threeDimensional, threeDimensional = _props_threeDimensional === void 0 ? true : _props_threeDimensional, _props_duration = props.duration, duration = _props_duration === void 0 ? 1000 : _props_duration, onSelect = props.onSelect, _props_renderLabel = props.renderLabel, renderLabel = _props_renderLabel === void 0 ? function(item) {
return item.label;
} : _props_renderLabel;
var classPrefix = 'nut-pickerview-roller';
var uuid = useUuid();
var DEFAULT_DURATION = 200;
var INERTIA_TIME = 300;
var INERTIA_DISTANCE = 15;
var ROTATION = 20;
var touch = useTouch();
var _useState = _sliced_to_array(useState(0), 2), currentIndex = _useState[0], setCurrentIndex = _useState[1];
var lineSpacing = useRef(36);
var _useState1 = _sliced_to_array(useState(0), 2), touchTime = _useState1[0], setTouchTime = _useState1[1];
var _useState2 = _sliced_to_array(useState('0deg'), 2), touchDeg = _useState2[0], setTouchDeg = _useState2[1];
var isMoving = useRef(false);
var rollerRef = useRef(null);
var pickerRollerRef = useRef(null);
var placeholderRef = useRef(null);
var _useState3 = _sliced_to_array(useState(0), 2), startTime = _useState3[0], setStartTime = _useState3[1];
var _useState4 = _sliced_to_array(useState(0), 2), startY = _useState4[0], setStartY = _useState4[1];
var transformY = useRef(0);
var _useState5 = _sliced_to_array(useState(0), 2), scrollDistance = _useState5[0], setScrollDistance = _useState5[1];
var _useState6 = _sliced_to_array(useState(web()), 2), isGetLineSpacing = _useState6[0], setGetStatus = _useState6[1];
var _useStyles = useStyles(touchTime, touchDeg, scrollDistance, lineSpacing, ROTATION), touchRollerStyle = _useStyles.touchRollerStyle, touchTiledStyle = _useStyles.touchTiledStyle, rollerStyle = _useStyles.rollerStyle;
var isItemHidden = function(index) {
return index >= currentIndex + 8 || index <= currentIndex - 8;
};
var applyTransform = function(type, deg) {
var time = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : DEFAULT_DURATION, translateY = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : 0;
setTouchTime(type !== 'end' ? 0 : time);
setTouchDeg(deg);
setScrollDistance(translateY);
};
var handleMove = function(move, type, time) {
var updatedMove = move + transformY.current;
if (type === 'end') {
updatedMove = Math.max(Math.min(updatedMove, 0), -(options.length - 1) * lineSpacing.current);
// 滚动距离为lineSpacing.current的倍数值
var endMove = Math.round(updatedMove / lineSpacing.current) * lineSpacing.current;
var deg = "".concat((Math.abs(Math.round(endMove / lineSpacing.current)) + 1) * ROTATION, "deg");
applyTransform(type, deg, time, endMove);
setCurrentIndex(Math.abs(Math.round(endMove / lineSpacing.current)) + 1);
} else {
var currentDeg = (-updatedMove / lineSpacing.current + 1) * ROTATION;
var deg1 = Math.min(Math.max(currentDeg, 0), (options.length + 1) * ROTATION);
if (deg1 >= 0 && deg1 < (options.length + 1) * ROTATION) {
applyTransform('', "".concat(deg1, "deg"), undefined, updatedMove);
deg1 > 0 && setCurrentIndex(Math.abs(Math.round(updatedMove / lineSpacing.current)) + 1);
}
}
};
var selectValue = function(move) {
onSelect === null || onSelect === void 0 ? void 0 : onSelect(options === null || options === void 0 ? void 0 : options[Math.round(-move / lineSpacing.current)], keyIndex);
};
var isScroll = useRef(false);
var handleTouchStart = function(event) {
isScroll.current = true;
touch.start(event);
setStartY(touch.deltaY.current);
setStartTime(Date.now());
transformY.current = scrollDistance;
};
var handleTouchMove = function(event) {
touch.move(event);
if (touch.isVertical) {
isMoving.current = true;
preventDefault(event, true);
}
var move = touch.deltaY.current - startY;
handleMove(move);
};
var handleTouchEnd = function() {
if (!isMoving.current) return;
var move = touch.deltaY.current - startY;
var moveTime = Date.now() - startTime;
if (moveTime <= INERTIA_TIME && Math.abs(move) > INERTIA_DISTANCE) {
var distance = momentum(move, moveTime);
handleMove(distance, 'end', +duration);
} else {
handleMove(move, 'end');
}
isScroll.current = false;
setTimeout(function() {
touch.reset();
}, 0);
};
var updateStatus = function(shouldSelect, value) {
var selectedValue = value || props.value;
var index = options.findIndex(function(item) {
return item.value === selectedValue;
});
setCurrentIndex(index === -1 ? 0 : index + 1);
var move = index * lineSpacing.current;
shouldSelect && selectValue(-move);
handleMove(-move);
};
var stopMomentumScroll = function() {
isMoving.current = false;
setTouchTime(0);
selectValue(scrollDistance);
};
var getReactHeight = function() {
return _async_to_generator(function() {
var placeholder, placeholderHeight, error;
return _ts_generator(this, function(_state) {
switch(_state.label){
case 0:
_state.trys.push([
0,
2,
,
3
]);
return [
4,
getRectInMultiPlatform(placeholderRef.current)
];
case 1:
placeholder = _state.sent();
placeholderHeight = placeholder.height || 36;
return [
2,
placeholderHeight
];
case 2:
error = _state.sent();
console.error('获取高度失败:', error);
return [
2,
36
];
case 3:
return [
2
];
}
});
})();
};
// lineSpacing.current CSS variable
useEffect(function() {
var element = pickerRollerRef.current;
var currentLineSpacing;
if (element && web()) {
var computedStyle = getComputedStyle(element);
currentLineSpacing = computedStyle.getPropertyValue('--nutui-picker-item-height');
if (currentLineSpacing) {
lineSpacing.current = parseFloat(currentLineSpacing);
}
} else if (placeholderRef.current) {
getReactHeight().then(function(height) {
currentLineSpacing = height;
if (currentLineSpacing) {
lineSpacing.current = currentLineSpacing;
setGetStatus(true);
}
});
}
}, [
pickerRollerRef.current,
placeholderRef.current
]);
useEffect(function() {
isMoving.current = false;
setScrollDistance(0);
transformY.current = 0;
updateStatus(false);
}, [
options,
props.value
]);
useImperativeHandle(ref, function() {
return {
stopMomentum: stopMomentumScroll,
moving: isMoving.current
};
});
useEffect(function() {
var _pickerRollerRef_current, _pickerRollerRef_current1, _pickerRollerRef_current2;
var eventOptions = passiveSupported ? {
passive: false,
once: true
} : false;
(_pickerRollerRef_current = pickerRollerRef.current) === null || _pickerRollerRef_current === void 0 ? void 0 : _pickerRollerRef_current.addEventListener('touchstart', handleTouchStart, eventOptions);
(_pickerRollerRef_current1 = pickerRollerRef.current) === null || _pickerRollerRef_current1 === void 0 ? void 0 : _pickerRollerRef_current1.addEventListener('touchmove', handleTouchMove, eventOptions);
(_pickerRollerRef_current2 = pickerRollerRef.current) === null || _pickerRollerRef_current2 === void 0 ? void 0 : _pickerRollerRef_current2.addEventListener('touchend', handleTouchEnd, eventOptions);
return function() {
var _pickerRollerRef_current, _pickerRollerRef_current1, _pickerRollerRef_current2;
(_pickerRollerRef_current = pickerRollerRef.current) === null || _pickerRollerRef_current === void 0 ? void 0 : _pickerRollerRef_current.removeEventListener('touchstart', handleTouchStart, eventOptions);
(_pickerRollerRef_current1 = pickerRollerRef.current) === null || _pickerRollerRef_current1 === void 0 ? void 0 : _pickerRollerRef_current1.removeEventListener('touchmove', handleTouchMove, eventOptions);
(_pickerRollerRef_current2 = pickerRollerRef.current) === null || _pickerRollerRef_current2 === void 0 ? void 0 : _pickerRollerRef_current2.removeEventListener('touchend', handleTouchEnd, eventOptions);
};
}, [
pickerRollerRef.current,
handleTouchStart,
handleTouchMove,
handleTouchEnd
]);
var onTransitionEnd = function() {
if (!isScroll.current) {
stopMomentumScroll();
}
};
return /*#__PURE__*/ React.createElement(View, {
className: "nut-pickerview-list",
ref: pickerRollerRef
}, /*#__PURE__*/ React.createElement(View, {
className: "".concat(classPrefix, "-placeholder"),
ref: placeholderRef,
id: "".concat(classPrefix, "-placeholder-").concat(uuid)
}), /*#__PURE__*/ React.createElement(View, {
className: classPrefix,
id: "".concat(classPrefix, "-").concat(uuid),
ref: rollerRef,
style: threeDimensional ? touchRollerStyle() : touchTiledStyle(),
onTransitionEnd: onTransitionEnd
}, threeDimensional && options.map(function(item, index) {
var _item_value;
var _obj;
return /*#__PURE__*/ React.createElement(React.Fragment, {
key: (_item_value = item.value) !== null && _item_value !== void 0 ? _item_value : index
}, isGetLineSpacing ? /*#__PURE__*/ React.createElement(View, {
className: classNames("".concat(classPrefix, "-item"), (_obj = {}, _define_property(_obj, "".concat(classPrefix, "-item-hidden"), isItemHidden(index + 1)), _define_property(_obj, "".concat(classPrefix, "-item-active"), index + 1 === currentIndex), _obj)),
style: rollerStyle(index)
}, renderLabel(item)) : null);
}), !threeDimensional && options.map(function(item, index) {
var _item_value;
return /*#__PURE__*/ React.createElement(View, {
className: classNames("".concat(classPrefix, "-item-tiled"), _define_property({}, "".concat(classPrefix, "-item-active"), index + 1 === currentIndex)),
key: (_item_value = item.value) !== null && _item_value !== void 0 ? _item_value : index
}, renderLabel(item));
})));
};
var PickerRoller = /*#__PURE__*/ React.forwardRef(InternalPickerRoller);
export default PickerRoller;