@carbon/react 1.68.0-rc.0 → 1.69.0-rc.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 (112) hide show
  1. package/.playwright/INTERNAL_AVT_REPORT_DO_NOT_USE.json +743 -743
  2. package/README.md +3 -3
  3. package/es/components/Accordion/AccordionItem.js +0 -1
  4. package/es/components/Button/Button.js +6 -0
  5. package/es/components/CheckboxGroup/CheckboxGroup.js +1 -2
  6. package/es/components/CheckboxGroup/index.d.ts +10 -0
  7. package/es/components/ComboBox/ComboBox.d.ts +5 -0
  8. package/es/components/ComboBox/ComboBox.js +139 -54
  9. package/es/components/ComboButton/index.js +10 -3
  10. package/es/components/DataTable/TableCell.d.ts +1 -4
  11. package/es/components/DataTable/TableCell.js +3 -2
  12. package/es/components/DatePicker/DatePicker.js +10 -6
  13. package/es/components/Disclosure/index.d.ts +18 -0
  14. package/es/components/Dropdown/Dropdown.js +11 -9
  15. package/es/components/FileUploader/FileUploader.d.ts +8 -92
  16. package/es/components/FileUploader/FileUploader.js +116 -137
  17. package/es/components/FileUploader/FileUploaderDropContainer.js +1 -1
  18. package/es/components/FluidComboBox/FluidComboBox.Skeleton.d.ts +15 -0
  19. package/es/components/FluidComboBox/FluidComboBox.Skeleton.js +1 -2
  20. package/es/components/FluidComboBox/FluidComboBox.d.ts +102 -0
  21. package/es/components/FluidComboBox/FluidComboBox.js +2 -3
  22. package/es/components/FluidComboBox/index.d.ts +13 -0
  23. package/es/components/FluidDatePicker/FluidDatePicker.Skeleton.d.ts +19 -0
  24. package/es/components/FluidDatePicker/FluidDatePicker.Skeleton.js +2 -2
  25. package/es/components/FluidDatePicker/FluidDatePicker.d.ts +39 -0
  26. package/es/components/FluidDatePicker/FluidDatePicker.js +2 -3
  27. package/es/components/FluidDatePicker/index.d.ts +13 -0
  28. package/es/components/FluidDatePickerInput/FluidDatePickerInput.d.ts +10 -0
  29. package/es/components/FluidDatePickerInput/FluidDatePickerInput.js +1 -2
  30. package/es/components/FluidDatePickerInput/index.d.ts +9 -0
  31. package/es/components/IdPrefix/index.d.ts +26 -0
  32. package/es/components/Menu/MenuItem.js +1 -4
  33. package/es/components/MenuButton/index.d.ts +4 -0
  34. package/es/components/MenuButton/index.js +19 -5
  35. package/es/components/MultiSelect/MultiSelect.js +11 -9
  36. package/es/components/OverflowMenu/next/index.d.ts +4 -0
  37. package/es/components/OverflowMenu/next/index.js +19 -9
  38. package/es/components/PaginationNav/PaginationNav.js +1 -1
  39. package/es/components/Popover/index.js +18 -14
  40. package/es/components/Portal/index.d.ts +25 -0
  41. package/es/components/Slider/Slider.js +2 -2
  42. package/es/components/Tabs/usePressable.js +2 -0
  43. package/es/components/Tag/DismissibleTag.js +2 -2
  44. package/es/components/Tag/OperationalTag.d.ts +2 -10
  45. package/es/components/Tag/OperationalTag.js +2 -14
  46. package/es/components/Tag/SelectableTag.d.ts +2 -10
  47. package/es/components/Tag/SelectableTag.js +2 -16
  48. package/es/components/Toggle/Toggle.js +2 -0
  49. package/es/components/ToggleSmall/ToggleSmall.Skeleton.d.ts +49 -0
  50. package/es/components/ToggleSmall/index.d.ts +7 -0
  51. package/es/components/TreeView/TreeNode.js +4 -2
  52. package/es/components/TreeView/TreeView.js +4 -4
  53. package/es/components/UIShell/SideNavMenuItem.d.ts +4 -3
  54. package/es/components/UIShell/SideNavMenuItem.js +1 -4
  55. package/es/index.js +6 -6
  56. package/es/internal/useIdPrefix.d.ts +9 -0
  57. package/lib/components/Accordion/AccordionItem.js +0 -1
  58. package/lib/components/Button/Button.js +6 -0
  59. package/lib/components/CheckboxGroup/CheckboxGroup.js +1 -2
  60. package/lib/components/CheckboxGroup/index.d.ts +10 -0
  61. package/lib/components/ComboBox/ComboBox.d.ts +5 -0
  62. package/lib/components/ComboBox/ComboBox.js +144 -59
  63. package/lib/components/ComboButton/index.js +12 -5
  64. package/lib/components/DataTable/TableCell.d.ts +1 -4
  65. package/lib/components/DataTable/TableCell.js +3 -2
  66. package/lib/components/DatePicker/DatePicker.js +9 -5
  67. package/lib/components/Disclosure/index.d.ts +18 -0
  68. package/lib/components/Dropdown/Dropdown.js +18 -16
  69. package/lib/components/FileUploader/FileUploader.d.ts +8 -92
  70. package/lib/components/FileUploader/FileUploader.js +113 -134
  71. package/lib/components/FileUploader/FileUploaderDropContainer.js +1 -1
  72. package/lib/components/FluidComboBox/FluidComboBox.Skeleton.d.ts +15 -0
  73. package/lib/components/FluidComboBox/FluidComboBox.Skeleton.js +1 -2
  74. package/lib/components/FluidComboBox/FluidComboBox.d.ts +102 -0
  75. package/lib/components/FluidComboBox/FluidComboBox.js +2 -3
  76. package/lib/components/FluidComboBox/index.d.ts +13 -0
  77. package/lib/components/FluidDatePicker/FluidDatePicker.Skeleton.d.ts +19 -0
  78. package/lib/components/FluidDatePicker/FluidDatePicker.Skeleton.js +2 -2
  79. package/lib/components/FluidDatePicker/FluidDatePicker.d.ts +39 -0
  80. package/lib/components/FluidDatePicker/FluidDatePicker.js +3 -4
  81. package/lib/components/FluidDatePicker/index.d.ts +13 -0
  82. package/lib/components/FluidDatePickerInput/FluidDatePickerInput.d.ts +10 -0
  83. package/lib/components/FluidDatePickerInput/FluidDatePickerInput.js +1 -2
  84. package/lib/components/FluidDatePickerInput/index.d.ts +9 -0
  85. package/lib/components/IdPrefix/index.d.ts +26 -0
  86. package/lib/components/Menu/MenuItem.js +1 -4
  87. package/lib/components/MenuButton/index.d.ts +4 -0
  88. package/lib/components/MenuButton/index.js +19 -5
  89. package/lib/components/MultiSelect/MultiSelect.js +18 -16
  90. package/lib/components/OverflowMenu/next/index.d.ts +4 -0
  91. package/lib/components/OverflowMenu/next/index.js +21 -11
  92. package/lib/components/PaginationNav/PaginationNav.js +1 -1
  93. package/lib/components/Popover/index.js +18 -14
  94. package/lib/components/Portal/index.d.ts +25 -0
  95. package/lib/components/Slider/Slider.js +2 -2
  96. package/lib/components/Tabs/usePressable.js +2 -0
  97. package/lib/components/Tag/DismissibleTag.js +2 -2
  98. package/lib/components/Tag/OperationalTag.d.ts +2 -10
  99. package/lib/components/Tag/OperationalTag.js +2 -14
  100. package/lib/components/Tag/SelectableTag.d.ts +2 -10
  101. package/lib/components/Tag/SelectableTag.js +2 -16
  102. package/lib/components/Toggle/Toggle.js +2 -0
  103. package/lib/components/ToggleSmall/ToggleSmall.Skeleton.d.ts +49 -0
  104. package/lib/components/ToggleSmall/index.d.ts +7 -0
  105. package/lib/components/TreeView/TreeNode.js +4 -2
  106. package/lib/components/TreeView/TreeView.js +4 -4
  107. package/lib/components/UIShell/SideNavMenuItem.d.ts +4 -3
  108. package/lib/components/UIShell/SideNavMenuItem.js +1 -4
  109. package/lib/index.js +12 -12
  110. package/lib/internal/useIdPrefix.d.ts +9 -0
  111. package/package.json +7 -7
  112. package/telemetry.yml +809 -809
