@elastic/eui 92.0.0 → 92.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. package/dist/eui_theme_dark.css +3 -18
  2. package/dist/eui_theme_dark.min.css +1 -1
  3. package/dist/eui_theme_light.css +3 -18
  4. package/dist/eui_theme_light.min.css +1 -1
  5. package/es/components/aspect_ratio/aspect_ratio.js +1 -1
  6. package/es/components/collapsible_nav_beta/collapsible_nav_body_footer.js +7 -3
  7. package/es/components/collapsible_nav_beta/collapsible_nav_body_footer.styles.js +4 -4
  8. package/es/components/datagrid/body/{data_grid_cell.js → cell/data_grid_cell.js} +56 -209
  9. package/es/components/datagrid/body/{data_grid_cell_actions.js → cell/data_grid_cell_actions.js} +5 -5
  10. package/es/components/datagrid/body/{data_grid_cell_popover.js → cell/data_grid_cell_popover.js} +4 -4
  11. package/es/components/datagrid/body/{data_grid_cell_wrapper.js → cell/data_grid_cell_wrapper.js} +1 -1
  12. package/es/components/datagrid/body/cell/focus_utils.js +166 -0
  13. package/es/components/datagrid/body/cell/index.js +11 -0
  14. package/es/components/datagrid/body/data_grid_body.js +0 -2
  15. package/es/components/datagrid/body/data_grid_body_custom.js +1 -7
  16. package/es/components/datagrid/body/data_grid_body_virtualized.js +1 -7
  17. package/es/components/datagrid/body/footer/data_grid_footer_row.js +1 -2
  18. package/es/components/datagrid/body/header/data_grid_control_header_cell.js +3 -6
  19. package/es/components/datagrid/body/header/data_grid_header_cell.js +27 -12
  20. package/es/components/datagrid/body/header/data_grid_header_cell_wrapper.js +45 -116
  21. package/es/components/datagrid/body/header/data_grid_header_row.js +5 -10
  22. package/es/components/datagrid/body/header/use_data_grid_header.js +3 -14
  23. package/es/components/datagrid/data_grid.js +2 -12
  24. package/es/components/datagrid/utils/focus.js +25 -54
  25. package/es/components/datagrid/utils/scrolling.js +1 -1
  26. package/es/components/flyout/flyout_resizable.js +10 -10
  27. package/es/components/flyout/flyout_resizable.styles.js +12 -6
  28. package/es/components/resizable_container/helpers.js +5 -6
  29. package/es/components/resizable_container/resizable_button.js +13 -4
  30. package/es/components/resizable_container/resizable_button.styles.js +18 -8
  31. package/es/components/resizable_container/resizable_container.js +28 -22
  32. package/es/components/steps/step_number.styles.js +6 -7
  33. package/es/components/tree_view/tree_view.js +9 -2
  34. package/eui.d.ts +125 -90
  35. package/i18ntokens.json +108 -72
  36. package/lib/components/aspect_ratio/aspect_ratio.js +1 -1
  37. package/lib/components/collapsible_nav_beta/collapsible_nav_body_footer.js +7 -3
  38. package/lib/components/collapsible_nav_beta/collapsible_nav_body_footer.styles.js +4 -4
  39. package/lib/components/datagrid/body/{data_grid_cell.js → cell/data_grid_cell.js} +56 -209
  40. package/lib/components/datagrid/body/{data_grid_cell_actions.js → cell/data_grid_cell_actions.js} +5 -5
  41. package/lib/components/datagrid/body/{data_grid_cell_popover.js → cell/data_grid_cell_popover.js} +4 -4
  42. package/lib/components/datagrid/body/{data_grid_cell_wrapper.js → cell/data_grid_cell_wrapper.js} +1 -1
  43. package/lib/components/datagrid/body/cell/focus_utils.js +174 -0
  44. package/lib/components/datagrid/body/cell/index.js +32 -0
  45. package/lib/components/datagrid/body/data_grid_body.js +0 -2
  46. package/lib/components/datagrid/body/data_grid_body_custom.js +2 -8
  47. package/lib/components/datagrid/body/data_grid_body_virtualized.js +2 -8
  48. package/lib/components/datagrid/body/footer/data_grid_footer_row.js +5 -6
  49. package/lib/components/datagrid/body/header/data_grid_control_header_cell.js +3 -6
  50. package/lib/components/datagrid/body/header/data_grid_header_cell.js +35 -20
  51. package/lib/components/datagrid/body/header/data_grid_header_cell_wrapper.js +47 -119
  52. package/lib/components/datagrid/body/header/data_grid_header_row.js +5 -10
  53. package/lib/components/datagrid/body/header/use_data_grid_header.js +10 -24
  54. package/lib/components/datagrid/data_grid.js +4 -14
  55. package/lib/components/datagrid/utils/focus.js +26 -56
  56. package/lib/components/datagrid/utils/scrolling.js +2 -2
  57. package/lib/components/flyout/flyout_resizable.js +10 -10
  58. package/lib/components/flyout/flyout_resizable.styles.js +12 -6
  59. package/lib/components/resizable_container/helpers.js +7 -7
  60. package/lib/components/resizable_container/resizable_button.js +13 -4
  61. package/lib/components/resizable_container/resizable_button.styles.js +18 -8
  62. package/lib/components/resizable_container/resizable_container.js +28 -22
  63. package/lib/components/steps/step_number.styles.js +6 -7
  64. package/lib/components/tree_view/tree_view.js +9 -2
  65. package/optimize/es/components/aspect_ratio/aspect_ratio.js +1 -1
  66. package/optimize/es/components/collapsible_nav_beta/collapsible_nav_body_footer.js +7 -3
  67. package/optimize/es/components/collapsible_nav_beta/collapsible_nav_body_footer.styles.js +4 -4
  68. package/optimize/es/components/datagrid/body/{data_grid_cell.js → cell/data_grid_cell.js} +56 -209
  69. package/optimize/es/components/datagrid/body/{data_grid_cell_actions.js → cell/data_grid_cell_actions.js} +5 -5
  70. package/optimize/es/components/datagrid/body/{data_grid_cell_popover.js → cell/data_grid_cell_popover.js} +4 -4
  71. package/optimize/es/components/datagrid/body/{data_grid_cell_wrapper.js → cell/data_grid_cell_wrapper.js} +1 -1
  72. package/optimize/es/components/datagrid/body/cell/focus_utils.js +153 -0
  73. package/optimize/es/components/datagrid/body/cell/index.js +11 -0
  74. package/optimize/es/components/datagrid/body/data_grid_body_custom.js +1 -5
  75. package/optimize/es/components/datagrid/body/data_grid_body_virtualized.js +1 -5
  76. package/optimize/es/components/datagrid/body/footer/data_grid_footer_row.js +1 -2
  77. package/optimize/es/components/datagrid/body/header/data_grid_control_header_cell.js +2 -4
  78. package/optimize/es/components/datagrid/body/header/data_grid_header_cell.js +25 -10
  79. package/optimize/es/components/datagrid/body/header/data_grid_header_cell_wrapper.js +41 -115
  80. package/optimize/es/components/datagrid/body/header/data_grid_header_row.js +4 -8
  81. package/optimize/es/components/datagrid/body/header/use_data_grid_header.js +3 -13
  82. package/optimize/es/components/datagrid/data_grid.js +2 -12
  83. package/optimize/es/components/datagrid/utils/focus.js +25 -54
  84. package/optimize/es/components/datagrid/utils/scrolling.js +1 -1
  85. package/optimize/es/components/flyout/flyout_resizable.js +10 -10
  86. package/optimize/es/components/flyout/flyout_resizable.styles.js +12 -6
  87. package/optimize/es/components/resizable_container/helpers.js +5 -6
  88. package/optimize/es/components/resizable_container/resizable_button.js +5 -2
  89. package/optimize/es/components/resizable_container/resizable_button.styles.js +18 -8
  90. package/optimize/es/components/resizable_container/resizable_container.js +28 -22
  91. package/optimize/es/components/steps/step_number.styles.js +6 -7
  92. package/optimize/es/components/tree_view/tree_view.js +9 -2
  93. package/optimize/lib/components/aspect_ratio/aspect_ratio.js +1 -1
  94. package/optimize/lib/components/collapsible_nav_beta/collapsible_nav_body_footer.js +7 -3
  95. package/optimize/lib/components/collapsible_nav_beta/collapsible_nav_body_footer.styles.js +4 -4
  96. package/optimize/lib/components/datagrid/body/{data_grid_cell.js → cell/data_grid_cell.js} +56 -209
  97. package/optimize/lib/components/datagrid/body/{data_grid_cell_actions.js → cell/data_grid_cell_actions.js} +5 -5
  98. package/optimize/lib/components/datagrid/body/{data_grid_cell_popover.js → cell/data_grid_cell_popover.js} +4 -4
  99. package/optimize/lib/components/datagrid/body/{data_grid_cell_wrapper.js → cell/data_grid_cell_wrapper.js} +1 -1
  100. package/optimize/lib/components/datagrid/body/cell/focus_utils.js +163 -0
  101. package/optimize/lib/components/datagrid/body/cell/index.js +32 -0
  102. package/optimize/lib/components/datagrid/body/data_grid_body_custom.js +2 -6
  103. package/optimize/lib/components/datagrid/body/data_grid_body_virtualized.js +2 -6
  104. package/optimize/lib/components/datagrid/body/footer/data_grid_footer_row.js +5 -6
  105. package/optimize/lib/components/datagrid/body/header/data_grid_control_header_cell.js +2 -4
  106. package/optimize/lib/components/datagrid/body/header/data_grid_header_cell.js +25 -10
  107. package/optimize/lib/components/datagrid/body/header/data_grid_header_cell_wrapper.js +41 -115
  108. package/optimize/lib/components/datagrid/body/header/data_grid_header_row.js +4 -8
  109. package/optimize/lib/components/datagrid/body/header/use_data_grid_header.js +4 -14
  110. package/optimize/lib/components/datagrid/data_grid.js +4 -14
  111. package/optimize/lib/components/datagrid/utils/focus.js +26 -56
  112. package/optimize/lib/components/datagrid/utils/scrolling.js +2 -2
  113. package/optimize/lib/components/flyout/flyout_resizable.js +10 -10
  114. package/optimize/lib/components/flyout/flyout_resizable.styles.js +12 -6
  115. package/optimize/lib/components/resizable_container/helpers.js +7 -7
  116. package/optimize/lib/components/resizable_container/resizable_button.js +5 -2
  117. package/optimize/lib/components/resizable_container/resizable_button.styles.js +18 -8
  118. package/optimize/lib/components/resizable_container/resizable_container.js +28 -22
  119. package/optimize/lib/components/steps/step_number.styles.js +6 -7
  120. package/optimize/lib/components/tree_view/tree_view.js +9 -2
  121. package/package.json +1 -1
  122. package/src/components/datagrid/body/header/_data_grid_header_row.scss +8 -7
  123. package/test-env/components/aspect_ratio/aspect_ratio.js +1 -1
  124. package/test-env/components/collapsible_nav_beta/collapsible_nav_body_footer.js +7 -3
  125. package/test-env/components/collapsible_nav_beta/collapsible_nav_body_footer.styles.js +4 -4
  126. package/test-env/components/datagrid/body/{data_grid_cell.js → cell/data_grid_cell.js} +56 -209
  127. package/test-env/components/datagrid/body/{data_grid_cell_actions.js → cell/data_grid_cell_actions.js} +5 -5
  128. package/test-env/components/datagrid/body/{data_grid_cell_popover.js → cell/data_grid_cell_popover.js} +4 -4
  129. package/test-env/components/datagrid/body/{data_grid_cell_wrapper.js → cell/data_grid_cell_wrapper.js} +1 -1
  130. package/test-env/components/datagrid/body/cell/focus_utils.js +172 -0
  131. package/test-env/components/datagrid/body/cell/index.js +32 -0
  132. package/test-env/components/datagrid/body/data_grid_body.js +0 -2
  133. package/test-env/components/datagrid/body/data_grid_body_custom.js +2 -8
  134. package/test-env/components/datagrid/body/data_grid_body_virtualized.js +2 -8
  135. package/test-env/components/datagrid/body/footer/data_grid_footer_row.js +5 -6
  136. package/test-env/components/datagrid/body/header/data_grid_control_header_cell.js +3 -6
  137. package/test-env/components/datagrid/body/header/data_grid_header_cell.js +25 -10
  138. package/test-env/components/datagrid/body/header/data_grid_header_cell_wrapper.js +44 -116
  139. package/test-env/components/datagrid/body/header/data_grid_header_row.js +5 -10
  140. package/test-env/components/datagrid/body/header/use_data_grid_header.js +4 -14
  141. package/test-env/components/datagrid/data_grid.js +4 -14
  142. package/test-env/components/datagrid/utils/focus.js +26 -56
  143. package/test-env/components/datagrid/utils/scrolling.js +2 -2
  144. package/test-env/components/flyout/flyout_resizable.js +10 -10
  145. package/test-env/components/flyout/flyout_resizable.styles.js +12 -6
  146. package/test-env/components/resizable_container/helpers.js +7 -7
  147. package/test-env/components/resizable_container/resizable_button.js +13 -4
  148. package/test-env/components/resizable_container/resizable_button.styles.js +18 -8
  149. package/test-env/components/resizable_container/resizable_container.js +28 -22
  150. package/test-env/components/steps/step_number.styles.js +6 -7
  151. package/test-env/components/tree_view/tree_view.js +9 -2
  152. package/es/components/datagrid/body/header/header_is_interactive.js +0 -58
  153. package/lib/components/datagrid/body/header/header_is_interactive.js +0 -63
  154. package/optimize/es/components/datagrid/body/header/header_is_interactive.js +0 -53
  155. package/optimize/lib/components/datagrid/body/header/header_is_interactive.js +0 -61
  156. package/test-env/components/datagrid/body/header/header_is_interactive.js +0 -61
