@carbon/react 1.97.0 → 1.99.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 (83) hide show
  1. package/.playwright/INTERNAL_AVT_REPORT_DO_NOT_USE.json +1002 -967
  2. package/es/components/ButtonSet/ButtonSet.d.ts +5 -0
  3. package/es/components/ButtonSet/ButtonSet.js +68 -4
  4. package/es/components/CodeSnippet/CodeSnippet.d.ts +1 -1
  5. package/es/components/Copy/Copy.d.ts +1 -1
  6. package/es/components/CopyButton/CopyButton.d.ts +1 -1
  7. package/es/components/DataTable/DataTable.d.ts +2 -1
  8. package/es/components/DataTable/TableContainer.d.ts +10 -2
  9. package/es/components/DataTable/TableContainer.js +15 -3
  10. package/es/components/DataTable/state/sorting.d.ts +2 -4
  11. package/es/components/DatePicker/DatePicker.d.ts +3 -2
  12. package/es/components/DatePicker/DatePicker.js +18 -135
  13. package/es/components/DatePicker/DatePickerLocales.d.ts +12 -0
  14. package/es/components/DatePicker/DatePickerLocales.js +135 -0
  15. package/es/components/DatePickerInput/DatePickerInput.js +50 -28
  16. package/es/components/Dropdown/Dropdown.js +13 -1
  17. package/es/components/FileUploader/FileUploader.d.ts +23 -8
  18. package/es/components/FileUploader/FileUploader.js +53 -33
  19. package/es/components/FileUploader/FileUploaderButton.js +2 -2
  20. package/es/components/FileUploader/FileUploaderDropContainer.d.ts +13 -2
  21. package/es/components/FileUploader/FileUploaderDropContainer.js +15 -6
  22. package/es/components/FileUploader/FileUploaderItem.js +9 -6
  23. package/es/components/Link/Link.js +1 -1
  24. package/es/components/Menu/index.d.ts +4 -3
  25. package/es/components/MultiSelect/FilterableMultiSelect.js +1 -0
  26. package/es/components/MultiSelect/MultiSelect.js +1 -0
  27. package/es/components/NumberInput/NumberInput.d.ts +6 -2
  28. package/es/components/NumberInput/NumberInput.js +17 -5
  29. package/es/components/Pagination/Pagination.js +5 -5
  30. package/es/components/Popover/index.d.ts +1 -1
  31. package/es/components/Popover/index.js +27 -13
  32. package/es/components/Select/Select.js +27 -33
  33. package/es/components/Tabs/Tabs.js +1 -1
  34. package/es/components/TextArea/TextArea.js +14 -4
  35. package/es/components/TextInput/PasswordInput.js +3 -2
  36. package/es/components/Toggletip/index.d.ts +1 -0
  37. package/es/components/Toggletip/index.js +1 -1
  38. package/es/components/Tooltip/index.d.ts +3 -2
  39. package/es/internal/FloatingMenu.js +6 -5
  40. package/es/internal/OptimizedResize.js +4 -5
  41. package/es/tools/events.d.ts +1 -1
  42. package/lib/components/ButtonSet/ButtonSet.d.ts +5 -0
  43. package/lib/components/ButtonSet/ButtonSet.js +67 -3
  44. package/lib/components/CodeSnippet/CodeSnippet.d.ts +1 -1
  45. package/lib/components/Copy/Copy.d.ts +1 -1
  46. package/lib/components/CopyButton/CopyButton.d.ts +1 -1
  47. package/lib/components/DataTable/DataTable.d.ts +2 -1
  48. package/lib/components/DataTable/TableContainer.d.ts +10 -2
  49. package/lib/components/DataTable/TableContainer.js +15 -3
  50. package/lib/components/DataTable/state/sorting.d.ts +2 -4
  51. package/lib/components/DatePicker/DatePicker.d.ts +3 -2
  52. package/lib/components/DatePicker/DatePicker.js +18 -135
  53. package/lib/components/DatePicker/DatePickerLocales.d.ts +12 -0
  54. package/lib/components/DatePicker/DatePickerLocales.js +137 -0
  55. package/lib/components/DatePickerInput/DatePickerInput.js +49 -27
  56. package/lib/components/Dropdown/Dropdown.js +13 -1
  57. package/lib/components/FileUploader/FileUploader.d.ts +23 -8
  58. package/lib/components/FileUploader/FileUploader.js +53 -33
  59. package/lib/components/FileUploader/FileUploaderButton.js +2 -2
  60. package/lib/components/FileUploader/FileUploaderDropContainer.d.ts +13 -2
  61. package/lib/components/FileUploader/FileUploaderDropContainer.js +15 -6
  62. package/lib/components/FileUploader/FileUploaderItem.js +9 -6
  63. package/lib/components/Link/Link.js +1 -1
  64. package/lib/components/Menu/index.d.ts +4 -3
  65. package/lib/components/MultiSelect/FilterableMultiSelect.js +1 -0
  66. package/lib/components/MultiSelect/MultiSelect.js +1 -0
  67. package/lib/components/NumberInput/NumberInput.d.ts +6 -2
  68. package/lib/components/NumberInput/NumberInput.js +17 -5
  69. package/lib/components/Pagination/Pagination.js +5 -5
  70. package/lib/components/Popover/index.d.ts +1 -1
  71. package/lib/components/Popover/index.js +27 -13
  72. package/lib/components/Select/Select.js +27 -33
  73. package/lib/components/Tabs/Tabs.js +1 -1
  74. package/lib/components/TextArea/TextArea.js +14 -4
  75. package/lib/components/TextInput/PasswordInput.js +3 -2
  76. package/lib/components/Toggletip/index.d.ts +1 -0
  77. package/lib/components/Toggletip/index.js +3 -0
  78. package/lib/components/Tooltip/index.d.ts +3 -2
  79. package/lib/internal/FloatingMenu.js +6 -5
  80. package/lib/internal/OptimizedResize.js +4 -5
  81. package/lib/tools/events.d.ts +1 -1
  82. package/package.json +21 -29
  83. package/telemetry.yml +3 -0
