@carbon/ibm-products 2.67.0 → 2.68.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/css/index-full-carbon.css +252 -261
  2. package/css/index-full-carbon.css.map +1 -1
  3. package/css/index-full-carbon.min.css +1 -1
  4. package/css/index-full-carbon.min.css.map +1 -1
  5. package/css/index-without-carbon-released-only.css +13 -31
  6. package/css/index-without-carbon-released-only.css.map +1 -1
  7. package/css/index-without-carbon-released-only.min.css +1 -1
  8. package/css/index-without-carbon-released-only.min.css.map +1 -1
  9. package/css/index-without-carbon.css +252 -261
  10. package/css/index-without-carbon.css.map +1 -1
  11. package/css/index-without-carbon.min.css +1 -1
  12. package/css/index-without-carbon.min.css.map +1 -1
  13. package/css/index.css +26 -35
  14. package/css/index.css.map +1 -1
  15. package/css/index.min.css +1 -1
  16. package/css/index.min.css.map +1 -1
  17. package/es/components/Carousel/Carousel.d.ts +6 -0
  18. package/es/components/Carousel/Carousel.js +45 -0
  19. package/es/components/CreateFullPage/CreateFullPage.d.ts +3 -2
  20. package/es/components/Datagrid/Datagrid/DraggableElement.d.ts +3 -0
  21. package/es/components/Datagrid/Datagrid/DraggableElement.js +23 -15
  22. package/es/components/Datagrid/Datagrid/addons/CustomizeColumns/ButtonWrapper.d.ts +16 -20
  23. package/es/components/Datagrid/Datagrid/addons/CustomizeColumns/ButtonWrapper.js +3 -5
  24. package/es/components/Datagrid/Datagrid/addons/CustomizeColumns/Columns.js +1 -3
  25. package/es/components/Datagrid/Datagrid/addons/CustomizeColumns/CustomizeColumnsTearsheet.d.ts +2 -1
  26. package/es/components/Datagrid/Datagrid/addons/CustomizeColumns/CustomizeColumnsTearsheet.js +2 -0
  27. package/es/components/Datagrid/Datagrid/addons/CustomizeColumns/DraggableItemsList.js +4 -11
  28. package/es/components/Datagrid/Datagrid/addons/CustomizeColumns/TearsheetWrapper.d.ts +2 -1
  29. package/es/components/Datagrid/Datagrid/addons/CustomizeColumns/TearsheetWrapper.js +3 -1
  30. package/es/components/Datagrid/useCustomizeColumns.js +29 -22
  31. package/es/components/Guidebanner/Guidebanner.js +2 -1
  32. package/es/components/InterstitialScreen/InterstitialScreen.d.ts +4 -0
  33. package/es/components/InterstitialScreen/InterstitialScreen.js +16 -4
  34. package/es/components/InterstitialScreen/InterstitialScreenBody.js +7 -7
  35. package/es/components/InterstitialScreen/InterstitialScreenFooter.js +8 -1
  36. package/es/components/InterstitialScreen/InterstitialScreenHeader.js +10 -4
  37. package/es/components/PageHeader/PageHeaderUtils.js +2 -1
  38. package/es/components/Tearsheet/TearsheetShell.js +0 -1
  39. package/es/global/js/hooks/useResizeObserver.d.ts +8 -1
  40. package/es/global/js/hooks/useResizeObserver.js +12 -13
  41. package/lib/components/Carousel/Carousel.d.ts +6 -0
  42. package/lib/components/Carousel/Carousel.js +45 -0
  43. package/lib/components/CreateFullPage/CreateFullPage.d.ts +3 -2
  44. package/lib/components/Datagrid/Datagrid/DraggableElement.d.ts +3 -0
  45. package/lib/components/Datagrid/Datagrid/DraggableElement.js +23 -15
  46. package/lib/components/Datagrid/Datagrid/addons/CustomizeColumns/ButtonWrapper.d.ts +16 -20
  47. package/lib/components/Datagrid/Datagrid/addons/CustomizeColumns/ButtonWrapper.js +3 -5
  48. package/lib/components/Datagrid/Datagrid/addons/CustomizeColumns/Columns.js +1 -3
  49. package/lib/components/Datagrid/Datagrid/addons/CustomizeColumns/CustomizeColumnsTearsheet.d.ts +2 -1
  50. package/lib/components/Datagrid/Datagrid/addons/CustomizeColumns/CustomizeColumnsTearsheet.js +2 -0
  51. package/lib/components/Datagrid/Datagrid/addons/CustomizeColumns/DraggableItemsList.js +4 -11
  52. package/lib/components/Datagrid/Datagrid/addons/CustomizeColumns/TearsheetWrapper.d.ts +2 -1
  53. package/lib/components/Datagrid/Datagrid/addons/CustomizeColumns/TearsheetWrapper.js +3 -1
  54. package/lib/components/Datagrid/useCustomizeColumns.js +29 -22
  55. package/lib/components/Guidebanner/Guidebanner.js +2 -1
  56. package/lib/components/InterstitialScreen/InterstitialScreen.d.ts +4 -0
  57. package/lib/components/InterstitialScreen/InterstitialScreen.js +15 -3
  58. package/lib/components/InterstitialScreen/InterstitialScreenBody.js +7 -7
  59. package/lib/components/InterstitialScreen/InterstitialScreenFooter.js +7 -0
  60. package/lib/components/InterstitialScreen/InterstitialScreenHeader.js +9 -3
  61. package/lib/components/PageHeader/PageHeaderUtils.js +2 -1
  62. package/lib/components/Tearsheet/TearsheetShell.js +0 -1
  63. package/lib/global/js/hooks/useResizeObserver.d.ts +8 -1
  64. package/lib/global/js/hooks/useResizeObserver.js +12 -13
  65. package/package.json +5 -5
  66. package/scss/components/AboutModal/_about-modal.scss +3 -1
  67. package/scss/components/BreadcrumbWithOverflow/_breadcrumb-with-overflow.scss +0 -1
  68. package/scss/components/Carousel/_carousel.scss +5 -0
  69. package/scss/components/Datagrid/styles/_draggableElement.scss +14 -8
  70. package/scss/components/Datagrid/styles/addons/_CustomizeColumnsTearsheet.scss +0 -7
  71. package/scss/components/FilterSummary/_filter-summary.scss +0 -5
  72. package/scss/components/InterstitialScreen/_interstitial-screen.scss +2 -2
  73. package/scss/global/styles/_display-box.scss +1 -3
  74. package/telemetry.yml +1 -0
  75. package/scss/components/FilterSummary/_animations.scss +0 -20
