@carbon/react 1.44.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 (122) hide show
  1. package/.playwright/INTERNAL_AVT_REPORT_DO_NOT_USE.json +805 -805
  2. package/es/components/Checkbox/Checkbox.d.ts +1 -1
  3. package/es/components/Checkbox/Checkbox.js +1 -1
  4. package/es/components/CheckboxGroup/CheckboxGroup.js +1 -1
  5. package/es/components/ComboBox/ComboBox.d.ts +1 -1
  6. package/es/components/ComboBox/ComboBox.js +1 -1
  7. package/es/components/ComboButton/index.js +1 -1
  8. package/es/components/ComposedModal/ModalFooter.d.ts +2 -1
  9. package/es/components/DataTable/DataTable.d.ts +2 -0
  10. package/es/components/DataTable/DataTable.js +3 -0
  11. package/es/components/DataTable/TableExpandRow.js +20 -3
  12. package/es/components/DataTable/TableHeader.d.ts +5 -0
  13. package/es/components/DataTable/TableHeader.js +30 -6
  14. package/es/components/DataTable/TableSlugRow.d.ts +31 -0
  15. package/es/components/DataTable/TableSlugRow.js +49 -0
  16. package/es/components/DataTable/index.d.ts +2 -1
  17. package/es/components/DataTable/index.js +3 -0
  18. package/es/components/DatePickerInput/DatePickerInput.d.ts +1 -1
  19. package/es/components/DatePickerInput/DatePickerInput.js +1 -1
  20. package/es/components/Dropdown/Dropdown.d.ts +1 -1
  21. package/es/components/Dropdown/Dropdown.js +1 -1
  22. package/es/components/InlineLoading/InlineLoading.d.ts +68 -0
  23. package/es/components/InlineLoading/InlineLoading.js +4 -4
  24. package/es/components/InlineLoading/index.d.ts +9 -0
  25. package/es/components/Layer/LayerContext.d.ts +8 -0
  26. package/es/components/Layer/LayerLevel.d.ts +5 -0
  27. package/es/components/Layer/LayerLevel.js +12 -0
  28. package/es/components/Layer/index.d.ts +38 -0
  29. package/es/components/Layer/index.js +9 -8
  30. package/es/components/Menu/MenuItem.js +2 -1
  31. package/es/components/MenuButton/index.js +1 -1
  32. package/es/components/Modal/Modal.d.ts +3 -2
  33. package/es/components/MultiSelect/FilterableMultiSelect.js +1 -1
  34. package/es/components/MultiSelect/MultiSelect.d.ts +1 -1
  35. package/es/components/MultiSelect/MultiSelect.js +1 -1
  36. package/es/components/Notification/Notification.js +1 -0
  37. package/es/components/NumberInput/NumberInput.d.ts +1 -1
  38. package/es/components/NumberInput/NumberInput.js +1 -1
  39. package/es/components/RadioButton/RadioButton.d.ts +1 -1
  40. package/es/components/RadioButton/RadioButton.js +1 -1
  41. package/es/components/RadioButtonGroup/RadioButtonGroup.d.ts +1 -1
  42. package/es/components/RadioButtonGroup/RadioButtonGroup.js +1 -1
  43. package/es/components/Select/Select.d.ts +1 -1
  44. package/es/components/Select/Select.js +1 -1
  45. package/es/components/Slider/Slider.Skeleton.js +17 -3
  46. package/es/components/Slider/Slider.js +132 -93
  47. package/es/components/Slider/SliderHandles.d.ts +4 -0
  48. package/es/components/Slider/SliderHandles.js +65 -0
  49. package/es/components/Tabs/Tabs.js +1 -1
  50. package/es/components/TextArea/TextArea.d.ts +7 -3
  51. package/es/components/TextArea/TextArea.js +84 -17
  52. package/es/components/TextInput/TextInput.d.ts +1 -1
  53. package/es/components/TextInput/TextInput.js +1 -1
  54. package/es/components/Tile/Tile.d.ts +8 -8
  55. package/es/components/Tile/Tile.js +9 -5
  56. package/es/components/Tooltip/Tooltip.js +48 -2
  57. package/es/components/UIShell/HeaderPanel.d.ts +36 -0
  58. package/es/components/UIShell/HeaderPanel.js +6 -6
  59. package/es/index.js +2 -1
  60. package/es/internal/useAnnouncer.js +2 -1
  61. package/es/internal/useNoInteractiveChildren.js +2 -6
  62. package/lib/components/Checkbox/Checkbox.d.ts +1 -1
  63. package/lib/components/Checkbox/Checkbox.js +1 -1
  64. package/lib/components/CheckboxGroup/CheckboxGroup.js +1 -1
  65. package/lib/components/ComboBox/ComboBox.d.ts +1 -1
  66. package/lib/components/ComboBox/ComboBox.js +1 -1
  67. package/lib/components/ComboButton/index.js +1 -1
  68. package/lib/components/ComposedModal/ModalFooter.d.ts +2 -1
  69. package/lib/components/DataTable/DataTable.d.ts +2 -0
  70. package/lib/components/DataTable/DataTable.js +3 -0
  71. package/lib/components/DataTable/TableExpandRow.js +20 -3
  72. package/lib/components/DataTable/TableHeader.d.ts +5 -0
  73. package/lib/components/DataTable/TableHeader.js +29 -5
  74. package/lib/components/DataTable/TableSlugRow.d.ts +31 -0
  75. package/lib/components/DataTable/TableSlugRow.js +59 -0
  76. package/lib/components/DataTable/index.d.ts +2 -1
  77. package/lib/components/DataTable/index.js +3 -0
  78. package/lib/components/DatePickerInput/DatePickerInput.d.ts +1 -1
  79. package/lib/components/DatePickerInput/DatePickerInput.js +1 -1
  80. package/lib/components/Dropdown/Dropdown.d.ts +1 -1
  81. package/lib/components/Dropdown/Dropdown.js +1 -1
  82. package/lib/components/InlineLoading/InlineLoading.d.ts +68 -0
  83. package/lib/components/InlineLoading/InlineLoading.js +4 -4
  84. package/lib/components/InlineLoading/index.d.ts +9 -0
  85. package/lib/components/Layer/LayerContext.d.ts +8 -0
  86. package/lib/components/Layer/LayerLevel.d.ts +5 -0
  87. package/lib/components/Layer/LayerLevel.js +18 -0
  88. package/lib/components/Layer/index.d.ts +38 -0
  89. package/lib/components/Layer/index.js +10 -9
  90. package/lib/components/Menu/MenuItem.js +2 -1
  91. package/lib/components/MenuButton/index.js +1 -1
  92. package/lib/components/Modal/Modal.d.ts +3 -2
  93. package/lib/components/MultiSelect/FilterableMultiSelect.js +1 -1
  94. package/lib/components/MultiSelect/MultiSelect.d.ts +1 -1
  95. package/lib/components/MultiSelect/MultiSelect.js +1 -1
  96. package/lib/components/Notification/Notification.js +1 -0
  97. package/lib/components/NumberInput/NumberInput.d.ts +1 -1
  98. package/lib/components/NumberInput/NumberInput.js +1 -1
  99. package/lib/components/RadioButton/RadioButton.d.ts +1 -1
  100. package/lib/components/RadioButton/RadioButton.js +1 -1
  101. package/lib/components/RadioButtonGroup/RadioButtonGroup.d.ts +1 -1
  102. package/lib/components/RadioButtonGroup/RadioButtonGroup.js +1 -1
  103. package/lib/components/Select/Select.d.ts +1 -1
  104. package/lib/components/Select/Select.js +1 -1
  105. package/lib/components/Slider/Slider.Skeleton.js +17 -3
  106. package/lib/components/Slider/Slider.js +132 -93
  107. package/lib/components/Slider/SliderHandles.d.ts +4 -0
  108. package/lib/components/Slider/SliderHandles.js +76 -0
  109. package/lib/components/Tabs/Tabs.js +1 -1
  110. package/lib/components/TextArea/TextArea.d.ts +7 -3
  111. package/lib/components/TextArea/TextArea.js +83 -16
  112. package/lib/components/TextInput/TextInput.d.ts +1 -1
  113. package/lib/components/TextInput/TextInput.js +1 -1
  114. package/lib/components/Tile/Tile.d.ts +8 -8
  115. package/lib/components/Tile/Tile.js +9 -5
  116. package/lib/components/Tooltip/Tooltip.js +47 -1
  117. package/lib/components/UIShell/HeaderPanel.d.ts +36 -0
  118. package/lib/components/UIShell/HeaderPanel.js +7 -7
  119. package/lib/index.js +4 -2
  120. package/lib/internal/useAnnouncer.js +2 -1
  121. package/lib/internal/useNoInteractiveChildren.js +2 -6
  122. package/package.json +4 -7
