@carbon/react 1.111.1 → 1.112.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 (37) hide show
  1. package/.playwright/INTERNAL_AVT_REPORT_DO_NOT_USE.json +994 -994
  2. package/es/components/ComboBox/ComboBox.js +7 -7
  3. package/es/components/Dropdown/Dropdown.js +1 -4
  4. package/es/components/FeatureFlags/index.js +32 -14
  5. package/es/components/IconIndicator/index.d.ts +33 -1
  6. package/es/components/IconIndicator/index.js +55 -26
  7. package/es/components/MultiSelect/FilterableMultiSelect.js +6 -7
  8. package/es/components/MultiSelect/MultiSelect.js +3 -4
  9. package/es/components/OverflowMenu/OverflowMenu.js +31 -6
  10. package/es/components/OverflowMenu/next/index.d.ts +1 -1
  11. package/es/components/OverflowMenu/next/index.js +2 -2
  12. package/es/components/ShapeIndicator/index.d.ts +18 -0
  13. package/es/components/ShapeIndicator/index.js +49 -7
  14. package/es/components/Tabs/Tabs.js +1 -1
  15. package/es/components/Tooltip/DefinitionTooltip.js +5 -2
  16. package/es/internal/index.d.ts +2 -1
  17. package/es/internal/isItemDisabled.d.ts +7 -0
  18. package/es/internal/isItemDisabled.js +17 -0
  19. package/lib/components/ComboBox/ComboBox.js +7 -7
  20. package/lib/components/Dropdown/Dropdown.js +2 -5
  21. package/lib/components/FeatureFlags/index.js +32 -14
  22. package/lib/components/IconIndicator/index.d.ts +33 -1
  23. package/lib/components/IconIndicator/index.js +54 -25
  24. package/lib/components/MultiSelect/FilterableMultiSelect.js +6 -7
  25. package/lib/components/MultiSelect/MultiSelect.js +3 -4
  26. package/lib/components/OverflowMenu/OverflowMenu.js +30 -5
  27. package/lib/components/OverflowMenu/next/index.d.ts +1 -1
  28. package/lib/components/OverflowMenu/next/index.js +2 -2
  29. package/lib/components/ShapeIndicator/index.d.ts +18 -0
  30. package/lib/components/ShapeIndicator/index.js +48 -6
  31. package/lib/components/Tabs/Tabs.js +1 -1
  32. package/lib/components/Tooltip/DefinitionTooltip.js +4 -1
  33. package/lib/internal/index.d.ts +2 -1
  34. package/lib/internal/isItemDisabled.d.ts +7 -0
  35. package/lib/internal/isItemDisabled.js +17 -0
  36. package/package.json +9 -8
  37. package/telemetry.yml +2 -0
