@carbon/react 1.87.1-rc.0 → 1.88.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 (95) hide show
  1. package/.playwright/INTERNAL_AVT_REPORT_DO_NOT_USE.json +792 -792
  2. package/es/components/AILabel/index.d.ts +4 -3
  3. package/es/components/AILabel/index.js +3 -1
  4. package/es/components/Button/Button.js +3 -1
  5. package/es/components/CodeSnippet/CodeSnippet.d.ts +9 -5
  6. package/es/components/CodeSnippet/CodeSnippet.js +3 -1
  7. package/es/components/ComboBox/ComboBox.d.ts +2 -1
  8. package/es/components/ComboBox/ComboBox.js +2 -1
  9. package/es/components/ContentSwitcher/ContentSwitcher.d.ts +1 -6
  10. package/es/components/Copy/Copy.d.ts +9 -5
  11. package/es/components/Copy/Copy.js +3 -1
  12. package/es/components/CopyButton/CopyButton.d.ts +9 -5
  13. package/es/components/CopyButton/CopyButton.js +3 -1
  14. package/es/components/Dropdown/Dropdown.d.ts +4 -1
  15. package/es/components/Dropdown/Dropdown.js +4 -1
  16. package/es/components/FileUploader/FileUploaderButton.js +6 -3
  17. package/es/components/IconButton/index.d.ts +6 -4
  18. package/es/components/IconButton/index.js +3 -4
  19. package/es/components/MultiSelect/FilterableMultiSelect.d.ts +5 -2
  20. package/es/components/MultiSelect/FilterableMultiSelect.js +101 -22
  21. package/es/components/MultiSelect/MultiSelect.d.ts +2 -1
  22. package/es/components/MultiSelect/MultiSelect.js +2 -1
  23. package/es/components/Notification/Notification.d.ts +9 -1
  24. package/es/components/Notification/Notification.js +9 -1
  25. package/es/components/NumberInput/NumberInput.d.ts +4 -0
  26. package/es/components/NumberInput/NumberInput.js +12 -7
  27. package/es/components/OverflowMenu/next/index.d.ts +6 -2
  28. package/es/components/OverflowMenu/next/index.js +4 -1
  29. package/es/components/Popover/index.d.ts +4 -1
  30. package/es/components/Popover/index.js +12 -2
  31. package/es/components/Switch/IconSwitch.d.ts +44 -2
  32. package/es/components/Switch/IconSwitch.js +34 -27
  33. package/es/components/Switch/Switch.js +1 -0
  34. package/es/components/Toggletip/index.d.ts +4 -1
  35. package/es/components/Toggletip/index.js +4 -1
  36. package/es/components/Tooltip/DefinitionTooltip.d.ts +4 -2
  37. package/es/components/Tooltip/DefinitionTooltip.js +3 -1
  38. package/es/components/Tooltip/Tooltip.d.ts +0 -3
  39. package/es/components/Tooltip/Tooltip.js +2 -10
  40. package/es/components/TreeView/TreeContext.d.ts +1 -2
  41. package/es/components/TreeView/TreeNode.d.ts +12 -8
  42. package/es/components/TreeView/TreeNode.js +3 -9
  43. package/es/components/TreeView/TreeView.d.ts +7 -5
  44. package/es/components/TreeView/TreeView.js +20 -22
  45. package/es/components/UIShell/HeaderPanel.js +1 -1
  46. package/es/internal/Selection.d.ts +1 -0
  47. package/es/internal/Selection.js +10 -0
  48. package/lib/components/AILabel/index.d.ts +4 -3
  49. package/lib/components/AILabel/index.js +3 -1
  50. package/lib/components/Button/Button.js +3 -1
  51. package/lib/components/CodeSnippet/CodeSnippet.d.ts +9 -5
  52. package/lib/components/CodeSnippet/CodeSnippet.js +3 -1
  53. package/lib/components/ComboBox/ComboBox.d.ts +2 -1
  54. package/lib/components/ComboBox/ComboBox.js +2 -1
  55. package/lib/components/ContentSwitcher/ContentSwitcher.d.ts +1 -6
  56. package/lib/components/Copy/Copy.d.ts +9 -5
  57. package/lib/components/Copy/Copy.js +3 -1
  58. package/lib/components/CopyButton/CopyButton.d.ts +9 -5
  59. package/lib/components/CopyButton/CopyButton.js +3 -1
  60. package/lib/components/Dropdown/Dropdown.d.ts +4 -1
  61. package/lib/components/Dropdown/Dropdown.js +4 -1
  62. package/lib/components/FileUploader/FileUploaderButton.js +6 -3
  63. package/lib/components/IconButton/index.d.ts +6 -4
  64. package/lib/components/IconButton/index.js +3 -4
  65. package/lib/components/MultiSelect/FilterableMultiSelect.d.ts +5 -2
  66. package/lib/components/MultiSelect/FilterableMultiSelect.js +100 -21
  67. package/lib/components/MultiSelect/MultiSelect.d.ts +2 -1
  68. package/lib/components/MultiSelect/MultiSelect.js +2 -1
  69. package/lib/components/Notification/Notification.d.ts +9 -1
  70. package/lib/components/Notification/Notification.js +9 -1
  71. package/lib/components/NumberInput/NumberInput.d.ts +4 -0
  72. package/lib/components/NumberInput/NumberInput.js +12 -7
  73. package/lib/components/OverflowMenu/next/index.d.ts +6 -2
  74. package/lib/components/OverflowMenu/next/index.js +4 -1
  75. package/lib/components/Popover/index.d.ts +4 -1
  76. package/lib/components/Popover/index.js +12 -2
  77. package/lib/components/Switch/IconSwitch.d.ts +44 -2
  78. package/lib/components/Switch/IconSwitch.js +35 -28
  79. package/lib/components/Switch/Switch.js +1 -0
  80. package/lib/components/Toggletip/index.d.ts +4 -1
  81. package/lib/components/Toggletip/index.js +4 -1
  82. package/lib/components/Tooltip/DefinitionTooltip.d.ts +4 -2
  83. package/lib/components/Tooltip/DefinitionTooltip.js +3 -1
  84. package/lib/components/Tooltip/Tooltip.d.ts +0 -3
  85. package/lib/components/Tooltip/Tooltip.js +2 -10
  86. package/lib/components/TreeView/TreeContext.d.ts +1 -2
  87. package/lib/components/TreeView/TreeNode.d.ts +12 -8
  88. package/lib/components/TreeView/TreeNode.js +3 -9
  89. package/lib/components/TreeView/TreeView.d.ts +7 -5
  90. package/lib/components/TreeView/TreeView.js +20 -22
  91. package/lib/components/UIShell/HeaderPanel.js +2 -2
  92. package/lib/internal/Selection.d.ts +1 -0
  93. package/lib/internal/Selection.js +10 -0
  94. package/package.json +7 -7
  95. package/telemetry.yml +2 -9
