# react-native-modal-selector

> A cross-platform (iOS / Android), selector/picker component for React Native that is highly customizable and supports sections.

Latest version **2.1.2** (published 2022-10-24) · MIT license · 0 weekly downloads

## Install

```sh
npm install react-native-modal-selector
pnpm add react-native-modal-selector
yarn add react-native-modal-selector
bun add react-native-modal-selector
```

## Health

**Score 25/100 (F)** — status: abandoned.

Positive: has types; no vulnerabilities; high quality score.

Warnings: low downloads; no esm support.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 2.1.2 |
| Published | 2022-10-24 |
| First published | 2017-08-08 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | CommonJS |
| Dependencies | 1 |
| Unpacked size | 42.4 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 369 |
| Author | Daniel Korger |
| Maintainers | peace, mikaello |
| Keywords | react-native, dropdown, popover, select, picker, modal, ios, android, react-component |

## Links

- npm: https://www.npmjs.com/package/react-native-modal-selector
- Repository: https://github.com/peacechen/react-native-modal-selector
- Issues: https://github.com/peacechen/react-native-modal-selector/issues
- npm.io page: https://npm.io/package/react-native-modal-selector

## Dependencies (1)

- [prop-types](https://npm.io/package/prop-types.md) ^15.5.10

## Alternatives

- [react-native-root-siblings](https://npm.io/package/react-native-root-siblings.md) — 102.9K weekly downloads
- [@praxisui/dialog](https://npm.io/package/@praxisui/dialog.md) — 2.0K weekly downloads
- [easy-toggle-state](https://npm.io/package/easy-toggle-state.md) — 350 weekly downloads
- [ngx-lightbox-evp](https://npm.io/package/ngx-lightbox-evp.md) — 19 weekly downloads
- [react-native-modal-translucent-axton](https://npm.io/package/react-native-modal-translucent-axton.md) — 4 weekly downloads

## Recent versions

- 2.1.2 (latest) — 2022-10-24
- 2.1.1 — 2022-06-21
- 2.1.0 — 2021-09-10
- 2.0.9 — 2021-09-02
- 2.0.8 — 2021-08-05
- 2.0.7 — 2021-07-12
- 2.0.6 — 2021-07-07
- 2.0.5 — 2021-07-07
- 2.0.4 — 2021-07-05
- 2.0.3 — 2020-08-20
- 2.0.2 — 2020-06-11
- 2.0.1 — 2020-04-16
- 2.0.0 — 2020-03-10
- 1.1.5 — 2020-03-02
- 1.1.4 — 2020-02-07
- … 21 more at https://npm.io/package/react-native-modal-selector/versions

## README

# react-native-modal-selector [![npm version](https://badge.fury.io/js/react-native-modal-selector.svg)](https://badge.fury.io/js/react-native-modal-selector)

A cross-platform (iOS / Android), selector/picker component for React Native that is highly customizable and supports sections.

This project is the official continuation of the abandoned `react-native-modal-picker` repo. Contributors are welcome to [request a promotion to collaborator status](https://github.com/peacechen/react-native-modal-selector/issues/1).

## Demo

<img src="https://github.com/peacechen/react-native-modal-selector/blob/master/docs/demo.gif" />

## Install

```sh
npm install react-native-modal-selector
```

## Usage

You can either use this component in its default mode, as a wrapper around your existing component or provide a custom component (where you need to control opening of the modal yourself). In default mode a customizable button is rendered.

See `SampleApp` for an example how to use this component.

```jsx
import ModalSelector from 'react-native-modal-selector'

class SampleApp extends Component {

    constructor(props) {
        super(props);

        this.state = {
            textInputValue: ''
        }
    }

    render() {
        let index = 0;
        const data = [
            { key: index++, section: true, label: 'Fruits' },
            { key: index++, label: 'Red Apples' },
            { key: index++, label: 'Cherries' },
            { key: index++, label: 'Cranberries', accessibilityLabel: 'Tap here for cranberries' },
            // etc...
            // Can also add additional custom keys which are passed to the onChange callback
            { key: index++, label: 'Vegetable', customKey: 'Not a fruit' }
        ];

        return (
            <View style={{flex:1, justifyContent:'space-around', padding:50}}>

                // Default mode
                <ModalSelector
                    data={data}
                    initValue="Select something yummy!"
                    onChange={(option)=>{ alert(`${option.label} (${option.key}) nom nom nom`) }} />

                // Wrapper
                <ModalSelector
                    data={data}
                    initValue="Select something yummy!"
                    supportedOrientations={['landscape']}
                    accessible={true}
                    scrollViewAccessibilityLabel={'Scrollable options'}
                    cancelButtonAccessibilityLabel={'Cancel Button'}
                    onChange={(option)=>{ this.setState({textInputValue:option.label})}}>

                    <TextInput
                        style={{borderWidth:1, borderColor:'#ccc', padding:10, height:30}}
                        editable={false}
                        placeholder="Select something yummy!"
                        value={this.state.textInputValue} />

                </ModalSelector>

                // Custom component
                <ModalSelector
                    data={data}
                    ref={selector => { this.selector = selector; }}
                    customSelector={<Switch onValueChange={() => this.selector.open()} />}
                />
            </View>
        );
    }
}
```

## Data Format

The selector accepts a specific format of data:
```javascript
[{ key: 5, label: 'Red Apples' }]
```

Optionally provide a `component` key which overrides the default label text. Optionally provide a unique `testID` for each item:
```javascript
[{
  key: 5,
  label: 'Red Apples',
  // The next keys are optional --
  component: <View style={{backgroundColor: 'red'}}><Text style={{color: 'white'}}>Red Apples custom component ☺</Text></View>,
  testID: '5-red-apples'
}]
```

<img src="https://user-images.githubusercontent.com/6295083/51210593-d3fbae00-18d8-11e9-8f51-d1ca4f9f8267.png" />

If your data has a specific format, you can define extractors of data, example:
```javascript
this.setState({data: [{ id: 5, name: 'Red Apples' }]});

return (
  <ModalSelector
    data={this.state.data}
    keyExtractor= {item => item.id}
    labelExtractor= {item => item.name}
  />
);
```

## API

### Props

Prop                | Type     | Optional | Default      | Description
------------------- | -------- | -------- | ------------ | -----------
`data`              | array    | No       | []           | array of objects with a unique `key` and `label` to select in the modal. Optional `component` overrides label text. Optional unique `testID` for each item.
`onChange`          | function | Yes      | () => {}     | callback function, when the users has selected an option
`onModalOpen`       | function | Yes      | () => {}     | callback function, when modal is opening
`onModalClose`      | function | Yes      | (item) => {} | callback function, when modal is closing. Returns the selected item.
`keyExtractor`      | function | Yes      | (data) => data.key   | extract the key from the data item
`labelExtractor`    | function | Yes      | (data) => data.label | extract the label from the data item
`componentExtractor`| function | Yes      | (data) => data.component | extract the component from the data item
`visible`           | bool     | Yes      | false        | control open/close state of modal
`closeOnChange`     | bool     | Yes      | true         | control if modal closes on select
`initValue`         | string   | Yes      | `Select me!` | text that is initially shown on the button
`cancelText`        | string   | Yes      | `cancel`     | text of the cancel button
`disabled`          | bool     | Yes      | false        | `true` disables opening of the modal
`supportedOrientations`    | ['portrait', 'landscape'] | Yes      | both      | orientations the modal supports
`keyboardShouldPersistTaps`| `string` / `bool`         | Yes      | `always`  | passed to underlying ScrollView
`listType`          | string   | Yes      | `SCROLLVIEW` | scroller type: `SCROLLVIEW` or `FLATLIST`
`animationType`     | string   | Yes      | `slide`      | type of animation to be used to show the modal. Must be one of `none`, `slide` or `fade`.
`style`             | object   | Yes      |              | style definitions for the root element
`childrenContainerStyle`| object   | Yes      | {}           | style definitions for the children container view
`touchableStyle`    | object   | Yes      | {}           | style definitions for the touchable element
`touchableActiveOpacity`    | number   | Yes      | 0.2           | opacity for the touchable element on touch
`selectStyle`       | object   | Yes      | {}           | style definitions for the select element (available in default mode only!). NOTE: Due to breaking changes in React Native, RN < 0.39.0 should pass `flex:1` explicitly to `selectStyle` as a prop.
`selectTextStyle`   | object   | Yes      | {}           | style definitions for the select element (available in default mode only!)
`overlayStyle`      | object   | Yes      | { flex: 1, padding: '5%', justifyContent: 'center', backgroundColor: 'rgba(0,0,0,0.7)' } | style definitions for the overlay background element. RN <= 0.41 should override this with pixel value for padding.
`sectionStyle`      | object   | Yes      | {}           | style definitions for the section element
`sectionTextStyle`  | object   | Yes      | {}           | style definitions for the select text element
`selectedItemTextStyle` | object | Yes    | {}           | style definitions for the currently selected text element
`optionStyle`       | object   | Yes      | {}           | style definitions for the option element
`optionTextStyle`   | object   | Yes      | {}           | style definitions for the option text element
`optionContainerStyle`| object | Yes      | {}           | style definitions for the option container element
`cancelStyle`       | object   | Yes      | {}           | style definitions for the cancel element
`cancelTextStyle`   | object   | Yes      | {}           | style definitions for the cancel text element
`initValueTextStyle`| object   | Yes      | {}           | style definitions for the initValue text element
`cancelContainerStyle`| object | Yes      | {}           | style definitions for the cancel container
`backdropPressToClose`| bool   | Yes  | false        | `true` makes the modal close when the overlay is pressed
`passThruProps`| object   | Yes  | {}        | props to pass through to the container View and each option TouchableOpacity (e.g. testID for testing)
`selectTextPassThruProps`| object   | Yes  | {}        | props to pass through to the select text component
`optionTextPassThruProps`| object   | Yes  | {}        | props to pass through to the options text components in the modal
`cancelTextPassThruProps`| object   | Yes  | {}        | props to pass through to the cancel text components in the modal
`scrollViewPassThruProps`| object   | Yes  | {}        | props to pass through to the internal ScrollView
`openButtonContainerAccessible`| bool   | Yes  | false        | `true` enables accessibility for the open button container. Note: if `false` be sure to define accessibility props directly in the wrapped component.
`listItemAccessible`| bool   | Yes  | false        | `true` enables accessibility for data items. Note: data items should have an `accessibilityLabel` property if this is enabled
`cancelButtonAccessible`| bool   | Yes  | false        | `true` enables accessibility for cancel button.
`scrollViewAccessible`| bool   | Yes  | false        | `true` enables accessibility for the scroll view. Only enable this if you don't want to interact with individual data items.
`scrollViewAccessibilityLabel` | string   | Yes      | undefined | Accessibility label for the modal ScrollView
`cancelButtonAccessibilityLabel` | string   | Yes      | undefined | Accessibility label for the cancel button
`modalOpenerHitSlop` | object | Yes | {} | How far touch can stray away from touchable that opens modal ([RN docs](https://facebook.github.io/react-native/docs/touchablewithoutfeedback.html#hitslop))
`customSelector`     | node   | Yes | undefined          | Render a custom node instead of the built-in select box.
`selectedKey`        | any    | Yes | ''                 | Key of the item to be initially selected
`enableShortPress`          | bool   | Yes | true               | enables short press. This is regular touch behavior.
`enableLongPress`           | bool   | Yes | false              | enables long press. When true, `onModalOpen` returns `{longPress: true}`
`optionsTestIDPrefix`       | string   | Yes | `'default'`      | This prefixes each selectable option's testID prop if no testID keys are provided in `props.data` array objects. Default for each option's testID: 'default-\<optionLabel\>'
`header`     | node   | Yes | undefined          | Render a header above the list
`onEndReached`     | function                  | Yes | undefined          | Called once when the scroll position gets of the rendered content.

### Methods

* `open()`: open the modal.
* `close()`: close the modal.
* `getSelectedItem()`: get current selected item, updated by onChange event.

## See also

* A similar project is [hepter/react-native-modal-selector-searchable](https://github.com/hepter/react-native-modal-selector-searchable), which is a fork of this module that adds searching capabilities.

---
_Source: https://npm.io/package/react-native-modal-selector · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
