@elastic/eui 95.9.0 → 95.10.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 (101) hide show
  1. package/dist/eui_theme_dark.css +35 -6
  2. package/dist/eui_theme_dark.min.css +1 -1
  3. package/dist/eui_theme_light.css +35 -6
  4. package/dist/eui_theme_light.min.css +1 -1
  5. package/es/components/basic_table/in_memory_table.js +2 -1
  6. package/es/components/datagrid/body/cell/data_grid_cell.js +2 -0
  7. package/es/components/datagrid/body/cell/focus_utils.js +57 -11
  8. package/es/components/datagrid/body/data_grid_body.js +1 -0
  9. package/es/components/datagrid/body/data_grid_body_custom.js +1 -0
  10. package/es/components/datagrid/body/data_grid_body_virtualized.js +1 -0
  11. package/es/components/datagrid/body/header/data_grid_header_cell.js +92 -83
  12. package/es/components/datagrid/body/header/data_grid_header_cell_wrapper.js +37 -22
  13. package/es/components/datagrid/controls/column_sorting.js +1 -0
  14. package/es/components/datagrid/data_grid.a11y.js +2 -0
  15. package/es/components/datagrid/utils/in_memory.js +1 -0
  16. package/es/components/date_picker/date_picker.js +32 -10
  17. package/es/components/date_picker/date_picker.styles.js +3 -2
  18. package/es/components/date_picker/date_picker_range.styles.js +1 -1
  19. package/es/components/form/super_select/super_select.styles.js +1 -1
  20. package/es/components/markdown_editor/plugins/markdown_default_plugins/parsing_plugins.js +15 -8
  21. package/es/components/markdown_editor/plugins/markdown_default_plugins/plugins.js +21 -4
  22. package/es/components/markdown_editor/plugins/markdown_default_plugins/processing_plugins.js +5 -2
  23. package/es/components/markdown_editor/plugins/markdown_link_validator.js +8 -2
  24. package/es/components/search_bar/filters/field_value_selection_filter.js +171 -152
  25. package/es/components/search_bar/search_bar.js +2 -1
  26. package/es/components/search_bar/search_filters.js +2 -1
  27. package/eui.d.ts +138 -69
  28. package/i18ntokens.json +78 -42
  29. package/lib/components/basic_table/in_memory_table.js +2 -1
  30. package/lib/components/datagrid/body/cell/data_grid_cell.js +2 -0
  31. package/lib/components/datagrid/body/cell/focus_utils.js +58 -12
  32. package/lib/components/datagrid/body/data_grid_body.js +1 -0
  33. package/lib/components/datagrid/body/data_grid_body_custom.js +1 -0
  34. package/lib/components/datagrid/body/data_grid_body_virtualized.js +1 -0
  35. package/lib/components/datagrid/body/header/data_grid_header_cell.js +98 -88
  36. package/lib/components/datagrid/body/header/data_grid_header_cell_wrapper.js +38 -23
  37. package/lib/components/datagrid/controls/column_sorting.js +1 -0
  38. package/lib/components/datagrid/data_grid.a11y.js +2 -0
  39. package/lib/components/datagrid/utils/in_memory.js +1 -0
  40. package/lib/components/date_picker/date_picker.js +32 -10
  41. package/lib/components/date_picker/date_picker.styles.js +3 -2
  42. package/lib/components/date_picker/date_picker_range.styles.js +1 -1
  43. package/lib/components/form/super_select/super_select.styles.js +1 -1
  44. package/lib/components/markdown_editor/plugins/markdown_default_plugins/parsing_plugins.js +26 -17
  45. package/lib/components/markdown_editor/plugins/markdown_default_plugins/plugins.js +21 -6
  46. package/lib/components/markdown_editor/plugins/markdown_default_plugins/processing_plugins.js +5 -2
  47. package/lib/components/markdown_editor/plugins/markdown_link_validator.js +9 -2
  48. package/lib/components/search_bar/filters/field_value_selection_filter.js +170 -151
  49. package/lib/components/search_bar/search_bar.js +2 -1
  50. package/lib/components/search_bar/search_filters.js +2 -1
  51. package/optimize/es/components/datagrid/body/cell/focus_utils.js +55 -10
  52. package/optimize/es/components/datagrid/body/header/data_grid_header_cell.js +90 -83
  53. package/optimize/es/components/datagrid/body/header/data_grid_header_cell_wrapper.js +33 -19
  54. package/optimize/es/components/datagrid/data_grid.a11y.js +2 -0
  55. package/optimize/es/components/date_picker/date_picker.js +15 -9
  56. package/optimize/es/components/date_picker/date_picker.styles.js +3 -2
  57. package/optimize/es/components/date_picker/date_picker_range.styles.js +1 -1
  58. package/optimize/es/components/form/super_select/super_select.styles.js +1 -1
  59. package/optimize/es/components/markdown_editor/plugins/markdown_default_plugins/parsing_plugins.js +14 -8
  60. package/optimize/es/components/markdown_editor/plugins/markdown_default_plugins/plugins.js +18 -4
  61. package/optimize/es/components/markdown_editor/plugins/markdown_default_plugins/processing_plugins.js +5 -2
  62. package/optimize/es/components/markdown_editor/plugins/markdown_link_validator.js +8 -2
  63. package/optimize/es/components/search_bar/filters/field_value_selection_filter.js +168 -151
  64. package/optimize/lib/components/datagrid/body/cell/focus_utils.js +56 -11
  65. package/optimize/lib/components/datagrid/body/header/data_grid_header_cell.js +92 -84
  66. package/optimize/lib/components/datagrid/body/header/data_grid_header_cell_wrapper.js +33 -19
  67. package/optimize/lib/components/datagrid/data_grid.a11y.js +2 -0
  68. package/optimize/lib/components/date_picker/date_picker.js +15 -9
  69. package/optimize/lib/components/date_picker/date_picker.styles.js +3 -2
  70. package/optimize/lib/components/date_picker/date_picker_range.styles.js +1 -1
  71. package/optimize/lib/components/form/super_select/super_select.styles.js +1 -1
  72. package/optimize/lib/components/markdown_editor/plugins/markdown_default_plugins/parsing_plugins.js +15 -11
  73. package/optimize/lib/components/markdown_editor/plugins/markdown_default_plugins/plugins.js +19 -6
  74. package/optimize/lib/components/markdown_editor/plugins/markdown_default_plugins/processing_plugins.js +5 -2
  75. package/optimize/lib/components/markdown_editor/plugins/markdown_link_validator.js +9 -2
  76. package/optimize/lib/components/search_bar/filters/field_value_selection_filter.js +167 -150
  77. package/package.json +1 -1
  78. package/src/components/datagrid/_data_grid_data_row.scss +5 -0
  79. package/src/components/datagrid/body/header/_data_grid_header_row.scss +27 -5
  80. package/test-env/components/basic_table/in_memory_table.js +2 -1
  81. package/test-env/components/datagrid/body/cell/data_grid_cell.js +2 -0
  82. package/test-env/components/datagrid/body/cell/focus_utils.js +58 -12
  83. package/test-env/components/datagrid/body/data_grid_body.js +1 -0
  84. package/test-env/components/datagrid/body/data_grid_body_custom.js +1 -0
  85. package/test-env/components/datagrid/body/data_grid_body_virtualized.js +1 -0
  86. package/test-env/components/datagrid/body/header/data_grid_header_cell.js +93 -84
  87. package/test-env/components/datagrid/body/header/data_grid_header_cell_wrapper.js +37 -22
  88. package/test-env/components/datagrid/controls/column_sorting.js +1 -0
  89. package/test-env/components/datagrid/data_grid.a11y.js +2 -0
  90. package/test-env/components/datagrid/utils/in_memory.js +1 -0
  91. package/test-env/components/date_picker/date_picker.js +32 -10
  92. package/test-env/components/date_picker/date_picker.styles.js +3 -2
  93. package/test-env/components/date_picker/date_picker_range.styles.js +1 -1
  94. package/test-env/components/form/super_select/super_select.styles.js +1 -1
  95. package/test-env/components/markdown_editor/plugins/markdown_default_plugins/parsing_plugins.js +15 -11
  96. package/test-env/components/markdown_editor/plugins/markdown_default_plugins/plugins.js +19 -6
  97. package/test-env/components/markdown_editor/plugins/markdown_default_plugins/processing_plugins.js +5 -2
  98. package/test-env/components/markdown_editor/plugins/markdown_link_validator.js +9 -2
  99. package/test-env/components/search_bar/filters/field_value_selection_filter.js +169 -151
  100. package/test-env/components/search_bar/search_bar.js +2 -1
  101. package/test-env/components/search_bar/search_filters.js +2 -1
