@elastic/eui 90.0.0 → 90.0.1-backport.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 (84) hide show
  1. package/es/components/collapsible_nav_beta/collapsible_nav_beta.styles.js +2 -2
  2. package/es/components/collapsible_nav_beta/collapsible_nav_body_footer.js +4 -1
  3. package/es/components/collapsible_nav_beta/collapsible_nav_body_footer.styles.js +13 -9
  4. package/es/components/collapsible_nav_beta/collapsible_nav_group/collapsible_nav_group.js +1 -101
  5. package/es/components/collapsible_nav_beta/collapsible_nav_item/collapsed/collapsed_nav_button.js +20 -58
  6. package/es/components/collapsible_nav_beta/collapsible_nav_item/collapsed/collapsed_nav_item.js +89 -37
  7. package/es/components/collapsible_nav_beta/collapsible_nav_item/collapsed/collapsed_nav_popover.js +67 -81
  8. package/es/components/collapsible_nav_beta/collapsible_nav_item/collapsed/collapsed_nav_popover.styles.js +1 -19
  9. package/es/components/collapsible_nav_beta/collapsible_nav_item/collapsible_nav_accordion.js +7 -102
  10. package/es/components/collapsible_nav_beta/collapsible_nav_item/collapsible_nav_accordion.styles.js +4 -4
  11. package/es/components/collapsible_nav_beta/collapsible_nav_item/collapsible_nav_group.js +11 -90
  12. package/es/components/collapsible_nav_beta/collapsible_nav_item/collapsible_nav_item.js +150 -130
  13. package/es/components/collapsible_nav_beta/collapsible_nav_item/collapsible_nav_link.js +0 -10
  14. package/es/components/combo_box/combo_box.js +1 -1
  15. package/es/components/selectable/selectable.js +16 -1
  16. package/es/components/selectable/selectable_list/selectable_list.js +232 -78
  17. package/es/components/selectable/selectable_templates/selectable_template_sitewide.js +16 -1
  18. package/es/components/text_truncate/text_truncate.js +33 -10
  19. package/eui.d.ts +381 -68
  20. package/i18ntokens.json +38 -38
  21. package/lib/components/collapsible_nav_beta/collapsible_nav_beta.styles.js +1 -1
  22. package/lib/components/collapsible_nav_beta/collapsible_nav_body_footer.js +4 -1
  23. package/lib/components/collapsible_nav_beta/collapsible_nav_body_footer.styles.js +13 -9
  24. package/lib/components/collapsible_nav_beta/collapsible_nav_group/collapsible_nav_group.js +1 -101
  25. package/lib/components/collapsible_nav_beta/collapsible_nav_item/collapsed/collapsed_nav_button.js +20 -58
  26. package/lib/components/collapsible_nav_beta/collapsible_nav_item/collapsed/collapsed_nav_item.js +89 -37
  27. package/lib/components/collapsible_nav_beta/collapsible_nav_item/collapsed/collapsed_nav_popover.js +66 -80
  28. package/lib/components/collapsible_nav_beta/collapsible_nav_item/collapsed/collapsed_nav_popover.styles.js +11 -28
  29. package/lib/components/collapsible_nav_beta/collapsible_nav_item/collapsible_nav_accordion.js +7 -104
  30. package/lib/components/collapsible_nav_beta/collapsible_nav_item/collapsible_nav_accordion.styles.js +4 -4
  31. package/lib/components/collapsible_nav_beta/collapsible_nav_item/collapsible_nav_group.js +10 -89
  32. package/lib/components/collapsible_nav_beta/collapsible_nav_item/collapsible_nav_item.js +150 -130
  33. package/lib/components/collapsible_nav_beta/collapsible_nav_item/collapsible_nav_link.js +0 -10
  34. package/lib/components/combo_box/combo_box.js +1 -1
  35. package/lib/components/selectable/selectable.js +16 -1
  36. package/lib/components/selectable/selectable_list/selectable_list.js +232 -78
  37. package/lib/components/selectable/selectable_templates/selectable_template_sitewide.js +16 -1
  38. package/lib/components/text_truncate/text_truncate.js +32 -9
  39. package/optimize/es/components/collapsible_nav_beta/collapsible_nav_beta.styles.js +2 -2
  40. package/optimize/es/components/collapsible_nav_beta/collapsible_nav_body_footer.js +4 -1
  41. package/optimize/es/components/collapsible_nav_beta/collapsible_nav_body_footer.styles.js +13 -9
  42. package/optimize/es/components/collapsible_nav_beta/collapsible_nav_item/collapsed/collapsed_nav_button.js +1 -3
  43. package/optimize/es/components/collapsible_nav_beta/collapsible_nav_item/collapsed/collapsed_nav_item.js +10 -5
  44. package/optimize/es/components/collapsible_nav_beta/collapsible_nav_item/collapsed/collapsed_nav_popover.js +8 -36
  45. package/optimize/es/components/collapsible_nav_beta/collapsible_nav_item/collapsed/collapsed_nav_popover.styles.js +1 -19
  46. package/optimize/es/components/collapsible_nav_beta/collapsible_nav_item/collapsible_nav_accordion.js +6 -23
  47. package/optimize/es/components/collapsible_nav_beta/collapsible_nav_item/collapsible_nav_accordion.styles.js +4 -4
  48. package/optimize/es/components/collapsible_nav_beta/collapsible_nav_item/collapsible_nav_group.js +10 -10
  49. package/optimize/es/components/collapsible_nav_beta/collapsible_nav_item/collapsible_nav_item.js +9 -5
  50. package/optimize/es/components/selectable/selectable_list/selectable_list.js +204 -76
  51. package/optimize/es/components/text_truncate/text_truncate.js +26 -9
  52. package/optimize/lib/components/collapsible_nav_beta/collapsible_nav_beta.styles.js +1 -1
  53. package/optimize/lib/components/collapsible_nav_beta/collapsible_nav_body_footer.js +4 -1
  54. package/optimize/lib/components/collapsible_nav_beta/collapsible_nav_body_footer.styles.js +13 -9
  55. package/optimize/lib/components/collapsible_nav_beta/collapsible_nav_item/collapsed/collapsed_nav_button.js +1 -3
  56. package/optimize/lib/components/collapsible_nav_beta/collapsible_nav_item/collapsed/collapsed_nav_item.js +10 -5
  57. package/optimize/lib/components/collapsible_nav_beta/collapsible_nav_item/collapsed/collapsed_nav_popover.js +8 -36
  58. package/optimize/lib/components/collapsible_nav_beta/collapsible_nav_item/collapsed/collapsed_nav_popover.styles.js +11 -28
  59. package/optimize/lib/components/collapsible_nav_beta/collapsible_nav_item/collapsible_nav_accordion.js +6 -26
  60. package/optimize/lib/components/collapsible_nav_beta/collapsible_nav_item/collapsible_nav_accordion.styles.js +4 -4
  61. package/optimize/lib/components/collapsible_nav_beta/collapsible_nav_item/collapsible_nav_group.js +9 -9
  62. package/optimize/lib/components/collapsible_nav_beta/collapsible_nav_item/collapsible_nav_item.js +9 -5
  63. package/optimize/lib/components/selectable/selectable_list/selectable_list.js +204 -76
  64. package/optimize/lib/components/text_truncate/text_truncate.js +25 -8
  65. package/package.json +3 -4
  66. package/test-env/components/auto_sizer/auto_sizer.js +10 -3
  67. package/test-env/components/collapsible_nav_beta/collapsible_nav_beta.styles.js +1 -1
  68. package/test-env/components/collapsible_nav_beta/collapsible_nav_body_footer.js +4 -1
  69. package/test-env/components/collapsible_nav_beta/collapsible_nav_body_footer.styles.js +13 -9
  70. package/test-env/components/collapsible_nav_beta/collapsible_nav_group/collapsible_nav_group.js +1 -101
  71. package/test-env/components/collapsible_nav_beta/collapsible_nav_item/collapsed/collapsed_nav_button.js +20 -58
  72. package/test-env/components/collapsible_nav_beta/collapsible_nav_item/collapsed/collapsed_nav_item.js +89 -37
  73. package/test-env/components/collapsible_nav_beta/collapsible_nav_item/collapsed/collapsed_nav_popover.js +66 -80
  74. package/test-env/components/collapsible_nav_beta/collapsible_nav_item/collapsed/collapsed_nav_popover.styles.js +11 -28
  75. package/test-env/components/collapsible_nav_beta/collapsible_nav_item/collapsible_nav_accordion.js +7 -105
  76. package/test-env/components/collapsible_nav_beta/collapsible_nav_item/collapsible_nav_accordion.styles.js +4 -4
  77. package/test-env/components/collapsible_nav_beta/collapsible_nav_item/collapsible_nav_group.js +10 -89
  78. package/test-env/components/collapsible_nav_beta/collapsible_nav_item/collapsible_nav_item.js +150 -130
  79. package/test-env/components/collapsible_nav_beta/collapsible_nav_item/collapsible_nav_link.js +0 -10
  80. package/test-env/components/combo_box/combo_box.js +1 -1
  81. package/test-env/components/selectable/selectable.js +16 -1
  82. package/test-env/components/selectable/selectable_list/selectable_list.js +232 -78
  83. package/test-env/components/selectable/selectable_templates/selectable_template_sitewide.js +16 -1
  84. package/test-env/components/text_truncate/text_truncate.js +32 -9
