@carbon/react 1.43.0-rc.0 → 1.44.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 (46) hide show
  1. package/.playwright/INTERNAL_AVT_REPORT_DO_NOT_USE.json +1161 -1001
  2. package/es/components/ComboBox/ComboBox.js +12 -0
  3. package/es/components/ComboButton/index.js +2 -1
  4. package/es/components/ComposedModal/ComposedModal.d.ts +3 -3
  5. package/es/components/ComposedModal/ComposedModal.js +3 -3
  6. package/es/components/ContextMenu/useContextMenu.js +2 -1
  7. package/es/components/DataTableSkeleton/DataTableSkeleton.js +1 -1
  8. package/es/components/Dropdown/Dropdown.js +4 -1
  9. package/es/components/Link/Link.d.ts +5 -0
  10. package/es/components/Link/Link.js +9 -2
  11. package/es/components/Menu/Menu.js +14 -0
  12. package/es/components/Menu/MenuContext.js +1 -0
  13. package/es/components/Menu/MenuItem.js +19 -4
  14. package/es/components/MenuButton/index.js +3 -1
  15. package/es/components/Slug/index.js +1 -1
  16. package/es/components/UIShell/SideNav.js +1 -1
  17. package/es/components/UIShell/Switcher.d.ts +38 -0
  18. package/es/components/UIShell/Switcher.js +14 -13
  19. package/es/components/UIShell/SwitcherDivider.d.ts +9 -0
  20. package/es/components/UIShell/SwitcherDivider.js +4 -5
  21. package/es/components/UIShell/SwitcherItem.d.ts +49 -0
  22. package/es/components/UIShell/SwitcherItem.js +13 -17
  23. package/es/prop-types/tools/getDisplayName.js +34 -0
  24. package/lib/components/ComboBox/ComboBox.js +12 -0
  25. package/lib/components/ComboButton/index.js +2 -1
  26. package/lib/components/ComposedModal/ComposedModal.d.ts +3 -3
  27. package/lib/components/ComposedModal/ComposedModal.js +3 -3
  28. package/lib/components/ContextMenu/useContextMenu.js +2 -1
  29. package/lib/components/DataTableSkeleton/DataTableSkeleton.js +1 -1
  30. package/lib/components/Dropdown/Dropdown.js +4 -1
  31. package/lib/components/Link/Link.d.ts +5 -0
  32. package/lib/components/Link/Link.js +9 -2
  33. package/lib/components/Menu/Menu.js +14 -0
  34. package/lib/components/Menu/MenuContext.js +1 -0
  35. package/lib/components/Menu/MenuItem.js +19 -4
  36. package/lib/components/MenuButton/index.js +3 -1
  37. package/lib/components/Slug/index.js +1 -1
  38. package/lib/components/UIShell/SideNav.js +1 -1
  39. package/lib/components/UIShell/Switcher.d.ts +38 -0
  40. package/lib/components/UIShell/Switcher.js +13 -12
  41. package/lib/components/UIShell/SwitcherDivider.d.ts +9 -0
  42. package/lib/components/UIShell/SwitcherDivider.js +4 -5
  43. package/lib/components/UIShell/SwitcherItem.d.ts +49 -0
  44. package/lib/components/UIShell/SwitcherItem.js +12 -16
  45. package/lib/prop-types/tools/getDisplayName.js +38 -0
  46. package/package.json +3 -3
@@ -351,6 +351,18 @@ const ComboBox = /*#__PURE__*/forwardRef((props, ref) => {
351
351
  if (match(event, End) && event.code !== 'Numpad1') {
352
352
  event.target.setSelectionRange(event.target.value.length, event.target.value.length);
353
353
  }
354
+ if (event.altKey && event.key == 'ArrowDown') {
355
+ event.preventDownshiftDefault = true;
356
+ if (!isOpen) {
357
+ toggleMenu();
358
+ }
359
+ }
360
+ if (event.altKey && event.key == 'ArrowUp') {
361
+ event.preventDownshiftDefault = true;
362
+ if (isOpen) {
363
+ toggleMenu();
364
+ }
365
+ }
354
366
  }
355
367
  });
