@carbon/react 1.63.0 → 1.63.2

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 (30) hide show
  1. package/.playwright/INTERNAL_AVT_REPORT_DO_NOT_USE.json +930 -971
  2. package/es/components/ComboBox/ComboBox.d.ts +21 -3
  3. package/es/components/ComboBox/ComboBox.js +65 -9
  4. package/es/components/DataTable/TableSelectRow.js +2 -1
  5. package/es/components/DataTable/TableToolbarSearch.js +2 -2
  6. package/es/components/DatePicker/DatePicker.js +65 -14
  7. package/es/components/DatePicker/plugins/fixEventsPlugin.js +11 -0
  8. package/es/components/Dropdown/Dropdown.d.ts +6 -1
  9. package/es/components/Dropdown/Dropdown.js +25 -22
  10. package/es/components/FluidMultiSelect/FluidMultiSelect.js +6 -1
  11. package/es/components/MultiSelect/FilterableMultiSelect.d.ts +6 -1
  12. package/es/components/MultiSelect/FilterableMultiSelect.js +8 -3
  13. package/es/components/MultiSelect/MultiSelect.d.ts +6 -1
  14. package/es/components/MultiSelect/MultiSelect.js +8 -3
  15. package/es/internal/useId.js +39 -18
  16. package/lib/components/ComboBox/ComboBox.d.ts +21 -3
  17. package/lib/components/ComboBox/ComboBox.js +65 -9
  18. package/lib/components/DataTable/TableSelectRow.js +2 -1
  19. package/lib/components/DataTable/TableToolbarSearch.js +2 -2
  20. package/lib/components/DatePicker/DatePicker.js +65 -14
  21. package/lib/components/DatePicker/plugins/fixEventsPlugin.js +11 -0
  22. package/lib/components/Dropdown/Dropdown.d.ts +6 -1
  23. package/lib/components/Dropdown/Dropdown.js +25 -22
  24. package/lib/components/FluidMultiSelect/FluidMultiSelect.js +6 -1
  25. package/lib/components/MultiSelect/FilterableMultiSelect.d.ts +6 -1
  26. package/lib/components/MultiSelect/FilterableMultiSelect.js +8 -3
  27. package/lib/components/MultiSelect/MultiSelect.d.ts +6 -1
  28. package/lib/components/MultiSelect/MultiSelect.js +8 -3
  29. package/lib/internal/useId.js +39 -17
  30. package/package.json +2 -2
@@ -4,8 +4,8 @@
4
4
  * This source code is licensed under the Apache-2.0 license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
- import { UseComboboxProps } from 'downshift';
8
- import { type ReactNode, type ComponentType, type ReactElement, type RefAttributes, type PropsWithChildren, type PropsWithRef, type InputHTMLAttributes, type MouseEvent } from 'react';
7
+ import { UseComboboxProps, UseComboboxActions } from 'downshift';
8
+ import React, { type ReactNode, type ComponentType, type ReactElement, type RefAttributes, type PropsWithChildren, type PropsWithRef, type InputHTMLAttributes, type MouseEvent } from 'react';
9
9
  import { ListBoxSize } from '../ListBox';
10
10
  import { TranslateWithId } from '../../types/common';
11
11
  type ExcludedAttributes = 'id' | 'onChange' | 'onClick' | 'type' | 'size';
@@ -57,9 +57,27 @@ export interface ComboBoxProps<ItemType> extends Omit<InputHTMLAttributes<HTMLIn
57
57
  */
58
58
  disabled?: boolean;
59
59
  /**
60
- * Additional props passed to Downshift
60
+ * Additional props passed to Downshift.
61
+ *
62
+ * **Use with caution:** anything you define here overrides the components'
63
+ * internal handling of that prop. Downshift APIs and internals are subject to
64
+ * change, and in some cases they can not be shimmed by Carbon to shield you
65
+ * from potentially breaking changes.
66
+ *
61
67
  */
62
68
  downshiftProps?: Partial<UseComboboxProps<ItemType>>;
