UNPKG

@jdcfe/yep-react

Version:

一套移动端的React组件库

397 lines (334 loc) 16.5 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _typeof = require("@babel/runtime/helpers/typeof"); Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "ScrollDirection", { enumerable: true, get: function get() { return _constants.DIRECTION; } }); exports.default = void 0; var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits")); var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn")); var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf")); var React = _interopRequireWildcard(require("react")); var PropTypes = _interopRequireWildcard(require("prop-types")); var _SizeAndPositionManager = _interopRequireDefault(require("./SizeAndPositionManager")); var _constants = require("./constants"); 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 _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0, _getPrototypeOf2.default)(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2.default)(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2.default)(this, result); }; } function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } var __rest = void 0 && (void 0).__rest || function (s, e) { var t = {}; for (var p in s) { if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; } if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; var STYLE_WRAPPER = { overflow: 'auto', willChange: 'transform', WebkitOverflowScrolling: 'touch' }; var STYLE_INNER = { position: 'relative', width: '100%', minHeight: '100%' }; var STYLE_ITEM = { position: 'absolute', top: 0, left: 0, width: '100%' }; var STYLE_STICKY_ITEM = Object.assign(Object.assign({}, STYLE_ITEM), { position: 'sticky' }); var VirtualList = /*#__PURE__*/function (_React$PureComponent) { (0, _inherits2.default)(VirtualList, _React$PureComponent); var _super = _createSuper(VirtualList); function VirtualList() { var _this; (0, _classCallCheck2.default)(this, VirtualList); _this = _super.apply(this, arguments); _this.itemSizeGetter = function (itemSize) { return function (index) { return _this.getSize(index, itemSize); }; }; _this.sizeAndPositionManager = new _SizeAndPositionManager.default({ itemCount: _this.props.itemCount, itemSizeGetter: _this.itemSizeGetter(_this.props.itemSize), estimatedItemSize: _this.getEstimatedItemSize() }); _this.state = { offset: _this.props.scrollOffset || _this.props.scrollToIndex != null && _this.getOffsetForIndex(_this.props.scrollToIndex) || 0, scrollChangeReason: _constants.SCROLL_CHANGE_REASON.REQUESTED }; _this.styleCache = {}; _this.getRef = function (node) { _this.rootNode = node; }; _this.handleScroll = function (event) { var onScroll = _this.props.onScroll; var offset = _this.getNodeOffset(); if (offset < 0 || _this.state.offset === offset || event.target !== _this.rootNode) { return; } _this.setState({ offset: offset, scrollChangeReason: _constants.SCROLL_CHANGE_REASON.OBSERVED }); if (typeof onScroll === 'function') { onScroll(offset, event); } }; return _this; } (0, _createClass2.default)(VirtualList, [{ key: "componentDidMount", value: function componentDidMount() { var _this$props = this.props, scrollOffset = _this$props.scrollOffset, scrollToIndex = _this$props.scrollToIndex; this.rootNode.addEventListener('scroll', this.handleScroll, { passive: true }); if (scrollOffset != null) { this.scrollTo(scrollOffset); } else if (scrollToIndex != null) { this.scrollTo(this.getOffsetForIndex(scrollToIndex)); } } }, { key: "componentWillReceiveProps", value: function componentWillReceiveProps(nextProps) { var _this$props2 = this.props, estimatedItemSize = _this$props2.estimatedItemSize, itemCount = _this$props2.itemCount, itemSize = _this$props2.itemSize, scrollOffset = _this$props2.scrollOffset, scrollToAlignment = _this$props2.scrollToAlignment, scrollToIndex = _this$props2.scrollToIndex; var scrollPropsHaveChanged = nextProps.scrollToIndex !== scrollToIndex || nextProps.scrollToAlignment !== scrollToAlignment; var itemPropsHaveChanged = nextProps.itemCount !== itemCount || nextProps.itemSize !== itemSize || nextProps.estimatedItemSize !== estimatedItemSize; if (nextProps.itemSize !== itemSize) { this.sizeAndPositionManager.updateConfig({ itemSizeGetter: this.itemSizeGetter(nextProps.itemSize) }); } if (nextProps.itemCount !== itemCount || nextProps.estimatedItemSize !== estimatedItemSize) { this.sizeAndPositionManager.updateConfig({ itemCount: nextProps.itemCount, estimatedItemSize: this.getEstimatedItemSize(nextProps) }); } if (itemPropsHaveChanged) { this.recomputeSizes(); } if (nextProps.scrollOffset !== scrollOffset) { this.setState({ offset: nextProps.scrollOffset || 0, scrollChangeReason: _constants.SCROLL_CHANGE_REASON.REQUESTED }); } else if (typeof nextProps.scrollToIndex === 'number' && (scrollPropsHaveChanged || itemPropsHaveChanged)) { this.setState({ offset: this.getOffsetForIndex(nextProps.scrollToIndex, nextProps.scrollToAlignment, nextProps.itemCount), scrollChangeReason: _constants.SCROLL_CHANGE_REASON.REQUESTED }); } } }, { key: "componentDidUpdate", value: function componentDidUpdate(_, prevState) { var _this$state = this.state, offset = _this$state.offset, scrollChangeReason = _this$state.scrollChangeReason; if (prevState.offset !== offset && scrollChangeReason === _constants.SCROLL_CHANGE_REASON.REQUESTED) { this.scrollTo(offset); } } }, { key: "componentWillUnmount", value: function componentWillUnmount() { this.rootNode.removeEventListener('scroll', this.handleScroll); } }, { key: "scrollTo", value: function scrollTo(value) { var _this$props$scrollDir = this.props.scrollDirection, scrollDirection = _this$props$scrollDir === void 0 ? _constants.DIRECTION.VERTICAL : _this$props$scrollDir; // @ts-ignore this.rootNode[_constants.scrollProp[scrollDirection]] = value; } }, { key: "getOffsetForIndex", value: function getOffsetForIndex(index) { var scrollToAlignment = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.props.scrollToAlignment; var itemCount = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this.props.itemCount; var _this$props$scrollDir2 = this.props.scrollDirection, scrollDirection = _this$props$scrollDir2 === void 0 ? _constants.DIRECTION.VERTICAL : _this$props$scrollDir2; if (index < 0 || index >= itemCount) { index = 0; } return this.sizeAndPositionManager.getUpdatedOffsetForIndex({ align: scrollToAlignment, // @ts-ignore containerSize: this.props[_constants.sizeProp[scrollDirection]], currentOffset: this.state && this.state.offset || 0, targetIndex: index }); } }, { key: "recomputeSizes", value: function recomputeSizes() { var startIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; this.styleCache = {}; this.sizeAndPositionManager.resetItem(startIndex); } }, { key: "render", value: function render() { var _this2 = this; var _a = this.props, estimatedItemSize = _a.estimatedItemSize, height = _a.height, _a$overscanCount = _a.overscanCount, overscanCount = _a$overscanCount === void 0 ? 3 : _a$overscanCount, renderItem = _a.renderItem, itemCount = _a.itemCount, itemSize = _a.itemSize, onItemsRendered = _a.onItemsRendered, onScroll = _a.onScroll, _a$scrollDirection = _a.scrollDirection, scrollDirection = _a$scrollDirection === void 0 ? _constants.DIRECTION.VERTICAL : _a$scrollDirection, scrollOffset = _a.scrollOffset, scrollToIndex = _a.scrollToIndex, scrollToAlignment = _a.scrollToAlignment, stickyIndices = _a.stickyIndices, style = _a.style, width = _a.width, props = __rest(_a, ["estimatedItemSize", "height", "overscanCount", "renderItem", "itemCount", "itemSize", "onItemsRendered", "onScroll", "scrollDirection", "scrollOffset", "scrollToIndex", "scrollToAlignment", "stickyIndices", "style", "width"]); var offset = this.state.offset; var _this$sizeAndPosition = this.sizeAndPositionManager.getVisibleRange({ // @ts-ignore containerSize: this.props[_constants.sizeProp[scrollDirection]] || 0, offset: offset, overscanCount: overscanCount }), start = _this$sizeAndPosition.start, stop = _this$sizeAndPosition.stop; var items = []; var wrapperStyle = Object.assign(Object.assign(Object.assign({}, STYLE_WRAPPER), style), { height: height, width: width }); var innerStyle = Object.assign(Object.assign({}, STYLE_INNER), (0, _defineProperty2.default)({}, _constants.sizeProp[scrollDirection], this.sizeAndPositionManager.getTotalSize())); if (stickyIndices != null && stickyIndices.length !== 0) { stickyIndices.forEach(function (index) { return items.push(renderItem({ index: index, style: _this2.getStyle(index, true) })); }); if (scrollDirection === _constants.DIRECTION.HORIZONTAL) { innerStyle.display = 'flex'; } } if (typeof start !== 'undefined' && typeof stop !== 'undefined') { for (var index = start; index <= stop; index++) { if (stickyIndices != null && stickyIndices.includes(index)) { continue; } items.push(renderItem({ index: index, style: this.getStyle(index, false) })); } if (typeof onItemsRendered === 'function') { onItemsRendered({ startIndex: start, stopIndex: stop }); } } return /*#__PURE__*/React.createElement("div", (0, _extends2.default)({ ref: this.getRef }, props, { style: wrapperStyle }), /*#__PURE__*/React.createElement("div", { style: innerStyle }, items)); } }, { key: "getNodeOffset", value: function getNodeOffset() { var _this$props$scrollDir3 = this.props.scrollDirection, scrollDirection = _this$props$scrollDir3 === void 0 ? _constants.DIRECTION.VERTICAL : _this$props$scrollDir3; // @ts-ignore return this.rootNode[_constants.scrollProp[scrollDirection]]; } }, { key: "getEstimatedItemSize", value: function getEstimatedItemSize() { var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.props; return props.estimatedItemSize || typeof props.itemSize === 'number' && props.itemSize || 50; } }, { key: "getSize", value: function getSize(index, itemSize) { if (typeof itemSize === 'function') { return itemSize(index); } return Array.isArray(itemSize) ? itemSize[index] : itemSize; } }, { key: "getStyle", value: function getStyle(index, sticky) { var _Object$assign2, _Object$assign3; var style = this.styleCache[index]; if (style) { return style; } var _this$props$scrollDir4 = this.props.scrollDirection, scrollDirection = _this$props$scrollDir4 === void 0 ? _constants.DIRECTION.VERTICAL : _this$props$scrollDir4; var _this$sizeAndPosition2 = this.sizeAndPositionManager.getSizeAndPositionForIndex(index), size = _this$sizeAndPosition2.size, offset = _this$sizeAndPosition2.offset; return this.styleCache[index] = sticky ? Object.assign(Object.assign({}, STYLE_STICKY_ITEM), (_Object$assign2 = {}, (0, _defineProperty2.default)(_Object$assign2, _constants.sizeProp[scrollDirection], size), (0, _defineProperty2.default)(_Object$assign2, _constants.marginProp[scrollDirection], offset), (0, _defineProperty2.default)(_Object$assign2, _constants.oppositeMarginProp[scrollDirection], -(offset + size)), (0, _defineProperty2.default)(_Object$assign2, "zIndex", 1), _Object$assign2)) : Object.assign(Object.assign({}, STYLE_ITEM), (_Object$assign3 = {}, (0, _defineProperty2.default)(_Object$assign3, _constants.sizeProp[scrollDirection], size), (0, _defineProperty2.default)(_Object$assign3, _constants.positionProp[scrollDirection], offset), _Object$assign3)); } }]); return VirtualList; }(React.PureComponent); exports.default = VirtualList; VirtualList.defaultProps = { overscanCount: 3, scrollDirection: _constants.DIRECTION.VERTICAL, width: '100%' }; VirtualList.propTypes = { estimatedItemSize: PropTypes.number, height: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, itemCount: PropTypes.number.isRequired, itemSize: PropTypes.oneOfType([PropTypes.number, PropTypes.array, PropTypes.func]).isRequired, onScroll: PropTypes.func, onItemsRendered: PropTypes.func, overscanCount: PropTypes.number, renderItem: PropTypes.func.isRequired, scrollOffset: PropTypes.number, scrollToIndex: PropTypes.number, scrollToAlignment: PropTypes.oneOf([_constants.ALIGNMENT.AUTO, _constants.ALIGNMENT.START, _constants.ALIGNMENT.CENTER, _constants.ALIGNMENT.END]), scrollDirection: PropTypes.oneOf([_constants.DIRECTION.HORIZONTAL, _constants.DIRECTION.VERTICAL]), stickyIndices: PropTypes.arrayOf(PropTypes.number), style: PropTypes.object, width: PropTypes.oneOfType([PropTypes.number, PropTypes.string]) };