@leafygreen-ui/combobox 7.2.0 → 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/CHANGELOG.md +15 -0
- package/dist/Combobox/Combobox.d.ts +1 -1
- package/dist/Combobox/Combobox.d.ts.map +1 -1
- package/dist/Combobox/Combobox.types.d.ts +8 -0
- package/dist/Combobox/Combobox.types.d.ts.map +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/utils/doesSelectionExist.d.ts +3 -0
- package/dist/utils/doesSelectionExist.d.ts.map +1 -0
- package/package.json +5 -4
- package/src/Combobox/Combobox.spec.tsx +90 -56
- package/src/Combobox/Combobox.tsx +54 -33
- package/src/Combobox/Combobox.types.ts +10 -0
- package/src/Combobox.story.tsx +1 -0
- package/src/utils/doesSelectionExist.ts +16 -0
- package/stories.js +1 -1
- package/tsconfig.json +3 -0
- package/tsdoc.json +20 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doesSelectionExist.d.ts","sourceRoot":"","sources":["../../src/utils/doesSelectionExist.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAE3C,eAAO,MAAM,kBAAkB,4EAE5B,OAMF,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leafygreen-ui/combobox",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "8.0.0",
|
|
4
4
|
"description": "leafyGreen UI Kit Combobox",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/esm/index.js",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"access": "public"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@leafygreen-ui/checkbox": "^12.0
|
|
25
|
+
"@leafygreen-ui/checkbox": "^12.1.0",
|
|
26
26
|
"@leafygreen-ui/chip": "^1.0.0",
|
|
27
27
|
"@leafygreen-ui/emotion": "^4.0.7",
|
|
28
28
|
"@leafygreen-ui/hooks": "^8.1.1",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"@leafygreen-ui/palette": "^4.0.7",
|
|
35
35
|
"@leafygreen-ui/popover": "^11.1.1",
|
|
36
36
|
"@leafygreen-ui/tokens": "^2.3.0",
|
|
37
|
-
"@leafygreen-ui/typography": "^18.
|
|
37
|
+
"@leafygreen-ui/typography": "^18.2.0",
|
|
38
38
|
"chalk": "^4.1.2",
|
|
39
39
|
"lodash": "^4.17.21",
|
|
40
40
|
"polished": "^4.2.2"
|
|
@@ -43,7 +43,8 @@
|
|
|
43
43
|
"@leafygreen-ui/leafygreen-provider": "^3.1.10"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
|
-
"@leafygreen-ui/button": "^21.0.12"
|
|
46
|
+
"@leafygreen-ui/button": "^21.0.12",
|
|
47
|
+
"@leafygreen-ui/testing-lib": "^0.4.0"
|
|
47
48
|
},
|
|
48
49
|
"homepage": "https://github.com/mongodb/leafygreen-ui/tree/main/packages/combobox",
|
|
49
50
|
"repository": {
|
|
@@ -16,6 +16,7 @@ import isUndefined from 'lodash/isUndefined';
|
|
|
16
16
|
|
|
17
17
|
import Button from '@leafygreen-ui/button';
|
|
18
18
|
import { keyMap } from '@leafygreen-ui/lib';
|
|
19
|
+
import { eventContainingTargetValue } from '@leafygreen-ui/testing-lib';
|
|
19
20
|
|
|
20
21
|
import { OptionObject } from '../ComboboxOption/ComboboxOption.types';
|
|
21
22
|
import {
|
|
@@ -134,6 +135,13 @@ describe('packages/combobox', () => {
|
|
|
134
135
|
});
|
|
135
136
|
expect(clearButtonEl).not.toBeInTheDocument();
|
|
136
137
|
});
|
|
138
|
+
|
|
139
|
+
test('`inputValue` prop is rendered in the textbox', () => {
|
|
140
|
+
const { inputEl } = renderCombobox(select, {
|
|
141
|
+
inputValue: 'abc',
|
|
142
|
+
});
|
|
143
|
+
expect(inputEl).toHaveValue('abc');
|
|
144
|
+
});
|
|
137
145
|
});
|
|
138
146
|
|
|
139
147
|
/**
|
|
@@ -420,7 +428,7 @@ describe('packages/combobox', () => {
|
|
|
420
428
|
/**
|
|
421
429
|
* Input element
|
|
422
430
|
*/
|
|
423
|
-
describe('Input interaction', () => {
|
|
431
|
+
describe('Typing (Input interaction)', () => {
|
|
424
432
|
test('Typing any character updates the input', () => {
|
|
425
433
|
const { inputEl } = renderCombobox(select);
|
|
426
434
|
userEvent.type(inputEl, 'zy');
|
|
@@ -434,70 +442,103 @@ describe('packages/combobox', () => {
|
|
|
434
442
|
expect(inputEl).toHaveValue(displayName);
|
|
435
443
|
expect(inputEl.scrollWidth).toBeGreaterThanOrEqual(inputEl.clientWidth);
|
|
436
444
|
});
|
|
437
|
-
});
|
|
438
445
|
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
test('Typing any character updates the input', () => {
|
|
445
|
-
const value = select === 'multiple' ? [] : '';
|
|
446
|
-
const { inputEl } = renderCombobox(select, {
|
|
447
|
-
value,
|
|
448
|
-
});
|
|
449
|
-
expect(inputEl).toHaveValue('');
|
|
450
|
-
userEvent.type(inputEl, 'z');
|
|
451
|
-
expect(inputEl).toHaveValue('z');
|
|
446
|
+
test('Typing does not fire onChange callback', () => {
|
|
447
|
+
const onChange = jest.fn();
|
|
448
|
+
const { inputEl } = renderCombobox(select, { onChange });
|
|
449
|
+
userEvent.type(inputEl, 'Apple');
|
|
450
|
+
expect(onChange).not.toHaveBeenCalled();
|
|
452
451
|
});
|
|
453
452
|
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
const { inputEl
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
rerenderCombobox({ value });
|
|
462
|
-
expect(inputEl).toHaveValue('Banana');
|
|
453
|
+
test('Typing fires onInputChange callback', () => {
|
|
454
|
+
const onInputChange = jest.fn();
|
|
455
|
+
const { inputEl } = renderCombobox(select, { onInputChange });
|
|
456
|
+
userEvent.type(inputEl, 'abc');
|
|
457
|
+
expect(onInputChange).toHaveBeenCalledWith(
|
|
458
|
+
eventContainingTargetValue('abc'),
|
|
459
|
+
);
|
|
463
460
|
});
|
|
464
461
|
|
|
465
|
-
|
|
466
|
-
const
|
|
467
|
-
const { inputEl } = renderCombobox(select, {
|
|
468
|
-
|
|
462
|
+
test('Blurring the input after typing a valid value fires onChange', async () => {
|
|
463
|
+
const onChange = jest.fn();
|
|
464
|
+
const { inputEl, openMenu } = renderCombobox(select, { onChange });
|
|
465
|
+
const { menuContainerEl } = openMenu();
|
|
466
|
+
userEvent.type(inputEl, 'Apple');
|
|
467
|
+
userEvent.tab();
|
|
468
|
+
await waitForElementToBeRemoved(menuContainerEl);
|
|
469
|
+
if (select === 'multiple') {
|
|
470
|
+
expect(onChange).toHaveBeenCalledWith(['apple'], expect.anything());
|
|
471
|
+
} else {
|
|
472
|
+
expect(onChange).toHaveBeenCalledWith('apple');
|
|
473
|
+
}
|
|
469
474
|
});
|
|
470
475
|
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
476
|
+
/**
|
|
477
|
+
* Controlled
|
|
478
|
+
* (i.e. `value` prop is set)
|
|
479
|
+
*/
|
|
480
|
+
describe('When value is controlled', () => {
|
|
481
|
+
test('Typing any character updates the input', () => {
|
|
482
|
+
const value = select === 'multiple' ? [] : '';
|
|
483
|
+
const { inputEl } = renderCombobox(select, {
|
|
475
484
|
value,
|
|
476
485
|
});
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
486
|
+
expect(inputEl).toHaveValue('');
|
|
487
|
+
userEvent.type(inputEl, 'z');
|
|
488
|
+
expect(inputEl).toHaveValue('z');
|
|
489
|
+
});
|
|
490
|
+
|
|
491
|
+
testSingleSelect('Text input renders with value update', () => {
|
|
492
|
+
let value = 'apple';
|
|
493
|
+
const { inputEl, rerenderCombobox } = renderCombobox(select, {
|
|
494
|
+
value,
|
|
495
|
+
});
|
|
496
|
+
expect(inputEl).toHaveValue('Apple');
|
|
497
|
+
value = 'banana';
|
|
482
498
|
rerenderCombobox({ value });
|
|
499
|
+
expect(inputEl).toHaveValue('Banana');
|
|
500
|
+
});
|
|
501
|
+
|
|
502
|
+
testSingleSelect(
|
|
503
|
+
'Invalid option passed as value is not selected',
|
|
504
|
+
() => {
|
|
505
|
+
const value = 'jellybean';
|
|
506
|
+
const { inputEl } = renderCombobox(select, { value });
|
|
507
|
+
expect(inputEl).toHaveValue('');
|
|
508
|
+
},
|
|
509
|
+
);
|
|
510
|
+
|
|
511
|
+
testMultiSelect('Updating `value` updates the chips', () => {
|
|
512
|
+
let value = ['apple', 'banana'];
|
|
513
|
+
const { queryChipsByName, queryAllChips, rerenderCombobox } =
|
|
514
|
+
renderCombobox(select, {
|
|
515
|
+
value,
|
|
516
|
+
});
|
|
483
517
|
waitFor(() => {
|
|
484
|
-
const allChips = queryChipsByName(['
|
|
518
|
+
const allChips = queryChipsByName(['Apple', 'Banana']);
|
|
485
519
|
allChips?.forEach(chip => expect(chip).toBeInTheDocument());
|
|
486
520
|
expect(queryAllChips()).toHaveLength(2);
|
|
521
|
+
value = ['banana', 'carrot'];
|
|
522
|
+
rerenderCombobox({ value });
|
|
523
|
+
waitFor(() => {
|
|
524
|
+
const allChips = queryChipsByName(['Carrot', 'Banana']);
|
|
525
|
+
allChips?.forEach(chip => expect(chip).toBeInTheDocument());
|
|
526
|
+
expect(queryAllChips()).toHaveLength(2);
|
|
527
|
+
});
|
|
487
528
|
});
|
|
488
529
|
});
|
|
489
|
-
});
|
|
490
530
|
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
531
|
+
testMultiSelect('Invalid options are not selected', () => {
|
|
532
|
+
const value = ['apple', 'jellybean'];
|
|
533
|
+
const { queryChipsByName, queryAllChips } = renderCombobox(select, {
|
|
534
|
+
value,
|
|
535
|
+
});
|
|
536
|
+
waitFor(() => {
|
|
537
|
+
const allChips = queryChipsByName(['Apple']);
|
|
538
|
+
allChips?.forEach(chip => expect(chip).toBeInTheDocument());
|
|
539
|
+
expect(queryChipsByName('Jellybean')).not.toBeInTheDocument();
|
|
540
|
+
expect(queryAllChips()).toHaveLength(1);
|
|
541
|
+
});
|
|
501
542
|
});
|
|
502
543
|
});
|
|
503
544
|
});
|
|
@@ -1538,13 +1579,6 @@ describe('packages/combobox', () => {
|
|
|
1538
1579
|
expect(onChange).toHaveBeenCalled();
|
|
1539
1580
|
});
|
|
1540
1581
|
|
|
1541
|
-
test('Typing does not call onChange callback', () => {
|
|
1542
|
-
const onChange = jest.fn();
|
|
1543
|
-
const { inputEl } = renderCombobox(select, { onChange });
|
|
1544
|
-
userEvent.type(inputEl, 'a');
|
|
1545
|
-
expect(onChange).not.toHaveBeenCalled();
|
|
1546
|
-
});
|
|
1547
|
-
|
|
1548
1582
|
test('Closing the menu without making a selection does not call onChange callback', async () => {
|
|
1549
1583
|
const onChange = jest.fn();
|
|
1550
1584
|
const { containerEl, openMenu } = renderCombobox(select, { onChange });
|
|
@@ -62,6 +62,7 @@ import {
|
|
|
62
62
|
getOptionObjectFromValue,
|
|
63
63
|
getValueForDisplayName,
|
|
64
64
|
} from '../utils';
|
|
65
|
+
import { doesSelectionExist } from '../utils/doesSelectionExist';
|
|
65
66
|
|
|
66
67
|
import { isValueCurrentSelection } from './utils/isValueCurrentSelection';
|
|
67
68
|
import {
|
|
@@ -121,6 +122,8 @@ export function Combobox<M extends boolean>({
|
|
|
121
122
|
overflow = Overflow.expandY,
|
|
122
123
|
multiselect = false as M,
|
|
123
124
|
initialValue,
|
|
125
|
+
inputValue: inputValueProp,
|
|
126
|
+
onInputChange,
|
|
124
127
|
onChange,
|
|
125
128
|
value,
|
|
126
129
|
chipTruncationLocation,
|
|
@@ -154,16 +157,23 @@ export function Combobox<M extends boolean>({
|
|
|
154
157
|
);
|
|
155
158
|
const [selection, setSelection] = useState<SelectValueType<M> | null>(null);
|
|
156
159
|
const prevSelection = usePrevious(selection);
|
|
157
|
-
const [inputValue, setInputValue] = useState<string>('');
|
|
160
|
+
const [inputValue, setInputValue] = useState<string>(inputValueProp ?? '');
|
|
161
|
+
|
|
162
|
+
useEffect(() => {
|
|
163
|
+
if (!isUndefined(inputValueProp)) {
|
|
164
|
+
setInputValue(inputValueProp);
|
|
165
|
+
}
|
|
166
|
+
}, [inputValueProp]);
|
|
167
|
+
|
|
168
|
+
const updateInputValue = (newInputVal: string) => {
|
|
169
|
+
setInputValue(newInputVal);
|
|
170
|
+
};
|
|
171
|
+
|
|
158
172
|
const prevValue = usePrevious(inputValue);
|
|
159
173
|
const [focusedChip, setFocusedChip] = useState<string | null>(null);
|
|
160
174
|
const [shouldShowOverflowShadow, setShouldShowOverflowShadow] =
|
|
161
175
|
useState<boolean>(false);
|
|
162
176
|
|
|
163
|
-
const doesSelectionExist =
|
|
164
|
-
!isNull(selection) &&
|
|
165
|
-
((isArray(selection) && selection.length > 0) || isString(selection));
|
|
166
|
-
|
|
167
177
|
const placeholderValue =
|
|
168
178
|
multiselect && isArray(selection) && selection.length > 0
|
|
169
179
|
? undefined
|
|
@@ -243,7 +253,7 @@ export function Combobox<M extends boolean>({
|
|
|
243
253
|
newSelection.push(value);
|
|
244
254
|
diff.diffType = 'insert';
|
|
245
255
|
// clear text
|
|
246
|
-
|
|
256
|
+
updateInputValue('');
|
|
247
257
|
}
|
|
248
258
|
}
|
|
249
259
|
setSelection(newSelection as SelectValueType<M>);
|
|
@@ -757,31 +767,30 @@ export function Combobox<M extends boolean>({
|
|
|
757
767
|
);
|
|
758
768
|
|
|
759
769
|
/**
|
|
760
|
-
|
|
770
|
+
*`
|
|
761
771
|
* Selection Management
|
|
762
772
|
*
|
|
763
773
|
*/
|
|
764
774
|
|
|
765
775
|
const onCloseMenu = useCallback(() => {
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
} else {
|
|
776
|
+
const exactMatchedOption = visibleOptions.find(
|
|
777
|
+
option =>
|
|
778
|
+
option.displayName === inputValue || option.value === inputValue,
|
|
779
|
+
);
|
|
780
|
+
|
|
781
|
+
// check if inputValue is matches a valid option
|
|
782
|
+
// Set the selection to that value if the component is not controlled
|
|
783
|
+
if (!value && exactMatchedOption) {
|
|
784
|
+
updateSelection(exactMatchedOption.value);
|
|
785
|
+
} else {
|
|
786
|
+
if (!isMultiselect(selection)) {
|
|
778
787
|
// Revert the value to the previous selection
|
|
779
788
|
const displayName =
|
|
780
789
|
getDisplayNameForValue(
|
|
781
790
|
selection as SelectValueType<false>,
|
|
782
791
|
allOptions,
|
|
783
|
-
) ??
|
|
784
|
-
|
|
792
|
+
) ?? prevSelection;
|
|
793
|
+
updateInputValue(displayName);
|
|
785
794
|
}
|
|
786
795
|
}
|
|
787
796
|
}, [
|
|
@@ -790,12 +799,16 @@ export function Combobox<M extends boolean>({
|
|
|
790
799
|
isMultiselect,
|
|
791
800
|
prevSelection,
|
|
792
801
|
selection,
|
|
802
|
+
updateSelection,
|
|
793
803
|
value,
|
|
794
804
|
visibleOptions,
|
|
795
805
|
]);
|
|
796
806
|
|
|
807
|
+
/**
|
|
808
|
+
* Side effects to run when the selection changes
|
|
809
|
+
*/
|
|
797
810
|
const onSelect = useCallback(() => {
|
|
798
|
-
if (doesSelectionExist) {
|
|
811
|
+
if (doesSelectionExist(selection)) {
|
|
799
812
|
if (isMultiselect(selection)) {
|
|
800
813
|
scrollInputToEnd(overflow);
|
|
801
814
|
} else if (!isMultiselect(selection)) {
|
|
@@ -805,13 +818,13 @@ export function Combobox<M extends boolean>({
|
|
|
805
818
|
selection as SelectValueType<false>,
|
|
806
819
|
allOptions,
|
|
807
820
|
) ?? '';
|
|
808
|
-
|
|
821
|
+
updateInputValue(displayName);
|
|
809
822
|
closeMenu();
|
|
810
823
|
}
|
|
811
824
|
} else {
|
|
812
|
-
|
|
825
|
+
updateInputValue('');
|
|
813
826
|
}
|
|
814
|
-
}, [
|
|
827
|
+
}, [allOptions, isMultiselect, selection, overflow]);
|
|
815
828
|
|
|
816
829
|
// Set the initialValue
|
|
817
830
|
useEffect(() => {
|
|
@@ -853,7 +866,14 @@ export function Combobox<M extends boolean>({
|
|
|
853
866
|
// onSelect
|
|
854
867
|
// Side effects to run when the selection changes
|
|
855
868
|
useEffect(() => {
|
|
856
|
-
|
|
869
|
+
const hasSelectionChanged =
|
|
870
|
+
!isUndefined(prevSelection) &&
|
|
871
|
+
((isArray(selection) && !isNull(prevSelection)) ||
|
|
872
|
+
isString(selection) ||
|
|
873
|
+
isNull(selection)) &&
|
|
874
|
+
!isEqual(selection, prevSelection);
|
|
875
|
+
|
|
876
|
+
if (hasSelectionChanged) {
|
|
857
877
|
onSelect();
|
|
858
878
|
}
|
|
859
879
|
}, [onSelect, prevSelection, selection]);
|
|
@@ -926,12 +946,13 @@ export function Combobox<M extends boolean>({
|
|
|
926
946
|
};
|
|
927
947
|
|
|
928
948
|
// Fired onChange
|
|
929
|
-
const handleInputChange: ChangeEventHandler<HTMLInputElement> = (
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
949
|
+
const handleInputChange: ChangeEventHandler<HTMLInputElement> = (
|
|
950
|
+
e: React.ChangeEvent<HTMLInputElement>,
|
|
951
|
+
) => {
|
|
952
|
+
updateInputValue(e.target.value);
|
|
933
953
|
// fire any filter function passed in
|
|
934
|
-
onFilter?.(value);
|
|
954
|
+
onFilter?.(e.target.value);
|
|
955
|
+
onInputChange?.(e);
|
|
935
956
|
};
|
|
936
957
|
|
|
937
958
|
const handleClearButtonFocus: FocusEventHandler<HTMLButtonElement> = () => {
|
|
@@ -969,7 +990,7 @@ export function Combobox<M extends boolean>({
|
|
|
969
990
|
case keyMap.Tab: {
|
|
970
991
|
switch (focusedElementName) {
|
|
971
992
|
case 'Input': {
|
|
972
|
-
if (!doesSelectionExist) {
|
|
993
|
+
if (!doesSelectionExist(selection)) {
|
|
973
994
|
closeMenu();
|
|
974
995
|
updateHighlightedOption('first');
|
|
975
996
|
updateFocusedChip(null);
|
|
@@ -1268,7 +1289,7 @@ export function Combobox<M extends boolean>({
|
|
|
1268
1289
|
className={endIconStyle}
|
|
1269
1290
|
/>
|
|
1270
1291
|
)}
|
|
1271
|
-
{clearable && doesSelectionExist && !disabled && (
|
|
1292
|
+
{clearable && doesSelectionExist(selection) && !disabled && (
|
|
1272
1293
|
<IconButton
|
|
1273
1294
|
aria-label="Clear selection"
|
|
1274
1295
|
aria-disabled={disabled}
|
|
@@ -155,6 +155,16 @@ export type BaseComboboxProps = Omit<HTMLElementProps<'div'>, 'onChange'> &
|
|
|
155
155
|
* Do not remove options from the JSX children, as this will affect the selected options
|
|
156
156
|
*/
|
|
157
157
|
filteredOptions?: Array<string>;
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* A callback fired when the input text changes
|
|
161
|
+
*/
|
|
162
|
+
onInputChange?: React.ChangeEventHandler<HTMLInputElement>;
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Allows for a controlled text-input value
|
|
166
|
+
*/
|
|
167
|
+
inputValue?: string;
|
|
158
168
|
};
|
|
159
169
|
|
|
160
170
|
export type ComboboxProps<M extends boolean> = Either<
|
package/src/Combobox.story.tsx
CHANGED
|
@@ -99,6 +99,7 @@ const meta: StoryMetaType<typeof Combobox> = {
|
|
|
99
99
|
label: { control: 'text' },
|
|
100
100
|
description: { control: 'text' },
|
|
101
101
|
placeholder: { control: 'text' },
|
|
102
|
+
inputValue: { control: 'text' },
|
|
102
103
|
size: {
|
|
103
104
|
options: Object.values(ComboboxSize),
|
|
104
105
|
control: 'select',
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import isArray from 'lodash/isArray';
|
|
2
|
+
import isNull from 'lodash/isNull';
|
|
3
|
+
import isString from 'lodash/isString';
|
|
4
|
+
import isUndefined from 'lodash/isUndefined';
|
|
5
|
+
|
|
6
|
+
import { SelectValueType } from '../types';
|
|
7
|
+
|
|
8
|
+
export const doesSelectionExist = <M extends boolean>(
|
|
9
|
+
selection?: SelectValueType<M> | null,
|
|
10
|
+
): boolean => {
|
|
11
|
+
return (
|
|
12
|
+
!isUndefined(selection) &&
|
|
13
|
+
!isNull(selection) &&
|
|
14
|
+
(isString(selection) || (isArray(selection) && selection.length > 0))
|
|
15
|
+
);
|
|
16
|
+
};
|