@carbon/react 1.84.0 → 1.85.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 (181) hide show
  1. package/.playwright/INTERNAL_AVT_REPORT_DO_NOT_USE.json +899 -829
  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 +15 -10
  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/DatePicker/DatePicker.d.ts +1 -1
  24. package/es/components/DatePicker/DatePicker.js +2 -2
  25. package/es/components/DatePicker/plugins/appendToPlugin.d.ts +12 -0
  26. package/es/components/DatePicker/plugins/appendToPlugin.js +9 -12
  27. package/es/components/DatePickerInput/DatePickerInput.js +8 -7
  28. package/es/components/Dialog/index.d.ts +5 -1
  29. package/es/components/Dialog/index.js +20 -0
  30. package/es/components/Dropdown/Dropdown.d.ts +1 -1
  31. package/es/components/Dropdown/Dropdown.js +8 -10
  32. package/es/components/FileUploader/FileUploaderButton.js +2 -2
  33. package/es/components/FileUploader/FileUploaderDropContainer.js +2 -2
  34. package/es/components/FileUploader/FileUploaderItem.js +2 -2
  35. package/es/components/Layer/index.d.ts +1 -3
  36. package/es/components/Layer/index.js +9 -8
  37. package/es/components/Menu/Menu.js +7 -8
  38. package/es/components/Menu/MenuItem.js +13 -2
  39. package/es/components/Modal/Modal.d.ts +2 -2
  40. package/es/components/Modal/Modal.js +20 -9
  41. package/es/components/MultiSelect/FilterableMultiSelect.d.ts +1 -1
  42. package/es/components/MultiSelect/FilterableMultiSelect.js +9 -8
  43. package/es/components/MultiSelect/MultiSelect.d.ts +1 -1
  44. package/es/components/MultiSelect/MultiSelect.js +8 -7
  45. package/es/components/MultiSelect/filter.d.ts +10 -0
  46. package/es/components/MultiSelect/filter.js +21 -0
  47. package/es/components/NumberInput/NumberInput.d.ts +1 -1
  48. package/es/components/NumberInput/NumberInput.js +9 -8
  49. package/es/components/PageHeader/PageHeader.js +2 -2
  50. package/es/components/Popover/index.js +2 -1
  51. package/es/components/RadioButton/RadioButton.d.ts +2 -2
  52. package/es/components/RadioButton/RadioButton.js +8 -8
  53. package/es/components/RadioButtonGroup/RadioButtonGroup.d.ts +2 -2
  54. package/es/components/RadioButtonGroup/RadioButtonGroup.js +9 -8
  55. package/es/components/RadioTile/RadioTile.d.ts +1 -1
  56. package/es/components/RadioTile/RadioTile.js +8 -7
  57. package/es/components/Select/Select.d.ts +2 -2
  58. package/es/components/Select/Select.js +8 -7
  59. package/es/components/Slider/Slider.d.ts +59 -198
  60. package/es/components/Slider/Slider.js +68 -120
  61. package/es/components/Tabs/usePressable.d.ts +19 -0
  62. package/es/components/Tabs/usePressable.js +19 -33
  63. package/es/components/Tag/DismissibleTag.d.ts +1 -1
  64. package/es/components/Tag/DismissibleTag.js +9 -8
  65. package/es/components/Tag/Tag.d.ts +1 -1
  66. package/es/components/Tag/Tag.js +9 -8
  67. package/es/components/TextArea/TextArea.js +8 -7
  68. package/es/components/TextInput/TextInput.d.ts +1 -1
  69. package/es/components/TextInput/TextInput.js +20 -9
  70. package/es/components/Tile/Tile.d.ts +2 -2
  71. package/es/components/Tile/Tile.js +30 -36
  72. package/es/components/Toggletip/index.js +2 -2
  73. package/es/components/Tooltip/DefinitionTooltip.js +1 -0
  74. package/es/components/Tooltip/Tooltip.d.ts +2 -2
  75. package/es/components/Tooltip/Tooltip.js +2 -2
  76. package/es/components/TreeView/TreeNode.d.ts +22 -0
  77. package/es/components/TreeView/TreeNode.js +119 -12
  78. package/es/components/TreeView/TreeView.js +3 -3
  79. package/es/components/UIShell/Content.d.ts +5 -3
  80. package/es/components/UIShell/HeaderPanel.d.ts +2 -2
  81. package/es/components/UIShell/HeaderPanel.js +9 -5
  82. package/es/internal/Selection.js +8 -3
  83. package/es/internal/environment.js +1 -12
  84. package/{lib/internal/__mocks__/mockHTMLElement.d.ts → es/internal/index.d.ts} +2 -4
  85. package/es/internal/useResizeObserver.d.ts +1 -1
  86. package/es/internal/utils.d.ts +14 -0
  87. package/es/internal/utils.js +18 -0
  88. package/es/tools/uniqueId.d.ts +1 -6
  89. package/lib/components/AILabel/index.js +6 -1
  90. package/lib/components/Checkbox/Checkbox.d.ts +2 -2
  91. package/lib/components/Checkbox/Checkbox.js +7 -7
  92. package/lib/components/CheckboxGroup/CheckboxGroup.d.ts +2 -2
  93. package/lib/components/CheckboxGroup/CheckboxGroup.js +8 -7
  94. package/lib/components/CodeSnippet/CodeSnippet.js +2 -4
  95. package/lib/components/ComboBox/ComboBox.d.ts +1 -1
  96. package/lib/components/ComboBox/ComboBox.js +11 -10
  97. package/lib/components/ComposedModal/ComposedModal.d.ts +1 -1
  98. package/lib/components/ComposedModal/ComposedModal.js +16 -11
  99. package/lib/components/ContainedList/ContainedList.d.ts +1 -1
  100. package/lib/components/ContainedList/ContainedList.js +4 -2
  101. package/lib/components/ContentSwitcher/ContentSwitcher.js +5 -4
  102. package/lib/components/DataTable/DataTable.js +3 -0
  103. package/lib/components/DataTable/TableDecoratorRow.d.ts +2 -2
  104. package/lib/components/DataTable/TableDecoratorRow.js +8 -8
  105. package/lib/components/DataTable/TableExpandRow.d.ts +1 -1
  106. package/lib/components/DataTable/TableExpandRow.js +14 -5
  107. package/lib/components/DataTable/TableHeader.js +9 -9
  108. package/lib/components/DataTable/TableRow.js +11 -3
  109. package/lib/components/DataTable/tools/normalize.js +2 -1
  110. package/lib/components/DatePicker/DatePicker.d.ts +1 -1
  111. package/lib/components/DatePicker/DatePicker.js +1 -1
  112. package/lib/components/DatePicker/plugins/appendToPlugin.d.ts +12 -0
  113. package/lib/components/DatePicker/plugins/appendToPlugin.js +9 -12
  114. package/lib/components/DatePickerInput/DatePickerInput.js +7 -6
  115. package/lib/components/Dialog/index.d.ts +5 -1
  116. package/lib/components/Dialog/index.js +20 -0
  117. package/lib/components/Dropdown/Dropdown.d.ts +1 -1
  118. package/lib/components/Dropdown/Dropdown.js +12 -14
  119. package/lib/components/FileUploader/FileUploaderButton.js +2 -2
  120. package/lib/components/FileUploader/FileUploaderDropContainer.js +2 -2
  121. package/lib/components/FileUploader/FileUploaderItem.js +2 -2
  122. package/lib/components/Layer/index.d.ts +1 -3
  123. package/lib/components/Layer/index.js +9 -8
  124. package/lib/components/Menu/Menu.js +7 -8
  125. package/lib/components/Menu/MenuItem.js +13 -2
  126. package/lib/components/Modal/Modal.d.ts +2 -2
  127. package/lib/components/Modal/Modal.js +28 -17
  128. package/lib/components/MultiSelect/FilterableMultiSelect.d.ts +1 -1
  129. package/lib/components/MultiSelect/FilterableMultiSelect.js +13 -12
  130. package/lib/components/MultiSelect/MultiSelect.d.ts +1 -1
  131. package/lib/components/MultiSelect/MultiSelect.js +13 -12
  132. package/lib/components/MultiSelect/filter.d.ts +10 -0
  133. package/lib/components/MultiSelect/filter.js +25 -0
  134. package/lib/components/NumberInput/NumberInput.d.ts +1 -1
  135. package/lib/components/NumberInput/NumberInput.js +8 -7
  136. package/lib/components/PageHeader/PageHeader.js +2 -2
  137. package/lib/components/Popover/index.js +2 -1
  138. package/lib/components/RadioButton/RadioButton.d.ts +2 -2
  139. package/lib/components/RadioButton/RadioButton.js +7 -7
  140. package/lib/components/RadioButtonGroup/RadioButtonGroup.d.ts +2 -2
  141. package/lib/components/RadioButtonGroup/RadioButtonGroup.js +10 -9
  142. package/lib/components/RadioTile/RadioTile.d.ts +1 -1
  143. package/lib/components/RadioTile/RadioTile.js +7 -6
  144. package/lib/components/Select/Select.d.ts +2 -2
  145. package/lib/components/Select/Select.js +7 -6
  146. package/lib/components/Slider/Slider.d.ts +59 -198
  147. package/lib/components/Slider/Slider.js +67 -119
  148. package/lib/components/Tabs/usePressable.d.ts +19 -0
  149. package/lib/components/Tabs/usePressable.js +19 -33
  150. package/lib/components/Tag/DismissibleTag.d.ts +1 -1
  151. package/lib/components/Tag/DismissibleTag.js +8 -7
  152. package/lib/components/Tag/Tag.d.ts +1 -1
  153. package/lib/components/Tag/Tag.js +8 -7
  154. package/lib/components/TextArea/TextArea.js +7 -6
  155. package/lib/components/TextInput/TextInput.d.ts +1 -1
  156. package/lib/components/TextInput/TextInput.js +19 -8
  157. package/lib/components/Tile/Tile.d.ts +2 -2
  158. package/lib/components/Tile/Tile.js +29 -35
  159. package/lib/components/Toggletip/index.js +2 -2
  160. package/lib/components/Tooltip/DefinitionTooltip.js +1 -0
  161. package/lib/components/Tooltip/Tooltip.d.ts +2 -2
  162. package/lib/components/Tooltip/Tooltip.js +2 -2
  163. package/lib/components/TreeView/TreeNode.d.ts +22 -0
  164. package/lib/components/TreeView/TreeNode.js +118 -11
  165. package/lib/components/TreeView/TreeView.js +3 -3
  166. package/lib/components/UIShell/Content.d.ts +5 -3
  167. package/lib/components/UIShell/HeaderPanel.d.ts +2 -2
  168. package/lib/components/UIShell/HeaderPanel.js +8 -4
  169. package/lib/internal/Selection.js +8 -3
  170. package/lib/internal/environment.js +1 -12
  171. package/{es/internal/__mocks__/mockHTMLElement.d.ts → lib/internal/index.d.ts} +2 -4
  172. package/lib/internal/useResizeObserver.d.ts +1 -1
  173. package/lib/internal/utils.d.ts +14 -0
  174. package/lib/internal/utils.js +22 -0
  175. package/lib/tools/uniqueId.d.ts +1 -6
  176. package/package.json +11 -20
  177. package/telemetry.yml +1 -0
  178. package/es/components/ComboBox/tools/filter.js +0 -18
  179. package/es/tools/uniqueId.js +0 -14
  180. package/lib/components/ComboBox/tools/filter.js +0 -22
  181. package/lib/tools/uniqueId.js +0 -18
