@carbon/react 1.43.0-rc.0 → 1.44.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 (82) hide show
  1. package/.playwright/INTERNAL_AVT_REPORT_DO_NOT_USE.json +1024 -905
  2. package/es/components/Accordion/AccordionItem.d.ts +1 -1
  3. package/es/components/Accordion/AccordionItem.js +19 -15
  4. package/es/components/Checkbox/Checkbox.d.ts +4 -0
  5. package/es/components/Checkbox/Checkbox.js +15 -2
  6. package/es/components/CheckboxGroup/CheckboxGroup.js +17 -2
  7. package/es/components/ComboBox/ComboBox.js +12 -0
  8. package/es/components/ComboButton/index.js +2 -1
  9. package/es/components/ComposedModal/ComposedModal.d.ts +3 -3
  10. package/es/components/ComposedModal/ComposedModal.js +3 -3
  11. package/es/components/ContextMenu/useContextMenu.js +2 -1
  12. package/es/components/DataTable/tools/sorting.js +1 -1
  13. package/es/components/DataTableSkeleton/DataTableSkeleton.js +1 -1
  14. package/es/components/Dropdown/Dropdown.js +4 -1
  15. package/es/components/FileUploader/FileUploader.js +5 -3
  16. package/es/components/Grid/Column.js +11 -1
  17. package/es/components/Link/Link.d.ts +5 -0
  18. package/es/components/Link/Link.js +9 -2
  19. package/es/components/Menu/Menu.js +14 -0
  20. package/es/components/Menu/MenuContext.js +1 -0
  21. package/es/components/Menu/MenuItem.js +19 -4
  22. package/es/components/MenuButton/index.js +10 -2
  23. package/es/components/RadioButton/RadioButton.d.ts +4 -0
  24. package/es/components/RadioButton/RadioButton.js +15 -2
  25. package/es/components/RadioButtonGroup/RadioButtonGroup.d.ts +4 -0
  26. package/es/components/RadioButtonGroup/RadioButtonGroup.js +17 -2
  27. package/es/components/Select/Select.d.ts +1 -1
  28. package/es/components/Slug/index.js +2 -2
  29. package/es/components/Tile/Tile.d.ts +37 -0
  30. package/es/components/Tile/Tile.js +110 -13
  31. package/es/components/UIShell/Content.d.ts +296 -0
  32. package/es/components/UIShell/Content.js +1 -2
  33. package/es/components/UIShell/SideNav.d.ts +1 -1
  34. package/es/components/UIShell/SideNav.js +1 -1
  35. package/es/components/UIShell/Switcher.d.ts +38 -0
  36. package/es/components/UIShell/Switcher.js +14 -13
  37. package/es/components/UIShell/SwitcherDivider.d.ts +9 -0
  38. package/es/components/UIShell/SwitcherDivider.js +4 -5
  39. package/es/components/UIShell/SwitcherItem.d.ts +49 -0
  40. package/es/components/UIShell/SwitcherItem.js +13 -17
  41. package/es/prop-types/tools/getDisplayName.js +34 -0
  42. package/lib/components/Accordion/AccordionItem.d.ts +1 -1
  43. package/lib/components/Accordion/AccordionItem.js +18 -14
  44. package/lib/components/Checkbox/Checkbox.d.ts +4 -0
  45. package/lib/components/Checkbox/Checkbox.js +15 -2
  46. package/lib/components/CheckboxGroup/CheckboxGroup.js +17 -2
  47. package/lib/components/ComboBox/ComboBox.js +12 -0
  48. package/lib/components/ComboButton/index.js +2 -1
  49. package/lib/components/ComposedModal/ComposedModal.d.ts +3 -3
  50. package/lib/components/ComposedModal/ComposedModal.js +3 -3
  51. package/lib/components/ContextMenu/useContextMenu.js +2 -1
  52. package/lib/components/DataTable/tools/sorting.js +1 -1
  53. package/lib/components/DataTableSkeleton/DataTableSkeleton.js +1 -1
  54. package/lib/components/Dropdown/Dropdown.js +4 -1
  55. package/lib/components/FileUploader/FileUploader.js +5 -3
  56. package/lib/components/Grid/Column.js +11 -1
  57. package/lib/components/Link/Link.d.ts +5 -0
  58. package/lib/components/Link/Link.js +9 -2
  59. package/lib/components/Menu/Menu.js +14 -0
  60. package/lib/components/Menu/MenuContext.js +1 -0
  61. package/lib/components/Menu/MenuItem.js +19 -4
  62. package/lib/components/MenuButton/index.js +10 -2
  63. package/lib/components/RadioButton/RadioButton.d.ts +4 -0
  64. package/lib/components/RadioButton/RadioButton.js +15 -2
  65. package/lib/components/RadioButtonGroup/RadioButtonGroup.d.ts +4 -0
  66. package/lib/components/RadioButtonGroup/RadioButtonGroup.js +17 -2
  67. package/lib/components/Select/Select.d.ts +1 -1
  68. package/lib/components/Slug/index.js +2 -2
  69. package/lib/components/Tile/Tile.d.ts +37 -0
  70. package/lib/components/Tile/Tile.js +110 -13
  71. package/lib/components/UIShell/Content.d.ts +296 -0
  72. package/lib/components/UIShell/Content.js +1 -2
  73. package/lib/components/UIShell/SideNav.d.ts +1 -1
  74. package/lib/components/UIShell/SideNav.js +1 -1
  75. package/lib/components/UIShell/Switcher.d.ts +38 -0
  76. package/lib/components/UIShell/Switcher.js +13 -12
  77. package/lib/components/UIShell/SwitcherDivider.d.ts +9 -0
  78. package/lib/components/UIShell/SwitcherDivider.js +4 -5
  79. package/lib/components/UIShell/SwitcherItem.d.ts +49 -0
  80. package/lib/components/UIShell/SwitcherItem.js +12 -16
  81. package/lib/prop-types/tools/getDisplayName.js +38 -0
  82. package/package.json +5 -5