@@ -11,8 +11,10 @@ var _react = _interopRequireWildcard(require("react"));
11
11
  var _propTypes = _interopRequireDefault(require("prop-types"));
12
12
  var _tabbable = require("tabbable");
13
13
  var _services = require("../../../../services");
14
+ var _accessibility = require("../../../../services/accessibility");
15
+ var _utils = require("../../../../utils");
14
16
  var _focus_trap = require("../../../focus_trap");
15
- var _accessibility = require("../../../accessibility");
17
+ var _accessibility2 = require("../../../accessibility");
16
18
  var _i18n = require("../../../i18n");
17
19
  var _react2 = require("@emotion/react");
18
20
  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); }
@@ -39,7 +41,8 @@ var HandleInteractiveChildren = exports.HandleInteractiveChildren = function Han
39
41
  var cellEl = _ref.cellEl,
40
42
  children = _ref.children,
41
43
  updateCellFocusContext = _ref.updateCellFocusContext,
42
- renderFocusTrap = _ref.renderFocusTrap;
44
+ renderFocusTrap = _ref.renderFocusTrap,
45
+ onInteractiveChildrenFound = _ref.onInteractiveChildrenFound;
43
46
  var _useState = (0, _react.useState)(false),
44
47
  _useState2 = (0, _slicedToArray2.default)(_useState, 2),
45
48
  hasInteractiveChildren = _useState2[0],
@@ -48,12 +51,11 @@ var HandleInteractiveChildren = exports.HandleInteractiveChildren = function Han
48
51
  // On mount, disable all interactive children
49
52
  (0, _react.useEffect)(function () {
50
53
  if (cellEl) {
51
- var interactiveChildren = disableInteractives(cellEl);
52
- if (renderFocusTrap) {
53
- setHasInteractiveChildren(interactiveChildren.length > 0);
54
- }
54
+ var interactives = disableInteractives(cellEl);
55
+ onInteractiveChildrenFound === null || onInteractiveChildrenFound === void 0 || onInteractiveChildrenFound(interactives);
56
+ setHasInteractiveChildren(interactives.length > 0);
55
57
  }
56
- }, [cellEl, renderFocusTrap]);
58
+ }, [cellEl, onInteractiveChildrenFound]);
57
59
 
