react-native-input-select 1.1.0 → 1.1.2
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 +1 -2
- package/lib/commonjs/components/CheckBox/index.js +17 -7
- package/lib/commonjs/components/CheckBox/index.js.map +1 -1
- package/lib/commonjs/components/Dropdown/Dropdown.js +4 -2
- package/lib/commonjs/components/Dropdown/Dropdown.js.map +1 -1
- package/lib/commonjs/components/Dropdown/DropdownFlatList.js +29 -4
- package/lib/commonjs/components/Dropdown/DropdownFlatList.js.map +1 -1
- package/lib/commonjs/components/Dropdown/DropdownSectionList.js +25 -1
- package/lib/commonjs/components/Dropdown/DropdownSectionList.js.map +1 -1
- package/lib/commonjs/components/Dropdown/DropdownSelectedItemsView.js +41 -9
- package/lib/commonjs/components/Dropdown/DropdownSelectedItemsView.js.map +1 -1
- package/lib/commonjs/index.js +60 -15
- package/lib/commonjs/index.js.map +1 -1
- package/lib/module/components/CheckBox/index.js +17 -6
- package/lib/module/components/CheckBox/index.js.map +1 -1
- package/lib/module/components/Dropdown/Dropdown.js +4 -2
- package/lib/module/components/Dropdown/Dropdown.js.map +1 -1
- package/lib/module/components/Dropdown/DropdownFlatList.js +27 -4
- package/lib/module/components/Dropdown/DropdownFlatList.js.map +1 -1
- package/lib/module/components/Dropdown/DropdownSectionList.js +26 -2
- package/lib/module/components/Dropdown/DropdownSectionList.js.map +1 -1
- package/lib/module/components/Dropdown/DropdownSelectedItemsView.js +42 -10
- package/lib/module/components/Dropdown/DropdownSelectedItemsView.js.map +1 -1
- package/lib/module/index.js +61 -16
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/components/CheckBox/index.d.ts +16 -4
- package/lib/typescript/components/Dropdown/Dropdown.d.ts +1 -1
- package/lib/typescript/components/Dropdown/DropdownFlatList.d.ts +1 -1
- package/lib/typescript/components/Dropdown/DropdownSectionList.d.ts +1 -1
- package/lib/typescript/components/Dropdown/DropdownSelectedItemsView.d.ts +1 -1
- package/package.json +2 -2
- package/src/components/CheckBox/index.tsx +17 -6
- package/src/components/Dropdown/Dropdown.tsx +3 -0
- package/src/components/Dropdown/DropdownFlatList.tsx +24 -1
- package/src/components/Dropdown/DropdownSectionList.tsx +27 -1
- package/src/components/Dropdown/DropdownSelectedItemsView.tsx +32 -13
- package/src/index.tsx +61 -18
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* eslint-disable react-native/no-inline-styles */
|
|
2
|
-
import React, { useEffect, useState } from 'react';
|
|
2
|
+
import React, { useEffect, useState, useRef } from 'react';
|
|
3
3
|
import { SectionList, StyleSheet } from 'react-native';
|
|
4
4
|
import DropdownListItem from './DropdownListItem';
|
|
5
5
|
import {
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
SectionHeaderTitle,
|
|
9
9
|
} from '../Others';
|
|
10
10
|
import { extractPropertyFromArray } from '../../utils';
|
|
11
|
+
import { TSectionList } from 'src/types/index.types';
|
|
11
12
|
|
|
12
13
|
const DropdownSectionList = ({
|
|
13
14
|
options,
|
|
@@ -25,6 +26,7 @@ const DropdownSectionList = ({
|
|
|
25
26
|
checkboxLabelStyle,
|
|
26
27
|
checkboxComponentStyles,
|
|
27
28
|
listComponentStyles,
|
|
29
|
+
listIndex,
|
|
28
30
|
...rest
|
|
29
31
|
}: any) => {
|
|
30
32
|
const [expandedSections, setExpandedSections] = useState(new Set());
|
|
@@ -53,6 +55,24 @@ const DropdownSectionList = ({
|
|
|
53
55
|
});
|
|
54
56
|
};
|
|
55
57
|
|
|
58
|
+
/**
|
|
59
|
+
* @description Scroll to item location
|
|
60
|
+
*/
|
|
61
|
+
|
|
62
|
+
const sectionlistRef = useRef<SectionList<TSectionList>>(null);
|
|
63
|
+
|
|
64
|
+
const scrollToLocation = (listIndex: any) => {
|
|
65
|
+
sectionlistRef.current?.scrollToLocation({
|
|
66
|
+
sectionIndex: listIndex.sectionIndex,
|
|
67
|
+
animated: true,
|
|
68
|
+
itemIndex: listIndex.itemIndex,
|
|
69
|
+
});
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
useEffect(() => {
|
|
73
|
+
scrollToLocation(listIndex);
|
|
74
|
+
}, [listIndex]);
|
|
75
|
+
|
|
56
76
|
return (
|
|
57
77
|
<SectionList
|
|
58
78
|
sections={options}
|
|
@@ -100,6 +120,12 @@ const DropdownSectionList = ({
|
|
|
100
120
|
}
|
|
101
121
|
keyExtractor={(_item, index) => `Options${index}`}
|
|
102
122
|
stickySectionHeadersEnabled={false}
|
|
123
|
+
ref={sectionlistRef}
|
|
124
|
+
onScrollToIndexFailed={() => {
|
|
125
|
+
setTimeout(() => {
|
|
126
|
+
scrollToLocation(listIndex);
|
|
127
|
+
}, 500);
|
|
128
|
+
}}
|
|
103
129
|
{...rest}
|
|
104
130
|
/>
|
|
105
131
|
);
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
ScrollView,
|
|
7
7
|
StyleSheet,
|
|
8
8
|
Image,
|
|
9
|
+
TouchableOpacity,
|
|
9
10
|
} from 'react-native';
|
|
10
11
|
import { colors } from '../../styles/colors';
|
|
11
12
|
import { inputStyles } from '../../styles/input';
|
|
@@ -27,6 +28,7 @@ const DropdownSelectedItemsView = ({
|
|
|
27
28
|
dropdownErrorStyle,
|
|
28
29
|
primaryColor,
|
|
29
30
|
disabled,
|
|
31
|
+
setIndexOfSelectedItem,
|
|
30
32
|
}: any) => {
|
|
31
33
|
return (
|
|
32
34
|
<Pressable
|
|
@@ -36,8 +38,7 @@ const DropdownSelectedItemsView = ({
|
|
|
36
38
|
...inputStyles.inputFocusState,
|
|
37
39
|
borderColor: primaryColor,
|
|
38
40
|
},
|
|
39
|
-
inputStyles.input,
|
|
40
|
-
dropdownStyle,
|
|
41
|
+
{ ...inputStyles.input, ...dropdownStyle },
|
|
41
42
|
error && //this must be last
|
|
42
43
|
error !== '' &&
|
|
43
44
|
!pressed && {
|
|
@@ -57,27 +58,37 @@ const DropdownSelectedItemsView = ({
|
|
|
57
58
|
onStartShouldSetResponder={() => true}
|
|
58
59
|
>
|
|
59
60
|
{isMultiple ? (
|
|
60
|
-
getSelectedItemsLabel()?.map((
|
|
61
|
-
<
|
|
61
|
+
getSelectedItemsLabel()?.map((label: string, i: Number) => (
|
|
62
|
+
<DropdownContent
|
|
63
|
+
onPress={() => {
|
|
64
|
+
handleToggleModal();
|
|
65
|
+
setIndexOfSelectedItem(label); // immediately scrolls to list item with the specified label when modal
|
|
66
|
+
}}
|
|
62
67
|
key={`react-native-input-select-${Math.random()}-${i}`}
|
|
63
68
|
style={[
|
|
64
69
|
styles.selectedItems,
|
|
65
70
|
{ backgroundColor: primaryColor },
|
|
66
71
|
multipleSelectedItemStyle,
|
|
67
72
|
]}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
</Text>
|
|
73
|
+
label={label}
|
|
74
|
+
/>
|
|
71
75
|
))
|
|
72
76
|
) : (
|
|
73
|
-
<
|
|
74
|
-
{
|
|
75
|
-
|
|
77
|
+
<DropdownContent
|
|
78
|
+
onPress={() => {
|
|
79
|
+
handleToggleModal();
|
|
80
|
+
setIndexOfSelectedItem(getSelectedItemsLabel()); // immediately scrolls to list item with the specified label when modal
|
|
81
|
+
}}
|
|
82
|
+
style={[styles.blackText, selectedItemStyle]}
|
|
83
|
+
label={getSelectedItemsLabel()}
|
|
84
|
+
/>
|
|
76
85
|
)}
|
|
77
86
|
{!selectedItem && selectedItems?.length === 0 && (
|
|
78
|
-
<
|
|
79
|
-
{
|
|
80
|
-
|
|
87
|
+
<DropdownContent
|
|
88
|
+
onPress={() => handleToggleModal()}
|
|
89
|
+
style={[styles.blackText, placeholderStyle]}
|
|
90
|
+
label={placeholder ?? 'Select an option'}
|
|
91
|
+
/>
|
|
81
92
|
)}
|
|
82
93
|
</View>
|
|
83
94
|
</ScrollView>
|
|
@@ -90,6 +101,14 @@ const DropdownSelectedItemsView = ({
|
|
|
90
101
|
);
|
|
91
102
|
};
|
|
92
103
|
|
|
104
|
+
const DropdownContent = ({ onPress, style, label, ...rest }: any) => {
|
|
105
|
+
return (
|
|
106
|
+
<TouchableOpacity onPress={() => onPress()} {...rest}>
|
|
107
|
+
<Text style={style}>{label}</Text>
|
|
108
|
+
</TouchableOpacity>
|
|
109
|
+
);
|
|
110
|
+
};
|
|
111
|
+
|
|
93
112
|
const styles = StyleSheet.create({
|
|
94
113
|
iconStyle: { position: 'absolute', right: 25, top: 25 },
|
|
95
114
|
selectedItemsContainer: {
|
package/src/index.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useState, useEffect } from 'react';
|
|
1
|
+
import React, { useState, useEffect, useCallback } from 'react';
|
|
2
2
|
import { TouchableOpacity, StyleSheet, View } from 'react-native';
|
|
3
3
|
import Input from './components/Input';
|
|
4
4
|
import CheckBox from './components/CheckBox';
|
|
@@ -62,9 +62,13 @@ export const DropdownSelect: React.FC<DropdownProps> = ({
|
|
|
62
62
|
const [newOptions, setNewOptions] = useState<TFlatList | TSectionList>([]);
|
|
63
63
|
const [open, setOpen] = useState<boolean>(false);
|
|
64
64
|
const [selectAll, setSelectAll] = useState<boolean>(false);
|
|
65
|
-
const [selectedItem, setSelectedItem] = useState<any>(''); //for single selection
|
|
66
|
-
const [selectedItems, setSelectedItems] = useState<any[]>([]); //for multiple selection
|
|
65
|
+
const [selectedItem, setSelectedItem] = useState<any>(''); // for single selection
|
|
66
|
+
const [selectedItems, setSelectedItems] = useState<any[]>([]); // for multiple selection
|
|
67
67
|
const [searchValue, setSearchValue] = useState<string>('');
|
|
68
|
+
const [listIndex, setListIndex] = useState<{
|
|
69
|
+
sectionIndex?: number;
|
|
70
|
+
itemIndex: number;
|
|
71
|
+
}>({ itemIndex: 0 }); // for scrollToIndex in Sectionlist and Flatlist
|
|
68
72
|
|
|
69
73
|
useEffect(() => {
|
|
70
74
|
if (options) {
|
|
@@ -92,11 +96,15 @@ export const DropdownSelect: React.FC<DropdownProps> = ({
|
|
|
92
96
|
const ListTypeComponent = isSectionList
|
|
93
97
|
? DropdownSectionList
|
|
94
98
|
: DropdownFlatList;
|
|
95
|
-
|
|
96
|
-
|
|
99
|
+
const modifiedSectionData = extractPropertyFromArray(
|
|
100
|
+
newOptions,
|
|
101
|
+
'data'
|
|
102
|
+
).flat();
|
|
103
|
+
const modifiedOptions = isSectionList ? modifiedSectionData : newOptions;
|
|
97
104
|
|
|
98
105
|
const optLabel = optionLabel || DEFAULT_OPTION_LABEL;
|
|
99
106
|
const optValue = optionValue || DEFAULT_OPTION_VALUE;
|
|
107
|
+
const optionsCopy = JSON.parse(JSON.stringify(options)); //copy of the original options array
|
|
100
108
|
|
|
101
109
|
/*===========================================
|
|
102
110
|
* Selection handlers
|
|
@@ -121,19 +129,7 @@ export const DropdownSelect: React.FC<DropdownProps> = ({
|
|
|
121
129
|
} else {
|
|
122
130
|
selectedValues.push(value);
|
|
123
131
|
}
|
|
124
|
-
|
|
125
|
-
setSelectedItems(selectedValues);
|
|
126
132
|
onValueChange(selectedValues); //send value to parent
|
|
127
|
-
|
|
128
|
-
//select all checkbox should not be checked if the list contains disabled values
|
|
129
|
-
if (
|
|
130
|
-
modifiedOptions.filter((item: TFlatListItem) => !item.disabled)
|
|
131
|
-
.length === selectedValues.length
|
|
132
|
-
) {
|
|
133
|
-
setSelectAll(true);
|
|
134
|
-
} else {
|
|
135
|
-
setSelectAll(false);
|
|
136
|
-
}
|
|
137
133
|
return selectedValues;
|
|
138
134
|
});
|
|
139
135
|
};
|
|
@@ -159,6 +155,32 @@ export const DropdownSelect: React.FC<DropdownProps> = ({
|
|
|
159
155
|
});
|
|
160
156
|
};
|
|
161
157
|
|
|
158
|
+
/*===========================================
|
|
159
|
+
* Handle side effects
|
|
160
|
+
*==========================================*/
|
|
161
|
+
const checkSelectAll = useCallback(
|
|
162
|
+
(selectedValues: any[]) => {
|
|
163
|
+
//if the list contains disabled values, those values will not be selected
|
|
164
|
+
if (
|
|
165
|
+
modifiedOptions.filter((item: TFlatListItem) => !item.disabled)
|
|
166
|
+
.length === selectedValues.length
|
|
167
|
+
) {
|
|
168
|
+
setSelectAll(true);
|
|
169
|
+
} else {
|
|
170
|
+
setSelectAll(false);
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
[modifiedOptions]
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
// anytime the selected items change, check if it is time to set `selectAll` to true
|
|
177
|
+
useEffect(() => {
|
|
178
|
+
if (isMultiple) {
|
|
179
|
+
checkSelectAll(selectedItems);
|
|
180
|
+
}
|
|
181
|
+
return () => {};
|
|
182
|
+
}, [checkSelectAll, isMultiple, selectedItems]);
|
|
183
|
+
|
|
162
184
|
/*===========================================
|
|
163
185
|
* Get label handler
|
|
164
186
|
*==========================================*/
|
|
@@ -192,7 +214,6 @@ export const DropdownSelect: React.FC<DropdownProps> = ({
|
|
|
192
214
|
const regexFilter = new RegExp(searchText, 'i');
|
|
193
215
|
|
|
194
216
|
//Because Search mutates the initial state, we have to search with a copy of the original array
|
|
195
|
-
const optionsCopy = JSON.parse(JSON.stringify(options));
|
|
196
217
|
const searchResults = isSectionList
|
|
197
218
|
? searchSectionList(optionsCopy as TSectionList, regexFilter)
|
|
198
219
|
: searchFlatList(optionsCopy as TFlatList, regexFilter);
|
|
@@ -241,6 +262,7 @@ export const DropdownSelect: React.FC<DropdownProps> = ({
|
|
|
241
262
|
setOpen(!open);
|
|
242
263
|
setSearchValue('');
|
|
243
264
|
setNewOptions(options);
|
|
265
|
+
setListIndex({ itemIndex: 0, sectionIndex: 0 });
|
|
244
266
|
};
|
|
245
267
|
|
|
246
268
|
useEffect(() => {
|
|
@@ -261,6 +283,25 @@ export const DropdownSelect: React.FC<DropdownProps> = ({
|
|
|
261
283
|
? sectionListMaxLength > 1
|
|
262
284
|
: newOptions.length > 1;
|
|
263
285
|
|
|
286
|
+
/*===========================================
|
|
287
|
+
* setIndexOfSelectedItem - For ScrollToIndex
|
|
288
|
+
*==========================================*/
|
|
289
|
+
const setIndexOfSelectedItem = (selectedLabel: string) => {
|
|
290
|
+
isSectionList
|
|
291
|
+
? optionsCopy.map((item: TSectionListItem, sectionIndex: number) => {
|
|
292
|
+
item.data?.find((dataItem: TFlatListItem, itemIndex: number) => {
|
|
293
|
+
if (dataItem[optLabel] === selectedLabel) {
|
|
294
|
+
setListIndex({ sectionIndex, itemIndex });
|
|
295
|
+
}
|
|
296
|
+
});
|
|
297
|
+
})
|
|
298
|
+
: optionsCopy?.find((item: TFlatListItem, itemIndex: number) => {
|
|
299
|
+
if (item[optLabel] === selectedLabel) {
|
|
300
|
+
setListIndex({ itemIndex });
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
};
|
|
304
|
+
|
|
264
305
|
return (
|
|
265
306
|
<>
|
|
266
307
|
<Dropdown
|
|
@@ -286,6 +327,7 @@ export const DropdownSelect: React.FC<DropdownProps> = ({
|
|
|
286
327
|
primaryColor={primary}
|
|
287
328
|
disabled={disabled}
|
|
288
329
|
placeholderStyle={placeholderStyle}
|
|
330
|
+
setIndexOfSelectedItem={setIndexOfSelectedItem}
|
|
289
331
|
{...rest}
|
|
290
332
|
/>
|
|
291
333
|
<CustomModal
|
|
@@ -342,6 +384,7 @@ export const DropdownSelect: React.FC<DropdownProps> = ({
|
|
|
342
384
|
checkboxStyle={checkboxStyle}
|
|
343
385
|
checkboxLabelStyle={checkboxLabelStyle}
|
|
344
386
|
checkboxComponentStyles={checkboxComponentStyles}
|
|
387
|
+
listIndex={listIndex}
|
|
345
388
|
/>
|
|
346
389
|
</CustomModal>
|
|
347
390
|
</>
|