@elastic/eui 74.1.0 → 75.0.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 (27) hide show
  1. package/es/components/collapsible_nav/collapsible_nav.js +10 -11
  2. package/es/components/flyout/flyout.js +88 -24
  3. package/es/components/header/header.js +3 -1
  4. package/es/components/search_bar/filters/field_value_selection_filter.js +6 -10
  5. package/es/components/selectable/selectable_list/selectable_list.js +19 -5
  6. package/eui.d.ts +15 -12
  7. package/i18ntokens.json +50 -2
  8. package/lib/components/collapsible_nav/collapsible_nav.js +10 -11
  9. package/lib/components/flyout/flyout.js +85 -22
  10. package/lib/components/header/header.js +3 -1
  11. package/lib/components/search_bar/filters/field_value_selection_filter.js +6 -10
  12. package/lib/components/selectable/selectable_list/selectable_list.js +19 -5
  13. package/optimize/es/components/collapsible_nav/collapsible_nav.js +1 -4
  14. package/optimize/es/components/flyout/flyout.js +81 -24
  15. package/optimize/es/components/header/header.js +3 -1
  16. package/optimize/es/components/search_bar/filters/field_value_selection_filter.js +6 -10
  17. package/optimize/es/components/selectable/selectable_list/selectable_list.js +19 -5
  18. package/optimize/lib/components/collapsible_nav/collapsible_nav.js +1 -4
  19. package/optimize/lib/components/flyout/flyout.js +80 -22
  20. package/optimize/lib/components/header/header.js +3 -1
  21. package/optimize/lib/components/search_bar/filters/field_value_selection_filter.js +6 -10
  22. package/optimize/lib/components/selectable/selectable_list/selectable_list.js +16 -5
  23. package/package.json +2 -2
  24. package/test-env/components/collapsible_nav/collapsible_nav.js +10 -11
  25. package/test-env/components/header/header.js +3 -1
  26. package/test-env/components/search_bar/filters/field_value_selection_filter.js +6 -10
  27. package/test-env/components/selectable/selectable_list/selectable_list.js +16 -5
@@ -27,11 +27,13 @@ var _resize_observer = require("../observer/resize_observer");
27
27
 
28
28
  var _portal = require("../portal");
29
29
 
30
+ var _accessibility = require("../accessibility");
31
+
30
32
  var _flyout = require("./flyout.styles");
31
33
 
32
34
  var _react2 = require("@emotion/react");
33
35
 
34
- var _excluded = ["className", "children", "as", "hideCloseButton", "closeButtonProps", "closeButtonAriaLabel", "closeButtonPosition", "onClose", "ownFocus", "side", "size", "paddingSize", "maxWidth", "style", "maskProps", "type", "outsideClickCloses", "role", "pushMinBreakpoint", "focusTrapProps"];
36
+ var _excluded = ["className", "children", "as", "hideCloseButton", "closeButtonProps", "closeButtonPosition", "onClose", "ownFocus", "side", "size", "paddingSize", "maxWidth", "style", "maskProps", "type", "outsideClickCloses", "pushMinBreakpoint", "focusTrapProps", "includeFixedHeadersInFocusTrap"];
35
37
 
36
38
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
37
39
 
@@ -39,6 +41,14 @@ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "functio
39
41
 
40
42
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
41
43
 
44
+ function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
45
+
46
+ function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
47
+
48
+ function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
49
+
50
+ function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
51
+
42
52
  function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
43
53
 
44
54
  function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
