@xqmsg/ui-core 0.24.2 → 0.24.4

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.
Files changed (47) hide show
  1. package/README.md +8 -13
  2. package/dist/components/input/StackedMultiSelect/index.d.ts +1 -0
  3. package/dist/components/input/StackedSelect/index.d.ts +1 -0
  4. package/dist/components/input/components/dropdown/index.d.ts +2 -0
  5. package/dist/components/input/index.d.ts +2 -1
  6. package/dist/ui-core.cjs.development.js +197 -113
  7. package/dist/ui-core.cjs.development.js.map +1 -1
  8. package/dist/ui-core.cjs.production.min.js +1 -1
  9. package/dist/ui-core.cjs.production.min.js.map +1 -1
  10. package/dist/ui-core.esm.js +198 -114
  11. package/dist/ui-core.esm.js.map +1 -1
  12. package/package.json +6 -2
  13. package/src/components/icons/checkmark/index.tsx +1 -1
  14. package/src/components/icons/chevron/down/index.tsx +7 -1
  15. package/src/components/icons/chevron/right/index.tsx +1 -1
  16. package/src/components/icons/clock/index.tsx +1 -1
  17. package/src/components/icons/dropdown/index.tsx +5 -1
  18. package/src/components/icons/error/index.tsx +1 -1
  19. package/src/components/icons/file/fill/index.tsx +1 -1
  20. package/src/components/icons/file/outline/index.tsx +1 -1
  21. package/src/components/icons/folder/add/fill/index.tsx +1 -1
  22. package/src/components/icons/folder/add/outline/index.tsx +1 -1
  23. package/src/components/icons/folder/outline/index.tsx +1 -1
  24. package/src/components/icons/group/index.tsx +1 -1
  25. package/src/components/icons/home/index.tsx +1 -1
  26. package/src/components/icons/image/index.tsx +1 -1
  27. package/src/components/icons/link/index.tsx +1 -1
  28. package/src/components/icons/menu/index.tsx +1 -1
  29. package/src/components/icons/microsoft/index.tsx +1 -1
  30. package/src/components/icons/neutral/index.tsx +3 -1
  31. package/src/components/icons/page/index.tsx +1 -1
  32. package/src/components/icons/positive/index.tsx +1 -1
  33. package/src/components/icons/question/index.tsx +1 -1
  34. package/src/components/icons/search/index.tsx +1 -1
  35. package/src/components/icons/services/index.tsx +1 -1
  36. package/src/components/icons/settings/index.tsx +3 -1
  37. package/src/components/icons/table/fill/index.tsx +1 -1
  38. package/src/components/icons/table/outline/index.tsx +1 -1
  39. package/src/components/icons/task/index.tsx +1 -1
  40. package/src/components/icons/trash/index.tsx +1 -1
  41. package/src/components/icons/video/index.tsx +1 -1
  42. package/src/components/icons/warning/index.tsx +1 -1
  43. package/src/components/input/Input.stories.tsx +9 -0
  44. package/src/components/input/StackedMultiSelect/index.tsx +296 -277
  45. package/src/components/input/StackedSelect/index.tsx +46 -33
  46. package/src/components/input/components/dropdown/index.tsx +61 -12
  47. package/src/components/input/index.tsx +4 -0
@@ -1,12 +1,10 @@
1
1
  import React, {
2
2
  KeyboardEventHandler,
3
3
  useEffect,
4
- useMemo,
5
4
  useRef,
6
5
  useState,
7
6
  } from 'react';
8
7
  import { Box, Flex, Text, Input } from '@chakra-ui/react';
