react-native-sectioned-multi-select
Advanced tools
Comparing version 0.8.1 to 0.8.2
@@ -0,0 +0,0 @@ { |
@@ -0,0 +0,0 @@ module.exports = { |
# Changelog | ||
## 0.8.2 - 2021-12-13 | ||
### Added | ||
- onChangeSearchText event #210 | ||
### Fixed | ||
- Various types fixes | ||
- all props that return components are now `ReactNode`. #253 | ||
- `icons` individual icon objects are now optional and allow any extra properties you wish to be added to your icon component. #253 #232 | ||
- added types for some useful internal methods. | ||
- Fix TypeError: undefined is not an object (evaluating 'item[subKey]') with unpopulated items. #237 | ||
## 0.8.1 - 2020-11-03 | ||
@@ -7,7 +23,8 @@ | ||
- React NAtive's UIManager.setLayoutAnimationEnabledExperimental causing tests fail. This version has fix for it. \n Details: | ||
```sh | ||
TypeError: _reactNative.UIManager.setLayoutAnimationEnabledExperimental is not a function | ||
``` | ||
- React Native's UIManager.setLayoutAnimationEnabledExperimental causing tests fail. This version has fix for it. \n Details: | ||
```sh | ||
TypeError: _reactNative.UIManager.setLayoutAnimationEnabledExperimental is not a function | ||
``` | ||
## 0.8.0 - 2020-10-01 | ||
@@ -14,0 +31,0 @@ |
@@ -0,0 +0,0 @@ import 'react-native' |
@@ -0,0 +0,0 @@ import React, { Component } from 'react' |
@@ -0,0 +0,0 @@ { |
module.exports = { | ||
presets: ['module:metro-react-native-babel-preset'], | ||
}; |
@@ -0,0 +0,0 @@ import { AppRegistry } from 'react-native'; |
@@ -0,0 +0,0 @@ /** |
@@ -11,3 +11,3 @@ { | ||
"react": "16.9.0", | ||
"react-native": "0.61.2", | ||
"react-native": "0.62.3", | ||
"react-native-sectioned-multi-select": "github:renrizzolo/react-native-sectioned-multi-select#master", | ||
@@ -14,0 +14,0 @@ "react-native-vector-icons": "^4.4.2" |
import * as React from 'react' | ||
import * as ReactNative from 'react-native' | ||
type IconProps = { | ||
name: string | ||
size?: number | ||
[x: string]: any | ||
} | ||
export interface Styles { | ||
@@ -67,4 +73,4 @@ container?: ReactNative.StyleProp<ReactNative.ViewStyle> | ||
searchPlaceholderText?: string | ||
noResultsComponent?: (() => void) | JSX.Element | ||
loadingComponent?: (() => void) | JSX.Element | ||
noResultsComponent?: React.ReactNode | ||
loadingComponent?: React.ReactNode | ||
loading?: boolean | ||
@@ -82,12 +88,12 @@ subItemFontFamily?: object | ||
hideSearch?: boolean | ||
footerComponent?: (() => void) | JSX.Element | ||
stickyFooterComponent?: (() => void) | JSX.Element | ||
selectToggleIconComponent?: (() => void) | JSX.Element | ||
cancelIconComponent?: (() => void) | JSX.Element | ||
searchIconComponent?: (() => void) | JSX.Element | ||
selectedIconComponent?: (() => void) | JSX.Element | ||
unselectedIconComponent?: (() => void) | JSX.Element | ||
dropDownToggleIconUpComponent?: (() => void) | JSX.Element | ||
dropDownToggleIconDownComponent?: (() => void) | JSX.Element | ||
chipRemoveIconComponent?: (() => void) | JSX.Element | ||
footerComponent?: React.ReactNode | ||
stickyFooterComponent?: React.ReactNode | ||
selectToggleIconComponent?: React.ReactNode | ||
cancelIconComponent?: React.ReactNode | ||
searchIconComponent?: React.ReactNode | ||
selectedIconComponent?: React.ReactNode | ||
unselectedIconComponent?: React.ReactNode | ||
dropDownToggleIconUpComponent?: React.ReactNode | ||
dropDownToggleIconDownComponent?: React.ReactNode | ||
chipRemoveIconComponent?: React.ReactNode | ||
selectChildren?: boolean | ||
@@ -102,3 +108,3 @@ highlightChildren?: boolean | ||
onCancel?: () => void | ||
headerComponent?: (() => void) | JSX.Element | ||
headerComponent?: React.ReactNode | ||
alwaysShowSelectText?: boolean | ||
@@ -109,5 +115,6 @@ searchAdornment?: (searchText: string) => void | ||
customLayoutAnimation?: object | ||
onChangeSearchText?: (searchTerm: string) => void | ||
filterItems?: (searchTerm: string) => void | ||
onToggleSelector?: (selected: boolean) => void | ||
noItemsComponent?: (() => void) | JSX.Element | ||
noItemsComponent?: React.ReactNode | ||
customChipsRenderer?: (chipProperties: object) => void | ||
@@ -120,3 +127,4 @@ chipsPosition?: 'top' | 'bottom' | ||
parentChipsRemoveChildren?: boolean | ||
IconRenderer?: (() => void) | JSX.Element | ||
hideChipRemove?: boolean | ||
IconRenderer?: React.ReactNode | ||
itemsFlatListProps?: Omit<ReactNative.FlatListProps<T>, 'data' | 'renderItem'> | ||
@@ -127,28 +135,11 @@ subItemsFlatListProps?: Omit< | ||
> | ||
icons: { | ||
search: { | ||
name: string | ||
size: number | ||
} | ||
arrowUp: { | ||
name: string | ||
size: number | ||
} | ||
arrowDown: { | ||
name: string | ||
size: number | ||
} | ||
close: { | ||
name: string | ||
size: number | ||
} | ||
check: { | ||
name: string | ||
size: number | ||
} | ||
cancel: { | ||
name: string | ||
size: number | ||
} | ||
} | ||
icons?: Partial<{ | ||
search: IconProps | ||
arrowUp: IconProps | ||
arrowDown: IconProps | ||
close: IconProps | ||
check: IconProps | ||
cancel: IconProps | ||
}> | ||
} | ||
@@ -159,2 +150,7 @@ export default class SectionedMultiSelect<ItemType> extends React.Component< | ||
_toggleSelector: () => void | ||
_removeAllItems: () => void | ||
_removeItem: (item: ItemType) => void | ||
_selectAllItems: () => void | ||
_findItem: (id: string | number) => ItemType | object | undefined | ||
_itemSelected: (item: ItemType) => boolean | ||
} |
import SectionedMultiSelect from './lib/sectioned-multi-select'; | ||
export default SectionedMultiSelect; |
@@ -0,0 +0,0 @@ { |
export { default as RowItem } from './RowItem'; | ||
export { default as RowSubItem } from './RowSubItem'; | ||
export { default as ItemIcon } from './ItemIcon'; |
@@ -0,0 +0,0 @@ import React from 'react' |
@@ -0,0 +0,0 @@ import React, { Component } from 'react' |
@@ -0,0 +0,0 @@ import React, { Component } from 'react' |
export const callIfFunction = maybeFn => | ||
(maybeFn ? (maybeFn && typeof maybeFn === 'function' ? maybeFn() : maybeFn) : null) |
@@ -199,2 +199,3 @@ import React, { PureComponent } from 'react' | ||
customLayoutAnimation: PropTypes.object, | ||
onChangeSearchText: PropTypes.func, | ||
filterItems: PropTypes.func, | ||
@@ -431,3 +432,13 @@ onToggleSelector: PropTypes.func, | ||
} | ||
_onChangeSearchText = (searchTerm) => { | ||
const { onChangeSearchText } = this.props | ||
if (onChangeSearchText) { | ||
onChangeSearchText(searchTerm); | ||
} | ||
this.setState({ searchTerm }) | ||
} | ||
_filterItems = (searchTerm) => { | ||
@@ -885,6 +896,7 @@ const { items, subKey, uniqueKey, displayKey, filterItems } = this.props | ||
const item = this._findItem(singleSelectedItem) | ||
if (!item || !item[displayKey]) return null | ||
const isParent = subKey && item[subKey] && item[subKey].length | ||
if (!item || !item[displayKey]) return null | ||
return ( | ||
@@ -1123,3 +1135,3 @@ <View | ||
selectionColor={colors.searchSelectionColor} | ||
onChangeText={(searchTerm) => this.setState({ searchTerm })} | ||
onChangeText={this._onChangeSearchText} | ||
placeholder={searchPlaceholderText} | ||
@@ -1126,0 +1138,0 @@ autoFocus={autoFocus} |
{ | ||
"name": "react-native-sectioned-multi-select", | ||
"version": "0.8.1", | ||
"version": "0.8.2", | ||
"description": "a multi (or single) select component with support for sub categories, search, chips.", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
# react-native-sectioned-multi-select | ||
Hi, there's a breaking change in v0.8.0, I chose not to release a major version for various reasons. Please see [Icons](#icons). In short, you must pass `Icon` (from `react-native-vector-icons`, or any icon lib) to the `IconRenderer` prop now. | ||
[![NPM Version](https://img.shields.io/npm/v/react-native-sectioned-multi-select.svg?style=flat)](https://www.npmjs.com/package/react-native-sectioned-multi-select) | ||
@@ -42,2 +40,3 @@ | ||
Similarly, for Expo environments you can use: | ||
``` | ||
@@ -97,3 +96,3 @@ import {MaterialIcons} from '@expo/vector-icons'; | ||
`uniqueKey` | string | ||
`onSelectedItemsChange` | function | ||
`onSelectedItemsChange` | function | ||
`IconRenderer` | function or object | ||
@@ -180,5 +179,21 @@ | ||
You can programatically remove all items by setting up a ref to the component: | ||
### Refs / internal methods | ||
``` | ||
You can do some programatic operations by setting up a ref to the component and accessing its internal methods: | ||
```JS | ||
// function component | ||
import React, { useRef } from 'react' | ||
const App = () => { | ||
const ref = useRef(null) | ||
return ( | ||
<SectionedMultiSelect | ||
... | ||
ref={ref} | ||
/> | ||
) | ||
} | ||
// class component | ||
<SectionedMultiSelect | ||
@@ -190,11 +205,17 @@ ... | ||
and then use the `_removeAllItems` function: | ||
Remove all items: | ||
``` | ||
```JS | ||
// function component | ||
onPress={() => ref && ref.current && ref.current._removeAllItems()} | ||
// class component | ||
onPress={() => this.SectionedMultiSelect._removeAllItems()} | ||
``` | ||
You can open the modal programatically with the \_toggleSelector() method: | ||
Toggle the modal: | ||
``` | ||
```JS | ||
// function component | ||
onPress={() => ref && ref.current && ref.current._removeAllItems()} | ||
// class component | ||
onPress={() => this.SectionedMultiSelect._toggleSelector()} | ||
@@ -201,0 +222,0 @@ ``` |
150
Recipes.md
@@ -7,4 +7,36 @@ # Recipes | ||
Some of these examples use a ref to the component like this: `ref={SectionedMultiSelect => (this.SectionedMultiSelect = SectionedMultiSelect)}` | ||
Some of these examples use a ref to the component like this: | ||
Function component: | ||
```JS | ||
import React, { useRef } from 'react' | ||
const App = () => { | ||
const ref = useRef(null) | ||
// ref.current._toggleSelector() | ||
return ( | ||
<> | ||
<SectionedMultiSelect | ||
... | ||
ref={ref} | ||
/> | ||
<Button onPress={() => ref?.current?._toggleSelector()} /> | ||
</> | ||
) | ||
} | ||
``` | ||
Class component: | ||
```JS | ||
<> | ||
<SectionedMultiSelect | ||
... | ||
ref={SectionedMultiSelect => this.SectionedMultiSelect = SectionedMultiSelect} | ||
/> | ||
<Button onPress={() => this.SectionedMultiSelect._toggleSelector()} /> | ||
</> | ||
``` | ||
## Custom select text | ||
@@ -37,3 +69,5 @@ | ||
renderSelectText={this.renderSelectText} | ||
onSelectedItemObjectsChange={(selectedItemObjects) => this.setState({ selectedItemObjects })} | ||
onSelectedItemObjectsChange={(selectedItemObjects) => | ||
this.setState({ selectedItemObjects }) | ||
} | ||
/> | ||
@@ -94,3 +128,3 @@ ``` | ||
backgroundColor: 'darkgrey', | ||
alignItems: 'center', | ||
alignItems: 'center' | ||
}} | ||
@@ -101,4 +135,3 @@ onPress={ | ||
: this.SectionedMultiSelect._selectAllItems | ||
} | ||
> | ||
}> | ||
<Text style={{ color: 'white', fontWeight: 'bold' }}> | ||
@@ -108,3 +141,3 @@ {this.state.selectedItems.length ? 'Remove' : 'Select'} all | ||
</TouchableOpacity> | ||
); | ||
) | ||
``` | ||
@@ -146,9 +179,10 @@ | ||
// flatten the styles | ||
const flat = StyleSheet.flatten(style); | ||
const flat = StyleSheet.flatten(style) | ||
// remove out the keys that aren't accepted on View | ||
const { color, fontSize, ...styles } = flat; | ||
const { color, fontSize, ...styles } = flat | ||
let iconComponent; | ||
let iconComponent | ||
// the colour in the url on this site has to be a hex w/o hash | ||
const iconColor = color && color.substr(0, 1) === '#' ? `${color.substr(1)}/` : ''; | ||
const iconColor = | ||
color && color.substr(0, 1) === '#' ? `${color.substr(1)}/` : '' | ||
@@ -160,3 +194,3 @@ const Search = ( | ||
/> | ||
); | ||
) | ||
const Down = ( | ||
@@ -167,3 +201,3 @@ <Image | ||
/> | ||
); | ||
) | ||
const Up = ( | ||
@@ -174,3 +208,3 @@ <Image | ||
/> | ||
); | ||
) | ||
const Close = ( | ||
@@ -181,3 +215,3 @@ <Image | ||
/> | ||
); | ||
) | ||
@@ -189,3 +223,3 @@ const Check = ( | ||
/> | ||
); | ||
) | ||
const Cancel = ( | ||
@@ -196,29 +230,29 @@ <Image | ||
/> | ||
); | ||
) | ||
switch (name) { | ||
case 'search': | ||
iconComponent = Search; | ||
break; | ||
iconComponent = Search | ||
break | ||
case 'keyboard-arrow-up': | ||
iconComponent = Up; | ||
break; | ||
iconComponent = Up | ||
break | ||
case 'keyboard-arrow-down': | ||
iconComponent = Down; | ||
break; | ||
iconComponent = Down | ||
break | ||
case 'close': | ||
iconComponent = Close; | ||
break; | ||
iconComponent = Close | ||
break | ||
case 'check': | ||
iconComponent = Check; | ||
break; | ||
iconComponent = Check | ||
break | ||
case 'cancel': | ||
iconComponent = Cancel; | ||
break; | ||
iconComponent = Cancel | ||
break | ||
default: | ||
iconComponent = null; | ||
break; | ||
iconComponent = null | ||
break | ||
} | ||
return <View style={styles}>{iconComponent}</View>; | ||
}; | ||
return <View style={styles}>{iconComponent}</View> | ||
} | ||
``` | ||
@@ -232,27 +266,27 @@ | ||
icon = ({ name, size = 18, style }) => { | ||
switch (name) { | ||
case 'search': | ||
iconName = 'magnifier' | ||
break | ||
case 'keyboard-arrow-up': | ||
iconName = 'arrow-up' | ||
break | ||
case 'keyboard-arrow-down': | ||
iconName = 'arrow-down' | ||
break | ||
case 'close': | ||
iconName = 'close | ||
break | ||
case 'check': | ||
iconName = 'check' | ||
break | ||
case 'cancel': | ||
iconName = 'close' | ||
break | ||
default: | ||
iconName = null | ||
break | ||
} | ||
return <Icon style={style} size={size} name={iconName}/> | ||
switch (name) { | ||
case 'search': | ||
iconName = 'magnifier' | ||
break | ||
case 'keyboard-arrow-up': | ||
iconName = 'arrow-up' | ||
break | ||
case 'keyboard-arrow-down': | ||
iconName = 'arrow-down' | ||
break | ||
case 'close': | ||
iconName = 'close' | ||
break | ||
case 'check': | ||
iconName = 'check' | ||
break | ||
case 'cancel': | ||
iconName = 'close' | ||
break | ||
default: | ||
iconName = null | ||
break | ||
} | ||
return <Icon style={style} size={size} name={iconName} /> | ||
} | ||
``` | ||
@@ -308,3 +342,5 @@ | ||
```js | ||
<SectionedMultiSelect searchAdornment={(searchTerm) => this.searchAdornment(searchTerm)} /> | ||
<SectionedMultiSelect | ||
searchAdornment={(searchTerm) => this.searchAdornment(searchTerm)} | ||
/> | ||
``` |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
7082854
70
25144
381
2