@carbon/react 1.70.0 → 1.71.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 (160) hide show
  1. package/.playwright/INTERNAL_AVT_REPORT_DO_NOT_USE.json +972 -947
  2. package/es/components/AILabel/index.js +15 -15
  3. package/es/components/Checkbox/Checkbox.d.ts +5 -0
  4. package/es/components/Checkbox/Checkbox.js +16 -7
  5. package/es/components/CheckboxGroup/CheckboxGroup.d.ts +5 -0
  6. package/es/components/CheckboxGroup/CheckboxGroup.js +16 -7
  7. package/es/components/CodeSnippet/CodeSnippet.d.ts +5 -2
  8. package/es/components/CodeSnippet/CodeSnippet.js +40 -1
  9. package/es/components/ComboBox/ComboBox.d.ts +1 -1
  10. package/es/components/ComboBox/ComboBox.js +19 -22
  11. package/es/components/ComboButton/index.js +40 -1
  12. package/es/components/ComposedModal/ComposedModal.d.ts +5 -0
  13. package/es/components/ComposedModal/ComposedModal.js +16 -10
  14. package/es/components/ContentSwitcher/ContentSwitcher.d.ts +2 -2
  15. package/es/components/ContentSwitcher/ContentSwitcher.js +1 -1
  16. package/es/components/Copy/Copy.d.ts +5 -2
  17. package/es/components/Copy/Copy.js +40 -1
  18. package/es/components/CopyButton/CopyButton.d.ts +5 -2
  19. package/es/components/CopyButton/CopyButton.js +40 -1
  20. package/es/components/DataTable/TableSelectRow.js +14 -6
  21. package/es/components/DataTable/TableToolbarSearch.js +1 -1
  22. package/es/components/DataTable/stories/examples/TableToolbarFilter.d.ts +1 -1
  23. package/es/components/DatePicker/plugins/fixEventsPlugin.js +2 -2
  24. package/es/components/DatePickerInput/DatePickerInput.d.ts +6 -1
  25. package/es/components/DatePickerInput/DatePickerInput.js +16 -10
  26. package/es/components/Dropdown/Dropdown.d.ts +5 -0
  27. package/es/components/Dropdown/Dropdown.js +132 -92
  28. package/es/components/FeatureFlags/index.js +1 -2
  29. package/es/components/FluidNumberInput/FluidNumberInput.d.ts +4 -0
  30. package/es/components/FluidSelect/FluidSelect.d.ts +4 -0
  31. package/es/components/FluidSelect/FluidSelect.js +5 -1
  32. package/es/components/FluidTextArea/FluidTextArea.d.ts +4 -0
  33. package/es/components/FluidTextArea/FluidTextArea.js +5 -1
  34. package/es/components/FluidTextInput/FluidPasswordInput.d.ts +4 -0
  35. package/es/components/FluidTextInput/FluidPasswordInput.js +5 -1
  36. package/es/components/FluidTextInput/FluidTextInput.d.ts +4 -0
  37. package/es/components/FluidTextInput/FluidTextInput.js +5 -1
  38. package/es/components/FluidTimePicker/FluidTimePicker.d.ts +4 -0
  39. package/es/components/FluidTimePicker/FluidTimePicker.js +23 -7
  40. package/es/components/IconButton/index.d.ts +4 -1
  41. package/es/components/IconButton/index.js +40 -1
  42. package/es/components/InlineCheckbox/InlineCheckbox.d.ts +50 -0
  43. package/es/components/InlineCheckbox/InlineCheckbox.js +3 -6
  44. package/es/components/InlineCheckbox/index.d.ts +9 -0
  45. package/es/components/LayoutDirection/LayoutDirection.d.ts +44 -0
  46. package/es/components/LayoutDirection/LayoutDirectionContext.d.ts +10 -0
  47. package/es/components/LayoutDirection/useLayoutDirection.d.ts +12 -0
  48. package/es/components/Menu/MenuItem.js +0 -3
  49. package/es/components/Modal/Modal.d.ts +5 -0
  50. package/es/components/Modal/Modal.js +16 -10
  51. package/es/components/MultiSelect/FilterableMultiSelect.d.ts +1 -1
  52. package/es/components/MultiSelect/FilterableMultiSelect.js +1 -2
  53. package/es/components/MultiSelect/MultiSelect.js +1 -1
  54. package/es/components/Notification/Notification.d.ts +9 -2
  55. package/es/components/Notification/Notification.js +16 -2
  56. package/es/components/NumberInput/NumberInput.d.ts +5 -0
  57. package/es/components/NumberInput/NumberInput.js +17 -9
  58. package/es/components/OverflowMenu/next/index.js +40 -1
  59. package/es/components/Pagination/Pagination.js +1 -1
  60. package/es/components/PaginationNav/PaginationNav.d.ts +1 -1
  61. package/es/components/PaginationNav/PaginationNav.js +22 -5
  62. package/es/components/RadioButton/RadioButton.d.ts +5 -0
  63. package/es/components/RadioButton/RadioButton.js +16 -7
  64. package/es/components/RadioButtonGroup/RadioButtonGroup.d.ts +5 -0
  65. package/es/components/RadioButtonGroup/RadioButtonGroup.js +16 -7
  66. package/es/components/RadioTile/RadioTile.d.ts +5 -0
  67. package/es/components/RadioTile/RadioTile.js +17 -8
  68. package/es/components/Tabs/Tabs.js +46 -29
  69. package/es/components/Tag/DismissibleTag.d.ts +11 -2
  70. package/es/components/Tag/DismissibleTag.js +13 -5
  71. package/es/components/Tag/Tag.d.ts +5 -0
  72. package/es/components/Tag/Tag.js +14 -7
  73. package/es/components/TextArea/TextArea.d.ts +5 -0
  74. package/es/components/TextArea/TextArea.js +15 -7
  75. package/es/components/TextInput/TextInput.d.ts +5 -0
  76. package/es/components/TextInput/TextInput.js +15 -7
  77. package/es/components/Tile/Tile.d.ts +21 -1
  78. package/es/components/Tile/Tile.js +68 -48
  79. package/es/components/UIShell/SideNavMenuItem.d.ts +5 -1
  80. package/es/components/UIShell/SideNavMenuItem.js +7 -2
  81. package/lib/components/AILabel/index.js +15 -15
  82. package/lib/components/Checkbox/Checkbox.d.ts +5 -0
  83. package/lib/components/Checkbox/Checkbox.js +16 -7
  84. package/lib/components/CheckboxGroup/CheckboxGroup.d.ts +5 -0
  85. package/lib/components/CheckboxGroup/CheckboxGroup.js +16 -7
  86. package/lib/components/CodeSnippet/CodeSnippet.d.ts +5 -2
  87. package/lib/components/CodeSnippet/CodeSnippet.js +40 -1
  88. package/lib/components/ComboBox/ComboBox.d.ts +1 -1
  89. package/lib/components/ComboBox/ComboBox.js +19 -22
  90. package/lib/components/ComboButton/index.js +40 -1
  91. package/lib/components/ComposedModal/ComposedModal.d.ts +5 -0
  92. package/lib/components/ComposedModal/ComposedModal.js +16 -10
  93. package/lib/components/ContentSwitcher/ContentSwitcher.d.ts +2 -2
  94. package/lib/components/ContentSwitcher/ContentSwitcher.js +1 -1
  95. package/lib/components/Copy/Copy.d.ts +5 -2
  96. package/lib/components/Copy/Copy.js +40 -1
  97. package/lib/components/CopyButton/CopyButton.d.ts +5 -2
  98. package/lib/components/CopyButton/CopyButton.js +40 -1
  99. package/lib/components/DataTable/TableSelectRow.js +14 -6
  100. package/lib/components/DataTable/TableToolbarSearch.js +1 -1
  101. package/lib/components/DataTable/stories/examples/TableToolbarFilter.d.ts +1 -1
  102. package/lib/components/DatePicker/plugins/fixEventsPlugin.js +2 -2
  103. package/lib/components/DatePickerInput/DatePickerInput.d.ts +6 -1
  104. package/lib/components/DatePickerInput/DatePickerInput.js +16 -10
  105. package/lib/components/Dropdown/Dropdown.d.ts +5 -0
  106. package/lib/components/Dropdown/Dropdown.js +131 -91
  107. package/lib/components/FeatureFlags/index.js +1 -2
  108. package/lib/components/FluidNumberInput/FluidNumberInput.d.ts +4 -0
  109. package/lib/components/FluidSelect/FluidSelect.d.ts +4 -0
  110. package/lib/components/FluidSelect/FluidSelect.js +5 -1
  111. package/lib/components/FluidTextArea/FluidTextArea.d.ts +4 -0
  112. package/lib/components/FluidTextArea/FluidTextArea.js +5 -1
  113. package/lib/components/FluidTextInput/FluidPasswordInput.d.ts +4 -0
  114. package/lib/components/FluidTextInput/FluidPasswordInput.js +5 -1
  115. package/lib/components/FluidTextInput/FluidTextInput.d.ts +4 -0
  116. package/lib/components/FluidTextInput/FluidTextInput.js +5 -1
  117. package/lib/components/FluidTimePicker/FluidTimePicker.d.ts +4 -0
  118. package/lib/components/FluidTimePicker/FluidTimePicker.js +23 -7
  119. package/lib/components/IconButton/index.d.ts +4 -1
  120. package/lib/components/IconButton/index.js +40 -1
  121. package/lib/components/InlineCheckbox/InlineCheckbox.d.ts +50 -0
  122. package/lib/components/InlineCheckbox/InlineCheckbox.js +3 -6
  123. package/lib/components/InlineCheckbox/index.d.ts +9 -0
  124. package/lib/components/LayoutDirection/LayoutDirection.d.ts +44 -0
  125. package/lib/components/LayoutDirection/LayoutDirectionContext.d.ts +10 -0
  126. package/lib/components/LayoutDirection/useLayoutDirection.d.ts +12 -0
  127. package/lib/components/Menu/MenuItem.js +0 -3
  128. package/lib/components/Modal/Modal.d.ts +5 -0
  129. package/lib/components/Modal/Modal.js +16 -10
  130. package/lib/components/MultiSelect/FilterableMultiSelect.d.ts +1 -1
  131. package/lib/components/MultiSelect/FilterableMultiSelect.js +1 -2
  132. package/lib/components/MultiSelect/MultiSelect.js +1 -1
  133. package/lib/components/Notification/Notification.d.ts +9 -2
  134. package/lib/components/Notification/Notification.js +16 -2
  135. package/lib/components/NumberInput/NumberInput.d.ts +5 -0
  136. package/lib/components/NumberInput/NumberInput.js +17 -9
  137. package/lib/components/OverflowMenu/next/index.js +40 -1
  138. package/lib/components/Pagination/Pagination.js +1 -1
  139. package/lib/components/PaginationNav/PaginationNav.d.ts +1 -1
  140. package/lib/components/PaginationNav/PaginationNav.js +22 -5
  141. package/lib/components/RadioButton/RadioButton.d.ts +5 -0
  142. package/lib/components/RadioButton/RadioButton.js +16 -7
  143. package/lib/components/RadioButtonGroup/RadioButtonGroup.d.ts +5 -0
  144. package/lib/components/RadioButtonGroup/RadioButtonGroup.js +16 -7
  145. package/lib/components/RadioTile/RadioTile.d.ts +5 -0
  146. package/lib/components/RadioTile/RadioTile.js +17 -8
  147. package/lib/components/Tabs/Tabs.js +46 -29
  148. package/lib/components/Tag/DismissibleTag.d.ts +11 -2
  149. package/lib/components/Tag/DismissibleTag.js +13 -5
  150. package/lib/components/Tag/Tag.d.ts +5 -0
  151. package/lib/components/Tag/Tag.js +14 -7
  152. package/lib/components/TextArea/TextArea.d.ts +5 -0
  153. package/lib/components/TextArea/TextArea.js +15 -7
  154. package/lib/components/TextInput/TextInput.d.ts +5 -0
  155. package/lib/components/TextInput/TextInput.js +15 -7
  156. package/lib/components/Tile/Tile.d.ts +21 -1
  157. package/lib/components/Tile/Tile.js +67 -47
  158. package/lib/components/UIShell/SideNavMenuItem.d.ts +5 -1
  159. package/lib/components/UIShell/SideNavMenuItem.js +7 -2
  160. package/package.json +5 -5
