@carbon/react 1.89.0 → 1.90.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/.playwright/INTERNAL_AVT_REPORT_DO_NOT_USE.json +922 -881
  2. package/README.md +2 -2
  3. package/es/components/ComposedModal/ComposedModal.js +14 -3
  4. package/es/components/DataTable/DataTable.d.ts +3 -8
  5. package/es/components/DataTable/TableExpandRow.d.ts +33 -5
  6. package/es/components/DataTable/TableExpandRow.js +4 -2
  7. package/es/components/DataTable/TableHeader.d.ts +1 -2
  8. package/es/components/DataTable/TableHeader.js +1 -2
  9. package/es/components/DataTable/TableRow.d.ts +3 -6
  10. package/es/components/DataTable/TableRow.js +35 -22
  11. package/es/components/DataTable/state/sorting.d.ts +55 -14
  12. package/es/components/DataTable/state/sorting.js +40 -50
  13. package/es/components/DataTable/tools/sorting.js +4 -0
  14. package/es/components/Modal/Modal.js +12 -6
  15. package/es/components/NumberInput/NumberInput.js +11 -6
  16. package/es/components/Popover/index.js +6 -2
  17. package/es/components/Tag/DismissibleTag.d.ts +5 -0
  18. package/es/components/Tag/DismissibleTag.js +6 -1
  19. package/es/components/Toggletip/index.js +19 -8
  20. package/es/components/TreeView/TreeNode.d.ts +28 -0
  21. package/es/components/TreeView/TreeNode.js +6 -5
  22. package/lib/components/ComposedModal/ComposedModal.js +14 -3
  23. package/lib/components/DataTable/DataTable.d.ts +3 -8
  24. package/lib/components/DataTable/TableExpandRow.d.ts +33 -5
  25. package/lib/components/DataTable/TableExpandRow.js +4 -2
  26. package/lib/components/DataTable/TableHeader.d.ts +1 -2
  27. package/lib/components/DataTable/TableHeader.js +1 -2
  28. package/lib/components/DataTable/TableRow.d.ts +3 -6
  29. package/lib/components/DataTable/TableRow.js +34 -21
  30. package/lib/components/DataTable/state/sorting.d.ts +55 -14
  31. package/lib/components/DataTable/state/sorting.js +39 -50
  32. package/lib/components/DataTable/tools/sorting.js +4 -0
  33. package/lib/components/Modal/Modal.js +12 -6
  34. package/lib/components/NumberInput/NumberInput.js +10 -5
  35. package/lib/components/Popover/index.js +6 -2
  36. package/lib/components/Tag/DismissibleTag.d.ts +5 -0
  37. package/lib/components/Tag/DismissibleTag.js +6 -1
  38. package/lib/components/Toggletip/index.js +18 -7
  39. package/lib/components/TreeView/TreeNode.d.ts +28 -0
  40. package/lib/components/TreeView/TreeNode.js +6 -5
  41. package/package.json +9 -9
  42. package/telemetry.yml +14 -0
@@ -44,6 +44,10 @@ const compareStrings = (a, b, locale = 'en') => {
44
44
  numeric: isNumeric
45
45
  });
46
46
  };
47
+
48
+ // TODO: Should `SortRowParams` in
49
+ // packages/react/src/components/DataTable/state/sorting.ts be used here?
50
+
47
51
  /**
48
52
  * Sorts table rows based on the provided column key and direction.
49
53
  */
