@nutui/nutui-react-taro
Version:
京东风格的轻量级移动端 React 组件库,支持一套代码生成 H5 和小程序
186 lines (185 loc) • 8.75 kB
JavaScript
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';