@carbon/react 1.49.0 → 1.50.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 (56) hide show
  1. package/.playwright/INTERNAL_AVT_REPORT_DO_NOT_USE.json +1074 -996
  2. package/es/components/Accordion/AccordionItem.js +10 -15
  3. package/es/components/Button/Button.js +3 -2
  4. package/es/components/ChatButton/ChatButton.Skeleton.js +40 -0
  5. package/es/components/ChatButton/ChatButton.js +81 -0
  6. package/es/components/ComboButton/index.js +14 -0
  7. package/es/components/ContainedList/ContainedList.js +5 -3
  8. package/es/components/ContainedList/ContainedListItem/ContainedListItem.js +5 -3
  9. package/es/components/DataTable/DataTable.d.ts +21 -0
  10. package/es/components/DataTable/DataTable.js +19 -0
  11. package/es/components/DataTable/TableCell.d.ts +28 -3
  12. package/es/components/DataTable/TableCell.js +22 -5
  13. package/es/components/DataTable/TableExpandRow.js +1 -1
  14. package/es/components/DataTable/TableHeader.js +2 -2
  15. package/es/components/DataTable/TableRow.js +12 -1
  16. package/es/components/DataTable/tools/normalize.js +3 -1
  17. package/es/components/Menu/Menu.d.ts +9 -1
  18. package/es/components/Menu/Menu.js +34 -0
  19. package/es/components/MenuButton/index.js +13 -0
  20. package/es/components/MultiSelect/MultiSelect.js +2 -1
  21. package/es/components/Notification/Notification.d.ts +75 -0
  22. package/es/components/Notification/Notification.js +84 -2
  23. package/es/components/Notification/index.d.ts +1 -1
  24. package/es/components/OverflowMenu/next/index.js +16 -2
  25. package/es/index.d.ts +1 -0
  26. package/es/index.js +3 -1
  27. package/es/internal/useNoInteractiveChildren.js +13 -1
  28. package/lib/components/Accordion/AccordionItem.js +9 -14
  29. package/lib/components/Button/Button.js +3 -2
  30. package/lib/components/ChatButton/ChatButton.Skeleton.js +50 -0
  31. package/lib/components/ChatButton/ChatButton.js +91 -0
  32. package/lib/components/ComboButton/index.js +14 -0
  33. package/lib/components/ContainedList/ContainedList.js +5 -3
  34. package/lib/components/ContainedList/ContainedListItem/ContainedListItem.js +5 -3
  35. package/lib/components/DataTable/DataTable.d.ts +21 -0
  36. package/lib/components/DataTable/DataTable.js +19 -0
  37. package/lib/components/DataTable/TableCell.d.ts +28 -3
  38. package/lib/components/DataTable/TableCell.js +27 -5
  39. package/lib/components/DataTable/TableExpandRow.js +1 -1
  40. package/lib/components/DataTable/TableHeader.js +2 -2
  41. package/lib/components/DataTable/TableRow.js +12 -1
  42. package/lib/components/DataTable/tools/normalize.js +3 -1
  43. package/lib/components/Menu/Menu.d.ts +9 -1
  44. package/lib/components/Menu/Menu.js +34 -0
  45. package/lib/components/MenuButton/index.js +13 -0
  46. package/lib/components/MultiSelect/MultiSelect.js +2 -1
  47. package/lib/components/Notification/Notification.d.ts +75 -0
  48. package/lib/components/Notification/Notification.js +83 -0
  49. package/lib/components/Notification/index.d.ts +1 -1
  50. package/lib/components/OverflowMenu/next/index.js +16 -2
  51. package/lib/index.d.ts +1 -0
  52. package/lib/index.js +5 -0
  53. package/lib/internal/useNoInteractiveChildren.js +13 -0
  54. package/package.json +5 -5
  55. package/scss/components/chat-button/_chat-button.scss +9 -0
  56. package/scss/components/chat-button/_index.scss +9 -0
@@ -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, useRef } from 'react';
12
+ import React__default, { useState, useContext } 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';
@@ -51,7 +51,15 @@ function AccordionItem(_ref) {
51
51
  });
52
52
  const Toggle = renderToggle || renderExpando; // remove renderExpando in next major release
53
53
 