69
+ /**
70
+ * Provide a ref that will be mutated to contain an object of downshift
71
+ * action functions. These can be called to change the internal state of the
72
+ * downshift useCombobox hook.
73
+ *
74
+ * **Use with caution:** calling these actions modifies the internal state of
75
+ * downshift. It may conflict with or override the state management used within
76
+ * Combobox. Downshift APIs and internals are subject to change, and in some
77
+ * cases they can not be shimmed by Carbon to shield you from potentially breaking
78
+ * changes.
79
+ */
80
+ downshiftActions?: React.MutableRefObject<UseComboboxActions<ItemType> | undefined>;
63
81
  /**
64
82
  * Provide helper text that is used alongside the control label for
65
83
  * additional help
@@ -109,6 +109,7 @@ const ComboBox = /*#__PURE__*/React.forwardRef((props, ref) => {
109
109
  className: containerClassName,
110
110
  direction = 'bottom',
111
111
  disabled = false,
112
+ downshiftActions,
112
113
  downshiftProps,
113
114
  helperText,
114
115
  id,
@@ -327,19 +328,25 @@ const ComboBox = /*#__PURE__*/React.forwardRef((props, ref) => {
327
328
  });
328
329
  }
329
330
  const {
331
+ // Prop getters
330
332
  getInputProps,
331
333
  getItemProps,
332
334
  getLabelProps,
333
335
  getMenuProps,
334
336
  getToggleButtonProps,
337
+ // State
335
338
  isOpen,
336
339
  highlightedIndex,
337
- selectItem,
338
340
  selectedItem,
339
- toggleMenu,
340
- setHighlightedIndex
341
+ // Actions
342
+ closeMenu,
343
+ openMenu,
344
+ reset,
345
+ selectItem,
346
+ setHighlightedIndex,
347
+ setInputValue: downshiftSetInputValue,
348
+ toggleMenu
341
349
  } = Downshift.useCombobox({
342
- ...downshiftProps,
343
350
  items: filterItems(items, itemToString, inputValue),
344
351
  inputValue: inputValue,
345
352
  itemToString: item => {
@@ -360,13 +367,45 @@ const ComboBox = /*#__PURE__*/React.forwardRef((props, ref) => {
360
367
  selectedItem
361
368
  });
362
369
  },
370
+ onHighlightedIndexChange: _ref5 => {
371
+ let {
372
+ highlightedIndex
373
+ } = _ref5;
374
+ if (highlightedIndex > -1 && typeof window !== undefined) {
375
+ const itemArray = document.querySelectorAll(`li.${prefix}--list-box__menu-item[role="option"]`);
376
+ const highlightedItem = itemArray[highlightedIndex];
377
+ if (highlightedItem) {
378
+ highlightedItem.scrollIntoView({
379
+ behavior: 'smooth',
380
+ block: 'nearest'
381
+ });
382
+ }
383
+ }
384
+ },
363
385
  initialSelectedItem: initialSelectedItem,
364
386
  inputId: id,
365
387
  stateReducer,
366
388
  isItemDisabled(item, _index) {
367
389
  return item.disabled;
368
- }
390
+ },
391
+ ...downshiftProps
369
392
  });
