@carbon/react 1.100.0-rc.0 → 1.101.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (148) hide show
  1. package/.playwright/INTERNAL_AVT_REPORT_DO_NOT_USE.json +933 -933
  2. package/es/components/AILabel/index.d.ts +1 -1
  3. package/es/components/AILabel/index.js +1 -12
  4. package/es/components/Checkbox/Checkbox.js +5 -3
  5. package/es/components/CheckboxGroup/CheckboxGroup.js +4 -3
  6. package/es/components/CodeSnippet/CodeSnippet.d.ts +1 -1
  7. package/es/components/ComboBox/ComboBox.d.ts +3 -4
  8. package/es/components/ComboBox/ComboBox.js +20 -18
  9. package/es/components/ComboButton/index.d.ts +1 -1
  10. package/es/components/ComboButton/index.js +3 -2
  11. package/es/components/ComposedModal/ComposedModal.js +17 -22
  12. package/es/components/ComposedModal/ModalHeader.d.ts +2 -2
  13. package/es/components/ComposedModal/ModalHeader.js +1 -1
  14. package/es/components/Copy/Copy.d.ts +1 -1
  15. package/es/components/CopyButton/CopyButton.d.ts +1 -1
  16. package/es/components/DataTable/DataTable.d.ts +2 -0
  17. package/es/components/DataTable/DataTable.js +6 -5
  18. package/es/components/DataTable/Table.d.ts +1 -1
  19. package/es/components/DataTable/Table.js +10 -4
  20. package/es/components/DataTable/state/sorting.d.ts +4 -2
  21. package/es/components/Dropdown/Dropdown.d.ts +3 -4
  22. package/es/components/Dropdown/Dropdown.js +16 -13
  23. package/es/components/FileUploader/FileUploaderItem.d.ts +1 -1
  24. package/es/components/FileUploader/FileUploaderItem.js +3 -2
  25. package/es/components/FluidComboBox/FluidComboBox.d.ts +2 -7
  26. package/es/components/FluidComboBox/FluidComboBox.js +1 -2
  27. package/es/components/FluidDropdown/FluidDropdown.d.ts +1 -6
  28. package/es/components/FluidDropdown/FluidDropdown.js +1 -2
  29. package/es/components/FluidMultiSelect/FluidMultiSelect.d.ts +1 -6
  30. package/es/components/FluidMultiSelect/FluidMultiSelect.js +1 -2
  31. package/es/components/InlineLoading/InlineLoading.js +5 -11
  32. package/es/components/Menu/Menu.js +8 -4
  33. package/es/components/Menu/MenuItem.d.ts +5 -1
  34. package/es/components/Menu/MenuItem.js +11 -1
  35. package/es/components/MenuButton/index.d.ts +1 -1
  36. package/es/components/MenuButton/index.js +3 -2
  37. package/es/components/MultiSelect/FilterableMultiSelect.d.ts +1 -1
  38. package/es/components/MultiSelect/FilterableMultiSelect.js +7 -5
  39. package/es/components/MultiSelect/MultiSelect.d.ts +3 -4
  40. package/es/components/MultiSelect/MultiSelect.js +10 -13
  41. package/es/components/Notification/Notification.js +5 -3
  42. package/es/components/NumberInput/NumberInput.d.ts +1 -1
  43. package/es/components/NumberInput/NumberInput.js +5 -4
  44. package/es/components/OverflowMenu/OverflowMenu.d.ts +1 -0
  45. package/es/components/OverflowMenu/OverflowMenu.js +8 -4
  46. package/es/components/PageHeader/PageHeader.d.ts +1 -1
  47. package/es/components/PageHeader/PageHeader.js +5 -5
  48. package/es/components/RadioButtonGroup/RadioButtonGroup.js +4 -3
  49. package/es/components/Select/Select.js +2 -1
  50. package/es/components/StructuredList/StructuredList.d.ts +1 -1
  51. package/es/components/StructuredList/StructuredList.js +2 -4
  52. package/es/components/Tabs/Tabs.d.ts +2 -2
  53. package/es/components/Tabs/Tabs.js +20 -26
  54. package/es/components/Tag/DismissibleTag.js +3 -2
  55. package/es/components/Tag/OperationalTag.js +3 -2
  56. package/es/components/Tag/SelectableTag.js +3 -2
  57. package/es/components/Tag/Tag.js +3 -2
  58. package/es/components/TextArea/TextArea.d.ts +1 -1
  59. package/es/components/TextArea/TextArea.js +7 -8
  60. package/es/components/TextInput/ControlledPasswordInput.js +7 -6
  61. package/es/components/TextInput/PasswordInput.js +5 -6
  62. package/es/components/TextInput/TextInput.js +4 -4
  63. package/es/components/Tile/Tile.d.ts +1 -1
  64. package/es/components/Tile/Tile.js +37 -69
  65. package/es/components/TimePicker/TimePicker.js +2 -2
  66. package/es/components/Tooltip/DefinitionTooltip.d.ts +1 -1
  67. package/es/components/Tooltip/DefinitionTooltip.js +3 -2
  68. package/es/components/UIShell/SideNav.d.ts +0 -1
  69. package/es/components/UIShell/SideNav.js +12 -3
  70. package/es/internal/useId.js +3 -4
  71. package/es/internal/usePresence.js +3 -2
  72. package/es/internal/useResizeObserver.d.ts +1 -1
  73. package/es/internal/useResizeObserver.js +5 -7
  74. package/es/tools/events.d.ts +1 -1
  75. package/lib/components/AILabel/index.d.ts +1 -1
  76. package/lib/components/AILabel/index.js +1 -12
  77. package/lib/components/Checkbox/Checkbox.js +5 -3
  78. package/lib/components/CheckboxGroup/CheckboxGroup.js +4 -3
  79. package/lib/components/CodeSnippet/CodeSnippet.d.ts +1 -1
  80. package/lib/components/ComboBox/ComboBox.d.ts +3 -4
  81. package/lib/components/ComboBox/ComboBox.js +20 -18
  82. package/lib/components/ComboButton/index.d.ts +1 -1
  83. package/lib/components/ComboButton/index.js +2 -1
  84. package/lib/components/ComposedModal/ComposedModal.js +16 -21
  85. package/lib/components/ComposedModal/ModalHeader.d.ts +2 -2
  86. package/lib/components/ComposedModal/ModalHeader.js +1 -1
  87. package/lib/components/Copy/Copy.d.ts +1 -1
  88. package/lib/components/CopyButton/CopyButton.d.ts +1 -1
  89. package/lib/components/DataTable/DataTable.d.ts +2 -0
  90. package/lib/components/DataTable/DataTable.js +6 -5
  91. package/lib/components/DataTable/Table.d.ts +1 -1
  92. package/lib/components/DataTable/Table.js +10 -4
  93. package/lib/components/DataTable/state/sorting.d.ts +4 -2
  94. package/lib/components/Dropdown/Dropdown.d.ts +3 -4
  95. package/lib/components/Dropdown/Dropdown.js +16 -13
  96. package/lib/components/FileUploader/FileUploaderItem.d.ts +1 -1
  97. package/lib/components/FileUploader/FileUploaderItem.js +2 -1
  98. package/lib/components/FluidComboBox/FluidComboBox.d.ts +2 -7
  99. package/lib/components/FluidComboBox/FluidComboBox.js +1 -2
  100. package/lib/components/FluidDropdown/FluidDropdown.d.ts +1 -6
  101. package/lib/components/FluidDropdown/FluidDropdown.js +1 -2
  102. package/lib/components/FluidMultiSelect/FluidMultiSelect.d.ts +1 -6
  103. package/lib/components/FluidMultiSelect/FluidMultiSelect.js +1 -2
  104. package/lib/components/InlineLoading/InlineLoading.js +5 -11
  105. package/lib/components/Menu/Menu.js +7 -3
  106. package/lib/components/Menu/MenuItem.d.ts +5 -1
  107. package/lib/components/Menu/MenuItem.js +11 -1
  108. package/lib/components/MenuButton/index.d.ts +1 -1
  109. package/lib/components/MenuButton/index.js +2 -1
  110. package/lib/components/MultiSelect/FilterableMultiSelect.d.ts +1 -1
  111. package/lib/components/MultiSelect/FilterableMultiSelect.js +6 -4
  112. package/lib/components/MultiSelect/MultiSelect.d.ts +3 -4
  113. package/lib/components/MultiSelect/MultiSelect.js +9 -12
  114. package/lib/components/Notification/Notification.js +5 -3
  115. package/lib/components/NumberInput/NumberInput.d.ts +1 -1
  116. package/lib/components/NumberInput/NumberInput.js +5 -4
  117. package/lib/components/OverflowMenu/OverflowMenu.d.ts +1 -0
  118. package/lib/components/OverflowMenu/OverflowMenu.js +7 -3
  119. package/lib/components/PageHeader/PageHeader.d.ts +1 -1
  120. package/lib/components/PageHeader/PageHeader.js +4 -4
  121. package/lib/components/RadioButtonGroup/RadioButtonGroup.js +4 -3
  122. package/lib/components/Select/Select.js +2 -1
  123. package/lib/components/StructuredList/StructuredList.d.ts +1 -1
  124. package/lib/components/StructuredList/StructuredList.js +2 -4
  125. package/lib/components/Tabs/Tabs.d.ts +2 -2
  126. package/lib/components/Tabs/Tabs.js +15 -21
  127. package/lib/components/Tag/DismissibleTag.js +2 -1
  128. package/lib/components/Tag/OperationalTag.js +2 -1
  129. package/lib/components/Tag/SelectableTag.js +2 -1
  130. package/lib/components/Tag/Tag.js +2 -1
  131. package/lib/components/TextArea/TextArea.d.ts +1 -1
  132. package/lib/components/TextArea/TextArea.js +7 -8
  133. package/lib/components/TextInput/ControlledPasswordInput.js +7 -6
  134. package/lib/components/TextInput/PasswordInput.js +5 -6
  135. package/lib/components/TextInput/TextInput.js +4 -4
  136. package/lib/components/Tile/Tile.d.ts +1 -1
  137. package/lib/components/Tile/Tile.js +35 -67
  138. package/lib/components/TimePicker/TimePicker.js +2 -2
  139. package/lib/components/Tooltip/DefinitionTooltip.d.ts +1 -1
  140. package/lib/components/Tooltip/DefinitionTooltip.js +3 -2
  141. package/lib/components/UIShell/SideNav.d.ts +0 -1
  142. package/lib/components/UIShell/SideNav.js +11 -2
  143. package/lib/internal/useId.js +2 -3
  144. package/lib/internal/usePresence.js +2 -1
  145. package/lib/internal/useResizeObserver.d.ts +1 -1
  146. package/lib/internal/useResizeObserver.js +4 -6
  147. package/lib/tools/events.d.ts +1 -1
  148. package/package.json +8 -8
