UNPKG

@cainiaofe/cn-ui-m

Version:
181 lines (180 loc) 7.85 kB
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 };