58
60
  // Ensure that any interactive children that are clicked update the latest cell focus context
59
61
  (0, _react.useEffect)(function () {
@@ -87,7 +89,8 @@ var HandleInteractiveChildren = exports.HandleInteractiveChildren = function Han
87
89
  HandleInteractiveChildren.propTypes = {
88
90
  cellEl: _propTypes.default.oneOfType([_propTypes.default.any.isRequired, _propTypes.default.oneOf([null])]),
89
91
  updateCellFocusContext: _propTypes.default.func.isRequired,
90
- renderFocusTrap: _propTypes.default.bool
92
+ renderFocusTrap: _propTypes.default.bool,
93
+ onInteractiveChildrenFound: _propTypes.default.func
91
94
  };
92
95
  var FocusTrappedChildren = exports.FocusTrappedChildren = function FocusTrappedChildren(_ref2) {
93
96
  var cellEl = _ref2.cellEl,
@@ -96,6 +99,24 @@ var FocusTrappedChildren = exports.FocusTrappedChildren = function FocusTrappedC
96
99
  _useState4 = (0, _slicedToArray2.default)(_useState3, 2),
97
100
  isCellEntered = _useState4[0],
98
101
  setIsCellEntered = _useState4[1];
102
+ var _useState5 = (0, _react.useState)(false),
103
+ _useState6 = (0, _slicedToArray2.default)(_useState5, 2),
104
+ isExited = _useState6[0],
105
+ setExited = _useState6[1];
106
+ var keyboardHintAriaId = (0, _accessibility.useGeneratedHtmlId)({
107
+ prefix: 'euiDataGridCellHeader',
108
+ suffix: 'keyboardHint'
109
+ });
110
+ var exitedHintAriaId = (0, _accessibility.useGeneratedHtmlId)({
111
+ prefix: 'euiDataGridCellHeader',
112
+ suffix: 'exited'
113
+ });
114
+
115
+ // direct DOM manipulation as workaround to attach required hints
116
+ (0, _react.useEffect)(function () {
117
+ var currentAriaDescribedbyId = cellEl.getAttribute('aria-describedby');
118
+ cellEl.setAttribute('aria-describedby', "".concat(currentAriaDescribedbyId, " ").concat(exitedHintAriaId, " ").concat(keyboardHintAriaId, " "));
119
+ }, [cellEl, keyboardHintAriaId, exitedHintAriaId]);
99
120
  (0, _react.useEffect)(function () {
100
121
  if (isCellEntered) {
101
122
  enableAndFocusInteractives(cellEl);
@@ -115,28 +136,52 @@ var FocusTrappedChildren = exports.FocusTrappedChildren = function FocusTrappedC
115
136
  event.preventDefault();
116
137
  setIsCellEntered(function (isCellEntered) {
117
138
  if (isCellEntered === true) {
139
+ setExited(true);
118
140
  requestAnimationFrame(function () {
119
141
  return cellEl.focus();
120
142
  }); // move focus to cell
121
143
  return false;
144
+ } else if (
145
+ // when opened content is closed, we don't want Escape to return to the cell
146
+ // immediately but instead return focus to a trigger as expected
147
+ isCellEntered === false && (0, _utils.isDOMNode)(event.target) && (0, _utils.isDOMNode)(event.currentTarget) && event.currentTarget.contains(event.target)) {
148
+ return true;
122
149
  }
123
150
  return isCellEntered;
124
151
  });
125
152
  break;
126
153
  }
127
154
  };
155
+
156
+ // ensures the SR text is reset when navigating to a different cell
157
+ var onBlur = function onBlur() {
158
+ return setExited(false);
159
+ };
128
160
  cellEl.addEventListener('keyup', onKeyUp);
161
+ cellEl.addEventListener('blur', onBlur);
129
162
  return function () {
130
163
  cellEl.removeEventListener('keyup', onKeyUp);
164
+ cellEl.removeEventListener('blur', onBlur);
131
165
  };
132
166
  }, [cellEl]);
133
167
  return (0, _react2.jsx)(_focus_trap.EuiFocusTrap, {
134
168
  disabled: !isCellEntered,
169
+ clickOutsideDisables: true,
135
170
  onDeactivation: function onDeactivation() {
136
171
  return setIsCellEntered(false);
137
- },
138
- clickOutsideDisables: true
139
- }, children, (0, _react2.jsx)(_accessibility.EuiScreenReaderOnly, null, (0, _react2.jsx)("p", null, ' - ', (0, _react2.jsx)(_i18n.EuiI18n
172
+ }
173
+ }, children, (0, _react2.jsx)(_accessibility2.EuiScreenReaderOnly, null, (0, _react2.jsx)("p", {
174
+ id: exitedHintAriaId,
175
+ "aria-hidden": "true"
176
+ }, isExited && (0, _react2.jsx)(_i18n.EuiI18n
177
+ // eslint-disable-next-line local/i18n
178
+ , {
179
+ token: "euiDataGridCell.focusTrapExitPrompt",
180
+ default: "Exited cell content."
181
+ }))), (0, _react2.jsx)(_accessibility2.EuiScreenReaderOnly, null, (0, _react2.jsx)("p", {
182
+ id: keyboardHintAriaId,
183
+ "aria-hidden": "true"
184
+ }, !isCellEntered && (0, _react2.jsx)(_i18n.EuiI18n
140
185
  // eslint-disable-next-line local/i18n
141
186
  , {
142
187
  token: "euiDataGridCell.focusTrapEnterPrompt",
@@ -162,7 +207,8 @@ var enableAndFocusInteractives = function enableAndFocusInteractives(cell) {
162
207
  var interactives = cell.querySelectorAll('[data-euigrid-tab-managed]');
163
208
  interactives.forEach(function (element, i) {
164
209
  element.setAttribute('tabIndex', '0');
165
- if (i === 0) {
210
+ // focus the first element only if we're on the cell and not inside of it
211
+ if (i === 0 && !cell.contains(document.activeElement)) {
166
212
  element.focus();
167
213
  }
168
214
  });
@@ -107,6 +107,7 @@ EuiDataGridBody.propTypes = {
107
107
  * This can be used to display a readable column name in column hiding/sorting, where `display` won't be used.
108
108
  * This will also be used as a `title` attribute that will display on mouseover (useful if the display text is being truncated by the column width).
109
109
  * If not passed, `id` will be shown as the column name.
110
+ * Passing this together with `display` is useful to ensure an accessible label is added to the column.
110
111
  */
111
112
  displayAsText: _propTypes.default.string,
112
113
  /**
@@ -247,6 +247,7 @@ EuiDataGridBodyCustomRender.propTypes = {
247
247
  * This can be used to display a readable column name in column hiding/sorting, where `display` won't be used.
248
248
  * This will also be used as a `title` attribute that will display on mouseover (useful if the display text is being truncated by the column width).
249
249
  * If not passed, `id` will be shown as the column name.
250
+ * Passing this together with `display` is useful to ensure an accessible label is added to the column.
250
251
  */
251
252
  displayAsText: _propTypes.default.string,
252
253
  /**
@@ -394,6 +394,7 @@ EuiDataGridBodyVirtualized.propTypes = {
394
394
  * This can be used to display a readable column name in column hiding/sorting, where `display` won't be used.
395
395
  * This will also be used as a `title` attribute that will display on mouseover (useful if the display text is being truncated by the column width).
396
396
  * If not passed, `id` will be shown as the column name.
397
+ * Passing this together with `display` is useful to ensure an accessible label is added to the column.
397
398
  */
398
399
  displayAsText: _propTypes.default.string,
399
400
  /**
@@ -6,42 +6,46 @@ Object.defineProperty(exports, "__esModule", {
6
6
  value: true
7
7
  });
8
8
  exports.useSortingUtils = exports.usePopoverArrowNavigation = exports.EuiDataGridHeaderCell = void 0;
9
- var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
10
9
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
11
10
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
11
+ var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
12
+ var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
12
13
  var _classnames2 = _interopRequireDefault(require("classnames"));
13
14
  var _propTypes = _interopRequireDefault(require("prop-types"));
14
15
  var _react = _interopRequireWildcard(require("react"));
15
16
  var _tabbable = require("tabbable");
16
17
  var _services = require("../../../../services");
17
18
  var _accessibility = require("../../../../services/accessibility");
18
- var _accessibility2 = require("../../../accessibility");
19
19
  var _i18n = require("../../../i18n");
20
20
  var _icon = require("../../../icon");
21
21
  var _list_group = require("../../../list_group");
22
22
  var _popover = require("../../../popover");
23
+ var _button_icon = require("../../../button/button_icon/button_icon.styles");
23
24
  var _focus = require("../../utils/focus");
24
25
  var _column_actions = require("./column_actions");
25
26
  var _data_grid_column_resizer = require("./data_grid_column_resizer");
26
27
  var _data_grid_header_cell_wrapper = require("./data_grid_header_cell_wrapper");
27
28
  var _react2 = require("@emotion/react");
28
- 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); }
29
- 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; }
30
- 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)."; } /*
29
+ var _excluded = ["children", "title", "arrow"];
30
+ /*
31
31
  * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
32
32
  * or more contributor license agreements. Licensed under the Elastic License
33
33
  * 2.0 and the Server Side Public License, v 1; you may not use this file except
34
34
  * in compliance with, at your election, the Elastic License 2.0 or the Server
35
35
  * Side Public License, v 1.
36
36
  */
37
+ 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); }
38
+ 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; }
39
+ 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)."; }
37
40
  var CellContent = function CellContent(_ref) {
38
41
  var children = _ref.children,
39
42
  title = _ref.title,
40
- arrow = _ref.arrow;
41
- return (0, _react2.jsx)(_react.default.Fragment, null, (0, _react2.jsx)("div", {
43
+ arrow = _ref.arrow,
44
+ rest = (0, _objectWithoutProperties2.default)(_ref, _excluded);
45
+ return (0, _react2.jsx)(_react.default.Fragment, null, (0, _react2.jsx)("div", (0, _extends2.default)({}, rest, {
42
46
  title: title,
43
47
  className: "euiDataGridHeaderCell__content"
44
- }, children), arrow);
48
+ }), children), arrow);
45
49
  };
46
50
  CellContent.propTypes = {
47
51
  title: _propTypes.default.string.isRequired,
@@ -71,15 +75,29 @@ var EuiDataGridHeaderCell = exports.EuiDataGridHeaderCell = /*#__PURE__*/(0, _re
71
75
  display = column.display,
72
76
  displayAsText = column.displayAsText,
73
77
  displayHeaderCellProps = column.displayHeaderCellProps;
78
+ var title = displayAsText || id;
79
+ var children = display || displayAsText || id;
74
80
  var width = columnWidths[id] || defaultColumnWidth;
75
81
  var columnType = schema[id] ? schema[id].columnType : null;
76
82
  var _useContext = (0, _react.useContext)(_focus.DataGridFocusContext),
77
83
  setFocusedCell = _useContext.setFocusedCell,
78
84
  focusFirstVisibleInteractiveCell = _useContext.focusFirstVisibleInteractiveCell;
85
+
86
+ /*
87
+ * Column actions
88
+ */
79
89
  var _useState = (0, _react.useState)(false),
80
90
  _useState2 = (0, _slicedToArray2.default)(_useState, 2),
81
91
  isPopoverOpen = _useState2[0],
82
92
  setIsPopoverOpen = _useState2[1];
93
+ var togglePopover = (0, _react.useCallback)(function () {
94
+ setIsPopoverOpen(function (isOpen) {
95
+ return !isOpen;
96
+ });
97
+ }, []);
98
+ var closePopover = (0, _react.useCallback)(function () {
99
+ return setIsPopoverOpen(false);
100
+ }, []);
83
101
  var popoverArrowNavigationProps = usePopoverArrowNavigation();
84
102
  var columnActions = (0, _react.useMemo)(function () {
85
103
  return (0, _column_actions.getColumnActions)({
@@ -98,14 +116,22 @@ var EuiDataGridHeaderCell = exports.EuiDataGridHeaderCell = /*#__PURE__*/(0, _re
98
116
  }, [column, columns, schema, schemaDetectors, setVisibleColumns, focusFirstVisibleInteractiveCell, setIsPopoverOpen, sorting, switchColumnPos, setFocusedCell, index]);
99
117
  var showColumnActions = columnActions && columnActions.length > 0;
100
118
  var actionsButtonRef = (0, _react.useRef)(null);
101
- var focusActionsButton = (0, _react.useCallback)(function () {
119
+ var clickActionsButton = (0, _react.useCallback)(function () {
102
120
  var _actionsButtonRef$cur;
103
- (_actionsButtonRef$cur = actionsButtonRef.current) === null || _actionsButtonRef$cur === void 0 || _actionsButtonRef$cur.focus();
121
+ (_actionsButtonRef$cur = actionsButtonRef.current) === null || _actionsButtonRef$cur === void 0 || _actionsButtonRef$cur.click();
104
122
  }, []);
105
123
  var _useState3 = (0, _react.useState)(false),
106
124
  _useState4 = (0, _slicedToArray2.default)(_useState3, 2),
107
125
  isActionsButtonFocused = _useState4[0],
108
126
  setIsActionsButtonFocused = _useState4[1];
127
+ var actionsButtonAriaLabel = (0, _i18n.useEuiI18n)('euiDataGridHeaderCell.actionsButtonAriaLabel', '{title}. Click to view column header actions.', {
128
+ title: title
129
+ });
130
+ var actionsEnterKeyInstructions = (0, _i18n.useEuiI18n)('euiDataGridHeaderCell.actionsEnterKeyInstructions', "Press the Enter key to view this column's actions");
131
+
132
+ /*
133
+ * Column sorting
134
+ */
109
135
  var _useSortingUtils = useSortingUtils({
110
136
  sorting: sorting,
111
137
  id: id,
@@ -118,13 +144,12 @@ var EuiDataGridHeaderCell = exports.EuiDataGridHeaderCell = /*#__PURE__*/(0, _re
118
144
  prefix: 'euiDataGridCellHeader',
119
145
  suffix: 'sorting'
120
146
  });
121
- var actionsAriaId = (0, _accessibility.useGeneratedHtmlId)({
122
- prefix: 'euiDataGridCellHeader',
123
- suffix: 'actions'
124
- });
147
+
148
+ /*
149
+ * Rendering
150
+ */
125
151
  var classes = (0, _classnames2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)({}, "euiDataGridHeaderCell--".concat(columnType), columnType), 'euiDataGridHeaderCell--hasColumnActions', showColumnActions), 'euiDataGridHeaderCell--isActionsPopoverOpen', isPopoverOpen), displayHeaderCellProps === null || displayHeaderCellProps === void 0 ? void 0 : displayHeaderCellProps.className);
126
- var title = displayAsText || id;
127
- var children = display || displayAsText || id;
152
+ var emptyHoverStyles = (0, _services.useEuiMemoizedStyles)(_button_icon._emptyHoverStyles);
128
153
  return (0, _react2.jsx)(_data_grid_header_cell_wrapper.EuiDataGridHeaderCellWrapper, (0, _extends2.default)({}, displayHeaderCellProps, {
129
154
  className: classes,
130
155
  id: id,
@@ -132,75 +157,58 @@ var EuiDataGridHeaderCell = exports.EuiDataGridHeaderCell = /*#__PURE__*/(0, _re
132
157
  width: width,
133
158
  "aria-sort": ariaSort,
134
159
  hasActionsPopover: showColumnActions,
135
- isActionsButtonFocused: isActionsButtonFocused,
136
- focusActionsButton: focusActionsButton
137
- }), column.isResizable !== false && width != null ? (0, _react2.jsx)(_data_grid_column_resizer.EuiDataGridColumnResizer, {
138
- columnId: id,
139
- columnWidth: width,
140
- setColumnWidth: setColumnWidth
141
- }) : null, !showColumnActions ? (0, _react2.jsx)(_react.default.Fragment, null, (0, _react2.jsx)(CellContent, {
142
- title: title,
143
- arrow: sortingArrow
144
- }, children), sortingScreenReaderText && (0, _react2.jsx)(_accessibility2.EuiScreenReaderOnly, null, (0, _react2.jsx)("p", null, sortingScreenReaderText))) : (0, _react2.jsx)(_react.default.Fragment, null, (0, _react2.jsx)("button", {
145
- className: "euiDataGridHeaderCell__button",
146
- onClick: function onClick() {
147
- return setIsPopoverOpen(function (isPopoverOpen) {
148
- return !isPopoverOpen;
149
- });
150
- },
151
- onFocus: function onFocus() {
152
- return setIsActionsButtonFocused(true);
153
- },
154
- onBlur: function onBlur() {
155
- return setIsActionsButtonFocused(false);
156
- },
157
- "aria-describedby": "".concat(sortingAriaId, " ").concat(actionsAriaId),
158
- ref: actionsButtonRef,
159
- "data-test-subj": "dataGridHeaderCellActionButton-".concat(id)
160
- }, (0, _react2.jsx)(CellContent, {
161
- title: title,
162
- arrow: sortingArrow
163
- }, children), (0, _react2.jsx)(_popover.EuiPopover, (0, _extends2.default)({
164
- display: "block",
165
- panelPaddingSize: "none",
166
- offset: 7,
167
- anchorPosition: "downRight",
168
- css: _ref3 // Align to right
160
+ openActionsPopover: clickActionsButton,
161
+ "aria-label": displayAsText && "".concat(displayAsText, ", ") // ensure cell text content is read first, if available
169
162
  ,
170
- focusTrapProps: {
171
- // We need to override the default EuiPopover `onClickOutside` since the anchor is separate from the actual button
172
- onClickOutside: function onClickOutside(event) {
173
- var _actionsButtonRef$cur2;
174
- if (((_actionsButtonRef$cur2 = actionsButtonRef.current) === null || _actionsButtonRef$cur2 === void 0 ? void 0 : _actionsButtonRef$cur2.contains(event.target)) === false) {
175
- setIsPopoverOpen(false);
176
- }
177
- }
178
- },
179
- button: (0, _react2.jsx)("div", {
180
- className: "euiDataGridHeaderCell__icon"
181
- }, (0, _react2.jsx)(_icon.EuiIcon, {
182
- type: "boxesVertical",
183
- size: "s",
184
- color: "text"
185
- })),
186
- isOpen: isPopoverOpen,
187
- closePopover: function closePopover() {
188
- return setIsPopoverOpen(false);
189
- }
190
- }, popoverArrowNavigationProps), (0, _react2.jsx)(_list_group.EuiListGroup, {
191
- listItems: columnActions,
192
- gutterSize: "none",
193
- "data-test-subj": "dataGridHeaderCellActionGroup-".concat(id)
194
- }))), (0, _react2.jsx)("p", {
195
- id: sortingAriaId,
196
- hidden: true
197
- }, sortingScreenReaderText), (0, _react2.jsx)("p", {
198
- id: actionsAriaId,
199
- hidden: true
200
- }, (0, _react2.jsx)(_i18n.EuiI18n, {
201
- token: "euiDataGridHeaderCell.headerActions",
202
- default: "Click to view column header actions"
203
- }))));
163
+ "aria-describedby": sortingAriaId
164
+ }), function (hasFocusTrap) {
165
+ return (0, _react2.jsx)(_react.default.Fragment, null, column.isResizable !== false && width != null ? (0, _react2.jsx)(_data_grid_column_resizer.EuiDataGridColumnResizer, {
166
+ columnId: id,
167
+ columnWidth: width,
168
+ setColumnWidth: setColumnWidth
169
+ }) : null, (0, _react2.jsx)(CellContent, {
170
+ title: title,
171
+ arrow: sortingArrow
172
+ }, children), sortingScreenReaderText && (0, _react2.jsx)("p", {
173
+ id: sortingAriaId,
174
+ hidden: true
175
+ }, sortingScreenReaderText), showColumnActions && (0, _react2.jsx)(_popover.EuiPopover, (0, _extends2.default)({
176
+ display: "block",
177
+ panelPaddingSize: "none",
178
+ offset: 7,
179
+ anchorPosition: "downRight",
180
+ css: _ref3 // Align to right
181
+ ,
182
+ button: (0, _react2.jsx)("button", {
183
+ ref: actionsButtonRef,
184
+ className: "euiDataGridHeaderCell__button",
185
+ css: emptyHoverStyles.text,
186
+ onClick: togglePopover,
187
+ onFocus: function onFocus() {
188
+ return setIsActionsButtonFocused(true);
189
+ },
190
+ onBlur: function onBlur() {
191
+ return setIsActionsButtonFocused(false);
192
+ },
193
+ "aria-hidden": hasFocusTrap && !isActionsButtonFocused ? 'true' // prevent the actions button from being read on cell focus
194
+ : undefined,
195
+ "aria-label": hasFocusTrap ? actionsButtonAriaLabel : actionsEnterKeyInstructions,
196
+ "data-test-subj": "dataGridHeaderCellActionButton-".concat(id)
197
+ }, (0, _react2.jsx)("div", {
198
+ className: "euiDataGridHeaderCell__icon"
199
+ }, (0, _react2.jsx)(_icon.EuiIcon, {
200
+ type: "boxesVertical",
201
+ size: "s",
202
+ color: "text"
203
+ }))),
204
+ isOpen: isPopoverOpen,
205
+ closePopover: closePopover
206
+ }, popoverArrowNavigationProps), (0, _react2.jsx)(_list_group.EuiListGroup, {
207
+ listItems: columnActions,
208
+ gutterSize: "none",
209
+ "data-test-subj": "dataGridHeaderCellActionGroup-".concat(id)
210
+ })));
211
+ });
204
212
  });
205
213
  EuiDataGridHeaderCell.propTypes = {
206
214
  column: _propTypes.default.shape({
@@ -217,6 +225,7 @@ EuiDataGridHeaderCell.propTypes = {
217
225
  * This can be used to display a readable column name in column hiding/sorting, where `display` won't be used.
218
226
  * This will also be used as a `title` attribute that will display on mouseover (useful if the display text is being truncated by the column width).
219
227
  * If not passed, `id` will be shown as the column name.
228
+ * Passing this together with `display` is useful to ensure an accessible label is added to the column.
220
229
  */
221
230
  displayAsText: _propTypes.default.string,
222
231
  /**
@@ -9,13 +9,14 @@ exports.EuiDataGridHeaderCellWrapper = void 0;
9
9
  var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
10
10
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
11
11
  var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
12
- var _classnames = _interopRequireDefault(require("classnames"));
13
- var _propTypes = _interopRequireDefault(require("prop-types"));
14
12
  var _react = _interopRequireWildcard(require("react"));
13
+ var _propTypes = _interopRequireDefault(require("prop-types"));
14
+ var _classnames = _interopRequireDefault(require("classnames"));
15
+ var _services = require("../../../../services");
15
16
  var _focus = require("../../utils/focus");
16
17
  var _focus_utils = require("../cell/focus_utils");
17
18
  var _react2 = require("@emotion/react");
18
- var _excluded = ["id", "index", "width", "className", "children", "hasActionsPopover", "isActionsButtonFocused", "focusActionsButton"];
19
+ var _excluded = ["id", "index", "width", "className", "children", "hasActionsPopover", "openActionsPopover", "aria-label"];
19
20
  /*
20
21
  * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
21
22
  * or more contributor license agreements. Licensed under the Elastic License
@@ -37,8 +38,8 @@ var EuiDataGridHeaderCellWrapper = exports.EuiDataGridHeaderCellWrapper = functi
37
38
  className = _ref.className,
38
39
  children = _ref.children,
39
40
  hasActionsPopover = _ref.hasActionsPopover,
40
- isActionsButtonFocused = _ref.isActionsButtonFocused,
41
- focusActionsButton = _ref.focusActionsButton,
41
+ openActionsPopover = _ref.openActionsPopover,
42
+ ariaLabel = _ref['aria-label'],
42
43
  rest = (0, _objectWithoutProperties2.default)(_ref, _excluded);
43
44
  var classes = (0, _classnames.default)('euiDataGridHeaderCell', className);
44
45
 
@@ -47,16 +48,28 @@ var EuiDataGridHeaderCellWrapper = exports.EuiDataGridHeaderCellWrapper = functi
47
48
  _useState2 = (0, _slicedToArray2.default)(_useState, 2),
48
49
  headerEl = _useState2[0],
49
50
  setHeaderEl = _useState2[1];
51
+ var _useState3 = (0, _react.useState)(false),
52
+ _useState4 = (0, _slicedToArray2.default)(_useState3, 2),
53
+ renderFocusTrap = _useState4[0],
54
+ setRenderFocusTrap = _useState4[1];
55
+ var _useState5 = (0, _react.useState)([]),
56
+ _useState6 = (0, _slicedToArray2.default)(_useState5, 2),
57
+ interactiveChildren = _useState6[0],
58
+ setInteractiveChildren = _useState6[1];
59
+ (0, _react.useEffect)(function () {
60
+ // We're checking for interactive children outside of the default actions button
61
+ setRenderFocusTrap(interactiveChildren.length > (hasActionsPopover ? 1 : 0));
62
+ }, [hasActionsPopover, interactiveChildren]);
50
63
  var _useContext = (0, _react.useContext)(_focus.DataGridFocusContext),
51
64
  setFocusedCell = _useContext.setFocusedCell,
52
65
  onFocusUpdate = _useContext.onFocusUpdate;
53
66
  var updateCellFocusContext = (0, _react.useCallback)(function () {
54
67
  setFocusedCell([index, -1]);
55
68
  }, [index, setFocusedCell]);
56
- var _useState3 = (0, _react.useState)(false),
57
- _useState4 = (0, _slicedToArray2.default)(_useState3, 2),
58
- isFocused = _useState4[0],
59
- setIsFocused = _useState4[1];
69
+ var _useState7 = (0, _react.useState)(false),
70
+ _useState8 = (0, _slicedToArray2.default)(_useState7, 2),
71
+ isFocused = _useState8[0],
72
+ setIsFocused = _useState8[1];
60
73
  (0, _react.useEffect)(function () {
61
74
  onFocusUpdate([index, -1], function (isFocused) {
62
75
  setIsFocused(isFocused);
@@ -69,18 +82,17 @@ var EuiDataGridHeaderCellWrapper = exports.EuiDataGridHeaderCellWrapper = functi
69
82
  });
70
83
  }, [index, onFocusUpdate, headerEl]);
71
84
 
72
- // For cell headers with actions, auto-focus into the button instead of the cell wrapper div
73
- // The button text is significantly more useful to screen readers (e.g. contains sort order & hints)
74
- var onFocus = (0, _react.useCallback)(function (e) {
75
- if (hasActionsPopover && e.target === headerEl) {
76
- focusActionsButton === null || focusActionsButton === void 0 || focusActionsButton();
85
+ // For cell headers with only actions, auto-open the actions popover on enter keypress
86
+ var onKeyDown = (0, _react.useCallback)(function (e) {
87
+ if (e.key === _services.keys.ENTER && hasActionsPopover && !renderFocusTrap && e.target === headerEl) {
88
+ openActionsPopover === null || openActionsPopover === void 0 || openActionsPopover();
77
89
  }
78
- }, [hasActionsPopover, focusActionsButton, headerEl]);
90
+ }, [hasActionsPopover, openActionsPopover, renderFocusTrap, headerEl]);
79
91
  return (0, _react2.jsx)("div", (0, _extends2.default)({
80
92
  role: "columnheader",
81
93
  ref: setHeaderEl,
82
- tabIndex: isFocused && !isActionsButtonFocused ? 0 : -1,
83
- onFocus: onFocus,
94
+ tabIndex: isFocused ? 0 : -1,
95
+ onKeyDown: onKeyDown,
84
96
  className: classes,
85
97
  "data-test-subj": "dataGridHeaderCell-".concat(id),
86
98
  "data-gridcell-column-id": id,
@@ -89,19 +101,22 @@ var EuiDataGridHeaderCellWrapper = exports.EuiDataGridHeaderCellWrapper = functi
89
101
  "data-gridcell-visible-row-index": "-1",
90
102
  style: width != null ? {
91
103
  width: "".concat(width, "px")
92
- } : {}
104
+ } : {},
105
+ "aria-label": renderFocusTrap ? ariaLabel : undefined
93
106
  }, rest), (0, _react2.jsx)(_focus_utils.HandleInteractiveChildren, {
94
107
  cellEl: headerEl,
95
108
  updateCellFocusContext: updateCellFocusContext,
96
- renderFocusTrap: !hasActionsPopover
97
- }, children));
109
+ renderFocusTrap: renderFocusTrap,
110
+ onInteractiveChildrenFound: setInteractiveChildren
111
+ }, typeof children === 'function' ? children(renderFocusTrap) : children));
98
112
  };
99
113
  EuiDataGridHeaderCellWrapper.propTypes = {
114
+ children: _propTypes.default.oneOfType([_propTypes.default.node.isRequired, _propTypes.default.func.isRequired]).isRequired,
100
115
  id: _propTypes.default.string.isRequired,
101
116
  index: _propTypes.default.number.isRequired,
102
117
  width: _propTypes.default.oneOfType([_propTypes.default.number.isRequired, _propTypes.default.oneOf([null])]),
103
118
  className: _propTypes.default.string,
119
+ "aria-label": _propTypes.default.any,
104
120
  hasActionsPopover: _propTypes.default.bool,
105
- isActionsButtonFocused: _propTypes.default.bool,
106
- focusActionsButton: _propTypes.default.func
121
+ openActionsPopover: _propTypes.default.func
107
122
  };
@@ -274,6 +274,7 @@ DataGridSortingControl.propTypes = {
274
274
  * This can be used to display a readable column name in column hiding/sorting, where `display` won't be used.
275
275
  * This will also be used as a `title` attribute that will display on mouseover (useful if the display text is being truncated by the column width).
276
276
  * If not passed, `id` will be shown as the column name.
277
+ * Passing this together with `display` is useful to ensure an accessible label is added to the column.
277
278
  */
278
279
  displayAsText: _propTypes.default.string,
279
280
  /**
@@ -210,6 +210,7 @@ describe('EuiDataGrid', function () {
210
210
  cy.checkAxe();
211
211
  });
212
212
  it('has zero violations when the column actions menu is open', function () {
213
+ cy.get('.euiDataGridHeaderCell').first().realHover();
213
214
  cy.get('button.euiDataGridHeaderCell__button').first().realClick();
214
215
  cy.checkAxe();
215
216
  });
@@ -219,6 +220,7 @@ describe('EuiDataGrid', function () {
219
220
  cy.checkAxe();
220
221
  });
221
222
  it('has zero violations on sort and when the columns sorting menu is open', function () {
223
+ cy.get('.euiDataGridHeaderCell').last().realHover();
222
224
  cy.get('button.euiDataGridHeaderCell__button').last().realClick();
223
225
  cy.get('button.euiListGroupItem__button').contains('Sort Alma to Debian').should('exist').realClick();
224
226
  cy.get('div[data-test-subj="dataGridColumnSortingPopover"] button').realClick();
@@ -206,6 +206,7 @@ EuiDataGridInMemoryRenderer.propTypes = {
206
206
  * This can be used to display a readable column name in column hiding/sorting, where `display` won't be used.
207
207
  * This will also be used as a `title` attribute that will display on mouseover (useful if the display text is being truncated by the column width).
208
208
  * If not passed, `id` will be shown as the column name.
209
+ * Passing this together with `display` is useful to ensure an accessible label is added to the column.
209
210
  */
210
211
  displayAsText: _propTypes.default.string,
211
212
  /**