@@ -0,0 +1,153 @@
1
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
2
+ /*
3
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
4
+ * or more contributor license agreements. Licensed under the Elastic License
5
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
6
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
7
+ * Side Public License, v 1.
8
+ */
9
+
10
+ import React, { useEffect, useState, useMemo } from 'react';
11
+ import { tabbable } from 'tabbable';
12
+ import { keys } from '../../../../services';
13
+ import { EuiFocusTrap } from '../../../focus_trap';
14
+ import { EuiScreenReaderOnly } from '../../../accessibility';
15
+ import { EuiI18n } from '../../../i18n';
16
+
17
+ /**
18
+ * This internal utility component is used by all cells, both header and body/footer cells.
19
+ * It always handles:
20
+ * 1. Removing any interactive children from keyboard tab order on cell mount
21
+ * 2. Listening for focus on any interactive children and updating the cell focus context
22
+ *
23
+ * It should *only* render focus traps for:
24
+ * 1. Header cells that are `actions: false` but still have interactive children
25
+ * 2. Body cells that are `isExpandable: false` but still have interactive children
26
+ */
27
+ import { jsx as ___EmotionJSX } from "@emotion/react";
28
+ export var HandleInteractiveChildren = function HandleInteractiveChildren(_ref) {
29
+ var cellEl = _ref.cellEl,
30
+ children = _ref.children,
31
+ updateCellFocusContext = _ref.updateCellFocusContext,
32
+ renderFocusTrap = _ref.renderFocusTrap;
33
+ var _useState = useState(false),
34
+ _useState2 = _slicedToArray(_useState, 2),
35
+ hasInteractiveChildren = _useState2[0],
36
+ setHasInteractiveChildren = _useState2[1];
37
+
38
+ // On mount, disable all interactive children
39
+ useEffect(function () {
40
+ if (cellEl) {
41
+ var interactiveChildren = disableInteractives(cellEl);
42
+ if (renderFocusTrap) {
43
+ setHasInteractiveChildren(interactiveChildren.length > 0);
44
+ }
45
+ }
46
+ }, [cellEl, renderFocusTrap]);
47
+
48
+ // Ensure that any interactive children that are clicked update the latest cell focus context
49
+ useEffect(function () {
50
+ if (cellEl) {
51
+ var onFocus = function onFocus() {
52
+ return updateCellFocusContext();
53
+ };
54
+ cellEl.addEventListener('focus', onFocus, true); // useCapture listens for focus on children
55
+ return function () {
56
+ cellEl.removeEventListener('focus', onFocus, true);
57
+ };
58
+ }
59
+ }, [cellEl, updateCellFocusContext]);
60
+ var _children = useMemo(function () {
61
+ return ___EmotionJSX(React.Fragment, null, children);
62
+ }, [children]);
63
+ if (!cellEl) return _children; // Do nothing if cell has yet to mount or is unmounting
64
+ if (!renderFocusTrap) return _children; // Cells with default actions / expansion popovers do not need to trap
65
+ if (!hasInteractiveChildren) return _children; // No need to focus trap if no children are interactive
66
+
67
+ return ___EmotionJSX(FocusTrappedChildren, {
68
+ cellEl: cellEl
69
+ }, children);
70
+ };
71
+
72
+ /**
73
+ * Cells with interactive children but no cell popover expansion should render a
74
+ * focus trap that can be entered with the Enter key, which cycles keyboard tabs
75
+ * through the cell contents only, and exited with the Escape key
76
+ */
77
+ export var FocusTrappedChildren = function FocusTrappedChildren(_ref2) {
78
+ var cellEl = _ref2.cellEl,
79
+ children = _ref2.children;
80
+ var _useState3 = useState(false),
81
+ _useState4 = _slicedToArray(_useState3, 2),
82
+ isCellEntered = _useState4[0],
83
+ setIsCellEntered = _useState4[1];
84
+ useEffect(function () {
85
+ if (isCellEntered) {
86
+ enableAndFocusInteractives(cellEl);
87
+ } else {
88
+ disableInteractives(cellEl);
89
+ }
90
+ }, [isCellEntered, cellEl]);
91
+ useEffect(function () {
92
+ var onKeyUp = function onKeyUp(event) {
93
+ switch (event.key) {
94
+ case keys.ENTER:
95
+ case keys.F2:
96
+ event.preventDefault();
97
+ setIsCellEntered(true);
98
+ break;
99
+ case keys.ESCAPE:
100
+ event.preventDefault();
101
+ setIsCellEntered(function (isCellEntered) {
102
+ if (isCellEntered === true) {
103
+ requestAnimationFrame(function () {
104
+ return cellEl.focus();
105
+ }); // move focus to cell
106
+ return false;
107
+ }
108
+ return isCellEntered;
109
+ });
110
+ break;
111
+ }
112
+ };
113
+ cellEl.addEventListener('keyup', onKeyUp);
114
+ return function () {
115
+ cellEl.removeEventListener('keyup', onKeyUp);
116
+ };
117
+ }, [cellEl]);
118
+ return ___EmotionJSX(EuiFocusTrap, {
119
+ disabled: !isCellEntered,
120
+ onDeactivation: function onDeactivation() {
121
+ return setIsCellEntered(false);
122
+ },
123
+ clickOutsideDisables: true
124
+ }, children, ___EmotionJSX(EuiScreenReaderOnly, null, ___EmotionJSX("p", null, ' - ', ___EmotionJSX(EuiI18n
125
+ // eslint-disable-next-line local/i18n
126
+ , {
127
+ token: "euiDataGridCell.focusTrapEnterPrompt",
128
+ default: "Press the Enter key to interact with this cell's contents."
129
+ }))));
130
+ };
131
+
132
+ /**
133
+ * Utility fns for managing child interactive tabIndex state
134
+ */
135
+
136
+ var disableInteractives = function disableInteractives(cell) {
137
+ var interactives = tabbable(cell);
138
+ interactives.forEach(function (element) {
139
+ element.setAttribute('data-euigrid-tab-managed', 'true');
140
+ element.setAttribute('tabIndex', '-1');
141
+ });
142
+ return interactives;
143
+ };
144
+ var enableAndFocusInteractives = function enableAndFocusInteractives(cell) {
145
+ var interactives = cell.querySelectorAll('[data-euigrid-tab-managed]');
146
+ interactives.forEach(function (element, i) {
147
+ element.setAttribute('tabIndex', '0');
148
+ if (i === 0) {
149
+ element.focus();
150
+ }
151
+ });
152
+ return interactives;
153
+ };
@@ -0,0 +1,11 @@
1
+ /*
2
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3
+ * or more contributor license agreements. Licensed under the Elastic License
4
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
5
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
6
+ * Side Public License, v 1.
7
+ */
8
+
9
+ export { EuiDataGridCell } from './data_grid_cell';
10
+ export { Cell } from './data_grid_cell_wrapper';
11
+ export { DataGridCellPopoverContext, useCellPopover } from './data_grid_cell_popover';
@@ -20,7 +20,7 @@ import { useDefaultColumnWidth, useColumnWidths } from '../utils/col_widths';
20
20
  import { useRowHeightUtils, useDefaultRowHeight } from '../utils/row_heights';
