@carbon/react 1.100.0-rc.0 → 1.101.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 (148) hide show
  1. package/.playwright/INTERNAL_AVT_REPORT_DO_NOT_USE.json +933 -933
  2. package/es/components/AILabel/index.d.ts +1 -1
  3. package/es/components/AILabel/index.js +1 -12
  4. package/es/components/Checkbox/Checkbox.js +5 -3
  5. package/es/components/CheckboxGroup/CheckboxGroup.js +4 -3
  6. package/es/components/CodeSnippet/CodeSnippet.d.ts +1 -1
  7. package/es/components/ComboBox/ComboBox.d.ts +3 -4
  8. package/es/components/ComboBox/ComboBox.js +20 -18
  9. package/es/components/ComboButton/index.d.ts +1 -1
  10. package/es/components/ComboButton/index.js +3 -2
  11. package/es/components/ComposedModal/ComposedModal.js +17 -22
  12. package/es/components/ComposedModal/ModalHeader.d.ts +2 -2
  13. package/es/components/ComposedModal/ModalHeader.js +1 -1
  14. package/es/components/Copy/Copy.d.ts +1 -1
  15. package/es/components/CopyButton/CopyButton.d.ts +1 -1
  16. package/es/components/DataTable/DataTable.d.ts +2 -0
  17. package/es/components/DataTable/DataTable.js +6 -5
  18. package/es/components/DataTable/Table.d.ts +1 -1
  19. package/es/components/DataTable/Table.js +10 -4
  20. package/es/components/DataTable/state/sorting.d.ts +4 -2
  21. package/es/components/Dropdown/Dropdown.d.ts +3 -4
  22. package/es/components/Dropdown/Dropdown.js +16 -13
  23. package/es/components/FileUploader/FileUploaderItem.d.ts +1 -1
  24. package/es/components/FileUploader/FileUploaderItem.js +3 -2
  25. package/es/components/FluidComboBox/FluidComboBox.d.ts +2 -7
  26. package/es/components/FluidComboBox/FluidComboBox.js +1 -2
  27. package/es/components/FluidDropdown/FluidDropdown.d.ts +1 -6
  28. package/es/components/FluidDropdown/FluidDropdown.js +1 -2
  29. package/es/components/FluidMultiSelect/FluidMultiSelect.d.ts +1 -6
  30. package/es/components/FluidMultiSelect/FluidMultiSelect.js +1 -2
  31. package/es/components/InlineLoading/InlineLoading.js +5 -11
  32. package/es/components/Menu/Menu.js +8 -4
  33. package/es/components/Menu/MenuItem.d.ts +5 -1
  34. package/es/components/Menu/MenuItem.js +11 -1
  35. package/es/components/MenuButton/index.d.ts +1 -1
  36. package/es/components/MenuButton/index.js +3 -2
  37. package/es/components/MultiSelect/FilterableMultiSelect.d.ts +1 -1
  38. package/es/components/MultiSelect/FilterableMultiSelect.js +7 -5
  39. package/es/components/MultiSelect/MultiSelect.d.ts +3 -4
  40. package/es/components/MultiSelect/MultiSelect.js +10 -13
  41. package/es/components/Notification/Notification.js +5 -3
  42. package/es/components/NumberInput/NumberInput.d.ts +1 -1
  43. package/es/components/NumberInput/NumberInput.js +5 -4
  44. package/es/components/OverflowMenu/OverflowMenu.d.ts +1 -0
  45. package/es/components/OverflowMenu/OverflowMenu.js +8 -4
  46. package/es/components/PageHeader/PageHeader.d.ts +1 -1
  47. package/es/components/PageHeader/PageHeader.js +5 -5
  48. package/es/components/RadioButtonGroup/RadioButtonGroup.js +4 -3
  49. package/es/components/Select/Select.js +2 -1
  50. package/es/components/StructuredList/StructuredList.d.ts +1 -1
  51. package/es/components/StructuredList/StructuredList.js +2 -4
  52. package/es/components/Tabs/Tabs.d.ts +2 -2
  53. package/es/components/Tabs/Tabs.js +20 -26
  54. package/es/components/Tag/DismissibleTag.js +3 -2
  55. package/es/components/Tag/OperationalTag.js +3 -2
  56. package/es/components/Tag/SelectableTag.js +3 -2
  57. package/es/components/Tag/Tag.js +3 -2
  58. package/es/components/TextArea/TextArea.d.ts +1 -1
  59. package/es/components/TextArea/TextArea.js +7 -8
  60. package/es/components/TextInput/ControlledPasswordInput.js +7 -6
  61. package/es/components/TextInput/PasswordInput.js +5 -6
  62. package/es/components/TextInput/TextInput.js +4 -4
  63. package/es/components/Tile/Tile.d.ts +1 -1
  64. package/es/components/Tile/Tile.js +37 -69
  65. package/es/components/TimePicker/TimePicker.js +2 -2
  66. package/es/components/Tooltip/DefinitionTooltip.d.ts +1 -1
  67. package/es/components/Tooltip/DefinitionTooltip.js +3 -2
  68. package/es/components/UIShell/SideNav.d.ts +0 -1
  69. package/es/components/UIShell/SideNav.js +12 -3
  70. package/es/internal/useId.js +3 -4
  71. package/es/internal/usePresence.js +3 -2
  72. package/es/internal/useResizeObserver.d.ts +1 -1
  73. package/es/internal/useResizeObserver.js +5 -7
  74. package/es/tools/events.d.ts +1 -1
  75. package/lib/components/AILabel/index.d.ts +1 -1
  76. package/lib/components/AILabel/index.js +1 -12
  77. package/lib/components/Checkbox/Checkbox.js +5 -3
  78. package/lib/components/CheckboxGroup/CheckboxGroup.js +4 -3
  79. package/lib/components/CodeSnippet/CodeSnippet.d.ts +1 -1
  80. package/lib/components/ComboBox/ComboBox.d.ts +3 -4
  81. package/lib/components/ComboBox/ComboBox.js +20 -18
  82. package/lib/components/ComboButton/index.d.ts +1 -1
  83. package/lib/components/ComboButton/index.js +2 -1
  84. package/lib/components/ComposedModal/ComposedModal.js +16 -21
  85. package/lib/components/ComposedModal/ModalHeader.d.ts +2 -2
  86. package/lib/components/ComposedModal/ModalHeader.js +1 -1
  87. package/lib/components/Copy/Copy.d.ts +1 -1
  88. package/lib/components/CopyButton/CopyButton.d.ts +1 -1
  89. package/lib/components/DataTable/DataTable.d.ts +2 -0
  90. package/lib/components/DataTable/DataTable.js +6 -5
  91. package/lib/components/DataTable/Table.d.ts +1 -1
  92. package/lib/components/DataTable/Table.js +10 -4
  93. package/lib/components/DataTable/state/sorting.d.ts +4 -2
  94. package/lib/components/Dropdown/Dropdown.d.ts +3 -4
  95. package/lib/components/Dropdown/Dropdown.js +16 -13
  96. package/lib/components/FileUploader/FileUploaderItem.d.ts +1 -1
  97. package/lib/components/FileUploader/FileUploaderItem.js +2 -1
  98. package/lib/components/FluidComboBox/FluidComboBox.d.ts +2 -7
  99. package/lib/components/FluidComboBox/FluidComboBox.js +1 -2
  100. package/lib/components/FluidDropdown/FluidDropdown.d.ts +1 -6
  101. package/lib/components/FluidDropdown/FluidDropdown.js +1 -2
  102. package/lib/components/FluidMultiSelect/FluidMultiSelect.d.ts +1 -6
  103. package/lib/components/FluidMultiSelect/FluidMultiSelect.js +1 -2
  104. package/lib/components/InlineLoading/InlineLoading.js +5 -11
  105. package/lib/components/Menu/Menu.js +7 -3
  106. package/lib/components/Menu/MenuItem.d.ts +5 -1
  107. package/lib/components/Menu/MenuItem.js +11 -1
  108. package/lib/components/MenuButton/index.d.ts +1 -1
  109. package/lib/components/MenuButton/index.js +2 -1
  110. package/lib/components/MultiSelect/FilterableMultiSelect.d.ts +1 -1
  111. package/lib/components/MultiSelect/FilterableMultiSelect.js +6 -4
  112. package/lib/components/MultiSelect/MultiSelect.d.ts +3 -4
  113. package/lib/components/MultiSelect/MultiSelect.js +9 -12
  114. package/lib/components/Notification/Notification.js +5 -3
  115. package/lib/components/NumberInput/NumberInput.d.ts +1 -1
  116. package/lib/components/NumberInput/NumberInput.js +5 -4
  117. package/lib/components/OverflowMenu/OverflowMenu.d.ts +1 -0
  118. package/lib/components/OverflowMenu/OverflowMenu.js +7 -3
  119. package/lib/components/PageHeader/PageHeader.d.ts +1 -1
  120. package/lib/components/PageHeader/PageHeader.js +4 -4
  121. package/lib/components/RadioButtonGroup/RadioButtonGroup.js +4 -3
  122. package/lib/components/Select/Select.js +2 -1
  123. package/lib/components/StructuredList/StructuredList.d.ts +1 -1
  124. package/lib/components/StructuredList/StructuredList.js +2 -4
  125. package/lib/components/Tabs/Tabs.d.ts +2 -2
  126. package/lib/components/Tabs/Tabs.js +15 -21
  127. package/lib/components/Tag/DismissibleTag.js +2 -1
  128. package/lib/components/Tag/OperationalTag.js +2 -1
  129. package/lib/components/Tag/SelectableTag.js +2 -1
  130. package/lib/components/Tag/Tag.js +2 -1
  131. package/lib/components/TextArea/TextArea.d.ts +1 -1
  132. package/lib/components/TextArea/TextArea.js +7 -8
  133. package/lib/components/TextInput/ControlledPasswordInput.js +7 -6
  134. package/lib/components/TextInput/PasswordInput.js +5 -6
  135. package/lib/components/TextInput/TextInput.js +4 -4
  136. package/lib/components/Tile/Tile.d.ts +1 -1
  137. package/lib/components/Tile/Tile.js +35 -67
  138. package/lib/components/TimePicker/TimePicker.js +2 -2
  139. package/lib/components/Tooltip/DefinitionTooltip.d.ts +1 -1
  140. package/lib/components/Tooltip/DefinitionTooltip.js +3 -2
  141. package/lib/components/UIShell/SideNav.d.ts +0 -1
  142. package/lib/components/UIShell/SideNav.js +11 -2
  143. package/lib/internal/useId.js +2 -3
  144. package/lib/internal/usePresence.js +2 -1
  145. package/lib/internal/useResizeObserver.d.ts +1 -1
  146. package/lib/internal/useResizeObserver.js +4 -6
  147. package/lib/tools/events.d.ts +1 -1
  148. package/package.json +8 -8
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright IBM Corp. 2016, 2025
2
+ * Copyright IBM Corp. 2016, 2026
3
3
  *
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.
@@ -23,20 +23,9 @@ const AILabelContent = /*#__PURE__*/React.forwardRef(function AILabelContent({
23
23
  }, ref // eslint-disable-line @typescript-eslint/no-unused-vars -- https://github.com/carbon-design-system/carbon/issues/20452
24
24
  ) {
25
25
  const prefix = usePrefix();
26
- const hasAILabelActions = React.Children.toArray(children).some(child => {
27
- // eslint-disable-next-line @typescript-eslint/no-explicit-any -- https://github.com/carbon-design-system/carbon/issues/20452
28
- const item = child;
29
- // TODO: Is there supposed to be a `return` here? If so, this issue would
30
- // have been caught by ESLint. It's concerning that this code is 7 months
31
- // old and no one has noticed any issues with it. It also makes me question
32
- // whether the code is necessary.
33
- // https://github.com/carbon-design-system/carbon/issues/18991
34
- // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- https://github.com/carbon-design-system/carbon/issues/20452
35
- item.type === AILabelActions;
36
- });
37
26
  const aiLabelContentClasses = cx(className, {
38
27
  [`${prefix}--ai-label-content`]: true,
39
- [`${prefix}--ai-label-content--with-actions`]: hasAILabelActions
28
+ [`${prefix}--ai-label-content--with-actions`]: false
40
29
  });
41
30
  return /*#__PURE__*/React.createElement(ToggletipContent, {
42
31
  className: aiLabelContentClasses
@@ -42,11 +42,12 @@ const Checkbox = /*#__PURE__*/React.forwardRef(({
42
42
  const showWarning = !readOnly && !invalid && warn;
43
43
  const showHelper = !invalid && !warn;
44
44
  const checkboxGroupInstanceId = useId();
45
- const helperId = !helperText ? undefined : `checkbox-helper-text-${checkboxGroupInstanceId}`;
46
- const helper = helperText ? /*#__PURE__*/React.createElement("div", {
45
+ const hasHelper = typeof helperText !== 'undefined' && helperText !== null;
46
+ const helperId = !hasHelper ? undefined : `checkbox-helper-text-${checkboxGroupInstanceId}`;
47
+ const helper = hasHelper && /*#__PURE__*/React.createElement("div", {
47
48
  id: helperId,
48
49
  className: `${prefix}--form__helper-text`
49
- }, helperText) : null;
50
+ }, helperText);
50
51
  const wrapperClasses = cx(`${prefix}--form-item`, `${prefix}--checkbox-wrapper`, className, {
51
52
  [`${prefix}--checkbox-wrapper--readonly`]: readOnly,
52
53
  [`${prefix}--checkbox-wrapper--invalid`]: !readOnly && invalid,
@@ -106,6 +107,7 @@ const Checkbox = /*#__PURE__*/React.forwardRef(({
106
107
  className: `${prefix}--checkbox-label`,
107
108
  title: title
108
109
  }, /*#__PURE__*/React.createElement(Text, {
110
+ as: "div",
109
111
  className: innerLabelClasses
110
112
  }, labelText, slug ? normalizedDecorator : decorator ? /*#__PURE__*/React.createElement("div", {
111
113
  className: `${prefix}--checkbox-wrapper-inner--decorator`
@@ -38,11 +38,12 @@ const CheckboxGroup = ({
38
38
  const showWarning = !readOnly && !invalid && warn;
39
39
  const showHelper = !invalid && !warn;
40
40
  const checkboxGroupInstanceId = useId();
41
- const helperId = !helperText ? undefined : `checkbox-group-helper-text-${checkboxGroupInstanceId}`;
42
- const helper = helperText ? /*#__PURE__*/React.createElement("div", {
41
+ const hasHelper = typeof helperText !== 'undefined' && helperText !== null;
42
+ const helperId = !hasHelper ? undefined : `checkbox-group-helper-text-${checkboxGroupInstanceId}`;
43
+ const helper = hasHelper && /*#__PURE__*/React.createElement("div", {
43
44
  id: helperId,
44
45
  className: `${prefix}--form__helper-text`
45
- }, helperText) : null;
46
+ }, helperText);
46
47
  const fieldsetClasses = cx(`${prefix}--checkbox-group`, className, {
47
48
  [`${prefix}--checkbox-group--${orientation}`]: orientation === 'horizontal',
48
49
  [`${prefix}--checkbox-group--readonly`]: readOnly,
@@ -111,7 +111,7 @@ declare namespace CodeSnippet {
111
111
  /**
112
112
  * Specify how the trigger should align with the tooltip
113
113
  */
114
- align: PropTypes.Requireable<string> | PropTypes.Validator<string>;
114
+ align: PropTypes.Requireable<import("@floating-ui/utils").Placement | "top-left" | "top-right" | "bottom-left" | "bottom-right" | "left-bottom" | "left-top" | "right-bottom" | "right-top"> | PropTypes.Validator<import("@floating-ui/utils").Placement | "top-left" | "top-right" | "bottom-left" | "bottom-right" | "left-bottom" | "left-top" | "right-bottom" | "right-top">;
115
115
  /**
116
116
  * Specify a label to be read by screen readers on the containing textbox
117
117
  * node
@@ -5,7 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  import { UseComboboxProps, UseComboboxActions } from 'downshift';
8
- import { type ComponentType, type InputHTMLAttributes, type MouseEvent, type PropsWithChildren, type ReactElement, type ReactNode, type RefAttributes, type RefObject } from 'react';
8
+ import { type InputHTMLAttributes, type MouseEvent, type PropsWithChildren, type ReactElement, type ReactNode, type RefAttributes, type RefObject } from 'react';
9
9
  import { type ListBoxMenuIconTranslationKey, type ListBoxSelectionTranslationKey, type ListBoxSize } from '../ListBox';
10
10
  import type { TranslateWithId } from '../../types/common';
11
11
  type ExcludedAttributes = 'id' | 'onChange' | 'onClick' | 'type' | 'size';
@@ -98,10 +98,9 @@ export interface ComboBoxProps<ItemType> extends Omit<InputHTMLAttributes<HTMLIn
98
98
  */
99
99
  invalidText?: ReactNode;
100
100
  /**
101
- * Optional function to render items as custom components instead of strings.
102
- * Defaults to null and is overridden by a getter
101
+ * Renders an item as a custom React node instead of a string.
103
102
  */
104
- itemToElement?: ComponentType<ItemType> | null;
103
+ itemToElement?: ((item: ItemType) => ReactNode) | null;
105
104
  /**
106
105
  * Helper function passed to downshift that allows the library to render a
107
106
  * given item to a string label. By default, it extracts the `label` field
@@ -23,6 +23,7 @@ import { useId } from '../../internal/useId.js';
23
23
  import { mergeRefs } from '../../tools/mergeRefs.js';
24
24
  import { deprecate } from '../../prop-types/deprecate.js';
25
25
  import { usePrefix } from '../../internal/usePrefix.js';
26
+ import { useNormalizedInputProps } from '../../internal/useNormalizedInputProps.js';
26
27
  import '../FluidForm/FluidForm.js';
27
28
  import { FormContext } from '../FluidForm/FormContext.js';
28
29
  import { useFloating, autoUpdate, flip, hide } from '@floating-ui/react';
@@ -247,8 +248,7 @@ const ComboBox = /*#__PURE__*/forwardRef((props, ref) => {
247
248
  useEffect(() => {
248
249
  if (prevInputValue.current !== inputValue) {
249
250
  prevInputValue.current = inputValue;
250
- // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- https://github.com/carbon-design-system/carbon/issues/20452
251
- onInputChange && onInputChange(inputValue);
251
+ onInputChange?.(inputValue);
252
252
  }
253
253
  // eslint-disable-next-line react-hooks/exhaustive-deps -- https://github.com/carbon-design-system/carbon/issues/20452
254
254
  }, [inputValue]);
@@ -423,11 +423,19 @@ const ComboBox = /*#__PURE__*/forwardRef((props, ref) => {
423
423
  event?.persist?.();
424
424
  }
425
425
  };
426
- const showWarning = !invalid && warn;
426
+ const normalizedProps = useNormalizedInputProps({
427
+ id,
428
+ readOnly,
429
+ disabled: disabled || false,
430
+ invalid: invalid || false,
431
+ invalidText,
432
+ warn: warn || false,
433
+ warnText
434
+ });
427
435
  const className = cx(`${prefix}--combo-box`, {
428
436
  [`${prefix}--combo-box--invalid--focused`]: invalid && isFocused,
429
437
  [`${prefix}--list-box--up`]: direction === 'top',
430
- [`${prefix}--combo-box--warning`]: showWarning,
438
+ [`${prefix}--combo-box--warning`]: normalizedProps.warn,
431
439
  [`${prefix}--combo-box--readonly`]: readOnly,
432
440
  [`${prefix}--autoalign`]: enableFloatingStyles
433
441
  });
@@ -450,9 +458,6 @@ const ComboBox = /*#__PURE__*/forwardRef((props, ref) => {
450
458
  [`${prefix}--combo-box--input--focus`]: isFocused
451
459
  });
452
460
 
453
- // needs to be Capitalized for react to render it correctly
454
- const ItemToElement = itemToElement;
455
-
456
461
  // AILabel always size `mini`
457
462
  const candidate = slug ?? decorator;
458
463
  const candidateIsAILabel = isComponentElement(candidate, AILabel);
@@ -600,7 +605,7 @@ const ComboBox = /*#__PURE__*/forwardRef((props, ref) => {
600
605
  // The input should be described by the appropriate message text id
601
606
  // when both the message is supplied *and* when the component is in
602
607
  // the matching state (invalid, warn, etc).
603
- const ariaDescribedBy = invalid && invalidText && invalidTextId || warn && warnText && warnTextId || helperText && !isFluid && helperTextId || undefined;
608
+ const ariaDescribedBy = normalizedProps.invalid && invalidText && invalidTextId || normalizedProps.warn && warnText && warnTextId || helperText && !isFluid && helperTextId || undefined;
604
609
 
605
610
  // Memoize the value of getMenuProps to avoid an infinite loop
606
611
  const menuProps = useMemo(() => getMenuProps({
@@ -628,13 +633,13 @@ const ComboBox = /*#__PURE__*/forwardRef((props, ref) => {
628
633
  onBlur: handleFocus,
629
634
  className: className,
630
635
  disabled: disabled,
631
- invalid: invalid,
636
+ invalid: normalizedProps.invalid,
632
637
  invalidText: invalidText,
633
638
  invalidTextId: invalidTextId,
634
639
  isOpen: isOpen,
635
640
  light: light,
636
641
  size: size,
637
- warn: warn,
642
+ warn: normalizedProps.warn,
638
643
  ref: enableFloatingStyles ? refs.setReference : null,
639
644
  warnText: warnText,
640
645
  warnTextId: warnTextId
@@ -736,9 +741,9 @@ const ComboBox = /*#__PURE__*/forwardRef((props, ref) => {
736
741
  }), rest, readOnlyEventHandlers, {
737
742
  readOnly: readOnly,
738
743
  "aria-describedby": ariaDescribedBy
739
- })), invalid && /*#__PURE__*/React.createElement(WarningFilled, {
744
+ })), normalizedProps.invalid && /*#__PURE__*/React.createElement(WarningFilled, {
740
745
  className: `${prefix}--list-box__invalid-icon`
741
- }), showWarning && /*#__PURE__*/React.createElement(WarningAltFilled, {
746
+ }), normalizedProps.warn && /*#__PURE__*/React.createElement(WarningAltFilled, {
742
747
  className: `${prefix}--list-box__invalid-icon ${prefix}--list-box__invalid-icon--warning`
743
748
  }), inputValue && /*#__PURE__*/React.createElement(ListBoxSelection, {
744
749
  clearSelection: () => {
@@ -784,12 +789,10 @@ const ComboBox = /*#__PURE__*/forwardRef((props, ref) => {
784
789
  isHighlighted: highlightedIndex === index,
785
790
  title: title,
786
791
  disabled: disabled
787
- }, modifiedItemProps), ItemToElement ? /*#__PURE__*/React.createElement(ItemToElement, _extends({
788
- key: itemProps.id
789
- }, item)) : itemToString(item), isEqual(currentSelectedItem, item) && /*#__PURE__*/React.createElement(Checkmark, {
792
+ }, modifiedItemProps), itemToElement ? itemToElement(item) : itemToString(item), isEqual(currentSelectedItem, item) && /*#__PURE__*/React.createElement(Checkmark, {
790
793
  className: `${prefix}--list-box__menu-item__selected-icon`
791
794
  }));
792
- }) : null)), helperText && !invalid && !warn && !isFluid && /*#__PURE__*/React.createElement(Text, {
795
+ }) : null)), helperText && !normalizedProps.invalid && !normalizedProps.warn && !isFluid && /*#__PURE__*/React.createElement(Text, {
793
796
  as: "div",
794
797
  id: helperTextId,
795
798
  className: helperClasses
@@ -882,8 +885,7 @@ ComboBox.propTypes = {
882
885
  */
883
886
  invalidText: PropTypes.node,
884
887
  /**
885
- * Optional function to render items as custom components instead of strings.
886
- * Defaults to null and is overridden by a getter
888
+ * Renders an item as a custom React node instead of a string.
887
889
  */
888
890
  itemToElement: PropTypes.func,
889
891
  /**
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright IBM Corp. 2023, 2025
2
+ * Copyright IBM Corp. 2023, 2026
3
3
  *
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,7 +6,7 @@
6
6
  */
7
7
 
8
8
  import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
9
- import React, { useRef, useLayoutEffect } from 'react';
9
+ import React, { useRef } from 'react';
10
10
  import PropTypes from 'prop-types';
11
11
  import cx from 'classnames';
12
12
  import { ChevronDown } from '@carbon/icons-react';
@@ -18,6 +18,7 @@ import '../Menu/MenuItem.js';
18
18
  import { useAttachedMenu } from '../../internal/useAttachedMenu.js';
19
19
  import { useId } from '../../internal/useId.js';
20
20
  import { usePrefix } from '../../internal/usePrefix.js';
21
+ import useIsomorphicEffect from '../../internal/useIsomorphicEffect.js';
21
22
  import { flip, hide, size, useFloating, autoUpdate } from '@floating-ui/react';
22
23
  import { useFeatureFlag } from '../FeatureFlags/index.js';
23
24
  import { mergeRefs } from '../../tools/mergeRefs.js';
@@ -94,7 +95,7 @@ const ComboButton = /*#__PURE__*/React.forwardRef(function ComboButton({
94
95
  handleMousedown: handleTriggerMousedown,
95
96
  handleClose
96
97
  } = useAttachedMenu(containerRef);
97
- useLayoutEffect(() => {
98
+ useIsomorphicEffect(() => {
98
99
  const updatedFloatingStyles = {
99
100
  ...floatingStyles,
100
101
  visibility: middlewareData.hide?.referenceHidden ? 'hidden' : 'visible'
@@ -6,9 +6,8 @@
6
6
  */
7
7
 
8
8
  import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
9
- import React, { useRef, useContext, useEffect, Children, cloneElement } from 'react';
9
+ import React, { useRef, useContext, useEffect, cloneElement, Children } from 'react';
10
10
  import { useResizeObserver } from '../../internal/useResizeObserver.js';
11
- import { isElement } from 'react-is';
12
11
  import PropTypes from 'prop-types';
13
12
  import { Layer } from '../Layer/index.js';
14
13
  import { ModalHeader } from './ModalHeader.js';
@@ -259,29 +258,25 @@ const ComposedModalDialog = /*#__PURE__*/React.forwardRef(function ComposedModal
259
258
  const containerClass = cx(`${prefix}--modal-container`, size && `${prefix}--modal-container--${size}`, isFullWidth && `${prefix}--modal-container--full-width`, containerClassName);
260
259
 
261
260
  // Generate aria-label based on Modal Header label if one is not provided (L253)
261
+ //
262
+ // TODO: Confirm whether `ModalHeader` `label` should allow `ReactNode`. If
263
+ // so, define how to derive a string for `aria-label`.
262
264
  let generatedAriaLabel;
263
265
  const childrenWithProps = React.Children.toArray(children).map(child => {
264
- switch (true) {
265
- case isElement(child) && child.type === /*#__PURE__*/React.createElement(ModalHeader).type:
266
- {
267
- const el = child;
268
- generatedAriaLabel = el.props.label;
269
- return /*#__PURE__*/React.cloneElement(el, {
270
- closeModal
271
- });
272
- }
273
- case isElement(child) && child.type === /*#__PURE__*/React.createElement(ModalFooter).type:
274
- {
275
- const el = child;
276
- return /*#__PURE__*/React.cloneElement(el, {
277
- closeModal,
278
- inputref: button,
279
- danger
280
- });
281
- }
282
- default:
283
- return child;
266
+ if (isComponentElement(child, ModalHeader)) {
267
+ generatedAriaLabel = child.props.label;
268
+ return /*#__PURE__*/cloneElement(child, {
269
+ closeModal
270
+ });
271
+ }
272
+ if (isComponentElement(child, ModalFooter)) {
273
+ return /*#__PURE__*/cloneElement(child, {
274
+ closeModal,
275
+ inputref: button,
276
+ danger
277
+ });
284
278
  }
279
+ return child;
285
280
  });
286
281
 
287
282
  // Modals without a footer are considered passive and carry limitations as
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright IBM Corp. 2016, 2023
2
+ * Copyright IBM Corp. 2016, 2026
3
3
  *
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.
@@ -40,7 +40,7 @@ export interface ModalHeaderProps extends DivProps {
40
40
  /**
41
41
  * Specify an optional label to be displayed
42
42
  */
43
- label?: ReactNode;
43
+ label?: string;
44
44
  /**
45
45
  * Specify an optional className to be applied to the modal header label
46
46
  */
@@ -94,7 +94,7 @@ ModalHeader.propTypes = {
94
94
  /**
95
95
  * Specify an optional label to be displayed
96
96
  */
97
- label: PropTypes.node,
97
+ label: PropTypes.string,
98
98
  /**
99
99
  * Specify an optional className to be applied to the modal header label
100
100
  */
@@ -50,7 +50,7 @@ declare namespace Copy {
50
50
  /**
51
51
  * Specify how the trigger should align with the tooltip
52
52
  */
53
- align: PropTypes.Requireable<string> | PropTypes.Validator<string>;
53
+ align: PropTypes.Requireable<import("@floating-ui/utils").Placement | "top-left" | "top-right" | "bottom-left" | "bottom-right" | "left-bottom" | "left-top" | "right-bottom" | "right-top"> | PropTypes.Validator<import("@floating-ui/utils").Placement | "top-left" | "top-right" | "bottom-left" | "bottom-right" | "left-bottom" | "left-top" | "right-bottom" | "right-top">;
54
54
  /**
55
55
  * **Experimental**: Will attempt to automatically align the tooltip. Requires
56
56
  * React v17+
@@ -51,7 +51,7 @@ declare namespace CopyButton {
51
51
  /**
52
52
  * Specify how the trigger should align with the tooltip
53
53
  */
54
- align: PropTypes.Requireable<string> | PropTypes.Validator<string>;
54
+ align: PropTypes.Requireable<import("@floating-ui/utils").Placement | "top-left" | "top-right" | "bottom-left" | "bottom-right" | "left-bottom" | "left-top" | "right-bottom" | "right-top"> | PropTypes.Validator<import("@floating-ui/utils").Placement | "top-left" | "top-right" | "bottom-left" | "bottom-right" | "left-bottom" | "left-top" | "right-bottom" | "right-top">;
55
55
  /**
56
56
  * **Experimental**: Will attempt to automatically align the tooltip. Requires
57
57
  * React v17+
@@ -51,6 +51,7 @@ export interface DataTableHeader {
51
51
  header: ReactNode;
52
52
  slug?: ReactElement;
53
53
  decorator?: ReactElement;
54
+ isSortable?: boolean;
54
55
  }
55
56
  export interface DataTableRenderProps<RowType, ColTypes extends any[]> {
56
57
  /**
@@ -435,6 +436,7 @@ export declare const DataTable: {
435
436
  headers: PropTypes.Validator<(PropTypes.InferProps<{
436
437
  key: PropTypes.Validator<string>;
437
438
  header: PropTypes.Validator<NonNullable<PropTypes.ReactNodeLike>>;
439
+ isSortable: PropTypes.Requireable<boolean>;
438
440
  }> | null | undefined)[]>;
439
441
  /**
440
442
  * Specify whether the table should be able to be sorted by its headers
@@ -96,7 +96,7 @@ const DataTable = props => {
96
96
  render,
97
97
  translateWithId: t = defaultTranslateWithId,
98
98
  size,
99
- isSortable: isSortableProp,
99
+ isSortable,
100
100
  useZebraStyles,
101
101
  useStaticWidth,
102
102
  stickyHeader,
@@ -135,7 +135,7 @@ const DataTable = props => {
135
135
  const getHeaderProps = ({
136
136
  header,
137
137
  onClick,
138
- isSortable = isSortableProp,
138
+ isSortable: headerIsSortable,
139
139
  ...rest
140
140
  }) => {
141
141
  const {
@@ -151,7 +151,7 @@ const DataTable = props => {
151
151
  ...rest,
152
152
  key,
153
153
  sortDirection,
154
- isSortable,
154
+ isSortable: headerIsSortable ?? header.isSortable ?? isSortable,
155
155
  isSortHeader: sortHeaderKey === key,
156
156
  slug,
157
157
  decorator,
@@ -310,7 +310,7 @@ const DataTable = props => {
310
310
  return {
311
311
  useZebraStyles,
312
312
  size: size ?? 'lg',
313
- isSortable: isSortableProp,
313
+ isSortable,
314
314
  useStaticWidth,
315
315
  stickyHeader,
316
316
  overflowMenuOnHover: overflowMenuOnHover ?? false,
@@ -600,7 +600,8 @@ DataTable.propTypes = {
600
600
  */
601
601
  headers: PropTypes.arrayOf(PropTypes.shape({
602
602
  key: PropTypes.string.isRequired,
603
- header: PropTypes.node.isRequired
603
+ header: PropTypes.node.isRequired,
604
+ isSortable: PropTypes.bool
604
605
  })).isRequired,
605
606
  /**
606
607
  * Specify whether the table should be able to be sorted by its headers
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright IBM Corp. 2016, 2025
2
+ * Copyright IBM Corp. 2016, 2026
3
3
  *
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.
@@ -70,12 +70,18 @@ const Table = ({
70
70
  [`${prefix}--data-table--visible-overflow-menu`]: !overflowMenuOnHover
71
71
  });
72
72
  const toggleTableBodyAlignmentClass = useCallback((alignTop = false) => {
73
- // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- https://github.com/carbon-design-system/carbon/issues/20452
74
- alignTop ? tableRef.current?.classList.add(`${prefix}--data-table--top-aligned-body`) : tableRef.current?.classList.remove(`${prefix}--data-table--top-aligned-body`);
73
+ if (alignTop) {
74
+ tableRef.current?.classList.add(`${prefix}--data-table--top-aligned-body`);
75
+ } else {
76
+ tableRef.current?.classList.remove(`${prefix}--data-table--top-aligned-body`);
77
+ }
75
78
  }, [prefix]);
76
79
  const toggleTableHeaderAlignmentClass = useCallback((alignTop = false) => {
77
- // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- https://github.com/carbon-design-system/carbon/issues/20452
78
- alignTop ? tableRef.current?.classList.add(`${prefix}--data-table--top-aligned-header`) : tableRef.current?.classList.remove(`${prefix}--data-table--top-aligned-header`);
80
+ if (alignTop) {
81
+ tableRef.current?.classList.add(`${prefix}--data-table--top-aligned-header`);
82
+ } else {
83
+ tableRef.current?.classList.remove(`${prefix}--data-table--top-aligned-header`);
84
+ }
79
85
  }, [prefix]);
80
86
  const setTableAlignment = useCallback(() => {
81
87
  if (experimentalAutoAlign) {
@@ -43,7 +43,8 @@ export declare const getNextSortDirection: (prevHeader: string, currentHeader: s
43
43
  * @param state - Current table state.
44
44
  * @param key - Header key to sort by.
45
45
  */
46
- export declare const getNextSortState: <ColTypes extends any[]>(props: Props, state: State<ColTypes>, { key }: {
46
+ export declare const getNextSortState: <ColTypes extends any[]>(// eslint-disable-line @typescript-eslint/no-explicit-any -- https://github.com/carbon-design-system/carbon/issues/20452
47
+ props: Props, state: State<ColTypes>, { key }: {
47
48
  key: string;
48
49
  }) => Pick<State<ColTypes>, "sortHeaderKey" | "sortDirection" | "rowIds">;
49
50
  /**
@@ -54,5 +55,6 @@ export declare const getNextSortState: <ColTypes extends any[]>(props: Props, st
54
55
  * @param key - Header key to sort by.
55
56
  * @param sortDirection - Sort direction to apply.
56
57
  */
57
- export declare const getSortedState: <ColTypes extends any[]>({ locale, sortRow }: Props, { rowIds, cellsById, initialRowOrder }: State<ColTypes>, key: string, sortDirection: DataTableSortState) => Pick<State<ColTypes>, "rowIds" | "sortDirection" | "sortHeaderKey">;
58
+ export declare const getSortedState: <ColTypes extends any[]>(// eslint-disable-line @typescript-eslint/no-explicit-any -- https://github.com/carbon-design-system/carbon/issues/20452
59
+ { locale, sortRow }: Props, { rowIds, cellsById, initialRowOrder }: State<ColTypes>, key: string, sortDirection: DataTableSortState) => Pick<State<ColTypes>, "rowIds" | "sortDirection" | "sortHeaderKey">;
58
60
  export {};
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright IBM Corp. 2022, 2025
2
+ * Copyright IBM Corp. 2022, 2026
3
3
  *
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.
@@ -78,10 +78,9 @@ export interface DropdownProps<ItemType> extends Omit<HTMLAttributes<HTMLDivElem
78
78
  */
79
79
  invalidText?: ReactNode;
80
80
  /**
81
- * Function to render items as custom components instead of strings.
82
- * Defaults to null and is overridden by a getter
81
+ * Renders an item as a custom React node instead of a string.
83
82
  */
84
- itemToElement?: React.JSXElementConstructor<ItemType> | null;
83
+ itemToElement?: ((item: ItemType) => NonNullable<ReactNode>) | null;
85
84
  /**
86
85
  * Helper function passed to downshift that allows the library to render a
87
86
  * given item to a string label. By default, it extracts the `label` field
@@ -252,9 +252,6 @@ const Dropdown = /*#__PURE__*/React.forwardRef(({
252
252
  [`${prefix}--list-box__wrapper--slug`]: slug,
253
253
  [`${prefix}--list-box__wrapper--decorator`]: decorator
254
254
  });
255
-
256
- // needs to be Capitalized for react to render it correctly
257
- const ItemToElement = itemToElement;
258
255
  const toggleButtonProps = getToggleButtonProps({
259
256
  'aria-label': ariaLabel || deprecatedAriaLabel
260
257
  });
@@ -270,10 +267,20 @@ const Dropdown = /*#__PURE__*/React.forwardRef(({
270
267
  const [currTimer, setCurrTimer] = useState();
271
268
  const [isTyping, setIsTyping] = useState(false);
272
269
  const onKeyDownHandler = useCallback(evt => {
273
- if (evt.code !== 'Space' || !['ArrowDown', 'ArrowUp', ' ', 'Enter'].includes(evt.key)) {
270
+ const navigationKeys = ['ArrowDown', 'ArrowUp', ' ', 'Enter'];
271
+
272
+ // If the key is not a navigation key, the user is typing
273
+ if (!navigationKeys.includes(evt.key)) {
274
274
  setIsTyping(true);
275
- }
276
- if (isTyping && evt.code === 'Space' || !['ArrowDown', 'ArrowUp', ' ', 'Enter'].includes(evt.key)) {
275
+ // Reset the timer for typing timeout
276
+ if (currTimer) {
277
+ clearTimeout(currTimer);
278
+ }
279
+ setCurrTimer(setTimeout(() => {
280
+ setIsTyping(false);
281
+ }, 3000));
282
+ } else if (isTyping && evt.key === ' ') {
283
+ // If user is typing and presses space, reset the timer
277
284
  if (currTimer) {
278
285
  clearTimeout(currTimer);
279
286
  }
@@ -377,21 +384,18 @@ const Dropdown = /*#__PURE__*/React.forwardRef(({
377
384
  })), slug ? normalizedDecorator : decorator ? /*#__PURE__*/React.createElement("div", {
378
385
  className: `${prefix}--list-box__inner-wrapper--decorator`
379
386
  }, normalizedDecorator) : '', /*#__PURE__*/React.createElement(ListBox.Menu, menuProps, isOpen && items.map((item, index) => {
380
- const isObject = item !== null && typeof item === 'object';
381
387
  const itemProps = getItemProps({
382
388
  item,
383
389
  index
384
390
  });
385
- const title = isObject && 'text' in item && itemToElement ? item.text : itemToString(item);
391
+ const title = itemToString(item);
386
392
  return /*#__PURE__*/React.createElement(ListBox.MenuItem, _extends({
387
393
  key: itemProps.id,
388
394
  isActive: selectedItem === item,
389
395
  isHighlighted: highlightedIndex === index,
390
396
  title: title,
391
397
  disabled: itemProps['aria-disabled']
392
- }, itemProps), typeof item === 'object' && ItemToElement !== undefined && ItemToElement !== null ? /*#__PURE__*/React.createElement(ItemToElement, _extends({
393
- key: itemProps.id
394
- }, item)) : itemToString(item), selectedItem === item && /*#__PURE__*/React.createElement(Checkmark, {
398
+ }, itemProps), itemToElement ? itemToElement(item) : itemToString(item), selectedItem === item && /*#__PURE__*/React.createElement(Checkmark, {
395
399
  className: `${prefix}--list-box__menu-item__selected-icon`
396
400
  }));
397
401
  }))), !inline && !isFluid && !normalizedProps.validation && helper, !inline && !isFluid && normalizedProps.validation);
@@ -471,8 +475,7 @@ Dropdown.propTypes = {
471
475
  */
472
476
  invalidText: PropTypes.node,
473
477
  /**
474
- * Function to render items as custom components instead of strings.
475
- * Defaults to null and is overridden by a getter
478
+ * Renders an item as a custom React node instead of a string.
476
479
  */
477
480
  itemToElement: PropTypes.func,
478
481
  /**
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright IBM Corp. 2016, 2025
2
+ * Copyright IBM Corp. 2016, 2026
3
3
  *
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.
@@ -8,13 +8,14 @@
8
8
  import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
9
9
  import cx from 'classnames';
10
10
  import PropTypes from 'prop-types';
11
- import React, { useRef, useState, useLayoutEffect } from 'react';
11
+ import React, { useRef, useState } from 'react';
12
12
  import Filename from './Filename.js';
13
13
  import { Enter, Space } from '../../internal/keyboard/keys.js';
14
14
  import { matches } from '../../internal/keyboard/match.js';
15
15
  import { useId } from '../../internal/useId.js';
16
16
  import { usePrefix } from '../../internal/usePrefix.js';
17
17
  import { noopFn } from '../../internal/noopFn.js';
18
+ import useIsomorphicEffect from '../../internal/useIsomorphicEffect.js';
18
19
  import { Text } from '../Text/Text.js';
19
20
  import '../Text/TextDirection.js';
20
21
  import '../Tooltip/DefinitionTooltip.js';
@@ -58,7 +59,7 @@ function FileUploaderItem({
58
59
  setIsEllipsisApplied(isActive);
59
60
  return isActive;
60
61
  };
61
- useLayoutEffect(() => {
62
+ useIsomorphicEffect(() => {
62
63
  isEllipsisActive(textRef.current);
63
64
  }, [prefix, name]);
64
65
  return /*#__PURE__*/React.createElement("span", _extends({
@@ -1,10 +1,10 @@
1
1
  /**
2
- * Copyright IBM Corp. 2022, 2025
2
+ * Copyright IBM Corp. 2022, 2026
3
3
  *
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 React, { ComponentType, type ComponentProps } from 'react';
7
+ import React, { type ComponentProps } from 'react';
8
8
  import ComboBox from '../ComboBox';
9
9
  import { ComboBoxProps } from '../ComboBox/ComboBox';
10
10
  type ItemToStringHandler<ItemType> = (item: ItemType | null) => string;
@@ -46,11 +46,6 @@ export interface FluidComboBoxProps<ItemType> extends ComboBoxProps<ItemType>, P
46
46
  * Specify if the `FluidComboBox` should render its menu items in condensed mode
47
47
  */
48
48
  isCondensed?: boolean;
49
- /**
50
- * Function to render items as custom components instead of strings.
51
- * Defaults to null and is overridden by a getter
52
- */
53
- itemToElement?: ComponentType<ItemType> | null;
54
49
  /**
55
50
  * Helper function passed to downshift that allows the library to render a
56
51
  * given item to a string label. By default, it extracts the `label` field
@@ -66,8 +66,7 @@ FluidComboBox.propTypes = {
66
66
  */
67
67
  isCondensed: PropTypes.bool,
68
68
  /**
69
- * Function to render items as custom components instead of strings.
70
- * Defaults to null and is overridden by a getter
69
+ * Renders an item as a custom React node instead of a string.
71
70
  */
72
71
  itemToElement: PropTypes.func,
73
72
  /**