1 | import _extends from 'babel-runtime/helpers/extends';
|
2 | import _objectWithoutProperties from 'babel-runtime/helpers/objectWithoutProperties';
|
3 | import _classCallCheck from 'babel-runtime/helpers/classCallCheck';
|
4 | import _possibleConstructorReturn from 'babel-runtime/helpers/possibleConstructorReturn';
|
5 | import _inherits from 'babel-runtime/helpers/inherits';
|
6 | import React from 'react';
|
7 | import { findDOMNode } from 'react-dom';
|
8 | import PropTypes from 'prop-types';
|
9 | import { polyfill } from 'react-lifecycles-compat';
|
10 | import { dom } from '../util';
|
11 | import VirtualBody from './virtual/body';
|
12 | import { statics } from './util';
|
13 |
|
14 | var noop = function noop() {};
|
15 | var THRESHOLD = 10;
|
16 | export default function virtual(BaseComponent) {
|
17 | var _class, _temp;
|
18 |
|
19 | var VirtualTable = (_temp = _class = function (_React$Component) {
|
20 | _inherits(VirtualTable, _React$Component);
|
21 |
|
22 | function VirtualTable(props, context) {
|
23 | _classCallCheck(this, VirtualTable);
|
24 |
|
25 | var _this = _possibleConstructorReturn(this, _React$Component.call(this, props, context));
|
26 |
|
27 | _this.onScroll = function () {
|
28 |
|
29 | var scrollTop = _this.bodyNode.scrollTop;
|
30 | if (scrollTop === _this.lastScrollTop) {
|
31 | return;
|
32 | }
|
33 | var start = _this.computeScrollToRow(scrollTop);
|
34 | if (!('scrollToRow' in _this.props)) {
|
35 | _this.setState({
|
36 | scrollToRow: start
|
37 | });
|
38 | }
|
39 | _this.props.onBodyScroll(start);
|
40 | _this.lastScrollTop = scrollTop;
|
41 | };
|
42 |
|
43 | _this.getBodyNode = function (node, lockType) {
|
44 | lockType = lockType ? lockType.charAt(0).toUpperCase() + lockType.substr(1) : '';
|
45 | _this['body' + lockType + 'Node'] = node;
|
46 | };
|
47 |
|
48 | _this.getTableInstance = function (type, instance) {
|
49 | type = type ? type.charAt(0).toUpperCase() + type.substr(1) : '';
|
50 | _this['table' + type + 'Inc'] = instance;
|
51 | };
|
52 |
|
53 | var useVirtual = props.useVirtual,
|
54 | dataSource = props.dataSource;
|
55 |
|
56 |
|
57 | var hasVirtualData = useVirtual && dataSource && dataSource.length > 0;
|
58 |
|
59 | _this.state = {
|
60 | rowHeight: _this.props.rowHeight,
|
61 | scrollToRow: _this.props.scrollToRow,
|
62 | height: _this.props.maxBodyHeight,
|
63 | hasVirtualData: hasVirtualData
|
64 | };
|
65 | return _this;
|
66 | }
|
67 |
|
68 | VirtualTable.prototype.getChildContext = function getChildContext() {
|
69 | return {
|
70 | onVirtualScroll: this.onScroll,
|
71 | bodyHeight: this.computeBodyHeight(),
|
72 | innerTop: this.computeInnerTop(),
|
73 | getBodyNode: this.getBodyNode,
|
74 | getTableInstanceForVirtual: this.getTableInstance,
|
75 | rowSelection: this.rowSelection
|
76 | };
|
77 | };
|
78 |
|
79 | VirtualTable.getDerivedStateFromProps = function getDerivedStateFromProps(nextProps, prevState) {
|
80 | var state = {};
|
81 |
|
82 | if ('maxBodyHeight' in nextProps) {
|
83 | if (prevState.height !== nextProps.maxBodyHeight) {
|
84 | state.height = nextProps.maxBodyHeight;
|
85 | }
|
86 | }
|
87 |
|
88 | if ('scrollToRow' in nextProps) {
|
89 | state.scrollToRow = nextProps.scrollToRow;
|
90 | }
|
91 |
|
92 | if (prevState.useVirtual !== nextProps.useVirtual || prevState.dataSource !== nextProps.dataSource) {
|
93 | state.hasVirtualData = nextProps.useVirtual && nextProps.dataSource && nextProps.dataSource.length > 0;
|
94 | }
|
95 |
|
96 | return state;
|
97 | };
|
98 |
|
99 | VirtualTable.prototype.componentDidMount = function componentDidMount() {
|
100 | if (this.state.hasVirtualData && this.bodyNode) {
|
101 | this.lastScrollTop = this.bodyNode.scrollTop;
|
102 | }
|
103 |
|
104 | this.adjustScrollTop();
|
105 | this.adjustSize();
|
106 | this.reComputeSize();
|
107 | };
|
108 |
|
109 | VirtualTable.prototype.componentDidUpdate = function componentDidUpdate() {
|
110 | this.adjustScrollTop();
|
111 | this.adjustSize();
|
112 | this.reComputeSize();
|
113 | };
|
114 |
|
115 | VirtualTable.prototype.reComputeSize = function reComputeSize() {
|
116 | var _state = this.state,
|
117 | rowHeight = _state.rowHeight,
|
118 | hasVirtualData = _state.hasVirtualData;
|
119 |
|
120 | if (typeof rowHeight === 'function' && hasVirtualData) {
|
121 | var row = this.getRowNode();
|
122 | var rowClientHeight = row && row.clientHeight;
|
123 | if (rowClientHeight !== this.state.rowHeight) {
|
124 | this.setState({
|
125 | rowHeight: rowClientHeight
|
126 | });
|
127 | }
|
128 | }
|
129 | };
|
130 |
|
131 | VirtualTable.prototype.computeBodyHeight = function computeBodyHeight() {
|
132 | var rowHeight = this.state.rowHeight;
|
133 | var dataSource = this.props.dataSource;
|
134 |
|
135 | if (typeof rowHeight === 'function') {
|
136 | return 0;
|
137 | }
|
138 | var count = 0;
|
139 | dataSource.forEach(function (item) {
|
140 | if (!item.__hidden) {
|
141 | count += 1;
|
142 | }
|
143 | });
|
144 | return count * rowHeight;
|
145 | };
|
146 |
|
147 | VirtualTable.prototype.computeInnerTop = function computeInnerTop() {
|
148 | var rowHeight = this.state.rowHeight;
|
149 |
|
150 | if (typeof rowHeight === 'function') {
|
151 | return 0;
|
152 | }
|
153 |
|
154 | var start = Math.max(this.start - THRESHOLD, 0);
|
155 |
|
156 | return start * rowHeight;
|
157 | };
|
158 |
|
159 | VirtualTable.prototype.getVisibleRange = function getVisibleRange(ExpectStart) {
|
160 | var _state2 = this.state,
|
161 | height = _state2.height,
|
162 | rowHeight = _state2.rowHeight;
|
163 |
|
164 | var len = this.props.dataSource.length;
|
165 |
|
166 | var end = void 0,
|
167 | visibleCount = 0;
|
168 | var start = 0;
|
169 | if (typeof rowHeight === 'function') {
|
170 |
|
171 | end = 1;
|
172 | } else {
|
173 | visibleCount = parseInt(dom.getPixels(height) / rowHeight, 10);
|
174 |
|
175 | if ('number' === typeof ExpectStart) {
|
176 | start = ExpectStart < len ? ExpectStart : 0;
|
177 | }
|
178 |
|
179 | end = Math.min(+start + 1 + visibleCount + 10, len);
|
180 | }
|
181 | this.end = end;
|
182 | this.visibleCount = visibleCount;
|
183 | return {
|
184 | start: start,
|
185 | end: end
|
186 | };
|
187 | };
|
188 |
|
189 | VirtualTable.prototype.adjustScrollTop = function adjustScrollTop() {
|
190 | if (this.state.hasVirtualData && this.bodyNode) {
|
191 | this.bodyNode.scrollTop = this.lastScrollTop % this.state.rowHeight + this.state.rowHeight * this.state.scrollToRow;
|
192 | }
|
193 | };
|
194 |
|
195 | VirtualTable.prototype.adjustSize = function adjustSize() {
|
196 | if (this.state.hasVirtualData && this.bodyNode) {
|
197 | var body = this.bodyNode;
|
198 | var virtualScrollNode = body.querySelector('div');
|
199 | var clientHeight = body.clientHeight,
|
200 | clientWidth = body.clientWidth;
|
201 |
|
202 |
|
203 | var tableInc = this.tableInc;
|
204 | var tableNode = findDOMNode(tableInc);
|
205 | var prefix = this.props.prefix;
|
206 |
|
207 | var headerNode = tableNode.querySelector('.' + prefix + 'table-header table');
|
208 | var headerClientWidth = headerNode && headerNode.clientWidth;
|
209 |
|
210 | if (clientWidth < headerClientWidth) {
|
211 | dom.setStyle(virtualScrollNode, 'min-width', headerClientWidth);
|
212 | var leftNode = this.bodyLeftNode;
|
213 | var rightNode = this.bodyRightNode;
|
214 | leftNode && dom.setStyle(leftNode, 'max-height', clientHeight);
|
215 | rightNode && dom.setStyle(rightNode, 'max-height', clientHeight);
|
216 | } else {
|
217 | dom.setStyle(virtualScrollNode, 'min-width', 'auto');
|
218 | }
|
219 | }
|
220 | };
|
221 |
|
222 | VirtualTable.prototype.computeScrollToRow = function computeScrollToRow(offset) {
|
223 | var rowHeight = this.state.rowHeight;
|
224 |
|
225 | var start = parseInt(offset / rowHeight);
|
226 | this.start = start;
|
227 | return start;
|
228 | };
|
229 |
|
230 | VirtualTable.prototype.getRowNode = function getRowNode() {
|
231 | try {
|
232 |
|
233 |
|
234 |
|
235 | return findDOMNode(this.tableInc.getRowRef(0));
|
236 | } catch (error) {
|
237 | return null;
|
238 | }
|
239 | };
|
240 |
|
241 | VirtualTable.prototype.render = function render() {
|
242 |
|
243 | var _props = this.props,
|
244 | useVirtual = _props.useVirtual,
|
245 | components = _props.components,
|
246 | dataSource = _props.dataSource,
|
247 | fixedHeader = _props.fixedHeader,
|
248 | rowHeight = _props.rowHeight,
|
249 | scrollToRow = _props.scrollToRow,
|
250 | onBodyScroll = _props.onBodyScroll,
|
251 | others = _objectWithoutProperties(_props, ['useVirtual', 'components', 'dataSource', 'fixedHeader', 'rowHeight', 'scrollToRow', 'onBodyScroll']);
|
252 |
|
253 | var entireDataSource = dataSource;
|
254 | var newDataSource = dataSource;
|
255 |
|
256 | this.rowSelection = this.props.rowSelection;
|
257 | if (this.state.hasVirtualData) {
|
258 | newDataSource = [];
|
259 | components = _extends({}, components);
|
260 |
|
261 | var _getVisibleRange = this.getVisibleRange(this.state.scrollToRow),
|
262 | start = _getVisibleRange.start,
|
263 | end = _getVisibleRange.end;
|
264 |
|
265 | var count = -1;
|
266 | dataSource.forEach(function (current, index, record) {
|
267 | if (!current.__hidden) {
|
268 | count += 1;
|
269 | if (count >= Math.max(start - THRESHOLD, 0) && count < end) {
|
270 | newDataSource.push(current);
|
271 | }
|
272 | }
|
273 | current.__rowIndex = index;
|
274 | });
|
275 |
|
276 | if (!components.Body) {
|
277 | components.Body = VirtualBody;
|
278 | }
|
279 | fixedHeader = true;
|
280 | }
|
281 |
|
282 | return React.createElement(BaseComponent, _extends({}, others, {
|
283 | scrollToRow: scrollToRow,
|
284 | dataSource: newDataSource,
|
285 | entireDataSource: entireDataSource,
|
286 | components: components,
|
287 | fixedHeader: fixedHeader
|
288 | }));
|
289 | };
|
290 |
|
291 | return VirtualTable;
|
292 | }(React.Component), _class.VirtualBody = VirtualBody, _class.propTypes = _extends({
|
293 | |
294 |
|
295 |
|
296 | useVirtual: PropTypes.bool,
|
297 | |
298 |
|
299 |
|
300 | rowHeight: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),
|
301 | maxBodyHeight: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
|
302 | primaryKey: PropTypes.oneOfType([PropTypes.symbol, PropTypes.string]),
|
303 | dataSource: PropTypes.array,
|
304 | |
305 |
|
306 |
|
307 | onBodyScroll: PropTypes.func
|
308 | }, BaseComponent.propTypes), _class.defaultProps = _extends({}, BaseComponent.defaultProps, {
|
309 | primaryKey: 'id',
|
310 | rowHeight: noop,
|
311 | maxBodyHeight: 200,
|
312 | components: {},
|
313 | prefix: 'next-',
|
314 | onBodyScroll: noop
|
315 | }), _class.childContextTypes = {
|
316 | onVirtualScroll: PropTypes.func,
|
317 | bodyHeight: PropTypes.number,
|
318 | innerTop: PropTypes.number,
|
319 | getBodyNode: PropTypes.func,
|
320 | getTableInstanceForVirtual: PropTypes.func,
|
321 | rowSelection: PropTypes.object
|
322 | }, _temp);
|
323 | VirtualTable.displayName = 'VirtualTable';
|
324 |
|
325 | statics(VirtualTable, BaseComponent);
|
326 | return polyfill(VirtualTable);
|
327 | } |
\ | No newline at end of file |