UNPKG

32.7 kBJavaScriptView Raw
1"use strict";
2
3function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
4
5Object.defineProperty(exports, "__esModule", {
6 value: true
7});
8exports.Unstable_DataTable = Unstable_DataTable;
9
10var React = _interopRequireWildcard(require("react"));
11
12var _reactWindow = require("react-window");
13
14var _reactVirtualizedAutoSizer = _interopRequireDefault(require("react-virtualized-auto-sizer"));
15
16var _index = require("../button/index.js");
17
18var _index2 = require("../styles/index.js");
19
20var _index3 = require("../tooltip/index.js");
21
22var _constants = require("./constants.js");
23
24var _headerCell = _interopRequireDefault(require("./header-cell.js"));
25
26var _measureColumnWidths = _interopRequireDefault(require("./measure-column-widths.js"));
27
28var _index4 = require("../locale/index.js");
29
30function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
31
32function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; }
33
34function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (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; }
35
36function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }
37
38function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); }
39
40function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); }
41
42function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }
43
44function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
45
46function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
47
48function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
49
50function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }
51
52function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }
53
54function _iterableToArrayLimit(arr, i) { if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) { return; } var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
55
56function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
57
58// consider pulling this out to a prop if useful.
59var HEADER_ROW_HEIGHT = 48;
60
61function CellPlacement(_ref) {
62 var columnIndex = _ref.columnIndex,
63 rowIndex = _ref.rowIndex,
64 data = _ref.data,
65 style = _ref.style;
66
67 var _useStyletron = (0, _index2.useStyletron)(),
68 _useStyletron2 = _slicedToArray(_useStyletron, 2),
69 css = _useStyletron2[0],
70 theme = _useStyletron2[1]; // ignores the table header row
71
72
73 if (rowIndex === 0) {
74 return null;
75 }
76
77 var backgroundColor = theme.colors.backgroundPrimary;
78
79 if (rowIndex % 2 && columnIndex === data.columnHighlightIndex || rowIndex === data.rowHighlightIndex) {
80 backgroundColor = theme.colors.backgroundTertiary;
81 } else if (rowIndex % 2 || columnIndex === data.columnHighlightIndex) {
82 backgroundColor = theme.colors.backgroundSecondary;
83 }
84
85 var Cell = data.columns[columnIndex].renderCell;
86 var value = data.columns[columnIndex].mapDataToValue(data.rows[rowIndex - 1].data);
87 return React.createElement("div", {
88 className: css(_objectSpread({}, theme.borders.border200, {
89 backgroundColor: backgroundColor,
90 borderTop: 'none',
91 borderBottom: 'none',
92 borderLeft: 'none',
93 // do not render a border on cells in the right-most column
94 borderRight: columnIndex === data.columns.length - 1 ? 'none' : null,
95 boxSizing: 'border-box'
96 })),
97 style: style,
98 onMouseEnter: function onMouseEnter() {
99 return data.onRowMouseEnter(rowIndex, data.rows[rowIndex - 1]);
100 }
101 }, React.createElement(Cell, {
102 value: value,
103 onSelect: data.isSelectable && columnIndex === 0 ? function () {
104 return data.onSelectOne(data.rows[rowIndex - 1]);
105 } : undefined,
106 isSelected: data.isRowSelected(data.rows[rowIndex - 1].id),
107 textQuery: data.textQuery
108 }));
109}
110
111function compareCellPlacement(prevProps, nextProps) {
112 // header cells are not rendered through this component
113 if (prevProps.rowIndex === 0) {
114 return true;
115 }
116
117 if (prevProps.data.columns !== nextProps.data.columns || prevProps.data.rows !== nextProps.data.rows || prevProps.style !== nextProps.style) {
118 return false;
119 }
120
121 if (prevProps.data.isSelectable === nextProps.data.isSelectable && prevProps.data.columnHighlightIndex === nextProps.data.columnHighlightIndex && prevProps.data.rowHighlightIndex === nextProps.data.rowHighlightIndex && prevProps.data.textQuery === nextProps.data.textQuery && prevProps.data.isRowSelected === nextProps.data.isRowSelected) {
122 return true;
123 } // at this point we know that the rowHighlightIndex or the columnHighlightIndex has changed.
124 // row does not need to re-render if not transitioning _from_ or _to_ highlighted
125 // also ensures that all cells are invalidated on column-header hover
126
127
128 if (prevProps.rowIndex !== prevProps.data.rowHighlightIndex && prevProps.rowIndex !== nextProps.data.rowHighlightIndex && prevProps.data.columnHighlightIndex === nextProps.data.columnHighlightIndex && prevProps.data.isRowSelected === nextProps.data.isRowSelected) {
129 return true;
130 } // similar to the row highlight optimization, do not update the cell if not in the previously
131 // highlighted column or next highlighted.
132
133
134 if (prevProps.columnIndex !== prevProps.data.columnHighlightIndex && prevProps.columnIndex !== nextProps.data.columnHighlightIndex && prevProps.data.rowHighlightIndex === nextProps.data.rowHighlightIndex && prevProps.data.isRowSelected === nextProps.data.isRowSelected) {
135 return true;
136 }
137
138 return false;
139}
140
141var CellPlacementMemo = React.memo(CellPlacement, compareCellPlacement);
142CellPlacementMemo.displayName = 'CellPlacement';
143var HeaderContext = React.createContext({
144 columns: [],
145 columnHighlightIndex: -1,
146 emptyMessage: '',
147 filters: new Map(),
148 loading: false,
149 loadingMessage: '',
150 isScrollingX: false,
151 isSelectable: false,
152 isSelectedAll: false,
153 isSelectedIndeterminate: false,
154 measuredWidths: [],
155 onMouseEnter: function onMouseEnter() {},
156 onMouseLeave: function onMouseLeave() {},
157 onResize: function onResize() {},
158 onSelectMany: function onSelectMany() {},
159 onSelectNone: function onSelectNone() {},
160 onSort: function onSort() {},
161 resizableColumnWidths: false,
162 rowActions: [],
163 rowHeight: 0,
164 rowHighlightIndex: -1,
165 rows: [],
166 scrollLeft: 0,
167 sortIndex: -1,
168 sortDirection: null,
169 tableHeight: 0,
170 widths: []
171});
172HeaderContext.displayName = 'HeaderContext';
173
174function Header(props) {
175 var _useStyletron3 = (0, _index2.useStyletron)(),
176 _useStyletron4 = _slicedToArray(_useStyletron3, 2),
177 css = _useStyletron4[0],
178 theme = _useStyletron4[1];
179
180 var _React$useState = React.useState(0),
181 _React$useState2 = _slicedToArray(_React$useState, 2),
182 startResizePos = _React$useState2[0],
183 setStartResizePos = _React$useState2[1];
184
185 var _React$useState3 = React.useState(0),
186 _React$useState4 = _slicedToArray(_React$useState3, 2),
187 endResizePos = _React$useState4[0],
188 setEndResizePos = _React$useState4[1]; // eslint-disable-next-line flowtype/no-weak-types
189
190
191 var headerCellRef = React.useRef(null);
192 var RULER_OFFSET = 2;
193 var isResizingThisColumn = props.resizeIndex === props.index;
194 var isResizing = props.resizeIndex >= 0;
195
196 function getPositionX(el) {
197 if (typeof document !== 'undefined') {
198 var rect = el.getBoundingClientRect();
199 return rect.left + window.scrollX;
200 }
201
202 return 0;
203 }
204
205 React.useLayoutEffect(function () {
206 function handleMouseMove(event) {
207 if (isResizingThisColumn) {
208 event.preventDefault();
209
210 if (headerCellRef.current) {
211 var left = getPositionX(headerCellRef.current);
212 var width = event.clientX - left - 5;
213 var max = Math.ceil(props.resizeMaxWidth);
214 var min = Math.ceil(props.resizeMinWidth);
215
216 if (min === max) {
217 return;
218 }
219
220 if (width >= min && width <= max) {
221 setEndResizePos(event.clientX - RULER_OFFSET);
222 }
223
224 if (width < min) {
225 setEndResizePos(left + min - RULER_OFFSET);
226 }
227
228 if (width > max) {
229 setEndResizePos(max - width - RULER_OFFSET);
230 }
231 }
232 }
233 }
234
235 function handleMouseUp(event) {
236 props.onResize(props.index, endResizePos - startResizePos);
237 props.onResizeIndexChange(-1);
238 setStartResizePos(0);
239 setEndResizePos(0);
240 }
241
242 if (typeof document !== 'undefined') {
243 if (isResizingThisColumn) {
244 document.addEventListener('mousemove', handleMouseMove);
245 document.addEventListener('mouseup', handleMouseUp);
246 }
247 }
248
249 return function () {
250 if (typeof document !== 'undefined') {
251 document.removeEventListener('mousemove', handleMouseMove);
252 document.removeEventListener('mouseup', handleMouseUp);
253 }
254 };
255 }, [isResizingThisColumn, setEndResizePos, setStartResizePos, setEndResizePos, props.onResize, props.onResizeIndexChange, props.index, endResizePos, startResizePos, headerCellRef.current]);
256 return React.createElement(React.Fragment, null, React.createElement(_headerCell.default, {
257 ref: headerCellRef,
258 index: props.index,
259 sortable: props.isSortable,
260 isHovered: !isResizing && props.hoverIndex === props.index,
261 isSelectable: props.isSelectable && props.index === 0,
262 isSelectedAll: props.isSelectedAll,
263 isSelectedIndeterminate: props.isSelectedIndeterminate,
264 onMouseEnter: function onMouseEnter() {
265 if (!isResizing) {
266 props.onMouseEnter(props.index);
267 }
268 },
269 onMouseLeave: function onMouseLeave() {
270 if (!isResizing) {
271 props.onMouseLeave();
272 }
273 },
274 onSelectAll: props.onSelectMany,
275 onSelectNone: props.onSelectNone,
276 onSort: props.onSort,
277 sortDirection: props.sortIndex === props.index ? props.sortDirection : null,
278 title: props.columnTitle
279 }), props.resizableColumnWidths && React.createElement("div", {
280 className: css({
281 position: 'relative',
282 display: 'flex',
283 alignItems: 'center'
284 })
285 }, React.createElement("div", {
286 role: "presentation",
287 onMouseDown: function onMouseDown(event) {
288 props.onResizeIndexChange(props.index);
289 var x = getPositionX(event.target);
290 setStartResizePos(x);
291 setEndResizePos(x);
292 },
293 className: css({
294 backgroundColor: isResizingThisColumn ? theme.colors.contentPrimary : null,
295 cursor: 'ew-resize',
296 position: 'absolute',
297 height: '100%',
298 width: '3px',
299 ':hover': {
300 backgroundColor: theme.colors.contentPrimary
301 }
302 }),
303 style: {
304 right: "".concat((RULER_OFFSET + endResizePos - startResizePos) * -1, "px")
305 }
306 }, isResizingThisColumn && React.createElement("div", {
307 className: css({
308 backgroundColor: theme.colors.contentPrimary,
309 position: 'absolute',
310 height: "".concat(props.tableHeight, "px"),
311 right: '1px',
312 width: '1px'
313 })
314 }))));
315}
316
317function Headers(props) {
318 var _useStyletron5 = (0, _index2.useStyletron)(),
319 _useStyletron6 = _slicedToArray(_useStyletron5, 2),
320 css = _useStyletron6[0],
321 theme = _useStyletron6[1];
322
323 var ctx = React.useContext(HeaderContext);
324
325 var _React$useState5 = React.useState(-1),
326 _React$useState6 = _slicedToArray(_React$useState5, 2),
327 resizeIndex = _React$useState6[0],
328 setResizeIndex = _React$useState6[1];
329
330 return React.createElement("div", {
331 className: css({
332 position: 'sticky',
333 top: 0,
334 left: 0,
335 width: "".concat(ctx.widths.reduce(function (sum, w) {
336 return sum + w;
337 }, 0), "px"),
338 height: "".concat(HEADER_ROW_HEIGHT, "px"),
339 display: 'flex',
340 // this feels bad.. the absolutely positioned children elements
341 // stack on top of this element with the layer component.
342 zIndex: 2
343 })
344 }, ctx.columns.map(function (column, columnIndex) {
345 var activeFilter = ctx.filters ? ctx.filters.get(column.title) : null;
346 return React.createElement(React.Fragment, {
347 key: columnIndex
348 }, React.createElement(_index3.Tooltip, {
349 key: columnIndex,
350 placement: _index3.PLACEMENT.bottomLeft,
351 isOpen: ctx.columnHighlightIndex === columnIndex && Boolean(activeFilter),
352 content: function content() {
353 return React.createElement("div", null, React.createElement("p", {
354 className: css(_objectSpread({}, theme.typography.font100, {
355 color: theme.colors.contentInversePrimary
356 }))
357 }, "filter applied to ", column.title), activeFilter && React.createElement("p", {
358 className: css(_objectSpread({}, theme.typography.font150, {
359 color: theme.colors.contentInversePrimary
360 }))
361 }, activeFilter.description));
362 }
363 }, React.createElement("div", {
364 className: css(_objectSpread({}, theme.borders.border200, {
365 backgroundColor: theme.colors.backgroundPrimary,
366 borderTop: 'none',
367 borderLeft: 'none',
368 borderRight: columnIndex === ctx.columns.length - 1 ? 'none' : null,
369 boxSizing: 'border-box',
370 display: 'flex'
371 })),
372 style: {
373 width: ctx.widths[columnIndex]
374 }
375 }, React.createElement(Header, {
376 columnTitle: column.title,
377 hoverIndex: ctx.columnHighlightIndex,
378 index: columnIndex,
379 isSortable: column.sortable,
380 isSelectable: ctx.isSelectable,
381 isSelectedAll: ctx.isSelectedAll,
382 isSelectedIndeterminate: ctx.isSelectedIndeterminate,
383 onMouseEnter: ctx.onMouseEnter,
384 onMouseLeave: ctx.onMouseLeave,
385 onResize: ctx.onResize,
386 onResizeIndexChange: setResizeIndex,
387 onSelectMany: ctx.onSelectMany,
388 onSelectNone: ctx.onSelectNone,
389 onSort: function onSort() {
390 return ctx.onSort(columnIndex);
391 },
392 resizableColumnWidths: ctx.resizableColumnWidths,
393 resizeIndex: resizeIndex,
394 resizeMinWidth: ctx.measuredWidths[columnIndex],
395 resizeMaxWidth: column.maxWidth || Infinity,
396 sortIndex: ctx.sortIndex,
397 sortDirection: ctx.sortDirection,
398 tableHeight: ctx.tableHeight
399 }))));
400 }));
401}
402
403function LoadingOrEmptyMessage(props) {
404 var _useStyletron7 = (0, _index2.useStyletron)(),
405 _useStyletron8 = _slicedToArray(_useStyletron7, 2),
406 css = _useStyletron8[0],
407 theme = _useStyletron8[1];
408
409 return React.createElement("p", {
410 className: css(_objectSpread({}, theme.typography.ParagraphSmall, {
411 color: theme.colors.contentPrimary,
412 marginLeft: theme.sizing.scale500
413 }))
414 }, typeof props.children === 'function' ? props.children() : String(props.children));
415} // replaces the content of the virtualized window with contents. in this case,
416// we are prepending a table header row before the table rows (children to the fn).
417
418
419var InnerTableElement = React.forwardRef(function (props, ref) {
420 var _useStyletron9 = (0, _index2.useStyletron)(),
421 _useStyletron10 = _slicedToArray(_useStyletron9, 2),
422 theme = _useStyletron10[1];
423
424 var ctx = React.useContext(HeaderContext); // no need to render the cells until the columns have been measured
425
426 if (!ctx.widths.filter(Boolean).length) {
427 return null;
428 }
429
430 var RENDERING = 0;
431 var LOADING = 1;
432 var EMPTY = 2;
433 var viewState = RENDERING;
434
435 if (ctx.loading) {
436 viewState = LOADING;
437 } else if (ctx.rows.length === 0) {
438 viewState = EMPTY;
439 }
440
441 return React.createElement("div", {
442 ref: ref,
443 "data-baseweb": "data-table",
444 style: props.style
445 }, React.createElement(Headers, null), viewState === LOADING && React.createElement(LoadingOrEmptyMessage, null, ctx.loadingMessage), viewState === EMPTY && React.createElement(LoadingOrEmptyMessage, null, ctx.emptyMessage), viewState === RENDERING && props.children, ctx.rowActions && Boolean(ctx.rowActions.length) && ctx.rowHighlightIndex > 0 && !ctx.isScrollingX && React.createElement("div", {
446 style: {
447 alignItems: 'center',
448 backgroundColor: theme.colors.backgroundTertiary,
449 display: 'flex',
450 height: "".concat(ctx.rowHeight, "px"),
451 padding: '0 16px',
452 paddingLeft: theme.sizing.scale300,
453 paddingRight: theme.sizing.scale300,
454 position: 'absolute',
455 right: theme.direction !== 'rtl' ? 0 - ctx.scrollLeft : 'initial',
456 left: theme.direction === 'rtl' ? 0 : 'initial',
457 top: (ctx.rowHighlightIndex - 1) * ctx.rowHeight + HEADER_ROW_HEIGHT
458 }
459 }, ctx.rowActions.map(function (rowAction) {
460 var RowActionIcon = rowAction.renderIcon;
461 return React.createElement(_index.Button, {
462 alt: rowAction.label,
463 key: rowAction.label,
464 onClick: function onClick(event) {
465 return rowAction.onClick({
466 event: event,
467 row: ctx.rows[ctx.rowHighlightIndex - 1]
468 });
469 },
470 size: _index.SIZE.compact,
471 kind: _index.KIND.minimal,
472 shape: _index.SHAPE.round,
473 overrides: {
474 BaseButton: {
475 style: {
476 marginLeft: theme.sizing.scale300
477 }
478 }
479 }
480 }, React.createElement(RowActionIcon, {
481 size: 24
482 }));
483 })));
484});
485InnerTableElement.displayName = 'InnerTableElement';
486
487function Unstable_DataTable(props) {
488 var _useStyletron11 = (0, _index2.useStyletron)(),
489 _useStyletron12 = _slicedToArray(_useStyletron11, 2),
490 theme = _useStyletron12[1];
491
492 var locale = React.useContext(_index4.LocaleContext);
493
494 var _rowHeight = props.rowHeight || 36;
495
496 var gridRef = React.useRef(null);
497
498 var _React$useState7 = React.useState(props.columns.map(function () {
499 return 0;
500 })),
501 _React$useState8 = _slicedToArray(_React$useState7, 2),
502 measuredWidths = _React$useState8[0],
503 setMeasuredWidths = _React$useState8[1];
504
505 var _React$useState9 = React.useState(props.columns.map(function () {
506 return 0;
507 })),
508 _React$useState10 = _slicedToArray(_React$useState9, 2),
509 resizeDeltas = _React$useState10[0],
510 setResizeDeltas = _React$useState10[1];
511
512 var resetAfterColumnIndex = React.useCallback(function (columnIndex) {
513 if (gridRef.current) {
514 // $FlowFixMe trigger react-window to layout the elements again
515 gridRef.current.resetAfterColumnIndex(columnIndex, true);
516 }
517 }, [gridRef.current]);
518 var handleWidthsChange = React.useCallback(function (nextWidths) {
519 setMeasuredWidths(nextWidths);
520 resetAfterColumnIndex(0);
521 }, [setMeasuredWidths, resetAfterColumnIndex]);
522 var handleColumnResize = React.useCallback(function (columnIndex, delta) {
523 setResizeDeltas(function (prev) {
524 prev[columnIndex] = Math.max(prev[columnIndex] + delta, 0);
525 return _toConsumableArray(prev);
526 });
527 resetAfterColumnIndex(columnIndex);
528 }, [setResizeDeltas, resetAfterColumnIndex]);
529 var normalizedWidths = React.useMemo(function () {
530 var sum = function sum(ns) {
531 return ns.reduce(function (s, n) {
532 return s + n;
533 }, 0);
534 };
535
536 var resizedWidths = measuredWidths.map(function (w, i) {
537 return Math.floor(w) + Math.floor(resizeDeltas[i]);
538 });
539
540 if (gridRef.current) {
541 // minus 2 to account for the border stroke width
542 // $FlowFixMe
543 var domWidth = gridRef.current.props.width - 2;
544 var measuredWidth = sum(resizedWidths); // $FlowFixMe
545
546 var offsetWidth = gridRef.current._outerRef.offsetWidth; // $FlowFixMe
547
548 var clientWidth = gridRef.current._outerRef.clientWidth; // sub 2 for border width
549
550 var scrollbar = offsetWidth - clientWidth - 2;
551 var remainder = domWidth - measuredWidth - scrollbar;
552 var padding = Math.floor(remainder / measuredWidths.length);
553
554 if (padding > 0) {
555 var result = []; // -1 so that we loop over all but the last item
556
557 for (var i = 0; i < resizedWidths.length - 1; i++) {
558 result.push(resizedWidths[i] + padding);
559 }
560
561 result.push(domWidth - sum(result));
562 return result;
563 }
564 }
565
566 return resizedWidths;
567 }, [measuredWidths, resizeDeltas]);
568
569 var _React$useState11 = React.useState(0),
570 _React$useState12 = _slicedToArray(_React$useState11, 2),
571 scrollLeft = _React$useState12[0],
572 setScrollLeft = _React$useState12[1];
573
574 var _React$useState13 = React.useState(false),
575 _React$useState14 = _slicedToArray(_React$useState13, 2),
576 isScrollingX = _React$useState14[0],
577 setIsScrollingX = _React$useState14[1];
578
579 var _React$useState15 = React.useState(false),
580 _React$useState16 = _slicedToArray(_React$useState15, 2),
581 recentlyScrolledX = _React$useState16[0],
582 setRecentlyScrolledX = _React$useState16[1];
583
584 React.useLayoutEffect(function () {
585 if (recentlyScrolledX !== isScrollingX) {
586 setIsScrollingX(recentlyScrolledX);
587 }
588
589 if (recentlyScrolledX) {
590 var timeout = setTimeout(function () {
591 setRecentlyScrolledX(false);
592 }, 200);
593 return function () {
594 return clearTimeout(timeout);
595 };
596 }
597 }, [recentlyScrolledX]);
598 var handleScroll = React.useCallback(function (params) {
599 setScrollLeft(params.scrollLeft);
600
601 if (params.scrollLeft !== scrollLeft) {
602 setRecentlyScrolledX(true);
603 }
604 }, [scrollLeft, setScrollLeft, setRecentlyScrolledX]);
605 var sortedIndices = React.useMemo(function () {
606 var toSort = props.rows.map(function (r, i) {
607 return [r, i];
608 });
609 var index = props.sortIndex;
610
611 if (index !== null && index !== undefined && index !== -1) {
612 var sortFn = props.columns[index].sortFn;
613
614 var getValue = function getValue(row) {
615 return props.columns[index].mapDataToValue(row.data);
616 };
617
618 if (props.sortDirection === _constants.SORT_DIRECTIONS.DESC) {
619 toSort.sort(function (a, b) {
620 return sortFn(getValue(a[0]), getValue(b[0]));
621 });
622 } else if (props.sortDirection === _constants.SORT_DIRECTIONS.ASC) {
623 toSort.sort(function (a, b) {
624 return sortFn(getValue(b[0]), getValue(a[0]));
625 });
626 }
627 }
628
629 return toSort.map(function (el) {
630 return el[1];
631 });
632 }, [props.sortIndex, props.sortDirection, props.columns, props.rows]);
633 var textQuery = React.useMemo(function () {
634 return props.textQuery || '';
635 }, [props.textQuery]);
636 var filteredIndices = React.useMemo(function () {
637 var set = new Set(props.rows.map(function (_, idx) {
638 return idx;
639 }));
640 Array.from(props.filters || new Set(), function (f) {
641 return f;
642 }).forEach(function (_ref2) {
643 var _ref3 = _slicedToArray(_ref2, 2),
644 title = _ref3[0],
645 filter = _ref3[1];
646
647 var columnIndex = props.columns.findIndex(function (c) {
648 return c.title === title;
649 });
650 var column = props.columns[columnIndex];
651
652 if (!column) {
653 return;
654 }
655
656 var filterFn = column.buildFilter(filter);
657 Array.from(set).forEach(function (idx) {
658 if (!filterFn(column.mapDataToValue(props.rows[idx].data))) {
659 set.delete(idx);
660 }
661 });
662 });
663
664 if (textQuery) {
665 var stringishColumnIndices = [];
666
667 for (var i = 0; i < props.columns.length; i++) {
668 if (props.columns[i].textQueryFilter) {
669 stringishColumnIndices.push(i);
670 }
671 }
672
673 Array.from(set).forEach(function (idx) {
674 var matches = stringishColumnIndices.some(function (cdx) {
675 var column = props.columns[cdx];
676 var textQueryFilter = column.textQueryFilter;
677
678 if (textQueryFilter) {
679 return textQueryFilter(textQuery, column.mapDataToValue(props.rows[idx].data));
680 }
681
682 return false;
683 });
684
685 if (!matches) {
686 set.delete(idx);
687 }
688 });
689 }
690
691 return set;
692 }, [props.filters, textQuery, props.columns, props.rows]);
693 var rows = React.useMemo(function () {
694 var result = sortedIndices.filter(function (idx) {
695 return filteredIndices.has(idx);
696 }).map(function (idx) {
697 return props.rows[idx];
698 });
699
700 if (props.onIncludedRowsChange) {
701 props.onIncludedRowsChange(result);
702 }
703
704 return result;
705 }, [sortedIndices, filteredIndices, props.onIncludedRowsChange, props.rows]);
706 var isSelectable = props.batchActions ? !!props.batchActions.length : false;
707 var isSelectedAll = React.useMemo(function () {
708 if (!props.selectedRowIds) {
709 return false;
710 }
711
712 return !!rows.length && props.selectedRowIds.size >= rows.length;
713 }, [props.selectedRowIds, rows.length]);
714 var isSelectedIndeterminate = React.useMemo(function () {
715 if (!props.selectedRowIds) {
716 return false;
717 }
718
719 return !!props.selectedRowIds.size && props.selectedRowIds.size < rows.length;
720 }, [props.selectedRowIds, rows.length]);
721 var isRowSelected = React.useCallback(function (id) {
722 if (props.selectedRowIds) {
723 return props.selectedRowIds.has(id);
724 }
725
726 return false;
727 }, [props.selectedRowIds]);
728 var handleSelectMany = React.useCallback(function () {
729 if (props.onSelectMany) {
730 props.onSelectMany(rows);
731 }
732 }, [rows, props.onSelectMany]);
733 var handleSelectNone = React.useCallback(function () {
734 if (props.onSelectNone) {
735 props.onSelectNone();
736 }
737 }, [props.onSelectNone]);
738 var handleSelectOne = React.useCallback(function (row) {
739 if (props.onSelectOne) {
740 props.onSelectOne(row);
741 }
742 }, [props.onSelectOne]);
743 var handleSort = React.useCallback(function (columnIndex) {
744 if (props.onSort) {
745 props.onSort(columnIndex);
746 }
747 }, [props.onSort]);
748
749 var _React$useState17 = React.useState(-1),
750 _React$useState18 = _slicedToArray(_React$useState17, 2),
751 columnHighlightIndex = _React$useState18[0],
752 setColumnHighlightIndex = _React$useState18[1];
753
754 var _React$useState19 = React.useState(-1),
755 _React$useState20 = _slicedToArray(_React$useState19, 2),
756 rowHighlightIndex = _React$useState20[0],
757 setRowHighlightIndex = _React$useState20[1];
758
759 function handleRowHighlightIndexChange(nextIndex) {
760 setRowHighlightIndex(nextIndex);
761
762 if (gridRef.current) {
763 if (nextIndex >= 0) {
764 // $FlowFixMe - unable to get react-window types
765 gridRef.current.scrollToItem({
766 rowIndex: nextIndex
767 });
768 }
769
770 if (props.onRowHighlightChange) {
771 props.onRowHighlightChange(nextIndex, rows[nextIndex - 1]);
772 }
773 }
774 }
775
776 var handleRowMouseEnter = React.useCallback(function (nextIndex) {
777 setColumnHighlightIndex(-1);
778
779 if (nextIndex !== rowHighlightIndex) {
780 handleRowHighlightIndexChange(nextIndex);
781 }
782 }, [rowHighlightIndex]);
783
784 function handleColumnHeaderMouseEnter(columnIndex) {
785 setColumnHighlightIndex(columnIndex);
786 handleRowHighlightIndexChange(-1);
787 }
788
789 function handleColumnHeaderMouseLeave() {
790 setColumnHighlightIndex(-1);
791 }
792
793 React.useEffect(function () {
794 if (typeof props.rowHighlightIndex === 'number') {
795 handleRowHighlightIndexChange(props.rowHighlightIndex);
796 }
797 }, [props.rowHighlightIndex]);
798 var itemData = React.useMemo(function () {
799 return {
800 columnHighlightIndex: columnHighlightIndex,
801 rowHighlightIndex: rowHighlightIndex,
802 isRowSelected: isRowSelected,
803 isSelectable: isSelectable,
804 onRowMouseEnter: handleRowMouseEnter,
805 onSelectOne: handleSelectOne,
806 columns: props.columns,
807 rows: rows,
808 textQuery: textQuery
809 };
810 }, [handleRowMouseEnter, columnHighlightIndex, isRowSelected, isSelectable, rowHighlightIndex, rows, props.columns, handleSelectOne, textQuery]);
811 return React.createElement(React.Fragment, null, React.createElement(_measureColumnWidths.default, {
812 columns: props.columns,
813 rows: props.rows,
814 widths: measuredWidths,
815 isSelectable: isSelectable,
816 onWidthsChange: handleWidthsChange
817 }), React.createElement(_reactVirtualizedAutoSizer.default, null, function (_ref4) {
818 var height = _ref4.height,
819 width = _ref4.width;
820 return React.createElement(HeaderContext.Provider, {
821 value: {
822 columns: props.columns,
823 columnHighlightIndex: columnHighlightIndex,
824 emptyMessage: props.emptyMessage || locale.datatable.emptyState,
825 filters: props.filters,
826 loading: Boolean(props.loading),
827 loadingMessage: props.loadingMessage || locale.datatable.loadingState,
828 isScrollingX: isScrollingX,
829 isSelectable: isSelectable,
830 isSelectedAll: isSelectedAll,
831 isSelectedIndeterminate: isSelectedIndeterminate,
832 measuredWidths: measuredWidths,
833 onMouseEnter: handleColumnHeaderMouseEnter,
834 onMouseLeave: handleColumnHeaderMouseLeave,
835 onResize: handleColumnResize,
836 onSelectMany: handleSelectMany,
837 onSelectNone: handleSelectNone,
838 onSort: handleSort,
839 resizableColumnWidths: Boolean(props.resizableColumnWidths),
840 rowActions: props.rowActions || [],
841 rowHeight: _rowHeight,
842 rowHighlightIndex: rowHighlightIndex,
843 rows: rows,
844 scrollLeft: scrollLeft,
845 sortDirection: props.sortDirection || null,
846 sortIndex: typeof props.sortIndex === 'number' ? props.sortIndex : -1,
847 tableHeight: height,
848 widths: normalizedWidths
849 }
850 }, React.createElement(_reactWindow.VariableSizeGrid // eslint-disable-next-line flowtype/no-weak-types
851 , {
852 ref: gridRef,
853 overscanRowCount: 10,
854 innerElementType: InnerTableElement,
855 columnCount: props.columns.length,
856 columnWidth: function columnWidth(columnIndex) {
857 return normalizedWidths[columnIndex];
858 },
859 height: height - 2 // plus one to account for additional header row
860 ,
861 rowCount: rows.length + 1,
862 rowHeight: function rowHeight(rowIndex) {
863 return rowIndex === 0 ? HEADER_ROW_HEIGHT : _rowHeight;
864 },
865 width: width - 2,
866 itemData: itemData,
867 onScroll: handleScroll,
868 style: _objectSpread({}, theme.borders.border200, {
869 borderColor: theme.colors.borderOpaque
870 }),
871 direction: theme.direction === 'rtl' ? 'rtl' : 'ltr'
872 }, CellPlacementMemo));
873 }));
874}
\No newline at end of file