@carbon/react 1.44.0-rc.0 → 1.45.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 (140) hide show
  1. package/.playwright/INTERNAL_AVT_REPORT_DO_NOT_USE.json +1009 -1050
  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.d.ts +1 -1
  8. package/es/components/ComboBox/ComboBox.js +1 -1
  9. package/es/components/ComboButton/index.js +1 -1
  10. package/es/components/ComposedModal/ModalFooter.d.ts +2 -1
  11. package/es/components/DataTable/DataTable.d.ts +2 -0
  12. package/es/components/DataTable/DataTable.js +3 -0
  13. package/es/components/DataTable/TableExpandRow.js +20 -3
  14. package/es/components/DataTable/TableHeader.d.ts +5 -0
  15. package/es/components/DataTable/TableHeader.js +30 -6
  16. package/es/components/DataTable/TableSlugRow.d.ts +31 -0
  17. package/es/components/DataTable/TableSlugRow.js +49 -0
  18. package/es/components/DataTable/index.d.ts +2 -1
  19. package/es/components/DataTable/index.js +3 -0
  20. package/es/components/DataTable/tools/sorting.js +1 -1
  21. package/es/components/DatePickerInput/DatePickerInput.d.ts +1 -1
  22. package/es/components/DatePickerInput/DatePickerInput.js +1 -1
  23. package/es/components/Dropdown/Dropdown.d.ts +1 -1
  24. package/es/components/Dropdown/Dropdown.js +1 -1
  25. package/es/components/FileUploader/FileUploader.js +5 -3
  26. package/es/components/Grid/Column.js +11 -1
  27. package/es/components/InlineLoading/InlineLoading.d.ts +68 -0
  28. package/es/components/InlineLoading/InlineLoading.js +4 -4
  29. package/es/components/InlineLoading/index.d.ts +9 -0
  30. package/es/components/Layer/LayerContext.d.ts +8 -0
  31. package/es/components/Layer/LayerLevel.d.ts +5 -0
  32. package/es/components/Layer/LayerLevel.js +12 -0
  33. package/es/components/Layer/index.d.ts +38 -0
  34. package/es/components/Layer/index.js +9 -8
  35. package/es/components/Menu/MenuItem.js +2 -1
  36. package/es/components/MenuButton/index.js +8 -2
  37. package/es/components/Modal/Modal.d.ts +3 -2
  38. package/es/components/MultiSelect/FilterableMultiSelect.js +1 -1
  39. package/es/components/MultiSelect/MultiSelect.d.ts +1 -1
  40. package/es/components/MultiSelect/MultiSelect.js +1 -1
  41. package/es/components/Notification/Notification.js +1 -0
  42. package/es/components/NumberInput/NumberInput.d.ts +1 -1
  43. package/es/components/NumberInput/NumberInput.js +1 -1
  44. package/es/components/RadioButton/RadioButton.d.ts +4 -0
  45. package/es/components/RadioButton/RadioButton.js +15 -2
  46. package/es/components/RadioButtonGroup/RadioButtonGroup.d.ts +4 -0
  47. package/es/components/RadioButtonGroup/RadioButtonGroup.js +17 -2
  48. package/es/components/Select/Select.d.ts +2 -2
  49. package/es/components/Select/Select.js +1 -1
  50. package/es/components/Slider/Slider.Skeleton.js +17 -3
  51. package/es/components/Slider/Slider.js +132 -93
  52. package/es/components/Slider/SliderHandles.d.ts +4 -0
  53. package/es/components/Slider/SliderHandles.js +65 -0
  54. package/es/components/Slug/index.js +1 -1
  55. package/es/components/Tabs/Tabs.js +1 -1
  56. package/es/components/TextArea/TextArea.d.ts +7 -3
  57. package/es/components/TextArea/TextArea.js +84 -17
  58. package/es/components/TextInput/TextInput.d.ts +1 -1
  59. package/es/components/TextInput/TextInput.js +1 -1
  60. package/es/components/Tile/Tile.d.ts +37 -0
  61. package/es/components/Tile/Tile.js +114 -13
  62. package/es/components/Tooltip/Tooltip.js +48 -2
  63. package/es/components/UIShell/Content.d.ts +296 -0
  64. package/es/components/UIShell/Content.js +1 -2
  65. package/es/components/UIShell/HeaderPanel.d.ts +36 -0
  66. package/es/components/UIShell/HeaderPanel.js +6 -6
  67. package/es/components/UIShell/SideNav.d.ts +1 -1
  68. package/es/index.js +2 -1
  69. package/es/internal/useAnnouncer.js +2 -1
  70. package/es/internal/useNoInteractiveChildren.js +2 -6
  71. package/lib/components/Accordion/AccordionItem.d.ts +1 -1
  72. package/lib/components/Accordion/AccordionItem.js +18 -14
  73. package/lib/components/Checkbox/Checkbox.d.ts +4 -0
  74. package/lib/components/Checkbox/Checkbox.js +15 -2
  75. package/lib/components/CheckboxGroup/CheckboxGroup.js +17 -2
  76. package/lib/components/ComboBox/ComboBox.d.ts +1 -1
  77. package/lib/components/ComboBox/ComboBox.js +1 -1
  78. package/lib/components/ComboButton/index.js +1 -1
  79. package/lib/components/ComposedModal/ModalFooter.d.ts +2 -1
  80. package/lib/components/DataTable/DataTable.d.ts +2 -0
  81. package/lib/components/DataTable/DataTable.js +3 -0
  82. package/lib/components/DataTable/TableExpandRow.js +20 -3
  83. package/lib/components/DataTable/TableHeader.d.ts +5 -0
  84. package/lib/components/DataTable/TableHeader.js +29 -5
  85. package/lib/components/DataTable/TableSlugRow.d.ts +31 -0
  86. package/lib/components/DataTable/TableSlugRow.js +59 -0
  87. package/lib/components/DataTable/index.d.ts +2 -1
  88. package/lib/components/DataTable/index.js +3 -0
  89. package/lib/components/DataTable/tools/sorting.js +1 -1
  90. package/lib/components/DatePickerInput/DatePickerInput.d.ts +1 -1
  91. package/lib/components/DatePickerInput/DatePickerInput.js +1 -1
  92. package/lib/components/Dropdown/Dropdown.d.ts +1 -1
  93. package/lib/components/Dropdown/Dropdown.js +1 -1
  94. package/lib/components/FileUploader/FileUploader.js +5 -3
  95. package/lib/components/Grid/Column.js +11 -1
  96. package/lib/components/InlineLoading/InlineLoading.d.ts +68 -0
  97. package/lib/components/InlineLoading/InlineLoading.js +4 -4
  98. package/lib/components/InlineLoading/index.d.ts +9 -0
  99. package/lib/components/Layer/LayerContext.d.ts +8 -0
  100. package/lib/components/Layer/LayerLevel.d.ts +5 -0
  101. package/lib/components/Layer/LayerLevel.js +18 -0
  102. package/lib/components/Layer/index.d.ts +38 -0
  103. package/lib/components/Layer/index.js +10 -9
  104. package/lib/components/Menu/MenuItem.js +2 -1
  105. package/lib/components/MenuButton/index.js +8 -2
  106. package/lib/components/Modal/Modal.d.ts +3 -2
  107. package/lib/components/MultiSelect/FilterableMultiSelect.js +1 -1
  108. package/lib/components/MultiSelect/MultiSelect.d.ts +1 -1
  109. package/lib/components/MultiSelect/MultiSelect.js +1 -1
  110. package/lib/components/Notification/Notification.js +1 -0
  111. package/lib/components/NumberInput/NumberInput.d.ts +1 -1
  112. package/lib/components/NumberInput/NumberInput.js +1 -1
  113. package/lib/components/RadioButton/RadioButton.d.ts +4 -0
  114. package/lib/components/RadioButton/RadioButton.js +15 -2
  115. package/lib/components/RadioButtonGroup/RadioButtonGroup.d.ts +4 -0
  116. package/lib/components/RadioButtonGroup/RadioButtonGroup.js +17 -2
  117. package/lib/components/Select/Select.d.ts +2 -2
  118. package/lib/components/Select/Select.js +1 -1
  119. package/lib/components/Slider/Slider.Skeleton.js +17 -3
  120. package/lib/components/Slider/Slider.js +132 -93
  121. package/lib/components/Slider/SliderHandles.d.ts +4 -0
  122. package/lib/components/Slider/SliderHandles.js +76 -0
  123. package/lib/components/Slug/index.js +1 -1
  124. package/lib/components/Tabs/Tabs.js +1 -1
  125. package/lib/components/TextArea/TextArea.d.ts +7 -3
  126. package/lib/components/TextArea/TextArea.js +83 -16
  127. package/lib/components/TextInput/TextInput.d.ts +1 -1
  128. package/lib/components/TextInput/TextInput.js +1 -1
  129. package/lib/components/Tile/Tile.d.ts +37 -0
  130. package/lib/components/Tile/Tile.js +114 -13
  131. package/lib/components/Tooltip/Tooltip.js +47 -1
  132. package/lib/components/UIShell/Content.d.ts +296 -0
  133. package/lib/components/UIShell/Content.js +1 -2
  134. package/lib/components/UIShell/HeaderPanel.d.ts +36 -0
  135. package/lib/components/UIShell/HeaderPanel.js +7 -7
  136. package/lib/components/UIShell/SideNav.d.ts +1 -1
  137. package/lib/index.js +4 -2
  138. package/lib/internal/useAnnouncer.js +2 -1
  139. package/lib/internal/useNoInteractiveChildren.js +2 -6
  140. package/package.json +5 -8
