react-native-input-select 1.1.5 → 1.1.7
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/README.md +31 -5
- package/lib/commonjs/components/CustomModal/index.js +1 -2
- package/lib/commonjs/components/CustomModal/index.js.map +1 -1
- package/lib/commonjs/components/Input/index.js +7 -2
- package/lib/commonjs/components/Input/index.js.map +1 -1
- package/lib/commonjs/index.js +34 -22
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/types/index.types.js.map +1 -1
- package/lib/commonjs/utils/index.js +2 -12
- package/lib/commonjs/utils/index.js.map +1 -1
- package/lib/module/components/CustomModal/index.js +1 -2
- package/lib/module/components/CustomModal/index.js.map +1 -1
- package/lib/module/components/Input/index.js +7 -2
- package/lib/module/components/Input/index.js.map +1 -1
- package/lib/module/index.js +35 -23
- package/lib/module/index.js.map +1 -1
- package/lib/module/types/index.types.js.map +1 -1
- package/lib/module/utils/index.js +1 -10
- package/lib/module/utils/index.js.map +1 -1
- package/lib/typescript/components/CustomModal/index.d.ts +1 -1
- package/lib/typescript/components/Input/index.d.ts +1 -1
- package/lib/typescript/types/index.types.d.ts +6 -1
- package/lib/typescript/utils/index.d.ts +0 -2
- package/package.json +1 -1
- package/src/components/CustomModal/index.tsx +1 -2
- package/src/components/Input/index.tsx +7 -2
- package/src/index.tsx +43 -42
- package/src/types/index.types.ts +6 -0
- package/src/utils/index.ts +1 -17
package/src/index.tsx
CHANGED
|
@@ -15,10 +15,7 @@ import type {
|
|
|
15
15
|
TSectionList,
|
|
16
16
|
TSectionListItem,
|
|
17
17
|
} from './types/index.types';
|
|
18
|
-
import {
|
|
19
|
-
extractPropertyFromArray,
|
|
20
|
-
getMaxLengthOfSectionListProperty,
|
|
21
|
-
} from './utils';
|
|
18
|
+
import { extractPropertyFromArray } from './utils';
|
|
22
19
|
|
|
23
20
|
export const DropdownSelect: React.FC<DropdownProps> = ({
|
|
24
21
|
placeholder,
|
|
@@ -45,7 +42,7 @@ export const DropdownSelect: React.FC<DropdownProps> = ({
|
|
|
45
42
|
multipleSelectedItemStyle,
|
|
46
43
|
modalBackgroundStyle,
|
|
47
44
|
modalOptionsContainerStyle,
|
|
48
|
-
searchInputStyle,
|
|
45
|
+
searchInputStyle, // kept for backwards compatibility
|
|
49
46
|
primaryColor,
|
|
50
47
|
disabled,
|
|
51
48
|
checkboxSize, // kept for backwards compatibility
|
|
@@ -59,6 +56,7 @@ export const DropdownSelect: React.FC<DropdownProps> = ({
|
|
|
59
56
|
modalProps,
|
|
60
57
|
hideModal = false,
|
|
61
58
|
listControls,
|
|
59
|
+
searchControls,
|
|
62
60
|
...rest
|
|
63
61
|
}) => {
|
|
64
62
|
const [newOptions, setNewOptions] = useState<TFlatList | TSectionList>([]);
|
|
@@ -72,10 +70,12 @@ export const DropdownSelect: React.FC<DropdownProps> = ({
|
|
|
72
70
|
itemIndex: number;
|
|
73
71
|
}>({ itemIndex: 0 }); // for scrollToIndex in Sectionlist and Flatlist
|
|
74
72
|
|
|
73
|
+
if (!options || options.length === 0) {
|
|
74
|
+
throw new Error('Options array cannot be empty or undefined');
|
|
75
|
+
}
|
|
76
|
+
|
|
75
77
|
useEffect(() => {
|
|
76
|
-
|
|
77
|
-
setNewOptions(options);
|
|
78
|
-
}
|
|
78
|
+
setNewOptions(options);
|
|
79
79
|
return () => {};
|
|
80
80
|
}, [options]);
|
|
81
81
|
|
|
@@ -91,6 +91,7 @@ export const DropdownSelect: React.FC<DropdownProps> = ({
|
|
|
91
91
|
* List type
|
|
92
92
|
*==========================================*/
|
|
93
93
|
|
|
94
|
+
// check the structure of the new options array to determine if it is a section list or a
|
|
94
95
|
const isSectionList = newOptions.some(
|
|
95
96
|
(item) => item.title && item.data && Array.isArray(item.data)
|
|
96
97
|
);
|
|
@@ -102,11 +103,16 @@ export const DropdownSelect: React.FC<DropdownProps> = ({
|
|
|
102
103
|
newOptions,
|
|
103
104
|
'data'
|
|
104
105
|
).flat();
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
*`modifiedOptions` should only be used for computations newOptions remains the default array.
|
|
109
|
+
* At this point modifiedOptions now has the same structure for both `FlatList` and `SectionList`
|
|
110
|
+
*/
|
|
105
111
|
const modifiedOptions = isSectionList ? modifiedSectionData : newOptions;
|
|
106
112
|
|
|
107
113
|
const optLabel = optionLabel || DEFAULT_OPTION_LABEL;
|
|
108
114
|
const optValue = optionValue || DEFAULT_OPTION_VALUE;
|
|
109
|
-
const optionsCopy = JSON.parse(JSON.stringify(options)); //copy of the original options array
|
|
115
|
+
const optionsCopy = JSON.parse(JSON.stringify(options)); // copy of the original options array
|
|
110
116
|
|
|
111
117
|
/*===========================================
|
|
112
118
|
* Selection handlers
|
|
@@ -114,11 +120,11 @@ export const DropdownSelect: React.FC<DropdownProps> = ({
|
|
|
114
120
|
const handleSingleSelection = (value: string | number) => {
|
|
115
121
|
if (selectedItem === value) {
|
|
116
122
|
setSelectedItem(null);
|
|
117
|
-
onValueChange(null); //send value to parent
|
|
123
|
+
onValueChange(null); // send value to parent
|
|
118
124
|
} else {
|
|
119
125
|
setSelectedItem(value);
|
|
120
|
-
onValueChange(value); //send value to parent
|
|
121
|
-
setOpen(false); //close modal upon selection
|
|
126
|
+
onValueChange(value); // send value to parent
|
|
127
|
+
setOpen(false); // close modal upon selection
|
|
122
128
|
}
|
|
123
129
|
};
|
|
124
130
|
|
|
@@ -131,18 +137,24 @@ export const DropdownSelect: React.FC<DropdownProps> = ({
|
|
|
131
137
|
} else {
|
|
132
138
|
selectedValues.push(value);
|
|
133
139
|
}
|
|
134
|
-
onValueChange(selectedValues); //send value to parent
|
|
140
|
+
onValueChange(selectedValues); // send value to parent
|
|
135
141
|
return selectedValues;
|
|
136
142
|
});
|
|
137
143
|
};
|
|
138
144
|
|
|
145
|
+
const removeDisabledItems = (items: TFlatList) => {
|
|
146
|
+
return items.filter((item: TFlatListItem) => !item.disabled);
|
|
147
|
+
};
|
|
148
|
+
|
|
139
149
|
const handleSelectAll = () => {
|
|
140
150
|
setSelectAll((prevVal) => {
|
|
141
151
|
const selectedValues = [];
|
|
142
152
|
|
|
143
|
-
//don't select disabled items
|
|
144
|
-
const filteredOptions =
|
|
145
|
-
|
|
153
|
+
// don't select disabled items
|
|
154
|
+
const filteredOptions = removeDisabledItems(
|
|
155
|
+
isSectionList
|
|
156
|
+
? extractPropertyFromArray(optionsCopy, 'data').flat()
|
|
157
|
+
: optionsCopy
|
|
146
158
|
);
|
|
147
159
|
|
|
148
160
|
if (!prevVal) {
|
|
@@ -152,21 +164,15 @@ export const DropdownSelect: React.FC<DropdownProps> = ({
|
|
|
152
164
|
}
|
|
153
165
|
|
|
154
166
|
setSelectedItems(selectedValues);
|
|
155
|
-
onValueChange(selectedValues); //send value to parent
|
|
167
|
+
onValueChange(selectedValues); // send value to parent
|
|
156
168
|
return !prevVal;
|
|
157
169
|
});
|
|
158
170
|
|
|
159
|
-
if (
|
|
160
|
-
typeof listControls?.selectAllCallback === 'function' &&
|
|
161
|
-
!selectAll
|
|
162
|
-
) {
|
|
171
|
+
if (typeof listControls?.selectAllCallback === 'function' && !selectAll) {
|
|
163
172
|
listControls.selectAllCallback();
|
|
164
173
|
}
|
|
165
174
|
|
|
166
|
-
if (
|
|
167
|
-
typeof listControls?.unselectAllCallback === 'function' &&
|
|
168
|
-
selectAll
|
|
169
|
-
) {
|
|
175
|
+
if (typeof listControls?.unselectAllCallback === 'function' && selectAll) {
|
|
170
176
|
listControls.unselectAllCallback();
|
|
171
177
|
}
|
|
172
178
|
};
|
|
@@ -178,8 +184,7 @@ export const DropdownSelect: React.FC<DropdownProps> = ({
|
|
|
178
184
|
(selectedValues: any[]) => {
|
|
179
185
|
//if the list contains disabled values, those values will not be selected
|
|
180
186
|
if (
|
|
181
|
-
modifiedOptions.
|
|
182
|
-
.length === selectedValues.length
|
|
187
|
+
removeDisabledItems(modifiedOptions).length === selectedValues.length
|
|
183
188
|
) {
|
|
184
189
|
setSelectAll(true);
|
|
185
190
|
} else {
|
|
@@ -229,7 +234,7 @@ export const DropdownSelect: React.FC<DropdownProps> = ({
|
|
|
229
234
|
|
|
230
235
|
const regexFilter = new RegExp(searchText, 'i');
|
|
231
236
|
|
|
232
|
-
//Because
|
|
237
|
+
// Because the options array will be mutated after Search, we have to search with a copy of the original array
|
|
233
238
|
const searchResults = isSectionList
|
|
234
239
|
? searchSectionList(optionsCopy as TSectionList, regexFilter)
|
|
235
240
|
: searchFlatList(optionsCopy as TFlatList, regexFilter);
|
|
@@ -243,7 +248,7 @@ export const DropdownSelect: React.FC<DropdownProps> = ({
|
|
|
243
248
|
item[optLabel].toString().toLowerCase().search(regexFilter) !== -1 ||
|
|
244
249
|
item[optValue].toString().toLowerCase().search(regexFilter) !== -1
|
|
245
250
|
) {
|
|
246
|
-
return
|
|
251
|
+
return true;
|
|
247
252
|
}
|
|
248
253
|
return;
|
|
249
254
|
});
|
|
@@ -290,15 +295,6 @@ export const DropdownSelect: React.FC<DropdownProps> = ({
|
|
|
290
295
|
|
|
291
296
|
let primary = primaryColor || colors.gray;
|
|
292
297
|
|
|
293
|
-
const sectionListMaxLength = getMaxLengthOfSectionListProperty(
|
|
294
|
-
newOptions as TSectionList,
|
|
295
|
-
'data'
|
|
296
|
-
);
|
|
297
|
-
|
|
298
|
-
const listIsEmpty = isSectionList
|
|
299
|
-
? sectionListMaxLength > 1
|
|
300
|
-
: newOptions.length > 1;
|
|
301
|
-
|
|
302
298
|
/*===========================================
|
|
303
299
|
* setIndexOfSelectedItem - For ScrollToIndex
|
|
304
300
|
*==========================================*/
|
|
@@ -348,25 +344,30 @@ export const DropdownSelect: React.FC<DropdownProps> = ({
|
|
|
348
344
|
/>
|
|
349
345
|
<CustomModal
|
|
350
346
|
open={open}
|
|
351
|
-
handleToggleModal={handleToggleModal}
|
|
352
347
|
modalBackgroundStyle={modalBackgroundStyle}
|
|
353
348
|
modalOptionsContainerStyle={modalOptionsContainerStyle}
|
|
354
|
-
onRequestClose={() =>
|
|
349
|
+
onRequestClose={() => handleToggleModal()}
|
|
355
350
|
modalProps={modalProps}
|
|
356
351
|
>
|
|
357
352
|
<ListTypeComponent
|
|
353
|
+
removeClippedSubviews={false}
|
|
358
354
|
ListHeaderComponent={
|
|
359
355
|
<>
|
|
360
356
|
{isSearchable && (
|
|
361
357
|
<Input
|
|
362
358
|
value={searchValue}
|
|
363
359
|
onChangeText={(text: string) => onSearch(text)}
|
|
364
|
-
style={searchInputStyle}
|
|
360
|
+
style={searchControls?.textInputStyle || searchInputStyle}
|
|
365
361
|
primaryColor={primary}
|
|
362
|
+
textInputContainerStyle={
|
|
363
|
+
searchControls?.textInputContainerStyle
|
|
364
|
+
}
|
|
365
|
+
openModal={() => setOpen(true)} // There seems to a known issue on expo web that closes the modal when the input is focused
|
|
366
|
+
{...searchControls?.textInputProps}
|
|
366
367
|
/>
|
|
367
368
|
)}
|
|
368
369
|
{listHeaderComponent}
|
|
369
|
-
{isMultiple &&
|
|
370
|
+
{isMultiple && modifiedOptions.length > 1 && (
|
|
370
371
|
<View style={styles.optionsContainerStyle}>
|
|
371
372
|
<TouchableOpacity onPress={() => {}}>
|
|
372
373
|
<CheckBox
|
package/src/types/index.types.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type {
|
|
|
3
3
|
ColorValue,
|
|
4
4
|
TextStyle,
|
|
5
5
|
ModalProps,
|
|
6
|
+
TextInputProps,
|
|
6
7
|
} from 'react-native';
|
|
7
8
|
|
|
8
9
|
export type DropdownProps = {
|
|
@@ -64,6 +65,11 @@ export type DropdownProps = {
|
|
|
64
65
|
selectAllCallback?: () => void;
|
|
65
66
|
unselectAllCallback?: () => void;
|
|
66
67
|
};
|
|
68
|
+
searchControls?: {
|
|
69
|
+
textInputStyle?: ViewStyle | TextStyle;
|
|
70
|
+
textInputContainerStyle?: ViewStyle;
|
|
71
|
+
textInputProps?: TextInputProps;
|
|
72
|
+
};
|
|
67
73
|
};
|
|
68
74
|
|
|
69
75
|
export type TFlatList = TFlatListItem[];
|
package/src/utils/index.ts
CHANGED
|
@@ -1,25 +1,9 @@
|
|
|
1
|
-
import { TSectionList } from 'src/types/index.types';
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
2
|
* Extract property from array
|
|
5
3
|
*/
|
|
4
|
+
|
|
6
5
|
export const extractPropertyFromArray = (arr: any, property: string) => {
|
|
7
6
|
let extractedValue = arr.map((item: any) => item[property]);
|
|
8
7
|
|
|
9
8
|
return extractedValue;
|
|
10
9
|
};
|
|
11
|
-
|
|
12
|
-
export const getMaxLengthOfSectionListProperty = (
|
|
13
|
-
sectionList: TSectionList,
|
|
14
|
-
property: 'title' | 'data'
|
|
15
|
-
) => {
|
|
16
|
-
let maxLength = 0;
|
|
17
|
-
|
|
18
|
-
sectionList.forEach((obj) => {
|
|
19
|
-
if (obj[property]?.length > maxLength) {
|
|
20
|
-
maxLength = obj.data.length;
|
|
21
|
-
}
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
return maxLength;
|
|
25
|
-
};
|