UNPKG

@nutui/nutui-react

Version:

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

240 lines (239 loc) 9.96 kB
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';