@@ -1,6 +1,6 @@
1
1
  var _excluded = ["data"],
2
- _excluded2 = ["label", "isGroupLabel", "checked", "disabled", "prepend", "append", "ref", "key", "searchableLabel", "data"],
3
- _excluded3 = ["className", "options", "searchValue", "onOptionClick", "renderOption", "height", "windowProps", "rowHeight", "activeOptionIndex", "makeOptionId", "showIcons", "singleSelection", "visibleOptions", "allowExclusions", "bordered", "paddingSize", "searchable", "onFocusBadge", "listId", "setActiveOptionIndex", "aria-label", "aria-labelledby", "aria-describedby", "role", "isVirtualized", "textWrap"];
2
+ _excluded2 = ["label", "isGroupLabel", "checked", "disabled", "prepend", "append", "ref", "key", "searchableLabel", "data", "truncationProps"],
3
+ _excluded3 = ["className", "options", "searchValue", "onOptionClick", "renderOption", "height", "windowProps", "rowHeight", "activeOptionIndex", "makeOptionId", "showIcons", "singleSelection", "visibleOptions", "allowExclusions", "bordered", "paddingSize", "searchable", "onFocusBadge", "listId", "setActiveOptionIndex", "aria-label", "aria-labelledby", "aria-describedby", "role", "isVirtualized", "textWrap", "truncationProps"];
4
4
  function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
5
5
  function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
6
6
  function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
@@ -34,6 +34,8 @@ import classNames from 'classnames';
34
34
  import { FixedSizeList, areEqual } from 'react-window';
35
35
  import { EuiAutoSizer } from '../../auto_sizer';
