@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 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**.
@@ -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, name: newItemName }];
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, style: [styles.tagRemoveIcon, { color: tagRemoveIconColor }] }) })] }, getItemKey(item)));
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, style: [styles.checkIcon, { color: selectedItemIconColor }] })) : null] }) }) })), [
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, 'name'), " (tap or press return)"] }) }) }) })), [addItem, itemStyle]);
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.name === searchTerm);
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({ name: searchTerm });
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riebel/react-native-multiple-select",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "description": "Modernized Simple multi-select component for react-native",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -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, name: newItemName }]
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
- style={[styles.tagRemoveIcon, { color: tagRemoveIconColor }]}
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
- style={[styles.checkIcon, { color: selectedItemIconColor }]}
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, 'name')} (tap or press return)
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((item) => item.name === searchTerm)
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({ name: searchTerm })
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
- export type IconComponentType = ComponentType<IconProps>
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