"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.stopPropagationAndPreventDefault = exports.skipFocusInContainerTo = exports.onPageDownOrPageUp = exports.onKeyDownFocusHandler = exports.onHomeEndDown = exports.onFocusReFocusDraggable = exports.onArrowKeyDown = exports.isTab = exports.isPageUp = exports.isPageDownOrPageUp = exports.isPageDown = exports.isHomeOrEnd = exports.isHome = exports.isEscape = exports.isEnd = exports.isArrowUp = exports.isArrowRightOrArrowLeft = exports.isArrowRight = exports.isArrowKey = exports.isArrowDownOrArrowUp = exports.isArrowDown = exports.handleSkipFocus = exports.getTableSkipFocus = exports.getRowindex = exports.getRowRendererClassName = exports.getRowByAriaRowindex = exports.getNotesContainerClassName = exports.getNewAriaRowindex = exports.getNewAriaColindex = exports.getFocusedRow = exports.getFocusedDataColindexCell = exports.getFocusedColumn = exports.getFocusedAriaColindexCell = exports.getFocusableChidren = exports.getFocusOnFromArrowKey = exports.getFirstOrLastAriaRowindex = exports.getFirstNonVisibleAriaRowindex = exports.getElementWithMatchingAriaColindex = exports.getColindex = exports.focusedCellIsPlainColumnHeader = exports.focusedCellHasMoreFocusableChildren = exports.focusedCellHasAlwaysOpenHoverContent = exports.focusColumn = exports.elementOrChildrenHasFocus = exports.arrayIndexToAriaIndex = exports.ariaIndexToArrayIndex = exports.FIRST_ARIA_INDEX = exports.DATA_ROWINDEX_ATTRIBUTE = exports.DATA_COLINDEX_ATTRIBUTE = exports.ARIA_ROWINDEX_ATTRIBUTE = exports.ARIA_COLINDEX_ATTRIBUTE = void 0; var _securitysolutionTGrid = require("@kbn/securitysolution-t-grid"); /* * 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; you may not use this file except in compliance with the Elastic License * 2.0. */ /** * The name of the ARIA attribute representing a column, used in conjunction with * the ARIA: grid role https://www.w3.org/TR/wai-aria-practices-1.1/examples/grid/dataGrids.html */ const ARIA_COLINDEX_ATTRIBUTE = 'aria-colindex'; /** * This alternative attribute to `aria-colindex` is used to decorate the data * in existing `EuiTable`s to enable keyboard navigation with minimal * refactoring of existing code until we're ready to migrate to `EuiDataGrid`. * It may be applied directly to keyboard-focusable elements and thus doesn't * have exactly the same semantics as `aria-colindex`. */ exports.ARIA_COLINDEX_ATTRIBUTE = ARIA_COLINDEX_ATTRIBUTE; const DATA_COLINDEX_ATTRIBUTE = 'data-colindex'; /** * The name of the ARIA attribute representing a row, used in conjunction with * the ARIA: grid role https://www.w3.org/TR/wai-aria-practices-1.1/examples/grid/dataGrids.html */ exports.DATA_COLINDEX_ATTRIBUTE = DATA_COLINDEX_ATTRIBUTE; const ARIA_ROWINDEX_ATTRIBUTE = 'aria-rowindex'; /** * This alternative attribute to `aria-rowindex` is used to decorate the data * in existing `EuiTable`s to enable keyboard navigation with minimal * refactoring of existing code until we're ready to migrate to `EuiDataGrid`. * It's typically applied to `` elements via `EuiTable`'s `rowProps` prop. */ exports.ARIA_ROWINDEX_ATTRIBUTE = ARIA_ROWINDEX_ATTRIBUTE; const DATA_ROWINDEX_ATTRIBUTE = 'data-rowindex'; /** `aria-colindex` and `aria-rowindex` start at one */ exports.DATA_ROWINDEX_ATTRIBUTE = DATA_ROWINDEX_ATTRIBUTE; const FIRST_ARIA_INDEX = 1; /** Converts an aria index, which starts at one, to an array index, which starts at zero */ exports.FIRST_ARIA_INDEX = FIRST_ARIA_INDEX; const ariaIndexToArrayIndex = ariaIndex => ariaIndex - 1; /** Converts an array index, which starts at zero, to an aria index, which starts at one */ exports.ariaIndexToArrayIndex = ariaIndexToArrayIndex; const arrayIndexToAriaIndex = arrayIndex => arrayIndex + 1; /** Returns `true` if the left or right arrow was pressed */ exports.arrayIndexToAriaIndex = arrayIndexToAriaIndex; const isArrowRightOrArrowLeft = event => event.key === 'ArrowLeft' || event.key === 'ArrowRight'; /** Returns `true` if the down arrow key was pressed */ exports.isArrowRightOrArrowLeft = isArrowRightOrArrowLeft; const isArrowDown = event => event.key === 'ArrowDown'; /** Returns `true` if the up arrow key was pressed */ exports.isArrowDown = isArrowDown; const isArrowUp = event => event.key === 'ArrowUp'; /** Returns `true` if the down or up arrow was pressed */ exports.isArrowUp = isArrowUp; const isArrowDownOrArrowUp = event => isArrowDown(event) || isArrowUp(event); /** Returns `true` if an arrow key was pressed */ exports.isArrowDownOrArrowUp = isArrowDownOrArrowUp; const isArrowKey = event => isArrowRightOrArrowLeft(event) || isArrowDownOrArrowUp(event); /** Returns `true` if the right arrow key was pressed */ exports.isArrowKey = isArrowKey; const isArrowRight = event => event.key === 'ArrowRight'; /** Returns `true` if the escape key was pressed */ exports.isArrowRight = isArrowRight; const isEscape = event => event.key === 'Escape'; /** Returns `true` if the home key was pressed */ exports.isEscape = isEscape; const isHome = event => event.key === 'Home'; /** Returns `true` if the end key was pressed */ exports.isHome = isHome; const isEnd = event => event.key === 'End'; /** Returns `true` if the home or end key was pressed */ exports.isEnd = isEnd; const isHomeOrEnd = event => isHome(event) || isEnd(event); /** Returns `true` if the page up key was pressed */ exports.isHomeOrEnd = isHomeOrEnd; const isPageUp = event => event.key === 'PageUp'; /** Returns `true` if the page down key was pressed */ exports.isPageUp = isPageUp; const isPageDown = event => event.key === 'PageDown'; /** Returns `true` if the page up or page down key was pressed */ exports.isPageDown = isPageDown; const isPageDownOrPageUp = event => isPageDown(event) || isPageUp(event); /** Returns `true` if the tab key was pressed */ exports.isPageDownOrPageUp = isPageDownOrPageUp; const isTab = event => event.key === 'Tab'; /** Returns `previous` or `next`, depending on which arrow key was pressed */ exports.isTab = isTab; const getFocusOnFromArrowKey = event => event.key === 'ArrowUp' || event.key === 'ArrowLeft' ? 'previous' : 'next'; /** * Returns the column that directly owns focus, or contains a focused element, * using the `aria-colindex` attribute. */ exports.getFocusOnFromArrowKey = getFocusOnFromArrowKey; const getFocusedColumn = ({ colindexAttribute, element }) => { var _element$querySelecto; return (_element$querySelecto = element === null || element === void 0 ? void 0 : element.querySelector(`[${colindexAttribute}]:focus-within`)) !== null && _element$querySelecto !== void 0 ? _element$querySelecto : null; }; /** Returns the numeric `aria-colindex` of the specified element */ exports.getFocusedColumn = getFocusedColumn; const getColindex = ({ colindexAttribute, element }) => (element === null || element === void 0 ? void 0 : element.getAttribute(colindexAttribute)) != null ? Number(element === null || element === void 0 ? void 0 : element.getAttribute(colindexAttribute)) : null; /** Returns the row that directly owns focus, or contains a focused element */ exports.getColindex = getColindex; const getFocusedRow = ({ rowindexAttribute, element }) => { var _element$querySelecto2; return (_element$querySelecto2 = element === null || element === void 0 ? void 0 : element.querySelector(`[${rowindexAttribute}]:focus-within`)) !== null && _element$querySelecto2 !== void 0 ? _element$querySelecto2 : null; }; /** Returns the numeric `aria-rowindex` of the specified element */ exports.getFocusedRow = getFocusedRow; const getRowindex = ({ rowindexAttribute, element }) => (element === null || element === void 0 ? void 0 : element.getAttribute(rowindexAttribute)) != null ? Number(element === null || element === void 0 ? void 0 : element.getAttribute(rowindexAttribute)) : null; /** Returns the row with the specified `aria-rowindex` */ exports.getRowindex = getRowindex; const getRowByAriaRowindex = ({ ariaRowindex, element, rowindexAttribute }) => { var _element$querySelecto3; return (_element$querySelecto3 = element === null || element === void 0 ? void 0 : element.querySelector(`[${rowindexAttribute}="${ariaRowindex}"]`)) !== null && _element$querySelecto3 !== void 0 ? _element$querySelecto3 : null; }; /** Returns the `previous` or `next` `aria-colindex` relative to the currently focused `aria-colindex` */ exports.getRowByAriaRowindex = getRowByAriaRowindex; const getNewAriaColindex = ({ focusedAriaColindex, focusOn, maxAriaColindex }) => { const newAriaColindex = focusOn === 'previous' ? focusedAriaColindex - 1 : focusedAriaColindex + 1; if (newAriaColindex < FIRST_ARIA_INDEX) { return FIRST_ARIA_INDEX; } if (newAriaColindex > maxAriaColindex) { return maxAriaColindex; } return newAriaColindex; }; /** Returns the element at the specified `aria-colindex` */ exports.getNewAriaColindex = getNewAriaColindex; const getElementWithMatchingAriaColindex = ({ ariaColindex, colindexAttribute, element }) => { var _element$querySelecto4; if ((element === null || element === void 0 ? void 0 : element.getAttribute(colindexAttribute)) === `${ariaColindex}`) { return element; // the current element has it } return (_element$querySelecto4 = element === null || element === void 0 ? void 0 : element.querySelector(`[${colindexAttribute}="${ariaColindex}"]`)) !== null && _element$querySelecto4 !== void 0 ? _element$querySelecto4 : null; }; /** Returns the `previous` or `next` `aria-rowindex` relative to the currently focused `aria-rowindex` */ exports.getElementWithMatchingAriaColindex = getElementWithMatchingAriaColindex; const getNewAriaRowindex = ({ focusedAriaRowindex, focusOn, maxAriaRowindex }) => { const newAriaRowindex = focusOn === 'previous' ? focusedAriaRowindex - 1 : focusedAriaRowindex + 1; if (newAriaRowindex < FIRST_ARIA_INDEX) { return FIRST_ARIA_INDEX; } if (newAriaRowindex > maxAriaRowindex) { return maxAriaRowindex; } return newAriaRowindex; }; /** Returns the first `aria-rowindex` if the home key is pressed, otherwise the last `aria-rowindex` is returned */ exports.getNewAriaRowindex = getNewAriaRowindex; const getFirstOrLastAriaRowindex = ({ event, maxAriaRowindex }) => isHome(event) ? FIRST_ARIA_INDEX : maxAriaRowindex; exports.getFirstOrLastAriaRowindex = getFirstOrLastAriaRowindex; /** * SIDE EFFECT: mutates the DOM by focusing the specified column * returns the `aria-colindex` of the newly-focused column */ const focusColumn = ({ colindexAttribute, containerElement, ariaColindex, ariaRowindex, rowindexAttribute }) => { if (containerElement == null) { return { newFocusedColumnAriaColindex: null, newFocusedColumn: null }; } const row = getRowByAriaRowindex({ ariaRowindex, element: containerElement, rowindexAttribute }); const column = getElementWithMatchingAriaColindex({ ariaColindex, colindexAttribute, element: row }); if (column != null) { column.focus(); // DOM mutation side effect return { newFocusedColumnAriaColindex: ariaColindex, newFocusedColumn: column }; } return { newFocusedColumnAriaColindex: null, newFocusedColumn: null }; }; exports.focusColumn = focusColumn; const getRowRendererClassName = ariaRowindex => `${_securitysolutionTGrid.ROW_RENDERER_CLASS_NAME}-${ariaRowindex}`; exports.getRowRendererClassName = getRowRendererClassName; const getNotesContainerClassName = ariaRowindex => `${_securitysolutionTGrid.NOTES_CONTAINER_CLASS_NAME}-${ariaRowindex}`; /** * This function implements arrow key support for the `onKeyDownFocusHandler`. * * See the `Keyboard Support` section of * https://www.w3.org/TR/wai-aria-practices-1.1/examples/grid/dataGrids.html * for details */ exports.getNotesContainerClassName = getNotesContainerClassName; const onArrowKeyDown = ({ colindexAttribute, containerElement, event, focusedAriaColindex, focusedAriaRowindex, maxAriaColindex, maxAriaRowindex, onColumnFocused, rowindexAttribute }) => { if (isArrowDown(event) && event.shiftKey) { const firstRowRendererDraggable = containerElement === null || containerElement === void 0 ? void 0 : containerElement.querySelector(`.${getRowRendererClassName(focusedAriaRowindex)} .${_securitysolutionTGrid.DRAGGABLE_KEYBOARD_WRAPPER_CLASS_NAME}`); if (firstRowRendererDraggable) { firstRowRendererDraggable.focus(); return; } } if (isArrowRight(event) && event.shiftKey) { const firstNoteContent = containerElement === null || containerElement === void 0 ? void 0 : containerElement.querySelector(`.${getNotesContainerClassName(focusedAriaRowindex)} .${_securitysolutionTGrid.NOTE_CONTENT_CLASS_NAME}`); if (firstNoteContent) { firstNoteContent.focus(); return; } } const ariaColindex = isArrowRightOrArrowLeft(event) ? getNewAriaColindex({ focusedAriaColindex, focusOn: getFocusOnFromArrowKey(event), maxAriaColindex }) : focusedAriaColindex; const ariaRowindex = isArrowDownOrArrowUp(event) ? getNewAriaRowindex({ focusedAriaRowindex, focusOn: getFocusOnFromArrowKey(event), maxAriaRowindex }) : focusedAriaRowindex; const { newFocusedColumn, newFocusedColumnAriaColindex } = focusColumn({ ariaColindex, ariaRowindex, colindexAttribute, containerElement, rowindexAttribute }); if (onColumnFocused != null && newFocusedColumnAriaColindex != null) { onColumnFocused({ newFocusedColumn, newFocusedColumnAriaColindex }); } }; /** * This function implements `home` and `end` key support for the `onKeyDownFocusHandler`. * * See the `Keyboard Support` section of * https://www.w3.org/TR/wai-aria-practices-1.1/examples/grid/dataGrids.html * for details */ exports.onArrowKeyDown = onArrowKeyDown; const onHomeEndDown = ({ colindexAttribute, containerElement, event, focusedAriaRowindex, maxAriaColindex, maxAriaRowindex, onColumnFocused, rowindexAttribute }) => { const ariaColindex = isHome(event) ? FIRST_ARIA_INDEX : maxAriaColindex; const ariaRowindex = event.ctrlKey ? getFirstOrLastAriaRowindex({ event, maxAriaRowindex }) : focusedAriaRowindex; const { newFocusedColumn, newFocusedColumnAriaColindex } = focusColumn({ ariaColindex, ariaRowindex, colindexAttribute, containerElement, rowindexAttribute }); if (isHome(event) && event.ctrlKey) { containerElement === null || containerElement === void 0 ? void 0 : containerElement.scrollTo(0, 0); } if (onColumnFocused != null && newFocusedColumnAriaColindex != null) { onColumnFocused({ newFocusedColumn, newFocusedColumnAriaColindex }); } }; /** Returns `true` if the specified row is completely visible in the container */ exports.onHomeEndDown = onHomeEndDown; const isRowCompletelyScrolledIntoView = ({ container, row }) => { const rect = row.getBoundingClientRect(); const top = rect.top; const bottom = rect.bottom; return top >= container.top && bottom <= container.bottom; }; const getFirstNonVisibleAriaRowindex = ({ focusedAriaRowindex, element, event, maxAriaRowindex, rowindexAttribute }) => { var _element$querySelecto5; const defaultAriaRowindex = isPageUp(event) ? FIRST_ARIA_INDEX : maxAriaRowindex; // default to the first or last row if (element === null) { return defaultAriaRowindex; } const container = element.getBoundingClientRect(); const rows = Array.from((_element$querySelecto5 = element.querySelectorAll(`[${rowindexAttribute}]`)) !== null && _element$querySelecto5 !== void 0 ? _element$querySelecto5 : []); if (isPageUp(event)) { return arrayIndexToAriaIndex(rows.reduceRight((found, row, i) => i < ariaIndexToArrayIndex(focusedAriaRowindex) && found === ariaIndexToArrayIndex(defaultAriaRowindex) && !isRowCompletelyScrolledIntoView({ container, row }) ? i : found, ariaIndexToArrayIndex(defaultAriaRowindex))); } else if (isPageDown(event)) { return arrayIndexToAriaIndex(rows.reduce((found, row, i) => i > ariaIndexToArrayIndex(focusedAriaRowindex) && found === ariaIndexToArrayIndex(defaultAriaRowindex) && !isRowCompletelyScrolledIntoView({ container, row }) ? i : found, ariaIndexToArrayIndex(defaultAriaRowindex))); } else { return defaultAriaRowindex; } }; /** * This function implements `page down` and `page up` key support for the `onKeyDownFocusHandler`. * * See the `Keyboard Support` section of * https://www.w3.org/TR/wai-aria-practices-1.1/examples/grid/dataGrids.html * for details */ exports.getFirstNonVisibleAriaRowindex = getFirstNonVisibleAriaRowindex; const onPageDownOrPageUp = ({ colindexAttribute, containerElement, event, focusedAriaColindex, focusedAriaRowindex, maxAriaRowindex, onColumnFocused, rowindexAttribute }) => { const ariaRowindex = getFirstNonVisibleAriaRowindex({ element: containerElement, event, focusedAriaRowindex, maxAriaRowindex, rowindexAttribute }); const { newFocusedColumn, newFocusedColumnAriaColindex } = focusColumn({ ariaColindex: focusedAriaColindex, ariaRowindex, colindexAttribute, containerElement, rowindexAttribute }); if (onColumnFocused != null) { onColumnFocused({ newFocusedColumn, newFocusedColumnAriaColindex }); } }; /** * This function has side effects: It stops propagation of the provided * `KeyboardEvent` and prevents the browser's default behavior. */ exports.onPageDownOrPageUp = onPageDownOrPageUp; const stopPropagationAndPreventDefault = event => { event.stopPropagation(); event.preventDefault(); }; /** * This function adds keyboard accessability to any `containerElement` that * renders its rows with support for `aria-colindex` and `aria-rowindex`. * * To use this function, invoke it in the `onKeyDown` handler of the specified * `containerElement`. * * See the `Keyboard Support` section of * https://www.w3.org/TR/wai-aria-practices-1.1/examples/grid/dataGrids.html * for details of the behavior. */ exports.stopPropagationAndPreventDefault = stopPropagationAndPreventDefault; const onKeyDownFocusHandler = ({ colindexAttribute, containerElement, event, maxAriaColindex, maxAriaRowindex, onColumnFocused, rowindexAttribute }) => { var _getColindex; // NOTE: When a row has focus, but none of the columns in that row have focus // because, for example, the row renderer contained by the row has focus, we // default `focusedAriaColindex` to be the first non-action column: const focusedAriaColindex = (_getColindex = getColindex({ colindexAttribute, element: getFocusedColumn({ colindexAttribute, element: containerElement }) })) !== null && _getColindex !== void 0 ? _getColindex : FIRST_ARIA_INDEX; const focusedAriaRowindex = getRowindex({ rowindexAttribute, element: getFocusedRow({ rowindexAttribute, element: containerElement }) }); if (focusedAriaColindex != null && focusedAriaRowindex != null) { if (isArrowKey(event)) { stopPropagationAndPreventDefault(event); onArrowKeyDown({ colindexAttribute, containerElement, event, focusedAriaColindex, focusedAriaRowindex, maxAriaColindex, maxAriaRowindex, onColumnFocused, rowindexAttribute }); } else if (isHomeOrEnd(event)) { stopPropagationAndPreventDefault(event); onHomeEndDown({ colindexAttribute, containerElement, event, focusedAriaRowindex, maxAriaColindex, maxAriaRowindex, onColumnFocused, rowindexAttribute }); } else if (isPageDownOrPageUp(event)) { stopPropagationAndPreventDefault(event); onPageDownOrPageUp({ colindexAttribute, containerElement, event, focusedAriaColindex, focusedAriaRowindex, maxAriaRowindex, onColumnFocused, rowindexAttribute }); } } }; /** * An `onFocus` event handler that focuses the first child draggable * keyboard handler */ exports.onKeyDownFocusHandler = onKeyDownFocusHandler; const onFocusReFocusDraggable = event => { var _event$target$querySe; return (_event$target$querySe = event.target.querySelector(`.${_securitysolutionTGrid.DRAGGABLE_KEYBOARD_WRAPPER_CLASS_NAME}`)) === null || _event$target$querySe === void 0 ? void 0 : _event$target$querySe.focus(); }; /** Returns `true` when the element, or one of it's children has focus */ exports.onFocusReFocusDraggable = onFocusReFocusDraggable; const elementOrChildrenHasFocus = element => element === document.activeElement || (element === null || element === void 0 ? void 0 : element.querySelector(':focus-within')) != null; exports.elementOrChildrenHasFocus = elementOrChildrenHasFocus; /** * This function has a side effect. It focuses the first element with a * matching `className` in the `containerElement`. */ const skipFocusInContainerTo = ({ containerElement, className }) => { var _containerElement$que; return containerElement === null || containerElement === void 0 ? void 0 : (_containerElement$que = containerElement.querySelector(`.${className}`)) === null || _containerElement$que === void 0 ? void 0 : _containerElement$que.focus(); }; /** * Returns a table cell's focusable children, which may be one of the following * a) a `HTMLButtonElement` that does NOT have the `disabled` attribute * b) an element with the `DRAGGABLE_KEYBOARD_WRAPPER_CLASS_NAME` */ exports.skipFocusInContainerTo = skipFocusInContainerTo; const getFocusableChidren = cell => { var _cell$querySelectorAl; return Array.from((_cell$querySelectorAl = cell === null || cell === void 0 ? void 0 : cell.querySelectorAll(`button:not([disabled]), button:not([tabIndex="-1"]), .${_securitysolutionTGrid.DRAGGABLE_KEYBOARD_WRAPPER_CLASS_NAME}`)) !== null && _cell$querySelectorAl !== void 0 ? _cell$querySelectorAl : []); }; exports.getFocusableChidren = getFocusableChidren; /** * If the value of `skipFocus` is `SKIP_FOCUS_BACKWARDS` or `SKIP_FOCUS_FORWARD` * this function will invoke the provided `onSkipFocusBackwards` or * `onSkipFocusForward` functions respectively. * * If `skipFocus` is `SKIP_FOCUS_NOOP`, the `onSkipFocusBackwards` and * `onSkipFocusForward` functions will not be invoked. */ const handleSkipFocus = ({ onSkipFocusBackwards, onSkipFocusForward, skipFocus }) => { switch (skipFocus) { case 'SKIP_FOCUS_BACKWARDS': onSkipFocusBackwards(); break; case 'SKIP_FOCUS_FORWARD': onSkipFocusForward(); break; case 'SKIP_FOCUS_NOOP': // fall through to the default, which does nothing default: break; } }; /** * The provided `focusedCell` may contain multiple focusable children. For, * example, the cell may contain multiple `HTMLButtonElement`s that represent * actions, or the cell may contain multiple draggables. * * This function returns `true` when there are still more children of the cell * that should receive focus when the tab key is pressed. * * When this function returns `true`, the caller should NOT move focus away * from the table. Instead, the browser's "natural" focus management should be * allowed to automatically focus the next (or previous) focusable child of the * cell. */ exports.handleSkipFocus = handleSkipFocus; const focusedCellHasMoreFocusableChildren = ({ focusedCell, shiftKey }) => { const focusableChildren = getFocusableChidren(focusedCell); if (focusableChildren.length === 0) { return false; // there no children to focus } const firstOrLastChild = shiftKey ? focusableChildren[0] : focusableChildren[focusableChildren.length - 1]; return firstOrLastChild !== document.activeElement; }; /** * Returns `true` when the provided `focusedCell` has always-open hover * content (i.e. a hover menu) * * When this function returns true, the caller should `NOT` move focus away * from the table. Instead, the browser's "natural" focus management should * be allowed to manage focus between the table and the hover content. */ exports.focusedCellHasMoreFocusableChildren = focusedCellHasMoreFocusableChildren; const focusedCellHasAlwaysOpenHoverContent = focusedCell => (focusedCell === null || focusedCell === void 0 ? void 0 : focusedCell.querySelector(`.${_securitysolutionTGrid.HOVER_ACTIONS_ALWAYS_SHOW_CLASS_NAME}`)) != null; exports.focusedCellHasAlwaysOpenHoverContent = focusedCellHasAlwaysOpenHoverContent; /** * Returns true if the focused cell is a plain, non-action `columnheader` */ const focusedCellIsPlainColumnHeader = focusedCell => (focusedCell === null || focusedCell === void 0 ? void 0 : focusedCell.getAttribute('role')) === 'columnheader' && !(focusedCell !== null && focusedCell !== void 0 && focusedCell.classList.contains('siemEventsTable__thGroupActions')); /** * This function, which works with tables that use the `aria-colindex` or * `data-colindex` attributes, examines the focus state of the table, and * returns a `SkipFocus` enumeration. * * The `SkipFocus` return value indicates whether the caller should skip focus * to "before" the table, "after" the table, or take no action, and let the * browser's "natural" focus management manage focus. */ exports.focusedCellIsPlainColumnHeader = focusedCellIsPlainColumnHeader; const getTableSkipFocus = ({ containerElement, getFocusedCell, shiftKey, tableHasFocus, tableClassName }) => { if (tableHasFocus(containerElement)) { const focusedCell = getFocusedCell({ containerElement, tableClassName }); if (focusedCell == null) { return 'SKIP_FOCUS_NOOP'; // no cells have focus, often because something with a `dialog` role has focus } if (focusedCellHasMoreFocusableChildren({ focusedCell, shiftKey }) && !focusedCellIsPlainColumnHeader(focusedCell)) { return 'SKIP_FOCUS_NOOP'; // the focused cell still has focusable children } if (focusedCellHasAlwaysOpenHoverContent(focusedCell)) { return 'SKIP_FOCUS_NOOP'; // the focused cell has always-open hover content } return shiftKey ? 'SKIP_FOCUS_BACKWARDS' : 'SKIP_FOCUS_FORWARD'; // the caller should skip focus "before" or "after" the table } return 'SKIP_FOCUS_NOOP'; // the table does NOT have focus }; /** * Returns the focused cell for tables that use `aria-colindex` */ exports.getTableSkipFocus = getTableSkipFocus; const getFocusedAriaColindexCell = ({ containerElement, tableClassName }) => { var _containerElement$que2; return (_containerElement$que2 = containerElement === null || containerElement === void 0 ? void 0 : containerElement.querySelector(`.${tableClassName} [aria-colindex]:focus-within`)) !== null && _containerElement$que2 !== void 0 ? _containerElement$que2 : null; }; /** * Returns the focused cell for tables that use `data-colindex` */ exports.getFocusedAriaColindexCell = getFocusedAriaColindexCell; const getFocusedDataColindexCell = ({ containerElement, tableClassName }) => { var _containerElement$que3; return (_containerElement$que3 = containerElement === null || containerElement === void 0 ? void 0 : containerElement.querySelector(`.${tableClassName} [data-colindex]:focus-within`)) !== null && _containerElement$que3 !== void 0 ? _containerElement$que3 : null; }; exports.getFocusedDataColindexCell = getFocusedDataColindexCell;