@@ -930,7 +930,7 @@ function TabPanels({ children }) {
930
930
  const isVertical = tabContainer?.classList.contains(`${prefix}--tabs--vertical`);
931
931
  const parentHasHeight = tabContainer?.parentElement?.style.height;
932
932
  if (isVertical && !parentHasHeight) {
933
- hiddenStates.current = refs.current.map((ref) => ref?.hidden || false);
933
+ hiddenStates.current = refs.current.map((ref) => ref?.hasAttribute("hidden") || false);
934
934
  refs.current.forEach((ref) => {
935
935
  if (ref) ref.hidden = false;
936
936
  });
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  import { usePrefix } from "../../internal/usePrefix.js";
9
- import { Escape } from "../../internal/keyboard/keys.js";
9
+ import { Enter, Escape, Space } from "../../internal/keyboard/keys.js";
10
10
  import { match } from "../../internal/keyboard/match.js";
11
11
  import { useFallbackId } from "../../internal/useId.js";
12
12
  import { deprecate } from "../../prop-types/deprecate.js";
@@ -27,7 +27,10 @@ const DefinitionTooltip = ({ align = "bottom", autoAlign, className, children, d
27
27
  const prefix = usePrefix();
28
28
  const tooltipId = useFallbackId(id);
29
29
  function onKeyDown(event) {
30
- if (isOpen && match(event, Escape)) {
30
+ if (match(event, Enter) || match(event, Space)) {
31
+ event.preventDefault();
32
+ setOpen(!isOpen);
33
+ } else if (isOpen && match(event, Escape)) {
31
34
  event.stopPropagation();
32
35
  setOpen(false);
33
36
  }
@@ -1,8 +1,9 @@
1
1
  /**
2
- * Copyright IBM Corp. 2025
2
+ * Copyright IBM Corp. 2025, 2026
3
3
  *
4
4
  * This source code is licensed under the Apache-2.0 license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  export * from './defaultItemToString';
8
+ export * from './isItemDisabled';
8
9
  export * from './utils';
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Copyright IBM Corp. 2026
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 isItemDisabled: (item: unknown) => boolean;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Copyright IBM Corp. 2016, 2026
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
+ //#region src/internal/isItemDisabled.ts
9
+ /**
10
+ * Copyright IBM Corp. 2026
11
+ *
12
+ * This source code is licensed under the Apache-2.0 license found in the
13
+ * LICENSE file in the root directory of this source tree.
14
+ */
15
+ const isItemDisabled = (item) => item !== null && typeof item === "object" && "disabled" in item && item.disabled === true;
16
+ //#endregion
17
+ export { isItemDisabled };
@@ -13,6 +13,7 @@ const require_match = require("../../internal/keyboard/match.js");
13
13
  const require_useId = require("../../internal/useId.js");
14
14
  const require_deprecate = require("../../prop-types/deprecate.js");
15
15
  const require_defaultItemToString = require("../../internal/defaultItemToString.js");
16
+ const require_isItemDisabled = require("../../internal/isItemDisabled.js");
16
17
  const require_utils = require("../../internal/utils.js");
17
18
  const require_index = require("../FeatureFlags/index.js");
18
19
  const require_useNormalizedInputProps = require("../../internal/useNormalizedInputProps.js");
@@ -44,7 +45,6 @@ react_fast_compare = require_runtime.__toESM(react_fast_compare);
44
45
  */
45
46
  const { InputBlur, InputKeyDownEnter, FunctionToggleMenu, ToggleButtonClick, ItemMouseMove, InputKeyDownArrowUp, InputKeyDownArrowDown, MenuMouseLeave, ItemClick, FunctionSelectItem } = downshift.useCombobox.stateChangeTypes;
46
47
  const defaultShouldFilterItem = () => true;
47
- const isDisabledItem = (item) => item !== null && typeof item === "object" && "disabled" in item && Boolean(item.disabled);
48
48
  const autocompleteCustomFilter = ({ item, inputValue }) => {
49
49
  if (inputValue === null || inputValue === "") return true;
50
50
  const lowercaseItem = item.toLowerCase();
@@ -61,7 +61,7 @@ const findHighlightedIndex = ({ items, itemToString = require_defaultItemToStrin
61
61
  const searchValue = inputValue.toLowerCase();
62
62
  for (let i = 0; i < items.length; i++) {
63
63
  const item = itemToString(items[i]).toLowerCase();
64
- if (!isDisabledItem(items[i]) && item.indexOf(searchValue) !== -1) return i;
64
+ if (!require_isItemDisabled.isItemDisabled(items[i]) && item.indexOf(searchValue) !== -1) return i;
65
65
  }
66
66
  return -1;
67
67
  };
@@ -104,7 +104,7 @@ const ComboBox = (0, react.forwardRef)((props, ref) => {
104
104
  (0, react.useEffect)(() => {
105
105
  if (typeahead) {
106
106
  if (inputValue.length >= prevInputLengthRef.current) if (inputValue) {
107
- const filteredItems = items.filter((item) => !isDisabledItem(item) && autocompleteCustomFilter({
107
+ const filteredItems = items.filter((item) => !require_isItemDisabled.isItemDisabled(item) && autocompleteCustomFilter({
108
108
  item: itemToString(item),
109
109
  inputValue
110
110
  }));
@@ -226,7 +226,7 @@ const ComboBox = (0, react.forwardRef)((props, ref) => {
226
226
  case InputKeyDownEnter:
227
227
  if (!allowCustomValue) if (state.highlightedIndex !== -1) {
228
228
  const highlightedItem = filterItems(items, itemToString, inputValue)[state.highlightedIndex];
229
- if (highlightedItem && !isDisabledItem(highlightedItem)) return {
229
+ if (highlightedItem && !require_isItemDisabled.isItemDisabled(highlightedItem)) return {
230
230
  ...changes,
231
231
  selectedItem: highlightedItem,
232
232
  inputValue: itemToString(highlightedItem)
@@ -235,7 +235,7 @@ const ComboBox = (0, react.forwardRef)((props, ref) => {
235
235
  const autoIndex = indexToHighlight(inputValue);
236
236
  if (autoIndex !== -1) {
237
237
  const matchingItem = items[autoIndex];
238
- if (matchingItem && !isDisabledItem(matchingItem)) return {
238
+ if (matchingItem && !require_isItemDisabled.isItemDisabled(matchingItem)) return {
239
239
  ...changes,
240
240
  selectedItem: matchingItem,
241
241
  inputValue: itemToString(matchingItem)
@@ -357,7 +357,7 @@ const ComboBox = (0, react.forwardRef)((props, ref) => {
357
357
  initialSelectedItem,
358
358
  inputId: id,
359
359
  stateReducer,
360
- isItemDisabled: isDisabledItem,
360
+ isItemDisabled: require_isItemDisabled.isItemDisabled,
361
361
  ...downshiftProps,
362
362
  onStateChange: ({ type, selectedItem: newSelectedItem }) => {
363
363
  if (isManualClearingRef.current || isSyncingControlledSelectionRef.current) {
@@ -544,7 +544,7 @@ const ComboBox = (0, react.forwardRef)((props, ref) => {
544
544
  }
545
545
  if (typeahead && event.key === "Tab") {
546
546
  if (!isOpen) return;
547
- const matchingItem = items.find((item) => !isDisabledItem(item) && itemToString(item).toLowerCase().startsWith(inputValue.toLowerCase()));
547
+ const matchingItem = items.find((item) => !require_isItemDisabled.isItemDisabled(item) && itemToString(item).toLowerCase().startsWith(inputValue.toLowerCase()));
548
548
  if (matchingItem) {
549
549
  downshiftSetInputValue(itemToString(matchingItem));
550
550
  selectItem(matchingItem);
@@ -9,6 +9,7 @@ const require_runtime = require("../../_virtual/_rolldown/runtime.js");
9
9
  const require_usePrefix = require("../../internal/usePrefix.js");
10
10
  const require_deprecate = require("../../prop-types/deprecate.js");
11
11
  const require_defaultItemToString = require("../../internal/defaultItemToString.js");
12
+ const require_isItemDisabled = require("../../internal/isItemDisabled.js");
12
13
  const require_utils = require("../../internal/utils.js");
13
14
  const require_index = require("../FeatureFlags/index.js");
14
15
  const require_useNormalizedInputProps = require("../../internal/useNormalizedInputProps.js");
@@ -103,9 +104,6 @@ const Dropdown = react.default.forwardRef(({ autoAlign = false, className: conta
103
104
  const onSelectedItemChange = (0, react.useCallback)(({ selectedItem }) => {
104
105
  if (onChange) onChange({ selectedItem: selectedItem ?? null });
105
106
  }, [onChange]);
106
- const isItemDisabled = (0, react.useCallback)((item) => {
107
- return item !== null && typeof item === "object" && "disabled" in item && item.disabled === true;
108
- }, []);
109
107
  const onHighlightedIndexChange = (0, react.useCallback)((changes) => {
110
108
  const { highlightedIndex } = changes;
111
109
  if (highlightedIndex !== void 0 && highlightedIndex > -1) {
@@ -123,7 +121,7 @@ const Dropdown = react.default.forwardRef(({ autoAlign = false, className: conta
123
121
  initialSelectedItem,
124
122
  onSelectedItemChange,
125
123
  stateReducer,
126
- isItemDisabled,
124
+ isItemDisabled: require_isItemDisabled.isItemDisabled,
127
125
  onHighlightedIndexChange,
128
126
  ...downshiftProps
129
127
  }), [
@@ -132,7 +130,6 @@ const Dropdown = react.default.forwardRef(({ autoAlign = false, className: conta
132
130
  initialSelectedItem,
133
131
  onSelectedItemChange,
134
132
  stateReducer,
135
- isItemDisabled,
136
133
  onHighlightedIndexChange,
137
134
  downshiftProps
138
135
  ]);
@@ -25,27 +25,45 @@ let react_jsx_runtime = require("react/jsx-runtime");
25
25
  * or disable feature flags in a given React tree
26
26
  */
27
27
  const FeatureFlagContext = (0, react.createContext)(_carbon_feature_flags.FeatureFlags);
28
+ const PROP_TO_FLAG = {
29
+ enableV12TileDefaultIcons: "enable-v12-tile-default-icons",
30
+ enableV12TileRadioIcons: "enable-v12-tile-radio-icons",
31
+ enableV12Overflowmenu: "enable-v12-overflowmenu",
32
+ enableTreeviewControllable: "enable-treeview-controllable",
33
+ enableExperimentalFocusWrapWithoutSentinels: "enable-experimental-focus-wrap-without-sentinels",
34
+ enableFocusWrapWithoutSentinels: "enable-focus-wrap-without-sentinels",
35
+ enableDialogElement: "enable-dialog-element",
36
+ enableV12DynamicFloatingStyles: "enable-v12-dynamic-floating-styles",
37
+ enableEnhancedFileUploader: "enable-enhanced-file-uploader",
38
+ enablePresence: "enable-presence"
39
+ };
28
40
  /**
29
41
  * Supports an object of feature flag values with the `flags` prop, merging them
30
42
  * along with the current `FeatureFlagContext` to provide consumers to check if
31
43
  * a feature flag is enabled or disabled in a given React tree
32
44
  */
33
- const FeatureFlags = ({ children, flags = {}, enableV12TileDefaultIcons = false, enableV12TileRadioIcons = false, enableV12Overflowmenu = false, enableTreeviewControllable = false, enableExperimentalFocusWrapWithoutSentinels = false, enableFocusWrapWithoutSentinels = false, enableDialogElement = false, enableV12DynamicFloatingStyles = false, enableEnhancedFileUploader = false, enablePresence = false }) => {
45
+ const FeatureFlags = ({ children, flags, enableV12TileDefaultIcons, enableV12TileRadioIcons, enableV12Overflowmenu, enableTreeviewControllable, enableExperimentalFocusWrapWithoutSentinels, enableFocusWrapWithoutSentinels, enableDialogElement, enableV12DynamicFloatingStyles, enableEnhancedFileUploader, enablePresence }) => {
34
46
  const parentScope = (0, react.useContext)(FeatureFlagContext);
35
47
  const scope = (0, react.useMemo)(() => {
36
- const scope = (0, _carbon_feature_flags.createScope)({
37
- "enable-v12-tile-default-icons": enableV12TileDefaultIcons,
38
- "enable-v12-tile-radio-icons": enableV12TileRadioIcons,
39
- "enable-v12-overflowmenu": enableV12Overflowmenu,
40
- "enable-treeview-controllable": enableTreeviewControllable,
41
- "enable-experimental-focus-wrap-without-sentinels": enableExperimentalFocusWrapWithoutSentinels,
42
- "enable-focus-wrap-without-sentinels": enableFocusWrapWithoutSentinels,
43
- "enable-dialog-element": enableDialogElement,
44
- "enable-v12-dynamic-floating-styles": enableV12DynamicFloatingStyles,
45
- "enable-enhanced-file-uploader": enableEnhancedFileUploader,
46
- "enable-presence": enablePresence,
47
- ...flags
48
- });
48
+ const flagProps = {
49
+ enableV12TileDefaultIcons,
50
+ enableV12TileRadioIcons,
51
+ enableV12Overflowmenu,
52
+ enableTreeviewControllable,
53
+ enableExperimentalFocusWrapWithoutSentinels,
54
+ enableFocusWrapWithoutSentinels,
55
+ enableDialogElement,
56
+ enableV12DynamicFloatingStyles,
57
+ enableEnhancedFileUploader,
58
+ enablePresence
59
+ };
60
+ const explicitFlags = {};
61
+ for (const [prop, flagKey] of Object.entries(PROP_TO_FLAG)) {
62
+ const value = flagProps[prop];
63
+ if (value !== void 0) explicitFlags[flagKey] = value;
64
+ }
65
+ if (flags) Object.assign(explicitFlags, flags);
66
+ const scope = (0, _carbon_feature_flags.createScope)(explicitFlags);
49
67
  scope.mergeWithScope(parentScope);
50
68
  return scope;
51
69
  }, [
@@ -5,13 +5,45 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  import React from 'react';
8
- export declare const IconIndicatorKinds: string[];
8
+ import { PopoverAlignment } from '../Popover';
9
+ declare const iconTypes: {
10
+ readonly failed: import("@carbon/icons-react").CarbonIconType;
11
+ readonly 'caution-major': import("@carbon/icons-react").CarbonIconType;
12
+ readonly 'caution-minor': import("@carbon/icons-react").CarbonIconType;
13
+ readonly undefined: import("@carbon/icons-react").CarbonIconType;
14
+ readonly succeeded: import("@carbon/icons-react").CarbonIconType;
15
+ readonly normal: import("@carbon/icons-react").CarbonIconType;
16
+ readonly 'in-progress': import("@carbon/icons-react").CarbonIconType;
17
+ readonly incomplete: import("@carbon/icons-react").CarbonIconType;
18
+ readonly 'not-started': import("@carbon/icons-react").CarbonIconType;
19
+ readonly pending: import("@carbon/icons-react").CarbonIconType;
20
+ readonly unknown: import("@carbon/icons-react").CarbonIconType;
21
+ readonly informative: import("@carbon/icons-react").CarbonIconType;
22
+ };
23
+ export declare const IconIndicatorKinds: (keyof typeof iconTypes)[];
9
24
  export type IconIndicatorKind = (typeof IconIndicatorKinds)[number];
10
25
  export interface IconIndicatorProps {
26
+ /**
27
+ * Specify how the tooltip should align with the icon in compact mode
28
+ */
29
+ align?: PopoverAlignment;
30
+ /**
31
+ * Will auto-align the tooltip in compact mode.
32
+ */
33
+ autoAlign?: boolean;
11
34
  /**
12
35
  * Specify an optional className to add.
13
36
  */
14
37
  className?: string;
38
+ /**
39
+ * When true, displays only the icon with the label in a tooltip
40
+ */
41
+ compact?: boolean;
42
+ /**
43
+ * Description for the icon announced to screen readers in compact mode.
44
+ * Defaults to `label` when not provided.
45
+ */
46
+ iconDescription?: string;
15
47
  /**
16
48
  * Specify the kind of icon to be used
17
49
  */
@@ -7,6 +7,7 @@
7
7
 
8
8
  const require_runtime = require("../../_virtual/_rolldown/runtime.js");
9
9
  const require_usePrefix = require("../../internal/usePrefix.js");
10
+ const require_DefinitionTooltip = require("../Tooltip/DefinitionTooltip.js");
10
11
  let classnames = require("classnames");
11
12
  classnames = require_runtime.__toESM(classnames);
12
13
  let react = require("react");
@@ -22,54 +23,82 @@ let _carbon_icons_react = require("@carbon/icons-react");
22
23
  * This source code is licensed under the Apache-2.0 license found in the
23
24
  * LICENSE file in the root directory of this source tree.
24
25
  */
25
- const IconIndicatorKinds = [
26
- "failed",
27
- "caution-major",
28
- "caution-minor",
29
- "undefined",
30
- "succeeded",
31
- "normal",
32
- "in-progress",
33
- "incomplete",
34
- "not-started",
35
- "pending",
36
- "unknown",
37
- "informative"
38
- ];
39
26
  const iconTypes = {
40
27
  failed: _carbon_icons_react.ErrorFilled,
41
- ["caution-major"]: _carbon_icons_react.WarningAltInvertedFilled,
42
- ["caution-minor"]: _carbon_icons_react.WarningAltFilled,
28
+ "caution-major": _carbon_icons_react.WarningAltInvertedFilled,
29
+ "caution-minor": _carbon_icons_react.WarningAltFilled,
43
30
  undefined: _carbon_icons_react.UndefinedFilled,
44
31
  succeeded: _carbon_icons_react.CheckmarkFilled,
45
32
  normal: _carbon_icons_react.CheckmarkOutline,
46
- ["in-progress"]: _carbon_icons_react.InProgress,
33
+ "in-progress": _carbon_icons_react.InProgress,
47
34
  incomplete: _carbon_icons_react.Incomplete,
48
- ["not-started"]: _carbon_icons_react.CircleDash,
35
+ "not-started": _carbon_icons_react.CircleDash,
49
36
  pending: _carbon_icons_react.PendingFilled,
50
37
  unknown: _carbon_icons_react.UnknownFilled,
51
38
  informative: _carbon_icons_react.WarningSquareFilled
52
39
  };
53
- const IconIndicator = react.default.forwardRef(({ className: customClassName, kind, label, size = 16 }, ref) => {
40
+ const IconIndicatorKinds = Object.keys(iconTypes);
41
+ const IconIndicator = react.default.forwardRef(({ align = "right", autoAlign = false, className: customClassName, compact = false, iconDescription, kind, label, size = 16 }, ref) => {
54
42
  const prefix = require_usePrefix.usePrefix();
55
- const classNames = (0, classnames.default)(`${prefix}--icon-indicator`, customClassName, { [`${prefix}--icon-indicator--20`]: size == 20 });
43
+ const classNames = (0, classnames.default)(`${prefix}--icon-indicator`, customClassName, { [`${prefix}--icon-indicator--20`]: size === 20 });
56
44
  const IconForKind = iconTypes[kind];
57
45
  if (!IconForKind) return null;
58
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
46
+ const iconElement = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconForKind, {
47
+ size,
48
+ className: `${prefix}--icon-indicator--${kind}`
49
+ });
50
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
59
51
  className: classNames,
60
52
  ref,
61
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconForKind, {
62
- size,
63
- className: `${prefix}--icon-indicator--${kind}`
64
- }), label]
53
+ children: compact ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_DefinitionTooltip.DefinitionTooltip, {
54
+ align,
55
+ autoAlign,
56
+ openOnHover: true,
57
+ definition: label,
58
+ triggerClassName: `${prefix}--icon-indicator__button`,
59
+ children: [iconElement, /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
60
+ className: `${prefix}--visually-hidden`,
61
+ children: iconDescription ?? label
62
+ })]
63
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [iconElement, label] })
65
64
  });
66
65
  });
67
66
  IconIndicator.propTypes = {
67
+ /**
68
+ * Specify how the tooltip should align with the icon in compact mode
69
+ */
70
+ align: prop_types.default.oneOf([
71
+ "top",
72
+ "top-start",
73
+ "top-end",
74
+ "bottom",
75
+ "bottom-start",
76
+ "bottom-end",
77
+ "left",
78
+ "left-start",
79
+ "left-end",
80
+ "right",
81
+ "right-start",
82
+ "right-end"
83
+ ]),
84
+ /**
85
+ * Will auto-align the tooltip in compact mode
86
+ */
87
+ autoAlign: prop_types.default.bool,
68
88
  /**
69
89
  * Specify an optional className to add.
70
90
  */
71
91
  className: prop_types.default.string,
72
92
  /**
93
+ * When true, displays only the icon with the label in a tooltip
94
+ */
95
+ compact: prop_types.default.bool,
96
+ /**
97
+ * Description for the icon announced to screen readers in compact mode.
98
+ * Defaults to `label` when not provided.
99
+ */
100
+ iconDescription: prop_types.default.string,
101
+ /**
73
102
  * Specify the kind of the Icon Indicator
74
103
  */
75
104
  kind: prop_types.default.oneOf(IconIndicatorKinds).isRequired,
@@ -13,6 +13,7 @@ const require_useIsomorphicEffect = require("../../internal/useIsomorphicEffect.
13
13
  const require_useId = require("../../internal/useId.js");
14
14
  const require_deprecate = require("../../prop-types/deprecate.js");
15
15
  const require_defaultItemToString = require("../../internal/defaultItemToString.js");
16
+ const require_isItemDisabled = require("../../internal/isItemDisabled.js");
16
17
  const require_utils = require("../../internal/utils.js");
17
18
  const require_hasHelperText = require("../../internal/hasHelperText.js");
18
19
  const require_useNormalizedInputProps = require("../../internal/useNormalizedInputProps.js");
@@ -78,7 +79,7 @@ const FilterableMultiSelect = (0, react.forwardRef)(function FilterableMultiSele
78
79
  filteredItems
79
80
  });
80
81
  const selectAllStatus = (0, react.useMemo)(() => {
81
- const selectable = nonSelectAllItems.filter((item) => !item.disabled);
82
+ const selectable = nonSelectAllItems.filter((item) => !require_isItemDisabled.isItemDisabled(item));
82
83
  const nonSelectedCount = selectable.filter((item) => !controlledSelectedItems.some((sel) => (0, react_fast_compare.default)(sel, item))).length;
83
84
  const totalCount = selectable.length;
84
85
  return {
@@ -87,7 +88,7 @@ const FilterableMultiSelect = (0, react.forwardRef)(function FilterableMultiSele
87
88
  };
88
89
  }, [controlledSelectedItems, nonSelectAllItems]);
89
90
  const handleSelectAllClick = (0, react.useCallback)(() => {
90
- const selectable = nonSelectAllItems.filter((i) => !i.disabled);
91
+ const selectable = nonSelectAllItems.filter((item) => !require_isItemDisabled.isItemDisabled(item));
91
92
  const { checked, indeterminate } = selectAllStatus;
92
93
  if (checked || indeterminate) toggleAll(controlledSelectedItems.filter((sel) => !filteredItems.some((e) => (0, react_fast_compare.default)(e, sel))));
93
94
  else {
@@ -137,7 +138,7 @@ const FilterableMultiSelect = (0, react.forwardRef)(function FilterableMultiSele
137
138
  }, [open]);
138
139
  const sortedItems = (0, react.useMemo)(() => {
139
140
  const selectAllItem = items.find(require_isSelectAllItem.isSelectAllItem);
140
- const selectableRealItems = nonSelectAllItems.filter((item) => !item.disabled);
141
+ const selectableRealItems = nonSelectAllItems.filter((item) => !require_isItemDisabled.isItemDisabled(item));
141
142
  const sortedReal = sortItems(nonSelectAllItems, {
142
143
  selectedItems: {
143
144
  top: controlledSelectedItems,
@@ -261,9 +262,7 @@ const FilterableMultiSelect = (0, react.forwardRef)(function FilterableMultiSele
261
262
  inputId,
262
263
  inputValue,
263
264
  stateReducer,
264
- isItemDisabled(item) {
265
- return item?.disabled;
266
- }
265
+ isItemDisabled: require_isItemDisabled.isItemDisabled
267
266
  });
268
267
  function stateReducer(state, actionAndChanges) {
269
268
  const { type, props, changes } = actionAndChanges;
@@ -272,7 +271,7 @@ const FilterableMultiSelect = (0, react.forwardRef)(function FilterableMultiSele
272
271
  switch (type) {
273
272
  case InputKeyDownEnter:
274
273
  if (sortedItems.length === 0) return changes;
275
- if (changes.selectedItem && changes.selectedItem.disabled !== true) if (require_isSelectAllItem.isSelectAllItem(changes.selectedItem)) handleSelectAllClick();
274
+ if (changes.selectedItem && !require_isItemDisabled.isItemDisabled(changes.selectedItem)) if (require_isSelectAllItem.isSelectAllItem(changes.selectedItem)) handleSelectAllClick();
276
275
  else onItemChange(changes.selectedItem);
277
276
  setHighlightedIndex(changes.selectedItem);
278
277
  return {
@@ -14,6 +14,7 @@ const require_useId = require("../../internal/useId.js");
14
14
  const require_noopFn = require("../../internal/noopFn.js");
15
15
  const require_deprecate = require("../../prop-types/deprecate.js");
16
16
  const require_defaultItemToString = require("../../internal/defaultItemToString.js");
17
+ const require_isItemDisabled = require("../../internal/isItemDisabled.js");
17
18
  const require_utils = require("../../internal/utils.js");
18
19
  const require_index = require("../FeatureFlags/index.js");
19
20
  const require_useNormalizedInputProps = require("../../internal/useNormalizedInputProps.js");
@@ -119,9 +120,7 @@ const MultiSelect = react.default.forwardRef(({ autoAlign = false, className: co
119
120
  },
120
121
  selectedItem: controlledSelectedItems,
121
122
  items: filteredItems,
122
- isItemDisabled(item) {
123
- return item?.disabled;
124
- },
123
+ isItemDisabled: require_isItemDisabled.isItemDisabled,
125
124
  ...downshiftProps
126
125
  });
127
126
  const toggleButtonProps = getToggleButtonProps({
@@ -303,7 +302,7 @@ const MultiSelect = react.default.forwardRef(({ autoAlign = false, className: co
303
302
  return {
304
303
  hasIndividualSelections: selectedItems.some((selected) => !require_isSelectAllItem.isSelectAllItem(selected)),
305
304
  nonSelectAllSelectedCount: selectedItems.filter((selected) => !require_isSelectAllItem.isSelectAllItem(selected)).length,
306
- totalSelectableCount: filteredItems.filter((item) => !require_isSelectAllItem.isSelectAllItem(item) && !item.disabled).length
305
+ totalSelectableCount: filteredItems.filter((item) => !require_isSelectAllItem.isSelectAllItem(item) && !require_isItemDisabled.isItemDisabled(item)).length
307
306
  };
308
307
  }, [selectedItems, filteredItems]);
309
308
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -86,7 +86,7 @@ const getMenuOffset = (menuBody, direction, trigger, flip) => {
86
86
  };
87
87
  }
88
88
  };
89
- const OverflowMenu = (0, react.forwardRef)(({ align, ["aria-label"]: ariaLabel = null, ariaLabel: deprecatedAriaLabel, children, className, direction = require_FloatingMenu.DIRECTION_BOTTOM, flipped = false, focusTrap = false, iconClass, iconDescription = "Options", id, light, menuOffset = getMenuOffset, menuOffsetFlip = getMenuOffset, menuOptionsClass, onClick = require_noopFn.noopFn, onClose = require_noopFn.noopFn, onOpen = require_noopFn.noopFn, open: openProp, renderIcon: IconElement = _carbon_icons_react.OverflowMenuVertical, selectorPrimaryFocus = "[data-floating-menu-primary-focus]", size = "md", innerRef, ...other }, ref) => {
89
+ const OverflowMenu = (0, react.forwardRef)(({ align, ["aria-label"]: ariaLabel = null, ariaLabel: deprecatedAriaLabel, children, className, direction = require_FloatingMenu.DIRECTION_BOTTOM, flipped = false, focusTrap = false, iconClass, iconDescription = "Options", id, light, menuOffset = getMenuOffset, menuOffsetFlip = getMenuOffset, menuOptionsClass, onClick = require_noopFn.noopFn, onClose = require_noopFn.noopFn, onOpen = require_noopFn.noopFn, open: openProp, renderIcon: IconElement = _carbon_icons_react.OverflowMenuVertical, selectorPrimaryFocus = "[data-floating-menu-primary-focus]", size, innerRef, ...other }, ref) => {
90
90
  const prefix = (0, react.useContext)(require_usePrefix.PrefixContext);
91
91
  const [open, setOpen] = (0, react.useState)(openProp ?? false);
92
92
  const [click, setClick] = (0, react.useState)(false);
@@ -101,6 +101,8 @@ const OverflowMenu = (0, react.forwardRef)(({ align, ["aria-label"]: ariaLabel =
101
101
  /** The element ref of the tooltip's trigger button. */
102
102
  const triggerRef = (0, react.useRef)(null);
103
103
  const wrapperRef = (0, react.useRef)(null);
104
+ const [, forceUpdate] = (0, react.useReducer)((x) => x + 1, 0);
105
+ const resizeObserverRef = (0, react.useRef)(null);
104
106
  (0, react.useEffect)(() => {
105
107
  if (prevOpenProp.current !== openProp) {
106
108
  setOpen(!!openProp);
@@ -110,6 +112,26 @@ const OverflowMenu = (0, react.forwardRef)(({ align, ["aria-label"]: ariaLabel =
110
112
  (0, react.useEffect)(() => {
111
113
  if (triggerRef.current) setHasMountedTrigger(true);
112
114
  }, []);
115
+ /**
116
+ * When `size` is brought in from a contextual layout token, FloatingMenu can't detect size changes
117
+ * while the menu is open since there is no state/prop update. This ResizeObserver watches
118
+ * the trigger button when the menu is open and calls `forceUpdate()` on resize to force a re-render if its
119
+ * size changes while the menu is open
120
+ */
121
+ (0, react.useEffect)(() => {
122
+ resizeObserverRef.current = new ResizeObserver(() => {
123
+ forceUpdate();
124
+ });
125
+ return () => {
126
+ resizeObserverRef.current?.disconnect();
127
+ resizeObserverRef.current = null;
128
+ };
129
+ }, []);
130
+ (0, react.useEffect)(() => {
131
+ if (!triggerRef.current || !resizeObserverRef.current) return;
132
+ if (open) resizeObserverRef.current.observe(triggerRef.current);
133
+ else resizeObserverRef.current.disconnect();
134
+ }, [open]);
113
135
  (0, react.useEffect)(() => {
114
136
  if (open && !prevOpenState.current) onOpen();
115
137
  else if (!open && prevOpenState.current) onClose();
@@ -210,22 +232,25 @@ const OverflowMenu = (0, react.forwardRef)(({ align, ["aria-label"]: ariaLabel =
210
232
  };
211
233
  const getTarget = () => {
212
234
  const triggerEl = triggerRef.current;
213
- if (triggerEl instanceof Element) return triggerEl.closest("[data-floating-menu-container]") || document.body;
235
+ if (triggerEl instanceof Element) return triggerEl.closest("[data-floating-menu-container]") || triggerEl.closest(`.${prefix}--layout`) || document.body;
214
236
  return document.body;
215
237
  };
216
238
  const menuBodyId = `overflow-menu-${instanceId.current}__menu-body`;
217
239
  const overflowMenuClasses = (0, classnames.default)(className, `${prefix}--overflow-menu`, {
218
240
  [`${prefix}--overflow-menu--open`]: open,
219
241
  [`${prefix}--overflow-menu--light`]: light,
220
- [`${prefix}--overflow-menu--${size}`]: size
242
+ [`${prefix}--overflow-menu--${size}`]: size,
243
+ [`${prefix}--layout--size-${size}`]: size
221
244
  });
222
245
  const overflowMenuOptionsClasses = (0, classnames.default)(menuOptionsClass, `${prefix}--overflow-menu-options`, {
223
246
  [`${prefix}--overflow-menu--flip`]: flipped,
224
247
  [`${prefix}--overflow-menu-options--open`]: open,
225
248
  [`${prefix}--overflow-menu-options--light`]: light,
226
- [`${prefix}--overflow-menu-options--${size}`]: size
249
+ [`${prefix}--overflow-menu-options--${size}`]: size,
250
+ [`${prefix}--layout--size-${size}`]: size
227
251
  });
228
252
  const overflowMenuIconClasses = (0, classnames.default)(`${prefix}--overflow-menu__icon`, iconClass);
253
+ const overflowMenuWrapperClasses = (0, classnames.default)(`${prefix}--overflow-menu__wrapper`);
229
254
  const childrenWithProps = react.Children.toArray(children).map((child, index) => {
230
255
  if ((0, react.isValidElement)(child)) {
231
256
  const childElement = child;
@@ -262,7 +287,7 @@ const OverflowMenu = (0, react.forwardRef)(({ align, ["aria-label"]: ariaLabel =
262
287
  });
263
288
  const combinedRef = innerRef ? require_mergeRefs.mergeRefs(triggerRef, innerRef, ref) : require_mergeRefs.mergeRefs(triggerRef, ref);
264
289
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
265
- className: `${prefix}--overflow-menu__wrapper`,
290
+ className: overflowMenuWrapperClasses,
266
291
  "aria-owns": open ? menuBodyId : void 0,
267
292
  ref: wrapperRef,
268
293
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_index.IconButton, {
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright IBM Corp. 2020, 2025
2
+ * Copyright IBM Corp. 2020, 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.
@@ -26,7 +26,7 @@ let _carbon_icons_react = require("@carbon/icons-react");
26
26
  let _floating_ui_react = require("@floating-ui/react");
27
27
  //#region src/components/OverflowMenu/next/index.tsx
28
28
  /**
29
- * Copyright IBM Corp. 2020, 2025
29
+ * Copyright IBM Corp. 2020, 2026
30
30
  *
31
31
  * This source code is licensed under the Apache-2.0 license found in the
32
32
  * LICENSE file in the root directory of this source tree.
@@ -71,7 +71,7 @@ const OverflowMenu = react.default.forwardRef(({ autoAlign = false, children, cl
71
71
  }
72
72
  const containerClasses = (0, classnames.default)(className, `${prefix}--overflow-menu__container`, { [`${prefix}--autoalign`]: enableFloatingStyles });
73
73
  const menuClasses = (0, classnames.default)(`${prefix}--overflow-menu__${menuAlignment}`);
74
- const triggerClasses = (0, classnames.default)(`${prefix}--overflow-menu`, { [`${prefix}--overflow-menu--open`]: open }, size !== defaultSize && `${prefix}--overflow-menu--${size}`);
74
+ const triggerClasses = (0, classnames.default)(`${prefix}--overflow-menu`, { [`${prefix}--overflow-menu--open`]: open }, size !== defaultSize && `${prefix}--overflow-menu--${size}`, size !== defaultSize && `${prefix}--layout--size-${size}`);
75
75
  const floatingRef = require_mergeRefs.mergeRefs(triggerRef, refs.setReference);
76
76
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
77
77
  ...rest,
@@ -5,13 +5,26 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  import React from 'react';
8
+ import { PopoverAlignment } from '../Popover';
8
9
  export declare const ShapeIndicatorKinds: string[];
9
10
  export type ShapeIndicatorKind = (typeof ShapeIndicatorKinds)[number];
10
11
  export interface ShapeIndicatorProps {
12
+ /**
13
+ * Specify how the tooltip should align with the shape in compact mode
14
+ */
15
+ align?: PopoverAlignment;
16
+ /**
17
+ * Will auto-align the tooltip in compact mode.
18
+ */
19
+ autoAlign?: boolean;
11
20
  /**
12
21
  * Specify an optional className to add.
13
22
  */
14
23
  className?: string;
24
+ /**
25
+ * When true, displays only the shape with the label in a tooltip
26
+ */
27
+ compact?: boolean;
15
28
  /**
16
29
  * Specify the kind of shape to be used
17
30
  */
@@ -20,6 +33,11 @@ export interface ShapeIndicatorProps {
20
33
  * Label next to the shape
21
34
  */
22
35
  label: string;
36
+ /**
37
+ * Description for the shape announced to screen readers in compact mode.
38
+ * Defaults to `label` when not provided.
39
+ */
40
+ shapeDescription?: string;
23
41
  /**
24
42
  * Specify the text size of the Shape Indicator. Defaults to 12.
25
43
  */