@carbon/react 1.84.0-rc.0 → 1.85.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 (177) hide show
  1. package/.playwright/INTERNAL_AVT_REPORT_DO_NOT_USE.json +943 -943
  2. package/es/components/AILabel/index.js +6 -1
  3. package/es/components/Checkbox/Checkbox.d.ts +2 -2
  4. package/es/components/Checkbox/Checkbox.js +8 -8
  5. package/es/components/CheckboxGroup/CheckboxGroup.d.ts +2 -2
  6. package/es/components/CheckboxGroup/CheckboxGroup.js +9 -8
  7. package/es/components/CodeSnippet/CodeSnippet.js +2 -4
  8. package/es/components/ComboBox/ComboBox.d.ts +1 -1
  9. package/es/components/ComboBox/ComboBox.js +8 -7
  10. package/es/components/ComposedModal/ComposedModal.d.ts +1 -1
  11. package/es/components/ComposedModal/ComposedModal.js +34 -12
  12. package/es/components/ContainedList/ContainedList.d.ts +1 -1
  13. package/es/components/ContainedList/ContainedList.js +4 -2
  14. package/es/components/ContentSwitcher/ContentSwitcher.js +6 -5
  15. package/es/components/DataTable/DataTable.js +3 -0
  16. package/es/components/DataTable/TableDecoratorRow.d.ts +2 -2
  17. package/es/components/DataTable/TableDecoratorRow.js +8 -8
  18. package/es/components/DataTable/TableExpandRow.d.ts +1 -1
  19. package/es/components/DataTable/TableExpandRow.js +15 -6
  20. package/es/components/DataTable/TableHeader.js +10 -10
  21. package/es/components/DataTable/TableRow.js +12 -4
  22. package/es/components/DataTable/tools/normalize.js +2 -1
  23. package/es/components/DatePickerInput/DatePickerInput.js +8 -7
  24. package/es/components/Dialog/index.d.ts +5 -1
  25. package/es/components/Dialog/index.js +20 -0
  26. package/es/components/Dropdown/Dropdown.d.ts +1 -1
  27. package/es/components/Dropdown/Dropdown.js +8 -10
  28. package/es/components/FileUploader/FileUploaderButton.js +2 -2
  29. package/es/components/FileUploader/FileUploaderDropContainer.js +2 -2
  30. package/es/components/FileUploader/FileUploaderItem.js +2 -2
  31. package/es/components/Layer/index.d.ts +1 -3
  32. package/es/components/Layer/index.js +9 -8
  33. package/es/components/Menu/Menu.js +0 -6
  34. package/es/components/Modal/Modal.d.ts +2 -2
  35. package/es/components/Modal/Modal.js +39 -11
  36. package/es/components/MultiSelect/FilterableMultiSelect.d.ts +1 -1
  37. package/es/components/MultiSelect/FilterableMultiSelect.js +29 -7
  38. package/es/components/MultiSelect/MultiSelect.d.ts +1 -1
  39. package/es/components/MultiSelect/MultiSelect.js +8 -7
  40. package/es/components/NumberInput/NumberInput.d.ts +1 -1
  41. package/es/components/NumberInput/NumberInput.js +9 -8
  42. package/es/components/OverflowMenu/OverflowMenu.js +4 -5
  43. package/es/components/PageHeader/PageHeader.d.ts +10 -9
  44. package/es/components/PageHeader/PageHeader.js +94 -34
  45. package/es/components/PageHeader/index.d.ts +2 -2
  46. package/es/components/PageHeader/index.js +1 -1
  47. package/es/components/Popover/index.js +2 -1
  48. package/es/components/RadioButton/RadioButton.d.ts +2 -2
  49. package/es/components/RadioButton/RadioButton.js +8 -8
  50. package/es/components/RadioButtonGroup/RadioButtonGroup.d.ts +2 -2
  51. package/es/components/RadioButtonGroup/RadioButtonGroup.js +9 -8
  52. package/es/components/RadioTile/RadioTile.d.ts +1 -1
  53. package/es/components/RadioTile/RadioTile.js +8 -7
  54. package/es/components/Search/Search.js +0 -1
  55. package/es/components/Select/Select.d.ts +2 -2
  56. package/es/components/Select/Select.js +8 -7
  57. package/es/components/Slider/Slider.js +6 -0
  58. package/es/components/Tag/DismissibleTag.d.ts +1 -1
  59. package/es/components/Tag/DismissibleTag.js +9 -8
  60. package/es/components/Tag/Tag.d.ts +1 -1
  61. package/es/components/Tag/Tag.js +9 -8
  62. package/es/components/TextArea/TextArea.js +12 -11
  63. package/es/components/TextInput/TextInput.d.ts +1 -1
  64. package/es/components/TextInput/TextInput.js +20 -9
  65. package/es/components/Tile/Tile.d.ts +2 -2
  66. package/es/components/Tile/Tile.js +30 -36
  67. package/es/components/TileGroup/TileGroup.d.ts +4 -4
  68. package/es/components/TileGroup/TileGroup.js +45 -53
  69. package/es/components/TileGroup/index.d.ts +3 -3
  70. package/es/components/Toggletip/index.js +2 -2
  71. package/es/components/Tooltip/DefinitionTooltip.js +1 -0
  72. package/es/components/TreeView/TreeNode.js +3 -3
  73. package/es/components/TreeView/TreeView.js +3 -3
  74. package/es/components/UIShell/Content.d.ts +5 -3
  75. package/es/components/UIShell/HeaderMenuItem.js +2 -1
  76. package/es/components/UIShell/HeaderPanel.d.ts +2 -2
  77. package/es/components/UIShell/HeaderPanel.js +9 -5
  78. package/es/index.js +1 -1
  79. package/es/internal/Selection.js +8 -3
  80. package/es/internal/environment.js +1 -12
  81. package/es/internal/{__mocks__/mockHTMLElement.d.ts → index.d.ts} +2 -4
  82. package/es/internal/useOverflowItems.d.ts +29 -0
  83. package/es/internal/useOverflowItems.js +122 -0
  84. package/es/internal/useResizeObserver.d.ts +1 -1
  85. package/es/internal/utils.d.ts +14 -0
  86. package/es/internal/utils.js +18 -0
  87. package/es/tools/uniqueId.d.ts +1 -6
  88. package/lib/components/AILabel/index.js +6 -1
  89. package/lib/components/Checkbox/Checkbox.d.ts +2 -2
  90. package/lib/components/Checkbox/Checkbox.js +7 -7
  91. package/lib/components/CheckboxGroup/CheckboxGroup.d.ts +2 -2
  92. package/lib/components/CheckboxGroup/CheckboxGroup.js +8 -7
  93. package/lib/components/CodeSnippet/CodeSnippet.js +2 -4
  94. package/lib/components/ComboBox/ComboBox.d.ts +1 -1
  95. package/lib/components/ComboBox/ComboBox.js +11 -10
  96. package/lib/components/ComposedModal/ComposedModal.d.ts +1 -1
  97. package/lib/components/ComposedModal/ComposedModal.js +35 -13
  98. package/lib/components/ContainedList/ContainedList.d.ts +1 -1
  99. package/lib/components/ContainedList/ContainedList.js +4 -2
  100. package/lib/components/ContentSwitcher/ContentSwitcher.js +5 -4
  101. package/lib/components/DataTable/DataTable.js +3 -0
  102. package/lib/components/DataTable/TableDecoratorRow.d.ts +2 -2
  103. package/lib/components/DataTable/TableDecoratorRow.js +8 -8
  104. package/lib/components/DataTable/TableExpandRow.d.ts +1 -1
  105. package/lib/components/DataTable/TableExpandRow.js +14 -5
  106. package/lib/components/DataTable/TableHeader.js +9 -9
  107. package/lib/components/DataTable/TableRow.js +11 -3
  108. package/lib/components/DataTable/tools/normalize.js +2 -1
  109. package/lib/components/DatePickerInput/DatePickerInput.js +7 -6
  110. package/lib/components/Dialog/index.d.ts +5 -1
  111. package/lib/components/Dialog/index.js +20 -0
  112. package/lib/components/Dropdown/Dropdown.d.ts +1 -1
  113. package/lib/components/Dropdown/Dropdown.js +12 -14
  114. package/lib/components/FileUploader/FileUploaderButton.js +2 -2
  115. package/lib/components/FileUploader/FileUploaderDropContainer.js +2 -2
  116. package/lib/components/FileUploader/FileUploaderItem.js +2 -2
  117. package/lib/components/Layer/index.d.ts +1 -3
  118. package/lib/components/Layer/index.js +9 -8
  119. package/lib/components/Menu/Menu.js +0 -6
  120. package/lib/components/Modal/Modal.d.ts +2 -2
  121. package/lib/components/Modal/Modal.js +47 -19
  122. package/lib/components/MultiSelect/FilterableMultiSelect.d.ts +1 -1
  123. package/lib/components/MultiSelect/FilterableMultiSelect.js +33 -11
  124. package/lib/components/MultiSelect/MultiSelect.d.ts +1 -1
  125. package/lib/components/MultiSelect/MultiSelect.js +13 -12
  126. package/lib/components/NumberInput/NumberInput.d.ts +1 -1
  127. package/lib/components/NumberInput/NumberInput.js +8 -7
  128. package/lib/components/OverflowMenu/OverflowMenu.js +4 -5
  129. package/lib/components/PageHeader/PageHeader.d.ts +10 -9
  130. package/lib/components/PageHeader/PageHeader.js +92 -34
  131. package/lib/components/PageHeader/index.d.ts +2 -2
  132. package/lib/components/PageHeader/index.js +0 -2
  133. package/lib/components/Popover/index.js +2 -1
  134. package/lib/components/RadioButton/RadioButton.d.ts +2 -2
  135. package/lib/components/RadioButton/RadioButton.js +7 -7
  136. package/lib/components/RadioButtonGroup/RadioButtonGroup.d.ts +2 -2
  137. package/lib/components/RadioButtonGroup/RadioButtonGroup.js +10 -9
  138. package/lib/components/RadioTile/RadioTile.d.ts +1 -1
  139. package/lib/components/RadioTile/RadioTile.js +7 -6
  140. package/lib/components/Search/Search.js +0 -1
  141. package/lib/components/Select/Select.d.ts +2 -2
  142. package/lib/components/Select/Select.js +7 -6
  143. package/lib/components/Slider/Slider.js +6 -0
  144. package/lib/components/Tag/DismissibleTag.d.ts +1 -1
  145. package/lib/components/Tag/DismissibleTag.js +8 -7
  146. package/lib/components/Tag/Tag.d.ts +1 -1
  147. package/lib/components/Tag/Tag.js +8 -7
  148. package/lib/components/TextArea/TextArea.js +11 -10
  149. package/lib/components/TextInput/TextInput.d.ts +1 -1
  150. package/lib/components/TextInput/TextInput.js +19 -8
  151. package/lib/components/Tile/Tile.d.ts +2 -2
  152. package/lib/components/Tile/Tile.js +29 -35
  153. package/lib/components/TileGroup/TileGroup.d.ts +4 -4
  154. package/lib/components/TileGroup/TileGroup.js +44 -52
  155. package/lib/components/TileGroup/index.d.ts +3 -3
  156. package/lib/components/Toggletip/index.js +2 -2
  157. package/lib/components/Tooltip/DefinitionTooltip.js +1 -0
  158. package/lib/components/TreeView/TreeNode.js +3 -3
  159. package/lib/components/TreeView/TreeView.js +3 -3
  160. package/lib/components/UIShell/Content.d.ts +5 -3
  161. package/lib/components/UIShell/HeaderMenuItem.js +2 -1
  162. package/lib/components/UIShell/HeaderPanel.d.ts +2 -2
  163. package/lib/components/UIShell/HeaderPanel.js +8 -4
  164. package/lib/index.js +1 -1
  165. package/lib/internal/Selection.js +8 -3
  166. package/lib/internal/environment.js +1 -12
  167. package/lib/internal/{__mocks__/mockHTMLElement.d.ts → index.d.ts} +2 -4
  168. package/lib/internal/useOverflowItems.d.ts +29 -0
  169. package/lib/internal/useOverflowItems.js +126 -0
  170. package/lib/internal/useResizeObserver.d.ts +1 -1
  171. package/lib/internal/utils.d.ts +14 -0
  172. package/lib/internal/utils.js +22 -0
  173. package/lib/tools/uniqueId.d.ts +1 -6
  174. package/package.json +14 -23
  175. package/telemetry.yml +3 -0
  176. package/es/tools/uniqueId.js +0 -14
  177. package/lib/tools/uniqueId.js +0 -18
