@cainiaofe/cn-ui-m
Version:
181 lines (180 loc) • 7.85 kB
JavaScript
import { __awaiter, __generator } from "tslib";
import $i18n from "../../locales/i18n";
import * as React from 'react';
import { useRef, useEffect, useState } from 'react';
import { animated, useSpring } from '@react-spring/web';
import { useDrag } from '@use-gesture/react';
import { sleep } from "../../utils/sleep";
import { getScrollParent } from "../../utils/get-scroll-parent";
import { supportsPassive } from "../../utils/supports-passive";
import { rubberbandIfOutOfBounds } from "../../utils/rubberband";
import { withNativeProps } from '@cainiaofe/cn-ui-common';
import classNames from 'classnames';
var classPrefix = 'cn-ui-m-pull-to-refresh';
function getScrollTop(element) {
return 'scrollTop' in element ? element.scrollTop : element.scrollY;
}
var CnPullToRefresh = function (props) {
var _a, _b;
var headHeight = (_a = props.headHeight) !== null && _a !== void 0 ? _a : 40;
var threshold = (_b = props.threshold) !== null && _b !== void 0 ? _b : 60;
var _c = useState('pulling'), status = _c[0], setStatus = _c[1];
var _d = useSpring(function () { return ({
from: { height: 0 },
config: {
tension: 300,
friction: 30,
clamp: true,
},
}); }), springStyles = _d[0], api = _d[1];
var elementRef = useRef(null);
var pullingRef = useRef(false);
// 防止下拉时抖动
useEffect(function () {
var _a;
(_a = elementRef.current) === null || _a === void 0 ? void 0 : _a.addEventListener('touchmove', function () { });
}, []);
function doRefresh() {
return __awaiter(this, void 0, void 0, function () {
var e_1;
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
api.start({ height: headHeight });
setStatus('refreshing');
_a.label = 1;
case 1:
_a.trys.push([1, 4, , 5]);
if (!(typeof props.onRefresh === 'function')) return [3 /*break*/, 3];
return [4 /*yield*/, props.onRefresh()];
case 2:
_a.sent();
_a.label = 3;
case 3:
setStatus('complete');
return [3 /*break*/, 5];
case 4:
e_1 = _a.sent();
api.start({
to: function (next) { return __awaiter(_this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, next({ height: 0 })];
case 1:
_a.sent();
setStatus('pulling');
return [2 /*return*/];
}
});
}); },
});
throw e_1;
case 5:
if (!(props.completeDelay > 0)) return [3 /*break*/, 7];
return [4 /*yield*/, sleep(props.completeDelay)];
case 6:
_a.sent();
_a.label = 7;
case 7:
api.start({
to: function (next) { return __awaiter(_this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, next({ height: 0 })];
case 1:
_a.sent();
setStatus('pulling');
return [2 /*return*/];
}
});
}); },
});
return [2 /*return*/];
}
});
});
}
useDrag(function (state) {
if (status === 'refreshing' || status === 'complete')
return;
var event = state.event;
if (state.last) {
pullingRef.current = false;
if (status === 'canRelease') {
doRefresh();
}
else {
api.start({ height: 0 });
}
return;
}
var _a = state.movement, y = _a[1];
if (state.first && y > 0) {
var target = state.event.target;
if (!target || !(target instanceof Element))
return;
var scrollParent = getScrollParent(target);
while (true) {
if (!scrollParent)
return;
var scrollTop = getScrollTop(scrollParent);
if (scrollTop > 0) {
return;
}
if (scrollParent instanceof Window) {
break;
}
scrollParent = getScrollParent(scrollParent.parentNode);
}
pullingRef.current = true;
}
if (!pullingRef.current)
return;
if (event.cancelable) {
event.preventDefault();
}
event.stopPropagation();
var height = Math.max(rubberbandIfOutOfBounds(y, 0, 0, headHeight * 5, 0.5), 0);
api.start({ height: height });
setStatus(height > threshold ? 'canRelease' : 'pulling');
}, {
pointer: { touch: true },
axis: 'y',
target: elementRef,
enabled: !props.disabled,
eventOptions: supportsPassive
? { passive: false }
: false,
});
var renderStatusText = function () {
var _a;
if (props.renderText) {
return (_a = props.renderText) === null || _a === void 0 ? void 0 : _a.call(props, status);
}
var _b = props.canReleaseText, canReleaseText = _b === void 0 ? $i18n.get({
id: 'ReleaseImmediateRefresh',
dm: '释放立即刷新',
}) : _b, _c = props.completeText, completeText = _c === void 0 ? $i18n.get({ id: 'RefreshSuccessful', dm: '刷新成功' }) : _c, _d = props.pullingText, pullingText = _d === void 0 ? $i18n.get({ id: 'PulldownRefresh', dm: '下拉刷新' }) : _d, _e = props.refreshingText, refreshingText = _e === void 0 ? $i18n.get({ id: 'Loading', dm: '加载中' }) : _e;
if (status === 'pulling')
return pullingText;
if (status === 'canRelease')
return canReleaseText;
if (status === 'refreshing')
return refreshingText;
if (status === 'complete')
return completeText;
};
return withNativeProps(props, React.createElement(animated.div, { ref: elementRef, className: classNames(CN_UI_HASH_CLASS_NAME, classPrefix) },
React.createElement(animated.div, { style: springStyles, className: "".concat(classPrefix, "-head") },
React.createElement("div", { className: "".concat(classPrefix, "-head-content"), style: { height: headHeight } }, renderStatusText())),
React.createElement("div", { className: "".concat(classPrefix, "-content") }, props.children)));
};
CnPullToRefresh.displayName = 'CnPullToRefresh';
CnPullToRefresh.defaultProps = {
completeDelay: 500,
disabled: false,
headHeight: 40,
threshold: 60,
};
export { CnPullToRefresh };