@bigbinary/neetoui-rn 0.0.119 → 0.0.123
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/lib/components/Alert.js +1 -1
- package/lib/components/Avatar.js +1 -1
- package/lib/components/Badge.js +1 -1
- package/lib/components/BottomSheet.js +1 -1
- package/lib/components/Button.js +1 -1
- package/lib/components/ButtonGroup.js +1 -1
- package/lib/components/Card.js +1 -1
- package/lib/components/CheckBox.js +1 -1
- package/lib/components/Chip.js +1 -1
- package/lib/components/Container.js +1 -1
- package/lib/components/Divider.js +1 -1
- package/lib/components/FAB.js +1 -1
- package/lib/components/Input.js +1 -1
- package/lib/components/MultiSelect.js +1 -1
- package/lib/components/OtpInputs.js +1 -1
- package/lib/components/ParentView.js +1 -1
- package/lib/components/Popover.js +1 -1
- package/lib/components/RadioButton.js +1 -1
- package/lib/components/RichTextEditor.js +1 -1
- package/lib/components/Select.js +1 -1
- package/lib/components/Toast.js +1 -1
- package/lib/components/ToggleSwitch.js +1 -1
- package/lib/components/TopBar.js +1 -1
- package/lib/components/Touchable.js +1 -1
- package/lib/components/Typography.js +1 -1
- package/lib/config/toasterConfig.js +1 -1
- package/package.json +2 -1
- package/src/components/CheckBox.js +5 -4
- package/src/components/FAB.js +1 -0
- package/src/components/MultiSelect.js +131 -19
- package/src/components/RadioButton.js +4 -4
- package/src/components/Select.js +155 -44
package/src/components/Select.js
CHANGED
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
import { ThemeContext } from "styled-components/native";
|
|
17
17
|
import { ScrollView } from "react-native-gesture-handler";
|
|
18
18
|
|
|
19
|
-
import { Card, Container, Input, Typography } from "@components";
|
|
19
|
+
import { Card, Container, Input, Touchable, Typography } from "@components";
|
|
20
20
|
|
|
21
21
|
const DropdownItem = ({
|
|
22
22
|
label,
|
|
@@ -25,8 +25,8 @@ const DropdownItem = ({
|
|
|
25
25
|
onPress,
|
|
26
26
|
itemContainerStyle,
|
|
27
27
|
selectedItemContainerStyle,
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
itemLabelStyle,
|
|
29
|
+
selectedItemLabelStyle,
|
|
30
30
|
}) => (
|
|
31
31
|
<TouchableWithoutFeedback onPress={onPress}>
|
|
32
32
|
<Container
|
|
@@ -40,8 +40,8 @@ const DropdownItem = ({
|
|
|
40
40
|
fontFamily="inter400"
|
|
41
41
|
fontSize="s"
|
|
42
42
|
color={isSelectedItem ? "font.white" : "font.grey"}
|
|
43
|
-
{...
|
|
44
|
-
{...(isSelectedItem &&
|
|
43
|
+
{...itemLabelStyle}
|
|
44
|
+
{...(isSelectedItem && selectedItemLabelStyle)}
|
|
45
45
|
>
|
|
46
46
|
{label}
|
|
47
47
|
</Typography>
|
|
@@ -56,8 +56,8 @@ DropdownItem.propTypes = {
|
|
|
56
56
|
onPress: PropTypes.func,
|
|
57
57
|
itemContainerStyle: PropTypes.object,
|
|
58
58
|
selectedItemContainerStyle: PropTypes.object,
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
itemLabelStyle: PropTypes.object,
|
|
60
|
+
selectedItemLabelStyle: PropTypes.object,
|
|
61
61
|
};
|
|
62
62
|
|
|
63
63
|
/**
|
|
@@ -108,19 +108,30 @@ export const Select = ({
|
|
|
108
108
|
label,
|
|
109
109
|
value,
|
|
110
110
|
placeholder,
|
|
111
|
+
emptyOptionsPlaceholder,
|
|
111
112
|
labelExtractor,
|
|
112
113
|
valueExtractor,
|
|
113
114
|
onSelect,
|
|
114
115
|
isLoading,
|
|
115
116
|
isSearchable,
|
|
117
|
+
showCreateOption,
|
|
118
|
+
showCreateOptionLoader,
|
|
119
|
+
createOptionLabel,
|
|
120
|
+
onPressCreateOption,
|
|
116
121
|
labelStyle,
|
|
117
122
|
containerStyle,
|
|
118
123
|
inputContainerStyle,
|
|
119
124
|
dropdownContainerStyle,
|
|
120
125
|
itemContainerStyle,
|
|
121
|
-
|
|
126
|
+
itemLabelStyle,
|
|
122
127
|
selectedItemContainerStyle,
|
|
123
|
-
|
|
128
|
+
selectedItemLabelStyle,
|
|
129
|
+
searchInputContainerStyle,
|
|
130
|
+
searchInputStyle,
|
|
131
|
+
emptyOptionsContainerStyle,
|
|
132
|
+
emptyOptionsLabelStyle,
|
|
133
|
+
createSearchedOptionContainerStyle,
|
|
134
|
+
createSearchedOptionLabelStyle,
|
|
124
135
|
...rest
|
|
125
136
|
}) => {
|
|
126
137
|
const theme = useContext(ThemeContext);
|
|
@@ -128,16 +139,31 @@ export const Select = ({
|
|
|
128
139
|
const [searchQuery, setSearchQuery] = useState("");
|
|
129
140
|
const dropdownAnimatedHeight = useSharedValue(0);
|
|
130
141
|
|
|
142
|
+
const formatStr = str => str?.toLowerCase()?.trim();
|
|
143
|
+
const filteredOptions = options.filter((item, index) => {
|
|
144
|
+
const label = labelExtractor(item, index);
|
|
145
|
+
if (searchQuery?.length === 0) return true;
|
|
146
|
+
return formatStr(label).includes(formatStr(searchQuery));
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
const isOptionsEmpty = !options || options?.length === 0;
|
|
150
|
+
const isSearchedOptionsEmpty =
|
|
151
|
+
searchQuery.length > 0 && filteredOptions.length === 0;
|
|
152
|
+
const emptyOptionsPlaceholderHeight = 40;
|
|
153
|
+
const emptySearchedOptionsHeight = 40;
|
|
131
154
|
const searchInputHeight = 35;
|
|
132
155
|
const defaultDropdownItemHeight = itemContainerStyle?.height || 32;
|
|
133
156
|
const dropdownHeight =
|
|
134
157
|
dropdownContainerStyle?.height ||
|
|
135
158
|
dropdownContainerStyle?.maxHeight ||
|
|
136
|
-
defaultDropdownItemHeight * Math.min(
|
|
137
|
-
(isSearchable ? searchInputHeight + 10 : 0)
|
|
159
|
+
defaultDropdownItemHeight * Math.min(filteredOptions?.length, 6) +
|
|
160
|
+
(isSearchable ? searchInputHeight + 10 : 0) +
|
|
161
|
+
(isOptionsEmpty ? emptyOptionsPlaceholderHeight : 0) +
|
|
162
|
+
(isSearchedOptionsEmpty && showCreateOption
|
|
163
|
+
? emptySearchedOptionsHeight
|
|
164
|
+
: 0);
|
|
138
165
|
const selectedOptionLabel = labelExtractor(value || {});
|
|
139
166
|
const selectedOptionValue = valueExtractor(value || {});
|
|
140
|
-
const formatStr = str => str?.toLowerCase()?.trim();
|
|
141
167
|
|
|
142
168
|
const animatedStyles = useAnimatedStyle(() => {
|
|
143
169
|
return {
|
|
@@ -154,7 +180,7 @@ export const Select = ({
|
|
|
154
180
|
}
|
|
155
181
|
),
|
|
156
182
|
};
|
|
157
|
-
});
|
|
183
|
+
}, []);
|
|
158
184
|
|
|
159
185
|
const toggleAnimation = () => {
|
|
160
186
|
dropdownAnimatedHeight.value =
|
|
@@ -179,10 +205,10 @@ export const Select = ({
|
|
|
179
205
|
|
|
180
206
|
useEffect(() => {
|
|
181
207
|
if (showDropdown) {
|
|
182
|
-
|
|
208
|
+
dropdownAnimatedHeight.value = dropdownHeight;
|
|
183
209
|
}
|
|
184
210
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
185
|
-
}, [showDropdown]);
|
|
211
|
+
}, [showDropdown, dropdownHeight]);
|
|
186
212
|
|
|
187
213
|
return (
|
|
188
214
|
<Container {...containerStyle}>
|
|
@@ -237,7 +263,7 @@ export const Select = ({
|
|
|
237
263
|
{...dropdownContainerStyle}
|
|
238
264
|
>
|
|
239
265
|
{isSearchable && (
|
|
240
|
-
<Container p={1}>
|
|
266
|
+
<Container p={1} {...searchInputContainerStyle}>
|
|
241
267
|
<Input
|
|
242
268
|
placeholder="Search"
|
|
243
269
|
onChangeText={setSearchQuery}
|
|
@@ -247,40 +273,76 @@ export const Select = ({
|
|
|
247
273
|
height: searchInputHeight,
|
|
248
274
|
justifyContent: "center",
|
|
249
275
|
}}
|
|
276
|
+
{...searchInputStyle}
|
|
250
277
|
/>
|
|
251
278
|
</Container>
|
|
252
279
|
)}
|
|
280
|
+
{isOptionsEmpty && (
|
|
281
|
+
<Container
|
|
282
|
+
height={emptyOptionsPlaceholderHeight}
|
|
283
|
+
justifyContent="center"
|
|
284
|
+
alignItems="center"
|
|
285
|
+
{...emptyOptionsContainerStyle}
|
|
286
|
+
>
|
|
287
|
+
<Typography
|
|
288
|
+
fontFamily="inter400"
|
|
289
|
+
fontSize="s"
|
|
290
|
+
color="font.grey"
|
|
291
|
+
{...emptyOptionsLabelStyle}
|
|
292
|
+
>
|
|
293
|
+
{emptyOptionsPlaceholder || "No Options"}
|
|
294
|
+
</Typography>
|
|
295
|
+
</Container>
|
|
296
|
+
)}
|
|
297
|
+
{isSearchedOptionsEmpty && showCreateOption && (
|
|
298
|
+
<Touchable
|
|
299
|
+
height={emptySearchedOptionsHeight}
|
|
300
|
+
justifyContent="center"
|
|
301
|
+
alignItems="center"
|
|
302
|
+
onPress={() => onPressCreateOption(searchQuery)}
|
|
303
|
+
{...createSearchedOptionContainerStyle}
|
|
304
|
+
>
|
|
305
|
+
{showCreateOptionLoader ? (
|
|
306
|
+
<ActivityIndicator
|
|
307
|
+
size="small"
|
|
308
|
+
color={theme.colors.background.base}
|
|
309
|
+
/>
|
|
310
|
+
) : (
|
|
311
|
+
<Typography
|
|
312
|
+
fontFamily="inter400"
|
|
313
|
+
fontSize="s"
|
|
314
|
+
color="font.grey"
|
|
315
|
+
{...createSearchedOptionLabelStyle}
|
|
316
|
+
>
|
|
317
|
+
{createOptionLabel || `Create ${searchQuery} option`}
|
|
318
|
+
</Typography>
|
|
319
|
+
)}
|
|
320
|
+
</Touchable>
|
|
321
|
+
)}
|
|
253
322
|
{/* Animation not working without this hidden input */}
|
|
254
323
|
<Container height={0}>
|
|
255
324
|
<Input />
|
|
256
325
|
</Container>
|
|
257
326
|
<ScrollView>
|
|
258
|
-
{
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
itemContainerStyle={itemContainerStyle}
|
|
278
|
-
selectedItemContainerStyle={selectedItemContainerStyle}
|
|
279
|
-
itemTextStyle={itemTextStyle}
|
|
280
|
-
selectedItemTextStyle={selectedItemTextStyle}
|
|
281
|
-
/>
|
|
282
|
-
);
|
|
283
|
-
})}
|
|
327
|
+
{filteredOptions.map((item, index) => {
|
|
328
|
+
const optionLabel = labelExtractor(item, index);
|
|
329
|
+
const optionValue = valueExtractor(item, index);
|
|
330
|
+
const isSelectedItem =
|
|
331
|
+
selectedOptionValue && selectedOptionValue === optionValue;
|
|
332
|
+
return (
|
|
333
|
+
<DropdownItem
|
|
334
|
+
key={index}
|
|
335
|
+
label={optionLabel}
|
|
336
|
+
isSelectedItem={isSelectedItem}
|
|
337
|
+
defaultDropdownItemHeight={defaultDropdownItemHeight}
|
|
338
|
+
onPress={() => handleItemSelection(item, index)}
|
|
339
|
+
itemContainerStyle={itemContainerStyle}
|
|
340
|
+
selectedItemContainerStyle={selectedItemContainerStyle}
|
|
341
|
+
itemLabelStyle={itemLabelStyle}
|
|
342
|
+
selectedItemLabelStyle={selectedItemLabelStyle}
|
|
343
|
+
/>
|
|
344
|
+
);
|
|
345
|
+
})}
|
|
284
346
|
</ScrollView>
|
|
285
347
|
</Card>
|
|
286
348
|
</Animated.View>
|
|
@@ -308,6 +370,10 @@ Select.propTypes = {
|
|
|
308
370
|
* The text to be displayed if no option is selected.
|
|
309
371
|
*/
|
|
310
372
|
placeholder: PropTypes.string,
|
|
373
|
+
/**
|
|
374
|
+
* The text to be displayed if no options are provided.
|
|
375
|
+
*/
|
|
376
|
+
emptyOptionsPlaceholder: PropTypes.string,
|
|
311
377
|
/**
|
|
312
378
|
* Use custom key as label.
|
|
313
379
|
*/
|
|
@@ -332,6 +398,22 @@ Select.propTypes = {
|
|
|
332
398
|
* Toggle Search bar within the options dropdown to search through the options.
|
|
333
399
|
*/
|
|
334
400
|
isSearchable: PropTypes.bool,
|
|
401
|
+
/**
|
|
402
|
+
* Show option to create the searched label if not present in the options list
|
|
403
|
+
*/
|
|
404
|
+
showCreateOption: PropTypes.bool,
|
|
405
|
+
/**
|
|
406
|
+
* Show loader while creating a searched option not present in the options list
|
|
407
|
+
*/
|
|
408
|
+
showCreateOptionLoader: PropTypes.bool,
|
|
409
|
+
/**
|
|
410
|
+
* Custom label for creating searched option not present in the options list
|
|
411
|
+
*/
|
|
412
|
+
createOptionLabel: PropTypes.string,
|
|
413
|
+
/**
|
|
414
|
+
* Callback when create searched option is pressed
|
|
415
|
+
*/
|
|
416
|
+
onPressCreateOption: PropTypes.func,
|
|
335
417
|
/**
|
|
336
418
|
* To customise floating label styles.
|
|
337
419
|
*/
|
|
@@ -355,7 +437,7 @@ Select.propTypes = {
|
|
|
355
437
|
/**
|
|
356
438
|
* To customise dropdown item text styles.
|
|
357
439
|
*/
|
|
358
|
-
|
|
440
|
+
itemLabelStyle: PropTypes.object,
|
|
359
441
|
/**
|
|
360
442
|
* To customise dropdown item container styles for selected item.
|
|
361
443
|
*/
|
|
@@ -363,16 +445,45 @@ Select.propTypes = {
|
|
|
363
445
|
/**
|
|
364
446
|
* To customise dropdown item text styles for selected item.
|
|
365
447
|
*/
|
|
366
|
-
|
|
448
|
+
selectedItemLabelStyle: PropTypes.object,
|
|
449
|
+
/**
|
|
450
|
+
* To customise search input containerr style.
|
|
451
|
+
*/
|
|
452
|
+
searchInputContainerStyle: PropTypes.object,
|
|
453
|
+
/**
|
|
454
|
+
* To customise search input style.
|
|
455
|
+
*/
|
|
456
|
+
searchInputStyle: PropTypes.object,
|
|
457
|
+
/**
|
|
458
|
+
* To customise empty options placeholder container style.
|
|
459
|
+
*/
|
|
460
|
+
emptyOptionsContainerStyle: PropTypes.object,
|
|
461
|
+
/**
|
|
462
|
+
* To customise empty options placeholder text style.
|
|
463
|
+
*/
|
|
464
|
+
emptyOptionsLabelStyle: PropTypes.object,
|
|
465
|
+
/**
|
|
466
|
+
* To customise empty options placeholder container style.
|
|
467
|
+
*/
|
|
468
|
+
createSearchedOptionContainerStyle: PropTypes.object,
|
|
469
|
+
/**
|
|
470
|
+
* To customise empty options placeholder text style.
|
|
471
|
+
*/
|
|
472
|
+
createSearchedOptionLabelStyle: PropTypes.object,
|
|
367
473
|
};
|
|
368
474
|
|
|
369
475
|
Select.defaultProps = {
|
|
370
476
|
label: null,
|
|
371
477
|
placeholder: "Select Option",
|
|
478
|
+
emptyOptionsPlaceholder: null,
|
|
372
479
|
labelExtractor: option => option?.label,
|
|
373
480
|
valueExtractor: option => option?.value,
|
|
374
481
|
value: null,
|
|
375
482
|
onSelect: () => {},
|
|
376
483
|
isLoading: false,
|
|
377
484
|
isSearchable: false,
|
|
485
|
+
showCreateOption: false,
|
|
486
|
+
showCreateOptionLoader: false,
|
|
487
|
+
createOptionLabel: null,
|
|
488
|
+
onPressCreateOption: () => {},
|
|
378
489
|
};
|