You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

382 lines
14 KiB

'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _extends2 = require('babel-runtime/helpers/extends');
var _extends3 = _interopRequireDefault(_extends2);
var _objectWithoutProperties2 = require('babel-runtime/helpers/objectWithoutProperties');
var _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2);
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
var _createClass2 = require('babel-runtime/helpers/createClass');
var _createClass3 = _interopRequireDefault(_createClass2);
var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
var _inherits2 = require('babel-runtime/helpers/inherits');
var _inherits3 = _interopRequireDefault(_inherits2);
var _react = require('react');
var _react2 = _interopRequireDefault(_react);
var _propTypes = require('prop-types');
var _propTypes2 = _interopRequireDefault(_propTypes);
var _reactDom = require('react-dom');
var _reactDom2 = _interopRequireDefault(_reactDom);
var _ListViewDataSource = require('./ListViewDataSource');
var _ListViewDataSource2 = _interopRequireDefault(_ListViewDataSource);
var _ScrollView = require('./ScrollView');
var _ScrollView2 = _interopRequireDefault(_ScrollView);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
var DEFAULT_PAGE_SIZE = 1; /* eslint no-unused-vars: 0, react/no-multi-comp: 0
react/prop-types: 0, react/sort-comp: 0, no-unused-expressions: 0 */
var DEFAULT_INITIAL_ROWS = 10;
var DEFAULT_SCROLL_RENDER_AHEAD = 1000;
var DEFAULT_END_REACHED_THRESHOLD = 1000;
var DEFAULT_SCROLL_CALLBACK_THROTTLE = 50;
// const SCROLLVIEW_REF = 'ListViewRef';
var StaticRenderer = function (_React$Component) {
(0, _inherits3['default'])(StaticRenderer, _React$Component);
function StaticRenderer() {
(0, _classCallCheck3['default'])(this, StaticRenderer);
return (0, _possibleConstructorReturn3['default'])(this, (StaticRenderer.__proto__ || Object.getPrototypeOf(StaticRenderer)).apply(this, arguments));
}
(0, _createClass3['default'])(StaticRenderer, [{
key: 'shouldComponentUpdate',
value: function shouldComponentUpdate(nextProps) {
return nextProps.shouldUpdate;
}
}, {
key: 'render',
value: function render() {
return this.props.render();
}
}]);
return StaticRenderer;
}(_react2['default'].Component);
// https://github.com/facebook/react-native/blob/0.26-stable/Libraries/CustomComponents/ListView/ListView.js
var ListView = function (_React$Component2) {
(0, _inherits3['default'])(ListView, _React$Component2);
function ListView() {
var _ref;
var _temp, _this2, _ret;
(0, _classCallCheck3['default'])(this, ListView);
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
return _ret = (_temp = (_this2 = (0, _possibleConstructorReturn3['default'])(this, (_ref = ListView.__proto__ || Object.getPrototypeOf(ListView)).call.apply(_ref, [this].concat(args))), _this2), _initialiseProps.call(_this2), _temp), (0, _possibleConstructorReturn3['default'])(_this2, _ret);
}
/**
* Exports some data, e.g. for perf investigations or analytics.
*/
(0, _createClass3['default'])(ListView, [{
key: 'componentWillMount',
value: function componentWillMount() {
// this data should never trigger a render pass, so don't put in state
this.scrollProperties = {
visibleLength: null,
contentLength: null,
offset: 0
};
this._childFrames = [];
this._visibleRows = {};
this._prevRenderedRowsCount = 0;
this._sentEndForContentLength = null;
}
}, {
key: 'componentWillReceiveProps',
value: function componentWillReceiveProps(nextProps) {
var _this3 = this;
if (this.props.dataSource !== nextProps.dataSource || this.props.initialListSize !== nextProps.initialListSize) {
this.setState(function (state, props) {
_this3._prevRenderedRowsCount = 0;
return {
curRenderedRowsCount: Math.min(Math.max(state.curRenderedRowsCount, nextProps.initialListSize // for preact
), nextProps.dataSource.getRowCount() // for preact
)
};
}, function () {
return _this3._renderMoreRowsIfNeeded();
});
}
}
}, {
key: 'render',
value: function render() {
var _this4 = this;
var dataSource = this.props.dataSource;
var allRowIDs = dataSource.rowIdentities;
var bodyComponents = [];
var rowCount = 0;
for (var sectionIdx = 0; sectionIdx < allRowIDs.length; sectionIdx++) {
var sectionID = dataSource.sectionIdentities[sectionIdx];
var rowIDs = allRowIDs[sectionIdx];
if (rowIDs.length === 0) {
continue;
}
var renderSectionHeader = void 0;
if (this.props.renderSectionHeader) {
var shouldUpdateHeader = rowCount >= this._prevRenderedRowsCount && dataSource.sectionHeaderShouldUpdate(sectionIdx);
renderSectionHeader = _react2['default'].createElement(StaticRenderer, {
key: 's_' + sectionID,
shouldUpdate: !!shouldUpdateHeader,
render: this.props.renderSectionHeader.bind(null, dataSource.getSectionHeaderData(sectionIdx), sectionID)
});
}
var sectionBody = [];
for (var rowIdx = 0; rowIdx < rowIDs.length; rowIdx++) {
var rowID = rowIDs[rowIdx];
var comboID = sectionID + '_' + rowID;
var shouldUpdateRow = rowCount >= this._prevRenderedRowsCount && dataSource.rowShouldUpdate(sectionIdx, rowIdx);
var row = _react2['default'].createElement(StaticRenderer, {
key: 'r_' + comboID,
shouldUpdate: !!shouldUpdateRow,
render: this.props.renderRow.bind(null, dataSource.getRowData(sectionIdx, rowIdx), sectionID, rowID, this.onRowHighlighted)
});
sectionBody.push(row);
if (this.props.renderSeparator && (rowIdx !== rowIDs.length - 1 || sectionIdx === allRowIDs.length - 1)) {
var adjacentRowHighlighted = this.state.highlightedRow.sectionID === sectionID && (this.state.highlightedRow.rowID === rowID || this.state.highlightedRow.rowID === rowIDs[rowIdx + 1]);
var separator = this.props.renderSeparator(sectionID, rowID, adjacentRowHighlighted);
if (separator) {
sectionBody.push(separator);
}
}
if (++rowCount === this.state.curRenderedRowsCount) {
break;
}
}
var rowsAndSeparators = _react2['default'].cloneElement(this.props.renderSectionBodyWrapper(sectionID), {
className: this.props.sectionBodyClassName
}, sectionBody);
if (this.props.renderSectionWrapper) {
bodyComponents.push(_react2['default'].cloneElement(this.props.renderSectionWrapper(sectionID), {}, renderSectionHeader, rowsAndSeparators));
} else {
bodyComponents.push(renderSectionHeader);
bodyComponents.push(rowsAndSeparators);
}
if (rowCount >= this.state.curRenderedRowsCount) {
break;
}
}
var _props = this.props,
renderScrollComponent = _props.renderScrollComponent,
props = (0, _objectWithoutProperties3['default'])(_props, ['renderScrollComponent']);
return _react2['default'].cloneElement(renderScrollComponent((0, _extends3['default'])({}, props, { onScroll: this._onScroll })), {
ref: function ref(el) {
return _this4.ListViewRef = el;
},
onContentSizeChange: this._onContentSizeChange,
onLayout: this._onLayout
}, this.props.renderHeader ? this.props.renderHeader() : null, _react2['default'].cloneElement(props.renderBodyComponent(), {}, bodyComponents), this.props.renderFooter ? this.props.renderFooter() : null, props.children);
}
}]);
return ListView;
}(_react2['default'].Component);
ListView.DataSource = _ListViewDataSource2['default'];
ListView.propTypes = (0, _extends3['default'])({}, _ScrollView2['default'].propTypes, {
dataSource: _propTypes2['default'].instanceOf(_ListViewDataSource2['default']).isRequired,
renderSeparator: _propTypes2['default'].func,
renderRow: _propTypes2['default'].func.isRequired,
initialListSize: _propTypes2['default'].number,
onEndReached: _propTypes2['default'].func,
onEndReachedThreshold: _propTypes2['default'].number,
pageSize: _propTypes2['default'].number,
renderFooter: _propTypes2['default'].func,
renderHeader: _propTypes2['default'].func,
renderSectionHeader: _propTypes2['default'].func,
renderScrollComponent: _propTypes2['default'].func,
scrollRenderAheadDistance: _propTypes2['default'].number,
onChangeVisibleRows: _propTypes2['default'].func,
scrollEventThrottle: _propTypes2['default'].number,
// another added
renderBodyComponent: _propTypes2['default'].func,
renderSectionWrapper: _propTypes2['default'].func,
renderSectionBodyWrapper: _propTypes2['default'].func,
sectionBodyClassName: _propTypes2['default'].string,
listViewPrefixCls: _propTypes2['default'].string,
useBodyScroll: _propTypes2['default'].bool
});
ListView.defaultProps = {
initialListSize: DEFAULT_INITIAL_ROWS,
pageSize: DEFAULT_PAGE_SIZE,
renderScrollComponent: function renderScrollComponent(props) {
return _react2['default'].createElement(_ScrollView2['default'], props);
},
renderBodyComponent: function renderBodyComponent() {
return _react2['default'].createElement('div', null);
},
renderSectionBodyWrapper: function renderSectionBodyWrapper(sectionID) {
return _react2['default'].createElement('div', { key: sectionID });
},
sectionBodyClassName: 'list-view-section-body',
listViewPrefixCls: 'rmc-list-view',
scrollRenderAheadDistance: DEFAULT_SCROLL_RENDER_AHEAD,
onEndReachedThreshold: DEFAULT_END_REACHED_THRESHOLD,
scrollEventThrottle: DEFAULT_SCROLL_CALLBACK_THROTTLE,
scrollerOptions: {}
};
var _initialiseProps = function _initialiseProps() {
var _this5 = this;
this.state = {
curRenderedRowsCount: this.props.initialListSize,
highlightedRow: {} };
this.getMetrics = function () {
return {
contentLength: _this5.scrollProperties.contentLength,
totalRows: _this5.props.dataSource.getRowCount(),
renderedRows: _this5.state.curRenderedRowsCount,
visibleRows: Object.keys(_this5._visibleRows).length
};
};
this.getInnerViewNode = function () {
return _this5.ListViewRef.getInnerViewNode();
};
this.scrollTo = function () {
var _ListViewRef;
_this5.ListViewRef && _this5.ListViewRef.scrollTo && (_ListViewRef = _this5.ListViewRef).scrollTo.apply(_ListViewRef, arguments);
};
this.onRowHighlighted = function (sectionID, rowID) {
_this5.setState({ highlightedRow: { sectionID: sectionID, rowID: rowID } });
};
this._onContentSizeChange = function (width, height) {
var contentLength = !_this5.props.horizontal ? height : width;
if (contentLength !== _this5.scrollProperties.contentLength) {
_this5.scrollProperties.contentLength = contentLength;
_this5._renderMoreRowsIfNeeded();
}
_this5.props.onContentSizeChange && _this5.props.onContentSizeChange(width, height);
};
this._onLayout = function (event) {
var _event$nativeEvent$la = event.nativeEvent.layout,
width = _event$nativeEvent$la.width,
height = _event$nativeEvent$la.height;
var visibleLength = !_this5.props.horizontal ? height : width;
if (visibleLength !== _this5.scrollProperties.visibleLength) {
_this5.scrollProperties.visibleLength = visibleLength;
_this5._renderMoreRowsIfNeeded();
}
_this5.props.onLayout && _this5.props.onLayout(event);
};
this._maybeCallOnEndReached = function (event) {
// console.log(this.scrollProperties, this._getDistanceFromEnd(this.scrollProperties));
if (_this5.props.onEndReached && _this5.scrollProperties.contentLength !== _this5._sentEndForContentLength && _this5._getDistanceFromEnd(_this5.scrollProperties) < _this5.props.onEndReachedThreshold && _this5.state.curRenderedRowsCount === _this5.props.dataSource.getRowCount()) {
_this5._sentEndForContentLength = _this5.scrollProperties.contentLength;
_this5.props.onEndReached(event);
return true;
}
return false;
};
this._renderMoreRowsIfNeeded = function () {
if (_this5.scrollProperties.contentLength === null || _this5.scrollProperties.visibleLength === null || _this5.state.curRenderedRowsCount === _this5.props.dataSource.getRowCount()) {
_this5._maybeCallOnEndReached();
return;
}
var distanceFromEnd = _this5._getDistanceFromEnd(_this5.scrollProperties);
// console.log(distanceFromEnd, this.props.scrollRenderAheadDistance);
if (distanceFromEnd < _this5.props.scrollRenderAheadDistance) {
_this5._pageInNewRows();
}
};
this._pageInNewRows = function () {
_this5.setState(function (state, props) {
var rowsToRender = Math.min(state.curRenderedRowsCount + props.pageSize, props.dataSource.getRowCount());
_this5._prevRenderedRowsCount = state.curRenderedRowsCount;
return {
curRenderedRowsCount: rowsToRender
};
}, function () {
_this5._prevRenderedRowsCount = _this5.state.curRenderedRowsCount;
});
};
this._getDistanceFromEnd = function (scrollProperties) {
return scrollProperties.contentLength - scrollProperties.visibleLength - scrollProperties.offset;
};
this._onScroll = function (e, metrics) {
// when the ListView is destroyed,
// but also will trigger scroll event after `scrollEventThrottle`
if (!_this5.ListViewRef) {
return;
}
_this5.scrollProperties = metrics;
if (!_this5._maybeCallOnEndReached(e)) {
_this5._renderMoreRowsIfNeeded();
}
if (_this5.props.onEndReached && _this5._getDistanceFromEnd(_this5.scrollProperties) > _this5.props.onEndReachedThreshold) {
// Scrolled out of the end zone, so it should be able to trigger again.
_this5._sentEndForContentLength = null;
}
_this5.props.onScroll && _this5.props.onScroll(e);
};
};
exports['default'] = ListView;
module.exports = exports['default'];