356
368
  const handleFocus = evt => {
@@ -68,7 +68,7 @@ const ComboButton = /*#__PURE__*/React__default.forwardRef(function ComboButton(
68
68
  }
69
69
  }
70
70
  function handleOpen() {
71
- menuRef.current.style.width = `${width}px`;
71
+ menuRef.current.style.inlineSize = `${width}px`;
72
72
  }
73
73
  const containerClasses = cx(`${prefix}--combo-button__container`, `${prefix}--combo-button__container--${size}`, {
74
74
  [`${prefix}--combo-button__container--open`]: open
@@ -100,6 +100,7 @@ const ComboButton = /*#__PURE__*/React__default.forwardRef(function ComboButton(
100
100
  ref: menuRef,
101
101
  id: id,
102
102
  label: t('carbon.combo-button.additional-actions'),
103
+ mode: "basic",
103
104
  size: size,
104
105
  open: open,
105
106
  onClose: handleClose,
@@ -4,7 +4,7 @@ export interface ModalBodyProps extends HTMLAttributes<HTMLDivElement> {
4
4
  children?: ReactNode;
5
5
  /**
6
6
  * Provide whether the modal content has a form element.
7
- * If `true` is used here, non-form child content should have `bx--modal-content__regular-content` class.
7
+ * If `true` is used here, non-form child content should have `cds--modal-content__regular-content` class.
8
8
  */
9
9
  hasForm?: boolean;
10
10
  /**
@@ -15,11 +15,11 @@ export interface ModalBodyProps extends HTMLAttributes<HTMLDivElement> {
15
15
  export declare const ModalBody: React.ForwardRefExoticComponent<ModalBodyProps & React.RefAttributes<HTMLDivElement>>;
16
16
  export interface ComposedModalProps extends HTMLAttributes<HTMLDivElement> {
17
17
  /**
18
- * Specify the aria-label for bx--modal-container
18
+ * Specify the aria-label for cds--modal-container
19
19
  */
20
20
  'aria-label'?: string;
21
21
  /**
22
- * Specify the aria-labelledby for bx--modal-container
22
+ * Specify the aria-labelledby for cds--modal-container
23
23
  */
24
24
  'aria-labelledby'?: string;
25
25
  /**
@@ -56,7 +56,7 @@ ModalBody.propTypes = {
56
56
  className: PropTypes.string,
57
57
  /**
58
58
  * Provide whether the modal content has a form element.
59
- * If `true` is used here, non-form child content should have `bx--modal-content__regular-content` class.
59
+ * If `true` is used here, non-form child content should have `cds--modal-content__regular-content` class.
60
60
  */
61
61
  hasForm: PropTypes.bool,
62
62
  /**
@@ -231,11 +231,11 @@ const ComposedModal = /*#__PURE__*/React__default.forwardRef(function ComposedMo
231
231
  });
232
232
  ComposedModal.propTypes = {
233
233
  /**
234
- * Specify the aria-label for bx--modal-container
234
+ * Specify the aria-label for cds--modal-container
235
235
  */
236
236
  ['aria-label']: PropTypes.string,
237
237
  /**
238
- * Specify the aria-labelledby for bx--modal-container
238
+ * Specify the aria-labelledby for cds--modal-container
239
239
  */
240
240
  ['aria-labelledby']: PropTypes.string,
241
241
  /**
@@ -40,7 +40,8 @@ function useContextMenu() {
40
40
  open,
41
41
  x: position[0],
42
42
  y: position[1],
43
- onClose
43
+ onClose,
44
+ mode: 'full'
44
45
  };
45
46
  }
46
47
 
@@ -63,7 +63,7 @@ const DataTableSkeleton = _ref => {
63
63
  }, rest), /*#__PURE__*/React__default.createElement("thead", null, /*#__PURE__*/React__default.createElement("tr", null, columnsArray.map(i => /*#__PURE__*/React__default.createElement("th", {
64
64
  key: i
65
65
  }, headers ? /*#__PURE__*/React__default.createElement("div", {
66
- className: "bx--table-header-label"
66
+ className: "cds--table-header-label"
67
67
  }, headers[i]?.header) : _span2 || (_span2 = /*#__PURE__*/React__default.createElement("span", null)))))), /*#__PURE__*/React__default.createElement("tbody", null, rows)));
68
68
  };
69
69
  DataTableSkeleton.propTypes = {
@@ -277,6 +277,9 @@ const Dropdown = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
277
277
  item,
278
278
  index
279
279
  });
280
+ if (item !== null && typeof item === 'object' && Object.prototype.hasOwnProperty.call(item, 'id')) {
281
+ itemProps.id = item['id'];
282
+ }
280
283
  const title = isObject && 'text' in item && itemToElement ? item.text : itemToString(item);
281
284
  return /*#__PURE__*/React__default.createElement(ListBox.MenuItem, _extends({
282
285
  key: itemProps.id,
@@ -304,7 +307,7 @@ Dropdown.propTypes = {
304
307
  */
305
308
  ariaLabel: deprecate(PropTypes.string, 'This prop syntax has been deprecated. Please use the new `aria-label`.'),
306
309
  /**
307
- * Provide a custom className to be applied on the bx--dropdown node
310
+ * Provide a custom className to be applied on the cds--dropdown node
308
311
  */
309
312
  className: PropTypes.string,
310
313
  /**
@@ -6,6 +6,11 @@
6
6
  */
7
7
  import React, { AnchorHTMLAttributes, AriaAttributes, ComponentType, HTMLAttributeAnchorTarget } from 'react';
8
8
  export interface LinkProps extends AnchorHTMLAttributes<HTMLAnchorElement> {
9
+ /**
10
+ * Provide a custom element or component to render the top-level node for the
11
+ * component.
12
+ */
13
+ as?: string | undefined;
9
14
  /**
10
15
  * @description Indicates the element that represents the
11
16
  * current item within a container or set of related
@@ -13,6 +13,7 @@ import { usePrefix } from '../../internal/usePrefix.js';
13
13
 
14
14
  const Link = /*#__PURE__*/React__default.forwardRef(function Link(_ref, ref) {
15
15
  let {
16
+ as: BaseComponent,
16
17
  children,
17
18
  className: customClassName,
18
19
  href,
@@ -33,7 +34,7 @@ const Link = /*#__PURE__*/React__default.forwardRef(function Link(_ref, ref) {
33
34
  });
34
35
  const rel = target === '_blank' ? 'noopener' : undefined;
35
36
  const linkProps = {
36
- className,
37
+ className: BaseComponent ? undefined : className,
37
38
  rel,
38
39
  target
39
40
  };
@@ -46,7 +47,8 @@ const Link = /*#__PURE__*/React__default.forwardRef(function Link(_ref, ref) {
46
47
  linkProps.role = 'link';
47
48
  linkProps['aria-disabled'] = true;
48
49
  }
49
- return /*#__PURE__*/React__default.createElement("a", _extends({
50
+ const BaseComponentAsAny = BaseComponent ?? 'a';
51
+ return /*#__PURE__*/React__default.createElement(BaseComponentAsAny, _extends({
50
52
  ref: ref
51
53
  }, linkProps, rest), children, !inline && Icon && /*#__PURE__*/React__default.createElement("div", {
52
54
  className: `${prefix}--link__icon`
@@ -54,6 +56,11 @@ const Link = /*#__PURE__*/React__default.forwardRef(function Link(_ref, ref) {
54
56
  });
55
57
  Link.displayName = 'Link';
56
58
  Link.propTypes = {
59
+ /**
60
+ * Provide a custom element or component to render the top-level node for the
61
+ * component.
62
+ */
63
+ as: PropTypes.string,
57
64
  /**
58
65
  * Provide the content for the Link
59
66
  */
@@ -12,6 +12,7 @@ import React__default, { useRef, useContext, useReducer, useMemo, useState, useE
12
12
  import { createPortal } from 'react-dom';
13
13
  import { useMergedRefs } from '../../internal/useMergedRefs.js';
14
14
  import { usePrefix } from '../../internal/usePrefix.js';
15
+ import { warning } from '../../internal/warning.js';
15
16
  import { MenuContext, menuReducer } from './MenuContext.js';
16
17
  import { useLayoutDirection } from '../LayoutDirection/useLayoutDirection.js';
17
18
  import { match } from '../../internal/keyboard/match.js';
@@ -24,6 +25,7 @@ const Menu = /*#__PURE__*/React__default.forwardRef(function Menu(_ref, forwardR
24
25
  children,
25
26
  className,
26
27
  label,
28
+ mode = 'full',
27
29
  onClose,
28
30
  onOpen,
29
31
  open,
@@ -37,10 +39,14 @@ const Menu = /*#__PURE__*/React__default.forwardRef(function Menu(_ref, forwardR
37
39
  const focusReturn = useRef(null);
38
40
  const context = useContext(MenuContext);
39
41
  const isRoot = context.state.isRoot;
42
+ if (context.state.mode === 'basic' && !isRoot) {
43
+ process.env.NODE_ENV !== "production" ? warning(false, 'Nested menus are not supported when the menu is in "basic" mode.') : void 0;
44
+ }
40
45
  const menuSize = isRoot ? size : context.state.size;
41
46
  const [childState, childDispatch] = useReducer(menuReducer, {
42
47
  ...context.state,
43
48
  isRoot: false,
49
+ mode,
44
50
  size,
45
51
  requestCloseRoot: isRoot ? handleClose : context.state.requestCloseRoot
46
52
  });
@@ -245,6 +251,14 @@ Menu.propTypes = {
245
251
  * A label describing the Menu.
246
252
  */
247
253
  label: PropTypes.string,
254
+ /**
255
+ * The mode of this menu. Defaults to full.
256
+ * `full` supports nesting and selectable menu items, but no icons.
257
+ * `basic` supports icons but no nesting or selectable menu items.
258
+ *
259
+ * **This prop is not intended for use and will be set by the respective implementation (like useContextMenu, MenuButton, and ComboButton).**
260
+ */
261
+ mode: PropTypes.oneOf(['full', 'basic']),
248
262
  /**
249
263
  * Provide an optional function to be called when the Menu should be closed.
250
264
  */
@@ -9,6 +9,7 @@ import React__default from 'react';
9
9
 
10
10
  const menuDefaultState = {
11
11
  isRoot: true,
12
+ mode: 'full',
12
13
  hasIcons: false,
13
14
  size: null,
14
15
  items: [],
@@ -13,6 +13,7 @@ import { CaretLeft, CaretRight, Checkmark } from '@carbon/icons-react';
13
13
  import { useControllableState } from '../../internal/useControllableState.js';
14
14
  import { useMergedRefs } from '../../internal/useMergedRefs.js';
15
15
  import { usePrefix } from '../../internal/usePrefix.js';
16
+ import { warning } from '../../internal/warning.js';
16
17
  import { Menu } from './Menu.js';
17
18
  import { MenuContext } from './MenuContext.js';
18
19
  import '../Text/index.js';
@@ -143,6 +144,14 @@ const MenuItem = /*#__PURE__*/React__default.forwardRef(function MenuItem(_ref,
143
144
  setRtl(false);
144
145
  }
145
146
  }, [direction]);
147
+ const iconsAllowed = context.state.mode === 'basic' || rest.role === 'menuitemcheckbox' || rest.role === 'menuitemradio';
148
+ useEffect(() => {
149
+ if (iconsAllowed && IconElement && !context.state.hasIcons) {
150
+ context.dispatch({
151
+ type: 'enableIcons'
152
+ });
153
+ }
154
+ }, [iconsAllowed, IconElement, context.state.hasIcons, context]);
146
155
  return /*#__PURE__*/React__default.createElement("li", _extends({
147
156
  role: "menuitem"
148
157
  }, rest, {
@@ -158,7 +167,7 @@ const MenuItem = /*#__PURE__*/React__default.forwardRef(function MenuItem(_ref,
158
167
  onKeyDown: handleKeyDown
159
168
  }), /*#__PURE__*/React__default.createElement("div", {
160
169
  className: `${prefix}--menu-item__icon`
161
- }, IconElement && /*#__PURE__*/React__default.createElement(IconElement, null)), /*#__PURE__*/React__default.createElement(Text, {
170
+ }, iconsAllowed && IconElement && /*#__PURE__*/React__default.createElement(IconElement, null)), /*#__PURE__*/React__default.createElement(Text, {
162
171
  as: "div",
163
172
  className: `${prefix}--menu-item__label`
164
173
  }, label), shortcut && !hasChildren && /*#__PURE__*/React__default.createElement("div", {
@@ -202,7 +211,7 @@ MenuItem.propTypes = {
202
211
  */
203
212
  onClick: PropTypes.func,
204
213
  /**
205
- * This prop is not intended for use. The only supported icons are Checkmarks to depict single- and multi-selects. This prop is used by MenuItemSelectable and MenuItemRadioGroup automatically.
214
+ * Only applicable if the parent menu is in `basic` mode. Sets the menu item's icon.
206
215
  */
207
216
  renderIcon: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
208
217
  /**
@@ -221,6 +230,9 @@ const MenuItemSelectable = /*#__PURE__*/React__default.forwardRef(function MenuI
221
230
  } = _ref2;
222
231
  const prefix = usePrefix();
223
232
  const context = useContext(MenuContext);
233
+ if (context.state.mode === 'basic') {
234
+ process.env.NODE_ENV !== "production" ? warning(false, 'MenuItemSelectable is not supported when the menu is in "basic" mode.') : void 0;
235
+ }
224
236
  const [checked, setChecked] = useControllableState({
225
237
  value: selected,
226
238
  onChange,
@@ -246,7 +258,7 @@ const MenuItemSelectable = /*#__PURE__*/React__default.forwardRef(function MenuI
246
258
  className: classNames,
247
259
  role: "menuitemcheckbox",
248
260
  "aria-checked": checked,
249
- renderIcon: checked && Checkmark,
261
+ renderIcon: checked ? Checkmark : undefined,
250
262
  onClick: handleClick
251
263
  }));
252
264
  });
@@ -318,6 +330,9 @@ const MenuItemRadioGroup = /*#__PURE__*/React__default.forwardRef(function MenuI
318
330
  } = _ref4;
319
331
  const prefix = usePrefix();
320
332
  const context = useContext(MenuContext);
333
+ if (context.state.mode === 'basic') {
334
+ process.env.NODE_ENV !== "production" ? warning(false, 'MenuItemRadioGroup is not supported when the menu is in "basic" mode.') : void 0;
335
+ }
321
336
  const [selection, setSelection] = useControllableState({
322
337
  value: selectedItem,
323
338
  onChange,
@@ -349,7 +364,7 @@ const MenuItemRadioGroup = /*#__PURE__*/React__default.forwardRef(function MenuI
349
364
  label: itemToString(item),
350
365
  role: "menuitemradio",
351
366
  "aria-checked": item === selection,
352
- renderIcon: item === selection && Checkmark,
367
+ renderIcon: item === selection ? Checkmark : undefined,
353
368
  onClick: e => {
354
369
  handleClick(item, e);
355
370
  }
@@ -57,6 +57,7 @@ const MenuButton = /*#__PURE__*/React__default.forwardRef(function MenuButton(_r
57
57
  function handleOpen() {
58
58
  menuRef.current.style.inlineSize = `${width}px`;
59
59
  }
60
+ const containerClasses = cx(`${prefix}--menu-button__container`, className);
60
61
  const triggerClasses = cx(`${prefix}--menu-button__trigger`, {
61
62
  [`${prefix}--menu-button__trigger--open`]: open
62
63
  });
@@ -64,7 +65,7 @@ const MenuButton = /*#__PURE__*/React__default.forwardRef(function MenuButton(_r
64
65
  return /*#__PURE__*/React__default.createElement("div", _extends({}, rest, {
65
66
  ref: ref,
66
67
  "aria-owns": open ? id : null,
67
- className: className
68
+ className: containerClasses
68
69
  }), /*#__PURE__*/React__default.createElement(Button, {
69
70
  className: triggerClasses,
70
71
  size: size,
@@ -80,6 +81,7 @@ const MenuButton = /*#__PURE__*/React__default.forwardRef(function MenuButton(_r
80
81
  ref: menuRef,
81
82
  id: id,
82
83
  label: label,
84
+ mode: "basic",
83
85
  size: size,
84
86
  open: open,
85
87
  onClose: handleClose,
@@ -103,7 +103,7 @@ const Slug = /*#__PURE__*/React__default.forwardRef(function Slug(_ref3, ref) {
103
103
  onRevertClick(evt);
104
104
  }
105
105
  };
106
- const ariaLabel = `${aiText} - ${slugLabel}`;
106
+ const ariaLabel = !aiTextLabel ? `${aiText} - ${slugLabel}` : `${aiText} - ${aiTextLabel}`;
107
107
  return /*#__PURE__*/React__default.createElement("div", {
108
108
  className: slugClasses,
109
109
  ref: ref,
@@ -170,7 +170,7 @@ function SideNavRenderFunction(_ref, ref) {
170
170
  tabIndex: -1,
171
171
  ref: navRef,
172
172
  className: `${prefix}--side-nav__navigation ${className}`,
173
- inert: !isRail && (expanded || isLg ? undefined : -1)
173
+ inert: !isRail ? expanded || isLg ? undefined : -1 : undefined
174
174
  }, accessibilityLabel, eventHandlers, other), childrenToRender));
175
175
  }
176
176
  const SideNav = /*#__PURE__*/React__default.forwardRef(SideNavRenderFunction);
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Copyright IBM Corp. 2016, 2023
3
+ *
4
+ * This source code is licensed under the Apache-2.0 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ /**
8
+ * Copyright IBM Corp. 2016, 2023
9
+ *
10
+ * This source code is licensed under the Apache-2.0 license found in the
11
+ * LICENSE file in the root directory of this source tree.
12
+ */
13
+ import React, { ReactNode } from 'react';
14
+ interface BaseSwitcherProps {
15
+ /**
16
+ * expects to receive <SwitcherItem />
17
+ */
18
+ children: ReactNode;
19
+ /**
20
+ * Optionally provide a custom class to apply to the underlying `<ul>` node
21
+ */
22
+ className?: string;
23
+ /**
24
+ * Specify whether the panel is expanded
25
+ */
26
+ expanded?: boolean;
27
+ }
28
+ interface SwitcherWithAriaLabel extends BaseSwitcherProps {
29
+ 'aria-label': string;
30
+ 'aria-labelledby'?: never;
31
+ }
32
+ interface SwitcherWithAriaLabelledBy extends BaseSwitcherProps {
33
+ 'aria-label'?: never;
34
+ 'aria-labelledby': string;
35
+ }
36
+ type SwitcherProps = SwitcherWithAriaLabel | SwitcherWithAriaLabelledBy;
37
+ declare const Switcher: React.ForwardRefExoticComponent<SwitcherProps & React.RefAttributes<HTMLUListElement>>;
38
+ export default Switcher;
@@ -6,14 +6,15 @@
6
6
  */
7
7
 
8
8
  import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
9
- import React__default, { useRef } from 'react';
9
+ import React__default, { forwardRef, useRef } from 'react';
10
10
  import cx from 'classnames';
11
- import PropTypes from 'prop-types';
12
- import { AriaLabelPropType } from '../../prop-types/AriaPropTypes.js';
13
11
  import { usePrefix } from '../../internal/usePrefix.js';
14
12
  import { useMergedRefs } from '../../internal/useMergedRefs.js';
13
+ import PropTypes from 'prop-types';
14
+ import { AriaLabelPropType } from '../../prop-types/AriaPropTypes.js';
15
+ import getDisplayName from '../../prop-types/tools/getDisplayName.js';
15
16
 
16
- const Switcher = /*#__PURE__*/React__default.forwardRef(function Switcher(props, forwardRef) {
17
+ const Switcher = /*#__PURE__*/forwardRef(function Switcher(props, forwardRef) {
17
18
  const switcherRef = useRef(null);
18
19
  const ref = useMergedRefs([switcherRef, forwardRef]);
19
20
  const prefix = usePrefix();
@@ -29,7 +30,7 @@ const Switcher = /*#__PURE__*/React__default.forwardRef(function Switcher(props,
29
30
  'aria-labelledby': ariaLabelledBy
30
31
  };
31
32
  const className = cx(`${prefix}--switcher`, {
32
- [customClassName]: !!customClassName
33
+ [customClassName || '']: !!customClassName
33
34
  });
34
35
  const handleSwitcherItemFocus = _ref => {
35
36
  let {
@@ -54,13 +55,14 @@ const Switcher = /*#__PURE__*/React__default.forwardRef(function Switcher(props,
54
55
  return enabledIndices[nextIndex];
55
56
  }
56
57
  })();
57
- const switcherItem = switcherRef.current.children[nextValidIndex].children[0];
58
- switcherItem?.focus();
58
+ const switcherItem = switcherRef.current?.children[nextValidIndex]?.children[0];
59
+ if (switcherItem) {
60
+ switcherItem.focus();
61
+ }
59
62
  };
60
- const childrenWithProps = React__default.Children.toArray(children).map((child, index) => {
61
- // handleSwitcherItemFocus should only be passed down if the child is a SwitcherItem
62
- // SwitcherDivider, for example, does not accept a handleSwitcherItemFocus prop
63
- if (child.type?.displayName === 'SwitcherItem') {
63
+ const childrenWithProps = React__default.Children.map(children, (child, index) => {
64
+ // only setup click handlers if onChange event is passed
65
+ if ( /*#__PURE__*/React__default.isValidElement(child) && child.type && getDisplayName(child.type) === 'Switcher') {
64
66
  return /*#__PURE__*/React__default.cloneElement(child, {
65
67
  handleSwitcherItemFocus,
66
68
  index,
@@ -98,6 +100,5 @@ Switcher.propTypes = {
98
100
  */
99
101
  expanded: PropTypes.bool
100
102
  };
101
- var Switcher$1 = Switcher;
102
103
 
103
- export { Switcher$1 as default };
104
+ export { Switcher as default };
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ interface SwitcherDividerProps {
3
+ /**
4
+ * Optionally provide a custom class to apply to the underlying `<li>` node
5
+ */
6
+ className?: string;
7
+ }
8
+ declare const SwitcherDivider: React.FC<SwitcherDividerProps>;
9
+ export default SwitcherDivider;
@@ -17,11 +17,11 @@ const SwitcherDivider = _ref => {
17
17
  ...other
18
18
  } = _ref;
19
19
  const prefix = usePrefix();
20
- const className = cx(`${prefix}--switcher__item--divider`, {
21
- [customClassName]: !!customClassName
20
+ const classNames = cx(`${prefix}--switcher__item--divider`, {
21
+ [customClassName || '']: !!customClassName
22
22
  });
23
23
  return /*#__PURE__*/React__default.createElement("hr", _extends({}, other, {
24
- className: className
24
+ className: classNames
25
25
  }));
26
26
  };
27
27
  SwitcherDivider.propTypes = {
@@ -30,6 +30,5 @@ SwitcherDivider.propTypes = {
30
30
  */
31
31
  className: PropTypes.string
32
32
  };
33
- var SwitcherDivider$1 = SwitcherDivider;
34
33
 
35
- export { SwitcherDivider$1 as default };
34
+ export { SwitcherDivider as default };
@@ -0,0 +1,49 @@
1
+ import React from 'react';
2
+ interface BaseSwitcherItemProps {
3
+ /**
4
+ * Specify the text content for the link
5
+ */
6
+ children: React.ReactNode;
7
+ /**
8
+ * Optionally provide a custom class to apply to the underlying `<li>` node
9
+ */
10
+ className?: string;
11
+ /**
12
+ * event handlers
13
+ */
14
+ handleSwitcherItemFocus?: (event: {
15
+ currentIndex: number;
16
+ direction: number;
17
+ }) => void;
18
+ /**
19
+ * Specify the index of the SwitcherItem
20
+ */
21
+ index?: number;
22
+ /**
23
+ * event handlers
24
+ */
25
+ onKeyDown?: (event: KeyboardEvent) => void;
26
+ /**
27
+ * Specify the tab index of the Link
28
+ */
29
+ tabIndex?: number;
30
+ /**
31
+ * Specify whether the panel is expanded
32
+ */
33
+ expanded?: boolean;
34
+ /**
35
+ * Specify whether the panel is selected
36
+ */
37
+ isSelected?: boolean;
38
+ }
39
+ interface SwitcherItemWithAriaLabel extends BaseSwitcherItemProps {
40
+ 'aria-label': string;
41
+ 'aria-labelledby'?: never;
42
+ }
43
+ interface SwitcherItemWithAriaLabelledBy extends BaseSwitcherItemProps {
44
+ 'aria-label'?: never;
45
+ 'aria-labelledby': string;
46
+ }
47
+ type SwitcherItemProps = SwitcherItemWithAriaLabel | SwitcherItemWithAriaLabelledBy;
48
+ declare const SwitcherItem: React.ForwardRefExoticComponent<SwitcherItemProps & React.RefAttributes<React.ElementType<any>>>;
49
+ export default SwitcherItem;
@@ -6,17 +6,17 @@
6
6
  */
7
7
 
8
8
  import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
9
- import React__default from 'react';
9
+ import React__default, { forwardRef } from 'react';
10
10
  import cx from 'classnames';
11
11
  import PropTypes from 'prop-types';
12
- import { AriaLabelPropType } from '../../prop-types/AriaPropTypes.js';
13
12
  import Link from './Link.js';
14
13
  import { usePrefix } from '../../internal/usePrefix.js';
14
+ import { AriaLabelPropType } from '../../prop-types/AriaPropTypes.js';
15
15
  import { match } from '../../internal/keyboard/match.js';
16
16
  import { ArrowDown, ArrowUp } from '../../internal/keyboard/keys.js';
17
17
 
18
- const SwitcherItem = /*#__PURE__*/React__default.forwardRef(function SwitcherItem(_ref, ref) {
19
- let {
18
+ const SwitcherItem = /*#__PURE__*/forwardRef(function SwitcherItem(props, forwardRef) {
19
+ const {
20
20
  'aria-label': ariaLabel,
21
21
  'aria-labelledby': ariaLabelledBy,
22
22
  className: customClassName,
@@ -28,10 +28,10 @@ const SwitcherItem = /*#__PURE__*/React__default.forwardRef(function SwitcherIte
28
28
  handleSwitcherItemFocus,
29
29
  onKeyDown = () => {},
30
30
  ...rest
31
- } = _ref;
31
+ } = props;
32
32
  const prefix = usePrefix();
33
- const className = cx(`${prefix}--switcher__item`, {
34
- [customClassName]: !!customClassName
33
+ const classNames = cx(`${prefix}--switcher__item`, {
34
+ [customClassName || '']: !!customClassName
35
35
  });
36
36
  const accessibilityLabel = {
37
37
  'aria-label': ariaLabel,
@@ -44,36 +44,33 @@ const SwitcherItem = /*#__PURE__*/React__default.forwardRef(function SwitcherIte
44
44
  if (match(evt, ArrowDown)) {
45
45
  evt.preventDefault();
46
46
  handleSwitcherItemFocus?.({
47
- currentIndex: index,
47
+ currentIndex: index || -1,
48
48
  direction: 1
49
49
  });
50
50
  }
51
51
  if (match(evt, ArrowUp)) {
52
52
  evt.preventDefault();
53
53
  handleSwitcherItemFocus?.({
54
- currentIndex: index,
54
+ currentIndex: index || -1,
55
55
  direction: -1
56
56
  });
57
57
  }
58
58
  }
59
59
  return /*#__PURE__*/React__default.createElement("li", {
60
- className: className
60
+ className: classNames
61
61
  }, /*#__PURE__*/React__default.createElement(Link, _extends({
62
62
  onKeyDown: evt => {
63
63
  setTabFocus(evt);
64
64
  onKeyDown(evt);
65
- }
65
+ },
66
+ ref: forwardRef
66
67
  }, rest, {
67
- ref: ref,
68
68
  className: linkClassName,
69
69
  tabIndex: tabIndex
70
70
  }, accessibilityLabel), children));
71
71
  });
72
72
  SwitcherItem.displayName = 'SwitcherItem';
73
73
  SwitcherItem.propTypes = {
74
- /**
75
- * Required props for accessibility label on the underlying menuitem
76
- */
77
74
  ...AriaLabelPropType,
78
75
  /**
79
76
  * Specify the text content for the link
@@ -100,6 +97,5 @@ SwitcherItem.propTypes = {
100
97
  */
101
98
  tabIndex: PropTypes.number
102
99
  };
103
- var SwitcherItem$1 = SwitcherItem;
104
100
 
105
- export { SwitcherItem$1 as default };
101
+ export { SwitcherItem as default };
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Copyright IBM Corp. 2016, 2023
3
+ *
4
+ * This source code is licensed under the Apache-2.0 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ const cachedDisplayNames = new WeakMap();
9
+
10
+ /**
11
+ * `getDisplayName` is a utility function for getting a name from a given
12
+ * component type. It supports names from React elements, Stateless Functional
13
+ * Components, and Class-based Components
14
+ */
15
+ const getDisplayName = type => {
16
+ if (typeof type === 'string') {
17
+ return type;
18
+ }
19
+ if (cachedDisplayNames.has(type)) {
20
+ return cachedDisplayNames.get(type);
21
+ }
22
+ let displayName;
23
+ if (typeof type.displayName === 'string') {
24
+ displayName = type.displayName;
25
+ }
26
+ if (!displayName) {
27
+ displayName = type.name || 'Unknown';
28
+ }
29
+ cachedDisplayNames.set(type, displayName);
30
+ return displayName;
31
+ };
32
+ var getDisplayName$1 = getDisplayName;
33
+
34
+ export { getDisplayName$1 as default };