@jobber/components 9.6.0 → 9.6.2
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/dist/ActivityIndicator-cjs.js +1 -0
- package/dist/ActivityIndicator-es.js +1 -0
- package/dist/Autocomplete/index.cjs +2 -0
- package/dist/Autocomplete/index.mjs +2 -0
- package/dist/Autocomplete-cjs.js +6 -4
- package/dist/Autocomplete-es.js +3 -1
- package/dist/Banner-cjs.js +1 -0
- package/dist/Banner-es.js +1 -0
- package/dist/Card/index.cjs +2 -1
- package/dist/Card/index.mjs +2 -1
- package/dist/Chip/index.cjs +2 -0
- package/dist/Chip/index.mjs +2 -0
- package/dist/Chip-cjs.js +1 -0
- package/dist/Chip-es.js +1 -0
- package/dist/Chips/InternalChipDismissible/hooks/index.cjs +2 -0
- package/dist/Chips/InternalChipDismissible/hooks/index.mjs +2 -0
- package/dist/Chips/InternalChipDismissible/index.cjs +2 -0
- package/dist/Chips/InternalChipDismissible/index.mjs +2 -0
- package/dist/Chips/index.cjs +2 -0
- package/dist/Chips/index.mjs +2 -0
- package/dist/Combobox/index.cjs +4 -2
- package/dist/Combobox/index.mjs +4 -2
- package/dist/{ComboboxSeparator-cjs.js → ComboboxChipRemove-cjs.js} +455 -501
- package/dist/{ComboboxSeparator-es.js → ComboboxChipRemove-es.js} +456 -500
- package/dist/ComboboxPrimitive-cjs.js +30 -29
- package/dist/ComboboxPrimitive-es.js +3 -2
- package/dist/ConfirmationModal/index.cjs +2 -0
- package/dist/ConfirmationModal/index.mjs +2 -0
- package/dist/ConfirmationModal-cjs.js +1 -0
- package/dist/ConfirmationModal-es.js +1 -0
- package/dist/DataDump/index.cjs +2 -1
- package/dist/DataDump/index.mjs +2 -1
- package/dist/DataDump-cjs.js +1 -0
- package/dist/DataDump-es.js +1 -0
- package/dist/DataList/components/DataListActions/index.cjs +2 -0
- package/dist/DataList/components/DataListActions/index.mjs +2 -0
- package/dist/DataList/components/DataListBulkActions/index.cjs +2 -0
- package/dist/DataList/components/DataListBulkActions/index.mjs +2 -0
- package/dist/DataList/components/DataListFilters/components/DataListSort/index.cjs +2 -0
- package/dist/DataList/components/DataListFilters/components/DataListSort/index.mjs +2 -0
- package/dist/DataList/components/DataListFilters/index.cjs +2 -0
- package/dist/DataList/components/DataListFilters/index.mjs +2 -0
- package/dist/DataList/components/DataListHeader/index.cjs +2 -0
- package/dist/DataList/components/DataListHeader/index.mjs +2 -0
- package/dist/DataList/components/DataListItem/index.cjs +2 -0
- package/dist/DataList/components/DataListItem/index.mjs +2 -0
- package/dist/DataList/components/DataListItemActions/index.cjs +2 -0
- package/dist/DataList/components/DataListItemActions/index.mjs +2 -0
- package/dist/DataList/components/DataListItemActionsOverflow/index.cjs +2 -0
- package/dist/DataList/components/DataListItemActionsOverflow/index.mjs +2 -0
- package/dist/DataList/components/DataListItems/index.cjs +2 -0
- package/dist/DataList/components/DataListItems/index.mjs +2 -0
- package/dist/DataList/components/DataListLayout/index.cjs +2 -0
- package/dist/DataList/components/DataListLayout/index.mjs +2 -0
- package/dist/DataList/components/DataListLayoutActions/index.cjs +2 -0
- package/dist/DataList/components/DataListLayoutActions/index.mjs +2 -0
- package/dist/DataList/index.cjs +2 -0
- package/dist/DataList/index.mjs +2 -0
- package/dist/DataTable-cjs.js +1 -0
- package/dist/DataTable-es.js +1 -0
- package/dist/DatePicker/index.cjs +2 -0
- package/dist/DatePicker/index.mjs +2 -0
- package/dist/DatePicker-cjs.js +8 -7
- package/dist/DatePicker-es.js +6 -5
- package/dist/Dialog/index.cjs +2 -1
- package/dist/Dialog/index.mjs +2 -1
- package/dist/DrawerDescription-cjs.js +99 -268
- package/dist/DrawerDescription-es.js +103 -270
- package/dist/DrawerGrid-cjs.js +1 -0
- package/dist/DrawerGrid-es.js +1 -0
- package/dist/DrawerTitle-cjs.js +6 -2
- package/dist/DrawerTitle-es.js +7 -3
- package/dist/FeatureSwitch-cjs.js +1 -0
- package/dist/FeatureSwitch-es.js +1 -0
- package/dist/FieldDescription-cjs.js +181 -184
- package/dist/FieldDescription-es.js +184 -187
- package/dist/FilterPicker/components/FilterPickerActivator/index.cjs +2 -0
- package/dist/FilterPicker/components/FilterPickerActivator/index.mjs +2 -0
- package/dist/FilterPicker/components/FilterPickerContent/index.cjs +2 -0
- package/dist/FilterPicker/components/FilterPickerContent/index.mjs +2 -0
- package/dist/FilterPicker/components/FilterPickerTrigger/index.cjs +2 -0
- package/dist/FilterPicker/components/FilterPickerTrigger/index.mjs +2 -0
- package/dist/FilterPicker/index.cjs +2 -0
- package/dist/FilterPicker/index.mjs +2 -0
- package/dist/FilterPickerContent-cjs.js +5 -4
- package/dist/FilterPickerContent-es.js +2 -1
- package/dist/FormFieldWrapper-cjs.js +1 -0
- package/dist/FormFieldWrapper-es.js +1 -0
- package/dist/FormatFile/index.cjs +2 -0
- package/dist/FormatFile/index.mjs +2 -0
- package/dist/FormatFile-cjs.js +1 -0
- package/dist/FormatFile-es.js +1 -0
- package/dist/Gallery/index.cjs +2 -0
- package/dist/Gallery/index.mjs +2 -0
- package/dist/InputAvatar-cjs.js +1 -0
- package/dist/InputAvatar-es.js +1 -0
- package/dist/InputDate/index.cjs +2 -0
- package/dist/InputDate/index.mjs +2 -0
- package/dist/InputDate-cjs.js +1 -0
- package/dist/InputDate-es.js +1 -0
- package/dist/InputNumber/index.cjs +2 -1
- package/dist/InputNumber/index.mjs +2 -1
- package/dist/InternalChipDismissible-cjs.js +1 -0
- package/dist/InternalChipDismissible-es.js +1 -0
- package/dist/LightBox/index.cjs +2 -0
- package/dist/LightBox/index.mjs +2 -0
- package/dist/LightBox-cjs.js +1 -0
- package/dist/LightBox-es.js +1 -0
- package/dist/Menu/index.cjs +2 -1
- package/dist/Menu/index.mjs +2 -1
- package/dist/Menu-cjs.js +6 -4
- package/dist/Menu-es.js +3 -1
- package/dist/MenuSubmenuTrigger-cjs.js +164 -206
- package/dist/MenuSubmenuTrigger-es.js +152 -194
- package/dist/Modal/index.cjs +3 -1
- package/dist/Modal/index.mjs +4 -2
- package/dist/NumberFieldInput-cjs.js +308 -187
- package/dist/NumberFieldInput-es.js +308 -187
- package/dist/Page/index.cjs +2 -1
- package/dist/Page/index.mjs +2 -1
- package/dist/Page-cjs.js +1 -0
- package/dist/Page-es.js +1 -0
- package/dist/Popover/index.cjs +2 -0
- package/dist/Popover/index.mjs +2 -0
- package/dist/Popover-cjs.js +9 -7
- package/dist/Popover-es.js +3 -1
- package/dist/ProgressBar-cjs.js +1 -0
- package/dist/ProgressBar-es.js +1 -0
- package/dist/ScrollAreaViewport-cjs.js +1093 -747
- package/dist/ScrollAreaViewport-es.js +1081 -734
- package/dist/Select/index.cjs +2 -1
- package/dist/Select/index.mjs +2 -1
- package/dist/SelectGroupLabel-cjs.js +306 -207
- package/dist/SelectGroupLabel-es.js +302 -203
- package/dist/SideDrawer-cjs.js +1 -0
- package/dist/SideDrawer-es.js +1 -0
- package/dist/Spinner-cjs.js +1 -0
- package/dist/Spinner-es.js +1 -0
- package/dist/Tooltip/index.cjs +2 -0
- package/dist/Tooltip/index.mjs +2 -0
- package/dist/Tooltip-cjs.js +7 -6
- package/dist/Tooltip-es.js +2 -1
- package/dist/dialogReturnFocus-cjs.js +1 -1
- package/dist/dialogReturnFocus-es.js +2 -2
- package/dist/floating-ui.react-cjs.js +192 -2564
- package/dist/floating-ui.react-dom-cjs.js +2103 -0
- package/dist/floating-ui.react-dom-es.js +2072 -0
- package/dist/floating-ui.react-es.js +156 -2519
- package/dist/floating-ui.utils-cjs.js +342 -0
- package/dist/floating-ui.utils-es.js +300 -0
- package/dist/index.cjs +4 -3
- package/dist/index.mjs +4 -3
- package/dist/primitives/BottomSheet/index.cjs +1 -1
- package/dist/primitives/BottomSheet/index.mjs +1 -1
- package/dist/primitives/ComboboxPrimitive/index.cjs +4 -2
- package/dist/primitives/ComboboxPrimitive/index.mjs +4 -2
- package/dist/primitives/SelectPrimitive/index.cjs +2 -0
- package/dist/primitives/SelectPrimitive/index.mjs +2 -0
- package/dist/primitives/index.cjs +3 -2
- package/dist/primitives/index.mjs +3 -2
- package/dist/scrollEdges-cjs.js +11 -1
- package/dist/scrollEdges-es.js +11 -1
- package/dist/sharedHelpers/i18n/index.cjs +1 -0
- package/dist/sharedHelpers/i18n/index.d.ts +1 -0
- package/dist/sharedHelpers/i18n/index.mjs +1 -1
- package/dist/sharedHelpers/i18n/releasedLanguages.d.ts +12 -0
- package/dist/sharedHelpers/i18n/useReleasedLocale.d.ts +6 -0
- package/dist/showToast-cjs.js +1 -1
- package/dist/showToast-es.js +1 -1
- package/dist/testUtils/releasedLanguages.d.ts +16 -0
- package/dist/unstyledPrimitives/index.cjs +478 -720
- package/dist/unstyledPrimitives/index.mjs +421 -663
- package/dist/useAtlantisI18n-cjs.js +44 -11
- package/dist/useAtlantisI18n-es.js +44 -12
- package/dist/useCompositeListItem-cjs.js +361 -2108
- package/dist/useCompositeListItem-es.js +331 -2076
- package/dist/useLabel-cjs.js +3 -2
- package/dist/useLabel-es.js +3 -2
- package/dist/useRenderElement-cjs.js +7 -9
- package/dist/useRenderElement-es.js +7 -9
- package/dist/useScrollLock-cjs.js +344 -819
- package/dist/useScrollLock-es.js +296 -732
- package/dist/useScrollToActive-cjs.js +5 -4
- package/dist/useScrollToActive-es.js +2 -1
- package/package.json +3 -3
- package/dist/scrollable-cjs.js +0 -58
- package/dist/scrollable-es.js +0 -54
|
@@ -7,8 +7,8 @@ var useCompositeListItem = require('./useCompositeListItem-cjs.js');
|
|
|
7
7
|
var jsxRuntime = require('react/jsx-runtime');
|
|
8
8
|
var ReactDOM = require('react-dom');
|
|
9
9
|
var stringifyLocale = require('./stringifyLocale-cjs.js');
|
|
10
|
-
var scrollable = require('./scrollable-cjs.js');
|
|
11
10
|
var useLabel = require('./useLabel-cjs.js');
|
|
11
|
+
var floatingUi_utils = require('./floating-ui.utils-cjs.js');
|
|
12
12
|
|
|
13
13
|
function _interopNamespaceDefault(e) {
|
|
14
14
|
var n = Object.create(null);
|
|
@@ -104,15 +104,15 @@ function useComboboxHasItemsContext() {
|
|
|
104
104
|
}
|
|
105
105
|
|
|
106
106
|
const selectors = {
|
|
107
|
-
id: state => state.id,
|
|
108
|
-
labelId: state => state.labelId,
|
|
109
|
-
items: state => state.items,
|
|
110
|
-
selectedValue: state => state.selectedValue,
|
|
111
|
-
hasSelectionChips: state => {
|
|
107
|
+
id: useScrollLock.createSelector(state => state.id),
|
|
108
|
+
labelId: useScrollLock.createSelector(state => state.labelId),
|
|
109
|
+
items: useScrollLock.createSelector(state => state.items),
|
|
110
|
+
selectedValue: useScrollLock.createSelector(state => state.selectedValue),
|
|
111
|
+
hasSelectionChips: useScrollLock.createSelector(state => {
|
|
112
112
|
const selectedValue = state.selectedValue;
|
|
113
113
|
return Array.isArray(selectedValue) && selectedValue.length > 0;
|
|
114
|
-
},
|
|
115
|
-
hasSelectedValue: state => {
|
|
114
|
+
}),
|
|
115
|
+
hasSelectedValue: useScrollLock.createSelector(state => {
|
|
116
116
|
const {
|
|
117
117
|
selectedValue,
|
|
118
118
|
selectionMode
|
|
@@ -124,53 +124,53 @@ const selectors = {
|
|
|
124
124
|
return selectedValue.length > 0;
|
|
125
125
|
}
|
|
126
126
|
return true;
|
|
127
|
-
},
|
|
128
|
-
hasNullItemLabel: (state, enabled) => {
|
|
127
|
+
}),
|
|
128
|
+
hasNullItemLabel: useScrollLock.createSelector((state, enabled) => {
|
|
129
129
|
return enabled ? useCompositeListItem.hasNullItemLabel(state.items) : false;
|
|
130
|
-
},
|
|
131
|
-
open: state => state.open,
|
|
132
|
-
mounted: state => state.mounted,
|
|
133
|
-
forceMounted: state => state.forceMounted,
|
|
134
|
-
inline: state => state.inline,
|
|
135
|
-
activeIndex: state => state.activeIndex,
|
|
136
|
-
selectedIndex: state => state.selectedIndex,
|
|
137
|
-
isActive: (state, index) => state.activeIndex === index,
|
|
138
|
-
isSelected: (state, itemValue) => {
|
|
130
|
+
}),
|
|
131
|
+
open: useScrollLock.createSelector(state => state.open),
|
|
132
|
+
mounted: useScrollLock.createSelector(state => state.mounted),
|
|
133
|
+
forceMounted: useScrollLock.createSelector(state => state.forceMounted),
|
|
134
|
+
inline: useScrollLock.createSelector(state => state.inline),
|
|
135
|
+
activeIndex: useScrollLock.createSelector(state => state.activeIndex),
|
|
136
|
+
selectedIndex: useScrollLock.createSelector(state => state.selectedIndex),
|
|
137
|
+
isActive: useScrollLock.createSelector((state, index) => state.activeIndex === index),
|
|
138
|
+
isSelected: useScrollLock.createSelector((state, itemValue) => {
|
|
139
139
|
const comparer = state.isItemEqualToValue;
|
|
140
140
|
const selectedValue = state.selectedValue;
|
|
141
141
|
if (Array.isArray(selectedValue)) {
|
|
142
142
|
return selectedValue.some(selectedItem => useCompositeListItem.compareItemEquality(itemValue, selectedItem, comparer));
|
|
143
143
|
}
|
|
144
144
|
return useCompositeListItem.compareItemEquality(itemValue, selectedValue, comparer);
|
|
145
|
-
},
|
|
146
|
-
transitionStatus: state => state.transitionStatus,
|
|
147
|
-
popupProps: state => state.popupProps,
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
145
|
+
}),
|
|
146
|
+
transitionStatus: useScrollLock.createSelector(state => state.transitionStatus),
|
|
147
|
+
popupProps: useScrollLock.createSelector(state => state.popupProps),
|
|
148
|
+
inputProps: useScrollLock.createSelector(state => state.inputProps),
|
|
149
|
+
triggerProps: useScrollLock.createSelector(state => state.triggerProps),
|
|
150
|
+
itemProps: useScrollLock.createSelector(state => state.itemProps),
|
|
151
|
+
positionerElement: useScrollLock.createSelector(state => state.positionerElement),
|
|
152
|
+
listElement: useScrollLock.createSelector(state => state.listElement),
|
|
153
|
+
popupId: useScrollLock.createSelector(state => state.popupId),
|
|
154
|
+
triggerElement: useScrollLock.createSelector(state => state.triggerElement),
|
|
155
|
+
inputElement: useScrollLock.createSelector(state => state.inputElement),
|
|
156
|
+
inputGroupElement: useScrollLock.createSelector(state => state.inputGroupElement),
|
|
157
|
+
popupSide: useScrollLock.createSelector(state => state.popupSide),
|
|
158
|
+
openMethod: useScrollLock.createSelector(state => state.openMethod),
|
|
159
|
+
inputInsidePopup: useScrollLock.createSelector(state => state.inputInsidePopup),
|
|
160
|
+
inputOwnsFormValue: useScrollLock.createSelector(state => state.inputOwnsFormValue),
|
|
161
|
+
selectionMode: useScrollLock.createSelector(state => state.selectionMode),
|
|
162
|
+
name: useScrollLock.createSelector(state => state.name),
|
|
163
|
+
form: useScrollLock.createSelector(state => state.form),
|
|
164
|
+
disabled: useScrollLock.createSelector(state => state.disabled),
|
|
165
|
+
readOnly: useScrollLock.createSelector(state => state.readOnly),
|
|
166
|
+
required: useScrollLock.createSelector(state => state.required),
|
|
167
|
+
grid: useScrollLock.createSelector(state => state.grid),
|
|
168
|
+
virtualized: useScrollLock.createSelector(state => state.virtualized),
|
|
169
|
+
itemToStringLabel: useScrollLock.createSelector(state => state.itemToStringLabel),
|
|
170
|
+
isItemEqualToValue: useScrollLock.createSelector(state => state.isItemEqualToValue),
|
|
171
|
+
modal: useScrollLock.createSelector(state => state.modal),
|
|
172
|
+
autoHighlight: useScrollLock.createSelector(state => state.autoHighlight),
|
|
173
|
+
submitOnItemClick: useScrollLock.createSelector(state => state.submitOnItemClick)
|
|
174
174
|
};
|
|
175
175
|
|
|
176
176
|
/**
|
|
@@ -193,7 +193,8 @@ function createCollatorItemFilter(collatorFilter, itemToStringLabel) {
|
|
|
193
193
|
if (item == null) {
|
|
194
194
|
return false;
|
|
195
195
|
}
|
|
196
|
-
|
|
196
|
+
const itemString = useCompositeListItem.stringifyAsLabel(item, itemToStringLabel);
|
|
197
|
+
return collatorFilter.contains(itemString, query);
|
|
197
198
|
};
|
|
198
199
|
}
|
|
199
200
|
|
|
@@ -209,13 +210,14 @@ function createSingleSelectionCollatorFilter(collatorFilter, itemToStringLabel,
|
|
|
209
210
|
if (!query) {
|
|
210
211
|
return true;
|
|
211
212
|
}
|
|
213
|
+
const itemString = useCompositeListItem.stringifyAsLabel(item, itemToStringLabel);
|
|
212
214
|
const selectedString = selectedValue != null ? useCompositeListItem.stringifyAsLabel(selectedValue, itemToStringLabel) : '';
|
|
213
215
|
|
|
214
216
|
// Handle case-insensitive matching consistently
|
|
215
217
|
if (selectedString && collatorFilter.contains(selectedString, query) && selectedString.length === query.length) {
|
|
216
218
|
return true;
|
|
217
219
|
}
|
|
218
|
-
return collatorFilter.contains(
|
|
220
|
+
return collatorFilter.contains(itemString, query);
|
|
219
221
|
};
|
|
220
222
|
}
|
|
221
223
|
|
|
@@ -287,8 +289,9 @@ function useComboboxFilter(options = {}) {
|
|
|
287
289
|
return createSingleSelectionCollatorFilter(coreFilter, itemToString, value)(item, query);
|
|
288
290
|
}, [coreFilter, value, multiple]);
|
|
289
291
|
return React__namespace.useMemo(() => ({
|
|
290
|
-
|
|
291
|
-
|
|
292
|
+
contains,
|
|
293
|
+
startsWith: coreFilter.startsWith,
|
|
294
|
+
endsWith: coreFilter.endsWith
|
|
292
295
|
}), [contains, coreFilter]);
|
|
293
296
|
}
|
|
294
297
|
|
|
@@ -309,7 +312,7 @@ function AriaCombobox(props) {
|
|
|
309
312
|
inputValue: inputValueProp,
|
|
310
313
|
open: openProp,
|
|
311
314
|
defaultOpen = false,
|
|
312
|
-
selectionMode,
|
|
315
|
+
selectionMode = 'none',
|
|
313
316
|
onItemHighlighted: onItemHighlightedProp,
|
|
314
317
|
name: nameProp,
|
|
315
318
|
form,
|
|
@@ -382,10 +385,12 @@ function AriaCombobox(props) {
|
|
|
382
385
|
*/
|
|
383
386
|
const valuesRef = React__namespace.useRef([]);
|
|
384
387
|
/**
|
|
385
|
-
*
|
|
386
|
-
*
|
|
388
|
+
* Contains all item values in a stable, unfiltered order.
|
|
389
|
+
* This is only used when `items` prop is not provided.
|
|
390
|
+
* It accumulates values on first mount and does not remove them on unmount due to
|
|
391
|
+
* filtering, providing a stable index for selected value tracking.
|
|
387
392
|
*/
|
|
388
|
-
const
|
|
393
|
+
const allValuesRef = React__namespace.useRef([]);
|
|
389
394
|
const disabled = fieldDisabled || disabledProp;
|
|
390
395
|
const name = fieldName ?? nameProp;
|
|
391
396
|
const multiple = selectionMode === 'multiple';
|
|
@@ -412,10 +417,11 @@ function AriaCombobox(props) {
|
|
|
412
417
|
if (filterProp !== undefined) {
|
|
413
418
|
return filterProp;
|
|
414
419
|
}
|
|
415
|
-
|
|
416
|
-
|
|
420
|
+
if (single && !queryChangedAfterOpen) {
|
|
421
|
+
return createSingleSelectionCollatorFilter(collatorFilter, itemToStringLabel, selectedValue);
|
|
422
|
+
}
|
|
417
423
|
return createCollatorItemFilter(collatorFilter, itemToStringLabel);
|
|
418
|
-
}, [filterProp, collatorFilter, itemToStringLabel]);
|
|
424
|
+
}, [filterProp, single, selectedValue, queryChangedAfterOpen, collatorFilter, itemToStringLabel]);
|
|
419
425
|
|
|
420
426
|
// If neither inputValue nor defaultInputValue are provided, derive it from the
|
|
421
427
|
// selected value for single mode so the input reflects the selection on mount.
|
|
@@ -441,9 +447,9 @@ function AriaCombobox(props) {
|
|
|
441
447
|
state: 'open'
|
|
442
448
|
});
|
|
443
449
|
const isGrouped = useCompositeListItem.isGroupedItems(items);
|
|
444
|
-
const query = closeQuery ?? String(inputValue).trim();
|
|
450
|
+
const query = closeQuery ?? (inputValue === '' ? '' : String(inputValue).trim());
|
|
445
451
|
const selectedLabelString = single ? useCompositeListItem.stringifyAsLabel(selectedValue, itemToStringLabel) : '';
|
|
446
|
-
const shouldBypassFiltering = single && !queryChangedAfterOpen && query !== '' && selectedLabelString.length === query.length && collatorFilter.contains(selectedLabelString, query);
|
|
452
|
+
const shouldBypassFiltering = single && !queryChangedAfterOpen && query !== '' && selectedLabelString !== '' && selectedLabelString.length === query.length && collatorFilter.contains(selectedLabelString, query);
|
|
447
453
|
const filterQuery = shouldBypassFiltering ? '' : query;
|
|
448
454
|
const shouldIgnoreExternalFiltering = hasItems && hasFilteredItemsProp && shouldBypassFiltering;
|
|
449
455
|
const flatItems = React__namespace.useMemo(() => {
|
|
@@ -470,18 +476,12 @@ function AriaCombobox(props) {
|
|
|
470
476
|
if (limit > -1 && currentCount >= limit) {
|
|
471
477
|
break;
|
|
472
478
|
}
|
|
473
|
-
const
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
for (const item of group.items) {
|
|
477
|
-
if (itemsToTake.length >= remainingLimit) {
|
|
478
|
-
break;
|
|
479
|
-
}
|
|
480
|
-
if (filter(item, filterQuery, itemToStringLabel)) {
|
|
481
|
-
itemsToTake.push(item);
|
|
482
|
-
}
|
|
483
|
-
}
|
|
479
|
+
const candidateItems = filterQuery === '' ? group.items : group.items.filter(item => filter(item, filterQuery, itemToStringLabel));
|
|
480
|
+
if (candidateItems.length === 0) {
|
|
481
|
+
continue;
|
|
484
482
|
}
|
|
483
|
+
const remainingLimit = limit > -1 ? limit - currentCount : Infinity;
|
|
484
|
+
const itemsToTake = candidateItems.slice(0, remainingLimit);
|
|
485
485
|
if (itemsToTake.length > 0) {
|
|
486
486
|
const newGroup = {
|
|
487
487
|
...group,
|
|
@@ -521,85 +521,76 @@ function AriaCombobox(props) {
|
|
|
521
521
|
}
|
|
522
522
|
return filteredItems;
|
|
523
523
|
}, [filteredItems, isGrouped]);
|
|
524
|
-
const store = useRenderElement.useRefWithInit(() => {
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
setOpen: useRenderElement.NOOP,
|
|
595
|
-
setInputValue: useRenderElement.NOOP,
|
|
596
|
-
setSelectedValue: useRenderElement.NOOP,
|
|
597
|
-
setIndices: useRenderElement.NOOP,
|
|
598
|
-
handleSelection: useRenderElement.NOOP,
|
|
599
|
-
forceMount: useRenderElement.NOOP,
|
|
600
|
-
requestSubmit: useRenderElement.NOOP
|
|
601
|
-
});
|
|
602
|
-
}).current;
|
|
524
|
+
const store = useRenderElement.useRefWithInit(() => new useScrollLock.Store({
|
|
525
|
+
id,
|
|
526
|
+
labelId: undefined,
|
|
527
|
+
selectedValue,
|
|
528
|
+
open,
|
|
529
|
+
filter,
|
|
530
|
+
query,
|
|
531
|
+
items,
|
|
532
|
+
selectionMode,
|
|
533
|
+
listRef,
|
|
534
|
+
labelsRef,
|
|
535
|
+
popupRef,
|
|
536
|
+
emptyRef,
|
|
537
|
+
inputRef,
|
|
538
|
+
startDismissRef,
|
|
539
|
+
endDismissRef,
|
|
540
|
+
keyboardActiveRef,
|
|
541
|
+
chipsContainerRef,
|
|
542
|
+
clearRef,
|
|
543
|
+
valuesRef,
|
|
544
|
+
allValuesRef,
|
|
545
|
+
selectionEventRef,
|
|
546
|
+
name,
|
|
547
|
+
form,
|
|
548
|
+
disabled,
|
|
549
|
+
readOnly,
|
|
550
|
+
required,
|
|
551
|
+
grid,
|
|
552
|
+
isGrouped,
|
|
553
|
+
virtualized,
|
|
554
|
+
openOnInputClick,
|
|
555
|
+
itemToStringLabel,
|
|
556
|
+
isItemEqualToValue,
|
|
557
|
+
modal,
|
|
558
|
+
autoHighlight: autoHighlightMode,
|
|
559
|
+
submitOnItemClick,
|
|
560
|
+
hasInputValue,
|
|
561
|
+
mounted: false,
|
|
562
|
+
forceMounted: false,
|
|
563
|
+
transitionStatus: 'idle',
|
|
564
|
+
inline: inlineProp,
|
|
565
|
+
activeIndex: null,
|
|
566
|
+
selectedIndex: null,
|
|
567
|
+
popupProps: {},
|
|
568
|
+
inputProps: {},
|
|
569
|
+
triggerProps: {},
|
|
570
|
+
itemProps: useRenderElement.EMPTY_OBJECT,
|
|
571
|
+
positionerElement: null,
|
|
572
|
+
listElement: null,
|
|
573
|
+
popupId: undefined,
|
|
574
|
+
triggerElement: null,
|
|
575
|
+
inputElement: null,
|
|
576
|
+
inputGroupElement: null,
|
|
577
|
+
popupSide: null,
|
|
578
|
+
openMethod: null,
|
|
579
|
+
inputInsidePopup: true,
|
|
580
|
+
// Avoid duplicate names in the server HTML. Popup inputs aren't rendered
|
|
581
|
+
// until after hydration, so the hidden input takes over then if needed.
|
|
582
|
+
inputOwnsFormValue: selectionMode === 'none',
|
|
583
|
+
onOpenChangeComplete: onOpenChangeCompleteProp || useRenderElement.NOOP,
|
|
584
|
+
// Placeholder callbacks replaced on first render
|
|
585
|
+
setOpen: useRenderElement.NOOP,
|
|
586
|
+
setInputValue: useRenderElement.NOOP,
|
|
587
|
+
setSelectedValue: useRenderElement.NOOP,
|
|
588
|
+
setIndices: useRenderElement.NOOP,
|
|
589
|
+
onItemHighlighted: useRenderElement.NOOP,
|
|
590
|
+
handleSelection: useRenderElement.NOOP,
|
|
591
|
+
forceMount: useRenderElement.NOOP,
|
|
592
|
+
requestSubmit: useRenderElement.NOOP
|
|
593
|
+
})).current;
|
|
603
594
|
const fieldRawValue = selectionMode === 'none' ? inputValue : selectedValue;
|
|
604
595
|
const fieldStringValue = React__namespace.useMemo(() => {
|
|
605
596
|
if (selectionMode === 'none') {
|
|
@@ -642,38 +633,35 @@ function AriaCombobox(props) {
|
|
|
642
633
|
store.set('forceMounted', true);
|
|
643
634
|
}
|
|
644
635
|
});
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
const emitHighlight = useScrollLock.useStableCallback((value, index, type) => {
|
|
651
|
-
if (index === -1) {
|
|
652
|
-
if (lastHighlightRef.current === INITIAL_LAST_HIGHLIGHT) {
|
|
653
|
-
return;
|
|
654
|
-
}
|
|
655
|
-
lastHighlightRef.current = INITIAL_LAST_HIGHLIGHT;
|
|
656
|
-
} else {
|
|
657
|
-
lastHighlightRef.current = {
|
|
658
|
-
value,
|
|
659
|
-
index
|
|
660
|
-
};
|
|
636
|
+
const initialSelectedValueRef = React__namespace.useRef(selectedValue);
|
|
637
|
+
useScrollLock.useIsoLayoutEffect(() => {
|
|
638
|
+
// Ensure the values and labels are registered for programmatic value changes.
|
|
639
|
+
if (selectedValue !== initialSelectedValueRef.current) {
|
|
640
|
+
forceMount();
|
|
661
641
|
}
|
|
662
|
-
|
|
663
|
-
index
|
|
664
|
-
}));
|
|
665
|
-
});
|
|
642
|
+
}, [forceMount, selectedValue]);
|
|
666
643
|
const setIndices = useScrollLock.useStableCallback(options => {
|
|
667
644
|
store.update(options);
|
|
668
|
-
const
|
|
669
|
-
if (
|
|
645
|
+
const type = options.type || 'none';
|
|
646
|
+
if (options.activeIndex === undefined) {
|
|
670
647
|
return;
|
|
671
648
|
}
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
649
|
+
if (options.activeIndex === null) {
|
|
650
|
+
if (lastHighlightRef.current !== INITIAL_LAST_HIGHLIGHT) {
|
|
651
|
+
lastHighlightRef.current = INITIAL_LAST_HIGHLIGHT;
|
|
652
|
+
onItemHighlighted(undefined, useScrollLock.createGenericEventDetails(type, undefined, {
|
|
653
|
+
index: -1
|
|
654
|
+
}));
|
|
655
|
+
}
|
|
675
656
|
} else {
|
|
676
|
-
|
|
657
|
+
const activeValue = valuesRef.current[options.activeIndex];
|
|
658
|
+
lastHighlightRef.current = {
|
|
659
|
+
value: activeValue,
|
|
660
|
+
index: options.activeIndex
|
|
661
|
+
};
|
|
662
|
+
onItemHighlighted(activeValue, useScrollLock.createGenericEventDetails(type, undefined, {
|
|
663
|
+
index: options.activeIndex
|
|
664
|
+
}));
|
|
677
665
|
}
|
|
678
666
|
});
|
|
679
667
|
const setInputValue = useScrollLock.useStableCallback((next, eventDetails) => {
|
|
@@ -686,11 +674,6 @@ function AriaCombobox(props) {
|
|
|
686
674
|
// If user is typing, ensure we don't auto-highlight on open due to a race
|
|
687
675
|
// with the post-open effect that sets this flag.
|
|
688
676
|
if (eventDetails.reason === useScrollLock.inputChange) {
|
|
689
|
-
// A controlled popup may ignore a close request. Resuming input proves the popup
|
|
690
|
-
// is remaining open, so release the query captured for an exit animation.
|
|
691
|
-
if (open && closeQuery !== null) {
|
|
692
|
-
setCloseQuery(null);
|
|
693
|
-
}
|
|
694
677
|
const event = eventDetails.event;
|
|
695
678
|
const inputType = event.inputType;
|
|
696
679
|
// Treat composition commits as typed input; autofill may omit `inputType` or
|
|
@@ -706,34 +689,10 @@ function AriaCombobox(props) {
|
|
|
706
689
|
pendingQueryHighlightRef.current = {
|
|
707
690
|
hasQuery
|
|
708
691
|
};
|
|
709
|
-
|
|
710
|
-
// Virtualized lists own their scroller. Reset regular lists directly so a stale
|
|
711
|
-
// composite registry cannot select a reordered item and scrolling cannot escape
|
|
712
|
-
// the popup.
|
|
713
|
-
const list = store.state.listElement;
|
|
714
|
-
if (!store.state.virtualized && list) {
|
|
715
|
-
const popup = popupRef.current;
|
|
716
|
-
for (const ancestor of useScrollLock.getOverflowAncestors(list.firstElementChild ?? list)) {
|
|
717
|
-
if (!useScrollLock.isHTMLElement(ancestor) || (popup ? !useScrollLock.contains(popup, ancestor) : ancestor.getAttribute('role') === 'dialog')) {
|
|
718
|
-
break;
|
|
719
|
-
}
|
|
720
|
-
if (scrollable.isScrollableY(ancestor)) {
|
|
721
|
-
ancestor.scrollTop = 0;
|
|
722
|
-
break;
|
|
723
|
-
}
|
|
724
|
-
}
|
|
725
|
-
}
|
|
726
|
-
if (hasQuery && autoHighlightMode && store.state.activeIndex == null && (open || inline)) {
|
|
692
|
+
if (hasQuery && autoHighlightMode && store.state.activeIndex == null) {
|
|
727
693
|
store.set('activeIndex', 0);
|
|
728
694
|
}
|
|
729
695
|
}
|
|
730
|
-
} else if (eventDetails.reason === useScrollLock.inputClear && next === '' && store.state.inputInsidePopup) {
|
|
731
|
-
// A programmatic clear of an active query (e.g. after selecting an item with the
|
|
732
|
-
// input inside the popup): restore the highlight to the selected item.
|
|
733
|
-
pendingQueryHighlightRef.current = {
|
|
734
|
-
hasQuery: false,
|
|
735
|
-
selection: true
|
|
736
|
-
};
|
|
737
696
|
}
|
|
738
697
|
setInputValueUnwrapped(next);
|
|
739
698
|
});
|
|
@@ -745,7 +704,7 @@ function AriaCombobox(props) {
|
|
|
745
704
|
// If the `Empty` component is not used, the positioner or popup should be hidden
|
|
746
705
|
// with CSS. In this case, allow the Escape key to bubble to close a parent popup
|
|
747
706
|
// if there are no items to show.
|
|
748
|
-
if (eventDetails.reason ===
|
|
707
|
+
if (eventDetails.reason === 'escape-key' && hasItems && flatFilteredItems.length === 0 && !store.state.emptyRef.current) {
|
|
749
708
|
eventDetails.allowPropagation();
|
|
750
709
|
}
|
|
751
710
|
props.onOpenChange?.(nextOpen, eventDetails);
|
|
@@ -755,10 +714,10 @@ function AriaCombobox(props) {
|
|
|
755
714
|
|
|
756
715
|
// If reopening interrupts the close animation, handleUnmount won't run to clear the
|
|
757
716
|
// frozen closeQuery and pending popup input.
|
|
758
|
-
if (nextOpen && inputInsidePopup && !inline && closeQuery !== null) {
|
|
717
|
+
if (nextOpen && multiple && inputInsidePopup && !inline && closeQuery !== null) {
|
|
759
718
|
setQueryChangedAfterOpen(false);
|
|
760
719
|
setCloseQuery(null);
|
|
761
|
-
if (inputValue !== ''
|
|
720
|
+
if (inputValue !== '') {
|
|
762
721
|
setInputValue('', useScrollLock.createChangeEventDetails(useScrollLock.inputClear, eventDetails.event));
|
|
763
722
|
}
|
|
764
723
|
}
|
|
@@ -812,8 +771,18 @@ function AriaCombobox(props) {
|
|
|
812
771
|
if (shouldFillInput) {
|
|
813
772
|
setInputValue(useCompositeListItem.stringifyAsLabel(nextValue, itemToStringLabel), useScrollLock.createChangeEventDetails(eventDetails.reason, eventDetails.event));
|
|
814
773
|
}
|
|
774
|
+
if (single && nextValue != null && eventDetails.reason !== useScrollLock.inputChange && queryChangedAfterOpen && !inline) {
|
|
775
|
+
setCloseQuery(query);
|
|
776
|
+
}
|
|
815
777
|
});
|
|
816
|
-
const handleSelection = useScrollLock.useStableCallback((event,
|
|
778
|
+
const handleSelection = useScrollLock.useStableCallback((event, passedValue) => {
|
|
779
|
+
let itemValue = passedValue;
|
|
780
|
+
if (itemValue === undefined) {
|
|
781
|
+
if (activeIndex === null) {
|
|
782
|
+
return;
|
|
783
|
+
}
|
|
784
|
+
itemValue = valuesRef.current[activeIndex];
|
|
785
|
+
}
|
|
817
786
|
const targetEl = useScrollLock.getTarget(event);
|
|
818
787
|
const overrideEvent = selectionEventRef.current ?? event;
|
|
819
788
|
selectionEventRef.current = null;
|
|
@@ -829,8 +798,8 @@ function AriaCombobox(props) {
|
|
|
829
798
|
}
|
|
830
799
|
if (multiple) {
|
|
831
800
|
const currentSelectedValue = Array.isArray(selectedValue) ? selectedValue : [];
|
|
832
|
-
const isCurrentlySelected = useCompositeListItem.selectedValueIncludes(currentSelectedValue, itemValue, isItemEqualToValue);
|
|
833
|
-
const nextValue = isCurrentlySelected ? useCompositeListItem.removeItem(currentSelectedValue, itemValue, isItemEqualToValue) : [...currentSelectedValue, itemValue];
|
|
801
|
+
const isCurrentlySelected = useCompositeListItem.selectedValueIncludes(currentSelectedValue, itemValue, store.state.isItemEqualToValue);
|
|
802
|
+
const nextValue = isCurrentlySelected ? useCompositeListItem.removeItem(currentSelectedValue, itemValue, store.state.isItemEqualToValue) : [...currentSelectedValue, itemValue];
|
|
834
803
|
setSelectedValue(nextValue, eventDetails);
|
|
835
804
|
if (eventDetails.isCanceled) {
|
|
836
805
|
return;
|
|
@@ -853,6 +822,9 @@ function AriaCombobox(props) {
|
|
|
853
822
|
}
|
|
854
823
|
});
|
|
855
824
|
const requestSubmit = useScrollLock.useStableCallback(() => {
|
|
825
|
+
if (!store.state.submitOnItemClick) {
|
|
826
|
+
return;
|
|
827
|
+
}
|
|
856
828
|
const formElement = validation.inputRef.current?.form ?? store.state.inputElement?.form;
|
|
857
829
|
if (formElement && typeof formElement.requestSubmit === 'function') {
|
|
858
830
|
formElement.requestSubmit();
|
|
@@ -925,29 +897,25 @@ function AriaCombobox(props) {
|
|
|
925
897
|
React__namespace.useImperativeHandle(props.actionsRef, () => ({
|
|
926
898
|
unmount: handleUnmount
|
|
927
899
|
}), [handleUnmount]);
|
|
928
|
-
useScrollLock.useIsoLayoutEffect(function
|
|
929
|
-
if (open) {
|
|
900
|
+
useScrollLock.useIsoLayoutEffect(function syncSelectedIndex() {
|
|
901
|
+
if (open || selectionMode === 'none') {
|
|
930
902
|
return;
|
|
931
903
|
}
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
904
|
+
const registry = items ? flatItems : allValuesRef.current;
|
|
905
|
+
if (multiple) {
|
|
906
|
+
const currentValue = Array.isArray(selectedValue) ? selectedValue : [];
|
|
907
|
+
const lastValue = currentValue[currentValue.length - 1];
|
|
908
|
+
const lastIndex = useCompositeListItem.findItemIndex(registry, lastValue, isItemEqualToValue);
|
|
909
|
+
setIndices({
|
|
910
|
+
selectedIndex: lastIndex === -1 ? null : lastIndex
|
|
911
|
+
});
|
|
912
|
+
} else {
|
|
913
|
+
const index = useCompositeListItem.findItemIndex(registry, selectedValue, isItemEqualToValue);
|
|
914
|
+
setIndices({
|
|
915
|
+
selectedIndex: index === -1 ? null : index
|
|
916
|
+
});
|
|
938
917
|
}
|
|
939
|
-
|
|
940
|
-
// Without `items`, look the selection up in the live registry of mounted item
|
|
941
|
-
// values (the list stays mounted while closed when closed-state features need
|
|
942
|
-
// it — trigger interaction and rendered-label autofill force-mount it). Mounted
|
|
943
|
-
// items re-assert the index themselves when their registration moves; when
|
|
944
|
-
// nothing is mounted the lookup resolves to `null` and each item re-registers
|
|
945
|
-
// the index on the next open.
|
|
946
|
-
const registry = hasItems ? flatItems : valuesRef.current;
|
|
947
|
-
setIndices({
|
|
948
|
-
selectedIndex: useCompositeListItem.findSelectionIndex(registry, selectedValue, isItemEqualToValue, multiple)
|
|
949
|
-
});
|
|
950
|
-
}, [open, selectedValue, selectionMode, multiple, hasItems, flatItems, isItemEqualToValue, setIndices]);
|
|
918
|
+
}, [open, selectedValue, items, selectionMode, flatItems, multiple, isItemEqualToValue, setIndices]);
|
|
951
919
|
useScrollLock.useIsoLayoutEffect(() => {
|
|
952
920
|
if (items) {
|
|
953
921
|
valuesRef.current = flatFilteredItems;
|
|
@@ -957,52 +925,14 @@ function AriaCombobox(props) {
|
|
|
957
925
|
useScrollLock.useIsoLayoutEffect(() => {
|
|
958
926
|
const pendingHighlight = pendingQueryHighlightRef.current;
|
|
959
927
|
if (pendingHighlight) {
|
|
960
|
-
// A directly rendered list remains visible when the popup state is closed, while a
|
|
961
|
-
// kept-mounted Positioner is hidden and should stay inert.
|
|
962
|
-
const listIsNavigable = open || inline || store.state.positionerElement?.hidden === false;
|
|
963
928
|
if (pendingHighlight.hasQuery) {
|
|
964
|
-
if (autoHighlightMode
|
|
929
|
+
if (autoHighlightMode) {
|
|
965
930
|
store.set('activeIndex', 0);
|
|
966
931
|
}
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
// Only handle the clear once it has committed (a controlled input may reject it),
|
|
970
|
-
// so a restore cannot fire while a query is still active.
|
|
971
|
-
pendingQueryHighlightRef.current = null;
|
|
972
|
-
if (listIsNavigable) {
|
|
973
|
-
const clearedBySelection = pendingHighlight.selection;
|
|
974
|
-
if (autoHighlightMode === 'always' && !clearedBySelection && store.state.selectionMode === 'none') {
|
|
975
|
-
// There is no selection to restore in Autocomplete. Keep the first-item reset
|
|
976
|
-
// synchronous so list navigation sees it before a directly rendered list closes.
|
|
977
|
-
store.set('activeIndex', 0);
|
|
978
|
-
}
|
|
979
|
-
|
|
980
|
-
// Items re-mounted by the clear publish their composite indices in a follow-up
|
|
981
|
-
// commit, so the item registries are mid-update here. Defer past React's cascade.
|
|
982
|
-
queueMicrotask(() => {
|
|
983
|
-
if (!store.state.open && !store.state.inline || inputRef.current && inputRef.current.value.trim() !== '') {
|
|
984
|
-
return;
|
|
985
|
-
}
|
|
986
|
-
|
|
987
|
-
// Return the highlight to the selected item, the same anchor the popup uses
|
|
988
|
-
// when it first opens. Read the selection through the store so consumers can
|
|
989
|
-
// pass an inline `isItemEqualToValue` or a fresh `selectedValue` array without
|
|
990
|
-
// re-running this effect on every render.
|
|
991
|
-
const currentSelectedValue = store.state.selectedValue;
|
|
992
|
-
const isMultiple = store.state.selectionMode === 'multiple';
|
|
993
|
-
const lastSelectedValue = isMultiple && Array.isArray(currentSelectedValue) ? currentSelectedValue[currentSelectedValue.length - 1] : currentSelectedValue;
|
|
994
|
-
const hasSelection = store.state.selectionMode !== 'none' && lastSelectedValue != null;
|
|
995
|
-
if (hasSelection || clearedBySelection) {
|
|
996
|
-
const registry = hasItems || hasFilteredItemsProp ? flatFilteredItems : valuesRef.current;
|
|
997
|
-
// A selection that is no longer in the list drops the highlight rather than
|
|
998
|
-
// leaving it on whichever item now occupies that index.
|
|
999
|
-
store.set('activeIndex', hasSelection ? useCompositeListItem.findSelectionIndex(registry, currentSelectedValue, store.state.isItemEqualToValue, isMultiple) : null);
|
|
1000
|
-
} else if (autoHighlightMode === 'always') {
|
|
1001
|
-
store.set('activeIndex', 0);
|
|
1002
|
-
}
|
|
1003
|
-
});
|
|
1004
|
-
}
|
|
932
|
+
} else if (autoHighlightMode === 'always') {
|
|
933
|
+
store.set('activeIndex', 0);
|
|
1005
934
|
}
|
|
935
|
+
pendingQueryHighlightRef.current = null;
|
|
1006
936
|
}
|
|
1007
937
|
if (!open && !inline) {
|
|
1008
938
|
return;
|
|
@@ -1015,11 +945,21 @@ function AriaCombobox(props) {
|
|
|
1015
945
|
store.set('activeIndex', 0);
|
|
1016
946
|
return;
|
|
1017
947
|
}
|
|
1018
|
-
|
|
948
|
+
if (lastHighlightRef.current !== INITIAL_LAST_HIGHLIGHT) {
|
|
949
|
+
lastHighlightRef.current = INITIAL_LAST_HIGHLIGHT;
|
|
950
|
+
store.state.onItemHighlighted(undefined, useScrollLock.createGenericEventDetails(useScrollLock.none, undefined, {
|
|
951
|
+
index: -1
|
|
952
|
+
}));
|
|
953
|
+
}
|
|
1019
954
|
return;
|
|
1020
955
|
}
|
|
1021
956
|
if (storeActiveIndex >= candidateItems.length) {
|
|
1022
|
-
|
|
957
|
+
if (lastHighlightRef.current !== INITIAL_LAST_HIGHLIGHT) {
|
|
958
|
+
lastHighlightRef.current = INITIAL_LAST_HIGHLIGHT;
|
|
959
|
+
store.state.onItemHighlighted(undefined, useScrollLock.createGenericEventDetails(useScrollLock.none, undefined, {
|
|
960
|
+
index: -1
|
|
961
|
+
}));
|
|
962
|
+
}
|
|
1023
963
|
store.set('activeIndex', null);
|
|
1024
964
|
return;
|
|
1025
965
|
}
|
|
@@ -1027,12 +967,15 @@ function AriaCombobox(props) {
|
|
|
1027
967
|
const previouslyHighlightedItemValue = lastHighlightRef.current.value;
|
|
1028
968
|
const isSameItem = previouslyHighlightedItemValue !== NO_ACTIVE_VALUE && useCompositeListItem.compareItemEquality(itemValue, previouslyHighlightedItemValue, store.state.isItemEqualToValue);
|
|
1029
969
|
if (lastHighlightRef.current.index !== storeActiveIndex || !isSameItem) {
|
|
1030
|
-
|
|
970
|
+
lastHighlightRef.current = {
|
|
971
|
+
value: itemValue,
|
|
972
|
+
index: storeActiveIndex
|
|
973
|
+
};
|
|
974
|
+
store.state.onItemHighlighted(itemValue, useScrollLock.createGenericEventDetails(useScrollLock.none, undefined, {
|
|
975
|
+
index: storeActiveIndex
|
|
976
|
+
}));
|
|
1031
977
|
}
|
|
1032
|
-
}, [activeIndex, autoHighlightMode,
|
|
1033
|
-
// Reruns the effect when the query changes without affecting the deps above, such as
|
|
1034
|
-
// clearing the input when no items are filtered out (individually rendered items).
|
|
1035
|
-
inputValue]);
|
|
978
|
+
}, [activeIndex, autoHighlightMode, hasFilteredItemsProp, hasItems, flatFilteredItems, inline, open, store]);
|
|
1036
979
|
useScrollLock.useIsoLayoutEffect(() => {
|
|
1037
980
|
if (selectionMode === 'none') {
|
|
1038
981
|
setFilled(String(inputValue) !== '');
|
|
@@ -1063,12 +1006,6 @@ function AriaCombobox(props) {
|
|
|
1063
1006
|
}
|
|
1064
1007
|
setQueryChangedAfterOpen(true);
|
|
1065
1008
|
});
|
|
1066
|
-
function syncInputToSelectedLabel() {
|
|
1067
|
-
const nextInputValue = useCompositeListItem.stringifyAsLabel(selectedValue, itemToStringLabel);
|
|
1068
|
-
if (inputValue !== nextInputValue) {
|
|
1069
|
-
setInputValue(nextInputValue, useScrollLock.createChangeEventDetails(useScrollLock.none));
|
|
1070
|
-
}
|
|
1071
|
-
}
|
|
1072
1009
|
useScrollLock.useValueChanged(selectedValue, () => {
|
|
1073
1010
|
if (selectionMode === 'none') {
|
|
1074
1011
|
return;
|
|
@@ -1077,7 +1014,10 @@ function AriaCombobox(props) {
|
|
|
1077
1014
|
setDirty(isSelectedValueDirty(selectedValue));
|
|
1078
1015
|
validation.change(selectedValue);
|
|
1079
1016
|
if (single && !hasInputValue && !inputInsidePopup) {
|
|
1080
|
-
|
|
1017
|
+
const nextInputValue = useCompositeListItem.stringifyAsLabel(selectedValue, itemToStringLabel);
|
|
1018
|
+
if (inputValue !== nextInputValue) {
|
|
1019
|
+
setInputValue(nextInputValue, useScrollLock.createChangeEventDetails(useScrollLock.none));
|
|
1020
|
+
}
|
|
1081
1021
|
}
|
|
1082
1022
|
});
|
|
1083
1023
|
useScrollLock.useValueChanged(inputValue, () => {
|
|
@@ -1092,7 +1032,10 @@ function AriaCombobox(props) {
|
|
|
1092
1032
|
if (!single || hasInputValue || inputInsidePopup || queryChangedAfterOpen) {
|
|
1093
1033
|
return;
|
|
1094
1034
|
}
|
|
1095
|
-
|
|
1035
|
+
const nextInputValue = useCompositeListItem.stringifyAsLabel(selectedValue, itemToStringLabel);
|
|
1036
|
+
if (inputValue !== nextInputValue) {
|
|
1037
|
+
setInputValue(nextInputValue, useScrollLock.createChangeEventDetails(useScrollLock.none));
|
|
1038
|
+
}
|
|
1096
1039
|
});
|
|
1097
1040
|
const floatingRootContext = useCompositeListItem.useFloatingRootContext({
|
|
1098
1041
|
open: inline ? true : open,
|
|
@@ -1102,19 +1045,18 @@ function AriaCombobox(props) {
|
|
|
1102
1045
|
floating: positionerElement
|
|
1103
1046
|
}
|
|
1104
1047
|
});
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1048
|
+
let ariaHasPopup;
|
|
1049
|
+
let ariaExpanded;
|
|
1050
|
+
if (!inline) {
|
|
1051
|
+
ariaHasPopup = grid ? 'grid' : 'listbox';
|
|
1052
|
+
ariaExpanded = open ? 'true' : 'false';
|
|
1053
|
+
}
|
|
1110
1054
|
const role = React__namespace.useMemo(() => {
|
|
1111
1055
|
const isPlainInput = inputElement?.tagName === 'INPUT';
|
|
1112
1056
|
// During SSR and initial hydration, the input ref is not available yet.
|
|
1113
1057
|
// Assume an input-like control so combobox ARIA attributes are present.
|
|
1114
1058
|
const shouldTreatAsInput = inputElement == null || isPlainInput;
|
|
1115
|
-
|
|
1116
|
-
// an inline list is the whole time.
|
|
1117
|
-
const shouldApplyAria = shouldTreatAsInput || expanded;
|
|
1059
|
+
const shouldApplyAria = shouldTreatAsInput || open;
|
|
1118
1060
|
const reference = shouldTreatAsInput ? {
|
|
1119
1061
|
autoComplete: 'off',
|
|
1120
1062
|
spellCheck: 'false',
|
|
@@ -1125,7 +1067,7 @@ function AriaCombobox(props) {
|
|
|
1125
1067
|
reference.role = 'combobox';
|
|
1126
1068
|
reference['aria-expanded'] = ariaExpanded;
|
|
1127
1069
|
reference['aria-haspopup'] = ariaHasPopup;
|
|
1128
|
-
reference['aria-controls'] =
|
|
1070
|
+
reference['aria-controls'] = open ? listElement?.id : undefined;
|
|
1129
1071
|
reference['aria-autocomplete'] = autoComplete;
|
|
1130
1072
|
}
|
|
1131
1073
|
return {
|
|
@@ -1134,7 +1076,7 @@ function AriaCombobox(props) {
|
|
|
1134
1076
|
role: 'presentation'
|
|
1135
1077
|
}
|
|
1136
1078
|
};
|
|
1137
|
-
}, [inputElement,
|
|
1079
|
+
}, [inputElement, open, ariaExpanded, ariaHasPopup, listElement?.id, autoComplete]);
|
|
1138
1080
|
const click = useScrollLock.useClick(floatingRootContext, {
|
|
1139
1081
|
enabled: !readOnly && !disabled && openOnInputClick,
|
|
1140
1082
|
event: 'mousedown-only',
|
|
@@ -1188,7 +1130,7 @@ function AriaCombobox(props) {
|
|
|
1188
1130
|
} else {
|
|
1189
1131
|
setIndices({
|
|
1190
1132
|
activeIndex: nextActiveIndex,
|
|
1191
|
-
type: keyboardActiveRef.current ?
|
|
1133
|
+
type: keyboardActiveRef.current ? 'keyboard' : 'pointer'
|
|
1192
1134
|
});
|
|
1193
1135
|
}
|
|
1194
1136
|
}
|
|
@@ -1203,8 +1145,7 @@ function AriaCombobox(props) {
|
|
|
1203
1145
|
}
|
|
1204
1146
|
}
|
|
1205
1147
|
}, dismiss.reference, click.reference, role.reference), [listNavigation.reference, dismiss.reference, click.reference, role.reference, grid, store]);
|
|
1206
|
-
const popupProps = React__namespace.useMemo(() => useRenderElement.mergeProps(useScrollLock.FOCUSABLE_POPUP_PROPS, dismiss.floating), [dismiss.floating]);
|
|
1207
|
-
const listProps = React__namespace.useMemo(() => useRenderElement.mergeProps(listNavigation.floating, role.floating), [listNavigation.floating, role.floating]);
|
|
1148
|
+
const popupProps = React__namespace.useMemo(() => useRenderElement.mergeProps(useScrollLock.FOCUSABLE_POPUP_PROPS, listNavigation.floating, dismiss.floating, role.floating), [listNavigation.floating, dismiss.floating, role.floating]);
|
|
1208
1149
|
const itemProps = React__namespace.useMemo(() => {
|
|
1209
1150
|
const listNavigationItemProps = listNavigation.item;
|
|
1210
1151
|
if (!listNavigationItemProps) {
|
|
@@ -1218,11 +1159,10 @@ function AriaCombobox(props) {
|
|
|
1218
1159
|
onFocus: undefined
|
|
1219
1160
|
};
|
|
1220
1161
|
}, [listNavigation.item]);
|
|
1221
|
-
|
|
1162
|
+
useScrollLock.useOnFirstRender(() => {
|
|
1222
1163
|
store.update({
|
|
1223
1164
|
inline: inlineProp,
|
|
1224
1165
|
popupProps,
|
|
1225
|
-
listProps,
|
|
1226
1166
|
inputProps,
|
|
1227
1167
|
triggerProps,
|
|
1228
1168
|
itemProps,
|
|
@@ -1230,10 +1170,10 @@ function AriaCombobox(props) {
|
|
|
1230
1170
|
setInputValue,
|
|
1231
1171
|
setSelectedValue,
|
|
1232
1172
|
setIndices,
|
|
1173
|
+
onItemHighlighted,
|
|
1233
1174
|
handleSelection,
|
|
1234
1175
|
forceMount,
|
|
1235
|
-
requestSubmit
|
|
1236
|
-
onOpenChangeComplete
|
|
1176
|
+
requestSubmit
|
|
1237
1177
|
});
|
|
1238
1178
|
});
|
|
1239
1179
|
useScrollLock.useIsoLayoutEffect(() => {
|
|
@@ -1246,7 +1186,6 @@ function AriaCombobox(props) {
|
|
|
1246
1186
|
items,
|
|
1247
1187
|
inline: inlineProp,
|
|
1248
1188
|
popupProps,
|
|
1249
|
-
listProps,
|
|
1250
1189
|
inputProps,
|
|
1251
1190
|
triggerProps,
|
|
1252
1191
|
openMethod,
|
|
@@ -1258,7 +1197,9 @@ function AriaCombobox(props) {
|
|
|
1258
1197
|
readOnly,
|
|
1259
1198
|
required,
|
|
1260
1199
|
grid,
|
|
1200
|
+
isGrouped,
|
|
1261
1201
|
virtualized,
|
|
1202
|
+
onOpenChangeComplete,
|
|
1262
1203
|
openOnInputClick,
|
|
1263
1204
|
itemToStringLabel,
|
|
1264
1205
|
modal,
|
|
@@ -1266,9 +1207,10 @@ function AriaCombobox(props) {
|
|
|
1266
1207
|
isItemEqualToValue,
|
|
1267
1208
|
submitOnItemClick,
|
|
1268
1209
|
hasInputValue,
|
|
1210
|
+
requestSubmit,
|
|
1269
1211
|
inputOwnsFormValue: selectionMode === 'none' && (inlineProp || !store.state.inputInsidePopup)
|
|
1270
1212
|
});
|
|
1271
|
-
}, [store, id, selectedValue, open, mounted, transitionStatus, items, popupProps,
|
|
1213
|
+
}, [store, id, selectedValue, open, mounted, transitionStatus, items, popupProps, inputProps, itemProps, openMethod, triggerProps, selectionMode, name, disabled, readOnly, required, validation, grid, isGrouped, virtualized, onOpenChangeComplete, openOnInputClick, itemToStringLabel, modal, isItemEqualToValue, submitOnItemClick, hasInputValue, inlineProp, requestSubmit, autoHighlightMode, form]);
|
|
1272
1214
|
const hiddenInputRef = useRenderElement.useMergedRefs(inputRefProp, validation.inputRef);
|
|
1273
1215
|
const itemsContextValue = React__namespace.useMemo(() => ({
|
|
1274
1216
|
query,
|
|
@@ -1312,7 +1254,7 @@ function AriaCombobox(props) {
|
|
|
1312
1254
|
},
|
|
1313
1255
|
// Handle browser autofill.
|
|
1314
1256
|
onChange(event) {
|
|
1315
|
-
// Workaround for https://github.com/
|
|
1257
|
+
// Workaround for https://github.com/facebook/react/issues/9023
|
|
1316
1258
|
if (event.nativeEvent.defaultPrevented || disabled || readOnly) {
|
|
1317
1259
|
return;
|
|
1318
1260
|
}
|
|
@@ -1407,51 +1349,7 @@ const triggerStateAttributesMapping = {
|
|
|
1407
1349
|
} : null
|
|
1408
1350
|
};
|
|
1409
1351
|
|
|
1410
|
-
|
|
1411
|
-
* The popup side is only meaningful while the positioner is mounted, as the store retains the
|
|
1412
|
-
* last resolved side after the popup unmounts.
|
|
1413
|
-
*/
|
|
1414
|
-
function usePopupSide(store) {
|
|
1415
|
-
const mounted = useScrollLock.useStore(store, selectors.mounted);
|
|
1416
|
-
const popupSide = useScrollLock.useStore(store, selectors.popupSide);
|
|
1417
|
-
const positionerElement = useScrollLock.useStore(store, selectors.positionerElement);
|
|
1418
|
-
return mounted && positionerElement ? popupSide : null;
|
|
1419
|
-
}
|
|
1420
|
-
|
|
1421
|
-
/**
|
|
1422
|
-
* Whether the filtered list has no items to show.
|
|
1423
|
-
*/
|
|
1424
|
-
function useListEmpty() {
|
|
1425
|
-
return useComboboxDerivedItemsContext().filteredItems.length === 0;
|
|
1426
|
-
}
|
|
1427
|
-
|
|
1428
|
-
/**
|
|
1429
|
-
* The arrow keys that move the chip highlight backwards and forwards, in that order.
|
|
1430
|
-
*/
|
|
1431
|
-
function getChipNavigationKeys(direction) {
|
|
1432
|
-
return direction === 'rtl' ? ['ArrowRight', 'ArrowLeft'] : ['ArrowLeft', 'ArrowRight'];
|
|
1433
|
-
}
|
|
1434
|
-
|
|
1435
|
-
/**
|
|
1436
|
-
* Where the highlight lands once the chip at `index` is removed, or `undefined` for no highlight.
|
|
1437
|
-
*/
|
|
1438
|
-
function getIndexAfterChipRemoval(index, chipCount) {
|
|
1439
|
-
const nextIndex = index >= chipCount - 1 ? chipCount - 2 : index;
|
|
1440
|
-
return nextIndex >= 0 ? nextIndex : undefined;
|
|
1441
|
-
}
|
|
1442
|
-
|
|
1443
|
-
/**
|
|
1444
|
-
* Commits the highlighted item by clicking it, tagging the originating event so the item's
|
|
1445
|
-
* handler can attribute the selection to it.
|
|
1446
|
-
*/
|
|
1447
|
-
function clickHighlightedItem(store, activeIndex, nativeEvent) {
|
|
1448
|
-
const listItem = store.state.listRef.current[activeIndex];
|
|
1449
|
-
if (listItem) {
|
|
1450
|
-
store.state.selectionEventRef.current = nativeEvent;
|
|
1451
|
-
listItem.click();
|
|
1452
|
-
store.state.selectionEventRef.current = null;
|
|
1453
|
-
}
|
|
1454
|
-
}
|
|
1352
|
+
const BOUNDARY_OFFSET = 2;
|
|
1455
1353
|
|
|
1456
1354
|
/**
|
|
1457
1355
|
* A button that opens the popup.
|
|
@@ -1481,14 +1379,20 @@ const ComboboxTrigger = /*#__PURE__*/React__namespace.forwardRef(function Combob
|
|
|
1481
1379
|
labelId: fieldLabelId
|
|
1482
1380
|
} = useCompositeListItem.useLabelableContext();
|
|
1483
1381
|
const store = useComboboxRootContext();
|
|
1382
|
+
const {
|
|
1383
|
+
filteredItems
|
|
1384
|
+
} = useComboboxDerivedItemsContext();
|
|
1484
1385
|
const selectionMode = useScrollLock.useStore(store, selectors.selectionMode);
|
|
1485
1386
|
const comboboxDisabled = useScrollLock.useStore(store, selectors.disabled);
|
|
1486
1387
|
const readOnly = useScrollLock.useStore(store, selectors.readOnly);
|
|
1487
1388
|
const required = useScrollLock.useStore(store, selectors.required);
|
|
1389
|
+
const mounted = useScrollLock.useStore(store, selectors.mounted);
|
|
1390
|
+
const popupSideValue = useScrollLock.useStore(store, selectors.popupSide);
|
|
1488
1391
|
const positionerElement = useScrollLock.useStore(store, selectors.positionerElement);
|
|
1489
1392
|
const listElement = useScrollLock.useStore(store, selectors.listElement);
|
|
1490
1393
|
const storedPopupId = useScrollLock.useStore(store, selectors.popupId);
|
|
1491
1394
|
const triggerProps = useScrollLock.useStore(store, selectors.triggerProps);
|
|
1395
|
+
const triggerElement = useScrollLock.useStore(store, selectors.triggerElement);
|
|
1492
1396
|
const inputInsidePopup = useScrollLock.useStore(store, selectors.inputInsidePopup);
|
|
1493
1397
|
const rootId = useScrollLock.useStore(store, selectors.id);
|
|
1494
1398
|
const comboboxLabelId = useScrollLock.useStore(store, selectors.labelId);
|
|
@@ -1501,8 +1405,8 @@ const ComboboxTrigger = /*#__PURE__*/React__namespace.forwardRef(function Combob
|
|
|
1501
1405
|
const inputValue = useComboboxInputValueContext();
|
|
1502
1406
|
const focusTimeout = useScrollLock.useTimeout();
|
|
1503
1407
|
const disabled = fieldDisabled || comboboxDisabled || disabledProp;
|
|
1504
|
-
const listEmpty =
|
|
1505
|
-
const popupSide =
|
|
1408
|
+
const listEmpty = filteredItems.length === 0;
|
|
1409
|
+
const popupSide = mounted && positionerElement ? popupSideValue : null;
|
|
1506
1410
|
useCompositeListItem.useLabelableId({
|
|
1507
1411
|
id: inputInsidePopup ? idProp : undefined
|
|
1508
1412
|
});
|
|
@@ -1520,6 +1424,18 @@ const ComboboxTrigger = /*#__PURE__*/React__namespace.forwardRef(function Combob
|
|
|
1520
1424
|
function trackPointerType(event) {
|
|
1521
1425
|
currentPointerTypeRef.current = event.pointerType;
|
|
1522
1426
|
}
|
|
1427
|
+
const domReference = floatingRootContext.useState('domReferenceElement');
|
|
1428
|
+
|
|
1429
|
+
// Update the floating root context to use the trigger element when it differs from the current reference.
|
|
1430
|
+
// This ensures useClick and useTypeahead attach handlers to the correct element.
|
|
1431
|
+
React__namespace.useEffect(() => {
|
|
1432
|
+
if (!inputInsidePopup) {
|
|
1433
|
+
return;
|
|
1434
|
+
}
|
|
1435
|
+
if (triggerElement && triggerElement !== domReference) {
|
|
1436
|
+
floatingRootContext.set('domReferenceElement', triggerElement);
|
|
1437
|
+
}
|
|
1438
|
+
}, [triggerElement, domReference, floatingRootContext, inputInsidePopup]);
|
|
1523
1439
|
const {
|
|
1524
1440
|
reference: triggerTypeaheadProps
|
|
1525
1441
|
} = useCompositeListItem.useTypeahead(floatingRootContext, {
|
|
@@ -1530,7 +1446,7 @@ const ComboboxTrigger = /*#__PURE__*/React__namespace.forwardRef(function Combob
|
|
|
1530
1446
|
onMatch(index) {
|
|
1531
1447
|
const nextSelectedValue = store.state.valuesRef.current[index];
|
|
1532
1448
|
if (nextSelectedValue !== undefined) {
|
|
1533
|
-
store.state.setSelectedValue(nextSelectedValue, useScrollLock.createChangeEventDetails(
|
|
1449
|
+
store.state.setSelectedValue(nextSelectedValue, useScrollLock.createChangeEventDetails('none'));
|
|
1534
1450
|
}
|
|
1535
1451
|
}
|
|
1536
1452
|
});
|
|
@@ -1565,7 +1481,7 @@ const ComboboxTrigger = /*#__PURE__*/React__namespace.forwardRef(function Combob
|
|
|
1565
1481
|
id,
|
|
1566
1482
|
tabIndex: inputInsidePopup ? 0 : -1,
|
|
1567
1483
|
role: inputInsidePopup ? 'combobox' : undefined,
|
|
1568
|
-
'aria-expanded': open,
|
|
1484
|
+
'aria-expanded': open ? 'true' : 'false',
|
|
1569
1485
|
'aria-haspopup': inputInsidePopup ? 'dialog' : 'listbox',
|
|
1570
1486
|
'aria-controls': ariaControls,
|
|
1571
1487
|
'aria-required': inputInsidePopup ? required || undefined : undefined,
|
|
@@ -1612,20 +1528,22 @@ const ComboboxTrigger = /*#__PURE__*/React__namespace.forwardRef(function Combob
|
|
|
1612
1528
|
}
|
|
1613
1529
|
const doc = useScrollLock.ownerDocument(event.currentTarget);
|
|
1614
1530
|
function handleMouseUp(mouseEvent) {
|
|
1615
|
-
|
|
1616
|
-
if (!currentTriggerElement) {
|
|
1531
|
+
if (!triggerElement) {
|
|
1617
1532
|
return;
|
|
1618
1533
|
}
|
|
1619
1534
|
const mouseUpTarget = useScrollLock.getTarget(mouseEvent);
|
|
1620
1535
|
const positioner = store.state.positionerElement;
|
|
1621
1536
|
const list = store.state.listElement;
|
|
1622
|
-
if (useScrollLock.contains(
|
|
1537
|
+
if (useScrollLock.contains(triggerElement, mouseUpTarget) || useScrollLock.contains(positioner, mouseUpTarget) || useScrollLock.contains(list, mouseUpTarget) || mouseUpTarget === triggerElement) {
|
|
1623
1538
|
return;
|
|
1624
1539
|
}
|
|
1625
|
-
|
|
1540
|
+
const bounds = useCompositeListItem.getPseudoElementBounds(triggerElement);
|
|
1541
|
+
const withinHorizontal = mouseEvent.clientX >= bounds.left - BOUNDARY_OFFSET && mouseEvent.clientX <= bounds.right + BOUNDARY_OFFSET;
|
|
1542
|
+
const withinVertical = mouseEvent.clientY >= bounds.top - BOUNDARY_OFFSET && mouseEvent.clientY <= bounds.bottom + BOUNDARY_OFFSET;
|
|
1543
|
+
if (withinHorizontal && withinVertical) {
|
|
1626
1544
|
return;
|
|
1627
1545
|
}
|
|
1628
|
-
store.state.setOpen(false, useScrollLock.createChangeEventDetails(
|
|
1546
|
+
store.state.setOpen(false, useScrollLock.createChangeEventDetails('cancel-open', mouseEvent));
|
|
1629
1547
|
}
|
|
1630
1548
|
if (inputInsidePopup) {
|
|
1631
1549
|
doc.addEventListener('mouseup', handleMouseUp, {
|
|
@@ -1634,7 +1552,7 @@ const ComboboxTrigger = /*#__PURE__*/React__namespace.forwardRef(function Combob
|
|
|
1634
1552
|
}
|
|
1635
1553
|
},
|
|
1636
1554
|
onKeyDown(event) {
|
|
1637
|
-
if (readOnly) {
|
|
1555
|
+
if (disabled || readOnly) {
|
|
1638
1556
|
return;
|
|
1639
1557
|
}
|
|
1640
1558
|
if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {
|
|
@@ -1643,7 +1561,7 @@ const ComboboxTrigger = /*#__PURE__*/React__namespace.forwardRef(function Combob
|
|
|
1643
1561
|
store.state.inputRef.current?.focus();
|
|
1644
1562
|
}
|
|
1645
1563
|
}
|
|
1646
|
-
}, validation.getValidationProps(disabled, elementProps), getButtonProps],
|
|
1564
|
+
}, validation ? validation.getValidationProps(disabled, elementProps) : elementProps, getButtonProps],
|
|
1647
1565
|
stateAttributesMapping: triggerStateAttributesMapping
|
|
1648
1566
|
});
|
|
1649
1567
|
return element;
|
|
@@ -1718,6 +1636,9 @@ const ComboboxInput = /*#__PURE__*/React__namespace.forwardRef(function Combobox
|
|
|
1718
1636
|
const positioning = useComboboxPositionerContext(true);
|
|
1719
1637
|
const hasPositionerParent = Boolean(positioning);
|
|
1720
1638
|
const store = useComboboxRootContext();
|
|
1639
|
+
const {
|
|
1640
|
+
filteredItems
|
|
1641
|
+
} = useComboboxDerivedItemsContext();
|
|
1721
1642
|
// `inputValue` can't be placed in the store.
|
|
1722
1643
|
// https://github.com/mui/base-ui/issues/2703
|
|
1723
1644
|
const inputValue = useComboboxInputValueContext();
|
|
@@ -1734,16 +1655,19 @@ const ComboboxInput = /*#__PURE__*/React__namespace.forwardRef(function Combobox
|
|
|
1734
1655
|
const open = useScrollLock.useStore(store, selectors.open);
|
|
1735
1656
|
const mounted = useScrollLock.useStore(store, selectors.mounted);
|
|
1736
1657
|
const selectedValue = useScrollLock.useStore(store, selectors.selectedValue);
|
|
1658
|
+
const popupSideValue = useScrollLock.useStore(store, selectors.popupSide);
|
|
1659
|
+
const positionerElement = useScrollLock.useStore(store, selectors.positionerElement);
|
|
1737
1660
|
const rootId = useScrollLock.useStore(store, selectors.id);
|
|
1738
1661
|
const inline = useScrollLock.useStore(store, selectors.inline);
|
|
1739
1662
|
const modal = useScrollLock.useStore(store, selectors.modal);
|
|
1740
1663
|
const autoHighlightEnabled = Boolean(autoHighlightMode);
|
|
1741
|
-
const popupSide =
|
|
1664
|
+
const popupSide = mounted && positionerElement ? popupSideValue : null;
|
|
1742
1665
|
const disabled = fieldDisabled || comboboxDisabled || disabledProp;
|
|
1743
|
-
const listEmpty =
|
|
1666
|
+
const listEmpty = filteredItems.length === 0;
|
|
1744
1667
|
const isInsidePopup = hasPositionerParent || inline;
|
|
1745
1668
|
const focusManagerModal = !isInsidePopup || modal;
|
|
1746
1669
|
const id = useScrollLock.useBaseUiId(idProp ?? (!isInsidePopup ? rootId : undefined));
|
|
1670
|
+
const ariaLabelledBy = useCompositeListItem.resolveAriaLabelledBy(fieldLabelId, undefined);
|
|
1747
1671
|
const fieldStateForInput = hasPositionerParent ? useCompositeListItem.DEFAULT_FIELD_STATE_ATTRIBUTES : fieldState;
|
|
1748
1672
|
const [composingValue, setComposingValue] = React__namespace.useState(null);
|
|
1749
1673
|
const isComposingRef = React__namespace.useRef(false);
|
|
@@ -1761,17 +1685,7 @@ const ComboboxInput = /*#__PURE__*/React__namespace.forwardRef(function Combobox
|
|
|
1761
1685
|
inputOwnsFormValue
|
|
1762
1686
|
});
|
|
1763
1687
|
});
|
|
1764
|
-
const validationProps = hasPositionerParent ? elementProps : validation.getValidationProps(disabled, elementProps);
|
|
1765
|
-
function clearHighlight() {
|
|
1766
|
-
store.state.setIndices({
|
|
1767
|
-
activeIndex: null,
|
|
1768
|
-
selectedIndex: null,
|
|
1769
|
-
type: store.state.keyboardActiveRef.current ? useScrollLock.keyboard : useScrollLock.pointer
|
|
1770
|
-
});
|
|
1771
|
-
}
|
|
1772
|
-
function markPointerActive() {
|
|
1773
|
-
store.state.keyboardActiveRef.current = false;
|
|
1774
|
-
}
|
|
1688
|
+
const validationProps = hasPositionerParent || !validation ? elementProps : validation.getValidationProps(disabled, elementProps);
|
|
1775
1689
|
const state = {
|
|
1776
1690
|
...fieldStateForInput,
|
|
1777
1691
|
open,
|
|
@@ -1789,7 +1703,9 @@ const ComboboxInput = /*#__PURE__*/React__namespace.forwardRef(function Combobox
|
|
|
1789
1703
|
highlightedChipIndex
|
|
1790
1704
|
} = comboboxChipsContext;
|
|
1791
1705
|
const renderedChipsCount = comboboxChipsContext.chipsRef.current.length;
|
|
1792
|
-
const
|
|
1706
|
+
const isRtl = direction === 'rtl';
|
|
1707
|
+
const previousChipKey = isRtl ? 'ArrowRight' : 'ArrowLeft';
|
|
1708
|
+
const nextChipKey = isRtl ? 'ArrowLeft' : 'ArrowRight';
|
|
1793
1709
|
if (highlightedChipIndex !== undefined) {
|
|
1794
1710
|
if (event.key === previousChipKey) {
|
|
1795
1711
|
event.preventDefault();
|
|
@@ -1808,8 +1724,14 @@ const ComboboxInput = /*#__PURE__*/React__namespace.forwardRef(function Combobox
|
|
|
1808
1724
|
} else if (event.key === 'Backspace' || event.key === 'Delete') {
|
|
1809
1725
|
event.preventDefault();
|
|
1810
1726
|
// Move highlight appropriately after removal.
|
|
1811
|
-
|
|
1812
|
-
|
|
1727
|
+
const computedNextIndex = highlightedChipIndex >= selectedValue.length - 1 ? selectedValue.length - 2 : highlightedChipIndex;
|
|
1728
|
+
// If the computed index is negative, treat it as no highlight.
|
|
1729
|
+
nextIndex = computedNextIndex >= 0 ? computedNextIndex : undefined;
|
|
1730
|
+
store.state.setIndices({
|
|
1731
|
+
activeIndex: null,
|
|
1732
|
+
selectedIndex: null,
|
|
1733
|
+
type: 'keyboard'
|
|
1734
|
+
});
|
|
1813
1735
|
}
|
|
1814
1736
|
return nextIndex;
|
|
1815
1737
|
}
|
|
@@ -1818,6 +1740,13 @@ const ComboboxInput = /*#__PURE__*/React__namespace.forwardRef(function Combobox
|
|
|
1818
1740
|
if (event.key === previousChipKey && (event.currentTarget.selectionStart ?? 0) === 0 && selectedValue.length > 0) {
|
|
1819
1741
|
event.preventDefault();
|
|
1820
1742
|
nextIndex = renderedChipsCount > 0 ? renderedChipsCount - 1 : undefined;
|
|
1743
|
+
} else if (event.key === 'Backspace' && event.currentTarget.value === '' && selectedValue.length > 0) {
|
|
1744
|
+
store.state.setIndices({
|
|
1745
|
+
activeIndex: null,
|
|
1746
|
+
selectedIndex: null,
|
|
1747
|
+
type: 'keyboard'
|
|
1748
|
+
});
|
|
1749
|
+
event.preventDefault();
|
|
1821
1750
|
}
|
|
1822
1751
|
return nextIndex;
|
|
1823
1752
|
}
|
|
@@ -1825,10 +1754,11 @@ const ComboboxInput = /*#__PURE__*/React__namespace.forwardRef(function Combobox
|
|
|
1825
1754
|
state,
|
|
1826
1755
|
ref: [forwardedRef, store.state.inputRef, setInputElement],
|
|
1827
1756
|
props: [inputProps, triggerProps, {
|
|
1828
|
-
|
|
1757
|
+
type: 'text',
|
|
1758
|
+
value: componentProps.value ?? composingValue ?? inputValue,
|
|
1829
1759
|
'aria-readonly': readOnly || undefined,
|
|
1830
1760
|
'aria-required': required || undefined,
|
|
1831
|
-
'aria-labelledby':
|
|
1761
|
+
'aria-labelledby': ariaLabelledBy,
|
|
1832
1762
|
disabled,
|
|
1833
1763
|
readOnly,
|
|
1834
1764
|
required: selectionMode === 'none' ? required : undefined,
|
|
@@ -1883,23 +1813,11 @@ const ComboboxInput = /*#__PURE__*/React__namespace.forwardRef(function Combobox
|
|
|
1883
1813
|
store.state.setInputValue(next, useScrollLock.createChangeEventDetails(useScrollLock.inputChange, event.nativeEvent));
|
|
1884
1814
|
},
|
|
1885
1815
|
onChange(event) {
|
|
1886
|
-
const nativeEvent = event.nativeEvent;
|
|
1887
1816
|
// Autofill may not provide `inputType` (Chrome) or may report
|
|
1888
1817
|
// `insertReplacementText` (Firefox).
|
|
1889
|
-
const inputType = nativeEvent.inputType;
|
|
1818
|
+
const inputType = event.nativeEvent.inputType;
|
|
1890
1819
|
const autofillLikeInput = !inputType || inputType === 'insertReplacementText';
|
|
1891
|
-
// During composition the input is always considered typed into.
|
|
1892
1820
|
const shouldOpenOnInput = isComposingRef.current || !autofillLikeInput;
|
|
1893
|
-
function maybeOpenOnInput(trimmed) {
|
|
1894
|
-
if (readOnly || disabled || !trimmed || !shouldOpenOnInput) {
|
|
1895
|
-
return;
|
|
1896
|
-
}
|
|
1897
|
-
store.state.setOpen(true, useScrollLock.createChangeEventDetails(useScrollLock.inputChange, nativeEvent));
|
|
1898
|
-
// When autoHighlight is enabled, keep the highlight (will be set to 0 in root).
|
|
1899
|
-
if (!autoHighlightEnabled) {
|
|
1900
|
-
clearHighlight();
|
|
1901
|
-
}
|
|
1902
|
-
}
|
|
1903
1821
|
|
|
1904
1822
|
// During IME composition, avoid propagating controlled updates to prevent
|
|
1905
1823
|
// filtering the options prematurely so `Empty` won't show incorrectly.
|
|
@@ -1911,23 +1829,38 @@ const ComboboxInput = /*#__PURE__*/React__namespace.forwardRef(function Combobox
|
|
|
1911
1829
|
const nextVal = event.currentTarget.value;
|
|
1912
1830
|
setComposingValue(nextVal);
|
|
1913
1831
|
if (nextVal === '' && !store.state.openOnInputClick && !store.state.inputInsidePopup) {
|
|
1914
|
-
store.state.setOpen(false, useScrollLock.createChangeEventDetails(useScrollLock.inputClear, nativeEvent));
|
|
1832
|
+
store.state.setOpen(false, useScrollLock.createChangeEventDetails(useScrollLock.inputClear, event.nativeEvent));
|
|
1915
1833
|
}
|
|
1916
1834
|
const trimmed = nextVal.trim();
|
|
1917
1835
|
const shouldMaintainHighlight = autoHighlightEnabled && trimmed !== '';
|
|
1918
|
-
|
|
1836
|
+
if (!readOnly && !disabled && trimmed) {
|
|
1837
|
+
if (shouldOpenOnInput) {
|
|
1838
|
+
store.state.setOpen(true, useScrollLock.createChangeEventDetails(useScrollLock.inputChange, event.nativeEvent));
|
|
1839
|
+
if (!autoHighlightEnabled) {
|
|
1840
|
+
store.state.setIndices({
|
|
1841
|
+
activeIndex: null,
|
|
1842
|
+
selectedIndex: null,
|
|
1843
|
+
type: store.state.keyboardActiveRef.current ? 'keyboard' : 'pointer'
|
|
1844
|
+
});
|
|
1845
|
+
}
|
|
1846
|
+
}
|
|
1847
|
+
}
|
|
1919
1848
|
if (open && store.state.activeIndex !== null && !shouldMaintainHighlight) {
|
|
1920
|
-
|
|
1849
|
+
store.state.setIndices({
|
|
1850
|
+
activeIndex: null,
|
|
1851
|
+
selectedIndex: null,
|
|
1852
|
+
type: store.state.keyboardActiveRef.current ? 'keyboard' : 'pointer'
|
|
1853
|
+
});
|
|
1921
1854
|
}
|
|
1922
1855
|
return;
|
|
1923
1856
|
}
|
|
1924
|
-
const inputChangeDetails = useScrollLock.createChangeEventDetails(useScrollLock.inputChange, nativeEvent);
|
|
1857
|
+
const inputChangeDetails = useScrollLock.createChangeEventDetails(useScrollLock.inputChange, event.nativeEvent);
|
|
1925
1858
|
store.state.setInputValue(event.currentTarget.value, inputChangeDetails);
|
|
1926
1859
|
if (inputChangeDetails.isCanceled) {
|
|
1927
1860
|
return;
|
|
1928
1861
|
}
|
|
1929
1862
|
const empty = event.currentTarget.value === '';
|
|
1930
|
-
const clearDetails = useScrollLock.createChangeEventDetails(useScrollLock.inputClear, nativeEvent);
|
|
1863
|
+
const clearDetails = useScrollLock.createChangeEventDetails(useScrollLock.inputClear, event.nativeEvent);
|
|
1931
1864
|
if (empty && !store.state.inputInsidePopup) {
|
|
1932
1865
|
if (selectionMode === 'single') {
|
|
1933
1866
|
store.state.setSelectedValue(null, clearDetails);
|
|
@@ -1936,13 +1869,30 @@ const ComboboxInput = /*#__PURE__*/React__namespace.forwardRef(function Combobox
|
|
|
1936
1869
|
store.state.setOpen(false, clearDetails);
|
|
1937
1870
|
}
|
|
1938
1871
|
}
|
|
1939
|
-
|
|
1872
|
+
const trimmed = event.currentTarget.value.trim();
|
|
1873
|
+
if (!readOnly && !disabled && trimmed) {
|
|
1874
|
+
if (shouldOpenOnInput) {
|
|
1875
|
+
store.state.setOpen(true, useScrollLock.createChangeEventDetails(useScrollLock.inputChange, event.nativeEvent));
|
|
1876
|
+
// When autoHighlight is enabled, keep the highlight (will be set to 0 in root).
|
|
1877
|
+
if (!autoHighlightEnabled) {
|
|
1878
|
+
store.state.setIndices({
|
|
1879
|
+
activeIndex: null,
|
|
1880
|
+
selectedIndex: null,
|
|
1881
|
+
type: store.state.keyboardActiveRef.current ? 'keyboard' : 'pointer'
|
|
1882
|
+
});
|
|
1883
|
+
}
|
|
1884
|
+
}
|
|
1885
|
+
}
|
|
1940
1886
|
|
|
1941
1887
|
// When the user types, ensure the list resets its highlight so that
|
|
1942
1888
|
// virtual focus returns to the input (aria-activedescendant is
|
|
1943
1889
|
// cleared).
|
|
1944
1890
|
if (open && store.state.activeIndex !== null && !autoHighlightEnabled) {
|
|
1945
|
-
|
|
1891
|
+
store.state.setIndices({
|
|
1892
|
+
activeIndex: null,
|
|
1893
|
+
selectedIndex: null,
|
|
1894
|
+
type: store.state.keyboardActiveRef.current ? 'keyboard' : 'pointer'
|
|
1895
|
+
});
|
|
1946
1896
|
}
|
|
1947
1897
|
},
|
|
1948
1898
|
onKeyDown(event) {
|
|
@@ -1988,7 +1938,11 @@ const ComboboxInput = /*#__PURE__*/React__namespace.forwardRef(function Combobox
|
|
|
1988
1938
|
const removalIndex = renderedChipsCount > 0 ? renderedChipsCount - 1 : selectedValue.length - 1;
|
|
1989
1939
|
const newValue = selectedValue.filter((_, index) => index !== removalIndex);
|
|
1990
1940
|
// If the removed item was also the active (highlighted) item, clear highlight
|
|
1991
|
-
|
|
1941
|
+
store.state.setIndices({
|
|
1942
|
+
activeIndex: null,
|
|
1943
|
+
selectedIndex: null,
|
|
1944
|
+
type: store.state.keyboardActiveRef.current ? 'keyboard' : 'pointer'
|
|
1945
|
+
});
|
|
1992
1946
|
store.state.setSelectedValue(newValue, useScrollLock.createChangeEventDetails(useScrollLock.none, event.nativeEvent));
|
|
1993
1947
|
return;
|
|
1994
1948
|
}
|
|
@@ -2018,11 +1972,20 @@ const ComboboxInput = /*#__PURE__*/React__namespace.forwardRef(function Combobox
|
|
|
2018
1972
|
return;
|
|
2019
1973
|
}
|
|
2020
1974
|
useScrollLock.stopEvent(event);
|
|
2021
|
-
|
|
1975
|
+
const listItem = store.state.listRef.current[activeIndex];
|
|
1976
|
+
if (listItem) {
|
|
1977
|
+
store.state.selectionEventRef.current = nativeEvent;
|
|
1978
|
+
listItem.click();
|
|
1979
|
+
store.state.selectionEventRef.current = null;
|
|
1980
|
+
}
|
|
2022
1981
|
}
|
|
2023
1982
|
},
|
|
2024
|
-
onPointerMove
|
|
2025
|
-
|
|
1983
|
+
onPointerMove() {
|
|
1984
|
+
store.state.keyboardActiveRef.current = false;
|
|
1985
|
+
},
|
|
1986
|
+
onPointerDown() {
|
|
1987
|
+
store.state.keyboardActiveRef.current = false;
|
|
1988
|
+
}
|
|
2026
1989
|
}, validationProps],
|
|
2027
1990
|
stateAttributesMapping: triggerStateAttributesMapping
|
|
2028
1991
|
});
|
|
@@ -2043,7 +2006,7 @@ function handleInputPress(event, store, disabled, readOnly, shouldIgnoreTarget)
|
|
|
2043
2006
|
return;
|
|
2044
2007
|
}
|
|
2045
2008
|
const target = useScrollLock.getTarget(event.nativeEvent);
|
|
2046
|
-
const targetElement =
|
|
2009
|
+
const targetElement = floatingUi_utils.isElement(target) ? target : null;
|
|
2047
2010
|
if (targetElement !== event.currentTarget && (shouldIgnoreTarget?.(targetElement) || useScrollLock.isInteractiveElement(targetElement))) {
|
|
2048
2011
|
return;
|
|
2049
2012
|
}
|
|
@@ -2074,14 +2037,20 @@ const ComboboxInputGroup = /*#__PURE__*/React__namespace.forwardRef(function Com
|
|
|
2074
2037
|
state: fieldState
|
|
2075
2038
|
} = useCompositeListItem.useFieldRootContext();
|
|
2076
2039
|
const store = useComboboxRootContext();
|
|
2040
|
+
const {
|
|
2041
|
+
filteredItems
|
|
2042
|
+
} = useComboboxDerivedItemsContext();
|
|
2077
2043
|
const open = useScrollLock.useStore(store, selectors.open);
|
|
2044
|
+
const mounted = useScrollLock.useStore(store, selectors.mounted);
|
|
2045
|
+
const popupSideValue = useScrollLock.useStore(store, selectors.popupSide);
|
|
2046
|
+
const positionerElement = useScrollLock.useStore(store, selectors.positionerElement);
|
|
2078
2047
|
const comboboxDisabled = useScrollLock.useStore(store, selectors.disabled);
|
|
2079
2048
|
const readOnly = useScrollLock.useStore(store, selectors.readOnly);
|
|
2080
2049
|
const hasSelectedValue = useScrollLock.useStore(store, selectors.hasSelectedValue);
|
|
2081
2050
|
const selectionMode = useScrollLock.useStore(store, selectors.selectionMode);
|
|
2082
|
-
const popupSide =
|
|
2051
|
+
const popupSide = mounted && positionerElement ? popupSideValue : null;
|
|
2083
2052
|
const disabled = comboboxDisabled;
|
|
2084
|
-
const listEmpty =
|
|
2053
|
+
const listEmpty = filteredItems.length === 0;
|
|
2085
2054
|
const placeholder = selectionMode === 'none' ? false : !hasSelectedValue;
|
|
2086
2055
|
const state = {
|
|
2087
2056
|
...fieldState,
|
|
@@ -2217,21 +2186,19 @@ const ComboboxClear = /*#__PURE__*/React__namespace.forwardRef(function Combobox
|
|
|
2217
2186
|
if (disabled || readOnly) {
|
|
2218
2187
|
return;
|
|
2219
2188
|
}
|
|
2220
|
-
const
|
|
2189
|
+
const keyboardActiveRef = store.state.keyboardActiveRef;
|
|
2221
2190
|
store.state.setInputValue('', useScrollLock.createChangeEventDetails(useScrollLock.clearPress, event.nativeEvent));
|
|
2222
2191
|
if (selectionMode !== 'none') {
|
|
2223
2192
|
store.state.setSelectedValue(Array.isArray(selectedValue) ? [] : null, useScrollLock.createChangeEventDetails(useScrollLock.clearPress, event.nativeEvent));
|
|
2224
|
-
// A distinct object shape: `Store.update` iterates own keys, so passing an explicit
|
|
2225
|
-
// `selectedIndex: undefined` would overwrite the state instead of leaving it alone.
|
|
2226
2193
|
store.state.setIndices({
|
|
2227
2194
|
activeIndex: null,
|
|
2228
2195
|
selectedIndex: null,
|
|
2229
|
-
type
|
|
2196
|
+
type: keyboardActiveRef.current ? 'keyboard' : 'pointer'
|
|
2230
2197
|
});
|
|
2231
2198
|
} else {
|
|
2232
2199
|
store.state.setIndices({
|
|
2233
2200
|
activeIndex: null,
|
|
2234
|
-
type
|
|
2201
|
+
type: keyboardActiveRef.current ? 'keyboard' : 'pointer'
|
|
2235
2202
|
});
|
|
2236
2203
|
}
|
|
2237
2204
|
store.state.inputRef.current?.focus();
|
|
@@ -2275,6 +2242,9 @@ function ComboboxCollection(props) {
|
|
|
2275
2242
|
} = useComboboxDerivedItemsContext();
|
|
2276
2243
|
const groupContext = useGroupCollectionContext();
|
|
2277
2244
|
const itemsToRender = groupContext ? groupContext.items : filteredItems;
|
|
2245
|
+
if (!itemsToRender) {
|
|
2246
|
+
return null;
|
|
2247
|
+
}
|
|
2278
2248
|
return /*#__PURE__*/jsxRuntime.jsx(React__namespace.Fragment, {
|
|
2279
2249
|
children: itemsToRender.map(children)
|
|
2280
2250
|
});
|
|
@@ -2298,7 +2268,7 @@ const ComboboxList = /*#__PURE__*/React__namespace.forwardRef(function ComboboxL
|
|
|
2298
2268
|
} = useComboboxDerivedItemsContext();
|
|
2299
2269
|
const selectionMode = useScrollLock.useStore(store, selectors.selectionMode);
|
|
2300
2270
|
const grid = useScrollLock.useStore(store, selectors.grid);
|
|
2301
|
-
const
|
|
2271
|
+
const popupProps = useScrollLock.useStore(store, selectors.popupProps);
|
|
2302
2272
|
const virtualized = useScrollLock.useStore(store, selectors.virtualized);
|
|
2303
2273
|
const forceMounted = useScrollLock.useStore(store, selectors.forceMounted);
|
|
2304
2274
|
const multiple = selectionMode === 'multiple';
|
|
@@ -2312,7 +2282,7 @@ const ComboboxList = /*#__PURE__*/React__namespace.forwardRef(function ComboboxL
|
|
|
2312
2282
|
|
|
2313
2283
|
// Support "closed template" API: if children is a function, implicitly wrap it
|
|
2314
2284
|
// with a Combobox.Collection that reads items from context/root.
|
|
2315
|
-
// Ensures this component's `
|
|
2285
|
+
// Ensures this component's `popupProps` subscription does not cause <Combobox.Item>
|
|
2316
2286
|
// to re-render on every active index change.
|
|
2317
2287
|
const resolvedChildren = React__namespace.useMemo(() => {
|
|
2318
2288
|
if (typeof children === 'function') {
|
|
@@ -2329,7 +2299,7 @@ const ComboboxList = /*#__PURE__*/React__namespace.forwardRef(function ComboboxL
|
|
|
2329
2299
|
const element = useRenderElement.useRenderElement('div', componentProps, {
|
|
2330
2300
|
state,
|
|
2331
2301
|
ref: [forwardedRef, setListElement, hasPositionerContext ? null : setPositionerElement],
|
|
2332
|
-
props: [
|
|
2302
|
+
props: [popupProps, {
|
|
2333
2303
|
children: resolvedChildren,
|
|
2334
2304
|
tabIndex: -1,
|
|
2335
2305
|
id: floatingId,
|
|
@@ -2346,7 +2316,13 @@ const ComboboxList = /*#__PURE__*/React__namespace.forwardRef(function ComboboxL
|
|
|
2346
2316
|
return;
|
|
2347
2317
|
}
|
|
2348
2318
|
useScrollLock.stopEvent(event);
|
|
2349
|
-
|
|
2319
|
+
const nativeEvent = event.nativeEvent;
|
|
2320
|
+
const listItem = store.state.listRef.current[activeIndex];
|
|
2321
|
+
if (listItem) {
|
|
2322
|
+
store.state.selectionEventRef.current = nativeEvent;
|
|
2323
|
+
listItem.click();
|
|
2324
|
+
store.state.selectionEventRef.current = null;
|
|
2325
|
+
}
|
|
2350
2326
|
}
|
|
2351
2327
|
},
|
|
2352
2328
|
onKeyDownCapture() {
|
|
@@ -2405,7 +2381,7 @@ function useInitialLiveRegionTextMutation() {
|
|
|
2405
2381
|
if (textNode == null) {
|
|
2406
2382
|
return undefined;
|
|
2407
2383
|
}
|
|
2408
|
-
const originalValue = textNode.
|
|
2384
|
+
const originalValue = textNode.nodeValue ?? '';
|
|
2409
2385
|
const markedValue = `${originalValue}${LIVE_REGION_MARKER}`;
|
|
2410
2386
|
textNode.nodeValue = markedValue;
|
|
2411
2387
|
timeout.start(INITIAL_LIVE_REGION_TEXT_MUTATION_RESET_DELAY, () => {
|
|
@@ -2534,23 +2510,24 @@ const ComboboxPositioner = /*#__PURE__*/React__namespace.forwardRef(function Com
|
|
|
2534
2510
|
render,
|
|
2535
2511
|
className,
|
|
2536
2512
|
anchor,
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
sideOffset,
|
|
2543
|
-
alignOffset,
|
|
2513
|
+
positionMethod = 'absolute',
|
|
2514
|
+
side = 'bottom',
|
|
2515
|
+
align = 'center',
|
|
2516
|
+
sideOffset = 0,
|
|
2517
|
+
alignOffset = 0,
|
|
2544
2518
|
collisionBoundary = 'clipping-ancestors',
|
|
2545
|
-
collisionPadding,
|
|
2546
|
-
arrowPadding,
|
|
2547
|
-
sticky,
|
|
2519
|
+
collisionPadding = 5,
|
|
2520
|
+
arrowPadding = 5,
|
|
2521
|
+
sticky = false,
|
|
2548
2522
|
disableAnchorTracking = false,
|
|
2549
2523
|
collisionAvoidance = useScrollLock.DROPDOWN_COLLISION_AVOIDANCE,
|
|
2550
2524
|
style: styleProp,
|
|
2551
2525
|
...elementProps
|
|
2552
2526
|
} = componentProps;
|
|
2553
2527
|
const store = useComboboxRootContext();
|
|
2528
|
+
const {
|
|
2529
|
+
filteredItems
|
|
2530
|
+
} = useComboboxDerivedItemsContext();
|
|
2554
2531
|
const floatingRootContext = useComboboxFloatingContext();
|
|
2555
2532
|
const keepMounted = useComboboxPortalContext();
|
|
2556
2533
|
const modal = useScrollLock.useStore(store, selectors.modal);
|
|
@@ -2563,7 +2540,7 @@ const ComboboxPositioner = /*#__PURE__*/React__namespace.forwardRef(function Com
|
|
|
2563
2540
|
const inputGroupElement = useScrollLock.useStore(store, selectors.inputGroupElement);
|
|
2564
2541
|
const inputInsidePopup = useScrollLock.useStore(store, selectors.inputInsidePopup);
|
|
2565
2542
|
const transitionStatus = useScrollLock.useStore(store, selectors.transitionStatus);
|
|
2566
|
-
const empty =
|
|
2543
|
+
const empty = filteredItems.length === 0;
|
|
2567
2544
|
const resolvedAnchor = anchor ?? (inputInsidePopup ? triggerElement : inputGroupElement ?? inputElement);
|
|
2568
2545
|
const positioning = useCompositeListItem.useAnchorPositioning({
|
|
2569
2546
|
anchor: resolvedAnchor,
|
|
@@ -2638,16 +2615,18 @@ const ComboboxPopup = /*#__PURE__*/React__namespace.forwardRef(function Combobox
|
|
|
2638
2615
|
const store = useComboboxRootContext();
|
|
2639
2616
|
const positioning = useComboboxPositionerContext();
|
|
2640
2617
|
const floatingRootContext = useComboboxFloatingContext();
|
|
2618
|
+
const {
|
|
2619
|
+
filteredItems
|
|
2620
|
+
} = useComboboxDerivedItemsContext();
|
|
2641
2621
|
const mounted = useScrollLock.useStore(store, selectors.mounted);
|
|
2642
2622
|
const open = useScrollLock.useStore(store, selectors.open);
|
|
2643
2623
|
const openMethod = useScrollLock.useStore(store, selectors.openMethod);
|
|
2644
|
-
const popupProps = useScrollLock.useStore(store, selectors.popupProps);
|
|
2645
2624
|
const transitionStatus = useScrollLock.useStore(store, selectors.transitionStatus);
|
|
2646
2625
|
const inputInsidePopup = useScrollLock.useStore(store, selectors.inputInsidePopup);
|
|
2647
2626
|
const inputElement = useScrollLock.useStore(store, selectors.inputElement);
|
|
2648
2627
|
const modal = useScrollLock.useStore(store, selectors.modal);
|
|
2649
2628
|
const rootId = useScrollLock.useStore(store, selectors.id);
|
|
2650
|
-
const empty =
|
|
2629
|
+
const empty = filteredItems.length === 0;
|
|
2651
2630
|
const popupId = elementProps.id ?? (inputInsidePopup ? getComboboxPopupId(rootId) : undefined);
|
|
2652
2631
|
useScrollLock.useIsoLayoutEffect(() => {
|
|
2653
2632
|
// Prefer the rendered DOM id, which a `render` prop element or function may override.
|
|
@@ -2676,9 +2655,10 @@ const ComboboxPopup = /*#__PURE__*/React__namespace.forwardRef(function Combobox
|
|
|
2676
2655
|
const element = useRenderElement.useRenderElement('div', componentProps, {
|
|
2677
2656
|
state,
|
|
2678
2657
|
ref: [forwardedRef, store.state.popupRef],
|
|
2679
|
-
props: [
|
|
2658
|
+
props: [{
|
|
2680
2659
|
id: popupId,
|
|
2681
2660
|
role: inputInsidePopup ? 'dialog' : 'presentation',
|
|
2661
|
+
tabIndex: -1,
|
|
2682
2662
|
onFocus(event) {
|
|
2683
2663
|
const target = useScrollLock.getTarget(event.nativeEvent);
|
|
2684
2664
|
if (openMethod !== 'touch' && (useScrollLock.contains(store.state.listElement, target) || target === event.currentTarget)) {
|
|
@@ -2825,7 +2805,7 @@ const ComboboxGroupLabel = /*#__PURE__*/React__namespace.forwardRef(function Com
|
|
|
2825
2805
|
useScrollLock.useIsoLayoutEffect(() => {
|
|
2826
2806
|
setLabelId(id);
|
|
2827
2807
|
return () => {
|
|
2828
|
-
setLabelId(
|
|
2808
|
+
setLabelId(undefined);
|
|
2829
2809
|
};
|
|
2830
2810
|
}, [id, setLabelId]);
|
|
2831
2811
|
const element = useRenderElement.useRenderElement('div', componentProps, {
|
|
@@ -2867,27 +2847,27 @@ function ComboboxItemInner(props) {
|
|
|
2867
2847
|
style,
|
|
2868
2848
|
value: itemValue = null,
|
|
2869
2849
|
index: indexProp,
|
|
2870
|
-
disabled
|
|
2850
|
+
disabled = false,
|
|
2871
2851
|
nativeButton = false,
|
|
2872
2852
|
...elementProps
|
|
2873
2853
|
} = componentProps;
|
|
2854
|
+
const didPointerDownRef = React__namespace.useRef(false);
|
|
2874
2855
|
const textRef = React__namespace.useRef(null);
|
|
2875
2856
|
const listItem = useCompositeListItem.useCompositeListItem({
|
|
2876
|
-
guess: true,
|
|
2877
2857
|
index: indexProp,
|
|
2878
|
-
textRef
|
|
2858
|
+
textRef,
|
|
2859
|
+
indexGuessBehavior: useCompositeListItem.IndexGuessBehavior.GuessFromOrder
|
|
2879
2860
|
});
|
|
2880
2861
|
const store = useComboboxRootContext();
|
|
2881
2862
|
const isRow = useComboboxRowContext();
|
|
2882
2863
|
const hasItems = useComboboxHasItemsContext();
|
|
2864
|
+
const open = useScrollLock.useStore(store, selectors.open);
|
|
2883
2865
|
const selectionMode = useScrollLock.useStore(store, selectors.selectionMode);
|
|
2884
|
-
const rootDisabled = useScrollLock.useStore(store, selectors.disabled);
|
|
2885
2866
|
const readOnly = useScrollLock.useStore(store, selectors.readOnly);
|
|
2886
2867
|
const isItemEqualToValue = useScrollLock.useStore(store, selectors.isItemEqualToValue);
|
|
2887
|
-
const disabled = rootDisabled || disabledProp;
|
|
2888
2868
|
const selectable = selectionMode !== 'none';
|
|
2889
|
-
const index = indexProp ?? indexFromFilter ?? listItem.index;
|
|
2890
|
-
const hasRegistered = index !== -1;
|
|
2869
|
+
const index = indexProp ?? (virtualized ? indexFromFilter ?? -1 : listItem.index);
|
|
2870
|
+
const hasRegistered = listItem.index !== -1;
|
|
2891
2871
|
const rootId = useScrollLock.useStore(store, selectors.id);
|
|
2892
2872
|
const highlighted = useScrollLock.useStore(store, selectors.isActive, index);
|
|
2893
2873
|
const matchesSelectedValue = useScrollLock.useStore(store, selectors.isSelected, itemValue);
|
|
@@ -2912,24 +2892,31 @@ function ComboboxItemInner(props) {
|
|
|
2912
2892
|
}
|
|
2913
2893
|
const visibleMap = store.state.valuesRef.current;
|
|
2914
2894
|
visibleMap[index] = itemValue;
|
|
2895
|
+
|
|
2896
|
+
// Stable registry that doesn't depend on filtering. Assume that no
|
|
2897
|
+
// filtering had occurred at this point; otherwise, an `items` prop is
|
|
2898
|
+
// required.
|
|
2899
|
+
if (selectionMode !== 'none') {
|
|
2900
|
+
store.state.allValuesRef.current.push(itemValue);
|
|
2901
|
+
}
|
|
2915
2902
|
return () => {
|
|
2916
2903
|
delete visibleMap[index];
|
|
2917
2904
|
};
|
|
2918
|
-
}, [hasRegistered, hasItems, index, itemValue, store]);
|
|
2905
|
+
}, [hasRegistered, hasItems, index, itemValue, store, selectionMode]);
|
|
2919
2906
|
useScrollLock.useIsoLayoutEffect(() => {
|
|
2907
|
+
if (!open) {
|
|
2908
|
+
didPointerDownRef.current = false;
|
|
2909
|
+
return;
|
|
2910
|
+
}
|
|
2920
2911
|
if (!hasRegistered || hasItems) {
|
|
2921
2912
|
return;
|
|
2922
2913
|
}
|
|
2923
|
-
|
|
2924
|
-
// Runs while closed as well (the list can stay mounted via `keepMounted` or a
|
|
2925
|
-
// force-mount) so the index tracks the item's composite position, keeping features
|
|
2926
|
-
// like closed-trigger typeahead in sync when the rendered order changes.
|
|
2927
2914
|
const selectedValue = store.state.selectedValue;
|
|
2928
2915
|
const lastSelectedValue = Array.isArray(selectedValue) ? selectedValue[selectedValue.length - 1] : selectedValue;
|
|
2929
2916
|
if (useCompositeListItem.compareItemEquality(itemValue, lastSelectedValue, isItemEqualToValue)) {
|
|
2930
2917
|
store.set('selectedIndex', index);
|
|
2931
2918
|
}
|
|
2932
|
-
}, [hasRegistered, hasItems, store, index, itemValue, isItemEqualToValue]);
|
|
2919
|
+
}, [hasRegistered, hasItems, open, store, index, itemValue, isItemEqualToValue]);
|
|
2933
2920
|
const {
|
|
2934
2921
|
getButtonProps,
|
|
2935
2922
|
buttonRef
|
|
@@ -2964,12 +2951,7 @@ function ComboboxItemInner(props) {
|
|
|
2964
2951
|
// as it should be a `<div>` instead.
|
|
2965
2952
|
tabIndex: undefined,
|
|
2966
2953
|
onPointerDownCapture(event) {
|
|
2967
|
-
|
|
2968
|
-
// touch must not overwrite the shared ref — a mismatch would make the primary
|
|
2969
|
-
// pointer's release read as a drag-select and commit a second time after `click`.
|
|
2970
|
-
if (event.isPrimary) {
|
|
2971
|
-
store.state.pointerDownItemRef.current = event.currentTarget;
|
|
2972
|
-
}
|
|
2954
|
+
didPointerDownRef.current = true;
|
|
2973
2955
|
event.preventDefault();
|
|
2974
2956
|
},
|
|
2975
2957
|
onMouseDown(event) {
|
|
@@ -2984,8 +2966,8 @@ function ComboboxItemInner(props) {
|
|
|
2984
2966
|
commitSelection(event.nativeEvent);
|
|
2985
2967
|
},
|
|
2986
2968
|
onMouseUp(event) {
|
|
2987
|
-
const pointerStartedOnItem =
|
|
2988
|
-
|
|
2969
|
+
const pointerStartedOnItem = didPointerDownRef.current;
|
|
2970
|
+
didPointerDownRef.current = false;
|
|
2989
2971
|
if (disabled || readOnly || event.button !== 0 || pointerStartedOnItem || !highlighted) {
|
|
2990
2972
|
return;
|
|
2991
2973
|
}
|
|
@@ -3121,33 +3103,6 @@ const ComboboxEmpty = /*#__PURE__*/React__namespace.forwardRef(function Combobox
|
|
|
3121
3103
|
});
|
|
3122
3104
|
if (process.env.NODE_ENV !== "production") ComboboxEmpty.displayName = "ComboboxEmpty";
|
|
3123
3105
|
|
|
3124
|
-
/**
|
|
3125
|
-
* A visual separator between items.
|
|
3126
|
-
* Renders a `<div>` element.
|
|
3127
|
-
*
|
|
3128
|
-
* @internal
|
|
3129
|
-
*/
|
|
3130
|
-
const ListboxSeparator = /*#__PURE__*/React__namespace.forwardRef(function ListboxSeparator(componentProps, forwardedRef) {
|
|
3131
|
-
const {
|
|
3132
|
-
className,
|
|
3133
|
-
render,
|
|
3134
|
-
orientation = 'horizontal',
|
|
3135
|
-
style,
|
|
3136
|
-
...elementProps
|
|
3137
|
-
} = componentProps;
|
|
3138
|
-
const state = {
|
|
3139
|
-
orientation
|
|
3140
|
-
};
|
|
3141
|
-
return useRenderElement.useRenderElement('div', componentProps, {
|
|
3142
|
-
state,
|
|
3143
|
-
ref: forwardedRef,
|
|
3144
|
-
props: [{
|
|
3145
|
-
role: 'presentation'
|
|
3146
|
-
}, elementProps]
|
|
3147
|
-
});
|
|
3148
|
-
});
|
|
3149
|
-
if (process.env.NODE_ENV !== "production") ListboxSeparator.displayName = "ListboxSeparator";
|
|
3150
|
-
|
|
3151
3106
|
/**
|
|
3152
3107
|
* Returns the internally filtered items.
|
|
3153
3108
|
*/
|
|
@@ -3214,8 +3169,7 @@ const ComboboxLabel = /*#__PURE__*/React__namespace.forwardRef(function Combobox
|
|
|
3214
3169
|
id: defaultLabelId,
|
|
3215
3170
|
fallbackControlId: localControlId,
|
|
3216
3171
|
setLabelId(nextLabelId) {
|
|
3217
|
-
|
|
3218
|
-
store.set('labelId', resolvedLabelId);
|
|
3172
|
+
store.set('labelId', nextLabelId);
|
|
3219
3173
|
}
|
|
3220
3174
|
});
|
|
3221
3175
|
return useRenderElement.useRenderElement('div', componentProps, {
|
|
@@ -3258,10 +3212,11 @@ function ComboboxValue(props) {
|
|
|
3258
3212
|
}
|
|
3259
3213
|
|
|
3260
3214
|
const ComboboxItemIndicator = /*#__PURE__*/React__namespace.forwardRef(function ComboboxItemIndicator(componentProps, forwardedRef) {
|
|
3215
|
+
const keepMounted = componentProps.keepMounted ?? false;
|
|
3261
3216
|
const {
|
|
3262
3217
|
selected
|
|
3263
3218
|
} = useComboboxItemContext();
|
|
3264
|
-
const shouldRender =
|
|
3219
|
+
const shouldRender = keepMounted || selected;
|
|
3265
3220
|
if (!shouldRender) {
|
|
3266
3221
|
return null;
|
|
3267
3222
|
}
|
|
@@ -3391,7 +3346,9 @@ const ComboboxChip = /*#__PURE__*/React__namespace.forwardRef(function ComboboxC
|
|
|
3391
3346
|
} = useCompositeListItem.useCompositeListItem();
|
|
3392
3347
|
function handleKeyDown(event) {
|
|
3393
3348
|
let nextIndex = index;
|
|
3394
|
-
const
|
|
3349
|
+
const isRtl = direction === 'rtl';
|
|
3350
|
+
const previousChipKey = isRtl ? 'ArrowRight' : 'ArrowLeft';
|
|
3351
|
+
const nextChipKey = isRtl ? 'ArrowLeft' : 'ArrowRight';
|
|
3395
3352
|
if (event.key === previousChipKey) {
|
|
3396
3353
|
event.preventDefault();
|
|
3397
3354
|
if (index > 0) {
|
|
@@ -3407,12 +3364,13 @@ const ComboboxChip = /*#__PURE__*/React__namespace.forwardRef(function ComboboxC
|
|
|
3407
3364
|
nextIndex = undefined;
|
|
3408
3365
|
}
|
|
3409
3366
|
} else if (event.key === 'Backspace' || event.key === 'Delete') {
|
|
3410
|
-
|
|
3367
|
+
const computedNextIndex = index >= selectedValue.length - 1 ? selectedValue.length - 2 : index;
|
|
3368
|
+
nextIndex = computedNextIndex >= 0 ? computedNextIndex : undefined;
|
|
3411
3369
|
useScrollLock.stopEvent(event);
|
|
3412
3370
|
store.state.setIndices({
|
|
3413
3371
|
activeIndex: null,
|
|
3414
3372
|
selectedIndex: null,
|
|
3415
|
-
type:
|
|
3373
|
+
type: 'keyboard'
|
|
3416
3374
|
});
|
|
3417
3375
|
store.state.setSelectedValue(selectedValue.filter((_, i) => i !== index), useScrollLock.createChangeEventDetails(useScrollLock.none, event.nativeEvent));
|
|
3418
3376
|
} else if (event.key === 'Enter' || event.key === ' ') {
|
|
@@ -3512,7 +3470,7 @@ const ComboboxChipRemove = /*#__PURE__*/React__namespace.forwardRef(function Com
|
|
|
3512
3470
|
if (removedIndex !== -1 && activeIndex === removedIndex) {
|
|
3513
3471
|
store.state.setIndices({
|
|
3514
3472
|
activeIndex: null,
|
|
3515
|
-
type: store.state.keyboardActiveRef.current ?
|
|
3473
|
+
type: store.state.keyboardActiveRef.current ? 'keyboard' : 'pointer'
|
|
3516
3474
|
});
|
|
3517
3475
|
}
|
|
3518
3476
|
}
|
|
@@ -3533,12 +3491,18 @@ const ComboboxChipRemove = /*#__PURE__*/React__namespace.forwardRef(function Com
|
|
|
3533
3491
|
event.preventDefault();
|
|
3534
3492
|
},
|
|
3535
3493
|
onClick(event) {
|
|
3494
|
+
if (disabled || readOnly) {
|
|
3495
|
+
return;
|
|
3496
|
+
}
|
|
3536
3497
|
const eventDetails = removeChip(event);
|
|
3537
3498
|
if (!eventDetails.isPropagationAllowed) {
|
|
3538
3499
|
event.stopPropagation();
|
|
3539
3500
|
}
|
|
3540
3501
|
},
|
|
3541
3502
|
onKeyDown(event) {
|
|
3503
|
+
if (disabled || readOnly) {
|
|
3504
|
+
return;
|
|
3505
|
+
}
|
|
3542
3506
|
if (event.key === 'Enter' || event.key === ' ') {
|
|
3543
3507
|
const eventDetails = removeChip(event);
|
|
3544
3508
|
if (!eventDetails.isPropagationAllowed) {
|
|
@@ -3552,14 +3516,6 @@ const ComboboxChipRemove = /*#__PURE__*/React__namespace.forwardRef(function Com
|
|
|
3552
3516
|
});
|
|
3553
3517
|
if (process.env.NODE_ENV !== "production") ComboboxChipRemove.displayName = "ComboboxChipRemove";
|
|
3554
3518
|
|
|
3555
|
-
/**
|
|
3556
|
-
* A visual separator between items or groups.
|
|
3557
|
-
* Renders a `<div>` element.
|
|
3558
|
-
*
|
|
3559
|
-
* Documentation: [Base UI Combobox](https://base-ui.com/react/components/combobox)
|
|
3560
|
-
*/
|
|
3561
|
-
const ComboboxSeparator = ListboxSeparator;
|
|
3562
|
-
|
|
3563
3519
|
exports.AriaCombobox = AriaCombobox;
|
|
3564
3520
|
exports.ComboboxArrow = ComboboxArrow;
|
|
3565
3521
|
exports.ComboboxBackdrop = ComboboxBackdrop;
|
|
@@ -3583,11 +3539,9 @@ exports.ComboboxPortal = ComboboxPortal;
|
|
|
3583
3539
|
exports.ComboboxPositioner = ComboboxPositioner;
|
|
3584
3540
|
exports.ComboboxRoot = ComboboxRoot;
|
|
3585
3541
|
exports.ComboboxRow = ComboboxRow;
|
|
3586
|
-
exports.ComboboxSeparator = ComboboxSeparator;
|
|
3587
3542
|
exports.ComboboxStatus = ComboboxStatus;
|
|
3588
3543
|
exports.ComboboxTrigger = ComboboxTrigger;
|
|
3589
3544
|
exports.ComboboxValue = ComboboxValue;
|
|
3590
|
-
exports.ListboxSeparator = ListboxSeparator;
|
|
3591
3545
|
exports.useComboboxFilter = useComboboxFilter;
|
|
3592
3546
|
exports.useComboboxInputValueContext = useComboboxInputValueContext;
|
|
3593
3547
|
exports.useCoreFilter = useCoreFilter;
|