@@ -47,7 +47,7 @@ interface AccordionItemProps {
47
47
  * The callback function to run on the `onAnimationEnd`
48
48
  * event for the list item.
49
49
  */
50
- handleAnimationEnd?: AnimationEventHandler<HTMLLIElement>;
50
+ handleAnimationEnd?: AnimationEventHandler<HTMLElement>;
51
51
  }
52
52
  interface AccordionToggleProps {
53
53
  'aria-controls'?: AriaAttributes['aria-controls'];
@@ -9,7 +9,7 @@ import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js
9
9
  import { ChevronRight } from '@carbon/icons-react';
10
10
  import cx from 'classnames';
11
11
  import PropTypes from 'prop-types';
12
- import React__default, { useState, useContext } from 'react';
12
+ import React__default, { useState, useContext, useRef } from 'react';
13
13
  import '../Text/index.js';
14
14
  import { useId } from '../../internal/useId.js';
15
15
  import deprecate from '../../prop-types/deprecate.js';
@@ -37,8 +37,6 @@ function AccordionItem(_ref) {
37
37
  ...rest
38
38
  } = _ref;
39
39
  const [isOpen, setIsOpen] = useState(open);
40
- const [prevIsOpen, setPrevIsOpen] = useState(open);
41
- const [animation, setAnimation] = useState('');
42
40
  const accordionState = useContext(AccordionContext);
43
41
  const disabledIsControlled = typeof controlledDisabled === 'boolean';
44
42
  const disabled = disabledIsControlled ? controlledDisabled : accordionState.disabled;
@@ -47,23 +45,28 @@ function AccordionItem(_ref) {
47
45
  const className = cx({
48
46
  [`${prefix}--accordion__item`]: true,
49
47
  [`${prefix}--accordion__item--active`]: isOpen,
50
- [`${prefix}--accordion__item--${animation}`]: animation,
51
48
  [`${prefix}--accordion__item--disabled`]: disabled,
52
49
  [customClassName]: !!customClassName
53
50
  });
54
51
  const Toggle = renderToggle || renderExpando; // remove renderExpando in next major release
55
52
 
56
- if (open !== prevIsOpen) {
57
- setAnimation(isOpen ? 'collapsing' : 'expanding');
58
- setIsOpen(open);
59
- setPrevIsOpen(open);
60
- }
53
+ const content = useRef(null);
61
54
 
62
55
  // When the AccordionItem heading is clicked, toggle the open state of the
63
56
  // panel
64
57
  function onClick(event) {
58
+ // type guard for ref
59
+ if (!content.current) {
60
+ return;
61
+ }
62
+ if (isOpen) {
63
+ // accordion closes
64
+ content.current.style.maxBlockSize = '';
65
+ } else {
66
+ // accordion opens
67
+ content.current.style.maxBlockSize = content.current.scrollHeight + 15 + 'px';
68
+ }
65
69
  const nextValue = !isOpen;
66
- setAnimation(isOpen ? 'collapsing' : 'expanding');
67
70
  setIsOpen(nextValue);
68
71
  if (onHeadingClick) {
69
72
  // TODO: normalize signature, potentially:
@@ -85,13 +88,10 @@ function AccordionItem(_ref) {
85
88
  if (handleAnimationEnd) {
86
89
  handleAnimationEnd(event);
87
90
  }
88
- setAnimation('');
89
91
  }
90
92
  return /*#__PURE__*/React__default.createElement("li", _extends({
91
93
  className: className
92
- }, rest, {
93
- onAnimationEnd: onAnimationEnd
94
- }), /*#__PURE__*/React__default.createElement(Toggle, {
94
+ }, rest), /*#__PURE__*/React__default.createElement(Toggle, {
95
95
  disabled: disabled,
96
96
  "aria-controls": id,
97
97
  "aria-expanded": isOpen,
@@ -105,9 +105,13 @@ function AccordionItem(_ref) {
105
105
  as: "div",
106
106
  className: `${prefix}--accordion__title`
107
107
  }, title)), /*#__PURE__*/React__default.createElement("div", {
108
+ ref: content,
109
+ className: `${prefix}--accordion__wrapper`,
110
+ onTransitionEnd: onAnimationEnd
111
+ }, /*#__PURE__*/React__default.createElement("div", {
108
112
  id: id,
109
113
  className: `${prefix}--accordion__content`
110
- }, children));
114
+ }, children)));
111
115
  }
