@carbon/react 1.91.0-rc.0 → 1.92.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 (173) hide show
  1. package/.playwright/INTERNAL_AVT_REPORT_DO_NOT_USE.json +969 -934
  2. package/es/components/Accordion/AccordionItem.d.ts +12 -1
  3. package/es/components/Accordion/AccordionItem.js +9 -2
  4. package/es/components/Breadcrumb/Breadcrumb.Skeleton.d.ts +27 -2
  5. package/es/components/Breadcrumb/Breadcrumb.Skeleton.js +27 -4
  6. package/es/components/Breadcrumb/Breadcrumb.js +2 -1
  7. package/es/components/Breadcrumb/BreadcrumbItem.js +1 -1
  8. package/es/components/Checkbox/Checkbox.js +2 -2
  9. package/es/components/ComboBox/ComboBox.js +39 -23
  10. package/es/components/ComboButton/index.js +1 -1
  11. package/es/components/ComposedModal/ComposedModal.js +66 -17
  12. package/es/components/ComposedModal/ComposedModalPresence.d.ts +34 -0
  13. package/es/components/ComposedModal/ComposedModalPresence.js +42 -0
  14. package/es/components/ComposedModal/index.d.ts +1 -0
  15. package/es/components/ComposedModal/useComposedModalState.d.ts +7 -0
  16. package/es/components/ComposedModal/useComposedModalState.js +24 -0
  17. package/es/components/ContentSwitcher/ContentSwitcher.js +2 -2
  18. package/es/components/DataTable/TableBatchActions.js +2 -2
  19. package/es/components/DatePickerInput/DatePickerInput.js +2 -2
  20. package/es/components/Dialog/Dialog.js +2 -2
  21. package/es/components/Dropdown/Dropdown.js +5 -5
  22. package/es/components/ExpandableSearch/ExpandableSearch.d.ts +1 -1
  23. package/es/components/ExpandableSearch/ExpandableSearch.js +1 -1
  24. package/es/components/FeatureFlags/index.d.ts +2 -1
  25. package/es/components/FeatureFlags/index.js +3 -1
  26. package/es/components/FileUploader/FileUploader.js +2 -2
  27. package/es/components/FileUploader/FileUploaderItem.js +2 -2
  28. package/es/components/FluidTextInput/FluidPasswordInput.js +24 -5
  29. package/es/components/FluidTextInput/index.js +1 -1
  30. package/es/components/FormLabel/FormLabel.js +1 -1
  31. package/es/components/ListBox/ListBox.d.ts +1 -1
  32. package/es/components/ListBox/ListBox.js +1 -2
  33. package/es/components/ListItem/ListItem.js +1 -1
  34. package/es/components/Menu/MenuItem.js +2 -2
  35. package/es/components/MenuButton/index.d.ts +1 -1
  36. package/es/components/MenuButton/index.js +1 -1
  37. package/es/components/Modal/Modal.js +60 -10
  38. package/es/components/Modal/ModalPresence.d.ts +32 -0
  39. package/es/components/Modal/ModalPresence.js +37 -0
  40. package/es/components/Modal/index.d.ts +2 -1
  41. package/es/components/Modal/index.js +1 -0
  42. package/es/components/MultiSelect/FilterableMultiSelect.js +3 -3
  43. package/es/components/MultiSelect/MultiSelect.js +6 -5
  44. package/es/components/Notification/Notification.js +2 -2
  45. package/es/components/NumberInput/NumberInput.d.ts +21 -11
  46. package/es/components/NumberInput/NumberInput.js +40 -26
  47. package/es/components/OverflowMenu/OverflowMenu.js +2 -3
  48. package/es/components/OverflowMenu/next/index.js +1 -1
  49. package/es/components/OverflowMenuItem/OverflowMenuItem.js +1 -1
  50. package/es/components/PageHeader/PageHeader.js +2 -2
  51. package/es/components/PaginationNav/PaginationNav.d.ts +20 -0
  52. package/es/components/PaginationNav/PaginationNav.js +34 -5
  53. package/es/components/ProgressIndicator/ProgressIndicator.js +1 -1
  54. package/es/components/RadioButton/RadioButton.js +3 -3
  55. package/es/components/RadioButtonGroup/RadioButtonGroup.js +2 -2
  56. package/es/components/RadioTile/RadioTile.js +2 -2
  57. package/es/components/Select/Select.js +2 -2
  58. package/es/components/Slider/Slider.js +2 -2
  59. package/es/components/StructuredList/StructuredList.js +2 -2
  60. package/es/components/Tabs/Tabs.js +2 -2
  61. package/es/components/Tag/DismissibleTag.js +3 -3
  62. package/es/components/Tag/OperationalTag.js +3 -3
  63. package/es/components/Tag/SelectableTag.js +3 -3
  64. package/es/components/Tag/Tag.js +2 -2
  65. package/es/components/Text/Text.d.ts +1 -1
  66. package/es/components/Text/Text.js +0 -1
  67. package/es/components/Text/TextDirection.d.ts +1 -1
  68. package/es/components/Text/TextDirection.js +0 -1
  69. package/es/components/Text/createTextComponent.d.ts +2 -8
  70. package/es/components/Text/createTextComponent.js +2 -2
  71. package/es/components/Text/index.d.ts +0 -8
  72. package/es/components/TextArea/TextArea.js +2 -2
  73. package/es/components/TextInput/TextInput.js +2 -2
  74. package/es/components/Tile/Tile.js +2 -2
  75. package/es/components/Toggle/Toggle.js +2 -2
  76. package/es/components/UIShell/Switcher.js +0 -26
  77. package/es/index.d.ts +27 -23
  78. package/es/index.js +44 -41
  79. package/es/internal/useNormalizedInputProps.js +2 -2
  80. package/es/internal/usePresence.d.ts +17 -0
  81. package/es/internal/usePresence.js +66 -0
  82. package/es/internal/usePresenceContext.d.ts +25 -0
  83. package/es/internal/usePresenceContext.js +46 -0
  84. package/es/tools/mergeRefs.d.ts +5 -5
  85. package/es/tools/mergeRefs.js +16 -12
  86. package/lib/components/Accordion/AccordionItem.d.ts +12 -1
  87. package/lib/components/Accordion/AccordionItem.js +9 -2
  88. package/lib/components/Breadcrumb/Breadcrumb.Skeleton.d.ts +27 -2
  89. package/lib/components/Breadcrumb/Breadcrumb.Skeleton.js +27 -4
  90. package/lib/components/Breadcrumb/Breadcrumb.js +2 -1
  91. package/lib/components/Breadcrumb/BreadcrumbItem.js +1 -1
  92. package/lib/components/Checkbox/Checkbox.js +2 -2
  93. package/lib/components/ComboBox/ComboBox.js +39 -23
  94. package/lib/components/ComboButton/index.js +1 -1
  95. package/lib/components/ComposedModal/ComposedModal.js +65 -16
  96. package/lib/components/ComposedModal/ComposedModalPresence.d.ts +34 -0
  97. package/lib/components/ComposedModal/ComposedModalPresence.js +46 -0
  98. package/lib/components/ComposedModal/index.d.ts +1 -0
  99. package/lib/components/ComposedModal/useComposedModalState.d.ts +7 -0
  100. package/lib/components/ComposedModal/useComposedModalState.js +26 -0
  101. package/lib/components/ContentSwitcher/ContentSwitcher.js +1 -1
  102. package/lib/components/DataTable/TableBatchActions.js +2 -2
  103. package/lib/components/DatePickerInput/DatePickerInput.js +2 -2
  104. package/lib/components/Dialog/Dialog.js +2 -2
  105. package/lib/components/Dropdown/Dropdown.js +3 -3
  106. package/lib/components/ExpandableSearch/ExpandableSearch.d.ts +1 -1
  107. package/lib/components/ExpandableSearch/ExpandableSearch.js +1 -1
  108. package/lib/components/FeatureFlags/index.d.ts +2 -1
  109. package/lib/components/FeatureFlags/index.js +3 -1
  110. package/lib/components/FileUploader/FileUploader.js +2 -2
  111. package/lib/components/FileUploader/FileUploaderItem.js +2 -2
  112. package/lib/components/FluidTextInput/FluidPasswordInput.js +26 -5
  113. package/lib/components/FluidTextInput/index.js +2 -1
  114. package/lib/components/FormLabel/FormLabel.js +1 -1
  115. package/lib/components/ListBox/ListBox.d.ts +1 -1
  116. package/lib/components/ListBox/ListBox.js +1 -2
  117. package/lib/components/ListItem/ListItem.js +1 -1
  118. package/lib/components/Menu/MenuItem.js +2 -2
  119. package/lib/components/MenuButton/index.d.ts +1 -1
  120. package/lib/components/MenuButton/index.js +1 -1
  121. package/lib/components/Modal/Modal.js +59 -9
  122. package/lib/components/Modal/ModalPresence.d.ts +32 -0
  123. package/lib/components/Modal/ModalPresence.js +41 -0
  124. package/lib/components/Modal/index.d.ts +2 -1
  125. package/lib/components/Modal/index.js +1 -0
  126. package/lib/components/MultiSelect/FilterableMultiSelect.js +3 -3
  127. package/lib/components/MultiSelect/MultiSelect.js +4 -3
  128. package/lib/components/Notification/Notification.js +2 -2
  129. package/lib/components/NumberInput/NumberInput.d.ts +21 -11
  130. package/lib/components/NumberInput/NumberInput.js +40 -26
  131. package/lib/components/OverflowMenu/OverflowMenu.js +2 -3
  132. package/lib/components/OverflowMenu/next/index.js +1 -1
  133. package/lib/components/OverflowMenuItem/OverflowMenuItem.js +1 -1
  134. package/lib/components/PageHeader/PageHeader.js +2 -2
  135. package/lib/components/PaginationNav/PaginationNav.d.ts +20 -0
  136. package/lib/components/PaginationNav/PaginationNav.js +34 -5
  137. package/lib/components/ProgressIndicator/ProgressIndicator.js +1 -1
  138. package/lib/components/RadioButton/RadioButton.js +3 -3
  139. package/lib/components/RadioButtonGroup/RadioButtonGroup.js +3 -3
  140. package/lib/components/RadioTile/RadioTile.js +2 -2
  141. package/lib/components/Select/Select.js +2 -2
  142. package/lib/components/Slider/Slider.js +2 -2
  143. package/lib/components/StructuredList/StructuredList.js +2 -2
  144. package/lib/components/Tabs/Tabs.js +2 -2
  145. package/lib/components/Tag/DismissibleTag.js +3 -3
  146. package/lib/components/Tag/OperationalTag.js +3 -3
  147. package/lib/components/Tag/SelectableTag.js +3 -3
  148. package/lib/components/Tag/Tag.js +2 -2
  149. package/lib/components/Text/Text.d.ts +1 -1
  150. package/lib/components/Text/Text.js +0 -1
  151. package/lib/components/Text/TextDirection.d.ts +1 -1
  152. package/lib/components/Text/TextDirection.js +0 -1
  153. package/lib/components/Text/createTextComponent.d.ts +2 -8
  154. package/lib/components/Text/createTextComponent.js +2 -2
  155. package/lib/components/Text/index.d.ts +0 -8
  156. package/lib/components/TextArea/TextArea.js +2 -2
  157. package/lib/components/TextInput/TextInput.js +2 -2
  158. package/lib/components/Tile/Tile.js +2 -2
  159. package/lib/components/Toggle/Toggle.js +2 -2
  160. package/lib/components/UIShell/Switcher.js +0 -26
  161. package/lib/index.d.ts +27 -23
  162. package/lib/index.js +55 -6
  163. package/lib/internal/useNormalizedInputProps.js +2 -2
  164. package/lib/internal/usePresence.d.ts +17 -0
  165. package/lib/internal/usePresence.js +68 -0
  166. package/lib/internal/usePresenceContext.d.ts +25 -0
  167. package/lib/internal/usePresenceContext.js +48 -0
  168. package/lib/tools/mergeRefs.d.ts +5 -5
  169. package/lib/tools/mergeRefs.js +16 -14
  170. package/package.json +8 -8
  171. package/telemetry.yml +5 -2
  172. package/es/components/Text/index.js +0 -16
  173. package/lib/components/Text/index.js +0 -20