54
- const content = useRef(null);
54
+ const content = React__default.useCallback(node => {
55
+ if (!node) {
56
+ return;
57
+ }
58
+ if (isOpen) {
59
+ // accordion closes
60
+ node.style.maxBlockSize = '';
61
+ }
62
+ }, [isOpen]);
55
63
  if (open !== prevIsOpen) {
56
64
  setIsOpen(open);
57
65
  setPrevIsOpen(open);
@@ -60,19 +68,6 @@ function AccordionItem(_ref) {
60
68
  // When the AccordionItem heading is clicked, toggle the open state of the
61
69
  // panel
62
70
  function onClick(event) {
63
- // type guard for ref
64
- if (!content.current) {
65
- return;
66
- }
67
- if (isOpen) {
68
- // accordion closes
69
- content.current.style.maxBlockSize = '';
70
- } else {
71
- // accordion opens
72
- content.current.style.maxBlockSize =
73
- // Scroll height plus top/bottom padding
74
- content.current.scrollHeight + 32 + 'px';
75
- }
76
71
  const nextValue = !isOpen;
77
72
  setIsOpen(nextValue);
78
73
  if (onHeadingClick) {
@@ -90,12 +90,13 @@ const Button = /*#__PURE__*/React__default.forwardRef(function Button(_ref, ref)
90
90
  let component = 'button';
91
91
  const assistiveId = useId('danger-description');
92
92
  const {
93
- 'aria-pressed': ariaPressed
93
+ 'aria-pressed': ariaPressed,
94
+ 'aria-describedby': ariaDescribedBy
94
95
  } = rest;
95
96
  let otherProps = {
96
97
  disabled,
97
98
  type,
98
- 'aria-describedby': dangerButtonVariants.includes(kind) ? assistiveId : undefined,
99
+ 'aria-describedby': dangerButtonVariants.includes(kind) ? assistiveId : ariaDescribedBy || undefined,
99
100
  'aria-pressed': ariaPressed ?? (hasIconOnly && kind === 'ghost' ? isSelected : undefined)
100
101
  };
101
102
  const anchorProps = {
@@ -0,0 +1,40 @@
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
+ import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
9
+ import PropTypes from 'prop-types';
10
+ import React__default from 'react';
11
+ import cx from 'classnames';
12
+ import { usePrefix } from '../../internal/usePrefix.js';
13
+
14
+ const ChatButtonSkeleton = _ref => {
15
+ let {
16
+ className,
17
+ size,
18
+ ...rest
19
+ } = _ref;
20
+ const prefix = usePrefix();
21
+ const skeletonClasses = cx(className, `${prefix}--skeleton`, `${prefix}--btn`, `${prefix}--chat-btn`, {
22
+ [`${prefix}--layout--size-${size}`]: size
23
+ });
24
+ return /*#__PURE__*/React__default.createElement("div", _extends({
25
+ className: skeletonClasses
26
+ }, rest));
27
+ };
28
+ ChatButtonSkeleton.propTypes = {
29
+ /**
30
+ * Specify an optional className to add.
31
+ */
32
+ className: PropTypes.string,
33
+ /**
34
+ * Specify the size of the `ChatButtonSkeleton`, from the following list of sizes:
35
+ */
36
+ size: PropTypes.oneOf(['sm', 'md', 'lg'])
37
+ };
38
+ var ChatButtonSkeleton$1 = ChatButtonSkeleton;
39
+
40
+ export { ChatButtonSkeleton$1 as default };
@@ -0,0 +1,81 @@
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
+ import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
9
+ import PropTypes from 'prop-types';
10
+ import React__default from 'react';
11
+ import cx from 'classnames';
12
+ import Button from '../Button/Button.js';
13
+ import '../Button/Button.Skeleton.js';
14
+ import { usePrefix } from '../../internal/usePrefix.js';
15
+
16
+ const ChatButton = /*#__PURE__*/React__default.forwardRef(function ChatButton(_ref, ref) {
17
+ let {
18
+ className,
19
+ children,
20
+ disabled,
21
+ isQuickAction,
22
+ isSelected,
23
+ kind,
24
+ size,
25
+ ...other
26
+ } = _ref;
27
+ const prefix = usePrefix();
28
+ const classNames = cx(className, {
29
+ [`${prefix}--chat-btn`]: true,
30
+ [`${prefix}--chat-btn--quick-action`]: isQuickAction,
31
+ [`${prefix}--chat-btn--quick-action--selected`]: isSelected
32
+ });
33
+ const allowedSizes = ['sm', 'md', 'lg'];
34
+ if (isQuickAction) {
35
+ kind = 'ghost';
36
+ size = 'sm';
37
+ } else {
38
+ // Do not allow size larger than `lg`
39
+ size = allowedSizes.includes(size) ? size : 'lg';
40
+ }
41
+ return /*#__PURE__*/React__default.createElement(Button, _extends({
42
+ disabled: disabled,
43
+ className: classNames,
44
+ kind: kind,
45
+ ref: ref,
46
+ size: size
47
+ }, other), children);
48
+ });
49
+ ChatButton.propTypes = {
50
+ /**
51
+ * Provide the contents of your Select
52
+ */
53
+ children: PropTypes.node,
54
+ /**
55
+ * Specify an optional className to be applied to the node containing the label and the select box
56
+ */
57
+ className: PropTypes.string,
58
+ /**
59
+ * Specify whether the `ChatButton` should be disabled
60
+ */
61
+ disabled: PropTypes.bool,
62
+ /**
63
+ * Specify whether the `ChatButton` should be rendered as a quick action button
64
+ */
65
+ isQuickAction: PropTypes.bool,
66
+ /**
67
+ * Specify whether the quick action `ChatButton` should be rendered as selected. This disables the input
68
+ */
69
+ isSelected: PropTypes.bool,
70
+ /**
71
+ * Specify the kind of `ChatButton` you want to create
72
+ */
73
+ kind: PropTypes.oneOf(['primary', 'secondary', 'danger', 'ghost', 'tertiary']),
74
+ /**
75
+ * Specify the size of the `ChatButton`, from the following list of sizes:
76
+ */
77
+ size: PropTypes.oneOf(['sm', 'md', 'lg'])
78
+ };
79
+ var ChatButton$1 = ChatButton;
80
+
81
+ export { ChatButton$1 as default };
@@ -36,6 +36,7 @@ const ComboButton = /*#__PURE__*/React__default.forwardRef(function ComboButton(
36
36
  label,
37
37
  onClick,
38
38
  size = 'lg',
39
+ menuAlignment = 'bottom',
39
40
  tooltipAlignment,
40
41
  translateWithId: t = defaultTranslateWithId,
41
42
  ...rest
@@ -70,10 +71,15 @@ const ComboButton = /*#__PURE__*/React__default.forwardRef(function ComboButton(
70
71
  }
71
72
  function handleOpen() {
72
73
  menuRef.current.style.inlineSize = `${width}px`;
74
+ menuRef.current.style.minInlineSize = `${width}px`;
75
+ if (menuAlignment !== 'bottom' && menuAlignment !== 'top') {
76
+ menuRef.current.style.inlineSize = `fit-content`;
77
+ }
73
78
  }
74
79
  const containerClasses = cx(`${prefix}--combo-button__container`, `${prefix}--combo-button__container--${size}`, {
75
80
  [`${prefix}--combo-button__container--open`]: open
76
81
  }, className);
82
+ const menuClasses = cx(`${prefix}--combo-button__${menuAlignment}`);
77
83
  const primaryActionClasses = cx(`${prefix}--combo-button__primary-action`);
78
84
  const triggerClasses = cx(`${prefix}--combo-button__trigger`);
79
85
  return /*#__PURE__*/React__default.createElement("div", _extends({}, rest, {
@@ -83,6 +89,7 @@ const ComboButton = /*#__PURE__*/React__default.forwardRef(function ComboButton(
83
89
  }), /*#__PURE__*/React__default.createElement("div", {
84
90
  className: primaryActionClasses
85
91
  }, /*#__PURE__*/React__default.createElement(Button, {
92
+ title: label,
86
93
  size: size,
87
94
  disabled: disabled,
88
95
  onClick: handlePrimaryActionClick
@@ -98,6 +105,9 @@ const ComboButton = /*#__PURE__*/React__default.forwardRef(function ComboButton(
98
105
  onMouseDown: handleTriggerMousedown,
99
106
  "aria-controls": open ? id : null
100
107
  }, _ChevronDown || (_ChevronDown = /*#__PURE__*/React__default.createElement(ChevronDown, null))), /*#__PURE__*/React__default.createElement(Menu, {
108
+ containerRef: containerRef,
109
+ menuAlignment: menuAlignment,
110
+ className: menuClasses,
101
111
  ref: menuRef,
102
112
  id: id,
103
113
  label: t('carbon.combo-button.additional-actions'),
@@ -127,6 +137,10 @@ ComboButton.propTypes = {
127
137
  * Provide the label to be renderd on the primary action button.
128
138
  */
129
139
  label: PropTypes.string.isRequired,
140
+ /**
141
+ * Experimental property. Specify how the menu should align with the button element
142
+ */
143
+ menuAlignment: PropTypes.oneOf(['top', 'top-start', 'top-end', 'bottom', 'bottom-start', 'bottom-end']),
130
144
  /**
131
145
  * Provide an optional function to be called when the primary action element is clicked.
132
146
  */
@@ -5,6 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
+ import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
8
9
  import React__default from 'react';
9
10
  import PropTypes from 'prop-types';
10
11
  import cx from 'classnames';
@@ -44,7 +45,8 @@ function ContainedList(_ref) {
44
45
  isInset,
45
46
  kind = variants[0],
46
47
  label,
47
- size
48
+ size,
49
+ ...rest
48
50
  } = _ref;
49
51
  const labelId = `${useId('contained-list')}-header`;
50
52
  const prefix = usePrefix();
@@ -57,9 +59,9 @@ function ContainedList(_ref) {
57
59
  const filteredChildren = filterChildren(children);
58
60
  const isActionSearch = ['Search', 'ExpandableSearch'].includes(action?.type?.displayName);
59
61
  const renderedChildren = renderChildren(children);
60
- return /*#__PURE__*/React__default.createElement("div", {
62
+ return /*#__PURE__*/React__default.createElement("div", _extends({
61
63
  className: classes
62
- }, /*#__PURE__*/React__default.createElement("div", {
64
+ }, rest), /*#__PURE__*/React__default.createElement("div", {
63
65
  className: `${prefix}--contained-list__header`
64
66
  }, /*#__PURE__*/React__default.createElement("div", {
65
67
  id: labelId,
@@ -5,6 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
+ import { extends as _extends } from '../../../_virtual/_rollupPluginBabelHelpers.js';
8
9
  import React__default from 'react';
9
10
  import PropTypes from 'prop-types';
10
11
  import cx from 'classnames';
@@ -18,7 +19,8 @@ function ContainedListItem(_ref) {
18
19
  className,
19
20
  disabled = false,
20
21
  onClick,
21
- renderIcon: IconElement
22
+ renderIcon: IconElement,
23
+ ...rest
22
24
  } = _ref;
23
25
  const prefix = usePrefix();
24
26
  const isClickable = onClick !== undefined;
@@ -30,9 +32,9 @@ function ContainedListItem(_ref) {
30
32
  const content = /*#__PURE__*/React__default.createElement(React__default.Fragment, null, IconElement && /*#__PURE__*/React__default.createElement("div", {
31
33
  className: `${prefix}--contained-list-item__icon`
32
34
  }, /*#__PURE__*/React__default.createElement(IconElement, null)), /*#__PURE__*/React__default.createElement("div", null, children));
33
- return /*#__PURE__*/React__default.createElement("li", {
35
+ return /*#__PURE__*/React__default.createElement("li", _extends({
34
36
  className: classes
35
- }, isClickable ? /*#__PURE__*/React__default.createElement("button", {
37
+ }, rest), isClickable ? /*#__PURE__*/React__default.createElement("button", {
36
38
  className: `${prefix}--contained-list-item__content`,
37
39
  type: "button",
38
40
  disabled: disabled,
@@ -53,6 +53,7 @@ export interface DataTableRow<ColTypes extends any[]> {
53
53
  export interface DataTableHeader {
54
54
  key: string;
55
55
  header: React.ReactNode;
56
+ slug: React.ReactElement;
56
57
  }
57
58
  export interface DataTableRenderProps<RowType, ColTypes extends any[]> {
58
59
  headers: Array<DataTableHeader>;
@@ -152,6 +153,12 @@ export interface DataTableRenderProps<RowType, ColTypes extends any[]> {
152
153
  stickyHeader?: boolean;
153
154
  useStaticWidth?: boolean;
154
155
  };
156
+ getCellProps: (getCellPropsArgs: {
157
+ cell: DataTableCell<ColTypes>;
158
+ }) => {
159
+ [key: string]: unknown;
160
+ hasSlugHeader?: boolean;
161
+ };
155
162
  onInputChange: (e: React.ChangeEvent<HTMLInputElement>, defaultValue?: string) => void;
156
163
  sortBy: (headerKey: string) => void;
157
164
  selectAll: () => void;
@@ -334,6 +341,7 @@ declare class DataTable<RowType, ColTypes extends any[]> extends React.Component
334
341
  sortDirection: DataTableSortState;
335
342
  isSortable: boolean | undefined;
336
343
  isSortHeader: boolean;
344
+ slug: React.ReactElement<any, string | React.JSXElementConstructor<any>>;
337
345
  onClick: (event: any) => void;
338
346
  };
339
347
  /**
@@ -468,6 +476,19 @@ declare class DataTable<RowType, ColTypes extends any[]> extends React.Component
468
476
  stickyHeader: boolean | undefined;
469
477
  useStaticWidth: boolean | undefined;
470
478
  };
479
+ /**
480
+ * Get the props associated with the given table cell.
481
+ *
482
+ * @param {object} config
483
+ * @param {object} config.cell the cell we want the props for
484
+ * @returns {object}
485
+ */
486
+ getCellProps: ({ cell, ...rest }: {
487
+ [x: string]: any;
488
+ cell: any;
489
+ }) => {
490
+ hasSlugHeader: any;
491
+ };
471
492
  /**
472
493
  * Helper utility to get all the currently selected rows
473
494
  * @returns {Array<string>} the array of rowIds that are currently selected
@@ -103,6 +103,7 @@ class DataTable extends React__default.Component {
103
103
  sortDirection,
104
104
  isSortable,
105
105
  isSortHeader: sortHeaderKey === header.key,
106
+ slug: header.slug,
106
107
  onClick: event => {
107
108
  const nextSortState = getNextSortState(this.props, this.state, {
108
109
  key: header.key
@@ -339,6 +340,23 @@ class DataTable extends React__default.Component {
339
340
  useStaticWidth
340
341
  };
341
342
  });
343
+ /**
344
+ * Get the props associated with the given table cell.
345
+ *
346
+ * @param {object} config
347
+ * @param {object} config.cell the cell we want the props for
348
+ * @returns {object}
349
+ */
350
+ _defineProperty(this, "getCellProps", _ref4 => {
351
+ let {
352
+ cell,
353
+ ...rest
354
+ } = _ref4;
355
+ return {
356
+ ...rest,
357
+ hasSlugHeader: cell.hasSlugHeader
358
+ };
359
+ });
342
360
  /**
343
361
  * Helper utility to get all the currently selected rows
344
362
  * @returns {Array<string>} the array of rowIds that are currently selected
@@ -612,6 +630,7 @@ class DataTable extends React__default.Component {
612
630
  getBatchActionProps: this.getBatchActionProps,
613
631
  getTableProps: this.getTableProps,
614
632
  getTableContainerProps: this.getTableContainerProps,
633
+ getCellProps: this.getCellProps,
615
634
  // Custom event handlers
616
635
  onInputChange: this.handleOnInputValueChange,
617
636
  // Expose internal state change actions
@@ -4,7 +4,32 @@
4
4
  * This source code is licensed under the Apache-2.0 license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
- import { TdHTMLAttributes } from 'react';
8
- export type TableCellProps = TdHTMLAttributes<HTMLTableCellElement>;
9
- declare const TableCell: React.FC<TableCellProps>;
7
+ import React from 'react';
8
+ import { ReactAttr } from '../../types/common';
9
+ interface TableCellProps extends ReactAttr<HTMLTableCellElement> {
10
+ /**
11
+ * Pass in children that will be embedded in the table header label
12
+ */
13
+ children?: React.ReactNode;
14
+ /**
15
+ * Specify an optional className to be applied to the container node
16
+ */
17
+ className?: string;
18
+ /**
19
+ * The width of the expanded row's internal cell
20
+ */
21
+ colSpan?: number;
22
+ /**
23
+ * Specify if the table cell is in an AI column
24
+ */
25
+ hasSlugHeader?: boolean;
26
+ /**
27
+ * The id of the matching th node in the table head. Addresses a11y concerns outlined here: https://www.ibm.com/able/guidelines/ci162/info_and_relationships.html and https://www.w3.org/TR/WCAG20-TECHS/H43
28
+ */
29
+ headers?: string;
30
+ }
31
+ declare const TableCell: {
32
+ ({ children, className, hasSlugHeader, colSpan, ...rest }: TableCellProps): import("react/jsx-runtime").JSX.Element;
33
+ displayName: string;
34
+ };
10
35
  export default TableCell;
@@ -5,11 +5,28 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- import wrapComponent from '../../tools/wrapComponent.js';
8
+ import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
9
+ import React__default from 'react';
10
+ import cx from 'classnames';
11
+ import { usePrefix } from '../../internal/usePrefix.js';
9
12
 
10
- const TableCell = wrapComponent({
11
- name: 'TableCell',
12
- type: 'td'
13
- });
13
+ const TableCell = _ref => {
14
+ let {
15
+ children,
16
+ className,
17
+ hasSlugHeader,
18
+ colSpan,
19
+ ...rest
20
+ } = _ref;
21
+ const prefix = usePrefix();
22
+ const tableCellClassNames = cx(className, {
23
+ [`${prefix}--table-cell--column-slug`]: hasSlugHeader
24
+ });
25
+ return /*#__PURE__*/React__default.createElement("td", _extends({
26
+ className: tableCellClassNames ? tableCellClassNames : undefined,
27
+ colSpan: colSpan
28
+ }, rest), children);
29
+ };
30
+ TableCell.displayName = 'TableCell';
14
31
 
15
32
  export { TableCell as default };
@@ -48,7 +48,7 @@ const TableExpandRow = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
48
48
  [`${prefix}--parent-row`]: true,
49
49
  [`${prefix}--expandable-row`]: isExpanded,
50
50
  [`${prefix}--data-table--selected`]: isSelected,
51
- [`${prefix}--parent-row--slug`]: rowHasSlug
51
+ [`${prefix}--data-table--slug-row`]: rowHasSlug
52
52
  }, rowClassName);
53
53
  const previousValue = isExpanded ? 'collapsed' : undefined;
54
54
  return /*#__PURE__*/React__default.createElement("tr", _extends({}, rest, {
@@ -124,13 +124,13 @@ const TableHeader = /*#__PURE__*/React__default.forwardRef(function TableHeader(
124
124
  className: `${prefix}--table-sort__flex`
125
125
  }, /*#__PURE__*/React__default.createElement("div", {
126
126
  className: `${prefix}--table-header-label`
127
- }, children), normalizedSlug, /*#__PURE__*/React__default.createElement(ArrowUp, {
127
+ }, children), /*#__PURE__*/React__default.createElement(ArrowUp, {
128
128
  size: 20,
129
129
  className: `${prefix}--table-sort__icon`
130
130
  }), /*#__PURE__*/React__default.createElement(ArrowsVertical, {
131
131
  size: 20,
132
132
  className: `${prefix}--table-sort__icon-unsorted`
133
- }))));
133
+ }), normalizedSlug)));
134
134
  });
135
135
  TableHeader.propTypes = {
136
136
  /**
@@ -13,10 +13,21 @@ import { usePrefix } from '../../internal/usePrefix.js';
13
13
 
14
14
  const TableRow = props => {
15
15
  const prefix = usePrefix();
16
+ let rowHasSlug;
17
+ if (props?.children) {
18
+ React__default.Children.toArray(props.children).map(child => {
19
+ if (child.type?.displayName === 'TableSlugRow') {
20
+ if (child.props.slug) {
21
+ rowHasSlug = true;
22
+ }
23
+ }
24
+ });
25
+ }
16
26
  // Remove unnecessary props if provided to this component, these are
17
27
  // only useful in `TableExpandRow`
18
28
  const className = cx(props.className, {
19
- [`${prefix}--data-table--selected`]: props.isSelected
29
+ [`${prefix}--data-table--selected`]: props.isSelected,
30
+ [`${prefix}--data-table--slug-row`]: rowHasSlug
20
31
  });
21
32
  const cleanProps = {
22
33
  ...omit(props, ['ariaLabel', 'aria-label', 'aria-controls', 'onExpand', 'isExpanded', 'isSelected']),
@@ -48,7 +48,8 @@ const normalize = function (rows, headers) {
48
48
  }
49
49
  headers.forEach((_ref, i) => {
50
50
  let {
51
- key
51
+ key,
52
+ slug
52
53
  } = _ref;
53
54
  const id = getCellId(row.id, key);
54
55
  // Initialize the cell info and state values, namely for editing
@@ -59,6 +60,7 @@ const normalize = function (rows, headers) {
59
60
  isEditing: false,
60
61
  isValid: true,
61
62
  errors: null,
63
+ hasSlugHeader: !!slug,
62
64
  info: {
63
65
  header: key
64
66
  }
@@ -4,8 +4,12 @@
4
4
  * This source code is licensed under the Apache-2.0 license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
- import React from 'react';
7
+ import React, { RefObject } from 'react';
8
8
  interface MenuProps extends React.HTMLAttributes<HTMLUListElement> {
9
+ /**
10
+ * The ref of the containing element, used for positioning and alignment of the menu
11
+ */
12
+ containerRef?: RefObject<HTMLDivElement>;
9
13
  /**
10
14
  * A collection of MenuItems to be rendered within this Menu.
11
15
  */
@@ -18,6 +22,10 @@ interface MenuProps extends React.HTMLAttributes<HTMLUListElement> {
18
22
  * A label describing the Menu.
19
23
  */
20
24
  label?: string;
25
+ /**
26
+ * Specify how the menu should align with the button element
27
+ */
28
+ menuAlignment?: string;
21
29
  /**
22
30
  * The mode of this menu. Defaults to full.
23
31
  * `full` supports nesting and selectable menu items, but no icons.
@@ -24,7 +24,9 @@ const Menu = /*#__PURE__*/React__default.forwardRef(function Menu(_ref, forwardR
24
24
  let {
25
25
  children,
26
26
  className,
27
+ containerRef,
27
28
  label,
29
+ menuAlignment,
28
30
  mode = 'full',
29
31
  onClose,
30
32
  onOpen,
@@ -61,6 +63,15 @@ const Menu = /*#__PURE__*/React__default.forwardRef(function Menu(_ref, forwardR
61
63
  const [position, setPosition] = useState([-1, -1]);
62
64
  const focusableItems = childContext.state.items.filter(item => !item.disabled && item.ref.current);
63
65
 
66
+ // Getting the width from the parent container element - controlled
67
+ let actionButtonWidth;
68
+ if (containerRef?.current) {
69
+ const {
70
+ width: w
71
+ } = containerRef.current.getBoundingClientRect();
72
+ actionButtonWidth = w;
73
+ }
74
+
64
75
  // Set RTL based on document direction or `LayoutDirection`
65
76
  const {
66
77
  direction
@@ -174,6 +185,16 @@ const Menu = /*#__PURE__*/React__default.forwardRef(function Menu(_ref, forwardR
174
185
  }
175
186
  };
176
187
 
188
+ // Avoid that the Menu render incorrectly when the postion is set in the right side of the screen
189
+ if (actionButtonWidth && actionButtonWidth < axes.x.size && (menuAlignment === 'bottom' || menuAlignment === 'top')) {
190
+ axes.x.size = actionButtonWidth;
191
+ }
192
+
193
+ // if 'axes.x.anchor' is lower than 87px dynamically switch render side
194
+ if (actionButtonWidth && (menuAlignment === 'bottom-end' || menuAlignment === 'top-end') && axes.x.anchor >= 87 && actionButtonWidth < axes.x.size) {
195
+ const diff = axes.x.anchor + axes.x.reversedAnchor;
196
+ axes.x.anchor = axes.x.anchor + diff;
197
+ }
177
198
  const {
178
199
  max,
179
200
  size,
@@ -190,6 +211,14 @@ const Menu = /*#__PURE__*/React__default.forwardRef(function Menu(_ref, forwardR
190
211
  reversedAnchor - size >= 0 ? reversedAnchor - size + offset : false,
191
212
  // align at max (second fallback)
192
213
  max - spacing - size];
214
+ const topAlignment = menuAlignment === 'top' || menuAlignment === 'top-end' || menuAlignment === 'top-start';
215
+
216
+ // If the tooltip is not visible in the top, switch to the bototm
217
+ if (typeof options[0] === 'number' && topAlignment && options[0] >= 0 && !options[1] && axis === 'y') {
218
+ menu.current.style.transform = 'translate(0)';
219
+ } else if (topAlignment && !options[0] && axis === 'y') {
220
+ options[0] = anchor - offset;
221
+ }
193
222
 
194
223
  // Previous array `options`, has at least one item that is a number (the last one - second fallback).
195
224
  // That guarantees that the return of `find()` will always be a number
@@ -244,6 +273,7 @@ const Menu = /*#__PURE__*/React__default.forwardRef(function Menu(_ref, forwardR
244
273
  // visibility is needed for focusing elements.
245
274
  // opacity is only set once the position has been set correctly
246
275
  // to avoid a flicker effect when opening.
276
+ [`${prefix}--menu--box-shadow-top`]: menuAlignment && menuAlignment.slice(0, 3) === 'top',
247
277
  [`${prefix}--menu--open`]: open,
248
278
  [`${prefix}--menu--shown`]: position[0] >= 0 && position[1] >= 0,
249
279
  [`${prefix}--menu--with-icons`]: childContext.state.hasIcons
@@ -274,6 +304,10 @@ Menu.propTypes = {
274
304
  * A label describing the Menu.
275
305
  */
276
306
  label: PropTypes.string,
307
+ /**
308
+ * Specify how the menu should align with the button element
309
+ */
310
+ menuAlignment: PropTypes.string,
277
311
  /**
278
312
  * The mode of this menu. Defaults to full.
279
313
  * `full` supports nesting and selectable menu items, but no icons.
@@ -30,6 +30,7 @@ const MenuButton = /*#__PURE__*/React__default.forwardRef(function MenuButton(_r
30
30
  kind = defaultButtonKind,
31
31
  label,
32
32
  size = 'lg',
33
+ menuAlignment = 'bottom',
33
34
  tabIndex = 0,
34
35
  ...rest
35
36
  } = _ref;
@@ -58,11 +59,16 @@ const MenuButton = /*#__PURE__*/React__default.forwardRef(function MenuButton(_r
58
59
  }
59
60
  function handleOpen() {
60
61
  menuRef.current.style.inlineSize = `${width}px`;
62
+ menuRef.current.style.minInlineSize = `${width}px`;
63
+ if (menuAlignment !== 'bottom' && menuAlignment !== 'top') {
64
+ menuRef.current.style.inlineSize = `fit-content`;
65
+ }
61
66
  }
62
67
  const containerClasses = cx(`${prefix}--menu-button__container`, className);
63
68
  const triggerClasses = cx(`${prefix}--menu-button__trigger`, {
64
69
  [`${prefix}--menu-button__trigger--open`]: open
65
70
  });
71
+ const menuClasses = cx(`${prefix}--menu-button__${menuAlignment}`);
66
72
  const buttonKind = validButtonKinds.includes(kind) ? kind : defaultButtonKind;
67
73
  return /*#__PURE__*/React__default.createElement("div", _extends({}, rest, {
68
74
  ref: ref,
@@ -81,6 +87,9 @@ const MenuButton = /*#__PURE__*/React__default.forwardRef(function MenuButton(_r
81
87
  onMouseDown: handleMousedown,
82
88
  "aria-controls": open ? id : null
83
89
  }, label), /*#__PURE__*/React__default.createElement(Menu, {
90
+ containerRef: triggerRef,
91
+ menuAlignment: menuAlignment,
92
+ className: menuClasses,
84
93
  ref: menuRef,
85
94
  id: id,
86
95
  label: label,
@@ -114,6 +123,10 @@ MenuButton.propTypes = {
114
123
  * Provide the label to be renderd on the trigger button.
115
124
  */
116
125
  label: PropTypes.string.isRequired,
126
+ /**
127
+ * Experimental property. Specify how the menu should align with the button element
128
+ */
129
+ menuAlignment: PropTypes.oneOf(['top', 'top-start', 'top-end', 'bottom', 'bottom-start', 'bottom-end']),
117
130
  /**
118
131
  * Specify the size of the button and menu.
119
132
  */