UNPKG

vantui-edit

Version:

一套适用于Taro3及React的vantui组件库

699 lines (591 loc) 26.5 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _typeof = require("@babel/runtime/helpers/typeof"); Object.defineProperty(exports, "__esModule", { value: true }); exports.PowerScrollView = PowerScrollView; exports.default = void 0; var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator")); var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties")); var _react = _interopRequireWildcard(require("react")); var _components = require("@tarojs/components"); var _loading = require("./../loading"); var _empty = require("./../empty"); var _useTouch = require("./useTouch"); var _utils = require("./utils"); var _jsxRuntime = require("react/jsx-runtime"); var _excluded = ["minTriggerTopDistance", "headHeight", "successDuration", "animationDuration", "disabled", "pullDistance", "onRefresh", "renderHead", "successText", "children", "loadingText", "loosingText", "pullingText", "onLoad", "onScroll", "scrollTop", "offset", "finishedText", "renderFinished", "renderLoading", "finished", "renderError", "errorText", "total", "current", "pageSize", "emptyDescription", "emptyImage", "upperThreshold", "lowerThreshold", "refresherEnabled", "onScrollToLower", "onScrollToUpper", "scrollY", "className"]; function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; } /** * bem helper * b() // 'button' * b('text') // 'button__text' * b({ disabled }) // 'button button--disabled' * b('text', { disabled }) // 'button__text button__text--disabled' * b(['disabled', 'primary']) // 'button button--disabled button--primary' */ // const [name, bem, t] = createNamespace('pull-refresh') // const pullRefreshBem = (name?: string) => // name ? 'van-pull-refresh__' + name : 'van-pull-refresh' var bem = function bem(name) { return name ? 'van-power-scroll-view__' + name : 'van-power-scroll-view'; }; var sleep = function sleep(t) { return new Promise(function (resolve) { setTimeout(function () { resolve(); }, t); }); }; var DEFAULT_HEAD_HEIGHT = 50; var MIN_TRIGGER_TOP_DISTANCE = 150; var TEXT_STATUS = ['pulling', 'loosing', 'success']; // const RenderStatus: React.FC<{}> = (props) => {} function PowerScrollView(props) { var _ref, _props$refresherEnabl2, _props$scrollY2; var _props$minTriggerTopD = props.minTriggerTopDistance, minTriggerTopDistance = _props$minTriggerTopD === void 0 ? MIN_TRIGGER_TOP_DISTANCE : _props$minTriggerTopD, _props$headHeight = props.headHeight, headHeight = _props$headHeight === void 0 ? DEFAULT_HEAD_HEIGHT : _props$headHeight, _props$successDuratio = props.successDuration, successDuration = _props$successDuratio === void 0 ? 500 : _props$successDuratio, _props$animationDurat = props.animationDuration, animationDuration = _props$animationDurat === void 0 ? 300 : _props$animationDurat, disabled = props.disabled, _props$pullDistance = props.pullDistance, pullDistance = _props$pullDistance === void 0 ? props.refresherThreshold || props.pullDistance : _props$pullDistance, onRefresh = props.onRefresh, renderHead = props.renderHead, successText = props.successText, children = props.children, _props$loadingText = props.loadingText, loadingText = _props$loadingText === void 0 ? '加载中...' : _props$loadingText, _props$loosingText = props.loosingText, loosingText = _props$loosingText === void 0 ? '释放即可刷新...' : _props$loosingText, _props$pullingText = props.pullingText, pullingText = _props$pullingText === void 0 ? '下拉即可刷新...' : _props$pullingText, onLoad = props.onLoad, onScrollEvent = props.onScroll, scrollTop = props.scrollTop, offset = props.offset, _props$finishedText = props.finishedText, finishedText = _props$finishedText === void 0 ? '没有更多了' : _props$finishedText, renderFinished = props.renderFinished, renderLoading = props.renderLoading, _finished = props.finished, renderError = props.renderError, errorText = props.errorText, total = props.total, current = props.current, _props$pageSize = props.pageSize, pageSize = _props$pageSize === void 0 ? 20 : _props$pageSize, emptyDescription = props.emptyDescription, emptyImage = props.emptyImage, upperThreshold = props.upperThreshold, _props$lowerThreshold = props.lowerThreshold, lowerThreshold = _props$lowerThreshold === void 0 ? props.lowerThreshold || props.offset || 250 : _props$lowerThreshold, _props$refresherEnabl = props.refresherEnabled, refresherEnabled = _props$refresherEnabl === void 0 ? (_ref = (_props$refresherEnabl2 = props.refresherEnabled) !== null && _props$refresherEnabl2 !== void 0 ? _props$refresherEnabl2 : props.disabled) !== null && _ref !== void 0 ? _ref : true : _props$refresherEnabl, _props$onScrollToLowe = props.onScrollToLower, onScrollToLower = _props$onScrollToLowe === void 0 ? props.onScrollToLower || props.onLoad : _props$onScrollToLowe, _props$onScrollToUppe = props.onScrollToUpper, onScrollToUpper = _props$onScrollToUppe === void 0 ? props.onScrollToUpper || props.onRefresh : _props$onScrollToUppe, _props$scrollY = props.scrollY, scrollY = _props$scrollY === void 0 ? (_props$scrollY2 = props.scrollY) !== null && _props$scrollY2 !== void 0 ? _props$scrollY2 : true : _props$scrollY, className = props.className, rest = (0, _objectWithoutProperties2.default)(props, _excluded); // ==LIST======================================= // 是否到底了 // const reachDownRef = useRef(false) // 是否显示 loading // ts推断 var loadingRef = (0, _react.useRef)(false); // 是否显示 报错 var errorRef = (0, _react.useRef)(false); // 分页 var paginationRef = (0, _react.useRef)({ page: 0, pageSize: pageSize }); var startTop = (0, _react.useRef)(0); var _useState = (0, _react.useState)(_finished || false), _useState2 = (0, _slicedToArray2.default)(_useState, 2), finished = _useState2[0], setFinished = _useState2[1]; var count = Array.isArray(children) ? Array.from(children).length : toString.call(children) === '[object Object]' ? 1 : 0; var currentCount = current !== null && current !== void 0 ? current : count; var listCount = (0, _react.useRef)(0); (0, _react.useEffect)(function () { var pageSize = paginationRef.current.pageSize; if (currentCount <= pageSize) { paginationRef.current.page = 1; setFinished(false); } // 传入finished if (_finished !== undefined) { setFinished(_finished); return; } // 都没有传 if (total === undefined) { var addCount = currentCount - listCount.current; if (currentCount === 0 || listCount.current !== 0 && addCount > -1 && addCount < paginationRef.current.pageSize) { setFinished(true); } listCount.current = currentCount; return; } // 传入total if (currentCount >= total) { setFinished(true); } else { setFinished(false); } }, [total, currentCount, _finished]); var _useState3 = (0, _react.useState)(false), _useState4 = (0, _slicedToArray2.default)(_useState3, 2), isError = _useState4[0], setError = _useState4[1]; // 是否滚动最上面了 var reachTopRef = (0, _react.useRef)(true); var _useState5 = (0, _react.useState)('normal'), _useState6 = (0, _slicedToArray2.default)(_useState5, 2), status = _useState6[0], setState = _useState6[1]; var _useState7 = (0, _react.useState)(0), _useState8 = (0, _slicedToArray2.default)(_useState7, 2), distance = _useState8[0], setDistance = _useState8[1]; var _useState9 = (0, _react.useState)(0), _useState10 = (0, _slicedToArray2.default)(_useState9, 2), duration = _useState10[0], setDuration = _useState10[1]; var touch = (0, _useTouch.useTouch)(); var headStyle = (0, _react.useMemo)(function () { if (headHeight !== DEFAULT_HEAD_HEIGHT) { return { height: "".concat(headHeight, "px") }; } return ''; }, [headHeight]); var getScrollTop = (0, _react.useCallback)( /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee() { var _yield$scrollOffset, scrollTop; return _regenerator.default.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: _context.next = 2; return (0, _utils.scrollOffset)(scrollRef.current); case 2: _yield$scrollOffset = _context.sent; scrollTop = _yield$scrollOffset.scrollTop; return _context.abrupt("return", scrollTop); case 5: case "end": return _context.stop(); } } }, _callee); })), []); var isTouchable = (0, _react.useCallback)(function () { return status !== 'loading' && status !== 'success' && refresherEnabled && !loadingRef.current; }, [refresherEnabled, status]); var ease = (0, _react.useCallback)(function (distance) { var _pullDistance = +(pullDistance || headHeight); if (distance > _pullDistance) { if (distance < _pullDistance * 2) { distance = _pullDistance + (distance - _pullDistance) / 2; } else { distance = _pullDistance * 1.5 + (distance - _pullDistance * 2) / 4; } } return Math.round(distance); }, [headHeight, pullDistance]); var setStatus = (0, _react.useCallback)(function (distance, isLoading) { var _pullDistance = +(pullDistance || headHeight); setDistance(distance); if (isLoading) { setState('loading'); loadingRef.current = true; } else if (distance === 0) { setState('normal'); } else if (distance < _pullDistance) { setState('pulling'); } else { setState('loosing'); } }, [headHeight, pullDistance]); var statusText = (0, _react.useMemo)(function () { if (status === 'loading') { return loadingText; } if (status === 'loosing') { return loosingText; } if (status === 'pulling') { return pullingText; } if (status === 'success') { return successText; } return ''; }, [loadingText, loosingText, pullingText, status, successText]); var renderStatus = (0, _react.useMemo)(function () { var node = renderHead === null || renderHead === void 0 ? void 0 : renderHead({ status: status, distance: distance }); if (node) { return node; } if (TEXT_STATUS.includes(status)) { return /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.View, { className: bem('text'), children: statusText }); } if (status === 'loading') { return /*#__PURE__*/(0, _jsxRuntime.jsx)(_loading.Loading, { className: bem('loading'), children: statusText }); } return ''; }, [distance, statusText, status, renderHead]); var showSuccessTip = (0, _react.useCallback)( /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2() { return _regenerator.default.wrap(function _callee2$(_context2) { while (1) { switch (_context2.prev = _context2.next) { case 0: // state.status = 'success' setState('success'); _context2.next = 3; return sleep(+successDuration); case 3: case "end": return _context2.stop(); } } }, _callee2); })), [successDuration]); // 提前把reachTopRef.current的值 求出来 var debounceScrollOffset = (0, _react.useMemo)(function () { var _getScrollTop = /*#__PURE__*/function () { var _ref4 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee3() { var _scrollTop; return _regenerator.default.wrap(function _callee3$(_context3) { while (1) { switch (_context3.prev = _context3.next) { case 0: _context3.next = 2; return getScrollTop(); case 2: _scrollTop = _context3.sent; reachTopRef.current = _scrollTop <= 0; return _context3.abrupt("return", _scrollTop); case 5: case "end": return _context3.stop(); } } }, _callee3); })); return function _getScrollTop() { return _ref4.apply(this, arguments); }; }(); return (0, _utils.debounce)(_getScrollTop, 200); }, [getScrollTop]); // 如果这是了 scrollTop 要触发ScrollOffset计算 (0, _react.useEffect)(function () { // 立马执行一次 if (scrollTop) { reachTopRef.current = false; } }, [scrollTop]); var onScroll = (0, _react.useCallback)(function (e) { onScrollEvent === null || onScrollEvent === void 0 ? void 0 : onScrollEvent(e); // 模拟器 上 滑到顶 e.detail.scrollTop 不等于0, 低端机可能会出现 // reachTopRef.current = e.detail.scrollTop === 0 debounceScrollOffset(); }, [debounceScrollOffset, onScrollEvent]); // eslint-disable-next-line react-hooks/exhaustive-deps var checkPosition = (0, _react.useCallback)( /*#__PURE__*/function () { var _ref5 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee4(event) { return _regenerator.default.wrap(function _callee4$(_context4) { while (1) { switch (_context4.prev = _context4.next) { case 0: // const { scrollTop } = await scrollOffset(scrollRef.current!) // reachTopRef.current = scrollTop === 0 if (reachTopRef.current) { setDuration(0); touch.start(event); } case 1: case "end": return _context4.stop(); } } }, _callee4); })); return function (_x) { return _ref5.apply(this, arguments); }; }(), [touch]); var isStartRef = (0, _react.useRef)(false); var onTouchStart = (0, _react.useCallback)( /*#__PURE__*/function () { var _ref6 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee5(event) { var data; return _regenerator.default.wrap(function _callee5$(_context5) { while (1) { switch (_context5.prev = _context5.next) { case 0: if (!isTouchable()) { _context5.next = 8; break; } isStartRef.current = false; _context5.next = 4; return getScrollTop(); case 4: data = _context5.sent; isStartRef.current = true; startTop.current = data; checkPosition(event); case 8: case "end": return _context5.stop(); } } }, _callee5); })); return function (_x2) { return _ref6.apply(this, arguments); }; }(), [checkPosition, getScrollTop, isTouchable]); // list var onTouchMove = (0, _react.useCallback)(function (event) { if (isTouchable() && startTop.current < minTriggerTopDistance) { if (!isStartRef.current) { return; } var deltaY = touch.deltaY; touch.move(event); if (reachTopRef.current && deltaY.current >= 0 && touch.isVertical()) { (0, _utils.preventDefault)(event, true); setStatus(ease(deltaY.current)); } } }, [ease, isTouchable, minTriggerTopDistance, setStatus, touch]); // list var doRefresh = (0, _react.useCallback)( /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee6() { var event; return _regenerator.default.wrap(function _callee6$(_context6) { while (1) { switch (_context6.prev = _context6.next) { case 0: _context6.prev = 0; errorRef.current = false; setStatus(+headHeight, true); setError(false); paginationRef.current.page = 1; event = total === undefined ? 0 : paginationRef.current; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore _context6.next = 8; return onScrollToUpper === null || onScrollToUpper === void 0 ? void 0 : onScrollToUpper(event); case 8: setDuration(+animationDuration); if (!(successText || renderHead !== null && renderHead !== void 0 && renderHead({ status: 'success', distance: distance }))) { _context6.next = 12; break; } _context6.next = 12; return showSuccessTip(); case 12: _context6.prev = 12; setStatus(0, false); loadingRef.current = false; return _context6.finish(12); case 16: case "end": return _context6.stop(); } } }, _callee6, null, [[0,, 12, 16]]); })), [animationDuration, distance, headHeight, onScrollToUpper, renderHead, setStatus, showSuccessTip, successText, total]); var onTouchEnd = (0, _react.useCallback)(function () { if (reachTopRef.current && touch.deltaY.current && isTouchable()) { // state.duration = +animationDuration setDuration(+animationDuration); if (status === 'loosing') { doRefresh(); } else { setStatus(0); } } else { setStatus(0); } }, [doRefresh, isTouchable, animationDuration, setStatus, status, touch.deltaY]); var trackStyle = (0, _react.useMemo)(function () { return { transitionDuration: "".concat(duration, "ms"), transform: distance ? "translate3d(0,".concat(distance, "px, 0)") : '' }; }, [distance, duration]); var scrollRef = (0, _react.useRef)(); // ==LIST======================================= var isBanLoad = (0, _react.useCallback)(function () { return finished || status !== 'normal' || loadingRef.current || errorRef.current; }, [finished, status]); var doLoadMore = (0, _react.useCallback)( /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee7() { var event; return _regenerator.default.wrap(function _callee7$(_context7) { while (1) { switch (_context7.prev = _context7.next) { case 0: if (!isBanLoad()) { _context7.next = 2; break; } return _context7.abrupt("return"); case 2: _context7.prev = 2; loadingRef.current = true; paginationRef.current.page += 1; event = total === undefined ? currentCount : paginationRef.current; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore _context7.next = 8; return onScrollToLower === null || onScrollToLower === void 0 ? void 0 : onScrollToLower(event); case 8: _context7.next = 15; break; case 10: _context7.prev = 10; _context7.t0 = _context7["catch"](2); paginationRef.current.page -= 1; errorRef.current = true; setError(true); // 这里要主动触发刷新 // throw e case 15: _context7.prev = 15; loadingRef.current = false; return _context7.finish(15); case 18: case "end": return _context7.stop(); } } }, _callee7, null, [[2, 10, 15, 18]]); })), [currentCount, isBanLoad, onScrollToLower, total]); // const check = useCallback(async () => { // if (!immediateCheck || !scrollY || isBanLoad()) return // const scrollParentRect = await boundingClientRect(scrollRef.current!) // if (!scrollParentRect?.height) { // return // } // const placeholderRect = await boundingClientRect(placeholder.current!) // const isReachEdge = // placeholderRect.bottom - scrollParentRect.bottom <= lowerThreshold // if (isReachEdge) { // doLoadMore() // } else { // reachDownRef.current = true // } // }, [immediateCheck, scrollY, isBanLoad, lowerThreshold, doLoadMore]) // useEffect(() => { // // finished || status !== 'normal' || loadingRef.current || errorRef.current // if (reachDownRef.current) return // check() // console.log('loadingRef.current', loadingRef.current, '--change---') // // eslint-disable-next-line react-hooks/exhaustive-deps // }, [reachDownRef.current]) // useEffect(() => { // setTimeout(() => { // check() // }, 500) // // eslint-disable-next-line react-hooks/exhaustive-deps // }, []) // const placeholder = useRef<TaroElement>() var renderFinishedText = (0, _react.useMemo)(function () { if (finished) { var text = renderFinished ? renderFinished : finishedText; if (text) { return /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.View, { className: bem('finished-text'), children: text }); } } return null; }, [finished, renderFinished, finishedText]); var renderLoadingText = (0, _react.useMemo)(function () { if (!finished && scrollY) { return /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.View, { className: bem('loading'), children: renderLoading ? renderLoading : /*#__PURE__*/(0, _jsxRuntime.jsx)(_loading.Loading, { className: bem('loading-icon'), children: loadingText }) }); } return null; }, [finished, loadingText, scrollY, renderLoading]); var clickErrorTextHandle = (0, _react.useCallback)(function () { setError(false); errorRef.current = false; doLoadMore(); // web 很奇怪的问题 }, [doLoadMore]); var renderErrorText = (0, _react.useMemo)(function () { if (isError) { var text = renderError ? renderError : errorText; if (text) { return /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.View, { className: bem('error-text'), onClick: clickErrorTextHandle, children: text }); } } return null; }, [clickErrorTextHandle, isError, errorText, renderError]); // 如果不定高 一直下拉 var ListScrollContent = (0, _react.useMemo)(function () { if (finished && currentCount === 0) { return /*#__PURE__*/(0, _jsxRuntime.jsx)(_empty.Empty, { description: emptyDescription, image: emptyImage }); } if (isError) { return renderErrorText; } if (finished) { return renderFinishedText; } return renderLoadingText; }, [finished, currentCount, isError, renderLoadingText, emptyDescription, emptyImage, renderErrorText, renderFinishedText]); var renderStatusBody = /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.View, { className: bem('head'), style: headStyle, children: renderStatus }); var headElement = process.env.TARO_ENV === 'weapp' ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.CustomWrapper, { children: renderStatusBody }) : renderStatusBody; return /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.ScrollView, _objectSpread(_objectSpread({ ref: scrollRef, lowerThreshold: lowerThreshold, onScroll: onScroll, scrollTop: scrollTop, onScrollToLower: doLoadMore, scrollY: scrollY, className: "".concat(bem(), " ").concat(className || '') }, rest), {}, { children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_components.View, { className: bem('track'), style: trackStyle, onTouchMove: onTouchMove, onTouchEnd: onTouchEnd, onTouchCancel: onTouchEnd, onTouchStart: onTouchStart, children: [headElement, children, ListScrollContent] }) })); } var _default = PowerScrollView; exports.default = _default;