@carbon/react 1.51.0 → 1.52.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.
- package/.playwright/INTERNAL_AVT_REPORT_DO_NOT_USE.json +776 -729
- package/es/components/ChatButton/ChatButton.js +9 -1
- package/es/components/ComposedModal/ComposedModal.js +5 -4
- package/es/components/DataTable/TableActionList.d.ts +8 -0
- package/es/components/DataTable/TableActionList.js +1 -2
- package/es/components/DataTable/TableHead.d.ts +2 -2
- package/es/components/DataTable/TableToolbarContent.d.ts +1 -12
- package/es/components/Dropdown/Dropdown.d.ts +1 -1
- package/es/components/Link/Link.d.ts +5 -10
- package/es/components/Link/Link.js +1 -2
- package/es/components/Menu/Menu.d.ts +6 -6
- package/es/components/Menu/Menu.js +7 -3
- package/es/components/Menu/MenuContext.d.ts +14 -6
- package/es/components/Menu/MenuContext.js +3 -3
- package/es/components/Menu/MenuItem.d.ts +22 -31
- package/es/components/Menu/MenuItem.js +25 -13
- package/es/components/MenuButton/index.d.ts +43 -0
- package/es/components/MenuButton/index.js +15 -10
- package/es/components/Modal/Modal.js +2 -1
- package/es/components/Notification/Notification.d.ts +17 -1
- package/es/components/Notification/Notification.js +24 -9
- package/es/components/Toggletip/index.d.ts +1 -1
- package/es/components/Toggletip/index.js +4 -3
- package/es/components/TreeView/TreeNode.js +46 -24
- package/es/components/TreeView/TreeView.js +40 -13
- package/es/components/UIShell/Header.d.ts +24 -0
- package/es/components/UIShell/Header.js +1 -2
- package/es/components/UIShell/HeaderGlobalAction.d.ts +50 -0
- package/es/components/UIShell/HeaderGlobalAction.js +1 -2
- package/es/components/UIShell/HeaderGlobalBar.d.ts +11 -0
- package/es/components/UIShell/HeaderGlobalBar.js +2 -1
- package/es/components/UIShell/SideNavLink.d.ts +57 -0
- package/es/components/UIShell/SideNavLink.js +4 -4
- package/es/internal/useAttachedMenu.d.ts +45 -0
- package/es/internal/useAttachedMenu.js +1 -7
- package/es/tools/wrapComponent.d.ts +20 -0
- package/es/tools/wrapComponent.js +3 -4
- package/lib/components/ChatButton/ChatButton.js +9 -1
- package/lib/components/ComposedModal/ComposedModal.js +5 -4
- package/lib/components/DataTable/TableActionList.d.ts +8 -0
- package/lib/components/DataTable/TableActionList.js +1 -2
- package/lib/components/DataTable/TableHead.d.ts +2 -2
- package/lib/components/DataTable/TableToolbarContent.d.ts +1 -12
- package/lib/components/Dropdown/Dropdown.d.ts +1 -1
- package/lib/components/Link/Link.d.ts +5 -10
- package/lib/components/Link/Link.js +1 -2
- package/lib/components/Menu/Menu.d.ts +6 -6
- package/lib/components/Menu/Menu.js +6 -2
- package/lib/components/Menu/MenuContext.d.ts +14 -6
- package/lib/components/Menu/MenuContext.js +2 -6
- package/lib/components/Menu/MenuItem.d.ts +22 -31
- package/lib/components/Menu/MenuItem.js +24 -12
- package/lib/components/MenuButton/index.d.ts +43 -0
- package/lib/components/MenuButton/index.js +14 -9
- package/lib/components/Modal/Modal.js +2 -1
- package/lib/components/Notification/Notification.d.ts +17 -1
- package/lib/components/Notification/Notification.js +24 -9
- package/lib/components/Toggletip/index.d.ts +1 -1
- package/lib/components/Toggletip/index.js +4 -3
- package/lib/components/TreeView/TreeNode.js +46 -24
- package/lib/components/TreeView/TreeView.js +40 -13
- package/lib/components/UIShell/Header.d.ts +24 -0
- package/lib/components/UIShell/Header.js +1 -2
- package/lib/components/UIShell/HeaderGlobalAction.d.ts +50 -0
- package/lib/components/UIShell/HeaderGlobalAction.js +1 -2
- package/lib/components/UIShell/HeaderGlobalBar.d.ts +11 -0
- package/lib/components/UIShell/HeaderGlobalBar.js +2 -1
- package/lib/components/UIShell/SideNavLink.d.ts +57 -0
- package/lib/components/UIShell/SideNavLink.js +3 -3
- package/lib/internal/useAttachedMenu.d.ts +45 -0
- package/lib/internal/useAttachedMenu.js +1 -7
- package/lib/tools/wrapComponent.d.ts +20 -0
- package/lib/tools/wrapComponent.js +5 -6
- package/package.json +8 -8
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright IBM Corp. 2023
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the Apache-2.0 license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
import React, { ComponentProps, ReactNode } from 'react';
|
|
8
|
+
export interface MenuButtonProps extends ComponentProps<'div'> {
|
|
9
|
+
/**
|
|
10
|
+
* A collection of MenuItems to be rendered as actions for this MenuButton.
|
|
11
|
+
*/
|
|
12
|
+
children?: ReactNode;
|
|
13
|
+
/**
|
|
14
|
+
* Additional CSS class names.
|
|
15
|
+
*/
|
|
16
|
+
className?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Specify whether the MenuButton should be disabled, or not.
|
|
19
|
+
*/
|
|
20
|
+
disabled?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Specify the type of button to be used as the base for the trigger button.
|
|
23
|
+
*/
|
|
24
|
+
kind?: 'primary' | 'tertiary' | 'ghost';
|
|
25
|
+
/**
|
|
26
|
+
* Provide the label to be rendered on the trigger button.
|
|
27
|
+
*/
|
|
28
|
+
label: string;
|
|
29
|
+
/**
|
|
30
|
+
* Experimental property. Specify how the menu should align with the button element
|
|
31
|
+
*/
|
|
32
|
+
menuAlignment: 'top' | 'top-start' | 'top-end' | 'bottom' | 'bottom-start' | 'bottom-end';
|
|
33
|
+
/**
|
|
34
|
+
* Specify the size of the button and menu.
|
|
35
|
+
*/
|
|
36
|
+
size?: 'sm' | 'md' | 'lg';
|
|
37
|
+
/**
|
|
38
|
+
* Specify the tabIndex of the button.
|
|
39
|
+
*/
|
|
40
|
+
tabIndex?: number;
|
|
41
|
+
}
|
|
42
|
+
declare const MenuButton: React.ForwardRefExoticComponent<Omit<MenuButtonProps, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
43
|
+
export { MenuButton };
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
|
|
9
|
-
import React__default, { useRef, useState } from 'react';
|
|
9
|
+
import React__default, { forwardRef, useRef, useState } from 'react';
|
|
10
10
|
import PropTypes from 'prop-types';
|
|
11
11
|
import cx from 'classnames';
|
|
12
12
|
import { ChevronDown } from '@carbon/icons-react';
|
|
@@ -22,7 +22,7 @@ import { usePrefix } from '../../internal/usePrefix.js';
|
|
|
22
22
|
const spacing = 0; // top and bottom spacing between the button and the menu. in px
|
|
23
23
|
const validButtonKinds = ['primary', 'tertiary', 'ghost'];
|
|
24
24
|
const defaultButtonKind = 'primary';
|
|
25
|
-
const MenuButton = /*#__PURE__*/
|
|
25
|
+
const MenuButton = /*#__PURE__*/forwardRef(function MenuButton(_ref, forwardRef) {
|
|
26
26
|
let {
|
|
27
27
|
children,
|
|
28
28
|
className,
|
|
@@ -58,10 +58,12 @@ const MenuButton = /*#__PURE__*/React__default.forwardRef(function MenuButton(_r
|
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
60
|
function handleOpen() {
|
|
61
|
-
menuRef.current
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
61
|
+
if (menuRef.current) {
|
|
62
|
+
menuRef.current.style.inlineSize = `${width}px`;
|
|
63
|
+
menuRef.current.style.minInlineSize = `${width}px`;
|
|
64
|
+
if (menuAlignment !== 'bottom' && menuAlignment !== 'top') {
|
|
65
|
+
menuRef.current.style.inlineSize = `fit-content`;
|
|
66
|
+
}
|
|
65
67
|
}
|
|
66
68
|
}
|
|
67
69
|
const containerClasses = cx(`${prefix}--menu-button__container`, className);
|
|
@@ -69,23 +71,22 @@ const MenuButton = /*#__PURE__*/React__default.forwardRef(function MenuButton(_r
|
|
|
69
71
|
[`${prefix}--menu-button__trigger--open`]: open
|
|
70
72
|
});
|
|
71
73
|
const menuClasses = cx(`${prefix}--menu-button__${menuAlignment}`);
|
|
72
|
-
const buttonKind = validButtonKinds.includes(kind) ? kind : defaultButtonKind;
|
|
73
74
|
return /*#__PURE__*/React__default.createElement("div", _extends({}, rest, {
|
|
74
75
|
ref: ref,
|
|
75
|
-
"aria-owns": open ? id :
|
|
76
|
+
"aria-owns": open ? id : undefined,
|
|
76
77
|
className: containerClasses
|
|
77
78
|
}), /*#__PURE__*/React__default.createElement(Button, {
|
|
78
79
|
className: triggerClasses,
|
|
79
80
|
size: size,
|
|
80
81
|
tabIndex: tabIndex,
|
|
81
|
-
kind:
|
|
82
|
+
kind: kind,
|
|
82
83
|
renderIcon: ChevronDown,
|
|
83
84
|
disabled: disabled,
|
|
84
85
|
"aria-haspopup": true,
|
|
85
86
|
"aria-expanded": open,
|
|
86
87
|
onClick: handleClick,
|
|
87
88
|
onMouseDown: handleMousedown,
|
|
88
|
-
"aria-controls": open ? id :
|
|
89
|
+
"aria-controls": open ? id : undefined
|
|
89
90
|
}, label), /*#__PURE__*/React__default.createElement(Menu, {
|
|
90
91
|
containerRef: triggerRef,
|
|
91
92
|
menuAlignment: menuAlignment,
|
|
@@ -118,6 +119,7 @@ MenuButton.propTypes = {
|
|
|
118
119
|
/**
|
|
119
120
|
* Specify the type of button to be used as the base for the trigger button.
|
|
120
121
|
*/
|
|
122
|
+
// @ts-ignore-next-line -- avoid spurious (?) TS2322 error
|
|
121
123
|
kind: PropTypes.oneOf(validButtonKinds),
|
|
122
124
|
/**
|
|
123
125
|
* Provide the label to be renderd on the trigger button.
|
|
@@ -126,14 +128,17 @@ MenuButton.propTypes = {
|
|
|
126
128
|
/**
|
|
127
129
|
* Experimental property. Specify how the menu should align with the button element
|
|
128
130
|
*/
|
|
131
|
+
// @ts-ignore-next-line -- avoid spurious (?) TS2322 error
|
|
129
132
|
menuAlignment: PropTypes.oneOf(['top', 'top-start', 'top-end', 'bottom', 'bottom-start', 'bottom-end']),
|
|
130
133
|
/**
|
|
131
134
|
* Specify the size of the button and menu.
|
|
132
135
|
*/
|
|
136
|
+
// @ts-ignore-next-line -- avoid spurious (?) TS2322 error
|
|
133
137
|
size: PropTypes.oneOf(['sm', 'md', 'lg']),
|
|
134
138
|
/**
|
|
135
139
|
* Specify the tabIndex of the button.
|
|
136
140
|
*/
|
|
141
|
+
// @ts-ignore-next-line -- avoid spurious (?) TS2322 error
|
|
137
142
|
tabIndex: PropTypes.number
|
|
138
143
|
};
|
|
139
144
|
|
|
@@ -86,6 +86,7 @@ const Modal = /*#__PURE__*/React__default.forwardRef(function Modal(_ref, ref) {
|
|
|
86
86
|
return !onSecondarySubmit && element === secondaryButton.current || element.classList.contains(modalCloseButtonClass);
|
|
87
87
|
}
|
|
88
88
|
function handleKeyDown(evt) {
|
|
89
|
+
evt.stopPropagation();
|
|
89
90
|
if (open) {
|
|
90
91
|
if (match(evt, Escape)) {
|
|
91
92
|
onRequestClose(evt);
|
|
@@ -97,6 +98,7 @@ const Modal = /*#__PURE__*/React__default.forwardRef(function Modal(_ref, ref) {
|
|
|
97
98
|
}
|
|
98
99
|
function handleMousedown(evt) {
|
|
99
100
|
const target = evt.target;
|
|
101
|
+
evt.stopPropagation();
|
|
100
102
|
if (innerModal.current && !innerModal.current.contains(target) && !elementOrParentIsFloatingMenu(target, selectorsFloatingMenus) && !preventCloseOnClickOutside) {
|
|
101
103
|
onRequestClose(evt);
|
|
102
104
|
}
|
|
@@ -228,7 +230,6 @@ const Modal = /*#__PURE__*/React__default.forwardRef(function Modal(_ref, ref) {
|
|
|
228
230
|
className: modalCloseButtonClass,
|
|
229
231
|
label: closeButtonLabel,
|
|
230
232
|
onClick: onRequestClose,
|
|
231
|
-
title: closeButtonLabel,
|
|
232
233
|
"aria-label": closeButtonLabel,
|
|
233
234
|
align: "left",
|
|
234
235
|
ref: button
|
|
@@ -518,6 +518,10 @@ export declare namespace ActionableNotification {
|
|
|
518
518
|
* ==================
|
|
519
519
|
*/
|
|
520
520
|
export interface StaticNotificationProps extends HTMLAttributes<HTMLDivElement> {
|
|
521
|
+
/**
|
|
522
|
+
* Pass in the action button label that will be rendered within the ActionableNotification.
|
|
523
|
+
*/
|
|
524
|
+
actionButtonLabel?: string;
|
|
521
525
|
/**
|
|
522
526
|
* Specify the content
|
|
523
527
|
*/
|
|
@@ -534,6 +538,10 @@ export interface StaticNotificationProps extends HTMLAttributes<HTMLDivElement>
|
|
|
534
538
|
* Specify whether you are using the low contrast variant of the StaticNotification.
|
|
535
539
|
*/
|
|
536
540
|
lowContrast?: boolean;
|
|
541
|
+
/**
|
|
542
|
+
* Provide a function that is called when the action is clicked
|
|
543
|
+
*/
|
|
544
|
+
onActionButtonClick?(): void;
|
|
537
545
|
/**
|
|
538
546
|
* Provide a description for "status" icon that can be read by screen readers
|
|
539
547
|
*/
|
|
@@ -551,9 +559,13 @@ export interface StaticNotificationProps extends HTMLAttributes<HTMLDivElement>
|
|
|
551
559
|
*/
|
|
552
560
|
titleId?: string;
|
|
553
561
|
}
|
|
554
|
-
export declare function StaticNotification({ children, title, titleId, subtitle, statusIconDescription, className, kind, lowContrast, ...rest }: StaticNotificationProps): import("react/jsx-runtime").JSX.Element;
|
|
562
|
+
export declare function StaticNotification({ actionButtonLabel, children, onActionButtonClick, title, titleId, subtitle, statusIconDescription, className, kind, lowContrast, ...rest }: StaticNotificationProps): import("react/jsx-runtime").JSX.Element;
|
|
555
563
|
export declare namespace StaticNotification {
|
|
556
564
|
var propTypes: {
|
|
565
|
+
/**
|
|
566
|
+
* Pass in the action button label that will be rendered within the ActionableNotification.
|
|
567
|
+
*/
|
|
568
|
+
actionButtonLabel: PropTypes.Requireable<string>;
|
|
557
569
|
/**
|
|
558
570
|
* Specify the content
|
|
559
571
|
*/
|
|
@@ -570,6 +582,10 @@ export declare namespace StaticNotification {
|
|
|
570
582
|
* Specify whether you are using the low contrast variant of the StaticNotification.
|
|
571
583
|
*/
|
|
572
584
|
lowContrast: PropTypes.Requireable<boolean>;
|
|
585
|
+
/**
|
|
586
|
+
* Provide a function that is called when the action is clicked
|
|
587
|
+
*/
|
|
588
|
+
onActionButtonClick: PropTypes.Requireable<(...args: any[]) => any>;
|
|
573
589
|
/**
|
|
574
590
|
* Provide a description for "status" icon that can be read by screen readers
|
|
575
591
|
*/
|
|
@@ -685,7 +685,9 @@ ActionableNotification.propTypes = {
|
|
|
685
685
|
|
|
686
686
|
function StaticNotification(_ref8) {
|
|
687
687
|
let {
|
|
688
|
+
actionButtonLabel,
|
|
688
689
|
children,
|
|
690
|
+
onActionButtonClick,
|
|
689
691
|
title,
|
|
690
692
|
titleId,
|
|
691
693
|
subtitle,
|
|
@@ -697,10 +699,10 @@ function StaticNotification(_ref8) {
|
|
|
697
699
|
} = _ref8;
|
|
698
700
|
const prefix = usePrefix();
|
|
699
701
|
const containerClassName = cx(className, {
|
|
700
|
-
[`${prefix}--
|
|
701
|
-
[`${prefix}--
|
|
702
|
-
[`${prefix}--
|
|
703
|
-
[`${prefix}--
|
|
702
|
+
[`${prefix}--actionable-notification`]: true,
|
|
703
|
+
[`${prefix}--actionable-notification--low-contrast`]: lowContrast,
|
|
704
|
+
[`${prefix}--actionable-notification--${kind}`]: kind,
|
|
705
|
+
[`${prefix}--actionable-notification--hide-close-button`]: true
|
|
704
706
|
});
|
|
705
707
|
const ref = useRef(null);
|
|
706
708
|
useInteractiveChildrenNeedDescription(ref, `interactive child node(s) should have an \`aria-describedby\` property with a value matching the value of \`titleId\``);
|
|
@@ -709,23 +711,32 @@ function StaticNotification(_ref8) {
|
|
|
709
711
|
}, rest, {
|
|
710
712
|
className: containerClassName
|
|
711
713
|
}), /*#__PURE__*/React__default.createElement("div", {
|
|
712
|
-
className: `${prefix}--
|
|
714
|
+
className: `${prefix}--actionable-notification__details`
|
|
713
715
|
}, /*#__PURE__*/React__default.createElement(NotificationIcon, {
|
|
714
716
|
notificationType: "inline",
|
|
715
717
|
kind: kind,
|
|
716
718
|
iconDescription: statusIconDescription || `${kind} icon`
|
|
717
719
|
}), /*#__PURE__*/React__default.createElement("div", {
|
|
718
|
-
className: `${prefix}--
|
|
720
|
+
className: `${prefix}--actionable-notification__text-wrapper`
|
|
719
721
|
}, title && /*#__PURE__*/React__default.createElement(Text, {
|
|
720
722
|
as: "div",
|
|
721
723
|
id: titleId,
|
|
722
|
-
className: `${prefix}--
|
|
724
|
+
className: `${prefix}--actionable-notification__title`
|
|
723
725
|
}, title), subtitle && /*#__PURE__*/React__default.createElement(Text, {
|
|
724
726
|
as: "div",
|
|
725
|
-
className: `${prefix}--
|
|
726
|
-
}, subtitle), children))
|
|
727
|
+
className: `${prefix}--actionable-notification__subtitle`
|
|
728
|
+
}, subtitle), children)), /*#__PURE__*/React__default.createElement("div", {
|
|
729
|
+
className: `${prefix}--actionable-notification__button-wrapper`
|
|
730
|
+
}, actionButtonLabel && /*#__PURE__*/React__default.createElement(NotificationActionButton, {
|
|
731
|
+
onClick: onActionButtonClick,
|
|
732
|
+
inline: true
|
|
733
|
+
}, actionButtonLabel)));
|
|
727
734
|
}
|
|
728
735
|
StaticNotification.propTypes = {
|
|
736
|
+
/**
|
|
737
|
+
* Pass in the action button label that will be rendered within the ActionableNotification.
|
|
738
|
+
*/
|
|
739
|
+
actionButtonLabel: PropTypes.string,
|
|
729
740
|
/**
|
|
730
741
|
* Specify the content
|
|
731
742
|
*/
|
|
@@ -742,6 +753,10 @@ StaticNotification.propTypes = {
|
|
|
742
753
|
* Specify whether you are using the low contrast variant of the StaticNotification.
|
|
743
754
|
*/
|
|
744
755
|
lowContrast: PropTypes.bool,
|
|
756
|
+
/**
|
|
757
|
+
* Provide a function that is called when the action is clicked
|
|
758
|
+
*/
|
|
759
|
+
onActionButtonClick: PropTypes.func,
|
|
745
760
|
/**
|
|
746
761
|
* Provide a description for "status" icon that can be read by screen readers
|
|
747
762
|
*/
|
|
@@ -47,7 +47,7 @@ interface ToggletipProps<E extends ElementType> {
|
|
|
47
47
|
* is responsible for coordinating between interactions with the button and the
|
|
48
48
|
* visibility of the content
|
|
49
49
|
*/
|
|
50
|
-
export declare function Toggletip<E extends ElementType = 'span'>({ align, as, autoAlign, className: customClassName, children, defaultOpen, }: ToggletipProps<E>): import("react/jsx-runtime").JSX.Element;
|
|
50
|
+
export declare function Toggletip<E extends ElementType = 'span'>({ align, as, autoAlign, className: customClassName, children, defaultOpen, ...rest }: ToggletipProps<E>): import("react/jsx-runtime").JSX.Element;
|
|
51
51
|
export declare namespace Toggletip {
|
|
52
52
|
var propTypes: {
|
|
53
53
|
/**
|
|
@@ -66,7 +66,8 @@ function Toggletip(_ref2) {
|
|
|
66
66
|
autoAlign,
|
|
67
67
|
className: customClassName,
|
|
68
68
|
children,
|
|
69
|
-
defaultOpen = false
|
|
69
|
+
defaultOpen = false,
|
|
70
|
+
...rest
|
|
70
71
|
} = _ref2;
|
|
71
72
|
const ref = useRef(null);
|
|
72
73
|
const [open, setOpen] = useState(defaultOpen);
|
|
@@ -128,7 +129,7 @@ function Toggletip(_ref2) {
|
|
|
128
129
|
});
|
|
129
130
|
return /*#__PURE__*/React__default.createElement(ToggletipContext.Provider, {
|
|
130
131
|
value: value
|
|
131
|
-
}, /*#__PURE__*/React__default.createElement(Popover, {
|
|
132
|
+
}, /*#__PURE__*/React__default.createElement(Popover, _extends({
|
|
132
133
|
align: align,
|
|
133
134
|
as: as,
|
|
134
135
|
caret: true,
|
|
@@ -140,7 +141,7 @@ function Toggletip(_ref2) {
|
|
|
140
141
|
onBlur: handleBlur,
|
|
141
142
|
ref: ref,
|
|
142
143
|
autoAlign: autoAlign
|
|
143
|
-
}, children));
|
|
144
|
+
}, rest), children));
|
|
144
145
|
}
|
|
145
146
|
Toggletip.propTypes = {
|
|
146
147
|
/**
|
|
@@ -12,6 +12,8 @@ import { CaretDown } from '@carbon/icons-react';
|
|
|
12
12
|
import cx from 'classnames';
|
|
13
13
|
import uniqueId from '../../tools/uniqueId.js';
|
|
14
14
|
import { usePrefix } from '../../internal/usePrefix.js';
|
|
15
|
+
import { useControllableState } from '../../internal/useControllableState.js';
|
|
16
|
+
import { useFeatureFlag } from '../FeatureFlags/index.js';
|
|
15
17
|
import { matches, match } from '../../internal/keyboard/match.js';
|
|
16
18
|
import { ArrowLeft, ArrowRight, Enter, Space } from '../../internal/keyboard/keys.js';
|
|
17
19
|
|
|
@@ -24,6 +26,7 @@ const TreeNode = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
|
|
|
24
26
|
disabled,
|
|
25
27
|
id: nodeId,
|
|
26
28
|
isExpanded,
|
|
29
|
+
defaultIsExpanded,
|
|
27
30
|
label,
|
|
28
31
|
onNodeFocusEvent,
|
|
29
32
|
onSelect: onNodeSelect,
|
|
@@ -34,10 +37,17 @@ const TreeNode = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
|
|
|
34
37
|
value,
|
|
35
38
|
...rest
|
|
36
39
|
} = _ref;
|
|
40
|
+
const enableTreeviewControllable = useFeatureFlag('enable-treeview-controllable');
|
|
37
41
|
const {
|
|
38
42
|
current: id
|
|
39
43
|
} = useRef(nodeId || uniqueId());
|
|
40
|
-
const
|
|
44
|
+
const controllableExpandedState = useControllableState({
|
|
45
|
+
value: isExpanded,
|
|
46
|
+
onChange: onToggle,
|
|
47
|
+
defaultValue: defaultIsExpanded
|
|
48
|
+
});
|
|
49
|
+
const uncontrollableExpandedState = useState(isExpanded);
|
|
50
|
+
const [expanded, setExpanded] = enableTreeviewControllable ? controllableExpandedState : uncontrollableExpandedState;
|
|
41
51
|
const currentNode = useRef(null);
|
|
42
52
|
const currentNodeLabel = useRef(null);
|
|
43
53
|
const prefix = usePrefix();
|
|
@@ -73,12 +83,14 @@ const TreeNode = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
|
|
|
73
83
|
|
|
74
84
|
// Prevent the node from being selected
|
|
75
85
|
event.stopPropagation();
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
86
|
+
if (!enableTreeviewControllable) {
|
|
87
|
+
onToggle?.(event, {
|
|
88
|
+
id,
|
|
89
|
+
isExpanded: !expanded,
|
|
90
|
+
label,
|
|
91
|
+
value
|
|
92
|
+
});
|
|
93
|
+
}
|
|
82
94
|
setExpanded(!expanded);
|
|
83
95
|
}
|
|
84
96
|
function handleClick(event) {
|
|
@@ -115,12 +127,14 @@ const TreeNode = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
|
|
|
115
127
|
return findParentTreeNode(node.parentNode);
|
|
116
128
|
};
|
|
117
129
|
if (children && expanded) {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
130
|
+
if (!enableTreeviewControllable) {
|
|
131
|
+
onToggle?.(event, {
|
|
132
|
+
id,
|
|
133
|
+
isExpanded: false,
|
|
134
|
+
label,
|
|
135
|
+
value
|
|
136
|
+
});
|
|
137
|
+
}
|
|
124
138
|
setExpanded(false);
|
|
125
139
|
} else {
|
|
126
140
|
/**
|
|
@@ -138,12 +152,14 @@ const TreeNode = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
|
|
|
138
152
|
*/
|
|
139
153
|
currentNode.current.lastChild.firstChild.focus();
|
|
140
154
|
} else {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
155
|
+
if (!enableTreeviewControllable) {
|
|
156
|
+
onToggle?.(event, {
|
|
157
|
+
id,
|
|
158
|
+
isExpanded: true,
|
|
159
|
+
label,
|
|
160
|
+
value
|
|
161
|
+
});
|
|
162
|
+
}
|
|
147
163
|
setExpanded(true);
|
|
148
164
|
}
|
|
149
165
|
}
|
|
@@ -194,10 +210,11 @@ const TreeNode = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
|
|
|
194
210
|
currentNodeLabel.current.style.marginInlineStart = `-${calcOffset()}rem`;
|
|
195
211
|
currentNodeLabel.current.style.paddingInlineStart = `${calcOffset()}rem`;
|
|
196
212
|
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
213
|
+
if (!enableTreeviewControllable) {
|
|
214
|
+
// sync props and state
|
|
215
|
+
setExpanded(isExpanded);
|
|
216
|
+
}
|
|
217
|
+
}, [children, depth, Icon, isExpanded, enableTreeviewControllable, setExpanded]);
|
|
201
218
|
const treeNodeProps = {
|
|
202
219
|
...rest,
|
|
203
220
|
['aria-current']: isActive || null,
|
|
@@ -260,7 +277,12 @@ TreeNode.propTypes = {
|
|
|
260
277
|
*/
|
|
261
278
|
className: PropTypes.string,
|
|
262
279
|
/**
|
|
263
|
-
*
|
|
280
|
+
* **[Experimental]** The default expansion state of the node.
|
|
281
|
+
* *This is only supported with the `enable-treeview-controllable` feature flag!*
|
|
282
|
+
*/
|
|
283
|
+
defaultIsExpanded: PropTypes.bool,
|
|
284
|
+
/**
|
|
285
|
+
* **Note:** this is controlled by the parent TreeView component, do not set manually.
|
|
264
286
|
* TreeNode depth to determine spacing
|
|
265
287
|
*/
|
|
266
288
|
depth: PropTypes.number,
|
|
@@ -11,6 +11,8 @@ import PropTypes from 'prop-types';
|
|
|
11
11
|
import cx from 'classnames';
|
|
12
12
|
import uniqueId from '../../tools/uniqueId.js';
|
|
13
13
|
import { usePrefix } from '../../internal/usePrefix.js';
|
|
14
|
+
import { useControllableState } from '../../internal/useControllableState.js';
|
|
15
|
+
import { useFeatureFlag } from '../FeatureFlags/index.js';
|
|
14
16
|
import { matches, match } from '../../internal/keyboard/match.js';
|
|
15
17
|
import { ArrowUp, ArrowDown, Home, End } from '../../internal/keyboard/keys.js';
|
|
16
18
|
|
|
@@ -22,11 +24,13 @@ function TreeView(_ref) {
|
|
|
22
24
|
hideLabel = false,
|
|
23
25
|
label,
|
|
24
26
|
multiselect = false,
|
|
27
|
+
onActivate,
|
|
25
28
|
onSelect,
|
|
26
|
-
selected: preselected
|
|
29
|
+
selected: preselected,
|
|
27
30
|
size = 'sm',
|
|
28
31
|
...rest
|
|
29
32
|
} = _ref;
|
|
33
|
+
const enableTreeviewControllable = useFeatureFlag('enable-treeview-controllable');
|
|
30
34
|
const {
|
|
31
35
|
current: treeId
|
|
32
36
|
} = useRef(rest.id || uniqueId());
|
|
@@ -36,8 +40,20 @@ function TreeView(_ref) {
|
|
|
36
40
|
});
|
|
37
41
|
const treeRootRef = useRef(null);
|
|
38
42
|
const treeWalker = useRef(treeRootRef?.current);
|
|
39
|
-
const
|
|
40
|
-
|
|
43
|
+
const controllableSelectionState = useControllableState({
|
|
44
|
+
value: preselected,
|
|
45
|
+
onChange: onSelect,
|
|
46
|
+
defaultValue: []
|
|
47
|
+
});
|
|
48
|
+
const uncontrollableSelectionState = useState(preselected ?? []);
|
|
49
|
+
const [selected, setSelected] = enableTreeviewControllable ? controllableSelectionState : uncontrollableSelectionState;
|
|
50
|
+
const controllableActiveState = useControllableState({
|
|
51
|
+
value: prespecifiedActive,
|
|
52
|
+
onChange: onActivate,
|
|
53
|
+
defaultValue: undefined
|
|
54
|
+
});
|
|
55
|
+
const uncontrollableActiveState = useState(prespecifiedActive);
|
|
56
|
+
const [active, setActive] = enableTreeviewControllable ? controllableActiveState : uncontrollableActiveState;
|
|
41
57
|
function resetNodeTabIndices() {
|
|
42
58
|
Array.prototype.forEach.call(treeRootRef?.current?.querySelectorAll('[tabIndex="0"]') ?? [], item => {
|
|
43
59
|
item.tabIndex = -1;
|
|
@@ -54,14 +70,18 @@ function TreeView(_ref) {
|
|
|
54
70
|
} else {
|
|
55
71
|
setSelected(selected.filter(selectedId => selectedId !== nodeId));
|
|
56
72
|
}
|
|
57
|
-
|
|
73
|
+
if (!enableTreeviewControllable) {
|
|
74
|
+
onSelect?.(event, node);
|
|
75
|
+
}
|
|
58
76
|
} else {
|
|
59
77
|
setSelected([nodeId]);
|
|
60
78
|
setActive(nodeId);
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
79
|
+
if (!enableTreeviewControllable) {
|
|
80
|
+
onSelect?.(event, {
|
|
81
|
+
activeNodeId: nodeId,
|
|
82
|
+
...node
|
|
83
|
+
});
|
|
84
|
+
}
|
|
65
85
|
}
|
|
66
86
|
}
|
|
67
87
|
function handleFocusEvent(event) {
|
|
@@ -167,11 +187,13 @@ function TreeView(_ref) {
|
|
|
167
187
|
});
|
|
168
188
|
}, [prefix]);
|
|
169
189
|
const useActiveAndSelectedOnMount = () => useEffect(() => {
|
|
170
|
-
if (
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
190
|
+
if (!enableTreeviewControllable) {
|
|
191
|
+
if (preselected?.length) {
|
|
192
|
+
setSelected(preselected);
|
|
193
|
+
}
|
|
194
|
+
if (prespecifiedActive) {
|
|
195
|
+
setActive(prespecifiedActive);
|
|
196
|
+
}
|
|
175
197
|
}
|
|
176
198
|
}, []);
|
|
177
199
|
useActiveAndSelectedOnMount();
|
|
@@ -216,6 +238,11 @@ TreeView.propTypes = {
|
|
|
216
238
|
* If `multiselect` is `false` then only one node can be selected at a time
|
|
217
239
|
*/
|
|
218
240
|
multiselect: PropTypes.bool,
|
|
241
|
+
/**
|
|
242
|
+
* **[Experimental]** Callback function that is called when any node is activated.
|
|
243
|
+
* *This is only supported with the `enable-treeview-controllable` feature flag!*
|
|
244
|
+
*/
|
|
245
|
+
onActivate: PropTypes.func,
|
|
219
246
|
/**
|
|
220
247
|
* Callback function that is called when any node is selected
|
|
221
248
|
*/
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright IBM Corp. 2016, 2023
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the Apache-2.0 license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
import React, { ReactNode } from 'react';
|
|
8
|
+
interface HeaderProps {
|
|
9
|
+
children?: ReactNode;
|
|
10
|
+
/**
|
|
11
|
+
* Required props for the accessibility label of the header
|
|
12
|
+
*/
|
|
13
|
+
'aria-label'?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Required props for the accessibility label of the header
|
|
16
|
+
*/
|
|
17
|
+
'aria-labelledby'?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Optionally provide a custom class name that is applied to the underlying <header>
|
|
20
|
+
*/
|
|
21
|
+
className?: string;
|
|
22
|
+
}
|
|
23
|
+
declare const Header: React.FC<HeaderProps>;
|
|
24
|
+
export default Header;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright IBM Corp. 2016, 2023
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the Apache-2.0 license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
import React, { ReactNode } from 'react';
|
|
8
|
+
interface HeaderGlobalActionProps {
|
|
9
|
+
/**
|
|
10
|
+
* Required props for the accessibility label of the button
|
|
11
|
+
*/
|
|
12
|
+
'aria-label'?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Required props for the accessibility label of the button
|
|
15
|
+
*/
|
|
16
|
+
'aria-labelledby'?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Provide a custom icon for this global action
|
|
19
|
+
*/
|
|
20
|
+
children: ReactNode;
|
|
21
|
+
/**
|
|
22
|
+
* Optionally provide a custom class name that is applied to the underlying
|
|
23
|
+
* button
|
|
24
|
+
*/
|
|
25
|
+
className?: string;
|
|
26
|
+
/**
|
|
27
|
+
* Specify whether the action is currently active
|
|
28
|
+
*/
|
|
29
|
+
isActive?: boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Optionally provide an onClick handler that is called when the underlying
|
|
32
|
+
* button fires it's onclick event
|
|
33
|
+
*/
|
|
34
|
+
onClick?: () => void;
|
|
35
|
+
/**
|
|
36
|
+
* Specify the alignment of the tooltip to the icon-only button.
|
|
37
|
+
* Can be one of: start, center, or end.
|
|
38
|
+
*/
|
|
39
|
+
tooltipAlignment?: 'start' | 'center' | 'end';
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* HeaderGlobalAction is used as a part of the `HeaderGlobalBar`. It is
|
|
43
|
+
* essentially an Icon Button with an additional state to indicate whether it is
|
|
44
|
+
* "active". The active state comes from when a user clicks on the global action
|
|
45
|
+
* which should trigger a panel to appear.
|
|
46
|
+
*
|
|
47
|
+
* Note: children passed to this component should be an Icon.
|
|
48
|
+
*/
|
|
49
|
+
declare const HeaderGlobalAction: React.FC<HeaderGlobalActionProps>;
|
|
50
|
+
export default HeaderGlobalAction;
|
|
@@ -84,6 +84,5 @@ HeaderGlobalAction.propTypes = {
|
|
|
84
84
|
tooltipAlignment: PropTypes.oneOf(['start', 'center', 'end'])
|
|
85
85
|
};
|
|
86
86
|
HeaderGlobalAction.displayName = 'HeaderGlobalAction';
|
|
87
|
-
var HeaderGlobalAction$1 = HeaderGlobalAction;
|
|
88
87
|
|
|
89
|
-
export { HeaderGlobalAction
|
|
88
|
+
export { HeaderGlobalAction as default };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright IBM Corp. 2016, 2023
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the Apache-2.0 license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Generic container for `HeaderGlobalAction` components
|
|
9
|
+
*/
|
|
10
|
+
declare const HeaderGlobalBar: (props: import("../../types/common").ReactAttr<"div">) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
|
|
11
|
+
export default HeaderGlobalBar;
|
|
@@ -10,7 +10,8 @@ import wrapComponent from '../../tools/wrapComponent.js';
|
|
|
10
10
|
/**
|
|
11
11
|
* Generic container for `HeaderGlobalAction` components
|
|
12
12
|
*/
|
|
13
|
-
|
|
13
|
+
|
|
14
|
+
const HeaderGlobalBar = wrapComponent({
|
|
14
15
|
name: 'HeaderGlobalBar',
|
|
15
16
|
className: prefix => `${prefix}--header__global`,
|
|
16
17
|
type: 'div'
|