112
116
  AccordionItem.propTypes = {
113
117
  /**
@@ -45,6 +45,10 @@ export interface CheckboxProps extends Omit<React.InputHTMLAttributes<HTMLInputE
45
45
  * Provide the text that is displayed when the Checkbox is in an invalid state
46
46
  */
47
47
  invalidText?: React.ReactNode;
48
+ /**
49
+ * Provide a `Slug` component to be rendered inside the `Checkbox` component
50
+ */
51
+ slug?: ReactNodeLike;
48
52
  /**
49
53
  * Specify whether the Checkbox is currently invalid
50
54
  */
@@ -33,6 +33,7 @@ const Checkbox = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
33
33
  title = '',
34
34
  warn,
35
35
  warnText,
36
+ slug,
36
37
  ...other
37
38
  } = _ref;
38
39
  const prefix = usePrefix();
@@ -47,11 +48,19 @@ const Checkbox = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
47
48
  const wrapperClasses = cx(`${prefix}--form-item`, `${prefix}--checkbox-wrapper`, className, {
48
49
  [`${prefix}--checkbox-wrapper--readonly`]: readOnly,
49
50
  [`${prefix}--checkbox-wrapper--invalid`]: !readOnly && invalid,
50
- [`${prefix}--checkbox-wrapper--warning`]: showWarning
51
+ [`${prefix}--checkbox-wrapper--warning`]: showWarning,
52
+ [`${prefix}--checkbox-wrapper--slug`]: slug
51
53
  });
52
54
  const innerLabelClasses = cx(`${prefix}--checkbox-label-text`, {
53
55
  [`${prefix}--visually-hidden`]: hideLabel
54
56
  });