393
+ React.useEffect(() => {
394
+ // Used to expose the downshift actions to consumers for use with downshiftProps
395
+ // An odd pattern, here we mutate the value stored in the ref provided from the consumer.
396
+ // A riff of https://gist.github.com/gaearon/1a018a023347fe1c2476073330cc5509
397
+ if (downshiftActions) {
398
+ downshiftActions.current = {
399
+ closeMenu,
400
+ openMenu,
401
+ reset,
402
+ selectItem,
403
+ setHighlightedIndex,
404
+ setInputValue: downshiftSetInputValue,
405
+ toggleMenu
406
+ };
407
+ }
408
+ }, [closeMenu, openMenu, reset, selectItem, setHighlightedIndex, downshiftSetInputValue, toggleMenu]);
370
409
  const buttonProps = getToggleButtonProps({
371
410
  disabled: disabled || readOnly,
372
411
  onClick: handleToggleClick(isOpen),
@@ -439,9 +478,7 @@ const ComboBox = /*#__PURE__*/React.forwardRef((props, ref) => {
439
478
  }, getInputProps({
440
479
  'aria-controls': isOpen ? undefined : menuProps.id,
441
480
  placeholder,
442
- ref: {
443
- ...mergeRefs["default"](textInput, ref)
444
- },
481
+ ref: mergeRefs["default"](textInput, ref),
445
482
  onKeyDown: event => {
446
483
  if (match.match(event, keys.Space)) {
447
484
  event.stopPropagation();
@@ -581,9 +618,28 @@ ComboBox.propTypes = {
581
618
  */
582
619
  disabled: PropTypes__default["default"].bool,
583
620
  /**
584
- * Additional props passed to Downshift
621
+ * Additional props passed to Downshift.
622
+ *
623
+ * **Use with caution:** anything you define here overrides the components'
624
+ * internal handling of that prop. Downshift APIs and internals are subject to
625
+ * change, and in some cases they can not be shimmed by Carbon to shield you
626
+ * from potentially breaking changes.
585
627
  */
586
628
  downshiftProps: PropTypes__default["default"].object,
629
+ /**
630
+ * Provide a ref that will be mutated to contain an object of downshift
631
+ * action functions. These can be called to change the internal state of the
632
+ * downshift useCombobox hook.
633
+ *
634
+ * **Use with caution:** calling these actions modifies the internal state of
635
+ * downshift. It may conflict with or override the state management used within
636
+ * Combobox. Downshift APIs and internals are subject to change, and in some
637
+ * cases they can not be shimmed by Carbon to shield you from potentially breaking
638
+ * changes.
639
+ */
640
+ downshiftActions: PropTypes__default["default"].exact({
641
+ current: PropTypes__default["default"].any
642
+ }),
587
643
  /**
588
644
  * Provide helper text that is used alongside the control label for
589
645
  * additional help
@@ -15,6 +15,7 @@ var React = require('react');
15
15
  var cx = require('classnames');
16
16
  var InlineCheckbox = require('../InlineCheckbox/InlineCheckbox.js');
17
17
  var RadioButton = require('../RadioButton/RadioButton.js');
18
+ var useId = require('../../internal/useId.js');
18
19
  var usePrefix = require('../../internal/usePrefix.js');
19
20
  var deprecate = require('../../prop-types/deprecate.js');
20
21
 
@@ -38,7 +39,7 @@ const TableSelectRow = _ref => {
38
39
  className
39
40
  } = _ref;
40
41
  const prefix = usePrefix.usePrefix();
41
- const uniqueNameId = React.useId();
42
+ const uniqueNameId = useId.useId();
42
43
  const selectionInputProps = {
43
44
  id,
44
45
  name: name ? name : uniqueNameId,
@@ -64,7 +64,7 @@ const TableToolbarSearch = _ref => {
64
64
  const [expandedState, setExpandedState] = React.useState(Boolean(defaultExpanded || defaultValue));
65
65
  const expanded = controlled ? expandedProp : expandedState;
66
66
  const [value, setValue] = React.useState(defaultValue || '');
67
- const uniqueId = useId.useId();
67
+ const uniqueId = useId.useId('table-toolbar-search');
68
68
  const [focusTarget, setFocusTarget] = React.useState(null);
69
69
  const prefix = usePrefix.usePrefix();
70
70
  React.useEffect(() => {
@@ -111,7 +111,7 @@ const TableToolbarSearch = _ref => {
111
111
  disabled: disabled,
112
112
  className: searchClasses,
113
113
  value: value,
114
- id: typeof id !== 'undefined' ? id : `table-toolbar-search-${uniqueId.toString()}`,
114
+ id: typeof id !== 'undefined' ? id : uniqueId,
115
115
  labelText: labelText || t('carbon.table.toolbar.search.label'),
116
116
  placeholder: placeholder || t('carbon.table.toolbar.search.placeholder'),
117
117
  onChange: onChange,
@@ -185,25 +185,42 @@ const DatePicker = /*#__PURE__*/React__default["default"].forwardRef(function Da
185
185
  }
186
186
  }, []);
187
187
  const lastStartValue = React.useRef('');
188
+ const [calendarCloseEvent, setCalendarCloseEvent] = React.useState(null);
188
189
 
189
190
  // fix datepicker deleting the selectedDate when the calendar closes
190
- const onCalendarClose = (selectedDates, dateStr) => {
191
- endInputField?.current?.focus();
192
- calendarRef?.current?.calendarContainer?.classList.remove('open');
193
- setTimeout(() => {
194
- if (lastStartValue.current && selectedDates[0] && !startInputField.current.value) {
195
- startInputField.current.value = lastStartValue.current;
196
- calendarRef.current.setDate([startInputField.current.value, endInputField?.current?.value], true, calendarRef.current.config.dateFormat);
197
- }
198
- if (onClose) {
199
- onClose(calendarRef.current.selectedDates, dateStr, calendarRef.current);
200
- }
191
+ const handleCalendarClose = React.useCallback((selectedDates, dateStr, instance) => {
192
+ if (lastStartValue.current && selectedDates[0] && !startInputField.current.value) {
193
+ startInputField.current.value = lastStartValue.current;
194
+ calendarRef.current.setDate([startInputField.current.value, endInputField?.current?.value], true, calendarRef.current.config.dateFormat);
195
+ }
196
+ if (onClose) {
197
+ onClose(selectedDates, dateStr, instance);
198
+ }
199
+ }, [onClose]);
200
+ const onCalendarClose = (selectedDates, dateStr, instance, e) => {
201
+ if (e && e.type === 'clickOutside') {
202
+ return;
203
+ }
204
+ setCalendarCloseEvent({
205
+ selectedDates,
206
+ dateStr,
207
+ instance
201
208
  });
202
209
  };
210
+ React.useEffect(() => {
211
+ if (calendarCloseEvent) {
212
+ const {
213
+ selectedDates,
214
+ dateStr,
215
+ instance
216
+ } = calendarCloseEvent;
217
+ handleCalendarClose(selectedDates, dateStr, instance);
218
+ setCalendarCloseEvent(null);
219
+ }
220
+ }, [calendarCloseEvent, handleCalendarClose]);
203
221
  const endInputField = React.useRef(null);
204
222
  const calendarRef = React.useRef(null);
205
223
  const savedOnChange = useSavedCallback.useSavedCallback(onChange);
206
- const savedOnClose = useSavedCallback.useSavedCallback(datePickerType === 'range' ? onCalendarClose : onClose);
207
224
  const savedOnOpen = useSavedCallback.useSavedCallback(onOpen);
208
225
  const datePickerClasses = cx__default["default"](`${prefix}--date-picker`, {
209
226
  [`${prefix}--date-picker--short`]: short,
@@ -321,6 +338,7 @@ const DatePicker = /*#__PURE__*/React__default["default"].forwardRef(function Da
321
338
  } = endInputField;
322
339
  const flatpickerconfig = {
323
340
  inline: inline ?? false,
341
+ onClose: onCalendarClose,
324
342
  disableMobile: true,
325
343
  defaultDate: value,
326
344
  closeOnSelect: closeOnSelect,
@@ -355,7 +373,6 @@ const DatePicker = /*#__PURE__*/React__default["default"].forwardRef(function Da
355
373
  savedOnChange(...arguments);
356
374
  }
357
375
  },
358
- onClose: savedOnClose,
359
376
  onReady: onHook,
360
377
  onMonthChange: onHook,
361
378
  onYearChange: onHook,
@@ -452,7 +469,7 @@ const DatePicker = /*#__PURE__*/React__default["default"].forwardRef(function Da
452
469
  }
453
470
  };
454
471
  // eslint-disable-next-line react-hooks/exhaustive-deps
455
- }, [savedOnChange, savedOnClose, savedOnOpen, readOnly, closeOnSelect, hasInput]);
472
+ }, [savedOnChange, savedOnOpen, readOnly, closeOnSelect, hasInput]);
456
473
 
457
474
  // this hook allows consumers to access the flatpickr calendar
458
475
  // instance for cases where functions like open() or close()
@@ -499,6 +516,40 @@ const DatePicker = /*#__PURE__*/React__default["default"].forwardRef(function Da
499
516
  calendarRef.current.set('inline', inline);
500
517
  }
501
518
  }, [inline]);
519
+ React.useEffect(() => {
520
+ //when value prop is set to empty, this clears the faltpicker's calendar instance and text input
521
+ if (value === '') {
522
+ calendarRef.current?.clear();
523
+ if (startInputField.current) {
524
+ startInputField.current.value = '';
525
+ }
526
+ if (endInputField.current) {
527
+ endInputField.current.value = '';
528
+ }
529
+ }
530
+ }, [value]);
531
+ React.useEffect(() => {
532
+ const handleMouseDown = event => {
533
+ if (calendarRef.current && calendarRef.current.isOpen && !calendarRef.current.calendarContainer.contains(event.target) && !startInputField.current.contains(event.target) && !endInputField.current?.contains(event.target)) {
534
+ // Close the calendar immediately on mousedown
535
+ closeCalendar();
536
+ }
537
+ };
538
+ const closeCalendar = event => {
539
+ calendarRef.current.close();
540
+ // Remove focus from endDate calendar input
541
+ if (document.activeElement instanceof HTMLElement) {
542
+ document.activeElement.blur();
543
+ }
544
+ onCalendarClose(calendarRef.current.selectedDates, '', calendarRef.current, {
545
+ type: 'clickOutside'
546
+ });
547
+ };
548
+ document.addEventListener('mousedown', handleMouseDown, true);
549
+ return () => {
550
+ document.removeEventListener('mousedown', handleMouseDown, true);
551
+ };
552
+ }, [calendarRef, startInputField, endInputField, onCalendarClose]);
502
553
  React.useEffect(() => {
503
554
  if (calendarRef?.current?.set) {
504
555
  if (value !== undefined) {
@@ -22,6 +22,15 @@ var carbonFlatpickrFixEventsPlugin = (config => fp => {
22
22
  inputTo,
23
23
  lastStartValue
24
24
  } = config;
25
+ /**
26
+ * Handles `click` outside to close calendar
27
+ */
28
+ const handleClickOutside = event => {
29
+ if (!fp.isOpen || fp.calendarContainer.contains(event.target) || event.target === inputFrom || event.target === inputTo) {
30
+ return;
31
+ }
32
+ fp.close();
33
+ };
25
34
  /**
26
35
  * Handles `keydown` event.
27
36
  */
@@ -115,6 +124,7 @@ var carbonFlatpickrFixEventsPlugin = (config => fp => {
115
124
  inputTo.removeEventListener('blur', handleBlur, true);
116
125
  }
117
126
  inputFrom.removeEventListener('keydown', handleKeydown, true);
127
+ document.removeEventListener('click', handleClickOutside, true);
118
128
  };
119
129
 
120
130
  /**
@@ -131,6 +141,7 @@ var carbonFlatpickrFixEventsPlugin = (config => fp => {
131
141
  inputTo.addEventListener('keydown', handleKeydown, true);
132
142
  inputTo.addEventListener('blur', handleBlur, true);
133
143
  }
144
+ document.addEventListener('click', handleClickOutside, true);
134
145
  };
135
146
 
136
147
  /**
@@ -36,7 +36,12 @@ export interface DropdownProps<ItemType> extends Omit<ReactAttr<HTMLDivElement>,
36
36
  */
37
37
  disabled?: boolean;
38
38
  /**
39
- * Additional props passed to Downshift
39
+ * Additional props passed to Downshift.
40
+ *
41
+ * **Use with caution:** anything you define here overrides the components'
42
+ * internal handling of that prop. Downshift APIs and internals are subject to
43
+ * change, and in some cases they can not be shimmed by Carbon to shield you
44
+ * from potentially breaking changes.
40
45
  */
41
46
  downshiftProps?: Partial<UseSelectProps<ItemType>>;
42
47
  /**
@@ -32,10 +32,6 @@ var cx__default = /*#__PURE__*/_interopDefaultLegacy(cx);
32
32
  var PropTypes__default = /*#__PURE__*/_interopDefaultLegacy(PropTypes);
33
33
 
34
34
  const {
35
- ToggleButtonKeyDownArrowDown,
36
- ToggleButtonKeyDownArrowUp,
37
- ToggleButtonKeyDownHome,
38
- ToggleButtonKeyDownEnd,
39
35
  ItemMouseMove,
40
36
  MenuMouseLeave
41
37
  } = Downshift.useSelect.stateChangeTypes;
@@ -123,7 +119,6 @@ const Dropdown = /*#__PURE__*/React__default["default"].forwardRef((_ref, ref) =
123
119
  isFluid
124
120
  } = React.useContext(FormContext.FormContext);
125
121
  const selectProps = {
126
- ...downshiftProps,
127
122
  items,
128
123
  itemToString,
129
124
  initialSelectedItem,
@@ -132,28 +127,31 @@ const Dropdown = /*#__PURE__*/React__default["default"].forwardRef((_ref, ref) =
132
127
  isItemDisabled(item, _index) {
133
128
  const isObject = item !== null && typeof item === 'object';
134
129
  return isObject && 'disabled' in item && item.disabled === true;
135
- }
130
+ },
131
+ onHighlightedIndexChange: _ref3 => {
132
+ let {
133
+ highlightedIndex
134
+ } = _ref3;
135
+ if (highlightedIndex > -1 && typeof window !== undefined) {
136
+ const itemArray = document.querySelectorAll(`li.${prefix}--list-box__menu-item[role="option"]`);
137
+ const highlightedItem = itemArray[highlightedIndex];
138
+ if (highlightedItem) {
139
+ highlightedItem.scrollIntoView({
140
+ behavior: 'smooth',
141
+ block: 'nearest'
142
+ });
143
+ }
144
+ }
145
+ },
146
+ ...downshiftProps
136
147
  };
137
148
  const dropdownInstanceId = useId.useId();
138
149
  function stateReducer(state, actionAndChanges) {
139
150
  const {
140
151
  changes,
141
- props,
142
152
  type
143
153
  } = actionAndChanges;
144
- const {
145
- highlightedIndex
146
- } = changes;
147
154
  switch (type) {
148
- case ToggleButtonKeyDownArrowDown:
149
- case ToggleButtonKeyDownArrowUp:
150
- case ToggleButtonKeyDownHome:
151
- case ToggleButtonKeyDownEnd:
152
- if (highlightedIndex > -1) {
153
- const itemArray = document.querySelectorAll(`li.${prefix}--list-box__menu-item[role="option"]`);
154
- props.scrollIntoView(itemArray[highlightedIndex]);
155
- }
156
- return changes;
157
155
  case ItemMouseMove:
158
156
  case MenuMouseLeave:
159
157
  return {
@@ -218,10 +216,10 @@ const Dropdown = /*#__PURE__*/React__default["default"].forwardRef((_ref, ref) =
218
216
  id: helperId,
219
217
  className: helperClasses
220
218
  }, helperText) : null;
221
- function onSelectedItemChange(_ref3) {
219
+ function onSelectedItemChange(_ref4) {
222
220
  let {
223
221
  selectedItem
224
- } = _ref3;
222
+ } = _ref4;
225
223
  if (onChange) {
226
224
  onChange({
227
225
  selectedItem: selectedItem ?? null
@@ -372,7 +370,12 @@ Dropdown.propTypes = {
372
370
  */
373
371
  disabled: PropTypes__default["default"].bool,
374
372
  /**
375
- * Additional props passed to Downshift
373
+ * Additional props passed to Downshift.
374
+ *
375
+ * **Use with caution:** anything you define here overrides the components'
376
+ * internal handling of that prop. Downshift APIs and internals are subject to
377
+ * change, and in some cases they can not be shimmed by Carbon to shield you
378
+ * from potentially breaking changes.
376
379
  */
377
380
  downshiftProps: PropTypes__default["default"].object,
378
381
  /**
@@ -75,7 +75,12 @@ FluidMultiSelect.propTypes = {
75
75
  */
76
76
  disabled: PropTypes__default["default"].bool,
77
77
  /**
78
- * Additional props passed to Downshift
78
+ * Additional props passed to Downshift.
79
+ *
80
+ * **Use with caution:** anything you define here overrides the components'
81
+ * internal handling of that prop. Downshift APIs and internals are subject to
82
+ * change, and in some cases they can not be shimmed by Carbon to shield you
83
+ * from potentially breaking changes.
79
84
  */
80
85
  downshiftProps: PropTypes__default["default"].object,
81
86
  /**
@@ -48,7 +48,12 @@ export interface FilterableMultiSelectProps<ItemType> extends MultiSelectSorting
48
48
  */
49
49
  disabled?: boolean;
50
50
  /**
51
- * Additional props passed to Downshift
51
+ * Additional props passed to Downshift.
52
+ *
53
+ * **Use with caution:** anything you define here overrides the components'
54
+ * internal handling of that prop. Downshift APIs and internals are subject to
55
+ * change, and in some cases they can not be shimmed by Carbon to shield you
56
+ * from potentially breaking changes.
52
57
  */
53
58
  downshiftProps?: UseMultipleSelectionProps<ItemType>;
54
59
  /**
@@ -360,7 +360,6 @@ const FilterableMultiSelect = /*#__PURE__*/React__default["default"].forwardRef(
360
360
  const {
361
361
  getDropdownProps
362
362
  } = Downshift.useMultipleSelection({
363
- ...downshiftProps,
364
363
  activeIndex: highlightedIndex,
365
364
  initialSelectedItems,
366
365
  selectedItems: controlledSelectedItems,
@@ -376,7 +375,8 @@ const FilterableMultiSelect = /*#__PURE__*/React__default["default"].forwardRef(
376
375
  break;
377
376
  }
378
377
  }
379
- }
378
+ },
379
+ ...downshiftProps
380
380
  });
381
381
  React.useEffect(() => {
382
382
  if (isOpen && !isMenuOpen) {
@@ -634,7 +634,12 @@ FilterableMultiSelect.propTypes = {
634
634
  */
635
635
  disabled: PropTypes__default["default"].bool,
636
636
  /**
637
- * Additional props passed to Downshift
637
+ * Additional props passed to Downshift.
638
+ *
639
+ * **Use with caution:** anything you define here overrides the components'
640
+ * internal handling of that prop. Downshift APIs and internals are subject to
641
+ * change, and in some cases they can not be shimmed by Carbon to shield you
642
+ * from potentially breaking changes.
638
643
  */
639
644
  // @ts-ignore
640
645
  downshiftProps: PropTypes__default["default"].shape(Downshift__default["default"].propTypes),
@@ -42,7 +42,12 @@ export interface MultiSelectProps<ItemType> extends MultiSelectSortingProps<Item
42
42
  */
43
43
  disabled?: ListBoxProps['disabled'];
44
44
  /**
45
- * Additional props passed to Downshift
45
+ * Additional props passed to Downshift.
46
+ *
47
+ * **Use with caution:** anything you define here overrides the components'
48
+ * internal handling of that prop. Downshift APIs and internals are subject to
49
+ * change, and in some cases they can not be shimmed by Carbon to shield you
50
+ * from potentially breaking changes.
46
51
  */
47
52
  downshiftProps?: Partial<UseSelectProps<ItemType>>;
48
53
  /**
@@ -177,7 +177,6 @@ const MultiSelect = /*#__PURE__*/React__default["default"].forwardRef((_ref, ref
177
177
  });
178
178
  }, [items]);
179
179
  const selectProps = {
180
- ...downshiftProps,
181
180
  stateReducer,
182
181
  isOpen,
183
182
  itemToString: filteredItems => {
@@ -189,7 +188,8 @@ const MultiSelect = /*#__PURE__*/React__default["default"].forwardRef((_ref, ref
189
188
  items: filteredItems,
190
189
  isItemDisabled(item, _index) {
191
190
  return item.disabled;
192
- }
191
+ },
192
+ ...downshiftProps
193
193
  };
194
194
  const {
195
195
  getToggleButtonProps,
@@ -529,7 +529,12 @@ MultiSelect.propTypes = {
529
529
  */
530
530
  disabled: PropTypes__default["default"].bool,
531
531
  /**
532
- * Additional props passed to Downshift
532
+ * Additional props passed to Downshift.
533
+ *
534
+ * **Use with caution:** anything you define here overrides the components'
535
+ * internal handling of that prop. Downshift APIs and internals are subject to
536
+ * change, and in some cases they can not be shimmed by Carbon to shield you
537
+ * from potentially breaking changes.
533
538
  */
534
539
  downshiftProps: PropTypes__default["default"].object,
535
540
  /**
@@ -18,49 +18,70 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'defau
18
18
 
19
19
  var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
20
20
 
21
- // This file was heavily inspired by Reach UI and their work on their auto-id
22
- const getId = setupGetInstanceId["default"]();
21
+ // This file was heavily inspired by:
22
+
23
+ // This tricks bundlers so they can't statically analyze this and produce
24
+ // compilation warnings/errors.
25
+ // https://github.com/webpack/webpack/issues/14814
26
+ // https://github.com/mui/material-ui/issues/41190
27
+ const _React = {
28
+ ...React__default["default"]
29
+ };
30
+ const instanceId = setupGetInstanceId["default"]();
23
31
  const useIsomorphicLayoutEffect = environment.canUseDOM ? React.useLayoutEffect : React.useEffect;
24
32
  let serverHandoffCompleted = false;
33
+ const defaultId = 'id';
25
34
 
26
35
  /**
27
- * Generate a unique ID with an optional prefix prepended to it
36
+ * Generate a unique ID for React <=17 with an optional prefix prepended to it.
37
+ * This is an internal utility, not intended for public usage.
28
38
  * @param {string} [prefix]
29
39
  * @returns {string}
30
40
  */
31
- function useId() {
32
- let prefix = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'id';
33
- const _prefix = useIdPrefix.useIdPrefix();
41
+ function useCompatibleId() {
42
+ let prefix = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : defaultId;
43
+ const contextPrefix = useIdPrefix.useIdPrefix();
34
44
  const [id, setId] = React.useState(() => {
35
45
  if (serverHandoffCompleted) {
36
- return `${_prefix ? `${_prefix}-` : ``}${prefix}-${getId()}`;
46
+ return `${contextPrefix ? `${contextPrefix}-` : ``}${prefix}-${instanceId()}`;
37
47
  }
38
48
  return null;
39
49
  });
40
50
  useIsomorphicLayoutEffect(() => {
41
51
  if (id === null) {
42
- setId(`${_prefix ? `${_prefix}-` : ``}${prefix}-${getId()}`);
52
+ setId(`${contextPrefix ? `${contextPrefix}-` : ``}${prefix}-${instanceId()}`);
43
53
  }
44
- }, [getId]);
54
+ }, [instanceId]);
45
55
  React.useEffect(() => {
46
56
  if (serverHandoffCompleted === false) {
47
57
  serverHandoffCompleted = true;
48
58
  }
49
59
  }, []);
50
- if (typeof React__default["default"]['useId'] === 'function') {
51
- const id = nativeReactUseId(_prefix, prefix);
52
- return id;
53
- }
54
60
  return id;
55
61
  }
56
- function nativeReactUseId(_prefix, prefix) {
57
- const getId = React__default["default"]['useId']();
58
- const id = `${_prefix ? `${_prefix}-` : ``}${prefix}-${getId}`;
59
- return id;
62
+
63
+ /**
64
+ * Generate a unique ID for React >=18 with an optional prefix prepended to it.
65
+ * This is an internal utility, not intended for public usage.
66
+ * @param {string} [prefix]
67
+ * @returns {string}
68
+ */
69
+ function useReactId() {
70
+ let prefix = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : defaultId;
71
+ const contextPrefix = useIdPrefix.useIdPrefix();
72
+ return `${contextPrefix ? `${contextPrefix}-` : ``}${prefix}-${_React.useId()}`;
60
73
  }
61
74
 
75
+ /**
76
+ * Uses React 18's built-in `useId()` when available, or falls back to a
77
+ * slightly less performant (requiring a double render) implementation for
78
+ * earlier React versions.
79
+ */
80
+ const useId = _React.useId ? useReactId : useCompatibleId;
81
+
62
82
  /**
63
83
  * Generate a unique id if a given `id` is not provided
84
+ * This is an internal utility, not intended for public usage.
64
85
  * @param {string|undefined} id
65
86
  * @returns {string}
66
87
  */
@@ -69,5 +90,6 @@ function useFallbackId(id) {
69
90
  return id ?? fallback;
70
91
  }
71
92
 
93
+ exports.useCompatibleId = useCompatibleId;
72
94
  exports.useFallbackId = useFallbackId;
73
95
  exports.useId = useId;