UNPKG

@nutui/nutui-react-taro

Version:

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

186 lines (185 loc) 8.75 kB
import { _ as _async_to_generator } from "@swc/helpers/_/_async_to_generator"; import { _ as _define_property } from "@swc/helpers/_/_define_property"; import { _ as _object_spread } from "@swc/helpers/_/_object_spread"; import { _ as _object_spread_props } from "@swc/helpers/_/_object_spread_props"; import { _ as _sliced_to_array } from "@swc/helpers/_/_sliced_to_array"; import { _ as _ts_generator } from "@swc/helpers/_/_ts_generator"; import React, { useRef, useState } from "react"; import classNames from "classnames"; import { View } from "@tarojs/components"; import { Loading, More } from "@nutui/icons-react-taro"; import Taro from "@tarojs/taro"; import { useConfig } from "../configprovider/index"; import { useTouch } from "../../hooks/use-touch"; import { rubberbandIfOutOfBounds } from "../../utils/rubberband"; import { sleep } from "../../utils/sleep"; import { ComponentDefaults } from "../../utils/typings"; import { pxTransform } from "../../utils/taro/px-transform"; import { getDeviceInfo } from "../../utils/taro/get-system-info"; var defaultProps = _object_spread_props(_object_spread({}, ComponentDefaults), { type: 'default', pullingText: '', canReleaseText: '', refreshingText: '', completeText: '', completeDelay: 500, disabled: false, headHeight: 80, threshold: 60, scrollTop: 0, onRefresh: function() {} }); export var PullToRefresh = function(p) { var doRefresh = function doRefresh() { return _async_to_generator(function() { var e; return _ts_generator(this, function(_state) { switch(_state.label){ case 0: setHeight(headHeight); setStatus('refreshing'); _state.label = 1; case 1: _state.trys.push([ 1, 3, , 4 ]); return [ 4, props.onRefresh() ]; case 2: _state.sent(); setStatus('complete'); return [ 3, 4 ]; case 3: e = _state.sent(); setHeight(0); setStatus('pulling'); throw e; case 4: if (!(props.completeDelay > 0)) return [ 3, 6 ]; return [ 4, sleep(props.completeDelay) ]; case 5: _state.sent(); _state.label = 6; case 6: setHeight(0); setStatus('pulling'); return [ 2 ]; } }); })(); }; var classPrefix = 'nut-pulltorefresh'; var locale = useConfig().locale; var touch = useTouch(); var props = _object_spread({}, defaultProps, p, { pullingText: p.pullingText || locale.pullToRefresh.pullingText, canReleaseText: p.canReleaseText || locale.pullToRefresh.canReleaseText, refreshingText: p.refreshingText || locale.pullToRefresh.refreshingText, completeText: p.completeText || locale.pullToRefresh.completeText }); var classes = classNames(classPrefix, props.className, "".concat(classPrefix, "-").concat(props.type)); var headHeight = props.headHeight; var threshold = props.threshold; var pullingRef = useRef(false); var _useState = _sliced_to_array(useState('pulling'), 2), status = _useState[0], setStatus = _useState[1]; var _useState1 = _sliced_to_array(useState(0), 2), height = _useState1[0], setHeight = _useState1[1]; var timer = useRef(); var renderIcons = function(status) { return /*#__PURE__*/ React.createElement(React.Fragment, null, (status === 'pulling' || status === 'complete') && /*#__PURE__*/ React.createElement(Loading, null), (status === 'canRelease' || status === 'refreshing') && /*#__PURE__*/ React.createElement(More, null)); }; var renderStatusIcon = function() { if (props.renderIcon) { var _props_renderIcon; return (_props_renderIcon = props.renderIcon) === null || _props_renderIcon === void 0 ? void 0 : _props_renderIcon.call(props, status); } return renderIcons(status); }; var renderStatusText = function() { if (props.renderText) { var _props_renderText; return (_props_renderText = props.renderText) === null || _props_renderText === void 0 ? void 0 : _props_renderText.call(props, status); } if (status === 'pulling') return props.pullingText; if (status === 'canRelease') return props.canReleaseText; if (status === 'refreshing') return props.refreshingText; if (status === 'complete') return props.completeText; return ''; }; var handleTouchStart = function(e) { if (props.disabled) return; touch.start(e); }; var handleTouchMove = function(e) { if (props.scrollTop > 0 || props.disabled) { return; } if (status === 'refreshing' || status === 'complete') return; // touch 的封装不好,比如在使用高度控制的时候,就很迷 touch.move(e); if (touch.isVertical()) { pullingRef.current = true; setHeight(Math.max(rubberbandIfOutOfBounds(touch.deltaY.current, 0, 0, headHeight * 5, 0.5), 0)); setStatus(height > threshold ? 'canRelease' : 'pulling'); } clearTimeout(timer.current); }; var handleTouchEnd = function() { if (props.disabled) return; pullingRef.current = false; if (status === 'canRelease') { doRefresh(); } else { // 时序问题,可能会先setStatus再修改heightRef,导致下拉不到位后组件不会自动回弹 setHeight(0); // heightRef.current = 0 setStatus('pulling'); } }; // 安卓微信小程序onTouchMove回调次数少导致下拉卡顿,增加动效会更顺畅 var isAndroidWeApp = getDeviceInfo().platform === 'android' && Taro.getEnv() === 'WEAPP'; var springStyles = _object_spread({ height: pxTransform(height) }, !pullingRef.current || isAndroidWeApp ? { transition: 'height .3s ease' } : {}); var _obj, _obj1, _obj2, _obj3, _obj4; return /*#__PURE__*/ React.createElement(View, { className: classes, style: props.style, catchMove: props.catchMove, onTouchStart: handleTouchStart, onTouchMove: handleTouchMove, onTouchEnd: handleTouchEnd }, /*#__PURE__*/ React.createElement(View, { style: springStyles, className: classNames((_obj = {}, _define_property(_obj, "".concat(classPrefix, "-head"), true), _define_property(_obj, "".concat(classPrefix, "-primary-head"), props.type === 'primary'), _obj)) }, /*#__PURE__*/ React.createElement(View, { className: classNames((_obj1 = {}, _define_property(_obj1, "".concat(classPrefix, "-head-content"), true), _define_property(_obj1, "".concat(classPrefix, "-primary-head-content"), props.type === 'primary'), _obj1)), style: { height: pxTransform(headHeight) } }, /*#__PURE__*/ React.createElement(View, { className: classNames((_obj2 = {}, _define_property(_obj2, "".concat(classPrefix, "-status-icon"), true), _define_property(_obj2, "".concat(classPrefix, "-primary-status-icon"), props.type === 'primary'), _obj2)) }, renderStatusIcon()), /*#__PURE__*/ React.createElement(View, { className: classNames((_obj3 = {}, _define_property(_obj3, "".concat(classPrefix, "-status-text"), true), _define_property(_obj3, "".concat(classPrefix, "-primary-status-text"), props.type === 'primary'), _obj3)) }, renderStatusText()))), /*#__PURE__*/ React.createElement(View, { className: classNames((_obj4 = {}, _define_property(_obj4, "".concat(classPrefix, "-content"), true), _define_property(_obj4, "".concat(classPrefix, "-primary-content}"), props.type === 'primary'), _obj4)) }, props.children)); }; PullToRefresh.displayName = 'NutPullToRefresh';