@@ -0,0 +1,65 @@
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 { PrefixContext } from '../../internal/usePrefix.js';
9
+ import React__default from 'react';
10
+
11
+ var _path, _path2, _path3, _path4, _path5, _path6, _path7, _path8, _path9, _path10, _path11, _path12, _path13, _path14;
12
+ const LowerHandle = () => /*#__PURE__*/React__default.createElement(PrefixContext.Consumer, null, prefix => /*#__PURE__*/React__default.createElement("svg", {
13
+ xmlns: "http://www.w3.org/2000/svg",
14
+ viewBox: "0 0 16 24",
15
+ className: `${prefix}--slider__thumb-icon ${prefix}--slider__thumb-icon--lower`
16
+ }, _path || (_path = /*#__PURE__*/React__default.createElement("path", {
17
+ d: "M15.08 6.46H16v11.08h-.92zM4.46 17.54c-.25 0-.46-.21-.46-.46V6.92a.465.465 0 0 1 .69-.4l8.77 5.08a.46.46 0 0 1 0 .8l-8.77 5.08c-.07.04-.15.06-.23.06Z"
18
+ })), _path2 || (_path2 = /*#__PURE__*/React__default.createElement("path", {
19
+ fill: "none",
20
+ d: "M-4 0h24v24H-4z"
21
+ }))));
22
+ const LowerHandleFocus = () => /*#__PURE__*/React__default.createElement(PrefixContext.Consumer, null, prefix => /*#__PURE__*/React__default.createElement("svg", {
23
+ xmlns: "http://www.w3.org/2000/svg",
24
+ viewBox: "0 0 16 24",
25
+ className: `${prefix}--slider__thumb-icon ${prefix}--slider__thumb-icon--lower ${prefix}--slider__thumb-icon--focus`
26
+ }, _path3 || (_path3 = /*#__PURE__*/React__default.createElement("path", {
27
+ d: "M15.08 6.46H16v11.08h-.92zM4.46 17.54c-.25 0-.46-.21-.46-.46V6.92a.465.465 0 0 1 .69-.4l8.77 5.08a.46.46 0 0 1 0 .8l-8.77 5.08c-.07.04-.15.06-.23.06Z"
28
+ })), _path4 || (_path4 = /*#__PURE__*/React__default.createElement("path", {
29
+ fill: "none",
30
+ d: "M-4 0h24v24H-4z"
31
+ })), _path5 || (_path5 = /*#__PURE__*/React__default.createElement("path", {
32
+ d: "M15.08 0H16v6.46h-.92z"
33
+ })), _path6 || (_path6 = /*#__PURE__*/React__default.createElement("path", {
34
+ d: "M0 0h.92v24H0zM15.08 0H16v24h-.92z"
35
+ })), _path7 || (_path7 = /*#__PURE__*/React__default.createElement("path", {
36
+ d: "M0 .92V0h16v.92zM0 24v-.92h16V24z"
37
+ }))));
38
+ const UpperHandle = () => /*#__PURE__*/React__default.createElement(PrefixContext.Consumer, null, prefix => /*#__PURE__*/React__default.createElement("svg", {
39
+ xmlns: "http://www.w3.org/2000/svg",
40
+ viewBox: "0 0 16 24",
41
+ className: `${prefix}--slider__thumb-icon ${prefix}--slider__thumb-icon--upper`
42
+ }, _path8 || (_path8 = /*#__PURE__*/React__default.createElement("path", {
43
+ d: "M0 6.46h.92v11.08H0zM11.54 6.46c.25 0 .46.21.46.46v10.15a.465.465 0 0 1-.69.4L2.54 12.4a.46.46 0 0 1 0-.8l8.77-5.08c.07-.04.15-.06.23-.06Z"
44
+ })), _path9 || (_path9 = /*#__PURE__*/React__default.createElement("path", {
45
+ fill: "none",
46
+ d: "M-4 0h24v24H-4z"
47
+ }))));
48
+ const UpperHandleFocus = () => /*#__PURE__*/React__default.createElement(PrefixContext.Consumer, null, prefix => /*#__PURE__*/React__default.createElement("svg", {
49
+ xmlns: "http://www.w3.org/2000/svg",
50
+ viewBox: "0 0 16 24",
51
+ className: `${prefix}--slider__thumb-icon ${prefix}--slider__thumb-icon--upper ${prefix}--slider__thumb-icon--focus`
52
+ }, _path10 || (_path10 = /*#__PURE__*/React__default.createElement("path", {
53
+ d: "M0 6.46h.92v11.08H0zM11.54 6.46c.25 0 .46.21.46.46v10.15a.465.465 0 0 1-.69.4L2.54 12.4a.46.46 0 0 1 0-.8l8.77-5.08c.07-.04.15-.06.23-.06Z"
54
+ })), _path11 || (_path11 = /*#__PURE__*/React__default.createElement("path", {
55
+ fill: "none",
56
+ d: "M-4 0h24v24H-4z"
57
+ })), _path12 || (_path12 = /*#__PURE__*/React__default.createElement("path", {
58
+ d: "M.92 24H0v-6.46h.92z"
59
+ })), _path13 || (_path13 = /*#__PURE__*/React__default.createElement("path", {
60
+ d: "M16 24h-.92V0H16zM.92 24H0V0h.92z"
61
+ })), _path14 || (_path14 = /*#__PURE__*/React__default.createElement("path", {
62
+ d: "M16 23.08V24H0v-.92zM16 0v.92H0V0z"
63
+ }))));
64
+
65
+ export { LowerHandle, LowerHandleFocus, UpperHandle, UpperHandleFocus };
@@ -257,7 +257,7 @@ function TabList(_ref2) {
257
257
  }
