@octanejs/select 0.1.13 → 0.1.15
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/package.json +5 -5
- package/src/animated/input.tsrx +4 -2
- package/src/animated/transitions.tsrx +17 -15
- package/src/animated/value-container.tsrx +2 -2
- package/src/async-creatable.tsrx +8 -7
- package/src/async.tsrx +1 -1
- package/src/components.tsrx +71 -61
- package/src/creatable.tsrx +6 -3
- package/src/select.tsrx +466 -459
- package/src/state-managed-select.tsrx +2 -3
- package/src/style-context.tsrx +3 -11
- package/src/use-async.tsrx +63 -59
- package/src/use-creatable.tsrx +61 -54
- package/src/use-state-manager.tsrx +17 -15
package/src/select.tsrx
CHANGED
|
@@ -185,10 +185,11 @@ export type RawSelectRequiredPropKeys =
|
|
|
185
185
|
| 'unstyled'
|
|
186
186
|
| 'value';
|
|
187
187
|
|
|
188
|
-
export type RawSelectProps<Option, IsMulti extends boolean, Group extends GroupBase<Option>> =
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
188
|
+
export type RawSelectProps<Option, IsMulti extends boolean, Group extends GroupBase<Option>> = Omit<
|
|
189
|
+
SelectProps<Option, IsMulti, Group>,
|
|
190
|
+
RawSelectRequiredPropKeys
|
|
191
|
+
> &
|
|
192
|
+
Required<Pick<SelectProps<Option, IsMulti, Group>, RawSelectRequiredPropKeys>>;
|
|
192
193
|
|
|
193
194
|
export interface SelectInstance<
|
|
194
195
|
Option = unknown,
|
|
@@ -259,9 +260,8 @@ export const defaultProps = {
|
|
|
259
260
|
options: [],
|
|
260
261
|
pageSize: 5,
|
|
261
262
|
placeholder: 'Select...',
|
|
262
|
-
screenReaderStatus: ({ count }: { count: number }) =>
|
|
263
|
-
count !== 1 ? 's' : ''
|
|
264
|
-
} available`,
|
|
263
|
+
screenReaderStatus: ({ count }: { count: number }) =>
|
|
264
|
+
`${count} result${count !== 1 ? 's' : ''} available`,
|
|
265
265
|
styles: {},
|
|
266
266
|
tabIndex: 0,
|
|
267
267
|
tabSelectsValue: true,
|
|
@@ -299,48 +299,51 @@ function isSelected<Option, IsMulti extends boolean, Group extends GroupBase<Opt
|
|
|
299
299
|
return selectValue.some((value) => props.getOptionValue(value) === candidate);
|
|
300
300
|
}
|
|
301
301
|
|
|
302
|
-
type RequiredSelectProps<
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
302
|
+
type RequiredSelectProps<
|
|
303
|
+
Option,
|
|
304
|
+
IsMulti extends boolean,
|
|
305
|
+
Group extends GroupBase<Option>,
|
|
306
|
+
> = SelectProps<Option, IsMulti, Group> & {
|
|
307
|
+
'aria-live': 'off' | 'polite' | 'assertive';
|
|
308
|
+
captureMenuScroll: boolean;
|
|
309
|
+
classNames: ClassNamesConfig<Option, IsMulti, Group>;
|
|
310
|
+
closeMenuOnSelect: boolean;
|
|
311
|
+
closeMenuOnScroll: boolean | ((event: Event) => boolean);
|
|
312
|
+
components: SelectComponentsConfig;
|
|
313
|
+
controlShouldRenderValue: boolean;
|
|
314
|
+
filterOption: ((option: FilterOptionOption<Option>, inputValue: string) => boolean) | null;
|
|
315
|
+
formatGroupLabel: (group: Group) => OctaneNode;
|
|
316
|
+
getOptionLabel: GetOptionLabel<Option>;
|
|
317
|
+
getOptionValue: GetOptionValue<Option>;
|
|
318
|
+
inputValue: string;
|
|
319
|
+
isDisabled: boolean;
|
|
320
|
+
isLoading: boolean;
|
|
321
|
+
isMulti: IsMulti;
|
|
322
|
+
isOptionDisabled: (option: Option, selectValue: Options<Option>) => boolean;
|
|
323
|
+
isRtl: boolean;
|
|
324
|
+
loadingMessage: (value: { inputValue: string }) => OctaneNode;
|
|
325
|
+
maxMenuHeight: number;
|
|
326
|
+
menuIsOpen: boolean;
|
|
327
|
+
menuPlacement: 'auto' | 'bottom' | 'top';
|
|
328
|
+
menuPosition: 'absolute' | 'fixed';
|
|
329
|
+
menuShouldBlockScroll: boolean;
|
|
330
|
+
menuShouldScrollIntoView: boolean;
|
|
331
|
+
minMenuHeight: number;
|
|
332
|
+
noOptionsMessage: (value: { inputValue: string }) => OctaneNode;
|
|
333
|
+
onChange: (value: OnChangeValue<Option, IsMulti>, actionMeta: ActionMeta<Option>) => void;
|
|
334
|
+
onInputChange: (newValue: string, actionMeta: InputActionMeta) => void;
|
|
335
|
+
onMenuClose: () => void;
|
|
336
|
+
onMenuOpen: () => void;
|
|
337
|
+
openMenuOnClick: boolean;
|
|
338
|
+
options: OptionsOrGroups<Option, Group>;
|
|
339
|
+
pageSize: number;
|
|
340
|
+
placeholder: OctaneNode;
|
|
341
|
+
screenReaderStatus: (value: { count: number }) => string;
|
|
342
|
+
styles: StylesConfig<Option, IsMulti, Group>;
|
|
343
|
+
tabIndex: number;
|
|
344
|
+
tabSelectsValue: boolean;
|
|
345
|
+
unstyled: boolean;
|
|
346
|
+
};
|
|
344
347
|
|
|
345
348
|
export function buildCategorizedOptions<
|
|
346
349
|
Option,
|
|
@@ -362,12 +365,12 @@ export function buildCategorizedOptions<
|
|
|
362
365
|
});
|
|
363
366
|
const focusable = (option: CategorizedOption<Option>) =>
|
|
364
367
|
(!hideSelected || !option.isSelected) &&
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
368
|
+
(props.filterOption
|
|
369
|
+
? props.filterOption(
|
|
370
|
+
{ label: option.label, value: option.value, data: option.data },
|
|
371
|
+
props.inputValue ?? '',
|
|
372
|
+
)
|
|
373
|
+
: true);
|
|
371
374
|
const result: CategorizedGroupOrOption<Option, Group>[] = [];
|
|
372
375
|
props.options.forEach((item, outerIndex) => {
|
|
373
376
|
if (typeof item === 'object' && item !== null && 'options' in item) {
|
|
@@ -511,9 +514,8 @@ const defaultAriaLiveMessages = {
|
|
|
511
514
|
isSelected: boolean;
|
|
512
515
|
isAppleDevice: boolean;
|
|
513
516
|
}) {
|
|
514
|
-
const index = (values: readonly Option[]) =>
|
|
515
|
-
? `${values.indexOf(props.focused) + 1} of ${values.length}`
|
|
516
|
-
: '';
|
|
517
|
+
const index = (values: readonly Option[]) =>
|
|
518
|
+
values.length ? `${values.indexOf(props.focused) + 1} of ${values.length}` : '';
|
|
517
519
|
if (props.context === 'value') {
|
|
518
520
|
return `value ${props.label} focused, ${index(props.selectValue)}.`;
|
|
519
521
|
}
|
|
@@ -554,42 +556,40 @@ function LiveRegion<Option, IsMulti extends boolean, Group extends GroupBase<Opt
|
|
|
554
556
|
})
|
|
555
557
|
| null;
|
|
556
558
|
const selected =
|
|
557
|
-
selection?.removedValue ??
|
|
558
|
-
|
|
559
|
+
selection?.removedValue ??
|
|
560
|
+
selection?.option ??
|
|
561
|
+
(selection && !Array.isArray(selection.value) ? (selection.value as Option) : undefined);
|
|
559
562
|
const selectedMany = selection?.options ?? selection?.removedValues;
|
|
560
563
|
const ariaSelected =
|
|
561
564
|
selection && messages.onChange
|
|
562
|
-
? messages.onChange(
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
} as never,
|
|
571
|
-
)
|
|
565
|
+
? messages.onChange({
|
|
566
|
+
...selection,
|
|
567
|
+
isDisabled: selected
|
|
568
|
+
? props.selectProps.isOptionDisabled(selected, props.selectValue)
|
|
569
|
+
: false,
|
|
570
|
+
label: selected ? props.selectProps.getOptionLabel(selected) : '',
|
|
571
|
+
labels: selectedMany ? selectedMany.map(props.selectProps.getOptionLabel) : [],
|
|
572
|
+
} as never)
|
|
572
573
|
: '';
|
|
573
574
|
const focused = props.focusedOption ?? props.focusedValue;
|
|
574
575
|
const ariaFocused =
|
|
575
576
|
focused && messages.onFocus
|
|
576
|
-
? messages.onFocus(
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
} as never,
|
|
589
|
-
)
|
|
577
|
+
? messages.onFocus({
|
|
578
|
+
context: focused === props.focusedOption ? 'menu' : 'value',
|
|
579
|
+
focused,
|
|
580
|
+
isDisabled: props.selectProps.isOptionDisabled(focused, props.selectValue),
|
|
581
|
+
isSelected: Boolean(
|
|
582
|
+
props.focusedOption && props.selectValue.includes(props.focusedOption),
|
|
583
|
+
),
|
|
584
|
+
label: props.selectProps.getOptionLabel(focused),
|
|
585
|
+
options: props.focusableOptions,
|
|
586
|
+
selectValue: props.selectValue,
|
|
587
|
+
isAppleDevice: props.isAppleDevice,
|
|
588
|
+
} as never)
|
|
590
589
|
: '';
|
|
591
590
|
const ariaResults =
|
|
592
|
-
props.selectProps.menuIsOpen &&
|
|
591
|
+
props.selectProps.menuIsOpen &&
|
|
592
|
+
props.selectProps.options.length &&
|
|
593
593
|
!props.selectProps.isLoading &&
|
|
594
594
|
messages.onFilter
|
|
595
595
|
? messages.onFilter({
|
|
@@ -600,33 +600,27 @@ function LiveRegion<Option, IsMulti extends boolean, Group extends GroupBase<Opt
|
|
|
600
600
|
})
|
|
601
601
|
: '';
|
|
602
602
|
const isInitialFocus = selection?.action === 'initial-input-focus';
|
|
603
|
-
const context =
|
|
604
|
-
props.focusedValue
|
|
605
|
-
? 'value'
|
|
606
|
-
: props.selectProps.menuIsOpen
|
|
607
|
-
? 'menu'
|
|
608
|
-
: 'input';
|
|
603
|
+
const context = props.focusedValue ? 'value' : props.selectProps.menuIsOpen ? 'menu' : 'input';
|
|
609
604
|
const ariaGuidance =
|
|
610
|
-
messages.guidance?.(
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
</>;
|
|
605
|
+
messages.guidance?.({
|
|
606
|
+
'aria-label': props.selectProps['aria-label'],
|
|
607
|
+
context,
|
|
608
|
+
isDisabled: props.focusedOption
|
|
609
|
+
? props.selectProps.isOptionDisabled(props.focusedOption, props.selectValue)
|
|
610
|
+
: false,
|
|
611
|
+
isMulti: Boolean(props.selectProps.isMulti),
|
|
612
|
+
isSearchable: props.selectProps.isSearchable,
|
|
613
|
+
tabSelectsValue: props.selectProps.tabSelectsValue,
|
|
614
|
+
isInitialFocus,
|
|
615
|
+
} as never) ?? '';
|
|
616
|
+
const screenReaderText = (
|
|
617
|
+
<>
|
|
618
|
+
<span id="aria-selection">{ariaSelected}</span>
|
|
619
|
+
<span id="aria-focused">{ariaFocused}</span>
|
|
620
|
+
<span id="aria-results">{ariaResults}</span>
|
|
621
|
+
<span id="aria-guidance">{ariaGuidance}</span>
|
|
622
|
+
</>
|
|
623
|
+
);
|
|
630
624
|
<>
|
|
631
625
|
<span id={props.id} className={resolved.className}>
|
|
632
626
|
{isInitialFocus ? screenReaderText : null}
|
|
@@ -647,7 +641,7 @@ function isAppleDevice() {
|
|
|
647
641
|
if (typeof window === 'undefined' || window.navigator == null) return false;
|
|
648
642
|
const platform = window.navigator.platform;
|
|
649
643
|
const isMac = /^Mac/i.test(platform);
|
|
650
|
-
return /^iPhone|^iPad/i.test(platform) || isMac && navigator.maxTouchPoints > 1 || isMac;
|
|
644
|
+
return /^iPhone|^iPad/i.test(platform) || (isMac && navigator.maxTouchPoints > 1) || isMac;
|
|
651
645
|
}
|
|
652
646
|
|
|
653
647
|
export function Select<
|
|
@@ -746,15 +740,16 @@ export function Select<
|
|
|
746
740
|
const nextFocusedOption =
|
|
747
741
|
focusedOption && focusableOptions.includes(focusedOption)
|
|
748
742
|
? focusedOption
|
|
749
|
-
: focusableOptions[0] ?? null;
|
|
743
|
+
: (focusableOptions[0] ?? null);
|
|
750
744
|
if (nextFocusedOption !== focusedOption) setFocusedOption(nextFocusedOption);
|
|
751
745
|
}, [props.options, props.value, props.menuIsOpen, props.inputValue, focusedOption]);
|
|
752
746
|
useEffect(() => {
|
|
753
747
|
const prev = prevFocusReconcileRef.current;
|
|
754
748
|
const changed =
|
|
755
|
-
props.value !== prev.value ||
|
|
756
|
-
|
|
757
|
-
|
|
749
|
+
props.value !== prev.value ||
|
|
750
|
+
props.options !== prev.options ||
|
|
751
|
+
props.menuIsOpen !== prev.menuIsOpen ||
|
|
752
|
+
props.inputValue !== prev.inputValue;
|
|
758
753
|
if (!changed) return;
|
|
759
754
|
prevFocusReconcileRef.current = {
|
|
760
755
|
options: props.options,
|
|
@@ -764,10 +759,9 @@ export function Select<
|
|
|
764
759
|
};
|
|
765
760
|
const lastSelectValue = prevSelectValueRef.current;
|
|
766
761
|
prevSelectValueRef.current = selectValue;
|
|
767
|
-
const nextFocusedValue =
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
: null;
|
|
762
|
+
const nextFocusedValue = clearFocusValueOnUpdateRef.current
|
|
763
|
+
? getNextFocusedValue(focusedValue, lastSelectValue, selectValue)
|
|
764
|
+
: null;
|
|
771
765
|
clearFocusValueOnUpdateRef.current = false;
|
|
772
766
|
if (nextFocusedValue !== focusedValue) setFocusedValue(nextFocusedValue);
|
|
773
767
|
}, [props.options, props.value, props.menuIsOpen, props.inputValue, selectValue, focusedValue]);
|
|
@@ -786,11 +780,8 @@ export function Select<
|
|
|
786
780
|
};
|
|
787
781
|
const getClassNames = (name: string, componentProps: unknown) =>
|
|
788
782
|
props.classNames[name as StyleKey]?.(componentProps);
|
|
789
|
-
const cx = (state: Record<string, boolean>, ...names: (string | undefined)[]) =>
|
|
790
|
-
props.classNamePrefix,
|
|
791
|
-
state,
|
|
792
|
-
...names,
|
|
793
|
-
);
|
|
783
|
+
const cx = (state: Record<string, boolean>, ...names: (string | undefined)[]) =>
|
|
784
|
+
classNames(props.classNamePrefix, state, ...names);
|
|
794
785
|
|
|
795
786
|
const closeMenu = () => {
|
|
796
787
|
props.onInputChange('', {
|
|
@@ -810,8 +801,9 @@ export function Select<
|
|
|
810
801
|
const target = event.target;
|
|
811
802
|
if (
|
|
812
803
|
target instanceof HTMLElement &&
|
|
813
|
-
|
|
814
|
-
)
|
|
804
|
+
(target === document.documentElement || target === document.body)
|
|
805
|
+
)
|
|
806
|
+
props.onMenuClose();
|
|
815
807
|
};
|
|
816
808
|
document.addEventListener('scroll', onScroll, true);
|
|
817
809
|
return () => document.removeEventListener('scroll', onScroll, true);
|
|
@@ -827,16 +819,20 @@ export function Select<
|
|
|
827
819
|
const onTouchMove = (event: TouchEvent) => {
|
|
828
820
|
const touch = event.touches.item(0);
|
|
829
821
|
if (!touch) return;
|
|
830
|
-
userIsDragging.current =
|
|
822
|
+
userIsDragging.current =
|
|
823
|
+
Math.abs(touch.clientX - initialTouch.current.x) > 5 ||
|
|
831
824
|
Math.abs(touch.clientY - initialTouch.current.y) > 5;
|
|
832
825
|
};
|
|
833
826
|
const onTouchEnd = (event: TouchEvent) => {
|
|
834
827
|
if (!userIsDragging.current) {
|
|
835
828
|
const target = event.target as Node;
|
|
836
829
|
if (
|
|
837
|
-
controlRef.current &&
|
|
838
|
-
|
|
839
|
-
|
|
830
|
+
controlRef.current &&
|
|
831
|
+
!controlRef.current.contains(target) &&
|
|
832
|
+
menuListRef.current &&
|
|
833
|
+
!menuListRef.current.contains(target)
|
|
834
|
+
)
|
|
835
|
+
inputRef.current?.blur();
|
|
840
836
|
}
|
|
841
837
|
initialTouch.current = { x: 0, y: 0 };
|
|
842
838
|
};
|
|
@@ -876,14 +872,12 @@ export function Select<
|
|
|
876
872
|
option,
|
|
877
873
|
);
|
|
878
874
|
} else if (props.isOptionDisabled(option, selectValue)) {
|
|
879
|
-
setAriaSelection(
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
} as AriaSelection<Option, IsMulti>,
|
|
886
|
-
);
|
|
875
|
+
setAriaSelection({
|
|
876
|
+
action: 'select-option',
|
|
877
|
+
option,
|
|
878
|
+
name: props.name,
|
|
879
|
+
value: option,
|
|
880
|
+
} as AriaSelection<Option, IsMulti>);
|
|
887
881
|
return;
|
|
888
882
|
} else if (props.isMulti) {
|
|
889
883
|
setValue([...selectValue, option] as OnChangeValue<Option, IsMulti>, 'select-option', option);
|
|
@@ -911,7 +905,7 @@ export function Select<
|
|
|
911
905
|
const nextValue = valueTernary(
|
|
912
906
|
props.isMulti,
|
|
913
907
|
newValue,
|
|
914
|
-
newValue[0] ?? null as Option,
|
|
908
|
+
newValue[0] ?? (null as Option),
|
|
915
909
|
) as OnChangeValue<Option, IsMulti>;
|
|
916
910
|
const actionMeta = {
|
|
917
911
|
action: 'remove-value',
|
|
@@ -930,7 +924,7 @@ export function Select<
|
|
|
930
924
|
const nextValue = valueTernary(
|
|
931
925
|
props.isMulti,
|
|
932
926
|
newValue,
|
|
933
|
-
newValue[0] ?? null as Option,
|
|
927
|
+
newValue[0] ?? (null as Option),
|
|
934
928
|
) as OnChangeValue<Option, IsMulti>;
|
|
935
929
|
const actionMeta = {
|
|
936
930
|
action: 'pop-value',
|
|
@@ -962,8 +956,7 @@ export function Select<
|
|
|
962
956
|
const focusOption = (direction: FocusDirection = 'first') => {
|
|
963
957
|
if (!focusableOptions.length) return;
|
|
964
958
|
if (ariaSelection?.action === 'initial-input-focus') setAriaSelection(null);
|
|
965
|
-
const current =
|
|
966
|
-
focusedOption ? focusableOptions.indexOf(focusedOption) : -1;
|
|
959
|
+
const current = focusedOption ? focusableOptions.indexOf(focusedOption) : -1;
|
|
967
960
|
const index =
|
|
968
961
|
direction === 'first'
|
|
969
962
|
? 0
|
|
@@ -985,8 +978,7 @@ export function Select<
|
|
|
985
978
|
const focusValue = (direction: 'previous' | 'next') => {
|
|
986
979
|
if (!props.isMulti || !selectValue.length) return;
|
|
987
980
|
if (ariaSelection?.action === 'initial-input-focus') setAriaSelection(null);
|
|
988
|
-
const current =
|
|
989
|
-
focusedValue ? selectValue.indexOf(focusedValue) : -1;
|
|
981
|
+
const current = focusedValue ? selectValue.indexOf(focusedValue) : -1;
|
|
990
982
|
const next =
|
|
991
983
|
direction === 'previous'
|
|
992
984
|
? current === 0
|
|
@@ -1008,12 +1000,9 @@ export function Select<
|
|
|
1008
1000
|
const selectedIndex =
|
|
1009
1001
|
!props.isMulti && selectValue.length ? focusableOptions.indexOf(selectValue[0]) : -1;
|
|
1010
1002
|
setFocusedOption(
|
|
1011
|
-
focusableOptions[
|
|
1012
|
-
? selectedIndex
|
|
1013
|
-
|
|
1014
|
-
? 0
|
|
1015
|
-
: focusableOptions.length - 1] ??
|
|
1016
|
-
null,
|
|
1003
|
+
focusableOptions[
|
|
1004
|
+
selectedIndex > -1 ? selectedIndex : direction === 'first' ? 0 : focusableOptions.length - 1
|
|
1005
|
+
] ?? null,
|
|
1017
1006
|
);
|
|
1018
1007
|
props.onMenuOpen();
|
|
1019
1008
|
};
|
|
@@ -1039,13 +1028,7 @@ export function Select<
|
|
|
1039
1028
|
selectOption,
|
|
1040
1029
|
setValue,
|
|
1041
1030
|
}),
|
|
1042
|
-
[
|
|
1043
|
-
categorized,
|
|
1044
|
-
focusableOptions,
|
|
1045
|
-
props.getOptionLabel,
|
|
1046
|
-
props.getOptionValue,
|
|
1047
|
-
selectValue,
|
|
1048
|
-
],
|
|
1031
|
+
[categorized, focusableOptions, props.getOptionLabel, props.getOptionValue, selectValue],
|
|
1049
1032
|
);
|
|
1050
1033
|
|
|
1051
1034
|
const onKeyDown = (event: KeyboardEvent) => {
|
|
@@ -1107,9 +1090,13 @@ export function Select<
|
|
|
1107
1090
|
case 'Tab':
|
|
1108
1091
|
if (isComposing) return;
|
|
1109
1092
|
if (
|
|
1110
|
-
!event.shiftKey &&
|
|
1111
|
-
|
|
1112
|
-
|
|
1093
|
+
!event.shiftKey &&
|
|
1094
|
+
props.tabSelectsValue &&
|
|
1095
|
+
props.menuIsOpen &&
|
|
1096
|
+
focusedOption &&
|
|
1097
|
+
!(props.openMenuOnFocus && selectValue.includes(focusedOption))
|
|
1098
|
+
)
|
|
1099
|
+
selectOption(focusedOption);
|
|
1113
1100
|
else return;
|
|
1114
1101
|
break;
|
|
1115
1102
|
case ' ':
|
|
@@ -1166,58 +1153,58 @@ export function Select<
|
|
|
1166
1153
|
};
|
|
1167
1154
|
|
|
1168
1155
|
const valueUI =
|
|
1169
|
-
!selectValue.length || !props.controlShouldRenderValue
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1156
|
+
!selectValue.length || !props.controlShouldRenderValue ? (
|
|
1157
|
+
props.inputValue ? null : (
|
|
1158
|
+
<Components.Placeholder
|
|
1159
|
+
{...commonProps}
|
|
1160
|
+
key="placeholder"
|
|
1161
|
+
isDisabled={props.isDisabled}
|
|
1162
|
+
isFocused={isFocused}
|
|
1163
|
+
innerProps={{ id: elementId('placeholder') }}
|
|
1164
|
+
>
|
|
1165
|
+
{props.placeholder}
|
|
1166
|
+
</Components.Placeholder>
|
|
1167
|
+
)
|
|
1168
|
+
) : props.isMulti ? (
|
|
1169
|
+
selectValue.map((option, index) => (
|
|
1170
|
+
<Components.MultiValue
|
|
1171
|
+
{...commonProps}
|
|
1172
|
+
key={`${props.getOptionLabel(option)}-${props.getOptionValue(option)}`}
|
|
1173
|
+
components={{
|
|
1174
|
+
Container: Components.MultiValueContainer,
|
|
1175
|
+
Label: Components.MultiValueLabel,
|
|
1176
|
+
Remove: Components.MultiValueRemove,
|
|
1177
|
+
}}
|
|
1178
|
+
data={option}
|
|
1179
|
+
index={index}
|
|
1180
|
+
isDisabled={props.isDisabled}
|
|
1181
|
+
isFocused={focusedValue === option}
|
|
1182
|
+
removeProps={{
|
|
1183
|
+
onClick: () => removeValue(option),
|
|
1184
|
+
onMouseDown: (event: MouseEvent) => event.preventDefault(),
|
|
1185
|
+
onTouchEnd: () => {
|
|
1186
|
+
if (!userIsDragging.current) removeValue(option);
|
|
1187
|
+
},
|
|
1188
|
+
}}
|
|
1189
|
+
>
|
|
1190
|
+
{formatOption(option, 'value')}
|
|
1191
|
+
</Components.MultiValue>
|
|
1192
|
+
))
|
|
1193
|
+
) : props.inputValue ? null : (
|
|
1194
|
+
<Components.SingleValue {...commonProps} data={selectValue[0]} isDisabled={props.isDisabled}>
|
|
1195
|
+
{formatOption(selectValue[0], 'value')}
|
|
1196
|
+
</Components.SingleValue>
|
|
1197
|
+
);
|
|
1209
1198
|
|
|
1210
1199
|
const inputId = props.inputId || elementId('input');
|
|
1211
1200
|
const handleInputFocus = (event: FocusEvent) => {
|
|
1212
1201
|
setInputIsHidden(false);
|
|
1213
1202
|
setIsFocused(true);
|
|
1214
|
-
setAriaSelection(
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
} as AriaSelection<Option, IsMulti>,
|
|
1220
|
-
);
|
|
1203
|
+
setAriaSelection({
|
|
1204
|
+
action: 'initial-input-focus',
|
|
1205
|
+
value: valueTernary(props.isMulti, selectValue, selectValue[0] ?? (null as Option)),
|
|
1206
|
+
options: selectValue,
|
|
1207
|
+
} as AriaSelection<Option, IsMulti>);
|
|
1221
1208
|
props.onFocus?.(event);
|
|
1222
1209
|
if (props.openMenuOnFocus) openMenu('first');
|
|
1223
1210
|
};
|
|
@@ -1235,12 +1222,11 @@ export function Select<
|
|
|
1235
1222
|
setFocusedValue(null);
|
|
1236
1223
|
setIsFocused(false);
|
|
1237
1224
|
};
|
|
1238
|
-
const ariaDescribedBy =
|
|
1239
|
-
|
|
1240
|
-
?
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
: elementId('placeholder');
|
|
1225
|
+
const ariaDescribedBy = selectValue.length
|
|
1226
|
+
? ariaSelection?.action === 'initial-input-focus'
|
|
1227
|
+
? elementId('live-region')
|
|
1228
|
+
: undefined
|
|
1229
|
+
: elementId('placeholder');
|
|
1244
1230
|
function focusedOptionId(): string {
|
|
1245
1231
|
if (!focusedOption) return '';
|
|
1246
1232
|
for (const item of categorized) {
|
|
@@ -1256,8 +1242,7 @@ export function Select<
|
|
|
1256
1242
|
}
|
|
1257
1243
|
return '';
|
|
1258
1244
|
}
|
|
1259
|
-
const ariaActiveDescendant =
|
|
1260
|
-
appleDevice ? undefined : focusedOptionId();
|
|
1245
|
+
const ariaActiveDescendant = appleDevice ? undefined : focusedOptionId();
|
|
1261
1246
|
const commonInputAttributes: Omit<Octane.JSX.IntrinsicElements['input'], 'ref'> & {
|
|
1262
1247
|
ref?: Octane.Ref<HTMLInputElement>;
|
|
1263
1248
|
} = {
|
|
@@ -1281,56 +1266,57 @@ export function Select<
|
|
|
1281
1266
|
'aria-describedby': ariaDescribedBy,
|
|
1282
1267
|
ref: inputRef,
|
|
1283
1268
|
};
|
|
1284
|
-
const inputUI =
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1269
|
+
const inputUI = !props.isSearchable ? (
|
|
1270
|
+
<input
|
|
1271
|
+
{...commonInputAttributes}
|
|
1272
|
+
className={resolveStyle(dummyInputStyle).className}
|
|
1273
|
+
inputMode="none"
|
|
1274
|
+
value=""
|
|
1275
|
+
onInput={() => {}}
|
|
1276
|
+
aria-readonly="true"
|
|
1277
|
+
/>
|
|
1278
|
+
) : (
|
|
1279
|
+
<Components.Input
|
|
1280
|
+
{...commonProps}
|
|
1281
|
+
autoCapitalize="none"
|
|
1282
|
+
autoComplete="off"
|
|
1283
|
+
autoCorrect="off"
|
|
1284
|
+
id={inputId}
|
|
1285
|
+
innerRef={inputRef}
|
|
1286
|
+
isDisabled={props.isDisabled}
|
|
1287
|
+
isHidden={inputIsHidden}
|
|
1288
|
+
onBlur={commonInputAttributes.onBlur}
|
|
1289
|
+
onInput={(event: InputEvent) => {
|
|
1290
|
+
const target = event.currentTarget as HTMLInputElement;
|
|
1291
|
+
setInputIsHidden(false);
|
|
1292
|
+
props.onInputChange(target.value, {
|
|
1293
|
+
action: 'input-change',
|
|
1294
|
+
prevInputValue: props.inputValue ?? '',
|
|
1295
|
+
});
|
|
1296
|
+
if (!props.menuIsOpen) props.onMenuOpen();
|
|
1297
|
+
}}
|
|
1298
|
+
onFocus={handleInputFocus}
|
|
1299
|
+
spellCheck="false"
|
|
1300
|
+
onCompositionStart={() => setIsComposing(true)}
|
|
1301
|
+
onCompositionEnd={() => setIsComposing(false)}
|
|
1302
|
+
tabIndex={props.tabIndex}
|
|
1303
|
+
form={props.form}
|
|
1304
|
+
type="text"
|
|
1305
|
+
value={props.inputValue ?? ''}
|
|
1306
|
+
aria-autocomplete="list"
|
|
1307
|
+
aria-expanded={props.menuIsOpen}
|
|
1308
|
+
aria-haspopup="true"
|
|
1309
|
+
aria-errormessage={props['aria-errormessage']}
|
|
1310
|
+
aria-invalid={props['aria-invalid']}
|
|
1311
|
+
aria-label={props['aria-label']}
|
|
1312
|
+
aria-labelledby={props['aria-labelledby']}
|
|
1313
|
+
aria-required={props.required}
|
|
1314
|
+
role="combobox"
|
|
1315
|
+
aria-activedescendant={ariaActiveDescendant}
|
|
1316
|
+
aria-controls={props.menuIsOpen ? elementId('listbox') : undefined}
|
|
1317
|
+
aria-describedby={ariaDescribedBy}
|
|
1318
|
+
/>
|
|
1319
|
+
);
|
|
1334
1320
|
|
|
1335
1321
|
const onOptionHover = (option: Option) => {
|
|
1336
1322
|
if (blockOptionHover.current || focusedOption === option) return;
|
|
@@ -1339,171 +1325,193 @@ export function Select<
|
|
|
1339
1325
|
const renderOption = (option: CategorizedOption<Option>, id: string) => {
|
|
1340
1326
|
const optionIsFocused = focusedOption === option.data;
|
|
1341
1327
|
const optionId = elementId(`option-${id}`);
|
|
1342
|
-
return
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1328
|
+
return (
|
|
1329
|
+
<Components.Option
|
|
1330
|
+
{...commonProps}
|
|
1331
|
+
key={optionId}
|
|
1332
|
+
data={option.data}
|
|
1333
|
+
innerRef={optionIsFocused ? focusedOptionRef : null}
|
|
1334
|
+
innerProps={{
|
|
1335
|
+
id: optionId,
|
|
1336
|
+
onClick: option.isDisabled ? undefined : () => selectOption(option.data),
|
|
1337
|
+
onMouseMove: option.isDisabled ? undefined : () => onOptionHover(option.data),
|
|
1338
|
+
onMouseOver: option.isDisabled ? undefined : () => onOptionHover(option.data),
|
|
1339
|
+
onTouchEnd: option.isDisabled
|
|
1340
|
+
? undefined
|
|
1341
|
+
: () => {
|
|
1342
|
+
if (!userIsDragging.current) selectOption(option.data);
|
|
1343
|
+
},
|
|
1344
|
+
tabIndex: -1,
|
|
1345
|
+
role: 'option',
|
|
1346
|
+
'aria-selected': appleDevice ? undefined : option.isSelected,
|
|
1347
|
+
}}
|
|
1348
|
+
isDisabled={option.isDisabled}
|
|
1349
|
+
isFocused={optionIsFocused}
|
|
1350
|
+
isSelected={option.isSelected}
|
|
1351
|
+
label={option.label}
|
|
1352
|
+
type="option"
|
|
1353
|
+
>
|
|
1354
|
+
{formatOption(option.data, 'menu')}
|
|
1355
|
+
</Components.Option>
|
|
1356
|
+
);
|
|
1367
1357
|
};
|
|
1368
1358
|
|
|
1369
1359
|
let menuUI: OctaneNode = null;
|
|
1370
1360
|
if (props.menuIsOpen) {
|
|
1371
|
-
const children =
|
|
1372
|
-
categorized.
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
)
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1361
|
+
const children = categorized.length
|
|
1362
|
+
? categorized.map((item) =>
|
|
1363
|
+
item.type === 'group' ? (
|
|
1364
|
+
<Components.Group
|
|
1365
|
+
{...commonProps}
|
|
1366
|
+
key={elementId(`group-${item.index}`)}
|
|
1367
|
+
Heading={Components.GroupHeading}
|
|
1368
|
+
data={item.data}
|
|
1369
|
+
headingProps={{
|
|
1370
|
+
id: `${elementId(`group-${item.index}`)}-heading`,
|
|
1371
|
+
data: item.data,
|
|
1372
|
+
}}
|
|
1373
|
+
label={props.formatGroupLabel(item.data)}
|
|
1374
|
+
options={item.options}
|
|
1375
|
+
>
|
|
1376
|
+
{item.options.map((option) => renderOption(option, `${item.index}-${option.index}`))}
|
|
1377
|
+
</Components.Group>
|
|
1378
|
+
) : (
|
|
1379
|
+
renderOption(item, String(item.index))
|
|
1380
|
+
),
|
|
1381
|
+
)
|
|
1382
|
+
: props.isLoading
|
|
1383
|
+
? props.loadingMessage({ inputValue: props.inputValue ?? '' })
|
|
1384
|
+
: props.noOptionsMessage({ inputValue: props.inputValue ?? '' });
|
|
1394
1385
|
if (children === null) {
|
|
1395
1386
|
menuUI = null;
|
|
1396
1387
|
} else {
|
|
1397
|
-
const renderedChildren =
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
{...commonProps}
|
|
1407
|
-
innerRef={menuRef}
|
|
1408
|
-
innerProps={{
|
|
1409
|
-
onMouseDown: (event: MouseEvent) => {
|
|
1410
|
-
event.stopPropagation();
|
|
1411
|
-
event.preventDefault();
|
|
1412
|
-
},
|
|
1413
|
-
onMouseMove: (event: MouseEvent) => {
|
|
1414
|
-
blockOptionHover.current = false;
|
|
1415
|
-
event.stopPropagation();
|
|
1416
|
-
},
|
|
1417
|
-
}}
|
|
1418
|
-
isLoading={props.isLoading}
|
|
1419
|
-
placement={menuPlacement}
|
|
1420
|
-
minMenuHeight={props.minMenuHeight}
|
|
1421
|
-
maxMenuHeight={menuMaxHeight}
|
|
1422
|
-
menuPlacement={props.menuPlacement}
|
|
1423
|
-
menuPosition={props.menuPosition}
|
|
1424
|
-
menuShouldScrollIntoView={props.menuShouldScrollIntoView}
|
|
1425
|
-
>
|
|
1426
|
-
<Components.MenuList
|
|
1388
|
+
const renderedChildren = categorized.length ? (
|
|
1389
|
+
children
|
|
1390
|
+
) : props.isLoading ? (
|
|
1391
|
+
<Components.LoadingMessage {...commonProps}>{children}</Components.LoadingMessage>
|
|
1392
|
+
) : (
|
|
1393
|
+
<Components.NoOptionsMessage {...commonProps}>{children}</Components.NoOptionsMessage>
|
|
1394
|
+
);
|
|
1395
|
+
const menuElement = (
|
|
1396
|
+
<Components.Menu
|
|
1427
1397
|
{...commonProps}
|
|
1428
|
-
innerRef={
|
|
1398
|
+
innerRef={menuRef}
|
|
1429
1399
|
innerProps={{
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1400
|
+
onMouseDown: (event: MouseEvent) => {
|
|
1401
|
+
event.stopPropagation();
|
|
1402
|
+
event.preventDefault();
|
|
1403
|
+
},
|
|
1404
|
+
onMouseMove: (event: MouseEvent) => {
|
|
1405
|
+
blockOptionHover.current = false;
|
|
1406
|
+
event.stopPropagation();
|
|
1407
|
+
},
|
|
1433
1408
|
}}
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1409
|
+
isLoading={props.isLoading}
|
|
1410
|
+
placement={menuPlacement}
|
|
1411
|
+
minMenuHeight={props.minMenuHeight}
|
|
1412
|
+
maxMenuHeight={menuMaxHeight}
|
|
1413
|
+
menuPlacement={props.menuPlacement}
|
|
1414
|
+
menuPosition={props.menuPosition}
|
|
1415
|
+
menuShouldScrollIntoView={props.menuShouldScrollIntoView}
|
|
1416
|
+
>
|
|
1417
|
+
<Components.MenuList
|
|
1418
|
+
{...commonProps}
|
|
1419
|
+
innerRef={menuListRef}
|
|
1420
|
+
innerProps={{
|
|
1421
|
+
role: 'listbox',
|
|
1422
|
+
'aria-multiselectable': Boolean(props.isMulti),
|
|
1423
|
+
id: elementId('listbox'),
|
|
1424
|
+
}}
|
|
1425
|
+
maxHeight={menuMaxHeight}
|
|
1426
|
+
focusedOption={focusedOption}
|
|
1427
|
+
>
|
|
1428
|
+
{renderedChildren}
|
|
1429
|
+
</Components.MenuList>
|
|
1430
|
+
</Components.Menu>
|
|
1431
|
+
);
|
|
1432
|
+
menuUI =
|
|
1433
|
+
props.menuPortalTarget || props.menuPosition === 'fixed' ? (
|
|
1434
|
+
<Components.MenuPortal
|
|
1440
1435
|
{...commonProps}
|
|
1441
1436
|
appendTo={props.menuPortalTarget ?? undefined}
|
|
1442
1437
|
controlElement={controlRef.current}
|
|
1443
1438
|
innerProps={{}}
|
|
1444
1439
|
menuPlacement={menuPlacement}
|
|
1445
1440
|
menuPosition={props.menuPosition}
|
|
1446
|
-
>
|
|
1447
|
-
|
|
1441
|
+
>
|
|
1442
|
+
{menuElement}
|
|
1443
|
+
</Components.MenuPortal>
|
|
1444
|
+
) : (
|
|
1445
|
+
menuElement
|
|
1446
|
+
);
|
|
1448
1447
|
if (props.menuShouldBlockScroll) {
|
|
1449
1448
|
const unlockedMenu = menuUI;
|
|
1450
|
-
menuUI =
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1449
|
+
menuUI = (
|
|
1450
|
+
<>
|
|
1451
|
+
<div
|
|
1452
|
+
className={resolveStyle(scrollBlockerStyle).className}
|
|
1453
|
+
onClick={(event: MouseEvent) => {
|
|
1454
|
+
const target = event.target as HTMLElement;
|
|
1455
|
+
(target.ownerDocument.activeElement as HTMLElement | null)?.blur();
|
|
1456
|
+
}}
|
|
1457
|
+
/>
|
|
1458
|
+
{unlockedMenu}
|
|
1459
|
+
</>
|
|
1460
|
+
);
|
|
1460
1461
|
}
|
|
1461
1462
|
}
|
|
1462
1463
|
}
|
|
1463
1464
|
|
|
1464
1465
|
let formField: OctaneNode = null;
|
|
1465
1466
|
if (props.required && !selectValue.length && !props.isDisabled) {
|
|
1466
|
-
formField =
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
event
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1467
|
+
formField = (
|
|
1468
|
+
<input
|
|
1469
|
+
required={true}
|
|
1470
|
+
name={props.name}
|
|
1471
|
+
tabIndex={-1}
|
|
1472
|
+
aria-hidden="true"
|
|
1473
|
+
onFocus={(event: FocusEvent) => {
|
|
1474
|
+
event.preventDefault();
|
|
1475
|
+
event.stopPropagation();
|
|
1476
|
+
inputRef.current?.focus();
|
|
1477
|
+
}}
|
|
1478
|
+
className={resolveStyle(requiredInputStyle).className}
|
|
1479
|
+
value=""
|
|
1480
|
+
onInput={() => {}}
|
|
1481
|
+
/>
|
|
1482
|
+
);
|
|
1480
1483
|
} else if (props.name && !props.isDisabled) {
|
|
1481
1484
|
if (props.isMulti) {
|
|
1482
|
-
formField = props.delimiter
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1485
|
+
formField = props.delimiter ? (
|
|
1486
|
+
<input
|
|
1487
|
+
name={props.name}
|
|
1488
|
+
type="hidden"
|
|
1489
|
+
value={selectValue.map(props.getOptionValue).join(props.delimiter)}
|
|
1490
|
+
/>
|
|
1491
|
+
) : (
|
|
1492
|
+
<div>
|
|
1493
|
+
{selectValue.length ? (
|
|
1494
|
+
selectValue.map((option, index) => (
|
|
1495
|
+
<input
|
|
1496
|
+
key={`i-${index}`}
|
|
1497
|
+
name={props.name}
|
|
1498
|
+
type="hidden"
|
|
1499
|
+
value={props.getOptionValue(option)}
|
|
1500
|
+
/>
|
|
1501
|
+
))
|
|
1502
|
+
) : (
|
|
1503
|
+
<input name={props.name} type="hidden" value="" />
|
|
1504
|
+
)}
|
|
1505
|
+
</div>
|
|
1506
|
+
);
|
|
1501
1507
|
} else {
|
|
1502
|
-
formField =
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1508
|
+
formField = (
|
|
1509
|
+
<input
|
|
1510
|
+
name={props.name}
|
|
1511
|
+
type="hidden"
|
|
1512
|
+
value={selectValue[0] ? props.getOptionValue(selectValue[0]) : ''}
|
|
1513
|
+
/>
|
|
1514
|
+
);
|
|
1507
1515
|
}
|
|
1508
1516
|
}
|
|
1509
1517
|
<Components.SelectContainer
|
|
@@ -1542,15 +1550,13 @@ export function Select<
|
|
|
1542
1550
|
{createElement(Components.ValueContainer, {
|
|
1543
1551
|
...commonProps,
|
|
1544
1552
|
isDisabled: props.isDisabled,
|
|
1545
|
-
children:
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
createElement(Fragment, { key: 'select-input', children: inputUI }),
|
|
1553
|
-
],
|
|
1553
|
+
children:
|
|
1554
|
+
props.isMulti && Array.isArray(valueUI)
|
|
1555
|
+
? [...valueUI, createElement(Fragment, { key: 'select-input', children: inputUI })]
|
|
1556
|
+
: [
|
|
1557
|
+
createElement(Fragment, { key: 'select-value', children: valueUI }),
|
|
1558
|
+
createElement(Fragment, { key: 'select-input', children: inputUI }),
|
|
1559
|
+
],
|
|
1554
1560
|
})}
|
|
1555
1561
|
</>
|
|
1556
1562
|
} @else {
|
|
@@ -1560,50 +1566,52 @@ export function Select<
|
|
|
1560
1566
|
</Components.ValueContainer>
|
|
1561
1567
|
}
|
|
1562
1568
|
<Components.IndicatorsContainer {...commonProps} isDisabled={props.isDisabled}>
|
|
1563
|
-
{(props.isClearable ?? Boolean(props.isMulti)) &&
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1569
|
+
{(props.isClearable ?? Boolean(props.isMulti)) &&
|
|
1570
|
+
selectValue.length &&
|
|
1571
|
+
!props.isDisabled &&
|
|
1572
|
+
!props.isLoading ? (
|
|
1573
|
+
<Components.ClearIndicator
|
|
1574
|
+
{...commonProps}
|
|
1575
|
+
innerProps={{
|
|
1576
|
+
'aria-hidden': 'true',
|
|
1577
|
+
onMouseDown: handleClearPointerEnd,
|
|
1578
|
+
onTouchEnd: (event: TouchEvent) => {
|
|
1579
|
+
if (!userIsDragging.current) handleClearPointerEnd(event);
|
|
1580
|
+
},
|
|
1581
|
+
}}
|
|
1582
|
+
isDisabled={props.isDisabled}
|
|
1583
|
+
isFocused={isFocused}
|
|
1584
|
+
/>
|
|
1585
|
+
) : null}
|
|
1586
|
+
{props.isLoading ? (
|
|
1587
|
+
<Components.LoadingIndicator
|
|
1588
|
+
{...commonProps}
|
|
1589
|
+
innerProps={{ 'aria-hidden': 'true' }}
|
|
1590
|
+
isDisabled={props.isDisabled}
|
|
1591
|
+
isFocused={isFocused}
|
|
1592
|
+
/>
|
|
1593
|
+
) : null}
|
|
1594
|
+
{Components.DropdownIndicator && Components.IndicatorSeparator ? (
|
|
1595
|
+
<Components.IndicatorSeparator
|
|
1596
|
+
{...commonProps}
|
|
1597
|
+
isDisabled={props.isDisabled}
|
|
1598
|
+
isFocused={isFocused}
|
|
1599
|
+
/>
|
|
1600
|
+
) : null}
|
|
1601
|
+
{Components.DropdownIndicator ? (
|
|
1602
|
+
<Components.DropdownIndicator
|
|
1603
|
+
{...commonProps}
|
|
1604
|
+
innerProps={{
|
|
1605
|
+
'aria-hidden': 'true',
|
|
1606
|
+
onMouseDown: handleDropdownPointerEnd,
|
|
1607
|
+
onTouchEnd: (event: TouchEvent) => {
|
|
1608
|
+
if (!userIsDragging.current) handleDropdownPointerEnd(event);
|
|
1609
|
+
},
|
|
1610
|
+
}}
|
|
1611
|
+
isDisabled={props.isDisabled}
|
|
1612
|
+
isFocused={isFocused}
|
|
1613
|
+
/>
|
|
1614
|
+
) : null}
|
|
1607
1615
|
</Components.IndicatorsContainer>
|
|
1608
1616
|
</Components.Control>
|
|
1609
1617
|
{menuUI}
|
|
@@ -1615,7 +1623,6 @@ export type PublicBaseSelectProps<
|
|
|
1615
1623
|
Option,
|
|
1616
1624
|
IsMulti extends boolean,
|
|
1617
1625
|
Group extends GroupBase<Option>,
|
|
1618
|
-
> =
|
|
1619
|
-
SelectProps<Option, IsMulti, Group>;
|
|
1626
|
+
> = SelectProps<Option, IsMulti, Group>;
|
|
1620
1627
|
|
|
1621
1628
|
export const baseComponents = builtinComponents;
|