@carbon/react 1.107.1 → 1.108.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 (75) hide show
  1. package/.playwright/INTERNAL_AVT_REPORT_DO_NOT_USE.json +960 -960
  2. package/es/components/Button/Button.d.ts +2 -2
  3. package/es/components/Button/ButtonBase.js +5 -5
  4. package/es/components/ChatButton/ChatButton.d.ts +1 -1
  5. package/es/components/ChatButton/ChatButton.js +1 -1
  6. package/es/components/ComposedModal/ComposedModal.js +10 -5
  7. package/es/components/ComposedModal/ModalFooter.d.ts +5 -0
  8. package/es/components/ComposedModal/ModalFooter.js +3 -1
  9. package/es/components/Dialog/Dialog.d.ts +5 -0
  10. package/es/components/Dialog/Dialog.js +3 -1
  11. package/es/components/ErrorBoundary/ErrorBoundaryContext.d.ts +1 -1
  12. package/es/components/ErrorBoundary/ErrorBoundaryContext.js +1 -1
  13. package/es/components/FileUploader/FileUploader.d.ts +5 -0
  14. package/es/components/FileUploader/FileUploader.js +14 -6
  15. package/es/components/FileUploader/FileUploaderItem.d.ts +5 -1
  16. package/es/components/FileUploader/FileUploaderItem.js +4 -2
  17. package/es/components/FileUploader/Filename.d.ts +5 -1
  18. package/es/components/FileUploader/Filename.js +2 -1
  19. package/es/components/Menu/MenuItem.js +16 -7
  20. package/es/components/Modal/Modal.d.ts +5 -0
  21. package/es/components/Modal/Modal.js +26 -13
  22. package/es/components/Modal/isTopmostVisibleModal.d.ts +7 -0
  23. package/es/components/Modal/isTopmostVisibleModal.js +21 -0
  24. package/es/components/MultiSelect/FilterableMultiSelect.js +9 -8
  25. package/es/components/MultiSelect/MultiSelect.js +9 -8
  26. package/es/components/MultiSelect/tools/isSelectAllItem.d.ts +9 -0
  27. package/es/components/MultiSelect/tools/isSelectAllItem.js +17 -0
  28. package/es/components/MultiSelect/tools/sorting.js +1 -1
  29. package/es/components/OverflowMenuItem/OverflowMenuItem.js +3 -2
  30. package/es/components/PageHeader/PageHeader.d.ts +4 -0
  31. package/es/components/PageHeader/PageHeader.js +18 -0
  32. package/es/components/PageHeader/index.d.ts +4 -0
  33. package/es/components/Tabs/Tabs.d.ts +5 -1
  34. package/es/components/Tabs/Tabs.js +2 -1
  35. package/es/components/UIShell/SwitcherDivider.d.ts +2 -2
  36. package/es/components/UIShell/SwitcherDivider.js +2 -2
  37. package/es/internal/warning.d.ts +1 -1
  38. package/lib/components/Button/Button.d.ts +2 -2
  39. package/lib/components/Button/ButtonBase.js +5 -5
  40. package/lib/components/ChatButton/ChatButton.d.ts +1 -1
  41. package/lib/components/ChatButton/ChatButton.js +1 -1
  42. package/lib/components/ComposedModal/ComposedModal.js +10 -5
  43. package/lib/components/ComposedModal/ModalFooter.d.ts +5 -0
  44. package/lib/components/ComposedModal/ModalFooter.js +3 -1
  45. package/lib/components/Dialog/Dialog.d.ts +5 -0
  46. package/lib/components/Dialog/Dialog.js +3 -1
  47. package/lib/components/ErrorBoundary/ErrorBoundaryContext.d.ts +1 -1
  48. package/lib/components/ErrorBoundary/ErrorBoundaryContext.js +1 -1
  49. package/lib/components/FileUploader/FileUploader.d.ts +5 -0
  50. package/lib/components/FileUploader/FileUploader.js +14 -6
  51. package/lib/components/FileUploader/FileUploaderItem.d.ts +5 -1
  52. package/lib/components/FileUploader/FileUploaderItem.js +4 -2
  53. package/lib/components/FileUploader/Filename.d.ts +5 -1
  54. package/lib/components/FileUploader/Filename.js +2 -1
  55. package/lib/components/Menu/MenuItem.js +15 -6
  56. package/lib/components/Modal/Modal.d.ts +5 -0
  57. package/lib/components/Modal/Modal.js +26 -13
  58. package/lib/components/Modal/isTopmostVisibleModal.d.ts +7 -0
  59. package/lib/components/Modal/isTopmostVisibleModal.js +21 -0
  60. package/lib/components/MultiSelect/FilterableMultiSelect.js +9 -8
  61. package/lib/components/MultiSelect/MultiSelect.js +9 -8
  62. package/lib/components/MultiSelect/tools/isSelectAllItem.d.ts +9 -0
  63. package/lib/components/MultiSelect/tools/isSelectAllItem.js +17 -0
  64. package/lib/components/MultiSelect/tools/sorting.js +3 -3
  65. package/lib/components/OverflowMenuItem/OverflowMenuItem.js +3 -2
  66. package/lib/components/PageHeader/PageHeader.d.ts +4 -0
  67. package/lib/components/PageHeader/PageHeader.js +18 -0
  68. package/lib/components/PageHeader/index.d.ts +4 -0
  69. package/lib/components/Tabs/Tabs.d.ts +5 -1
  70. package/lib/components/Tabs/Tabs.js +2 -1
  71. package/lib/components/UIShell/SwitcherDivider.d.ts +2 -2
  72. package/lib/components/UIShell/SwitcherDivider.js +2 -2
  73. package/lib/internal/warning.d.ts +1 -1
  74. package/lib/internal/warning.js +1 -1
  75. package/package.json +10 -10
@@ -158,9 +158,14 @@ const FileUploader = (0, react.forwardRef)(({ accept, buttonKind, buttonLabel, c
158
158
  });
159
159
  } else setLegacyFileNames([]);
160
160
  },