@@ -88,7 +98,6 @@ var EuiFlyout = /*#__PURE__*/(0, _react.forwardRef)(function (_ref, ref) {
88
98
  _ref$hideCloseButton = _ref.hideCloseButton,
89
99
  hideCloseButton = _ref$hideCloseButton === void 0 ? false : _ref$hideCloseButton,
90
100
  closeButtonProps = _ref.closeButtonProps,
91
- closeButtonAriaLabel = _ref.closeButtonAriaLabel,
92
101
  _ref$closeButtonPosit = _ref.closeButtonPosition,
93
102
  closeButtonPosition = _ref$closeButtonPosit === void 0 ? 'inside' : _ref$closeButtonPosit,
94
103
  onClose = _ref.onClose,
@@ -107,11 +116,12 @@ var EuiFlyout = /*#__PURE__*/(0, _react.forwardRef)(function (_ref, ref) {
107
116
  _ref$type = _ref.type,
108
117
  type = _ref$type === void 0 ? 'overlay' : _ref$type,
109
118
  outsideClickCloses = _ref.outsideClickCloses,
110
- _ref$role = _ref.role,
111
- role = _ref$role === void 0 ? 'dialog' : _ref$role,
112
119
  _ref$pushMinBreakpoin = _ref.pushMinBreakpoint,
113
120
  pushMinBreakpoint = _ref$pushMinBreakpoin === void 0 ? 'l' : _ref$pushMinBreakpoin,
114
- focusTrapProps = _ref.focusTrapProps,
121
+ _ref$focusTrapProps = _ref.focusTrapProps,
122
+ _focusTrapProps = _ref$focusTrapProps === void 0 ? {} : _ref$focusTrapProps,
123
+ _ref$includeFixedHead = _ref.includeFixedHeadersInFocusTrap,
124
+ includeFixedHeadersInFocusTrap = _ref$includeFixedHead === void 0 ? true : _ref$includeFixedHead,
115
125
  rest = _objectWithoutProperties(_ref, _excluded);
116
126
 
117
127
  var Element = as || defaultElement;
@@ -204,7 +214,7 @@ var EuiFlyout = /*#__PURE__*/(0, _react.forwardRef)(function (_ref, ref) {
204
214
  display: closeButtonPosition === 'outside' ? 'fill' : 'empty',
205
215
  iconType: "cross",
206
216
  color: "text",
207
- "aria-label": closeButtonAriaLabel || closeAriaLabel,
217
+ "aria-label": closeAriaLabel,
208
218
  "data-test-subj": "euiFlyoutCloseButton"
209
219
  }, closeButtonProps, {
210
220
  className: closeButtonClasses,
@@ -217,24 +227,60 @@ var EuiFlyout = /*#__PURE__*/(0, _react.forwardRef)(function (_ref, ref) {
217
227
  }));
218
228
  });
219
229
  }
230
+ /*
231
+ * If not disabled, automatically add fixed EuiHeaders as shards
232
+ * to EuiFlyout focus traps, to prevent focus fighting
233
+ */
220
234
 
221
- var hasOverlayMask = ownFocus && !isPushed;
222
235
 
223
- var onClickOutside = function onClickOutside(event) {
224
- // Do not close the flyout for any external click
225
- if (outsideClickCloses === false) return undefined;
236
+ var flyoutToggle = (0, _react.useRef)(document.activeElement);
226
237
 
227
- if (hasOverlayMask) {
228
- // The overlay mask is present, so only clicks on the mask should close the flyout, regardless of outsideClickCloses
229
- if (event.target === maskRef.current) return onClose(event);
238
+ var _useState3 = (0, _react.useState)([]),
239
+ _useState4 = _slicedToArray(_useState3, 2),
240
+ fixedHeaders = _useState4[0],
241
+ setFixedHeaders = _useState4[1];
242
+
243
+ (0, _react.useEffect)(function () {
244
+ if (includeFixedHeadersInFocusTrap) {
245
+ var fixedHeaderEls = document.querySelectorAll('.euiHeader[data-fixed-header]');
246
+ setFixedHeaders(Array.from(fixedHeaderEls)); // Flyouts that are toggled from fixed headers do not have working
247
+ // focus trap autoFocus, so we need to focus the flyout wrapper ourselves
248
+
249
+ fixedHeaderEls.forEach(function (header) {
250
+ if (header.contains(flyoutToggle.current)) {
251
+ resizeRef === null || resizeRef === void 0 ? void 0 : resizeRef.focus();
252
+ }
253
+ });
230
254
  } else {
231
- // No overlay mask is present, so any outside clicks should close the flyout
232
- if (outsideClickCloses === true) return onClose(event);
233
- } // Otherwise if ownFocus is false and outsideClickCloses is undefined, outside clicks should not close the flyout
255
+ // Clear existing headers if necessary, e.g. switching to `false`
256
+ setFixedHeaders(function (headers) {
257
+ return headers.length ? [] : headers;
258
+ });
259
+ }
260
+ }, [includeFixedHeadersInFocusTrap, resizeRef]);
234
261
 
262
+ var focusTrapProps = _objectSpread(_objectSpread({}, _focusTrapProps), {}, {
263
+ shards: [].concat(_toConsumableArray(fixedHeaders), _toConsumableArray(_focusTrapProps.shards || []))
264
+ });
265
+ /*
266
+ * Provide meaningful screen reader instructions/details
267
+ */
235
268
 
236
- return undefined;
237
- };
269
+
270
+ var hasOverlayMask = ownFocus && !isPushed;
271
+ var descriptionId = (0, _services.useGeneratedHtmlId)();
272
+ var screenReaderDescription = (0, _react2.jsx)(_accessibility.EuiScreenReaderOnly, null, (0, _react2.jsx)("p", {
273
+ id: descriptionId
274
+ }, hasOverlayMask ? (0, _react2.jsx)(_i18n.EuiI18n, {
275
+ token: "euiFlyout.screenReaderModalDialog",
276
+ default: "You are in a modal dialog. Press Escape or tap/click outside the dialog on the shadowed overlay to close."
277
+ }) : (0, _react2.jsx)(_i18n.EuiI18n, {
278
+ token: "euiFlyout.screenReaderNonModalDialog",
279
+ default: "You are in a non-modal dialog. To close the dialog, press Escape."
280
+ }), ' ', fixedHeaders.length > 0 && (0, _react2.jsx)(_i18n.EuiI18n, {
281
+ token: "euiFlyout.screenReaderFixedHeaders",
282
+ default: "You can still continue tabbing through the page headers in addition to the dialog."
283
+ })));
238
284
  /*
239
285
  * Trap focus even when `ownFocus={false}`, otherwise closing
240
286
  * the flyout won't return focus to the originating button.
@@ -248,6 +294,21 @@ var EuiFlyout = /*#__PURE__*/(0, _react.forwardRef)(function (_ref, ref) {
248
294
  * (both mousedown and mouseup) the overlay mask.
249
295
  */
250
296
 
297
+ var onClickOutside = function onClickOutside(event) {
298
+ // Do not close the flyout for any external click
299
+ if (outsideClickCloses === false) return undefined;
300
+
301
+ if (hasOverlayMask) {
302
+ // The overlay mask is present, so only clicks on the mask should close the flyout, regardless of outsideClickCloses
303
+ if (event.target === maskRef.current) return onClose(event);
304
+ } else {
305
+ // No overlay mask is present, so any outside clicks should close the flyout
306
+ if (outsideClickCloses === true) return onClose(event);
307
+ } // Otherwise if ownFocus is false and outsideClickCloses is undefined, outside clicks should not close the flyout
308
+
309
+
310
+ return undefined;
311
+ };
251
312
 
252
313
  var flyout = (0, _react2.jsx)(_focus_trap.EuiFocusTrap, _extends({
253
314
  disabled: isPushed,
@@ -256,12 +317,14 @@ var EuiFlyout = /*#__PURE__*/(0, _react.forwardRef)(function (_ref, ref) {
256
317
  }, focusTrapProps), (0, _react2.jsx)(Element, _extends({
257
318
  css: cssStyles
258
319
  }, rest, {
259
- role: role,
320
+ role: "dialog",
260
321
  className: classes,
261
- tabIndex: -1,
322
+ tabIndex: 0,
323
+ "data-autofocus": true,
324
+ "aria-describedby": !isPushed ? descriptionId : undefined,
262
325
  style: newStyle,
263
326
  ref: setRef
264
- }), closeButton, children)); // If ownFocus is set, wrap with an overlay and allow the user to click it to close it.
327
+ }), !isPushed && screenReaderDescription, closeButton, children)); // If ownFocus is set, wrap with an overlay and allow the user to click it to close it.
265
328
 
266
329
  var mergedMaskProps = _objectSpread(_objectSpread({}, maskProps), {}, {
267
330
  maskRef: (0, _services.useCombinedRefs)([maskProps === null || maskProps === void 0 ? void 0 : maskProps.maskRef, maskRef])
@@ -276,7 +339,7 @@ var EuiFlyout = /*#__PURE__*/(0, _react.forwardRef)(function (_ref, ref) {
276
339
  flyout = (0, _react2.jsx)(_portal.EuiPortal, null, flyout);
277
340
  }
278
341
 
279
- return (0, _react2.jsx)(_react.Fragment, null, (0, _react2.jsx)(_services.EuiWindowEvent, {
342
+ return (0, _react2.jsx)(_react.default.Fragment, null, (0, _react2.jsx)(_services.EuiWindowEvent, {
280
343
  event: "keydown",
281
344
  handler: onKeyDown
282
345
  }), flyout);
@@ -106,7 +106,9 @@ var EuiHeader = function EuiHeader(_ref) {
106
106
  }
107
107
 
108
108
  return (0, _react2.jsx)("div", _extends({
109
- className: classes
109
+ className: classes,
110
+ "data-fixed-header": position === 'fixed' || undefined // Used by EuiFlyouts as a query selector
111
+
110
112
  }, rest), contents);
111
113
  };
112
114
 
@@ -292,16 +292,16 @@ var FieldValueSelectionFilter = /*#__PURE__*/function (_Component) {
292
292
  if (!multiSelect && autoClose) {
293
293
  this.closePopover();
294
294
 
295
- var _query = checked ? this.props.query.removeSimpleFieldClauses(field) : this.props.query.removeSimpleFieldClauses(field).addSimpleFieldValue(field, value, true, operator);
295
+ var _query = checked ? this.props.query.removeSimpleFieldClauses(field).addSimpleFieldValue(field, value, true, operator) : this.props.query.removeSimpleFieldClauses(field);
296
296
 
297
297
  this.props.onChange(_query);
298
298
  } else {
299
299
  if (multiSelect === 'or') {
300
- var _query2 = checked ? this.props.query.removeOrFieldValue(field, value) : this.props.query.addOrFieldValue(field, value, true, operator);
300
+ var _query2 = checked ? this.props.query.addOrFieldValue(field, value, true, operator) : this.props.query.removeOrFieldValue(field, value);
301
301
 
302
302
  this.props.onChange(_query2);
303
303
  } else {
304
- var _query3 = checked ? this.props.query.removeSimpleFieldValue(field, value) : this.props.query.addSimpleFieldValue(field, value, true, operator);
304
+ var _query3 = checked ? this.props.query.addSimpleFieldValue(field, value, true, operator) : this.props.query.removeSimpleFieldValue(field, value);
305
305
 
306
306
  this.props.onChange(_query3);
307
307
  }
@@ -409,13 +409,9 @@ var FieldValueSelectionFilter = /*#__PURE__*/function (_Component) {
409
409
  listProps: {
410
410
  isVirtualized: isOverSearchThreshold || false
411
411
  },
412
- onChange: function onChange(options) {
413
- var diff = items.find(function (item, index) {
414
- return item.checked !== options[index].checked;
415
- });
416
-
417
- if (diff) {
418
- _this5.onOptionClick(diff.data.optionField, diff.data.value, diff.checked);
412
+ onChange: function onChange(options, event, changedOption) {
413
+ if (changedOption.data) {
414
+ _this5.onOptionClick(changedOption.data.optionField, changedOption.data.value, changedOption.checked);
419
415
  }
420
416
  }
421
417
  }, searchProps), function (list, search) {
@@ -131,6 +131,22 @@ var EuiSelectableList = /*#__PURE__*/function (_Component) {
131
131
  }
132
132
  });
133
133
 
134
+ _defineProperty(_assertThisInitialized(_this), "ariaSetSize", 0);
135
+
136
+ _defineProperty(_assertThisInitialized(_this), "ariaPosInSetMap", {});
137
+
138
+ _defineProperty(_assertThisInitialized(_this), "calculateAriaSetAttrs", function (optionArray) {
139
+ _this.ariaPosInSetMap = {};
140
+ var latestAriaPosIndex = 0;
141
+ optionArray.forEach(function (option, index) {
142
+ if (!option.isGroupLabel) {
143
+ latestAriaPosIndex++;
144
+ _this.ariaPosInSetMap[index] = latestAriaPosIndex;
145
+ }
146
+ });
147
+ _this.ariaSetSize = latestAriaPosIndex;
148
+ });
149
+
134
150
  _defineProperty(_assertThisInitialized(_this), "ListRow", /*#__PURE__*/(0, _react.memo)(function (_ref) {
135
151
  var data = _ref.data,
136
152
  index = _ref.index,
@@ -174,9 +190,6 @@ var EuiSelectableList = /*#__PURE__*/function (_Component) {
174
190
  }, optionRest), prepend, label, append);
175
191
  }
176
192
 
177
- var labelCount = data.filter(function (option) {
178
- return option.isGroupLabel;
179
- }).length;
180
193
  var id = makeOptionId(index);
181
194
  return (0, _react2.jsx)(_selectable_list_item.EuiSelectableListItem, _extends({
182
195
  key: id,
@@ -197,8 +210,8 @@ var EuiSelectableList = /*#__PURE__*/function (_Component) {
197
210
  disabled: disabled,
198
211
  prepend: prepend,
199
212
  append: append,
200
- "aria-posinset": index + 1 - labelCount,
201
- "aria-setsize": data.length - labelCount,
213
+ "aria-posinset": _this.ariaPosInSetMap[index],
214
+ "aria-setsize": _this.ariaSetSize,
202
215
  onFocusBadge: onFocusBadge,
203
216
  allowExclusions: allowExclusions,
204
217
  showIcons: showIcons,
@@ -355,6 +368,7 @@ var EuiSelectableList = /*#__PURE__*/function (_Component) {
355
368
  rest = _objectWithoutProperties(_this$props7, _excluded3);
356
369
 
357
370
  var optionArray = visibleOptions || options;
371
+ this.calculateAriaSetAttrs(optionArray);
358
372
  var heightIsFull = forcedHeight === 'full';
359
373
  var calculatedHeight = heightIsFull ? false : forcedHeight; // If calculatedHeight is still undefined, then calculate it
360
374
 
@@ -2,7 +2,7 @@ import _extends from "@babel/runtime/helpers/extends";
2
2
  import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
3
3
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
4
4
  import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
5
- var _excluded = ["id", "children", "className", "isDocked", "isOpen", "button", "showButtonIfDocked", "dockedBreakpoint", "as", "size", "side", "role", "ownFocus", "outsideClickCloses", "closeButtonPosition", "paddingSize", "focusTrapProps"];
5
+ var _excluded = ["id", "children", "className", "isDocked", "isOpen", "button", "showButtonIfDocked", "dockedBreakpoint", "as", "size", "side", "ownFocus", "outsideClickCloses", "closeButtonPosition", "paddingSize", "focusTrapProps"];
6
6
 
7
7
  function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
8
8
 
@@ -40,8 +40,6 @@ export var EuiCollapsibleNav = function EuiCollapsibleNav(_ref) {
40
40
  size = _ref$size === void 0 ? 320 : _ref$size,
41
41
  _ref$side = _ref.side,
42
42
  side = _ref$side === void 0 ? 'left' : _ref$side,
43
- _ref$role = _ref.role,
44
- role = _ref$role === void 0 ? null : _ref$role,
45
43
  _ref$ownFocus = _ref.ownFocus,
46
44
  ownFocus = _ref$ownFocus === void 0 ? true : _ref$ownFocus,
47
45
  _ref$outsideClickClos = _ref.outsideClickCloses,
@@ -91,7 +89,6 @@ export var EuiCollapsibleNav = function EuiCollapsibleNav(_ref) {
91
89
  as: as,
92
90
  size: size,
93
91
  side: side,
94
- role: role,
95
92
  ownFocus: ownFocus,
96
93
  outsideClickCloses: outsideClickCloses,
97
94
  closeButtonPosition: closeButtonPosition,
@@ -1,8 +1,9 @@
1
+ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
1
2
  import _extends from "@babel/runtime/helpers/extends";
2
3
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
3
4
  import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
4
5
  import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
5
- var _excluded = ["className", "children", "as", "hideCloseButton", "closeButtonProps", "closeButtonAriaLabel", "closeButtonPosition", "onClose", "ownFocus", "side", "size", "paddingSize", "maxWidth", "style", "maskProps", "type", "outsideClickCloses", "role", "pushMinBreakpoint", "focusTrapProps"];
6
+ var _excluded = ["className", "children", "as", "hideCloseButton", "closeButtonProps", "closeButtonPosition", "onClose", "ownFocus", "side", "size", "paddingSize", "maxWidth", "style", "maskProps", "type", "outsideClickCloses", "pushMinBreakpoint", "focusTrapProps", "includeFixedHeadersInFocusTrap"];
6
7
 
7
8
  function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
8
9
 
@@ -15,9 +16,9 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
15
16
  * in compliance with, at your election, the Elastic License 2.0 or the Server
16
17
  * Side Public License, v 1.
17
18
  */
18
- import React, { useEffect, useRef, useState, forwardRef, Fragment } from 'react';
19
+ import React, { useEffect, useRef, useState, forwardRef } from 'react';
19
20
  import classnames from 'classnames';
20
- import { keys, EuiWindowEvent, useCombinedRefs, useIsWithinMinBreakpoint, useEuiTheme } from '../../services';
21
+ import { keys, EuiWindowEvent, useCombinedRefs, useIsWithinMinBreakpoint, useEuiTheme, useGeneratedHtmlId } from '../../services';
21
22
  import { logicalStyle } from '../../global_styling';
22
23
  import { EuiFocusTrap } from '../focus_trap';
23
24
  import { EuiOverlayMask } from '../overlay_mask';
@@ -25,6 +26,7 @@ import { EuiButtonIcon } from '../button';
25
26
  import { EuiI18n } from '../i18n';
26
27
  import { useResizeObserver } from '../observer/resize_observer';
27
28
  import { EuiPortal } from '../portal';
29
+ import { EuiScreenReaderOnly } from '../accessibility';
28
30
  import { euiFlyoutStyles, euiFlyoutCloseButtonStyles } from './flyout.styles';
29
31
  import { jsx as ___EmotionJSX } from "@emotion/react";
30
32
  export var TYPES = ['push', 'overlay'];
@@ -48,7 +50,6 @@ export var EuiFlyout = /*#__PURE__*/forwardRef(function (_ref, ref) {
48
50
  _ref$hideCloseButton = _ref.hideCloseButton,
49
51
  hideCloseButton = _ref$hideCloseButton === void 0 ? false : _ref$hideCloseButton,
50
52
  closeButtonProps = _ref.closeButtonProps,
51
- closeButtonAriaLabel = _ref.closeButtonAriaLabel,
52
53
  _ref$closeButtonPosit = _ref.closeButtonPosition,
53
54
  closeButtonPosition = _ref$closeButtonPosit === void 0 ? 'inside' : _ref$closeButtonPosit,
54
55
  onClose = _ref.onClose,
@@ -67,11 +68,12 @@ export var EuiFlyout = /*#__PURE__*/forwardRef(function (_ref, ref) {
67
68
  _ref$type = _ref.type,
68
69
  type = _ref$type === void 0 ? 'overlay' : _ref$type,
69
70
  outsideClickCloses = _ref.outsideClickCloses,
70
- _ref$role = _ref.role,
71
- role = _ref$role === void 0 ? 'dialog' : _ref$role,
72
71
  _ref$pushMinBreakpoin = _ref.pushMinBreakpoint,
73
72
  pushMinBreakpoint = _ref$pushMinBreakpoin === void 0 ? 'l' : _ref$pushMinBreakpoin,
74
- focusTrapProps = _ref.focusTrapProps,
73
+ _ref$focusTrapProps = _ref.focusTrapProps,
74
+ _focusTrapProps = _ref$focusTrapProps === void 0 ? {} : _ref$focusTrapProps,
75
+ _ref$includeFixedHead = _ref.includeFixedHeadersInFocusTrap,
76
+ includeFixedHeadersInFocusTrap = _ref$includeFixedHead === void 0 ? true : _ref$includeFixedHead,
75
77
  rest = _objectWithoutProperties(_ref, _excluded);
76
78
 
77
79
  var Element = as || defaultElement;
@@ -164,7 +166,7 @@ export var EuiFlyout = /*#__PURE__*/forwardRef(function (_ref, ref) {
164
166
  display: closeButtonPosition === 'outside' ? 'fill' : 'empty',
165
167
  iconType: "cross",
166
168
  color: "text",
167
- "aria-label": closeButtonAriaLabel || closeAriaLabel,
169
+ "aria-label": closeAriaLabel,
168
170
  "data-test-subj": "euiFlyoutCloseButton"
169
171
  }, closeButtonProps, {
170
172
  className: closeButtonClasses,
@@ -177,24 +179,61 @@ export var EuiFlyout = /*#__PURE__*/forwardRef(function (_ref, ref) {
177
179
  }));
178
180
  });
179
181
  }
182
+ /*
183
+ * If not disabled, automatically add fixed EuiHeaders as shards
184
+ * to EuiFlyout focus traps, to prevent focus fighting
185
+ */
180
186
 
181
- var hasOverlayMask = ownFocus && !isPushed;
182
187
 
183
- var onClickOutside = function onClickOutside(event) {
184
- // Do not close the flyout for any external click
185
- if (outsideClickCloses === false) return undefined;
188
+ var flyoutToggle = useRef(document.activeElement);
186
189
 
187
- if (hasOverlayMask) {
188
- // The overlay mask is present, so only clicks on the mask should close the flyout, regardless of outsideClickCloses
189
- if (event.target === maskRef.current) return onClose(event);
190
+ var _useState3 = useState([]),
191
+ _useState4 = _slicedToArray(_useState3, 2),
192
+ fixedHeaders = _useState4[0],
193
+ setFixedHeaders = _useState4[1];
194
+
195
+ useEffect(function () {
196
+ if (includeFixedHeadersInFocusTrap) {
197
+ var fixedHeaderEls = document.querySelectorAll('.euiHeader[data-fixed-header]');
198
+ setFixedHeaders(Array.from(fixedHeaderEls)); // Flyouts that are toggled from fixed headers do not have working
199
+ // focus trap autoFocus, so we need to focus the flyout wrapper ourselves
200
+
201
+ fixedHeaderEls.forEach(function (header) {
202
+ if (header.contains(flyoutToggle.current)) {
203
+ resizeRef === null || resizeRef === void 0 ? void 0 : resizeRef.focus();
204
+ }
205
+ });
190
206
  } else {
191
- // No overlay mask is present, so any outside clicks should close the flyout
192
- if (outsideClickCloses === true) return onClose(event);
193
- } // Otherwise if ownFocus is false and outsideClickCloses is undefined, outside clicks should not close the flyout
207
+ // Clear existing headers if necessary, e.g. switching to `false`
208
+ setFixedHeaders(function (headers) {
209
+ return headers.length ? [] : headers;
210
+ });
211
+ }
212
+ }, [includeFixedHeadersInFocusTrap, resizeRef]);
194
213
 
214
+ var focusTrapProps = _objectSpread(_objectSpread({}, _focusTrapProps), {}, {
215
+ shards: [].concat(_toConsumableArray(fixedHeaders), _toConsumableArray(_focusTrapProps.shards || []))
216
+ });
217
+ /*
218
+ * Provide meaningful screen reader instructions/details
219
+ */
195
220
 
196
- return undefined;
197
- };
221
+
222
+ var hasOverlayMask = ownFocus && !isPushed;
223
+ var descriptionId = useGeneratedHtmlId();
224
+
225
+ var screenReaderDescription = ___EmotionJSX(EuiScreenReaderOnly, null, ___EmotionJSX("p", {
226
+ id: descriptionId
227
+ }, hasOverlayMask ? ___EmotionJSX(EuiI18n, {
228
+ token: "euiFlyout.screenReaderModalDialog",
229
+ default: "You are in a modal dialog. Press Escape or tap/click outside the dialog on the shadowed overlay to close."
230
+ }) : ___EmotionJSX(EuiI18n, {
231
+ token: "euiFlyout.screenReaderNonModalDialog",
232
+ default: "You are in a non-modal dialog. To close the dialog, press Escape."
233
+ }), ' ', fixedHeaders.length > 0 && ___EmotionJSX(EuiI18n, {
234
+ token: "euiFlyout.screenReaderFixedHeaders",
235
+ default: "You can still continue tabbing through the page headers in addition to the dialog."
236
+ })));
198
237
  /*
199
238
  * Trap focus even when `ownFocus={false}`, otherwise closing
200
239
  * the flyout won't return focus to the originating button.
@@ -209,6 +248,22 @@ export var EuiFlyout = /*#__PURE__*/forwardRef(function (_ref, ref) {
209
248
  */
210
249
 
211
250
 
251
+ var onClickOutside = function onClickOutside(event) {
252
+ // Do not close the flyout for any external click
253
+ if (outsideClickCloses === false) return undefined;
254
+
255
+ if (hasOverlayMask) {
256
+ // The overlay mask is present, so only clicks on the mask should close the flyout, regardless of outsideClickCloses
257
+ if (event.target === maskRef.current) return onClose(event);
258
+ } else {
259
+ // No overlay mask is present, so any outside clicks should close the flyout
260
+ if (outsideClickCloses === true) return onClose(event);
261
+ } // Otherwise if ownFocus is false and outsideClickCloses is undefined, outside clicks should not close the flyout
262
+
263
+
264
+ return undefined;
265
+ };
266
+
212
267
  var flyout = ___EmotionJSX(EuiFocusTrap, _extends({
213
268
  disabled: isPushed,
214
269
  clickOutsideDisables: !ownFocus,
@@ -216,12 +271,14 @@ export var EuiFlyout = /*#__PURE__*/forwardRef(function (_ref, ref) {
216
271
  }, focusTrapProps), ___EmotionJSX(Element, _extends({
217
272
  css: cssStyles
218
273
  }, rest, {
219
- role: role,
274
+ role: "dialog",
220
275
  className: classes,
221
- tabIndex: -1,
276
+ tabIndex: 0,
277
+ "data-autofocus": true,
278
+ "aria-describedby": !isPushed ? descriptionId : undefined,
222
279
  style: newStyle,
223
280
  ref: setRef
224
- }), closeButton, children)); // If ownFocus is set, wrap with an overlay and allow the user to click it to close it.
281
+ }), !isPushed && screenReaderDescription, closeButton, children)); // If ownFocus is set, wrap with an overlay and allow the user to click it to close it.
225
282
 
226
283
 
227
284
  var mergedMaskProps = _objectSpread(_objectSpread({}, maskProps), {}, {
@@ -237,7 +294,7 @@ export var EuiFlyout = /*#__PURE__*/forwardRef(function (_ref, ref) {
237
294
  flyout = ___EmotionJSX(EuiPortal, null, flyout);
238
295
  }
239
296
 
240
- return ___EmotionJSX(Fragment, null, ___EmotionJSX(EuiWindowEvent, {
297
+ return ___EmotionJSX(React.Fragment, null, ___EmotionJSX(EuiWindowEvent, {
241
298
  event: "keydown",
242
299
  handler: onKeyDown
243
300
  }), flyout);
@@ -87,6 +87,8 @@ export var EuiHeader = function EuiHeader(_ref) {
87
87
  }
88
88
 
89
89
  return ___EmotionJSX("div", _extends({
90
- className: classes
90
+ className: classes,
91
+ "data-fixed-header": position === 'fixed' || undefined // Used by EuiFlyouts as a query selector
92
+
91
93
  }, rest), contents);
92
94
  };
@@ -251,16 +251,16 @@ export var FieldValueSelectionFilter = /*#__PURE__*/function (_Component) {
251
251
  if (!multiSelect && autoClose) {
252
252
  this.closePopover();
253
253
 
254
- var _query = checked ? this.props.query.removeSimpleFieldClauses(field) : this.props.query.removeSimpleFieldClauses(field).addSimpleFieldValue(field, value, true, operator);
254
+ var _query = checked ? this.props.query.removeSimpleFieldClauses(field).addSimpleFieldValue(field, value, true, operator) : this.props.query.removeSimpleFieldClauses(field);
255
255
 
256
256
  this.props.onChange(_query);
257
257
  } else {
258
258
  if (multiSelect === 'or') {
259
- var _query2 = checked ? this.props.query.removeOrFieldValue(field, value) : this.props.query.addOrFieldValue(field, value, true, operator);
259
+ var _query2 = checked ? this.props.query.addOrFieldValue(field, value, true, operator) : this.props.query.removeOrFieldValue(field, value);
260
260
 
261
261
  this.props.onChange(_query2);
262
262
  } else {
263
- var _query3 = checked ? this.props.query.removeSimpleFieldValue(field, value) : this.props.query.addSimpleFieldValue(field, value, true, operator);
263
+ var _query3 = checked ? this.props.query.addSimpleFieldValue(field, value, true, operator) : this.props.query.removeSimpleFieldValue(field, value);
264
264
 
265
265
  this.props.onChange(_query3);
266
266
  }
@@ -370,13 +370,9 @@ export var FieldValueSelectionFilter = /*#__PURE__*/function (_Component) {
370
370
  listProps: {
371
371
  isVirtualized: isOverSearchThreshold || false
372
372
  },
373
- onChange: function onChange(options) {
374
- var diff = items.find(function (item, index) {
375
- return item.checked !== options[index].checked;
376
- });
377
-
378
- if (diff) {
379
- _this5.onOptionClick(diff.data.optionField, diff.data.value, diff.checked);
373
+ onChange: function onChange(options, event, changedOption) {
374
+ if (changedOption.data) {
375
+ _this5.onOptionClick(changedOption.data.optionField, changedOption.data.value, changedOption.checked);
380
376
  }
381
377
  }
382
378
  }, searchProps), function (list, search) {
@@ -99,6 +99,22 @@ export var EuiSelectableList = /*#__PURE__*/function (_Component) {
99
99
  }
100
100
  });
101
101
 
102
+ _defineProperty(_assertThisInitialized(_this), "ariaSetSize", 0);
103
+
104
+ _defineProperty(_assertThisInitialized(_this), "ariaPosInSetMap", {});
105
+
106
+ _defineProperty(_assertThisInitialized(_this), "calculateAriaSetAttrs", function (optionArray) {
107
+ _this.ariaPosInSetMap = {};
108
+ var latestAriaPosIndex = 0;
109
+ optionArray.forEach(function (option, index) {
110
+ if (!option.isGroupLabel) {
111
+ latestAriaPosIndex++;
112
+ _this.ariaPosInSetMap[index] = latestAriaPosIndex;
113
+ }
114
+ });
115
+ _this.ariaSetSize = latestAriaPosIndex;
116
+ });
117
+
102
118
  _defineProperty(_assertThisInitialized(_this), "ListRow", /*#__PURE__*/memo(function (_ref) {
103
119
  var data = _ref.data,
104
120
  index = _ref.index,
@@ -142,9 +158,6 @@ export var EuiSelectableList = /*#__PURE__*/function (_Component) {
142
158
  }, optionRest), prepend, label, append);
143
159
  }
144
160
 
145
- var labelCount = data.filter(function (option) {
146
- return option.isGroupLabel;
147
- }).length;
148
161
  var id = makeOptionId(index);
149
162
  return ___EmotionJSX(EuiSelectableListItem, _extends({
150
163
  key: id,
@@ -165,8 +178,8 @@ export var EuiSelectableList = /*#__PURE__*/function (_Component) {
165
178
  disabled: disabled,
166
179
  prepend: prepend,
167
180
  append: append,
168
- "aria-posinset": index + 1 - labelCount,
169
- "aria-setsize": data.length - labelCount,
181
+ "aria-posinset": _this.ariaPosInSetMap[index],
182
+ "aria-setsize": _this.ariaSetSize,
170
183
  onFocusBadge: onFocusBadge,
171
184
  allowExclusions: allowExclusions,
172
185
  showIcons: showIcons,
@@ -323,6 +336,7 @@ export var EuiSelectableList = /*#__PURE__*/function (_Component) {
323
336
  rest = _objectWithoutProperties(_this$props7, _excluded3);
324
337
 
325
338
  var optionArray = visibleOptions || options;
339
+ this.calculateAriaSetAttrs(optionArray);
326
340
  var heightIsFull = forcedHeight === 'full';
327
341
  var calculatedHeight = heightIsFull ? false : forcedHeight; // If calculatedHeight is still undefined, then calculate it
328
342
 
@@ -27,7 +27,7 @@ var _flyout = require("../flyout");
27
27
 
28
28
  var _react2 = require("@emotion/react");
29
29
 
30
- var _excluded = ["id", "children", "className", "isDocked", "isOpen", "button", "showButtonIfDocked", "dockedBreakpoint", "as", "size", "side", "role", "ownFocus", "outsideClickCloses", "closeButtonPosition", "paddingSize", "focusTrapProps"];
30
+ var _excluded = ["id", "children", "className", "isDocked", "isOpen", "button", "showButtonIfDocked", "dockedBreakpoint", "as", "size", "side", "ownFocus", "outsideClickCloses", "closeButtonPosition", "paddingSize", "focusTrapProps"];
31
31
 
32
32
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
33
33
 
@@ -56,8 +56,6 @@ var EuiCollapsibleNav = function EuiCollapsibleNav(_ref) {
56
56
  size = _ref$size === void 0 ? 320 : _ref$size,
57
57
  _ref$side = _ref.side,
58
58
  side = _ref$side === void 0 ? 'left' : _ref$side,
59
- _ref$role = _ref.role,
60
- role = _ref$role === void 0 ? null : _ref$role,
61
59
  _ref$ownFocus = _ref.ownFocus,
62
60
  ownFocus = _ref$ownFocus === void 0 ? true : _ref$ownFocus,
63
61
  _ref$outsideClickClos = _ref.outsideClickCloses,
@@ -106,7 +104,6 @@ var EuiCollapsibleNav = function EuiCollapsibleNav(_ref) {
106
104
  as: as,
107
105
  size: size,
108
106
  side: side,
109
- role: role,
110
107
  ownFocus: ownFocus,
111
108
  outsideClickCloses: outsideClickCloses,
112
109
  closeButtonPosition: closeButtonPosition,