258
258
  }, [scrollLeft, children, dismissable]);
259
259
  useEffectOnce(() => {
260
- if (tabs.current[selectedIndex].disabled) {
260
+ if (tabs.current[selectedIndex]?.disabled) {
261
261
  const activeTabs = tabs.current.filter(tab => {
262
262
  return !tab.disabled;
263
263
  });
@@ -25,7 +25,7 @@ export interface TextAreaProps extends React.InputHTMLAttributes<HTMLTextAreaEle
25
25
  */
26
26
  disabled?: boolean;
27
27
  /**
28
- * Specify whether to display the character counter
28
+ * Specify whether to display the counter
29
29
  */
30
30
  enableCounter?: boolean;
31
31
  /**
@@ -60,7 +60,7 @@ export interface TextAreaProps extends React.InputHTMLAttributes<HTMLTextAreaEle
60
60
  */
61
61
  light?: boolean;
62
62
  /**
63
- * Max character count allowed for the textarea. This is needed in order for enableCounter to display
63
+ * Max entity count allowed for the textarea. This is needed in order for enableCounter to display
64
64
  */
65
65
  maxCount?: number;
66
66
  /**
@@ -86,7 +86,7 @@ export interface TextAreaProps extends React.InputHTMLAttributes<HTMLTextAreaEle
86
86
  */
87
87
  rows?: number;
88
88
  /**
89
- * Provide a `Slug` component to be rendered inside the `TextArea` component
89
+ * **Experimental**: Provide a `Slug` component to be rendered inside the `TextArea` component
90
90
  */
91
91
  slug?: ReactNodeLike;
92
92
  /**
@@ -101,6 +101,10 @@ export interface TextAreaProps extends React.InputHTMLAttributes<HTMLTextAreaEle
101
101
  * Provide the text that is displayed when the control is in warning state
102
102
  */
103
103
  warnText?: ReactNodeLike;
104
+ /**
105
+ * Specify the method used for calculating the counter number
106
+ */
107
+ counterMode?: 'character' | 'word';
104
108
  }
105
109
  declare const TextArea: React.ForwardRefExoticComponent<TextAreaProps & React.RefAttributes<unknown>>;
106
110
  export default TextArea;
@@ -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
  /**
@@ -6,12 +6,12 @@ export interface TileProps extends HTMLAttributes<HTMLDivElement> {
6
6
  /** @deprecated */
7
7
  light?: boolean;
8
8
  /**
9
- * Specify if the `Tile` component should be rendered with rounded corners. Only valid
9
+ * **Experimental**: Specify if the `Tile` component should be rendered with rounded corners. Only valid
10
10
  * when `slug` prop is present
11
11
  */
12
12
  hasRoundedCorners?: boolean;
13
13
  /**
14
- * Provide a `Slug` component to be rendered inside the `SelectableTile` component
14
+ * **Experimental**: Provide a `Slug` component to be rendered inside the `SelectableTile` component
15
15
  */
16
16
  slug?: ReactNodeLike;
17
17
  }
@@ -30,7 +30,7 @@ export interface ClickableTileProps extends HTMLAttributes<HTMLAnchorElement> {
30
30
  */
31
31
  disabled?: boolean;
32
32
  /**
33
- * Specify if the `ClickableTile` component should be rendered with rounded corners.
33
+ * **Experimental**: Specify if the `ClickableTile` component should be rendered with rounded corners.
34
34
  * Only valid when `slug` prop is present
35
35
  */
36
36
  hasRoundedCorners?: boolean;
@@ -57,7 +57,7 @@ export interface ClickableTileProps extends HTMLAttributes<HTMLAnchorElement> {
57
57
  */
58
58
  rel?: string;
59
59
  /**
60
- * Specify if a `Slug` icon should be rendered inside the `ClickableTile`
60
+ * **Experimental**: Specify if a `Slug` icon should be rendered inside the `ClickableTile`
61
61
  */
62
62
  slug?: boolean;
63
63
  }
@@ -72,7 +72,7 @@ export interface SelectableTileProps extends HTMLAttributes<HTMLDivElement> {
72
72
  */
73
73
  disabled?: boolean;
74
74
  /**
75
- * Specify if the `SelectableTile` component should be rendered with rounded corners.
75
+ * **Experimental**: Specify if the `SelectableTile` component should be rendered with rounded corners.
76
76
  * Only valid when `slug` prop is present
77
77
  */
78
78
  hasRoundedCorners?: boolean;
@@ -102,7 +102,7 @@ export interface SelectableTileProps extends HTMLAttributes<HTMLDivElement> {
102
102
  */
103
103
  selected?: boolean;
104
104
  /**
105
- * Provide a `Slug` component to be rendered inside the `SelectableTile` component
105
+ * **Experimental**: Provide a `Slug` component to be rendered inside the `SelectableTile` component
106
106
  */
107
107
  slug?: ReactNodeLike;
108
108
  /**
@@ -130,7 +130,7 @@ export interface ExpandableTileProps extends HTMLAttributes<HTMLDivElement> {
130
130
  */
131
131
  expanded?: boolean;
132
132
  /**
133
- * Specify if the `ExpandableTile` component should be rendered with rounded corners.
133
+ * **Experimental**: Specify if the `ExpandableTile` component should be rendered with rounded corners.
134
134
  * Only valid when `slug` prop is present
135
135
  */
136
136
  hasRoundedCorners?: boolean;
@@ -147,7 +147,7 @@ export interface ExpandableTileProps extends HTMLAttributes<HTMLDivElement> {
147
147
  */
148
148
  onKeyUp?(event: KeyboardEvent): void;
149
149
  /**
150
- * Provide a `Slug` component to be rendered inside the `ExpandableTile` component
150
+ * **Experimental**: Provide a `Slug` component to be rendered inside the `ExpandableTile` component
151
151
  */
152
152
  slug?: ReactNodeLike;
153
153
  /**
@@ -56,7 +56,7 @@ Tile.propTypes = {
56
56
  */
57
57
  className: PropTypes.string,
58
58
  /**
59
- * Specify if the `Tile` component should be rendered with rounded corners. Only valid
59
+ * **Experimental**: Specify if the `Tile` component should be rendered with rounded corners. Only valid
60
60
  * when `slug` prop is present
61
61
  */
62
62
  hasRoundedCorners: PropTypes.bool,
@@ -68,7 +68,7 @@ Tile.propTypes = {
68
68
  */
69
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
70
  /**
71
- * Provide a `Slug` component to be rendered inside the `Tile` component
71
+ * **Experimental**: Provide a `Slug` component to be rendered inside the `Tile` component
72
72
  */
73
73
  slug: PropTypes.node
74
74
  };
@@ -173,7 +173,7 @@ ClickableTile.propTypes = {
173
173
  */
174
174
  disabled: PropTypes.bool,
175
175
  /**
176
- * Specify if the `ClickableTile` component should be rendered with rounded corners.
176
+ * **Experimental**: Specify if the `ClickableTile` component should be rendered with rounded corners.
177
177
  * Only valid when `slug` prop is present
178
178
  */
179
179
  hasRoundedCorners: PropTypes.bool,
@@ -308,7 +308,7 @@ SelectableTile.propTypes = {
308
308
  */
309
309
  disabled: PropTypes.bool,
310
310
  /**
311
- * Specify if the `SelectableTile` component should be rendered with rounded corners.
311
+ * **Experimental**: Specify if the `SelectableTile` component should be rendered with rounded corners.
312
312
  * Only valid when `slug` prop is present
313
313
  */
314
314
  hasRoundedCorners: PropTypes.bool,
@@ -343,7 +343,7 @@ SelectableTile.propTypes = {
343
343
  */
344
344
  selected: PropTypes.bool,
345
345
  /**
346
- * Provide a `Slug` component to be rendered inside the `SelectableTile` component
346
+ * **Experimental**: Provide a `Slug` component to be rendered inside the `SelectableTile` component
347
347
  */
348
348
  slug: PropTypes.node,
349
349
  /**
@@ -573,6 +573,10 @@ ExpandableTile.propTypes = {
573
573
  * optional handler to trigger a function when a key is pressed
574
574
  */
575
575
  onKeyUp: PropTypes.func,
576
+ /**
577
+ * **Experimental**: Provide a `Slug` component to be rendered inside the `ExpandableTile` component
578
+ */
579
+ slug: PropTypes.node,
576
580
  /**
577
581
  * The `tabindex` attribute.
578
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),
@@ -0,0 +1,36 @@
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
+ import React, { ReactNode } from 'react';
8
+ interface HeaderPanelProps {
9
+ /**
10
+ * Specify whether focus and blur listeners are added. They are by default.
11
+ */
12
+ addFocusListeners?: boolean;
13
+ /**
14
+ * The content that will render inside of the `HeaderPanel`
15
+ */
16
+ children?: ReactNode;
17
+ /**
18
+ * Optionally provide a custom class to apply to the underlying `<li>` node
19
+ */
20
+ className?: string;
21
+ /**
22
+ * Specify whether the panel is expanded
23
+ */
24
+ expanded?: boolean;
25
+ /**
26
+ * Provide the `href` to the id of the element on your package that could
27
+ * be target.
28
+ */
29
+ href?: string;
30
+ /**
31
+ * An optional listener that is called a callback to collapse the HeaderPanel
32
+ */
33
+ onHeaderPanelFocus?: () => void;
34
+ }
35
+ declare const HeaderPanel: React.FC<HeaderPanelProps>;
36
+ export default HeaderPanel;
@@ -6,9 +6,9 @@
6
6
  */
7
7
 
8
8
  import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
9
- import React__default, { useRef, useState } from 'react';
10
9
  import cx from 'classnames';
11
10
  import PropTypes from 'prop-types';
11
+ import React__default, { useRef, useState } from 'react';
12
12
  import { usePrefix } from '../../internal/usePrefix.js';
13
13
  import { useWindowEvent } from '../../internal/useEvent.js';
14
14
  import { useMergedRefs } from '../../internal/useMergedRefs.js';
@@ -24,7 +24,7 @@ const HeaderPanel = /*#__PURE__*/React__default.forwardRef(function HeaderPanel(
24
24
  addFocusListeners = true,
25
25
  onHeaderPanelFocus = noopFn,
26
26
  href,
27
- ...other
27
+ ...rest
28
28
  } = _ref;
29
29
  const prefix = usePrefix();
30
30
  const headerPanelReference = useRef(null);
@@ -61,12 +61,13 @@ const HeaderPanel = /*#__PURE__*/React__default.forwardRef(function HeaderPanel(
61
61
  useWindowEvent('click', () => {
62
62
  const focusedElement = document.activeElement;
63
63
  setLastClickedElement(focusedElement);
64
- if (children.type?.displayName === 'Switcher' && !focusedElement?.closest(`.${prefix}--header-panel--expanded`) && !focusedElement?.closest(`.${prefix}--header__action`) && !headerPanelRef?.current?.classList.contains(`${prefix}--switcher`) && expanded) {
64
+ const childJsxElement = children;
65
+ if (childJsxElement.type?.displayName === 'Switcher' && !focusedElement?.closest(`.${prefix}--header-panel--expanded`) && !focusedElement?.closest(`.${prefix}--header__action`) && !headerPanelReference?.current?.classList.contains(`${prefix}--switcher`) && expanded) {
65
66
  setExpandedState(false);
66
67
  onHeaderPanelFocus();
67
68
  }
68
69
  });
69
- return /*#__PURE__*/React__default.createElement("div", _extends({}, other, {
70
+ return /*#__PURE__*/React__default.createElement("div", _extends({}, rest, {
70
71
  className: className,
71
72
  ref: headerPanelRef
72
73
  }, eventHandlers), children);
@@ -99,6 +100,5 @@ HeaderPanel.propTypes = {
99
100
  onHeaderPanelFocus: PropTypes.func
100
101
  };
101
102
  HeaderPanel.displayName = 'HeaderPanel';
102
- var HeaderPanel$1 = HeaderPanel;
103
103
 
104
- export { HeaderPanel$1 as default };
104
+ export { HeaderPanel as default };
package/es/index.js CHANGED
@@ -54,6 +54,7 @@ export { ColumnHang } from './components/Grid/ColumnHang.js';
54
54
  export { GridSettings } from './components/Grid/GridContext.js';
55
55
  export { default as IconSkeleton } from './components/Icon/Icon.Skeleton.js';
56
56
  export { IdPrefix } from './components/IdPrefix/index.js';
57
+ export { default as InlineLoading } from './components/InlineLoading/InlineLoading.js';
57
58
  export { default as Link } from './components/Link/Link.js';
58
59
  export { default as ListItem } from './components/ListItem/ListItem.js';
59
60
  export { default as Loading } from './components/Loading/Loading.js';
@@ -157,7 +158,6 @@ export { default as useContextMenu } from './components/ContextMenu/useContextMe
157
158
  export { default as Copy } from './components/Copy/Copy.js';
158
159
  export { default as CopyButton } from './components/CopyButton/CopyButton.js';
159
160
  export { default as ErrorBoundary } from './components/ErrorBoundary/ErrorBoundary.js';
160
- export { default as InlineLoading } from './components/InlineLoading/InlineLoading.js';
161
161
  export { default as ModalWrapper } from './components/ModalWrapper/ModalWrapper.js';
162
162
  export { default as ProgressIndicatorSkeleton } from './components/ProgressIndicator/ProgressIndicator.Skeleton.js';
163
163
  export { default as TextInputSkeleton } from './components/TextInput/TextInput.Skeleton.js';
@@ -197,6 +197,7 @@ export { default as TableHeader } from './components/DataTable/TableHeader.js';
197
197
  export { default as TableRow } from './components/DataTable/TableRow.js';
198
198
  export { default as TableSelectAll } from './components/DataTable/TableSelectAll.js';
199
199
  export { default as TableSelectRow } from './components/DataTable/TableSelectRow.js';
200
+ export { default as TableSlugRow } from './components/DataTable/TableSlugRow.js';
200
201
  export { default as TableToolbar } from './components/DataTable/TableToolbar.js';
201
202
  export { default as TableToolbarAction } from './components/DataTable/TableToolbarAction.js';
202
203
  export { default as TableToolbarContent } from './components/DataTable/TableToolbarContent.js';
@@ -6,9 +6,10 @@
6
6
  */
7
7
 
8
8
  function useAnnouncer(textCount, maxCount) {
9
+ let entityName = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'characters';
9
10
  const lastTen = maxCount - 10;
10
11
  if (textCount >= lastTen) {
11
- return `${maxCount - textCount} characters left.`;
12
+ return `${maxCount - textCount} ${entityName} left.`;
12
13
  }
13
14
  }
14
15
 
@@ -74,7 +74,7 @@ function getRoleContent(node) {
74
74
  * @see https://github.com/w3c/aria-practices/blob/0553bb51588ffa517506e2a1b2ca1422ed438c5f/examples/js/utils.js#L68
75
75
  */
76
76
  function isFocusable(element) {
77
- if (element.tabIndex < 0) {
77
+ if (element.tabIndex === undefined || element.tabIndex < 0) {
78
78
  return false;
79
79
  }
80
80
  if (element.disabled) {
@@ -85,12 +85,8 @@ function isFocusable(element) {
85
85
  return !!element.href && element.rel !== 'ignore';
86
86
  case 'INPUT':
87
87
  return element.type !== 'hidden';
88
- case 'BUTTON':
89
- case 'SELECT':
90
- case 'TEXTAREA':
91
- return true;
92
88
  default:
93
- return false;
89
+ return true;
94
90
  }
95
91
  }
96
92