@@ -10,14 +10,13 @@ import { Close, ChevronLeft, ChevronRight } from '@carbon/icons-react';
10
10
  import { breakpoints } from '@carbon/layout';
11
11
  import cx from 'classnames';
12
12
  import PropTypes from 'prop-types';
13
- import React, { forwardRef, createContext, useRef, useState, useMemo, isValidElement, useCallback, useEffect } from 'react';
13
+ import React, { forwardRef, createContext, useRef, useState, useMemo, isValidElement, Children, cloneElement, useCallback, useEffect } from 'react';
14
14
  import '../Grid/FlexGrid.js';
15
15
  import { Grid as GridAsGridComponent } from '../Grid/Grid.js';
16
16
  import '../Grid/Row.js';
17
17
  import '../Grid/Column.js';
18
18
  import '../Grid/ColumnHang.js';
19
19
  import '../Grid/GridContext.js';
20
- import { isElement } from 'react-is';
21
20
  import '../Tooltip/DefinitionTooltip.js';
22
21
  import { Tooltip } from '../Tooltip/Tooltip.js';
23
22
  import { useControllableState } from '../../internal/useControllableState.js';
@@ -34,6 +33,7 @@ import { useMatchMedia } from '../../internal/useMatchMedia.js';
34
33
  import { Text } from '../Text/Text.js';
