@riebel/react-native-multiple-select 0.6.0 → 0.6.1
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 +26 -2
- package/dist/MultiSelect.js +11 -9
- package/dist/types.d.ts +1 -1
- package/package.json +1 -1
- package/src/MultiSelect.tsx +20 -8
- package/src/types.ts +2 -1
package/README.md
CHANGED
|
@@ -9,13 +9,13 @@
|
|
|
9
9
|
## Installation
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
|
-
npm install react-native-multiple-select
|
|
12
|
+
npm install @riebel/react-native-multiple-select
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
or with yarn:
|
|
16
16
|
|
|
17
17
|
```bash
|
|
18
|
-
yarn add react-native-multiple-select
|
|
18
|
+
yarn add @riebel/react-native-multiple-select
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
### Peer dependencies
|
|
@@ -246,6 +246,30 @@ import type {
|
|
|
246
246
|
} from 'react-native-multiple-select'
|
|
247
247
|
```
|
|
248
248
|
|
|
249
|
+
### Type assertions
|
|
250
|
+
|
|
251
|
+
**`iconComponent`** — Icon libraries such as `@expo/vector-icons` type their `name` prop as a narrow union of string literals, which conflicts with `IconComponentType`'s `name: string`. Cast the component to silence this:
|
|
252
|
+
|
|
253
|
+
```tsx
|
|
254
|
+
import MaterialCommunityIcons from '@expo/vector-icons/MaterialCommunityIcons'
|
|
255
|
+
import type { IconComponentType } from '@riebel/react-native-multiple-select'
|
|
256
|
+
|
|
257
|
+
<MultiSelect iconComponent={MaterialCommunityIcons as IconComponentType} ... />
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
**`items`** — `MultiSelectItem` has an index signature (`[key: string]: unknown`). Custom interfaces without that signature are not directly assignable, even if all properties match at runtime. Use a double assertion:
|
|
261
|
+
|
|
262
|
+
```tsx
|
|
263
|
+
interface MyItem {
|
|
264
|
+
id: string
|
|
265
|
+
label: string
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
const items: MyItem[] = [...]
|
|
269
|
+
|
|
270
|
+
<MultiSelect items={items as unknown as MultiSelectItem[]} ... />
|
|
271
|
+
```
|
|
272
|
+
|
|
249
273
|
## Contributing
|
|
250
274
|
|
|
251
275
|
Contributions are **welcome** and will be fully **credited**.
|
package/dist/MultiSelect.js
CHANGED
|
@@ -98,7 +98,7 @@ const MultiSelect = forwardRef(({ single = false, selectedItems = [], items, ico
|
|
|
98
98
|
.split(' ')
|
|
99
99
|
.filter((word) => word.length)
|
|
100
100
|
.join('-');
|
|
101
|
-
const newItems = [...items, { [uniqueKey]: newItemId,
|
|
101
|
+
const newItems = [...items, { [uniqueKey]: newItemId, [displayKey]: newItemName }];
|
|
102
102
|
const newSelectedItems = [...selectedItems, newItemId];
|
|
103
103
|
onAddItem?.(newItems);
|
|
104
104
|
onSelectedItemsChange(newSelectedItems);
|
|
@@ -108,6 +108,7 @@ const MultiSelect = forwardRef(({ single = false, selectedItems = [], items, ico
|
|
|
108
108
|
searchTerm,
|
|
109
109
|
items,
|
|
110
110
|
uniqueKey,
|
|
111
|
+
displayKey,
|
|
111
112
|
selectedItems,
|
|
112
113
|
onAddItem,
|
|
113
114
|
onSelectedItemsChange,
|
|
@@ -156,7 +157,7 @@ const MultiSelect = forwardRef(({ single = false, selectedItems = [], items, ico
|
|
|
156
157
|
fontFamily ? { fontFamily } : {}
|
|
157
158
|
], numberOfLines: 1, children: label }), _jsx(TouchableOpacity, { onPress: () => {
|
|
158
159
|
removeItem(item);
|
|
159
|
-
}, children: _jsx(Icon, { name: names.close,
|
|
160
|
+
}, children: _jsx(Icon, { name: names.close, size: 22, color: tagRemoveIconColor, style: styles.tagRemoveIcon }) })] }, getItemKey(item)));
|
|
160
161
|
});
|
|
161
162
|
}, [
|
|
162
163
|
Icon,
|
|
@@ -196,7 +197,7 @@ const MultiSelect = forwardRef(({ single = false, selectedItems = [], items, ico
|
|
|
196
197
|
styles.rowItemText,
|
|
197
198
|
itemStyle(item),
|
|
198
199
|
item.disabled ? styles.disabledText : {}
|
|
199
|
-
], children: getDisplayValue(item, displayKey) }), itemSelected(item) ? (_jsx(Icon, { name: names.check,
|
|
200
|
+
], children: getDisplayValue(item, displayKey) }), itemSelected(item) ? (_jsx(Icon, { name: names.check, size: 20, color: selectedItemIconColor, style: styles.checkIcon })) : null] }) }) })), [
|
|
200
201
|
Icon,
|
|
201
202
|
names,
|
|
202
203
|
toggleItem,
|
|
@@ -212,7 +213,7 @@ const MultiSelect = forwardRef(({ single = false, selectedItems = [], items, ico
|
|
|
212
213
|
styles.rowItemText,
|
|
213
214
|
itemStyle(item),
|
|
214
215
|
item.disabled ? styles.disabledText : {}
|
|
215
|
-
], children: ["Add ", getDisplayValue(item,
|
|
216
|
+
], children: ["Add ", getDisplayValue(item, displayKey), " (tap or press return)"] }) }) }) })), [addItem, itemStyle, displayKey]);
|
|
216
217
|
const renderItems = useCallback(() => {
|
|
217
218
|
let renderList = searchTerm ? filterItems(searchTerm) : items;
|
|
218
219
|
if (removeSelected) {
|
|
@@ -222,14 +223,14 @@ const MultiSelect = forwardRef(({ single = false, selectedItems = [], items, ico
|
|
|
222
223
|
let searchTermMatch = false;
|
|
223
224
|
if (renderList.length) {
|
|
224
225
|
itemList = (_jsx(FlatList, { data: renderList, extraData: selectedItems, keyExtractor: (_item, index) => index.toString(), renderItem: (rowData) => getRow(rowData.item), ...flatListProps, nestedScrollEnabled: true }));
|
|
225
|
-
searchTermMatch = renderList.some((item) => item
|
|
226
|
+
searchTermMatch = renderList.some((item) => getDisplayValue(item, displayKey) === searchTerm);
|
|
226
227
|
}
|
|
227
228
|
else if (!canAddItems) {
|
|
228
229
|
itemList = (_jsx(View, { style: styles.noItemsRow, children: _jsx(Text, { style: [styles.noItemsText, fontFamily ? { fontFamily } : {}], children: noItemsText }) }));
|
|
229
230
|
}
|
|
230
231
|
let addItemRow = null;
|
|
231
232
|
if (canAddItems && !searchTermMatch && searchTerm.length) {
|
|
232
|
-
addItemRow = getRowNew({
|
|
233
|
+
addItemRow = getRowNew({ [displayKey]: searchTerm });
|
|
233
234
|
}
|
|
234
235
|
return (_jsxs(View, { style: styleListContainer, children: [itemList, addItemRow] }));
|
|
235
236
|
}, [
|
|
@@ -245,9 +246,10 @@ const MultiSelect = forwardRef(({ single = false, selectedItems = [], items, ico
|
|
|
245
246
|
fontFamily,
|
|
246
247
|
noItemsText,
|
|
247
248
|
getRowNew,
|
|
248
|
-
styleListContainer
|
|
249
|
+
styleListContainer,
|
|
250
|
+
displayKey
|
|
249
251
|
]);
|
|
250
|
-
return (_jsx(View, { style: styleMainWrapper, children: selector ? (_jsxs(View, { style: [selectorViewStyle(fixedHeight), styleSelectorContainer], children: [_jsxs(View, { style: [styles.inputGroup, styleInputGroup], children: [resolvedSearchIcon, _jsx(TextInput, { autoFocus: true, onChangeText: handleChangeInput, onSubmitEditing: addItem, placeholder: searchInputPlaceholderText, placeholderTextColor: colorPack.placeholderTextColor, underlineColorAndroid: "transparent", style: [searchInputStyle, styles.searchInputFlex], value: searchTerm, ...textInputProps }), hideSubmitButton && (_jsx(TouchableOpacity, { onPress: submitSelection, children: _jsx(Icon, { name: names.arrowDown, style: [styles.indicator, styles.indicatorPadded, styleIndicator] }) })), !hideDropdown && (_jsx(Icon, { name: names.arrowLeft, size: 20, onPress: clearSelectorCallback, color: colorPack.placeholderTextColor, style: styles.backArrowMargin }))] }), _jsxs(View, { style: styles.selectorContent, children: [_jsx(View, { style: styleItemsContainer, children: renderItems() }), !single && !hideSubmitButton && (_jsx(TouchableOpacity, { onPress: submitSelection, style: [styles.button, { backgroundColor: submitButtonColor }], children: _jsx(Text, { style: [styles.buttonText, fontFamily ? { fontFamily } : {}], children: submitButtonText }) }))] })] })) : (_jsxs(View, { children: [_jsx(View, { style: [styles.dropdownView, styleDropdownMenu], children: _jsx(View, { style: [
|
|
252
|
+
return (_jsx(View, { style: styleMainWrapper, children: selector ? (_jsxs(View, { style: [selectorViewStyle(fixedHeight), styleSelectorContainer], children: [_jsxs(View, { style: [styles.inputGroup, styleInputGroup], children: [resolvedSearchIcon, _jsx(TextInput, { autoFocus: true, onChangeText: handleChangeInput, onSubmitEditing: addItem, placeholder: searchInputPlaceholderText, placeholderTextColor: colorPack.placeholderTextColor, underlineColorAndroid: "transparent", style: [searchInputStyle, styles.searchInputFlex], value: searchTerm, ...textInputProps }), hideSubmitButton && (_jsx(TouchableOpacity, { onPress: submitSelection, children: _jsx(Icon, { name: names.arrowDown, size: 30, color: colorPack.placeholderTextColor, style: [styles.indicator, styles.indicatorPadded, styleIndicator] }) })), !hideDropdown && (_jsx(Icon, { name: names.arrowLeft, size: 20, onPress: clearSelectorCallback, color: colorPack.placeholderTextColor, style: styles.backArrowMargin }))] }), _jsxs(View, { style: styles.selectorContent, children: [_jsx(View, { style: styleItemsContainer, children: renderItems() }), !single && !hideSubmitButton && (_jsx(TouchableOpacity, { onPress: submitSelection, style: [styles.button, { backgroundColor: submitButtonColor }], children: _jsx(Text, { style: [styles.buttonText, fontFamily ? { fontFamily } : {}], children: submitButtonText }) }))] })] })) : (_jsxs(View, { children: [_jsx(View, { style: [styles.dropdownView, styleDropdownMenu], children: _jsx(View, { style: [
|
|
251
253
|
styles.subSection,
|
|
252
254
|
styles.subSectionPadded,
|
|
253
255
|
styleDropdownMenuSubsection
|
|
@@ -272,7 +274,7 @@ const MultiSelect = forwardRef(({ single = false, selectedItems = [], items, ico
|
|
|
272
274
|
color: textColor || colorPack.placeholderTextColor
|
|
273
275
|
},
|
|
274
276
|
styleTextDropdownSelected
|
|
275
|
-
], numberOfLines: 1, children: getSelectLabel() }), _jsx(Icon, { name: hideSubmitButton ? names.arrowRight : names.arrowDown, style: [styles.indicator, styleIndicator] })] }) }) }) }), !single && !hideTags && selectedItems.length ? (_jsx(View, { style: styles.rowWrap, children: displaySelectedItems() })) : null] })) }));
|
|
277
|
+
], numberOfLines: 1, children: getSelectLabel() }), _jsx(Icon, { name: hideSubmitButton ? names.arrowRight : names.arrowDown, size: 30, color: colorPack.placeholderTextColor, style: [styles.indicator, styleIndicator] })] }) }) }) }), !single && !hideTags && selectedItems.length ? (_jsx(View, { style: styles.rowWrap, children: displaySelectedItems() })) : null] })) }));
|
|
276
278
|
});
|
|
277
279
|
MultiSelect.displayName = 'MultiSelect';
|
|
278
280
|
export default MultiSelect;
|
package/dist/types.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export interface IconProps {
|
|
|
7
7
|
style?: StyleProp<TextStyle | ViewStyle>;
|
|
8
8
|
onPress?: () => void;
|
|
9
9
|
}
|
|
10
|
-
export type IconComponentType = ComponentType<IconProps>;
|
|
10
|
+
export type IconComponentType = ComponentType<any> & ComponentType<IconProps>;
|
|
11
11
|
export interface IconNames {
|
|
12
12
|
search?: string;
|
|
13
13
|
close?: string;
|
package/package.json
CHANGED
package/src/MultiSelect.tsx
CHANGED
|
@@ -209,7 +209,7 @@ const MultiSelect = forwardRef<MultiSelectRef, MultiSelectProps>(
|
|
|
209
209
|
.split(' ')
|
|
210
210
|
.filter((word) => word.length)
|
|
211
211
|
.join('-')
|
|
212
|
-
const newItems = [...items, { [uniqueKey]: newItemId,
|
|
212
|
+
const newItems = [...items, { [uniqueKey]: newItemId, [displayKey]: newItemName }]
|
|
213
213
|
const newSelectedItems = [...selectedItems, newItemId]
|
|
214
214
|
onAddItem?.(newItems)
|
|
215
215
|
onSelectedItemsChange(newSelectedItems)
|
|
@@ -219,6 +219,7 @@ const MultiSelect = forwardRef<MultiSelectRef, MultiSelectProps>(
|
|
|
219
219
|
searchTerm,
|
|
220
220
|
items,
|
|
221
221
|
uniqueKey,
|
|
222
|
+
displayKey,
|
|
222
223
|
selectedItems,
|
|
223
224
|
onAddItem,
|
|
224
225
|
onSelectedItemsChange,
|
|
@@ -287,7 +288,9 @@ const MultiSelect = forwardRef<MultiSelectRef, MultiSelectProps>(
|
|
|
287
288
|
>
|
|
288
289
|
<Icon
|
|
289
290
|
name={names.close}
|
|
290
|
-
|
|
291
|
+
size={22}
|
|
292
|
+
color={tagRemoveIconColor}
|
|
293
|
+
style={styles.tagRemoveIcon}
|
|
291
294
|
/>
|
|
292
295
|
</TouchableOpacity>
|
|
293
296
|
</View>
|
|
@@ -371,7 +374,9 @@ const MultiSelect = forwardRef<MultiSelectRef, MultiSelectProps>(
|
|
|
371
374
|
{itemSelected(item) ? (
|
|
372
375
|
<Icon
|
|
373
376
|
name={names.check}
|
|
374
|
-
|
|
377
|
+
size={20}
|
|
378
|
+
color={selectedItemIconColor}
|
|
379
|
+
style={styles.checkIcon}
|
|
375
380
|
/>
|
|
376
381
|
) : null}
|
|
377
382
|
</View>
|
|
@@ -408,13 +413,13 @@ const MultiSelect = forwardRef<MultiSelectRef, MultiSelectProps>(
|
|
|
408
413
|
item.disabled ? styles.disabledText : {}
|
|
409
414
|
]}
|
|
410
415
|
>
|
|
411
|
-
Add {getDisplayValue(item,
|
|
416
|
+
Add {getDisplayValue(item, displayKey)} (tap or press return)
|
|
412
417
|
</Text>
|
|
413
418
|
</View>
|
|
414
419
|
</View>
|
|
415
420
|
</TouchableOpacity>
|
|
416
421
|
),
|
|
417
|
-
[addItem, itemStyle]
|
|
422
|
+
[addItem, itemStyle, displayKey]
|
|
418
423
|
)
|
|
419
424
|
|
|
420
425
|
const renderItems = useCallback(() => {
|
|
@@ -440,7 +445,9 @@ const MultiSelect = forwardRef<MultiSelectRef, MultiSelectProps>(
|
|
|
440
445
|
nestedScrollEnabled
|
|
441
446
|
/>
|
|
442
447
|
)
|
|
443
|
-
searchTermMatch = renderList.some(
|
|
448
|
+
searchTermMatch = renderList.some(
|
|
449
|
+
(item) => getDisplayValue(item, displayKey) === searchTerm
|
|
450
|
+
)
|
|
444
451
|
} else if (!canAddItems) {
|
|
445
452
|
itemList = (
|
|
446
453
|
<View style={styles.noItemsRow}>
|
|
@@ -453,7 +460,7 @@ const MultiSelect = forwardRef<MultiSelectRef, MultiSelectProps>(
|
|
|
453
460
|
|
|
454
461
|
let addItemRow: React.ReactNode = null
|
|
455
462
|
if (canAddItems && !searchTermMatch && searchTerm.length) {
|
|
456
|
-
addItemRow = getRowNew({
|
|
463
|
+
addItemRow = getRowNew({ [displayKey]: searchTerm })
|
|
457
464
|
}
|
|
458
465
|
|
|
459
466
|
return (
|
|
@@ -475,7 +482,8 @@ const MultiSelect = forwardRef<MultiSelectRef, MultiSelectProps>(
|
|
|
475
482
|
fontFamily,
|
|
476
483
|
noItemsText,
|
|
477
484
|
getRowNew,
|
|
478
|
-
styleListContainer
|
|
485
|
+
styleListContainer,
|
|
486
|
+
displayKey
|
|
479
487
|
])
|
|
480
488
|
|
|
481
489
|
return (
|
|
@@ -499,6 +507,8 @@ const MultiSelect = forwardRef<MultiSelectRef, MultiSelectProps>(
|
|
|
499
507
|
<TouchableOpacity onPress={submitSelection}>
|
|
500
508
|
<Icon
|
|
501
509
|
name={names.arrowDown}
|
|
510
|
+
size={30}
|
|
511
|
+
color={colorPack.placeholderTextColor}
|
|
502
512
|
style={[styles.indicator, styles.indicatorPadded, styleIndicator]}
|
|
503
513
|
/>
|
|
504
514
|
</TouchableOpacity>
|
|
@@ -570,6 +580,8 @@ const MultiSelect = forwardRef<MultiSelectRef, MultiSelectProps>(
|
|
|
570
580
|
</Text>
|
|
571
581
|
<Icon
|
|
572
582
|
name={hideSubmitButton ? names.arrowRight : names.arrowDown}
|
|
583
|
+
size={30}
|
|
584
|
+
color={colorPack.placeholderTextColor}
|
|
573
585
|
style={[styles.indicator, styleIndicator]}
|
|
574
586
|
/>
|
|
575
587
|
</View>
|
package/src/types.ts
CHANGED
|
@@ -15,7 +15,8 @@ export interface IconProps {
|
|
|
15
15
|
onPress?: () => void
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
19
|
+
export type IconComponentType = ComponentType<any> & ComponentType<IconProps>
|
|
19
20
|
|
|
20
21
|
export interface IconNames {
|
|
21
22
|
search?: string
|