36
36
  import { EuiHighlight } from '../../highlight';
37
+ import { EuiMark } from '../../mark';
38
+ import { EuiTextTruncate } from '../../text_truncate';
37
39
  import { EuiSelectableListItem } from './selectable_list_item';
38
40
 
39
41
  // Consumer Configurable Props via `EuiSelectable.listProps`
@@ -88,20 +90,23 @@ export var EuiSelectableList = /*#__PURE__*/function (_Component) {
88
90
  }
89
91
  }
90
92
  });
91
- _defineProperty(_assertThisInitialized(_this), "ariaSetSize", 0);
92
- _defineProperty(_assertThisInitialized(_this), "ariaPosInSetMap", {});
93
+ // This utility is necessary to exclude group labels from the aria set count
93
94
  _defineProperty(_assertThisInitialized(_this), "calculateAriaSetAttrs", function (optionArray) {
94
- _this.ariaPosInSetMap = {};
95
+ var ariaPosInSetMap = {};
95
96
  var latestAriaPosIndex = 0;
96
97
  optionArray.forEach(function (option, index) {
97
98
  if (!option.isGroupLabel) {
98
99
  latestAriaPosIndex++;
99
- _this.ariaPosInSetMap[index] = latestAriaPosIndex;
100
+ ariaPosInSetMap[index] = latestAriaPosIndex;
100
101
  }
101
102
  });
102
- _this.ariaSetSize = latestAriaPosIndex;
103
+ return {
104
+ ariaPosInSetMap: ariaPosInSetMap,
105
+ ariaSetSize: latestAriaPosIndex
106
+ };
103
107
  });
