react-native-input-select 2.1.4 → 2.1.6

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 (89) hide show
  1. package/README.md +14 -0
  2. package/lib/commonjs/asset/close.png +0 -0
  3. package/lib/commonjs/components/CheckBox/index.js +11 -8
  4. package/lib/commonjs/components/CheckBox/index.js.map +1 -1
  5. package/lib/commonjs/components/Dropdown/Dropdown.js +26 -11
  6. package/lib/commonjs/components/Dropdown/Dropdown.js.map +1 -1
  7. package/lib/commonjs/components/Dropdown/DropdownSelectedItem.js +53 -0
  8. package/lib/commonjs/components/Dropdown/DropdownSelectedItem.js.map +1 -0
  9. package/lib/commonjs/components/Dropdown/{DropdownSelectedItemsView.js → DropdownSelectedItemsContainer.js} +41 -46
  10. package/lib/commonjs/components/Dropdown/DropdownSelectedItemsContainer.js.map +1 -0
  11. package/lib/commonjs/components/List/DropdownFlatList.js +1 -1
  12. package/lib/commonjs/components/List/DropdownListItem.js.map +1 -0
  13. package/lib/commonjs/components/List/DropdownSectionList.js +1 -1
  14. package/lib/commonjs/hooks/use-selection-handler.js +13 -7
  15. package/lib/commonjs/hooks/use-selection-handler.js.map +1 -1
  16. package/lib/commonjs/index.js +13 -6
  17. package/lib/commonjs/index.js.map +1 -1
  18. package/lib/commonjs/styles/colors.js.map +1 -1
  19. package/lib/commonjs/styles/input.js.map +1 -1
  20. package/lib/commonjs/utils/index.js +30 -13
  21. package/lib/commonjs/utils/index.js.map +1 -1
  22. package/lib/module/asset/close.png +0 -0
  23. package/lib/module/components/CheckBox/index.js +11 -8
  24. package/lib/module/components/CheckBox/index.js.map +1 -1
  25. package/lib/module/components/Dropdown/Dropdown.js +27 -12
  26. package/lib/module/components/Dropdown/Dropdown.js.map +1 -1
  27. package/lib/module/components/Dropdown/DropdownSelectedItem.js +46 -0
  28. package/lib/module/components/Dropdown/DropdownSelectedItem.js.map +1 -0
  29. package/lib/module/components/Dropdown/{DropdownSelectedItemsView.js → DropdownSelectedItemsContainer.js} +42 -47
  30. package/lib/module/components/Dropdown/DropdownSelectedItemsContainer.js.map +1 -0
  31. package/lib/module/components/List/DropdownFlatList.js +1 -1
  32. package/lib/module/components/List/DropdownFlatList.js.map +1 -1
  33. package/lib/module/components/List/DropdownListItem.js.map +1 -0
  34. package/lib/module/components/List/DropdownSectionList.js +1 -1
  35. package/lib/module/components/List/DropdownSectionList.js.map +1 -1
  36. package/lib/module/hooks/use-selection-handler.js +13 -7
  37. package/lib/module/hooks/use-selection-handler.js.map +1 -1
  38. package/lib/module/index.js +14 -7
  39. package/lib/module/index.js.map +1 -1
  40. package/lib/module/styles/colors.js.map +1 -1
  41. package/lib/module/styles/input.js.map +1 -1
  42. package/lib/module/utils/index.js +27 -11
  43. package/lib/module/utils/index.js.map +1 -1
  44. package/lib/typescript/src/components/CheckBox/index.d.ts.map +1 -1
  45. package/lib/typescript/src/components/Dropdown/Dropdown.d.ts +3 -1
  46. package/lib/typescript/src/components/Dropdown/Dropdown.d.ts.map +1 -1
  47. package/lib/typescript/src/components/Dropdown/DropdownSelectedItem.d.ts +16 -0
  48. package/lib/typescript/src/components/Dropdown/DropdownSelectedItem.d.ts.map +1 -0
  49. package/lib/typescript/src/components/Dropdown/DropdownSelectedItemsContainer.d.ts +16 -0
  50. package/lib/typescript/src/components/Dropdown/DropdownSelectedItemsContainer.d.ts.map +1 -0
  51. package/lib/typescript/src/components/List/DropdownListItem.d.ts.map +1 -0
  52. package/lib/typescript/src/hooks/use-selection-handler.d.ts +2 -1
  53. package/lib/typescript/src/hooks/use-selection-handler.d.ts.map +1 -1
  54. package/lib/typescript/src/index.d.ts +1 -0
  55. package/lib/typescript/src/index.d.ts.map +1 -1
  56. package/lib/typescript/src/styles/colors.d.ts +10 -1
  57. package/lib/typescript/src/styles/colors.d.ts.map +1 -1
  58. package/lib/typescript/src/styles/input.d.ts +23 -1
  59. package/lib/typescript/src/styles/input.d.ts.map +1 -1
  60. package/lib/typescript/src/types/index.types.d.ts +13 -6
  61. package/lib/typescript/src/types/index.types.d.ts.map +1 -1
  62. package/lib/typescript/src/utils/index.d.ts +5 -4
  63. package/lib/typescript/src/utils/index.d.ts.map +1 -1
  64. package/package.json +5 -5
  65. package/src/asset/close.png +0 -0
  66. package/src/components/CheckBox/index.tsx +16 -11
  67. package/src/components/Dropdown/Dropdown.tsx +29 -10
  68. package/src/components/Dropdown/DropdownSelectedItem.tsx +78 -0
  69. package/src/components/Dropdown/DropdownSelectedItemsContainer.tsx +164 -0
  70. package/src/components/List/DropdownFlatList.tsx +1 -1
  71. package/src/components/List/DropdownSectionList.tsx +1 -1
  72. package/src/hooks/use-selection-handler.ts +20 -7
  73. package/src/index.tsx +12 -12
  74. package/src/styles/colors.ts +1 -1
  75. package/src/styles/input.ts +1 -1
  76. package/src/types/index.types.ts +14 -6
  77. package/src/utils/index.ts +55 -23
  78. package/lib/commonjs/components/Dropdown/DropdownListItem.js.map +0 -1
  79. package/lib/commonjs/components/Dropdown/DropdownSelectedItemsView.js.map +0 -1
  80. package/lib/module/components/Dropdown/DropdownListItem.js.map +0 -1
  81. package/lib/module/components/Dropdown/DropdownSelectedItemsView.js.map +0 -1
  82. package/lib/typescript/src/components/Dropdown/DropdownListItem.d.ts.map +0 -1
  83. package/lib/typescript/src/components/Dropdown/DropdownSelectedItemsView.d.ts +0 -4
  84. package/lib/typescript/src/components/Dropdown/DropdownSelectedItemsView.d.ts.map +0 -1
  85. package/src/components/Dropdown/DropdownSelectedItemsView.tsx +0 -134
  86. /package/lib/commonjs/components/{Dropdown → List}/DropdownListItem.js +0 -0
  87. /package/lib/module/components/{Dropdown → List}/DropdownListItem.js +0 -0
  88. /package/lib/typescript/src/components/{Dropdown → List}/DropdownListItem.d.ts +0 -0
  89. /package/src/components/{Dropdown → List}/DropdownListItem.tsx +0 -0
