terra-data-grid
Version:
Package containing data grid container components that enable users to navigate the grid information using directional navigation keys.
647 lines (613 loc) • 29.1 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _typeof = require("@babel/runtime/helpers/typeof");
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "ColumnHighlightColor", {
enumerable: true,
get: function get() {
return _terraTable.ColumnHighlightColor;
}
});
exports.default = void 0;
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _react = _interopRequireWildcard(require("react"));
var _propTypes = _interopRequireDefault(require("prop-types"));
var _bind = _interopRequireDefault(require("classnames/bind"));
var KeyCode = _interopRequireWildcard(require("keycode-js"));
var _terraTable = _interopRequireWildcard(require("terra-table"));
var _focusManagement = _interopRequireDefault(require("terra-table/lib/utils/focusManagement"));
var _terraVisuallyHiddenText = _interopRequireDefault(require("terra-visually-hidden-text"));
var _DataGridModule = _interopRequireDefault(require("./DataGrid.module.scss"));
require("./_elementPolyfill");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
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) { (0, _defineProperty2.default)(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; }
var cx = _bind.default.bind(_DataGridModule.default);
var propTypes = {
/**
* String that identifies the element (or elements) that labels the grid.
*/
ariaLabelledBy: _propTypes.default.string,
/**
* String that labels the grid for accessibility. If ariaLabelledBy is specified, ariaLabel will not be used.
*/
ariaLabel: _propTypes.default.string,
/**
* String that will be used to identify the Grid. If multiple grids are on the same page, each grid should have
* a unique id.
*/
id: _propTypes.default.string.isRequired,
/**
* Data for content in the body of the Grid. Rows will be rendered in the order given.
*/
rows: _propTypes.default.arrayOf(_terraTable.rowShape),
/**
* Data for content in the body of the table. Sections will be rendered in the order given.
*/
sections: _propTypes.default.arrayOf(_terraTable.sectionShape),
/**
* Data for pinned columns. Pinned columns are the stickied leftmost columns of the grid.
* Columns will be presented in the order given.
*/
pinnedColumns: _propTypes.default.arrayOf(_terraTable.columnShape),
/**
* Data for overflow columns. Overflow columns are rendered in the Data Grid's horizontal overflow.
* Columns will be presented in the order given.
*/
overflowColumns: _propTypes.default.arrayOf(_terraTable.columnShape),
/**
* Number indicating the default column width in px. This value will be used if no overriding width value is provided on a per-column basis.
*/
defaultColumnWidth: _propTypes.default.number,
/**
* String that specifies the column height. Any valid CSS height value is accepted.
*/
columnHeaderHeight: _propTypes.default.string,
/**
* Numeric increment in pixels to adjust column width when resizing via the keyboard.
*/
columnResizeIncrement: _propTypes.default.number,
/**
* String that specifies the height for the rows in the grid. Any valid CSS value is accepted.
*/
rowHeight: _propTypes.default.string,
/**
* Number indicating the index of the column that represents row header. Index is 0 based and cannot exceed one less than the number of columns in the grid.
*/
rowHeaderIndex: _terraTable.validateRowHeaderIndex,
/**
* Function that is called when a resizable column is resized. Parameters:
* @param {string} columnId columnId
* @param {string} requestedWidth requestedWidth
*/
onColumnResize: _propTypes.default.func,
/**
* Callback function that is called when a selectable cell is selected. Parameters:
* @param {string} rowId rowId
* @param {string} columnId columnId
* @param {object} event event
*/
onCellSelect: _propTypes.default.func,
/**
* Function that is called when a collapsible section is selected. Parameters: `onSectionSelect(sectionId)`
*/
onSectionSelect: _propTypes.default.func,
/**
* Callback function that is called when a selectable column is selected. Parameters:
* @param {string} columnId columnId
*/
onColumnSelect: _propTypes.default.func,
/**
* Callback function that is called when all selected cells need to be unselected. Parameters: none.
*/
onClearSelection: _propTypes.default.func,
/**
* Callback function that is called when a range selection occurs. Parameters:
* @param {number} rowIndex RowIndex of the cell from which the range selection was triggered.
* @param {number} columnIndex ColumnIndex of the cell from which the range selection was triggered.
* @param {number} direction Direction keycode representing the direction of the selection.
*/
onRangeSelection: _propTypes.default.func,
/**
* Callback function that is called when you click on the row selection header.
*/
onRowSelectionHeaderSelect: _propTypes.default.func,
/**
* Callback function that is called when a cell range selection occurs. Parameters:
* @param {number} rowIndex RowIndex of the cell from which the range selection was triggered.
* @param {number} columnIndex ColumnIndex of the cell from which the range selection was triggered.
* @param {number} direction Direction keycode representing the direction of the selection.
*/
onCellRangeSelect: _propTypes.default.func,
/**
* Boolean indicating whether or not the DataGrid should allow entire rows to be selectable. An additional column will be
* rendered to allow for row selection to occur.
*/
hasSelectableRows: _propTypes.default.bool,
/**
* Boolean indicating whether or not the DataGrid should hide the column headers.
*/
hasVisibleColumnHeaders: _propTypes.default.bool,
/**
* String that specifies the minimum height for the rows on the table. rowHeight takes precedence if valid CSS value is passed.
* With this property the height of the cell will grow to fit the cell content.
*/
rowMinimumHeight: _propTypes.default.string,
/**
* Determines if focus is moved to the interactive element of a cell when a single button or hyperlink element is the only interactive element.
*/
isAutoFocusEnabled: _propTypes.default.bool
};
var defaultProps = {
rowHeaderIndex: 0,
defaultColumnWidth: 200,
columnHeaderHeight: '2.5rem',
pinnedColumns: [],
overflowColumns: [],
rows: [],
hasVisibleColumnHeaders: true
};
var DataGrid = /*#__PURE__*/(0, _react.forwardRef)(function (props, ref) {
var _grid$current;
var ariaLabel = props.ariaLabel,
ariaLabelledBy = props.ariaLabelledBy,
columnHeaderHeight = props.columnHeaderHeight,
columnResizeIncrement = props.columnResizeIncrement,
defaultColumnWidth = props.defaultColumnWidth,
hasVisibleColumnHeaders = props.hasVisibleColumnHeaders,
hasSelectableRows = props.hasSelectableRows,
id = props.id,
onCellRangeSelect = props.onCellRangeSelect,
onCellSelect = props.onCellSelect,
onClearSelection = props.onClearSelection,
onColumnResize = props.onColumnResize,
onColumnSelect = props.onColumnSelect,
onRangeSelection = props.onRangeSelection,
onRowSelectionHeaderSelect = props.onRowSelectionHeaderSelect,
onSectionSelect = props.onSectionSelect,
overflowColumns = props.overflowColumns,
pinnedColumns = props.pinnedColumns,
rowHeaderIndex = props.rowHeaderIndex,
rowHeight = props.rowHeight,
rows = props.rows,
sections = props.sections,
rowMinimumHeight = props.rowMinimumHeight,
isAutoFocusEnabled = props.isAutoFocusEnabled;
// By default, all grid-based components have selectable cells.
var dataGridRows = (0, _react.useMemo)(function () {
return rows.map(function (row) {
return _objectSpread(_objectSpread({}, row), {}, {
cells: row.cells.map(function (cell) {
return _objectSpread(_objectSpread({}, cell), {}, {
isSelectable: cell.isSelectable !== false
});
})
});
});
}, [rows]);
// Reference variable for WorklistDataGrid table element
var grid = (0, _react.useRef)();
var gridContainerRef = (0, _react.useRef)();
var tableContainerRef = (0, _react.useRef)();
var tableBodyColumnsRef = (0, _react.useRef)();
var handleFocus = (0, _react.useRef)(true);
var focusedCellRef = (0, _react.useRef)({
rowId: '',
columnId: ''
});
var _useState = (0, _react.useState)(false),
_useState2 = (0, _slicedToArray2.default)(_useState, 2),
checkResizable = _useState2[0],
setCheckResizable = _useState2[1];
// check if at least one column has an action prop
// same check is done in Table, but as Table can be a stand-alone component, it can't rely on a passed prop.
var hasColumnHeaderActions = (0, _terraTable.hasColumnActions)(pinnedColumns) || (0, _terraTable.hasColumnActions)(overflowColumns);
// eslint-disable-next-line no-nested-ternary
var firstRowIndex = hasVisibleColumnHeaders ? 0 : 1;
// if columns are not visible then set the first selectable row index to 1 or 2
var _useState3 = (0, _react.useState)(firstRowIndex),
_useState4 = (0, _slicedToArray2.default)(_useState3, 2),
focusedRow = _useState4[0],
setFocusedRow = _useState4[1];
var _useState5 = (0, _react.useState)(0),
_useState6 = (0, _slicedToArray2.default)(_useState5, 2),
focusedCol = _useState6[0],
setFocusedCol = _useState6[1];
// Aria live region message management
var _useState7 = (0, _react.useState)(null),
_useState8 = (0, _slicedToArray2.default)(_useState7, 2),
cellAriaLiveMessage = _useState8[0],
setCellAriaLiveMessage = _useState8[1];
var gridContextValue = (0, _react.useMemo)(function () {
return {
role: _terraTable.GridConstants.GRID,
setCellAriaLiveMessage: setCellAriaLiveMessage,
tableRef: grid,
tableContainerRef: tableContainerRef,
tableBodyColumnsRef: tableBodyColumnsRef,
isAutoFocusEnabled: isAutoFocusEnabled
};
}, [grid, isAutoFocusEnabled, tableContainerRef]);
// -------------------------------------
// functions
var isRowSelectionCell = (0, _react.useCallback)(function (columnIndex) {
return hasSelectableRows && columnIndex === 0;
}, [hasSelectableRows]);
var isSection = (0, _react.useCallback)(function (rowIndex) {
return grid.current.rows[rowIndex].hasAttribute('data-section-id') || grid.current.rows[rowIndex].hasAttribute('data-subsection-id');
}, []);
var setFocusedRowCol = (0, _react.useCallback)(function (newRowIndex, newColIndex, makeActiveElement) {
var _focusedCell5;
setCellAriaLiveMessage(null);
setFocusedRow(newRowIndex);
setFocusedCol(newColIndex);
if (newColIndex < tableBodyColumnsRef.current.length) {
focusedCellRef.current = {
rowId: grid.current.rows[newRowIndex].getAttribute('data-row-id'),
columnId: tableBodyColumnsRef.current[newColIndex].id
};
}
if (!makeActiveElement) {
return;
}
var focusedCell;
if (isSection(newRowIndex)) {
var _focusedCell;
var _grid$current$rows$ne = (0, _slicedToArray2.default)(grid.current.rows[newRowIndex].cells, 1);
focusedCell = _grid$current$rows$ne[0];
if (!focusedCell.hasAttribute('tabindex')) {
focusedCell = grid.current.rows[newRowIndex].querySelector('button');
}
(_focusedCell = focusedCell) === null || _focusedCell === void 0 || _focusedCell.focus();
return;
}
focusedCell = grid.current.rows[newRowIndex].cells[newColIndex];
// If there are multiple focusable elements, set focus on the cell
if ((0, _focusManagement.default)(focusedCell).length > 1) {
var _focusedCell2;
(_focusedCell2 = focusedCell) === null || _focusedCell2 === void 0 || _focusedCell2.focus();
return;
}
// Check if cell is in header row (for focusing on resize handles)
var isHeaderRow = newRowIndex === 0 || hasColumnHeaderActions && newRowIndex === 1;
// Set focus to a single header button or hyperlink if they are the only content in cell
var cellButtonOrHyperlink = focusedCell.querySelector('a, button');
if (isHeaderRow && !focusedCell.hasAttribute('tabindex') || isAutoFocusEnabled && cellButtonOrHyperlink) {
var _focusedCell3;
focusedCell = focusedCell.querySelector('a, button, [role="button"]');
(_focusedCell3 = focusedCell) === null || _focusedCell3 === void 0 || _focusedCell3.focus();
return;
}
// Set focus on input field (checkbox) of row selection cells.
var rowSelectionCheckbox = focusedCell.querySelector('input');
if (isRowSelectionCell(newColIndex) && rowSelectionCheckbox) {
var _focusedCell4;
focusedCell = rowSelectionCheckbox;
(_focusedCell4 = focusedCell) === null || _focusedCell4 === void 0 || _focusedCell4.focus();
return;
}
(_focusedCell5 = focusedCell) === null || _focusedCell5 === void 0 || _focusedCell5.focus();
}, [isSection, hasColumnHeaderActions, isAutoFocusEnabled, isRowSelectionCell]);
// The focus is handled by the DataGrid. However, there are times
// when the other components may want to change the currently focus
// cells. In order to do so, these datagrid methods will be exposed to
// allow those components to request focus change.
(0, _react.useImperativeHandle)(ref, function () {
return {
setFocusedRowCol: setFocusedRowCol,
getFocusedCell: function getFocusedCell() {
return {
row: focusedRow,
col: focusedCol
};
},
getGridRef: function getGridRef() {
return grid.current;
},
getTableBodyColumnsRef: function getTableBodyColumnsRef() {
return tableBodyColumnsRef.current;
}
};
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[focusedCol, focusedRow]);
// -------------------------------------
var handleMoveCellFocus = function handleMoveCellFocus(fromCell, toCell) {
if (!isSection(toCell.row)) {
// Obtain coordinate rectangles for grid container, column header, and new cell selection
var gridContainerRect = tableContainerRef.current.getBoundingClientRect();
var columnHeaderRect = grid.current.rows[0].getBoundingClientRect();
var nextCellRect = grid.current.rows[toCell.row].cells[toCell.col].getBoundingClientRect();
// Calculate horizontal scroll offset for right boundary
if (nextCellRect.right > gridContainerRect.right) {
tableContainerRef.current.scrollBy(nextCellRect.right - gridContainerRect.right, 0);
} else {
// Calculate horizontal scroll offset for left boundary
var scrollOffsetX = 0;
var pinnedColumnOffset = hasSelectableRows ? 1 : 0;
var lastPinnedColumnIndex = pinnedColumns.length - 1 + pinnedColumnOffset;
if (lastPinnedColumnIndex >= 0) {
if (toCell.col > lastPinnedColumnIndex) {
var lastPinnedColumnRect = grid.current.rows[toCell.row].cells[lastPinnedColumnIndex].getBoundingClientRect();
scrollOffsetX = nextCellRect.left - lastPinnedColumnRect.right;
}
} else {
scrollOffsetX = nextCellRect.left - gridContainerRect.left;
}
if (scrollOffsetX < 0) {
tableContainerRef.current.scrollBy(scrollOffsetX, 0);
}
}
// Calculate vertical scroll offset
var scrollOffsetY = nextCellRect.top - columnHeaderRect.bottom;
if (scrollOffsetY < 0) {
tableContainerRef.current.scrollBy(0, scrollOffsetY);
}
}
setFocusedRowCol(toCell.row, toCell.col, true);
};
// callBack to trigger re-focusing when focused row or col didn't change, but focus update is needed
var triggerFocus = (0, _react.useCallback)(function () {
return setFocusedRowCol(focusedRow, focusedCol, true);
}, [setFocusedRowCol, focusedRow, focusedCol]);
// -------------------------------------
// event handlers
/**
* Move focus to next focusable element outside the data grid
*/
var moveFocusFromGrid = function moveFocusFromGrid(moveForward) {
// add all elements we want to include in our selection
var focusableElementSelector = "#".concat(id, ", a[href]:not([tabindex='-1']), area[href]:not([tabindex='-1']), input:not([disabled]):not([tabindex='-1']), ") + 'select:not([disabled]):not([tabindex=\'-1\']), textarea:not([disabled]):not([tabindex=\'-1\']), button:not([disabled]):not([tabindex=\'-1\']), ' + 'iframe:not([tabindex=\'-1\']), [tabindex]:not([tabindex=\'-1\']), [contentEditable=true]:not([tabindex=\'-1\'])';
var focusableElements = (0, _toConsumableArray2.default)(document.body.querySelectorAll("".concat(focusableElementSelector))).filter(function (element) {
return !element.hasAttribute('disabled') && !element.getAttribute('aria-hidden') && !!(element.offsetWidth || element.offsetHeight || element.getClientRects().length) && window.getComputedStyle(element).visibility !== 'hidden' && element.closest('[inert]') === null && (element.id === id || !gridContainerRef.current.contains(element));
});
// Identify index of the active element in the DOM excluding data grid children
var index = focusableElements.indexOf(gridContainerRef.current);
if (index > -1) {
// Move focus outside data grid
var indexOffset = moveForward ? 1 : -1;
var newFocusElement;
if (index + indexOffset < focusableElements.length) {
newFocusElement = focusableElements[index + indexOffset];
} else if (focusableElements[0].id !== id) {
// eslint-disable-next-line prefer-destructuring
newFocusElement = focusableElements[0];
}
if (newFocusElement) {
newFocusElement.focus();
}
}
};
/**
*
* @param {HTMLElement} element - The element to check if it is a text input
* @returns True if the element is a text input. Otherwise, false.
*/
var isTextInput = function isTextInput(element) {
var tagName = element.tagName;
if (tagName.toLowerCase() === 'input') {
var validTypes = ['text', 'password', 'number', 'email', 'tel', 'url', 'search', 'date', 'datetime', 'datetime-local', 'time', 'month', 'week'];
var inputType = element.type;
return validTypes.indexOf(inputType) >= 0;
}
return false;
};
var handleKeyDown = function handleKeyDown(event) {
var cellCoordinates = {
row: focusedRow,
col: focusedCol
};
var nextRow = cellCoordinates.row;
var nextCol = cellCoordinates.col;
setCheckResizable(false);
var targetElement = event.target;
var key = event.keyCode;
// Allow default behavior if the event target is an editable field
if (key !== KeyCode.KEY_TAB && (isTextInput(targetElement) || ['textarea', 'select'].indexOf(targetElement.tagName.toLowerCase()) >= 0 || targetElement.hasAttribute('contentEditable') && targetElement.getAttribute('contentEditable') !== false)) {
return;
}
// Disable horizontal navigation when section has focus
if ((key === KeyCode.KEY_RIGHT || key === KeyCode.KEY_LEFT) && isSection(cellCoordinates.row)) {
event.preventDefault();
return;
}
// Get grid row count
var gridRowCount = grid.current.rows.length;
switch (key) {
case KeyCode.KEY_UP:
nextRow -= 1;
// Select proper header cell column
if ((nextRow === 0 || hasColumnHeaderActions && nextRow === 1) && !(cellCoordinates.row === 1 && hasColumnHeaderActions)) {
// Account for navigation to column header and action header rows
nextCol = tableBodyColumnsRef.current[nextCol].columnHeaderIndex;
}
break;
case KeyCode.KEY_DOWN:
nextRow += 1;
// Select starting cell for column header when navigating to table body
if (cellCoordinates.row === 0 && !hasColumnHeaderActions || hasColumnHeaderActions && cellCoordinates.row === 1) {
// Account for navigation from column header and action header rows
var startCellIndex = 0;
for (var headerIndex = 0; headerIndex < cellCoordinates.col; headerIndex += 1) {
startCellIndex += grid.current.rows[0].cells[headerIndex].colSpan || 1;
}
nextCol = startCellIndex;
}
break;
case KeyCode.KEY_LEFT:
if (event.metaKey) {
// Mac: Ctrl + Cmd + Left
// Win: Ctrl + Home
nextCol = 0;
if (event.ctrlKey) {
// Mac: Ctrl + Cmd + Left
// Windows: Ctrl + Home
nextRow = 1; // Assumption is that the first row is the column Heading.
}
} else {
// Left key
nextCol -= 1;
setCheckResizable(cellCoordinates.row === 0 || hasColumnHeaderActions && cellCoordinates.row === 1);
}
break;
case KeyCode.KEY_RIGHT:
if (event.metaKey) {
// Mac: Cmd + Right
// Win: End
nextCol = grid.current.rows[nextRow].cells.length - 1;
if (event.ctrlKey) {
// Mac: Ctrl + Cmd + Right
// Windows: Ctrl + End
nextRow = gridRowCount - 1;
}
} else {
// Right key
nextCol += 1;
}
break;
case KeyCode.KEY_HOME:
nextCol = 0;
if (event.ctrlKey) {
nextRow = 1; // Assumption is that the first row is the column Heading.
}
break;
case KeyCode.KEY_END:
nextCol = grid.current.rows[nextRow].cells.length - 1; // Col are zero based.
if (event.ctrlKey) {
// Though rows are zero based, the header is the first row so the rowsLength will
// always be one more than then actual number of data rows.
nextRow = gridRowCount - 1;
}
break;
case KeyCode.KEY_ESCAPE:
if (onClearSelection) {
onClearSelection();
}
event.preventDefault();
return;
case KeyCode.KEY_TAB:
moveFocusFromGrid(!event.shiftKey);
event.preventDefault();
return;
default:
return;
}
var upDownKeys = new Set([KeyCode.KEY_UP, KeyCode.KEY_DOWN]);
var directionalKeys = new Set([KeyCode.KEY_UP, KeyCode.KEY_DOWN, KeyCode.KEY_LEFT, KeyCode.KEY_RIGHT]);
if (onRangeSelection && event.shiftKey && upDownKeys.has(event.keyCode)) {
onRangeSelection(cellCoordinates.row, cellCoordinates.col, event.keyCode);
}
if (onCellRangeSelect && event.shiftKey && directionalKeys.has(event.keyCode)) {
onCellRangeSelect(cellCoordinates.row, cellCoordinates.col, event.keyCode);
}
if (nextRow >= gridRowCount || !isSection(nextRow) && nextCol >= grid.current.rows[nextRow].cells.length) {
event.preventDefault(); // prevent the page from moving with the arrow keys.
return;
}
if (nextCol < 0 || nextRow < firstRowIndex) {
event.preventDefault(); // prevent the page from moving with the arrow keys.
return;
}
handleMoveCellFocus(cellCoordinates, {
row: nextRow,
col: nextCol
});
event.preventDefault(); // prevent the page from moving with the arrow keys.
};
var handleMouseDown = function handleMouseDown(event) {
// Determine cell containing click event
var clickTarget = event.target;
var targetCell = clickTarget.closest('td, th');
// Store focused cell position
if (targetCell) {
// Prevent focus event updates when triggered by mouse
handleFocus.current = false;
setCheckResizable(false);
setFocusedRowCol(targetCell.parentElement.rowIndex, targetCell.cellIndex);
}
};
/**
* Establishes selection state when the WorklistDataGrid gains focus
* @param {*} event focus event data
*/
var onFocus = function onFocus(event) {
if (!event.currentTarget.contains(event.relatedTarget)) {
// Not triggered when swapping focus between children
if (handleFocus.current) {
var newRowIndex = focusedRow;
var newColumnIndex = focusedCol;
// Check for last focused row ID. If found set the index. Otherwise set it to the last focused row or last index.
if (focusedCellRef.current.rowId) {
newRowIndex = (0, _toConsumableArray2.default)(grid.current.rows).findIndex(function (row) {
return row.getAttribute('data-row-id') === focusedCellRef.current.rowId;
});
newRowIndex = newRowIndex === -1 ? Math.min(focusedRow, grid.current.rows.length - 1) : newRowIndex;
}
// Check for last focused column ID. If found set the index. Otherwise set it to the last focused column or last index.
if (focusedCellRef.current.columnId) {
newColumnIndex = (0, _toConsumableArray2.default)(grid.current.rows[newRowIndex].cells).findIndex(function (column) {
return column.getAttribute('data-cell-column-id') === focusedCellRef.current.columnId;
});
newColumnIndex = newColumnIndex === -1 ? Math.min(focusedCol, grid.current.rows[newRowIndex].cells.length - 1) : newColumnIndex;
}
setFocusedRowCol(newRowIndex, newColumnIndex, true);
}
}
handleFocus.current = true;
};
// -------------------------------------
var isGridActive = (_grid$current = grid.current) === null || _grid$current === void 0 ? void 0 : _grid$current.contains(document.activeElement);
var isOneOfHeaderRows = focusedRow === 0 || hasColumnHeaderActions && focusedRow === 1;
return (
/*#__PURE__*/
// eslint-disable-next-line jsx-a11y/no-static-element-interactions
_react.default.createElement("div", {
ref: gridContainerRef,
onKeyDown: handleKeyDown,
onMouseDown: handleMouseDown,
onFocus: onFocus,
id: id,
className: cx('data-grid-container')
}, /*#__PURE__*/_react.default.createElement(_terraTable.GridContext.Provider, {
value: gridContextValue
}, /*#__PURE__*/_react.default.createElement(_terraTable.default, {
id: "".concat(id, "-table"),
rows: dataGridRows,
sections: sections,
ariaLabelledBy: ariaLabelledBy,
ariaLabel: ariaLabel,
activeColumnIndex: isGridActive && (focusedRow === 0 || hasColumnHeaderActions && focusedRow === 1) ? focusedCol : undefined,
focusedRowIndex: focusedRow,
triggerFocus: triggerFocus,
isActiveColumnResizing: isOneOfHeaderRows && checkResizable,
columnResizeIncrement: columnResizeIncrement,
pinnedColumns: pinnedColumns,
overflowColumns: overflowColumns,
defaultColumnWidth: defaultColumnWidth,
columnHeaderHeight: columnHeaderHeight,
rowHeight: rowHeight,
rowHeaderIndex: rowHeaderIndex,
onColumnResize: onColumnResize,
onColumnSelect: onColumnSelect,
onSectionSelect: onSectionSelect,
onRowSelectionHeaderSelect: onRowSelectionHeaderSelect,
onCellSelect: onCellSelect,
rowSelectionMode: hasSelectableRows ? 'multiple' : undefined,
hasVisibleColumnHeaders: hasVisibleColumnHeaders,
isStriped: true,
rowMinimumHeight: rowMinimumHeight
})), /*#__PURE__*/_react.default.createElement(_terraVisuallyHiddenText.default, {
"aria-live": "polite",
"aria-atomic": "true",
text: cellAriaLiveMessage
}))
);
});
DataGrid.defaultProps = defaultProps;
DataGrid.propTypes = propTypes;
var _default = exports.default = DataGrid;