35
34
  import '../Text/TextDirection.js';
36
35
  import { BadgeIndicator } from '../BadgeIndicator/index.js';
36
+ import { isComponentElement } from '../../internal/utils.js';
37
37
  import { debounce } from '../../node_modules/es-toolkit/dist/compat/function/debounce.js';
38
38
 
39
39
  var _ChevronLeft, _ChevronRight, _BadgeIndicator;
@@ -269,14 +269,7 @@ function TabList({
269
269
  const nextButton = useRef(null);
270
270
  const [isScrollable, setIsScrollable] = useState(false);
271
271
  const [scrollLeft, setScrollLeft] = useState(0);
272
- let hasSecondaryLabelTabs = false;
273
- if (contained) {
274
- hasSecondaryLabelTabs = React.Children.toArray(children).some(child => {
275
- // eslint-disable-next-line @typescript-eslint/no-explicit-any -- https://github.com/carbon-design-system/carbon/issues/20452
276
- const _child = child;
277
- return /*#__PURE__*/React.isValidElement(child) && !!_child.props.secondaryLabel;
278
- });
279
- }
272
+ const hasSecondaryLabelTabs = contained && Children.toArray(children).some(child => isComponentElement(child, Tab) && typeof child.props.secondaryLabel !== 'undefined');
280
273
  const isLg = useMatchMedia(lgMediaQuery);
281
274
  const distributeWidth = fullWidth && contained && isLg && React.Children.toArray(children).length < 9;
282
275
  const className = cx(`${prefix}--tabs`, {
@@ -487,17 +480,16 @@ function TabList({
487
480
  onScroll: debouncedOnScroll,
488
481
  onKeyDown: onKeyDown,
489
482
  onBlur: handleBlur
490
- }), React.Children.map(children, (child, index) => {
491
- return !isElement(child) ? null : /*#__PURE__*/React.createElement(TabContext.Provider, {
483
+ }), Children.map(children, (child, index) => {
484
+ return ! /*#__PURE__*/isValidElement(child) ? null : /*#__PURE__*/React.createElement(TabContext.Provider, {
492
485
  value: {
493
486
  index,
494
487
  hasSecondaryLabel: hasSecondaryLabelTabs,
495
488
  contained
496
489
  }
497
- }, /*#__PURE__*/React.cloneElement(
498
- // eslint-disable-next-line @typescript-eslint/no-explicit-any -- https://github.com/carbon-design-system/carbon/issues/20452
499
- child, {
490
+ }, /*#__PURE__*/cloneElement(child, {
500
491
  ref: node => {
492
+ if (!node) return;
501
493
  tabs.current[index] = node;
502
494
  }
503
495
  }));
@@ -641,8 +633,7 @@ function TabListVertical({
641
633
  if (containerTop && containerHeight) {
642
634
  // scrolls so selected tab is in view
643
635
  if (selectedPositionTop - halfTabHeight < containerTop || selectedPositionTop - containerTop + verticalTabHeight + halfTabHeight > containerHeight) {
644
- // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- https://github.com/carbon-design-system/carbon/issues/20452
645
- ref.current && ref.current.scrollTo({
636
+ ref.current?.scrollTo({
646
637
  top: (selectedIndex - 1) * verticalTabHeight,
647
638
  behavior: 'smooth'
648
639
  });
@@ -690,16 +681,15 @@ function TabListVertical({
690
681
  className: `${prefix}--tab--list`,
691
682
  onKeyDown: onKeyDown,
692
683
  onBlur: handleBlur
693
- }), React.Children.map(children, (child, index) => {
694
- return !isElement(child) ? null : /*#__PURE__*/React.createElement(TabContext.Provider, {
684
+ }), Children.map(children, (child, index) => {
685
+ return ! /*#__PURE__*/isValidElement(child) ? null : /*#__PURE__*/React.createElement(TabContext.Provider, {
695
686
  value: {
696
687
  index,
697
688
  hasSecondaryLabel: false
698
689
  }
699
- }, /*#__PURE__*/React.cloneElement(
700
- // eslint-disable-next-line @typescript-eslint/no-explicit-any -- https://github.com/carbon-design-system/carbon/issues/20452
701
- child, {
690
+ }, /*#__PURE__*/cloneElement(child, {
702
691
  ref: node => {
692
+ if (!node) return;
703
693
  tabs.current[index] = node;
704
694
  }
705
695
  }));
@@ -1045,7 +1035,11 @@ const IconTab = /*#__PURE__*/React.forwardRef(({
1045
1035
  const value = useMemo(() => ({
1046
1036
  badgeIndicator
1047
1037
  }), [badgeIndicator]);
1048
- const hasSize20 = /*#__PURE__*/isValidElement(children) && children.props.size === 20;
1038
+ const hasSize20 = /*#__PURE__*/isValidElement(children) &&
1039
+ // TODO: The interface allows `size` to be a string. Should this case be
1040
+ // handled here, or should the prop type be restricted to `number`
1041
+ // instead?
1042
+ children.props.size === 20;
1049
1043
  const classNames = cx(`${prefix}--tabs__nav-item--icon-only`, customClassName, {
1050
1044
  [`${prefix}--tabs__nav-item--icon-only__20`]: hasSize20
1051
1045
  });
@@ -1176,10 +1170,10 @@ function TabPanels({
1176
1170
  });
1177
1171
  }
1178
1172
  });
1179
- return /*#__PURE__*/React.createElement(React.Fragment, null, React.Children.map(children, (child, index) => {
1180
- return !isElement(child) ? null : /*#__PURE__*/React.createElement(TabPanelContext.Provider, {
1173
+ return /*#__PURE__*/React.createElement(React.Fragment, null, Children.map(children, (child, index) => {
1174
+ return ! /*#__PURE__*/isValidElement(child) ? null : /*#__PURE__*/React.createElement(TabPanelContext.Provider, {
1181
1175
  value: index
1182
- }, /*#__PURE__*/React.cloneElement(child, {
1176
+ }, /*#__PURE__*/cloneElement(child, {
1183
1177
  ref: element => {
1184
1178
  refs.current[index] = element;
1185
1179
  }
@@ -7,7 +7,7 @@
7
7
 
8
8
  import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
9
9
  import PropTypes from 'prop-types';
10
- import React, { forwardRef, useRef, useState, useLayoutEffect, cloneElement } from 'react';
10
+ import React, { forwardRef, useRef, useState, cloneElement } from 'react';
11
11
  import cx from 'classnames';
12
12
  import { useId } from '../../internal/useId.js';
13
13
  import { usePrefix } from '../../internal/usePrefix.js';
@@ -22,6 +22,7 @@ import { isEllipsisActive } from './isEllipsisActive.js';
22
22
  import { mergeRefs } from '../../tools/mergeRefs.js';
23
23
  import { AILabel } from '../AILabel/index.js';
24
24
  import { isComponentElement } from '../../internal/utils.js';
25
+ import useIsomorphicEffect from '../../internal/useIsomorphicEffect.js';
25
26
 
26
27
  var _Close;
27
28
  // eslint-disable-next-line react/display-name -- https://github.com/carbon-design-system/carbon/issues/20452
@@ -48,7 +49,7 @@ const DismissibleTag = /*#__PURE__*/forwardRef(({
48
49
  const tagId = id || `tag-${useId()}`;
49
50
  const tagClasses = cx(`${prefix}--tag--filter`, className);
50
51
  const [isEllipsisApplied, setIsEllipsisApplied] = useState(false);
51
- useLayoutEffect(() => {
52
+ useIsomorphicEffect(() => {
52
53
  const newElement = tagLabelRef.current?.getElementsByClassName(`${prefix}--tag__label`)[0];
53
54
  setIsEllipsisApplied(isEllipsisActive(newElement));
54
55
  }, [prefix, tagLabelRef]);
@@ -7,7 +7,7 @@
7
7
 
8
8
  import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
9
9
  import PropTypes from 'prop-types';
10
- import React, { forwardRef, useRef, useState, useLayoutEffect } from 'react';
10
+ import React, { forwardRef, useRef, useState } from 'react';
11
11
  import cx from 'classnames';
12
12
  import { useId } from '../../internal/useId.js';
13
13
  import { usePrefix } from '../../internal/usePrefix.js';
@@ -18,6 +18,7 @@ import { Text } from '../Text/Text.js';
18
18
  import '../Text/TextDirection.js';
19
19
  import { isEllipsisActive } from './isEllipsisActive.js';
20
20
  import { mergeRefs } from '../../tools/mergeRefs.js';
21
+ import useIsomorphicEffect from '../../internal/useIsomorphicEffect.js';
21
22
 
22
23
  const TYPES = {
23
24
  red: 'Red',
@@ -48,7 +49,7 @@ const OperationalTag = /*#__PURE__*/forwardRef(({
48
49
  const tagId = id || `tag-${useId()}`;
49
50
  const tagClasses = cx(`${prefix}--tag--operational`, className);
50
51
  const [isEllipsisApplied, setIsEllipsisApplied] = useState(false);
51
- useLayoutEffect(() => {
52
+ useIsomorphicEffect(() => {
52
53
  const newElement = tagRef.current?.getElementsByClassName(`${prefix}--tag__label`)[0];
53
54
  setIsEllipsisApplied(isEllipsisActive(newElement));
54
55
  }, [prefix, tagRef]);
@@ -7,7 +7,7 @@
7
7
 
8
8
  import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
9
9
  import PropTypes from 'prop-types';
10
- import React, { forwardRef, useRef, useState, useLayoutEffect } from 'react';
10
+ import React, { forwardRef, useRef, useState } from 'react';
11
11
  import cx from 'classnames';
12
12
  import { useId } from '../../internal/useId.js';
13
13
  import { usePrefix } from '../../internal/usePrefix.js';
@@ -19,6 +19,7 @@ import '../Text/TextDirection.js';
19
19
  import { isEllipsisActive } from './isEllipsisActive.js';
20
20
  import { mergeRefs } from '../../tools/mergeRefs.js';
21
21
  import { useControllableState } from '../../internal/useControllableState.js';
22
+ import useIsomorphicEffect from '../../internal/useIsomorphicEffect.js';
22
23
 
23
24
  // eslint-disable-next-line react/display-name -- https://github.com/carbon-design-system/carbon/issues/20452
24
25
  const SelectableTag = /*#__PURE__*/forwardRef(({
@@ -47,7 +48,7 @@ const SelectableTag = /*#__PURE__*/forwardRef(({
47
48
  [`${prefix}--tag--selectable-selected`]: selectedTag
48
49
  });
49
50
  const [isEllipsisApplied, setIsEllipsisApplied] = useState(false);
50
- useLayoutEffect(() => {
51
+ useIsomorphicEffect(() => {
51
52
  const newElement = tagRef.current?.getElementsByClassName(`${prefix}--tag__label`)[0];
52
53
  setIsEllipsisApplied(isEllipsisActive(newElement));
53
54
  }, [prefix, tagRef]);
@@ -7,7 +7,7 @@
7
7
 
8
8
  import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
9
9
  import PropTypes from 'prop-types';
10
- import React, { useRef, useState, useLayoutEffect, cloneElement } from 'react';
10
+ import React, { useRef, useState, cloneElement } from 'react';
11
11
  import cx from 'classnames';
12
12
  import { Close } from '@carbon/icons-react';
13
13
  import { useId } from '../../internal/useId.js';
@@ -21,6 +21,7 @@ import { isEllipsisActive } from './isEllipsisActive.js';
21
21
  import { useMergedRefs } from '../../internal/useMergedRefs.js';
22
22
  import { AILabel } from '../AILabel/index.js';
23
23
  import { isComponentElement } from '../../internal/utils.js';
24
+ import useIsomorphicEffect from '../../internal/useIsomorphicEffect.js';
24
25
 
25
26
  var _Close;
26
27
  const TYPES = {
@@ -76,7 +77,7 @@ const TagBase = /*#__PURE__*/React.forwardRef(({
76
77
  // eslint-disable-next-line react-hooks/rules-of-hooks -- https://github.com/carbon-design-system/carbon/issues/20452
77
78
  const tagId = id || `tag-${useId()}`;
78
79
  const [isEllipsisApplied, setIsEllipsisApplied] = useState(false);
79
- useLayoutEffect(() => {
80
+ useIsomorphicEffect(() => {
80
81
  const newElement = tagRef.current?.getElementsByClassName(`${prefix}--tag__label`)[0];
81
82
  setIsEllipsisApplied(isEllipsisActive(newElement));
82
83
  }, [prefix, tagRef]);
@@ -5,7 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  import React, { type ReactNode } from 'react';
8
- export interface TextAreaProps extends React.InputHTMLAttributes<HTMLTextAreaElement> {
8
+ export interface TextAreaProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {
9
9
  /**
10
10
  * Provide a custom className that is applied directly to the underlying
11
11
  * `<textarea>` node
@@ -144,9 +144,7 @@ const TextArea = frFn((props, forwardRef) => {
144
144
  setTimeout(() => {
145
145
  setTextCount(0);
146
146
  }, 0);
147
- return;
148
- }
149
- if (enableCounter && typeof maxCount !== 'undefined' && textareaRef.current !== null) {
147
+ } else if (enableCounter && typeof maxCount !== 'undefined' && textareaRef.current !== null) {
150
148
  const matchedWords = evt.target?.value?.match(/\p{L}+/gu);
151
149
  if (matchedWords && matchedWords.length <= maxCount) {
152
150
  textareaRef.current.removeAttribute('maxLength');
@@ -195,24 +193,25 @@ const TextArea = frFn((props, forwardRef) => {
195
193
  const helperTextClasses = cx(`${prefix}--form__helper-text`, {
196
194
  [`${prefix}--form__helper-text--disabled`]: disabled
197
195
  });
198
- const label = labelText ? /*#__PURE__*/React.createElement(Text, {
196
+ const label = typeof labelText !== 'undefined' && labelText !== null && /*#__PURE__*/React.createElement(Text, {
199
197
  as: "label",
200
198
  htmlFor: id,
201
199
  className: labelClasses
202
- }, labelText) : null;
200
+ }, labelText);
203
201
  const counter = enableCounter && maxCount && (counterMode === 'character' || counterMode === 'word') ? /*#__PURE__*/React.createElement(Text, {
204
202
  as: "div",
205
203
  className: counterClasses,
206
204
  "aria-hidden": "true"
207
205
  }, `${textCount}/${maxCount}`) : null;
208
206
  const counterDescriptionId = enableCounter && maxCount ? `${id}-counter-desc` : undefined;
209
- const helperId = !helperText ? undefined : `text-area-helper-text-${textAreaInstanceId}`;
210
- const helper = helperText ? /*#__PURE__*/React.createElement(Text, {
207
+ const hasHelper = typeof helperText !== 'undefined' && helperText !== null;
208
+ const helperId = !hasHelper ? undefined : `text-area-helper-text-${textAreaInstanceId}`;
209
+ const helper = hasHelper && /*#__PURE__*/React.createElement(Text, {
211
210
  as: "div",
212
211
  id: helperId,
213
212
  className: helperTextClasses,
214
213
  ref: helperTextRef
215
- }, helperText) : null;
214
+ }, helperText);
216
215
  const errorId = id + '-error-msg';
217
216
  const error = invalid ? /*#__PURE__*/React.createElement(Text, {
218
217
  as: "div",
@@ -71,10 +71,10 @@ const ControlledPasswordInput = /*#__PURE__*/forwardRef(({
71
71
  const helperTextClasses = cx(`${prefix}--form__helper-text`, {
72
72
  [`${prefix}--form__helper-text--disabled`]: disabled
73
73
  });
74
- const label = labelText ? /*#__PURE__*/React.createElement("label", {
74
+ const label = typeof labelText !== 'undefined' && labelText !== null && /*#__PURE__*/React.createElement("label", {
75
75
  htmlFor: id,
76
76
  className: labelClasses
77
- }, labelText) : null;
77
+ }, labelText);
78
78
  const error = invalid ? /*#__PURE__*/React.createElement("div", {
79
79
  className: `${prefix}--form-requirement`,
80
80
  id: errorId
@@ -89,12 +89,13 @@ const ControlledPasswordInput = /*#__PURE__*/forwardRef(({
89
89
  [`${prefix}--tooltip--${tooltipPosition}`]: tooltipPosition,
90
90
  [`${prefix}--tooltip--align-${tooltipAlignment}`]: tooltipAlignment
91
91
  });
92
- const helperId = !helperText ? undefined : `controlled-password-helper-text-${controlledPasswordInstanceId}`;
92
+ const hasHelper = typeof helperText !== 'undefined' && helperText !== null;
93
+ const helperId = !hasHelper ? undefined : `controlled-password-helper-text-${controlledPasswordInstanceId}`;
93
94
  const input = /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("input", _extends({}, getTextInputProps({
94
95
  invalid,
95
96
  sharedTextInputProps,
96
97
  invalidId: errorId,
97
- hasHelper: !error && helperText ? true : false,
98
+ hasHelper: !error && hasHelper,
98
99
  helperId
99
100
  }), {
100
101
  "data-toggle-password-visibility": type === 'password'
@@ -105,10 +106,10 @@ const ControlledPasswordInput = /*#__PURE__*/forwardRef(({
105
106
  }, /*#__PURE__*/React.createElement("span", {
106
107
  className: `${prefix}--assistive-text`
107
108
  }, passwordIsVisible ? hidePasswordLabel : showPasswordLabel), passwordVisibilityIcon));
108
- const helper = helperText ? /*#__PURE__*/React.createElement("div", {
109
+ const helper = hasHelper && /*#__PURE__*/React.createElement("div", {
109
110
  id: helperId,
110
111
  className: helperTextClasses
111
- }, helperText) : null;
112
+ }, helperText);
112
113
  return /*#__PURE__*/React.createElement("div", {
113
114
  className: `${prefix}--form-item ${prefix}--text-input-wrapper ${prefix}--password-input-wrapper`
114
115
  }, label, /*#__PURE__*/React.createElement("div", {
@@ -61,8 +61,7 @@ const PasswordInput = /*#__PURE__*/forwardRef(({
61
61
  } = useContext(FormContext);
62
62
  const handleTogglePasswordVisibility = event => {
63
63
  setInputType(inputType === 'password' ? 'text' : 'password');
64
- // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- https://github.com/carbon-design-system/carbon/issues/20452
65
- onTogglePasswordVisibility && onTogglePasswordVisibility(event);
64
+ onTogglePasswordVisibility?.(event);
66
65
  };
67
66
  const textInputClasses = cx(`${prefix}--text-input`, `${prefix}--password-input`, className, {
68
67
  [`${prefix}--text-input--light`]: light,
@@ -117,14 +116,14 @@ const PasswordInput = /*#__PURE__*/forwardRef(({
117
116
  [`${prefix}--text-input__invalid-icon`]: normalizedProps.invalid || normalizedProps.warn,
118
117
  [`${prefix}--text-input__invalid-icon--warning`]: normalizedProps.warn
119
118
  });
120
- const label = labelText ? /*#__PURE__*/React.createElement("label", {
119
+ const label = typeof labelText !== 'undefined' && labelText !== null && /*#__PURE__*/React.createElement("label", {
121
120
  htmlFor: id,
122
121
  className: labelClasses
123
- }, labelText) : null;
124
- const helper = helperText ? /*#__PURE__*/React.createElement("div", {
122
+ }, labelText);
123
+ const helper = typeof helperText !== 'undefined' && helperText !== null && /*#__PURE__*/React.createElement("div", {
125
124
  id: normalizedProps.helperId,
126
125
  className: helperTextClasses
127
- }, helperText) : null;
126
+ }, helperText);
128
127
  const passwordIsVisible = inputType === 'text';
129
128
  const passwordVisibilityIcon = passwordIsVisible ? /*#__PURE__*/React.createElement(ViewOff, {
130
129
  className: `${prefix}--icon-visibility-off`
@@ -141,19 +141,19 @@ const TextInput = /*#__PURE__*/forwardRef(({
141
141
  as: "div",
142
142
  className: counterClasses
143
143
  }, `${textCount}/${maxCount}`) : null;
144
- const label = labelText ? /*#__PURE__*/React.createElement(Text, {
144
+ const label = typeof labelText !== 'undefined' && labelText !== null && /*#__PURE__*/React.createElement(Text, {
145
145
  as: "label",
146
146
  htmlFor: id,
147
147
  className: labelClasses
148
- }, labelText) : null;
148
+ }, labelText);
149
149
  const labelWrapper = /*#__PURE__*/React.createElement("div", {
150
150
  className: `${prefix}--text-input__label-wrapper`
151
151
  }, label, counter);
152
- const helper = helperText ? /*#__PURE__*/React.createElement(Text, {
152
+ const helper = typeof helperText !== 'undefined' && helperText !== null && /*#__PURE__*/React.createElement(Text, {
153
153
  as: "div",
154
154
  id: normalizedProps.helperId,
155
155
  className: helperTextClasses
156
- }, helperText) : null;
156
+ }, helperText);
157
157
  const input = /*#__PURE__*/React.createElement("input", getTextInputProps({
158
158
  sharedTextInputProps,
159
159
  invalid: normalizedProps.invalid,
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright IBM Corp. 2019, 2025
2
+ * Copyright IBM Corp. 2019, 2026
3
3
  *
4
4
  * This source code is licensed under the Apache-2.0 license found in the
5
5
  * LICENSE file in the root directory of this source tree.
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
9
- import React, { useState, useEffect, useCallback, useRef, cloneElement } from 'react';
9
+ import React, { forwardRef, useState, useEffect, useCallback, useRef, cloneElement, Children } from 'react';
10
10
  import PropTypes from 'prop-types';
11
11
  import cx from 'classnames';
12
12
  import { AiLabel, CheckboxCheckedFilled, Checkbox, ChevronDown, ArrowRight, Error } from '@carbon/icons-react';
@@ -363,7 +363,7 @@ SelectableTile.propTypes = {
363
363
  */
364
364
  value: deprecate(PropTypes.oneOfType([PropTypes.string, PropTypes.number]), 'The `value` property is no longer used. It will be removed in the next major release.`')
365
365
  };
366
- const ExpandableTile = /*#__PURE__*/React.forwardRef(({
366
+ const ExpandableTile = /*#__PURE__*/forwardRef(({
367
367
  tabIndex = 0,
368
368
  className,
369
369
  children,
@@ -382,11 +382,8 @@ const ExpandableTile = /*#__PURE__*/React.forwardRef(({
382
382
  hasRoundedCorners,
383
383
  ...rest
384
384
  }, forwardRef) => {
385
- const [isTileMaxHeight, setIsTileMaxHeight] = useState(tileMaxHeight);
386
- const [isTilePadding, setIsTilePadding] = useState(tilePadding);
387
- const [prevExpanded, setPrevExpanded] = useState(expanded);
388
- const [prevTileMaxHeight, setPrevTileMaxHeight] = useState(tileMaxHeight);
389
- const [prevTilePadding, setPrevTilePadding] = useState(tilePadding);
385
+ const [measuredAboveHeight, setMeasuredAboveHeight] = useState(0);
386
+ const [measuredPadding, setMeasuredPadding] = useState(0);
390
387
  const [isExpanded, setIsExpanded] = useState(expanded);
391
388
  const [interactive, setInteractive] = useState(true);
392
389
  const aboveTheFold = useRef(null);
@@ -396,105 +393,74 @@ const ExpandableTile = /*#__PURE__*/React.forwardRef(({
396
393
  const tile = useRef(null);
397
394
  const ref = useMergedRefs([forwardRef, tile]);
398
395
  const prefix = usePrefix();
399
- if (expanded !== prevExpanded) {
396
+ useEffect(() => {
400
397
  setIsExpanded(expanded);
401
- setPrevExpanded(expanded);
402
- setMaxHeight();
403
- }
404
- if (tileMaxHeight !== prevTileMaxHeight) {
405
- setIsTileMaxHeight(tileMaxHeight);
406
- setPrevTileMaxHeight(tileMaxHeight);
407
- }
408
- if (tilePadding !== prevTilePadding) {
409
- setIsTilePadding(tilePadding);
410
- setPrevTilePadding(tilePadding);
411
- }
412
- function setMaxHeight() {
413
- if (isExpanded && tileContent.current) {
414
- setIsTileMaxHeight(tileContent.current.getBoundingClientRect()?.height);
415
- }
416
- if (aboveTheFold.current) {
417
- setIsTileMaxHeight(aboveTheFold.current.getBoundingClientRect().height);
418
- }
419
- }
420
- function handleClick(evt) {
421
- evt?.persist?.();
422
- setIsExpanded(!isExpanded);
423
- setMaxHeight();
424
- }
425
- function handleKeyUp(evt) {
398
+ }, [expanded]);
399
+ const handleClick = () => {
400
+ setIsExpanded(prev => !prev);
401
+ };
402
+ const handleKeyUp = evt => {
426
403
  if (evt.target !== tile.current && evt.target !== chevronInteractiveRef.current) {
427
404
  if (matches(evt, [Enter, Space])) {
428
405
  evt.preventDefault();
429
406
  }
430
407
  }
431
- }
432
- function getChildren() {
433
- return React.Children.toArray(children);
434
- }
408
+ };
435
409
  const classNames = cx(`${prefix}--tile`, `${prefix}--tile--expandable`, {
436
410
  [`${prefix}--tile--is-expanded`]: isExpanded,
437
411
  [`${prefix}--tile--light`]: light
438
412
  }, className);
439
- const interactiveClassNames = cx(`${prefix}--tile`, `${prefix}--tile--expandable`, `${prefix}--tile--expandable--interactive`, {
440
- [`${prefix}--tile--is-expanded`]: isExpanded,
441
- [`${prefix}--tile--light`]: light,
413
+ const interactiveClassNames = cx(classNames, `${prefix}--tile--expandable--interactive`, {
442
414
  [`${prefix}--tile--slug`]: slug,
443
415
  [`${prefix}--tile--slug-rounded`]: slug && hasRoundedCorners,
444
416
  [`${prefix}--tile--decorator`]: decorator,
445
417
  [`${prefix}--tile--decorator-rounded`]: decorator && hasRoundedCorners
446
- }, className);
418
+ });
447
419
  const chevronInteractiveClassNames = cx(`${prefix}--tile__chevron`, `${prefix}--tile__chevron--interactive`);
448
- const childrenAsArray = getChildren();
420
+ const childrenAsArray = Children.toArray(children);
449
421
  useIsomorphicEffect(() => {
450
422
  if (!tile.current || !aboveTheFold.current) {
451
423
  return;
452
424
  }
453
- const getStyle = window.getComputedStyle(tile.current, null);
454
- const {
455
- current: node
456
- } = aboveTheFold;
457
- const {
458
- height
459
- } = node.getBoundingClientRect();
460
- const paddingTop = parseInt(getStyle.getPropertyValue('padding-top'), 10);
461
- const paddingBottom = parseInt(getStyle.getPropertyValue('padding-bottom'), 10);
462
- setIsTileMaxHeight(height);
463
- setIsTilePadding(paddingTop + paddingBottom);
464
- }, [isTileMaxHeight]);
425
+ const style = window.getComputedStyle(tile.current);
426
+ const paddingTop = parseInt(style.getPropertyValue('padding-top'), 10) || 0;
427
+ const paddingBottom = parseInt(style.getPropertyValue('padding-bottom'), 10) || 0;
428
+ setMeasuredPadding(paddingTop + paddingBottom);
429
+ setMeasuredAboveHeight(aboveTheFold.current.scrollHeight);
430
+ }, []);
465
431
  useIsomorphicEffect(() => {
466
432
  if (!aboveTheFold.current || !belowTheFold.current) {
467
433
  return;
468
434
  }
469
-
470
- // Interactive elements or elements that are given a role should be treated
471
- // the same because elements with a role can not be rendered inside a `button`
472
- if (!getInteractiveContent(belowTheFold.current) && !getRoleContent(belowTheFold.current) && !getInteractiveContent(aboveTheFold.current) && !getRoleContent(aboveTheFold.current) && !(slug || decorator)) {
473
- setInteractive(false);
474
- }
475
- }, [slug, decorator]);
435
+ const hasInteractive = Boolean(getInteractiveContent(aboveTheFold.current)) || Boolean(getRoleContent(aboveTheFold.current)) || Boolean(getInteractiveContent(belowTheFold.current)) || Boolean(getRoleContent(belowTheFold.current)) || Boolean(slug || decorator);
436
+ setInteractive(hasInteractive);
437
+ }, [slug, decorator, children]);
476
438
  useIsomorphicEffect(() => {
477
439
  if (!tile.current) {
478
440
  return;
479
441
  }
480
442
  if (isExpanded) {
481
443
  tile.current.style.maxHeight = '';
482
- } else {
483
- tile.current.style.maxHeight = isTileMaxHeight + isTilePadding + 'px';
444
+ return;
484
445
  }
485
- }, [isExpanded, isTileMaxHeight, isTilePadding]);
446
+ const measured = measuredAboveHeight || aboveTheFold.current?.scrollHeight || 0;
447
+ const baseHeight = tileMaxHeight > 0 ? tileMaxHeight : measured;
448
+ const pad = tilePadding > 0 ? tilePadding : measuredPadding;
449
+ tile.current.style.maxHeight = `${baseHeight + pad}px`;
450
+ }, [isExpanded, tileMaxHeight, tilePadding, measuredAboveHeight, measuredPadding]);
486
451
  useEffect(() => {
487
452
  if (!aboveTheFold.current) {
488
453
  return;
489
454
  }
490
- const resizeObserver = new ResizeObserver(entries => {
491
- const [aboveTheFold] = entries;
492
- setIsTileMaxHeight(aboveTheFold.contentRect.height);
455
+ const resizeObserver = new ResizeObserver(() => {
456
+ if (aboveTheFold.current) {
457
+ setMeasuredAboveHeight(aboveTheFold.current.scrollHeight);
458
+ }
493
459
  });
494
460
  resizeObserver.observe(aboveTheFold.current);
495
461
  return () => resizeObserver.disconnect();
496
- }, [isTileMaxHeight, isTilePadding]);
497
- const belowTheFoldId = useId('expandable-tile-interactive');
462
+ }, []);
463
+ const belowTheFoldId = useId(interactive ? 'expandable-tile-interactive' : 'expandable-tile');
498
464
 
499
465
  // AILabel is always size `xs`
500
466
  const candidate = slug ?? decorator;
@@ -529,6 +495,7 @@ const ExpandableTile = /*#__PURE__*/React.forwardRef(({
529
495
  type: "button",
530
496
  ref: ref,
531
497
  className: classNames,
498
+ "aria-controls": belowTheFoldId,
532
499
  "aria-expanded": isExpanded,
533
500
  title: isExpanded ? tileExpandedIconText : tileCollapsedIconText
534
501
  }, rest, {
@@ -544,6 +511,7 @@ const ExpandableTile = /*#__PURE__*/React.forwardRef(({
544
511
  className: `${prefix}--tile__chevron`
545
512
  }, /*#__PURE__*/React.createElement("span", null, isExpanded ? tileExpandedLabel : tileCollapsedLabel), _ChevronDown2 || (_ChevronDown2 = /*#__PURE__*/React.createElement(ChevronDown, null))), /*#__PURE__*/React.createElement("div", {
546
513
  ref: belowTheFold,
514
+ id: belowTheFoldId,
547
515
  className: `${prefix}--tile-content`
548
516
  }, childrenAsArray[1])));
549
517
  });
@@ -98,10 +98,10 @@ const TimePicker = frFn((props, ref) => {
98
98
  [`${prefix}--visually-hidden`]: hideLabel,
99
99
  [`${prefix}--label--disabled`]: disabled
100
100
  });
101
- const label = labelText ? /*#__PURE__*/React.createElement("label", {
101
+ const label = typeof labelText !== 'undefined' && labelText !== null && /*#__PURE__*/React.createElement("label", {
102
102
  htmlFor: id,
103
103
  className: labelClasses
104
- }, labelText) : null;
104
+ }, labelText);
105
105
  function getInternalPickerSelects() {
106
106
  const readOnlyEventHandlers = {
107
107
  onMouseDown: evt => {
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright IBM Corp. 2016, 2025
2
+ * Copyright IBM Corp. 2016, 2026
3
3
  *
4
4
  * This source code is licensed under the Apache-2.0 license found in the
5
5
  * LICENSE file in the root directory of this source tree.
@@ -48,8 +48,9 @@ const DefinitionTooltip = ({
48
48
  setOpen(false);
49
49
  },
50
50
  onMouseEnter: () => {
51
- // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- https://github.com/carbon-design-system/carbon/issues/20452
52
- openOnHover ? setOpen(true) : null;
51
+ if (openOnHover) {
52
+ setOpen(true);
53
+ }
53
54
  },
54
55
  onFocus: () => {
55
56
  setOpen(true);
@@ -19,7 +19,6 @@ export interface SideNavProps {
19
19
  onOverlayClick?: MouseEventHandler<HTMLDivElement> | undefined;
20
20
  onSideNavBlur?: () => void;
21
21
  enterDelayMs?: number;
22
- inert?: boolean;
23
22
  }
24
23
  interface SideNavContextData {
25
24
  isRail?: boolean | undefined;
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
9
- import React, { forwardRef, useRef, isValidElement, createContext } from 'react';
9
+ import React, { forwardRef, useRef, isValidElement, useEffect, createContext } from 'react';
10
10
  import cx from 'classnames';
11
11
  import PropTypes from 'prop-types';
12
12
  import { AriaLabelPropType } from '../../prop-types/AriaPropTypes.js';
@@ -157,6 +157,16 @@ const SideNav = frFn((props, ref) => {
157
157
  });
158
158
  const lgMediaQuery = `(min-width: ${breakpoints.lg.width})`;
159
159
  const isLg = useMatchMedia(lgMediaQuery);
160
+ const inertEnabled = !isRail ? !(expanded || isLg) : false;
161
+ useEffect(() => {
162
+ const node = sideNavRef.current;
163
+ if (!node) return;
164
+ if (inertEnabled) {
165
+ node.setAttribute('inert', '');
166
+ } else {
167
+ node.removeAttribute('inert');
168
+ }
169
+ }, [inertEnabled]);
160
170
  return /*#__PURE__*/React.createElement(SideNavContext.Provider, {
161
171
  value: {
162
172
  isRail
@@ -170,8 +180,7 @@ const SideNav = frFn((props, ref) => {
170
180
  }), /*#__PURE__*/React.createElement("nav", _extends({
171
181
  tabIndex: -1,
172
182
  ref: navRef,
173
- className: `${prefix}--side-nav__navigation ${className}`,
174
- inert: !isRail ? !(expanded || isLg) : undefined
183
+ className: `${prefix}--side-nav__navigation ${className}`
175
184
  }, accessibilityLabel, eventHandlers, other), childrenToRender));
176
185
  });
177
186
  SideNav.displayName = 'SideNav';