@@ -12,6 +12,7 @@ import { CarouselItem } from './CarouselItem.js';
12
12
  import cx from 'classnames';
13
13
  import { getDevtoolsProps } from '../../global/js/utils/devtools.js';
14
14
  import { pkg } from '../../settings.js';
15
+ import { usePrefix } from '@carbon/react';
15
16
  import { useIsomorphicEffect } from '../../global/js/hooks/useIsomorphicEffect.js';
16
17
 
17
18
  // The block part of our conventional BEM class names (blockClass__E--M).
@@ -49,6 +50,7 @@ const Carousel = /*#__PURE__*/React__default.forwardRef((props, ref) => {
49
50
  fadedEdgeColor,
50
51
  onChangeIsScrollable = defaults.onChangeIsScrollable,
51
52
  onScroll = defaults.onScroll,
53
+ isScrollMode = false,
52
54
  ...rest
53
55
  } = props;
54
56
  const carouselRef = useRef(null);
@@ -59,6 +61,7 @@ const Carousel = /*#__PURE__*/React__default.forwardRef((props, ref) => {
59
61
  const childElementsRef = useRef(Array(React__default.Children.count(children)).fill(useRef(null)));
60
62
  const leftFadedEdgeColor = typeof fadedEdgeColor === 'object' ? fadedEdgeColor?.left : fadedEdgeColor;
61
63
  const rightFadedEdgeColor = typeof fadedEdgeColor === 'object' ? fadedEdgeColor?.right : fadedEdgeColor;
64
+ const carbonPrefix = usePrefix();
62
65
 
63
66
  // Trigger callbacks to report state of the carousel
64
67
  const handleOnScroll = useCallback(() => {
@@ -156,8 +159,42 @@ const Carousel = /*#__PURE__*/React__default.forwardRef((props, ref) => {
156
159
  handleOnScroll();
157
160
  }, [handleOnScroll]);
158
161
  const handleScrollToView = useCallback(itemNumber => {
162
+ updateAriaHiddenTabIndex(itemNumber);
159
163
  childElementsRef.current[itemNumber].scrollIntoView();
164
+ // eslint-disable-next-line react-hooks/exhaustive-deps
160
165
  }, []);
166
+ const getFocusableElements = container => {
167
+ const notQuery = `:not(.${carbonPrefix}--visually-hidden,.${carbonPrefix}--btn--disabled,[aria-hidden="true"],[disabled])`;
168
+ // Queries to include element types button, input, select, textarea
169
+ const queryButton = `button${notQuery}`;
170
+ const queryInput = `input${notQuery}`;
171
+ const querySelect = `select${notQuery}`;
172
+ const queryTextarea = `textarea${notQuery}`;
173
+ const queryLink = `[href]${notQuery}`;
174
+ const queryAnchor = `a${notQuery}`;
175
+ const queryTabIndex = `[tabindex="0"]${notQuery}`;
176
+ // Final query
177
+ const query = `${queryButton},${queryLink},${queryAnchor},${queryInput},${querySelect},${queryTextarea},${queryTabIndex}`;
178
+ return container?.querySelectorAll(`${query}`) ?? [];
179
+ };
180
+ const updateAriaHiddenTabIndex = itemNumber => {
181
+ //aria-hidden need to updated based on the active item, otherwise screen reader will reset to first item while
182
+ //interact with element via Control + Option + Down Arrow
183
+ // aria-hidden is set to true to inactive carousal items
184
+ // tab-index is set to -1 for all inputs in in active elements
185
+
186
+ !isScrollMode && childElementsRef.current?.forEach((item, idx) => {
187
+ const isActive = idx === itemNumber;
188
+ // Set aria-hidden based on active state
189
+ item?.setAttribute('aria-hidden', String(!isActive));
190
+
191
+ // Update tabIndex for all focusable elements within the item
192
+ const focusableElements = getFocusableElements(item);
193
+ focusableElements.forEach(el => {
194
+ el.tabIndex = isActive ? 0 : -1;
195
+ });
196
+ });
197
+ };
161
198
 
162
199
  // Trigger a callback after first render (and applied CSS).
163
200
  useEffect(() => {
@@ -168,6 +205,8 @@ const Carousel = /*#__PURE__*/React__default.forwardRef((props, ref) => {
168
205
  setTimeout(() => {
169
206
  // But, because we are making calculations based on the final,
170
207
  // applied CSS, we must wait for one more "tick".
208
+
209
+ updateAriaHiddenTabIndex(0);
171
210
  handleOnScroll();
172
211
  }, 0);
173
212
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -316,6 +355,12 @@ Carousel.propTypes = {
316
355
  left: PropTypes.string,
317
356
  right: PropTypes.string
318
357
  })]),
358
+ /**
359
+ * enable scroll mode when only scroll functionality is required, more than one items will be visible at a time
360
+ * when isScrollMode is false, component behaves like a carousal and on item will be active at a time
361
+ * and other items will be hidden and inactive.
362
+ */
363
+ isScrollMode: PropTypes.bool,
319
364
  /**
320
365
  * An optional callback function that returns `true`
321
366
  * when the carousel has enough content to be scrollable,
@@ -20,6 +20,7 @@ interface HeaderBreadcrumb {
20
20
  /** Provide if this breadcrumb item represents the current page */
21
21
  isCurrentPage?: boolean;
22
22
  }
23
+ type MaybePromise<T> = Promise<T> | T;
23
24
  type CreateFullPageBreadcrumbsProps = {
24
25
  /** The header breadcrumbs */
25
26
  breadcrumbs?: null | undefined;
@@ -107,9 +108,9 @@ type CreateFullPageBaseProps = {
107
108
  *
108
109
  * @returns Object - if you want to prevent the modal from closing, return an object with the property preventClose set to true
109
110
  */
110
- onRequestSubmit: () => {
111
+ onRequestSubmit: () => MaybePromise<{
111
112
  preventClose?: boolean;
112
- } | void;
113
+ } | void>;
113
114
  /**
114
115
  * A secondary title of the full page, displayed in the influencer area
115
116
  */
@@ -15,6 +15,9 @@ interface DraggableElementProps extends PropsWithChildren {
15
15
  isSticky?: boolean;
16
16
  selected?: boolean;
17
17
  }
18
+ /**
19
+ * Single row in the DraggableItemsList used by CustomizeColumnsTearsheet.
20
+ */
18
21
  declare const DraggableElement: {
19
22
  ({ id, elementId, children, classList, disabled, ariaLabel, isSticky, selected, }: DraggableElementProps): React.JSX.Element;
20
23
  propTypes: {
@@ -16,6 +16,9 @@ import { useSortable } from '@dnd-kit/sortable';
16
16
 
17
17
  var _Locked, _DraggableIcon;
18
18
  const blockClass = `${pkg.prefix}--datagrid`;
19
+ /**
20
+ * Single row in the DraggableItemsList used by CustomizeColumnsTearsheet.
21
+ */
19
22
  const DraggableElement = _ref => {
20
23
  let {
21
24
  id,
@@ -38,20 +41,33 @@ const DraggableElement = _ref => {
38
41
  disabled,
39
42
  id
40
43
  });
41
- const content = /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement("div", {
44
+
45
+ // Most of the attributes (ex: role, tabIndex, aria-disabled) are unnecessary for a <button>, so just get the ones we need.
46
+ const {
47
+ 'aria-pressed': ariaPressed,
48
+ 'aria-describedby': ariaDescribedby
49
+ } = attributes;
50
+ const dragHandle = isSticky ? /*#__PURE__*/React__default.createElement("div", {
42
51
  className: cx({
43
52
  disabled
44
53
  }, `${blockClass}__draggable-handleStyle`)
45
- }, isSticky ? _Locked || (_Locked = /*#__PURE__*/React__default.createElement(Locked, {
54
+ }, _Locked || (_Locked = /*#__PURE__*/React__default.createElement(Locked, {
46
55
  size: 16
47
- })) : _DraggableIcon || (_DraggableIcon = /*#__PURE__*/React__default.createElement(Draggable, {
56
+ })), ' ') : /*#__PURE__*/React__default.createElement("button", _extends({
57
+ className: `${blockClass}__draggable-handleStyle`,
58
+ type: "button",
59
+ "aria-label": ariaLabel,
60
+ "aria-describedby": ariaDescribedby,
61
+ "aria-pressed": ariaPressed
62
+ }, listeners), _DraggableIcon || (_DraggableIcon = /*#__PURE__*/React__default.createElement(Draggable, {
48
63
  size: 16
49
- }))), children);
64
+ })));
65
+ const content = /*#__PURE__*/React__default.createElement(React__default.Fragment, null, dragHandle, children);
50
66
  const style = {
51
67
  transform: !disabled ? CSS.Transform.toString(transform) : undefined,
52
68
  transition
53
69
  };
54
- return /*#__PURE__*/React__default.createElement("li", _extends({
70
+ return /*#__PURE__*/React__default.createElement("li", {
55
71
  className: cx(classList, `${blockClass}__draggable-handleHolder`, {
56
72
  [`${blockClass}__draggable-handleHolder--selected`]: selected,
57
73
  [`${blockClass}__draggable-handleHolder--sticky`]: isSticky,
@@ -60,16 +76,8 @@ const DraggableElement = _ref => {
60
76
  id: elementId ? elementId : id,
61
77
  ref: setNodeRef,
62
78
  style: style
63
- }, attributes, listeners, {
64
- "aria-disabled": undefined,
65
- "aria-selected": selected,
66
- role: "option"
67
- }), /*#__PURE__*/React__default.createElement("span", {
68
- className: `${blockClass}__shared-ui--assistive-text`
69
- }, ariaLabel), /*#__PURE__*/React__default.createElement("div", {
70
- className: cx({
71
- [`${blockClass}__draggable-handleStyle`]: !disabled
72
- }, [`${blockClass}__draggable-handleHolder-droppable`])
79
+ }, /*#__PURE__*/React__default.createElement("div", {
80
+ className: cx([`${blockClass}__draggable-handleHolder-droppable`])
73
81
  }, content));
74
82
  };
75
83
  DraggableElement.propTypes = {
@@ -1,21 +1,17 @@
1
- export default ButtonWrapper;
2
- declare function ButtonWrapper({ onClick, setIsTearsheetOpen, isTearsheetOpen, iconTooltipLabel, ...rest }: {
3
- [x: string]: any;
4
- onClick: any;
5
- setIsTearsheetOpen: any;
6
- isTearsheetOpen: any;
7
- iconTooltipLabel?: string | undefined;
8
- }): React.JSX.Element;
9
- declare namespace ButtonWrapper {
10
- namespace defaultProps {
11
- function onClick(): void;
12
- }
13
- namespace propTypes {
14
- export let iconTooltipLabel: any;
15
- export let isTearsheetOpen: any;
16
- let onClick_1: any;
17
- export { onClick_1 as onClick };
18
- export let setIsTearsheetOpen: any;
19
- }
20
- }
1
+ /**
2
+ * Copyright IBM Corp. 2022, 2024
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
+ */
21
7
  import * as React from 'react';
8
+ import { Button } from '@carbon/react';
9
+ import { ComponentProps } from 'react';
10
+ interface ButtonWrapperProps extends ComponentProps<typeof Button> {
11
+ isTearsheetOpen: boolean;
12
+ iconTooltipLabel?: string;
13
+ onClick?: () => void;
14
+ setIsTearsheetOpen: (open: boolean) => void;
15
+ }
16
+ declare const ButtonWrapper: React.ForwardRefExoticComponent<ButtonWrapperProps & React.RefAttributes<HTMLButtonElement>>;
17
+ export default ButtonWrapper;
@@ -13,7 +13,7 @@ import { Button } from '@carbon/react';
13
13
  import { pkg } from '../../../../../settings.js';
14
14
 
15
15
  const blockClass = `${pkg.prefix}--datagrid`;
16
- const ButtonWrapper = _ref => {
16
+ const ButtonWrapper = /*#__PURE__*/React.forwardRef((_ref, ref) => {
17
17
  let {
18
18
  onClick,
19
19
  setIsTearsheetOpen,
@@ -30,6 +30,7 @@ const ButtonWrapper = _ref => {
30
30
  kind: "ghost",
31
31
  hasIconOnly: true,
32
32
  "test-id": `${blockClass}__customize-columns-trigger`,
33
+ ref: ref,
33
34
  onClick: () => {
34
35
  setIsTearsheetOpen(!isTearsheetOpen);
35
36
  if (typeof onClick === 'function') {
@@ -37,10 +38,7 @@ const ButtonWrapper = _ref => {
37
38
  }
38
39
  }
39
40
  }));
40
- };
41
- ButtonWrapper.defaultProps = {
42
- onClick: () => {}
43
- };
41
+ });
44
42
  ButtonWrapper.propTypes = {
45
43
  iconTooltipLabel: PropTypes.string,
46
44
  isTearsheetOpen: PropTypes.bool.isRequired,
@@ -45,10 +45,8 @@ const Columns = _ref => {
45
45
  ref: listRef
46
46
  }, /*#__PURE__*/React__default.createElement("ol", {
47
47
  className: `${blockClass}__customize-columns-column-list--focus`,
48
- role: "listbox",
49
48
  "aria-label": customizeTearsheetHeadingLabel,
50
- "aria-describedby": `${blockClass}__customize-columns--instructions`,
51
- tabIndex: 0
49
+ "aria-describedby": `${blockClass}__customize-columns--instructions`
52
50
  }, /*#__PURE__*/React__default.createElement("span", {
53
51
  "aria-live": "assertive",
54
52
  className: `${blockClass}__shared-ui--assistive-text`
@@ -1,7 +1,8 @@
1
1
  export default CustomizeColumnsTearsheet;
2
- declare function CustomizeColumnsTearsheet({ isOpen, setIsTearsheetOpen, onSaveColumnPrefs, columnDefinitions, originalColumnDefinitions, customizeTearsheetHeadingLabel, primaryButtonTextLabel, secondaryButtonTextLabel, instructionsLabel, findColumnPlaceholderLabel, resetToDefaultLabel, assistiveTextInstructionsLabel, assistiveTextDisabledInstructionsLabel, selectAllLabel, }: {
2
+ declare function CustomizeColumnsTearsheet({ isOpen, setIsTearsheetOpen, launcherButtonRef, onSaveColumnPrefs, columnDefinitions, originalColumnDefinitions, customizeTearsheetHeadingLabel, primaryButtonTextLabel, secondaryButtonTextLabel, instructionsLabel, findColumnPlaceholderLabel, resetToDefaultLabel, assistiveTextInstructionsLabel, assistiveTextDisabledInstructionsLabel, selectAllLabel, }: {
3
3
  isOpen: any;
4
4
  setIsTearsheetOpen: any;
5
+ launcherButtonRef: any;
5
6
  onSaveColumnPrefs: any;
6
7
  columnDefinitions: any;
7
8
  originalColumnDefinitions: any;
@@ -18,6 +18,7 @@ const CustomizeColumnsTearsheet = _ref => {
18
18
  let {
19
19
  isOpen,
20
20
  setIsTearsheetOpen,
21
+ launcherButtonRef,
21
22
  onSaveColumnPrefs,
22
23
  columnDefinitions,
23
24
  originalColumnDefinitions,
@@ -106,6 +107,7 @@ const CustomizeColumnsTearsheet = _ref => {
106
107
  open: isOpen,
107
108
  title: `${customizeTearsheetHeadingLabel} (${visibleColumnsCount}/${totalColumns})`,
108
109
  description: instructionsLabel,
110
+ launcherButtonRef: launcherButtonRef,
109
111
  actions: [{
110
112
  kind: 'secondary',
111
113
  label: secondaryButtonTextLabel,
@@ -148,10 +148,10 @@ const DraggableItemsList = _ref => {
148
148
  }, visibleCols.map(colDef => {
149
149
  const colHeaderTitle = getNodeTextContent(colDef.Header);
150
150
  const parts = colHeaderTitle.split(new RegExp(`(${filterString})`, 'gi'));
151
- const highlightedText = parts.map(part => part.toLowerCase() === filterString.toLowerCase() ? `<strong>${part}</strong>` : part).join('');
151
+ const highlightedText = parts.map(part => part.toLowerCase() === filterString.toLowerCase() ? /*#__PURE__*/React__default.createElement("strong", null, part) : part);
152
152
  const isFrozenColumn = !!colDef.sticky;
153
153
  const isDisabled = colDef.disabled;
154
- const listContents = /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(Checkbox, {
154
+ const listContents = /*#__PURE__*/React__default.createElement(Checkbox, {
155
155
  checked: isColumnVisible(colDef),
156
156
  disabled: isDisabled || isFrozenColumn,
157
157
  onChange: (_, _ref2) => {
@@ -161,17 +161,10 @@ const DraggableItemsList = _ref => {
161
161
  return onSelectColumn(colDef, checked);
162
162
  },
163
163
  id: `${blockClass}__customization-column-${colDef.id}`,
164
- labelText: colHeaderTitle,
165
- title: colHeaderTitle,
164
+ labelText: highlightedText,
166
165
  className: `${blockClass}__customize-columns-checkbox`,
167
- hideLabel: true,
168
166
  onKeyDown: event => handleCheckboxKeydown(event, colDef)
169
- }), /*#__PURE__*/React__default.createElement("div", {
170
- dangerouslySetInnerHTML: {
171
- __html: highlightedText
172
- },
173
- className: `${blockClass}__customize-columns-checkbox-visible-label`
174
- }));
167
+ });
175
168
  return /*#__PURE__*/React__default.createElement(DraggableElement, {
176
169
  classList: draggableClass,
177
170
  key: colDef.id,
@@ -1,6 +1,7 @@
1
1
  export default TearsheetWrapper;
2
- declare function TearsheetWrapper({ instance }: {
2
+ declare function TearsheetWrapper({ instance, launcherButtonRef }: {
3
3
  instance: any;
4
+ launcherButtonRef: any;
4
5
  }): React.JSX.Element;
5
6
  declare namespace TearsheetWrapper {
6
7
  namespace propTypes {
@@ -14,7 +14,8 @@ import { InlineEditContext } from '../InlineEdit/InlineEditContext/InlineEditCon
14
14
 
15
15
  const TearsheetWrapper = _ref => {
16
16
  let {
17
- instance
17
+ instance,
18
+ launcherButtonRef
18
19
  } = _ref;
19
20
  const {
20
21
  onSaveColumnPrefs,
@@ -37,6 +38,7 @@ const TearsheetWrapper = _ref => {
37
38
  return /*#__PURE__*/React__default.createElement(CustomizeColumnsTearsheet, _extends({}, rest, labels, {
38
39
  isOpen: isTearsheetOpen,
39
40
  setIsTearsheetOpen: setIsTearsheetOpen,
41
+ launcherButtonRef: launcherButtonRef,
40
42
  columnDefinitions: instance.allColumns,
41
43
  originalColumnDefinitions: instance.columns,
42
44
  onSaveColumnPrefs: updatedColDefs => {
@@ -7,32 +7,39 @@
7
7
 
8
8
  import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
9
9
  import * as React from 'react';
10
- import TearsheetWrapper from './Datagrid/addons/CustomizeColumns/TearsheetWrapper.js';
11
10
  import ButtonWrapper from './Datagrid/addons/CustomizeColumns/ButtonWrapper.js';
11
+ import TearsheetWrapper from './Datagrid/addons/CustomizeColumns/TearsheetWrapper.js';
12
12
 
13
- const useCustomizeColumns = hooks => {
13
+ const useInstance = instance => {
14
+ const {
15
+ customizeColumnsProps
16
+ } = instance;
17
+ const {
18
+ labels
19
+ } = customizeColumnsProps || {};
14
20
  const [isTearsheetOpen, setIsTearsheetOpen] = React.useState(false);
15
- hooks.useInstance.push(instance => {
16
- const {
17
- customizeColumnsProps
18
- } = instance;
19
- const {
20
- labels
21
- } = customizeColumnsProps || {};
22
- Object.assign(instance, {
23
- customizeColumnsProps: {
24
- ...customizeColumnsProps,
25
- isTearsheetOpen,
26
- setIsTearsheetOpen
27
- },
28
- CustomizeColumnsButton: props => /*#__PURE__*/React.createElement(ButtonWrapper, _extends({
29
- iconTooltipLabel: labels?.iconTooltipLabel,
30
- isTearsheetOpen: isTearsheetOpen,
31
- setIsTearsheetOpen: setIsTearsheetOpen
32
- }, props)),
33
- CustomizeColumnsTearsheet: TearsheetWrapper
34
- });
21
+ const launcherButtonRef = React.useRef(null);
22
+ const CustomizeColumnsButton = React.useCallback(props => /*#__PURE__*/React.createElement(ButtonWrapper, _extends({}, props, {
23
+ iconTooltipLabel: labels?.iconTooltipLabel,
24
+ isTearsheetOpen: isTearsheetOpen,
25
+ setIsTearsheetOpen: setIsTearsheetOpen,
26
+ ref: launcherButtonRef
27
+ })), [isTearsheetOpen, labels?.iconTooltipLabel]);
28
+ const CustomizeColumnsTearsheet = React.useCallback(props => /*#__PURE__*/React.createElement(TearsheetWrapper, _extends({}, props, {
29
+ launcherButtonRef: launcherButtonRef
30
+ })), [launcherButtonRef]);
31
+ Object.assign(instance, {
32
+ customizeColumnsProps: {
33
+ ...customizeColumnsProps,
34
+ isTearsheetOpen,
35
+ setIsTearsheetOpen
36
+ },
37
+ CustomizeColumnsButton,
38
+ CustomizeColumnsTearsheet
35
39
  });
36
40
  };
41
+ const useCustomizeColumns = hooks => {
42
+ hooks.useInstance.push(useInstance);
43
+ };
37
44
 
38
45
  export { useCustomizeColumns as default };
@@ -88,7 +88,8 @@ let Guidebanner = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
88
88
  },
89
89
  onScroll: scrollPercent => {
90
90
  setScrollPosition(scrollPercent);
91
- }
91
+ },
92
+ isScrollMode: true
92
93
  }, children), /*#__PURE__*/React__default.createElement("div", {
93
94
  className: cx([collapsible || showNavigation ? `${blockClass}__navigation` : null])
94
95
  }, collapsible && /*#__PURE__*/React__default.createElement(Button, {
@@ -35,6 +35,10 @@ export interface InterstitialScreenProps {
35
35
  * Function to call when the close button is clicked.
36
36
  */
37
37
  onClose?: (value: ActionType) => void;
38
+ /**
39
+ * Provide a ref to return focus to once the interstitial is closed.
40
+ */
41
+ launcherButtonRef?: RefObject<HTMLElement>;
38
42
  }
39
43
  type InterstitialScreenComponent = React.ForwardRefExoticComponent<InterstitialScreenProps & React.RefAttributes<HTMLDivElement>> & {
40
44
  Header: React.FC<InterstitialScreenHeaderProps>;
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
9
- import { ComposedModal } from '@carbon/react';
9
+ import { unstable_FeatureFlags, ComposedModal } from '@carbon/react';
10
10
  import React__default, { createContext, useRef, useState, useCallback, useEffect } from 'react';
11
11
  import PropTypes from '../../_virtual/index.js';
12
12
  import cx from 'classnames';
@@ -50,6 +50,7 @@ let InterstitialScreen = /*#__PURE__*/React__default.forwardRef((props, ref) =>
50
50
  interstitialAriaLabel = 'Interstitial screen',
51
51
  isFullScreen = false,
52
52
  isOpen = false,
53
+ launcherButtonRef,
53
54
  onClose,
54
55
  ...rest
55
56
  } = props;
@@ -84,7 +85,12 @@ let InterstitialScreen = /*#__PURE__*/React__default.forwardRef((props, ref) =>
84
85
  // for modal only, "is-visible" triggers animation
85
86
  setIsVisibleClass(!isFullScreen && isOpen ? 'is-visible' : null);
86
87
  nextButtonRef?.current?.focus();
87
- }, [isFullScreen, isOpen]);
88
+ if (!isOpen && launcherButtonRef) {
89
+ setTimeout(() => {
90
+ launcherButtonRef.current.focus();
91
+ }, 0);
92
+ }
93
+ }, [launcherButtonRef, isFullScreen, isOpen]);
88
94
 
89
95
  // hitting escape key also closes this component
90
96
  useEffect(() => {
@@ -103,7 +109,9 @@ let InterstitialScreen = /*#__PURE__*/React__default.forwardRef((props, ref) =>
103
109
  return null;
104
110
  }
105
111
  const renderModal = () => {
106
- return /*#__PURE__*/React__default.createElement(ComposedModal, _extends({}, rest, {
112
+ return /*#__PURE__*/React__default.createElement(unstable_FeatureFlags, {
113
+ enableExperimentalFocusWrapWithoutSentinels: true
114
+ }, /*#__PURE__*/React__default.createElement(ComposedModal, _extends({}, rest, {
107
115
  preventCloseOnClickOutside: true,
108
116
  className: cx(blockClass,
109
117
  // Apply the block class to the main HTML element
@@ -114,7 +122,7 @@ let InterstitialScreen = /*#__PURE__*/React__default.forwardRef((props, ref) =>
114
122
  open: isOpen,
115
123
  ref: _forwardedRef,
116
124
  "aria-label": interstitialAriaLabel
117
- }, getDevtoolsProps(componentName)), children);
125
+ }, getDevtoolsProps(componentName)), children));
118
126
  };
119
127
  const renderFullScreen = () => {
120
128
  return /*#__PURE__*/React__default.createElement("div", _extends({}, rest, {
@@ -195,6 +203,10 @@ InterstitialScreen.propTypes = {
195
203
  * Specifies whether the component is currently open.
196
204
  */
197
205
  isOpen: PropTypes.bool,
206
+ /**
207
+ * Provide a ref to return focus to once the interstitial is closed.
208
+ */
209
+ launcherButtonRef: PropTypes.any,
198
210
  /**
199
211
  * Function to call when the close button is clicked.
200
212
  */
@@ -22,7 +22,7 @@ const InterstitialScreenBody = /*#__PURE__*/React__default.forwardRef(props => {
22
22
  } = props;
23
23
  const blockClass = `${pkg.prefix}--interstitial-screen`;
24
24
  const bodyBlockClass = `${blockClass}--internal-body`;
25
- const [isMultiStep, setIsMultiStep] = useState(false);
25
+ const [stepType, setStepType] = useState();
26
26
  const {
27
27
  setBodyChildrenData,
28
28
  bodyChildrenData,
@@ -48,12 +48,12 @@ const InterstitialScreenBody = /*#__PURE__*/React__default.forwardRef(props => {
48
48
 
49
49
  // Set body children data
50
50
  setBodyChildrenData?.(children);
51
-
52
51
  // If the children is an array, treat it as a multiStep
53
52
  if (isElement && Array.isArray(children)) {
54
- const stepLength = children.length;
55
- setIsMultiStep(!!stepLength);
56
- setStepCount?.(stepLength);
53
+ setStepType('multi');
54
+ setStepCount?.(children.length);
55
+ } else {
56
+ setStepType('single');
57
57
  }
58
58
 
59
59
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -78,13 +78,13 @@ const InterstitialScreenBody = /*#__PURE__*/React__default.forwardRef(props => {
78
78
  ref: bodyScrollRef
79
79
  }, rest), /*#__PURE__*/React__default.createElement("div", {
80
80
  className: `${blockClass}--content`
81
- }, isMultiStep ? /*#__PURE__*/React__default.createElement("div", {
81
+ }, stepType === 'multi' ? /*#__PURE__*/React__default.createElement("div", {
82
82
  className: `${blockClass}__carousel`
83
83
  }, /*#__PURE__*/React__default.createElement(Carousel, {
84
84
  disableArrowScroll: true,
85
85
  ref: scrollRef,
86
86
  onScroll: onScrollHandler
87
- }, bodyChildrenData)) : bodyChildrenData));
87
+ }, bodyChildrenData)) : stepType === 'single' ? bodyChildrenData : ''));
88
88
  return isFullScreen ? renderBody() : /*#__PURE__*/React__default.createElement(ModalBody, {
89
89
  className: bodyBlockClass
90
90
  }, renderBody());
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
9
- import React__default, { useContext, useRef, useState, useMemo } from 'react';
9
+ import React__default, { useContext, useRef, useState, useEffect, useMemo } from 'react';
10
10
  import { pkg } from '../../settings.js';
11
11
  import PropTypes from '../../_virtual/index.js';
12
12
  import { InterstitialScreenContext } from './InterstitialScreen.js';
@@ -40,6 +40,13 @@ const InterstitialScreenFooter = /*#__PURE__*/React__default.forwardRef(props =>
40
40
  const isMultiStep = !!stepCount;
41
41
  const progStepFloor = 0;
42
42
  const progStepCeil = stepCount - 1;
43
+ //this will focus the start button on last step when next button is hidden and start button is shown
44
+ useEffect(() => {
45
+ if (progStep + 1 === stepCount && startButtonRef.current) {
46
+ startButtonRef.current.focus();
47
+ }
48
+ // eslint-disable-next-line react-hooks/exhaustive-deps
49
+ }, [progStep]);
43
50
  const handleAction = async actionType => {
44
51
  setLoadingAction(actionType);
45
52
  await onAction?.(actionType, {
@@ -5,7 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- import { ModalHeader, ProgressIndicator, ProgressStep } from '@carbon/react';
8
+ import { usePrefix, ModalHeader, ProgressIndicator, ProgressStep } from '@carbon/react';
9
9
  import React__default from 'react';
10
10
  import PropTypes from '../../_virtual/index.js';
11
11
  import { pkg } from '../../settings.js';
@@ -27,15 +27,17 @@ const InterstitialScreenHeader = /*#__PURE__*/React__default.forwardRef(props =>
27
27
  bodyChildrenData,
28
28
  isFullScreen,
29
29
  progStep,
30
- handleClose
30
+ handleClose,
31
+ stepCount
31
32
  } = React__default.useContext(InterstitialScreenContext);
32
33
  const blockClass = `${pkg.prefix}--interstitial-screen`;
33
34
  const headerBlockClass = `${blockClass}--internal-header`;
34
35
  const _useId = useId();
36
+ const carbonPrefix = usePrefix();
35
37
  const headerContent = () => {
36
38
  return /*#__PURE__*/React__default.createElement(React__default.Fragment, null, (headerTitle || headerSubTitle) && /*#__PURE__*/React__default.createElement("div", {
37
39
  className: `${blockClass}--titleContainer`
38
- }, headerTitle && (_h || (_h = /*#__PURE__*/React__default.createElement("h2", null, headerTitle))), headerSubTitle && (_h2 || (_h2 = /*#__PURE__*/React__default.createElement("h3", null, headerSubTitle)))), children, !hideProgressIndicator && bodyChildrenData && Array.isArray(bodyChildrenData) && /*#__PURE__*/React__default.createElement("div", {
40
+ }, headerTitle && (_h || (_h = /*#__PURE__*/React__default.createElement("h1", null, headerTitle))), headerSubTitle && (_h2 || (_h2 = /*#__PURE__*/React__default.createElement("h2", null, headerSubTitle)))), children, !hideProgressIndicator && bodyChildrenData && Array.isArray(bodyChildrenData) && /*#__PURE__*/React__default.createElement("div", {
39
41
  className: `${blockClass}--progress`
40
42
  }, /*#__PURE__*/React__default.createElement(ProgressIndicator, {
41
43
  vertical: false,
@@ -49,7 +51,11 @@ const InterstitialScreenHeader = /*#__PURE__*/React__default.forwardRef(props =>
49
51
  translateWithId: child.props.translateWithId
50
52
  });
51
53
  }
52
- }))));
54
+ })), /*#__PURE__*/React__default.createElement("div", {
55
+ "aria-live": "polite",
56
+ "aria-atomic": "true",
57
+ className: `${carbonPrefix}--visually-hidden`
58
+ }, "Step ", progStep + 1, " of ", stepCount)));
53
59
  };
54
60
  return isFullScreen ? /*#__PURE__*/React__default.createElement("header", {
55
61
  className: cx(headerBlockClass, className, {
@@ -158,7 +158,7 @@ const utilGetBreadcrumbItemForTitle = (blockClass, collapseTitle, title) => {
158
158
  if (title.text !== undefined) {
159
159
  // Shape title provided
160
160
  breadcrumbTitle = {
161
- label: /*#__PURE__*/React__default.createElement("span", null, title.loading ? _SkeletonText || (_SkeletonText = /*#__PURE__*/React__default.createElement(SkeletonText, null)) : title.text),
161
+ label: title.loading ? _SkeletonText || (_SkeletonText = /*#__PURE__*/React__default.createElement(SkeletonText, null)) : title.text,
162
162
  title: title.text
163
163
  };
164
164
  } else if (title.content !== undefined) {
@@ -176,6 +176,7 @@ const utilGetBreadcrumbItemForTitle = (blockClass, collapseTitle, title) => {
176
176
  if (breadcrumbTitle) {
177
177
  breadcrumbTitle.key = 'breadcrumb-title';
178
178
  breadcrumbTitle.isCurrentPage = true;
179
+ breadcrumbTitle.href = '#';
179
180
  breadcrumbTitle.className = cx([`${blockClass}__breadcrumb-title`, {
180
181
  [`${blockClass}__breadcrumb-title--pre-collapsed`]: collapseTitle
181
182
  }]);
@@ -305,7 +305,6 @@ const TearsheetShell = /*#__PURE__*/React__default.forwardRef((_ref2, ref) => {
305
305
  }, /*#__PURE__*/React__default.createElement(Wrap, {
306
306
  className: `${bc}__content`,
307
307
  alwaysRender: !!(influencer && influencerPosition === 'right'),
308
- tabIndex: -1,
309
308
  element: SectionLevel3
310
309
  }, children), /*#__PURE__*/React__default.createElement(Wrap, {
311
310
  className: cx({
@@ -1,4 +1,11 @@
1
- export function useResizeObserver(ref: any, callback: any, deps?: any[]): {
1
+ /**
2
+ * Copyright IBM Corp. 2023, 2025
3
+ *
4
+ * This source code is licensed under the Apache-2.0 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ import { RefObject } from 'react';
8
+ export declare const useResizeObserver: (ref: RefObject<HTMLElement>, onResize?: (rect: DOMRectReadOnly) => void) => {
2
9
  width: number;
3
10
  height: number;
4
11
  };