@@ -27,7 +27,12 @@ const AILabelContent = /*#__PURE__*/React.forwardRef(function AILabelContent({
27
27
  const prefix = usePrefix();
28
28
  const hasAILabelActions = React.Children.toArray(children).some(child => {
29
29
  const item = child;
30
- item.type?.displayName === 'AILabelActions';
30
+ // TODO: Is there supposed to be a `return` here? If so, this issue would
31
+ // have been caught by ESLint. It's concerning that this code is 7 months
32
+ // old and no one has noticed any issues with it. It also makes me question
33
+ // whether the code is necessary.
34
+ // https://github.com/carbon-design-system/carbon/issues/18991
35
+ item.type === AILabelActions;
31
36
  });
32
37
  const aiLabelContentClasses = cx(className, {
33
38
  [`${prefix}--ai-label-content`]: true,
@@ -1,10 +1,10 @@
1
1
  /**
2
- * Copyright IBM Corp. 2016, 2023
2
+ * Copyright IBM Corp. 2016, 2025
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, { ReactNode } from 'react';
7
+ import React, { type ReactNode } from 'react';
8
8
  type ExcludedAttributes = 'id' | 'onChange' | 'onClick' | 'type';
9
9
  export interface CheckboxProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, ExcludedAttributes> {
10
10
  /**
@@ -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 from 'react';
10
+ import React, { cloneElement } from 'react';
11
11
  import cx from 'classnames';
12
12
  import '../Text/index.js';
13
13
  import deprecate from '../../prop-types/deprecate.js';
@@ -15,6 +15,8 @@ import { usePrefix } from '../../internal/usePrefix.js';
15
15
  import { WarningFilled, WarningAltFilled } from '@carbon/icons-react';
16
16
  import { useId } from '../../internal/useId.js';
17
17
  import { noopFn } from '../../internal/noopFn.js';
18
+ import { AILabel } from '../AILabel/index.js';
19
+ import { isComponentElement } from '../../internal/utils.js';
18
20
  import { Text } from '../Text/Text.js';
19
21
 
20
22
  const Checkbox = /*#__PURE__*/React.forwardRef(({
@@ -55,13 +57,11 @@ const Checkbox = /*#__PURE__*/React.forwardRef(({
55
57
  const innerLabelClasses = cx(`${prefix}--checkbox-label-text`, {
56
58
  [`${prefix}--visually-hidden`]: hideLabel
57
59
  });
58
- let normalizedDecorator = /*#__PURE__*/React.isValidElement(slug ?? decorator) ? slug ?? decorator : null;
59
- if (normalizedDecorator && normalizedDecorator['type']?.displayName === 'AILabel') {
60
- const size = normalizedDecorator.props?.['kind'] === 'inline' ? 'md' : 'mini';
61
- normalizedDecorator = /*#__PURE__*/React.cloneElement(normalizedDecorator, {
62
- size
63
- });
64
- }
60
+ const candidate = slug ?? decorator;
61
+ const candidateIsAILabel = isComponentElement(candidate, AILabel);
62
+ const normalizedDecorator = candidateIsAILabel ? /*#__PURE__*/cloneElement(candidate, {
63
+ size: candidate.props.kind === 'inline' ? 'md' : 'mini'
64
+ }) : null;
65
65
  return /*#__PURE__*/React.createElement("div", {
66
66
  className: wrapperClasses
67
67
  }, /*#__PURE__*/React.createElement("input", _extends({}, other, {
@@ -1,10 +1,10 @@
1
1
  /**
2
- * Copyright IBM Corp. 2016, 2023
2
+ * Copyright IBM Corp. 2016, 2025
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, { ReactNode } from 'react';
7
+ import React, { type ReactNode } from 'react';
8
8
  export interface CheckboxGroupProps {
9
9
  children?: ReactNode;
10
10
  className?: string;
@@ -7,12 +7,14 @@
7
7
 
8
8
  import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
9
9
  import PropTypes from 'prop-types';
10
- import React from 'react';
10
+ import React, { cloneElement } from 'react';
11
11
  import cx from 'classnames';
12
12
  import deprecate from '../../prop-types/deprecate.js';
13
13
  import { usePrefix } from '../../internal/usePrefix.js';
14
14
  import { WarningFilled, WarningAltFilled } from '@carbon/icons-react';
15
15
  import { useId } from '../../internal/useId.js';
16
+ import { AILabel } from '../AILabel/index.js';
17
+ import { isComponentElement } from '../../internal/utils.js';
16
18
 
17
19
  const CheckboxGroup = ({
18
20
  children,
@@ -49,13 +51,12 @@ const CheckboxGroup = ({
49
51
  });
50
52
 
51
53
  // AILabel always size `mini`
52
- let normalizedDecorator = /*#__PURE__*/React.isValidElement(slug ?? decorator) ? slug ?? decorator : null;
53
- if (normalizedDecorator && normalizedDecorator['type']?.displayName === 'AILabel') {
54
- normalizedDecorator = /*#__PURE__*/React.cloneElement(normalizedDecorator, {
55
- size: 'mini',
56
- kind: 'default'
57
- });
58
- }
54
+ const candidate = slug ?? decorator;
55
+ const candidateIsAILabel = isComponentElement(candidate, AILabel);
56
+ const normalizedDecorator = candidateIsAILabel ? /*#__PURE__*/cloneElement(candidate, {
57
+ size: 'mini',
58
+ kind: 'default'
59
+ }) : null;
59
60
  return /*#__PURE__*/React.createElement("fieldset", _extends({
60
61
  className: fieldsetClasses,
61
62
  "data-invalid": invalid ? true : undefined,
@@ -15,7 +15,7 @@ import Copy from '../Copy/Copy.js';
15
15
  import Button from '../Button/Button.js';
16
16
  import '../Button/Button.Skeleton.js';
17
17
  import CopyButton from '../CopyButton/CopyButton.js';
18
- import { uniqueId } from '../../tools/uniqueId.js';
18
+ import { useId } from '../../internal/useId.js';
19
19
  import copy from 'copy-to-clipboard';
20
20
  import deprecate from '../../prop-types/deprecate.js';
21
21
  import { usePrefix } from '../../internal/usePrefix.js';
@@ -56,7 +56,7 @@ function CodeSnippet({
56
56
  const [shouldShowMoreLessBtn, setShouldShowMoreLessBtn] = useState(false);
57
57
  const {
58
58
  current: uid
59
- } = useRef(uniqueId());
59
+ } = useRef(useId());
60
60
  const codeContentRef = useRef(null);
61
61
  const codeContainerRef = useRef(null);
62
62
  const innerCodeRef = useRef(null);
@@ -100,8 +100,6 @@ function CodeSnippet({
100
100
  setHasRightOverflow(horizontalOverflow && codeScrollLeft + codeClientWidth !== codeScrollWidth);
101
101
  }, [type, getCodeRefDimensions]);
102
102
  useResizeObserver({
103
- // Cast the ref until the hook supports React 19
104
- // https://github.com/ZeeCoder/use-resize-observer/issues/108
105
103
  ref: getCodeRef(),
106
104
  onResize: () => {
107
105
  if (codeContentRef?.current && type === 'multi') {
@@ -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 React, { type ReactNode, type ComponentType, type ReactElement, type RefAttributes, type PropsWithChildren, type PropsWithRef, type InputHTMLAttributes, type MouseEvent } from 'react';
8
+ import React, { type ComponentType, type InputHTMLAttributes, type MouseEvent, type PropsWithChildren, type PropsWithRef, type ReactElement, type ReactNode, type RefAttributes } from 'react';
9
9
  import { type ListBoxSize } from '../ListBox';
10
10
  import { TranslateWithId } from '../../types/common';
11
11
  type ExcludedAttributes = 'id' | 'onChange' | 'onClick' | 'type' | 'size';
@@ -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, { forwardRef, useRef, useEffect, useState, useContext, useCallback, useMemo } from 'react';
12
+ import React, { forwardRef, useRef, useEffect, useState, useContext, useCallback, useMemo, cloneElement } from 'react';
13
13
  import '../Text/index.js';
14
14
  import { WarningFilled, WarningAltFilled, Checkmark } from '@carbon/icons-react';
15
15
  import isEqual from 'react-fast-compare';
@@ -26,6 +26,8 @@ import '../FluidForm/FluidForm.js';
26
26
  import { FormContext } from '../FluidForm/FormContext.js';
27
27
  import { useFloating, flip, hide, autoUpdate } from '@floating-ui/react';
28
28
  import { useFeatureFlag } from '../FeatureFlags/index.js';
29
+ import { AILabel } from '../AILabel/index.js';
30
+ import { isComponentElement } from '../../internal/utils.js';
29
31
  import { ListBoxSizePropType } from '../ListBox/ListBoxPropTypes.js';
30
32
  import { Text } from '../Text/Text.js';
31
33
 
@@ -437,12 +439,11 @@ const ComboBox = /*#__PURE__*/forwardRef((props, ref) => {
437
439
  const ItemToElement = itemToElement;
438
440
 
439
441
  // AILabel always size `mini`
440
- let normalizedDecorator = /*#__PURE__*/React.isValidElement(slug ?? decorator) ? slug ?? decorator : null;
441
- if (normalizedDecorator && normalizedDecorator['type']?.displayName === 'AILabel') {
442
- normalizedDecorator = /*#__PURE__*/React.cloneElement(normalizedDecorator, {
443
- size: 'mini'
444
- });
445
- }
442
+ const candidate = slug ?? decorator;
443
+ const candidateIsAILabel = isComponentElement(candidate, AILabel);
444
+ const normalizedDecorator = candidateIsAILabel ? /*#__PURE__*/cloneElement(candidate, {
445
+ size: 'mini'
446
+ }) : null;
446
447
  const {
447
448
  // Prop getters
448
449
  getInputProps,
@@ -4,7 +4,7 @@
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, { type MouseEvent, type KeyboardEvent, type HTMLAttributes, type ReactNode, type RefObject } from 'react';
7
+ import React, { type HTMLAttributes, type KeyboardEvent, type MouseEvent, type ReactNode, type RefObject } from 'react';
8
8
  export interface ModalBodyProps extends HTMLAttributes<HTMLDivElement> {
9
9
  /** Specify the content to be placed in the ModalBody. */
10
10
  children?: ReactNode;
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
9
- import React, { useRef, useState, useEffect } from 'react';
9
+ import React, { useRef, useState, useEffect, Children, cloneElement } from 'react';
10
10
  import { isElement } from 'react-is';
11
11
  import PropTypes from 'prop-types';
12
12
  import { Layer } from '../Layer/index.js';
@@ -26,6 +26,8 @@ import { composeEventHandlers } from '../../tools/events.js';
26
26
  import deprecate from '../../prop-types/deprecate.js';
27
27
  import { unstable__Dialog } from '../Dialog/index.js';
28
28
  import { warning } from '../../internal/warning.js';
29
+ import { AILabel } from '../AILabel/index.js';
30
+ import { isComponentElement } from '../../internal/utils.js';
29
31
  import { debounce } from '../../node_modules/es-toolkit/dist/compat/function/debounce.mjs.js';
30
32
 
31
33
  const ModalBody = /*#__PURE__*/React.forwardRef(function ModalBody({
@@ -168,7 +170,10 @@ const ComposedModal = /*#__PURE__*/React.forwardRef(function ComposedModal({
168
170
  } = evt;
169
171
  const mouseDownTarget = onMouseDownTarget.current;
170
172
  evt.stopPropagation();
171
- if (!preventCloseOnClickOutside && target instanceof Node && !elementOrParentIsFloatingMenu(target, selectorsFloatingMenus) && innerModal.current && !innerModal.current.contains(target) && !innerModal.current.contains(mouseDownTarget)) {
173
+ const containsModalFooter = Children.toArray(childrenWithProps).some(child => isComponentElement(child, ModalFooter));
174
+ const isPassive = !containsModalFooter;
175
+ const shouldCloseOnOutsideClick = isPassive ? preventCloseOnClickOutside !== false : preventCloseOnClickOutside === true;
176
+ if (shouldCloseOnOutsideClick && target instanceof Node && !elementOrParentIsFloatingMenu(target, selectorsFloatingMenus) && innerModal.current && !innerModal.current.contains(target) && !innerModal.current.contains(mouseDownTarget)) {
172
177
  closeModal(evt);
173
178
  }
174
179
  }
@@ -176,7 +181,7 @@ const ComposedModal = /*#__PURE__*/React.forwardRef(function ComposedModal({
176
181
  target: oldActiveNode,
177
182
  relatedTarget: currentActiveNode
178
183
  }) {
179
- if (open && currentActiveNode && oldActiveNode && innerModal.current) {
184
+ if (!enableDialogElement && !focusTrapWithoutSentinels && open && currentActiveNode && oldActiveNode && innerModal.current) {
180
185
  const {
181
186
  current: bodyNode
182
187
  } = innerModal;
@@ -195,6 +200,23 @@ const ComposedModal = /*#__PURE__*/React.forwardRef(function ComposedModal({
195
200
  selectorsFloatingMenus: selectorsFloatingMenus?.filter(Boolean)
196
201
  });
197
202
  }
203
+
204
+ // Adjust scroll if needed so that element with focus is not obscured by gradient
205
+ const modalContent = document.querySelector(`.${prefix}--modal-content`);
206
+ if (!modalContent || !modalContent.classList.contains(`${prefix}--modal-scroll-content`) || !currentActiveNode || !modalContent.contains(currentActiveNode)) {
207
+ return;
208
+ }
209
+ const lastContent = modalContent.children[modalContent.children.length - 1];
210
+ const gradientSpacing = modalContent.scrollHeight - lastContent.offsetTop - lastContent.clientHeight;
211
+ for (let elem of modalContent.children) {
212
+ if (elem.contains(currentActiveNode)) {
213
+ const spaceBelow = modalContent.clientHeight - elem.offsetTop + modalContent.scrollTop - elem.clientHeight;
214
+ if (spaceBelow < gradientSpacing) {
215
+ modalContent.scrollTop = modalContent.scrollTop + (gradientSpacing - spaceBelow);
216
+ }
217
+ break;
218
+ }
219
+ }
198
220
  }
199
221
  function closeModal(evt) {
200
222
  if (!onClose || onClose(evt) !== false) {
@@ -237,10 +259,10 @@ const ComposedModal = /*#__PURE__*/React.forwardRef(function ComposedModal({
237
259
  useEffect(() => {
238
260
  if (!enableDialogElement && !open && launcherButtonRef) {
239
261
  setTimeout(() => {
240
- launcherButtonRef?.current?.focus();
262
+ launcherButtonRef.current?.focus();
241
263
  });
242
264
  }
243
- }, [open, launcherButtonRef]);
265
+ }, [enableDialogElement, open, launcherButtonRef]);
244
266
  useEffect(() => {
245
267
  if (!enableDialogElement) {
246
268
  const initialFocus = focusContainerElement => {
@@ -267,14 +289,14 @@ const ComposedModal = /*#__PURE__*/React.forwardRef(function ComposedModal({
267
289
  }, [open, selectorPrimaryFocus, isOpen]);
268
290
 
269
291
  // AILabel is always size `sm`
270
- let normalizedDecorator = /*#__PURE__*/React.isValidElement(slug ?? decorator) ? slug ?? decorator : null;
271
- if (normalizedDecorator && normalizedDecorator['type']?.displayName === 'AILabel') {
272
- normalizedDecorator = /*#__PURE__*/React.cloneElement(normalizedDecorator, {
273
- size: 'sm'
274
- });
275
- }
292
+ const candidate = slug ?? decorator;
293
+ const candidateIsAILabel = isComponentElement(candidate, AILabel);
294
+ const normalizedDecorator = candidateIsAILabel ? /*#__PURE__*/cloneElement(candidate, {
295
+ size: 'sm'
296
+ }) : null;
276
297
  const modalBody = enableDialogElement ? /*#__PURE__*/React.createElement(unstable__Dialog, {
277
298
  open: open,
299
+ focusAfterCloseRef: launcherButtonRef,
278
300
  modal: true,
279
301
  className: containerClass,
280
302
  "aria-label": ariaLabel ? ariaLabel : generatedAriaLabel,
@@ -309,7 +331,7 @@ const ComposedModal = /*#__PURE__*/React.forwardRef(function ComposedModal({
309
331
  role: "presentation",
310
332
  ref: ref,
311
333
  "aria-hidden": !open,
312
- onBlur: !enableDialogElement && !focusTrapWithoutSentinels ? handleBlur : () => {},
334
+ onBlur: handleBlur,
313
335
  onClick: composeEventHandlers([rest?.onClick, handleOnClick]),
314
336
  onMouseDown: composeEventHandlers([rest?.onMouseDown, handleOnMouseDown]),
315
337
  onKeyDown: handleKeyDown,
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright IBM Corp. 2022
2
+ * Copyright IBM Corp. 2022, 2025
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.
@@ -13,6 +13,8 @@ import { LayoutConstraint } from '../Layout/index.js';
13
13
  import { useId } from '../../internal/useId.js';
14
14
  import { usePrefix } from '../../internal/usePrefix.js';
15
15
  import ContainedListItem from './ContainedListItem/ContainedListItem.js';
16
+ import Search from '../Search/Search.js';
17
+ import '../Search/Search.Skeleton.js';
16
18
 
17
19
  const variants = ['on-page', 'disclosed'];
18
20
  function filterChildren(children) {
@@ -27,13 +29,13 @@ function filterChildren(children) {
27
29
  function renderChildren(children) {
28
30
  if (Array.isArray(children)) {
29
31
  children.map((child, index) => {
30
- if (index === 0 && child.type?.displayName === 'Search') {
32
+ if (index === 0 && child.type === Search) {
31
33
  return child;
32
34
  }
33
35
  return child;
34
36
  });
35
37
  }
36
- if (children && children.type?.displayName === 'Search') {
38
+ if (children && children.type === Search) {
37
39
  return children;
38
40
  }
39
41
  return children;
@@ -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, { useContext, useState, useRef, Children, useEffect, cloneElement, isValidElement } from 'react';
10
+ import React, { useContext, useState, useRef, Children, useEffect, isValidElement, cloneElement } from 'react';
11
11
  import cx from 'classnames';
12
12
  import deprecate from '../../prop-types/deprecate.js';
13
13
  import { LayoutConstraint } from '../Layout/index.js';
@@ -17,6 +17,8 @@ import { matches } from '../../internal/keyboard/match.js';
17
17
  import { getNextIndex } from '../../internal/keyboard/navigation.js';
18
18
  import { PrefixContext } from '../../internal/usePrefix.js';
19
19
  import { noopFn } from '../../internal/noopFn.js';
20
+ import '../Switch/Switch.js';
21
+ import IconSwitch from '../Switch/IconSwitch.js';
20
22
 
21
23
  const ContentSwitcher = ({
22
24
  children,
@@ -79,10 +81,9 @@ const ContentSwitcher = ({
79
81
  onChange(event);
80
82
  }
81
83
  };
82
- const isIconOnly = childrenArray.every(
83
- // TODO: Update this code when
84
- // https://github.com/carbon-design-system/carbon/pull/18971 is merged.
85
- child => child.type.displayName === 'IconSwitch');
84
+ const isIconOnly = Children.map(children, child => {
85
+ return /*#__PURE__*/isValidElement(child) ? child.type === IconSwitch : null;
86
+ })?.every(val => val === true);
86
87
  const classes = cx(`${prefix}--content-switcher`, className, {
87
88
  [`${prefix}--content-switcher--light`]: light,
88
89
  [`${prefix}--content-switcher--${size}`]: size,
@@ -176,6 +176,7 @@ class DataTable extends Component {
176
176
  return {
177
177
  ...rest,
178
178
  key: row.id,
179
+ onClick,
179
180
  // Compose the event handlers so we don't overwrite a consumer's `onClick`
180
181
  // handler
181
182
  onExpand: composeEventHandlers([this.handleOnExpandRow(row.id), onClick]),
@@ -298,6 +299,8 @@ class DataTable extends Component {
298
299
  useStaticWidth
299
300
  };
300
301
  });
302
+ // TODO: `getHeaderProps` and `getRowProps` return `key` props. Would it be
303
+ // beneficial for this function to also return a `key` prop?
301
304
  /**
302
305
  * Get the props associated with the given table cell.
303
306
  */
@@ -1,11 +1,11 @@
1
1
  /**
2
- * Copyright IBM Corp. 2016, 2023
2
+ * Copyright IBM Corp. 2016, 2025
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 PropTypes from 'prop-types';
8
- import { ReactNode } from 'react';
8
+ import { type ReactNode } from 'react';
9
9
  export interface TableDecoratorRowProps {
10
10
  /**
11
11
  * The CSS class names of the cell that wraps the underlying input control
@@ -5,10 +5,12 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- import PropTypes from 'prop-types';
9
- import React from 'react';
10
8
  import cx from 'classnames';
9
+ import PropTypes from 'prop-types';
10
+ import React, { cloneElement } from 'react';
11
11
  import { usePrefix } from '../../internal/usePrefix.js';
12
+ import { AILabel } from '../AILabel/index.js';
13
+ import { isComponentElement } from '../../internal/utils.js';
12
14
 
13
15
  const TableDecoratorRow = ({
14
16
  className,
@@ -22,12 +24,10 @@ const TableDecoratorRow = ({
22
24
  [`${prefix}--table-column-decorator`]: true,
23
25
  [`${prefix}--table-column-decorator--active`]: decorator
24
26
  });
25
- let normalizedDecorator = /*#__PURE__*/React.isValidElement(decorator) ? decorator : null;
26
- if (normalizedDecorator && normalizedDecorator['type']?.displayName === 'AILabel') {
27
- normalizedDecorator = /*#__PURE__*/React.cloneElement(normalizedDecorator, {
28
- size: 'mini'
29
- });
30
- }
27
+ const decoratorIsAILabel = isComponentElement(decorator, AILabel);
28
+ const normalizedDecorator = decoratorIsAILabel ? /*#__PURE__*/cloneElement(decorator, {
29
+ size: 'mini'
30
+ }) : null;
31
31
  return /*#__PURE__*/React.createElement("td", {
32
32
  className: TableDecoratorRowClasses
33
33
  }, normalizedDecorator);
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright IBM Corp. 2016, 2023
2
+ * Copyright IBM Corp. 2016, 2025
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,10 +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 from 'react';
11
+ import React, { Children, isValidElement } from 'react';
12
12
  import { ChevronRight } from '@carbon/icons-react';
13
13
  import TableCell from './TableCell.js';
14
14
  import { usePrefix } from '../../internal/usePrefix.js';
15
+ import TableSlugRow from './TableSlugRow.js';
16
+ import TableDecoratorRow from './TableDecoratorRow.js';
17
+ import { AILabel } from '../AILabel/index.js';
18
+ import { isComponentElement } from '../../internal/utils.js';
15
19
 
16
20
  const TableExpandRow = /*#__PURE__*/React.forwardRef(({
17
21
  ['aria-controls']: ariaControls,
@@ -30,16 +34,21 @@ const TableExpandRow = /*#__PURE__*/React.forwardRef(({
30
34
 
31
35
  // We need to put the AILabel and Decorator before the expansion arrow and all other table cells after the arrow.
32
36
  let rowHasAILabel;
33
- const decorator = React.Children.toArray(children).map(child => {
34
- if (child.type?.displayName === 'TableSlugRow' || child.type?.displayName === 'TableDecoratorRow') {
35
- if (child.props.slug || child.props.decorator?.type.displayName === 'AILabel') {
37
+ const decorator = Children.toArray(children).map(child => {
38
+ if (isComponentElement(child, TableSlugRow)) {
39
+ if (child.props.slug) {
40
+ rowHasAILabel = true;
41
+ }
42
+ return child;
43
+ } else if (isComponentElement(child, TableDecoratorRow)) {
44
+ if (isComponentElement(child.props.decorator, AILabel)) {
36
45
  rowHasAILabel = true;
37
46
  }
38
47
  return child;
39
48
  }
40
49
  });
41
- const normalizedChildren = React.Children.toArray(children).map(child => {
42
- if (child.type?.displayName !== 'TableSlugRow' && child.type?.displayName !== 'TableDecoratorRow') {
50
+ const normalizedChildren = Children.toArray(children).map(child => {
51
+ if (/*#__PURE__*/isValidElement(child) && child.type !== TableSlugRow && child.type !== TableDecoratorRow) {
43
52
  return child;
44
53
  }
45
54
  });
@@ -8,11 +8,13 @@
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 } from 'react';
11
+ import React, { useRef, cloneElement } from 'react';
12
12
  import { ArrowUp, ArrowsVertical } from '@carbon/icons-react';
13
13
  import './state/sorting.js';
14
14
  import { useId } from '../../internal/useId.js';
15
15
  import { usePrefix } from '../../internal/usePrefix.js';
16
+ import { AILabel } from '../AILabel/index.js';
17
+ import { isComponentElement } from '../../internal/utils.js';
16
18
  import { sortStates } from './state/sortStates.js';
17
19
 
18
20
  const defaultScope = 'col';
@@ -61,15 +63,13 @@ const TableHeader = /*#__PURE__*/React.forwardRef(function TableHeader({
61
63
 
62
64
  // AILabel is always size `mini`
63
65
  const AILableRef = useRef(null);
64
- let colHasAILabel;
65
- let normalizedDecorator = /*#__PURE__*/React.isValidElement(slug ?? decorator) ? slug ?? decorator : null;
66
- if (normalizedDecorator && normalizedDecorator['type']?.displayName === 'AILabel') {
67
- colHasAILabel = true;
68
- normalizedDecorator = /*#__PURE__*/React.cloneElement(normalizedDecorator, {
69
- size: 'mini',
70
- ref: AILableRef
71
- });
72
- }
66
+ const candidate = slug ?? decorator;
67
+ const candidateIsAILabel = isComponentElement(candidate, AILabel);
68
+ const colHasAILabel = candidateIsAILabel;
69
+ const normalizedDecorator = candidateIsAILabel ? /*#__PURE__*/cloneElement(candidate, {
70
+ size: 'mini',
71
+ ref: AILableRef
72
+ }) : null;
73
73
  const headerLabelClassNames = cx({
74
74
  [`${prefix}--table-header-label`]: true,
75
75
  [`${prefix}--table-header-label--slug ${prefix}--table-header-label--ai-label`]: colHasAILabel,
@@ -6,20 +6,28 @@
6
6
  */
7
7
 
8
8
  import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
9
- import React from 'react';
9
+ import React, { Children } from 'react';
10
10
  import PropTypes from 'prop-types';
11
11
  import cx from 'classnames';
12
12
  import { usePrefix } from '../../internal/usePrefix.js';
13
+ import TableSlugRow from './TableSlugRow.js';
14
+ import TableDecoratorRow from './TableDecoratorRow.js';
15
+ import { AILabel } from '../AILabel/index.js';
16
+ import { isComponentElement } from '../../internal/utils.js';
13
17
 
14
18
  const TableRow = /*#__PURE__*/React.forwardRef((props, ref) => {
15
19
  const prefix = usePrefix();
16
20
  let rowHasAILabel;
17
21
  if (props?.children) {
18
- React.Children.toArray(props.children).map(child => {
19
- if (child.type?.displayName === 'TableSlugRow' || child.type?.displayName === 'TableDecoratorRow') {
20
- if (child.props.slug || child.props.decorator?.type.displayName === 'AILabel') {
22
+ // TODO: Why is this loop a `map`? It's not returning anything. Ideally,
23
+ // it seems that it should be a `some`. Maybe I'm missing something?
24
+ Children.toArray(props.children).map(child => {
25
+ if (isComponentElement(child, TableSlugRow)) {
26
+ if (child.props.slug) {
21
27
  rowHasAILabel = true;
22
28
  }
29
+ } else if (isComponentElement(child, TableDecoratorRow) && isComponentElement(child.props.decorator, AILabel)) {
30
+ rowHasAILabel = true;
23
31
  }
24
32
  });
25
33
  }
@@ -5,6 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
+ import { AILabel } from '../../AILabel/index.js';
8
9
  import { getCellId } from './cells.js';
9
10
 
10
11
  /**
@@ -59,7 +60,7 @@ const normalize = (rows, headers, prevState = {}) => {
59
60
  isEditing: false,
60
61
  isValid: true,
61
62
  errors: null,
62
- hasAILabelHeader: !!(slug || decorator?.type?.displayName === 'AILabel'),
63
+ hasAILabelHeader: !!(slug || decorator?.type === AILabel),
63
64
  info: {
64
65
  header: key
65
66
  }
@@ -8,13 +8,15 @@
8
8
  import { WarningFilled, WarningAltFilled, Calendar } from '@carbon/icons-react';
9
9
  import cx from 'classnames';
10
10
  import PropTypes from 'prop-types';
11
- import React, { useContext } from 'react';
11
+ import React, { useContext, cloneElement } from 'react';
12
12
  import { usePrefix } from '../../internal/usePrefix.js';
13
13
  import '../FluidForm/FluidForm.js';
14
14
  import { FormContext } from '../FluidForm/FormContext.js';
15
15
  import { useId } from '../../internal/useId.js';
16
16
  import '../Text/index.js';
17
17
  import deprecate from '../../prop-types/deprecate.js';
18
+ import { AILabel } from '../AILabel/index.js';
19
+ import { isComponentElement } from '../../internal/utils.js';
18
20
  import { Text } from '../Text/Text.js';
19
21
 
20
22
  const DatePickerInput = /*#__PURE__*/React.forwardRef(function DatePickerInput(props, ref) {
@@ -99,12 +101,11 @@ const DatePickerInput = /*#__PURE__*/React.forwardRef(function DatePickerInput(p
99
101
  const input = /*#__PURE__*/React.createElement("input", inputProps);
100
102
 
101
103
  // AILabel always size `mini`
102
- let normalizedDecorator = /*#__PURE__*/React.isValidElement(slug ?? decorator) ? slug ?? decorator : null;
103
- if (normalizedDecorator && normalizedDecorator['type']?.displayName === 'AILabel') {
104
- normalizedDecorator = /*#__PURE__*/React.cloneElement(normalizedDecorator, {
105
- size: 'mini'
106
- });
107
- }
104
+ const candidate = slug ?? decorator;
105
+ const candidateIsAILabel = isComponentElement(candidate, AILabel);
106
+ const normalizedDecorator = candidateIsAILabel ? /*#__PURE__*/cloneElement(candidate, {
107
+ size: 'mini'
108
+ }) : null;
108
109
  return /*#__PURE__*/React.createElement("div", {
109
110
  className: containerClasses
110
111
  }, labelText && /*#__PURE__*/React.createElement(Text, {
@@ -4,7 +4,7 @@
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, { type HTMLAttributes } from 'react';
7
+ import React, { type HTMLAttributes, type RefObject } from 'react';
8
8
  import { InlineLoadingStatus } from '../InlineLoading/InlineLoading';
9
9
  /**
10
10
  * ----------
@@ -20,6 +20,10 @@ interface DialogProps extends HTMLAttributes<HTMLDialogElement> {
20
20
  * Specify an optional className to be applied to the modal root node
21
21
  */
22
22
  className?: string;
23
+ /**
24
+ * Provide a ref to return focus to once the dialog is closed.
25
+ */
26
+ focusAfterCloseRef?: RefObject<HTMLElement | null>;
23
27
  /**
24
28
  * Specifies whether the dialog is modal or non-modal. This cannot be changed
25
29
  * while open=true