@elastic/eui
Version:
Elastic UI Component Library
432 lines (416 loc) • 22 kB
JavaScript
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
var _excluded = ["leadingControlColumns", "trailingControlColumns", "columns", "columnVisibility", "schemaDetectors", "rowCount", "renderCellValue", "cellContext", "renderCellPopover", "renderFooterCellValue", "className", "gridStyle", "toolbarVisibility", "headerVisibility", "pagination", "sorting", "inMemory", "onColumnResize", "minSizeForControls", "height", "width", "rowHeightsOptions", "virtualizationOptions", "renderCustomGridBody", "renderCustomToolbar", "onFullScreenChange"];
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }
function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], t.indexOf(o) >= 0 || {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (e.indexOf(n) >= 0) continue; t[n] = r[n]; } return t; }
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import classNames from 'classnames';
import React, { forwardRef, useMemo, useRef, useState, memo, useCallback } from 'react';
import { useGeneratedHtmlId, useEuiMemoizedStyles, OverrideCopiedTabularContent } from '../../services';
import { useEuiTablePaginationDefaults } from '../table/table_pagination';
import { EuiFocusTrap } from '../focus_trap';
import { EuiI18n, useEuiI18n } from '../i18n';
import { useMutationObserver } from '../observer/mutation_observer';
import { useResizeObserver } from '../observer/resize_observer';
import { EuiDataGridBody } from './body';
import { useDataGridColumnSelector, useDataGridColumnSorting, useDataGridDisplaySelector, startingStyles, useDataGridFullScreenSelector, useDataGridKeyboardShortcuts, checkOrDefaultToolBarDisplayOptions, EuiDataGridToolbar } from './controls';
import { EuiDataGridPagination, shouldRenderPagination } from './pagination';
import { DataGridSortedContext, useSorting } from './utils/sorting';
import { DataGridFocusContext, useFocus, createKeyDownHandler, preventTabbing } from './utils/focus';
import { useInMemoryValues, EuiDataGridInMemoryRenderer } from './utils/in_memory';
import { DataGridCellPopoverContext, useCellPopover } from './body/cell';
import { computeVisibleRows } from './utils/row_count';
import { schemaDetectors as providedSchemaDetectors, useMergedSchema } from './utils/data_grid_schema';
import { useImperativeGridRef } from './utils/ref';
import { emptyControlColumns } from './data_grid_types';
import { euiDataGridStyles } from './data_grid.styles';
// Each gridStyle object above sets a specific CSS select to .euiGrid
import { jsx as ___EmotionJSX } from "@emotion/react";
var fontSizesToClassMap = {
s: 'euiDataGrid--fontSizeSmall',
m: '',
l: 'euiDataGrid--fontSizeLarge'
};
var headerToClassMap = {
shade: 'euiDataGrid--headerShade',
underline: 'euiDataGrid--headerUnderline'
};
var footerToClassMap = {
shade: 'euiDataGrid--footerShade',
overline: 'euiDataGrid--footerOverline',
striped: ''
};
var rowHoverToClassMap = {
highlight: 'euiDataGrid--rowHoverHighlight',
none: ''
};
var bordersToClassMap = {
all: 'euiDataGrid--bordersAll',
horizontal: 'euiDataGrid--bordersHorizontal',
none: 'euiDataGrid--bordersNone'
};
var cellPaddingsToClassMap = {
s: 'euiDataGrid--paddingSmall',
m: '',
l: 'euiDataGrid--paddingLarge'
};
var emptyVirtualizationOptions = {};
export var EuiDataGrid = /*#__PURE__*/memo( /*#__PURE__*/forwardRef(function (props, ref) {
var _props$leadingControl = props.leadingControlColumns,
leadingControlColumns = _props$leadingControl === void 0 ? emptyControlColumns : _props$leadingControl,
_props$trailingContro = props.trailingControlColumns,
trailingControlColumns = _props$trailingContro === void 0 ? emptyControlColumns : _props$trailingContro,
columns = props.columns,
columnVisibility = props.columnVisibility,
schemaDetectors = props.schemaDetectors,
rowCount = props.rowCount,
renderCellValue = props.renderCellValue,
cellContext = props.cellContext,
renderCellPopover = props.renderCellPopover,
renderFooterCellValue = props.renderFooterCellValue,
className = props.className,
gridStyle = props.gridStyle,
_props$toolbarVisibil = props.toolbarVisibility,
toolbarVisibility = _props$toolbarVisibil === void 0 ? true : _props$toolbarVisibil,
_props$headerVisibili = props.headerVisibility,
headerVisibility = _props$headerVisibili === void 0 ? true : _props$headerVisibili,
_pagination = props.pagination,
sorting = props.sorting,
inMemory = props.inMemory,
onColumnResize = props.onColumnResize,
minSizeForControls = props.minSizeForControls,
height = props.height,
width = props.width,
_rowHeightsOptions = props.rowHeightsOptions,
virtualizationOptions = props.virtualizationOptions,
renderCustomGridBody = props.renderCustomGridBody,
renderCustomToolbar = props.renderCustomToolbar,
onFullScreenChange = props.onFullScreenChange,
rest = _objectWithoutProperties(props, _excluded);
/**
* Merge consumer settings with defaults
*/
var paginationDefaults = useEuiTablePaginationDefaults();
var pagination = useMemo(function () {
return _pagination ? _objectSpread({
pageSize: paginationDefaults.itemsPerPage,
pageSizeOptions: paginationDefaults.itemsPerPageOptions
}, _pagination) : _pagination;
}, [_pagination, paginationDefaults]);
var showPagination = pagination && shouldRenderPagination(rowCount, pagination);
var gridStyleWithDefaults = useMemo(function () {
return _objectSpread(_objectSpread({}, startingStyles), gridStyle);
}, [gridStyle]);
var _useInMemoryValues = useInMemoryValues(inMemory, rowCount),
_useInMemoryValues2 = _slicedToArray(_useInMemoryValues, 2),
inMemoryValues = _useInMemoryValues2[0],
onCellRender = _useInMemoryValues2[1];
var allSchemaDetectors = useMemo(function () {
return [].concat(_toConsumableArray(providedSchemaDetectors), _toConsumableArray(schemaDetectors || []));
}, [schemaDetectors]);
var mergedSchema = useMergedSchema({
columns: columns,
inMemory: inMemory,
inMemoryValues: inMemoryValues,
schemaDetectors: allSchemaDetectors,
autoDetectSchema: inMemory != null
});
/**
* Grid refs & observers
*/
// Outermost wrapper div
// this ref needs to be managed by a state, to cause a re-render after mount
// and passing the mounted element to the resize observer
var _useState = useState(null),
_useState2 = _slicedToArray(_useState, 2),
resizeRef = _useState2[0],
setResizeRef = _useState2[1];
var _useResizeObserver = useResizeObserver(resizeRef, 'width'),
gridWidth = _useResizeObserver.width;
// Wrapper div around EuiDataGridBody
var contentRef = useRef(null);
useMutationObserver(contentRef.current, preventTabbing, {
subtree: true,
childList: true
});
// Imperative handler passed back by react-window - we're setting this at
// the top datagrid level to make passing it to other children & utils easier
var gridRef = useRef(null);
var gridItemsRendered = useRef(null);
/**
* Display
*/
var displayValues = useMemo(function () {
return columns.reduce(function (acc, column) {
// prevent duplicate values
if (!acc[column.id]) {
return _objectSpread(_objectSpread({}, acc), {}, _defineProperty({}, column.id, column.displayAsText || column.id));
}
return acc;
}, {});
}, [columns]);
var _useDataGridDisplaySe = useDataGridDisplaySelector(checkOrDefaultToolBarDisplayOptions(toolbarVisibility, 'showDisplaySelector'), gridStyleWithDefaults, _rowHeightsOptions),
_useDataGridDisplaySe2 = _slicedToArray(_useDataGridDisplaySe, 3),
displaySelector = _useDataGridDisplaySe2[0],
gridStyles = _useDataGridDisplaySe2[1],
rowHeightsOptions = _useDataGridDisplaySe2[2];
/**
* Column order & visibility
*/
var _useDataGridColumnSel = useDataGridColumnSelector(columns, columnVisibility, checkOrDefaultToolBarDisplayOptions(toolbarVisibility, 'showColumnSelector'), displayValues),
_useDataGridColumnSel2 = _slicedToArray(_useDataGridColumnSel, 4),
columnSelector = _useDataGridColumnSel2[0],
orderedVisibleColumns = _useDataGridColumnSel2[1],
setVisibleColumns = _useDataGridColumnSel2[2],
switchColumnPos = _useDataGridColumnSel2[3];
var visibleColCount = useMemo(function () {
return orderedVisibleColumns.length + leadingControlColumns.length + trailingControlColumns.length;
}, [orderedVisibleColumns, leadingControlColumns, trailingControlColumns]);
var visibleRows = useMemo(function () {
return computeVisibleRows({
pagination: pagination,
rowCount: rowCount
});
}, [pagination, rowCount]);
var visibleRowCount = visibleRows.visibleRowCount;
/**
* Sorting
*/
var columnSorting = useDataGridColumnSorting({
sorting: sorting,
columns: orderedVisibleColumns,
displayValues: displayValues,
schema: mergedSchema,
schemaDetectors: allSchemaDetectors
});
var sortedContext = useSorting({
sorting: sorting,
inMemory: inMemory,
inMemoryValues: inMemoryValues,
schema: mergedSchema,
schemaDetectors: allSchemaDetectors,
startRow: visibleRows.startRow
});
/**
* Focus
*/
var _useFocus = useFocus(),
wrappingDivFocusProps = _useFocus.focusProps,
onFocusUpdate = _useFocus.onFocusUpdate,
focusedCell = _useFocus.focusedCell,
setFocusedCell = _useFocus.setFocusedCell,
setIsFocusedCellInView = _useFocus.setIsFocusedCellInView,
focusFirstVisibleInteractiveCell = _useFocus.focusFirstVisibleInteractiveCell;
var focusContext = useMemo(function () {
return {
onFocusUpdate: onFocusUpdate,
focusedCell: focusedCell,
setFocusedCell: setFocusedCell,
setIsFocusedCellInView: setIsFocusedCellInView,
focusFirstVisibleInteractiveCell: focusFirstVisibleInteractiveCell
};
}, [onFocusUpdate, focusedCell, setFocusedCell, setIsFocusedCellInView, focusFirstVisibleInteractiveCell]);
/**
* Cell popover
*/
var _useCellPopover = useCellPopover(),
cellPopoverContext = _useCellPopover.cellPopoverContext,
cellPopover = _useCellPopover.cellPopover;
/**
* Toolbar, keyboard shortcuts, & fullscreen
*/
var showToolbar = !!toolbarVisibility;
var _useDataGridKeyboardS = useDataGridKeyboardShortcuts(),
keyboardShortcuts = _useDataGridKeyboardS.keyboardShortcuts;
var _useDataGridFullScree = useDataGridFullScreenSelector(onFullScreenChange),
isFullScreen = _useDataGridFullScree.isFullScreen,
setIsFullScreen = _useDataGridFullScree.setIsFullScreen,
fullScreenSelector = _useDataGridFullScree.fullScreenSelector,
handleGridKeyDown = _useDataGridFullScree.handleGridKeyDown,
fullScreenStyles = _useDataGridFullScree.fullScreenStyles;
/**
* Expose certain internal APIs as ref to consumer
*/
useImperativeGridRef({
ref: ref,
gridRef: gridRef,
setIsFullScreen: setIsFullScreen,
focusContext: focusContext,
cellPopoverContext: cellPopoverContext,
sortedContext: sortedContext,
pagination: pagination,
rowCount: rowCount,
visibleColCount: visibleColCount
});
/**
* Classes
*/
var classes = classNames('euiDataGrid', fontSizesToClassMap[gridStyles.fontSize], bordersToClassMap[gridStyles.border], headerToClassMap[gridStyles.header], footerToClassMap[gridStyles.footer], rowHoverToClassMap[gridStyles.rowHover], cellPaddingsToClassMap[gridStyles.cellPadding], {
'euiDataGrid--stripes': gridStyles.stripes
}, {
'euiDataGrid--stickyFooter': gridStyles.footer && gridStyles.stickyFooter
}, _defineProperty({
'euiDataGrid--fullScreen': isFullScreen
}, fullScreenStyles, isFullScreen), {
'euiDataGrid--noControls': !toolbarVisibility,
'euiDataGrid--noHeader': !headerVisibility
}, className);
/**
* Accessibility
*/
var gridId = useGeneratedHtmlId();
var interactiveCellId = useGeneratedHtmlId();
var ariaLabelledById = useGeneratedHtmlId();
var ariaPage = pagination ? pagination.pageIndex + 1 : 1;
var ariaPageCount = pagination !== null && pagination !== void 0 && pagination.pageSize ? Math.ceil(rowCount / pagination.pageSize) : 1;
var ariaLabel = useEuiI18n('euiDataGrid.ariaLabel', '{label}; Page {page} of {pageCount}.', {
label: rest['aria-label'],
page: ariaPage,
pageCount: ariaPageCount
});
var ariaLabelledBy = useEuiI18n('euiDataGrid.ariaLabelledBy', 'Page {page} of {pageCount}.', {
page: ariaPage,
pageCount: ariaPageCount
});
// extract aria-label and/or aria-labelledby from `rest`
var gridAriaProps = {};
if ('aria-label' in rest) {
gridAriaProps['aria-label'] = pagination ? ariaLabel : rest['aria-label'];
delete rest['aria-label'];
}
if ('aria-labelledby' in rest) {
gridAriaProps['aria-labelledby'] = "".concat(rest['aria-labelledby'], " ").concat(pagination ? ariaLabelledById : '');
delete rest['aria-labelledby'];
}
var onKeyDown = useCallback(function (event) {
var _gridItemsRendered$cu;
createKeyDownHandler({
gridElement: contentRef.current,
visibleColCount: visibleColCount,
visibleRowCount: visibleRowCount,
visibleRowStartIndex: ((_gridItemsRendered$cu = gridItemsRendered.current) === null || _gridItemsRendered$cu === void 0 ? void 0 : _gridItemsRendered$cu.visibleRowStartIndex) || 0,
rowCount: rowCount,
pagination: pagination,
hasFooter: !!renderFooterCellValue,
focusContext: focusContext
})(event);
}, [focusContext, visibleColCount, visibleRowCount, rowCount, pagination, renderFooterCellValue]);
var styles = useEuiMemoizedStyles(euiDataGridStyles);
var cssStyles = [styles.euiDataGrid, styles.cellPadding[gridStyles.cellPadding], styles.fontSize[gridStyles.fontSize], styles.borders[gridStyles.border]];
return ___EmotionJSX(DataGridFocusContext.Provider, {
value: focusContext
}, ___EmotionJSX(DataGridCellPopoverContext.Provider, {
value: cellPopoverContext
}, ___EmotionJSX(DataGridSortedContext.Provider, {
value: sortedContext
}, ___EmotionJSX(EuiFocusTrap, {
disabled: !isFullScreen,
className: "euiDataGrid__focusWrap",
css: styles.euiDataGrid__focusWrap
}, ___EmotionJSX("div", _extends({
css: cssStyles,
className: classes,
onKeyDown: handleGridKeyDown,
style: isFullScreen ? undefined : {
width: width,
height: height
},
ref: setResizeRef
}, rest), showToolbar && ___EmotionJSX(EuiDataGridToolbar, {
gridWidth: gridWidth,
minSizeForControls: minSizeForControls,
toolbarVisibility: toolbarVisibility,
isFullScreen: isFullScreen,
fullScreenSelector: fullScreenSelector,
keyboardShortcuts: keyboardShortcuts,
displaySelector: displaySelector,
columnSelector: columnSelector,
columnSorting: columnSorting,
renderCustomToolbar: renderCustomToolbar
}), inMemory ? ___EmotionJSX(EuiDataGridInMemoryRenderer, {
inMemory: inMemory,
renderCellValue: renderCellValue,
columns: columns,
rowCount: inMemory.level === 'enhancements' ?
// if `inMemory.level === enhancements` then we can only be sure the pagination's pageSize is available in memory
(pagination === null || pagination === void 0 ? void 0 : pagination.pageSize) || rowCount :
// otherwise, all of the data is present and usable
rowCount,
onCellRender: onCellRender
}) : null, ___EmotionJSX("div", _extends({
// eslint-disable-line jsx-a11y/interactive-supports-focus
ref: contentRef,
onKeyDown: onKeyDown,
"data-test-subj": "euiDataGridBody",
css: styles.euiDataGrid__content,
className: "euiDataGrid__content",
role: "grid",
"aria-rowcount": rowCount,
id: gridId
}, wrappingDivFocusProps, gridAriaProps), ___EmotionJSX(OverrideCopiedTabularContent, null, ___EmotionJSX(EuiDataGridBody, {
columns: orderedVisibleColumns,
visibleColCount: visibleColCount,
leadingControlColumns: leadingControlColumns,
schema: mergedSchema,
trailingControlColumns: trailingControlColumns,
setVisibleColumns: setVisibleColumns,
switchColumnPos: switchColumnPos,
onColumnResize: onColumnResize,
schemaDetectors: allSchemaDetectors,
sorting: sorting,
pagination: pagination,
renderCellValue: renderCellValue,
cellContext: cellContext,
renderCellPopover: renderCellPopover,
renderFooterCellValue: renderFooterCellValue,
rowCount: rowCount,
visibleRows: visibleRows,
interactiveCellId: interactiveCellId,
rowHeightsOptions: rowHeightsOptions,
virtualizationOptions: virtualizationOptions || emptyVirtualizationOptions,
isFullScreen: isFullScreen,
gridStyles: gridStyles,
gridWidth: gridWidth,
gridRef: gridRef,
gridItemsRendered: gridItemsRendered,
wrapperRef: contentRef,
renderCustomGridBody: renderCustomGridBody,
canDragAndDropColumns: columnVisibility.canDragAndDropColumns,
showHeader: !!headerVisibility
}))), showPagination && props['aria-labelledby'] && ___EmotionJSX("p", {
id: ariaLabelledById,
hidden: true
}, ariaLabelledBy), showPagination && ___EmotionJSX(EuiDataGridPagination, _extends({}, pagination, {
rowCount: rowCount,
controls: gridId,
"aria-label": props['aria-label']
})), ___EmotionJSX("p", {
id: interactiveCellId,
hidden: true
}, ___EmotionJSX(EuiI18n, {
token: "euiDataGrid.screenReaderNotice",
default: "Cell contains interactive content."
}))))), cellPopover));
}));
EuiDataGrid.displayName = 'EuiDataGrid';