@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
@@ -49,6 +49,7 @@ const TextArea = /*#__PURE__*/React__default["default"].forwardRef((props, forwa
49
49
  placeholder = '',
50
50
  enableCounter = false,
51
51
  maxCount = undefined,
52
+ counterMode = 'character',
52
53
  warn = false,
53
54
  warnText = '',
54
55
  rows = 4,
@@ -63,15 +64,25 @@ const TextArea = /*#__PURE__*/React__default["default"].forwardRef((props, forwa
63
64
  defaultValue,
64
65
  value
65
66
  } = other;
66
- const [textCount, setTextCount] = React.useState(defaultValue?.toString()?.length || value?.toString()?.length || 0);
67
67
  const {
68
68
  current: textAreaInstanceId
69
69
  } = React.useRef(getInstanceId());
70
70
  const textareaRef = React.useRef(null);
71
71
  const ref = useMergedRefs.useMergedRefs([forwardRef, textareaRef]);
72
+ function getInitialTextCount() {
73
+ const targetValue = defaultValue || value || textareaRef.current?.value || '';
74
+ const strValue = targetValue.toString();
75
+ if (counterMode === 'character') {
76
+ return strValue.length;
77
+ } else {
78
+ return strValue.match(/\w+/g)?.length || 0;
79
+ }
80
+ }
81
+ const [textCount, setTextCount] = React.useState(getInitialTextCount());
72
82
  React.useEffect(() => {
73
- setTextCount(defaultValue?.toString()?.length || value?.toString()?.length || 0);
74
- }, [value, defaultValue]);
83
+ setTextCount(getInitialTextCount());
84
+ // eslint-disable-next-line react-hooks/exhaustive-deps
85
+ }, [value, defaultValue, counterMode]);
75
86
  useIsomorphicEffect["default"](() => {
76
87
  if (other.cols && textareaRef.current) {
77
88
  textareaRef.current.style.width = '';
@@ -82,14 +93,63 @@ const TextArea = /*#__PURE__*/React__default["default"].forwardRef((props, forwa
82
93
  }, [other.cols]);
83
94
  const textareaProps = {
84
95
  id,
96
+ onKeyDown: evt => {
97
+ if (!disabled && enableCounter && counterMode === 'word') {
98
+ const key = evt.which;
99
+ if (maxCount && textCount >= maxCount && key === 32) {
100
+ evt.preventDefault();
101
+ }
102
+ }
103
+ },
104
+ onPaste: evt => {
105
+ if (!disabled) {
106
+ if (counterMode === 'word' && enableCounter && typeof maxCount !== 'undefined' && textareaRef.current !== null) {
107
+ const existingWords = textareaRef.current.value.match(/\w+/g) || [];
108
+ const pastedWords = evt.clipboardData.getData('Text').match(/\w+/g) || [];
109
+ const totalWords = existingWords.length + pastedWords.length;
110
+ if (totalWords > maxCount) {
111
+ evt.preventDefault();
112
+ const allowedWords = existingWords.concat(pastedWords).slice(0, maxCount);
113
+ setTimeout(() => {
114
+ setTextCount(maxCount);
115
+ }, 0);
116
+ textareaRef.current.value = allowedWords.join(' ');
117
+ }
118
+ }
119
+ }
120
+ },
85
121
  onChange: evt => {
86
- if (!disabled && onChange) {
87
- evt?.persist?.();
88
- // delay textCount assignation to give the textarea element value time to catch up if is a controlled input
89
- setTimeout(() => {
90
- setTextCount(evt.target?.value?.length);
91
- }, 0);
92
- onChange(evt);
122
+ if (!disabled) {
123
+ if (counterMode == 'character') {
124
+ evt?.persist?.();
125
+ // delay textCount assignation to give the textarea element value time to catch up if is a controlled input
126
+ setTimeout(() => {
127
+ setTextCount(evt.target?.value?.length);
128
+ }, 0);
129
+ } else if (counterMode == 'word') {
130
+ if (!evt.target.value) {
131
+ setTimeout(() => {
132
+ setTextCount(0);
133
+ }, 0);
134
+ return;
135
+ }
136
+ if (enableCounter && typeof maxCount !== 'undefined' && textareaRef.current !== null) {
137
+ const matchedWords = evt.target?.value?.match(/\w+/g);
138
+ if (matchedWords && matchedWords.length <= maxCount) {
139
+ textareaRef.current.removeAttribute('maxLength');
140
+ setTimeout(() => {
141
+ setTextCount(matchedWords.length);
142
+ }, 0);
143
+ } else if (matchedWords && matchedWords.length > maxCount) {
144
+ setTimeout(() => {
145
+ setTextCount(matchedWords.length);
146
+ }, 0);
147
+ }
148
+ }
149
+ }
150
+ if (onChange) {
151
+ onChange(evt);
152
+ }
93
153
  }
94
154
  },
95
155
  onClick: evt => {
@@ -124,7 +184,7 @@ const TextArea = /*#__PURE__*/React__default["default"].forwardRef((props, forwa
124
184
  htmlFor: id,
125
185
  className: labelClasses
126
186
  }, labelText) : null;
127
- const counter = enableCounter && maxCount ? /*#__PURE__*/React__default["default"].createElement(Text.Text, {
187
+ const counter = enableCounter && maxCount && (counterMode === 'character' || counterMode === 'word') ? /*#__PURE__*/React__default["default"].createElement(Text.Text, {
128
188
  as: "div",
129
189
  className: counterClasses
130
190
  }, `${textCount}/${maxCount}`) : null;
@@ -157,9 +217,12 @@ const TextArea = /*#__PURE__*/React__default["default"].forwardRef((props, forwa
157
217
  ariaDescribedBy = helperId;
158
218
  }
159
219
  if (enableCounter) {
160
- textareaProps.maxLength = maxCount;
220
+ // handle different counter mode
221
+ if (counterMode == 'character') {
222
+ textareaProps.maxLength = maxCount;
223
+ }
161
224
  }
162
- const ariaAnnouncement = useAnnouncer.useAnnouncer(textCount, maxCount);
225
+ const ariaAnnouncement = useAnnouncer.useAnnouncer(textCount, maxCount, counterMode === 'word' ? 'words' : undefined);
163
226
  const input = /*#__PURE__*/React__default["default"].createElement("textarea", _rollupPluginBabelHelpers["extends"]({}, other, textareaProps, {
164
227
  placeholder: placeholder,
165
228
  className: textareaClasses,
@@ -207,6 +270,10 @@ TextArea.propTypes = {
207
270
  * Specify the `cols` attribute for the underlying `<textarea>` node
208
271
  */
209
272
  cols: PropTypes__default["default"].number,
273
+ /**
274
+ * Specify the method used for calculating the counter number
275
+ */
276
+ counterMode: PropTypes__default["default"].oneOf(['character', 'word']),
210
277
  /**
211
278
  * Optionally provide the default value of the `<textarea>`
212
279
  */
@@ -216,7 +283,7 @@ TextArea.propTypes = {
216
283
  */
217
284
  disabled: PropTypes__default["default"].bool,
218
285
  /**
219
- * Specify whether to display the character counter
286
+ * Specify whether to display the counter
220
287
  */
221
288
  enableCounter: PropTypes__default["default"].bool,
222
289
  /**
@@ -250,7 +317,7 @@ TextArea.propTypes = {
250
317
  */
251
318
  light: deprecate["default"](PropTypes__default["default"].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.'),
252
319
  /**
253
- * Max character count allowed for the textarea. This is needed in order for enableCounter to display
320
+ * Max entity count allowed for the textarea. This is needed in order for enableCounter to display
254
321
  */
255
322
  maxCount: PropTypes__default["default"].number,
256
323
  /**
@@ -276,7 +343,7 @@ TextArea.propTypes = {
276
343
  */
277
344
  rows: PropTypes__default["default"].number,
278
345
  /**
279
- * Provide a `Slug` component to be rendered inside the `TextArea` component
346
+ * **Experimental**: Provide a `Slug` component to be rendered inside the `TextArea` component
280
347
  */
281
348
  slug: PropTypes__default["default"].node,
282
349
  /**
@@ -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
  /**
@@ -271,7 +271,7 @@ TextInput.propTypes = {
271
271
  */
272
272
  size: PropTypes__default["default"].oneOf(['sm', 'md', 'lg']),
273
273
  /**
274
- * Provide a `Slug` component to be rendered inside the `TextInput` component
274
+ * **Experimental**: Provide a `Slug` component to be rendered inside the `TextInput` component
275
275
  */
276
276
  slug: PropTypes__default["default"].node,
277
277
  /**
@@ -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
  */
@@ -34,20 +34,26 @@ var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
34
34
  var PropTypes__default = /*#__PURE__*/_interopDefaultLegacy(PropTypes);
35
35
  var cx__default = /*#__PURE__*/_interopDefaultLegacy(cx);
36
36
 
37
- var _CheckboxCheckedFille, _Checkbox, _ChevronDown, _ChevronDown2;
37
+ var _rect, _path, _CheckboxCheckedFille, _Checkbox, _ChevronDown, _ChevronDown2;
38
38
  const Tile = /*#__PURE__*/React__default["default"].forwardRef(function Tile(_ref, ref) {
39
39
  let {
40
40
  children,
41
41
  className,
42
42
  light = false,
43
+ slug,
44
+ hasRoundedCorners = false,
43
45
  ...rest
44
46
  } = _ref;
45
47
  const prefix = usePrefix.usePrefix();
46
- const tileClasses = cx__default["default"](`${prefix}--tile`, light && `${prefix}--tile--light`, className);
48
+ const tileClasses = cx__default["default"](`${prefix}--tile`, {
49
+ [`${prefix}--tile--light`]: light,
50
+ [`${prefix}--tile--slug`]: slug,
51
+ [`${prefix}--tile--slug-rounded`]: slug && hasRoundedCorners
52
+ }, className);
47
53
  return /*#__PURE__*/React__default["default"].createElement("div", _rollupPluginBabelHelpers["extends"]({
48
54
  className: tileClasses,
49
55
  ref: ref
50
- }, rest), children);
56
+ }, rest), children, slug);
51
57
  });
52
58
  Tile.displayName = 'Tile';
53
59
  Tile.propTypes = {
@@ -59,13 +65,22 @@ Tile.propTypes = {
59
65
  * The CSS class names.
60
66
  */
61
67
  className: PropTypes__default["default"].string,
68
+ /**
69
+ * **Experimental**: Specify if the `Tile` component should be rendered with rounded corners. Only valid
70
+ * when `slug` prop is present
71
+ */
72
+ hasRoundedCorners: PropTypes__default["default"].bool,
62
73
  /**
63
74
  * `true` to use the light version. For use on $ui-01 backgrounds only.
64
75
  * Don't use this to make tile background color same as container background color.
65
76
  *
66
77
  * @deprecated
67
78
  */
68
- light: deprecate["default"](PropTypes__default["default"].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.')
79
+ light: deprecate["default"](PropTypes__default["default"].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.'),
80
+ /**
81
+ * **Experimental**: Provide a `Slug` component to be rendered inside the `Tile` component
82
+ */
83
+ slug: PropTypes__default["default"].node
69
84
  };
70
85
  const ClickableTile = /*#__PURE__*/React__default["default"].forwardRef(function ClickableTile(_ref2, ref) {
71
86
  let {
@@ -78,10 +93,17 @@ const ClickableTile = /*#__PURE__*/React__default["default"].forwardRef(function
78
93
  onClick = () => {},
79
94
  onKeyDown = () => {},
80
95
  renderIcon: Icon,
96
+ hasRoundedCorners,
97
+ slug,
81
98
  ...rest
82
99
  } = _ref2;
83
100
  const prefix = usePrefix.usePrefix();
84
- const classes = cx__default["default"](`${prefix}--tile`, `${prefix}--tile--clickable`, clicked && `${prefix}--tile--is-clicked`, light && `${prefix}--tile--light`, className);
101
+ const classes = cx__default["default"](`${prefix}--tile`, `${prefix}--tile--clickable`, {
102
+ [`${prefix}--tile--is-clicked`]: clicked,
103
+ [`${prefix}--tile--light`]: light,
104
+ [`${prefix}--tile--slug`]: slug,
105
+ [`${prefix}--tile--slug-rounded`]: slug && hasRoundedCorners
106
+ }, className);
85
107
  const [isSelected, setIsSelected] = React.useState(clicked);
86
108
  function handleOnClick(evt) {
87
109
  evt?.persist?.();
@@ -95,6 +117,25 @@ const ClickableTile = /*#__PURE__*/React__default["default"].forwardRef(function
95
117
  }
96
118
  onKeyDown(evt);
97
119
  }
120
+
121
+ // To Do: Replace with an an icon from `@carbon/react`
122
+ // since the hollow slug in `ClickableTile` is not interactive
123
+ const hollowSlugIcon = /*#__PURE__*/React__default["default"].createElement("svg", {
124
+ className: `${prefix}--tile--slug-icon`,
125
+ width: "24",
126
+ height: "24",
127
+ viewBox: "0 0 24 24",
128
+ fill: "none",
129
+ xmlns: "http://www.w3.org/2000/svg"
130
+ }, _rect || (_rect = /*#__PURE__*/React__default["default"].createElement("rect", {
131
+ x: "0.5",
132
+ y: "0.5",
133
+ width: "23",
134
+ height: "23"
135
+ })), _path || (_path = /*#__PURE__*/React__default["default"].createElement("path", {
136
+ 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",
137
+ fill: "#161616"
138
+ })));
98
139
  const v12DefaultIcons = index.useFeatureFlag('enable-v12-tile-default-icons');
99
140
  if (v12DefaultIcons) {
100
141
  if (!Icon) {
@@ -116,7 +157,9 @@ const ClickableTile = /*#__PURE__*/React__default["default"].forwardRef(function
116
157
  onKeyDown: handleOnKeyDown,
117
158
  ref: ref,
118
159
  disabled: disabled
119
- }, rest), children, Icon && /*#__PURE__*/React__default["default"].createElement(Icon, {
160
+ }, rest), slug ? /*#__PURE__*/React__default["default"].createElement("div", {
161
+ className: `${prefix}--tile-content`
162
+ }, children) : children, slug && hollowSlugIcon, Icon && /*#__PURE__*/React__default["default"].createElement(Icon, {
120
163
  className: iconClasses,
121
164
  "aria-hidden": "true"
122
165
  }));
@@ -139,6 +182,11 @@ ClickableTile.propTypes = {
139
182
  * Specify whether the ClickableTile should be disabled
140
183
  */
141
184
  disabled: PropTypes__default["default"].bool,
185
+ /**
186
+ * **Experimental**: Specify if the `ClickableTile` component should be rendered with rounded corners.
187
+ * Only valid when `slug` prop is present
188
+ */
189
+ hasRoundedCorners: PropTypes__default["default"].bool,
142
190
  /**
143
191
  * The href for the link.
144
192
  */
@@ -180,6 +228,8 @@ const SelectableTile = /*#__PURE__*/React__default["default"].forwardRef(functio
180
228
  selected = false,
181
229
  tabIndex = 0,
182
230
  title = 'title',
231
+ slug,
232
+ hasRoundedCorners,
183
233
  ...rest
184
234
  } = _ref3;
185
235
  const prefix = usePrefix.usePrefix();
@@ -187,12 +237,21 @@ const SelectableTile = /*#__PURE__*/React__default["default"].forwardRef(functio
187
237
  const keyDownHandler = onKeyDown;
188
238
  const [isSelected, setIsSelected] = React.useState(selected);
189
239
  const [prevSelected, setPrevSelected] = React.useState(selected);
190
- const classes = cx__default["default"](`${prefix}--tile`, `${prefix}--tile--selectable`, isSelected && `${prefix}--tile--is-selected`, light && `${prefix}--tile--light`, disabled && `${prefix}--tile--disabled`, className);
240
+ const classes = cx__default["default"](`${prefix}--tile`, `${prefix}--tile--selectable`, {
241
+ [`${prefix}--tile--is-selected`]: isSelected,
242
+ [`${prefix}--tile--light`]: light,
243
+ [`${prefix}--tile--disabled`]: disabled,
244
+ [`${prefix}--tile--slug`]: slug,
245
+ [`${prefix}--tile--slug-rounded`]: slug && hasRoundedCorners
246
+ }, className);
191
247
 
192
248
  // TODO: rename to handleClick when handleClick prop is deprecated
193
249
  function handleOnClick(evt) {
194
250
  evt.preventDefault();
195
251
  evt?.persist?.();
252
+ if (slug && slugRef.current && slugRef.current.contains(evt.target)) {
253
+ return;
254
+ }
196
255
  setIsSelected(!isSelected);
197
256
  clickHandler(evt);
198
257
  onChange(evt);
@@ -216,6 +275,16 @@ const SelectableTile = /*#__PURE__*/React__default["default"].forwardRef(functio
216
275
  setIsSelected(selected);
217
276
  setPrevSelected(selected);
218
277
  }
278
+
279
+ // Slug is always size `xs`
280
+ const slugRef = React.useRef(null);
281
+ let normalizedSlug;
282
+ if (slug) {
283
+ normalizedSlug = /*#__PURE__*/React__default["default"].cloneElement(slug, {
284
+ size: 'xs',
285
+ ref: slugRef
286
+ });
287
+ }
219
288
  return (
220
289
  /*#__PURE__*/
221
290
  // eslint-disable-next-line jsx-a11y/interactive-supports-focus
@@ -238,10 +307,9 @@ const SelectableTile = /*#__PURE__*/React__default["default"].forwardRef(functio
238
307
  as: "label",
239
308
  htmlFor: id,
240
309
  className: `${prefix}--tile-content`
241
- }, children))
310
+ }, children), normalizedSlug)
242
311
  );
243
312
  });
244
- SelectableTile.displayName = 'SelectableTile';
245
313
  SelectableTile.propTypes = {
246
314
  children: PropTypes__default["default"].node,
247
315
  className: PropTypes__default["default"].string,
@@ -249,6 +317,11 @@ SelectableTile.propTypes = {
249
317
  * Specify whether the SelectableTile should be disabled
250
318
  */
251
319
  disabled: PropTypes__default["default"].bool,
320
+ /**
321
+ * **Experimental**: Specify if the `SelectableTile` component should be rendered with rounded corners.
322
+ * Only valid when `slug` prop is present
323
+ */
324
+ hasRoundedCorners: PropTypes__default["default"].bool,
252
325
  /**
253
326
  * The ID of the `<input>`.
254
327
  */
@@ -279,6 +352,10 @@ SelectableTile.propTypes = {
279
352
  * `true` to select this tile.
280
353
  */
281
354
  selected: PropTypes__default["default"].bool,
355
+ /**
356
+ * **Experimental**: Provide a `Slug` component to be rendered inside the `SelectableTile` component
357
+ */
358
+ slug: PropTypes__default["default"].node,
282
359
  /**
283
360
  * Specify the tab index of the wrapper element
284
361
  */
@@ -310,6 +387,8 @@ const ExpandableTile = /*#__PURE__*/React__default["default"].forwardRef(functio
310
387
  tileCollapsedLabel,
311
388
  tileExpandedLabel,
312
389
  light,
390
+ slug,
391
+ hasRoundedCorners,
313
392
  ...rest
314
393
  } = _ref4;
315
394
  const [isTileMaxHeight, setIsTileMaxHeight] = React.useState(tileMaxHeight);
@@ -365,7 +444,12 @@ const ExpandableTile = /*#__PURE__*/React__default["default"].forwardRef(functio
365
444
  [`${prefix}--tile--is-expanded`]: isExpanded,
366
445
  [`${prefix}--tile--light`]: light
367
446
  }, className);
368
- const interactiveClassNames = cx__default["default"](`${prefix}--tile`, `${prefix}--tile--expandable`, `${prefix}--tile--expandable--interactive`, isExpanded && `${prefix}--tile--is-expanded`, light && `${prefix}--tile--light`, className);
447
+ const interactiveClassNames = cx__default["default"](`${prefix}--tile`, `${prefix}--tile--expandable`, `${prefix}--tile--expandable--interactive`, {
448
+ [`${prefix}--tile--is-expanded`]: isExpanded,
449
+ [`${prefix}--tile--light`]: light,
450
+ [`${prefix}--tile--slug`]: slug,
451
+ [`${prefix}--tile--slug-rounded`]: slug && hasRoundedCorners
452
+ }, className);
369
453
  const chevronInteractiveClassNames = cx__default["default"](`${prefix}--tile__chevron`, `${prefix}--tile__chevron--interactive`);
370
454
  const childrenAsArray = getChildren();
371
455
  useIsomorphicEffect["default"](() => {
@@ -391,10 +475,10 @@ const ExpandableTile = /*#__PURE__*/React__default["default"].forwardRef(functio
391
475
 
392
476
  // Interactive elements or elements that are given a role should be treated
393
477
  // the same because elements with a role can not be rendered inside a `button`
394
- if (!useNoInteractiveChildren.getInteractiveContent(belowTheFold.current) && !useNoInteractiveChildren.getRoleContent(belowTheFold.current) && !useNoInteractiveChildren.getInteractiveContent(aboveTheFold.current) && !useNoInteractiveChildren.getRoleContent(aboveTheFold.current)) {
478
+ if (!useNoInteractiveChildren.getInteractiveContent(belowTheFold.current) && !useNoInteractiveChildren.getRoleContent(belowTheFold.current) && !useNoInteractiveChildren.getInteractiveContent(aboveTheFold.current) && !useNoInteractiveChildren.getRoleContent(aboveTheFold.current) && !slug) {
395
479
  setInteractive(false);
396
480
  }
397
- }, []);
481
+ }, [slug]);
398
482
  useIsomorphicEffect["default"](() => {
399
483
  if (!tile.current) {
400
484
  return;
@@ -417,13 +501,21 @@ const ExpandableTile = /*#__PURE__*/React__default["default"].forwardRef(functio
417
501
  return () => resizeObserver.disconnect();
418
502
  }, []);
419
503
  const belowTheFoldId = useId.useId('expandable-tile-interactive');
504
+
505
+ // Slug is always size `xs`
506
+ let normalizedSlug;
507
+ if (slug) {
508
+ normalizedSlug = /*#__PURE__*/React__default["default"].cloneElement(slug, {
509
+ size: 'xs'
510
+ });
511
+ }
420
512
  return interactive ? /*#__PURE__*/React__default["default"].createElement("div", _rollupPluginBabelHelpers["extends"]({
421
513
  // @ts-expect-error: Needlesly strict & deep typing for the element type
422
514
  ref: ref,
423
515
  className: interactiveClassNames
424
516
  }, rest), /*#__PURE__*/React__default["default"].createElement("div", {
425
517
  ref: tileContent
426
- }, /*#__PURE__*/React__default["default"].createElement("div", {
518
+ }, normalizedSlug, /*#__PURE__*/React__default["default"].createElement("div", {
427
519
  ref: aboveTheFold,
428
520
  className: `${prefix}--tile-content`
429
521
  }, childrenAsArray[0]), /*#__PURE__*/React__default["default"].createElement("button", {
@@ -469,6 +561,11 @@ ExpandableTile.propTypes = {
469
561
  * `true` if the tile is expanded.
470
562
  */
471
563
  expanded: PropTypes__default["default"].bool,
564
+ /**
565
+ * Specify if the `ExpandableTile` component should be rendered with rounded corners.
566
+ * Only valid when `slug` prop is present
567
+ */
568
+ hasRoundedCorners: PropTypes__default["default"].bool,
472
569
  /**
473
570
  * An ID that can be provided to aria-labelledby
474
571
  */
@@ -486,6 +583,10 @@ ExpandableTile.propTypes = {
486
583
  * optional handler to trigger a function when a key is pressed
487
584
  */
488
585
  onKeyUp: PropTypes__default["default"].func,
586
+ /**
587
+ * **Experimental**: Provide a `Slug` component to be rendered inside the `ExpandableTile` component
588
+ */
589
+ slug: PropTypes__default["default"].node,
489
590
  /**
490
591
  * The `tabindex` attribute.
491
592
  */
@@ -27,6 +27,10 @@ var cx__default = /*#__PURE__*/_interopDefaultLegacy(cx);
27
27
  var PropTypes__default = /*#__PURE__*/_interopDefaultLegacy(PropTypes);
28
28
  var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
29
29
 
30
+ /**
31
+ * Event types that trigger a "drag" to stop.
32
+ */
33
+ const DRAG_STOP_EVENT_TYPES = new Set(['mouseup', 'touchend', 'touchcancel']);
30
34
  function Tooltip(_ref) {
31
35
  let {
32
36
  align = 'top',
@@ -43,6 +47,8 @@ function Tooltip(_ref) {
43
47
  const containerRef = React.useRef(null);
44
48
  const tooltipRef = React.useRef(null);
45
49
  const [open, setOpen] = useDelayedState.useDelayedState(defaultOpen);
50
+ const [isDragging, setIsDragging] = React.useState(false);
51
+ const [isPointerIntersecting, setIsPointerIntersecting] = React.useState(false);
46
52
  const id = useId.useId('tooltip');
47
53
  const prefix = usePrefix.usePrefix();
48
54
  const child = React__default["default"].Children.only(children);
@@ -51,7 +57,11 @@ function Tooltip(_ref) {
51
57
  onBlur: () => setOpen(false),
52
58
  onClick: () => closeOnActivation && setOpen(false),
53
59
  // This should be placed on the trigger in case the element is disabled
54
- onMouseEnter
60
+ onMouseEnter,
61
+ onMouseLeave,
62
+ onMouseDown: onDragStart,
63
+ onMouseMove: onMouseMove,
64
+ onTouchStart: onDragStart
55
65
  };
56
66
  function getChildEventHandlers(childProps) {
57
67
  const eventHandlerFunctions = ['onFocus', 'onBlur', 'onClick', 'onMouseEnter'];
@@ -81,11 +91,34 @@ function Tooltip(_ref) {
81
91
  }
82
92
  }
83
93
  function onMouseEnter() {
94
+ setIsPointerIntersecting(true);
84
95
  setOpen(true, enterDelayMs);
85
96
  }
86
97
  function onMouseLeave() {
98
+ setIsPointerIntersecting(false);
99
+ if (isDragging) {
100
+ return;
101
+ }
87
102
  setOpen(false, leaveDelayMs);
88
103
  }
104
+ function onMouseMove(evt) {
105
+ if (evt.buttons === 1) {
106
+ setIsDragging(true);
107
+ } else {
108
+ setIsDragging(false);
109
+ }
110
+ }
111
+ function onDragStart() {
112
+ setIsDragging(true);
113
+ }
114
+ const onDragStop = React.useCallback(() => {
115
+ setIsDragging(false);
116
+ // Close the tooltip, unless the mouse pointer is within the bounds of the
117
+ // trigger.
118
+ if (!isPointerIntersecting) {
119
+ setOpen(false, leaveDelayMs);
120
+ }
121
+ }, [isPointerIntersecting, leaveDelayMs, setOpen]);
89
122
  useNoInteractiveChildren.useNoInteractiveChildren(tooltipRef, 'The Tooltip component must have no interactive content rendered by the' + '`label` or `description` prop');
90
123
  React.useEffect(() => {
91
124
  if (containerRef !== null && containerRef.current) {
@@ -95,6 +128,19 @@ function Tooltip(_ref) {
95
128
  }
96
129
  }
97
130
  });
131
+ React.useEffect(() => {
132
+ if (isDragging) {
133
+ // Register drag stop handlers.
134
+ DRAG_STOP_EVENT_TYPES.forEach(eventType => {
135
+ document.addEventListener(eventType, onDragStop);
136
+ });
137
+ }
138
+ return () => {
139
+ DRAG_STOP_EVENT_TYPES.forEach(eventType => {
140
+ document.removeEventListener(eventType, onDragStop);
141
+ });
142
+ };
143
+ }, [isDragging, onDragStop]);
98
144
  return /*#__PURE__*/React__default["default"].createElement(index.Popover, _rollupPluginBabelHelpers["extends"]({}, rest, {
99
145
  align: align,
100
146
  className: cx__default["default"](`${prefix}--tooltip`, customClassName),