@@ -7,7 +7,7 @@
7
7
 
8
8
  import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
9
9
  import PropTypes from 'prop-types';
10
- import React__default, { useContext, useState, useRef, useEffect } from 'react';
10
+ import React__default, { useContext, useRef, useState, useEffect } from 'react';
11
11
  import cx from 'classnames';
12
12
  import deprecate from '../../prop-types/deprecate.js';
13
13
  import { WarningFilled, WarningAltFilled } from '@carbon/icons-react';
@@ -39,6 +39,7 @@ const TextArea = /*#__PURE__*/React__default.forwardRef((props, forwardRef) => {
39
39
  placeholder = '',
40
40
  enableCounter = false,
41
41
  maxCount = undefined,
42
+ counterMode = 'character',
42
43
  warn = false,
43
44
  warnText = '',
44
45
  rows = 4,
@@ -53,15 +54,25 @@ const TextArea = /*#__PURE__*/React__default.forwardRef((props, forwardRef) => {
53
54
  defaultValue,
54
55
  value
55
56
  } = other;
56
- const [textCount, setTextCount] = useState(defaultValue?.toString()?.length || value?.toString()?.length || 0);
57
57
  const {
58
58
  current: textAreaInstanceId
59
59
  } = useRef(getInstanceId());
60
60
  const textareaRef = useRef(null);
61
61
  const ref = useMergedRefs([forwardRef, textareaRef]);
62
+ function getInitialTextCount() {
63
+ const targetValue = defaultValue || value || textareaRef.current?.value || '';
64
+ const strValue = targetValue.toString();
65
+ if (counterMode === 'character') {
66
+ return strValue.length;
67
+ } else {
68
+ return strValue.match(/\w+/g)?.length || 0;
69
+ }
70
+ }
71
+ const [textCount, setTextCount] = useState(getInitialTextCount());
62
72
  useEffect(() => {
63
- setTextCount(defaultValue?.toString()?.length || value?.toString()?.length || 0);
64
- }, [value, defaultValue]);
73
+ setTextCount(getInitialTextCount());
74
+ // eslint-disable-next-line react-hooks/exhaustive-deps
75
+ }, [value, defaultValue, counterMode]);
65
76
  useIsomorphicEffect(() => {
66
77
  if (other.cols && textareaRef.current) {
67
78
  textareaRef.current.style.width = '';
@@ -72,14 +83,63 @@ const TextArea = /*#__PURE__*/React__default.forwardRef((props, forwardRef) => {
72
83
  }, [other.cols]);
73
84
  const textareaProps = {
74
85
  id,
86
+ onKeyDown: evt => {
87
+ if (!disabled && enableCounter && counterMode === 'word') {
88
+ const key = evt.which;
89
+ if (maxCount && textCount >= maxCount && key === 32) {
90
+ evt.preventDefault();
91
+ }
92
+ }
93
+ },
94
+ onPaste: evt => {
95
+ if (!disabled) {
96
+ if (counterMode === 'word' && enableCounter && typeof maxCount !== 'undefined' && textareaRef.current !== null) {
97
+ const existingWords = textareaRef.current.value.match(/\w+/g) || [];
98
+ const pastedWords = evt.clipboardData.getData('Text').match(/\w+/g) || [];
99
+ const totalWords = existingWords.length + pastedWords.length;
100
+ if (totalWords > maxCount) {
101
+ evt.preventDefault();
102
+ const allowedWords = existingWords.concat(pastedWords).slice(0, maxCount);
103
+ setTimeout(() => {
104
+ setTextCount(maxCount);
105
+ }, 0);
106
+ textareaRef.current.value = allowedWords.join(' ');
107
+ }
108
+ }
109
+ }
110
+ },
75
111
  onChange: evt => {
76
- if (!disabled && onChange) {
77
- evt?.persist?.();
78
- // delay textCount assignation to give the textarea element value time to catch up if is a controlled input
79
- setTimeout(() => {
80
- setTextCount(evt.target?.value?.length);
81
- }, 0);
82
- onChange(evt);
112
+ if (!disabled) {
113
+ if (counterMode == 'character') {
114
+ evt?.persist?.();
115
+ // delay textCount assignation to give the textarea element value time to catch up if is a controlled input
116
+ setTimeout(() => {
117
+ setTextCount(evt.target?.value?.length);
118
+ }, 0);
119
+ } else if (counterMode == 'word') {
120
+ if (!evt.target.value) {
121
+ setTimeout(() => {
122
+ setTextCount(0);
123
+ }, 0);
124
+ return;
125
+ }
126
+ if (enableCounter && typeof maxCount !== 'undefined' && textareaRef.current !== null) {
127
+ const matchedWords = evt.target?.value?.match(/\w+/g);
128
+ if (matchedWords && matchedWords.length <= maxCount) {
129
+ textareaRef.current.removeAttribute('maxLength');
130
+ setTimeout(() => {
131
+ setTextCount(matchedWords.length);
132
+ }, 0);
133
+ } else if (matchedWords && matchedWords.length > maxCount) {
134
+ setTimeout(() => {
135
+ setTextCount(matchedWords.length);
136
+ }, 0);
137
+ }
138
+ }
139
+ }
140
+ if (onChange) {
141
+ onChange(evt);
142
+ }
83
143
  }
84
144
  },
85
145
  onClick: evt => {
@@ -114,7 +174,7 @@ const TextArea = /*#__PURE__*/React__default.forwardRef((props, forwardRef) => {
114
174
  htmlFor: id,
115
175
  className: labelClasses
116
176
  }, labelText) : null;
117
- const counter = enableCounter && maxCount ? /*#__PURE__*/React__default.createElement(Text, {
177
+ const counter = enableCounter && maxCount && (counterMode === 'character' || counterMode === 'word') ? /*#__PURE__*/React__default.createElement(Text, {
118
178
  as: "div",
119
179
  className: counterClasses
120
180
  }, `${textCount}/${maxCount}`) : null;
@@ -147,9 +207,12 @@ const TextArea = /*#__PURE__*/React__default.forwardRef((props, forwardRef) => {
147
207
  ariaDescribedBy = helperId;
148
208
  }
149
209
  if (enableCounter) {
150
- textareaProps.maxLength = maxCount;
210
+ // handle different counter mode
211
+ if (counterMode == 'character') {
212
+ textareaProps.maxLength = maxCount;
213
+ }
151
214
  }
152
- const ariaAnnouncement = useAnnouncer(textCount, maxCount);
215
+ const ariaAnnouncement = useAnnouncer(textCount, maxCount, counterMode === 'word' ? 'words' : undefined);
153
216
  const input = /*#__PURE__*/React__default.createElement("textarea", _extends({}, other, textareaProps, {
154
217
  placeholder: placeholder,
155
218
  className: textareaClasses,
@@ -197,6 +260,10 @@ TextArea.propTypes = {
197
260
  * Specify the `cols` attribute for the underlying `<textarea>` node
198
261
  */
199
262
  cols: PropTypes.number,
263
+ /**
264
+ * Specify the method used for calculating the counter number
265
+ */
266
+ counterMode: PropTypes.oneOf(['character', 'word']),
200
267
  /**
201
268
  * Optionally provide the default value of the `<textarea>`
202
269
  */
@@ -206,7 +273,7 @@ TextArea.propTypes = {
206
273
  */
207
274
  disabled: PropTypes.bool,
208
275
  /**
209
- * Specify whether to display the character counter
276
+ * Specify whether to display the counter
210
277
  */
211
278
  enableCounter: PropTypes.bool,
212
279
  /**
@@ -240,7 +307,7 @@ TextArea.propTypes = {
240
307
  */
241
308
  light: deprecate(PropTypes.bool, 'The `light` prop for `TextArea` has ' + 'been deprecated in favor of the new `Layer` component. It will be removed in the next major release.'),
242
309
  /**
243
- * Max character count allowed for the textarea. This is needed in order for enableCounter to display
310
+ * Max entity count allowed for the textarea. This is needed in order for enableCounter to display
244
311
  */
245
312
  maxCount: PropTypes.number,
246
313
  /**
@@ -266,7 +333,7 @@ TextArea.propTypes = {
266
333
  */
267
334
  rows: PropTypes.number,
268
335
  /**
269
- * Provide a `Slug` component to be rendered inside the `TextArea` component
336
+ * **Experimental**: Provide a `Slug` component to be rendered inside the `TextArea` component
270
337
  */
271
338
  slug: PropTypes.node,
272
339
  /**
@@ -87,7 +87,7 @@ export interface TextInputProps extends Omit<React.InputHTMLAttributes<HTMLInput
87
87
  */
88
88
  size?: 'sm' | 'md' | 'lg' | 'xl';
89
89
  /**
90
- * Provide a `Slug` component to be rendered inside the `TextInput` component
90
+ * **Experimental**: Provide a `Slug` component to be rendered inside the `TextInput` component
91
91
  */
92
92
  slug?: ReactNodeLike;
93
93
  /**
@@ -261,7 +261,7 @@ TextInput.propTypes = {
261
261
  */
262
262
  size: PropTypes.oneOf(['sm', 'md', 'lg']),
263
263
  /**
264
- * Provide a `Slug` component to be rendered inside the `TextInput` component
264
+ * **Experimental**: Provide a `Slug` component to be rendered inside the `TextInput` component
265
265
  */
266
266
  slug: PropTypes.node,
267
267
  /**
@@ -1,9 +1,19 @@
1
1
  import React, { type ReactNode, type MouseEvent, type KeyboardEvent, type HTMLAttributes, type ChangeEvent, type ComponentType } from 'react';
2
+ import { ReactNodeLike } from 'prop-types';
2
3
  export interface TileProps extends HTMLAttributes<HTMLDivElement> {
3
4
  children?: ReactNode;
4
5
  className?: string;
5
6
  /** @deprecated */
6
7
  light?: boolean;
8
+ /**
9
+ * **Experimental**: Specify if the `Tile` component should be rendered with rounded corners. Only valid
10
+ * when `slug` prop is present
11
+ */
12
+ hasRoundedCorners?: boolean;
13
+ /**
14
+ * **Experimental**: Provide a `Slug` component to be rendered inside the `SelectableTile` component
15
+ */
16
+ slug?: ReactNodeLike;
7
17
  }
8
18
  export declare const Tile: React.ForwardRefExoticComponent<TileProps & React.RefAttributes<HTMLDivElement>>;
9
19
  export interface ClickableTileProps extends HTMLAttributes<HTMLAnchorElement> {
@@ -19,6 +29,11 @@ export interface ClickableTileProps extends HTMLAttributes<HTMLAnchorElement> {
19
29
  * Specify whether the ClickableTile should be disabled
20
30
  */
21
31
  disabled?: boolean;
32
+ /**
33
+ * **Experimental**: Specify if the `ClickableTile` component should be rendered with rounded corners.
34
+ * Only valid when `slug` prop is present
35
+ */
36
+ hasRoundedCorners?: boolean;
22
37
  /**
23
38
  * The href for the link.
24
39
  */
@@ -41,6 +56,10 @@ export interface ClickableTileProps extends HTMLAttributes<HTMLAnchorElement> {
41
56
  * The rel property for the link.
42
57
  */
43
58
  rel?: string;
59
+ /**
60
+ * **Experimental**: Specify if a `Slug` icon should be rendered inside the `ClickableTile`
61
+ */
62
+ slug?: boolean;
44
63
  }
45
64
  export declare const ClickableTile: React.ForwardRefExoticComponent<ClickableTileProps & React.RefAttributes<HTMLAnchorElement>>;
46
65
  export interface SelectableTileProps extends HTMLAttributes<HTMLDivElement> {
@@ -52,6 +71,11 @@ export interface SelectableTileProps extends HTMLAttributes<HTMLDivElement> {
52
71
  * Specify whether the SelectableTile should be disabled
53
72
  */
54
73
  disabled?: boolean;
74
+ /**
75
+ * **Experimental**: Specify if the `SelectableTile` component should be rendered with rounded corners.
76
+ * Only valid when `slug` prop is present
77
+ */
78
+ hasRoundedCorners?: boolean;
55
79
  /**
56
80
  * The ID of the `<input>`.
57
81
  */
@@ -77,6 +101,10 @@ export interface SelectableTileProps extends HTMLAttributes<HTMLDivElement> {
77
101
  * `true` to select this tile.
78
102
  */
79
103
  selected?: boolean;
104
+ /**
105
+ * **Experimental**: Provide a `Slug` component to be rendered inside the `SelectableTile` component
106
+ */
107
+ slug?: ReactNodeLike;
80
108
  /**
81
109
  * Specify the tab index of the wrapper element
82
110
  */
@@ -101,6 +129,11 @@ export interface ExpandableTileProps extends HTMLAttributes<HTMLDivElement> {
101
129
  * `true` if the tile is expanded.
102
130
  */
103
131
  expanded?: boolean;
132
+ /**
133
+ * **Experimental**: Specify if the `ExpandableTile` component should be rendered with rounded corners.
134
+ * Only valid when `slug` prop is present
135
+ */
136
+ hasRoundedCorners?: boolean;
104
137
  /**
105
138
  * An ID that can be provided to aria-labelledby
106
139
  */
@@ -113,6 +146,10 @@ export interface ExpandableTileProps extends HTMLAttributes<HTMLDivElement> {
113
146
  * optional handler to trigger a function when a key is pressed
114
147
  */
115
148
  onKeyUp?(event: KeyboardEvent): void;
149
+ /**
150
+ * **Experimental**: Provide a `Slug` component to be rendered inside the `ExpandableTile` component
151
+ */
152
+ slug?: ReactNodeLike;
116
153
  /**
117
154
  * The `tabindex` attribute.
118
155
  */
@@ -24,20 +24,26 @@ import { Text } from '../Text/Text.js';
24
24
  import { matches } from '../../internal/keyboard/match.js';
25
25
  import { Enter, Space } from '../../internal/keyboard/keys.js';
26
26
 
27
- var _CheckboxCheckedFille, _Checkbox, _ChevronDown, _ChevronDown2;
27
+ var _rect, _path, _CheckboxCheckedFille, _Checkbox, _ChevronDown, _ChevronDown2;
28
28
  const Tile = /*#__PURE__*/React__default.forwardRef(function Tile(_ref, ref) {
29
29
  let {
30
30
  children,
31
31
  className,
32
32
  light = false,
33
+ slug,
34
+ hasRoundedCorners = false,
33
35
  ...rest
34
36
  } = _ref;
35
37
  const prefix = usePrefix();
36
- const tileClasses = cx(`${prefix}--tile`, light && `${prefix}--tile--light`, className);
38
+ const tileClasses = cx(`${prefix}--tile`, {
39
+ [`${prefix}--tile--light`]: light,
40
+ [`${prefix}--tile--slug`]: slug,
41
+ [`${prefix}--tile--slug-rounded`]: slug && hasRoundedCorners
42
+ }, className);
37
43
  return /*#__PURE__*/React__default.createElement("div", _extends({
38
44
  className: tileClasses,
39
45
  ref: ref
40
- }, rest), children);
46
+ }, rest), children, slug);
41
47
  });
42
48
  Tile.displayName = 'Tile';
43
49
  Tile.propTypes = {
@@ -49,13 +55,22 @@ Tile.propTypes = {
49
55
  * The CSS class names.
50
56
  */
51
57
  className: PropTypes.string,
58
+ /**
59
+ * **Experimental**: Specify if the `Tile` component should be rendered with rounded corners. Only valid
60
+ * when `slug` prop is present
61
+ */
62
+ hasRoundedCorners: PropTypes.bool,
52
63
  /**
53
64
  * `true` to use the light version. For use on $ui-01 backgrounds only.
54
65
  * Don't use this to make tile background color same as container background color.
55
66
  *
56
67
  * @deprecated
57
68
  */
58
- light: deprecate(PropTypes.bool, 'The `light` prop for `Tile` is no longer needed and has been deprecated. It will be removed in the next major release. Use the Layer component instead.')
69
+ light: deprecate(PropTypes.bool, 'The `light` prop for `Tile` is no longer needed and has been deprecated. It will be removed in the next major release. Use the Layer component instead.'),
70
+ /**
71
+ * **Experimental**: Provide a `Slug` component to be rendered inside the `Tile` component
72
+ */
73
+ slug: PropTypes.node
59
74
  };
60
75
  const ClickableTile = /*#__PURE__*/React__default.forwardRef(function ClickableTile(_ref2, ref) {
61
76
  let {
@@ -68,10 +83,17 @@ const ClickableTile = /*#__PURE__*/React__default.forwardRef(function ClickableT
68
83
  onClick = () => {},
69
84
  onKeyDown = () => {},
70
85
  renderIcon: Icon,
86
+ hasRoundedCorners,
87
+ slug,
71
88
  ...rest
72
89
  } = _ref2;
73
90
  const prefix = usePrefix();
74
- const classes = cx(`${prefix}--tile`, `${prefix}--tile--clickable`, clicked && `${prefix}--tile--is-clicked`, light && `${prefix}--tile--light`, className);
91
+ const classes = cx(`${prefix}--tile`, `${prefix}--tile--clickable`, {
92
+ [`${prefix}--tile--is-clicked`]: clicked,
93
+ [`${prefix}--tile--light`]: light,
94
+ [`${prefix}--tile--slug`]: slug,
95
+ [`${prefix}--tile--slug-rounded`]: slug && hasRoundedCorners
96
+ }, className);
75
97
  const [isSelected, setIsSelected] = useState(clicked);
76
98
  function handleOnClick(evt) {
77
99
  evt?.persist?.();
@@ -85,6 +107,25 @@ const ClickableTile = /*#__PURE__*/React__default.forwardRef(function ClickableT
85
107
  }
86
108
  onKeyDown(evt);
87
109
  }
110
+
111
+ // To Do: Replace with an an icon from `@carbon/react`
112
+ // since the hollow slug in `ClickableTile` is not interactive
113
+ const hollowSlugIcon = /*#__PURE__*/React__default.createElement("svg", {
114
+ className: `${prefix}--tile--slug-icon`,
115
+ width: "24",
116
+ height: "24",
117
+ viewBox: "0 0 24 24",
118
+ fill: "none",
119
+ xmlns: "http://www.w3.org/2000/svg"
120
+ }, _rect || (_rect = /*#__PURE__*/React__default.createElement("rect", {
121
+ x: "0.5",
122
+ y: "0.5",
123
+ width: "23",
124
+ height: "23"
125
+ })), _path || (_path = /*#__PURE__*/React__default.createElement("path", {
126
+ d: "M13.2436 16H11.5996L10.9276 13.864H7.95164L7.29164 16H5.68364L8.49164 7.624H10.4596L13.2436 16ZM10.5436 12.508L9.46364 9.064H9.40364L8.33564 12.508H10.5436ZM17.9341 16H14.1301V14.728H15.2341V8.896H14.1301V7.624H17.9341V8.896H16.8181V14.728H17.9341V16Z",
127
+ fill: "#161616"
128
+ })));
88
129
  const v12DefaultIcons = useFeatureFlag('enable-v12-tile-default-icons');
89
130
  if (v12DefaultIcons) {
90
131
  if (!Icon) {
@@ -106,7 +147,9 @@ const ClickableTile = /*#__PURE__*/React__default.forwardRef(function ClickableT
106
147
  onKeyDown: handleOnKeyDown,
107
148
  ref: ref,
108
149
  disabled: disabled
109
- }, rest), children, Icon && /*#__PURE__*/React__default.createElement(Icon, {
150
+ }, rest), slug ? /*#__PURE__*/React__default.createElement("div", {
151
+ className: `${prefix}--tile-content`
152
+ }, children) : children, slug && hollowSlugIcon, Icon && /*#__PURE__*/React__default.createElement(Icon, {
110
153
  className: iconClasses,
111
154
  "aria-hidden": "true"
112
155
  }));
@@ -129,6 +172,11 @@ ClickableTile.propTypes = {
129
172
  * Specify whether the ClickableTile should be disabled
130
173
  */
131
174
  disabled: PropTypes.bool,
175
+ /**
176
+ * **Experimental**: Specify if the `ClickableTile` component should be rendered with rounded corners.
177
+ * Only valid when `slug` prop is present
178
+ */
179
+ hasRoundedCorners: PropTypes.bool,
132
180
  /**
133
181
  * The href for the link.
134
182
  */
@@ -170,6 +218,8 @@ const SelectableTile = /*#__PURE__*/React__default.forwardRef(function Selectabl
170
218
  selected = false,
171
219
  tabIndex = 0,
172
220
  title = 'title',
221
+ slug,
222
+ hasRoundedCorners,
173
223
  ...rest
174
224
  } = _ref3;
175
225
  const prefix = usePrefix();
@@ -177,12 +227,21 @@ const SelectableTile = /*#__PURE__*/React__default.forwardRef(function Selectabl
177
227
  const keyDownHandler = onKeyDown;
178
228
  const [isSelected, setIsSelected] = useState(selected);
179
229
  const [prevSelected, setPrevSelected] = useState(selected);
180
- const classes = cx(`${prefix}--tile`, `${prefix}--tile--selectable`, isSelected && `${prefix}--tile--is-selected`, light && `${prefix}--tile--light`, disabled && `${prefix}--tile--disabled`, className);
230
+ const classes = cx(`${prefix}--tile`, `${prefix}--tile--selectable`, {
231
+ [`${prefix}--tile--is-selected`]: isSelected,
232
+ [`${prefix}--tile--light`]: light,
233
+ [`${prefix}--tile--disabled`]: disabled,
234
+ [`${prefix}--tile--slug`]: slug,
235
+ [`${prefix}--tile--slug-rounded`]: slug && hasRoundedCorners
236
+ }, className);
181
237
 
182
238
  // TODO: rename to handleClick when handleClick prop is deprecated
183
239
  function handleOnClick(evt) {
184
240
  evt.preventDefault();
185
241
  evt?.persist?.();
242
+ if (slug && slugRef.current && slugRef.current.contains(evt.target)) {
243
+ return;
244
+ }
186
245
  setIsSelected(!isSelected);
187
246
  clickHandler(evt);
188
247
  onChange(evt);
@@ -206,6 +265,16 @@ const SelectableTile = /*#__PURE__*/React__default.forwardRef(function Selectabl
206
265
  setIsSelected(selected);
207
266
  setPrevSelected(selected);
208
267
  }
268
+
269
+ // Slug is always size `xs`
270
+ const slugRef = useRef(null);
271
+ let normalizedSlug;
272
+ if (slug) {
273
+ normalizedSlug = /*#__PURE__*/React__default.cloneElement(slug, {
274
+ size: 'xs',
275
+ ref: slugRef
276
+ });
277
+ }
209
278
  return (
210
279
  /*#__PURE__*/
211
280
  // eslint-disable-next-line jsx-a11y/interactive-supports-focus
@@ -228,10 +297,9 @@ const SelectableTile = /*#__PURE__*/React__default.forwardRef(function Selectabl
228
297
  as: "label",
229
298
  htmlFor: id,
230
299
  className: `${prefix}--tile-content`
231
- }, children))
300
+ }, children), normalizedSlug)
232
301
  );
233
302
  });
234
- SelectableTile.displayName = 'SelectableTile';
235
303
  SelectableTile.propTypes = {
236
304
  children: PropTypes.node,
237
305
  className: PropTypes.string,
@@ -239,6 +307,11 @@ SelectableTile.propTypes = {
239
307
  * Specify whether the SelectableTile should be disabled
240
308
  */
241
309
  disabled: PropTypes.bool,
310
+ /**
311
+ * **Experimental**: Specify if the `SelectableTile` component should be rendered with rounded corners.
312
+ * Only valid when `slug` prop is present
313
+ */
314
+ hasRoundedCorners: PropTypes.bool,
242
315
  /**
243
316
  * The ID of the `<input>`.
244
317
  */
@@ -269,6 +342,10 @@ SelectableTile.propTypes = {
269
342
  * `true` to select this tile.
270
343
  */
271
344
  selected: PropTypes.bool,
345
+ /**
346
+ * **Experimental**: Provide a `Slug` component to be rendered inside the `SelectableTile` component
347
+ */
348
+ slug: PropTypes.node,
272
349
  /**
273
350
  * Specify the tab index of the wrapper element
274
351
  */
@@ -300,6 +377,8 @@ const ExpandableTile = /*#__PURE__*/React__default.forwardRef(function Expandabl
300
377
  tileCollapsedLabel,
301
378
  tileExpandedLabel,
302
379
  light,
380
+ slug,
381
+ hasRoundedCorners,
303
382
  ...rest
304
383
  } = _ref4;
305
384
  const [isTileMaxHeight, setIsTileMaxHeight] = useState(tileMaxHeight);
@@ -355,7 +434,12 @@ const ExpandableTile = /*#__PURE__*/React__default.forwardRef(function Expandabl
355
434
  [`${prefix}--tile--is-expanded`]: isExpanded,
356
435
  [`${prefix}--tile--light`]: light
357
436
  }, className);
358
- const interactiveClassNames = cx(`${prefix}--tile`, `${prefix}--tile--expandable`, `${prefix}--tile--expandable--interactive`, isExpanded && `${prefix}--tile--is-expanded`, light && `${prefix}--tile--light`, className);
437
+ const interactiveClassNames = cx(`${prefix}--tile`, `${prefix}--tile--expandable`, `${prefix}--tile--expandable--interactive`, {
438
+ [`${prefix}--tile--is-expanded`]: isExpanded,
439
+ [`${prefix}--tile--light`]: light,
440
+ [`${prefix}--tile--slug`]: slug,
441
+ [`${prefix}--tile--slug-rounded`]: slug && hasRoundedCorners
442
+ }, className);
359
443
  const chevronInteractiveClassNames = cx(`${prefix}--tile__chevron`, `${prefix}--tile__chevron--interactive`);
360
444
  const childrenAsArray = getChildren();
361
445
  useIsomorphicEffect(() => {
@@ -381,10 +465,10 @@ const ExpandableTile = /*#__PURE__*/React__default.forwardRef(function Expandabl
381
465
 
382
466
  // Interactive elements or elements that are given a role should be treated
383
467
  // the same because elements with a role can not be rendered inside a `button`
384
- if (!getInteractiveContent(belowTheFold.current) && !getRoleContent(belowTheFold.current) && !getInteractiveContent(aboveTheFold.current) && !getRoleContent(aboveTheFold.current)) {
468
+ if (!getInteractiveContent(belowTheFold.current) && !getRoleContent(belowTheFold.current) && !getInteractiveContent(aboveTheFold.current) && !getRoleContent(aboveTheFold.current) && !slug) {
385
469
  setInteractive(false);
386
470
  }
387
- }, []);
471
+ }, [slug]);
388
472
  useIsomorphicEffect(() => {
389
473
  if (!tile.current) {
390
474
  return;
@@ -407,13 +491,21 @@ const ExpandableTile = /*#__PURE__*/React__default.forwardRef(function Expandabl
407
491
  return () => resizeObserver.disconnect();
408
492
  }, []);
409
493
  const belowTheFoldId = useId('expandable-tile-interactive');
494
+
495
+ // Slug is always size `xs`
496
+ let normalizedSlug;
497
+ if (slug) {
498
+ normalizedSlug = /*#__PURE__*/React__default.cloneElement(slug, {
499
+ size: 'xs'
500
+ });
501
+ }
410
502
  return interactive ? /*#__PURE__*/React__default.createElement("div", _extends({
411
503
  // @ts-expect-error: Needlesly strict & deep typing for the element type
412
504
  ref: ref,
413
505
  className: interactiveClassNames
414
506
  }, rest), /*#__PURE__*/React__default.createElement("div", {
415
507
  ref: tileContent
416
- }, /*#__PURE__*/React__default.createElement("div", {
508
+ }, normalizedSlug, /*#__PURE__*/React__default.createElement("div", {
417
509
  ref: aboveTheFold,
418
510
  className: `${prefix}--tile-content`
419
511
  }, childrenAsArray[0]), /*#__PURE__*/React__default.createElement("button", {
@@ -459,6 +551,11 @@ ExpandableTile.propTypes = {
459
551
  * `true` if the tile is expanded.
460
552
  */
461
553
  expanded: PropTypes.bool,
554
+ /**
555
+ * Specify if the `ExpandableTile` component should be rendered with rounded corners.
556
+ * Only valid when `slug` prop is present
557
+ */
558
+ hasRoundedCorners: PropTypes.bool,
462
559
  /**
463
560
  * An ID that can be provided to aria-labelledby
464
561
  */
@@ -476,6 +573,10 @@ ExpandableTile.propTypes = {
476
573
  * optional handler to trigger a function when a key is pressed
477
574
  */
478
575
  onKeyUp: PropTypes.func,
576
+ /**
577
+ * **Experimental**: Provide a `Slug` component to be rendered inside the `ExpandableTile` component
578
+ */
579
+ slug: PropTypes.node,
479
580
  /**
480
581
  * The `tabindex` attribute.
481
582
  */
@@ -8,7 +8,7 @@
8
8
  import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
9
9
  import cx from 'classnames';
10
10
  import PropTypes from 'prop-types';
11
- import React__default, { useRef, useEffect } from 'react';
11
+ import React__default, { useRef, useState, useCallback, useEffect } from 'react';
12
12
  import { Popover, PopoverContent } from '../Popover/index.js';
13
13
  import { useDelayedState } from '../../internal/useDelayedState.js';
14
14
  import { useId } from '../../internal/useId.js';
@@ -17,6 +17,10 @@ import { usePrefix } from '../../internal/usePrefix.js';
17
17
  import { match } from '../../internal/keyboard/match.js';
18
18
  import { Escape, Enter, Space } from '../../internal/keyboard/keys.js';
19
19
 
20
+ /**
21
+ * Event types that trigger a "drag" to stop.
22
+ */
23
+ const DRAG_STOP_EVENT_TYPES = new Set(['mouseup', 'touchend', 'touchcancel']);
20
24
  function Tooltip(_ref) {
21
25
  let {
22
26
  align = 'top',
@@ -33,6 +37,8 @@ function Tooltip(_ref) {
33
37
  const containerRef = useRef(null);
34
38
  const tooltipRef = useRef(null);
35
39
  const [open, setOpen] = useDelayedState(defaultOpen);
40
+ const [isDragging, setIsDragging] = useState(false);
41
+ const [isPointerIntersecting, setIsPointerIntersecting] = useState(false);
36
42
  const id = useId('tooltip');
37
43
  const prefix = usePrefix();
38
44
  const child = React__default.Children.only(children);
@@ -41,7 +47,11 @@ function Tooltip(_ref) {
41
47
  onBlur: () => setOpen(false),
42
48
  onClick: () => closeOnActivation && setOpen(false),
43
49
  // This should be placed on the trigger in case the element is disabled
44
- onMouseEnter
50
+ onMouseEnter,
51
+ onMouseLeave,
52
+ onMouseDown: onDragStart,
53
+ onMouseMove: onMouseMove,
54
+ onTouchStart: onDragStart
45
55
  };
46
56
  function getChildEventHandlers(childProps) {
47
57
  const eventHandlerFunctions = ['onFocus', 'onBlur', 'onClick', 'onMouseEnter'];
@@ -71,11 +81,34 @@ function Tooltip(_ref) {
71
81
  }
72
82
  }
73
83
  function onMouseEnter() {
84
+ setIsPointerIntersecting(true);
74
85
  setOpen(true, enterDelayMs);
75
86
  }
76
87
  function onMouseLeave() {
88
+ setIsPointerIntersecting(false);
89
+ if (isDragging) {
90
+ return;
91
+ }
77
92
  setOpen(false, leaveDelayMs);
78
93
  }
94
+ function onMouseMove(evt) {
95
+ if (evt.buttons === 1) {
96
+ setIsDragging(true);
97
+ } else {
98
+ setIsDragging(false);
99
+ }
100
+ }
101
+ function onDragStart() {
102
+ setIsDragging(true);
103
+ }
104
+ const onDragStop = useCallback(() => {
105
+ setIsDragging(false);
106
+ // Close the tooltip, unless the mouse pointer is within the bounds of the
107
+ // trigger.
108
+ if (!isPointerIntersecting) {
109
+ setOpen(false, leaveDelayMs);
110
+ }
111
+ }, [isPointerIntersecting, leaveDelayMs, setOpen]);
79
112
  useNoInteractiveChildren(tooltipRef, 'The Tooltip component must have no interactive content rendered by the' + '`label` or `description` prop');
80
113
  useEffect(() => {
81
114
  if (containerRef !== null && containerRef.current) {
@@ -85,6 +118,19 @@ function Tooltip(_ref) {
85
118
  }
86
119
  }
87
120
  });
121
+ useEffect(() => {
122
+ if (isDragging) {
123
+ // Register drag stop handlers.
124
+ DRAG_STOP_EVENT_TYPES.forEach(eventType => {
125
+ document.addEventListener(eventType, onDragStop);
126
+ });
127
+ }
128
+ return () => {
129
+ DRAG_STOP_EVENT_TYPES.forEach(eventType => {
130
+ document.removeEventListener(eventType, onDragStop);
131
+ });
132
+ };
133
+ }, [isDragging, onDragStop]);
88
134
  return /*#__PURE__*/React__default.createElement(Popover, _extends({}, rest, {
89
135
  align: align,
90
136
  className: cx(`${prefix}--tooltip`, customClassName),