@@ -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
@@ -35,6 +35,7 @@ const DialogContext = /*#__PURE__*/createContext({});
35
35
  const unstable__Dialog = /*#__PURE__*/React.forwardRef(({
36
36
  children,
37
37
  className,
38
+ focusAfterCloseRef,
38
39
  modal,
39
40
  onCancel = noopFn,
40
41
  onClick = noopFn,
@@ -93,6 +94,19 @@ const unstable__Dialog = /*#__PURE__*/React.forwardRef(({
93
94
  }
94
95
  }
95
96
  }, [modal, open]);
97
+ useEffect(() => {
98
+ if (!open && focusAfterCloseRef) {
99
+ // use setTimeout to ensure focus is set after all other default focus behavior
100
+ const moveFocus = setTimeout(() => {
101
+ focusAfterCloseRef.current?.focus();
102
+ });
103
+
104
+ //component did unmount equivalent
105
+ return () => {
106
+ clearTimeout(moveFocus);
107
+ };
108
+ }
109
+ }, [open, focusAfterCloseRef]);
96
110
  const containerClasses = cx(`${prefix}--dialog-container`);
97
111
  const contextValue = {
98
112
  dialogId,
@@ -138,6 +152,12 @@ unstable__Dialog.propTypes = {
138
152
  * Specify an optional className to be applied to the modal root node
139
153
  */
140
154
  className: PropTypes.string,
155
+ /**
156
+ * Provide a ref to return focus to once the dialog is closed.
157
+ */
158
+ focusAfterCloseRef: PropTypes.oneOfType([PropTypes.func, PropTypes.shape({
159
+ current: PropTypes.any
160
+ })]),
141
161
  /**
142
162
  * Modal specifies whether the Dialog is modal or non-modal. This cannot be
143
163
  * changed while open=true
@@ -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, { Ref, type HTMLAttributes, type ReactNode } from 'react';
7
+ import React, { type HTMLAttributes, type ReactNode, type Ref } from 'react';
8
8
  import { UseSelectProps } from 'downshift';
9
9
  import { type ListBoxMenuIconTranslationKey, type ListBoxSize, type ListBoxType } from '../ListBox';
10
10
  import { TranslateWithId } from '../../types/common';
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
9
- import React, { useEffect, useContext, useCallback, useMemo, useState, isValidElement } from 'react';
9
+ import React, { useEffect, useContext, useCallback, useMemo, useState, isValidElement, cloneElement } from 'react';
10
10
  import { useSelect } from 'downshift';
11
11
  import cx from 'classnames';
12
12
  import PropTypes from 'prop-types';
@@ -20,6 +20,8 @@ import { FormContext } from '../FluidForm/FormContext.js';
20
20
  import { useId } from '../../internal/useId.js';
21
21
  import { useFloating, size, flip, hide, autoUpdate } from '@floating-ui/react';
22
22
  import { useFeatureFlag } from '../FeatureFlags/index.js';
23
+ import { AILabel } from '../AILabel/index.js';
24
+ import { isComponentElement } from '../../internal/utils.js';
23
25
  import { ListBoxSizePropType, ListBoxTypePropType } from '../ListBox/ListBoxPropTypes.js';
24
26
 
25
27
  const {
@@ -308,15 +310,11 @@ const Dropdown = /*#__PURE__*/React.forwardRef(({
308
310
  }), [autoAlign, getMenuProps, refs.setFloating, enableFloatingStyles]);
309
311
 
310
312
  // AILabel is always size `mini`
311
- const normalizedDecorator = useMemo(() => {
312
- let element = slug ?? decorator;
313
- if (element && element['type']?.displayName === 'AILabel') {
314
- return /*#__PURE__*/React.cloneElement(element, {
315
- size: 'mini'
316
- });
317
- }
318
- return /*#__PURE__*/React.isValidElement(element) ? element : null;
319
- }, [slug, decorator]);
313
+ const candidate = slug ?? decorator;
314
+ const candidateIsAILabel = isComponentElement(candidate, AILabel);
315
+ const normalizedDecorator = candidateIsAILabel ? /*#__PURE__*/cloneElement(candidate, {
316
+ size: 'mini'
317
+ }) : null;
320
318
  const allLabelProps = getLabelProps();
321
319
  const labelProps = /*#__PURE__*/isValidElement(titleText) ? {
322
320
  id: allLabelProps.id
@@ -11,7 +11,7 @@ import PropTypes from 'prop-types';
11
11
  import React, { useState, useRef } from 'react';
12
12
  import { Enter, Space } from '../../internal/keyboard/keys.js';
13
13
  import { matches } from '../../internal/keyboard/match.js';
14
- import { uniqueId } from '../../tools/uniqueId.js';
14
+ import { useId } from '../../internal/useId.js';
15
15
  import { usePrefix } from '../../internal/usePrefix.js';
16
16
  import deprecate from '../../prop-types/deprecate.js';
17
17
  import { noopFn } from '../../internal/noopFn.js';
@@ -39,7 +39,7 @@ function FileUploaderButton({
39
39
  const [prevOwnerLabelText, setPrevOwnerLabelText] = useState(ownerLabelText);
40
40
  const {
41
41
  current: inputId
42
- } = useRef(id || uniqueId());
42
+ } = useRef(id || useId());
43
43
  const inputNode = useRef(null);
44
44
  const classes = cx(`${prefix}--btn`, className, {
45
45
  [`${prefix}--btn--${buttonKind}`]: buttonKind,
@@ -11,7 +11,7 @@ import PropTypes from 'prop-types';
11
11
  import cx from 'classnames';
12
12
  import { Enter, Space } from '../../internal/keyboard/keys.js';
13
13
  import { matches } from '../../internal/keyboard/match.js';
14
- import { uniqueId } from '../../tools/uniqueId.js';
14
+ import { useId } from '../../internal/useId.js';
15
15
  import { usePrefix } from '../../internal/usePrefix.js';
16
16
  import { composeEventHandlers } from '../../tools/events.js';
17
17
  import deprecate from '../../prop-types/deprecate.js';
@@ -36,7 +36,7 @@ function FileUploaderDropContainer({
36
36
  const inputRef = useRef(null);
37
37
  const {
38
38
  current: uid
39
- } = useRef(id || uniqueId());
39
+ } = useRef(id || useId());
40
40
  const [isActive, setActive] = useState(false);
41
41
  const dropareaClasses = cx(`${prefix}--file__drop-container`, `${prefix}--file-browse-btn`, {
42
42
  [`${prefix}--file__drop-container--drag-over`]: isActive,
@@ -12,7 +12,7 @@ import React, { useRef, useState, useLayoutEffect } 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
- import { uniqueId } from '../../tools/uniqueId.js';
15
+ import { useId } from '../../internal/useId.js';
16
16
  import { usePrefix } from '../../internal/usePrefix.js';
17
17
  import { noopFn } from '../../internal/noopFn.js';
18
18
  import '../Text/index.js';
@@ -38,7 +38,7 @@ function FileUploaderItem({
38
38
  const prefix = usePrefix();
39
39
  const {
40
40
  current: id
41
- } = useRef(uuid || uniqueId());
41
+ } = useRef(uuid || useId());
42
42
  const classes = cx(`${prefix}--file__selected-file`, className, {
43
43
  [`${prefix}--file__selected-file--invalid`]: invalid,
44
44
  [`${prefix}--file__selected-file--md`]: size === 'md',
@@ -35,7 +35,5 @@ export interface LayerBaseProps {
35
35
  withBackground?: boolean;
36
36
  }
37
37
  export type LayerProps<T extends React.ElementType> = PolymorphicComponentPropWithRef<T, LayerBaseProps>;
38
- declare const Layer: React.ForwardRefExoticComponent<LayerBaseProps & {
39
- as?: React.ElementType;
40
- } & React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<any>>;
38
+ declare const Layer: React.ForwardRefExoticComponent<Omit<LayerProps<React.ElementType<any, keyof React.JSX.IntrinsicElements>>, "ref"> & React.RefAttributes<unknown>>;
41
39
  export { Layer };
@@ -25,14 +25,15 @@ function useLayer() {
25
25
  level
26
26
  };
27
27
  }
28
- const Layer = /*#__PURE__*/React.forwardRef(({
29
- as,
30
- className: customClassName,
31
- children,
32
- level: overrideLevel,
33
- withBackground = false,
34
- ...rest
35
- }, ref) => {
28
+ const Layer = /*#__PURE__*/React.forwardRef((props, ref) => {
29
+ const {
30
+ as,
31
+ className: customClassName,
32
+ children,
33
+ level: overrideLevel,
34
+ withBackground = false,
35
+ ...rest
36
+ } = props;
36
37
  const contextLevel = React.useContext(LayerContext);
37
38
  const level = overrideLevel ?? contextLevel;
38
39
  const prefix = usePrefix();
@@ -34,12 +34,6 @@ const Menu = /*#__PURE__*/forwardRef(function Menu({
34
34
  open,
35
35
  size = 'sm',
36
36
  legacyAutoalign = 'true',
37
- // TODO: `ssr-friendly` doesn't support ESLint v9.
38
- // https://github.com/kopiro/eslint-plugin-ssr-friendly/issues/30
39
- // https://github.com/carbon-design-system/carbon/issues/18991
40
- /*
41
- // eslint-disable-next-line ssr-friendly/no-dom-globals-in-react-fc
42
- */
43
37
  target = canUseDOM && document.body,
44
38
  x = 0,
45
39
  y = 0,
@@ -250,8 +244,13 @@ const Menu = /*#__PURE__*/forwardRef(function Menu({
250
244
  return [fitValue(ranges.x, 'x') ?? -1, fitValue(ranges.y, 'y') ?? -1];
251
245
  }
252
246
  useEffect(() => {
253
- if (open && focusableItems.length > 0) {
254
- focusItem();
247
+ if (open) {
248
+ const raf = requestAnimationFrame(() => {
249
+ if (focusableItems.length > 0) {
250
+ focusItem();
251
+ }
252
+ });
253
+ return () => cancelAnimationFrame(raf);
255
254
  }
256
255
  // eslint-disable-next-line react-hooks/exhaustive-deps
257
256
  }, [open, focusableItems]);
@@ -107,7 +107,11 @@ const MenuItem = /*#__PURE__*/forwardRef(function MenuItem({
107
107
  function handleKeyDown(e) {
108
108
  if (hasChildren && match(e, ArrowRight)) {
109
109
  openSubmenu();
110
+ requestAnimationFrame(() => {
111
+ refs.floating.current?.focus();
112
+ });
110
113
  e.stopPropagation();
114
+ e.preventDefault();
111
115
  }
112
116
  pendingKeyboardClick.current = keyboardClickEvent(e);
113
117
  if (rest.onKeyDown) {
@@ -124,11 +128,18 @@ const MenuItem = /*#__PURE__*/forwardRef(function MenuItem({
124
128
  [`${prefix}--menu-item--disabled`]: isDisabled,
125
129
  [`${prefix}--menu-item--danger`]: isDanger
126
130
  });
127
-
131
+ const [isFocusable, setIsFocusable] = useState(false);
128
132
  // on first render, register this menuitem in the context's state
129
133
  // (used for keyboard navigation)
130
134
  useEffect(() => {
131
135
  registerItem();
136
+
137
+ // Detects if this is the first focusable item
138
+ const currentItems = context.state.items;
139
+ if (!disabled && menuItem.current && currentItems.length === 0) {
140
+ setIsFocusable(true);
141
+ }
142
+
132
143
  // eslint-disable-next-line react-hooks/exhaustive-deps
133
144
  }, []);
134
145
 
@@ -167,7 +178,7 @@ const MenuItem = /*#__PURE__*/forwardRef(function MenuItem({
167
178
  }, rest, {
168
179
  ref: ref,
169
180
  className: classNames,
170
- tabIndex: -1,
181
+ tabIndex: isFocusable ? 0 : -1,
171
182
  "aria-disabled": isDisabled ?? undefined,
172
183
  "aria-haspopup": hasChildren ?? undefined,
173
184
  "aria-expanded": hasChildren ? submenuOpen : undefined,
@@ -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, type ReactNode, type Ref } from 'react';
7
+ import React, { type HTMLAttributes, type ReactNode, type RefObject } from 'react';
8
8
  import { InlineLoadingStatus } from '../InlineLoading/InlineLoading';
9
9
  export declare const ModalSizes: readonly ["xs", "sm", "md", "lg"];
10
10
  export type ModalSize = (typeof ModalSizes)[number];
@@ -57,7 +57,7 @@ export interface ModalProps extends HTMLAttributes<HTMLDivElement> {
57
57
  /**
58
58
  * Provide a ref to return focus to once the modal is closed.
59
59
  */
60
- launcherButtonRef?: Ref<HTMLButtonElement>;
60
+ launcherButtonRef?: RefObject<HTMLButtonElement | null>;
61
61
  /**
62
62
  * Specify the description for the loading text
63
63
  */
@@ -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, useEffect } from 'react';
10
+ import React, { useRef, useState, useEffect, cloneElement } from 'react';
11
11
  import cx from 'classnames';
12
12
  import { Close } from '@carbon/icons-react';
13
13
  import { toggleClass } from '../../tools/toggleClass.js';
@@ -31,11 +31,14 @@ import { useFeatureFlag } from '../FeatureFlags/index.js';
31
31
  import { composeEventHandlers } from '../../tools/events.js';
32
32
  import deprecate from '../../prop-types/deprecate.js';
33
33
  import { unstable__Dialog } from '../Dialog/index.js';
34
+ import { AILabel } from '../AILabel/index.js';
35
+ import { isComponentElement } from '../../internal/utils.js';
34
36
  import { warning } from '../../internal/warning.js';
35
37
  import { debounce } from '../../node_modules/es-toolkit/dist/compat/function/debounce.mjs.js';
36
38
  import { Text } from '../Text/Text.js';
37
39
 
38
40
  const ModalSizes = ['xs', 'sm', 'md', 'lg'];
41
+ const invalidOutsideClickMessage = '`Modal`: `preventCloseOnClickOutside` should not be `false` when `passiveModal` is `false`. Non-passive `Modal`s should not be dismissible by clicking outside.';
39
42
  const Modal = /*#__PURE__*/React.forwardRef(function Modal({
40
43
  'aria-label': ariaLabelProp,
41
44
  children,
@@ -61,7 +64,7 @@ const Modal = /*#__PURE__*/React.forwardRef(function Modal({
61
64
  size,
62
65
  hasScrollingContent = false,
63
66
  closeButtonLabel = 'Close',
64
- preventCloseOnClickOutside = false,
67
+ preventCloseOnClickOutside = !passiveModal,
65
68
  isFullWidth,
66
69
  launcherButtonRef,
67
70
  loadingStatus = 'inactive',
@@ -92,6 +95,9 @@ const Modal = /*#__PURE__*/React.forwardRef(function Modal({
92
95
  const focusTrapWithoutSentinels = useFeatureFlag('enable-experimental-focus-wrap-without-sentinels');
93
96
  const enableDialogElement = useFeatureFlag('enable-dialog-element');
94
97
  process.env.NODE_ENV !== "production" ? warning(!(focusTrapWithoutSentinels && enableDialogElement), '`<Modal>` detected both `focusTrapWithoutSentinels` and ' + '`enableDialogElement` feature flags are enabled. The native dialog ' + 'element handles focus, so `enableDialogElement` must be off for ' + '`focusTrapWithoutSentinels` to have any effect.') : void 0;
98
+ if (!passiveModal && preventCloseOnClickOutside === false) {
99
+ console.error(invalidOutsideClickMessage);
100
+ }
95
101
  function isCloseButton(element) {
96
102
  return !onSecondarySubmit && element === secondaryButton.current || element.classList.contains(modalCloseButtonClass);
97
103
  }
@@ -265,12 +271,11 @@ const Modal = /*#__PURE__*/React.forwardRef(function Modal({
265
271
  }, []);
266
272
 
267
273
  // AILabel always size `sm`
268
- let normalizedDecorator = /*#__PURE__*/React.isValidElement(slug ?? decorator) ? slug ?? decorator : null;
269
- if (normalizedDecorator && normalizedDecorator['type']?.displayName === 'AILabel') {
270
- normalizedDecorator = /*#__PURE__*/React.cloneElement(normalizedDecorator, {
271
- size: 'sm'
272
- });
273
- }
274
+ const candidate = slug ?? decorator;
275
+ const candidateIsAILabel = isComponentElement(candidate, AILabel);
276
+ const normalizedDecorator = candidateIsAILabel ? /*#__PURE__*/cloneElement(candidate, {
277
+ size: 'sm'
278
+ }) : null;
274
279
  const modalButton = /*#__PURE__*/React.createElement("div", {
275
280
  className: `${prefix}--modal-close-button`
276
281
  }, /*#__PURE__*/React.createElement(IconButton, {
@@ -292,6 +297,7 @@ const Modal = /*#__PURE__*/React.forwardRef(function Modal({
292
297
  const isAlertDialog = alert && !passiveModal;
293
298
  const modalBody = enableDialogElement ? /*#__PURE__*/React.createElement(unstable__Dialog, {
294
299
  open: open,
300
+ focusAfterCloseRef: launcherButtonRef,
295
301
  modal: true,
296
302
  ref: innerModal,
297
303
  role: isAlertDialog ? 'alertdialog' : '',
@@ -538,7 +544,12 @@ Modal.propTypes = {
538
544
  /**
539
545
  * Prevent closing on click outside of modal
540
546
  */
541
- preventCloseOnClickOutside: PropTypes.bool,
547
+ preventCloseOnClickOutside: (props, propName) => {
548
+ if (!props.passiveModal && props[propName] === false) {
549
+ return new Error(invalidOutsideClickMessage);
550
+ }
551
+ return null;
552
+ },
542
553
  /**
543
554
  * Specify whether the Button should be disabled, or not
544
555
  */
@@ -5,7 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  import { type UseComboboxProps, type UseMultipleSelectionProps } from 'downshift';
8
- import React, { ReactNode, FunctionComponent, ReactElement } from 'react';
8
+ import React, { type FunctionComponent, type ReactElement, type ReactNode } from 'react';
9
9
  import { type MultiSelectSortingProps } from './MultiSelectPropTypes';
10
10
  import { type ListBoxSize, type ListBoxType } from '../ListBox';
11
11
  import { TranslateWithId } from '../../types/common';
@@ -11,8 +11,8 @@ import cx from 'classnames';
11
11
  import Downshift, { useCombobox, useMultipleSelection } from 'downshift';
12
12
  import isEqual from 'react-fast-compare';
13
13
  import PropTypes from 'prop-types';
14
- import React, { forwardRef, useContext, useRef, useState, useLayoutEffect, useMemo, useEffect } from 'react';
15
- import { defaultFilterItems } from '../ComboBox/tools/filter.js';
14
+ import React, { forwardRef, useContext, useRef, useState, useLayoutEffect, useMemo, useEffect, cloneElement } from 'react';
15
+ import { defaultFilterItems } from './filter.js';
16
16
  import { sortingPropTypes } from './MultiSelectPropTypes.js';
17
17
  import ListBox from '../ListBox/index.js';
18
18
  import ListBoxSelection from '../ListBox/next/ListBoxSelection.js';
@@ -29,6 +29,8 @@ import '../FluidForm/FluidForm.js';
29
29
  import { FormContext } from '../FluidForm/FormContext.js';
30
30
  import { useSelection } from '../../internal/Selection.js';
31
31
  import { useFloating, flip, size, hide, autoUpdate } from '@floating-ui/react';
32
+ import { AILabel } from '../AILabel/index.js';
33
+ import { isComponentElement } from '../../internal/utils.js';
32
34
  import { ListBoxSizePropType, ListBoxTypePropType } from '../ListBox/ListBoxPropTypes.js';
33
35
 
34
36
  const {
@@ -444,12 +446,11 @@ const FilterableMultiSelect = /*#__PURE__*/forwardRef(function FilterableMultiSe
444
446
  }
445
447
 
446
448
  // AILabel always size `mini`
447
- let normalizedDecorator = /*#__PURE__*/React.isValidElement(slug ?? decorator) ? slug ?? decorator : null;
448
- if (normalizedDecorator && normalizedDecorator['type']?.displayName === 'AILabel') {
449
- normalizedDecorator = /*#__PURE__*/React.cloneElement(normalizedDecorator, {
450
- size: 'mini'
451
- });
452
- }
449
+ const candidate = slug ?? decorator;
450
+ const candidateIsAILabel = isComponentElement(candidate, AILabel);
451
+ const normalizedDecorator = candidateIsAILabel ? /*#__PURE__*/cloneElement(candidate, {
452
+ size: 'mini'
453
+ }) : null;
453
454
  const className = cx(`${prefix}--multi-select`, `${prefix}--combo-box`, `${prefix}--multi-select--filterable`, {
454
455
  [`${prefix}--multi-select--invalid`]: invalid,
455
456
  [`${prefix}--multi-select--invalid--focused`]: invalid && inputFocused,
@@ -5,7 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  import { UseSelectProps } from 'downshift';
8
- import React, { ReactNode } from 'react';
8
+ import React, { type ReactNode } from 'react';
9
9
  import { type ListBoxSize, type ListBoxType } from '../ListBox';
10
10
  import { MultiSelectSortingProps } from './MultiSelectPropTypes';
11
11
  import { ListBoxProps } from '../ListBox/ListBox';
@@ -11,7 +11,7 @@ import cx from 'classnames';
11
11
  import { useSelect } from 'downshift';
12
12
  import isEqual from 'react-fast-compare';
13
13
  import PropTypes from 'prop-types';
14
- import React, { useMemo, useContext, useState, useLayoutEffect, isValidElement, useCallback } from 'react';
14
+ import React, { useMemo, useContext, useState, useLayoutEffect, isValidElement, useCallback, cloneElement } from 'react';
15
15
  import ListBox from '../ListBox/index.js';
16
16
  import { sortingPropTypes } from './MultiSelectPropTypes.js';
17
17
  import { defaultSortItems, defaultCompareItems } from './tools/sorting.js';
@@ -29,6 +29,8 @@ import '../Checkbox/Checkbox.Skeleton.js';
29
29
  import { noopFn } from '../../internal/noopFn.js';
30
30
  import { useFloating, flip, size, hide, autoUpdate } from '@floating-ui/react';
31
31
  import { useFeatureFlag } from '../FeatureFlags/index.js';
32
+ import { AILabel } from '../AILabel/index.js';
33
+ import { isComponentElement } from '../../internal/utils.js';
32
34
  import { ListBoxSizePropType, ListBoxTypePropType } from '../ListBox/ListBoxPropTypes.js';
33
35
 
34
36
  const {
@@ -409,12 +411,11 @@ const MultiSelect = /*#__PURE__*/React.forwardRef(({
409
411
  } : {};
410
412
 
411
413
  // AILabel always size `mini`
412
- let normalizedDecorator = /*#__PURE__*/React.isValidElement(slug ?? decorator) ? slug ?? decorator : null;
413
- if (normalizedDecorator && normalizedDecorator['type']?.displayName === 'AILabel') {
414
- normalizedDecorator = /*#__PURE__*/React.cloneElement(normalizedDecorator, {
415
- size: 'mini'
416
- });
417
- }
414
+ const candidate = slug ?? decorator;
415
+ const candidateIsAILabel = isComponentElement(candidate, AILabel);
416
+ const normalizedDecorator = candidateIsAILabel ? /*#__PURE__*/cloneElement(candidate, {
417
+ size: 'mini'
418
+ }) : null;
418
419
  const itemsSelectedText = selectedItems.length > 0 && selectedItems.map(item => item?.text);
419
420
  const selectedItemsLength = selectAll ? selectedItems.filter(item => !item.isSelectAll).length : selectedItems.length;
420
421
 
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Copyright IBM Corp. 2016, 2025
3
+ *
4
+ * This source code is licensed under the Apache-2.0 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ export declare const defaultFilterItems: <ItemType>(items: ItemType[], { itemToString, inputValue, }: {
8
+ itemToString: (item: ItemType | null) => string;
9
+ inputValue: string | null;
10
+ }) => ItemType[];
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Copyright IBM Corp. 2016, 2023
3
+ *
4
+ * This source code is licensed under the Apache-2.0 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ // TODO [@carbon-design-system/monorepo-reviewers]: This file was in the
9
+ // `ComboBox` directory before but it wasn't used there. Now it's used in
10
+ // `FilterableMultiSelect`. Is that expected?
11
+
12
+ const defaultFilterItems = (items, {
13
+ itemToString,
14
+ inputValue
15
+ }) => {
16
+ if (!inputValue) return items;
17
+ const normalizedInput = inputValue.toLowerCase();
18
+ return items.filter(item => itemToString(item).toLowerCase().includes(normalizedInput));
19
+ };
20
+
21
+ export { defaultFilterItems };
@@ -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, { ReactNode } from 'react';
7
+ import React, { type ReactNode } from 'react';
8
8
  import { TranslateWithId } from '../../types/common';
9
9
  import { type NumberFormatOptions } from '@carbon/utilities';
10
10
  export declare const translationIds: {
@@ -9,7 +9,7 @@ import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js
9
9
  import { Subtract, Add } from '@carbon/icons-react';
10
10
  import cx from 'classnames';
11
11
  import PropTypes from 'prop-types';
12
- import React, { useContext, useState, useMemo, useCallback, useRef, useEffect } from 'react';
12
+ import React, { useContext, useState, useMemo, useCallback, useRef, useEffect, cloneElement } from 'react';
13
13
  import { useMergedRefs } from '../../internal/useMergedRefs.js';
14
14
  import { useNormalizedInputProps } from '../../internal/useNormalizedInputProps.js';
15
15
  import { usePrefix } from '../../internal/usePrefix.js';
@@ -23,6 +23,8 @@ import { NumberParser, NumberFormatter } from '@carbon/utilities';
23
23
  import { ArrowUp, ArrowDown } from '../../internal/keyboard/keys.js';
24
24
  import { match } from '../../internal/keyboard/match.js';
25
25
  import { NumberFormatOptionsPropType } from './NumberFormatPropTypes.js';
26
+ import { AILabel } from '../AILabel/index.js';
27
+ import { isComponentElement } from '../../internal/utils.js';
26
28
  import { Text } from '../Text/Text.js';
27
29
 
28
30
  var _Subtract, _Add;
@@ -262,16 +264,15 @@ const NumberInput = /*#__PURE__*/React.forwardRef(function NumberInput(props, fo
262
264
  };
263
265
 
264
266
  // AILabel always size `mini`
265
- let normalizedDecorator = /*#__PURE__*/React.isValidElement(slug ?? decorator) ? slug ?? decorator : null;
266
- if (normalizedDecorator && normalizedDecorator['type']?.displayName === 'AILabel') {
267
- normalizedDecorator = /*#__PURE__*/React.cloneElement(normalizedDecorator, {
268
- size: 'mini'
269
- });
270
- }
267
+ const candidate = slug ?? decorator;
268
+ const candidateIsAILabel = isComponentElement(candidate, AILabel);
269
+ const normalizedDecorator = candidateIsAILabel ? /*#__PURE__*/cloneElement(candidate, {
270
+ size: 'mini'
271
+ }) : null;
271
272
 
272
273
  // Need to update the internal value when the revert button is clicked
273
274
  let isRevertActive;
274
- if (normalizedDecorator && normalizedDecorator['type']?.displayName === 'AILabel') {
275
+ if (normalizedDecorator?.type === AILabel) {
275
276
  isRevertActive = normalizedDecorator.props.revertActive;
276
277
  }
277
278
  useEffect(() => {
@@ -470,9 +470,9 @@ BreadcrumbBar.displayName = 'PageHeaderBreadcrumbBar';
470
470
  const Content = PageHeaderContent;
471
471
  Content.displayName = 'PageHeaderContent';
472
472
  const ContentPageActions = PageHeaderContentPageActions;
473
- Content.displayName = 'PageHeaderContentPageActions';
473
+ ContentPageActions.displayName = 'PageHeaderContentPageActions';
474
474
  const ContentText = PageHeaderContentText;
475
- Content.displayName = 'PageHeaderContentText';
475
+ ContentText.displayName = 'PageHeaderContentText';
476
476
  const HeroImage = PageHeaderHeroImage;
477
477
  HeroImage.displayName = 'PageHeaderHeroImage';
478
478
  const TabBar = PageHeaderTabBar;
@@ -17,6 +17,7 @@ import { useWindowEvent } from '../../internal/useEvent.js';
17
17
  import { mapPopoverAlign } from '../../tools/mapPopoverAlign.js';
18
18
  import { useFloating, offset, flip, arrow, hide, autoUpdate } from '@floating-ui/react';
19
19
  import { useFeatureFlag } from '../FeatureFlags/index.js';
20
+ import { ToggletipButton } from '../Toggletip/index.js';
20
21
 
21
22
  const PopoverContext = /*#__PURE__*/React.createContext({
22
23
  setFloating: {
@@ -226,7 +227,7 @@ forwardRef) {
226
227
  // For a toggletip there is a specific trigger component, ToggletipButton.
227
228
  // In either of these cases we want to set this as the reference node for floating-ui autoAlign
228
229
  // positioning.
229
- if (enableFloatingStyles && item?.type?.displayName !== 'PopoverContent' || enableFloatingStyles && item?.type?.displayName === 'ToggletipButton') {
230
+ if (enableFloatingStyles && item?.type !== PopoverContent || enableFloatingStyles && item?.type === ToggletipButton) {
230
231
  // Set the reference element for floating-ui
231
232
  refs.setReference(node);
232
233
  }
@@ -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 = 'onChange';
9
9
  export interface RadioButtonProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, ExcludedAttributes> {
10
10
  /**