9
- import { debounce } from 'lodash';
10
8
  import {
11
9
  FieldOption,
12
10
  FieldOptions,
@@ -32,6 +30,7 @@ export interface StackedMultiSelectProps extends ReactSelectFieldProps {
32
30
  setError: UseFormSetError<FieldValues>;
33
31
  clearErrors: UseFormClearErrors<FieldValues>;
34
32
  control: Control<FieldValues, any>;
33
+ loadingOptions?: boolean;
35
34
  }
36
35
 
37
36
  /**
@@ -40,310 +39,330 @@ export interface StackedMultiSelectProps extends ReactSelectFieldProps {
40
39
  const StackedMultiSelect = React.forwardRef<
41
40
  HTMLInputElement,
42
41
  StackedMultiSelectProps
43
- >(({ options, setValue, control, name, placeholder, disabled }, _ref) => {
44
- const watchedValue = useWatch({ control, name: name as string });
45
- const dropdownRef = useRef<HTMLDivElement>(null);
46
- const dropdownMenuRef = useRef<HTMLDivElement>(null);
47
- const scrollRef = useRef<HTMLDivElement>(null);
48
- const inputRef = useRef<HTMLInputElement>(null);
49
-
50
- const [isInit, setIsInit] = useState(false);
51
- const [localValues, setLocalValues] = useState<FieldOptions>([]);
52
- const [localOptions, setLocalOptions] = useState<FieldOptions>(options);
53
- const [isFocussed, setIsFocussed] = useState(false);
54
- const [shouldSideScroll, setShouldSideScroll] = useState(false);
55
- const [optionIndex, setOptionIndex] = useState<number | null>(null);
56
-
57
- const [position, setPosition] = useState<'top' | 'bottom'>('top');
58
- const [searchValue, setSearchValue] = useState('');
59
- const [debouncedSearchValue, setDebouncedSearchValue] = useState('');
60
-
61
- const boundingClientRect = dropdownRef.current?.getBoundingClientRect() as DOMRect;
62
-
63
- useEffect(() => {
64
- if (window.innerHeight - (boundingClientRect?.y + 240) >= 0) {
65
- setPosition('top');
66
- } else {
67
- setPosition('bottom');
68
- }
69
- }, [boundingClientRect]);
70
-
71
- useOnClickOutside(dropdownRef, () => setIsFocussed(false));
72
-
73
- // gets latest watched form value (common delimited) from RHF state and creates a list
74
- useEffect(() => {
75
- if (watchedValue !== undefined && !watchedValue.length && !isInit) {
76
- setLocalValues([]);
77
- setIsInit(true);
78
- }
79
-
80
- if (watchedValue !== undefined && watchedValue?.length && !isInit) {
81
- if (shouldSideScroll) {
82
- (scrollRef.current as HTMLDivElement).scrollTo({
83
- left: scrollRef.current?.scrollWidth,
84
- behavior: 'smooth',
85
- });
86
- setShouldSideScroll(false);
42
+ >(
43
+ (
44
+ { options, setValue, control, name, placeholder, disabled, loadingOptions },
45
+ _ref
46
+ ) => {
47
+ const watchedValue = useWatch({ control, name: name as string });
48
+ const dropdownRef = useRef<HTMLDivElement>(null);
49
+ const dropdownMenuRef = useRef<HTMLDivElement>(null);
50
+ const scrollRef = useRef<HTMLDivElement>(null);
51
+ const inputRef = useRef<HTMLInputElement>(null);
52
+
53
+ const [isInit, setIsInit] = useState(false);
54
+ const [localValues, setLocalValues] = useState<FieldOptions>([]);
55
+ const [localOptions, setLocalOptions] = useState<FieldOptions>(options);
56
+ const [filteredOptions, setFilteredOptions] = useState<FieldOptions>(
57
+ localOptions
58
+ );
59
+ const [isFocussed, setIsFocussed] = useState(false);
60
+ const [shouldSideScroll, setShouldSideScroll] = useState(false);
61
+ const [optionIndex, setOptionIndex] = useState<number | null>(null);
62
+
63
+ const [position, setPosition] = useState<'top' | 'bottom'>('top');
64
+ const [searchValue, setSearchValue] = useState('');
65
+ // const [debouncedSearchValue, setDebouncedSearchValue] = useState('');
66
+
67
+ const boundingClientRect = dropdownRef.current?.getBoundingClientRect() as DOMRect;
68
+
69
+ useEffect(() => {
70
+ if (window.innerHeight - (boundingClientRect?.y + 240) >= 0) {
71
+ setPosition('top');
72
+ } else {
73
+ setPosition('bottom');
87
74
  }
75
+ }, [boundingClientRect]);
88
76
 
89
- if (isInit) return;
77
+ useOnClickOutside(dropdownRef, () => setIsFocussed(false));
90
78
 
91
- setLocalValues(
92
- watchedValue
93
- .split(',')
94
- .filter(Boolean)
95
- .map((value: string) =>
96
- options.find(option => option.value === value)
79
+ // gets latest watched form value (common delimited) from RHF state and creates a list
80
+ useEffect(() => {
81
+ if (watchedValue !== undefined && !watchedValue.length && !isInit) {
82
+ setLocalValues([]);
83
+ setIsInit(true);
84
+ }
85
+
86
+ if (watchedValue !== undefined && watchedValue?.length && !isInit) {
87
+ if (shouldSideScroll) {
88
+ (scrollRef.current as HTMLDivElement).scrollTo({
89
+ left: scrollRef.current?.scrollWidth,
90
+ behavior: 'smooth',
91
+ });
92
+ setShouldSideScroll(false);
93
+ }
94
+
95
+ if (isInit) return;
96
+
97
+ setLocalValues(
98
+ watchedValue
99
+ .split(',')
100
+ .filter(Boolean)
101
+ .map((value: string) =>
102
+ options.find(option => option.value === value)
103
+ )
104
+ );
105
+ // Filter out options that are already selected
106
+ setLocalOptions(prevLocalOptions =>
107
+ prevLocalOptions.filter(
108
+ localOption =>
109
+ !watchedValue
110
+ .split(',')
111
+ .filter(Boolean)
112
+ .map((value: string) =>
113
+ options.find(option => option.value === value)
114
+ )
115
+ .includes(localOption)
97
116
  )
98
- );
99
- // Filter out options that are already selected
117
+ );
118
+
119
+ setIsInit(true);
120
+ }
121
+ }, [
122
+ isInit,
123
+ localOptions,
124
+ localValues,
125
+ options,
126
+ shouldSideScroll,
127
+ watchedValue,
128
+ ]);
129
+
130
+ const handleChange = (option: FieldOption) => {
131
+ setShouldSideScroll(true);
132
+ const newValue = [...localValues, option]
133
+ .map(({ value }) => value)
134
+ .join(',');
135
+
136
+ setValue(name as string, newValue, {
137
+ shouldValidate: true,
138
+ shouldDirty: true,
139
+ });
140
+
100
141
  setLocalOptions(prevLocalOptions =>
101
- prevLocalOptions.filter(
102
- localOption =>
103
- !watchedValue
104
- .split(',')
105
- .filter(Boolean)
106
- .map((value: string) =>
107
- options.find(option => option.value === value)
108
- )
109
- .includes(localOption)
110
- )
142
+ prevLocalOptions.filter(prevLocalOption => prevLocalOption !== option)
111
143
  );
112
144
 
113
- setIsInit(true);
114
- }
115
- }, [
116
- isInit,
117
- localOptions,
118
- localValues,
119
- options,
120
- shouldSideScroll,
121
- watchedValue,
122
- ]);
123
-
124
- const handleChange = (option: FieldOption) => {
125
- setShouldSideScroll(true);
126
- const newValue = [...localValues, option]
127
- .map(({ value }) => value)
128
- .join(',');
129
-
130
- setValue(name as string, newValue, {
131
- shouldValidate: true,
132
- shouldDirty: true,
133
- });
134
-
135
- setLocalOptions(prevLocalOptions =>
136
- prevLocalOptions.filter(prevLocalOption => prevLocalOption !== option)
137
- );
138
-
139
- setLocalValues(prevLocalValues => [...prevLocalValues, option]);
140
- };
145
+ setLocalValues(prevLocalValues => [...prevLocalValues, option]);
141
146
 
142
- const handleDelete = (option: FieldOption) => {
143
- const newValue = localValues
144
- .filter(localValue => localValue !== option)
145
- .map(({ value }) => value)
146
- .join(',');
147
+ // reset search on value select
148
+ setSearchValue('');
149
+ };
147
150
 
148
- setValue(name as string, newValue, {
149
- shouldValidate: true,
150
- shouldDirty: true,
151
- });
151
+ const handleDelete = (option: FieldOption) => {
152
+ const newValue = localValues
153
+ .filter(localValue => localValue !== option)
154
+ .map(({ value }) => value)
155
+ .join(',');
152
156
 
153
- setLocalOptions(prevLocalOptions =>
154
- [...prevLocalOptions, option].sort((a, b) => a.sortValue - b.sortValue)
155
- );
157
+ setValue(name as string, newValue, {
158
+ shouldValidate: true,
159
+ shouldDirty: true,
160
+ });
156
161
 
157
- setLocalValues(prevLocalValues =>
158
- prevLocalValues.filter(prevLocalValue => prevLocalValue !== option)
159
- );
160
- };
162
+ setLocalOptions(prevLocalOptions =>
163
+ [...prevLocalOptions, option].sort((a, b) => a.sortValue - b.sortValue)
164
+ );
161
165
 
162
- const handleOnKeyDown: KeyboardEventHandler<HTMLInputElement> = e => {
163
- const initialOptionIndex = options[0].value === 'section_header' ? 1 : 0;
166
+ setLocalValues(prevLocalValues =>
167
+ prevLocalValues.filter(prevLocalValue => prevLocalValue !== option)
168
+ );
169
+ };
164
170
 
165
- if (
166
- !isFocussed &&
167
- (e.key === 'Enter' || e.key === 'ArrowUp' || e.key === 'ArrowDown')
168
- ) {
169
- setIsFocussed(true);
170
- return setOptionIndex(initialOptionIndex);
171
- }
171
+ const handleOnKeyDown: KeyboardEventHandler<HTMLInputElement> = e => {
172
+ const initialOptionIndex = options[0].value === 'section_header' ? 1 : 0;
172
173
 
173
- if (isFocussed) {
174
174
  if (
175
- optionIndex === null &&
175
+ !isFocussed &&
176
176
  (e.key === 'Enter' || e.key === 'ArrowUp' || e.key === 'ArrowDown')
177
177
  ) {
178
+ setIsFocussed(true);
178
179
  return setOptionIndex(initialOptionIndex);
179
180
  }
180
181
 
181
- if (e.key === 'ArrowUp' && optionIndex !== null && optionIndex > 0) {
182
- const incrementValue =
183
- localOptions[optionIndex - 1] &&
184
- localOptions[optionIndex - 1].value === 'section_header'
185
- ? 2
186
- : 1;
187
- setOptionIndex(optionIndex - incrementValue);
188
-
189
- return dropdownMenuRef.current?.scrollTo({
190
- top: optionIndex * 24,
191
- behavior: 'smooth',
192
- });
182
+ if (isFocussed) {
183
+ if (
184
+ optionIndex === null &&
185
+ (e.key === 'Enter' || e.key === 'ArrowUp' || e.key === 'ArrowDown')
186
+ ) {
187
+ return setOptionIndex(initialOptionIndex);
188
+ }
189
+
190
+ if (e.key === 'ArrowUp' && optionIndex !== null && optionIndex > 0) {
191
+ const incrementValue =
192
+ filteredOptions[optionIndex - 1] &&
193
+ filteredOptions[optionIndex - 1].value === 'section_header'
194
+ ? 2
195
+ : 1;
196
+ setOptionIndex(optionIndex - incrementValue);
197
+
198
+ return dropdownMenuRef.current?.scrollTo({
199
+ top: optionIndex * 24,
200
+ behavior: 'smooth',
201
+ });
202
+ }
203
+
204
+ if (
205
+ e.key === 'ArrowDown' &&
206
+ optionIndex !== null &&
207
+ optionIndex < filteredOptions.length
208
+ ) {
209
+ const incrementValue =
210
+ filteredOptions[optionIndex + 1] &&
211
+ filteredOptions[optionIndex + 1].value === 'section_header'
212
+ ? 2
213
+ : 1;
214
+ setOptionIndex(optionIndex + incrementValue);
215
+
216
+ return dropdownMenuRef.current?.scrollTo({
217
+ top: optionIndex * 24,
218
+ behavior: 'smooth',
219
+ });
220
+ }
221
+
222
+ if (e.key === 'Enter' && optionIndex !== null) {
223
+ const option = filteredOptions.find((_, idx) => optionIndex === idx);
224
+ if (!option) return;
225
+
226
+ handleChange(option);
227
+
228
+ return setIsFocussed(false);
229
+ }
230
+
231
+ if (e.key === 'Tab') {
232
+ return setIsFocussed(false);
233
+ }
193
234
  }
194
-
195
- if (
196
- e.key === 'ArrowDown' &&
197
- optionIndex !== null &&
198
- optionIndex < localOptions.length
199
- ) {
200
- const incrementValue =
201
- localOptions[optionIndex + 1] &&
202
- localOptions[optionIndex + 1].value === 'section_header'
203
- ? 2
204
- : 1;
205
- setOptionIndex(optionIndex + incrementValue);
206
-
207
- return dropdownMenuRef.current?.scrollTo({
208
- top: optionIndex * 24,
235
+ };
236
+
237
+ useEffect(() => {
238
+ if (searchValue.length) {
239
+ const idx = options.findIndex(
240
+ option =>
241
+ option.label.substring(0, searchValue.length).toLowerCase() ===
242
+ searchValue.toLowerCase()
243
+ );
244
+
245
+ dropdownMenuRef.current?.scrollTo({
246
+ top: idx * 27,
209
247
  behavior: 'smooth',
210
248
  });
211
249
  }
212
-
213
- if (e.key === 'Enter' && optionIndex !== null) {
214
- const option = localOptions.find((_, idx) => optionIndex === idx);
215
- if (!option) return;
216
-
217
- handleChange(option);
218
-
219
- return setIsFocussed(false);
220
- }
221
-
222
- if (e.key === 'Tab') {
223
- return setIsFocussed(false);
224
- }
225
-
226
- return update(debouncedSearchValue.concat(e.key));
227
- }
228
- };
229
-
230
- useEffect(() => {
231
- if (searchValue.length) {
232
- const idx = options.findIndex(
233
- option =>
234
- option.label.substring(0, searchValue.length).toLowerCase() ===
235
- searchValue.toLowerCase()
250
+ }, [options, searchValue]);
251
+
252
+ useEffect(() => {
253
+ setFilteredOptions(
254
+ localOptions.filter(element => {
255
+ return element.label
256
+ .toLowerCase()
257
+ .includes(searchValue.toLowerCase());
258
+ })
236
259
  );
237
-
238
- dropdownMenuRef.current?.scrollTo({
239
- top: idx * 24,
240
- behavior: 'smooth',
241
- });
242
-
243
- setSearchValue('');
244
- setDebouncedSearchValue('');
245
- }
246
- }, [options, searchValue]);
247
-
248
- const updateSearchValue = useMemo(() => {
249
- return debounce(val => {
250
- setSearchValue(val);
251
- }, 1000);
252
- }, []);
253
-
254
- const update = (value: string) => {
255
- updateSearchValue(value);
256
- setDebouncedSearchValue(value);
257
- };
258
-
259
- return (
260
- <Box ref={dropdownRef} position="relative" onKeyDown={handleOnKeyDown}>
261
- <Flex
262
- fontSize="13px"
263
- h="26px"
264
- border={isFocussed ? '2px solid' : '.5px solid'}
265
- borderColor={isFocussed ? colors.border.focus : colors.border.default}
266
- py="5px"
267
- pl="8px"
268
- borderRadius="4px"
269
- alignItems="center"
270
- justifyContent="space-between"
271
- onClick={() => {
272
- if (!disabled) {
273
- if (isFocussed) {
274
- return setIsFocussed(false);
275
- }
276
-
277
- inputRef.current?.focus();
278
- setIsFocussed(true);
279
- }
280
- }}
281
- bg={disabled ? colors.fill.light.quaternary : '#ffffff'}
282
- cursor={disabled ? 'not-allowed' : 'pointer'}
283
- >
260
+ }, [localOptions, searchValue]);
261
+
262
+ const handleInput = (e: React.ChangeEvent<HTMLInputElement>) => {
263
+ const initialOptionIndex =
264
+ filteredOptions[0]?.value === 'section_header' ? 1 : 0;
265
+ setOptionIndex(initialOptionIndex);
266
+ const { value } = e.target;
267
+ setSearchValue(value);
268
+ };
269
+
270
+ return (
271
+ <Box ref={dropdownRef} position="relative" onKeyDown={handleOnKeyDown}>
284
272
  <Flex
273
+ fontSize="13px"
274
+ h="26px"
275
+ border={isFocussed ? '2px solid' : '.5px solid'}
276
+ borderColor={isFocussed ? colors.border.focus : colors.border.default}
277
+ py="5px"
278
+ pl="8px"
279
+ borderRadius="4px"
285
280
  alignItems="center"
286
- h="inherit"
287
- width="90%"
288
- overflowX="scroll"
289
- style={{
290
- scrollbarWidth: 'none' /* Firefox */,
291
- msOverflowStyle: 'none',
292
- }}
293
- sx={{
294
- '::-webkit-scrollbar': {
295
- display: 'none',
296
- },
281
+ justifyContent="space-between"
282
+ onClick={() => {
283
+ if (!disabled) {
284
+ if (isFocussed) {
285
+ return setIsFocussed(false);
286
+ }
287
+
288
+ inputRef.current?.focus();
289
+ setIsFocussed(true);
290
+ }
297
291
  }}
298
- ref={scrollRef}
292
+ bg={disabled ? colors.fill.light.quaternary : '#ffffff'}
293
+ cursor={disabled ? 'not-allowed' : 'pointer'}
299
294
  >
300
- {localValues.length ? (
301
- localValues.map((option, idx) => (
302
- <Box
303
- key={idx}
304
- mr="4px"
305
- width="fit-content"
306
- h="16px"
307
- borderRadius="full"
308
- >
309
- <Token
310
- label={option.label}
311
- onDelete={() => handleDelete(option)}
312
- />
313
- </Box>
314
- ))
315
- ) : (
316
- <Text color={colors.label.secondary.light} fontSize="13px">
317
- {placeholder}
318
- </Text>
319
- )}
295
+ <Flex
296
+ alignItems="center"
297
+ h="inherit"
298
+ width="90%"
299
+ overflowX="scroll"
300
+ style={{
301
+ scrollbarWidth: 'none' /* Firefox */,
302
+ msOverflowStyle: 'none',
303
+ }}
304
+ sx={{
305
+ '::-webkit-scrollbar': {
306
+ display: 'none',
307
+ },
308
+ }}
309
+ ref={scrollRef}
310
+ >
311
+ {localValues.length ? (
312
+ localValues.map((option, idx) => (
313
+ <Box
314
+ key={idx}
315
+ mr="4px"
316
+ width="fit-content"
317
+ h="16px"
318
+ borderRadius="full"
319
+ >
320
+ <Token
321
+ label={option.label}
322
+ onDelete={() => handleDelete(option)}
323
+ />
324
+ </Box>
325
+ ))
326
+ ) : (
327
+ <Text color={colors.label.secondary.light} fontSize="13px">
328
+ {placeholder}
329
+ </Text>
330
+ )}
331
+ </Flex>
332
+ <Input
333
+ padding={0}
334
+ border="none"
335
+ height="0"
336
+ width="0"
337
+ autoComplete="off"
338
+ type="text"
339
+ ref={inputRef}
340
+ tabIndex={-1}
341
+ _focus={{ boxShadow: 'none !important' }}
342
+ />
343
+ <Flex mr="4px" justifyContent="center" alignItems="center">
344
+ <DropdownIcon boxSize="12px" disabled={disabled} />
345
+ </Flex>
320
346
  </Flex>
321
- <Input
322
- padding={0}
323
- border="none"
324
- height="0"
325
- width="0"
326
- autoComplete="off"
327
- type="text"
328
- ref={inputRef}
329
- tabIndex={-1}
330
- _focus={{ boxShadow: 'none !important' }}
331
- />
332
- <Flex mr="4px" justifyContent="center" alignItems="center">
333
- <DropdownIcon boxSize="16px" disabled={disabled} />
334
- </Flex>
335
- </Flex>
336
- {isFocussed && (
337
- <Dropdown
338
- dropdownRef={dropdownMenuRef}
339
- onSelectItem={option => handleChange(option)}
340
- options={localOptions}
341
- position={position}
342
- optionIndex={optionIndex}
343
- />
344
- )}
345
- </Box>
346
- );
347
- });
347
+ {isFocussed && (
348
+ <Dropdown
349
+ dropdownRef={dropdownMenuRef}
350
+ onSelectItem={option => handleChange(option)}
351
+ options={filteredOptions}
352
+ position={position}
353
+ optionIndex={optionIndex}
354
+ loading={loadingOptions}
355
+ >
356
+ <Input
357
+ value={searchValue}
358
+ onChange={handleInput}
359
+ disabled={loadingOptions}
360
+ />
361
+ </Dropdown>
362
+ )}
363
+ </Box>
364
+ );
365
+ }
366
+ );
348
367
 
349
368
  export default StackedMultiSelect;