161
- ...enhancedFileUploaderEnabled && { getCurrentFiles() {
162
- return [...fileItems];
163
- } }
161
+ ...enhancedFileUploaderEnabled && {
162
+ getCurrentFiles() {
163
+ return [...fileItems];
164
+ },
165
+ setCurrentFiles: (files) => {
166
+ setFileItems(files);
167
+ }
168
+ }
164
169
  }), [
165
170
  enhancedFileUploaderEnabled,
166
171
  fileItems,
@@ -171,12 +176,14 @@ const FileUploader = (0, react.forwardRef)(({ accept, buttonKind, buttonLabel, c
171
176
  [className]: className
172
177
  });
173
178
  const getHelperLabelClasses = (baseClass) => (0, classnames.default)(baseClass, { [`${prefix}--label-description--disabled`]: disabled });
174
- const selectedFileClasses = (0, classnames.default)(`${prefix}--file__selected-file`, {
179
+ const getSelectedFileClasses = (file) => (0, classnames.default)(`${prefix}--file__selected-file`, {
175
180
  [`${prefix}--file__selected-file--md`]: size === "field" || size === "md",
176
- [`${prefix}--file__selected-file--sm`]: size === "small" || size === "sm"
181
+ [`${prefix}--file__selected-file--sm`]: size === "small" || size === "sm",
182
+ [`${prefix}--file__selected-file--disabled`]: file.disabled
177
183
  });
178
184
  const displayFiles = enhancedFileUploaderEnabled ? fileItems.map((item, index) => ({
179
185
  name: item.name,
186
+ disabled: item.disabled,
180
187
  key: item.uuid,
181
188
  index
182
189
  })) : legacyFileNames.map((name, index) => ({
@@ -215,7 +222,7 @@ const FileUploader = (0, react.forwardRef)(({ accept, buttonKind, buttonLabel, c
215
222
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
216
223
  className: `${prefix}--file-container`,
217
224
  children: displayFiles.length === 0 ? null : displayFiles.map((file) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
218
- className: selectedFileClasses,
225
+ className: getSelectedFileClasses(file),
219
226
  ref: (node) => {
220
227
  nodes[file.index] = node;
221
228
  },
@@ -229,6 +236,7 @@ const FileUploader = (0, react.forwardRef)(({ accept, buttonKind, buttonLabel, c
229
236
  className: `${prefix}--file__state-container`,
230
237
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Filename.default, {
231
238
  name: file.name,
239
+ disabled: file.disabled,
232
240
  iconDescription,
233
241
  status: filenameStatus,
234
242
  onKeyDown: (evt) => {
@@ -7,6 +7,10 @@
7
7
  import PropTypes from 'prop-types';
8
8
  import React, { type HTMLAttributes } from 'react';
9
9
  export interface FileUploaderItemProps extends HTMLAttributes<HTMLSpanElement> {
10
+ /**
11
+ * Specify whether file uploader item is disabled
12
+ */
13
+ disabled?: boolean;
10
14
  /**
11
15
  * Error message body for an invalid file upload
12
16
  */
@@ -52,7 +56,7 @@ export interface FileUploaderItemProps extends HTMLAttributes<HTMLSpanElement> {
52
56
  */
53
57
  uuid?: string;
54
58
  }
55
- declare function FileUploaderItem({ uuid, name, status, iconDescription, onDelete, invalid, errorSubject, errorBody, size, className, ...other }: FileUploaderItemProps): import("react/jsx-runtime").JSX.Element;
59
+ declare function FileUploaderItem({ uuid, name, status, iconDescription, onDelete, invalid, errorSubject, errorBody, size, className, disabled, ...other }: FileUploaderItemProps): import("react/jsx-runtime").JSX.Element;
56
60
  declare namespace FileUploaderItem {
57
61
  var propTypes: {
58
62
  /**
@@ -29,7 +29,7 @@ let react_jsx_runtime = require("react/jsx-runtime");
29
29
  * This source code is licensed under the Apache-2.0 license found in the
30
30
  * LICENSE file in the root directory of this source tree.
31
31
  */
32
- function FileUploaderItem({ uuid, name, status = "uploading", iconDescription, onDelete = require_noopFn.noopFn, invalid, errorSubject, errorBody, size, className, ...other }) {
32
+ function FileUploaderItem({ uuid, name, status = "uploading", iconDescription, onDelete = require_noopFn.noopFn, invalid, errorSubject, errorBody, size, className, disabled, ...other }) {
33
33
  const textRef = (0, react.useRef)(null);
34
34
  const [isEllipsisApplied, setIsEllipsisApplied] = (0, react.useState)(false);
35
35
  const prefix = require_usePrefix.usePrefix();
@@ -38,7 +38,8 @@ function FileUploaderItem({ uuid, name, status = "uploading", iconDescription, o
38
38
  const classes = (0, classnames.default)(`${prefix}--file__selected-file`, className, {
39
39
  [`${prefix}--file__selected-file--invalid`]: invalid,
40
40
  [`${prefix}--file__selected-file--md`]: size === "md",
41
- [`${prefix}--file__selected-file--sm`]: size === "sm"
41
+ [`${prefix}--file__selected-file--sm`]: size === "sm",
42
+ [`${prefix}--file__selected-file--disabled`]: disabled
42
43
  });
43
44
  const isInvalid = invalid ? `${prefix}--file-filename-container-wrap-invalid` : `${prefix}--file-filename-container-wrap`;
44
45
  const filterSpaceName = (name) => {
@@ -93,6 +94,7 @@ function FileUploaderItem({ uuid, name, status = "uploading", iconDescription, o
93
94
  className: `${prefix}--file__state-container`,
94
95
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Filename.default, {
95
96
  name,
97
+ disabled,
96
98
  iconDescription,
97
99
  status,
98
100
  invalid,
@@ -17,6 +17,10 @@ export interface FilenameProps extends Omit<HTMLAttributes<HTMLElement> & SVGAtt
17
17
  * Provide a description of the SVG icon to denote file upload status
18
18
  */
19
19
  iconDescription?: string;
20
+ /**
21
+ * Specify whether the file uploader item is disabled
22
+ */
23
+ disabled?: boolean;
20
24
  /**
21
25
  * Specify if the file is invalid
22
26
  */
@@ -34,7 +38,7 @@ export interface FilenameProps extends Omit<HTMLAttributes<HTMLElement> & SVGAtt
34
38
  */
35
39
  tabIndex?: number;
36
40
  }
37
- declare function Filename({ iconDescription, status, invalid, name, tabIndex, ['aria-describedby']: ariaDescribedBy, ...rest }: FilenameProps): import("react/jsx-runtime").JSX.Element | null;
41
+ declare function Filename({ iconDescription, status, invalid, disabled, name, tabIndex, ['aria-describedby']: ariaDescribedBy, ...rest }: FilenameProps): import("react/jsx-runtime").JSX.Element | null;
38
42
  declare namespace Filename {
39
43
  var propTypes: {
40
44
  /**
@@ -21,7 +21,7 @@ let _carbon_icons_react = require("@carbon/icons-react");
21
21
  * This source code is licensed under the Apache-2.0 license found in the
22
22
  * LICENSE file in the root directory of this source tree.
23
23
  */
24
- function Filename({ iconDescription = "Uploading file", status = "uploading", invalid, name, tabIndex = 0, ["aria-describedby"]: ariaDescribedBy, ...rest }) {
24
+ function Filename({ iconDescription = "Uploading file", status = "uploading", invalid, disabled, name, tabIndex = 0, ["aria-describedby"]: ariaDescribedBy, ...rest }) {
25
25
  const prefix = require_usePrefix.usePrefix();
26
26
  switch (status) {
27
27
  case "uploading": return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_index.default, {
@@ -31,6 +31,7 @@ function Filename({ iconDescription = "Uploading file", status = "uploading", in
31
31
  className: `${prefix}--file-loading`
32
32
  });
33
33
  case "edit": return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [invalid && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_carbon_icons_react.WarningFilled, { className: `${prefix}--file-invalid` }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
34
+ disabled,
34
35
  "aria-label": `${iconDescription} - ${name}`,
35
36
  className: `${prefix}--file-close`,
36
37
  type: "button",
@@ -33,18 +33,26 @@ let _floating_ui_react = require("@floating-ui/react");
33
33
  * This source code is licensed under the Apache-2.0 license found in the
34
34
  * LICENSE file in the root directory of this source tree.
35
35
  */
36
- const MenuItem = (0, react.forwardRef)(function MenuItem({ children, className, dangerDescription = "danger", disabled, kind = "default", label, onClick, renderIcon: IconElement, shortcut, ...rest }, forwardRef) {
36
+ const MenuItem = (0, react.forwardRef)(function MenuItem({ children, className, dangerDescription = "", disabled, kind = "default", label, onClick, renderIcon: IconElement, shortcut, ...rest }, forwardRef) {
37
37
  const [submenuOpen, setSubmenuOpen] = (0, react.useState)(false);
38
38
  const [rtl, setRtl] = (0, react.useState)(false);
39
39
  const { refs, floatingStyles, context: floatingContext } = (0, _floating_ui_react.useFloating)({
40
40
  open: submenuOpen,
41
- onOpenChange: setSubmenuOpen,
41
+ onOpenChange: (open, event) => {
42
+ if (open) setSubmenuOpen(true);
43
+ else {
44
+ const relatedTarget = event && "relatedTarget" in event ? event.relatedTarget : null;
45
+ if (relatedTarget instanceof Node && menuItem.current?.contains(relatedTarget)) return;
46
+ setSubmenuOpen(false);
47
+ if (!(relatedTarget instanceof HTMLElement && relatedTarget.closest("[role=\"menuitem\"]")?.querySelector("[role=\"menu\"]"))) menuItem.current?.focus();
48
+ }
49
+ },
42
50
  placement: rtl ? "left-start" : "right-start",
43
51
  whileElementsMounted: _floating_ui_react.autoUpdate,
44
- middleware: [(0, _floating_ui_react.offset)({
45
- mainAxis: -6,
52
+ middleware: [(0, _floating_ui_react.flip)(), (0, _floating_ui_react.offset)(({ placement }) => ({
53
+ mainAxis: placement.startsWith("left") ? 10 : -6,
46
54
  crossAxis: -6
47
- })],
55
+ }))],
48
56
  strategy: "fixed"
49
57
  });
50
58
  const { getReferenceProps, getFloatingProps } = (0, _floating_ui_react.useInteractions)([(0, _floating_ui_react.useHover)(floatingContext, {
@@ -63,6 +71,7 @@ const MenuItem = (0, react.forwardRef)(function MenuItem({ children, className,
63
71
  const hasChildren = react.default.Children.toArray(children).length > 0;
64
72
  const isDisabled = disabled && !hasChildren;
65
73
  const isDanger = kind === "danger" && !hasChildren;
74
+ const hasDangerDescription = isDanger && Boolean(dangerDescription);
66
75
  function registerItem() {
67
76
  context.dispatch({
68
77
  type: "registerItem",
@@ -165,7 +174,7 @@ const MenuItem = (0, react.forwardRef)(function MenuItem({ children, className,
165
174
  className: `${prefix}--menu-item__label`,
166
175
  children: label
167
176
  }),
168
- isDanger && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
177
+ hasDangerDescription && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
169
178
  id: assistiveId,
170
179
  className: `${prefix}--visually-hidden`,
171
180
  children: dangerDescription
@@ -38,6 +38,11 @@ export interface ModalProps extends HTMLAttributes<HTMLDivElement> {
38
38
  * Specify whether the Modal is for dangerous actions
39
39
  */
40
40
  danger?: boolean;
41
+ /**
42
+ * Specify the message read by screen readers for the danger primary button.
43
+ * Defaults to an empty string; provide localized text to opt in.
44
+ */
45
+ dangerDescription?: string;
41
46
  /**
42
47
  * **Experimental**: Provide a decorator component to be rendered inside the `Modal` component
43
48
  */
@@ -30,6 +30,7 @@ const require_toggleClass = require("../../tools/toggleClass.js");
30
30
  const require_requiredIfGivenPropIsTruthy = require("../../prop-types/requiredIfGivenPropIsTruthy.js");
31
31
  const require_wrapFocus = require("../../internal/wrapFocus.js");
32
32
  const require_Dialog = require("../Dialog/Dialog.js");
33
+ const require_isTopmostVisibleModal = require("./isTopmostVisibleModal.js");
33
34
  const require_usePreviousValue = require("../../internal/usePreviousValue.js");
34
35
  const require_ModalPresence = require("./ModalPresence.js");
35
36
  let classnames = require("classnames");
@@ -76,12 +77,13 @@ const Modal = react.default.forwardRef(function Modal({ open, ...props }, ref) {
76
77
  ...props
77
78
  });
78
79
  });
79
- const ModalDialog = react.default.forwardRef(function ModalDialog({ "aria-label": ariaLabelProp, children, className, decorator, modalHeading = "", modalLabel = "", modalAriaLabel, passiveModal = false, secondaryButtonText, primaryButtonText, open: externalOpen, onRequestClose = require_noopFn.noopFn, onRequestSubmit = require_noopFn.noopFn, onSecondarySubmit, primaryButtonDisabled = false, danger, alert, secondaryButtons, selectorPrimaryFocus = "[data-modal-primary-focus]", selectorsFloatingMenus, shouldSubmitOnEnter, size, hasScrollingContent = false, closeButtonLabel = "Close", preventCloseOnClickOutside, isFullWidth, launcherButtonRef, loadingStatus = "inactive", loadingDescription, loadingIconDescription, onLoadingSuccess = require_noopFn.noopFn, slug, ...rest }, ref) {
80
+ const ModalDialog = react.default.forwardRef(function ModalDialog({ "aria-label": ariaLabelProp, children, className, decorator, modalHeading = "", modalLabel = "", modalAriaLabel, passiveModal = false, secondaryButtonText, primaryButtonText, open: externalOpen, onRequestClose = require_noopFn.noopFn, onRequestSubmit = require_noopFn.noopFn, onSecondarySubmit, primaryButtonDisabled = false, danger, dangerDescription = "", alert, secondaryButtons, selectorPrimaryFocus = "[data-modal-primary-focus]", selectorsFloatingMenus, shouldSubmitOnEnter, size, hasScrollingContent = false, closeButtonLabel = "Close", preventCloseOnClickOutside, isFullWidth, launcherButtonRef, loadingStatus = "inactive", loadingDescription, loadingIconDescription, onLoadingSuccess = require_noopFn.noopFn, slug, ...rest }, ref) {
80
81
  const prefix = require_usePrefix.usePrefix();
81
82
  const button = (0, react.useRef)(null);
82
83
  const secondaryButton = (0, react.useRef)(null);
83
84
  const contentRef = (0, react.useRef)(null);
84
85
  const innerModal = (0, react.useRef)(null);
86
+ const modalRef = (0, react.useRef)(null);
85
87
  const startTrap = (0, react.useRef)(null);
86
88
  const endTrap = (0, react.useRef)(null);
87
89
  const wrapFocusTimeout = (0, react.useRef)(null);
@@ -93,7 +95,11 @@ const ModalDialog = react.default.forwardRef(function ModalDialog({ "aria-label"
93
95
  const primaryButtonClass = (0, classnames.default)({ [`${prefix}--btn--loading`]: loadingStatus !== "inactive" });
94
96
  const loadingActive = loadingStatus !== "inactive";
95
97
  const presenceContext = (0, react.useContext)(require_ModalPresence.ModalPresenceContext);
96
- const mergedRefs = require_useMergedRefs.useMergedRefs([ref, presenceContext?.presenceRef]);
98
+ const mergedRefs = require_useMergedRefs.useMergedRefs([
99
+ modalRef,
100
+ ref,
101
+ presenceContext?.presenceRef
102
+ ]);
97
103
  const enablePresence = require_index.useFeatureFlag("enable-presence") || presenceContext?.autoEnablePresence;
98
104
  const open = externalOpen || enablePresence;
99
105
  const prevOpen = require_usePreviousValue.usePreviousValue(open);
@@ -107,14 +113,19 @@ const ModalDialog = react.default.forwardRef(function ModalDialog({ "aria-label"
107
113
  }
108
114
  function handleKeyDown(evt) {
109
115
  const { target } = evt;
110
- evt.stopPropagation();
111
116
  if (open && target instanceof HTMLElement) {
112
- if (require_match.match(evt, require_keys.Enter) && shouldSubmitOnEnter && !isCloseButton(target) && document.activeElement !== button.current) onRequestSubmit(evt);
113
- if (focusTrapWithoutSentinels && !enableDialogElement && require_match.match(evt, require_keys.Tab) && innerModal.current) require_wrapFocus.wrapFocusWithoutSentinels({
114
- containerNode: innerModal.current,
115
- currentActiveNode: target,
116
- event: evt
117
- });
117
+ if (require_match.match(evt, require_keys.Enter) && shouldSubmitOnEnter && !isCloseButton(target) && document.activeElement !== button.current) {
118
+ evt.stopPropagation();
119
+ onRequestSubmit(evt);
120
+ }
121
+ if (focusTrapWithoutSentinels && !enableDialogElement && require_match.match(evt, require_keys.Tab) && innerModal.current) {
122
+ evt.stopPropagation();
123
+ require_wrapFocus.wrapFocusWithoutSentinels({
124
+ containerNode: innerModal.current,
125
+ currentActiveNode: target,
126
+ event: evt
127
+ });
128
+ }
118
129
  }
119
130
  }
120
131
  function handleOnClick(evt) {
@@ -191,15 +202,14 @@ const ModalDialog = react.default.forwardRef(function ModalDialog({ "aria-label"
191
202
  (0, react.useEffect)(() => {
192
203
  if (!open) return;
193
204
  const handleEscapeKey = (event) => {
194
- if (require_match.match(event, require_keys.Escape)) {
205
+ if (require_match.match(event, require_keys.Escape) && require_isTopmostVisibleModal.isTopmostVisibleModal(modalRef.current, prefix)) {
195
206
  event.preventDefault();
196
- event.stopPropagation();
197
207
  onRequestClose(event);
198
208
  }
199
209
  };
200
- document.addEventListener("keydown", handleEscapeKey, true);
210
+ document.addEventListener("keydown", handleEscapeKey);
201
211
  return () => {
202
- document.removeEventListener("keydown", handleEscapeKey, true);
212
+ document.removeEventListener("keydown", handleEscapeKey);
203
213
  };
204
214
  }, [open]);
205
215
  (0, react.useEffect)(() => {
@@ -356,6 +366,7 @@ const ModalDialog = react.default.forwardRef(function ModalDialog({ "aria-label"
356
366
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_index$2.default, {
357
367
  className: primaryButtonClass,
358
368
  kind: danger ? "danger" : "primary",
369
+ dangerDescription,
359
370
  disabled: loadingActive || primaryButtonDisabled,
360
371
  onClick: onRequestSubmit,
361
372
  ref: button,
@@ -432,6 +443,7 @@ const ModalDialog = react.default.forwardRef(function ModalDialog({ "aria-label"
432
443
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_index$2.default, {
433
444
  className: primaryButtonClass,
434
445
  kind: danger ? "danger" : "primary",
446
+ dangerDescription,
435
447
  disabled: loadingActive || primaryButtonDisabled,
436
448
  onClick: onRequestSubmit,
437
449
  ref: button,
@@ -474,6 +486,7 @@ Modal.propTypes = {
474
486
  className: prop_types.default.string,
475
487
  closeButtonLabel: prop_types.default.string,
476
488
  danger: prop_types.default.bool,
489
+ dangerDescription: prop_types.default.string,
477
490
  decorator: prop_types.default.node,
478
491
  hasScrollingContent: prop_types.default.bool,
479
492
  id: prop_types.default.string,
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Copyright IBM Corp. 2026
3
+ *
4
+ * This source code is licensed under the Apache-2.0 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ export declare const isTopmostVisibleModal: (node: HTMLElement | null, prefix: string) => boolean;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Copyright IBM Corp. 2016, 2026
3
+ *
4
+ * This source code is licensed under the Apache-2.0 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ //#region src/components/Modal/isTopmostVisibleModal.ts
9
+ /**
10
+ * Copyright IBM Corp. 2026
11
+ *
12
+ * This source code is licensed under the Apache-2.0 license found in the
13
+ * LICENSE file in the root directory of this source tree.
14
+ */
15
+ const isTopmostVisibleModal = (node, prefix) => {
16
+ if (!node) return false;
17
+ const visibleModals = document.querySelectorAll(`.${prefix}--modal.is-visible`);
18
+ return visibleModals.item(visibleModals.length - 1) === node;
19
+ };
20
+ //#endregion
21
+ exports.isTopmostVisibleModal = isTopmostVisibleModal;
@@ -26,6 +26,7 @@ const require_ListBoxTrigger = require("../ListBox/next/ListBoxTrigger.js");
26
26
  const require_mergeRefs = require("../../tools/mergeRefs.js");
27
27
  const require_filter = require("./filter.js");
28
28
  const require_MultiSelectPropTypes = require("./MultiSelectPropTypes.js");
29
+ const require_isSelectAllItem = require("./tools/isSelectAllItem.js");
29
30
  const require_sorting = require("./tools/sorting.js");
30
31
  const require_Selection = require("../../internal/Selection.js");
31
32
  let classnames = require("classnames");
@@ -66,8 +67,8 @@ const FilterableMultiSelect = (0, react.forwardRef)(function FilterableMultiSele
66
67
  itemToString,
67
68
  filterItems
68
69
  ]);
69
- const nonSelectAllItems = (0, react.useMemo)(() => filteredItems.filter((item) => !item.isSelectAll), [filteredItems]);
70
- const selectAll = filteredItems.some((item) => item.isSelectAll);
70
+ const nonSelectAllItems = (0, react.useMemo)(() => filteredItems.filter((item) => !require_isSelectAllItem.isSelectAllItem(item)), [filteredItems]);
71
+ const selectAll = filteredItems.some(require_isSelectAllItem.isSelectAllItem);
71
72
  const { selectedItems: controlledSelectedItems, onItemChange, clearSelection, toggleAll } = require_Selection.useSelection({
72
73
  disabled,
73
74
  initialSelectedItems,
@@ -135,7 +136,7 @@ const FilterableMultiSelect = (0, react.forwardRef)(function FilterableMultiSele
135
136
  setIsOpen(open);
136
137
  }, [open]);
137
138
  const sortedItems = (0, react.useMemo)(() => {
138
- const selectAllItem = items.find((item) => item.isSelectAll);
139
+ const selectAllItem = items.find(require_isSelectAllItem.isSelectAllItem);
139
140
  const selectableRealItems = nonSelectAllItems.filter((item) => !item.disabled);
140
141
  const sortedReal = sortItems(nonSelectAllItems, {
141
142
  selectedItems: {
@@ -271,7 +272,7 @@ const FilterableMultiSelect = (0, react.forwardRef)(function FilterableMultiSele
271
272
  switch (type) {
272
273
  case InputKeyDownEnter:
273
274
  if (sortedItems.length === 0) return changes;
274
- if (changes.selectedItem && changes.selectedItem.disabled !== true) if (changes.selectedItem.isSelectAll) handleSelectAllClick();
275
+ if (changes.selectedItem && changes.selectedItem.disabled !== true) if (require_isSelectAllItem.isSelectAllItem(changes.selectedItem)) handleSelectAllClick();
275
276
  else onItemChange(changes.selectedItem);
276
277
  setHighlightedIndex(changes.selectedItem);
277
278
  return {
@@ -279,7 +280,7 @@ const FilterableMultiSelect = (0, react.forwardRef)(function FilterableMultiSele
279
280
  highlightedIndex: state.highlightedIndex
280
281
  };
281
282
  case ItemClick:
282
- if (changes.selectedItem.isSelectAll) handleSelectAllClick();
283
+ if (require_isSelectAllItem.isSelectAllItem(changes.selectedItem)) handleSelectAllClick();
283
284
  else onItemChange(changes.selectedItem);
284
285
  setHighlightedIndex(changes.selectedItem);
285
286
  return changes;
@@ -377,7 +378,7 @@ const FilterableMultiSelect = (0, react.forwardRef)(function FilterableMultiSele
377
378
  const candidate = slug ?? decorator;
378
379
  const candidateIsAILabel = require_utils.isComponentElement(candidate, require_index.AILabel);
379
380
  const normalizedDecorator = candidateIsAILabel ? (0, react.cloneElement)(candidate, { size: "mini" }) : candidate;
380
- const selectedItemsLength = controlledSelectedItems.filter((item) => !item.isSelectAll).length;
381
+ const selectedItemsLength = controlledSelectedItems.filter((item) => !require_isSelectAllItem.isSelectAllItem(item)).length;
381
382
  const className = (0, classnames.default)(`${prefix}--multi-select`, `${prefix}--combo-box`, `${prefix}--multi-select--filterable`, {
382
383
  [`${prefix}--multi-select--invalid`]: normalizedProps.invalid,
383
384
  [`${prefix}--multi-select--invalid--focused`]: inputFocused && normalizedProps.invalid,
@@ -534,7 +535,7 @@ const FilterableMultiSelect = (0, react.forwardRef)(function FilterableMultiSele
534
535
  children: isOpen ? sortedItems.map((item, index) => {
535
536
  let isChecked;
536
537
  let isIndeterminate = false;
537
- if (item.isSelectAll) {
538
+ if (require_isSelectAllItem.isSelectAllItem(item)) {
538
539
  isChecked = selectAllStatus.checked;
539
540
  isIndeterminate = selectAllStatus.indeterminate;
540
541
  } else isChecked = controlledSelectedItems.filter((selected) => (0, react_fast_compare.default)(selected, item)).length > 0;
@@ -548,7 +549,7 @@ const FilterableMultiSelect = (0, react.forwardRef)(function FilterableMultiSele
548
549
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_index$2.default.MenuItem, {
549
550
  "aria-label": itemText,
550
551
  "aria-checked": isIndeterminate ? "mixed" : isChecked,
551
- isActive: isChecked && !item["isSelectAll"],
552
+ isActive: isChecked && !require_isSelectAllItem.isSelectAllItem(item),
552
553
  isHighlighted: highlightedIndex === index,
553
554
  title: itemText,
554
555
  disabled,
@@ -24,6 +24,7 @@ const require_FormContext = require("../FluidForm/FormContext.js");
24
24
  const require_index$3 = require("../ListBox/index.js");
25
25
  const require_mergeRefs = require("../../tools/mergeRefs.js");
26
26
  const require_MultiSelectPropTypes = require("./MultiSelectPropTypes.js");
27
+ const require_isSelectAllItem = require("./tools/isSelectAllItem.js");
27
28
  const require_sorting = require("./tools/sorting.js");
28
29
  const require_Selection = require("../../internal/Selection.js");
29
30
  let classnames = require("classnames");
@@ -55,7 +56,7 @@ const MultiSelect = react.default.forwardRef(({ autoAlign = false, className: co
55
56
  return true;
56
57
  });
57
58
  }, [items]);
58
- const selectAll = filteredItems.some((item) => item.isSelectAll);
59
+ const selectAll = filteredItems.some(require_isSelectAllItem.isSelectAllItem);
59
60
  const prefix = require_usePrefix.usePrefix();
60
61
  const { isFluid } = (0, react.useContext)(require_FormContext.FormContext);
61
62
  const multiSelectInstanceId = require_useId.useId();
@@ -285,7 +286,7 @@ const MultiSelect = react.default.forwardRef(({ autoAlign = false, className: co
285
286
  const candidate = slug ?? decorator;
286
287
  const normalizedDecorator = require_utils.isComponentElement(candidate, require_index$1.AILabel) ? (0, react.cloneElement)(candidate, { size: "mini" }) : candidate;
287
288
  const itemsSelectedText = selectedItems.length > 0 && selectedItems.map((item) => item?.text);
288
- const selectedItemsLength = selectAll ? selectedItems.filter((item) => !item.isSelectAll).length : selectedItems.length;
289
+ const selectedItemsLength = selectAll ? selectedItems.filter((item) => !require_isSelectAllItem.isSelectAllItem(item)).length : selectedItems.length;
289
290
  const menuProps = (0, react.useMemo)(() => getMenuProps({
290
291
  ref: enableFloatingStyles ? refs.setFloating : null,
291
292
  hidden: !isOpen
@@ -299,9 +300,9 @@ const MultiSelect = react.default.forwardRef(({ autoAlign = false, className: co
299
300
  const labelProps = (0, react.isValidElement)(titleText) ? { id: allLabelProps.id } : allLabelProps;
300
301
  const getSelectionStats = (0, react.useCallback)((selectedItems, filteredItems) => {
301
302
  return {
302
- hasIndividualSelections: selectedItems.some((selected) => !selected.isSelectAll),
303
- nonSelectAllSelectedCount: selectedItems.filter((selected) => !selected.isSelectAll).length,
304
- totalSelectableCount: filteredItems.filter((item) => !item.isSelectAll && !item.disabled).length
303
+ hasIndividualSelections: selectedItems.some((selected) => !require_isSelectAllItem.isSelectAllItem(selected)),
304
+ nonSelectAllSelectedCount: selectedItems.filter((selected) => !require_isSelectAllItem.isSelectAllItem(selected)).length,
305
+ totalSelectableCount: filteredItems.filter((item) => !require_isSelectAllItem.isSelectAllItem(item) && !item.disabled).length
305
306
  };
306
307
  }, [selectedItems, filteredItems]);
307
308
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -377,15 +378,15 @@ const MultiSelect = react.default.forwardRef(({ autoAlign = false, className: co
377
378
  ...menuProps,
378
379
  children: isOpen && sortItems(filteredItems, sortOptions).map((item, index) => {
379
380
  const { hasIndividualSelections, nonSelectAllSelectedCount, totalSelectableCount } = getSelectionStats(selectedItems, filteredItems);
380
- const isChecked = item.isSelectAll ? nonSelectAllSelectedCount === totalSelectableCount && totalSelectableCount > 0 : selectedItems.some((selected) => (0, react_fast_compare.default)(selected, item));
381
- const isIndeterminate = item.isSelectAll && hasIndividualSelections && nonSelectAllSelectedCount < totalSelectableCount;
381
+ const isChecked = require_isSelectAllItem.isSelectAllItem(item) ? nonSelectAllSelectedCount === totalSelectableCount && totalSelectableCount > 0 : selectedItems.some((selected) => (0, react_fast_compare.default)(selected, item));
382
+ const isIndeterminate = require_isSelectAllItem.isSelectAllItem(item) && hasIndividualSelections && nonSelectAllSelectedCount < totalSelectableCount;
382
383
  const itemProps = getItemProps({
383
384
  item,
384
385
  ["aria-selected"]: isChecked
385
386
  });
386
387
  const itemText = itemToString(item);
387
388
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_index$3.default.MenuItem, {
388
- isActive: isChecked && !item["isSelectAll"],
389
+ isActive: isChecked && !require_isSelectAllItem.isSelectAllItem(item),
389
390
  "aria-label": itemText,
390
391
  "aria-checked": isIndeterminate ? "mixed" : isChecked,
391
392
  isHighlighted: highlightedIndex === index,
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Copyright IBM Corp. 2026
3
+ *
4
+ * This source code is licensed under the Apache-2.0 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ export declare const isSelectAllItem: (item: unknown) => item is {
8
+ isSelectAll?: boolean;
9
+ };
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Copyright IBM Corp. 2016, 2026
3
+ *
4
+ * This source code is licensed under the Apache-2.0 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ //#region src/components/MultiSelect/tools/isSelectAllItem.ts
9
+ /**
10
+ * Copyright IBM Corp. 2026
11
+ *
12
+ * This source code is licensed under the Apache-2.0 license found in the
13
+ * LICENSE file in the root directory of this source tree.
14
+ */
15
+ const isSelectAllItem = (item) => typeof item === "object" && item !== null && "isSelectAll" in item;
16
+ //#endregion
17
+ exports.isSelectAllItem = isSelectAllItem;
@@ -5,8 +5,8 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
+ const require_isSelectAllItem = require("./isSelectAllItem.js");
8
9
  //#region src/components/MultiSelect/tools/sorting.ts
9
- const isSelectAllItem = (item) => typeof item === "object" && item !== null && "isSelectAll" in item;
10
10
  /**
11
11
  * Use `localeCompare` with the `numeric` option enabled to sort two
12
12
  * alphanumeric strings.
@@ -17,8 +17,8 @@ const defaultCompareItems = (itemA, itemB, { locale }) => itemA.localeCompare(it
17
17
  */
18
18
  const defaultSortItems = (items, { selectedItems, itemToString, compareItems, locale }) => {
19
19
  return items.sort((itemA, itemB) => {
20
- if (isSelectAllItem(itemA) && itemA.isSelectAll) return -1;
21
- if (isSelectAllItem(itemB) && itemB.isSelectAll) return 1;
20
+ if (require_isSelectAllItem.isSelectAllItem(itemA) && itemA.isSelectAll) return -1;
21
+ if (require_isSelectAllItem.isSelectAllItem(itemB) && itemB.isSelectAll) return 1;
22
22
  const hasItemA = selectedItems.includes(itemA);
23
23
  const hasItemB = selectedItems.includes(itemB);
24
24
  if (hasItemA && !hasItemB) return -1;
@@ -27,7 +27,7 @@ let react_jsx_runtime = require("react/jsx-runtime");
27
27
  * LICENSE file in the root directory of this source tree.
28
28
  */
29
29
  const OverflowMenuItem = (0, react.forwardRef)((props, ref) => {
30
- const { className, closeMenu, dangerDescription = "danger", disabled = false, handleOverflowMenuItemFocus, hasDivider = false, href, isDelete = false, index, itemText = "Provide itemText", onClick = () => {}, onKeyDown = () => {}, requireTitle, title, wrapperClassName, ...rest } = props;
30
+ const { className, closeMenu, dangerDescription = "", disabled = false, handleOverflowMenuItemFocus, hasDivider = false, href, isDelete = false, index, itemText = "Provide itemText", onClick = () => {}, onKeyDown = () => {}, requireTitle, title, wrapperClassName, ...rest } = props;
31
31
  const prefix = require_usePrefix.usePrefix();
32
32
  function setTabFocus(evt) {
33
33
  if (require_match.match(evt, require_keys.ArrowDown)) handleOverflowMenuItemFocus?.({
@@ -51,13 +51,14 @@ const OverflowMenuItem = (0, react.forwardRef)((props, ref) => {
51
51
  [`${prefix}--overflow-menu-options__option--disabled`]: disabled
52
52
  }, wrapperClassName);
53
53
  const TagToUse = href ? "a" : "button";
54
+ const hasDangerDescription = isDelete && Boolean(dangerDescription);
54
55
  const assistiveId = require_useId.useId("danger-description");
55
56
  const OverflowMenuItemContent = (() => {
56
57
  if (typeof itemText !== "string") return itemText;
57
58
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
58
59
  className: `${prefix}--overflow-menu-options__option-content`,
59
60
  children: itemText
60
- }), isDelete && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
61
+ }), hasDangerDescription && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
61
62
  id: assistiveId,
62
63
  className: `${prefix}--visually-hidden`,
63
64
  children: dangerDescription
@@ -4,6 +4,10 @@
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
+ /**
8
+ * @deprecated PageHeader has moved to Carbon for IBM Products.
9
+ * See https://github.com/carbon-design-system/carbon/issues/21926
10
+ */
7
11
  import React, { type ElementType } from 'react';
8
12
  import PropTypes from 'prop-types';
9
13
  import { TYPES } from '../Tag/Tag';
@@ -14,6 +14,7 @@ const require_AspectRatio = require("../AspectRatio/AspectRatio.js");
14
14
  const require_index = require("../Popover/index.js");
15
15
  const require_DefinitionTooltip = require("../Tooltip/DefinitionTooltip.js");
16
16
  const require_MenuItem = require("../Menu/MenuItem.js");
17
+ const require_deprecateComponent = require("../../prop-types/deprecateComponent.js");
17
18
  const require_Grid = require("../Grid/Grid.js");
18
19
  const require_Column = require("../Grid/Column.js");
19
20
  const require_index$1 = require("../MenuButton/index.js");
@@ -37,7 +38,18 @@ let _carbon_layout = require("@carbon/layout");
37
38
  * This source code is licensed under the Apache-2.0 license found in the
38
39
  * LICENSE file in the root directory of this source tree.
39
40
  */
41
+ /**
42
+ * @deprecated PageHeader has moved to Carbon for IBM Products.
43
+ * See https://github.com/carbon-design-system/carbon/issues/21926
44
+ */
45
+ const pageHeaderDeprecationMessage = (componentName) => `The \`${componentName}\` component in \`@carbon/react\` has been deprecated and moved to \`@carbon/ibm-products\`. See https://github.com/carbon-design-system/carbon/issues/21926`;
46
+ const usePageHeaderDeprecation = (componentName) => {
47
+ (0, react.useEffect)(() => {
48
+ require_deprecateComponent.deprecateComponent(componentName, pageHeaderDeprecationMessage(componentName));
49
+ }, [componentName]);
50
+ };
40
51
  const PageHeader = react.default.forwardRef(({ className, children, ...other }, ref) => {
52
+ usePageHeaderDeprecation("PageHeader");
41
53
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
42
54
  className: (0, classnames.default)({ [`${require_usePrefix.usePrefix()}--page-header`]: true }, className),
43
55
  ref,
@@ -47,6 +59,7 @@ const PageHeader = react.default.forwardRef(({ className, children, ...other },
47
59
  });
48
60
  PageHeader.displayName = "PageHeader";
49
61
  const PageHeaderBreadcrumbBar = react.default.forwardRef(({ border = true, className, children, renderIcon: IconElement, contentActions, contentActionsFlush, pageActions, pageActionsFlush, ...other }, ref) => {
62
+ usePageHeaderDeprecation("PageHeaderBreadcrumbBar");
50
63
  const prefix = require_usePrefix.usePrefix();
51
64
  const classNames = (0, classnames.default)({
52
65
  [`${prefix}--page-header__breadcrumb-bar`]: true,
@@ -83,6 +96,7 @@ const PageHeaderBreadcrumbBar = react.default.forwardRef(({ border = true, class
83
96
  });
84
97
  PageHeaderBreadcrumbBar.displayName = "PageHeaderBreadcrumbBar";
85
98
  const PageHeaderContent = react.default.forwardRef(({ className, children, title, renderIcon: IconElement, contextualActions, pageActions, ...other }, ref) => {
99
+ usePageHeaderDeprecation("PageHeaderContent");
86
100
  const prefix = require_usePrefix.usePrefix();
87
101
  const classNames = (0, classnames.default)({ [`${prefix}--page-header__content`]: true }, className);
88
102
  const titleRef = (0, react.useRef)(null);
@@ -145,6 +159,7 @@ PageHeaderContent.propTypes = {
145
159
  pageActions: prop_types.default.node
146
160
  };
147
161
  const PageHeaderContentPageActions = ({ className, children, menuButtonLabel = "Actions", actions, ...other }) => {
162
+ usePageHeaderDeprecation("PageHeaderContentPageActions");
148
163
  const classNames = (0, classnames.default)({ [`${require_usePrefix.usePrefix()}--page-header__content__page-actions`]: true }, className);
149
164
  const containerRef = (0, react.useRef)(null);
150
165
  const offsetRef = (0, react.useRef)(null);
@@ -198,6 +213,7 @@ PageHeaderContentPageActions.propTypes = {
198
213
  actions: prop_types.default.oneOfType([prop_types.default.node, prop_types.default.array])
199
214
  };
200
215
  const PageHeaderContentText = ({ className, children, subtitle, ...other }) => {
216
+ usePageHeaderDeprecation("PageHeaderContentText");
201
217
  const prefix = require_usePrefix.usePrefix();
202
218
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
203
219
  className: (0, classnames.default)({ [`${prefix}--page-header__content__body`]: true }, className),
@@ -216,6 +232,7 @@ PageHeaderContentText.propTypes = {
216
232
  subtitle: prop_types.default.string
217
233
  };
218
234
  const PageHeaderHeroImage = ({ className, children, ...other }) => {
235
+ usePageHeaderDeprecation("PageHeaderHeroImage");
219
236
  const classNames = (0, classnames.default)({ [`${require_usePrefix.usePrefix()}--page-header__hero-image`]: true }, className);
220
237
  const isLg = require_useMatchMedia.useMatchMedia(`(min-width: ${_carbon_layout.breakpoints.lg.width})`);
221
238
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_AspectRatio.default, {
@@ -231,6 +248,7 @@ PageHeaderHeroImage.propTypes = {
231
248
  className: prop_types.default.string
232
249
  };
233
250
  const PageHeaderTabBar = react.default.forwardRef(({ className, children, tags = [], ...other }, ref) => {
251
+ usePageHeaderDeprecation("PageHeaderTabBar");
234
252
  const prefix = require_usePrefix.usePrefix();
235
253
  const classNames = (0, classnames.default)({ [`${prefix}--page-header__tab-bar`]: true }, className);
236
254
  const [openPopover, setOpenPopover] = (0, react.useState)(false);