@carbon/react 1.78.0-rc.0 → 1.78.1
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.
- package/.playwright/INTERNAL_AVT_REPORT_DO_NOT_USE.json +851 -816
- package/es/components/Accordion/AccordionItem.js +2 -2
- package/es/components/Button/Button.d.ts +2 -3
- package/es/components/Button/Button.js +1 -2
- package/es/components/Button/ButtonBase.js +1 -1
- package/es/components/ChatButton/ChatButton.d.ts +2 -3
- package/es/components/ChatButton/ChatButton.js +1 -2
- package/es/components/ComboBox/ComboBox.js +40 -30
- package/es/components/ComboButton/index.js +0 -1
- package/es/components/ComposedModal/ComposedModal.js +65 -51
- package/es/components/ContainedList/ContainedListItem/ContainedListItem.d.ts +2 -2
- package/es/components/ContainedList/ContainedListItem/ContainedListItem.js +1 -1
- package/es/components/ContentSwitcher/ContentSwitcher.js +3 -3
- package/es/components/ContextMenu/useContextMenu.d.ts +0 -1
- package/es/components/ContextMenu/useContextMenu.js +1 -2
- package/es/components/DataTable/TableBatchAction.d.ts +3 -3
- package/es/components/DataTable/TableBatchAction.js +1 -1
- package/es/components/DataTable/TableContainer.d.ts +1 -1
- package/es/components/DataTable/TableContainer.js +3 -3
- package/es/components/DataTable/TableExpandHeader.d.ts +6 -5
- package/es/components/DataTable/TableToolbarMenu.d.ts +2 -2
- package/es/components/DataTable/TableToolbarMenu.js +1 -1
- package/es/components/DatePicker/DatePicker.js +2 -2
- package/es/components/DatePicker/plugins/fixEventsPlugin.js +1 -1
- package/es/components/Dialog/index.d.ts +42 -4
- package/es/components/Dialog/index.js +177 -0
- package/es/components/ExpandableSearch/ExpandableSearch.js +2 -2
- package/es/components/FeatureFlags/index.d.ts +3 -1
- package/es/components/FeatureFlags/index.js +3 -0
- package/es/components/FileUploader/FileUploader.d.ts +1 -1
- package/es/components/FileUploader/FileUploader.js +2 -2
- package/es/components/FileUploader/FileUploaderButton.js +2 -2
- package/es/components/FileUploader/FileUploaderDropContainer.d.ts +1 -1
- package/es/components/FileUploader/FileUploaderDropContainer.js +6 -4
- package/es/components/FileUploader/FileUploaderItem.d.ts +1 -1
- package/es/components/FileUploader/FileUploaderItem.js +2 -2
- package/es/components/Grid/CSSGrid.js +18 -14
- package/es/components/Grid/FlexGrid.js +7 -6
- package/es/components/Grid/GridTypes.d.ts +5 -3
- package/es/components/IconButton/index.js +3 -3
- package/es/components/Layer/index.d.ts +4 -6
- package/es/components/Layer/index.js +5 -6
- package/es/components/Link/Link.d.ts +2 -3
- package/es/components/Link/Link.js +1 -2
- package/es/components/ListBox/ListBoxMenuItem.d.ts +3 -3
- package/es/components/ListBox/ListBoxMenuItem.js +37 -15
- package/es/components/Menu/Menu.d.ts +1 -0
- package/es/components/Menu/Menu.js +7 -9
- package/es/components/Menu/MenuContext.d.ts +4 -4
- package/es/components/Menu/MenuContext.js +6 -1
- package/es/components/Menu/MenuItem.d.ts +2 -2
- package/es/components/Menu/MenuItem.js +16 -24
- package/es/components/MenuButton/index.js +14 -2
- package/es/components/Modal/Modal.js +121 -49
- package/es/components/ModalWrapper/ModalWrapper.js +1 -1
- package/es/components/MultiSelect/FilterableMultiSelect.js +3 -3
- package/es/components/MultiSelect/MultiSelect.js +2 -2
- package/es/components/Notification/Notification.d.ts +5 -13
- package/es/components/Notification/Notification.js +7 -9
- package/es/components/OverflowMenu/OverflowMenu.d.ts +4 -8
- package/es/components/OverflowMenu/OverflowMenu.js +3 -3
- package/es/components/OverflowMenu/next/index.d.ts +2 -2
- package/es/components/OverflowMenu/next/index.js +1 -1
- package/es/components/OverflowMenuItem/OverflowMenuItem.js +2 -2
- package/es/components/ProgressIndicator/ProgressIndicator.js +2 -2
- package/es/components/RadioTile/RadioTile.js +2 -2
- package/es/components/Search/Search.d.ts +2 -3
- package/es/components/Search/Search.js +4 -6
- package/es/components/Slider/Slider.d.ts +16 -15
- package/es/components/Slider/Slider.js +22 -22
- package/es/components/Tabs/Tabs.d.ts +3 -6
- package/es/components/Tabs/Tabs.js +8 -9
- package/es/components/Tag/DismissibleTag.d.ts +3 -5
- package/es/components/Tag/DismissibleTag.js +1 -2
- package/es/components/Tag/OperationalTag.d.ts +2 -3
- package/es/components/Tag/OperationalTag.js +1 -2
- package/es/components/Tag/SelectableTag.d.ts +3 -5
- package/es/components/Tag/SelectableTag.js +1 -2
- package/es/components/Tag/Tag.d.ts +2 -3
- package/es/components/Tag/Tag.js +1 -2
- package/es/components/Tile/Tile.d.ts +3 -5
- package/es/components/Tile/Tile.js +8 -6
- package/es/components/Toggletip/index.js +2 -2
- package/es/components/Tooltip/DefinitionTooltip.js +2 -2
- package/es/components/Tooltip/Tooltip.d.ts +1 -1
- package/es/components/Tooltip/Tooltip.js +2 -2
- package/es/components/TreeView/TreeNode.d.ts +3 -5
- package/es/components/TreeView/TreeNode.js +3 -4
- package/es/components/TreeView/TreeView.js +2 -2
- package/es/components/UIShell/HeaderContainer.js +2 -2
- package/es/components/UIShell/HeaderMenu.js +2 -2
- package/es/components/UIShell/HeaderPanel.js +2 -2
- package/es/components/UIShell/SideNav.d.ts +1 -1
- package/es/components/UIShell/SideNav.js +2 -2
- package/es/components/UIShell/SideNavHeader.d.ts +2 -3
- package/es/components/UIShell/SideNavHeader.js +1 -2
- package/es/components/UIShell/SideNavLink.d.ts +2 -2
- package/es/components/UIShell/SideNavLink.js +1 -1
- package/es/components/UIShell/SideNavMenu.d.ts +2 -2
- package/es/components/UIShell/SideNavMenu.js +3 -3
- package/es/components/UIShell/SwitcherItem.js +2 -2
- package/es/internal/FloatingMenu.js +4 -4
- package/es/internal/OptimizedResize.d.ts +18 -0
- package/es/internal/OptimizedResize.js +21 -24
- package/es/internal/keyboard/index.d.ts +9 -0
- package/es/internal/keyboard/keys.d.ts +23 -0
- package/es/internal/keyboard/keys.js +2 -2
- package/es/internal/keyboard/match.d.ts +26 -0
- package/es/internal/keyboard/match.js +17 -41
- package/es/internal/keyboard/navigation.d.ts +37 -0
- package/es/internal/keyboard/navigation.js +15 -27
- package/es/internal/useMergedRefs.js +3 -0
- package/lib/components/Accordion/AccordionItem.js +2 -2
- package/lib/components/Button/Button.d.ts +2 -3
- package/lib/components/Button/Button.js +1 -2
- package/lib/components/Button/ButtonBase.js +1 -1
- package/lib/components/ChatButton/ChatButton.d.ts +2 -3
- package/lib/components/ChatButton/ChatButton.js +1 -2
- package/lib/components/ComboBox/ComboBox.js +40 -30
- package/lib/components/ComboButton/index.js +0 -1
- package/lib/components/ComposedModal/ComposedModal.js +64 -50
- package/lib/components/ContainedList/ContainedListItem/ContainedListItem.d.ts +2 -2
- package/lib/components/ContainedList/ContainedListItem/ContainedListItem.js +1 -1
- package/lib/components/ContentSwitcher/ContentSwitcher.js +3 -3
- package/lib/components/ContextMenu/useContextMenu.d.ts +0 -1
- package/lib/components/ContextMenu/useContextMenu.js +1 -2
- package/lib/components/DataTable/TableBatchAction.d.ts +3 -3
- package/lib/components/DataTable/TableBatchAction.js +1 -1
- package/lib/components/DataTable/TableContainer.d.ts +1 -1
- package/lib/components/DataTable/TableContainer.js +3 -3
- package/lib/components/DataTable/TableExpandHeader.d.ts +6 -5
- package/lib/components/DataTable/TableToolbarMenu.d.ts +2 -2
- package/lib/components/DataTable/TableToolbarMenu.js +1 -1
- package/lib/components/DatePicker/DatePicker.js +2 -2
- package/lib/components/DatePicker/plugins/fixEventsPlugin.js +1 -1
- package/lib/components/Dialog/index.d.ts +42 -4
- package/lib/components/Dialog/index.js +190 -0
- package/lib/components/ExpandableSearch/ExpandableSearch.js +2 -2
- package/lib/components/FeatureFlags/index.d.ts +3 -1
- package/lib/components/FeatureFlags/index.js +3 -0
- package/lib/components/FileUploader/FileUploader.d.ts +1 -1
- package/lib/components/FileUploader/FileUploader.js +2 -2
- package/lib/components/FileUploader/FileUploaderButton.js +2 -2
- package/lib/components/FileUploader/FileUploaderDropContainer.d.ts +1 -1
- package/lib/components/FileUploader/FileUploaderDropContainer.js +6 -4
- package/lib/components/FileUploader/FileUploaderItem.d.ts +1 -1
- package/lib/components/FileUploader/FileUploaderItem.js +2 -2
- package/lib/components/Grid/CSSGrid.js +18 -14
- package/lib/components/Grid/FlexGrid.js +7 -6
- package/lib/components/Grid/GridTypes.d.ts +5 -3
- package/lib/components/IconButton/index.js +3 -3
- package/lib/components/Layer/index.d.ts +4 -6
- package/lib/components/Layer/index.js +5 -6
- package/lib/components/Link/Link.d.ts +2 -3
- package/lib/components/Link/Link.js +1 -2
- package/lib/components/ListBox/ListBoxMenuItem.d.ts +3 -3
- package/lib/components/ListBox/ListBoxMenuItem.js +36 -14
- package/lib/components/Menu/Menu.d.ts +1 -0
- package/lib/components/Menu/Menu.js +7 -9
- package/lib/components/Menu/MenuContext.d.ts +4 -4
- package/lib/components/Menu/MenuContext.js +6 -1
- package/lib/components/Menu/MenuItem.d.ts +2 -2
- package/lib/components/Menu/MenuItem.js +15 -23
- package/lib/components/MenuButton/index.js +14 -2
- package/lib/components/Modal/Modal.js +123 -51
- package/lib/components/ModalWrapper/ModalWrapper.js +1 -1
- package/lib/components/MultiSelect/FilterableMultiSelect.js +3 -3
- package/lib/components/MultiSelect/MultiSelect.js +2 -2
- package/lib/components/Notification/Notification.d.ts +5 -13
- package/lib/components/Notification/Notification.js +7 -9
- package/lib/components/OverflowMenu/OverflowMenu.d.ts +4 -8
- package/lib/components/OverflowMenu/OverflowMenu.js +3 -3
- package/lib/components/OverflowMenu/next/index.d.ts +2 -2
- package/lib/components/OverflowMenu/next/index.js +1 -1
- package/lib/components/OverflowMenuItem/OverflowMenuItem.js +2 -2
- package/lib/components/ProgressIndicator/ProgressIndicator.js +2 -2
- package/lib/components/RadioTile/RadioTile.js +2 -2
- package/lib/components/Search/Search.d.ts +2 -3
- package/lib/components/Search/Search.js +4 -6
- package/lib/components/Slider/Slider.d.ts +16 -15
- package/lib/components/Slider/Slider.js +22 -22
- package/lib/components/Tabs/Tabs.d.ts +3 -6
- package/lib/components/Tabs/Tabs.js +8 -9
- package/lib/components/Tag/DismissibleTag.d.ts +3 -5
- package/lib/components/Tag/DismissibleTag.js +1 -2
- package/lib/components/Tag/OperationalTag.d.ts +2 -3
- package/lib/components/Tag/OperationalTag.js +1 -2
- package/lib/components/Tag/SelectableTag.d.ts +3 -5
- package/lib/components/Tag/SelectableTag.js +1 -2
- package/lib/components/Tag/Tag.d.ts +2 -3
- package/lib/components/Tag/Tag.js +1 -2
- package/lib/components/Tile/Tile.d.ts +3 -5
- package/lib/components/Tile/Tile.js +8 -6
- package/lib/components/Toggletip/index.js +2 -2
- package/lib/components/Tooltip/DefinitionTooltip.js +2 -2
- package/lib/components/Tooltip/Tooltip.d.ts +1 -1
- package/lib/components/Tooltip/Tooltip.js +2 -2
- package/lib/components/TreeView/TreeNode.d.ts +3 -5
- package/lib/components/TreeView/TreeNode.js +3 -4
- package/lib/components/TreeView/TreeView.js +2 -2
- package/lib/components/UIShell/HeaderContainer.js +2 -2
- package/lib/components/UIShell/HeaderMenu.js +2 -2
- package/lib/components/UIShell/HeaderPanel.js +2 -2
- package/lib/components/UIShell/SideNav.d.ts +1 -1
- package/lib/components/UIShell/SideNav.js +2 -2
- package/lib/components/UIShell/SideNavHeader.d.ts +2 -3
- package/lib/components/UIShell/SideNavHeader.js +1 -2
- package/lib/components/UIShell/SideNavLink.d.ts +2 -2
- package/lib/components/UIShell/SideNavLink.js +1 -1
- package/lib/components/UIShell/SideNavMenu.d.ts +2 -2
- package/lib/components/UIShell/SideNavMenu.js +3 -3
- package/lib/components/UIShell/SwitcherItem.js +2 -2
- package/lib/internal/FloatingMenu.js +5 -5
- package/lib/internal/OptimizedResize.d.ts +18 -0
- package/lib/internal/OptimizedResize.js +21 -24
- package/lib/internal/keyboard/index.d.ts +9 -0
- package/lib/internal/keyboard/keys.d.ts +23 -0
- package/lib/internal/keyboard/keys.js +2 -2
- package/lib/internal/keyboard/match.d.ts +26 -0
- package/lib/internal/keyboard/match.js +17 -41
- package/lib/internal/keyboard/navigation.d.ts +37 -0
- package/lib/internal/keyboard/navigation.js +15 -27
- package/lib/internal/useMergedRefs.js +3 -0
- package/package.json +7 -7
- package/scss/components/dialog/_dialog.scss +9 -0
- package/scss/components/dialog/_index.scss +9 -0
- package/telemetry.yml +1 -0
- package/es/components/Modal/next/index.d.ts +0 -171
- package/es/internal/focus/index.js +0 -15
- package/lib/components/Modal/next/index.d.ts +0 -171
- package/lib/internal/focus/index.js +0 -19
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Copyright IBM Corp. 2016,
|
|
2
|
+
* Copyright IBM Corp. 2016, 2025
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the Apache-2.0 license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
|
-
import
|
|
7
|
+
import { ForwardedRef, ReactNode, type Ref } from 'react';
|
|
8
8
|
import { ForwardRefReturn, ReactAttr } from '../../types/common';
|
|
9
9
|
export interface ListBoxMenuItemProps extends ReactAttr<HTMLLIElement> {
|
|
10
10
|
/**
|
|
@@ -30,7 +30,7 @@ export interface ListBoxMenuItemProps extends ReactAttr<HTMLLIElement> {
|
|
|
30
30
|
title?: string;
|
|
31
31
|
}
|
|
32
32
|
export type ListBoxMenuItemForwardedRef = (ForwardedRef<HTMLLIElement> & {
|
|
33
|
-
menuItemOptionRef?:
|
|
33
|
+
menuItemOptionRef?: Ref<HTMLDivElement>;
|
|
34
34
|
}) | null;
|
|
35
35
|
export type ListBoxMenuItemComponent = ForwardRefReturn<ListBoxMenuItemForwardedRef, ListBoxMenuItemProps>;
|
|
36
36
|
declare const _default: ListBoxMenuItemComponent;
|
|
@@ -7,28 +7,47 @@
|
|
|
7
7
|
|
|
8
8
|
import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
|
|
9
9
|
import cx from 'classnames';
|
|
10
|
-
import React__default, { useRef, useState, useEffect } from 'react';
|
|
10
|
+
import React__default, { forwardRef, useRef, useState, useEffect } from 'react';
|
|
11
11
|
import PropTypes from 'prop-types';
|
|
12
12
|
import { usePrefix } from '../../internal/usePrefix.js';
|
|
13
|
+
import { useMergedRefs } from '../../internal/useMergedRefs.js';
|
|
13
14
|
|
|
14
|
-
|
|
15
|
+
/**
|
|
16
|
+
* Determines if the content of an element is truncated.
|
|
17
|
+
*
|
|
18
|
+
* Merges a forwarded ref with a local ref to check the element's dimensions.
|
|
19
|
+
*
|
|
20
|
+
* @template T
|
|
21
|
+
* @param forwardedRef - A ref passed from the parent component.
|
|
22
|
+
* @param deps - Dependencies to re-run the truncation check.
|
|
23
|
+
* @returns An object containing the truncation state and the merged ref.
|
|
24
|
+
*/
|
|
25
|
+
const useIsTruncated = function (forwardedRef) {
|
|
26
|
+
let deps = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
|
|
27
|
+
const localRef = useRef(null);
|
|
28
|
+
const mergedRef = useMergedRefs([...(forwardedRef ? [forwardedRef] : []), localRef]);
|
|
15
29
|
const [isTruncated, setIsTruncated] = useState(false);
|
|
16
30
|
useEffect(() => {
|
|
17
|
-
const element =
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
31
|
+
const element = localRef.current;
|
|
32
|
+
if (element) {
|
|
33
|
+
const {
|
|
34
|
+
offsetWidth,
|
|
35
|
+
scrollWidth
|
|
36
|
+
} = element;
|
|
37
|
+
setIsTruncated(offsetWidth < scrollWidth);
|
|
38
|
+
}
|
|
39
|
+
}, [localRef, ...deps]);
|
|
40
|
+
return {
|
|
41
|
+
isTruncated,
|
|
42
|
+
ref: mergedRef
|
|
43
|
+
};
|
|
44
|
+
};
|
|
26
45
|
/**
|
|
27
46
|
* `ListBoxMenuItem` is a helper component for managing the container class
|
|
28
47
|
* name, alongside any classes for any corresponding states, for a generic list
|
|
29
48
|
* box menu item.
|
|
30
49
|
*/
|
|
31
|
-
const ListBoxMenuItem = /*#__PURE__*/
|
|
50
|
+
const ListBoxMenuItem = /*#__PURE__*/forwardRef((_ref, forwardedRef) => {
|
|
32
51
|
let {
|
|
33
52
|
children,
|
|
34
53
|
isActive = false,
|
|
@@ -37,8 +56,11 @@ const ListBoxMenuItem = /*#__PURE__*/React__default.forwardRef(function ListBoxM
|
|
|
37
56
|
...rest
|
|
38
57
|
} = _ref;
|
|
39
58
|
const prefix = usePrefix();
|
|
40
|
-
const
|
|
41
|
-
const
|
|
59
|
+
const menuItemOptionRefProp = forwardedRef && typeof forwardedRef !== 'function' ? forwardedRef.menuItemOptionRef : undefined;
|
|
60
|
+
const {
|
|
61
|
+
isTruncated,
|
|
62
|
+
ref: menuItemOptionRef
|
|
63
|
+
} = useIsTruncated(menuItemOptionRefProp, [children]);
|
|
42
64
|
const className = cx(`${prefix}--list-box__menu-item`, {
|
|
43
65
|
[`${prefix}--list-box__menu-item--active`]: isActive,
|
|
44
66
|
[`${prefix}--list-box__menu-item--highlighted`]: isHighlighted
|
|
@@ -48,7 +70,7 @@ const ListBoxMenuItem = /*#__PURE__*/React__default.forwardRef(function ListBoxM
|
|
|
48
70
|
title: isTruncated ? title : undefined
|
|
49
71
|
}), /*#__PURE__*/React__default.createElement("div", {
|
|
50
72
|
className: `${prefix}--list-box__menu-item__option`,
|
|
51
|
-
ref:
|
|
73
|
+
ref: menuItemOptionRef
|
|
52
74
|
}, children));
|
|
53
75
|
});
|
|
54
76
|
ListBoxMenuItem.displayName = 'ListBoxMenuItem';
|
|
@@ -27,6 +27,7 @@ export interface MenuProps extends React.HTMLAttributes<HTMLUListElement> {
|
|
|
27
27
|
*/
|
|
28
28
|
menuAlignment?: string;
|
|
29
29
|
/**
|
|
30
|
+
* @deprecated Menus now always support both icons as well as selectable items and nesting.
|
|
30
31
|
* The mode of this menu. Defaults to full.
|
|
31
32
|
* `full` supports nesting and selectable menu items, but no icons.
|
|
32
33
|
* `basic` supports icons but no nesting or selectable menu items.
|
|
@@ -10,14 +10,14 @@ import cx from 'classnames';
|
|
|
10
10
|
import PropTypes from 'prop-types';
|
|
11
11
|
import React__default, { forwardRef, useRef, useContext, useReducer, useMemo, useState, useEffect } from 'react';
|
|
12
12
|
import { createPortal } from 'react-dom';
|
|
13
|
+
import { Escape, ArrowLeft, ArrowUp, ArrowDown } from '../../internal/keyboard/keys.js';
|
|
14
|
+
import { match } from '../../internal/keyboard/match.js';
|
|
13
15
|
import { useMergedRefs } from '../../internal/useMergedRefs.js';
|
|
14
16
|
import { usePrefix } from '../../internal/usePrefix.js';
|
|
15
|
-
import
|
|
17
|
+
import deprecate from '../../prop-types/deprecate.js';
|
|
16
18
|
import { MenuContext, menuReducer } from './MenuContext.js';
|
|
17
19
|
import { canUseDOM } from '../../internal/environment.js';
|
|
18
20
|
import { useLayoutDirection } from '../LayoutDirection/useLayoutDirection.js';
|
|
19
|
-
import { match } from '../../internal/keyboard/match.js';
|
|
20
|
-
import { Escape, ArrowLeft, ArrowUp, ArrowDown } from '../../internal/keyboard/keys.js';
|
|
21
21
|
|
|
22
22
|
const spacing = 8; // distance to keep to window edges, in px
|
|
23
23
|
|
|
@@ -28,7 +28,7 @@ const Menu = /*#__PURE__*/forwardRef(function Menu(_ref, forwardRef) {
|
|
|
28
28
|
containerRef,
|
|
29
29
|
label,
|
|
30
30
|
menuAlignment,
|
|
31
|
-
mode
|
|
31
|
+
mode,
|
|
32
32
|
onClose,
|
|
33
33
|
onOpen,
|
|
34
34
|
open,
|
|
@@ -44,14 +44,10 @@ const Menu = /*#__PURE__*/forwardRef(function Menu(_ref, forwardRef) {
|
|
|
44
44
|
const focusReturn = useRef(null);
|
|
45
45
|
const context = useContext(MenuContext);
|
|
46
46
|
const isRoot = context.state.isRoot;
|
|
47
|
-
if (context.state.mode === 'basic' && !isRoot) {
|
|
48
|
-
process.env.NODE_ENV !== "production" ? warning(false, 'Nested menus are not supported when the menu is in "basic" mode.') : void 0;
|
|
49
|
-
}
|
|
50
47
|
const menuSize = isRoot ? size : context.state.size;
|
|
51
48
|
const [childState, childDispatch] = useReducer(menuReducer, {
|
|
52
49
|
...context.state,
|
|
53
50
|
isRoot: false,
|
|
54
|
-
mode,
|
|
55
51
|
size,
|
|
56
52
|
requestCloseRoot: isRoot ? handleClose : context.state.requestCloseRoot
|
|
57
53
|
});
|
|
@@ -283,6 +279,7 @@ const Menu = /*#__PURE__*/forwardRef(function Menu(_ref, forwardRef) {
|
|
|
283
279
|
[`${prefix}--menu--open`]: open,
|
|
284
280
|
[`${prefix}--menu--shown`]: open && !legacyAutoalign || position[0] >= 0 && position[1] >= 0,
|
|
285
281
|
[`${prefix}--menu--with-icons`]: childContext.state.hasIcons,
|
|
282
|
+
[`${prefix}--menu--with-selectable-items`]: childContext.state.hasSelectableItems,
|
|
286
283
|
[`${prefix}--autoalign`]: !legacyAutoalign
|
|
287
284
|
});
|
|
288
285
|
const rendered = /*#__PURE__*/React__default.createElement(MenuContext.Provider, {
|
|
@@ -320,13 +317,14 @@ Menu.propTypes = {
|
|
|
320
317
|
*/
|
|
321
318
|
menuAlignment: PropTypes.string,
|
|
322
319
|
/**
|
|
320
|
+
* **Deprecated**: Menus now always support both icons as well as selectable items and nesting.
|
|
323
321
|
* The mode of this menu. Defaults to full.
|
|
324
322
|
* `full` supports nesting and selectable menu items, but no icons.
|
|
325
323
|
* `basic` supports icons but no nesting or selectable menu items.
|
|
326
324
|
*
|
|
327
325
|
* **This prop is not intended for use and will be set by the respective implementation (like useContextMenu, MenuButton, and ComboButton).**
|
|
328
326
|
*/
|
|
329
|
-
mode: PropTypes.oneOf(['full', 'basic']),
|
|
327
|
+
mode: deprecate(PropTypes.oneOf(['full', 'basic']), 'Menus now always support both icons as well as selectable items and nesting.'),
|
|
330
328
|
/**
|
|
331
329
|
* Provide an optional function to be called when the Menu should be closed.
|
|
332
330
|
*/
|
|
@@ -6,13 +6,13 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { KeyboardEvent, RefObject } from 'react';
|
|
8
8
|
type ActionType = {
|
|
9
|
-
type: 'enableIcons' | 'registerItem';
|
|
9
|
+
type: 'enableIcons' | 'enableSelectableItems' | 'registerItem';
|
|
10
10
|
payload: any;
|
|
11
11
|
};
|
|
12
12
|
type StateType = {
|
|
13
13
|
isRoot: boolean;
|
|
14
|
-
mode: 'full' | 'basic';
|
|
15
14
|
hasIcons: boolean;
|
|
15
|
+
hasSelectableItems: boolean;
|
|
16
16
|
size: 'xs' | 'sm' | 'md' | 'lg' | null;
|
|
17
17
|
items: any[];
|
|
18
18
|
requestCloseRoot: (e: Pick<KeyboardEvent<HTMLUListElement>, 'type'>) => void;
|
|
@@ -20,13 +20,13 @@ type StateType = {
|
|
|
20
20
|
declare function menuReducer(state: StateType, action: ActionType): {
|
|
21
21
|
hasIcons: boolean;
|
|
22
22
|
isRoot: boolean;
|
|
23
|
-
|
|
23
|
+
hasSelectableItems: boolean;
|
|
24
24
|
size: "xs" | "sm" | "md" | "lg" | null;
|
|
25
25
|
items: any[];
|
|
26
26
|
requestCloseRoot: (e: Pick<KeyboardEvent<HTMLUListElement>, "type">) => void;
|
|
27
27
|
};
|
|
28
28
|
type DispatchFuncProps = {
|
|
29
|
-
type: '
|
|
29
|
+
type: ActionType['type'];
|
|
30
30
|
payload: {
|
|
31
31
|
ref: RefObject<HTMLLIElement>;
|
|
32
32
|
disabled: boolean;
|
|
@@ -9,8 +9,8 @@ import { createContext } from 'react';
|
|
|
9
9
|
|
|
10
10
|
const menuDefaultState = {
|
|
11
11
|
isRoot: true,
|
|
12
|
-
mode: 'full',
|
|
13
12
|
hasIcons: false,
|
|
13
|
+
hasSelectableItems: false,
|
|
14
14
|
size: null,
|
|
15
15
|
items: [],
|
|
16
16
|
requestCloseRoot: () => {}
|
|
@@ -22,6 +22,11 @@ function menuReducer(state, action) {
|
|
|
22
22
|
...state,
|
|
23
23
|
hasIcons: true
|
|
24
24
|
};
|
|
25
|
+
case 'enableSelectableItems':
|
|
26
|
+
return {
|
|
27
|
+
...state,
|
|
28
|
+
hasSelectableItems: true
|
|
29
|
+
};
|
|
25
30
|
case 'registerItem':
|
|
26
31
|
return {
|
|
27
32
|
...state,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Copyright IBM Corp.
|
|
2
|
+
* Copyright IBM Corp. 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.
|
|
@@ -31,7 +31,7 @@ export interface MenuItemProps extends LiHTMLAttributes<HTMLLIElement> {
|
|
|
31
31
|
*/
|
|
32
32
|
onClick?: (event: KeyboardEvent<HTMLLIElement> | MouseEvent<HTMLLIElement>) => void;
|
|
33
33
|
/**
|
|
34
|
-
*
|
|
34
|
+
* A component used to render an icon.
|
|
35
35
|
*/
|
|
36
36
|
renderIcon?: FC;
|
|
37
37
|
/**
|
|
@@ -10,20 +10,19 @@ import cx from 'classnames';
|
|
|
10
10
|
import PropTypes from 'prop-types';
|
|
11
11
|
import React__default, { forwardRef, useState, useContext, useRef, useEffect } from 'react';
|
|
12
12
|
import { useFloating, autoUpdate, offset, useInteractions, useHover, safePolygon, FloatingFocusManager } from '@floating-ui/react';
|
|
13
|
-
import { CaretLeft, CaretRight
|
|
13
|
+
import { Checkmark, CaretLeft, CaretRight } from '@carbon/icons-react';
|
|
14
|
+
import { ArrowRight, Enter, Space } from '../../internal/keyboard/keys.js';
|
|
15
|
+
import { match } from '../../internal/keyboard/match.js';
|
|
14
16
|
import { useControllableState } from '../../internal/useControllableState.js';
|
|
15
17
|
import { useMergedRefs } from '../../internal/useMergedRefs.js';
|
|
16
18
|
import { usePrefix } from '../../internal/usePrefix.js';
|
|
17
|
-
import { warning } from '../../internal/warning.js';
|
|
18
19
|
import { Menu } from './Menu.js';
|
|
19
20
|
import { MenuContext } from './MenuContext.js';
|
|
20
21
|
import '../Text/index.js';
|
|
21
22
|
import { useLayoutDirection } from '../LayoutDirection/useLayoutDirection.js';
|
|
22
|
-
import { match } from '../../internal/keyboard/match.js';
|
|
23
23
|
import { Text } from '../Text/Text.js';
|
|
24
|
-
import { ArrowRight, Enter, Space } from '../../internal/keyboard/keys.js';
|
|
25
24
|
|
|
26
|
-
var _CaretLeft, _CaretRight;
|
|
25
|
+
var _Checkmark, _CaretLeft, _CaretRight;
|
|
27
26
|
const MenuItem = /*#__PURE__*/forwardRef(function MenuItem(_ref, forwardRef) {
|
|
28
27
|
let {
|
|
29
28
|
children,
|
|
@@ -134,15 +133,14 @@ const MenuItem = /*#__PURE__*/forwardRef(function MenuItem(_ref, forwardRef) {
|
|
|
134
133
|
setRtl(false);
|
|
135
134
|
}
|
|
136
135
|
}, [direction]);
|
|
137
|
-
const iconsAllowed = context.state.mode === 'basic' || rest.role === 'menuitemcheckbox' || rest.role === 'menuitemradio';
|
|
138
136
|
useEffect(() => {
|
|
139
|
-
if (
|
|
137
|
+
if (IconElement && !context.state.hasIcons) {
|
|
140
138
|
// @ts-ignore - TODO: Should we be passing payload?
|
|
141
139
|
context.dispatch({
|
|
142
140
|
type: 'enableIcons'
|
|
143
141
|
});
|
|
144
142
|
}
|
|
145
|
-
}, [
|
|
143
|
+
}, [IconElement, context.state.hasIcons, context]);
|
|
146
144
|
useEffect(() => {
|
|
147
145
|
Object.keys(floatingStyles).forEach(style => {
|
|
148
146
|
if (refs.floating.current && style !== 'position') {
|
|
@@ -166,8 +164,10 @@ const MenuItem = /*#__PURE__*/forwardRef(function MenuItem(_ref, forwardRef) {
|
|
|
166
164
|
onClick: handleClick,
|
|
167
165
|
onKeyDown: handleKeyDown
|
|
168
166
|
}, getReferenceProps()), /*#__PURE__*/React__default.createElement("div", {
|
|
167
|
+
className: `${prefix}--menu-item__selection-icon`
|
|
168
|
+
}, rest['aria-checked'] && (_Checkmark || (_Checkmark = /*#__PURE__*/React__default.createElement(Checkmark, null)))), /*#__PURE__*/React__default.createElement("div", {
|
|
169
169
|
className: `${prefix}--menu-item__icon`
|
|
170
|
-
},
|
|
170
|
+
}, IconElement && /*#__PURE__*/React__default.createElement(IconElement, null)), /*#__PURE__*/React__default.createElement(Text, {
|
|
171
171
|
as: "div",
|
|
172
172
|
className: `${prefix}--menu-item__label`,
|
|
173
173
|
title: label
|
|
@@ -212,7 +212,7 @@ MenuItem.propTypes = {
|
|
|
212
212
|
// @ts-ignore-next-line -- avoid spurious (?) TS2322 error
|
|
213
213
|
onClick: PropTypes.func,
|
|
214
214
|
/**
|
|
215
|
-
*
|
|
215
|
+
* A component used to render an icon.
|
|
216
216
|
*/
|
|
217
217
|
// @ts-ignore-next-line -- avoid spurious (?) TS2322 error
|
|
218
218
|
renderIcon: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
|
|
@@ -233,9 +233,6 @@ const MenuItemSelectable = /*#__PURE__*/forwardRef(function MenuItemSelectable(_
|
|
|
233
233
|
} = _ref2;
|
|
234
234
|
const prefix = usePrefix();
|
|
235
235
|
const context = useContext(MenuContext);
|
|
236
|
-
if (context.state.mode === 'basic') {
|
|
237
|
-
process.env.NODE_ENV !== "production" ? warning(false, 'MenuItemSelectable is not supported when the menu is in "basic" mode.') : void 0;
|
|
238
|
-
}
|
|
239
236
|
const [checked, setChecked] = useControllableState({
|
|
240
237
|
value: selected,
|
|
241
238
|
onChange,
|
|
@@ -245,13 +242,13 @@ const MenuItemSelectable = /*#__PURE__*/forwardRef(function MenuItemSelectable(_
|
|
|
245
242
|
setChecked(!checked);
|
|
246
243
|
}
|
|
247
244
|
useEffect(() => {
|
|
248
|
-
if (!context.state.
|
|
245
|
+
if (!context.state.hasSelectableItems) {
|
|
249
246
|
// @ts-ignore - TODO: Should we be passing payload?
|
|
250
247
|
context.dispatch({
|
|
251
|
-
type: '
|
|
248
|
+
type: 'enableSelectableItems'
|
|
252
249
|
});
|
|
253
250
|
}
|
|
254
|
-
}, [context.state.
|
|
251
|
+
}, [context.state.hasSelectableItems, context]);
|
|
255
252
|
const classNames = cx(className, `${prefix}--menu-item-selectable--selected`);
|
|
256
253
|
return /*#__PURE__*/React__default.createElement(MenuItem, _extends({}, rest, {
|
|
257
254
|
ref: forwardRef,
|
|
@@ -259,7 +256,6 @@ const MenuItemSelectable = /*#__PURE__*/forwardRef(function MenuItemSelectable(_
|
|
|
259
256
|
className: classNames,
|
|
260
257
|
role: "menuitemcheckbox",
|
|
261
258
|
"aria-checked": checked,
|
|
262
|
-
renderIcon: checked ? Checkmark : undefined,
|
|
263
259
|
onClick: handleClick
|
|
264
260
|
}));
|
|
265
261
|
});
|
|
@@ -334,9 +330,6 @@ const MenuItemRadioGroup = /*#__PURE__*/forwardRef(function MenuItemRadioGroup(_
|
|
|
334
330
|
} = _ref4;
|
|
335
331
|
const prefix = usePrefix();
|
|
336
332
|
const context = useContext(MenuContext);
|
|
337
|
-
if (context.state.mode === 'basic') {
|
|
338
|
-
process.env.NODE_ENV !== "production" ? warning(false, 'MenuItemRadioGroup is not supported when the menu is in "basic" mode.') : void 0;
|
|
339
|
-
}
|
|
340
333
|
const [selection, setSelection] = useControllableState({
|
|
341
334
|
value: selectedItem,
|
|
342
335
|
onChange,
|
|
@@ -346,13 +339,13 @@ const MenuItemRadioGroup = /*#__PURE__*/forwardRef(function MenuItemRadioGroup(_
|
|
|
346
339
|
setSelection(item);
|
|
347
340
|
}
|
|
348
341
|
useEffect(() => {
|
|
349
|
-
if (!context.state.
|
|
342
|
+
if (!context.state.hasSelectableItems) {
|
|
350
343
|
// @ts-ignore - TODO: Should we be passing payload?
|
|
351
344
|
context.dispatch({
|
|
352
|
-
type: '
|
|
345
|
+
type: 'enableSelectableItems'
|
|
353
346
|
});
|
|
354
347
|
}
|
|
355
|
-
}, [context.state.
|
|
348
|
+
}, [context.state.hasSelectableItems, context]);
|
|
356
349
|
const classNames = cx(className, `${prefix}--menu-item-radio-group`);
|
|
357
350
|
return /*#__PURE__*/React__default.createElement("li", {
|
|
358
351
|
className: classNames,
|
|
@@ -366,7 +359,6 @@ const MenuItemRadioGroup = /*#__PURE__*/forwardRef(function MenuItemRadioGroup(_
|
|
|
366
359
|
label: itemToString(item),
|
|
367
360
|
role: "menuitemradio",
|
|
368
361
|
"aria-checked": item === selection,
|
|
369
|
-
renderIcon: item === selection ? Checkmark : undefined,
|
|
370
362
|
onClick: e => {
|
|
371
363
|
handleClick(item);
|
|
372
364
|
}
|
|
@@ -73,6 +73,15 @@ const MenuButton = /*#__PURE__*/forwardRef(function MenuButton(_ref, forwardRef)
|
|
|
73
73
|
// “break” the floating element out of a clipping ancestor.
|
|
74
74
|
// https://floating-ui.com/docs/misc#clipping
|
|
75
75
|
strategy: 'fixed',
|
|
76
|
+
// Submenus are using a fixed position to break out of the parent menu's
|
|
77
|
+
// box avoiding clipping while allowing for vertical scroll. When an
|
|
78
|
+
// element is using transform it establishes a new containing block
|
|
79
|
+
// block for all of its descendants. Therefore, its padding box will be
|
|
80
|
+
// used for fixed-positioned descendants. This would cause the submenu
|
|
81
|
+
// to be clipped by its parent menu.
|
|
82
|
+
// Reference: https://www.w3.org/TR/2019/CR-css-transforms-1-20190214/#current-transformation-matrix-computation
|
|
83
|
+
// Reference: https://github.com/carbon-design-system/carbon/pull/18153#issuecomment-2498548835
|
|
84
|
+
transform: false,
|
|
76
85
|
// Middleware order matters, arrow should be last
|
|
77
86
|
middleware: middlewares,
|
|
78
87
|
whileElementsMounted: autoUpdate
|
|
@@ -87,7 +96,11 @@ const MenuButton = /*#__PURE__*/forwardRef(function MenuButton(_ref, forwardRef)
|
|
|
87
96
|
useLayoutEffect(() => {
|
|
88
97
|
Object.keys(floatingStyles).forEach(style => {
|
|
89
98
|
if (refs.floating.current) {
|
|
90
|
-
|
|
99
|
+
let value = floatingStyles[style];
|
|
100
|
+
if (['top', 'right', 'bottom', 'left'].includes(style) && Number(value)) {
|
|
101
|
+
value += 'px';
|
|
102
|
+
}
|
|
103
|
+
refs.floating.current.style[style] = value;
|
|
91
104
|
}
|
|
92
105
|
});
|
|
93
106
|
}, [floatingStyles, refs.floating, middlewareData, placement, open]);
|
|
@@ -126,7 +139,6 @@ const MenuButton = /*#__PURE__*/forwardRef(function MenuButton(_ref, forwardRef)
|
|
|
126
139
|
id: id,
|
|
127
140
|
legacyAutoalign: false,
|
|
128
141
|
label: label,
|
|
129
|
-
mode: "basic",
|
|
130
142
|
size: size$1,
|
|
131
143
|
open: open,
|
|
132
144
|
onClose: handleClose,
|