@@ -42,7 +42,7 @@ var debounce = require('../../node_modules/es-toolkit/dist/compat/function/debou
42
42
  var Text = require('../Text/Text.js');
43
43
 
44
44
  const ModalSizes = ['xs', 'sm', 'md', 'lg'];
45
- const invalidOutsideClickMessage = '`Modal`: `preventCloseOnClickOutside` should not be `false` when `passiveModal` is `false`. Non-passive `Modal`s should not be dismissible by clicking outside.';
45
+ const invalidOutsideClickMessage = '`<Modal>` prop `preventCloseOnClickOutside` should not be `false` when ' + '`passiveModal` is `false`. Transactional, non-passive Modals should ' + 'not be dissmissable by clicking outside. ' + 'See: https://carbondesignsystem.com/components/modal/usage/#transactional-modal';
46
46
  const Modal = /*#__PURE__*/React.forwardRef(function Modal({
47
47
  'aria-label': ariaLabelProp,
48
48
  children,
@@ -68,7 +68,7 @@ const Modal = /*#__PURE__*/React.forwardRef(function Modal({
68
68
  size,
69
69
  hasScrollingContent = false,
70
70
  closeButtonLabel = 'Close',
71
- preventCloseOnClickOutside = !passiveModal,
71
+ preventCloseOnClickOutside,
72
72
  isFullWidth,
73
73
  launcherButtonRef,
74
74
  loadingStatus = 'inactive',
@@ -100,9 +100,7 @@ const Modal = /*#__PURE__*/React.forwardRef(function Modal({
100
100
  const focusTrapWithoutSentinels = index.useFeatureFlag('enable-experimental-focus-wrap-without-sentinels');
101
101
  const enableDialogElement = index.useFeatureFlag('enable-dialog-element');
102
102
  process.env.NODE_ENV !== "production" ? warning.warning(!(focusTrapWithoutSentinels && enableDialogElement), '`<Modal>` detected both `focusTrapWithoutSentinels` and ' + '`enableDialogElement` feature flags are enabled. The native dialog ' + 'element handles focus, so `enableDialogElement` must be off for ' + '`focusTrapWithoutSentinels` to have any effect.') : void 0;
103
- if (!passiveModal && preventCloseOnClickOutside === false) {
104
- console.error(invalidOutsideClickMessage);
105
- }
103
+ process.env.NODE_ENV !== "production" ? warning.warning(!(!passiveModal && preventCloseOnClickOutside === false), invalidOutsideClickMessage) : void 0;
106
104
  function isCloseButton(element) {
107
105
  return !onSecondarySubmit && element === secondaryButton.current || element.classList.contains(modalCloseButtonClass);
108
106
  }
@@ -129,7 +127,15 @@ const Modal = /*#__PURE__*/React.forwardRef(function Modal({
129
127
  target
130
128
  } = evt;
131
129
  evt.stopPropagation();
132
- if (!preventCloseOnClickOutside && target instanceof Node && !wrapFocus.elementOrParentIsFloatingMenu(target, selectorsFloatingMenus) && innerModal.current && !innerModal.current.contains(target)) {
130
+ const shouldCloseOnOutsideClick =
131
+ // Passive modals can close on clicks outside the modal when
132
+ // preventCloseOnClickOutside is undefined or explicitly set to false.
133
+ passiveModal && !preventCloseOnClickOutside ||
134
+ // Non-passive modals have to explicitly opt-in for close on outside
135
+ // behavior by explicitly setting preventCloseOnClickOutside to false,
136
+ // rather than just leaving it undefined.
137
+ !passiveModal && preventCloseOnClickOutside === false;
138
+ if (shouldCloseOnOutsideClick && target instanceof Node && !wrapFocus.elementOrParentIsFloatingMenu(target, selectorsFloatingMenus) && innerModal.current && !innerModal.current.contains(target)) {
133
139
  onRequestClose(evt);
134
140
  }
135
141
  }
@@ -175,11 +175,16 @@ const NumberInput = /*#__PURE__*/React.forwardRef(function NumberInput(props, fo
175
175
  [`${prefix}--number__invalid`]: normalizedProps.invalid || normalizedProps.warn,
176
176
  [`${prefix}--number__invalid--warning`]: normalizedProps.warn
177
177
  });
178
- if (controlledValue !== prevControlledValue && !(isNaN(Number(controlledValue)) === isNaN(Number(prevControlledValue)))) {
179
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
180
- setValue(controlledValue);
181
- setPrevControlledValue(controlledValue);
182
- }
178
+ React.useEffect(() => {
179
+ if (type === 'number' && controlledValue !== undefined) {
180
+ if (allowEmpty && controlledValue === '') {
181
+ setValue('');
182
+ } else {
183
+ setValue(controlledValue);
184
+ }
185
+ setPrevControlledValue(controlledValue);
186
+ }
187
+ }, [controlledValue, type, allowEmpty]);
183
188
  let ariaDescribedBy = undefined;
184
189
  if (normalizedProps.invalid) {
185
190
  ariaDescribedBy = normalizedProps.invalidId;
@@ -63,8 +63,12 @@ forwardRef) {
63
63
  // The `Popover` should close whenever it and its children loses focus
64
64
  useEvent.useEvent(popover, 'focusout', event => {
65
65
  const relatedTarget = event.relatedTarget;
66
-
67
- // No relatedTarget, focus moved to nowhere, so close the popover
66
+ if (isTabTip) {
67
+ if (relatedTarget && !popover.current?.contains(relatedTarget)) {
68
+ onRequestClose?.();
69
+ }
70
+ return;
71
+ }
68
72
  if (!relatedTarget) {
69
73
  onRequestClose?.();
70
74
  return;
@@ -7,6 +7,7 @@
7
7
  import React, { type ReactNode } from 'react';
8
8
  import { PolymorphicProps } from '../../types/common';
9
9
  import { SIZES, TYPES } from './Tag';
10
+ import { PopoverAlignment } from '../Popover';
10
11
  export interface DismissibleTagBaseProps {
11
12
  /**
12
13
  * Provide a custom className that is applied to the containing <span>
@@ -20,6 +21,10 @@ export interface DismissibleTagBaseProps {
20
21
  * Specify if the `DismissibleTag` is disabled
21
22
  */
22
23
  disabled?: boolean;
24
+ /**
25
+ * Specify the tooltip alignment for the dismiss button
26
+ */
27
+ dismissTooltipAlignment?: PopoverAlignment;
23
28
  /**
24
29
  * Provide a custom tooltip label for the dismiss button
25
30
  */
@@ -41,6 +41,7 @@ const DismissibleTag = /*#__PURE__*/React.forwardRef(({
41
41
  text,
42
42
  tagTitle,
43
43
  type,
44
+ dismissTooltipAlignment = 'bottom',
44
45
  dismissTooltipLabel = 'Dismiss tag',
45
46
  ...other
46
47
  }, forwardRef) => {
@@ -92,7 +93,7 @@ const DismissibleTag = /*#__PURE__*/React.forwardRef(({
92
93
  className: `${prefix}--tag__decorator`
93
94
  }, normalizedDecorator) : '', /*#__PURE__*/React.createElement(Tooltip.Tooltip, {
94
95
  label: dismissActionLabel,
95
- align: "bottom",
96
+ align: dismissTooltipAlignment,
96
97
  className: tooltipClasses,
97
98
  leaveDelayMs: 0,
98
99
  closeOnActivation: true
@@ -117,6 +118,10 @@ DismissibleTag.propTypes = {
117
118
  * Specify if the `DismissibleTag` is disabled
118
119
  */
119
120
  disabled: PropTypes.bool,
121
+ /**
122
+ * Specify the tooltip alignment for the dismiss button
123
+ */
124
+ dismissTooltipAlignment: PropTypes.oneOf(['top', 'bottom', 'left', 'right', 'top-start', 'top-end', 'bottom-start', 'bottom-end', 'left-end', 'left-start', 'right-end', 'right-start']),
120
125
  /**
121
126
  * Provide a custom tooltip label for the dismiss button
122
127
  */
@@ -129,13 +129,24 @@ function Toggletip({
129
129
  actions.close();
130
130
  }
131
131
  });
132
- useEvent.useWindowEvent('click', ({
133
- target
134
- }) => {
135
- if (open && target instanceof Node && !ref.current?.contains(target)) {
136
- actions.close();
137
- }
138
- });
132
+ React.useEffect(() => {
133
+ if (!ref.current) return;
134
+ const targetDocument = ref.current.ownerDocument || document;
135
+ const eventType = 'PointerEvent' in window ? 'pointerdown' : 'mousedown';
136
+ const handleOutsideClick = event => {
137
+ const node = event.target;
138
+ if (open && node && !ref.current.contains(node)) {
139
+ setOpen(false);
140
+ }
141
+ };
142
+ const options = {
143
+ capture: true
144
+ };
145
+ targetDocument.addEventListener(eventType, handleOutsideClick, options);
146
+ return () => {
147
+ targetDocument.removeEventListener(eventType, handleOutsideClick, options);
148
+ };
149
+ }, [open]);
139
150
  return /*#__PURE__*/React.createElement(ToggletipContext.Provider, {
140
151
  value: value
141
152
  }, /*#__PURE__*/React.createElement(index.Popover, _rollupPluginBabelHelpers.extends({
@@ -11,6 +11,9 @@ export type TreeNodeProps = {
11
11
  /**
12
12
  * **Note:** this is controlled by the parent TreeView component, do not set manually.
13
13
  * The ID of the active node in the tree
14
+ *
15
+ * @deprecated The `active` prop for `TreeNode` has
16
+ * been deprecated after the introduction of context. It will be removed in the next major release.
14
17
  */
15
18
  active?: string | number;
16
19
  /**
@@ -29,6 +32,9 @@ export type TreeNodeProps = {
29
32
  /**
30
33
  * **Note:** this is controlled by the parent TreeView component, do not set manually.
31
34
  * TreeNode depth to determine spacing
35
+ *
36
+ * @deprecated The `depth` prop for `TreeNode` has
37
+ * been deprecated after the introduction of context. It will be removed in the next major release.
32
38
  */
33
39
  depth?: number;
34
40
  /**
@@ -49,6 +55,9 @@ export type TreeNodeProps = {
49
55
  label: React.ReactNode;
50
56
  /**
51
57
  * Callback function for when the node receives or loses focus
58
+ *
59
+ * @deprecated The `onNodeFocusEvent` prop for `TreeNode` has
60
+ * been deprecated after the introduction of context. It will be removed in the next major release.
52
61
  */
53
62
  onNodeFocusEvent?: (event: React.FocusEvent<HTMLElement>) => void;
54
63
  /**
@@ -61,6 +70,9 @@ export type TreeNodeProps = {
61
70
  onToggle?: UncontrolledOnToggle | ControlledOnToggle;
62
71
  /**
63
72
  * Callback function for when any node in the tree is selected
73
+ *
74
+ * @deprecated The `onTreeSelect` prop for `TreeNode` has
75
+ * been deprecated after the introduction of context. It will be removed in the next major release.
64
76
  */
65
77
  onTreeSelect?: (event: React.MouseEvent | React.KeyboardEvent, node: Pick<TreeNodeProps, 'id' | 'label' | 'value'>) => void;
66
78
  /**
@@ -70,6 +82,8 @@ export type TreeNodeProps = {
70
82
  /**
71
83
  * **Note:** this is controlled by the parent TreeView component, do not set manually.
72
84
  * Array containing all selected node IDs in the tree
85
+ * @deprecated The `selected` prop for `TreeNode` has
86
+ * been deprecated after the introduction of context. It will be removed in the next major release.
73
87
  */
74
88
  selected?: Array<string | number>;
75
89
  /**
@@ -97,6 +111,9 @@ declare const TreeNode: React.ForwardRefExoticComponent<{
97
111
  /**
98
112
  * **Note:** this is controlled by the parent TreeView component, do not set manually.
99
113
  * The ID of the active node in the tree
114
+ *
115
+ * @deprecated The `active` prop for `TreeNode` has
116
+ * been deprecated after the introduction of context. It will be removed in the next major release.
100
117
  */
101
118
  active?: string | number;
102
119
  /**
@@ -115,6 +132,9 @@ declare const TreeNode: React.ForwardRefExoticComponent<{
115
132
  /**
116
133
  * **Note:** this is controlled by the parent TreeView component, do not set manually.
117
134
  * TreeNode depth to determine spacing
135
+ *
136
+ * @deprecated The `depth` prop for `TreeNode` has
137
+ * been deprecated after the introduction of context. It will be removed in the next major release.
118
138
  */
119
139
  depth?: number;
120
140
  /**
@@ -135,6 +155,9 @@ declare const TreeNode: React.ForwardRefExoticComponent<{
135
155
  label: React.ReactNode;
136
156
  /**
137
157
  * Callback function for when the node receives or loses focus
158
+ *
159
+ * @deprecated The `onNodeFocusEvent` prop for `TreeNode` has
160
+ * been deprecated after the introduction of context. It will be removed in the next major release.
138
161
  */
139
162
  onNodeFocusEvent?: (event: React.FocusEvent<HTMLElement>) => void;
140
163
  /**
@@ -147,6 +170,9 @@ declare const TreeNode: React.ForwardRefExoticComponent<{
147
170
  onToggle?: UncontrolledOnToggle | ControlledOnToggle;
148
171
  /**
149
172
  * Callback function for when any node in the tree is selected
173
+ *
174
+ * @deprecated The `onTreeSelect` prop for `TreeNode` has
175
+ * been deprecated after the introduction of context. It will be removed in the next major release.
150
176
  */
151
177
  onTreeSelect?: (event: React.MouseEvent | React.KeyboardEvent, node: Pick<TreeNodeProps, "id" | "label" | "value">) => void;
152
178
  /**
@@ -156,6 +182,8 @@ declare const TreeNode: React.ForwardRefExoticComponent<{
156
182
  /**
157
183
  * **Note:** this is controlled by the parent TreeView component, do not set manually.
158
184
  * Array containing all selected node IDs in the tree
185
+ * @deprecated The `selected` prop for `TreeNode` has
186
+ * been deprecated after the introduction of context. It will be removed in the next major release.
159
187
  */
160
188
  selected?: Array<string | number>;
161
189
  /**
@@ -16,6 +16,7 @@ var PropTypes = require('prop-types');
16
16
  var React = require('react');
17
17
  var keys = require('../../internal/keyboard/keys.js');
18
18
  var match = require('../../internal/keyboard/match.js');
19
+ var deprecate = require('../../prop-types/deprecate.js');
19
20
  var useControllableState = require('../../internal/useControllableState.js');
20
21
  var usePrefix = require('../../internal/usePrefix.js');
21
22
  var useId = require('../../internal/useId.js');
@@ -417,7 +418,7 @@ TreeNode.propTypes = {
417
418
  * **Note:** this is controlled by the parent TreeView component, do not set manually.
418
419
  * The ID of the active node in the tree
419
420
  */
420
- active: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
421
+ active: deprecate.deprecate(PropTypes.oneOfType([PropTypes.string, PropTypes.number]), 'The `active` prop for `TreeNode` is no longer needed and has ' + 'been deprecated. It will be removed in the next major release.'),
421
422
  /**
422
423
  * Specify the children of the TreeNode
423
424
  */
@@ -435,7 +436,7 @@ TreeNode.propTypes = {
435
436
  * **Note:** this is controlled by the parent TreeView component, do not set manually.
436
437
  * TreeNode depth to determine spacing
437
438
  */
438
- depth: PropTypes.number,
439
+ depth: deprecate.deprecate(PropTypes.number, 'The `depth` prop for `TreeNode` is no longer needed and has ' + 'been deprecated. It will be removed in the next major release.'),
439
440
  /**
440
441
  * Specify if the TreeNode is disabled
441
442
  */
@@ -455,7 +456,7 @@ TreeNode.propTypes = {
455
456
  /**
456
457
  * Callback function for when the node receives or loses focus
457
458
  */
458
- onNodeFocusEvent: PropTypes.func,
459
+ onNodeFocusEvent: deprecate.deprecate(PropTypes.func, 'The `onNodeFocusEvent` prop for `TreeNode` is no longer needed and has ' + 'been deprecated. It will be removed in the next major release.'),
459
460
  /**
460
461
  * Callback function for when the node is selected
461
462
  */
@@ -467,7 +468,7 @@ TreeNode.propTypes = {
467
468
  /**
468
469
  * Callback function for when any node in the tree is selected
469
470
  */
470
- onTreeSelect: PropTypes.func,
471
+ onTreeSelect: deprecate.deprecate(PropTypes.func, 'The `onTreeSelect` prop for `TreeNode` is no longer needed and has ' + 'been deprecated. It will be removed in the next major release.'),
471
472
  /**
472
473
  * A component used to render an icon.
473
474
  */
@@ -478,7 +479,7 @@ TreeNode.propTypes = {
478
479
  * Array containing all selected node IDs in the tree
479
480
  */
480
481
  // @ts-ignore
481
- selected: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.number])),
482
+ selected: deprecate.deprecate(PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.number])), 'The `selected` prop for `TreeNode` is no longer needed and has ' + 'been deprecated. It will be removed in the next major release.'),
482
483
  /**
483
484
  * Specify the value of the TreeNode
484
485
  */
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@carbon/react",
3
3
  "description": "React components for the Carbon Design System",
4
- "version": "1.89.0",
4
+ "version": "1.90.0-rc.0",
5
5
  "license": "Apache-2.0",
6
6
  "main": "lib/index.js",
7
7
  "types": "lib/index.d.ts",
@@ -53,9 +53,9 @@
53
53
  "dependencies": {
54
54
  "@babel/runtime": "^7.27.3",
55
55
  "@carbon/feature-flags": "^0.30.0",
56
- "@carbon/icons-react": "^11.65.0",
57
- "@carbon/layout": "^11.39.0",
58
- "@carbon/styles": "^1.88.0",
56
+ "@carbon/icons-react": "^11.66.0-rc.0",
57
+ "@carbon/layout": "^11.40.0-rc.0",
58
+ "@carbon/styles": "^1.89.0-rc.0",
59
59
  "@carbon/utilities": "^0.8.0",
60
60
  "@floating-ui/react": "^0.27.4",
61
61
  "@ibm/telemetry-js": "^1.5.0",
@@ -79,8 +79,8 @@
79
79
  "@babel/preset-env": "^7.27.2",
80
80
  "@babel/preset-react": "^7.27.1",
81
81
  "@babel/preset-typescript": "^7.27.1",
82
- "@carbon/test-utils": "^10.37.0",
83
- "@carbon/themes": "^11.58.0",
82
+ "@carbon/test-utils": "^10.38.0-rc.0",
83
+ "@carbon/themes": "^11.59.0-rc.0",
84
84
  "@figma/code-connect": "^1.3.2",
85
85
  "@rollup/plugin-babel": "^6.0.0",
86
86
  "@rollup/plugin-commonjs": "^28.0.3",
@@ -106,8 +106,8 @@
106
106
  "fs-extra": "^11.0.0",
107
107
  "html-webpack-plugin": "^5.5.0",
108
108
  "mini-css-extract-plugin": "^2.4.5",
109
- "postcss": "^8.4.5",
110
- "postcss-loader": "^8.0.0",
109
+ "postcss": "^8.5.6",
110
+ "postcss-loader": "^8.1.1",
111
111
  "process": "^0.11.10",
112
112
  "prop-types": "^15.8.1",
113
113
  "react": "^19.0.0",
@@ -138,5 +138,5 @@
138
138
  "**/*.scss",
139
139
  "**/*.css"
140
140
  ],
141
- "gitHead": "d66cc6afbdf6802cf8b14042f20f7c350beef90b"
141
+ "gitHead": "2c49b938cb0508beea4a04512813118549d90898"
142
142
  }
package/telemetry.yml CHANGED
@@ -328,6 +328,7 @@ collect:
328
328
  - focusAfterCloseRef
329
329
  - modal
330
330
  # DismissibleTag
331
+ - dismissTooltipAlignment
331
332
  - dismissTooltipLabel
332
333
  - tagTitle
333
334
  # ErrorBoundary
@@ -899,6 +900,19 @@ collect:
899
900
  # ContentSwitcher - selectionMode
900
901
  - automatic
901
902
  - manual
903
+ # DismissibleTag - dismissTooltipAlignment
904
+ - bottom
905
+ - bottom-end
906
+ - bottom-start
907
+ - left
908
+ - left-end
909
+ - left-start
910
+ - right
911
+ - right-end
912
+ - right-start
913
+ - top
914
+ - top-end
915
+ - top-start
902
916
  # FileUploader - filenameStatus
903
917
  - complete
904
918
  - edit