UNPKG

10.3 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6
7var _isEqual2 = require('lodash/isEqual');
8
9var _isEqual3 = _interopRequireDefault(_isEqual2);
10
11var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
12
13var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
14
15exports.heightPropCheck = heightPropCheck;
16
17var _react = require('react');
18
19var _react2 = _interopRequireDefault(_react);
20
21var _reactabularSticky = require('reactabular-sticky');
22
23var _reactabularTable = require('reactabular-table');
24
25var _types = require('./types');
26
27var _calculateAverageHeight = require('./calculate-average-height');
28
29var _calculateAverageHeight2 = _interopRequireDefault(_calculateAverageHeight);
30
31var _calculateRows = require('./calculate-rows');
32
33var _calculateRows2 = _interopRequireDefault(_calculateRows);
34
35function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
36
37function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }
38
39function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
40
41function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
42
43function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
44
45var VirtualizedBody = function (_React$Component) {
46 _inherits(VirtualizedBody, _React$Component);
47
48 function VirtualizedBody(props) {
49 _classCallCheck(this, VirtualizedBody);
50
51 var _this = _possibleConstructorReturn(this, (VirtualizedBody.__proto__ || Object.getPrototypeOf(VirtualizedBody)).call(this, props));
52
53 _this.measuredRows = {}; // row key -> measurement
54 _this.ref = null;
55 _this.scrollTop = 0;
56 _this.initialMeasurement = true;
57
58 _this.state = getInitialState();
59
60 _this.checkMeasurements = _this.checkMeasurements.bind(_this);
61 return _this;
62 }
63
64 _createClass(VirtualizedBody, [{
65 key: 'componentDidMount',
66 value: function componentDidMount() {
67 this.checkMeasurements();
68 }
69 }, {
70 key: 'componentDidUpdate',
71 value: function componentDidUpdate() {
72 this.checkMeasurements();
73 }
74 }, {
75 key: 'getHeight',
76 value: function getHeight(optionalProps) {
77 // If `optionalProps` is defined, we use `optionalProps` instead of `this.props`.
78 var props = optionalProps || this.props;
79 // If `props.height` is not defined, we use `props.style.maxHeight` instead.
80 return props.height || props.style.maxHeight;
81 }
82 }, {
83 key: 'componentWillReceiveProps',
84 value: function componentWillReceiveProps(nextProps) {
85 if (!(0, _isEqual3.default)(this.props.rows, nextProps.rows) || this.getHeight() !== this.getHeight(nextProps)) {
86 if (process.env.NODE_ENV !== 'production' && window.LOG_VIRTUALIZED) {
87 console.log('invalidating measurements'); // eslint-disable-line no-console
88 }
89
90 var rows = (0, _calculateRows2.default)({
91 scrollTop: this.scrollTop,
92 measuredRows: this.measuredRows,
93 height: this.getHeight(nextProps),
94 rowKey: nextProps.rowKey,
95 rows: nextProps.rows
96 });
97
98 if (!rows) {
99 return;
100 }
101
102 this.setState(rows);
103 }
104 }
105 }, {
106 key: 'getChildContext',
107 value: function getChildContext() {
108 var _this2 = this;
109
110 var _state = this.state,
111 startHeight = _state.startHeight,
112 endHeight = _state.endHeight,
113 showExtraRow = _state.showExtraRow;
114
115
116 return {
117 startHeight: startHeight,
118 endHeight: endHeight,
119 showExtraRow: showExtraRow,
120 updateHeight: function updateHeight(rowKey, height) {
121 _this2.measuredRows[rowKey] = height;
122 },
123 // Capture height data only during the initial measurement
124 initialMeasurement: this.initialMeasurement
125 };
126 }
127 }, {
128 key: 'render',
129 value: function render() {
130 var _this3 = this;
131
132 var _props = this.props,
133 _onRow = _props.onRow,
134 rows = _props.rows,
135 _onScroll = _props.onScroll,
136 props = _objectWithoutProperties(_props, ['onRow', 'rows', 'onScroll']);
137
138 var _state2 = this.state,
139 startIndex = _state2.startIndex,
140 amountOfRowsToRender = _state2.amountOfRowsToRender;
141
142 // Attach information about measuring status. This way we can implement
143 // proper shouldComponentUpdate
144
145 var rowsToRender = rows.slice(startIndex, startIndex + amountOfRowsToRender).map(function (rowData, rowIndex) {
146 return _extends({}, rowData, {
147 _measured: !!_this3.measuredRows[(0, _reactabularTable.resolveRowKey)({
148 rowData: rowData,
149 rowIndex: rowIndex,
150 rowKey: _this3.props.rowKey
151 })]
152 });
153 });
154
155 if (process.env.NODE_ENV !== 'production' && window.LOG_VIRTUALIZED) {
156 console.log( // eslint-disable-line no-console
157 'rendering', rowsToRender.length, '/', rows.length, 'rows to render', rowsToRender, 'start index', startIndex, 'amount of rows to render', amountOfRowsToRender);
158 }
159
160 return _react2.default.createElement(_reactabularSticky.Body, _extends({}, props, {
161 onRow: function onRow(row, extra) {
162 var rowProps = _onRow ? _onRow(row, extra) : {};
163
164 return _extends({
165 // Pass index so that row heights can be tracked properly
166 'data-rowkey': extra.rowKey
167 }, rowProps);
168 },
169 rows: rowsToRender,
170 ref: function ref(body) {
171 _this3.ref = body && body.getRef().getRef();
172 },
173 onScroll: function onScroll(e) {
174 _onScroll && _onScroll(e);
175
176 var scrollTop = e.target.scrollTop;
177
178 // Y didn't change, bail to avoid rendering rows
179
180 if (_this3.scrollTop === scrollTop) {
181 return;
182 }
183
184 _this3.scrollTop = scrollTop;
185
186 _this3.setState((0, _calculateRows2.default)({
187 scrollTop: scrollTop,
188 measuredRows: _this3.measuredRows,
189 height: _this3.getHeight(),
190 rowKey: _this3.props.rowKey,
191 rows: _this3.props.rows
192 }));
193 }
194 }));
195 }
196 }, {
197 key: 'getRef',
198 value: function getRef() {
199 var _this4 = this;
200
201 var ref = this.ref;
202
203 ref.scrollTo = function (index) {
204 var startIndex = parseInt(index, 10);
205
206 if (startIndex >= 0) {
207 var startHeight = (0, _calculateAverageHeight2.default)({
208 measuredRows: _this4.measuredRows,
209 rows: _this4.props.rows,
210 rowKey: _this4.props.rowKey
211 }) * startIndex;
212
213 _this4.scrollTop = startHeight;
214 _this4.ref.scrollTop = startHeight;
215 }
216 };
217
218 return ref;
219 }
220 }, {
221 key: 'checkMeasurements',
222 value: function checkMeasurements() {
223 var _this5 = this;
224
225 // If there are no valid measurements, calculate some after waiting a while.
226 // Without this styling solutions like Radium won't work as you might expect
227 // given they can take a while to set container height.
228 if (this.initialMeasurement) {
229 setTimeout(function () {
230 var rows = (0, _calculateRows2.default)({
231 scrollTop: _this5.scrollTop,
232 measuredRows: _this5.measuredRows,
233 height: _this5.getHeight(),
234 rowKey: _this5.props.rowKey,
235 rows: _this5.props.rows
236 });
237
238 if (!rows) {
239 // Refresh the rows to trigger measurement.
240 _this5.forceUpdate();
241
242 return;
243 }
244
245 _this5.setState(rows, function () {
246 _this5.initialMeasurement = false;
247 });
248 }, 100);
249 }
250 }
251 }]);
252
253 return VirtualizedBody;
254}(_react2.default.Component);
255
256VirtualizedBody.defaultProps = _reactabularSticky.Body.defaultProps;
257process.env.NODE_ENV !== "production" ? VirtualizedBody.propTypes = _extends({}, _reactabularSticky.Body.propTypes, {
258 height: heightPropCheck
259}) : void 0;
260VirtualizedBody.childContextTypes = _types.bodyChildContextTypes;
261
262/* eslint-disable consistent-return */
263function heightPropCheck(props, propName, componentName) {
264 if (typeof props[propName] !== 'number' && (!props.style || typeof props.style.maxHeight !== 'number')) {
265 return new Error('height or style.maxHeight of type \'number\' is marked as required in ' + componentName);
266 }
267}
268/* eslint-enable consistent-return */
269
270function getInitialState() {
271 return {
272 amountOfRowsToRender: 3, // First few rows for initial measurement
273 startIndex: 0, // Index where to start rendering
274
275 // Heights for extra rows to mimic scrolling
276 startHeight: 0,
277 endHeight: 0,
278
279 // Show extra row (even/odd issue)
280 showExtraRow: false
281 };
282}
283
284exports.default = VirtualizedBody;
\No newline at end of file