@carbon/react 1.68.0-rc.0 → 1.69.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.
- package/.playwright/INTERNAL_AVT_REPORT_DO_NOT_USE.json +743 -743
- package/README.md +3 -3
- package/es/components/Accordion/AccordionItem.js +0 -1
- package/es/components/Button/Button.js +6 -0
- package/es/components/CheckboxGroup/CheckboxGroup.js +1 -2
- package/es/components/CheckboxGroup/index.d.ts +10 -0
- package/es/components/ComboBox/ComboBox.d.ts +5 -0
- package/es/components/ComboBox/ComboBox.js +139 -54
- package/es/components/ComboButton/index.js +10 -3
- package/es/components/DataTable/TableCell.d.ts +1 -4
- package/es/components/DataTable/TableCell.js +3 -2
- package/es/components/DatePicker/DatePicker.js +10 -6
- package/es/components/Disclosure/index.d.ts +18 -0
- package/es/components/Dropdown/Dropdown.js +11 -9
- package/es/components/FileUploader/FileUploader.d.ts +8 -92
- package/es/components/FileUploader/FileUploader.js +116 -137
- package/es/components/FileUploader/FileUploaderDropContainer.js +1 -1
- package/es/components/FluidComboBox/FluidComboBox.Skeleton.d.ts +15 -0
- package/es/components/FluidComboBox/FluidComboBox.Skeleton.js +1 -2
- package/es/components/FluidComboBox/FluidComboBox.d.ts +102 -0
- package/es/components/FluidComboBox/FluidComboBox.js +2 -3
- package/es/components/FluidComboBox/index.d.ts +13 -0
- package/es/components/FluidDatePicker/FluidDatePicker.Skeleton.d.ts +19 -0
- package/es/components/FluidDatePicker/FluidDatePicker.Skeleton.js +2 -2
- package/es/components/FluidDatePicker/FluidDatePicker.d.ts +39 -0
- package/es/components/FluidDatePicker/FluidDatePicker.js +2 -3
- package/es/components/FluidDatePicker/index.d.ts +13 -0
- package/es/components/FluidDatePickerInput/FluidDatePickerInput.d.ts +10 -0
- package/es/components/FluidDatePickerInput/FluidDatePickerInput.js +1 -2
- package/es/components/FluidDatePickerInput/index.d.ts +9 -0
- package/es/components/IdPrefix/index.d.ts +26 -0
- package/es/components/Menu/MenuItem.js +1 -4
- package/es/components/MenuButton/index.d.ts +4 -0
- package/es/components/MenuButton/index.js +19 -5
- package/es/components/MultiSelect/MultiSelect.js +11 -9
- package/es/components/OverflowMenu/next/index.d.ts +4 -0
- package/es/components/OverflowMenu/next/index.js +19 -9
- package/es/components/PaginationNav/PaginationNav.js +1 -1
- package/es/components/Popover/index.js +18 -14
- package/es/components/Portal/index.d.ts +25 -0
- package/es/components/Slider/Slider.js +2 -2
- package/es/components/Tabs/usePressable.js +2 -0
- package/es/components/Tag/DismissibleTag.js +2 -2
- package/es/components/Tag/OperationalTag.d.ts +2 -10
- package/es/components/Tag/OperationalTag.js +2 -14
- package/es/components/Tag/SelectableTag.d.ts +2 -10
- package/es/components/Tag/SelectableTag.js +2 -16
- package/es/components/Toggle/Toggle.js +2 -0
- package/es/components/ToggleSmall/ToggleSmall.Skeleton.d.ts +49 -0
- package/es/components/ToggleSmall/index.d.ts +7 -0
- package/es/components/TreeView/TreeNode.js +4 -2
- package/es/components/TreeView/TreeView.js +4 -4
- package/es/components/UIShell/SideNavMenuItem.d.ts +4 -3
- package/es/components/UIShell/SideNavMenuItem.js +1 -4
- package/es/index.js +6 -6
- package/es/internal/useIdPrefix.d.ts +9 -0
- package/lib/components/Accordion/AccordionItem.js +0 -1
- package/lib/components/Button/Button.js +6 -0
- package/lib/components/CheckboxGroup/CheckboxGroup.js +1 -2
- package/lib/components/CheckboxGroup/index.d.ts +10 -0
- package/lib/components/ComboBox/ComboBox.d.ts +5 -0
- package/lib/components/ComboBox/ComboBox.js +144 -59
- package/lib/components/ComboButton/index.js +12 -5
- package/lib/components/DataTable/TableCell.d.ts +1 -4
- package/lib/components/DataTable/TableCell.js +3 -2
- package/lib/components/DatePicker/DatePicker.js +9 -5
- package/lib/components/Disclosure/index.d.ts +18 -0
- package/lib/components/Dropdown/Dropdown.js +18 -16
- package/lib/components/FileUploader/FileUploader.d.ts +8 -92
- package/lib/components/FileUploader/FileUploader.js +113 -134
- package/lib/components/FileUploader/FileUploaderDropContainer.js +1 -1
- package/lib/components/FluidComboBox/FluidComboBox.Skeleton.d.ts +15 -0
- package/lib/components/FluidComboBox/FluidComboBox.Skeleton.js +1 -2
- package/lib/components/FluidComboBox/FluidComboBox.d.ts +102 -0
- package/lib/components/FluidComboBox/FluidComboBox.js +2 -3
- package/lib/components/FluidComboBox/index.d.ts +13 -0
- package/lib/components/FluidDatePicker/FluidDatePicker.Skeleton.d.ts +19 -0
- package/lib/components/FluidDatePicker/FluidDatePicker.Skeleton.js +2 -2
- package/lib/components/FluidDatePicker/FluidDatePicker.d.ts +39 -0
- package/lib/components/FluidDatePicker/FluidDatePicker.js +3 -4
- package/lib/components/FluidDatePicker/index.d.ts +13 -0
- package/lib/components/FluidDatePickerInput/FluidDatePickerInput.d.ts +10 -0
- package/lib/components/FluidDatePickerInput/FluidDatePickerInput.js +1 -2
- package/lib/components/FluidDatePickerInput/index.d.ts +9 -0
- package/lib/components/IdPrefix/index.d.ts +26 -0
- package/lib/components/Menu/MenuItem.js +1 -4
- package/lib/components/MenuButton/index.d.ts +4 -0
- package/lib/components/MenuButton/index.js +19 -5
- package/lib/components/MultiSelect/MultiSelect.js +18 -16
- package/lib/components/OverflowMenu/next/index.d.ts +4 -0
- package/lib/components/OverflowMenu/next/index.js +21 -11
- package/lib/components/PaginationNav/PaginationNav.js +1 -1
- package/lib/components/Popover/index.js +18 -14
- package/lib/components/Portal/index.d.ts +25 -0
- package/lib/components/Slider/Slider.js +2 -2
- package/lib/components/Tabs/usePressable.js +2 -0
- package/lib/components/Tag/DismissibleTag.js +2 -2
- package/lib/components/Tag/OperationalTag.d.ts +2 -10
- package/lib/components/Tag/OperationalTag.js +2 -14
- package/lib/components/Tag/SelectableTag.d.ts +2 -10
- package/lib/components/Tag/SelectableTag.js +2 -16
- package/lib/components/Toggle/Toggle.js +2 -0
- package/lib/components/ToggleSmall/ToggleSmall.Skeleton.d.ts +49 -0
- package/lib/components/ToggleSmall/index.d.ts +7 -0
- package/lib/components/TreeView/TreeNode.js +4 -2
- package/lib/components/TreeView/TreeView.js +4 -4
- package/lib/components/UIShell/SideNavMenuItem.d.ts +4 -3
- package/lib/components/UIShell/SideNavMenuItem.js +1 -4
- package/lib/index.js +12 -12
- package/lib/internal/useIdPrefix.d.ts +9 -0
- package/package.json +7 -7
- package/telemetry.yml +809 -809
package/README.md
CHANGED
|
@@ -135,9 +135,9 @@ Licensed under the [Apache 2.0 License](/LICENSE).
|
|
|
135
135
|
|
|
136
136
|
## <picture><source height="20" width="20" media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/ibm-telemetry/telemetry-js/main/docs/images/ibm-telemetry-dark.svg"><source height="20" width="20" media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/ibm-telemetry/telemetry-js/main/docs/images/ibm-telemetry-light.svg"><img height="20" width="20" alt="IBM Telemetry" src="https://raw.githubusercontent.com/ibm-telemetry/telemetry-js/main/docs/images/ibm-telemetry-light.svg"></picture> IBM Telemetry
|
|
137
137
|
|
|
138
|
-
This package uses IBM Telemetry to collect
|
|
139
|
-
package as a dependency you are agreeing to telemetry
|
|
140
|
-
see
|
|
138
|
+
This package uses IBM Telemetry to collect de-identified and anonymized metrics
|
|
139
|
+
data. By installing this package as a dependency you are agreeing to telemetry
|
|
140
|
+
collection. To opt out, see
|
|
141
141
|
[Opting out of IBM Telemetry data collection](https://github.com/ibm-telemetry/telemetry-js/tree/main#opting-out-of-ibm-telemetry-data-collection).
|
|
142
142
|
For more information on the data being collected, please see the
|
|
143
143
|
[IBM Telemetry documentation](https://github.com/ibm-telemetry/telemetry-js/tree/main#ibm-telemetry-collection-basics).
|
|
@@ -108,7 +108,6 @@ function AccordionItem(_ref) {
|
|
|
108
108
|
className: `${prefix}--accordion__title`
|
|
109
109
|
}, title)), /*#__PURE__*/React__default.createElement("div", {
|
|
110
110
|
ref: content,
|
|
111
|
-
hidden: !isOpen,
|
|
112
111
|
className: `${prefix}--accordion__wrapper`,
|
|
113
112
|
onTransitionEnd: onAnimationEnd
|
|
114
113
|
}, /*#__PURE__*/React__default.createElement("div", {
|
|
@@ -26,6 +26,7 @@ const Button = /*#__PURE__*/React__default.forwardRef(function Button(props, ref
|
|
|
26
26
|
const tooltipRef = useRef(null);
|
|
27
27
|
const {
|
|
28
28
|
as,
|
|
29
|
+
autoAlign = false,
|
|
29
30
|
children,
|
|
30
31
|
hasIconOnly = false,
|
|
31
32
|
iconDescription,
|
|
@@ -84,6 +85,7 @@ const Button = /*#__PURE__*/React__default.forwardRef(function Button(props, ref
|
|
|
84
85
|
onMouseLeave: onMouseLeave,
|
|
85
86
|
onFocus: onFocus,
|
|
86
87
|
onBlur: onBlur,
|
|
88
|
+
autoAlign: autoAlign,
|
|
87
89
|
onClick: composeEventHandlers([onClick, handleClick]),
|
|
88
90
|
renderIcon: iconOnlyImage ? null : ButtonImageElement // avoid doubling the icon.
|
|
89
91
|
}), iconOnlyImage ?? children);
|
|
@@ -96,6 +98,10 @@ Button.propTypes = {
|
|
|
96
98
|
* Make sure to apply all props to the root node and render children appropriately
|
|
97
99
|
*/
|
|
98
100
|
as: PropTypes.oneOfType([PropTypes.func, PropTypes.string, PropTypes.elementType]),
|
|
101
|
+
/**
|
|
102
|
+
* **Experimental**: Will attempt to automatically align the tooltip
|
|
103
|
+
*/
|
|
104
|
+
autoAlign: PropTypes.bool,
|
|
99
105
|
/**
|
|
100
106
|
* Specify the content of your Button
|
|
101
107
|
*/
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright IBM Corp. 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 CheckboxGroup from './CheckboxGroup';
|
|
8
|
+
import { type CheckboxGroupProps, type CustomType } from './CheckboxGroup';
|
|
9
|
+
export default CheckboxGroup;
|
|
10
|
+
export { CheckboxGroup, type CheckboxGroupProps, type CustomType };
|
|
@@ -158,6 +158,7 @@ export interface ComboBoxProps<ItemType> extends Omit<InputHTMLAttributes<HTMLIn
|
|
|
158
158
|
* Specify your own filtering logic by passing in a `shouldFilterItem`
|
|
159
159
|
* function that takes in the current input and an item and passes back
|
|
160
160
|
* whether or not the item should be filtered.
|
|
161
|
+
* this prop will be ignored if `typeahead` prop is enabled
|
|
161
162
|
*/
|
|
162
163
|
shouldFilterItem?: (input: {
|
|
163
164
|
item: ItemType;
|
|
@@ -177,6 +178,10 @@ export interface ComboBoxProps<ItemType> extends Omit<InputHTMLAttributes<HTMLIn
|
|
|
177
178
|
* combobox via ARIA attributes.
|
|
178
179
|
*/
|
|
179
180
|
titleText?: ReactNode;
|
|
181
|
+
/**
|
|
182
|
+
* **Experimental**: will enable autcomplete and typeahead for the input field
|
|
183
|
+
*/
|
|
184
|
+
typeahead?: boolean;
|
|
180
185
|
/**
|
|
181
186
|
* Specify whether the control is currently in warning state
|
|
182
187
|
*/
|
|
@@ -9,7 +9,7 @@ import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js
|
|
|
9
9
|
import cx from 'classnames';
|
|
10
10
|
import { useCombobox } from 'downshift';
|
|
11
11
|
import PropTypes from 'prop-types';
|
|
12
|
-
import React__default, { forwardRef, useEffect,
|
|
12
|
+
import React__default, { forwardRef, useRef, useEffect, useState, useContext, useCallback, useMemo } from 'react';
|
|
13
13
|
import '../Text/index.js';
|
|
14
14
|
import { WarningFilled, WarningAltFilled, Checkmark } from '@carbon/icons-react';
|
|
15
15
|
import ListBox from '../ListBox/index.js';
|
|
@@ -23,6 +23,7 @@ import '../FluidForm/FluidForm.js';
|
|
|
23
23
|
import { FormContext } from '../FluidForm/FormContext.js';
|
|
24
24
|
import { useFloating, flip, autoUpdate } from '@floating-ui/react';
|
|
25
25
|
import { hide } from '../../node_modules/@floating-ui/dom/dist/floating-ui.dom.mjs.js';
|
|
26
|
+
import { useFeatureFlag } from '../FeatureFlags/index.js';
|
|
26
27
|
import { Text } from '../Text/Text.js';
|
|
27
28
|
import { match } from '../../internal/keyboard/match.js';
|
|
28
29
|
import { ListBoxSize } from '../ListBox/ListBoxPropTypes.js';
|
|
@@ -36,8 +37,7 @@ const {
|
|
|
36
37
|
ItemMouseMove,
|
|
37
38
|
InputKeyDownArrowUp,
|
|
38
39
|
InputKeyDownArrowDown,
|
|
39
|
-
MenuMouseLeave
|
|
40
|
-
FunctionSelectItem
|
|
40
|
+
MenuMouseLeave
|
|
41
41
|
} = useCombobox.stateChangeTypes;
|
|
42
42
|
const defaultItemToString = item => {
|
|
43
43
|
if (typeof item === 'string') {
|
|
@@ -52,26 +52,42 @@ const defaultItemToString = item => {
|
|
|
52
52
|
return '';
|
|
53
53
|
};
|
|
54
54
|
const defaultShouldFilterItem = () => true;
|
|
55
|
-
const
|
|
55
|
+
const autocompleteCustomFilter = _ref => {
|
|
56
|
+
let {
|
|
57
|
+
item,
|
|
58
|
+
inputValue
|
|
59
|
+
} = _ref;
|
|
60
|
+
if (inputValue === null || inputValue === '') {
|
|
61
|
+
return true; // Show all items if there's no input
|
|
62
|
+
}
|
|
63
|
+
const lowercaseItem = item.toLowerCase();
|
|
64
|
+
const lowercaseInput = inputValue.toLowerCase();
|
|
65
|
+
return lowercaseItem.startsWith(lowercaseInput);
|
|
66
|
+
};
|
|
67
|
+
const getInputValue = _ref2 => {
|
|
56
68
|
let {
|
|
57
69
|
initialSelectedItem,
|
|
58
70
|
inputValue,
|
|
59
71
|
itemToString,
|
|
60
|
-
selectedItem
|
|
61
|
-
|
|
72
|
+
selectedItem,
|
|
73
|
+
prevSelectedItem
|
|
74
|
+
} = _ref2;
|
|
62
75
|
if (selectedItem) {
|
|
63
76
|
return itemToString(selectedItem);
|
|
64
77
|
}
|
|
65
78
|
if (initialSelectedItem) {
|
|
66
79
|
return itemToString(initialSelectedItem);
|
|
67
80
|
}
|
|
81
|
+
if (!selectedItem && prevSelectedItem) {
|
|
82
|
+
return '';
|
|
83
|
+
}
|
|
68
84
|
return inputValue || '';
|
|
69
85
|
};
|
|
70
|
-
const findHighlightedIndex = (
|
|
86
|
+
const findHighlightedIndex = (_ref3, inputValue) => {
|
|
71
87
|
let {
|
|
72
88
|
items,
|
|
73
89
|
itemToString = defaultItemToString
|
|
74
|
-
} =
|
|
90
|
+
} = _ref3;
|
|
75
91
|
if (!inputValue) {
|
|
76
92
|
return -1;
|
|
77
93
|
}
|
|
@@ -94,6 +110,8 @@ const findHighlightedIndex = (_ref2, inputValue) => {
|
|
|
94
110
|
*/
|
|
95
111
|
|
|
96
112
|
const ComboBox = /*#__PURE__*/forwardRef((props, ref) => {
|
|
113
|
+
const prevInputLengthRef = useRef(0);
|
|
114
|
+
const inputRef = useRef(null);
|
|
97
115
|
const {
|
|
98
116
|
['aria-label']: ariaLabel = 'Choose an item',
|
|
99
117
|
ariaLabel: deprecatedAriaLabel,
|
|
@@ -122,25 +140,27 @@ const ComboBox = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
122
140
|
size,
|
|
123
141
|
titleText,
|
|
124
142
|
translateWithId,
|
|
143
|
+
typeahead = false,
|
|
125
144
|
warn,
|
|
126
145
|
warnText,
|
|
127
146
|
allowCustomValue = false,
|
|
128
147
|
slug,
|
|
129
148
|
...rest
|
|
130
149
|
} = props;
|
|
150
|
+
const enableFloatingStyles = useFeatureFlag('enable-v12-dynamic-floating-styles') || autoAlign;
|
|
131
151
|
const {
|
|
132
152
|
refs,
|
|
133
153
|
floatingStyles,
|
|
134
154
|
middlewareData
|
|
135
|
-
} = useFloating(
|
|
155
|
+
} = useFloating(enableFloatingStyles ? {
|
|
136
156
|
placement: direction,
|
|
137
157
|
strategy: 'fixed',
|
|
138
|
-
middleware: [flip(), hide()],
|
|
158
|
+
middleware: autoAlign ? [flip(), hide()] : undefined,
|
|
139
159
|
whileElementsMounted: autoUpdate
|
|
140
160
|
} : {});
|
|
141
161
|
const parentWidth = refs?.reference?.current?.clientWidth;
|
|
142
162
|
useEffect(() => {
|
|
143
|
-
if (
|
|
163
|
+
if (enableFloatingStyles) {
|
|
144
164
|
const updatedFloatingStyles = {
|
|
145
165
|
...floatingStyles,
|
|
146
166
|
visibility: middlewareData.hide?.referenceHidden ? 'hidden' : 'visible'
|
|
@@ -154,34 +174,69 @@ const ComboBox = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
154
174
|
refs.floating.current.style.width = parentWidth + 'px';
|
|
155
175
|
}
|
|
156
176
|
}
|
|
157
|
-
}, [
|
|
158
|
-
const prefix = usePrefix();
|
|
159
|
-
const {
|
|
160
|
-
isFluid
|
|
161
|
-
} = useContext(FormContext);
|
|
162
|
-
const textInput = useRef(null);
|
|
163
|
-
const comboBoxInstanceId = useId();
|
|
177
|
+
}, [enableFloatingStyles, floatingStyles, refs.floating, parentWidth]);
|
|
164
178
|
const [inputValue, setInputValue] = useState(getInputValue({
|
|
165
179
|
initialSelectedItem,
|
|
166
180
|
inputValue: '',
|
|
167
181
|
itemToString,
|
|
168
182
|
selectedItem: selectedItemProp
|
|
169
183
|
}));
|
|
184
|
+
const [typeaheadText, setTypeaheadText] = useState('');
|
|
185
|
+
useEffect(() => {
|
|
186
|
+
if (typeahead) {
|
|
187
|
+
if (inputValue.length >= prevInputLengthRef.current) {
|
|
188
|
+
if (inputValue) {
|
|
189
|
+
const filteredItems = items.filter(item => autocompleteCustomFilter({
|
|
190
|
+
item: itemToString(item),
|
|
191
|
+
inputValue: inputValue
|
|
192
|
+
}));
|
|
193
|
+
if (filteredItems.length > 0) {
|
|
194
|
+
const suggestion = itemToString(filteredItems[0]);
|
|
195
|
+
setTypeaheadText(suggestion.slice(inputValue.length));
|
|
196
|
+
} else {
|
|
197
|
+
setTypeaheadText('');
|
|
198
|
+
}
|
|
199
|
+
} else {
|
|
200
|
+
setTypeaheadText('');
|
|
201
|
+
}
|
|
202
|
+
} else {
|
|
203
|
+
setTypeaheadText('');
|
|
204
|
+
}
|
|
205
|
+
prevInputLengthRef.current = inputValue.length;
|
|
206
|
+
}
|
|
207
|
+
}, [typeahead, inputValue, items, itemToString, autocompleteCustomFilter]);
|
|
208
|
+
const prefix = usePrefix();
|
|
209
|
+
const {
|
|
210
|
+
isFluid
|
|
211
|
+
} = useContext(FormContext);
|
|
212
|
+
const textInput = useRef(null);
|
|
213
|
+
const comboBoxInstanceId = useId();
|
|
170
214
|
const [isFocused, setIsFocused] = useState(false);
|
|
171
|
-
const [prevSelectedItem, setPrevSelectedItem] = useState();
|
|
172
|
-
const [doneInitialSelectedItem, setDoneInitialSelectedItem] = useState(false);
|
|
173
215
|
const savedOnInputChange = useRef(onInputChange);
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
216
|
+
const prevSelectedItemProp = useRef(selectedItemProp);
|
|
217
|
+
|
|
218
|
+
// fully controlled combobox: handle changes to selectedItemProp
|
|
219
|
+
useEffect(() => {
|
|
220
|
+
if (prevSelectedItemProp.current !== selectedItemProp) {
|
|
221
|
+
const currentInputValue = getInputValue({
|
|
222
|
+
initialSelectedItem,
|
|
223
|
+
inputValue,
|
|
224
|
+
itemToString,
|
|
225
|
+
selectedItem: selectedItemProp,
|
|
226
|
+
prevSelectedItem: prevSelectedItemProp.current
|
|
227
|
+
});
|
|
228
|
+
setInputValue(currentInputValue);
|
|
229
|
+
onChange({
|
|
230
|
+
selectedItem: selectedItemProp,
|
|
231
|
+
inputValue: currentInputValue
|
|
232
|
+
});
|
|
233
|
+
prevSelectedItemProp.current = selectedItemProp;
|
|
234
|
+
}
|
|
235
|
+
}, [selectedItemProp]);
|
|
236
|
+
const filterItems = (items, itemToString, inputValue) => items.filter(item => typeahead ? autocompleteCustomFilter({
|
|
237
|
+
item: itemToString(item),
|
|
238
|
+
inputValue
|
|
239
|
+
}) : shouldFilterItem ? shouldFilterItem({
|
|
185
240
|
item,
|
|
186
241
|
itemToString,
|
|
187
242
|
inputValue
|
|
@@ -204,7 +259,7 @@ const ComboBox = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
204
259
|
...props,
|
|
205
260
|
items: filteredItems(inputValue)
|
|
206
261
|
}, inputValue);
|
|
207
|
-
const stateReducer =
|
|
262
|
+
const stateReducer = useCallback((state, actionAndChanges) => {
|
|
208
263
|
const {
|
|
209
264
|
type,
|
|
210
265
|
changes
|
|
@@ -240,14 +295,6 @@ const ComboBox = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
240
295
|
}
|
|
241
296
|
return changes;
|
|
242
297
|
}
|
|
243
|
-
case FunctionSelectItem:
|
|
244
|
-
if (onChange) {
|
|
245
|
-
onChange({
|
|
246
|
-
selectedItem: changes.selectedItem,
|
|
247
|
-
inputValue: changes.inputValue
|
|
248
|
-
});
|
|
249
|
-
}
|
|
250
|
-
return changes;
|
|
251
298
|
case InputKeyDownEnter:
|
|
252
299
|
if (allowCustomValue) {
|
|
253
300
|
setInputValue(inputValue);
|
|
@@ -321,7 +368,7 @@ const ComboBox = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
321
368
|
[`${prefix}--list-box--up`]: direction === 'top',
|
|
322
369
|
[`${prefix}--combo-box--warning`]: showWarning,
|
|
323
370
|
[`${prefix}--combo-box--readonly`]: readOnly,
|
|
324
|
-
[`${prefix}--autoalign`]:
|
|
371
|
+
[`${prefix}--autoalign`]: enableFloatingStyles
|
|
325
372
|
});
|
|
326
373
|
const titleClasses = cx(`${prefix}--label`, {
|
|
327
374
|
[`${prefix}--label--disabled`]: disabled
|
|
@@ -377,25 +424,33 @@ const ComboBox = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
377
424
|
itemToString: item => {
|
|
378
425
|
return itemToString(item);
|
|
379
426
|
},
|
|
380
|
-
onInputValueChange(
|
|
427
|
+
onInputValueChange(_ref4) {
|
|
381
428
|
let {
|
|
382
429
|
inputValue
|
|
383
|
-
} =
|
|
384
|
-
|
|
385
|
-
|
|
430
|
+
} = _ref4;
|
|
431
|
+
const normalizedInput = inputValue || '';
|
|
432
|
+
setInputValue(normalizedInput);
|
|
433
|
+
if (selectedItemProp && !inputValue) {
|
|
434
|
+
// ensure onChange is called when selectedItem is cleared
|
|
435
|
+
onChange({
|
|
436
|
+
selectedItem,
|
|
437
|
+
inputValue: normalizedInput
|
|
438
|
+
});
|
|
439
|
+
}
|
|
440
|
+
setHighlightedIndex(indexToHighlight(normalizedInput));
|
|
386
441
|
},
|
|
387
|
-
onSelectedItemChange(
|
|
442
|
+
onSelectedItemChange(_ref5) {
|
|
388
443
|
let {
|
|
389
444
|
selectedItem
|
|
390
|
-
} =
|
|
445
|
+
} = _ref5;
|
|
391
446
|
onChange({
|
|
392
447
|
selectedItem
|
|
393
448
|
});
|
|
394
449
|
},
|
|
395
|
-
onHighlightedIndexChange:
|
|
450
|
+
onHighlightedIndexChange: _ref6 => {
|
|
396
451
|
let {
|
|
397
452
|
highlightedIndex
|
|
398
|
-
} =
|
|
453
|
+
} = _ref6;
|
|
399
454
|
if (highlightedIndex > -1 && typeof window !== undefined) {
|
|
400
455
|
const itemArray = document.querySelectorAll(`li.${prefix}--list-box__menu-item[role="option"]`);
|
|
401
456
|
const highlightedItem = itemArray[highlightedIndex];
|
|
@@ -474,9 +529,18 @@ const ComboBox = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
474
529
|
|
|
475
530
|
// Memoize the value of getMenuProps to avoid an infinite loop
|
|
476
531
|
const menuProps = useMemo(() => getMenuProps({
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
532
|
+
ref: enableFloatingStyles ? refs.setFloating : null
|
|
533
|
+
}), [enableFloatingStyles, deprecatedAriaLabel, ariaLabel, getMenuProps, refs.setFloating]);
|
|
534
|
+
useEffect(() => {
|
|
535
|
+
if (textInput.current) {
|
|
536
|
+
if (inputRef.current && typeaheadText) {
|
|
537
|
+
const selectionStart = inputValue.length;
|
|
538
|
+
const selectionEnd = selectionStart + typeaheadText.length;
|
|
539
|
+
inputRef.current.value = inputValue + typeaheadText;
|
|
540
|
+
inputRef.current.setSelectionRange(selectionStart, selectionEnd);
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
}, [inputValue, typeaheadText]);
|
|
480
544
|
return /*#__PURE__*/React__default.createElement("div", {
|
|
481
545
|
className: wrapperClasses
|
|
482
546
|
}, titleText && /*#__PURE__*/React__default.createElement(Text, _extends({
|
|
@@ -494,7 +558,7 @@ const ComboBox = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
494
558
|
light: light,
|
|
495
559
|
size: size,
|
|
496
560
|
warn: warn,
|
|
497
|
-
ref:
|
|
561
|
+
ref: enableFloatingStyles ? refs.setReference : null,
|
|
498
562
|
warnText: warnText,
|
|
499
563
|
warnTextId: warnTextId
|
|
500
564
|
}, /*#__PURE__*/React__default.createElement("div", {
|
|
@@ -507,9 +571,16 @@ const ComboBox = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
507
571
|
"aria-haspopup": "listbox",
|
|
508
572
|
title: textInput?.current?.value
|
|
509
573
|
}, getInputProps({
|
|
574
|
+
'aria-label': titleText ? undefined : deprecatedAriaLabel || ariaLabel,
|
|
510
575
|
'aria-controls': isOpen ? undefined : menuProps.id,
|
|
511
576
|
placeholder,
|
|
512
|
-
|
|
577
|
+
value: inputValue,
|
|
578
|
+
onChange: e => {
|
|
579
|
+
const newValue = e.target.value;
|
|
580
|
+
setInputValue(newValue);
|
|
581
|
+
downshiftSetInputValue(newValue);
|
|
582
|
+
},
|
|
583
|
+
ref: mergeRefs(textInput, ref, inputRef),
|
|
513
584
|
onKeyDown: event => {
|
|
514
585
|
if (match(event, Space)) {
|
|
515
586
|
event.stopPropagation();
|
|
@@ -557,6 +628,15 @@ const ComboBox = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
557
628
|
toggleMenu();
|
|
558
629
|
}
|
|
559
630
|
}
|
|
631
|
+
if (typeahead && event.key === 'Tab') {
|
|
632
|
+
// event.preventDefault();
|
|
633
|
+
const matchingItem = items.find(item => itemToString(item).toLowerCase().startsWith(inputValue.toLowerCase()));
|
|
634
|
+
if (matchingItem) {
|
|
635
|
+
const newValue = itemToString(matchingItem);
|
|
636
|
+
downshiftSetInputValue(newValue);
|
|
637
|
+
selectItem(matchingItem);
|
|
638
|
+
}
|
|
639
|
+
}
|
|
560
640
|
}
|
|
561
641
|
}), rest, readOnlyEventHandlers, {
|
|
562
642
|
readOnly: readOnly,
|
|
@@ -749,6 +829,7 @@ ComboBox.propTypes = {
|
|
|
749
829
|
* Specify your own filtering logic by passing in a `shouldFilterItem`
|
|
750
830
|
* function that takes in the current input and an item and passes back
|
|
751
831
|
* whether or not the item should be filtered.
|
|
832
|
+
* this prop will be ignored if `typeahead` prop is enabled
|
|
752
833
|
*/
|
|
753
834
|
shouldFilterItem: PropTypes.func,
|
|
754
835
|
/**
|
|
@@ -769,6 +850,10 @@ ComboBox.propTypes = {
|
|
|
769
850
|
* and returns the localized string for the message
|
|
770
851
|
*/
|
|
771
852
|
translateWithId: PropTypes.func,
|
|
853
|
+
/**
|
|
854
|
+
* **Experimental**: will enable autcomplete and typeahead for the input field
|
|
855
|
+
*/
|
|
856
|
+
typeahead: PropTypes.bool,
|
|
772
857
|
/**
|
|
773
858
|
* Specify whether the control is currently in warning state
|
|
774
859
|
*/
|
|
@@ -20,6 +20,7 @@ import { useId } from '../../internal/useId.js';
|
|
|
20
20
|
import { usePrefix } from '../../internal/usePrefix.js';
|
|
21
21
|
import { flip, size, useFloating, autoUpdate } from '@floating-ui/react';
|
|
22
22
|
import { hide } from '../../node_modules/@floating-ui/dom/dist/floating-ui.dom.mjs.js';
|
|
23
|
+
import { useFeatureFlag } from '../FeatureFlags/index.js';
|
|
23
24
|
import mergeRefs from '../../tools/mergeRefs.js';
|
|
24
25
|
|
|
25
26
|
var _ChevronDown;
|
|
@@ -47,12 +48,18 @@ const ComboButton = /*#__PURE__*/React__default.forwardRef(function ComboButton(
|
|
|
47
48
|
translateWithId: t = defaultTranslateWithId,
|
|
48
49
|
...rest
|
|
49
50
|
} = _ref;
|
|
51
|
+
// feature flag utilized to separate out only the dynamic styles from @floating-ui
|
|
52
|
+
// flag is turned on when collision detection (ie. flip, hide) logic is not desired
|
|
53
|
+
const enableOnlyFloatingStyles = useFeatureFlag('enable-v12-dynamic-floating-styles');
|
|
50
54
|
const id = useId('combobutton');
|
|
51
55
|
const prefix = usePrefix();
|
|
52
56
|
const containerRef = useRef(null);
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
57
|
+
let middlewares = [];
|
|
58
|
+
if (!enableOnlyFloatingStyles) {
|
|
59
|
+
middlewares = [flip({
|
|
60
|
+
crossAxis: false
|
|
61
|
+
}), hide()];
|
|
62
|
+
}
|
|
56
63
|
if (menuAlignment === 'bottom' || menuAlignment === 'top') {
|
|
57
64
|
middlewares.push(size({
|
|
58
65
|
apply(_ref2) {
|
|
@@ -28,8 +28,5 @@ interface TableCellProps extends ReactAttr<HTMLTableCellElement> {
|
|
|
28
28
|
*/
|
|
29
29
|
headers?: string;
|
|
30
30
|
}
|
|
31
|
-
declare const TableCell:
|
|
32
|
-
({ children, className, hasSlugHeader, colSpan, ...rest }: TableCellProps): import("react/jsx-runtime").JSX.Element;
|
|
33
|
-
displayName: string;
|
|
34
|
-
};
|
|
31
|
+
declare const TableCell: React.ForwardRefExoticComponent<TableCellProps & React.RefAttributes<HTMLTableCellElement>>;
|
|
35
32
|
export default TableCell;
|
|
@@ -10,7 +10,7 @@ import React__default from 'react';
|
|
|
10
10
|
import cx from 'classnames';
|
|
11
11
|
import { usePrefix } from '../../internal/usePrefix.js';
|
|
12
12
|
|
|
13
|
-
const TableCell = _ref => {
|
|
13
|
+
const TableCell = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
|
|
14
14
|
let {
|
|
15
15
|
children,
|
|
16
16
|
className,
|
|
@@ -24,9 +24,10 @@ const TableCell = _ref => {
|
|
|
24
24
|
});
|
|
25
25
|
return /*#__PURE__*/React__default.createElement("td", _extends({
|
|
26
26
|
className: tableCellClassNames ? tableCellClassNames : undefined,
|
|
27
|
+
ref: ref,
|
|
27
28
|
colSpan: colSpan
|
|
28
29
|
}, rest), children);
|
|
29
|
-
};
|
|
30
|
+
});
|
|
30
31
|
TableCell.displayName = 'TableCell';
|
|
31
32
|
|
|
32
33
|
export { TableCell as default };
|
|
@@ -22,7 +22,7 @@ import '../FluidForm/FluidForm.js';
|
|
|
22
22
|
import { FormContext } from '../FluidForm/FormContext.js';
|
|
23
23
|
import { WarningFilled, WarningAltFilled } from '@carbon/icons-react';
|
|
24
24
|
import { match } from '../../internal/keyboard/match.js';
|
|
25
|
-
import { Escape, ArrowDown, Tab } from '../../internal/keyboard/keys.js';
|
|
25
|
+
import { Escape, ArrowDown, Enter, Tab } from '../../internal/keyboard/keys.js';
|
|
26
26
|
|
|
27
27
|
// Weekdays shorthand for english locale
|
|
28
28
|
l10n.en.weekdays.shorthand.forEach((_day, index) => {
|
|
@@ -391,9 +391,6 @@ const DatePicker = /*#__PURE__*/React__default.forwardRef(function DatePicker(_r
|
|
|
391
391
|
}
|
|
392
392
|
}
|
|
393
393
|
function handleOnChange(event) {
|
|
394
|
-
if (datePickerType == 'single' && closeOnSelect) {
|
|
395
|
-
calendar.calendarContainer.classList.remove('open');
|
|
396
|
-
}
|
|
397
394
|
const {
|
|
398
395
|
target
|
|
399
396
|
} = event;
|
|
@@ -409,12 +406,16 @@ const DatePicker = /*#__PURE__*/React__default.forwardRef(function DatePicker(_r
|
|
|
409
406
|
if (calendar.selectedDates.length === 0) {
|
|
410
407
|
return;
|
|
411
408
|
}
|
|
412
|
-
|
|
413
|
-
|
|
409
|
+
}
|
|
410
|
+
function handleKeyPress(event) {
|
|
411
|
+
if (match(event, Enter) && closeOnSelect && datePickerType == 'single') {
|
|
412
|
+
calendar.calendarContainer.classList.remove('open');
|
|
413
|
+
}
|
|
414
414
|
}
|
|
415
415
|
if (start) {
|
|
416
416
|
start.addEventListener('keydown', handleArrowDown);
|
|
417
417
|
start.addEventListener('change', handleOnChange);
|
|
418
|
+
start.addEventListener('keypress', handleKeyPress);
|
|
418
419
|
if (calendar && calendar.calendarContainer) {
|
|
419
420
|
// Flatpickr's calendar dialog is not rendered in a landmark causing an
|
|
420
421
|
// error with IBM Equal Access Accessibility Checker so we add an aria
|
|
@@ -427,6 +428,7 @@ const DatePicker = /*#__PURE__*/React__default.forwardRef(function DatePicker(_r
|
|
|
427
428
|
if (end) {
|
|
428
429
|
end.addEventListener('keydown', handleArrowDown);
|
|
429
430
|
end.addEventListener('change', handleOnChange);
|
|
431
|
+
end.addEventListener('keypress', handleKeyPress);
|
|
430
432
|
}
|
|
431
433
|
|
|
432
434
|
//component did unmount equivalent
|
|
@@ -450,10 +452,12 @@ const DatePicker = /*#__PURE__*/React__default.forwardRef(function DatePicker(_r
|
|
|
450
452
|
if (start) {
|
|
451
453
|
start.removeEventListener('keydown', handleArrowDown);
|
|
452
454
|
start.removeEventListener('change', handleOnChange);
|
|
455
|
+
start.removeEventListener('keypress', handleKeyPress);
|
|
453
456
|
}
|
|
454
457
|
if (end) {
|
|
455
458
|
end.removeEventListener('keydown', handleArrowDown);
|
|
456
459
|
end.removeEventListener('change', handleOnChange);
|
|
460
|
+
end.removeEventListener('change', handleKeyPress);
|
|
457
461
|
}
|
|
458
462
|
};
|
|
459
463
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
@@ -0,0 +1,18 @@
|
|
|
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
|
+
declare function useDisclosure(id: any): {
|
|
8
|
+
buttonProps: {
|
|
9
|
+
'aria-controls': any;
|
|
10
|
+
'aria-expanded': boolean;
|
|
11
|
+
onClick(): void;
|
|
12
|
+
};
|
|
13
|
+
contentProps: {
|
|
14
|
+
id: any;
|
|
15
|
+
};
|
|
16
|
+
open: boolean;
|
|
17
|
+
};
|
|
18
|
+
export { useDisclosure };
|
|
@@ -20,6 +20,7 @@ import { FormContext } from '../FluidForm/FormContext.js';
|
|
|
20
20
|
import { useId } from '../../internal/useId.js';
|
|
21
21
|
import { useFloating, size, flip, autoUpdate } from '@floating-ui/react';
|
|
22
22
|
import { hide } from '../../node_modules/@floating-ui/dom/dist/floating-ui.dom.mjs.js';
|
|
23
|
+
import { useFeatureFlag } from '../FeatureFlags/index.js';
|
|
23
24
|
import { ListBoxSize, ListBoxType } from '../ListBox/ListBoxPropTypes.js';
|
|
24
25
|
|
|
25
26
|
const {
|
|
@@ -71,11 +72,12 @@ const Dropdown = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
|
|
|
71
72
|
slug,
|
|
72
73
|
...other
|
|
73
74
|
} = _ref;
|
|
75
|
+
const enableFloatingStyles = useFeatureFlag('enable-v12-dynamic-floating-styles');
|
|
74
76
|
const {
|
|
75
77
|
refs,
|
|
76
78
|
floatingStyles,
|
|
77
79
|
middlewareData
|
|
78
|
-
} = useFloating(autoAlign ? {
|
|
80
|
+
} = useFloating(enableFloatingStyles || autoAlign ? {
|
|
79
81
|
placement: direction,
|
|
80
82
|
// The floating element is positioned relative to its nearest
|
|
81
83
|
// containing block (usually the viewport). It will in many cases also
|
|
@@ -93,12 +95,14 @@ const Dropdown = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
|
|
|
93
95
|
width: `${rects.reference.width}px`
|
|
94
96
|
});
|
|
95
97
|
}
|
|
96
|
-
}), flip(), hide()],
|
|
98
|
+
}), autoAlign && flip(), autoAlign && hide()],
|
|
97
99
|
whileElementsMounted: autoUpdate
|
|
98
|
-
} : {}
|
|
100
|
+
} : {}
|
|
101
|
+
// When autoAlign is turned off & the `enable-v12-dynamic-floating-styles` feature flag is not
|
|
102
|
+
// enabled, floating-ui will not be used
|
|
99
103
|
);
|
|
100
104
|
useEffect(() => {
|
|
101
|
-
if (autoAlign) {
|
|
105
|
+
if (enableFloatingStyles || autoAlign) {
|
|
102
106
|
const updatedFloatingStyles = {
|
|
103
107
|
...floatingStyles,
|
|
104
108
|
visibility: middlewareData.hide?.referenceHidden ? 'hidden' : 'visible'
|
|
@@ -237,9 +241,7 @@ const Dropdown = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
|
|
|
237
241
|
// NOTE: does not prevent click
|
|
238
242
|
evt.preventDefault();
|
|
239
243
|
// focus on the element as per readonly input behavior
|
|
240
|
-
|
|
241
|
-
mergedRef.current.focus();
|
|
242
|
-
}
|
|
244
|
+
mergedRef?.current?.focus();
|
|
243
245
|
},
|
|
244
246
|
onKeyDown: evt => {
|
|
245
247
|
const selectAccessKeys = ['ArrowDown', 'ArrowUp', ' ', 'Enter'];
|
|
@@ -267,7 +269,7 @@ const Dropdown = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
|
|
|
267
269
|
}
|
|
268
270
|
};
|
|
269
271
|
const menuProps = useMemo(() => getMenuProps({
|
|
270
|
-
ref: autoAlign ? refs.setFloating : null
|
|
272
|
+
ref: enableFloatingStyles || autoAlign ? refs.setFloating : null
|
|
271
273
|
}), [autoAlign, getMenuProps, refs.setFloating]);
|
|
272
274
|
|
|
273
275
|
// Slug is always size `mini`
|
|
@@ -292,7 +294,7 @@ const Dropdown = /*#__PURE__*/React__default.forwardRef((_ref, ref) => {
|
|
|
292
294
|
warnText: warnText,
|
|
293
295
|
light: light,
|
|
294
296
|
isOpen: isOpen,
|
|
295
|
-
ref: autoAlign ? refs.setReference : null,
|
|
297
|
+
ref: enableFloatingStyles || autoAlign ? refs.setReference : null,
|
|
296
298
|
id: id
|
|
297
299
|
}, invalid && /*#__PURE__*/React__default.createElement(WarningFilled, {
|
|
298
300
|
className: `${prefix}--list-box__invalid-icon`
|