@entur/dropdown 7.3.11 → 8.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Dropdown.d.ts +1 -7
- package/dist/MultiSelect.d.ts +4 -4
- package/dist/SearchableDropdown.d.ts +4 -4
- package/dist/components/DropdownList.d.ts +4 -5
- package/dist/components/FieldComponents.d.ts +1 -1
- package/dist/dropdown.cjs.js +339 -345
- package/dist/dropdown.cjs.js.map +1 -1
- package/dist/dropdown.esm.js +340 -346
- package/dist/dropdown.esm.js.map +1 -1
- package/dist/styles.css +4 -1
- package/dist/utils.d.ts +7 -1
- package/package.json +4 -4
package/dist/dropdown.cjs.js
CHANGED
|
@@ -16,21 +16,21 @@ const loader = require("@entur/loader");
|
|
|
16
16
|
const tooltip = require("@entur/tooltip");
|
|
17
17
|
const DropdownList = ({
|
|
18
18
|
ariaLabelChosenSingular = "valgt",
|
|
19
|
-
ariaLabelSelectedItem = ", valgt element
|
|
19
|
+
ariaLabelSelectedItem = ", valgt element",
|
|
20
20
|
getItemProps,
|
|
21
|
-
getMenuProps,
|
|
22
21
|
isOpen,
|
|
23
22
|
highlightedIndex,
|
|
24
23
|
listItems,
|
|
25
24
|
floatingStyles,
|
|
26
|
-
|
|
25
|
+
innerRef,
|
|
27
26
|
loading = false,
|
|
28
27
|
loadingText = "Laster inn …",
|
|
29
28
|
noMatchesText = "Ingen treff for søket",
|
|
29
|
+
readOnly = false,
|
|
30
30
|
selectAllCheckboxState,
|
|
31
31
|
selectAllItem,
|
|
32
32
|
selectedItems,
|
|
33
|
-
|
|
33
|
+
style,
|
|
34
34
|
...rest
|
|
35
35
|
}) => {
|
|
36
36
|
const isMultiselect = selectAllItem !== void 0;
|
|
@@ -43,7 +43,7 @@ const DropdownList = ({
|
|
|
43
43
|
return true;
|
|
44
44
|
});
|
|
45
45
|
const ariaValuesSelectAll = () => {
|
|
46
|
-
switch (selectAllCheckboxState
|
|
46
|
+
switch (selectAllCheckboxState) {
|
|
47
47
|
case "indeterminate": {
|
|
48
48
|
return {
|
|
49
49
|
label: `${selectAllItem?.label}, delvis valgt`,
|
|
@@ -66,7 +66,7 @@ const DropdownList = ({
|
|
|
66
66
|
form.Checkbox,
|
|
67
67
|
{
|
|
68
68
|
"aria-hidden": "true",
|
|
69
|
-
checked: selectAllCheckboxState
|
|
69
|
+
checked: selectAllCheckboxState,
|
|
70
70
|
className: "eds-dropdown__list__item__checkbox",
|
|
71
71
|
tabIndex: -1,
|
|
72
72
|
onChange: () => void 0
|
|
@@ -113,75 +113,68 @@ const DropdownList = ({
|
|
|
113
113
|
}) : null
|
|
114
114
|
] });
|
|
115
115
|
};
|
|
116
|
-
return (
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
"
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
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
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
},
|
|
179
|
-
key
|
|
180
|
-
);
|
|
181
|
-
});
|
|
182
|
-
})()
|
|
183
|
-
}
|
|
184
|
-
)
|
|
116
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
117
|
+
"ul",
|
|
118
|
+
{
|
|
119
|
+
className: "eds-dropdown__list",
|
|
120
|
+
ref: innerRef,
|
|
121
|
+
style: {
|
|
122
|
+
display: isOpen && !readOnly ? void 0 : "none",
|
|
123
|
+
...floatingStyles,
|
|
124
|
+
...style
|
|
125
|
+
},
|
|
126
|
+
...rest,
|
|
127
|
+
children: (() => {
|
|
128
|
+
if (!isOpen || readOnly) return null;
|
|
129
|
+
if (loading) {
|
|
130
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
131
|
+
"li",
|
|
132
|
+
{
|
|
133
|
+
className: "eds-dropdown__list__item",
|
|
134
|
+
children: loadingText
|
|
135
|
+
},
|
|
136
|
+
"dropdown-list-loading"
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
if (isNoMatches) {
|
|
140
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
141
|
+
"li",
|
|
142
|
+
{
|
|
143
|
+
className: "eds-dropdown__list__item",
|
|
144
|
+
children: noMatchesText
|
|
145
|
+
},
|
|
146
|
+
"dropdown-list-no-match"
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
return listItems.map((item, index) => {
|
|
150
|
+
const key = item.itemKey ?? `${item.label ?? ""}-${item.value ?? ""}-${(item.icons ?? []).map((icon) => icon?.displayName ?? icon?.name ?? "unknown").join("-")}`;
|
|
151
|
+
const itemIsSelectAll = item.value === selectAllItem?.value;
|
|
152
|
+
if (itemIsSelectAll && listItems.length <= 2) return null;
|
|
153
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
154
|
+
"li",
|
|
155
|
+
{
|
|
156
|
+
className: classNames("eds-dropdown__list__item", {
|
|
157
|
+
"eds-dropdown__list__item--select-all": itemIsSelectAll,
|
|
158
|
+
"eds-dropdown__list__item--highlighted": highlightedIndex === index,
|
|
159
|
+
"eds-dropdown__list__item--selected": !isMultiselect && isItemSelected(item)
|
|
160
|
+
}),
|
|
161
|
+
...getItemProps({
|
|
162
|
+
// @ts-expect-error Since getItemProps expects the same item type
|
|
163
|
+
// here as items, it throws error when selectAllItem is a string.
|
|
164
|
+
// This does, however, not cause any functional issues.
|
|
165
|
+
item,
|
|
166
|
+
index,
|
|
167
|
+
"aria-selected": itemIsSelectAll ? ariaValuesSelectAll().selected : isItemSelected(item)
|
|
168
|
+
}),
|
|
169
|
+
children: itemIsSelectAll ? selectAllListItemContent() : listItemContent(
|
|
170
|
+
item
|
|
171
|
+
)
|
|
172
|
+
},
|
|
173
|
+
key
|
|
174
|
+
);
|
|
175
|
+
});
|
|
176
|
+
})()
|
|
177
|
+
}
|
|
185
178
|
);
|
|
186
179
|
};
|
|
187
180
|
const SelectedItemTag = ({
|
|
@@ -194,6 +187,7 @@ const SelectedItemTag = ({
|
|
|
194
187
|
removeSelectedItem,
|
|
195
188
|
selectedItem
|
|
196
189
|
}) => {
|
|
190
|
+
if (!selectedItem) return null;
|
|
197
191
|
const { tabIndex: _, ...selectedItemProps } = getSelectedItemProps?.({
|
|
198
192
|
selectedItem,
|
|
199
193
|
index
|
|
@@ -331,25 +325,25 @@ const useNormalizedItems = (items) => React.useMemo(
|
|
|
331
325
|
);
|
|
332
326
|
const useResolvedItems = (itemsOrItemsResolver, debounceTimeout = 250) => {
|
|
333
327
|
const itemsIsAFunction = typeof itemsOrItemsResolver === "function";
|
|
334
|
-
const [
|
|
335
|
-
itemsIsAFunction ? [] : itemsOrItemsResolver
|
|
336
|
-
);
|
|
328
|
+
const [resolvedItems, setResolvedItems] = React.useState([]);
|
|
337
329
|
const [loading, setLoading] = React.useState(false);
|
|
338
330
|
const abortControllerRef = React.useRef(
|
|
339
331
|
new AbortController()
|
|
340
332
|
);
|
|
341
333
|
const itemsResolver = React.useMemo(() => {
|
|
342
|
-
if (itemsIsAFunction)
|
|
334
|
+
if (itemsIsAFunction) {
|
|
343
335
|
return itemsOrItemsResolver;
|
|
344
|
-
|
|
336
|
+
}
|
|
337
|
+
return null;
|
|
345
338
|
}, [itemsOrItemsResolver, itemsIsAFunction]);
|
|
346
339
|
const updateItems = async (inputValue) => {
|
|
340
|
+
if (!itemsResolver) return;
|
|
347
341
|
if (abortControllerRef?.current) abortControllerRef?.current?.abort();
|
|
348
342
|
const abortController = new AbortController();
|
|
349
343
|
abortControllerRef.current = abortController;
|
|
350
344
|
setLoading(true);
|
|
351
345
|
try {
|
|
352
|
-
const
|
|
346
|
+
const fetchedItems = await itemsResolver(
|
|
353
347
|
inputValue ?? "",
|
|
354
348
|
abortControllerRef
|
|
355
349
|
);
|
|
@@ -363,8 +357,7 @@ const useResolvedItems = (itemsOrItemsResolver, debounceTimeout = 250) => {
|
|
|
363
357
|
);
|
|
364
358
|
return;
|
|
365
359
|
}
|
|
366
|
-
|
|
367
|
-
setItems(resolvedItems);
|
|
360
|
+
setResolvedItems(fetchedItems);
|
|
368
361
|
} catch (error2) {
|
|
369
362
|
if (error2 && typeof error2 === "object" && "name" in error2 && error2.name === "AbortError") {
|
|
370
363
|
return;
|
|
@@ -373,9 +366,12 @@ const useResolvedItems = (itemsOrItemsResolver, debounceTimeout = 250) => {
|
|
|
373
366
|
"The following error was received but not handled inside Entur Designsystems useResolvedItems hook:"
|
|
374
367
|
);
|
|
375
368
|
throw error2;
|
|
369
|
+
} finally {
|
|
370
|
+
setLoading(false);
|
|
376
371
|
}
|
|
377
372
|
};
|
|
378
373
|
const debouncedFetchItems = utils.useDebounce(updateItems, debounceTimeout);
|
|
374
|
+
const items = itemsIsAFunction ? resolvedItems : itemsOrItemsResolver;
|
|
379
375
|
const normalizedItems = useNormalizedItems(items);
|
|
380
376
|
React.useEffect(() => {
|
|
381
377
|
return () => abortControllerRef?.current?.abort("Component unmounted");
|
|
@@ -410,6 +406,10 @@ const itemToString = (item) => item ? item.label : "";
|
|
|
410
406
|
const itemToKey = (item) => item?.label + item?.value;
|
|
411
407
|
const isFunctionWithQueryArgument = (object) => typeof object === "function" && object.length > 0;
|
|
412
408
|
const clamp = (val, min = 1, max = 10) => Math.min(Math.max(val, min), max);
|
|
409
|
+
const resetInputState = (changes) => ({
|
|
410
|
+
...changes,
|
|
411
|
+
inputValue: EMPTY_INPUT
|
|
412
|
+
});
|
|
413
413
|
const useMultiselectUtils = ({
|
|
414
414
|
listItems,
|
|
415
415
|
selectedItems,
|
|
@@ -457,11 +457,11 @@ const useMultiselectUtils = ({
|
|
|
457
457
|
(selectedItem) => selectedItem.value !== clickedItem.value
|
|
458
458
|
)
|
|
459
459
|
);
|
|
460
|
-
const selectAllCheckboxState = () => {
|
|
460
|
+
const selectAllCheckboxState = React.useMemo(() => {
|
|
461
461
|
if (allListItemsAreSelected) return true;
|
|
462
462
|
if (someListItemsAreSelected) return "indeterminate";
|
|
463
463
|
return false;
|
|
464
|
-
};
|
|
464
|
+
}, [allListItemsAreSelected, someListItemsAreSelected]);
|
|
465
465
|
const selectAllUnselectedItemsInListItems = (onChange) => {
|
|
466
466
|
onChange([...selectedItems, ...unselectedItemsInListItems]);
|
|
467
467
|
};
|
|
@@ -525,7 +525,6 @@ const SearchableDropdown = React.forwardRef(
|
|
|
525
525
|
prepend,
|
|
526
526
|
readOnly = false,
|
|
527
527
|
selectedItem: value,
|
|
528
|
-
selectOnBlur = false,
|
|
529
528
|
selectOnTab = false,
|
|
530
529
|
style,
|
|
531
530
|
variant = "info",
|
|
@@ -552,77 +551,65 @@ const SearchableDropdown = React.forwardRef(
|
|
|
552
551
|
if (shouldRefetchItems) fetchItems(inputValue2 ?? EMPTY_INPUT);
|
|
553
552
|
filterListItems({ inputValue: inputValue2 ?? EMPTY_INPUT });
|
|
554
553
|
};
|
|
555
|
-
const resetInputState = ({
|
|
556
|
-
changes
|
|
557
|
-
}) => {
|
|
558
|
-
updateListItems({ inputValue: EMPTY_INPUT });
|
|
559
|
-
return {
|
|
560
|
-
...changes,
|
|
561
|
-
inputValue: EMPTY_INPUT
|
|
562
|
-
};
|
|
563
|
-
};
|
|
564
554
|
const inputHasFocus = typeof document !== "undefined" ? inputRef?.current === document?.activeElement : false;
|
|
565
555
|
React.useEffect(() => {
|
|
566
556
|
filterListItems({ inputValue });
|
|
567
557
|
}, [normalizedItems]);
|
|
568
|
-
React.useEffect(() => {
|
|
569
|
-
if (selectedItem !== null && !inputHasFocus) {
|
|
570
|
-
setShowSelectedItem(true);
|
|
571
|
-
updateListItems({ inputValue: EMPTY_INPUT });
|
|
572
|
-
setInputValue(EMPTY_INPUT);
|
|
573
|
-
}
|
|
574
|
-
}, []);
|
|
575
558
|
const stateReducer = React.useCallback(
|
|
576
559
|
(state, {
|
|
577
560
|
type,
|
|
578
561
|
changes
|
|
579
562
|
}) => {
|
|
580
|
-
if (changes.highlightedIndex !== void 0 && changes?.highlightedIndex >= 0) {
|
|
581
|
-
setLastHighlightedIndex(changes?.highlightedIndex);
|
|
582
|
-
}
|
|
583
563
|
switch (type) {
|
|
584
564
|
// empty input to show selected item and reset dropdown list on item selection
|
|
585
565
|
case downshift.useCombobox.stateChangeTypes.ItemClick:
|
|
586
|
-
case downshift.useCombobox.stateChangeTypes.InputKeyDownEnter:
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
case downshift.useCombobox.stateChangeTypes.
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
566
|
+
case downshift.useCombobox.stateChangeTypes.InputKeyDownEnter: {
|
|
567
|
+
return resetInputState(changes);
|
|
568
|
+
}
|
|
569
|
+
case downshift.useCombobox.stateChangeTypes.InputBlur: {
|
|
570
|
+
return resetInputState({
|
|
571
|
+
...changes,
|
|
572
|
+
selectedItem: state.selectedItem
|
|
573
|
+
});
|
|
574
|
+
}
|
|
575
|
+
case downshift.useCombobox.stateChangeTypes.InputKeyDownEscape: {
|
|
576
|
+
return {
|
|
577
|
+
...changes,
|
|
578
|
+
selectedItem: clearable && !state.isOpen ? null : state.selectedItem
|
|
579
|
+
};
|
|
580
|
+
}
|
|
581
|
+
case downshift.useCombobox.stateChangeTypes.ControlledPropUpdatedSelectedItem: {
|
|
582
|
+
return { ...changes, inputValue: state.inputValue };
|
|
583
|
+
}
|
|
593
584
|
// remove leading whitespace, select element with spacebar on empty input
|
|
594
585
|
case downshift.useCombobox.stateChangeTypes.InputChange: {
|
|
595
|
-
const leadingWhitespaceTest = /^\s+/g;
|
|
596
586
|
const isSpacePressedOnEmptyInput = changes.inputValue === " ";
|
|
597
|
-
if (!isSpacePressedOnEmptyInput)
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
}
|
|
618
|
-
}
|
|
619
|
-
return { ...changes, highlightedIndex: 0 };
|
|
587
|
+
if (!isSpacePressedOnEmptyInput)
|
|
588
|
+
return { ...changes, highlightedIndex: 0 };
|
|
589
|
+
const sanitizedInputValue = (changes.inputValue ?? "").replace(
|
|
590
|
+
/^\s+/,
|
|
591
|
+
EMPTY_INPUT
|
|
592
|
+
);
|
|
593
|
+
if (!state.isOpen)
|
|
594
|
+
return {
|
|
595
|
+
...changes,
|
|
596
|
+
inputValue: sanitizedInputValue,
|
|
597
|
+
isOpen: true
|
|
598
|
+
};
|
|
599
|
+
const i = changes.highlightedIndex ?? -1;
|
|
600
|
+
if (i >= 0 && i < listItems.length)
|
|
601
|
+
return {
|
|
602
|
+
...changes,
|
|
603
|
+
inputValue: sanitizedInputValue,
|
|
604
|
+
selectedItem: listItems[i]
|
|
605
|
+
};
|
|
606
|
+
return { ...changes, inputValue: sanitizedInputValue };
|
|
620
607
|
}
|
|
621
608
|
default:
|
|
622
609
|
return changes;
|
|
623
610
|
}
|
|
624
611
|
},
|
|
625
|
-
[
|
|
612
|
+
[listItems, EMPTY_INPUT, clearable]
|
|
626
613
|
);
|
|
627
614
|
const {
|
|
628
615
|
isOpen,
|
|
@@ -649,9 +636,23 @@ const SearchableDropdown = React.forwardRef(
|
|
|
649
636
|
onSelectedItemChange({ selectedItem: newSelectedItem }) {
|
|
650
637
|
onChange(newSelectedItem);
|
|
651
638
|
},
|
|
639
|
+
onHighlightedIndexChange: ({ highlightedIndex: highlightedIndex2 }) => {
|
|
640
|
+
if (highlightedIndex2 >= 0) setLastHighlightedIndex(highlightedIndex2);
|
|
641
|
+
},
|
|
652
642
|
// Accessibility
|
|
653
643
|
getA11yStatusMessage: (options) => getA11yStatusMessage({ ...options, resultCount: listItems.length })
|
|
654
644
|
});
|
|
645
|
+
React.useEffect(() => {
|
|
646
|
+
if (value !== null && !inputHasFocus) {
|
|
647
|
+
setShowSelectedItem(true);
|
|
648
|
+
updateListItems({ inputValue: EMPTY_INPUT });
|
|
649
|
+
setInputValue(EMPTY_INPUT);
|
|
650
|
+
}
|
|
651
|
+
}, [value]);
|
|
652
|
+
const handleOnClear = () => {
|
|
653
|
+
inputRef.current?.focus();
|
|
654
|
+
reset();
|
|
655
|
+
};
|
|
655
656
|
const { refs, floatingStyles, update } = reactDom.useFloating({
|
|
656
657
|
open: isOpen,
|
|
657
658
|
placement: "bottom-start",
|
|
@@ -659,19 +660,17 @@ const SearchableDropdown = React.forwardRef(
|
|
|
659
660
|
reactDom.offset(tokens.space.extraSmall2),
|
|
660
661
|
reactDom.shift({ padding: tokens.space.extraSmall }),
|
|
661
662
|
reactDom.size({
|
|
662
|
-
apply({
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
maxHeight: `${clamp(10 * 16, availableHeight, 20 * 16)}px`
|
|
668
|
-
});
|
|
663
|
+
apply({ elements, availableHeight }) {
|
|
664
|
+
elements.floating.style.setProperty(
|
|
665
|
+
"--list-max-height",
|
|
666
|
+
`${clamp(10 * 16, availableHeight, 20 * 16)}px`
|
|
667
|
+
);
|
|
669
668
|
}
|
|
670
669
|
}),
|
|
671
670
|
reactDom.flip({ fallbackStrategy: "initialPlacement" })
|
|
672
671
|
]
|
|
673
672
|
});
|
|
674
|
-
React.
|
|
673
|
+
React.useLayoutEffect(() => {
|
|
675
674
|
if (isOpen && refs.reference.current && refs.floating.current) {
|
|
676
675
|
return reactDom.autoUpdate(
|
|
677
676
|
refs.reference.current,
|
|
@@ -680,10 +679,39 @@ const SearchableDropdown = React.forwardRef(
|
|
|
680
679
|
);
|
|
681
680
|
}
|
|
682
681
|
}, [isOpen, refs.reference, refs.floating, update]);
|
|
683
|
-
const
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
};
|
|
682
|
+
const labelProps = getLabelProps();
|
|
683
|
+
const toggleButtonProps = getToggleButtonProps({
|
|
684
|
+
"aria-busy": !(loading ?? resolvedItemsLoading) ? void 0 : "true"
|
|
685
|
+
});
|
|
686
|
+
const menuProps = getMenuProps({
|
|
687
|
+
refKey: "innerRef",
|
|
688
|
+
ref: refs.setFloating,
|
|
689
|
+
style: listStyle
|
|
690
|
+
});
|
|
691
|
+
const inputProps = getInputProps({
|
|
692
|
+
onKeyDown(e) {
|
|
693
|
+
if (isOpen && e.key === "Tab") {
|
|
694
|
+
const highlitedItem = listItems[highlightedIndex];
|
|
695
|
+
if (selectOnTab && highlitedItem) {
|
|
696
|
+
selectItem(highlitedItem);
|
|
697
|
+
setShowSelectedItem(true);
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
},
|
|
701
|
+
onBlur(e) {
|
|
702
|
+
if (selectedItem !== null) setShowSelectedItem(true);
|
|
703
|
+
onBlur?.(e);
|
|
704
|
+
},
|
|
705
|
+
onFocus(e) {
|
|
706
|
+
if (!readOnly) setShowSelectedItem(false);
|
|
707
|
+
onFocus?.(e);
|
|
708
|
+
},
|
|
709
|
+
disabled,
|
|
710
|
+
readOnly,
|
|
711
|
+
placeholder: selectedItem?.label ?? placeholder,
|
|
712
|
+
tabIndex: disabled || readOnly ? -1 : void 0,
|
|
713
|
+
ref: utils.mergeRefs(inputRef, ref)
|
|
714
|
+
});
|
|
687
715
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
688
716
|
form.BaseFormControl,
|
|
689
717
|
{
|
|
@@ -698,17 +726,14 @@ const SearchableDropdown = React.forwardRef(
|
|
|
698
726
|
feedback,
|
|
699
727
|
isFilled: selectedItem !== null || inputValue !== EMPTY_INPUT,
|
|
700
728
|
label,
|
|
701
|
-
labelId:
|
|
702
|
-
labelProps
|
|
729
|
+
labelId: labelProps.id,
|
|
730
|
+
labelProps,
|
|
703
731
|
labelTooltip,
|
|
704
732
|
onClick: (e) => {
|
|
705
|
-
if (e.target === e.currentTarget)
|
|
706
|
-
getInputProps()?.onClick?.(e);
|
|
707
|
-
}
|
|
733
|
+
if (e.target === e.currentTarget) inputProps?.onClick?.(e);
|
|
708
734
|
onClick?.(e);
|
|
709
735
|
},
|
|
710
736
|
onKeyDown,
|
|
711
|
-
onFocus,
|
|
712
737
|
prepend,
|
|
713
738
|
readOnly,
|
|
714
739
|
ref: refs.setReference,
|
|
@@ -722,17 +747,15 @@ const SearchableDropdown = React.forwardRef(
|
|
|
722
747
|
ariaLabelSelectedItem,
|
|
723
748
|
floatingStyles,
|
|
724
749
|
getItemProps,
|
|
725
|
-
getMenuProps,
|
|
726
750
|
highlightedIndex,
|
|
727
751
|
isOpen,
|
|
728
752
|
listItems,
|
|
729
|
-
style: listStyle,
|
|
730
|
-
setListRef: refs.setFloating,
|
|
731
753
|
loading: loading ?? resolvedItemsLoading,
|
|
732
754
|
loadingText,
|
|
733
755
|
noMatchesText,
|
|
734
756
|
selectedItems: selectedItem !== null ? [selectedItem] : [],
|
|
735
|
-
readOnly
|
|
757
|
+
readOnly,
|
|
758
|
+
...menuProps
|
|
736
759
|
}
|
|
737
760
|
),
|
|
738
761
|
...rest,
|
|
@@ -747,7 +770,7 @@ const SearchableDropdown = React.forwardRef(
|
|
|
747
770
|
onClick: (event) => {
|
|
748
771
|
if (!disabled && !readOnly) {
|
|
749
772
|
inputRef.current?.focus();
|
|
750
|
-
|
|
773
|
+
inputProps?.onClick?.(event);
|
|
751
774
|
}
|
|
752
775
|
},
|
|
753
776
|
tabIndex: readOnly ? 0 : -1,
|
|
@@ -760,38 +783,13 @@ const SearchableDropdown = React.forwardRef(
|
|
|
760
783
|
className: classNames("eds-dropdown__input eds-form-control", {
|
|
761
784
|
"eds-dropdown__input--hidden": showSelectedItem
|
|
762
785
|
}),
|
|
763
|
-
...
|
|
764
|
-
onKeyDown(e) {
|
|
765
|
-
if (isOpen && e.key === "Tab") {
|
|
766
|
-
const highlitedItem = listItems[highlightedIndex];
|
|
767
|
-
if ((selectOnTab || selectOnBlur) && highlitedItem && highlitedItem !== selectedItem) {
|
|
768
|
-
selectItem(highlitedItem);
|
|
769
|
-
}
|
|
770
|
-
}
|
|
771
|
-
},
|
|
772
|
-
onBlur(e) {
|
|
773
|
-
if (selectedItem !== null) setShowSelectedItem(true);
|
|
774
|
-
onBlur?.(e);
|
|
775
|
-
},
|
|
776
|
-
onFocus() {
|
|
777
|
-
if (!readOnly) {
|
|
778
|
-
setShowSelectedItem(false);
|
|
779
|
-
}
|
|
780
|
-
},
|
|
781
|
-
disabled,
|
|
782
|
-
readOnly,
|
|
783
|
-
placeholder: selectedItem?.label ?? placeholder,
|
|
784
|
-
tabIndex: disabled || readOnly ? -1 : void 0,
|
|
785
|
-
ref: utils.mergeRefs(inputRef, ref)
|
|
786
|
-
})
|
|
786
|
+
...inputProps
|
|
787
787
|
}
|
|
788
788
|
),
|
|
789
789
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
790
790
|
DropdownFieldAppendix,
|
|
791
791
|
{
|
|
792
|
-
...
|
|
793
|
-
"aria-busy": !(loading ?? resolvedItemsLoading) ? void 0 : "true"
|
|
794
|
-
}),
|
|
792
|
+
...toggleButtonProps,
|
|
795
793
|
ariaLabelCloseList,
|
|
796
794
|
ariaLabelOpenList,
|
|
797
795
|
clearable,
|
|
@@ -836,7 +834,6 @@ const MultiSelect = React.forwardRef(
|
|
|
836
834
|
placeholder,
|
|
837
835
|
readOnly = false,
|
|
838
836
|
selectedItems = [],
|
|
839
|
-
selectOnBlur = false,
|
|
840
837
|
selectOnTab = false,
|
|
841
838
|
style,
|
|
842
839
|
variant = "information",
|
|
@@ -867,10 +864,14 @@ const MultiSelect = React.forwardRef(
|
|
|
867
864
|
fetchItems
|
|
868
865
|
} = useResolvedItems(initialItems, debounceTimeout);
|
|
869
866
|
const isAllNonAsyncItemsSelected = typeof initialItems !== "function" && selectedItems.length === normalizedItems.length;
|
|
870
|
-
const
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
867
|
+
const selectAllUniqueId = utils.useRandomId("select-all");
|
|
868
|
+
const selectAll = React.useMemo(
|
|
869
|
+
() => ({
|
|
870
|
+
value: selectAllUniqueId,
|
|
871
|
+
label: labelSelectAll
|
|
872
|
+
}),
|
|
873
|
+
[labelSelectAll]
|
|
874
|
+
);
|
|
874
875
|
const summarySelectedItems = React.useMemo(
|
|
875
876
|
() => ({
|
|
876
877
|
value: EMPTY_INPUT,
|
|
@@ -887,15 +888,21 @@ const MultiSelect = React.forwardRef(
|
|
|
887
888
|
...!hideSelectAll ? [selectAll] : [],
|
|
888
889
|
...normalizedItems
|
|
889
890
|
]);
|
|
890
|
-
const filterListItems = (
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
891
|
+
const filterListItems = React.useCallback(
|
|
892
|
+
({ inputValue: inputValue2 }) => setListItems([
|
|
893
|
+
...!hideSelectAll ? [selectAll] : [],
|
|
894
|
+
...normalizedItems.filter((item) => itemFilter(item, inputValue2))
|
|
895
|
+
]),
|
|
896
|
+
[hideSelectAll, selectAll, normalizedItems, itemFilter]
|
|
897
|
+
);
|
|
898
|
+
const updateListItems = React.useCallback(
|
|
899
|
+
({ inputValue: inputValue2 }) => {
|
|
900
|
+
const shouldRefetchItems = isFunctionWithQueryArgument(initialItems);
|
|
901
|
+
if (shouldRefetchItems) fetchItems(inputValue2 ?? EMPTY_INPUT);
|
|
902
|
+
filterListItems({ inputValue: inputValue2 ?? EMPTY_INPUT });
|
|
903
|
+
},
|
|
904
|
+
[filterListItems, initialItems, fetchItems]
|
|
905
|
+
);
|
|
899
906
|
React.useEffect(() => {
|
|
900
907
|
filterListItems({ inputValue });
|
|
901
908
|
}, [normalizedItems]);
|
|
@@ -927,67 +934,57 @@ const MultiSelect = React.forwardRef(
|
|
|
927
934
|
});
|
|
928
935
|
const stateReducer = React.useCallback(
|
|
929
936
|
(state, {
|
|
930
|
-
|
|
931
|
-
|
|
937
|
+
type,
|
|
938
|
+
changes
|
|
932
939
|
}) => {
|
|
933
|
-
if (changes.highlightedIndex !== void 0 && changes?.highlightedIndex >= 0) {
|
|
934
|
-
setLastHighlightedIndex(changes?.highlightedIndex);
|
|
935
|
-
}
|
|
936
940
|
switch (type) {
|
|
937
|
-
// reset input value when leaving input field
|
|
938
|
-
case downshift.useCombobox.stateChangeTypes.InputBlur:
|
|
939
|
-
return {
|
|
940
|
-
...changes,
|
|
941
|
-
inputValue: EMPTY_INPUT
|
|
942
|
-
};
|
|
943
941
|
// keep menu open and edit input value on item selection
|
|
944
942
|
case downshift.useCombobox.stateChangeTypes.InputKeyDownEnter:
|
|
945
943
|
case downshift.useCombobox.stateChangeTypes.ItemClick: {
|
|
946
944
|
return {
|
|
947
945
|
...changes,
|
|
948
946
|
isOpen: true,
|
|
949
|
-
inputValue: clearInputOnSelect ? EMPTY_INPUT :
|
|
947
|
+
inputValue: clearInputOnSelect ? EMPTY_INPUT : state.inputValue
|
|
950
948
|
};
|
|
951
949
|
}
|
|
950
|
+
// reset input value when leaving input field
|
|
951
|
+
case downshift.useCombobox.stateChangeTypes.InputBlur: {
|
|
952
|
+
const { selectedItem: _, ...otherChanges } = changes;
|
|
953
|
+
return resetInputState(otherChanges);
|
|
954
|
+
}
|
|
952
955
|
// edit input value when selected items is updated outside component
|
|
953
956
|
case downshift.useCombobox.stateChangeTypes.ControlledPropUpdatedSelectedItem: {
|
|
954
|
-
return {
|
|
955
|
-
...changes,
|
|
956
|
-
inputValue: inputRef?.current?.value ?? EMPTY_INPUT
|
|
957
|
-
};
|
|
957
|
+
return { ...changes, inputValue: state.inputValue };
|
|
958
958
|
}
|
|
959
959
|
// remove leading whitespace, select item with spacebar if input is empty and filter list items
|
|
960
960
|
case downshift.useCombobox.stateChangeTypes.InputChange: {
|
|
961
|
-
const leadingWhitespaceTest = /^\s+/g;
|
|
962
961
|
const isSpacePressedOnEmptyInput = changes.inputValue === " ";
|
|
963
|
-
if (
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
}
|
|
984
|
-
return changes;
|
|
962
|
+
if (!isSpacePressedOnEmptyInput)
|
|
963
|
+
return { ...changes, highlightedIndex: hideSelectAll ? 0 : 1 };
|
|
964
|
+
const sanitizedInputValue = (changes.inputValue ?? "").replace(
|
|
965
|
+
/^\s+/,
|
|
966
|
+
EMPTY_INPUT
|
|
967
|
+
);
|
|
968
|
+
if (!state.isOpen)
|
|
969
|
+
return {
|
|
970
|
+
...changes,
|
|
971
|
+
inputValue: sanitizedInputValue,
|
|
972
|
+
isOpen: true
|
|
973
|
+
};
|
|
974
|
+
const i = changes.highlightedIndex ?? -1;
|
|
975
|
+
if (i >= 0 && i < listItems.length)
|
|
976
|
+
return {
|
|
977
|
+
...changes,
|
|
978
|
+
inputValue: sanitizedInputValue,
|
|
979
|
+
selectedItem: listItems[i]
|
|
980
|
+
};
|
|
981
|
+
return { ...changes, inputValue: sanitizedInputValue };
|
|
985
982
|
}
|
|
986
983
|
default:
|
|
987
984
|
return changes;
|
|
988
985
|
}
|
|
989
986
|
},
|
|
990
|
-
[hideSelectAll,
|
|
987
|
+
[hideSelectAll, listItems, clearInputOnSelect]
|
|
991
988
|
);
|
|
992
989
|
const {
|
|
993
990
|
getInputProps,
|
|
@@ -996,10 +993,8 @@ const MultiSelect = React.forwardRef(
|
|
|
996
993
|
getMenuProps,
|
|
997
994
|
getToggleButtonProps,
|
|
998
995
|
highlightedIndex,
|
|
999
|
-
setHighlightedIndex,
|
|
1000
996
|
inputValue,
|
|
1001
|
-
isOpen
|
|
1002
|
-
setInputValue
|
|
997
|
+
isOpen
|
|
1003
998
|
} = downshift.useCombobox({
|
|
1004
999
|
defaultHighlightedIndex: lastHighlightedIndex,
|
|
1005
1000
|
// after selection, highlight previously selected item.
|
|
@@ -1009,8 +1004,6 @@ const MultiSelect = React.forwardRef(
|
|
|
1009
1004
|
stateReducer,
|
|
1010
1005
|
onInputValueChange(changes) {
|
|
1011
1006
|
updateListItems({ inputValue: changes.inputValue });
|
|
1012
|
-
setHighlightedIndex(hideSelectAll ? 0 : 1);
|
|
1013
|
-
setLastHighlightedIndex(hideSelectAll ? 0 : 1);
|
|
1014
1007
|
},
|
|
1015
1008
|
onSelectedItemChange({ selectedItem: clickedItem }) {
|
|
1016
1009
|
if (!clickedItem) return;
|
|
@@ -1019,6 +1012,9 @@ const MultiSelect = React.forwardRef(
|
|
|
1019
1012
|
onChange: setSelectedItems
|
|
1020
1013
|
});
|
|
1021
1014
|
},
|
|
1015
|
+
onHighlightedIndexChange: ({ highlightedIndex: highlightedIndex2 }) => {
|
|
1016
|
+
if (highlightedIndex2 >= 0) setLastHighlightedIndex(highlightedIndex2);
|
|
1017
|
+
},
|
|
1022
1018
|
// Accessibility
|
|
1023
1019
|
getA11yStatusMessage: (options) => getA11yStatusMessage({
|
|
1024
1020
|
...options,
|
|
@@ -1034,19 +1030,17 @@ const MultiSelect = React.forwardRef(
|
|
|
1034
1030
|
reactDom.offset(tokens.space.extraSmall2),
|
|
1035
1031
|
reactDom.shift({ padding: tokens.space.extraSmall }),
|
|
1036
1032
|
reactDom.size({
|
|
1037
|
-
apply({
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
maxHeight: `${clamp(10 * 16, availableHeight, 20 * 16)}px`
|
|
1043
|
-
});
|
|
1033
|
+
apply({ elements, availableHeight }) {
|
|
1034
|
+
elements.floating.style.setProperty(
|
|
1035
|
+
"--list-max-height",
|
|
1036
|
+
`${clamp(10 * 16, availableHeight, 20 * 16)}px`
|
|
1037
|
+
);
|
|
1044
1038
|
}
|
|
1045
1039
|
}),
|
|
1046
1040
|
reactDom.flip({ fallbackStrategy: "initialPlacement" })
|
|
1047
1041
|
]
|
|
1048
1042
|
});
|
|
1049
|
-
React.
|
|
1043
|
+
React.useLayoutEffect(() => {
|
|
1050
1044
|
if (isOpen && refs.reference.current && refs.floating.current) {
|
|
1051
1045
|
return reactDom.autoUpdate(
|
|
1052
1046
|
refs.reference.current,
|
|
@@ -1059,6 +1053,42 @@ const MultiSelect = React.forwardRef(
|
|
|
1059
1053
|
inputRef.current?.focus();
|
|
1060
1054
|
reset();
|
|
1061
1055
|
};
|
|
1056
|
+
const dropdownProps = getDropdownProps({
|
|
1057
|
+
preventKeyAction: isOpen,
|
|
1058
|
+
value: inputValue ?? EMPTY_INPUT,
|
|
1059
|
+
ref: utils.mergeRefs(inputRef, ref)
|
|
1060
|
+
});
|
|
1061
|
+
const inputProps = getInputProps({
|
|
1062
|
+
onKeyDown: (e) => {
|
|
1063
|
+
if (selectOnTab && isOpen && e.key === "Tab") {
|
|
1064
|
+
const highlitedItem = listItems[highlightedIndex];
|
|
1065
|
+
if (!highlitedItem) return;
|
|
1066
|
+
const shouldSkipTabSelection = clickedItemIsSelectAll(highlitedItem) || !clickedItemIsSelectAll(highlitedItem) && clickedItemIsInSelectedItems(highlitedItem);
|
|
1067
|
+
if (shouldSkipTabSelection) return;
|
|
1068
|
+
handleListItemClicked({
|
|
1069
|
+
clickedItem: highlitedItem,
|
|
1070
|
+
onChange: setSelectedItems
|
|
1071
|
+
});
|
|
1072
|
+
}
|
|
1073
|
+
},
|
|
1074
|
+
onBlur,
|
|
1075
|
+
onFocus,
|
|
1076
|
+
...dropdownProps,
|
|
1077
|
+
className: "eds-dropdown__input eds-form-control",
|
|
1078
|
+
disabled: readOnly || disabled,
|
|
1079
|
+
placeholder,
|
|
1080
|
+
tabIndex: disabled || readOnly ? -1 : void 0
|
|
1081
|
+
});
|
|
1082
|
+
const labelProps = getLabelProps();
|
|
1083
|
+
const menuProps = getMenuProps({
|
|
1084
|
+
"aria-multiselectable": true,
|
|
1085
|
+
refKey: "innerRef",
|
|
1086
|
+
ref: refs.setFloating,
|
|
1087
|
+
style: listStyle
|
|
1088
|
+
});
|
|
1089
|
+
const toggleButtonProps = getToggleButtonProps({
|
|
1090
|
+
"aria-busy": !(loading ?? resolvedItemsLoading) ? void 0 : "true"
|
|
1091
|
+
});
|
|
1062
1092
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1063
1093
|
form.BaseFormControl,
|
|
1064
1094
|
{
|
|
@@ -1073,21 +1103,14 @@ const MultiSelect = React.forwardRef(
|
|
|
1073
1103
|
feedback,
|
|
1074
1104
|
isFilled: hasSelectedItems || inputValue !== EMPTY_INPUT,
|
|
1075
1105
|
label,
|
|
1076
|
-
labelId:
|
|
1077
|
-
labelProps
|
|
1106
|
+
labelId: labelProps.id,
|
|
1107
|
+
labelProps,
|
|
1078
1108
|
labelTooltip,
|
|
1079
|
-
onBlur: (e) => {
|
|
1080
|
-
setInputValue("");
|
|
1081
|
-
onBlur?.(e);
|
|
1082
|
-
},
|
|
1083
1109
|
onClick: (e) => {
|
|
1084
|
-
if (e.target === e.currentTarget)
|
|
1085
|
-
getInputProps()?.onClick?.(e);
|
|
1086
|
-
}
|
|
1110
|
+
if (e.target === e.currentTarget) inputProps?.onClick?.(e);
|
|
1087
1111
|
onClick?.(e);
|
|
1088
1112
|
},
|
|
1089
1113
|
onKeyDown,
|
|
1090
|
-
onFocus,
|
|
1091
1114
|
readOnly,
|
|
1092
1115
|
ref: refs.setReference,
|
|
1093
1116
|
style,
|
|
@@ -1099,19 +1122,17 @@ const MultiSelect = React.forwardRef(
|
|
|
1099
1122
|
ariaLabelSelectedItem,
|
|
1100
1123
|
floatingStyles,
|
|
1101
1124
|
getItemProps,
|
|
1102
|
-
getMenuProps,
|
|
1103
1125
|
highlightedIndex,
|
|
1104
1126
|
isOpen,
|
|
1105
1127
|
listItems,
|
|
1106
|
-
style: listStyle,
|
|
1107
|
-
setListRef: refs.setFloating,
|
|
1108
1128
|
loading: loading ?? resolvedItemsLoading,
|
|
1109
1129
|
loadingText,
|
|
1110
1130
|
noMatchesText,
|
|
1111
1131
|
selectAllCheckboxState,
|
|
1112
1132
|
selectAllItem: selectAll,
|
|
1113
1133
|
selectedItems,
|
|
1114
|
-
readOnly
|
|
1134
|
+
readOnly,
|
|
1135
|
+
...menuProps
|
|
1115
1136
|
}
|
|
1116
1137
|
),
|
|
1117
1138
|
...rest,
|
|
@@ -1126,7 +1147,7 @@ const MultiSelect = React.forwardRef(
|
|
|
1126
1147
|
}
|
|
1127
1148
|
),
|
|
1128
1149
|
children: [
|
|
1129
|
-
selectedItems.length > 1 ? /* @__PURE__ */ jsxRuntime.jsx(a11y.VisuallyHidden, { onClick: inputRef.current?.focus, children: ariaLabelJumpToInput }) : null,
|
|
1150
|
+
selectedItems.length > 1 ? /* @__PURE__ */ jsxRuntime.jsx(a11y.VisuallyHidden, { onClick: () => inputRef.current?.focus(), children: ariaLabelJumpToInput }) : null,
|
|
1130
1151
|
selectedItems.length <= maxChips ? selectedItems.map((selectedItem, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1131
1152
|
SelectedItemTag,
|
|
1132
1153
|
{
|
|
@@ -1154,43 +1175,14 @@ const MultiSelect = React.forwardRef(
|
|
|
1154
1175
|
selectedItem: summarySelectedItems
|
|
1155
1176
|
}
|
|
1156
1177
|
),
|
|
1157
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1158
|
-
"input",
|
|
1159
|
-
{
|
|
1160
|
-
...getInputProps({
|
|
1161
|
-
onKeyDown: (e) => {
|
|
1162
|
-
if (selectOnTab && isOpen && e.key === "Tab") {
|
|
1163
|
-
const highlitedItem = listItems[highlightedIndex];
|
|
1164
|
-
if (!highlitedItem) return;
|
|
1165
|
-
const shouldSkipTabSelection = clickedItemIsSelectAll(highlitedItem) || !clickedItemIsSelectAll(highlitedItem) && clickedItemIsInSelectedItems(highlitedItem);
|
|
1166
|
-
if (shouldSkipTabSelection) return;
|
|
1167
|
-
handleListItemClicked({
|
|
1168
|
-
clickedItem: highlitedItem,
|
|
1169
|
-
onChange: setSelectedItems
|
|
1170
|
-
});
|
|
1171
|
-
}
|
|
1172
|
-
},
|
|
1173
|
-
...getDropdownProps({
|
|
1174
|
-
preventKeyAction: isOpen,
|
|
1175
|
-
value: inputValue ?? EMPTY_INPUT,
|
|
1176
|
-
ref: utils.mergeRefs(inputRef, ref)
|
|
1177
|
-
}),
|
|
1178
|
-
className: "eds-dropdown__input eds-form-control",
|
|
1179
|
-
disabled: readOnly || disabled,
|
|
1180
|
-
placeholder,
|
|
1181
|
-
tabIndex: disabled || readOnly ? -1 : void 0
|
|
1182
|
-
})
|
|
1183
|
-
}
|
|
1184
|
-
)
|
|
1178
|
+
/* @__PURE__ */ jsxRuntime.jsx("input", { ...inputProps })
|
|
1185
1179
|
]
|
|
1186
1180
|
}
|
|
1187
1181
|
),
|
|
1188
1182
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1189
1183
|
DropdownFieldAppendix,
|
|
1190
1184
|
{
|
|
1191
|
-
...
|
|
1192
|
-
"aria-busy": !(loading ?? resolvedItemsLoading) ? void 0 : "true"
|
|
1193
|
-
}),
|
|
1185
|
+
...toggleButtonProps,
|
|
1194
1186
|
ariaLabelCloseList,
|
|
1195
1187
|
ariaLabelOpenList,
|
|
1196
1188
|
clearable,
|
|
@@ -1216,7 +1208,7 @@ const Dropdown = React.forwardRef(
|
|
|
1216
1208
|
ariaLabelOpenList = "Åpne liste med valg",
|
|
1217
1209
|
ariaLabelSelectedItem,
|
|
1218
1210
|
className,
|
|
1219
|
-
clearable
|
|
1211
|
+
clearable,
|
|
1220
1212
|
disabled = false,
|
|
1221
1213
|
disableLabelAnimation,
|
|
1222
1214
|
feedback,
|
|
@@ -1233,7 +1225,6 @@ const Dropdown = React.forwardRef(
|
|
|
1233
1225
|
prepend,
|
|
1234
1226
|
readOnly = false,
|
|
1235
1227
|
selectedItem,
|
|
1236
|
-
selectOnBlur = false,
|
|
1237
1228
|
selectOnTab = false,
|
|
1238
1229
|
style,
|
|
1239
1230
|
variant = "information",
|
|
@@ -1254,22 +1245,20 @@ const Dropdown = React.forwardRef(
|
|
|
1254
1245
|
items: normalizedItems,
|
|
1255
1246
|
defaultHighlightedIndex: selectedItem ? void 0 : 0,
|
|
1256
1247
|
selectedItem,
|
|
1257
|
-
stateReducer(
|
|
1248
|
+
stateReducer(state, { changes, type }) {
|
|
1258
1249
|
const toggleButtonIsFocused = typeof document !== "undefined" && document.activeElement === refs.reference.current;
|
|
1259
1250
|
switch (type) {
|
|
1260
1251
|
case downshift.useSelect.stateChangeTypes.ToggleButtonKeyDownArrowDown:
|
|
1261
1252
|
case downshift.useSelect.stateChangeTypes.ToggleButtonKeyDownArrowUp:
|
|
1262
1253
|
if (!toggleButtonIsFocused) return { ...changes, isOpen: false };
|
|
1254
|
+
break;
|
|
1255
|
+
case downshift.useSelect.stateChangeTypes.ToggleButtonBlur:
|
|
1256
|
+
return { ...changes, selectedItem: state.selectedItem };
|
|
1263
1257
|
}
|
|
1264
1258
|
return changes;
|
|
1265
1259
|
},
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
case downshift.useSelect.stateChangeTypes.ToggleButtonBlur:
|
|
1269
|
-
if (!selectOnBlur) return;
|
|
1270
|
-
}
|
|
1271
|
-
if (newSelectedItem === void 0) return;
|
|
1272
|
-
onChange?.(newSelectedItem ?? null);
|
|
1260
|
+
onSelectedItemChange({ selectedItem: newSelectedItem }) {
|
|
1261
|
+
onChange?.(newSelectedItem);
|
|
1273
1262
|
},
|
|
1274
1263
|
itemToString
|
|
1275
1264
|
});
|
|
@@ -1280,19 +1269,17 @@ const Dropdown = React.forwardRef(
|
|
|
1280
1269
|
reactDom.offset(tokens.space.extraSmall2),
|
|
1281
1270
|
reactDom.shift({ padding: tokens.space.extraSmall }),
|
|
1282
1271
|
reactDom.size({
|
|
1283
|
-
apply({
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
maxHeight: `${clamp(10 * 16, availableHeight, 20 * 16)}px`
|
|
1289
|
-
});
|
|
1272
|
+
apply({ elements, availableHeight }) {
|
|
1273
|
+
elements.floating.style.setProperty(
|
|
1274
|
+
"--list-max-height",
|
|
1275
|
+
`${clamp(10 * 16, availableHeight, 20 * 16)}px`
|
|
1276
|
+
);
|
|
1290
1277
|
}
|
|
1291
1278
|
}),
|
|
1292
1279
|
reactDom.flip({ fallbackStrategy: "initialPlacement" })
|
|
1293
1280
|
]
|
|
1294
1281
|
});
|
|
1295
|
-
React.
|
|
1282
|
+
React.useLayoutEffect(() => {
|
|
1296
1283
|
if (isOpen && refs.reference.current && refs.floating.current) {
|
|
1297
1284
|
return reactDom.autoUpdate(
|
|
1298
1285
|
refs.reference.current,
|
|
@@ -1302,9 +1289,37 @@ const Dropdown = React.forwardRef(
|
|
|
1302
1289
|
}
|
|
1303
1290
|
}, [isOpen, refs.reference, refs.floating, update]);
|
|
1304
1291
|
const handleOnClear = () => {
|
|
1305
|
-
reset();
|
|
1306
1292
|
refs.reference.current?.focus();
|
|
1293
|
+
reset();
|
|
1307
1294
|
};
|
|
1295
|
+
const labelProps = getLabelProps({
|
|
1296
|
+
isFilled
|
|
1297
|
+
});
|
|
1298
|
+
const toggleButtonProps = getToggleButtonProps({
|
|
1299
|
+
ref: utils.mergeRefs(ref, refs.setReference),
|
|
1300
|
+
"aria-disabled": disabled,
|
|
1301
|
+
"aria-label": disabled ? "Disabled dropdown" : "",
|
|
1302
|
+
disabled,
|
|
1303
|
+
readOnly,
|
|
1304
|
+
label,
|
|
1305
|
+
labelId: labelProps?.id,
|
|
1306
|
+
tabIndex: disabled || readOnly ? -1 : 0,
|
|
1307
|
+
onKeyDown(e) {
|
|
1308
|
+
if (isOpen && e.key === "Tab") {
|
|
1309
|
+
const highlitedItem = normalizedItems[highlightedIndex];
|
|
1310
|
+
if (selectOnTab && highlitedItem && highlitedItem !== selectedItem) {
|
|
1311
|
+
selectItem(highlitedItem);
|
|
1312
|
+
}
|
|
1313
|
+
} else if (!isOpen && e.key === "Escape" && clearable) {
|
|
1314
|
+
reset();
|
|
1315
|
+
}
|
|
1316
|
+
}
|
|
1317
|
+
});
|
|
1318
|
+
const menuProps = getMenuProps({
|
|
1319
|
+
refKey: "innerRef",
|
|
1320
|
+
ref: refs.setFloating,
|
|
1321
|
+
style: listStyle
|
|
1322
|
+
});
|
|
1308
1323
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1309
1324
|
form.BaseFormControl,
|
|
1310
1325
|
{
|
|
@@ -1313,31 +1328,12 @@ const Dropdown = React.forwardRef(
|
|
|
1313
1328
|
}),
|
|
1314
1329
|
disableLabelAnimation,
|
|
1315
1330
|
feedback,
|
|
1316
|
-
|
|
1317
|
-
labelProps: getLabelProps(),
|
|
1331
|
+
labelProps,
|
|
1318
1332
|
labelTooltip,
|
|
1319
1333
|
prepend,
|
|
1320
1334
|
style,
|
|
1321
1335
|
variant,
|
|
1322
|
-
...
|
|
1323
|
-
ref: utils.mergeRefs(ref, refs.setReference),
|
|
1324
|
-
"aria-disabled": disabled,
|
|
1325
|
-
"aria-label": disabled ? "Disabled dropdown" : "",
|
|
1326
|
-
disabled,
|
|
1327
|
-
readOnly,
|
|
1328
|
-
label,
|
|
1329
|
-
labelId: getLabelProps()?.id,
|
|
1330
|
-
children: void 0,
|
|
1331
|
-
tabIndex: disabled || readOnly ? -1 : 0,
|
|
1332
|
-
onKeyDown(e) {
|
|
1333
|
-
if (isOpen && e.key === "Tab") {
|
|
1334
|
-
const highlitedItem = normalizedItems[highlightedIndex];
|
|
1335
|
-
if ((selectOnTab || selectOnBlur) && highlitedItem && highlitedItem !== selectedItem) {
|
|
1336
|
-
selectItem(highlitedItem);
|
|
1337
|
-
}
|
|
1338
|
-
}
|
|
1339
|
-
}
|
|
1340
|
-
}),
|
|
1336
|
+
...toggleButtonProps,
|
|
1341
1337
|
after: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1342
1338
|
DropdownList,
|
|
1343
1339
|
{
|
|
@@ -1345,17 +1341,15 @@ const Dropdown = React.forwardRef(
|
|
|
1345
1341
|
ariaLabelSelectedItem,
|
|
1346
1342
|
floatingStyles,
|
|
1347
1343
|
getItemProps,
|
|
1348
|
-
getMenuProps,
|
|
1349
1344
|
highlightedIndex,
|
|
1350
1345
|
isOpen,
|
|
1351
1346
|
listItems: normalizedItems,
|
|
1352
|
-
noMatchesText,
|
|
1353
|
-
style: listStyle,
|
|
1354
|
-
setListRef: refs.setFloating,
|
|
1355
1347
|
loading: loading ?? resolvedItemsLoading,
|
|
1356
1348
|
loadingText,
|
|
1349
|
+
noMatchesText,
|
|
1357
1350
|
selectedItems: selectedItem !== null ? [selectedItem] : [],
|
|
1358
|
-
readOnly
|
|
1351
|
+
readOnly,
|
|
1352
|
+
...menuProps
|
|
1359
1353
|
}
|
|
1360
1354
|
),
|
|
1361
1355
|
...rest,
|