@carbon/react 1.100.0 → 1.101.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 (134) hide show
  1. package/.playwright/INTERNAL_AVT_REPORT_DO_NOT_USE.json +953 -953
  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.js +25 -12
  8. package/es/components/ComboButton/index.d.ts +1 -1
  9. package/es/components/ComboButton/index.js +3 -2
  10. package/es/components/ComposedModal/ComposedModal.js +17 -22
  11. package/es/components/ComposedModal/ModalHeader.d.ts +2 -2
  12. package/es/components/ComposedModal/ModalHeader.js +1 -1
  13. package/es/components/Copy/Copy.d.ts +1 -1
  14. package/es/components/CopyButton/CopyButton.d.ts +1 -1
  15. package/es/components/DataTable/DataTable.d.ts +2 -0
  16. package/es/components/DataTable/DataTable.js +6 -5
  17. package/es/components/DataTable/Table.d.ts +1 -1
  18. package/es/components/DataTable/Table.js +10 -4
  19. package/es/components/DataTable/state/sorting.d.ts +4 -2
  20. package/es/components/Dropdown/Dropdown.js +4 -4
  21. package/es/components/ExpandableSearch/ExpandableSearch.js +1 -1
  22. package/es/components/FileUploader/FileUploaderItem.d.ts +1 -1
  23. package/es/components/FileUploader/FileUploaderItem.js +3 -2
  24. package/es/components/ListBox/test-helpers.d.ts +71 -0
  25. package/es/components/Menu/Menu.js +8 -4
  26. package/es/components/Menu/MenuItem.d.ts +5 -1
  27. package/es/components/Menu/MenuItem.js +11 -1
  28. package/es/components/MenuButton/index.d.ts +1 -1
  29. package/es/components/MenuButton/index.js +3 -2
  30. package/es/components/MultiSelect/FilterableMultiSelect.d.ts +1 -1
  31. package/es/components/MultiSelect/FilterableMultiSelect.js +8 -6
  32. package/es/components/MultiSelect/MultiSelect.js +8 -4
  33. package/es/components/Notification/Notification.js +2 -1
  34. package/es/components/NumberInput/NumberInput.d.ts +1 -1
  35. package/es/components/NumberInput/NumberInput.js +6 -5
  36. package/es/components/OverflowMenu/OverflowMenu.d.ts +1 -0
  37. package/es/components/OverflowMenu/OverflowMenu.js +8 -4
  38. package/es/components/PageHeader/PageHeader.d.ts +1 -1
  39. package/es/components/PageHeader/PageHeader.js +5 -5
  40. package/es/components/Popover/index.js +1 -1
  41. package/es/components/ProgressIndicator/ProgressIndicator.d.ts +1 -1
  42. package/es/components/ProgressIndicator/ProgressIndicator.js +1 -1
  43. package/es/components/RadioButtonGroup/RadioButtonGroup.js +4 -3
  44. package/es/components/Search/Search.d.ts +1 -1
  45. package/es/components/Search/Search.js +1 -1
  46. package/es/components/Select/Select.js +3 -2
  47. package/es/components/StructuredList/StructuredList.d.ts +1 -1
  48. package/es/components/StructuredList/StructuredList.js +2 -4
  49. package/es/components/Tabs/Tabs.d.ts +2 -2
  50. package/es/components/Tabs/Tabs.js +20 -26
  51. package/es/components/Tag/DismissibleTag.js +3 -2
  52. package/es/components/Tag/OperationalTag.js +3 -2
  53. package/es/components/Tag/SelectableTag.js +3 -2
  54. package/es/components/Tag/Tag.js +3 -2
  55. package/es/components/TextArea/TextArea.d.ts +2 -2
  56. package/es/components/TextArea/TextArea.js +7 -6
  57. package/es/components/TextInput/ControlledPasswordInput.js +7 -6
  58. package/es/components/TextInput/PasswordInput.js +5 -6
  59. package/es/components/TextInput/TextInput.js +4 -4
  60. package/es/components/TimePicker/TimePicker.js +2 -2
  61. package/es/components/Tooltip/DefinitionTooltip.d.ts +1 -1
  62. package/es/components/Tooltip/DefinitionTooltip.js +3 -2
  63. package/es/internal/useId.js +3 -4
  64. package/es/internal/usePresence.js +3 -2
  65. package/es/internal/useResizeObserver.d.ts +1 -1
  66. package/es/internal/useResizeObserver.js +5 -7
  67. package/es/tools/events.d.ts +1 -1
  68. package/lib/components/AILabel/index.d.ts +1 -1
  69. package/lib/components/AILabel/index.js +1 -12
  70. package/lib/components/Checkbox/Checkbox.js +5 -3
  71. package/lib/components/CheckboxGroup/CheckboxGroup.js +4 -3
  72. package/lib/components/CodeSnippet/CodeSnippet.d.ts +1 -1
  73. package/lib/components/ComboBox/ComboBox.js +25 -12
  74. package/lib/components/ComboButton/index.d.ts +1 -1
  75. package/lib/components/ComboButton/index.js +2 -1
  76. package/lib/components/ComposedModal/ComposedModal.js +16 -21
  77. package/lib/components/ComposedModal/ModalHeader.d.ts +2 -2
  78. package/lib/components/ComposedModal/ModalHeader.js +1 -1
  79. package/lib/components/Copy/Copy.d.ts +1 -1
  80. package/lib/components/CopyButton/CopyButton.d.ts +1 -1
  81. package/lib/components/DataTable/DataTable.d.ts +2 -0
  82. package/lib/components/DataTable/DataTable.js +6 -5
  83. package/lib/components/DataTable/Table.d.ts +1 -1
  84. package/lib/components/DataTable/Table.js +10 -4
  85. package/lib/components/DataTable/state/sorting.d.ts +4 -2
  86. package/lib/components/Dropdown/Dropdown.js +4 -4
  87. package/lib/components/ExpandableSearch/ExpandableSearch.js +1 -1
  88. package/lib/components/FileUploader/FileUploaderItem.d.ts +1 -1
  89. package/lib/components/FileUploader/FileUploaderItem.js +2 -1
  90. package/lib/components/ListBox/test-helpers.d.ts +71 -0
  91. package/lib/components/Menu/Menu.js +7 -3
  92. package/lib/components/Menu/MenuItem.d.ts +5 -1
  93. package/lib/components/Menu/MenuItem.js +11 -1
  94. package/lib/components/MenuButton/index.d.ts +1 -1
  95. package/lib/components/MenuButton/index.js +2 -1
  96. package/lib/components/MultiSelect/FilterableMultiSelect.d.ts +1 -1
  97. package/lib/components/MultiSelect/FilterableMultiSelect.js +7 -5
  98. package/lib/components/MultiSelect/MultiSelect.js +7 -3
  99. package/lib/components/Notification/Notification.js +2 -1
  100. package/lib/components/NumberInput/NumberInput.d.ts +1 -1
  101. package/lib/components/NumberInput/NumberInput.js +6 -5
  102. package/lib/components/OverflowMenu/OverflowMenu.d.ts +1 -0
  103. package/lib/components/OverflowMenu/OverflowMenu.js +7 -3
  104. package/lib/components/PageHeader/PageHeader.d.ts +1 -1
  105. package/lib/components/PageHeader/PageHeader.js +4 -4
  106. package/lib/components/Popover/index.js +1 -1
  107. package/lib/components/ProgressIndicator/ProgressIndicator.d.ts +1 -1
  108. package/lib/components/ProgressIndicator/ProgressIndicator.js +1 -1
  109. package/lib/components/RadioButtonGroup/RadioButtonGroup.js +4 -3
  110. package/lib/components/Search/Search.d.ts +1 -1
  111. package/lib/components/Search/Search.js +1 -1
  112. package/lib/components/Select/Select.js +3 -2
  113. package/lib/components/StructuredList/StructuredList.d.ts +1 -1
  114. package/lib/components/StructuredList/StructuredList.js +2 -4
  115. package/lib/components/Tabs/Tabs.d.ts +2 -2
  116. package/lib/components/Tabs/Tabs.js +15 -21
  117. package/lib/components/Tag/DismissibleTag.js +2 -1
  118. package/lib/components/Tag/OperationalTag.js +2 -1
  119. package/lib/components/Tag/SelectableTag.js +2 -1
  120. package/lib/components/Tag/Tag.js +2 -1
  121. package/lib/components/TextArea/TextArea.d.ts +2 -2
  122. package/lib/components/TextArea/TextArea.js +7 -6
  123. package/lib/components/TextInput/ControlledPasswordInput.js +7 -6
  124. package/lib/components/TextInput/PasswordInput.js +5 -6
  125. package/lib/components/TextInput/TextInput.js +4 -4
  126. package/lib/components/TimePicker/TimePicker.js +2 -2
  127. package/lib/components/Tooltip/DefinitionTooltip.d.ts +1 -1
  128. package/lib/components/Tooltip/DefinitionTooltip.js +3 -2
  129. package/lib/internal/useId.js +2 -3
  130. package/lib/internal/usePresence.js +2 -1
  131. package/lib/internal/useResizeObserver.d.ts +1 -1
  132. package/lib/internal/useResizeObserver.js +4 -6
  133. package/lib/tools/events.d.ts +1 -1
  134. package/package.json +9 -9