@@ -1,8 +1,11 @@
1
1
  import React from 'react';
2
- import { View, Text, StyleSheet } from 'react-native';
3
- import DropdownSelectedItemsView from './DropdownSelectedItemsView';
2
+ import { View, Text, StyleSheet, Image, TouchableOpacity } from 'react-native';
3
+ import DropdownSelectedItemsContainer, {
4
+ DropdownSelectedItemsContainerProps,
5
+ } from './DropdownSelectedItemsContainer';
4
6
  import { colors } from '../../styles/colors';
5
7
  import { typography } from '../../styles/typography';
8
+ import { TDropdownInputProps } from 'src/types/index.types';
6
9
 
7
10
  const Dropdown = ({
8
11
  testID,
@@ -10,12 +13,14 @@ const Dropdown = ({
10
13
  placeholder,
11
14
  helperText,
12
15
  error,
13
- labelsOfSelectedItems,
16
+ selectionData,
14
17
  openModal,
15
- closeModal,
16
18
  isMultiple,
17
19
  selectedItem,
18
20
  selectedItems,
21
+ optionLabel,
22
+ optionValue,
23
+ selectedItemsControls,
19
24
  dropdownIcon,
20
25
  labelStyle,
21
26
  dropdownStyle,
@@ -30,7 +35,8 @@ const Dropdown = ({
30
35
  primaryColor,
31
36
  disabled,
32
37
  setIndexOfSelectedItem,
33
- }: any) => {
38
+ handleMultipleSelections,
39
+ }: TDropdownInputProps & DropdownSelectedItemsContainerProps) => {
34
40
  return (
35
41
  <View
36
42
  style={[styles.dropdownInputContainer, dropdownContainerStyle]}
@@ -42,18 +48,17 @@ const Dropdown = ({
42
48
  <Text style={[styles.label, labelStyle]}>{label}</Text>
43
49
  )}
44
50
 
45
- <DropdownSelectedItemsView
51
+ <DropdownSelectedItemsContainer
46
52
  placeholder={placeholder}
47
53
  error={error}
48
- labelsOfSelectedItems={labelsOfSelectedItems}
54
+ selectionData={selectionData}
49
55
  openModal={openModal}
50
- closeModal={closeModal}
51
56
  isMultiple={isMultiple}
52
57
  selectedItem={selectedItem}
53
58
  selectedItems={selectedItems}
54
- dropdownIcon={dropdownIcon}
59
+ optionLabel={optionLabel}
60
+ optionValue={optionValue}
55
61
  dropdownStyle={dropdownStyle}
56
- dropdownIconStyle={dropdownIconStyle}
57
62
  selectedItemStyle={selectedItemStyle}
58
63
  multipleSelectedItemStyle={multipleSelectedItemStyle}
59
64
  dropdownErrorStyle={dropdownErrorStyle}
@@ -61,6 +66,8 @@ const Dropdown = ({
61
66
  disabled={disabled}
62
67
  placeholderStyle={placeholderStyle}
63
68
  setIndexOfSelectedItem={setIndexOfSelectedItem}
69
+ handleMultipleSelections={handleMultipleSelections}
70
+ selectedItemsControls={selectedItemsControls}
64
71
  />
65
72
 
66
73
  {error && error !== '' && (
@@ -72,6 +79,17 @@ const Dropdown = ({
72
79
  {helperText}
73
80
  </Text>
74
81
  )}
82
+
83
+ {/* Trailing Icon */}
84
+ <TouchableOpacity
85
+ style={[styles.iconStyle, dropdownIconStyle]}
86
+ onPress={() => openModal()}
87
+ testID="dropdown-trailing-icon"
88
+ >
89
+ {dropdownIcon || (
90
+ <Image source={require('../../asset/arrow-down.png')} />
91
+ )}
92
+ </TouchableOpacity>
75
93
  </View>
76
94
  );
77
95
  };
@@ -82,6 +100,7 @@ const styles = StyleSheet.create({
82
100
  helper: { marginTop: 8, color: colors.primary, ...typography.caption },
83
101
  dropdownInputContainer: { marginBottom: 23, width: '100%' },
84
102
  blackText: { color: colors.black },
103
+ iconStyle: { position: 'absolute', right: 25, top: 60 },
85
104
  });
86
105
 
87
106
  export default Dropdown;
@@ -0,0 +1,78 @@
1
+ import React, { ReactNode } from 'react';
2
+ import {
3
+ Text,
4
+ Pressable,
5
+ StyleSheet,
6
+ Image,
7
+ TouchableOpacity,
8
+ ImageStyle,
9
+ ViewStyle,
10
+ TextStyle,
11
+ } from 'react-native';
12
+ import { extractTextStylesFromArray } from '../../utils';
13
+
14
+ export interface DropdownSelectedItemProps {
15
+ onPress: () => void;
16
+ style?: (TextStyle | ViewStyle)[];
17
+ label: string | ReactNode;
18
+ removeItemIcon?: ReactNode;
19
+ onRemoveItem?: () => void;
20
+ showRemoveIcon?: boolean;
21
+ disabled: boolean;
22
+ closeIconStyles?: ImageStyle;
23
+ testId?: string;
24
+ }
25
+
26
+ const DropdownSelectedItem = ({
27
+ onPress,
28
+ style,
29
+ label,
30
+ removeItemIcon,
31
+ onRemoveItem,
32
+ showRemoveIcon,
33
+ closeIconStyles,
34
+ testId,
35
+ disabled,
36
+ ...rest
37
+ }: DropdownSelectedItemProps) => {
38
+ return (
39
+ <TouchableOpacity
40
+ onPress={() => onPress()}
41
+ {...rest}
42
+ style={[styles.dropdownInputContent, ...(style ?? [])]}
43
+ testID={`dropdown-selected-item-${testId}`}
44
+ >
45
+ <Text style={extractTextStylesFromArray(style)}>{label}</Text>
46
+
47
+ {showRemoveIcon && (
48
+ <Pressable
49
+ onPress={disabled ? null : () => onRemoveItem?.()}
50
+ testID={`dropdown-selected-item-remove-icon-${testId}`}
51
+ >
52
+ {removeItemIcon || (
53
+ <Image
54
+ source={require('../../asset/close.png')}
55
+ style={[styles.removeItemIcon, closeIconStyles]}
56
+ />
57
+ )}
58
+ </Pressable>
59
+ )}
60
+ </TouchableOpacity>
61
+ );
62
+ };
63
+
64
+ const styles = StyleSheet.create({
65
+ dropdownInputContent: {
66
+ display: 'flex',
67
+ justifyContent: 'center',
68
+ alignItems: 'center',
69
+ flexDirection: 'row',
70
+ gap: 8,
71
+ },
72
+ removeItemIcon: {
73
+ height: 10,
74
+ width: 10,
75
+ },
76
+ });
77
+
78
+ export default DropdownSelectedItem;
@@ -0,0 +1,164 @@
1
+ import React from 'react';
2
+ import {
3
+ View,
4
+ Pressable,
5
+ ScrollView,
6
+ StyleSheet,
7
+ TextStyle,
8
+ } from 'react-native';
9
+ import { colors } from '../../styles/colors';
10
+ import { inputStyles } from '../../styles/input';
11
+ import DropdownSelectedItem from './DropdownSelectedItem';
12
+ import {
13
+ TDropdownInputProps,
14
+ TFlatListItem,
15
+ TSelectedItem,
16
+ TSelectedItemsControls,
17
+ TSelectedItemWithReactComponent,
18
+ } from 'src/types/index.types';
19
+
20
+ export interface DropdownSelectedItemsContainerProps {
21
+ openModal: () => void;
22
+ selectedItem: TSelectedItemWithReactComponent;
23
+ selectedItems: TSelectedItemWithReactComponent[];
24
+ optionLabel: string;
25
+ optionValue: string;
26
+ setIndexOfSelectedItem: (label: string) => void;
27
+ selectedItemsControls?: TSelectedItemsControls;
28
+ selectionData: TFlatListItem | TFlatListItem[];
29
+ handleMultipleSelections?: (value: TSelectedItem) => void;
30
+ }
31
+
32
+ const DropdownSelectedItemsContainer = ({
33
+ placeholder,
34
+ error,
35
+ selectionData = [],
36
+ openModal,
37
+ isMultiple,
38
+ selectedItem,
39
+ selectedItems,
40
+ optionLabel,
41
+ optionValue,
42
+ dropdownStyle,
43
+ placeholderStyle = {},
44
+ selectedItemStyle = {},
45
+ multipleSelectedItemStyle = {},
46
+ dropdownErrorStyle,
47
+ primaryColor,
48
+ disabled = false,
49
+ setIndexOfSelectedItem,
50
+ selectedItemsControls,
51
+ handleMultipleSelections,
52
+ }: TDropdownInputProps & DropdownSelectedItemsContainerProps) => {
53
+ const openActions = (label: string) => {
54
+ openModal();
55
+ setIndexOfSelectedItem(label); // immediately scrolls to list item with the specified label when modal
56
+ };
57
+
58
+ return (
59
+ <Pressable
60
+ onPress={() => openModal()}
61
+ style={({ pressed }) => [
62
+ pressed && {
63
+ ...inputStyles.inputFocusState,
64
+ borderColor: primaryColor,
65
+ },
66
+ { ...inputStyles.input, ...dropdownStyle },
67
+ error && //this must be last
68
+ error !== '' &&
69
+ !pressed && {
70
+ ...inputStyles.inputFocusErrorState,
71
+ ...dropdownErrorStyle,
72
+ },
73
+ ]}
74
+ disabled={disabled}
75
+ aria-disabled={disabled}
76
+ testID="react-native-input-select-dropdown-input-container"
77
+ >
78
+ <ScrollView
79
+ horizontal
80
+ alwaysBounceHorizontal
81
+ showsHorizontalScrollIndicator={false}
82
+ >
83
+ <View
84
+ style={styles.selectedItemsContainer}
85
+ onStartShouldSetResponder={() => true}
86
+ >
87
+ {isMultiple ? (
88
+ (selectionData as TFlatListItem[])?.map((data, i) => {
89
+ const label = data[optionLabel];
90
+ const value = data[optionValue];
91
+
92
+ return (
93
+ <DropdownSelectedItem
94
+ onPress={() => openActions(label as string)}
95
+ key={`react-native-input-select-list-item-${Math.random()}-${i}`}
96
+ style={[
97
+ styles.selectedItems,
98
+ { backgroundColor: primaryColor },
99
+ multipleSelectedItemStyle,
100
+ ]}
101
+ closeIconStyles={{
102
+ tintColor:
103
+ (multipleSelectedItemStyle as TextStyle)?.color ||
104
+ styles.selectedItems.color,
105
+ }}
106
+ label={label}
107
+ disabled={disabled || (data.disabled as boolean)}
108
+ showRemoveIcon={selectedItemsControls?.showRemoveIcon || true}
109
+ removeItemIcon={selectedItemsControls?.removeItemIcon}
110
+ onRemoveItem={() => {
111
+ handleMultipleSelections?.(value as TSelectedItem);
112
+ selectedItemsControls?.onRemoveItem?.(); //user defined control
113
+ }}
114
+ testId={`${i}`}
115
+ />
116
+ );
117
+ })
118
+ ) : (
119
+ <DropdownSelectedItem
120
+ onPress={() =>
121
+ openActions(
122
+ String((selectionData as TFlatListItem)?.[optionLabel] ?? '')
123
+ )
124
+ }
125
+ style={[styles.blackText, selectedItemStyle]}
126
+ label={(selectionData as TFlatListItem)[optionLabel] as string}
127
+ disabled={disabled}
128
+ />
129
+ )}
130
+
131
+ {/* Placeholder */}
132
+ {selectedItem === '' && selectedItems?.length === 0 && (
133
+ <DropdownSelectedItem
134
+ onPress={() => openModal()}
135
+ style={[styles.blackText, placeholderStyle]}
136
+ label={placeholder ?? 'Select an option'}
137
+ disabled={disabled}
138
+ />
139
+ )}
140
+ </View>
141
+ </ScrollView>
142
+ </Pressable>
143
+ );
144
+ };
145
+
146
+ const styles = StyleSheet.create({
147
+ selectedItemsContainer: {
148
+ flexDirection: 'row',
149
+ flexWrap: 'nowrap',
150
+ alignItems: 'center',
151
+ },
152
+ selectedItems: {
153
+ color: colors.white,
154
+ paddingHorizontal: 10,
155
+ paddingVertical: 5,
156
+ borderRadius: 10,
157
+ backgroundColor: colors.primary,
158
+ marginRight: 10,
159
+ overflow: 'hidden',
160
+ },
161
+ blackText: { color: colors.black },
162
+ });
163
+
164
+ export default DropdownSelectedItemsContainer;
@@ -1,7 +1,7 @@
1
1
  /* eslint-disable react-native/no-inline-styles */
2
2
  import React, { useEffect, useRef } from 'react';
3
3
  import { FlatList, FlatListProps, StyleSheet } from 'react-native';
4
- import DropdownListItem from '../Dropdown/DropdownListItem';
4
+ import DropdownListItem from './DropdownListItem';
5
5
  import { ItemSeparatorComponent, ListEmptyComponent } from '../Others';
6
6
  import { TFlatList } from '../../types/index.types';
7
7
 
@@ -1,7 +1,7 @@
1
1
  /* eslint-disable react-native/no-inline-styles */
2
2
  import React, { useEffect, useState, useRef } from 'react';
3
3
  import { SectionList, StyleSheet } from 'react-native';
4
- import DropdownListItem from '../Dropdown/DropdownListItem';
4
+ import DropdownListItem from './DropdownListItem';
5
5
  import {
6
6
  ItemSeparatorComponent,
7
7
  ListEmptyComponent,
@@ -4,6 +4,7 @@ import { TSelectedItem } from '../types/index.types';
4
4
  interface UseSelectionHandlerProps {
5
5
  initialSelectedValue: TSelectedItem | TSelectedItem[]; // Can be a single value or an array
6
6
  isMultiple: boolean;
7
+ minSelectableItems?: number;
7
8
  maxSelectableItems?: number;
8
9
  onValueChange: (selectedItems: TSelectedItem | TSelectedItem[]) => void;
9
10
  closeModal: () => void;
@@ -13,12 +14,13 @@ interface UseSelectionHandlerProps {
13
14
  export const useSelectionHandler = ({
14
15
  initialSelectedValue,
15
16
  isMultiple,
17
+ minSelectableItems = 0,
16
18
  maxSelectableItems,
17
19
  onValueChange,
18
20
  closeModal,
19
21
  autoCloseOnSelect,
20
22
  }: UseSelectionHandlerProps) => {
21
- // Initialize state based on whether it's multiple selection or not
23
+ // Initialize state based on whether it is multiple selection or not
22
24
  const [selectedItem, setSelectedItem] = useState<TSelectedItem>(
23
25
  isMultiple ? '' : (initialSelectedValue as TSelectedItem)
24
26
  );
@@ -29,8 +31,11 @@ export const useSelectionHandler = ({
29
31
  const handleSingleSelection = useCallback(
30
32
  (value: TSelectedItem) => {
31
33
  if (selectedItem === value) {
32
- setSelectedItem('');
33
- onValueChange(''); // Send null to parent when deselected
34
+ // Deselect item if minSelectableItems is not reached
35
+ if (minSelectableItems === 0) {
36
+ setSelectedItem('');
37
+ onValueChange(''); // Send null to parent when deselected
38
+ }
34
39
  } else {
35
40
  setSelectedItem(value);
36
41
  onValueChange(value); // Send selected value to parent
@@ -40,7 +45,13 @@ export const useSelectionHandler = ({
40
45
  }
41
46
  }
42
47
  },
43
- [selectedItem, onValueChange, autoCloseOnSelect, closeModal]
48
+ [
49
+ selectedItem,
50
+ minSelectableItems,
51
+ onValueChange,
52
+ autoCloseOnSelect,
53
+ closeModal,
54
+ ]
44
55
  );
45
56
 
46
57
  const handleMultipleSelections = useCallback(
@@ -49,8 +60,10 @@ export const useSelectionHandler = ({
49
60
  let selectedValues = [...prevVal];
50
61
 
51
62
  if (selectedValues.includes(value)) {
52
- // Remove item
53
- selectedValues = selectedValues.filter((item) => item !== value);
63
+ // Only remove item if it doesn't drop below the minimum required
64
+ if (selectedValues.length > minSelectableItems) {
65
+ selectedValues = selectedValues.filter((item) => item !== value);
66
+ }
54
67
  } else {
55
68
  // Add item
56
69
  if (
@@ -66,7 +79,7 @@ export const useSelectionHandler = ({
66
79
  return selectedValues;
67
80
  });
68
81
  },
69
- [maxSelectableItems, onValueChange]
82
+ [minSelectableItems, maxSelectableItems, onValueChange]
70
83
  );
71
84
 
72
85
  // Return the relevant state and handlers
package/src/index.tsx CHANGED
@@ -18,7 +18,7 @@ import type {
18
18
  DropdownSelectHandle,
19
19
  TSelectedItem,
20
20
  } from './types/index.types';
21
- import { extractPropertyFromArray, getLabelsOfSelectedItems } from './utils';
21
+ import { extractPropertyFromArray, getSelectionsData } from './utils';
22
22
  import {
23
23
  useSelectionHandler,
24
24
  useModal,
@@ -63,7 +63,9 @@ export const DropdownSelect = forwardRef<DropdownSelectHandle, DropdownProps>(
63
63
  searchControls,
64
64
  modalControls,
65
65
  checkboxControls,
66
+ selectedItemsControls,
66
67
  autoCloseOnSelect = true,
68
+ minSelectableItems,
67
69
  maxSelectableItems,
68
70
  ...rest
69
71
  },
@@ -138,6 +140,7 @@ export const DropdownSelect = forwardRef<DropdownSelectHandle, DropdownProps>(
138
140
  } = useSelectionHandler({
139
141
  initialSelectedValue: selectedValue,
140
142
  isMultiple,
143
+ minSelectableItems,
141
144
  maxSelectableItems,
142
145
  onValueChange,
143
146
  closeModal: () => closeModal(),
@@ -149,14 +152,9 @@ export const DropdownSelect = forwardRef<DropdownSelectHandle, DropdownProps>(
149
152
  ? setSelectedItems(selectedValue as TSelectedItem[])
150
153
  : setSelectedItem(selectedValue as TSelectedItem);
151
154
 
152
- return () => {};
153
- }, [
154
- selectedValue,
155
- setSelectedItems,
156
- setSelectedItem,
157
- isMultiple,
158
- onValueChange,
159
- ]);
155
+ // setSelectedItems already updates selectedValue, so omit it from dependency array to avoid infinite loop
156
+ // eslint-disable-next-line react-hooks/exhaustive-deps
157
+ }, [setSelectedItems, setSelectedItem, isMultiple, onValueChange]);
160
158
 
161
159
  /*===========================================
162
160
  * List type
@@ -198,18 +196,19 @@ export const DropdownSelect = forwardRef<DropdownSelectHandle, DropdownProps>(
198
196
  placeholder={placeholder}
199
197
  helperText={helperText}
200
198
  error={error}
201
- labelsOfSelectedItems={getLabelsOfSelectedItems({
199
+ selectionData={getSelectionsData({
202
200
  isMultiple,
203
- optionLabel,
204
201
  optionValue,
205
202
  selectedItem,
206
203
  selectedItems,
207
204
  modifiedOptions,
208
205
  })}
206
+ optionLabel={optionLabel}
207
+ optionValue={optionValue}
209
208
  selectedItem={selectedItem}
210
209
  selectedItems={selectedItems}
210
+ selectedItemsControls={selectedItemsControls}
211
211
  openModal={() => openModal()}
212
- closeModal={() => closeModal()}
213
212
  labelStyle={labelStyle}
214
213
  dropdownIcon={dropdownIcon}
215
214
  dropdownStyle={dropdownStyle}
@@ -225,6 +224,7 @@ export const DropdownSelect = forwardRef<DropdownSelectHandle, DropdownProps>(
225
224
  disabled={disabled}
226
225
  placeholderStyle={placeholderStyle}
227
226
  setIndexOfSelectedItem={setIndexOfSelectedItem}
227
+ handleMultipleSelections={handleMultipleSelections}
228
228
  {...rest}
229
229
  />
230
230
  <CustomModal
@@ -1,4 +1,4 @@
1
- export const colors: any = {
1
+ export const colors = {
2
2
  primary: 'green',
3
3
  red: '#FA4169',
4
4
  black: '#000000',
@@ -1,7 +1,7 @@
1
1
  import { StyleSheet } from 'react-native';
2
2
  import { colors } from './colors';
3
3
 
4
- export const inputStyles: any = StyleSheet.create({
4
+ export const inputStyles = StyleSheet.create({
5
5
  input: {
6
6
  paddingVertical: 18,
7
7
  paddingHorizontal: 23,
@@ -13,18 +13,19 @@ export type DropdownProps = CommonDropdownProps &
13
13
  TListProps;
14
14
 
15
15
  export type CommonDropdownProps = {
16
- testID?: string;
17
- label?: string;
18
16
  options: TFlatList | TSectionList;
19
- optionLabel?: string;
20
- optionValue?: string;
21
17
  onValueChange: (selectedItems: TSelectedItem | TSelectedItem[]) => void;
22
18
  selectedValue: TSelectedItem | TSelectedItem[];
19
+ optionLabel?: string;
20
+ optionValue?: string;
23
21
  autoCloseOnSelect?: boolean;
22
+ minSelectableItems?: number;
24
23
  maxSelectableItems?: number;
25
24
  };
26
25
 
27
26
  export type TDropdownInputProps = {
27
+ testID?: string;
28
+ label?: string;
28
29
  placeholder?: string;
29
30
  error?: string;
30
31
  helperText?: string;
@@ -38,8 +39,8 @@ export type TDropdownInputProps = {
38
39
  dropdownErrorStyle?: ViewStyle;
39
40
  dropdownErrorTextStyle?: TextStyle;
40
41
  dropdownHelperTextStyle?: TextStyle;
41
- selectedItemStyle?: TextStyle;
42
- multipleSelectedItemStyle?: TextStyle;
42
+ selectedItemStyle?: TextStyle | ViewStyle;
43
+ multipleSelectedItemStyle?: TextStyle | ViewStyle;
43
44
  primaryColor?: ColorValue;
44
45
  disabled?: boolean;
45
46
  placeholderStyle?: TextStyle;
@@ -50,6 +51,7 @@ type TControls = {
50
51
  checkboxControls?: TCheckboxControls;
51
52
  modalControls?: TCustomModalControls;
52
53
  listControls?: TListControls;
54
+ selectedItemsControls?: TSelectedItemsControls;
53
55
  };
54
56
 
55
57
  type TSearchControls = {
@@ -95,6 +97,12 @@ type TListControls = {
95
97
  keyboardShouldPersistTaps?: 'always' | 'never' | 'handled';
96
98
  };
97
99
 
100
+ export type TSelectedItemsControls = {
101
+ showRemoveIcon?: boolean;
102
+ removeItemIcon?: React.ReactNode;
103
+ onRemoveItem?: () => void;
104
+ };
105
+
98
106
  export type TSelectedItem = string | number | boolean | undefined;
99
107
  export type TSelectedItemWithReactComponent =
100
108
  | TSelectedItem
@@ -1,10 +1,6 @@
1
+ import { TextStyle, ViewStyle } from 'react-native';
1
2
  import { TSelectedItem } from '../types/index.types';
2
- import {
3
- TFlatList,
4
- TFlatListItem,
5
- TSectionList,
6
- TSelectedItemWithReactComponent,
7
- } from '../types/index.types';
3
+ import { TFlatList, TFlatListItem, TSectionList } from '../types/index.types';
8
4
 
9
5
  export const extractPropertyFromArray = (arr: any[], property: string) => {
10
6
  let extractedValue = arr?.map((item: any) => item[property]);
@@ -31,40 +27,76 @@ export const isSectionList = (options: TFlatList | TSectionList): boolean => {
31
27
  * @description get the labels of the items that were selected from the options array for either multiple or single selections
32
28
  * @returns
33
29
  */
34
- export const getLabelsOfSelectedItems = ({
30
+ export const getSelectionsData = ({
35
31
  isMultiple,
36
- optionLabel,
37
32
  optionValue,
38
33
  selectedItem,
39
34
  selectedItems,
40
35
  modifiedOptions,
41
36
  }: {
42
37
  isMultiple: boolean;
43
- optionLabel: string;
44
38
  optionValue: string;
45
39
  selectedItem: TSelectedItem;
46
40
  selectedItems: TSelectedItem[];
47
41
  modifiedOptions: TFlatList;
48
- }) => {
42
+ }): TFlatListItem | TFlatListItem[] => {
49
43
  // Multiple select
50
- if (isMultiple && Array.isArray(selectedItems)) {
51
- let selectedLabels: TSelectedItemWithReactComponent[] = [];
44
+ if (isMultiple) {
45
+ let currentSelections: TFlatListItem[] = [];
52
46
 
53
- selectedItems?.forEach((element: TSelectedItem) => {
54
- let selectedItemLabel = modifiedOptions?.find(
55
- (item: TFlatListItem) => item[optionValue] === element
56
- )?.[optionLabel];
47
+ Array.isArray(selectedItems) &&
48
+ selectedItems.forEach((element: TSelectedItem) => {
49
+ const currentSelection = modifiedOptions?.find(
50
+ (item: TFlatListItem) => item[optionValue] === element
51
+ );
57
52
 
58
- if (selectedItemLabel !== '') {
59
- selectedLabels.push(selectedItemLabel);
60
- }
61
- });
62
- return selectedLabels;
53
+ // Only push if currentSelection is defined and is of the correct type
54
+ if (currentSelection) {
55
+ currentSelections.push(currentSelection);
56
+ }
57
+ });
58
+
59
+ return currentSelections;
63
60
  }
64
61
 
65
62
  // Single select
66
- let selectedItemLabel = modifiedOptions?.find(
63
+ let current = modifiedOptions?.find(
67
64
  (item: TFlatListItem) => item[optionValue] === selectedItem
68
65
  );
69
- return selectedItemLabel?.[optionLabel];
66
+ return current ? current : {};
67
+ };
68
+
69
+ const textStyleKeys = [
70
+ 'color',
71
+ 'fontSize',
72
+ 'fontFamily',
73
+ 'fontWeight',
74
+ 'fontStyle',
75
+ 'textAlign',
76
+ 'lineHeight',
77
+ 'textDecorationLine',
78
+ 'textDecorationStyle',
79
+ 'textDecorationColor',
80
+ 'textShadowColor',
81
+ 'textShadowOffset',
82
+ 'textShadowRadius',
83
+ 'letterSpacing',
84
+ 'textTransform',
85
+ ];
86
+
87
+ export const extractTextStylesFromArray = (
88
+ styleArray: (ViewStyle & TextStyle)[] = []
89
+ ) => {
90
+ const extractedStyles: Record<string, any> = {};
91
+ for (const styleObject of styleArray) {
92
+ if (styleObject && typeof styleObject === 'object') {
93
+ // Ensure it's a valid style object
94
+ for (const prop in styleObject) {
95
+ if (textStyleKeys.includes(prop)) {
96
+ extractedStyles[prop] = (styleObject as Record<string, any>)[prop];
97
+ }
98
+ }
99
+ }
100
+ }
101
+ return extractedStyles;
70
102
  };