@jdcfe/yep-react
Version:
一套移动端的React组件库
397 lines (334 loc) • 16.5 kB
JavaScript
"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])
};