@nutui/nutui-react
Version:
京东风格的轻量级移动端 React 组件库,支持一套代码生成 H5 和小程序
240 lines (239 loc) • 9.96 kB
JavaScript
import { _ as _async_to_generator } from "@swc/helpers/_/_async_to_generator";
import { _ as _object_spread } from "@swc/helpers/_/_object_spread";
import { _ as _object_spread_props } from "@swc/helpers/_/_object_spread_props";
import { _ as _object_without_properties } from "@swc/helpers/_/_object_without_properties";
import { _ as _sliced_to_array } from "@swc/helpers/_/_sliced_to_array";
import { _ as _ts_generator } from "@swc/helpers/_/_ts_generator";
import React, { useEffect, useRef, useState } from "react";
import classNames from "classnames";
import { useConfig } from "../configprovider";
import { ComponentDefaults } from "../../utils/typings";
var defaultProps = _object_spread_props(_object_spread({}, ComponentDefaults), {
type: 'default',
hasMore: true,
threshold: 200,
target: '',
capture: false,
pullRefresh: false
});
var classPrefix = "nut-infiniteloading";
export var InfiniteLoading = function(props) {
var getBottomTipsText = function getBottomTipsText() {
if (isInfiniting) {
return loadingText || locale.infiniteloading.loadText;
}
if (!hasMore) {
return loadMoreText || locale.infiniteloading.loadMoreText;
}
return null;
};
var locale = useConfig().locale;
var _ref = _object_spread({}, defaultProps, props), children = _ref.children, type = _ref.type, hasMore = _ref.hasMore, threshold = _ref.threshold, target = _ref.target, capture = _ref.capture, pullRefresh = _ref.pullRefresh, pullingText = _ref.pullingText, loadingText = _ref.loadingText, loadMoreText = _ref.loadMoreText, className = _ref.className, onRefresh = _ref.onRefresh, onLoadMore = _ref.onLoadMore, onScroll = _ref.onScroll, restProps = _object_without_properties(_ref, [
"children",
"type",
"hasMore",
"threshold",
"target",
"capture",
"pullRefresh",
"pullingText",
"loadingText",
"loadMoreText",
"className",
"onRefresh",
"onLoadMore",
"onScroll"
]);
var _useState = _sliced_to_array(useState(false), 2), isInfiniting = _useState[0], setIsInfiniting = _useState[1];
var scroller = useRef(null);
var refreshTop = useRef(null);
var scrollEl = useRef(null);
var isTouching = useRef(false);
var beforeScrollTop = useRef(0);
var refreshMaxH = useRef(0);
var y = useRef(0);
var distance = useRef(0);
var classes = classNames(classPrefix, className, "".concat(classPrefix, "-").concat(type));
useEffect(function() {
var _scrollEl_current;
if (target && document.getElementById(target)) {
scrollEl.current = document.getElementById(target);
} else {
scrollEl.current = window;
}
(_scrollEl_current = scrollEl.current) === null || _scrollEl_current === void 0 ? void 0 : _scrollEl_current.addEventListener('scroll', handleScroll, capture);
return function() {
var _scrollEl_current;
(_scrollEl_current = scrollEl.current) === null || _scrollEl_current === void 0 ? void 0 : _scrollEl_current.removeEventListener('scroll', handleScroll, capture);
};
}, [
hasMore,
isInfiniting,
onLoadMore
]);
useEffect(function() {
var element = scroller.current;
element.addEventListener('touchmove', touchMove, {
passive: false
});
return function() {
element.removeEventListener('touchmove', touchMove, {
passive: false
});
};
}, []);
var getStyle = function() {
return {
height: distance.current < 0 ? "0px" : "".concat(distance.current, "px"),
transition: isTouching.current ? "height 0s cubic-bezier(0.25,0.1,0.25,1)" : "height 0.2s cubic-bezier(0.25,0.1,0.25,1)"
};
};
var handleScroll = /*#__PURE__*/ function() {
var _ref = _async_to_generator(function() {
return _ts_generator(this, function(_state) {
switch(_state.label){
case 0:
if (!isScrollAtBottom() || !hasMore || isInfiniting) {
return [
2
];
}
setIsInfiniting(true);
return [
4,
onLoadMore === null || onLoadMore === void 0 ? void 0 : onLoadMore()
];
case 1:
_state.sent();
infiniteDone();
return [
2
];
}
});
});
return function handleScroll() {
return _ref.apply(this, arguments);
};
}();
var infiniteDone = function() {
setIsInfiniting(false);
};
var getRefreshTop = function() {
return refreshTop.current;
};
var refreshDone = function() {
distance.current = 0;
getRefreshTop().style.height = "".concat(distance.current, "px");
isTouching.current = false;
};
var touchStart = function(event) {
if (beforeScrollTop.current === 0 && !isTouching.current && pullRefresh) {
y.current = event.touches[0].pageY;
isTouching.current = true;
var childHeight = getRefreshTop().firstElementChild.offsetHeight;
refreshMaxH.current = Math.floor(childHeight * 1 + 10);
}
};
var touchMove = function(event) {
distance.current = event.touches[0].pageY - y.current;
if (distance.current > 0 && isTouching.current) {
event.preventDefault();
if (distance.current >= refreshMaxH.current) {
distance.current = refreshMaxH.current;
getRefreshTop().style.height = "".concat(distance.current, "px");
} else {
getRefreshTop().style.height = "".concat(distance.current, "px");
}
} else {
distance.current = 0;
getRefreshTop().style.height = "".concat(distance.current, "px");
isTouching.current = false;
}
};
var touchEnd = /*#__PURE__*/ function() {
var _ref = _async_to_generator(function() {
return _ts_generator(this, function(_state) {
switch(_state.label){
case 0:
if (!(distance.current < refreshMaxH.current)) return [
3,
1
];
distance.current = 0;
getRefreshTop().style.height = "".concat(distance.current, "px");
isTouching.current = false;
return [
3,
3
];
case 1:
return [
4,
onRefresh === null || onRefresh === void 0 ? void 0 : onRefresh()
];
case 2:
_state.sent();
refreshDone();
_state.label = 3;
case 3:
return [
2
];
}
});
});
return function touchEnd() {
return _ref.apply(this, arguments);
};
}();
var getWindowScrollTop = function() {
return window.scrollY !== undefined ? window.scrollY : (document.documentElement || document.body.parentNode || document.body).scrollTop;
};
var calculateTopPosition = function(el) {
return !el ? 0 : el.offsetTop + calculateTopPosition(el.offsetParent);
};
var isScrollAtBottom = function() {
var offsetDistance = 0;
var resScrollTop = 0;
var direction = 'down';
var windowScrollTop = getWindowScrollTop();
if (!target || !document.getElementById(target)) {
if (scroller.current) {
offsetDistance = calculateTopPosition(scroller.current) + scroller.current.offsetHeight - windowScrollTop - window.innerHeight;
}
resScrollTop = windowScrollTop;
} else {
var _scrollEl_current = scrollEl.current, scrollHeight = _scrollEl_current.scrollHeight, clientHeight = _scrollEl_current.clientHeight, scrollTop = _scrollEl_current.scrollTop;
offsetDistance = scrollHeight - clientHeight - scrollTop;
resScrollTop = scrollTop;
}
if (beforeScrollTop.current > resScrollTop) {
direction = 'up';
} else {
direction = 'down';
}
beforeScrollTop.current = resScrollTop;
onScroll && onScroll(resScrollTop);
return offsetDistance <= threshold && direction === 'down';
};
return /*#__PURE__*/ React.createElement("div", _object_spread({
className: classes,
ref: scroller,
onTouchStart: touchStart,
onTouchEnd: touchEnd
}, restProps), /*#__PURE__*/ React.createElement("div", {
className: "nut-infinite-top",
ref: refreshTop,
style: getStyle()
}, /*#__PURE__*/ React.createElement("div", {
className: "nut-infinite-top-tips"
}, pullingText || locale.infiniteloading.pullRefreshText)), /*#__PURE__*/ React.createElement("div", {
className: "nut-infinite-container"
}, children), /*#__PURE__*/ React.createElement("div", {
className: "nut-infinite-bottom"
}, /*#__PURE__*/ React.createElement("div", {
className: "nut-infinite-bottom-tips"
}, getBottomTipsText())));
};
InfiniteLoading.displayName = 'NutInfiniteLoading';