@@ -7,7 +7,7 @@
7
7
 
8
8
  import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
9
9
  import PropTypes from 'prop-types';
10
- import React, { forwardRef, useRef, useState, useLayoutEffect } from 'react';
10
+ import React, { forwardRef, useRef, useState } from 'react';
11
11
  import cx from 'classnames';
12
12
  import { useId } from '../../internal/useId.js';
13
13
  import { usePrefix } from '../../internal/usePrefix.js';
@@ -19,6 +19,7 @@ import '../Text/TextDirection.js';
19
19
  import { isEllipsisActive } from './isEllipsisActive.js';
20
20
  import { mergeRefs } from '../../tools/mergeRefs.js';
21
21
  import { useControllableState } from '../../internal/useControllableState.js';
22
+ import useIsomorphicEffect from '../../internal/useIsomorphicEffect.js';
22
23
 
23
24
  // eslint-disable-next-line react/display-name -- https://github.com/carbon-design-system/carbon/issues/20452
24
25
  const SelectableTag = /*#__PURE__*/forwardRef(({
@@ -47,7 +48,7 @@ const SelectableTag = /*#__PURE__*/forwardRef(({
47
48
  [`${prefix}--tag--selectable-selected`]: selectedTag
48
49
  });
49
50
  const [isEllipsisApplied, setIsEllipsisApplied] = useState(false);
50
- useLayoutEffect(() => {
51
+ useIsomorphicEffect(() => {
51
52
  const newElement = tagRef.current?.getElementsByClassName(`${prefix}--tag__label`)[0];
52
53
  setIsEllipsisApplied(isEllipsisActive(newElement));
53
54
  }, [prefix, tagRef]);
@@ -7,7 +7,7 @@
7
7
 
8
8
  import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
9
9
  import PropTypes from 'prop-types';
10
- import React, { useRef, useState, useLayoutEffect, cloneElement } from 'react';
10
+ import React, { useRef, useState, cloneElement } from 'react';
11
11
  import cx from 'classnames';
12
12
  import { Close } from '@carbon/icons-react';
13
13
  import { useId } from '../../internal/useId.js';
@@ -21,6 +21,7 @@ import { isEllipsisActive } from './isEllipsisActive.js';
21
21
  import { useMergedRefs } from '../../internal/useMergedRefs.js';
22
22
  import { AILabel } from '../AILabel/index.js';
23
23
  import { isComponentElement } from '../../internal/utils.js';
24
+ import useIsomorphicEffect from '../../internal/useIsomorphicEffect.js';
24
25
 
25
26
  var _Close;
26
27
  const TYPES = {
@@ -76,7 +77,7 @@ const TagBase = /*#__PURE__*/React.forwardRef(({
76
77
  // eslint-disable-next-line react-hooks/rules-of-hooks -- https://github.com/carbon-design-system/carbon/issues/20452
77
78
  const tagId = id || `tag-${useId()}`;
78
79
  const [isEllipsisApplied, setIsEllipsisApplied] = useState(false);
79
- useLayoutEffect(() => {
80
+ useIsomorphicEffect(() => {
80
81
  const newElement = tagRef.current?.getElementsByClassName(`${prefix}--tag__label`)[0];
81
82
  setIsEllipsisApplied(isEllipsisActive(newElement));
82
83
  }, [prefix, tagRef]);
@@ -1,11 +1,11 @@
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.
6
6
  */
7
7
  import React, { type ReactNode } from 'react';
8
- export interface TextAreaProps extends React.InputHTMLAttributes<HTMLTextAreaElement> {
8
+ export interface TextAreaProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {
9
9
  /**
10
10
  * Provide a custom className that is applied directly to the underlying
11
11
  * `<textarea>` node
@@ -193,24 +193,25 @@ const TextArea = frFn((props, forwardRef) => {
193
193
  const helperTextClasses = cx(`${prefix}--form__helper-text`, {
194
194
  [`${prefix}--form__helper-text--disabled`]: disabled
195
195
  });
196
- const label = labelText ? /*#__PURE__*/React.createElement(Text, {
196
+ const label = typeof labelText !== 'undefined' && labelText !== null && /*#__PURE__*/React.createElement(Text, {
197
197
  as: "label",
198
198
  htmlFor: id,
199
199
  className: labelClasses
200
- }, labelText) : null;
200
+ }, labelText);
201
201
  const counter = enableCounter && maxCount && (counterMode === 'character' || counterMode === 'word') ? /*#__PURE__*/React.createElement(Text, {
202
202
  as: "div",
203
203
  className: counterClasses,
204
204
  "aria-hidden": "true"
205
205
  }, `${textCount}/${maxCount}`) : null;
206
206
  const counterDescriptionId = enableCounter && maxCount ? `${id}-counter-desc` : undefined;
207
- const helperId = !helperText ? undefined : `text-area-helper-text-${textAreaInstanceId}`;
208
- const helper = helperText ? /*#__PURE__*/React.createElement(Text, {
207
+ const hasHelper = typeof helperText !== 'undefined' && helperText !== null;
208
+ const helperId = !hasHelper ? undefined : `text-area-helper-text-${textAreaInstanceId}`;
209
+ const helper = hasHelper && /*#__PURE__*/React.createElement(Text, {
209
210
  as: "div",
210
211
  id: helperId,
211
212
  className: helperTextClasses,
212
213
  ref: helperTextRef
213
- }, helperText) : null;
214
+ }, helperText);
214
215
  const errorId = id + '-error-msg';
215
216
  const error = invalid ? /*#__PURE__*/React.createElement(Text, {
216
217
  as: "div",
@@ -277,7 +278,7 @@ const TextArea = frFn((props, forwardRef) => {
277
278
  }, [ariaAnnouncement, prevAnnouncement, counterMode]);
278
279
  const input = /*#__PURE__*/React.createElement("textarea", _extends({}, other, textareaProps, {
279
280
  placeholder: placeholder,
280
- "aria-readonly": other.readOnly ? true : false,
281
+ "aria-readonly": Boolean(other.readOnly),
281
282
  className: textareaClasses,
282
283
  "aria-invalid": invalid,
283
284
  "aria-describedby": ariaDescribedBy,
@@ -71,10 +71,10 @@ const ControlledPasswordInput = /*#__PURE__*/forwardRef(({
71
71
  const helperTextClasses = cx(`${prefix}--form__helper-text`, {
72
72
  [`${prefix}--form__helper-text--disabled`]: disabled
73
73
  });
74
- const label = labelText ? /*#__PURE__*/React.createElement("label", {
74
+ const label = typeof labelText !== 'undefined' && labelText !== null && /*#__PURE__*/React.createElement("label", {
75
75
  htmlFor: id,
76
76
  className: labelClasses
77
- }, labelText) : null;
77
+ }, labelText);
78
78
  const error = invalid ? /*#__PURE__*/React.createElement("div", {
79
79
  className: `${prefix}--form-requirement`,
80
80
  id: errorId
@@ -89,12 +89,13 @@ const ControlledPasswordInput = /*#__PURE__*/forwardRef(({
89
89
  [`${prefix}--tooltip--${tooltipPosition}`]: tooltipPosition,
90
90
  [`${prefix}--tooltip--align-${tooltipAlignment}`]: tooltipAlignment
91
91
  });
92
- const helperId = !helperText ? undefined : `controlled-password-helper-text-${controlledPasswordInstanceId}`;
92
+ const hasHelper = typeof helperText !== 'undefined' && helperText !== null;
93
+ const helperId = !hasHelper ? undefined : `controlled-password-helper-text-${controlledPasswordInstanceId}`;
93
94
  const input = /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("input", _extends({}, getTextInputProps({
94
95
  invalid,
95
96
  sharedTextInputProps,
96
97
  invalidId: errorId,
97
- hasHelper: !error && helperText ? true : false,
98
+ hasHelper: !error && hasHelper,
98
99
  helperId
99
100
  }), {
100
101
  "data-toggle-password-visibility": type === 'password'
@@ -105,10 +106,10 @@ const ControlledPasswordInput = /*#__PURE__*/forwardRef(({
105
106
  }, /*#__PURE__*/React.createElement("span", {
106
107
  className: `${prefix}--assistive-text`
107
108
  }, passwordIsVisible ? hidePasswordLabel : showPasswordLabel), passwordVisibilityIcon));
108
- const helper = helperText ? /*#__PURE__*/React.createElement("div", {
109
+ const helper = hasHelper && /*#__PURE__*/React.createElement("div", {
109
110
  id: helperId,
110
111
  className: helperTextClasses
111
- }, helperText) : null;
112
+ }, helperText);
112
113
  return /*#__PURE__*/React.createElement("div", {
113
114
  className: `${prefix}--form-item ${prefix}--text-input-wrapper ${prefix}--password-input-wrapper`
114
115
  }, label, /*#__PURE__*/React.createElement("div", {
@@ -61,8 +61,7 @@ const PasswordInput = /*#__PURE__*/forwardRef(({
61
61
  } = useContext(FormContext);
62
62
  const handleTogglePasswordVisibility = event => {
63
63
  setInputType(inputType === 'password' ? 'text' : 'password');
64
- // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- https://github.com/carbon-design-system/carbon/issues/20452
65
- onTogglePasswordVisibility && onTogglePasswordVisibility(event);
64
+ onTogglePasswordVisibility?.(event);
66
65
  };
67
66
  const textInputClasses = cx(`${prefix}--text-input`, `${prefix}--password-input`, className, {
68
67
  [`${prefix}--text-input--light`]: light,
@@ -117,14 +116,14 @@ const PasswordInput = /*#__PURE__*/forwardRef(({
117
116
  [`${prefix}--text-input__invalid-icon`]: normalizedProps.invalid || normalizedProps.warn,
118
117
  [`${prefix}--text-input__invalid-icon--warning`]: normalizedProps.warn
119
118
  });
120
- const label = labelText ? /*#__PURE__*/React.createElement("label", {
119
+ const label = typeof labelText !== 'undefined' && labelText !== null && /*#__PURE__*/React.createElement("label", {
121
120
  htmlFor: id,
122
121
  className: labelClasses
123
- }, labelText) : null;
124
- const helper = helperText ? /*#__PURE__*/React.createElement("div", {
122
+ }, labelText);
123
+ const helper = typeof helperText !== 'undefined' && helperText !== null && /*#__PURE__*/React.createElement("div", {
125
124
  id: normalizedProps.helperId,
126
125
  className: helperTextClasses
127
- }, helperText) : null;
126
+ }, helperText);
128
127
  const passwordIsVisible = inputType === 'text';
129
128
  const passwordVisibilityIcon = passwordIsVisible ? /*#__PURE__*/React.createElement(ViewOff, {
130
129
  className: `${prefix}--icon-visibility-off`
@@ -141,19 +141,19 @@ const TextInput = /*#__PURE__*/forwardRef(({
141
141
  as: "div",
142
142
  className: counterClasses
143
143
  }, `${textCount}/${maxCount}`) : null;
144
- const label = labelText ? /*#__PURE__*/React.createElement(Text, {
144
+ const label = typeof labelText !== 'undefined' && labelText !== null && /*#__PURE__*/React.createElement(Text, {
145
145
  as: "label",
146
146
  htmlFor: id,
147
147
  className: labelClasses
148
- }, labelText) : null;
148
+ }, labelText);
149
149
  const labelWrapper = /*#__PURE__*/React.createElement("div", {
150
150
  className: `${prefix}--text-input__label-wrapper`
151
151
  }, label, counter);
152
- const helper = helperText ? /*#__PURE__*/React.createElement(Text, {
152
+ const helper = typeof helperText !== 'undefined' && helperText !== null && /*#__PURE__*/React.createElement(Text, {
153
153
  as: "div",
154
154
  id: normalizedProps.helperId,
155
155
  className: helperTextClasses
156
- }, helperText) : null;
156
+ }, helperText);
157
157
  const input = /*#__PURE__*/React.createElement("input", getTextInputProps({
158
158
  sharedTextInputProps,
159
159
  invalid: normalizedProps.invalid,
@@ -98,10 +98,10 @@ const TimePicker = frFn((props, ref) => {
98
98
  [`${prefix}--visually-hidden`]: hideLabel,
99
99
  [`${prefix}--label--disabled`]: disabled
100
100
  });
101
- const label = labelText ? /*#__PURE__*/React.createElement("label", {
101
+ const label = typeof labelText !== 'undefined' && labelText !== null && /*#__PURE__*/React.createElement("label", {
102
102
  htmlFor: id,
103
103
  className: labelClasses
104
- }, labelText) : null;
104
+ }, labelText);
105
105
  function getInternalPickerSelects() {
106
106
  const readOnlyEventHandlers = {
107
107
  onMouseDown: evt => {
@@ -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.
@@ -48,8 +48,9 @@ const DefinitionTooltip = ({
48
48
  setOpen(false);
49
49
  },
50
50
  onMouseEnter: () => {
51
- // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- https://github.com/carbon-design-system/carbon/issues/20452
52
- openOnHover ? setOpen(true) : null;
51
+ if (openOnHover) {
52
+ setOpen(true);
53
+ }
53
54
  },
54
55
  onFocus: () => {
55
56
  setOpen(true);
@@ -5,9 +5,9 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- import React, { useState, useLayoutEffect, useEffect } from 'react';
8
+ import React, { useState, useEffect } from 'react';
9
9
  import { setupGetInstanceId } from '../tools/setupGetInstanceId.js';
10
- import { canUseDOM } from './environment.js';
10
+ import useIsomorphicEffect from './useIsomorphicEffect.js';
11
11
  import { useIdPrefix } from './useIdPrefix.js';
12
12
 
13
13
  // This file was heavily inspired by:
@@ -46,7 +46,6 @@ const _React = {
46
46
  ...React
47
47
  };
48
48
  const instanceId = setupGetInstanceId();
49
- const useIsomorphicLayoutEffect = canUseDOM ? useLayoutEffect : useEffect;
50
49
  let serverHandoffCompleted = false;
51
50
  const defaultId = 'id';
52
51
 
@@ -64,7 +63,7 @@ function useCompatibleId(prefix = defaultId) {
64
63
  }
65
64
  return null;
66
65
  });
67
- useIsomorphicLayoutEffect(() => {
66
+ useIsomorphicEffect(() => {
68
67
  if (id === null) {
69
68
  setId(`${contextPrefix ? `${contextPrefix}-` : ``}${prefix}-${instanceId()}`);
70
69
  }
@@ -5,8 +5,9 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- import { useState, useCallback, useLayoutEffect } from 'react';
8
+ import { useState, useCallback } from 'react';
9
9
  import { usePrefix } from './usePrefix.js';
10
+ import useIsomorphicEffect from './useIsomorphicEffect.js';
10
11
 
11
12
  const usePresence = (ref, isOpen) => {
12
13
  const prefix = usePrefix();
@@ -25,7 +26,7 @@ const usePresence = (ref, isOpen) => {
25
26
  const handleAnimationEnd = useCallback(() => {
26
27
  setExitState('finished');
27
28
  }, []);
28
- useLayoutEffect(() => {
29
+ useIsomorphicEffect(() => {
29
30
  if (!ref.current || !isExiting) return;
30
31
 
31
32
  // resolve for JSDOM
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright IBM Corp. 2025, 2025
2
+ * Copyright IBM Corp. 2025, 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.
@@ -5,7 +5,8 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- import { useState, useRef, useEffect, useLayoutEffect } from 'react';
8
+ import { useState, useRef, useEffect } from 'react';
9
+ import useIsomorphicEffect from './useIsomorphicEffect.js';
9
10
 
10
11
  const useResizeObserver = ({
11
12
  ref,
@@ -16,7 +17,7 @@ const useResizeObserver = ({
16
17
  const entriesToHandle = useRef(null);
17
18
  const cb = useRef(onResize);
18
19
  useEffect(() => {
19
- // ref for onResize removes it as dependency from useLayoutEffect
20
+ // ref for onResize removes it as dependency from useIsomorphicEffect
20
21
  // This significantly reduces repeated calls if a function is redefined on every
21
22
  // render
22
23
  cb.current = onResize;
@@ -37,7 +38,7 @@ const useResizeObserver = ({
37
38
  getInitialSize();
38
39
  // eslint-disable-next-line react-hooks/exhaustive-deps -- https://github.com/carbon-design-system/carbon/issues/20452
39
40
  }, [width, height]);
40
- useLayoutEffect(() => {
41
+ useIsomorphicEffect(() => {
41
42
  if (!ref?.current) {
42
43
  return;
43
44
  }
@@ -48,9 +49,7 @@ const useResizeObserver = ({
48
49
  const entry = entriesToHandle.current[0];
49
50
  setWidth(entry.contentRect.width);
50
51
  setHeight(entry.contentRect.height);
51
-
52
- // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- https://github.com/carbon-design-system/carbon/issues/20452
53
- cb.current && cb.current(entry.contentRect);
52
+ cb.current?.(entry.contentRect);
54
53
  };
55
54
  const observer = new ResizeObserver(entries => {
56
55
  // always update entriesToHandle
@@ -66,7 +65,6 @@ const useResizeObserver = ({
66
65
  return () => {
67
66
  observer.disconnect();
68
67
  };
69
- // eslint-disable-next-line react-hooks/exhaustive-deps -- https://github.com/carbon-design-system/carbon/issues/20452
70
68
  }, []);
71
69
  return {
72
70
  width,
@@ -14,4 +14,4 @@ import type { SyntheticEvent } from 'react';
14
14
  * @param handlers - An array of event handler functions.
15
15
  * @returns A composite event handler.
16
16
  */
17
- export declare const composeEventHandlers: <E extends SyntheticEvent = SyntheticEvent<Element, Event>>(handlers: (((event: E, ...args: any[]) => void) | undefined)[]) => (event: E, ...args: any[]) => void;
17
+ export declare const composeEventHandlers: <E extends SyntheticEvent = SyntheticEvent>(handlers: (((event: E, ...args: any[]) => void) | undefined)[]) => (event: E, ...args: any[]) => void;
@@ -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.
@@ -25,20 +25,9 @@ const AILabelContent = /*#__PURE__*/React.forwardRef(function AILabelContent({
25
25
  }, ref // eslint-disable-line @typescript-eslint/no-unused-vars -- https://github.com/carbon-design-system/carbon/issues/20452
26
26
  ) {
27
27
  const prefix = usePrefix.usePrefix();
28
- const hasAILabelActions = React.Children.toArray(children).some(child => {
29
- // eslint-disable-next-line @typescript-eslint/no-explicit-any -- https://github.com/carbon-design-system/carbon/issues/20452
30
- const item = child;
31
- // TODO: Is there supposed to be a `return` here? If so, this issue would
32
- // have been caught by ESLint. It's concerning that this code is 7 months
33
- // old and no one has noticed any issues with it. It also makes me question
34
- // whether the code is necessary.
35
- // https://github.com/carbon-design-system/carbon/issues/18991
36
- // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- https://github.com/carbon-design-system/carbon/issues/20452
37
- item.type === AILabelActions;
38
- });
39
28
  const aiLabelContentClasses = cx(className, {
40
29
  [`${prefix}--ai-label-content`]: true,
41
- [`${prefix}--ai-label-content--with-actions`]: hasAILabelActions
30
+ [`${prefix}--ai-label-content--with-actions`]: false
42
31
  });
43
32
  return /*#__PURE__*/React.createElement(index.ToggletipContent, {
44
33
  className: aiLabelContentClasses
@@ -46,11 +46,12 @@ const Checkbox = /*#__PURE__*/React.forwardRef(({
46
46
  const showWarning = !readOnly && !invalid && warn;
47
47
  const showHelper = !invalid && !warn;
48
48
  const checkboxGroupInstanceId = useId.useId();
49
- const helperId = !helperText ? undefined : `checkbox-helper-text-${checkboxGroupInstanceId}`;
50
- const helper = helperText ? /*#__PURE__*/React.createElement("div", {
49
+ const hasHelper = typeof helperText !== 'undefined' && helperText !== null;
50
+ const helperId = !hasHelper ? undefined : `checkbox-helper-text-${checkboxGroupInstanceId}`;
51
+ const helper = hasHelper && /*#__PURE__*/React.createElement("div", {
51
52
  id: helperId,
52
53
  className: `${prefix}--form__helper-text`
53
- }, helperText) : null;
54
+ }, helperText);
54
55
  const wrapperClasses = cx(`${prefix}--form-item`, `${prefix}--checkbox-wrapper`, className, {
55
56
  [`${prefix}--checkbox-wrapper--readonly`]: readOnly,
56
57
  [`${prefix}--checkbox-wrapper--invalid`]: !readOnly && invalid,
@@ -110,6 +111,7 @@ const Checkbox = /*#__PURE__*/React.forwardRef(({
110
111
  className: `${prefix}--checkbox-label`,
111
112
  title: title
112
113
  }, /*#__PURE__*/React.createElement(Text.Text, {
114
+ as: "div",
113
115
  className: innerLabelClasses
114
116
  }, labelText, slug ? normalizedDecorator : decorator ? /*#__PURE__*/React.createElement("div", {
115
117
  className: `${prefix}--checkbox-wrapper-inner--decorator`
@@ -42,11 +42,12 @@ const CheckboxGroup = ({
42
42
  const showWarning = !readOnly && !invalid && warn;
43
43
  const showHelper = !invalid && !warn;
44
44
  const checkboxGroupInstanceId = useId.useId();
45
- const helperId = !helperText ? undefined : `checkbox-group-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-group-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 fieldsetClasses = cx(`${prefix}--checkbox-group`, className, {
51
52
  [`${prefix}--checkbox-group--${orientation}`]: orientation === 'horizontal',
52
53
  [`${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
@@ -27,6 +27,7 @@ var useId = require('../../internal/useId.js');
27
27
  var mergeRefs = require('../../tools/mergeRefs.js');
28
28
  var deprecate = require('../../prop-types/deprecate.js');
29
29
  var usePrefix = require('../../internal/usePrefix.js');
30
+ var useNormalizedInputProps = require('../../internal/useNormalizedInputProps.js');
30
31
  require('../FluidForm/FluidForm.js');
31
32
  var FormContext = require('../FluidForm/FormContext.js');
32
33
  var react = require('@floating-ui/react');
@@ -251,8 +252,7 @@ const ComboBox = /*#__PURE__*/React.forwardRef((props, ref) => {
251
252
  React.useEffect(() => {
252
253
  if (prevInputValue.current !== inputValue) {
253
254
  prevInputValue.current = inputValue;
254
- // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- https://github.com/carbon-design-system/carbon/issues/20452
255
- onInputChange && onInputChange(inputValue);
255
+ onInputChange?.(inputValue);
256
256
  }
257
257
  // eslint-disable-next-line react-hooks/exhaustive-deps -- https://github.com/carbon-design-system/carbon/issues/20452
258
258
  }, [inputValue]);
@@ -427,11 +427,19 @@ const ComboBox = /*#__PURE__*/React.forwardRef((props, ref) => {
427
427
  event?.persist?.();
428
428
  }
429
429
  };
430
- const showWarning = !invalid && warn;
430
+ const normalizedProps = useNormalizedInputProps.useNormalizedInputProps({
431
+ id,
432
+ readOnly,
433
+ disabled: disabled || false,
434
+ invalid: invalid || false,
435
+ invalidText,
436
+ warn: warn || false,
437
+ warnText
438
+ });
431
439
  const className = cx(`${prefix}--combo-box`, {
432
440
  [`${prefix}--combo-box--invalid--focused`]: invalid && isFocused,
433
441
  [`${prefix}--list-box--up`]: direction === 'top',
434
- [`${prefix}--combo-box--warning`]: showWarning,
442
+ [`${prefix}--combo-box--warning`]: normalizedProps.warn,
435
443
  [`${prefix}--combo-box--readonly`]: readOnly,
436
444
  [`${prefix}--autoalign`]: enableFloatingStyles
437
445
  });
@@ -601,7 +609,7 @@ const ComboBox = /*#__PURE__*/React.forwardRef((props, ref) => {
601
609
  // The input should be described by the appropriate message text id
602
610
  // when both the message is supplied *and* when the component is in
603
611
  // the matching state (invalid, warn, etc).
604
- const ariaDescribedBy = invalid && invalidText && invalidTextId || warn && warnText && warnTextId || helperText && !isFluid && helperTextId || undefined;
612
+ const ariaDescribedBy = normalizedProps.invalid && invalidText && invalidTextId || normalizedProps.warn && warnText && warnTextId || helperText && !isFluid && helperTextId || undefined;
605
613
 
606
614
  // Memoize the value of getMenuProps to avoid an infinite loop
607
615
  const menuProps = React.useMemo(() => getMenuProps({
@@ -629,13 +637,13 @@ const ComboBox = /*#__PURE__*/React.forwardRef((props, ref) => {
629
637
  onBlur: handleFocus,
630
638
  className: className,
631
639
  disabled: disabled,
632
- invalid: invalid,
640
+ invalid: normalizedProps.invalid,
633
641
  invalidText: invalidText,
634
642
  invalidTextId: invalidTextId,
635
643
  isOpen: isOpen,
636
644
  light: light,
637
645
  size: size,
638
- warn: warn,
646
+ warn: normalizedProps.warn,
639
647
  ref: enableFloatingStyles ? refs.setReference : null,
640
648
  warnText: warnText,
641
649
  warnTextId: warnTextId
@@ -737,9 +745,9 @@ const ComboBox = /*#__PURE__*/React.forwardRef((props, ref) => {
737
745
  }), rest, readOnlyEventHandlers, {
738
746
  readOnly: readOnly,
739
747
  "aria-describedby": ariaDescribedBy
740
- })), invalid && /*#__PURE__*/React.createElement(iconsReact.WarningFilled, {
748
+ })), normalizedProps.invalid && /*#__PURE__*/React.createElement(iconsReact.WarningFilled, {
741
749
  className: `${prefix}--list-box__invalid-icon`
742
- }), showWarning && /*#__PURE__*/React.createElement(iconsReact.WarningAltFilled, {
750
+ }), normalizedProps.warn && /*#__PURE__*/React.createElement(iconsReact.WarningAltFilled, {
743
751
  className: `${prefix}--list-box__invalid-icon ${prefix}--list-box__invalid-icon--warning`
744
752
  }), inputValue && /*#__PURE__*/React.createElement(ListBoxSelection.default, {
745
753
  clearSelection: () => {
@@ -777,18 +785,23 @@ const ComboBox = /*#__PURE__*/React.forwardRef((props, ref) => {
777
785
  const {
778
786
  'aria-disabled': unusedAriaDisabled,
779
787
  // eslint-disable-line @typescript-eslint/no-unused-vars
788
+ 'aria-selected': unusedAriaSelected,
789
+ // eslint-disable-line @typescript-eslint/no-unused-vars
780
790
  ...modifiedItemProps
781
791
  } = itemProps;
792
+ const isSelected = isEqual(currentSelectedItem, item);
782
793
  return /*#__PURE__*/React.createElement(index$2.default.MenuItem, _rollupPluginBabelHelpers.extends({
783
794
  key: itemProps.id,
784
- isActive: isEqual(currentSelectedItem, item),
795
+ isActive: isSelected,
785
796
  isHighlighted: highlightedIndex === index,
786
797
  title: title,
787
798
  disabled: disabled
788
- }, modifiedItemProps), itemToElement ? itemToElement(item) : itemToString(item), isEqual(currentSelectedItem, item) && /*#__PURE__*/React.createElement(iconsReact.Checkmark, {
799
+ }, modifiedItemProps, {
800
+ "aria-selected": isSelected
801
+ }), itemToElement ? itemToElement(item) : itemToString(item), isSelected && /*#__PURE__*/React.createElement(iconsReact.Checkmark, {
789
802
  className: `${prefix}--list-box__menu-item__selected-icon`
790
803
  }));
791
- }) : null)), helperText && !invalid && !warn && !isFluid && /*#__PURE__*/React.createElement(Text.Text, {
804
+ }) : null)), helperText && !normalizedProps.invalid && !normalizedProps.warn && !isFluid && /*#__PURE__*/React.createElement(Text.Text, {
792
805
  as: "div",
793
806
  id: helperTextId,
794
807
  className: helperClasses
@@ -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.
@@ -20,6 +20,7 @@ require('../Menu/MenuItem.js');
20
20
  var useAttachedMenu = require('../../internal/useAttachedMenu.js');
21
21
  var useId = require('../../internal/useId.js');
22
22
  var usePrefix = require('../../internal/usePrefix.js');
23
+ var useIsomorphicEffect = require('../../internal/useIsomorphicEffect.js');
23
24
  var react = require('@floating-ui/react');
24
25
  var index = require('../FeatureFlags/index.js');
25
26
  var mergeRefs = require('../../tools/mergeRefs.js');
@@ -96,7 +97,7 @@ const ComboButton = /*#__PURE__*/React.forwardRef(function ComboButton({
96
97
  handleMousedown: handleTriggerMousedown,
97
98
  handleClose
98
99
  } = useAttachedMenu.useAttachedMenu(containerRef);
99
- React.useLayoutEffect(() => {
100
+ useIsomorphicEffect.default(() => {
100
101
  const updatedFloatingStyles = {
101
102
  ...floatingStyles,
102
103
  visibility: middlewareData.hide?.referenceHidden ? 'hidden' : 'visible'
@@ -12,7 +12,6 @@ Object.defineProperty(exports, '__esModule', { value: true });
12
12
  var _rollupPluginBabelHelpers = require('../../_virtual/_rollupPluginBabelHelpers.js');
13
13
  var React = require('react');
14
14
  var useResizeObserver = require('../../internal/useResizeObserver.js');
15
- var reactIs = require('react-is');
16
15
  var PropTypes = require('prop-types');
17
16
  var index = require('../Layer/index.js');
18
17
  var ModalHeader = require('./ModalHeader.js');
@@ -263,29 +262,25 @@ const ComposedModalDialog = /*#__PURE__*/React.forwardRef(function ComposedModal
263
262
  const containerClass = cx(`${prefix}--modal-container`, size && `${prefix}--modal-container--${size}`, isFullWidth && `${prefix}--modal-container--full-width`, containerClassName);
264
263
 
265
264
  // Generate aria-label based on Modal Header label if one is not provided (L253)
265
+ //
266
+ // TODO: Confirm whether `ModalHeader` `label` should allow `ReactNode`. If
267
+ // so, define how to derive a string for `aria-label`.
266
268
  let generatedAriaLabel;
267
269
  const childrenWithProps = React.Children.toArray(children).map(child => {
268
- switch (true) {
269
- case reactIs.isElement(child) && child.type === /*#__PURE__*/React.createElement(ModalHeader.ModalHeader).type:
270
- {
271
- const el = child;
272
- generatedAriaLabel = el.props.label;
273
- return /*#__PURE__*/React.cloneElement(el, {
274
- closeModal
275
- });
276
- }
277
- case reactIs.isElement(child) && child.type === /*#__PURE__*/React.createElement(ModalFooter.ModalFooter).type:
278
- {
279
- const el = child;
280
- return /*#__PURE__*/React.cloneElement(el, {
281
- closeModal,
282
- inputref: button,
283
- danger
284
- });
285
- }
286
- default:
287
- return child;
270
+ if (utils.isComponentElement(child, ModalHeader.ModalHeader)) {
271
+ generatedAriaLabel = child.props.label;
272
+ return /*#__PURE__*/React.cloneElement(child, {
273
+ closeModal
274
+ });
275
+ }
276
+ if (utils.isComponentElement(child, ModalFooter.ModalFooter)) {
277
+ return /*#__PURE__*/React.cloneElement(child, {
278
+ closeModal,
279
+ inputref: button,
280
+ danger
281
+ });
288
282
  }
283
+ return child;
289
284
  });
290
285
 
291
286
  // 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
  */