@@ -14,7 +14,21 @@ import { composeEventHandlers } from '../../tools/events.js';
14
14
  import { usePrefix } from '../../internal/usePrefix.js';
15
15
  import { IconButton } from '../IconButton/index.js';
16
16
  import { noopFn } from '../../internal/noopFn.js';
17
+ import deprecateValuesWithin from '../../prop-types/deprecateValuesWithin.js';
17
18
 
19
+ const propMappingFunction = deprecatedValue => {
20
+ const mapping = {
21
+ 'top-left': 'top-start',
22
+ 'top-right': 'top-end',
23
+ 'bottom-left': 'bottom-start',
24
+ 'bottom-right': 'bottom-end',
25
+ 'left-bottom': 'left-end',
26
+ 'left-top': 'left-start',
27
+ 'right-bottom': 'right-end',
28
+ 'right-top': 'right-start'
29
+ };
30
+ return mapping[deprecatedValue];
31
+ };
18
32
  function Copy(_ref) {
19
33
  let {
20
34
  align = 'bottom',
@@ -66,7 +80,32 @@ Copy.propTypes = {
66
80
  /**
67
81
  * Specify how the trigger should align with the tooltip
68
82
  */
69
- align: PropTypes.oneOf(['top', 'top-left', 'top-right', 'bottom', 'bottom-left', 'bottom-right', 'left', 'right']),
83
+ align: deprecateValuesWithin(PropTypes.oneOf(['top', 'top-left',
84
+ // deprecated use top-start instead
85
+ 'top-right',
86
+ // deprecated use top-end instead
87
+
88
+ 'bottom', 'bottom-left',
89
+ // deprecated use bottom-start instead
90
+ 'bottom-right',
91
+ // deprecated use bottom-end instead
92
+
93
+ 'left', 'left-bottom',
94
+ // deprecated use left-end instead
95
+ 'left-top',
96
+ // deprecated use left-start instead
97
+
98
+ 'right', 'right-bottom',
99
+ // deprecated use right-end instead
100
+ 'right-top',
101
+ // deprecated use right-start instead
102
+
103
+ // new values to match floating-ui
104
+ 'top-start', 'top-end', 'bottom-start', 'bottom-end', 'left-end', 'left-start', 'right-end', 'right-start']),
105
+ //allowed prop values
106
+ ['top', 'top-start', 'top-end', 'bottom', 'bottom-start', 'bottom-end', 'left', 'left-start', 'left-end', 'right', 'right-start', 'right-end'],
107
+ //optional mapper function
108
+ propMappingFunction),
70
109
  /**
71
110
  * **Experimental**: Will attempt to automatically align the tooltip
72
111
  */
@@ -7,11 +7,14 @@
7
7
  import PropTypes from 'prop-types';
8
8
  import { MouseEventHandler } from 'react';
9
9
  import { ButtonProps } from '../Button';
10
+ export type DeprecatedCopyButtonAlignment = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'left-bottom' | 'left-top' | 'right-bottom' | 'right-top';
11
+ export type NewCopyButtonAlignment = 'top' | 'bottom' | 'left' | 'right' | 'top-start' | 'top-end' | 'bottom-start' | 'bottom-end' | 'left-end' | 'left-start' | 'right-end' | 'right-start';
12
+ export type CopyButtonAlignment = DeprecatedCopyButtonAlignment | NewCopyButtonAlignment;
10
13
  export interface CopyButtonProps extends ButtonProps<'button'> {
11
14
  /**
12
15
  * Specify how the trigger should align with the tooltip
13
16
  */
14
- align?: 'top' | 'top-left' | 'top-right' | 'bottom' | 'bottom-left' | 'bottom-right' | 'left' | 'right';
17
+ align?: CopyButtonAlignment;
15
18
  /**
16
19
  * **Experimental**: Will attempt to automatically align the tooltip
17
20
  */
@@ -46,7 +49,7 @@ declare namespace CopyButton {
46
49
  /**
47
50
  * Specify how the trigger should align with the tooltip
48
51
  */
49
- align: PropTypes.Requireable<string>;
52
+ align: (props: any, propName: any, componentName: any, ...rest: any[]) => any;
50
53
  /**
51
54
  * **Experimental**: Will attempt to automatically align the tooltip
52
55
  */
@@ -14,7 +14,21 @@ import Copy from '../Copy/Copy.js';
14
14
  import { LayoutConstraint } from '../Layout/index.js';
15
15
  import { usePrefix } from '../../internal/usePrefix.js';
16
16
  import { noopFn } from '../../internal/noopFn.js';
17
+ import deprecateValuesWithin from '../../prop-types/deprecateValuesWithin.js';
17
18
 
19
+ const propMappingFunction = deprecatedValue => {
20
+ const mapping = {
21
+ 'top-left': 'top-start',
22
+ 'top-right': 'top-end',
23
+ 'bottom-left': 'bottom-start',
24
+ 'bottom-right': 'bottom-end',
25
+ 'left-bottom': 'left-end',
26
+ 'left-top': 'left-start',
27
+ 'right-bottom': 'right-end',
28
+ 'right-top': 'right-start'
29
+ };
30
+ return mapping[deprecatedValue];
31
+ };
18
32
  function CopyButton(_ref) {
19
33
  let {
20
34
  align = 'bottom',
@@ -48,7 +62,32 @@ CopyButton.propTypes = {
48
62
  /**
49
63
  * Specify how the trigger should align with the tooltip
50
64
  */
51
- align: PropTypes.oneOf(['top', 'top-left', 'top-right', 'bottom', 'bottom-left', 'bottom-right', 'left', 'right']),
65
+ align: deprecateValuesWithin(PropTypes.oneOf(['top', 'top-left',
66
+ // deprecated use top-start instead
67
+ 'top-right',
68
+ // deprecated use top-end instead
69
+
70
+ 'bottom', 'bottom-left',
71
+ // deprecated use bottom-start instead
72
+ 'bottom-right',
73
+ // deprecated use bottom-end instead
74
+
75
+ 'left', 'left-bottom',
76
+ // deprecated use left-end instead
77
+ 'left-top',
78
+ // deprecated use left-start instead
79
+
80
+ 'right', 'right-bottom',
81
+ // deprecated use right-end instead
82
+ 'right-top',
83
+ // deprecated use right-start instead
84
+
85
+ // new values to match floating-ui
86
+ 'top-start', 'top-end', 'bottom-start', 'bottom-end', 'left-end', 'left-start', 'right-end', 'right-start']),
87
+ //allowed prop values
88
+ ['top', 'top-start', 'top-end', 'bottom', 'bottom-start', 'bottom-end', 'left', 'left-start', 'left-end', 'right', 'right-start', 'right-end'],
89
+ //optional mapper function
90
+ propMappingFunction),
52
91
  /**
53
92
  * **Experimental**: Will attempt to automatically align the tooltip
54
93
  */
@@ -30,15 +30,21 @@ const TableSelectRow = _ref => {
30
30
  } = _ref;
31
31
  const prefix = usePrefix();
32
32
  const uniqueNameId = useId();
33
+ const handleRadioChange = onChange ? (value, name, event) => {
34
+ // Convert the radio value to boolean for consistency
35
+ onChange(!!value, name || '', event);
36
+ } : undefined;
37
+ const handleCheckboxChange = onChange ? (checked, name, event) => {
38
+ onChange(checked, name, event);
39
+ } : undefined;
33
40
  const selectionInputProps = {
34
41
  id,
35
42
  name: name ? name : uniqueNameId,
36
43
  onClick: onSelect,
37
- onChange,
38
44
  checked,
39
45
  disabled
40
46
  };
41
- const InlineInputComponent = radio ? RadioButton : InlineCheckbox;
47
+ const labelValue = ariaLabel || deprecatedAriaLabel || '';
42
48
  const tableSelectRowClasses = cx(`${prefix}--table-column-checkbox`, {
43
49
  ...(className && {
44
50
  [className]: true
@@ -48,11 +54,13 @@ const TableSelectRow = _ref => {
48
54
  return /*#__PURE__*/React__default.createElement("td", {
49
55
  className: tableSelectRowClasses,
50
56
  "aria-live": "off"
51
- }, /*#__PURE__*/React__default.createElement(InlineInputComponent, _extends({}, selectionInputProps, radio && {
52
- labelText: ariaLabel || deprecatedAriaLabel,
57
+ }, radio ? /*#__PURE__*/React__default.createElement(RadioButton, _extends({}, selectionInputProps, {
58
+ labelText: labelValue,
59
+ onChange: handleRadioChange,
53
60
  hideLabel: true
54
- }, !radio && {
55
- 'aria-label': ariaLabel || deprecatedAriaLabel
61
+ })) : /*#__PURE__*/React__default.createElement(InlineCheckbox, _extends({}, selectionInputProps, {
62
+ "aria-label": labelValue,
63
+ onChange: handleCheckboxChange
56
64
  })));
57
65
  };
58
66
  TableSelectRow.propTypes = {
@@ -92,7 +92,7 @@ const TableToolbarSearch = _ref => {
92
92
  const onChange = e => {
93
93
  setValue(e.target.value);
94
94
  if (onChangeProp) {
95
- onChangeProp(e);
95
+ onChangeProp(e, e.target.value);
96
96
  }
97
97
  };
98
98
  const handleOnFocus = event => handleExpand(event, true);
@@ -13,7 +13,7 @@ interface TableToolbarFilterProps {
13
13
  /**
14
14
  * Provide an optional hook that is called each time the input is updated
15
15
  */
16
- onChange?: (event: '' | ChangeEvent<HTMLInputElement>, value?: string) => void;
16
+ onChange?: (event: '' | ChangeEvent<HTMLInputElement>) => void;
17
17
  /**
18
18
  * Provide an function that is called when the apply button is clicked
19
19
  */
@@ -76,7 +76,7 @@ var carbonFlatpickrFixEventsPlugin = config => fp => {
76
76
  if (inputTo === target && fp.selectedDates[1]) {
77
77
  // Using getTime() enables the ability to more readily compare the date currently
78
78
  // selected in the calendar and the date currently in the value of the input
79
- const withoutTime = date => date.setHours(0, 0, 0, 0);
79
+ const withoutTime = date => date?.setHours(0, 0, 0, 0);
80
80
  const selectedToDate = withoutTime(new Date(fp.selectedDates[1]));
81
81
  const currentValueToDate = withoutTime(parseDateWithFormat(inputTo.value));
82
82
 
@@ -88,7 +88,7 @@ var carbonFlatpickrFixEventsPlugin = config => fp => {
88
88
  fp.setDate([inputFrom.value, inputTo && inputTo.value], true, fp.config.dateFormat);
89
89
  }
90
90
  }
91
- const isValidDate = date => date.toString() !== 'Invalid Date';
91
+ const isValidDate = date => date?.toString() !== 'Invalid Date';
92
92
  // save end date in calendar inmediately after it's been written down
93
93
  if (inputTo === target && fp.selectedDates.length === 1 && inputTo.value) {
94
94
  if (isValidDate(parseDateWithFormat(inputTo.value))) {
@@ -5,7 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  import { ReactElementLike, ReactNodeArray } from 'prop-types';
8
- import React from 'react';
8
+ import React, { ReactNode } from 'react';
9
9
  import { ReactAttr } from '../../types/common';
10
10
  type ExcludedAttributes = 'value' | 'onChange' | 'locale' | 'children';
11
11
  export type ReactNodeLike = ReactElementLike | ReactNodeArray | string | number | boolean | null | undefined;
@@ -19,6 +19,10 @@ export interface DatePickerInputProps extends Omit<ReactAttr<HTMLInputElement>,
19
19
  * * `range` - With calendar dropdown and a date range.
20
20
  */
21
21
  datePickerType?: 'simple' | 'single' | 'range';
22
+ /**
23
+ * **Experimental**: Provide a `decorator` component to be rendered inside the `DatePickerInput` component
24
+ */
25
+ decorator?: ReactNode;
22
26
  /**
23
27
  * Specify whether or not the input should be disabled
24
28
  */
@@ -77,6 +81,7 @@ export interface DatePickerInputProps extends Omit<ReactAttr<HTMLInputElement>,
77
81
  */
78
82
  size?: 'sm' | 'md' | 'lg';
79
83
  /**
84
+ * @deprecated please use decorator instead.
80
85
  * **Experimental**: Provide a `Slug` component to be rendered inside the `DatePickerInput` component
81
86
  */
82
87
  slug?: ReactNodeLike;
@@ -14,11 +14,13 @@ import '../FluidForm/FluidForm.js';
14
14
  import { FormContext } from '../FluidForm/FormContext.js';
15
15
  import { useId } from '../../internal/useId.js';
16
16
  import '../Text/index.js';
17
+ import deprecate from '../../prop-types/deprecate.js';
17
18
  import { Text } from '../Text/Text.js';
18
19
 
19
20
  const DatePickerInput = /*#__PURE__*/React__default.forwardRef(function DatePickerInput(props, ref) {
20
21
  const {
21
22
  datePickerType,
23
+ decorator,
22
24
  disabled = false,
23
25
  helperText,
24
26
  hideLabel,
@@ -61,7 +63,8 @@ const DatePickerInput = /*#__PURE__*/React__default.forwardRef(function DatePick
61
63
  const wrapperClasses = cx(`${prefix}--date-picker-input__wrapper`, {
62
64
  [`${prefix}--date-picker-input__wrapper--invalid`]: invalid,
63
65
  [`${prefix}--date-picker-input__wrapper--warn`]: warn,
64
- [`${prefix}--date-picker-input__wrapper--slug`]: slug
66
+ [`${prefix}--date-picker-input__wrapper--slug`]: slug,
67
+ [`${prefix}--date-picker-input__wrapper--decorator`]: decorator
65
68
  });
66
69
  const labelClasses = cx(`${prefix}--label`, {
67
70
  [`${prefix}--visually-hidden`]: hideLabel,
@@ -95,10 +98,10 @@ const DatePickerInput = /*#__PURE__*/React__default.forwardRef(function DatePick
95
98
  }
96
99
  const input = /*#__PURE__*/React__default.createElement("input", inputProps);
97
100
 
98
- // Slug is always size `mini`
99
- let normalizedSlug;
100
- if (slug && slug['type']?.displayName === 'AILabel') {
101
- normalizedSlug = /*#__PURE__*/React__default.cloneElement(slug, {
101
+ // AILabel always size `mini`
102
+ let normalizedDecorator = /*#__PURE__*/React__default.isValidElement(slug ?? decorator) ? slug ?? decorator : null;
103
+ if (normalizedDecorator && normalizedDecorator['type']?.displayName === 'AILabel') {
104
+ normalizedDecorator = /*#__PURE__*/React__default.cloneElement(normalizedDecorator, {
102
105
  size: 'mini'
103
106
  });
104
107
  }
@@ -110,7 +113,9 @@ const DatePickerInput = /*#__PURE__*/React__default.forwardRef(function DatePick
110
113
  className: labelClasses
111
114
  }, labelText), /*#__PURE__*/React__default.createElement("div", {
112
115
  className: wrapperClasses
113
- }, /*#__PURE__*/React__default.createElement("span", null, input, normalizedSlug, isFluid && /*#__PURE__*/React__default.createElement(DatePickerIcon, {
116
+ }, /*#__PURE__*/React__default.createElement("span", null, input, slug ? normalizedDecorator : decorator ? /*#__PURE__*/React__default.createElement("div", {
117
+ className: `${prefix}--date-picker-input-inner-wrapper--decorator`
118
+ }, normalizedDecorator) : '', isFluid && /*#__PURE__*/React__default.createElement(DatePickerIcon, {
114
119
  datePickerType: datePickerType
115
120
  }), /*#__PURE__*/React__default.createElement(DatePickerIcon, {
116
121
  datePickerType: datePickerType,
@@ -141,6 +146,10 @@ DatePickerInput.propTypes = {
141
146
  * * `range` - With calendar dropdown and a date range.
142
147
  */
143
148
  datePickerType: PropTypes.oneOf(['simple', 'single', 'range']),
149
+ /**
150
+ * **Experimental**: Provide a decorator component to be rendered inside the `RadioButton` component
151
+ */
152
+ decorator: PropTypes.node,
144
153
  /**
145
154
  * Specify whether or not the input should be disabled
146
155
  */
@@ -204,10 +213,7 @@ DatePickerInput.propTypes = {
204
213
  * Specify the size of the Date Picker Input. Currently supports either `sm`, `md`, or `lg` as an option.
205
214
  */
206
215
  size: PropTypes.oneOf(['sm', 'md', 'lg']),
207
- /**
208
- * **Experimental**: Provide a `Slug` component to be rendered inside the `DatePickerInput` component
209
- */
210
- slug: PropTypes.node,
216
+ slug: deprecate(PropTypes.node, 'The `slug` prop has been deprecated and will be removed in the next major version. Use the decorator prop instead.'),
211
217
  /**
212
218
  * Specify the type of the `<input>`
213
219
  */
@@ -27,6 +27,10 @@ export interface DropdownProps<ItemType> extends Omit<ReactAttr<HTMLDivElement>,
27
27
  * **Experimental**: Will attempt to automatically align the floating element to avoid collisions with the viewport and being clipped by ancestor elements.
28
28
  */
29
29
  autoAlign?: boolean;
30
+ /**
31
+ * **Experimental**: Provide a `decorator` component to be rendered inside the `Dropdown` component
32
+ */
33
+ decorator?: ReactNode;
30
34
  /**
31
35
  * Specify the direction of the dropdown. Can be either top or bottom.
32
36
  */
@@ -120,6 +124,7 @@ export interface DropdownProps<ItemType> extends Omit<ReactAttr<HTMLDivElement>,
120
124
  */
121
125
  size?: ListBoxSize;
122
126
  /**
127
+ * @deprecated please use `decorator` instead.
123
128
  * **Experimental**: Provide a `Slug` component to be rendered inside the `Dropdown` component
124
129
  */
125
130
  slug?: ReactNode;
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
9
- import React__default, { useEffect, useContext, useState, useMemo } from 'react';
9
+ import React__default, { useEffect, useContext, useCallback, useMemo, useState } from 'react';
10
10
  import { useSelect } from 'downshift';
11
11
  import cx from 'classnames';
12
12
  import PropTypes from 'prop-types';
@@ -39,13 +39,50 @@ const defaultItemToString = item => {
39
39
  }
40
40
  return '';
41
41
  };
42
+ /**
43
+ * Custom state reducer for `useSelect` in Downshift, providing control over
44
+ * state changes.
45
+ *
46
+ * This function is called each time `useSelect` updates its internal state or
47
+ * triggers `onStateChange`. It allows for fine-grained control of state
48
+ * updates by modifying or overriding the default changes from Downshift's
49
+ * reducer.
50
+ * https://github.com/downshift-js/downshift/tree/master/src/hooks/useSelect#statereducer
51
+ *
52
+ * @param {Object} state - The current full state of the Downshift component.
53
+ * @param {Object} actionAndChanges - Contains the action type and proposed
54
+ * changes from the default Downshift reducer.
55
+ * @param {Object} actionAndChanges.changes - Suggested state changes.
56
+ * @param {string} actionAndChanges.type - The action type for the state
57
+ * change (e.g., item selection).
58
+ * @returns {Object} - The modified state based on custom logic or default
59
+ * changes if no custom logic applies.
60
+ */
61
+ function stateReducer(state, actionAndChanges) {
62
+ const {
63
+ changes,
64
+ type
65
+ } = actionAndChanges;
66
+ switch (type) {
67
+ case ItemMouseMove:
68
+ case MenuMouseLeave:
69
+ if (changes.highlightedIndex === state.highlightedIndex) {
70
+ // Prevent state update if highlightedIndex hasn't changed
71
+ return state;
72
+ }
73
+ return changes;
74
+ default:
75
+ return changes;
76
+ }
77
+ }
42
78
  const Dropdown = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
43
79
  let {
44
80
  autoAlign = false,
45
81
  className: containerClassName,
82
+ decorator,
46
83
  disabled = false,
47
84
  direction = 'bottom',
48
- items,
85
+ items: itemsProp,
49
86
  label,
50
87
  ['aria-label']: ariaLabel,
51
88
  ariaLabel: deprecatedAriaLabel,
@@ -118,49 +155,47 @@ const Dropdown = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
118
155
  const {
119
156
  isFluid
120
157
  } = useContext(FormContext);
121
- const selectProps = {
158
+ const onSelectedItemChange = useCallback(_ref3 => {
159
+ let {
160
+ selectedItem
161
+ } = _ref3;
162
+ if (onChange) {
163
+ onChange({
164
+ selectedItem: selectedItem ?? null
165
+ });
166
+ }
167
+ }, [onChange]);
168
+ const isItemDisabled = useCallback((item, _index) => {
169
+ const isObject = item !== null && typeof item === 'object';
170
+ return isObject && 'disabled' in item && item.disabled === true;
171
+ }, []);
172
+ const onHighlightedIndexChange = useCallback(changes => {
173
+ const {
174
+ highlightedIndex
175
+ } = changes;
176
+ if (highlightedIndex !== undefined && highlightedIndex > -1 && typeof window !== undefined) {
177
+ const itemArray = document.querySelectorAll(`li.${prefix}--list-box__menu-item[role="option"]`);
178
+ const highlightedItem = itemArray[highlightedIndex];
179
+ if (highlightedItem) {
180
+ highlightedItem.scrollIntoView({
181
+ behavior: 'smooth',
182
+ block: 'nearest'
183
+ });
184
+ }
185
+ }
186
+ }, [prefix]);
187
+ const items = useMemo(() => itemsProp, [itemsProp]);
188
+ const selectProps = useMemo(() => ({
122
189
  items,
123
190
  itemToString,
124
191
  initialSelectedItem,
125
192
  onSelectedItemChange,
126
193
  stateReducer,
127
- isItemDisabled(item, _index) {
128
- const isObject = item !== null && typeof item === 'object';
129
- return isObject && 'disabled' in item && item.disabled === true;
130
- },
131
- onHighlightedIndexChange: _ref3 => {
132
- let {
133
- highlightedIndex
134
- } = _ref3;
135
- if (highlightedIndex > -1 && typeof window !== undefined) {
136
- const itemArray = document.querySelectorAll(`li.${prefix}--list-box__menu-item[role="option"]`);
137
- const highlightedItem = itemArray[highlightedIndex];
138
- if (highlightedItem) {
139
- highlightedItem.scrollIntoView({
140
- behavior: 'smooth',
141
- block: 'nearest'
142
- });
143
- }
144
- }
145
- },
194
+ isItemDisabled,
195
+ onHighlightedIndexChange,
146
196
  ...downshiftProps
147
- };
197
+ }), [items, itemToString, initialSelectedItem, onSelectedItemChange, stateReducer, isItemDisabled, onHighlightedIndexChange, downshiftProps]);
148
198
  const dropdownInstanceId = useId();
149
- function stateReducer(state, actionAndChanges) {
150
- const {
151
- changes,
152
- type
153
- } = actionAndChanges;
154
- switch (type) {
155
- case ItemMouseMove:
156
- case MenuMouseLeave:
157
- return {
158
- ...changes,
159
- highlightedIndex: state.highlightedIndex
160
- };
161
- }
162
- return changes;
163
- }
164
199
 
165
200
  // only set selectedItem if the prop is defined. Setting if it is undefined
166
201
  // will overwrite default selected items from useSelect
@@ -205,80 +240,79 @@ const Dropdown = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
205
240
  [`${prefix}--list-box__wrapper--inline--invalid`]: inline && invalid,
206
241
  [`${prefix}--list-box__wrapper--fluid--invalid`]: isFluid && invalid,
207
242
  [`${prefix}--list-box__wrapper--fluid--focus`]: isFluid && isFocused && !isOpen,
208
- [`${prefix}--list-box__wrapper--slug`]: slug
243
+ [`${prefix}--list-box__wrapper--slug`]: slug,
244
+ [`${prefix}--list-box__wrapper--decorator`]: decorator
209
245
  });
210
246
  const helperId = !helperText ? undefined : `dropdown-helper-text-${dropdownInstanceId}`;
211
247
 
212
248
  // needs to be Capitalized for react to render it correctly
213
249
  const ItemToElement = itemToElement;
214
- const toggleButtonProps = getToggleButtonProps({
250
+ const toggleButtonProps = useMemo(() => getToggleButtonProps({
215
251
  'aria-label': ariaLabel || deprecatedAriaLabel
216
- });
252
+ }), [getToggleButtonProps, ariaLabel, deprecatedAriaLabel, isOpen]);
217
253
  const helper = helperText && !isFluid ? /*#__PURE__*/React__default.createElement("div", {
218
254
  id: helperId,
219
255
  className: helperClasses
220
256
  }, helperText) : null;
221
- function onSelectedItemChange(_ref4) {
222
- let {
223
- selectedItem
224
- } = _ref4;
225
- if (onChange) {
226
- onChange({
227
- selectedItem: selectedItem ?? null
228
- });
229
- }
230
- }
231
257
  const handleFocus = evt => {
232
258
  setIsFocused(evt.type === 'focus' ? true : false);
233
259
  };
234
260
  const mergedRef = mergeRefs(toggleButtonProps.ref, ref);
235
261
  const [currTimer, setCurrTimer] = useState();
236
-
237
- // eslint-disable-next-line prefer-const
238
- let [isTyping, setIsTyping] = useState(false);
239
- const readOnlyEventHandlers = readOnly ? {
240
- onClick: evt => {
241
- // NOTE: does not prevent click
242
- evt.preventDefault();
243
- // focus on the element as per readonly input behavior
244
- mergedRef?.current?.focus();
245
- },
246
- onKeyDown: evt => {
247
- const selectAccessKeys = ['ArrowDown', 'ArrowUp', ' ', 'Enter'];
248
- // This prevents the select from opening for the above keys
249
- if (selectAccessKeys.includes(evt.key)) {
250
- evt.preventDefault();
251
- }
262
+ const [isTyping, setIsTyping] = useState(false);
263
+ const onKeyDownHandler = useCallback(evt => {
264
+ if (evt.code !== 'Space' || !['ArrowDown', 'ArrowUp', ' ', 'Enter'].includes(evt.key)) {
265
+ setIsTyping(true);
252
266
  }
253
- } : {
254
- onKeyDown: evt => {
255
- if (evt.code !== 'Space' || !['ArrowDown', 'ArrowUp', ' ', 'Enter'].includes(evt.key)) {
256
- setIsTyping(true);
267
+ if (isTyping && evt.code === 'Space' || !['ArrowDown', 'ArrowUp', ' ', 'Enter'].includes(evt.key)) {
268
+ if (currTimer) {
269
+ clearTimeout(currTimer);
257
270
  }
258
- if (isTyping && evt.code === 'Space' || !['ArrowDown', 'ArrowUp', ' ', 'Enter'].includes(evt.key)) {
259
- if (currTimer) {
260
- clearTimeout(currTimer);
271
+ setCurrTimer(setTimeout(() => {
272
+ setIsTyping(false);
273
+ }, 3000));
274
+ }
275
+ if (toggleButtonProps.onKeyDown) {
276
+ toggleButtonProps.onKeyDown(evt);
277
+ }
278
+ }, [isTyping, currTimer, toggleButtonProps]);
279
+ const readOnlyEventHandlers = useMemo(() => {
280
+ if (readOnly) {
281
+ return {
282
+ onClick: evt => {
283
+ // NOTE: does not prevent click
284
+ evt.preventDefault();
285
+ // focus on the element as per readonly input behavior
286
+ mergedRef?.current?.focus();
287
+ },
288
+ onKeyDown: evt => {
289
+ const selectAccessKeys = ['ArrowDown', 'ArrowUp', ' ', 'Enter'];
290
+ // This prevents the select from opening for the above keys
291
+ if (selectAccessKeys.includes(evt.key)) {
292
+ evt.preventDefault();
293
+ }
261
294
  }
262
- setCurrTimer(setTimeout(() => {
263
- setIsTyping(false);
264
- }, 3000));
265
- }
266
- if (toggleButtonProps.onKeyDown) {
267
- toggleButtonProps.onKeyDown(evt);
268
- }
295
+ };
296
+ } else {
297
+ return {
298
+ onKeyDown: onKeyDownHandler
299
+ };
269
300
  }
270
- };
301
+ }, [readOnly, onKeyDownHandler]);
271
302
  const menuProps = useMemo(() => getMenuProps({
272
303
  ref: enableFloatingStyles || autoAlign ? refs.setFloating : null
273
- }), [autoAlign, getMenuProps, refs.setFloating]);
304
+ }), [autoAlign, getMenuProps, refs.setFloating, enableFloatingStyles]);
274
305
 
275
- // Slug is always size `mini`
276
- let normalizedSlug;
277
- if (slug && slug['type']?.displayName === 'AILabel') {
278
- normalizedSlug = /*#__PURE__*/React__default.cloneElement(slug, {
279
- size: 'mini'
280
- });
281
- }
306
+ // AILabel is always size `mini`
307
+ const normalizedDecorator = useMemo(() => {
308
+ let element = slug ?? decorator;
309
+ if (element && element['type']?.displayName === 'AILabel') {
310
+ return /*#__PURE__*/React__default.cloneElement(element, {
311
+ size: 'mini'
312
+ });
313
+ }
314
+ return /*#__PURE__*/React__default.isValidElement(element) ? element : null;
315
+ }, [slug, decorator]);
282
316
  return /*#__PURE__*/React__default.createElement("div", _extends({
283
317
  className: wrapperClasses
284
318
  }, other), titleText && /*#__PURE__*/React__default.createElement("label", _extends({
@@ -317,7 +351,9 @@ const Dropdown = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
317
351
  }, selectedItem ? renderSelectedItem ? renderSelectedItem(selectedItem) : itemToString(selectedItem) : label), /*#__PURE__*/React__default.createElement(ListBox.MenuIcon, {
318
352
  isOpen: isOpen,
319
353
  translateWithId: translateWithId
320
- })), normalizedSlug, /*#__PURE__*/React__default.createElement(ListBox.Menu, menuProps, isOpen && items.map((item, index) => {
354
+ })), slug ? normalizedDecorator : decorator ? /*#__PURE__*/React__default.createElement("div", {
355
+ className: `${prefix}--list-box__inner-wrapper--decorator`
356
+ }, normalizedDecorator) : '', /*#__PURE__*/React__default.createElement(ListBox.Menu, menuProps, isOpen && items.map((item, index) => {
321
357
  const isObject = item !== null && typeof item === 'object';
322
358
  const itemProps = getItemProps({
323
359
  item,
@@ -360,6 +396,10 @@ Dropdown.propTypes = {
360
396
  * Provide a custom className to be applied on the cds--dropdown node
361
397
  */
362
398
  className: PropTypes.string,
399
+ /**
400
+ * **Experimental**: Provide a `decorator` component to be rendered inside the `Dropdown` component
401
+ */
402
+ decorator: PropTypes.node,
363
403
  /**
364
404
  * Specify the direction of the dropdown. Can be either top or bottom.
365
405
  */
@@ -453,7 +493,7 @@ Dropdown.propTypes = {
453
493
  /**
454
494
  * **Experimental**: Provide a `Slug` component to be rendered inside the `Dropdown` component
455
495
  */
456
- slug: PropTypes.node,
496
+ slug: deprecate(PropTypes.node, 'The `slug` prop for `Dropdown` has ' + 'been deprecated in favor of the new `decorator` prop. It will be removed in the next major release.'),
457
497
  /**
458
498
  * Provide the title text that will be read by a screen reader when
459
499
  * visiting this control
@@ -120,8 +120,7 @@ function useChangedValue(value, compare, callback) {
120
120
  */
121
121
  function useFeatureFlag(flag) {
122
122
  const scope = useContext(FeatureFlagContext);
123
- //updated to return false for undefined flags
124
- return scope.enabled(flag) ?? false;
123
+ return scope.enabled(flag);
125
124
  }
126
125
 
127
126
  /**
@@ -90,6 +90,10 @@ export interface FluidNumberInputProps {
90
90
  * Provide the text that is displayed when the control is in warning state
91
91
  */
92
92
  warnText?: React.ReactNode;
93
+ /**
94
+ * Whether or not the component is readonly
95
+ */
96
+ readOnly?: boolean;
93
97
  }
94
98
  declare const FluidNumberInput: React.FC<FluidNumberInputProps>;
95
99
  export default FluidNumberInput;