@@ -126,6 +126,7 @@ const NumberInput = /*#__PURE__*/React.forwardRef((props, forwardRef) => {
126
126
  max,
127
127
  min,
128
128
  onBlur,
129
+ onStepperBlur,
129
130
  onChange,
130
131
  onClick,
131
132
  onKeyUp,
@@ -426,6 +427,7 @@ const NumberInput = /*#__PURE__*/React.forwardRef((props, forwardRef) => {
426
427
  if (disableWheelProp) {
427
428
  e.target.removeEventListener('wheel', disableWheel);
428
429
  }
430
+ let parsedValueForBlur;
429
431
  if (type === 'text') {
430
432
  // When isControlled, the current inputValue needs re-parsed
431
433
  // because the consumer's onChange hasn't been called yet and
@@ -441,6 +443,7 @@ const NumberInput = /*#__PURE__*/React.forwardRef((props, forwardRef) => {
441
443
  // causing the _numberValue to mismatch the formatted value in
442
444
  // the input. To avoid this, formattedValue is re-parsed.
443
445
  const parsedFormattedNewValue = numberParser.parse(formattedValue);
446
+ parsedValueForBlur = parsedFormattedNewValue;
444
447
  if (onChange && isValid) {
445
448
  const state = {
446
449
  value: parsedFormattedNewValue,
@@ -466,7 +469,12 @@ const NumberInput = /*#__PURE__*/React.forwardRef((props, forwardRef) => {
466
469
  }
467
470
  }
468
471
  if (onBlur) {
469
- onBlur(e);
472
+ if (type === 'number') {
473
+ onBlur(e, value);
474
+ return;
475
+ }
476
+ const parsedTextValue = parsedValueForBlur ?? (isControlled ? numberParser.parse(inputValue) : numberValue);
477
+ onBlur(e, parsedTextValue);
470
478
  }
471
479
  },
472
480
  pattern: pattern,
@@ -486,7 +494,7 @@ const NumberInput = /*#__PURE__*/React.forwardRef((props, forwardRef) => {
486
494
  className: `${prefix}--number__control-btn down-icon`,
487
495
  disabled: disabled || readOnly,
488
496
  onClick: event => handleStepperClick(event, 'down'),
489
- onBlur: onBlur,
497
+ onBlur: onStepperBlur,
490
498
  tabIndex: -1,
491
499
  title: decrementNumLabel || iconDescription,
492
500
  type: "button"
@@ -499,7 +507,7 @@ const NumberInput = /*#__PURE__*/React.forwardRef((props, forwardRef) => {
499
507
  className: `${prefix}--number__control-btn up-icon`,
500
508
  disabled: disabled || readOnly,
501
509
  onClick: event => handleStepperClick(event, 'up'),
502
- onBlur: onBlur,
510
+ onBlur: onStepperBlur,
503
511
  tabIndex: -1,
504
512
  title: incrementNumLabel || iconDescription,
505
513
  type: "button"
@@ -610,10 +618,14 @@ NumberInput.propTypes = {
610
618
  */
611
619
  stepStartValue: PropTypes.number,
612
620
  /**
613
- * Provide an optional handler that is called when the input or stepper
614
- * buttons are blurred.
621
+ * Provide an optional handler that is called when the input is blurred.
615
622
  */
616
623
  onBlur: PropTypes.func,
624
+ /**
625
+ * Provide an optional handler that is called when the stepper
626
+ * buttons are blurred.
627
+ */
628
+ onStepperBlur: PropTypes.func,
617
629
  /**
618
630
  * Provide an optional handler that is called when the internal state of
619
631
  * NumberInput changes. This handler is called with event and state info.
@@ -7,16 +7,16 @@
7
7
 
8
8
  import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
9
9
  import { CaretLeft, CaretRight } from '@carbon/icons-react';
10
- import cx from 'classnames';
11
- import PropTypes from 'prop-types';
12
10
  import React, { useRef, useState, useEffect } from 'react';
11
+ import { IconButton } from '../IconButton/index.js';
12
+ import PropTypes from 'prop-types';
13
13
  import Select from '../Select/Select.js';
14
14
  import '../Select/Select.Skeleton.js';
15
15
  import SelectItem from '../SelectItem/SelectItem.js';
16
+ import cx from 'classnames';
17
+ import isEqual from 'react-fast-compare';
16
18
  import { useFallbackId } from '../../internal/useId.js';
17
19
  import { usePrefix } from '../../internal/usePrefix.js';
18
- import { IconButton } from '../IconButton/index.js';
19
- import isEqual from 'react-fast-compare';
20
20
 
21
21
  var _CaretLeft, _CaretRight;
22
22
  function mapPageSizesToObject(sizes) {
@@ -266,7 +266,7 @@ const Pagination = /*#__PURE__*/React.forwardRef(({
266
266
  onClick: decrementPage,
267
267
  ref: backBtnRef
268
268
  }, _CaretLeft || (_CaretLeft = /*#__PURE__*/React.createElement(CaretLeft, null))), /*#__PURE__*/React.createElement(IconButton, {
269
- align: "top-end",
269
+ align: "top",
270
270
  disabled: forwardButtonDisabled || isLastPage,
271
271
  kind: "ghost",
272
272
  className: forwardButtonClasses,
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright IBM Corp. 2016, 2025
2
+ * Copyright IBM Corp. 2016, 2026
3
3
  *
4
4
  * This source code is licensed under the Apache-2.0 license found in the
5
5
  * LICENSE file in the root directory of this source tree.
@@ -60,27 +60,41 @@ forwardRef) {
60
60
  const caretRef = useRef(null);
61
61
  const popover = useRef(null);
62
62
  const enableFloatingStyles = useFeatureFlag('enable-v12-dynamic-floating-styles') || autoAlign;
63
+ const lastClickWasInsidePopoverContent = useRef(false);
63
64
  let align = mapPopoverAlign(initialAlign);
64
65
 
66
+ // Tracks clicks inside PopoverContent to prevent it from closing when clicked, this handles an edge
67
+ // case where the popover will close when clicking non-focusable elements (e.g. text)
68
+ useEvent(popover, 'mousedown', event => {
69
+ const target = event.target;
70
+ lastClickWasInsidePopoverContent.current = refs.floating.current?.contains(target) || false;
71
+
72
+ // reset flag
73
+ if (lastClickWasInsidePopoverContent.current) {
74
+ setTimeout(() => {
75
+ lastClickWasInsidePopoverContent.current = false;
76
+ }, 0);
77
+ }
78
+ });
79
+
65
80
  // The `Popover` should close whenever it and its children loses focus
66
81
  useEvent(popover, 'focusout', event => {
67
82
  const relatedTarget = event.relatedTarget;
68
- if (isTabTip) {
69
- if (relatedTarget && !popover.current?.contains(relatedTarget)) {
70
- onRequestClose?.();
71
- }
72
- return;
73
- }
74
83
  if (!relatedTarget) {
84
+ // do not close if PopoverContent was clicked
85
+ if (lastClickWasInsidePopoverContent.current) {
86
+ lastClickWasInsidePopoverContent.current = false;
87
+ return;
88
+ }
75
89
  onRequestClose?.();
76
- return;
77
- }
78
- const isOutsideMainContainer = !popover.current?.contains(relatedTarget);
79
- const isOutsideFloating = enableFloatingStyles && refs.floating.current ? !refs.floating.current.contains(relatedTarget) : true;
90
+ } else if (relatedTarget && !popover.current?.contains(relatedTarget)) {
91
+ const isOutsideFloating = enableFloatingStyles && refs.floating.current ? !refs.floating.current.contains(relatedTarget) : true;
92
+ const isFocusableWrapper = relatedTarget && popover.current && relatedTarget.contains(popover.current);
80
93
 
81
- // Only close if focus moved outside both containers
82
- if (isOutsideMainContainer && isOutsideFloating) {
83
- onRequestClose?.();
94
+ // Only close if focus moved outside both containers and not to an interactive parent wrapper
95
+ if (isOutsideFloating && !isFocusableWrapper) {
96
+ onRequestClose?.();
97
+ }
84
98
  }
85
99
  });
86
100
  useWindowEvent('click', ({
@@ -14,12 +14,12 @@ import { deprecate } from '../../prop-types/deprecate.js';
14
14
  import { usePrefix } from '../../internal/usePrefix.js';
15
15
  import '../FluidForm/FluidForm.js';
16
16
  import { FormContext } from '../FluidForm/FormContext.js';
17
- import { useId } from '../../internal/useId.js';
18
17
  import { composeEventHandlers } from '../../tools/events.js';
19
18
  import { Text } from '../Text/Text.js';
20
19
  import '../Text/TextDirection.js';
21
20
  import { AILabel } from '../AILabel/index.js';
22
21
  import { isComponentElement } from '../../internal/utils.js';
22
+ import { useNormalizedInputProps } from '../../internal/useNormalizedInputProps.js';
23
23
 
24
24
  const Select = /*#__PURE__*/React.forwardRef(({
25
25
  className,
@@ -49,7 +49,6 @@ const Select = /*#__PURE__*/React.forwardRef(({
49
49
  isFluid
50
50
  } = useContext(FormContext);
51
51
  const [isFocused, setIsFocused] = useState(false);
52
- const selectInstanceId = useId();
53
52
  // Convert children to an array of valid elements once using type narrowing
54
53
  const validChildren = React.Children.toArray(children).filter(child => /*#__PURE__*/React.isValidElement(child));
55
54
 
@@ -61,55 +60,50 @@ const Select = /*#__PURE__*/React.forwardRef(({
61
60
  // otherwise, fallback to the first option's text
62
61
  const initialTitle = other?.title || selectedOption?.props?.text || validChildren[0]?.props?.text || '';
63
62
  const [title, setTitle] = useState(initialTitle);
63
+ const normalizedProps = useNormalizedInputProps({
64
+ id,
65
+ disabled,
66
+ readOnly,
67
+ invalid,
68
+ invalidText,
69
+ warn,
70
+ warnText
71
+ });
64
72
  const selectClasses = cx({
65
73
  [`${prefix}--select`]: true,
66
74
  [`${prefix}--select--inline`]: inline,
67
75
  [`${prefix}--select--light`]: light,
68
- [`${prefix}--select--invalid`]: invalid,
69
- [`${prefix}--select--disabled`]: disabled,
76
+ [`${prefix}--select--invalid`]: normalizedProps.invalid,
77
+ [`${prefix}--select--disabled`]: normalizedProps.disabled,
70
78
  [`${prefix}--select--readonly`]: readOnly,
71
- [`${prefix}--select--warning`]: warn,
72
- [`${prefix}--select--fluid--invalid`]: isFluid && invalid,
79
+ [`${prefix}--select--warning`]: normalizedProps.warn,
80
+ [`${prefix}--select--fluid--invalid`]: isFluid && normalizedProps.invalid,
73
81
  [`${prefix}--select--fluid--focus`]: isFluid && isFocused,
74
82
  [`${prefix}--select--slug`]: slug,
75
83
  [`${prefix}--select--decorator`]: decorator
76
84
  });
77
85
  const labelClasses = cx(`${prefix}--label`, {
78
86
  [`${prefix}--visually-hidden`]: hideLabel,
79
- [`${prefix}--label--disabled`]: disabled
87
+ [`${prefix}--label--disabled`]: normalizedProps.disabled
80
88
  });
81
89
  const inputClasses = cx({
82
90
  [`${prefix}--select-input`]: true,
83
91
  [`${prefix}--select-input--${size}`]: size
84
92
  });
85
- const errorId = `${id}-error-msg`;
86
- const errorText = (() => {
87
- if (invalid) {
88
- return invalidText;
89
- }
90
- if (warn) {
91
- return warnText;
92
- }
93
- })();
94
- const error = invalid || warn ? /*#__PURE__*/React.createElement(Text, {
95
- as: "div",
96
- className: `${prefix}--form-requirement`,
97
- id: errorId
98
- }, errorText) : null;
93
+ const error = normalizedProps.validation;
99
94
  const helperTextClasses = cx(`${prefix}--form__helper-text`, {
100
- [`${prefix}--form__helper-text--disabled`]: disabled
95
+ [`${prefix}--form__helper-text--disabled`]: normalizedProps.disabled
101
96
  });
102
- const helperId = !helperText ? undefined : `select-helper-text-${selectInstanceId}`;
103
97
  const helper = helperText ? /*#__PURE__*/React.createElement(Text, {
104
98
  as: "div",
105
- id: helperId,
99
+ id: normalizedProps.helperId,
106
100
  className: helperTextClasses
107
101
  }, helperText) : null;
108
102
  const ariaProps = {};
109
- if (invalid) {
110
- ariaProps['aria-describedby'] = errorId;
103
+ if (normalizedProps.invalid) {
104
+ ariaProps['aria-describedby'] = normalizedProps.invalidId;
111
105
  } else if (!inline && !isFluid) {
112
- ariaProps['aria-describedby'] = helper ? helperId : undefined;
106
+ ariaProps['aria-describedby'] = helper ? normalizedProps.helperId : undefined;
113
107
  }
114
108
  const handleFocus = evt => {
115
109
  setIsFocused(evt.type === 'focus' ? true : false);
@@ -146,8 +140,8 @@ const Select = /*#__PURE__*/React.forwardRef(({
146
140
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("select", _extends({}, other, ariaProps, {
147
141
  id: id,
148
142
  className: inputClasses,
149
- disabled: disabled || undefined,
150
- "aria-invalid": invalid || undefined,
143
+ disabled: normalizedProps.disabled || undefined,
144
+ "aria-invalid": normalizedProps.invalid || undefined,
151
145
  "aria-readonly": readOnly || undefined,
152
146
  title: title,
153
147
  onChange: composeEventHandlers([onChange, handleChange])
@@ -155,9 +149,9 @@ const Select = /*#__PURE__*/React.forwardRef(({
155
149
  ref: ref
156
150
  }), children), /*#__PURE__*/React.createElement(ChevronDown, {
157
151
  className: `${prefix}--select__arrow`
158
- }), invalid && /*#__PURE__*/React.createElement(WarningFilled, {
152
+ }), normalizedProps.invalid && /*#__PURE__*/React.createElement(WarningFilled, {
159
153
  className: `${prefix}--select__invalid-icon`
160
- }), !invalid && warn && /*#__PURE__*/React.createElement(WarningAltFilled, {
154
+ }), !normalizedProps.invalid && normalizedProps.warn && /*#__PURE__*/React.createElement(WarningAltFilled, {
161
155
  className: `${prefix}--select__invalid-icon ${prefix}--select__invalid-icon--warning`
162
156
  }));
163
157
  })();
@@ -173,10 +167,10 @@ const Select = /*#__PURE__*/React.forwardRef(({
173
167
  className: `${prefix}--select-input--inline__wrapper`
174
168
  }, /*#__PURE__*/React.createElement("div", {
175
169
  className: `${prefix}--select-input__wrapper`,
176
- "data-invalid": invalid || null
170
+ "data-invalid": normalizedProps.invalid || null
177
171
  }, input), error), !inline && /*#__PURE__*/React.createElement("div", {
178
172
  className: `${prefix}--select-input__wrapper`,
179
- "data-invalid": invalid || null,
173
+ "data-invalid": normalizedProps.invalid || null,
180
174
  onFocus: handleFocus,
181
175
  onBlur: handleFocus
182
176
  }, input, slug ? normalizedDecorator : decorator ? /*#__PURE__*/React.createElement("div", {
@@ -886,7 +886,7 @@ const Tab = /*#__PURE__*/forwardRef(({
886
886
  })
887
887
  }, /*#__PURE__*/React.createElement("button", {
888
888
  type: "button",
889
- tabIndex: selectedIndex === index && dismissable ? 0 : -1,
889
+ tabIndex: -1,
890
890
  "aria-disabled": disabled,
891
891
  "aria-hidden": selectedIndex === index && dismissable ? 'false' : 'true',
892
892
  disabled: disabled,
@@ -202,8 +202,10 @@ const TextArea = frFn((props, forwardRef) => {
202
202
  }, labelText) : null;
203
203
  const counter = enableCounter && maxCount && (counterMode === 'character' || counterMode === 'word') ? /*#__PURE__*/React.createElement(Text, {
204
204
  as: "div",
205
- className: counterClasses
205
+ className: counterClasses,
206
+ "aria-hidden": "true"
206
207
  }, `${textCount}/${maxCount}`) : null;
208
+ const counterDescriptionId = enableCounter && maxCount ? `${id}-counter-desc` : undefined;
207
209
  const helperId = !helperText ? undefined : `text-area-helper-text-${textAreaInstanceId}`;
208
210
  const helper = helperText ? /*#__PURE__*/React.createElement(Text, {
209
211
  as: "div",
@@ -234,8 +236,13 @@ const TextArea = frFn((props, forwardRef) => {
234
236
  let ariaDescribedBy;
235
237
  if (invalid) {
236
238
  ariaDescribedBy = errorId;
237
- } else if (!invalid && !warn && !isFluid && helperText) {
238
- ariaDescribedBy = helperId;
239
+ } else if (warn && !isFluid) {
240
+ ariaDescribedBy = warnId;
241
+ } else {
242
+ const ids = [];
243
+ if (!isFluid && helperText && helperId) ids.push(helperId);
244
+ if (counterDescriptionId) ids.push(counterDescriptionId);
245
+ ariaDescribedBy = ids.length > 0 ? ids.join(' ') : undefined;
239
246
  }
240
247
  if (enableCounter) {
241
248
  // handle different counter mode
@@ -292,7 +299,10 @@ const TextArea = frFn((props, forwardRef) => {
292
299
  className: formItemClasses
293
300
  }, /*#__PURE__*/React.createElement("div", {
294
301
  className: `${prefix}--text-area__label-wrapper`
295
- }, label, counter), /*#__PURE__*/React.createElement("div", {
302
+ }, label, counter), enableCounter && maxCount && /*#__PURE__*/React.createElement("span", {
303
+ id: counterDescriptionId,
304
+ className: `${prefix}--visually-hidden`
305
+ }, counterMode === 'word' ? `Word limit ${maxCount}` : `Character limit ${maxCount}`), /*#__PURE__*/React.createElement("div", {
296
306
  ref: wrapperRef,
297
307
  className: textAreaWrapperClasses,
298
308
  "data-invalid": invalid || null
@@ -135,6 +135,7 @@ const PasswordInput = /*#__PURE__*/React.forwardRef(({
135
135
  [`${prefix}--tooltip--${tooltipPosition}`]: tooltipPosition,
136
136
  [`${prefix}--tooltip--align-${tooltipAlignment}`]: tooltipAlignment
137
137
  });
138
+ const tooltipClasses = cx(`${prefix}--toggle-password-tooltip`, `${prefix}--icon-tooltip`);
138
139
  let align = undefined;
139
140
  if (tooltipPosition === 'top' || tooltipPosition === 'bottom') {
140
141
  if (tooltipAlignment === 'center') {
@@ -172,12 +173,12 @@ const PasswordInput = /*#__PURE__*/React.forwardRef(({
172
173
  className: `${prefix}--text-input__divider`
173
174
  }), /*#__PURE__*/React.createElement(Tooltip, {
174
175
  align: align,
175
- className: `${prefix}--toggle-password-tooltip`,
176
+ className: tooltipClasses,
176
177
  label: passwordIsVisible ? hidePasswordLabel : showPasswordLabel
177
178
  }, /*#__PURE__*/React.createElement("button", {
178
179
  type: "button",
179
180
  className: passwordVisibilityToggleClasses,
180
- disabled: disabled || readOnly,
181
+ disabled: disabled,
181
182
  onClick: handleTogglePasswordVisibility
182
183
  }, passwordVisibilityIcon)));
183
184
  useEffect(() => {
@@ -111,3 +111,4 @@ export declare namespace ToggletipActions {
111
111
  className: PropTypes.Requireable<string>;
112
112
  };
113
113
  }
114
+ export default Toggletip;
@@ -282,4 +282,4 @@ ToggletipActions.propTypes = {
282
282
  className: PropTypes.string
283
283
  };
284
284
 
285
- export { Toggletip, ToggletipActions, ToggletipButton, ToggletipContent, ToggletipLabel };
285
+ export { Toggletip, ToggletipActions, ToggletipButton, ToggletipContent, ToggletipLabel, Toggletip as default };
@@ -4,6 +4,7 @@
4
4
  * This source code is licensed under the Apache-2.0 license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
- import { DefinitionTooltip } from './DefinitionTooltip';
7
+ import { DefinitionTooltip, type DefinitionTooltipProps } from './DefinitionTooltip';
8
8
  import { Tooltip, type TooltipProps } from './Tooltip';
9
- export { DefinitionTooltip, Tooltip, type TooltipProps };
9
+ export { DefinitionTooltip, Tooltip, type DefinitionTooltipProps, type TooltipProps, };
10
+ export default Tooltip;
@@ -8,7 +8,6 @@
8
8
  import React, { useContext, useState, useRef, useCallback, useEffect, cloneElement } from 'react';
9
9
  import * as FeatureFlags from '@carbon/feature-flags';
10
10
  import ReactDOM from 'react-dom';
11
- import window from 'window-or-global';
12
11
  import { Tab } from './keyboard/keys.js';
13
12
  import { match } from './keyboard/match.js';
14
13
  import { selectorTabbable, selectorFocusable } from './keyboard/navigation.js';
@@ -109,14 +108,16 @@ const FloatingMenu = ({
109
108
  const menuSize = menuBody.getBoundingClientRect();
110
109
  const refPosition = triggerEl ? triggerEl.getBoundingClientRect() : undefined;
111
110
  const offsetValue = typeof menuOffset === 'function' ? menuOffset(menuBody, menuDirection, triggerEl, flipped) : menuOffset;
111
+ const scrollX = globalThis.scrollX ?? 0;
112
+ const scrollY = globalThis.scrollY ?? 0;
112
113
  if (updateOrientation) {
113
114
  updateOrientation({
114
115
  menuSize,
115
116
  refPosition,
116
117
  direction: menuDirection,
117
118
  offset: offsetValue,
118
- scrollX: window.pageXOffset,
119
- scrollY: window.pageYOffset,
119
+ scrollX,
120
+ scrollY,
120
121
  container: {
121
122
  rect: target().getBoundingClientRect(),
122
123
  position: getComputedStyle(target()).position
@@ -136,8 +137,8 @@ const FloatingMenu = ({
136
137
  },
137
138
  offset: offsetValue,
138
139
  direction: menuDirection,
139
- scrollX: window.pageXOffset,
140
- scrollY: window.pageYOffset,
140
+ scrollX,
141
+ scrollY,
141
142
  container: {
142
143
  rect: target().getBoundingClientRect(),
143
144
  position: getComputedStyle(target()).position
@@ -5,9 +5,8 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- import window from 'window-or-global';
9
-
10
- // mdn resize function
8
+ // Use `globalThis` for universal access to global object (browser, workers, Node).
9
+ const win = globalThis;
11
10
 
12
11
  /**
13
12
  * A callback function to be executed on `resize`.
@@ -25,7 +24,7 @@ const OptimizedResize = (() => {
25
24
  const handleResize = () => {
26
25
  if (!running) {
27
26
  running = true;
28
- window.requestAnimationFrame(runCallbacks);
27
+ win.requestAnimationFrame(runCallbacks);
29
28
  }
30
29
  };
31
30
  const addCallback = callback => {
@@ -38,7 +37,7 @@ const OptimizedResize = (() => {
38
37
  /** Adds a callback function to be executed on window `resize`. */
39
38
  add: callback => {
40
39
  if (!callbacks.length) {
41
- window.addEventListener('resize', handleResize);
40
+ win.addEventListener('resize', handleResize);
42
41
  }
43
42
  addCallback(callback);
44
43
  return {
@@ -14,4 +14,4 @@ import type { SyntheticEvent } from 'react';
14
14
  * @param handlers - An array of event handler functions.
15
15
  * @returns A composite event handler.
16
16
  */
17
- export declare const composeEventHandlers: <E extends SyntheticEvent = SyntheticEvent>(handlers: (((event: E, ...args: any[]) => void) | undefined)[]) => (event: E, ...args: any[]) => void;
17
+ export declare const composeEventHandlers: <E extends SyntheticEvent = SyntheticEvent<Element, Event>>(handlers: (((event: E, ...args: any[]) => void) | undefined)[]) => (event: E, ...args: any[]) => void;
@@ -6,6 +6,11 @@
6
6
  */
7
7
  import React from 'react';
8
8
  export interface ButtonSetProps extends React.HTMLAttributes<HTMLDivElement> {
9
+ /**
10
+ * fluid: button set resize to the size of the container up to a maximum dependant on the
11
+ * number of buttons. Overrides `stacked` property.
12
+ */
13
+ fluid?: boolean;
9
14
  /**
10
15
  * Specify the button arrangement of the set (vertically stacked or
11
16
  * horizontal)
@@ -14,22 +14,81 @@ var React = require('react');
14
14
  var PropTypes = require('prop-types');
15
15
  var cx = require('classnames');
16
16
  var usePrefix = require('../../internal/usePrefix.js');
17
+ var useIsomorphicEffect = require('../../internal/useIsomorphicEffect.js');
17
18
 
19
+ const buttonOrder = kind => ({
20
+ ghost: 1,
21
+ 'danger--ghost': 2,
22
+ tertiary: 3,
23
+ danger: 5,
24
+ primary: 6
25
+ })[kind] ?? 4;
26
+ const getButtonKind = element => {
27
+ if (/*#__PURE__*/React.isValidElement(element) && element.props && typeof element.props === 'object') {
28
+ const props = element.props;
29
+ return props.kind ?? 'primary';
30
+ }
31
+ return 'primary';
32
+ };
18
33
  const ButtonSet = /*#__PURE__*/React.forwardRef((props, ref) => {
19
34
  const {
20
35
  children,
21
36
  className,
37
+ fluid,
22
38
  stacked,
23
39
  ...rest
24
40
  } = props;
25
41
  const prefix = usePrefix.usePrefix();
42
+ const fluidInnerRef = React.useRef(null);
43
+ const [isStacked, setIsStacked] = React.useState(false);
44
+ const [sortedChildren, setSortedChildren] = React.useState(React.Children.toArray(children));
45
+
46
+ /**
47
+ * Used to determine if the buttons are currently stacked
48
+ */
49
+ useIsomorphicEffect.default(() => {
50
+ const checkStacking = () => {
51
+ let newIsStacked = stacked || false;
52
+ if (fluidInnerRef && fluidInnerRef.current) {
53
+ const computedStyle = window.getComputedStyle(fluidInnerRef.current);
54
+ newIsStacked = computedStyle?.getPropertyValue?.('--flex-direction') === 'column';
55
+ }
56
+ return newIsStacked;
57
+ };
58
+
59
+ /* initial value not dependant on observer */
60
+ setIsStacked(checkStacking());
61
+ if (!fluidInnerRef.current) {
62
+ return;
63
+ }
64
+ const resizeObserver = new ResizeObserver(() => {
65
+ setIsStacked(checkStacking());
66
+ });
67
+ resizeObserver.observe(fluidInnerRef.current);
68
+ return () => resizeObserver.disconnect();
69
+ }, [isStacked, stacked]);
70
+ React.useEffect(() => {
71
+ const newSortedChildren = React.Children.toArray(children);
72
+ newSortedChildren.sort((a, b) => {
73
+ return (buttonOrder(getButtonKind(a)) - buttonOrder(getButtonKind(b))) * (isStacked ? -1 : 1);
74
+ });
75
+ setSortedChildren(newSortedChildren);
76
+
77
+ // adding sortedChildren to deps causes an infinite loop
78
+ }, [children, isStacked]);
26
79
  const buttonSetClasses = cx(className, `${prefix}--btn-set`, {
27
- [`${prefix}--btn-set--stacked`]: stacked
80
+ [`${prefix}--btn-set--stacked`]: isStacked,
81
+ [`${prefix}--btn-set--fluid`]: fluid
28
82
  });
29
83
  return /*#__PURE__*/React.createElement("div", _rollupPluginBabelHelpers.extends({}, rest, {
30
84
  className: buttonSetClasses,
31
85
  ref: ref
32
- }), children);
86
+ }), fluid ? /*#__PURE__*/React.createElement("div", {
87
+ ref: fluidInnerRef,
88
+ className: cx(`${prefix}--btn-set__fluid-inner`, {
89
+ [`${prefix}--btn-set__fluid-inner--auto-stack`]: true
90
+ })
91
+ }, sortedChildren) : children);
33
92
  });
34
93
  ButtonSet.displayName = 'ButtonSet';
35
94
  ButtonSet.propTypes = {
@@ -41,9 +100,14 @@ ButtonSet.propTypes = {
41
100
  * Specify an optional className to be added to your ButtonSet
42
101
  */
43
102
  className: PropTypes.string,
103
+ /**
104
+ * fluid: button set resize to the size of the container up to a maximum dependant on the
105
+ * number of buttons.
106
+ */
107
+ fluid: PropTypes.bool,
44
108
  /**
45
109
  * Specify the button arrangement of the set (vertically stacked or
46
- * horizontal)
110
+ * horizontal) - ignored when fluid is true
47
111
  */
48
112
  stacked: PropTypes.bool
49
113
  };
@@ -111,7 +111,7 @@ declare namespace CodeSnippet {
111
111
  /**
112
112
  * Specify how the trigger should align with the tooltip
113
113
  */
114
- align: PropTypes.Requireable<import("@floating-ui/utils").Placement | "top-left" | "top-right" | "bottom-left" | "bottom-right" | "left-bottom" | "left-top" | "right-bottom" | "right-top"> | PropTypes.Validator<import("@floating-ui/utils").Placement | "top-left" | "top-right" | "bottom-left" | "bottom-right" | "left-bottom" | "left-top" | "right-bottom" | "right-top">;
114
+ align: PropTypes.Requireable<string> | PropTypes.Validator<string>;
115
115
  /**
116
116
  * Specify a label to be read by screen readers on the containing textbox
117
117
  * node
@@ -50,7 +50,7 @@ declare namespace Copy {
50
50
  /**
51
51
  * Specify how the trigger should align with the tooltip
52
52
  */
53
- align: PropTypes.Requireable<import("@floating-ui/utils").Placement | "top-left" | "top-right" | "bottom-left" | "bottom-right" | "left-bottom" | "left-top" | "right-bottom" | "right-top"> | PropTypes.Validator<import("@floating-ui/utils").Placement | "top-left" | "top-right" | "bottom-left" | "bottom-right" | "left-bottom" | "left-top" | "right-bottom" | "right-top">;
53
+ align: PropTypes.Requireable<string> | PropTypes.Validator<string>;
54
54
  /**
55
55
  * **Experimental**: Will attempt to automatically align the tooltip. Requires
56
56
  * React v17+
@@ -51,7 +51,7 @@ declare namespace CopyButton {
51
51
  /**
52
52
  * Specify how the trigger should align with the tooltip
53
53
  */
54
- align: PropTypes.Requireable<import("@floating-ui/utils").Placement | "top-left" | "top-right" | "bottom-left" | "bottom-right" | "left-bottom" | "left-top" | "right-bottom" | "right-top"> | PropTypes.Validator<import("@floating-ui/utils").Placement | "top-left" | "top-right" | "bottom-left" | "bottom-right" | "left-bottom" | "left-top" | "right-bottom" | "right-top">;
54
+ align: PropTypes.Requireable<string> | PropTypes.Validator<string>;
55
55
  /**
56
56
  * **Experimental**: Will attempt to automatically align the tooltip. Requires
57
57
  * React v17+
@@ -282,11 +282,12 @@ export declare const DataTable: {
282
282
  };
283
283
  TableCell: React.ForwardRefExoticComponent<import("./TableCell").TableCellProps & React.RefAttributes<HTMLTableCellElement>>;
284
284
  TableContainer: {
285
- ({ aiEnabled, className, children, title, description, stickyHeader, useStaticWidth, ...rest }: import("./TableContainer").TableContainerProps): import("react/jsx-runtime").JSX.Element;
285
+ ({ aiEnabled, className, children, decorator, title, description, stickyHeader, useStaticWidth, ...rest }: import("./TableContainer").TableContainerProps): import("react/jsx-runtime").JSX.Element;
286
286
  propTypes: {
287
287
  aiEnabled: PropTypes.Requireable<boolean>;
288
288
  children: PropTypes.Requireable<PropTypes.ReactNodeLike>;
289
289
  className: PropTypes.Requireable<string>;
290
+ decorator: PropTypes.Requireable<PropTypes.ReactNodeLike>;
290
291
  description: PropTypes.Requireable<PropTypes.ReactNodeLike>;
291
292
  stickyHeader: PropTypes.Requireable<boolean>;
292
293
  title: PropTypes.Requireable<PropTypes.ReactNodeLike>;