57
+ let normalizedSlug;
58
+ if (slug && /*#__PURE__*/React__default.isValidElement(slug)) {
59
+ const size = slug.props?.['kind'] === 'inline' ? 'md' : 'mini';
60
+ normalizedSlug = /*#__PURE__*/React__default.cloneElement(slug, {
61
+ size
62
+ });
63
+ }
55
64
  return /*#__PURE__*/React__default.createElement("div", {
56
65
  className: wrapperClasses
57
66
  }, /*#__PURE__*/React__default.createElement("input", _extends({}, other, {
@@ -97,7 +106,7 @@ const Checkbox = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
97
106
  title: title
98
107
  }, /*#__PURE__*/React__default.createElement(Text, {
99
108
  className: innerLabelClasses
100
- }, labelText)), /*#__PURE__*/React__default.createElement("div", {
109
+ }, labelText, normalizedSlug)), /*#__PURE__*/React__default.createElement("div", {
101
110
  className: `${prefix}--checkbox__validation-msg`
102
111
  }, !readOnly && invalid && /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(WarningFilled, {
103
112
  className: `${prefix}--checkbox__invalid-icon`
@@ -165,6 +174,10 @@ Checkbox.propTypes = {
165
174
  * Specify whether the Checkbox is read-only
166
175
  */
167
176
  readOnly: PropTypes.bool,
177
+ /**
178
+ * Provide a `Slug` component to be rendered inside the `Checkbox` component
179
+ */
180
+ slug: PropTypes.node,
168
181
  /**
169
182
  * Specify a title for the <label> node for the Checkbox
170
183
  */
@@ -26,6 +26,7 @@ function CheckboxGroup(_ref) {
26
26
  readOnly,
27
27
  warn,
28
28
  warnText,
29
+ slug,
29
30
  ...rest
30
31
  } = _ref;
31
32
  const prefix = usePrefix();
@@ -40,8 +41,18 @@ function CheckboxGroup(_ref) {
40
41
  const fieldsetClasses = cx(`${prefix}--checkbox-group`, className, {
41
42
  [`${prefix}--checkbox-group--readonly`]: readOnly,
42
43
  [`${prefix}--checkbox-group--invalid`]: !readOnly && invalid,
43
- [`${prefix}--checkbox-group--warning`]: showWarning
44
+ [`${prefix}--checkbox-group--warning`]: showWarning,
45
+ [`${prefix}--checkbox-group--slug`]: slug
44
46
  });
47
+
48
+ // Slug is always size `mini`
49
+ let normalizedSlug;
50
+ if (slug) {
51
+ normalizedSlug = /*#__PURE__*/React__default.cloneElement(slug, {
52
+ size: 'mini',
53
+ kind: 'default'
54
+ });
55
+ }
45
56
  return /*#__PURE__*/React__default.createElement("fieldset", _extends({
46
57
  className: fieldsetClasses,
47
58
  "data-invalid": invalid ? true : undefined,
@@ -51,7 +62,7 @@ function CheckboxGroup(_ref) {
51
62
  }, rest), /*#__PURE__*/React__default.createElement("legend", {
52
63
  className: `${prefix}--label`,
53
64
  id: legendId || rest['aria-labelledby']
54
- }, legendText), children, /*#__PURE__*/React__default.createElement("div", {
65
+ }, legendText, normalizedSlug), children, /*#__PURE__*/React__default.createElement("div", {
55
66
  className: `${prefix}--checkbox-group__validation-msg`
56
67
  }, !readOnly && invalid && /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(WarningFilled, {
57
68
  className: `${prefix}--checkbox__invalid-icon`
@@ -97,6 +108,10 @@ CheckboxGroup.propTypes = {
97
108
  * Whether the CheckboxGroup should be read-only
98
109
  */
99
110
  readOnly: PropTypes.bool,
111
+ /**
112
+ * Provide a `Slug` component to be rendered inside the `CheckboxGroup` component
113
+ */
114
+ slug: PropTypes.node,
100
115
  /**
101
116
  * Specify whether the form group is currently in warning state
102
117
  */
@@ -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
 
@@ -33,7 +33,7 @@ const compare = function (a, b) {
33
33
 
34
34
  // if column has React elements, this should sort by the child string if there is one
35
35
  if (typeof a === 'object' && typeof b === 'object') {
36
- if (typeof a.props.children === 'string' && typeof b.props.children === 'string') {
36
+ if (typeof a.props?.children === 'string' && typeof b.props?.children === 'string') {
37
37
  return compareStrings(a.props.children, b.props.children, locale);
38
38
  }
39
39
  }
@@ -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
  /**
@@ -106,11 +106,12 @@ class FileUploader extends React__default.Component {
106
106
  return /*#__PURE__*/React__default.createElement("div", _extends({
107
107
  className: classes
108
108
  }, other), !labelTitle ? null : /*#__PURE__*/React__default.createElement(Text, {
109
- as: "p",
109
+ as: "h3",
110
110
  className: getHelperLabelClasses(`${prefix}--file--label`)
111
111
  }, labelTitle), /*#__PURE__*/React__default.createElement(Text, {
112
112
  as: "p",
113
- className: getHelperLabelClasses(`${prefix}--label-description`)
113
+ className: getHelperLabelClasses(`${prefix}--label-description`),
114
+ id: "description"
114
115
  }, labelDescription), /*#__PURE__*/React__default.createElement(FileUploaderButton, {
115
116
  innerRef: this.uploaderButton,
116
117
  disabled: disabled,
@@ -121,7 +122,8 @@ class FileUploader extends React__default.Component {
121
122
  disableLabelChanges: true,
122
123
  accept: accept,
123
124
  name: name,
124
- size: size
125
+ size: size,
126
+ "aria-describedby": "description"
125
127
  }), /*#__PURE__*/React__default.createElement("div", {
126
128
  className: `${prefix}--file-container`
127
129
  }, this.state.filenames.length === 0 ? null : this.state.filenames.map((name, index) => /*#__PURE__*/React__default.createElement("span", _extends({
@@ -102,6 +102,11 @@ Column.propTypes = {
102
102
  * @see https://www.carbondesignsystem.com/guidelines/layout#breakpoints
103
103
  */
104
104
  sm: spanPropType,
105
+ /**
106
+ * Specify constant column span, start, or end values that will not change
107
+ * based on breakpoint
108
+ */
109
+ span: PropTypes.oneOfType([PropTypes.number, percentSpanType]),
105
110
  /**
106
111
  * Specify column span for the `xlg` breakpoint (Default breakpoint up to
107
112
  * 1584px) This breakpoint supports 16 columns by default.
@@ -311,8 +316,13 @@ function getClassNameForFlexGridBreakpoints(breakpoints, prefix) {
311
316
  */
312
317
  function getClassNameForSpan(value, prefix) {
313
318
  const classNames = [];
314
- if (typeof value === 'number' || typeof value === 'string') {
319
+ if (typeof value === 'number') {
315
320
  classNames.push(`${prefix}--col-span-${value}`);
321
+ }
322
+ // If value is a string, the user has specified a percent
323
+ // they'd like this column to span.
324
+ else if (typeof value === 'string') {
325
+ classNames.push(`${prefix}--col-span-${value.slice(0, -1)}`);
316
326
  } else if (typeof value === 'object') {
317
327
  const {
318
328
  span,
@@ -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
  }
@@ -29,6 +29,7 @@ const MenuButton = /*#__PURE__*/React__default.forwardRef(function MenuButton(_r
29
29
  kind = defaultButtonKind,
30
30
  label,
31
31
  size = 'lg',
32
+ tabIndex = 0,
32
33
  ...rest
33
34
  } = _ref;
34
35
  const id = useId('MenuButton');
@@ -57,6 +58,7 @@ const MenuButton = /*#__PURE__*/React__default.forwardRef(function MenuButton(_r
57
58
  function handleOpen() {
58
59
  menuRef.current.style.inlineSize = `${width}px`;
59
60
  }
61
+ const containerClasses = cx(`${prefix}--menu-button__container`, className);
60
62
  const triggerClasses = cx(`${prefix}--menu-button__trigger`, {
61
63
  [`${prefix}--menu-button__trigger--open`]: open
62
64
  });
@@ -64,10 +66,11 @@ const MenuButton = /*#__PURE__*/React__default.forwardRef(function MenuButton(_r
64
66
  return /*#__PURE__*/React__default.createElement("div", _extends({}, rest, {
65
67
  ref: ref,
66
68
  "aria-owns": open ? id : null,
67
- className: className
69
+ className: containerClasses
68
70
  }), /*#__PURE__*/React__default.createElement(Button, {
69
71
  className: triggerClasses,
70
72
  size: size,
73
+ tabIndex: tabIndex,
71
74
  kind: buttonKind,
72
75
  renderIcon: ChevronDown,
73
76
  disabled: disabled,
@@ -80,6 +83,7 @@ const MenuButton = /*#__PURE__*/React__default.forwardRef(function MenuButton(_r
80
83
  ref: menuRef,
81
84
  id: id,
82
85
  label: label,
86
+ mode: "basic",
83
87
  size: size,
84
88
  open: open,
85
89
  onClose: handleClose,
@@ -112,7 +116,11 @@ MenuButton.propTypes = {
112
116
  /**
113
117
  * Specify the size of the button and menu.
114
118
  */
115
- size: PropTypes.oneOf(['sm', 'md', 'lg'])
119
+ size: PropTypes.oneOf(['sm', 'md', 'lg']),
120
+ /**
121
+ * Specify the tabIndex of the button.
122
+ */
123
+ tabIndex: PropTypes.number
116
124
  };
117
125
 
118
126
  export { MenuButton };
@@ -55,6 +55,10 @@ export interface RadioButtonProps extends Omit<React.InputHTMLAttributes<HTMLInp
55
55
  * Provide a handler that is invoked when a user clicks on the control
56
56
  */
57
57
  onClick?: (evt: React.MouseEvent<HTMLInputElement>) => void;
58
+ /**
59
+ * Provide a `Slug` component to be rendered inside the `RadioButton` component
60
+ */
61
+ slug?: ReactNodeLike;
58
62
  /**
59
63
  * Specify the value of the `<RadioButton>`
60
64
  */