package/README.md CHANGED
@@ -135,9 +135,9 @@ Licensed under the [Apache 2.0 License](/LICENSE).
135
135
 
136
136
  ## <picture><source height="20" width="20" media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/ibm-telemetry/telemetry-js/main/docs/images/ibm-telemetry-dark.svg"><source height="20" width="20" media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/ibm-telemetry/telemetry-js/main/docs/images/ibm-telemetry-light.svg"><img height="20" width="20" alt="IBM Telemetry" src="https://raw.githubusercontent.com/ibm-telemetry/telemetry-js/main/docs/images/ibm-telemetry-light.svg"></picture> IBM Telemetry
137
137
 
138
- This package uses IBM Telemetry to collect metrics data. By installing this
139
- package as a dependency you are agreeing to telemetry collection. To opt out,
140
- see
138
+ This package uses IBM Telemetry to collect de-identified and anonymized metrics
139
+ data. By installing this package as a dependency you are agreeing to telemetry
140
+ collection. To opt out, see
141
141
  [Opting out of IBM Telemetry data collection](https://github.com/ibm-telemetry/telemetry-js/tree/main#opting-out-of-ibm-telemetry-data-collection).
142
142
  For more information on the data being collected, please see the
143
143
  [IBM Telemetry documentation](https://github.com/ibm-telemetry/telemetry-js/tree/main#ibm-telemetry-collection-basics).
@@ -108,7 +108,6 @@ function AccordionItem(_ref) {
108
108
  className: `${prefix}--accordion__title`
109
109
  }, title)), /*#__PURE__*/React__default.createElement("div", {
110
110
  ref: content,
111
- hidden: !isOpen,
112
111
  className: `${prefix}--accordion__wrapper`,
113
112
  onTransitionEnd: onAnimationEnd
114
113
  }, /*#__PURE__*/React__default.createElement("div", {
@@ -26,6 +26,7 @@ const Button = /*#__PURE__*/React__default.forwardRef(function Button(props, ref
26
26
  const tooltipRef = useRef(null);
27
27
  const {
28
28
  as,
29
+ autoAlign = false,
29
30
  children,
30
31
  hasIconOnly = false,
31
32
  iconDescription,
@@ -84,6 +85,7 @@ const Button = /*#__PURE__*/React__default.forwardRef(function Button(props, ref
84
85
  onMouseLeave: onMouseLeave,
85
86
  onFocus: onFocus,
86
87
  onBlur: onBlur,
88
+ autoAlign: autoAlign,
87
89
  onClick: composeEventHandlers([onClick, handleClick]),
88
90
  renderIcon: iconOnlyImage ? null : ButtonImageElement // avoid doubling the icon.
89
91
  }), iconOnlyImage ?? children);
@@ -96,6 +98,10 @@ Button.propTypes = {
96
98
  * Make sure to apply all props to the root node and render children appropriately
97
99
  */
98
100
  as: PropTypes.oneOfType([PropTypes.func, PropTypes.string, PropTypes.elementType]),
101
+ /**
102
+ * **Experimental**: Will attempt to automatically align the tooltip
103
+ */
104
+ autoAlign: PropTypes.bool,
99
105
  /**
100
106
  * Specify the content of your Button
101
107
  */
@@ -126,6 +126,5 @@ CheckboxGroup.propTypes = {
126
126
  */
127
127
  warnText: PropTypes.node
128
128
  };
129
- var CheckboxGroup$1 = CheckboxGroup;
130
129
 
131
- export { CheckboxGroup$1 as default };
130
+ export { CheckboxGroup as default };
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Copyright IBM Corp. 2023
3
+ *
4
+ * This source code is licensed under the Apache-2.0 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ import CheckboxGroup from './CheckboxGroup';
8
+ import { type CheckboxGroupProps, type CustomType } from './CheckboxGroup';
9
+ export default CheckboxGroup;
10
+ export { CheckboxGroup, type CheckboxGroupProps, type CustomType };
@@ -158,6 +158,7 @@ export interface ComboBoxProps<ItemType> extends Omit<InputHTMLAttributes<HTMLIn
158
158
  * Specify your own filtering logic by passing in a `shouldFilterItem`
159
159
  * function that takes in the current input and an item and passes back
160
160
  * whether or not the item should be filtered.
161
+ * this prop will be ignored if `typeahead` prop is enabled
161
162
  */
162
163
  shouldFilterItem?: (input: {
163
164
  item: ItemType;
@@ -177,6 +178,10 @@ export interface ComboBoxProps<ItemType> extends Omit<InputHTMLAttributes<HTMLIn
177
178
  * combobox via ARIA attributes.
178
179
  */
179
180
  titleText?: ReactNode;
181
+ /**
182
+ * **Experimental**: will enable autcomplete and typeahead for the input field
183
+ */
184
+ typeahead?: boolean;
180
185
  /**
181
186
  * Specify whether the control is currently in warning state
182
187
  */
@@ -9,7 +9,7 @@ import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js
9
9
  import cx from 'classnames';
10
10
  import { useCombobox } from 'downshift';
11
11
  import PropTypes from 'prop-types';
12
- import React__default, { forwardRef, useEffect, useContext, useRef, useState, useMemo } from 'react';
12
+ import React__default, { forwardRef, useRef, useEffect, useState, useContext, useCallback, useMemo } from 'react';
13
13
  import '../Text/index.js';
14
14
  import { WarningFilled, WarningAltFilled, Checkmark } from '@carbon/icons-react';
15
15
  import ListBox from '../ListBox/index.js';
@@ -23,6 +23,7 @@ import '../FluidForm/FluidForm.js';
23
23
  import { FormContext } from '../FluidForm/FormContext.js';
24
24
  import { useFloating, flip, autoUpdate } from '@floating-ui/react';
25
25
  import { hide } from '../../node_modules/@floating-ui/dom/dist/floating-ui.dom.mjs.js';
26
+ import { useFeatureFlag } from '../FeatureFlags/index.js';
26
27
  import { Text } from '../Text/Text.js';
27
28
  import { match } from '../../internal/keyboard/match.js';
28
29
  import { ListBoxSize } from '../ListBox/ListBoxPropTypes.js';
@@ -36,8 +37,7 @@ const {
36
37
  ItemMouseMove,
37
38
  InputKeyDownArrowUp,
38
39
  InputKeyDownArrowDown,
39
- MenuMouseLeave,
40
- FunctionSelectItem
40
+ MenuMouseLeave
41
41
  } = useCombobox.stateChangeTypes;
42
42
  const defaultItemToString = item => {
43
43
  if (typeof item === 'string') {
@@ -52,26 +52,42 @@ const defaultItemToString = item => {
52
52
  return '';
53
53
  };
54
54
  const defaultShouldFilterItem = () => true;
55
- const getInputValue = _ref => {
55
+ const autocompleteCustomFilter = _ref => {
56
+ let {
57
+ item,
58
+ inputValue
59
+ } = _ref;
60
+ if (inputValue === null || inputValue === '') {
61
+ return true; // Show all items if there's no input
62
+ }
63
+ const lowercaseItem = item.toLowerCase();
64
+ const lowercaseInput = inputValue.toLowerCase();
65
+ return lowercaseItem.startsWith(lowercaseInput);
66
+ };
67
+ const getInputValue = _ref2 => {
56
68
  let {
57
69
  initialSelectedItem,
58
70
  inputValue,
59
71
  itemToString,
60
- selectedItem
61
- } = _ref;
72
+ selectedItem,
73
+ prevSelectedItem
74
+ } = _ref2;
62
75
  if (selectedItem) {
63
76
  return itemToString(selectedItem);
64
77
  }
65
78
  if (initialSelectedItem) {
66
79
  return itemToString(initialSelectedItem);
67
80
  }
81
+ if (!selectedItem && prevSelectedItem) {
82
+ return '';
83
+ }
68
84
  return inputValue || '';
69
85
  };
70
- const findHighlightedIndex = (_ref2, inputValue) => {
86
+ const findHighlightedIndex = (_ref3, inputValue) => {
71
87
  let {
72
88
  items,
73
89
  itemToString = defaultItemToString
74
- } = _ref2;
90
+ } = _ref3;
75
91
  if (!inputValue) {
76
92
  return -1;
77
93
  }
@@ -94,6 +110,8 @@ const findHighlightedIndex = (_ref2, inputValue) => {
94
110
  */
95
111
 
96
112
  const ComboBox = /*#__PURE__*/forwardRef((props, ref) => {
113
+ const prevInputLengthRef = useRef(0);
114
+ const inputRef = useRef(null);
97
115
  const {
98
116
  ['aria-label']: ariaLabel = 'Choose an item',
99
117
  ariaLabel: deprecatedAriaLabel,
@@ -122,25 +140,27 @@ const ComboBox = /*#__PURE__*/forwardRef((props, ref) => {
122
140
  size,
123
141
  titleText,
124
142
  translateWithId,
143
+ typeahead = false,
125
144
  warn,
126
145
  warnText,
127
146
  allowCustomValue = false,
128
147
  slug,
129
148
  ...rest
130
149
  } = props;
150
+ const enableFloatingStyles = useFeatureFlag('enable-v12-dynamic-floating-styles') || autoAlign;
131
151
  const {
132
152
  refs,
133
153
  floatingStyles,
134
154
  middlewareData
135
- } = useFloating(autoAlign ? {
155
+ } = useFloating(enableFloatingStyles ? {
136
156
  placement: direction,
137
157
  strategy: 'fixed',
138
- middleware: [flip(), hide()],
158
+ middleware: autoAlign ? [flip(), hide()] : undefined,
139
159
  whileElementsMounted: autoUpdate
140
160
  } : {});
141
161
  const parentWidth = refs?.reference?.current?.clientWidth;
142
162
  useEffect(() => {
143
- if (autoAlign) {
163
+ if (enableFloatingStyles) {
144
164
  const updatedFloatingStyles = {
145
165
  ...floatingStyles,
146
166
  visibility: middlewareData.hide?.referenceHidden ? 'hidden' : 'visible'
@@ -154,34 +174,69 @@ const ComboBox = /*#__PURE__*/forwardRef((props, ref) => {
154
174
  refs.floating.current.style.width = parentWidth + 'px';
155
175
  }
156
176
  }
157
- }, [autoAlign, floatingStyles, refs.floating, parentWidth]);
158
- const prefix = usePrefix();
159
- const {
160
- isFluid
161
- } = useContext(FormContext);
162
- const textInput = useRef(null);
163
- const comboBoxInstanceId = useId();
177
+ }, [enableFloatingStyles, floatingStyles, refs.floating, parentWidth]);
164
178
  const [inputValue, setInputValue] = useState(getInputValue({
165
179
  initialSelectedItem,
166
180
  inputValue: '',
167
181
  itemToString,
168
182
  selectedItem: selectedItemProp
169
183
  }));
184
+ const [typeaheadText, setTypeaheadText] = useState('');
185
+ useEffect(() => {
186
+ if (typeahead) {
187
+ if (inputValue.length >= prevInputLengthRef.current) {
188
+ if (inputValue) {
189
+ const filteredItems = items.filter(item => autocompleteCustomFilter({
190
+ item: itemToString(item),
191
+ inputValue: inputValue
192
+ }));
193
+ if (filteredItems.length > 0) {
194
+ const suggestion = itemToString(filteredItems[0]);
195
+ setTypeaheadText(suggestion.slice(inputValue.length));
196
+ } else {
197
+ setTypeaheadText('');
198
+ }
199
+ } else {
200
+ setTypeaheadText('');
201
+ }
202
+ } else {
203
+ setTypeaheadText('');
204
+ }
205
+ prevInputLengthRef.current = inputValue.length;
206
+ }
207
+ }, [typeahead, inputValue, items, itemToString, autocompleteCustomFilter]);
208
+ const prefix = usePrefix();
209
+ const {
210
+ isFluid
211
+ } = useContext(FormContext);
212
+ const textInput = useRef(null);
213
+ const comboBoxInstanceId = useId();
170
214
  const [isFocused, setIsFocused] = useState(false);
171
- const [prevSelectedItem, setPrevSelectedItem] = useState();
172
- const [doneInitialSelectedItem, setDoneInitialSelectedItem] = useState(false);
173
215
  const savedOnInputChange = useRef(onInputChange);
174
- if (!doneInitialSelectedItem || prevSelectedItem !== selectedItemProp) {
175
- setDoneInitialSelectedItem(true);
176
- setPrevSelectedItem(selectedItemProp);
177
- setInputValue(getInputValue({
178
- initialSelectedItem,
179
- inputValue,
180
- itemToString,
181
- selectedItem: selectedItemProp
182
- }));
183
- }
184
- const filterItems = (items, itemToString, inputValue) => items.filter(item => shouldFilterItem ? shouldFilterItem({
216
+ const prevSelectedItemProp = useRef(selectedItemProp);
217
+
218
+ // fully controlled combobox: handle changes to selectedItemProp
219
+ useEffect(() => {
220
+ if (prevSelectedItemProp.current !== selectedItemProp) {
221
+ const currentInputValue = getInputValue({
222
+ initialSelectedItem,
223
+ inputValue,
224
+ itemToString,
225
+ selectedItem: selectedItemProp,
226
+ prevSelectedItem: prevSelectedItemProp.current
227
+ });
228
+ setInputValue(currentInputValue);
229
+ onChange({
230
+ selectedItem: selectedItemProp,
231
+ inputValue: currentInputValue
232
+ });
233
+ prevSelectedItemProp.current = selectedItemProp;
234
+ }
235
+ }, [selectedItemProp]);
236
+ const filterItems = (items, itemToString, inputValue) => items.filter(item => typeahead ? autocompleteCustomFilter({
237
+ item: itemToString(item),
238
+ inputValue
239
+ }) : shouldFilterItem ? shouldFilterItem({
185
240
  item,
186
241
  itemToString,
187
242
  inputValue
@@ -204,7 +259,7 @@ const ComboBox = /*#__PURE__*/forwardRef((props, ref) => {
204
259
  ...props,
205
260
  items: filteredItems(inputValue)
206
261
  }, inputValue);
207
- const stateReducer = React__default.useCallback((state, actionAndChanges) => {
262
+ const stateReducer = useCallback((state, actionAndChanges) => {
208
263
  const {
209
264
  type,
210
265
  changes
@@ -240,14 +295,6 @@ const ComboBox = /*#__PURE__*/forwardRef((props, ref) => {
240
295
  }
241
296
  return changes;
242
297
  }
243
- case FunctionSelectItem:
244
- if (onChange) {
245
- onChange({
246
- selectedItem: changes.selectedItem,
247
- inputValue: changes.inputValue
248
- });
249
- }
250
- return changes;
251
298
  case InputKeyDownEnter:
252
299
  if (allowCustomValue) {
253
300
  setInputValue(inputValue);
@@ -321,7 +368,7 @@ const ComboBox = /*#__PURE__*/forwardRef((props, ref) => {
321
368
  [`${prefix}--list-box--up`]: direction === 'top',
322
369
  [`${prefix}--combo-box--warning`]: showWarning,
323
370
  [`${prefix}--combo-box--readonly`]: readOnly,
324
- [`${prefix}--autoalign`]: autoAlign
371
+ [`${prefix}--autoalign`]: enableFloatingStyles
325
372
  });
326
373
  const titleClasses = cx(`${prefix}--label`, {
327
374
  [`${prefix}--label--disabled`]: disabled
@@ -377,25 +424,33 @@ const ComboBox = /*#__PURE__*/forwardRef((props, ref) => {
377
424
  itemToString: item => {
378
425
  return itemToString(item);
379
426
  },
380
- onInputValueChange(_ref3) {
427
+ onInputValueChange(_ref4) {
381
428
  let {
382
429
  inputValue
383
- } = _ref3;
384
- setInputValue(inputValue || '');
385
- setHighlightedIndex(indexToHighlight(inputValue));
430
+ } = _ref4;
431
+ const normalizedInput = inputValue || '';
432
+ setInputValue(normalizedInput);
433
+ if (selectedItemProp && !inputValue) {
434
+ // ensure onChange is called when selectedItem is cleared
435
+ onChange({
436
+ selectedItem,
437
+ inputValue: normalizedInput
438
+ });
439
+ }
440
+ setHighlightedIndex(indexToHighlight(normalizedInput));
386
441
  },
387
- onSelectedItemChange(_ref4) {
442
+ onSelectedItemChange(_ref5) {
388
443
  let {
389
444
  selectedItem
390
- } = _ref4;
445
+ } = _ref5;
391
446
  onChange({
392
447
  selectedItem
393
448
  });
394
449
  },
395
- onHighlightedIndexChange: _ref5 => {
450
+ onHighlightedIndexChange: _ref6 => {
396
451
  let {
397
452
  highlightedIndex
398
- } = _ref5;
453
+ } = _ref6;
399
454
  if (highlightedIndex > -1 && typeof window !== undefined) {
400
455
  const itemArray = document.querySelectorAll(`li.${prefix}--list-box__menu-item[role="option"]`);
401
456
  const highlightedItem = itemArray[highlightedIndex];
@@ -474,9 +529,18 @@ const ComboBox = /*#__PURE__*/forwardRef((props, ref) => {
474
529
 
475
530
  // Memoize the value of getMenuProps to avoid an infinite loop
476
531
  const menuProps = useMemo(() => getMenuProps({
477
- 'aria-label': deprecatedAriaLabel || ariaLabel,
478
- ref: autoAlign ? refs.setFloating : null
479
- }), [autoAlign, deprecatedAriaLabel, ariaLabel, getMenuProps, refs.setFloating]);
532
+ ref: enableFloatingStyles ? refs.setFloating : null
533
+ }), [enableFloatingStyles, deprecatedAriaLabel, ariaLabel, getMenuProps, refs.setFloating]);
534
+ useEffect(() => {
535
+ if (textInput.current) {
536
+ if (inputRef.current && typeaheadText) {
537
+ const selectionStart = inputValue.length;
538
+ const selectionEnd = selectionStart + typeaheadText.length;
539
+ inputRef.current.value = inputValue + typeaheadText;
540
+ inputRef.current.setSelectionRange(selectionStart, selectionEnd);
541
+ }
542
+ }
543
+ }, [inputValue, typeaheadText]);
480
544
  return /*#__PURE__*/React__default.createElement("div", {
481
545
  className: wrapperClasses
482
546
  }, titleText && /*#__PURE__*/React__default.createElement(Text, _extends({
@@ -494,7 +558,7 @@ const ComboBox = /*#__PURE__*/forwardRef((props, ref) => {
494
558
  light: light,
495
559
  size: size,
496
560
  warn: warn,
497
- ref: autoAlign ? refs.setReference : null,
561
+ ref: enableFloatingStyles ? refs.setReference : null,
498
562
  warnText: warnText,
499
563
  warnTextId: warnTextId
500
564
  }, /*#__PURE__*/React__default.createElement("div", {
@@ -507,9 +571,16 @@ const ComboBox = /*#__PURE__*/forwardRef((props, ref) => {
507
571
  "aria-haspopup": "listbox",
508
572
  title: textInput?.current?.value
509
573
  }, getInputProps({
574
+ 'aria-label': titleText ? undefined : deprecatedAriaLabel || ariaLabel,
510
575
  'aria-controls': isOpen ? undefined : menuProps.id,
511
576
  placeholder,
512
- ref: mergeRefs(textInput, ref),
577
+ value: inputValue,
578
+ onChange: e => {
579
+ const newValue = e.target.value;
580
+ setInputValue(newValue);
581
+ downshiftSetInputValue(newValue);
582
+ },
583
+ ref: mergeRefs(textInput, ref, inputRef),
513
584
  onKeyDown: event => {
514
585
  if (match(event, Space)) {
515
586
  event.stopPropagation();
@@ -557,6 +628,15 @@ const ComboBox = /*#__PURE__*/forwardRef((props, ref) => {
557
628
  toggleMenu();
558
629
  }
559
630
  }
631
+ if (typeahead && event.key === 'Tab') {
632
+ // event.preventDefault();
633
+ const matchingItem = items.find(item => itemToString(item).toLowerCase().startsWith(inputValue.toLowerCase()));
634
+ if (matchingItem) {
635
+ const newValue = itemToString(matchingItem);
636
+ downshiftSetInputValue(newValue);
637
+ selectItem(matchingItem);
638
+ }
639
+ }
560
640
  }
561
641
  }), rest, readOnlyEventHandlers, {
562
642
  readOnly: readOnly,
@@ -749,6 +829,7 @@ ComboBox.propTypes = {
749
829
  * Specify your own filtering logic by passing in a `shouldFilterItem`
750
830
  * function that takes in the current input and an item and passes back
751
831
  * whether or not the item should be filtered.
832
+ * this prop will be ignored if `typeahead` prop is enabled
752
833
  */
753
834
  shouldFilterItem: PropTypes.func,
754
835
  /**
@@ -769,6 +850,10 @@ ComboBox.propTypes = {
769
850
  * and returns the localized string for the message
770
851
  */
771
852
  translateWithId: PropTypes.func,
853
+ /**
854
+ * **Experimental**: will enable autcomplete and typeahead for the input field
855
+ */
856
+ typeahead: PropTypes.bool,
772
857
  /**
773
858
  * Specify whether the control is currently in warning state
774
859
  */
@@ -20,6 +20,7 @@ import { useId } from '../../internal/useId.js';
20
20
  import { usePrefix } from '../../internal/usePrefix.js';
21
21
  import { flip, size, useFloating, autoUpdate } from '@floating-ui/react';
22
22
  import { hide } from '../../node_modules/@floating-ui/dom/dist/floating-ui.dom.mjs.js';
23
+ import { useFeatureFlag } from '../FeatureFlags/index.js';
23
24
  import mergeRefs from '../../tools/mergeRefs.js';
24
25
 
25
26
  var _ChevronDown;
@@ -47,12 +48,18 @@ const ComboButton = /*#__PURE__*/React__default.forwardRef(function ComboButton(
47
48
  translateWithId: t = defaultTranslateWithId,
48
49
  ...rest
49
50
  } = _ref;
51
+ // feature flag utilized to separate out only the dynamic styles from @floating-ui
52
+ // flag is turned on when collision detection (ie. flip, hide) logic is not desired
53
+ const enableOnlyFloatingStyles = useFeatureFlag('enable-v12-dynamic-floating-styles');
50
54
  const id = useId('combobutton');
51
55
  const prefix = usePrefix();
52
56
  const containerRef = useRef(null);
53
- const middlewares = [flip({
54
- crossAxis: false
55
- }), hide()];
57
+ let middlewares = [];
58
+ if (!enableOnlyFloatingStyles) {
59
+ middlewares = [flip({
60
+ crossAxis: false
61
+ }), hide()];
62
+ }
56
63
  if (menuAlignment === 'bottom' || menuAlignment === 'top') {
57
64
  middlewares.push(size({
58
65
  apply(_ref2) {
@@ -28,8 +28,5 @@ interface TableCellProps extends ReactAttr<HTMLTableCellElement> {
28
28
  */
29
29
  headers?: string;
30
30
  }
31
- declare const TableCell: {
32
- ({ children, className, hasSlugHeader, colSpan, ...rest }: TableCellProps): import("react/jsx-runtime").JSX.Element;
33
- displayName: string;
34
- };
31
+ declare const TableCell: React.ForwardRefExoticComponent<TableCellProps & React.RefAttributes<HTMLTableCellElement>>;
35
32
  export default TableCell;
@@ -10,7 +10,7 @@ import React__default from 'react';
10
10
  import cx from 'classnames';
11
11
  import { usePrefix } from '../../internal/usePrefix.js';
12
12
 
13
- const TableCell = _ref => {
13
+ const TableCell = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
14
14
  let {
15
15
  children,
16
16
  className,
@@ -24,9 +24,10 @@ const TableCell = _ref => {
24
24
  });
25
25
  return /*#__PURE__*/React__default.createElement("td", _extends({
26
26
  className: tableCellClassNames ? tableCellClassNames : undefined,
27
+ ref: ref,
27
28
  colSpan: colSpan
28
29
  }, rest), children);
29
- };
30
+ });
30
31
  TableCell.displayName = 'TableCell';
31
32
 
32
33
  export { TableCell as default };
@@ -22,7 +22,7 @@ import '../FluidForm/FluidForm.js';
22
22
  import { FormContext } from '../FluidForm/FormContext.js';
23
23
  import { WarningFilled, WarningAltFilled } from '@carbon/icons-react';
24
24
  import { match } from '../../internal/keyboard/match.js';
25
- import { Escape, ArrowDown, Tab } from '../../internal/keyboard/keys.js';
25
+ import { Escape, ArrowDown, Enter, Tab } from '../../internal/keyboard/keys.js';
26
26
 
27
27
  // Weekdays shorthand for english locale
28
28
  l10n.en.weekdays.shorthand.forEach((_day, index) => {
@@ -391,9 +391,6 @@ const DatePicker = /*#__PURE__*/React__default.forwardRef(function DatePicker(_r
391
391
  }
392
392
  }
393
393
  function handleOnChange(event) {
394
- if (datePickerType == 'single' && closeOnSelect) {
395
- calendar.calendarContainer.classList.remove('open');
396
- }
397
394
  const {
398
395
  target
399
396
  } = event;
@@ -409,12 +406,16 @@ const DatePicker = /*#__PURE__*/React__default.forwardRef(function DatePicker(_r
409
406
  if (calendar.selectedDates.length === 0) {
410
407
  return;
411
408
  }
412
- calendar.clear();
413
- calendar.input.focus();
409
+ }
410
+ function handleKeyPress(event) {
411
+ if (match(event, Enter) && closeOnSelect && datePickerType == 'single') {
412
+ calendar.calendarContainer.classList.remove('open');
413
+ }
414
414
  }
415
415
  if (start) {
416
416
  start.addEventListener('keydown', handleArrowDown);
417
417
  start.addEventListener('change', handleOnChange);
418
+ start.addEventListener('keypress', handleKeyPress);
418
419
  if (calendar && calendar.calendarContainer) {
419
420
  // Flatpickr's calendar dialog is not rendered in a landmark causing an
420
421
  // error with IBM Equal Access Accessibility Checker so we add an aria
@@ -427,6 +428,7 @@ const DatePicker = /*#__PURE__*/React__default.forwardRef(function DatePicker(_r
427
428
  if (end) {
428
429
  end.addEventListener('keydown', handleArrowDown);
429
430
  end.addEventListener('change', handleOnChange);
431
+ end.addEventListener('keypress', handleKeyPress);
430
432
  }
431
433
 
432
434
  //component did unmount equivalent
@@ -450,10 +452,12 @@ const DatePicker = /*#__PURE__*/React__default.forwardRef(function DatePicker(_r
450
452
  if (start) {
451
453
  start.removeEventListener('keydown', handleArrowDown);
452
454
  start.removeEventListener('change', handleOnChange);
455
+ start.removeEventListener('keypress', handleKeyPress);
453
456
  }
454
457
  if (end) {
455
458
  end.removeEventListener('keydown', handleArrowDown);
456
459
  end.removeEventListener('change', handleOnChange);
460
+ end.removeEventListener('change', handleKeyPress);
457
461
  }
458
462
  };
459
463
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Copyright IBM Corp. 2016, 2023
3
+ *
4
+ * This source code is licensed under the Apache-2.0 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ declare function useDisclosure(id: any): {
8
+ buttonProps: {
9
+ 'aria-controls': any;
10
+ 'aria-expanded': boolean;
11
+ onClick(): void;
12
+ };
13
+ contentProps: {
14
+ id: any;
15
+ };
16
+ open: boolean;
17
+ };
18
+ export { useDisclosure };
@@ -20,6 +20,7 @@ import { FormContext } from '../FluidForm/FormContext.js';
20
20
  import { useId } from '../../internal/useId.js';
21
21
  import { useFloating, size, flip, autoUpdate } from '@floating-ui/react';
22
22
  import { hide } from '../../node_modules/@floating-ui/dom/dist/floating-ui.dom.mjs.js';
23
+ import { useFeatureFlag } from '../FeatureFlags/index.js';
23
24
  import { ListBoxSize, ListBoxType } from '../ListBox/ListBoxPropTypes.js';
24
25
 
25
26
  const {
@@ -71,11 +72,12 @@ const Dropdown = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
71
72
  slug,
72
73
  ...other
73
74
  } = _ref;
75
+ const enableFloatingStyles = useFeatureFlag('enable-v12-dynamic-floating-styles');
74
76
  const {
75
77
  refs,
76
78
  floatingStyles,
77
79
  middlewareData
78
- } = useFloating(autoAlign ? {
80
+ } = useFloating(enableFloatingStyles || autoAlign ? {
79
81
  placement: direction,
80
82
  // The floating element is positioned relative to its nearest
81
83
  // containing block (usually the viewport). It will in many cases also
@@ -93,12 +95,14 @@ const Dropdown = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
93
95
  width: `${rects.reference.width}px`
94
96
  });
95
97
  }
96
- }), flip(), hide()],
98
+ }), autoAlign && flip(), autoAlign && hide()],
97
99
  whileElementsMounted: autoUpdate
98
- } : {} // When autoAlign is turned off, floating-ui will not be used
100
+ } : {}
101
+ // When autoAlign is turned off & the `enable-v12-dynamic-floating-styles` feature flag is not
102
+ // enabled, floating-ui will not be used
99
103
  );
100
104
  useEffect(() => {
101
- if (autoAlign) {
105
+ if (enableFloatingStyles || autoAlign) {
102
106
  const updatedFloatingStyles = {
103
107
  ...floatingStyles,
104
108
  visibility: middlewareData.hide?.referenceHidden ? 'hidden' : 'visible'
@@ -237,9 +241,7 @@ const Dropdown = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
237
241
  // NOTE: does not prevent click
238
242
  evt.preventDefault();
239
243
  // focus on the element as per readonly input behavior
240
- if (mergedRef.current !== undefined) {
241
- mergedRef.current.focus();
242
- }
244
+ mergedRef?.current?.focus();
243
245
  },
244
246
  onKeyDown: evt => {
245
247
  const selectAccessKeys = ['ArrowDown', 'ArrowUp', ' ', 'Enter'];
@@ -267,7 +269,7 @@ const Dropdown = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
267
269
  }
268
270
  };
269
271
  const menuProps = useMemo(() => getMenuProps({
270
- ref: autoAlign ? refs.setFloating : null
272
+ ref: enableFloatingStyles || autoAlign ? refs.setFloating : null
271
273
  }), [autoAlign, getMenuProps, refs.setFloating]);
272
274
 
273
275
  // Slug is always size `mini`
@@ -292,7 +294,7 @@ const Dropdown = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
292
294
  warnText: warnText,
293
295
  light: light,
294
296
  isOpen: isOpen,
295
- ref: autoAlign ? refs.setReference : null,
297
+ ref: enableFloatingStyles || autoAlign ? refs.setReference : null,
296
298
  id: id
297
299
  }, invalid && /*#__PURE__*/React__default.createElement(WarningFilled, {
298
300
  className: `${prefix}--list-box__invalid-icon`