@@ -14,14 +14,14 @@ var iconsReact = require('@carbon/icons-react');
14
14
  var cx = require('classnames');
15
15
  var PropTypes = require('prop-types');
16
16
  var React = require('react');
17
- require('../Text/index.js');
17
+ var Text = require('../Text/Text.js');
18
+ require('../Text/TextDirection.js');
18
19
  var keys = require('../../internal/keyboard/keys.js');
19
20
  var match = require('../../internal/keyboard/match.js');
20
21
  var useId = require('../../internal/useId.js');
21
22
  var deprecate = require('../../prop-types/deprecate.js');
22
23
  var usePrefix = require('../../internal/usePrefix.js');
23
24
  var AccordionProvider = require('./AccordionProvider.js');
24
- var Text = require('../Text/Text.js');
25
25
 
26
26
  const defaultRenderToggle = props => /*#__PURE__*/React.createElement("button", _rollupPluginBabelHelpers.extends({
27
27
  type: "button"
@@ -37,6 +37,7 @@ function AccordionItem({
37
37
  title = 'title',
38
38
  disabled: controlledDisabled,
39
39
  handleAnimationEnd,
40
+ 'aria-label': ariaLabel,
40
41
  ...rest
41
42
  }) {
42
43
  const [isOpen, setIsOpen] = React.useState(open);
@@ -100,6 +101,7 @@ function AccordionItem({
100
101
  disabled: disabled,
101
102
  "aria-controls": id,
102
103
  "aria-expanded": isOpen,
104
+ "aria-label": ariaLabel,
103
105
  className: `${prefix}--accordion__heading`,
104
106
  onClick: onClick,
105
107
  onKeyDown: onKeyDown,
@@ -131,6 +133,11 @@ AccordionItem.propTypes = {
131
133
  * Specify whether an individual AccordionItem should be disabled
132
134
  */
133
135
  disabled: PropTypes.bool,
136
+ /**
137
+ * Specify a custom label for the accordion button.
138
+ * This is important for accessibility when the accordion has no visible title.
139
+ */
140
+ 'aria-label': PropTypes.string,
134
141
  /**
135
142
  * The handler of the massaged `click` event.
136
143
  */
@@ -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.
@@ -11,14 +11,39 @@ export interface BreadcrumbSkeletonProps extends React.HTMLAttributes<HTMLDivEle
11
11
  * Specify an optional className to add.
12
12
  */
13
13
  className?: string;
14
+ /**
15
+ * Specify the number of items
16
+ */
17
+ items?: number;
18
+ /**
19
+ * Optional prop to omit the trailing slash for the breadcrumbs
20
+ */
21
+ noTrailingSlash?: boolean;
22
+ /**
23
+ * Specify the size of the Breadcrumb. Currently
24
+ * supports the following: `sm` & `md` (default: 'md')
25
+ */
26
+ size?: 'sm' | 'md';
14
27
  }
15
- declare function BreadcrumbSkeleton({ className, ...rest }: BreadcrumbSkeletonProps): import("react/jsx-runtime").JSX.Element;
28
+ declare function BreadcrumbSkeleton({ className, items, noTrailingSlash, size, ...rest }: BreadcrumbSkeletonProps): import("react/jsx-runtime").JSX.Element;
16
29
  declare namespace BreadcrumbSkeleton {
17
30
  var propTypes: {
18
31
  /**
19
32
  * Specify an optional className to add.
20
33
  */
21
34
  className: PropTypes.Requireable<string>;
35
+ /**
36
+ * Specify the number of items
37
+ */
38
+ items: PropTypes.Requireable<number>;
39
+ /**
40
+ * Optional prop to omit the trailing slash for the breadcrumbs
41
+ */
42
+ noTrailingSlash: PropTypes.Requireable<boolean>;
43
+ /**
44
+ * Specify the size of the Breadcrumb. Currently supports the following: `sm` & `md` (default: 'md')
45
+ */
46
+ size: PropTypes.Requireable<string>;
22
47
  };
23
48
  }
24
49
  export default BreadcrumbSkeleton;
@@ -15,7 +15,6 @@ var React = require('react');
15
15
  var cx = require('classnames');
16
16
  var usePrefix = require('../../internal/usePrefix.js');
17
17
 
18
- var _Item, _Item2, _Item3;
19
18
  function Item() {
20
19
  const prefix = usePrefix.usePrefix();
21
20
  return /*#__PURE__*/React.createElement("div", {
@@ -26,19 +25,43 @@ function Item() {
26
25
  }
27
26
  function BreadcrumbSkeleton({
28
27
  className,
28
+ items = 3,
29
+ noTrailingSlash,
30
+ size,
29
31
  ...rest
30
32
  }) {
31
33
  const prefix = usePrefix.usePrefix();
32
- const classes = cx(`${prefix}--breadcrumb`, `${prefix}--skeleton`, className);
34
+ const classes = cx({
35
+ [`${prefix}--breadcrumb`]: true,
36
+ [`${prefix}--skeleton`]: true,
37
+ [`${prefix}--breadcrumb--no-trailing-slash`]: noTrailingSlash,
38
+ [`${prefix}--breadcrumb--sm`]: size === 'sm'
39
+ }, className);
33
40
  return /*#__PURE__*/React.createElement("div", _rollupPluginBabelHelpers.extends({
34
41
  className: classes
35
- }, rest), _Item || (_Item = /*#__PURE__*/React.createElement(Item, null)), _Item2 || (_Item2 = /*#__PURE__*/React.createElement(Item, null)), _Item3 || (_Item3 = /*#__PURE__*/React.createElement(Item, null)));
42
+ }, rest), Array.from({
43
+ length: items
44
+ }, (_, i) => /*#__PURE__*/React.createElement(Item, {
45
+ key: i
46
+ })));
36
47
  }
37
48
  BreadcrumbSkeleton.propTypes = {
38
49
  /**
39
50
  * Specify an optional className to add.
40
51
  */
41
- className: PropTypes.string
52
+ className: PropTypes.string,
53
+ /**
54
+ * Specify the number of items
55
+ */
56
+ items: PropTypes.number,
57
+ /**
58
+ * Optional prop to omit the trailing slash for the breadcrumbs
59
+ */
60
+ noTrailingSlash: PropTypes.bool,
61
+ /**
62
+ * Specify the size of the Breadcrumb. Currently supports the following: `sm` & `md` (default: 'md')
63
+ */
64
+ size: PropTypes.oneOf(['sm', 'md'])
42
65
  };
43
66
 
44
67
  exports.BreadcrumbSkeleton = BreadcrumbSkeleton;
@@ -57,7 +57,8 @@ Breadcrumb.propTypes = {
57
57
  */
58
58
  noTrailingSlash: PropTypes.bool,
59
59
  /**
60
- * Specify the size of the Breadcrumb. Currently supports the following:
60
+ * Specify the size of the Breadcrumb. Currently
61
+ * supports the following: `sm` & `md` (default: 'md')
61
62
  */
62
63
  size: PropTypes.oneOf(['sm', 'md'])
63
64
  };
@@ -16,8 +16,8 @@ var cx = require('classnames');
16
16
  var Link = require('../Link/Link.js');
17
17
  var iconsReact = require('@carbon/icons-react');
18
18
  var usePrefix = require('../../internal/usePrefix.js');
19
- require('../Text/index.js');
20
19
  var Text = require('../Text/Text.js');
20
+ require('../Text/TextDirection.js');
21
21
 
22
22
  const frFn = React.forwardRef;
23
23
  const BreadcrumbItem = frFn((props, ref) => {
@@ -13,7 +13,8 @@ var _rollupPluginBabelHelpers = require('../../_virtual/_rollupPluginBabelHelper
13
13
  var PropTypes = require('prop-types');
14
14
  var React = require('react');
15
15
  var cx = require('classnames');
16
- require('../Text/index.js');
16
+ var Text = require('../Text/Text.js');
17
+ require('../Text/TextDirection.js');
17
18
  var deprecate = require('../../prop-types/deprecate.js');
18
19
  var usePrefix = require('../../internal/usePrefix.js');
19
20
  var iconsReact = require('@carbon/icons-react');
@@ -21,7 +22,6 @@ var useId = require('../../internal/useId.js');
21
22
  var noopFn = require('../../internal/noopFn.js');
22
23
  var index = require('../AILabel/index.js');
23
24
  var utils = require('../../internal/utils.js');
24
- var Text = require('../Text/Text.js');
25
25
 
26
26
  const Checkbox = /*#__PURE__*/React.forwardRef(({
27
27
  className,
@@ -14,7 +14,8 @@ var cx = require('classnames');
14
14
  var Downshift = require('downshift');
15
15
  var PropTypes = require('prop-types');
16
16
  var React = require('react');
17
- require('../Text/index.js');
17
+ var Text = require('../Text/Text.js');
18
+ require('../Text/TextDirection.js');
18
19
  var iconsReact = require('@carbon/icons-react');
19
20
  var isEqual = require('react-fast-compare');
20
21
  var index$2 = require('../ListBox/index.js');
@@ -34,7 +35,6 @@ var index$1 = require('../AILabel/index.js');
34
35
  var defaultItemToString = require('../../internal/defaultItemToString.js');
35
36
  var utils = require('../../internal/utils.js');
36
37
  var ListBoxPropTypes = require('../ListBox/ListBoxPropTypes.js');
37
- var Text = require('../Text/Text.js');
38
38
 
39
39
  const {
40
40
  InputBlur,
@@ -285,9 +285,13 @@ const ComboBox = /*#__PURE__*/React.forwardRef((props, ref) => {
285
285
  switch (type) {
286
286
  case InputBlur:
287
287
  {
288
- if (allowCustomValue && highlightedIndex == '-1') {
289
- const customValue = inputValue;
290
- changes.selectedItem = customValue;
288
+ // If custom values are allowed, treat whatever the user typed as
289
+ // the value.
290
+ if (allowCustomValue && highlightedIndex === -1) {
291
+ const {
292
+ inputValue
293
+ } = state;
294
+ changes.selectedItem = inputValue;
291
295
  if (onChange) {
292
296
  onChange({
293
297
  selectedItem: inputValue,
@@ -296,17 +300,28 @@ const ComboBox = /*#__PURE__*/React.forwardRef((props, ref) => {
296
300
  }
297
301
  return changes;
298
302
  }
299
- if (state.inputValue && highlightedIndex == '-1' && changes.selectedItem) {
303
+
304
+ // If a new item was selected, keep its label in the input.
305
+ if (state.inputValue && highlightedIndex === -1 && changes.selectedItem) {
300
306
  return {
301
307
  ...changes,
302
308
  inputValue: itemToString(changes.selectedItem)
303
309
  };
304
310
  }
305
- if (state.inputValue && highlightedIndex == '-1' && !allowCustomValue && !changes.selectedItem) {
306
- return {
307
- ...changes,
308
- inputValue: ''
309
- };
311
+
312
+ // If custom values are not allowed, normalize any non-matching
313
+ // text. If the input isn’t an exact item label, restore the
314
+ // selected label if there is one, or clear it.
315
+ if (!allowCustomValue) {
316
+ const currentInput = state.inputValue ?? '';
317
+ const hasExactMatch = !!currentInput && items.some(item => itemToString(item) === currentInput);
318
+ if (!hasExactMatch) {
319
+ const restoredInput = state.selectedItem !== null ? itemToString(state.selectedItem) : '';
320
+ return {
321
+ ...changes,
322
+ inputValue: restoredInput
323
+ };
324
+ }
310
325
  }
311
326
  return changes;
312
327
  }
@@ -359,16 +374,17 @@ const ComboBox = /*#__PURE__*/React.forwardRef((props, ref) => {
359
374
  };
360
375
  case FunctionToggleMenu:
361
376
  case ToggleButtonClick:
362
- if (!changes.isOpen && state.inputValue && highlightedIndex === -1 && !allowCustomValue) {
363
- return {
364
- ...changes,
365
- inputValue: '' // Clear the input
366
- };
367
- }
368
- if (changes.isOpen && !changes.selectedItem) {
369
- return {
370
- ...changes
371
- };
377
+ // When closing the menu, apply the same normalization as blur.
378
+ if (state.isOpen && !changes.isOpen && !allowCustomValue) {
379
+ const currentInput = state.inputValue ?? '';
380
+ const hasExactMatch = !!currentInput && items.some(item => itemToString(item) === currentInput);
381
+ if (!hasExactMatch) {
382
+ const restoredInput = state.selectedItem !== null ? itemToString(state.selectedItem) : '';
383
+ return {
384
+ ...changes,
385
+ inputValue: restoredInput
386
+ };
387
+ }
372
388
  }
373
389
  return changes;
374
390
  case MenuMouseLeave:
@@ -395,7 +411,7 @@ const ComboBox = /*#__PURE__*/React.forwardRef((props, ref) => {
395
411
  }
396
412
  },
397
413
  // eslint-disable-next-line react-hooks/exhaustive-deps
398
- [allowCustomValue, inputValue, onChange]);
414
+ [allowCustomValue, inputValue, itemToString, items, onChange]);
399
415
  const handleToggleClick = isOpen => event => {
400
416
  if (onToggleClick) {
401
417
  onToggleClick(event);
@@ -639,7 +655,7 @@ const ComboBox = /*#__PURE__*/React.forwardRef((props, ref) => {
639
655
  setInputValue(newValue);
640
656
  downshiftSetInputValue(newValue);
641
657
  },
642
- ref: mergeRefs.default(textInput, ref, inputRef),
658
+ ref: mergeRefs.mergeRefs(textInput, ref, inputRef),
643
659
  onKeyDown: event => {
644
660
  if (match.match(event, keys.Space)) {
645
661
  event.stopPropagation();
@@ -91,7 +91,7 @@ const ComboButton = /*#__PURE__*/React.forwardRef(function ComboButton({
91
91
  middleware: middlewares,
92
92
  whileElementsMounted: react.autoUpdate
93
93
  });
94
- const ref = mergeRefs.default(forwardRef, containerRef, refs.setReference);
94
+ const ref = mergeRefs.mergeRefs(forwardRef, containerRef, refs.setReference);
95
95
  const {
96
96
  open,
97
97
  handleClick: hookOnClick,
@@ -32,6 +32,10 @@ var Dialog = require('../Dialog/Dialog.js');
32
32
  var warning = require('../../internal/warning.js');
33
33
  var index$2 = require('../AILabel/index.js');
34
34
  var utils = require('../../internal/utils.js');
35
+ var react = require('@floating-ui/react');
36
+ var ComposedModalPresence = require('./ComposedModalPresence.js');
37
+ var useId = require('../../internal/useId.js');
38
+ var useComposedModalState = require('./useComposedModalState.js');
35
39
  var debounce = require('../../node_modules/es-toolkit/dist/compat/function/debounce.js');
36
40
 
37
41
  const ModalBody = /*#__PURE__*/React.forwardRef(function ModalBody({
@@ -72,7 +76,7 @@ const ModalBody = /*#__PURE__*/React.forwardRef(function ModalBody({
72
76
  return /*#__PURE__*/React.createElement(index.Layer, _rollupPluginBabelHelpers.extends({
73
77
  className: contentClass
74
78
  }, hasScrollingContentProps, rest, {
75
- ref: mergeRefs.default(contentRef, ref)
79
+ ref: mergeRefs.mergeRefs(contentRef, ref)
76
80
  }), children);
77
81
  });
78
82
  ModalBody.propTypes = {
@@ -99,6 +103,34 @@ ModalBody.propTypes = {
99
103
  hasScrollingContent: PropTypes.bool
100
104
  };
101
105
  const ComposedModal = /*#__PURE__*/React.forwardRef(function ComposedModal({
106
+ open,
107
+ ...props
108
+ }, ref) {
109
+ const id = useId.useId();
110
+ const enablePresence = index$1.useFeatureFlag('enable-presence');
111
+ const hasPresenceContext = Boolean(React.useContext(ComposedModalPresence.ComposedModalPresenceContext));
112
+ const hasPresenceOptIn = enablePresence || hasPresenceContext;
113
+ const exclusivePresenceContext = ComposedModalPresence.useExclusiveComposedModalPresenceContext(id);
114
+
115
+ // if opt in and not exclusive to a presence context, wrap with presence
116
+ if (hasPresenceOptIn && !exclusivePresenceContext) {
117
+ return /*#__PURE__*/React.createElement(ComposedModalPresence.ComposedModalPresence, {
118
+ open: open ?? false,
119
+ _presenceId: id
120
+ // do not auto enable styles for opt-in by feature flag
121
+ ,
122
+ _autoEnablePresence: hasPresenceContext
123
+ }, /*#__PURE__*/React.createElement(ComposedModalDialog, _rollupPluginBabelHelpers.extends({
124
+ open: true,
125
+ ref: ref
126
+ }, props)));
127
+ }
128
+ return /*#__PURE__*/React.createElement(ComposedModalDialog, _rollupPluginBabelHelpers.extends({
129
+ ref: ref,
130
+ open: open
131
+ }, props));
132
+ });
133
+ const ComposedModalDialog = /*#__PURE__*/React.forwardRef(function ComposedModalDialog({
102
134
  ['aria-labelledby']: ariaLabelledBy,
103
135
  ['aria-label']: ariaLabel,
104
136
  children,
@@ -109,7 +141,7 @@ const ComposedModal = /*#__PURE__*/React.forwardRef(function ComposedModal({
109
141
  isFullWidth,
110
142
  onClose,
111
143
  onKeyDown,
112
- open,
144
+ open: externalOpen,
113
145
  preventCloseOnClickOutside,
114
146
  selectorPrimaryFocus = '[data-modal-primary-focus]',
115
147
  selectorsFloatingMenus,
@@ -119,27 +151,30 @@ const ComposedModal = /*#__PURE__*/React.forwardRef(function ComposedModal({
119
151
  ...rest
120
152
  }, ref) {
121
153
  const prefix = usePrefix.usePrefix();
122
- const [isOpen, setIsOpen] = React.useState(!!open);
123
- const [wasOpen, setWasOpen] = React.useState(!!open);
124
154
  const innerModal = React.useRef(null);
125
155
  const button = React.useRef(null);
126
156
  const startSentinel = React.useRef(null);
127
157
  const endSentinel = React.useRef(null);
128
158
  const onMouseDownTarget = React.useRef(null);
159
+ const presenceContext = React.useContext(ComposedModalPresence.ComposedModalPresenceContext);
160
+ const mergedRefs = react.useMergeRefs([ref, presenceContext?.presenceRef]);
161
+ const enablePresence = index$1.useFeatureFlag('enable-presence') || presenceContext?.autoEnablePresence;
162
+
163
+ // always mark as open when mounted with presence
164
+ const open = externalOpen || enablePresence;
165
+ const modalState = useComposedModalState.useComposedModalState(open);
166
+ const [isOpen, setIsOpen] = presenceContext?.modalState ?? modalState;
129
167
  const enableDialogElement = index$1.useFeatureFlag('enable-dialog-element');
130
168
  const focusTrapWithoutSentinels = index$1.useFeatureFlag('enable-experimental-focus-wrap-without-sentinels');
131
169
  process.env.NODE_ENV !== "production" ? warning.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;
132
170
 
133
- // Keep track of modal open/close state
134
- // and propagate it to the document.body
171
+ // Propagate open/close state to the document.body
135
172
  React.useEffect(() => {
136
- if (!enableDialogElement && open !== wasOpen) {
137
- setIsOpen(!!open);
138
- setWasOpen(!!open);
173
+ if (!enableDialogElement) {
139
174
  toggleClass.toggleClass(document.body, `${prefix}--body--with-modal-open`, !!open);
140
175
  }
141
176
  // eslint-disable-next-line react-hooks/exhaustive-deps -- https://github.com/carbon-design-system/carbon/issues/20071
142
- }, [open, wasOpen, prefix]);
177
+ }, [open, prefix]);
143
178
  // Remove the document.body className on unmount
144
179
  React.useEffect(() => {
145
180
  if (!enableDialogElement) {
@@ -230,7 +265,8 @@ const ComposedModal = /*#__PURE__*/React.forwardRef(function ComposedModal({
230
265
  }
231
266
  }
232
267
  const modalClass = cx(`${prefix}--modal`, {
233
- 'is-visible': isOpen,
268
+ 'is-visible': enablePresence || isOpen,
269
+ [`${prefix}--modal--enable-presence`]: presenceContext?.autoEnablePresence,
234
270
  [`${prefix}--modal--danger`]: danger,
235
271
  [`${prefix}--modal--slug`]: slug,
236
272
  [`${prefix}--modal--decorator`]: decorator
@@ -284,12 +320,23 @@ const ComposedModal = /*#__PURE__*/React.forwardRef(function ComposedModal({
284
320
  // eslint-disable-next-line react-hooks/exhaustive-deps -- https://github.com/carbon-design-system/carbon/issues/20071
285
321
  }, [open]);
286
322
  React.useEffect(() => {
287
- if (!enableDialogElement && !open && launcherButtonRef) {
323
+ if (!enableDialogElement && !enablePresence && !open && launcherButtonRef) {
288
324
  setTimeout(() => {
289
325
  launcherButtonRef.current?.focus();
290
326
  });
291
327
  }
292
- }, [enableDialogElement, open, launcherButtonRef]);
328
+ }, [enableDialogElement, enablePresence, open, launcherButtonRef]);
329
+ // Focus launcherButtonRef on unmount
330
+ React.useEffect(() => {
331
+ const launcherButton = launcherButtonRef?.current;
332
+ return () => {
333
+ if (enablePresence && launcherButton) {
334
+ setTimeout(() => {
335
+ launcherButton.focus();
336
+ });
337
+ }
338
+ };
339
+ }, [enablePresence, launcherButtonRef]);
293
340
  React.useEffect(() => {
294
341
  if (!enableDialogElement) {
295
342
  const initialFocus = focusContainerElement => {
@@ -328,7 +375,8 @@ const ComposedModal = /*#__PURE__*/React.forwardRef(function ComposedModal({
328
375
  modal: true,
329
376
  className: containerClass,
330
377
  "aria-label": ariaLabel ? ariaLabel : generatedAriaLabel,
331
- "aria-labelledby": ariaLabelledBy
378
+ "aria-labelledby": ariaLabelledBy,
379
+ "data-exiting": presenceContext?.isExiting || undefined
332
380
  }, /*#__PURE__*/React.createElement("div", {
333
381
  ref: innerModal,
334
382
  className: `${prefix}--modal-container-body`
@@ -357,13 +405,14 @@ const ComposedModal = /*#__PURE__*/React.forwardRef(function ComposedModal({
357
405
  return /*#__PURE__*/React.createElement(index.Layer, _rollupPluginBabelHelpers.extends({}, rest, {
358
406
  level: 0,
359
407
  role: "presentation",
360
- ref: ref,
408
+ ref: mergedRefs,
361
409
  "aria-hidden": !open,
362
410
  onBlur: handleBlur,
363
411
  onClick: events.composeEventHandlers([rest?.onClick, handleOnClick]),
364
412
  onMouseDown: events.composeEventHandlers([rest?.onMouseDown, handleOnMouseDown]),
365
413
  onKeyDown: handleKeyDown,
366
- className: modalClass
414
+ className: modalClass,
415
+ "data-exiting": presenceContext?.isExiting || undefined
367
416
  }), modalBody);
368
417
  });
369
418
  ComposedModal.propTypes = {
@@ -0,0 +1,34 @@
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
+ import React, { type PropsWithChildren } from 'react';
8
+ import { type PresenceContext } from '../../internal/usePresenceContext';
9
+ import { useComposedModalState } from './useComposedModalState';
10
+ export interface ComposedModalPresenceProps {
11
+ /**
12
+ * Specify whether the Modal is currently open
13
+ */
14
+ open: boolean;
15
+ /**
16
+ * Internal property for backwards compatibility. Specify whether the Modal should opt in to presence mode.
17
+ */
18
+ _autoEnablePresence?: boolean;
19
+ /**
20
+ * Internal property to predefine the presence context's id for exclusivity.
21
+ */
22
+ _presenceId?: string;
23
+ }
24
+ export declare const ComposedModalPresence: ({ open, _presenceId: presenceId, _autoEnablePresence: autoEnablePresence, children, }: PropsWithChildren<ComposedModalPresenceProps>) => import("react/jsx-runtime").JSX.Element | null;
25
+ interface ComposedModalPresenceContextProps extends PresenceContext {
26
+ modalState: ReturnType<typeof useComposedModalState>;
27
+ autoEnablePresence: boolean;
28
+ }
29
+ export declare const ComposedModalPresenceContext: React.Context<ComposedModalPresenceContextProps | undefined>;
30
+ /**
31
+ * Handles occurrences where only a single composed modal must consume a context.
32
+ */
33
+ export declare const useExclusiveComposedModalPresenceContext: (id: string) => ComposedModalPresenceContextProps | undefined;
34
+ export {};
@@ -0,0 +1,46 @@
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
+ 'use strict';
9
+
10
+ var React = require('react');
11
+ var usePresenceContext = require('../../internal/usePresenceContext.js');
12
+ var useComposedModalState = require('./useComposedModalState.js');
13
+
14
+ const ComposedModalPresence = ({
15
+ open,
16
+ _presenceId: presenceId,
17
+ _autoEnablePresence: autoEnablePresence = true,
18
+ children
19
+ }) => {
20
+ // Since the modal could be used without an onClose callback, we need to be aware of the internal isOpen state
21
+ const modalState = useComposedModalState.useComposedModalState(open);
22
+ const [isOpen] = modalState;
23
+ const [isPresent, context] = usePresenceContext.usePresenceContext(isOpen, presenceId);
24
+ const presenceContextValue = React.useMemo(() => ({
25
+ modalState,
26
+ autoEnablePresence,
27
+ ...context
28
+ }), [modalState, autoEnablePresence, context]);
29
+ if (!isPresent) return null;
30
+ return /*#__PURE__*/React.createElement(ComposedModalPresenceContext, {
31
+ value: presenceContextValue
32
+ }, children);
33
+ };
34
+ const ComposedModalPresenceContext = /*#__PURE__*/React.createContext(undefined);
35
+
36
+ /**
37
+ * Handles occurrences where only a single composed modal must consume a context.
38
+ */
39
+ const useExclusiveComposedModalPresenceContext = id => {
40
+ const ctx = React.useContext(ComposedModalPresenceContext);
41
+ return ctx?.isPresenceExclusive(id) ? ctx : undefined;
42
+ };
43
+
44
+ exports.ComposedModalPresence = ComposedModalPresence;
45
+ exports.ComposedModalPresenceContext = ComposedModalPresenceContext;
46
+ exports.useExclusiveComposedModalPresenceContext = useExclusiveComposedModalPresenceContext;
@@ -6,6 +6,7 @@
6
6
  */
7
7
  import ComposedModal from './ComposedModal';
8
8
  export { default as ComposedModal, type ComposedModalProps, ModalBody, type ModalBodyProps, } from './ComposedModal';
9
+ export { ComposedModalPresence, type ComposedModalPresenceProps, } from './ComposedModalPresence';
9
10
  export { ModalHeader, type ModalHeaderProps } from './ModalHeader';
10
11
  export { ModalFooter, type ModalFooterProps } from './ModalFooter';
11
12
  export default ComposedModal;
@@ -0,0 +1,7 @@
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 useComposedModalState: (open: boolean | undefined) => readonly [boolean, import("react").Dispatch<import("react").SetStateAction<boolean>>];
@@ -0,0 +1,26 @@
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
+ 'use strict';
9
+
10
+ var React = require('react');
11
+
12
+ const useComposedModalState = open => {
13
+ const [isOpen, setIsOpen] = React.useState(!!open);
14
+ const [wasOpen, setWasOpen] = React.useState(!!open);
15
+
16
+ // Keep track of modal open/close state
17
+ React.useEffect(() => {
18
+ if (open !== wasOpen) {
19
+ setIsOpen(!!open);
20
+ setWasOpen(!!open);
21
+ }
22
+ }, [open, wasOpen]);
23
+ return React.useMemo(() => [isOpen, setIsOpen], [isOpen]);
24
+ };
25
+
26
+ exports.useComposedModalState = useComposedModalState;
@@ -77,7 +77,7 @@ const ContentSwitcher = ({
77
77
  });
78
78
  }
79
79
  }
80
- } else if (selectedIndex !== index) {
80
+ } else if (selectedIndex !== index && (isKeyboardEvent(event) ? match.matches(event, [keys.Enter, keys.Space]) : true)) {
81
81
  setSelectedIndex(index);
82
82
  focusSwitch(index);
83
83
  onChange(event);
@@ -16,9 +16,9 @@ var React = require('react');
16
16
  var Button = require('../Button/Button.js');
17
17
  require('../Button/Button.Skeleton.js');
18
18
  var TableActionList = require('./TableActionList.js');
19
- require('../Text/index.js');
20
- var usePrefix = require('../../internal/usePrefix.js');
21
19
  var Text = require('../Text/Text.js');
20
+ require('../Text/TextDirection.js');
21
+ var usePrefix = require('../../internal/usePrefix.js');
22
22
 
23
23
  const TableBatchActionsTranslationKeys = ['carbon.table.batch.cancel', 'carbon.table.batch.items.selected', 'carbon.table.batch.item.selected', 'carbon.table.batch.selectAll'];
24
24
  const translationKeys = {
@@ -18,11 +18,11 @@ var usePrefix = require('../../internal/usePrefix.js');
18
18
  require('../FluidForm/FluidForm.js');
19
19
  var FormContext = require('../FluidForm/FormContext.js');
20
20
  var useId = require('../../internal/useId.js');
21
- require('../Text/index.js');
21
+ var Text = require('../Text/Text.js');
22
+ require('../Text/TextDirection.js');
22
23
  var deprecate = require('../../prop-types/deprecate.js');
23
24
  var index = require('../AILabel/index.js');
24
25
  var utils = require('../../internal/utils.js');
25
- var Text = require('../Text/Text.js');
26
26
 
27
27
  // eslint-disable-next-line @typescript-eslint/no-explicit-any -- https://github.com/carbon-design-system/carbon/issues/20071
28
28
 
@@ -16,7 +16,8 @@ var cx = require('classnames');
16
16
  var iconsReact = require('@carbon/icons-react');
17
17
  var index = require('../IconButton/index.js');
18
18
  var noopFn = require('../../internal/noopFn.js');
19
- require('../Text/index.js');
19
+ var Text = require('../Text/Text.js');
20
+ require('../Text/TextDirection.js');
20
21
  var index$1 = require('../Layer/index.js');
21
22
  var ButtonSet = require('../ButtonSet/ButtonSet.js');
22
23
  var Button = require('../Button/Button.js');
@@ -24,7 +25,6 @@ require('../Button/Button.Skeleton.js');
24
25
  var useId = require('../../internal/useId.js');
25
26
  var InlineLoading = require('../InlineLoading/InlineLoading.js');
26
27
  var debounce = require('../../node_modules/es-toolkit/dist/compat/function/debounce.js');
27
- var Text = require('../Text/Text.js');
28
28
 
29
29
  const DialogContext = /*#__PURE__*/React.createContext({});
30
30