21
21
  import { useDataGridHeader } from './header';
22
22
  import { useDataGridFooter } from './footer';
23
- import { Cell } from './data_grid_cell_wrapper';
23
+ import { Cell } from './cell';
24
24
  import { jsx as ___EmotionJSX } from "@emotion/react";
25
25
  export var EuiDataGridBodyCustomRender = function EuiDataGridBodyCustomRender(_ref) {
26
26
  var renderCustomGridBody = _ref.renderCustomGridBody,
@@ -35,8 +35,6 @@ export var EuiDataGridBodyCustomRender = function EuiDataGridBodyCustomRender(_r
35
35
  renderCellPopover = _ref.renderCellPopover,
36
36
  renderFooterCellValue = _ref.renderFooterCellValue,
37
37
  interactiveCellId = _ref.interactiveCellId,
38
- headerIsInteractive = _ref.headerIsInteractive,
39
- handleHeaderMutation = _ref.handleHeaderMutation,
40
38
  setVisibleColumns = _ref.setVisibleColumns,
41
39
  switchColumnPos = _ref.switchColumnPos,
42
40
  onColumnResize = _ref.onColumnResize,
@@ -82,8 +80,6 @@ export var EuiDataGridBodyCustomRender = function EuiDataGridBodyCustomRender(_r
82
80
  * Header & footer
83
81
  */
84
82
  var _useDataGridHeader = useDataGridHeader({
85
- headerIsInteractive: headerIsInteractive,
86
- handleHeaderMutation: handleHeaderMutation,
87
83
  switchColumnPos: switchColumnPos,
88
84
  setVisibleColumns: setVisibleColumns,
89
85
  leadingControlColumns: leadingControlColumns,
@@ -18,7 +18,7 @@ import { VariableSizeGrid as Grid } from 'react-window';
18
18
  import { useResizeObserver } from '../../observer/resize_observer';
19
19
  import { useDataGridHeader } from './header';
20
20
  import { useDataGridFooter } from './footer';
21
- import { Cell } from './data_grid_cell_wrapper';
21
+ import { Cell } from './cell';
22
22
  import { useRowManager } from './data_grid_row_manager';
23
23
  import { useFinalGridDimensions, useUnconstrainedHeight, useVirtualizeContainerWidth } from '../utils/grid_height_width';
24
24
  import { useDefaultColumnWidth, useColumnWidths } from '../utils/col_widths';
@@ -82,8 +82,6 @@ export var EuiDataGridBodyVirtualized = function EuiDataGridBodyVirtualized(_ref
82
82
  renderFooterCellValue = _ref3.renderFooterCellValue,
83
83
  interactiveCellId = _ref3.interactiveCellId,
84
84
  pagination = _ref3.pagination,
85
- headerIsInteractive = _ref3.headerIsInteractive,
86
- handleHeaderMutation = _ref3.handleHeaderMutation,
87
85
  setVisibleColumns = _ref3.setVisibleColumns,
88
86
  switchColumnPos = _ref3.switchColumnPos,
89
87
  onColumnResize = _ref3.onColumnResize,
@@ -133,8 +131,6 @@ export var EuiDataGridBodyVirtualized = function EuiDataGridBodyVirtualized(_ref
133
131
  * Header & footer
134
132
  */
135
133
  var _useDataGridHeader = useDataGridHeader({
136
- headerIsInteractive: headerIsInteractive,
137
- handleHeaderMutation: handleHeaderMutation,
138
134
  switchColumnPos: switchColumnPos,
139
135
  setVisibleColumns: setVisibleColumns,
140
136
  leadingControlColumns: leadingControlColumns,
@@ -11,8 +11,7 @@ var _excluded = ["leadingControlColumns", "trailingControlColumns", "columns", "
11
11
 
12
12
  import classnames from 'classnames';
13
13
  import React, { forwardRef, memo, useContext } from 'react';
14
- import { EuiDataGridCell } from '../data_grid_cell';
15
- import { DataGridCellPopoverContext } from '../data_grid_cell_popover';
14
+ import { EuiDataGridCell, DataGridCellPopoverContext } from '../cell';
16
15
  import { jsx as ___EmotionJSX } from "@emotion/react";
17
16
  var renderEmpty = function renderEmpty() {
18
17
  return null;
@@ -13,8 +13,7 @@ import { EuiDataGridHeaderCellWrapper } from './data_grid_header_cell_wrapper';
13
13
  import { jsx as ___EmotionJSX } from "@emotion/react";
14
14
  export var EuiDataGridControlHeaderCell = function EuiDataGridControlHeaderCell(_ref) {
15
15
  var controlColumn = _ref.controlColumn,
16
- index = _ref.index,
17
- headerIsInteractive = _ref.headerIsInteractive;
16
+ index = _ref.index;
18
17
  var HeaderCellRender = controlColumn.headerCellRender,
19
18
  headerCellProps = controlColumn.headerCellProps,
20
19
  width = controlColumn.width,
@@ -23,8 +22,7 @@ export var EuiDataGridControlHeaderCell = function EuiDataGridControlHeaderCell(
23
22
  className: classNames('euiDataGridHeaderCell--controlColumn', headerCellProps === null || headerCellProps === void 0 ? void 0 : headerCellProps.className),
24
23
  id: id,
25
24
  index: index,
26
- width: width,
27
- headerIsInteractive: headerIsInteractive
25
+ width: width
28
26
  }), ___EmotionJSX("div", {
29
27
  className: "euiDataGridHeaderCell__content"
30
28
  }, ___EmotionJSX(HeaderCellRender, null)));
@@ -1,6 +1,6 @@
1
1
  import _extends from "@babel/runtime/helpers/extends";
2
- import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
3
2
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
3
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
4
4
  function _EMOTION_STRINGIFIED_CSS_ERROR__() { return "You have tried to stringify object returned from `css` function. It isn't supposed to be used directly (e.g. as value of the `className` prop), but rather handed to emotion so it can handle it (e.g. as value of `css` prop)."; }
5
5
  /*
6
6
  * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
@@ -35,6 +35,7 @@ var _ref2 = process.env.NODE_ENV === "production" ? {
35
35
  toString: _EMOTION_STRINGIFIED_CSS_ERROR__
36
36
  };
37
37
  export var EuiDataGridHeaderCell = function EuiDataGridHeaderCell(_ref) {
38
+ var _classnames;
38
39
  var column = _ref.column,
39
40
  index = _ref.index,
40
41
  columns = _ref.columns,
@@ -44,15 +45,13 @@ export var EuiDataGridHeaderCell = function EuiDataGridHeaderCell(_ref) {
44
45
  defaultColumnWidth = _ref.defaultColumnWidth,
45
46
  setColumnWidth = _ref.setColumnWidth,
46
47
  setVisibleColumns = _ref.setVisibleColumns,
47
- switchColumnPos = _ref.switchColumnPos,
48
- headerIsInteractive = _ref.headerIsInteractive;
48
+ switchColumnPos = _ref.switchColumnPos;
49
49
  var id = column.id,
50
50
  display = column.display,
51
51
  displayAsText = column.displayAsText,
52
52
  displayHeaderCellProps = column.displayHeaderCellProps;
53
53
  var width = columnWidths[id] || defaultColumnWidth;
54
54
  var columnType = schema[id] ? schema[id].columnType : null;
55
- var classes = classnames(_defineProperty({}, "euiDataGridHeaderCell--".concat(columnType), columnType), displayHeaderCellProps === null || displayHeaderCellProps === void 0 ? void 0 : displayHeaderCellProps.className);
56
55
  var _useContext = useContext(DataGridFocusContext),
57
56
  setFocusedCell = _useContext.setFocusedCell,
58
57
  focusFirstVisibleInteractiveCell = _useContext.focusFirstVisibleInteractiveCell;
@@ -77,6 +76,14 @@ export var EuiDataGridHeaderCell = function EuiDataGridHeaderCell(_ref) {
77
76
  });
78
77
  var showColumnActions = columnActions && columnActions.length > 0;
79
78
  var actionsButtonRef = useRef(null);
79
+ var focusActionsButton = useCallback(function () {
80
+ var _actionsButtonRef$cur;
81
+ (_actionsButtonRef$cur = actionsButtonRef.current) === null || _actionsButtonRef$cur === void 0 ? void 0 : _actionsButtonRef$cur.focus();
82
+ }, []);
83
+ var _useState3 = useState(false),
84
+ _useState4 = _slicedToArray(_useState3, 2),
85
+ isActionsButtonFocused = _useState4[0],
86
+ setIsActionsButtonFocused = _useState4[1];
80
87
  var _useSortingUtils = useSortingUtils({
81
88
  sorting: sorting,
82
89
  id: id,
@@ -97,13 +104,16 @@ export var EuiDataGridHeaderCell = function EuiDataGridHeaderCell(_ref) {
97
104
  title: displayAsText || id,
98
105
  className: "euiDataGridHeaderCell__content"
99
106
  }, display || displayAsText || id), sortingArrow);
107
+ var classes = classnames((_classnames = {}, _defineProperty(_classnames, "euiDataGridHeaderCell--".concat(columnType), columnType), _defineProperty(_classnames, 'euiDataGridHeaderCell--hasColumnActions', showColumnActions), _defineProperty(_classnames, 'euiDataGridHeaderCell--isActionsPopoverOpen', isPopoverOpen), _classnames), displayHeaderCellProps === null || displayHeaderCellProps === void 0 ? void 0 : displayHeaderCellProps.className);
100
108
  return ___EmotionJSX(EuiDataGridHeaderCellWrapper, _extends({}, displayHeaderCellProps, {
101
109
  className: classes,
102
110
  id: id,
103
111
  index: index,
104
112
  width: width,
105
- headerIsInteractive: headerIsInteractive,
106
- "aria-sort": ariaSort
113
+ "aria-sort": ariaSort,
114
+ hasActionsPopover: showColumnActions,
115
+ isActionsButtonFocused: isActionsButtonFocused,
116
+ focusActionsButton: focusActionsButton
107
117
  }), column.isResizable !== false && width != null ? ___EmotionJSX(EuiDataGridColumnResizer, {
108
118
  columnId: id,
109
119
  columnWidth: width,
@@ -111,11 +121,16 @@ export var EuiDataGridHeaderCell = function EuiDataGridHeaderCell(_ref) {
111
121
  }) : null, !showColumnActions ? ___EmotionJSX(React.Fragment, null, cellContent, sortingScreenReaderText && ___EmotionJSX(EuiScreenReaderOnly, null, ___EmotionJSX("p", null, sortingScreenReaderText))) : ___EmotionJSX(React.Fragment, null, ___EmotionJSX("button", {
112
122
  className: "euiDataGridHeaderCell__button",
113
123
  onClick: function onClick() {
114
- setFocusedCell([index, -1]);
115
- setIsPopoverOpen(function (isPopoverOpen) {
124
+ return setIsPopoverOpen(function (isPopoverOpen) {
116
125
  return !isPopoverOpen;
117
126
  });
118
127
  },
128
+ onFocus: function onFocus() {
129
+ return setIsActionsButtonFocused(true);
130
+ },
131
+ onBlur: function onBlur() {
132
+ return setIsActionsButtonFocused(false);
133
+ },
119
134
  "aria-describedby": "".concat(sortingAriaId, " ").concat(actionsAriaId),
120
135
  ref: actionsButtonRef,
121
136
  "data-test-subj": "dataGridHeaderCellActionButton-".concat(id)
@@ -129,8 +144,8 @@ export var EuiDataGridHeaderCell = function EuiDataGridHeaderCell(_ref) {
129
144
  focusTrapProps: {
130
145
  // We need to override the default EuiPopover `onClickOutside` since the anchor is separate from the actual button
131
146
  onClickOutside: function onClickOutside(event) {
132
- var _actionsButtonRef$cur;
133
- if (((_actionsButtonRef$cur = actionsButtonRef.current) === null || _actionsButtonRef$cur === void 0 ? void 0 : _actionsButtonRef$cur.contains(event.target)) === false) {
147
+ var _actionsButtonRef$cur2;
148
+ if (((_actionsButtonRef$cur2 = actionsButtonRef.current) === null || _actionsButtonRef$cur2 === void 0 ? void 0 : _actionsButtonRef$cur2.contains(event.target)) === false) {
134
149
  setIsPopoverOpen(false);
135
150
  }
136
151
  }
@@ -1,7 +1,7 @@
1
1
  import _extends from "@babel/runtime/helpers/extends";
2
2
  import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
3
3
  import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
4
- var _excluded = ["id", "index", "headerIsInteractive", "width", "className", "children"];
4
+ var _excluded = ["id", "index", "width", "className", "children", "hasActionsPopover", "isActionsButtonFocused", "focusActionsButton"];
5
5
  /*
6
6
  * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
7
7
  * or more contributor license agreements. Licensed under the Elastic License
@@ -11,123 +11,69 @@ var _excluded = ["id", "index", "headerIsInteractive", "width", "className", "ch
11
11
  */
12
12
 
13
13
  import classnames from 'classnames';
14
- import React, { useContext, useEffect, useRef, useState } from 'react';
15
- import { tabbable } from 'tabbable';
16
- import { keys } from '../../../../services';
14
+ import React, { useContext, useEffect, useState, useCallback } from 'react';
17
15
  import { DataGridFocusContext } from '../../utils/focus';
18
- import { jsx as ___EmotionJSX } from "@emotion/react";
16
+ import { HandleInteractiveChildren } from '../cell/focus_utils';
17
+
19
18
  /**
20
19
  * This is a wrapper that handles repeated concerns between control &
21
20
  * standard header cells. Most of its shared logic is around focus state/UX,
22
21
  * but it also DRY's out certain class/data-test-subj/style attributes
23
22
  */
23
+ import { jsx as ___EmotionJSX } from "@emotion/react";
24
24
  export var EuiDataGridHeaderCellWrapper = function EuiDataGridHeaderCellWrapper(_ref) {
25
25
  var id = _ref.id,
26
26
  index = _ref.index,
27
- headerIsInteractive = _ref.headerIsInteractive,
28
27
  width = _ref.width,
29
28
  className = _ref.className,
30
29
  children = _ref.children,
30
+ hasActionsPopover = _ref.hasActionsPopover,
31
+ isActionsButtonFocused = _ref.isActionsButtonFocused,
32
+ focusActionsButton = _ref.focusActionsButton,
31
33
  rest = _objectWithoutProperties(_ref, _excluded);
32
34
  var classes = classnames('euiDataGridHeaderCell', className);
35
+
36
+ // Must be a state and not a ref to trigger a HandleInteractiveChildren rerender
37
+ var _useState = useState(null),
38
+ _useState2 = _slicedToArray(_useState, 2),
39
+ headerEl = _useState2[0],
40
+ setHeaderEl = _useState2[1];
33
41
  var _useContext = useContext(DataGridFocusContext),
34
42
  setFocusedCell = _useContext.setFocusedCell,
35
43
  onFocusUpdate = _useContext.onFocusUpdate;
36
- var _useState = useState(false),
37
- _useState2 = _slicedToArray(_useState, 2),
38
- isFocused = _useState2[0],
39
- setIsFocused = _useState2[1];
44
+ var updateCellFocusContext = useCallback(function () {
45
+ setFocusedCell([index, -1]);
46
+ }, [index, setFocusedCell]);
47
+ var _useState3 = useState(false),
48
+ _useState4 = _slicedToArray(_useState3, 2),
49
+ isFocused = _useState4[0],
50
+ setIsFocused = _useState4[1];
40
51
  useEffect(function () {
41
52
  onFocusUpdate([index, -1], function (isFocused) {
42
53
  setIsFocused(isFocused);
43
54
  });
44
55
  }, [index, onFocusUpdate]);
45
- var headerRef = useRef(null);
46
- var _useState3 = useState(false),
47
- _useState4 = _slicedToArray(_useState3, 2),
48
- isCellEntered = _useState4[0],
49
- setIsCellEntered = _useState4[1];
50
56
  useEffect(function () {
51
- var headerNode = headerRef.current;
52
- if (isCellEntered) {
53
- enableAndFocusInteractives(headerNode);
54
- } else {
55
- disableInteractives(headerNode);
56
- }
57
- }, [isCellEntered]);
58
- useEffect(function () {
59
- var headerNode = headerRef.current;
60
- if (isFocused) {
61
- var interactives = headerNode.querySelectorAll('[data-euigrid-tab-managed]');
62
- if (interactives.length === 1) {
63
- setIsCellEntered(true);
64
- } else {
65
- headerNode.focus();
57
+ if (isFocused && headerEl) {
58
+ // Only focus the cell if not already focused on something in the cell
59
+ if (!headerEl.contains(document.activeElement)) {
60
+ headerEl.focus();
66
61
  }
67
- } else {
68
- setIsCellEntered(false);
69
62
  }
63
+ }, [isFocused, headerEl]);
70
64
 
71
- // focusin bubbles while focus does not, and this needs to react to children gaining focus
72
- var onFocusIn = function onFocusIn(e) {
73
- if (!headerIsInteractive) {
74
- // header is not interactive, avoid focusing
75
- requestAnimationFrame(function () {
76
- return headerNode.blur();
77
- });
78
- e.preventDefault();
79
- return false;
80
- } else {
81
- // take the focus
82
- if (isFocused === false) {
83
- setFocusedCell([index, -1]);
84
- } else {
85
- // this cell already had the grid's focus, so re-enable and focus interactives
86
- setIsCellEntered(true);
87
- }
88
- }
89
- };
90
-
91
- // focusout bubbles while blur does not, and this needs to react to the children losing focus
92
- var onFocusOut = function onFocusOut() {
93
- // wait for the next element to receive focus, then update interactives' state
94
- requestAnimationFrame(function () {
95
- if (!headerNode.contains(document.activeElement)) {
96
- setIsCellEntered(false);
97
- }
98
- });
99
- };
100
- var onKeyUp = function onKeyUp(event) {
101
- switch (event.key) {
102
- case keys.ENTER:
103
- {
104
- event.preventDefault();
105
- setIsCellEntered(true);
106
- break;
107
- }
108
- case keys.ESCAPE:
109
- {
110
- event.preventDefault();
111
- // move focus to cell
112
- setIsCellEntered(false);
113
- headerNode.focus();
114
- break;
115
- }
116
- }
117
- };
118
- headerNode.addEventListener('focusin', onFocusIn);
119
- headerNode.addEventListener('focusout', onFocusOut);
120
- headerNode.addEventListener('keyup', onKeyUp);
121
- return function () {
122
- headerNode.removeEventListener('focusin', onFocusIn);
123
- headerNode.removeEventListener('focusout', onFocusOut);
124
- headerNode.removeEventListener('keyup', onKeyUp);
125
- };
126
- }, [headerIsInteractive, isFocused, index, setFocusedCell]);
65
+ // For cell headers with actions, auto-focus into the button instead of the cell wrapper div
66
+ // The button text is significantly more useful to screen readers (e.g. contains sort order & hints)
67
+ var onFocus = useCallback(function (e) {
68
+ if (hasActionsPopover && e.target === headerEl) {
69
+ focusActionsButton === null || focusActionsButton === void 0 ? void 0 : focusActionsButton();
70
+ }
71
+ }, [hasActionsPopover, focusActionsButton, headerEl]);
127
72
  return ___EmotionJSX("div", _extends({
128
73
  role: "columnheader",
129
- ref: headerRef,
130
- tabIndex: isFocused && !isCellEntered ? 0 : -1,
74
+ ref: setHeaderEl,
75
+ tabIndex: isFocused && !isActionsButtonFocused ? 0 : -1,
76
+ onFocus: onFocus,
131
77
  className: classes,
132
78
  "data-test-subj": "dataGridHeaderCell-".concat(id),
133
79
  "data-gridcell-column-id": id,
@@ -137,29 +83,9 @@ export var EuiDataGridHeaderCellWrapper = function EuiDataGridHeaderCellWrapper(
137
83
  style: width != null ? {
138
84
  width: "".concat(width, "px")
139
85
  } : {}
140
- }, rest), children);
141
- };
142
-
143
- /**
144
- * Utility fns for managing child interactive tabIndex state
145
- */
146
-
147
- var disableInteractives = function disableInteractives(headerNode) {
148
- var tabbables = tabbable(headerNode);
149
- if (tabbables.length > 1) {
150
- console.warn("EuiDataGridHeaderCell expects at most 1 tabbable element, ".concat(tabbables.length, " found instead"));
151
- }
152
- tabbables.forEach(function (element) {
153
- element.setAttribute('data-euigrid-tab-managed', 'true');
154
- element.setAttribute('tabIndex', '-1');
155
- });
156
- };
157
- var enableAndFocusInteractives = function enableAndFocusInteractives(headerNode) {
158
- var interactiveElements = headerNode.querySelectorAll('[data-euigrid-tab-managed]');
159
- interactiveElements.forEach(function (element, i) {
160
- element.setAttribute('tabIndex', '0');
161
- if (i === 0) {
162
- element.focus();
163
- }
164
- });
86
+ }, rest), ___EmotionJSX(HandleInteractiveChildren, {
87
+ cellEl: headerEl,
88
+ updateCellFocusContext: updateCellFocusContext,
89
+ renderFocusTrap: !hasActionsPopover
90
+ }, children));
165
91
  };
@@ -1,6 +1,6 @@
1
1
  import _extends from "@babel/runtime/helpers/extends";
2
2
  import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
3
- var _excluded = ["leadingControlColumns", "trailingControlColumns", "columns", "schema", "schemaDetectors", "columnWidths", "defaultColumnWidth", "className", "setColumnWidth", "setVisibleColumns", "switchColumnPos", "headerIsInteractive", "data-test-subj"];
3
+ var _excluded = ["leadingControlColumns", "trailingControlColumns", "columns", "schema", "schemaDetectors", "columnWidths", "defaultColumnWidth", "className", "setColumnWidth", "setVisibleColumns", "switchColumnPos", "data-test-subj"];
4
4
  /*
5
5
  * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
6
6
  * or more contributor license agreements. Licensed under the Elastic License
@@ -29,7 +29,6 @@ var EuiDataGridHeaderRow = /*#__PURE__*/forwardRef(function (props, ref) {
29
29
  setColumnWidth = props.setColumnWidth,
30
30
  setVisibleColumns = props.setVisibleColumns,
31
31
  switchColumnPos = props.switchColumnPos,
32
- headerIsInteractive = props.headerIsInteractive,
33
32
  _dataTestSubj = props['data-test-subj'],
34
33
  rest = _objectWithoutProperties(props, _excluded);
35
34
  var classes = classnames('euiDataGridHeader', className);
@@ -43,8 +42,7 @@ var EuiDataGridHeaderRow = /*#__PURE__*/forwardRef(function (props, ref) {
43
42
  return ___EmotionJSX(EuiDataGridControlHeaderCell, {
44
43
  key: controlColumn.id,
45
44
  index: index,
46
- controlColumn: controlColumn,
47
- headerIsInteractive: headerIsInteractive
45
+ controlColumn: controlColumn
48
46
  });
49
47
  }), columns.map(function (column, index) {
50
48
  return ___EmotionJSX(EuiDataGridHeaderCell, {
@@ -58,15 +56,13 @@ var EuiDataGridHeaderRow = /*#__PURE__*/forwardRef(function (props, ref) {
58
56
  setColumnWidth: setColumnWidth,
59
57
  setVisibleColumns: setVisibleColumns,
60
58
  switchColumnPos: switchColumnPos,
61
- defaultColumnWidth: defaultColumnWidth,
62
- headerIsInteractive: headerIsInteractive
59
+ defaultColumnWidth: defaultColumnWidth
63
60
  });
64
61
  }), trailingControlColumns.map(function (controlColumn, index) {
65
62
  return ___EmotionJSX(EuiDataGridControlHeaderCell, {
66
63
  key: controlColumn.id,
67
64
  index: index + leadingControlColumns.length + columns.length,
68
- controlColumn: controlColumn,
69
- headerIsInteractive: headerIsInteractive
65
+ controlColumn: controlColumn
70
66
  });
71
67
  }));
72
68
  });
@@ -1,7 +1,5 @@
1
1
  import _extends from "@babel/runtime/helpers/extends";
2
2
  import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
3
- import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
4
- var _excluded = ["handleHeaderMutation"];
5
3
  /*
6
4
  * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
7
5
  * or more contributor license agreements. Licensed under the Elastic License
@@ -11,25 +9,18 @@ var _excluded = ["handleHeaderMutation"];
11
9
  */
12
10
 
13
11
  import React, { useState, useMemo } from 'react';
14
- import { useMutationObserver } from '../../../observer/mutation_observer';
15
12
  import { useResizeObserver } from '../../../observer/resize_observer';
16
- import { useHeaderFocusWorkaround } from '../../utils/focus';
17
13
  import { EuiDataGridHeaderRow } from './data_grid_header_row';
18
- import { jsx as ___EmotionJSX } from "@emotion/react";
14
+
19
15
  /**
20
16
  * DRY out setting up the grid header and its refs & observers
21
17
  */
22
- export var useDataGridHeader = function useDataGridHeader(_ref) {
23
- var handleHeaderMutation = _ref.handleHeaderMutation,
24
- props = _objectWithoutProperties(_ref, _excluded);
18
+ import { jsx as ___EmotionJSX } from "@emotion/react";
19
+ export var useDataGridHeader = function useDataGridHeader(props) {
25
20
  var _useState = useState(null),
26
21
  _useState2 = _slicedToArray(_useState, 2),
27
22
  headerRowRef = _useState2[0],
28
23
  setHeaderRowRef = _useState2[1];
29
- useMutationObserver(headerRowRef, handleHeaderMutation, {
30
- subtree: true,
31
- childList: true
32
- });
33
24
  var _useResizeObserver = useResizeObserver(headerRowRef, 'height'),
34
25
  headerRowHeight = _useResizeObserver.height;
35
26
  var headerRow = useMemo(function () {
@@ -38,7 +29,6 @@ export var useDataGridHeader = function useDataGridHeader(_ref) {
38
29
  }, props));
39
30
  }, Object.values(props)); // eslint-disable-line react-hooks/exhaustive-deps
40
31
 
41
- useHeaderFocusWorkaround(props.headerIsInteractive);
42
32
  return {
43
33
  headerRow: headerRow,
44
34
  headerRowHeight: headerRowHeight