104
108
  _defineProperty(_assertThisInitialized(_this), "ListRow", /*#__PURE__*/memo(function (_ref) {
109
+ var _option$textWrap;
105
110
  var data = _ref.data,
106
111
  index = _ref.index,
107
112
  style = _ref.style;
@@ -118,19 +123,20 @@ export var EuiSelectableList = /*#__PURE__*/function (_Component) {
118
123
  key = option.key,
119
124
  searchableLabel = option.searchableLabel,
120
125
  _data = option.data,
126
+ _truncationProps = option.truncationProps,
121
127
  optionRest = _objectWithoutProperties(option, _excluded2);
122
128
  var _this$props2 = _this.props,
123
129
  activeOptionIndex = _this$props2.activeOptionIndex,
124
130
  allowExclusions = _this$props2.allowExclusions,
125
131
  onFocusBadge = _this$props2.onFocusBadge,
126
132
  paddingSize = _this$props2.paddingSize,
127
- searchValue = _this$props2.searchValue,
128
133
  showIcons = _this$props2.showIcons,
129
134
  makeOptionId = _this$props2.makeOptionId,
130
135
  renderOption = _this$props2.renderOption,
131
136
  setActiveOptionIndex = _this$props2.setActiveOptionIndex,
132
137
  searchable = _this$props2.searchable,
133
- textWrap = _this$props2.textWrap;
138
+ searchValue = _this$props2.searchValue,
139
+ isVirtualized = _this$props2.isVirtualized;
134
140
  if (isGroupLabel) {
135
141
  return ___EmotionJSX("li", _extends({
136
142
  role: "presentation",
@@ -140,6 +146,15 @@ export var EuiSelectableList = /*#__PURE__*/function (_Component) {
140
146
  }, optionRest), prepend, label, append);
141
147
  }
142
148
  var id = makeOptionId(index);
149
+ var isFocused = activeOptionIndex === index;
150
+
151
+ // Text wrapping
152
+ var canWrap = !isVirtualized;
153
+ var _textWrap = (_option$textWrap = option.textWrap) !== null && _option$textWrap !== void 0 ? _option$textWrap : _this.props.textWrap;
154
+ var textWrap = canWrap ? _textWrap : 'truncate';
155
+
156
+ // Truncation config (if any). If none, CSS truncation is used
157
+ var truncationProps = textWrap === 'truncate' ? _this.getTruncationProps(option, isFocused) : undefined;
143
158
  return ___EmotionJSX(EuiSelectableListItem, _extends({
144
159
  key: id,
145
160
  id: id,
@@ -152,14 +167,14 @@ export var EuiSelectableList = /*#__PURE__*/function (_Component) {
152
167
  _this.onAddOrRemoveOption(option, event);
153
168
  },
154
169
  ref: ref ? ref.bind(null, index) : undefined,
155
- isFocused: activeOptionIndex === index,
170
+ isFocused: isFocused,
156
171
  title: searchableLabel || label,
157
172
  checked: checked,
158
173
  disabled: disabled,
159
174
  prepend: prepend,
160
175
  append: append,
161
- "aria-posinset": _this.ariaPosInSetMap[index],
162
- "aria-setsize": _this.ariaSetSize,
176
+ "aria-posinset": _this.state.ariaPosInSetMap[index],
177
+ "aria-setsize": _this.state.ariaSetSize,
163
178
  onFocusBadge: onFocusBadge,
164
179
  allowExclusions: allowExclusions,
165
180
  showIcons: showIcons,
@@ -167,16 +182,18 @@ export var EuiSelectableList = /*#__PURE__*/function (_Component) {
167
182
  searchable: searchable,
168
183
  textWrap: textWrap
169
184
  }, optionRest), renderOption ? renderOption( // @ts-ignore complex
170
- _objectSpread(_objectSpread({}, _option), optionData), _this.props.searchValue) : ___EmotionJSX(EuiHighlight, {
171
- search: searchValue
172
- }, label));
185
+ _objectSpread(_objectSpread({}, _option), optionData), searchValue) : searchValue ? _this.renderSearchedText(label, truncationProps) : truncationProps ? _this.renderTruncatedText(label, truncationProps) : label);
173
186
  }, areEqual));
174
- _defineProperty(_assertThisInitialized(_this), "renderVirtualizedList", function (heightIsFull, optionArray) {
187
+ _defineProperty(_assertThisInitialized(_this), "renderVirtualizedList", function () {
175
188
  if (!_this.props.isVirtualized) return null;
189
+ var _this$state = _this.state,
190
+ optionArray = _this$state.optionArray,
191
+ itemData = _this$state.itemData;
176
192
  var _this$props3 = _this.props,
177
193
  windowProps = _this$props3.windowProps,
178
194
  forcedHeight = _this$props3.height,
179
195
  rowHeight = _this$props3.rowHeight;
196
+ var heightIsFull = forcedHeight === 'full';
180
197
  var virtualizationProps = _objectSpread({
181
198
  className: 'euiSelectableList__list',
182
199
  ref: _this.setListRef,
@@ -184,7 +201,7 @@ export var EuiSelectableList = /*#__PURE__*/function (_Component) {
184
201
  innerRef: _this.setListBoxRef,
185
202
  innerElementType: 'ul',
186
203
  itemCount: optionArray.length,
187
- itemData: optionArray,
204
+ itemData: itemData,
188
205
  itemSize: rowHeight,
189
206
  'data-skip-axe': 'scrollable-region-focusable'
190
207
  }, windowProps);
@@ -204,7 +221,9 @@ export var EuiSelectableList = /*#__PURE__*/function (_Component) {
204
221
  calculatedHeight = numVisibleOptions * rowHeight;
205
222
  }
206
223
  }
207
- return heightIsFull ? ___EmotionJSX(EuiAutoSizer, null, function (_ref2) {
224
+ return heightIsFull ? ___EmotionJSX(EuiAutoSizer, {
225
+ onResize: _this.calculateDefaultOptionWidth
226
+ }, function (_ref2) {
208
227
  var width = _ref2.width,
209
228
  height = _ref2.height;
210
229
  return ___EmotionJSX(FixedSizeList, _extends({
@@ -212,7 +231,8 @@ export var EuiSelectableList = /*#__PURE__*/function (_Component) {
212
231
  height: height
213
232
  }, virtualizationProps), _this.ListRow);
214
233
  }) : ___EmotionJSX(EuiAutoSizer, {
215
- disableHeight: true
234
+ disableHeight: true,
235
+ onResize: _this.calculateDefaultOptionWidth
216
236
  }, function (_ref3) {
217
237
  var width = _ref3.width;
218
238
  return ___EmotionJSX(FixedSizeList, _extends({
@@ -221,17 +241,111 @@ export var EuiSelectableList = /*#__PURE__*/function (_Component) {
221
241
  }, virtualizationProps), _this.ListRow);
222
242
  });
223
243
  });
244
+ _defineProperty(_assertThisInitialized(_this), "forceVirtualizedListRowRerender", function () {
245
+ _this.setState({
246
+ itemData: _objectSpread({}, _this.state.optionArray)
247
+ });
248
+ });
249
+ // EuiTextTruncate is expensive perf-wise - we use several utilities here to
250
+ // offset its performance cost
251
+ // and creates a resize observer for
252
+ // each individual item. This logic tries to offset this performance hit by
253
+ // guesstimating a default width for each option
254
+ _defineProperty(_assertThisInitialized(_this), "focusBadgeOffset", 0);
255
+ _defineProperty(_assertThisInitialized(_this), "calculateDefaultOptionWidth", function (_ref4) {
256
+ var containerWidth = _ref4.width;
257
+ var _this$props4 = _this.props,
258
+ truncationProps = _this$props4.truncationProps,
259
+ searchable = _this$props4.searchable,
260
+ searchValue = _this$props4.searchValue;
261
+
262
+ // If it's not likely we'll need to use EuiTextTruncate, don't set state/rerender on every panel resize
263
+ var mayTruncate = searchable || truncationProps;
264
+ if (!mayTruncate) return;
265
+ var paddingOffset = _this.props.paddingSize === 'none' ? 0 : 24; // Defaults to 's'
266
+ var checkedIconOffset = _this.props.showIcons === false ? 0 : 28; // Defaults to true
267
+ _this.focusBadgeOffset = _this.props.onFocusBadge === false ? 0 : 46;
268
+
269
+ // Wait a tick for the listbox ref to update before proceeding
270
+ requestAnimationFrame(function () {
271
+ var scrollbarOffset = _this.listBoxRef ? containerWidth - _this.listBoxRef.offsetWidth : 0;
272
+ _this.setState({
273
+ defaultOptionWidth: containerWidth - scrollbarOffset - paddingOffset - checkedIconOffset
274
+ });
275
+
276
+ // Potentially force list rows to rerender on dynamic resize as well,
277
+ // but try to do it as lightly as possible
278
+ if (truncationProps || searchable && searchValue) {
279
+ _this.forceVirtualizedListRowRerender();
280
+ }
281
+ });
282
+ });
283
+ _defineProperty(_assertThisInitialized(_this), "getTruncationProps", function (option, isFocused) {
284
+ // Individual truncation settings should override component-wide settings
285
+ var truncationProps = _objectSpread(_objectSpread({}, _this.props.truncationProps), option.truncationProps);
286
+
287
+ // If we're not actually using EuiTextTruncate, no need to continue
288
+ var hasComplexTruncation = _this.props.searchValue || Object.keys(truncationProps).length > 0;
289
+ if (!hasComplexTruncation) return undefined;
290
+
291
+ // Determine whether we can use the optimized default option width
292
+ var defaultOptionWidth = _this.state.defaultOptionWidth;
293
+ var useDefaultWidth = !option.append && !option.prepend;
294
+ var defaultWidth = useDefaultWidth && defaultOptionWidth ? isFocused ? defaultOptionWidth - _this.focusBadgeOffset : defaultOptionWidth : undefined;
295
+ return _objectSpread({
296
+ width: defaultWidth
297
+ }, truncationProps);
298
+ });
299
+ _defineProperty(_assertThisInitialized(_this), "renderSearchedText", function (text, truncationProps) {
300
+ var searchValue = _this.props.searchValue;
301
+
302
+ // If truncationProps is undefined, we're using non-virtualized text wrapping
303
+ if (!truncationProps) {
304
+ return ___EmotionJSX(EuiHighlight, {
305
+ search: searchValue
306
+ }, text);
307
+ }
308
+ var searchPositionStart = text.toLowerCase().indexOf(searchValue.toLowerCase());
309
+ var searchPositionCenter = searchPositionStart + Math.floor(searchValue.length / 2);
310
+ return ___EmotionJSX(EuiTextTruncate, _extends({}, truncationProps, {
311
+ // When searching, don't allow overriding the truncation settings
312
+ truncation: "startEnd",
313
+ truncationPosition: searchPositionCenter,
314
+ text: text
315
+ }), function (text) {
316
+ return ___EmotionJSX(React.Fragment, null, text.length >= searchValue.length ? ___EmotionJSX(EuiHighlight, {
317
+ search: searchValue
318
+ }, text) :
319
+ // If the available truncated text is shorter than the full search string,
320
+ // just highlight the entire truncated text
321
+ ___EmotionJSX(EuiMark, null, text));
322
+ });
323
+ });
324
+ _defineProperty(_assertThisInitialized(_this), "renderTruncatedText", function (text, truncationProps) {
325
+ return (
326
+ // For some bizarre reason, truncation in EuiSelectable is off on initial mount
327
+ // (but not on rerender) for Safari and _some_ truncation types in Firefox :|
328
+ // Waiting a tick before calculating truncation seems to smooth over the issue
329
+ ___EmotionJSX(EuiTextTruncate, _extends({
330
+ calculationDelayMs: 2
331
+ }, truncationProps, {
332
+ text: text
333
+ }), function (text) {
334
+ return text;
335
+ })
336
+ );
337
+ });
224
338
  _defineProperty(_assertThisInitialized(_this), "onAddOrRemoveOption", function (option, event) {
225
339
  if (option.disabled) {
226
340
  return;
227
341
  }
228
- var _this$props4 = _this.props,
229
- allowExclusions = _this$props4.allowExclusions,
230
- options = _this$props4.options,
231
- _this$props4$visibleO = _this$props4.visibleOptions,
232
- visibleOptions = _this$props4$visibleO === void 0 ? options : _this$props4$visibleO;
233
- _this.props.setActiveOptionIndex(visibleOptions.findIndex(function (_ref4) {
234
- var label = _ref4.label;
342
+ var _this$props5 = _this.props,
343
+ allowExclusions = _this$props5.allowExclusions,
344
+ options = _this$props5.options,
345
+ _this$props5$visibleO = _this$props5.visibleOptions,
346
+ visibleOptions = _this$props5$visibleO === void 0 ? options : _this$props5$visibleO;
347
+ _this.props.setActiveOptionIndex(visibleOptions.findIndex(function (_ref5) {
348
+ var label = _ref5.label;
235
349
  return label === option.label;
236
350
  }), function () {
237
351
  if (option.checked === 'on' && allowExclusions) {
@@ -244,10 +358,10 @@ export var EuiSelectableList = /*#__PURE__*/function (_Component) {
244
358
  });
245
359
  });
246
360
  _defineProperty(_assertThisInitialized(_this), "onAddOption", function (addedOption, event) {
247
- var _this$props5 = _this.props,
248
- onOptionClick = _this$props5.onOptionClick,
249
- options = _this$props5.options,
250
- singleSelection = _this$props5.singleSelection;
361
+ var _this$props6 = _this.props,
362
+ onOptionClick = _this$props6.onOptionClick,
363
+ options = _this$props6.options,
364
+ singleSelection = _this$props6.singleSelection;
251
365
  var changedOption = _objectSpread({}, addedOption);
252
366
  var updatedOptions = options.map(function (option) {
253
367
  // if singleSelection is enabled, uncheck any selected option(s)
@@ -266,10 +380,10 @@ export var EuiSelectableList = /*#__PURE__*/function (_Component) {
266
380
  onOptionClick(updatedOptions, event, changedOption);
267
381
  });
268
382
  _defineProperty(_assertThisInitialized(_this), "onRemoveOption", function (removedOption, event) {
269
- var _this$props6 = _this.props,
270
- onOptionClick = _this$props6.onOptionClick,
271
- singleSelection = _this$props6.singleSelection,
272
- options = _this$props6.options;
383
+ var _this$props7 = _this.props,
384
+ onOptionClick = _this$props7.onOptionClick,
385
+ singleSelection = _this$props7.singleSelection,
386
+ options = _this$props7.options;
273
387
  var changedOption = _objectSpread({}, removedOption);
274
388
  var updatedOptions = options.map(function (option) {
275
389
  var updatedOption = _objectSpread({}, option);
@@ -282,9 +396,9 @@ export var EuiSelectableList = /*#__PURE__*/function (_Component) {
282
396
  onOptionClick(updatedOptions, event, changedOption);
283
397
  });
284
398
  _defineProperty(_assertThisInitialized(_this), "onExcludeOption", function (excludedOption, event) {
285
- var _this$props7 = _this.props,
286
- onOptionClick = _this$props7.onOptionClick,
287
- options = _this$props7.options;
399
+ var _this$props8 = _this.props,
400
+ onOptionClick = _this$props8.onOptionClick,
401
+ options = _this$props8.options;
288
402
  var changedOption = _objectSpread({}, excludedOption);
289
403
  var updatedOptions = options.map(function (option) {
290
404
  var updatedOption = _objectSpread({}, option);
@@ -296,69 +410,83 @@ export var EuiSelectableList = /*#__PURE__*/function (_Component) {
296
410
  });
297
411
  onOptionClick(updatedOptions, event, changedOption);
298
412
  });
413
+ var _optionArray = props.visibleOptions || props.options;
414
+ _this.state = _objectSpread({
415
+ defaultOptionWidth: 0,
416
+ optionArray: _optionArray,
417
+ itemData: _objectSpread({}, _optionArray)
418
+ }, _this.calculateAriaSetAttrs(_optionArray));
299
419
  return _this;
300
420
  }
301
421
  _createClass(EuiSelectableList, [{
302
422
  key: "componentDidUpdate",
303
- value: function componentDidUpdate() {
304
- var activeOptionIndex = this.props.activeOptionIndex;
423
+ value: function componentDidUpdate(prevProps) {
424
+ var _this$props9 = this.props,
425
+ activeOptionIndex = _this$props9.activeOptionIndex,
426
+ visibleOptions = _this$props9.visibleOptions,
427
+ options = _this$props9.options;
305
428
  if (this.listBoxRef && this.props.searchable !== true) {
306
429
  this.listBoxRef.setAttribute('aria-activedescendant', "".concat(this.props.makeOptionId(activeOptionIndex)));
307
430
  }
308
- if (this.listRef && typeof this.props.activeOptionIndex !== 'undefined') {
309
- this.listRef.scrollToItem(this.props.activeOptionIndex, 'auto');
431
+ if (this.listRef && typeof activeOptionIndex !== 'undefined') {
432
+ this.listRef.scrollToItem(activeOptionIndex, 'auto');
433
+ }
434
+ if (prevProps.visibleOptions !== visibleOptions || prevProps.options !== options) {
435
+ var optionArray = visibleOptions || options;
436
+ this.setState(_objectSpread({
437
+ optionArray: optionArray,
438
+ itemData: _objectSpread({}, optionArray)
439
+ }, this.calculateAriaSetAttrs(optionArray)));
310
440
  }
311
441
  }
312
442
  }, {
313
443
  key: "render",
314
444
  value: function render() {
315
445
  var _this2 = this;
316
- var _this$props8 = this.props,
317
- className = _this$props8.className,
318
- options = _this$props8.options,
319
- searchValue = _this$props8.searchValue,
320
- onOptionClick = _this$props8.onOptionClick,
321
- renderOption = _this$props8.renderOption,
322
- forcedHeight = _this$props8.height,
323
- windowProps = _this$props8.windowProps,
324
- rowHeight = _this$props8.rowHeight,
325
- activeOptionIndex = _this$props8.activeOptionIndex,
326
- makeOptionId = _this$props8.makeOptionId,
327
- showIcons = _this$props8.showIcons,
328
- singleSelection = _this$props8.singleSelection,
329
- visibleOptions = _this$props8.visibleOptions,
330
- allowExclusions = _this$props8.allowExclusions,
331
- bordered = _this$props8.bordered,
332
- paddingSize = _this$props8.paddingSize,
333
- searchable = _this$props8.searchable,
334
- onFocusBadge = _this$props8.onFocusBadge,
335
- listId = _this$props8.listId,
336
- setActiveOptionIndex = _this$props8.setActiveOptionIndex,
337
- ariaLabel = _this$props8['aria-label'],
338
- ariaLabelledby = _this$props8['aria-labelledby'],
339
- ariaDescribedby = _this$props8['aria-describedby'],
340
- role = _this$props8.role,
341
- isVirtualized = _this$props8.isVirtualized,
342
- textWrap = _this$props8.textWrap,
343
- rest = _objectWithoutProperties(_this$props8, _excluded3);
344
- var optionArray = visibleOptions || options;
345
- this.calculateAriaSetAttrs(optionArray);
346
- var heightIsFull = forcedHeight === 'full';
446
+ var _this$props10 = this.props,
447
+ className = _this$props10.className,
448
+ options = _this$props10.options,
449
+ searchValue = _this$props10.searchValue,
450
+ onOptionClick = _this$props10.onOptionClick,
451
+ renderOption = _this$props10.renderOption,
452
+ forcedHeight = _this$props10.height,
453
+ windowProps = _this$props10.windowProps,
454
+ rowHeight = _this$props10.rowHeight,
455
+ activeOptionIndex = _this$props10.activeOptionIndex,
456
+ makeOptionId = _this$props10.makeOptionId,
457
+ showIcons = _this$props10.showIcons,
458
+ singleSelection = _this$props10.singleSelection,
459
+ visibleOptions = _this$props10.visibleOptions,
460
+ allowExclusions = _this$props10.allowExclusions,
461
+ bordered = _this$props10.bordered,
462
+ paddingSize = _this$props10.paddingSize,
463
+ searchable = _this$props10.searchable,
464
+ onFocusBadge = _this$props10.onFocusBadge,
465
+ listId = _this$props10.listId,
466
+ setActiveOptionIndex = _this$props10.setActiveOptionIndex,
467
+ ariaLabel = _this$props10['aria-label'],
468
+ ariaLabelledby = _this$props10['aria-labelledby'],
469
+ ariaDescribedby = _this$props10['aria-describedby'],
470
+ role = _this$props10.role,
471
+ isVirtualized = _this$props10.isVirtualized,
472
+ textWrap = _this$props10.textWrap,
473
+ truncationProps = _this$props10.truncationProps,
474
+ rest = _objectWithoutProperties(_this$props10, _excluded3);
347
475
  var classes = classNames('euiSelectableList', {
348
- 'euiSelectableList-fullHeight': heightIsFull,
476
+ 'euiSelectableList-fullHeight': forcedHeight === 'full',
349
477
  'euiSelectableList-bordered': bordered
350
478
  }, className);
351
479
  return ___EmotionJSX("div", _extends({
352
480
  className: classes
353
- }, rest), isVirtualized ? this.renderVirtualizedList(heightIsFull, optionArray) : ___EmotionJSX("div", {
481
+ }, rest), isVirtualized ? this.renderVirtualizedList() : ___EmotionJSX("div", {
354
482
  className: "euiSelectableList__list",
355
483
  ref: this.removeScrollableTabStop
356
484
  }, ___EmotionJSX("ul", {
357
485
  ref: this.setListBoxRef
358
- }, optionArray.map(function (_, index) {
486
+ }, this.state.optionArray.map(function (_, index) {
359
487
  return /*#__PURE__*/React.createElement(_this2.ListRow, {
360
488
  key: index,
361
- data: optionArray,
489
+ data: _this2.state.optionArray,
362
490
  index: index
363
491
  }, null);
364
492
  }))));
@@ -455,6 +583,15 @@ EuiSelectableList.propTypes = {
455
583
  * Wrapping only works if virtualization is off.
456
584
  */
457
585
  textWrap: PropTypes.oneOf(["truncate", "wrap"]),
586
+ /**
587
+ * If textWrap is set to `truncate`, you can pass a custom truncation configuration
588
+ * that accepts any [EuiTextTruncate](/#/utilities/text-truncation) prop except for
589
+ * `text` and `children`.
590
+ *
591
+ * Note: when searching, custom truncation props are ignored. The highlighted search
592
+ * text will always take precedence.
593
+ */
594
+ truncationProps: PropTypes.any,
458
595
  /**
459
596
  * Use virtualized rendering for list items with `react-window`.
460
597
  * Sets each row's height to the value of `rowHeight`.
@@ -513,7 +650,22 @@ EuiSelectableList.propTypes = {
513
650
  * Option data to pass through to the `renderOptions` element.
514
651
  * Bypass `EuiSelectableItem` and avoid DOM attribute warnings.
515
652
  */
516
- data: PropTypes.shape({})
653
+ data: PropTypes.shape({}),
654
+ /**
655
+ * How to handle long text within the item.
656
+ * Wrapping only works if `isVirtualization` is false.
657
+ * @default 'truncate'
658
+ */
659
+ textWrap: PropTypes.oneOf(["truncate", "wrap"]),
660
+ /**
661
+ * If textWrap is set to `truncate`, you can pass a custom truncation configuration
662
+ * that accepts any [EuiTextTruncate](/#/utilities/text-truncation) prop except for
663
+ * `text` and `children`.
664
+ *
665
+ * Note: when searching, custom truncation props are ignored. The highlighted search
666
+ * text will always take precedence.
667
+ */
668
+ truncationProps: PropTypes.any
517
669
  }).isRequired).isRequired,
518
670
  /**
519
671
  * Filtered options list (if applicable)
@@ -532,7 +684,9 @@ EuiSelectableList.propTypes = {
532
684
  prepend: PropTypes.node,
533
685
  append: PropTypes.node,
534
686
  ref: PropTypes.func,
535
- data: PropTypes.shape({})
687
+ data: PropTypes.shape({}),
688
+ textWrap: PropTypes.oneOf(["truncate", "wrap"]),
689
+ truncationProps: PropTypes.any
536
690
  }).isRequired),
537
691
  /**
538
692
  * Search value to highlight on the option render
@@ -383,7 +383,22 @@ EuiSelectableTemplateSitewide.propTypes = {
383
383
  * Option data to pass through to the `renderOptions` element.
384
384
  * Bypass `EuiSelectableItem` and avoid DOM attribute warnings.
385
385
  */
386
- data: PropTypes.shape({})
386
+ data: PropTypes.shape({}),
387
+ /**
388
+ * How to handle long text within the item.
389
+ * Wrapping only works if `isVirtualization` is false.
390
+ * @default 'truncate'
391
+ */
392
+ textWrap: PropTypes.oneOf(["truncate", "wrap"]),
393
+ /**
394
+ * If textWrap is set to `truncate`, you can pass a custom truncation configuration
395
+ * that accepts any [EuiTextTruncate](/#/utilities/text-truncation) prop except for
396
+ * `text` and `children`.
397
+ *
398
+ * Note: when searching, custom truncation props are ignored. The highlighted search
399
+ * text will always take precedence.
400
+ */
401
+ truncationProps: PropTypes.any
387
402
  }).isRequired).isRequired,
388
403
  /**
389
404
  * Override some of the EuiPopover props housing the list.
@@ -1,5 +1,5 @@
1
1
  var _excluded = ["width", "onResize"],
2
- _excluded2 = ["width", "children", "text", "truncation", "truncationOffset", "truncationPosition", "ellipsis", "containerRef", "className"],
2
+ _excluded2 = ["width", "children", "text", "truncation", "truncationOffset", "truncationPosition", "ellipsis", "calculationDelayMs", "containerRef", "className"],
3
3
  _excluded3 = ["onResize"];
4
4
  function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
5
5
  function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
@@ -18,7 +18,7 @@ function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) r
18
18
  * Side Public License, v 1.
19
19
  */
20
20
 
21
- import React, { useState, useMemo, useCallback } from 'react';
21
+ import React, { useState, useMemo, useCallback, useEffect } from 'react';
22
22
  import PropTypes from "prop-types";
23
23
  import classNames from 'classnames';
24
24
  import { useCombinedRefs } from '../../services';
@@ -98,7 +98,13 @@ EuiTextTruncate.propTypes = {
98
98
  * allows for more flexible text rendering, e.g. adding custom markup
99
99
  * or highlighting
100
100
  */
101
- children: PropTypes.func
101
+ children: PropTypes.func,
102
+ /**
103
+ * For some edge case scenarios, EuiTextTruncate's calculations may be off until
104
+ * fonts are done loading or layout is done shifting or settling. Adding a delay
105
+ * may help resolve any rendering issues.
106
+ */
107
+ calculationDelayMs: PropTypes.number
102
108
  };
103
109
  var EuiTextTruncateWithWidth = function EuiTextTruncateWithWidth(_ref2) {
104
110
  var width = _ref2.width,
@@ -111,6 +117,7 @@ var EuiTextTruncateWithWidth = function EuiTextTruncateWithWidth(_ref2) {
111
117
  truncationPosition = _ref2.truncationPosition,
112
118
  _ref2$ellipsis = _ref2.ellipsis,
113
119
  ellipsis = _ref2$ellipsis === void 0 ? '…' : _ref2$ellipsis,
120
+ calculationDelayMs = _ref2.calculationDelayMs,
114
121
  containerRef = _ref2.containerRef,
115
122
  className = _ref2.className,
116
123
  rest = _objectWithoutProperties(_ref2, _excluded2);
@@ -121,6 +128,19 @@ var EuiTextTruncateWithWidth = function EuiTextTruncateWithWidth(_ref2) {
121
128
  setContainerEl = _useState2[1];
122
129
  var refs = useCombinedRefs([setContainerEl, containerRef]);
123
130
 
131
+ // If necessary, wait a tick on mount before truncating
132
+ var _useState3 = useState(!calculationDelayMs),
133
+ _useState4 = _slicedToArray(_useState3, 2),
134
+ ready = _useState4[0],
135
+ setReady = _useState4[1];
136
+ useEffect(function () {
137
+ if (calculationDelayMs) {
138
+ setTimeout(function () {
139
+ return setReady(true);
140
+ }, calculationDelayMs);
141
+ }
142
+ }, [calculationDelayMs]);
143
+
124
144
  // Handle exceptions where we need to override the passed props
125
145
  var _useMemo = useMemo(function () {
126
146
  var truncation = _truncation;
@@ -145,7 +165,8 @@ var EuiTextTruncateWithWidth = function EuiTextTruncateWithWidth(_ref2) {
145
165
  truncationOffset = _useMemo.truncationOffset;
146
166
  var truncatedText = useMemo(function () {
147
167
  var truncatedText = '';
148
- if (!containerEl || !width) return truncatedText;
168
+ if (!ready || !containerEl) return text;
169
+ if (!width) return truncatedText;
149
170
  var utils = new TruncationUtils({
150
171
  fullText: text,
151
172
  ellipsis: ellipsis,
@@ -177,7 +198,7 @@ var EuiTextTruncateWithWidth = function EuiTextTruncateWithWidth(_ref2) {
177
198
  }
178
199
  }
179
200
  return truncatedText;
180
- }, [width, text, truncation, truncationOffset, truncationPosition, ellipsis, containerEl]);
201
+ }, [ready, width, text, truncation, truncationOffset, truncationPosition, ellipsis, containerEl]);
181
202
  var isTruncating = truncatedText !== text;
182
203
  return ___EmotionJSX("div", _extends({
183
204
  className: classNames('euiTextTruncate', className),
@@ -205,10 +226,10 @@ EuiTextTruncateWithWidth.propTypes = {
205
226
  var EuiTextTruncateWithResizeObserver = function EuiTextTruncateWithResizeObserver(_ref3) {
206
227
  var _onResize = _ref3.onResize,
207
228
  props = _objectWithoutProperties(_ref3, _excluded3);
208
- var _useState3 = useState(0),
209
- _useState4 = _slicedToArray(_useState3, 2),
210
- width = _useState4[0],
211
- setWidth = _useState4[1];
229
+ var _useState5 = useState(0),
230
+ _useState6 = _slicedToArray(_useState5, 2),
231
+ width = _useState6[0],
232
+ setWidth = _useState6[1];
212
233
  var onResize = useCallback(function (_ref4) {
213
234
  var width = _ref4.width;
214
235
  setWidth(width);
@@ -220,6 +241,8 @@ var EuiTextTruncateWithResizeObserver = function EuiTextTruncateWithResizeObserv
220
241
  return ___EmotionJSX(EuiTextTruncateWithWidth, _extends({
221
242
  width: width,
222
243
  containerRef: ref
223
- }, props));
244
+ }, props, {
245
+ "data-resize-observer": "true"
246
+ }));
224
247
  });
225
248
  };