@@ -472,6 +472,7 @@ function ActionableNotification({
472
472
  ['aria-label']: ariaLabel,
473
473
  // @ts-expect-error: deprecated prop
474
474
  ariaLabel: deprecatedAriaLabel,
475
+ caption,
475
476
  children,
476
477
  role = 'alertdialog',
477
478
  onActionButtonClick,
@@ -586,7 +587,10 @@ function ActionableNotification({
586
587
  as: "div",
587
588
  className: `${prefix}--actionable-notification__subtitle`,
588
589
  id: subtitleId
589
- }, subtitle), children))), /*#__PURE__*/React.createElement("div", {
590
+ }, subtitle), caption && /*#__PURE__*/React.createElement(Text, {
591
+ as: "div",
592
+ className: `${prefix}--actionable-notification__caption`
593
+ }, caption), children))), /*#__PURE__*/React.createElement("div", {
590
594
  className: `${prefix}--actionable-notification__button-wrapper`,
591
595
  ref: innerModal
592
596
  }, actionButtonLabel && /*#__PURE__*/React.createElement(NotificationActionButton, {
@@ -617,6 +621,10 @@ ActionableNotification.propTypes = {
617
621
  * Provide a description for "close" icon button that can be read by screen readers
618
622
  */
619
623
  ariaLabel: deprecate(PropTypes.string, 'This prop syntax has been deprecated. Please use the new `aria-label`.'),
624
+ /**
625
+ * Specify the caption
626
+ */
627
+ caption: PropTypes.string,
620
628
  /**
621
629
  * Specify the content
622
630
  */
@@ -51,6 +51,10 @@ export interface NumberInputProps extends Omit<React.InputHTMLAttributes<HTMLInp
51
51
  * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat#options
52
52
  */
53
53
  formatOptions?: NumberFormatOptions;
54
+ /**
55
+ * Provide the value stepping should begin at when the input is empty
56
+ */
57
+ stepStartValue?: number;
54
58
  /**
55
59
  * Provide text that is used alongside the control label for additional help
56
60
  */
@@ -76,6 +76,7 @@ const NumberInput = /*#__PURE__*/React.forwardRef(function NumberInput(props, fo
76
76
  defaultValue = type === 'number' ? 0 : NaN,
77
77
  warn = false,
78
78
  warnText = '',
79
+ stepStartValue = 0,
79
80
  value: controlledValue,
80
81
  ...rest
81
82
  } = props;
@@ -236,14 +237,14 @@ const NumberInput = /*#__PURE__*/React.forwardRef(function NumberInput(props, fo
236
237
  if (inputRef.current) {
237
238
  const currentValue = type === 'number' ? Number(inputRef.current.value) : numberValue;
238
239
  let rawValue;
239
- if (Number.isNaN(currentValue)) {
240
- // When the field is empty (NaN), incrementing begins at min,
241
- // decrementing begins at max.
242
- // When there's no min or max to use, it begins at 0.
243
- if (direction === `up` && min) {
240
+ if (Number.isNaN(currentValue) || !currentValue) {
241
+ if (typeof stepStartValue === 'number' && stepStartValue) {
242
+ rawValue = stepStartValue;
243
+ } else if (min && min < 0 && max && max > 0 || !max && !min || max) {
244
+ if (direction === `up`) rawValue = 1;
245
+ if (direction === `down`) rawValue = -1;
246
+ } else if (min && min > 0 && max && max > 0 || min) {
244
247
  rawValue = min;
245
- } else if (direction === `down` && max) {
246
- rawValue = max;
247
248
  } else {
248
249
  rawValue = 0;
249
250
  }
@@ -532,6 +533,10 @@ NumberInput.propTypes = {
532
533
  * The minimum value.
533
534
  */
534
535
  min: PropTypes.number,
536
+ /**
537
+ * Provide the value stepping should begin at when the input is empty
538
+ */
539
+ stepStartValue: PropTypes.number,
535
540
  /**
536
541
  * Provide an optional handler that is called when the input or stepper
537
542
  * buttons are blurred.
@@ -5,9 +5,13 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  import React, { type ElementType } from 'react';
8
+ import type { PopoverAlignment } from '../../Popover';
8
9
  interface OverflowMenuProps {
9
10
  /**
10
- * **Experimental**: Will attempt to automatically align the floating element to avoid collisions with the viewport and being clipped by ancestor elements.
11
+ * **Experimental**: Will attempt to automatically align the floating element
12
+ * to avoid collisions with the viewport and being clipped by ancestor
13
+ * elements. Requires React v17+
14
+ * @see https://github.com/carbon-design-system/carbon/issues/18714
11
15
  */
12
16
  autoAlign?: boolean;
13
17
  /**
@@ -37,7 +41,7 @@ interface OverflowMenuProps {
37
41
  /**
38
42
  * Specify how the trigger tooltip should be aligned.
39
43
  */
40
- tooltipAlignment?: 'top' | 'top-left' | 'top-right' | 'bottom' | 'bottom-left' | 'bottom-right' | 'left' | 'right';
44
+ tooltipAlignment?: PopoverAlignment;
41
45
  /**
42
46
  * Specify a DOM node where the Menu should be rendered in. Defaults to document.body.
43
47
  */
@@ -132,7 +132,10 @@ const OverflowMenu = /*#__PURE__*/React.forwardRef(function OverflowMenu({
132
132
  });
133
133
  OverflowMenu.propTypes = {
134
134
  /**
135
- * **Experimental**: Will attempt to automatically align the floating element to avoid collisions with the viewport and being clipped by ancestor elements.
135
+ * **Experimental**: Will attempt to automatically align the floating element
136
+ * to avoid collisions with the viewport and being clipped by ancestor
137
+ * elements. Requires React v17+
138
+ * @see https://github.com/carbon-design-system/carbon/issues/18714
136
139
  */
137
140
  autoAlign: PropTypes.bool,
138
141
  /**
@@ -26,7 +26,10 @@ export interface PopoverBaseProps {
26
26
  */
27
27
  align?: PopoverAlignment;
28
28
  /**
29
- * Will auto-align the popover on first render if it is not visible. This prop is currently experimental and is subject to future changes.
29
+ * Will auto-align the popover on first render if it is not visible. This prop
30
+ * is currently experimental and is subject to future changes. Requires
31
+ * React v17+
32
+ * @see https://github.com/carbon-design-system/carbon/issues/18714
30
33
  */
31
34
  autoAlign?: boolean;
32
35
  /**
@@ -62,7 +62,14 @@ forwardRef) {
62
62
  // The `Popover` should close whenever it and its children loses focus
63
63
  useEvent(popover, 'focusout', event => {
64
64
  const relatedTarget = event.relatedTarget;
65
- if (!popover.current?.contains(relatedTarget)) {
65
+ if (!relatedTarget) {
66
+ return;
67
+ }
68
+ const isOutsideMainContainer = !popover.current?.contains(relatedTarget);
69
+ const isOutsideFloating = enableFloatingStyles && refs.floating.current ? !refs.floating.current.contains(relatedTarget) : true;
70
+
71
+ // Only close if focus moved outside both containers
72
+ if (isOutsideMainContainer && isOutsideFloating) {
66
73
  onRequestClose?.();
67
74
  }
68
75
  });
@@ -291,7 +298,10 @@ Popover.propTypes = {
291
298
  */
292
299
  as: PropTypes.oneOfType([PropTypes.string, PropTypes.elementType]),
293
300
  /**
294
- * Will auto-align the popover on first render if it is not visible. This prop is currently experimental and is subject to future changes.
301
+ * Will auto-align the popover on first render if it is not visible. This prop
302
+ * is currently experimental and is subject to future changes. Requires
303
+ * React v17+
304
+ * @see https://github.com/carbon-design-system/carbon/issues/18714
295
305
  */
296
306
  autoAlign: PropTypes.bool,
297
307
  /**
@@ -1,3 +1,45 @@
1
- export default IconSwitch;
2
- declare const IconSwitch: React.ForwardRefExoticComponent<React.RefAttributes<any>>;
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
+ */
3
7
  import React from 'react';
8
+ import { type IconButtonProps } from '../IconButton';
9
+ import type { SwitchEventHandlersParams } from './Switch';
10
+ interface IconSwitchProps extends Omit<IconButtonProps, 'onClick' | 'onKeyDown' | 'label' | 'name'> {
11
+ /**
12
+ * The index of the `IconSwitch`.
13
+ *
14
+ * Reserved for usage in `ContentSwitcher`.
15
+ */
16
+ index?: number;
17
+ /**
18
+ * The name of the `IconSwitch`.
19
+ */
20
+ name?: string | number;
21
+ /**
22
+ * A handler that is invoked when a user clicks on the control.
23
+ *
24
+ * Reserved for usage in `ContentSwitcher`.
25
+ */
26
+ onClick?: (params: SwitchEventHandlersParams) => void;
27
+ /**
28
+ * A handler that is invoked on the key down event for the control.
29
+ *
30
+ * Reserved for usage in `ContentSwitcher`.
31
+ */
32
+ onKeyDown?: (params: SwitchEventHandlersParams) => void;
33
+ /**
34
+ * Whether the `IconSwitch` is selected.
35
+ *
36
+ * Reserved for usage in `ContentSwitcher`.
37
+ */
38
+ selected?: boolean;
39
+ /**
40
+ * `Tooltip` text.
41
+ */
42
+ text?: string;
43
+ }
44
+ declare const IconSwitch: React.ForwardRefExoticComponent<IconSwitchProps & React.RefAttributes<HTMLButtonElement>>;
45
+ export default IconSwitch;
@@ -7,13 +7,14 @@
7
7
 
8
8
  import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
9
9
  import PropTypes from 'prop-types';
10
- import React, { useState } from 'react';
10
+ import React, { forwardRef, useState } from 'react';
11
11
  import cx from 'classnames';
12
12
  import { IconButton } from '../IconButton/index.js';
13
13
  import { usePrefix } from '../../internal/usePrefix.js';
14
+ import { noopFn } from '../../internal/noopFn.js';
14
15
 
15
- const noopFn = () => {};
16
- const IconSwitch = /*#__PURE__*/React.forwardRef(function Switch(props, tabRef) {
16
+ const frFn = forwardRef;
17
+ const IconSwitch = frFn((props, ref) => {
17
18
  const {
18
19
  align,
19
20
  children,
@@ -32,8 +33,8 @@ const IconSwitch = /*#__PURE__*/React.forwardRef(function Switch(props, tabRef)
32
33
  } = props;
33
34
  const prefix = usePrefix();
34
35
  const [isHovered, setIsHovered] = useState(false);
35
- const handleClick = e => {
36
- e.preventDefault();
36
+ const handleClick = event => {
37
+ event.preventDefault();
37
38
  onClick({
38
39
  index,
39
40
  name,
@@ -41,6 +42,7 @@ const IconSwitch = /*#__PURE__*/React.forwardRef(function Switch(props, tabRef)
41
42
  });
42
43
  };
43
44
  const handleKeyDown = event => {
45
+ // TODO: `which` was deprecated years ago. When can its usage be deleted?
44
46
  const key = event.key || event.which;
45
47
  onKeyDown({
46
48
  index,
@@ -62,20 +64,10 @@ const IconSwitch = /*#__PURE__*/React.forwardRef(function Switch(props, tabRef)
62
64
  [`${prefix}--content-switcher-popover--selected`]: selected,
63
65
  [`${prefix}--content-switcher-popover--disabled`]: disabled
64
66
  });
65
- const commonProps = {
66
- onClick: handleClick,
67
- onKeyDown: handleKeyDown,
68
- className: classes,
69
- disabled,
70
- align,
71
- enterDelayMs,
72
- leaveDelayMs,
73
- size
74
- };
75
67
  return /*#__PURE__*/React.createElement(IconButton, _extends({
76
68
  label: text,
77
69
  type: "button",
78
- ref: tabRef,
70
+ ref: ref,
79
71
  role: "tab",
80
72
  tabIndex: selected || isHovered ? 0 : -1,
81
73
  onMouseEnter: handleMouseEnter,
@@ -85,7 +77,16 @@ const IconSwitch = /*#__PURE__*/React.forwardRef(function Switch(props, tabRef)
85
77
  "aria-selected": selected,
86
78
  "aria-label": text,
87
79
  wrapperClasses: iconButtonClasses
88
- }, other, commonProps), children);
80
+ }, other, {
81
+ align: align,
82
+ className: classes,
83
+ disabled: disabled,
84
+ enterDelayMs: enterDelayMs,
85
+ leaveDelayMs: leaveDelayMs,
86
+ onClick: handleClick,
87
+ onKeyDown: handleKeyDown,
88
+ size: size
89
+ }), children);
89
90
  });
90
91
  IconSwitch.displayName = 'IconSwitch';
91
92
  IconSwitch.propTypes = {
@@ -94,15 +95,15 @@ IconSwitch.propTypes = {
94
95
  */
95
96
  align: PropTypes.oneOf(['top', 'top-left', 'top-right', 'bottom', 'bottom-left', 'bottom-right', 'left', 'right']),
96
97
  /**
97
- * Provide child elements to be rendered inside of the Switch
98
+ * Children to be rendered inside of the `IconSwitch`.
98
99
  */
99
100
  children: PropTypes.node,
100
101
  /**
101
- * Specify an optional className to be added to your Switch
102
+ * Specify an optional className to be added to your `IconSwitch`.
102
103
  */
103
104
  className: PropTypes.string,
104
105
  /**
105
- * Specify whether or not the Switch should be disabled
106
+ * Whether the `IconSwitch` should be disabled.
106
107
  */
107
108
  disabled: PropTypes.bool,
108
109
  /**
@@ -110,8 +111,9 @@ IconSwitch.propTypes = {
110
111
  */
111
112
  enterDelayMs: PropTypes.number,
112
113
  /**
113
- * The index of your Switch in your ContentSwitcher that is used for event handlers.
114
- * Reserved for usage in ContentSwitcher
114
+ * The index of the `IconSwitch`.
115
+ *
116
+ * Reserved for usage in `ContentSwitcher`.
115
117
  */
116
118
  index: PropTypes.number,
117
119
  /**
@@ -119,29 +121,34 @@ IconSwitch.propTypes = {
119
121
  */
120
122
  leaveDelayMs: PropTypes.number,
121
123
  /**
122
- * Provide the name of your Switch that is used for event handlers
124
+ * The name of the `IconSwitch`.
123
125
  */
124
126
  name: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
125
127
  /**
126
128
  * A handler that is invoked when a user clicks on the control.
127
- * Reserved for usage in ContentSwitcher
129
+ *
130
+ * Reserved for usage in `ContentSwitcher`.
128
131
  */
129
132
  onClick: PropTypes.func,
130
133
  /**
131
134
  * A handler that is invoked on the key down event for the control.
132
- * Reserved for usage in ContentSwitcher
135
+ *
136
+ * Reserved for usage in `ContentSwitcher`.
133
137
  */
134
138
  onKeyDown: PropTypes.func,
135
139
  /**
136
- * Whether your Switch is selected. Reserved for usage in ContentSwitcher
140
+ * Whether the `IconSwitch` is selected.
141
+ *
142
+ * Reserved for usage in `ContentSwitcher`.
137
143
  */
138
144
  selected: PropTypes.bool,
145
+ // TODO: Icon only variant of what? Isn't the `IconSwitch` always icon only?
139
146
  /**
140
147
  * Passed in from `ContentSwitcher` to render icon-only variant
141
148
  */
142
149
  size: PropTypes.oneOf(['sm', 'md', 'lg']),
143
150
  /**
144
- * Provide the visible text displayed by the Tooltip
151
+ * `Tooltip` text.
145
152
  */
146
153
  text: PropTypes.string
147
154
  };
@@ -35,6 +35,7 @@ const Switch = /*#__PURE__*/React.forwardRef(function Switch(props, tabRef) {
35
35
  });
36
36
  };
37
37
  const handleKeyDown = event => {
38
+ // TODO: `which` was deprecated years ago. When can its usage be deleted?
38
39
  const key = event.key || event.which;
39
40
  onKeyDown?.({
40
41
  index,
@@ -67,7 +67,10 @@ export declare namespace Toggletip {
67
67
  */
68
68
  as: PropTypes.Requireable<PropTypes.ReactComponentLike>;
69
69
  /**
70
- * Will auto-align the popover on first render if it is not visible. This prop is currently experimental and is subject to future changes.
70
+ * Will auto-align the popover on first render if it is not visible. This prop
71
+ * is currently experimental and is subject to future changes. Requires
72
+ * React v17+
73
+ * @see https://github.com/carbon-design-system/carbon/issues/18714
71
74
  */
72
75
  autoAlign: PropTypes.Requireable<boolean>;
73
76
  /**
@@ -185,7 +185,10 @@ Toggletip.propTypes = {
185
185
  */
186
186
  as: PropTypes.elementType,
187
187
  /**
188
- * Will auto-align the popover on first render if it is not visible. This prop is currently experimental and is subject to future changes.
188
+ * Will auto-align the popover on first render if it is not visible. This prop
189
+ * is currently experimental and is subject to future changes. Requires
190
+ * React v17+
191
+ * @see https://github.com/carbon-design-system/carbon/issues/18714
189
192
  */
190
193
  autoAlign: PropTypes.bool,
191
194
  /**
@@ -12,13 +12,15 @@ export interface DefinitionTooltipProps extends Omit<React.ButtonHTMLAttributes<
12
12
  */
13
13
  align?: PopoverAlignment;
14
14
  /**
15
- * Will auto-align Definition Tooltip. This prop is currently experimental and is subject to future changes.
15
+ * Will auto-align Definition Tooltip. This prop is currently experimental
16
+ * and is subject to future changes. Requires React v17+
17
+ * @see https://github.com/carbon-design-system/carbon/issues/18714
16
18
  */
17
19
  autoAlign?: boolean;
18
20
  /**
19
21
  * The `children` prop will be used as the value that is being defined
20
22
  */
21
- children?: React.ReactNode;
23
+ children: React.ReactNode;
22
24
  /**
23
25
  * Specify an optional className to be applied to the container node
24
26
  */
@@ -101,7 +101,9 @@ DefinitionTooltip.propTypes = {
101
101
  // new values to match floating-ui
102
102
  'top-start', 'top-end', 'bottom-start', 'bottom-end', 'left-end', 'left-start', 'right-end', 'right-start']),
103
103
  /**
104
- * Will auto-align the popover. This prop is currently experimental and is subject to future changes.
104
+ * Will auto-align the popover. This prop is currently experimental and is
105
+ * subject to future changes. Requires React v17+
106
+ * @see https://github.com/carbon-design-system/carbon/issues/18714
105
107
  */
106
108
  autoAlign: PropTypes.bool,
107
109
  /**
@@ -54,9 +54,6 @@ interface TooltipBaseProps {
54
54
  /**
55
55
  * Provide the label to be rendered inside of the Tooltip. The label will use
56
56
  * `aria-labelledby` and will fully describe the child node that is provided.
57
- * If the child already has an `aria-label`, the tooltip will not apply
58
- * `aria-labelledby`. If the child has its own `aria-labelledby`, that value
59
- * will be kept. Otherwise, the tooltip will use its own ID to label the child.
60
57
  * This means that if you have text in the child node, that it will not be
61
58
  * announced to the screen reader.
62
59
  *
@@ -46,20 +46,12 @@ const Tooltip = /*#__PURE__*/React.forwardRef(({
46
46
  const prefix = usePrefix();
47
47
  const child = React.Children.only(children);
48
48
  const {
49
- 'aria-label': ariaLabel,
50
49
  'aria-labelledby': ariaLabelledBy,
51
50
  'aria-describedby': ariaDescribedBy
52
51
  } = child?.props ?? {};
53
52
  const hasLabel = !!label;
54
- const hasAriaLabel = typeof ariaLabel === 'string' ? ariaLabel.trim() !== '' : false;
55
-
56
- // An `aria-label` takes precedence over `aria-describedby`, but when it's
57
- // needed and the user doesn't specify one, the fallback `id` is used.
58
- const labelledBy = hasAriaLabel ? undefined : hasLabel ? ariaLabelledBy ?? id : undefined;
59
-
60
- // If `aria-label` is present, use any provided `aria-describedby`.
61
- // If not, fallback to child's `aria-describedby` or the tooltip `id` if needed.
62
- const describedBy = hasAriaLabel ? ariaDescribedBy : ariaDescribedBy ?? (!hasLabel && !ariaLabelledBy ? id : undefined);
53
+ const labelledBy = ariaLabelledBy ?? (hasLabel ? id : undefined);
54
+ const describedBy = ariaDescribedBy ?? (!hasLabel ? id : undefined);
63
55
  const triggerProps = {
64
56
  onFocus: () => !focusByMouse && setOpen(true),
65
57
  onBlur: () => {
@@ -4,13 +4,12 @@
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 { type MouseEvent } from 'react';
8
7
  import type { TreeNodeProps } from './TreeNode';
9
8
  interface TreeContextProps {
10
9
  active?: string | number;
11
10
  multiselect?: boolean;
12
11
  onActivate?: (nodeId?: string | number) => void;
13
- onTreeSelect?: (event: MouseEvent, node?: Partial<TreeNodeProps>) => void;
12
+ onTreeSelect?: TreeNodeProps['onTreeSelect'];
14
13
  selected?: Array<string | number>;
15
14
  size?: 'xs' | 'sm';
16
15
  }
@@ -5,6 +5,8 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  import React, { type ComponentType, type FunctionComponent } from 'react';
8
+ type UncontrolledOnToggle = (event: React.MouseEvent | React.KeyboardEvent, node: Pick<TreeNodeProps, 'id' | 'label' | 'value' | 'isExpanded'>) => void;
9
+ type ControlledOnToggle = (isExpanded: TreeNodeProps['isExpanded']) => void;
8
10
  export type TreeNodeProps = {
9
11
  /**
10
12
  * **Note:** this is controlled by the parent TreeView component, do not set manually.
@@ -52,15 +54,15 @@ export type TreeNodeProps = {
52
54
  /**
53
55
  * Callback function for when the node is selected
54
56
  */
55
- onSelect?: (event: React.MouseEvent, node?: Omit<TreeNodeProps, 'children'>) => void;
57
+ onSelect?: (event: React.MouseEvent | React.KeyboardEvent, node: Pick<TreeNodeProps, 'id' | 'label' | 'value'>) => void;
56
58
  /**
57
59
  * Callback function for when a parent node is expanded or collapsed
58
60
  */
59
- onToggle?: (event: React.MouseEvent | React.KeyboardEvent, node?: Omit<TreeNodeProps, 'children'>) => void;
61
+ onToggle?: UncontrolledOnToggle | ControlledOnToggle;
60
62
  /**
61
63
  * Callback function for when any node in the tree is selected
62
64
  */
63
- onTreeSelect?: (event: React.MouseEvent, node?: TreeNodeProps) => void;
65
+ onTreeSelect?: (event: React.MouseEvent | React.KeyboardEvent, node: Pick<TreeNodeProps, 'id' | 'label' | 'value'>) => void;
64
66
  /**
65
67
  * A component used to render an icon.
66
68
  */
@@ -86,7 +88,8 @@ export type TreeNodeProps = {
86
88
  /**
87
89
  * **Experimental**: Will attempt to automatically align the floating
88
90
  * element to avoid collisions with the viewport and being clipped by
89
- * ancestor elements.
91
+ * ancestor elements. Requires React v17+
92
+ * @see https://github.com/carbon-design-system/carbon/issues/18714
90
93
  */
91
94
  autoAlign?: boolean;
92
95
  } & Omit<React.LiHTMLAttributes<HTMLElement>, 'onSelect'>;
@@ -137,15 +140,15 @@ declare const TreeNode: React.ForwardRefExoticComponent<{
137
140
  /**
138
141
  * Callback function for when the node is selected
139
142
  */
140
- onSelect?: (event: React.MouseEvent, node?: Omit<TreeNodeProps, "children">) => void;
143
+ onSelect?: (event: React.MouseEvent | React.KeyboardEvent, node: Pick<TreeNodeProps, "id" | "label" | "value">) => void;
141
144
  /**
142
145
  * Callback function for when a parent node is expanded or collapsed
143
146
  */
144
- onToggle?: (event: React.MouseEvent | React.KeyboardEvent, node?: Omit<TreeNodeProps, "children">) => void;
147
+ onToggle?: UncontrolledOnToggle | ControlledOnToggle;
145
148
  /**
146
149
  * Callback function for when any node in the tree is selected
147
150
  */
148
- onTreeSelect?: (event: React.MouseEvent, node?: TreeNodeProps) => void;
151
+ onTreeSelect?: (event: React.MouseEvent | React.KeyboardEvent, node: Pick<TreeNodeProps, "id" | "label" | "value">) => void;
149
152
  /**
150
153
  * A component used to render an icon.
151
154
  */
@@ -171,7 +174,8 @@ declare const TreeNode: React.ForwardRefExoticComponent<{
171
174
  /**
172
175
  * **Experimental**: Will attempt to automatically align the floating
173
176
  * element to avoid collisions with the viewport and being clipped by
174
- * ancestor elements.
177
+ * ancestor elements. Requires React v17+
178
+ * @see https://github.com/carbon-design-system/carbon/issues/18714
175
179
  */
176
180
  autoAlign?: boolean;
177
181
  } & Omit<React.LiHTMLAttributes<HTMLElement>, "onSelect"> & React.RefAttributes<HTMLElement>>;
@@ -130,14 +130,7 @@ const TreeNode = /*#__PURE__*/React.forwardRef(({
130
130
  } = useRef(nodeId || useId());
131
131
  const controllableExpandedState = useControllableState({
132
132
  value: isExpanded,
133
- onChange: newValue => {
134
- onToggle?.(undefined, {
135
- id,
136
- isExpanded: newValue,
137
- label,
138
- value
139
- });
140
- },
133
+ onChange: onToggle,
141
134
  defaultValue: defaultIsExpanded ?? false
142
135
  });
143
136
  const uncontrollableExpandedState = useState(isExpanded ?? false);
@@ -497,7 +490,8 @@ TreeNode.propTypes = {
497
490
  /**
498
491
  * **Experimental**: Will attempt to automatically align the floating
499
492
  * element to avoid collisions with the viewport and being clipped by
500
- * ancestor elements.
493
+ * ancestor elements. Requires React v17+
494
+ * @see https://github.com/carbon-design-system/carbon/issues/18714
501
495
  */
502
496
  autoAlign: PropTypes.bool
503
497
  };
@@ -5,7 +5,11 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  import React, { type JSX } from 'react';
8
- import TreeNode, { TreeNodeProps } from './TreeNode';
8
+ import TreeNode, { type TreeNodeProps } from './TreeNode';
9
+ type UncontrolledOnSelect = (event: React.MouseEvent | React.KeyboardEvent, payload: Parameters<NonNullable<TreeNodeProps['onSelect']>>[1] & {
10
+ activeNodeId?: TreeViewProps['active'];
11
+ }) => void;
12
+ type ControlledOnSelect = (selected: TreeViewProps['selected']) => void;
9
13
  export type TreeViewProps = {
10
14
  /**
11
15
  * Mark the active node in the tree, represented by its ID
@@ -36,13 +40,11 @@ export type TreeViewProps = {
36
40
  * **[Experimental]** Callback function that is called when any node is activated.
37
41
  * *This is only supported with the `enable-treeview-controllable` feature flag!*
38
42
  */
39
- onActivate?: (activated?: string | number) => void;
43
+ onActivate?: (active: TreeViewProps['active']) => void;
40
44
  /**
41
45
  * Callback function that is called when any node is selected
42
46
  */
43
- onSelect?: (event: React.SyntheticEvent<HTMLUListElement>, payload?: Partial<TreeNodeProps> & {
44
- activeNodeId?: string | number;
45
- }) => void;
47
+ onSelect?: UncontrolledOnSelect | ControlledOnSelect;
46
48
  /**
47
49
  * Array representing all selected node IDs in the tree
48
50
  */
@@ -45,11 +45,7 @@ const TreeView = ({
45
45
  const treeWalker = useRef(null);
46
46
  const controllableSelectionState = useControllableState({
47
47
  value: preselected,
48
- onChange: newSelected => {
49
- onSelect?.(undefined, {
50
- activeNodeId: newSelected[0]
51
- });
52
- },
48
+ onChange: onSelect,
53
49
  defaultValue: []
54
50
  });
55
51
  const uncontrollableSelectionState = useState(preselected ?? []);
@@ -66,25 +62,27 @@ const TreeView = ({
66
62
  item.tabIndex = -1;
67
63
  });
68
64
  }
69
- function handleTreeSelect(event, node = {}) {
65
+ function handleTreeSelect(event, node) {
70
66
  const nodeId = node.id;
71
- if (multiselect && (event.metaKey || event.ctrlKey)) {
72
- if (!selected.includes(nodeId)) {
73
- setSelected(selected.concat(nodeId));
67
+ if (nodeId) {
68
+ if (multiselect && (event.metaKey || event.ctrlKey)) {
69
+ if (!selected.includes(nodeId)) {
70
+ setSelected(selected.concat(nodeId));
71
+ } else {
72
+ setSelected(selected.filter(selectedId => selectedId !== nodeId));
73
+ }
74
+ if (!enableTreeviewControllable) {
75
+ onSelect?.(event, node);
76
+ }
74
77
  } else {
75
- setSelected(selected.filter(selectedId => selectedId !== nodeId));
76
- }
77
- if (!enableTreeviewControllable) {
78
- onSelect?.(event, node);
79
- }
80
- } else {
81
- setSelected([nodeId]);
82
- setActive(nodeId);
83
- if (!enableTreeviewControllable) {
84
- onSelect?.(event, {
85
- activeNodeId: nodeId,
86
- ...node
87
- });
78
+ setSelected([nodeId]);
79
+ setActive(nodeId);
80
+ if (!enableTreeviewControllable) {
81
+ onSelect?.(event, {
82
+ activeNodeId: nodeId,
83
+ ...node
84
+ });
85
+ }
88
86
  }
89
87
  }
90
88
  }