Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
99 commits
Select commit Hold shift + click to select a range
00189fd
Use flex to automatically size optionContainer to its contents.
peacechen Jan 27, 2017
3bf0b7c
remove flex:1 from selectStyle to make the CSS work with RN39.
peacechen Feb 2, 2017
880e5fb
Add prop keyboardShouldPersistTaps to pass to ScrollView.
peacechen Aug 8, 2017
849c0b8
Conditionally use ViewPropTypes.
peacechen Aug 8, 2017
7fd3beb
Rename project
peacechen Aug 8, 2017
5ab3fec
Update props in Readme
peacechen Aug 8, 2017
0b8c145
Added NPM-version number and link to NPM-package (#3)
Aug 9, 2017
5e3efcc
Update Readme
peacechen Aug 9, 2017
b1456de
Wrapping of TextInput works in iOS fixes #4 (#5)
Aug 12, 2017
2e90685
Add disabled prop to modal picker (#9)
Aug 16, 2017
f31a3f6
Support orientation and resolution changes (#10)
peacechen Aug 16, 2017
78576a7
Prop to change supported orientation (#11)
Aug 16, 2017
fd060c7
Eslint rules (#15)
fabriziomoscon Aug 18, 2017
386a1c0
Typo in prop-type declaration
Aug 18, 2017
0551493
Removed react and react-native as devdependencies (#16)
Aug 18, 2017
5821867
Better way to support ViewPropTypes.
peacechen Aug 21, 2017
860c259
Upgrade SampleApp to RN 0.47 (#8)
Aug 27, 2017
d9ad661
Added prop for custom styling of options container (#21)
Aug 29, 2017
6eed2fa
add support for configurable animationType (#22)
mvanroon Sep 5, 2017
0a48df1
Readme: Pretty props table
peacechen Sep 5, 2017
9850cab
Update version for npm release
peacechen Sep 8, 2017
b55049f
Add selectTextStyle to propTypes/defaultProps, closes #24
Sep 12, 2017
7fb903d
reverted style changes introduced in orientation fixes (#20)
ChangedLater Sep 14, 2017
f30a589
Update version for npm release to v0.0.19
Sep 14, 2017
b9bd846
set selectTextStyle propType to Text.propTypes.style (#26)
mienaikoe Sep 23, 2017
ae8bdc8
Update version for npm release
peacechen Sep 29, 2017
aa5617e
Optionally close the modal by pressing the overlay (#31)
flyingace Oct 15, 2017
bbb3882
Added closeModalOnOverlayPress to documentation (#32)
flyingace Oct 15, 2017
16adad2
Update version for npm release
peacechen Oct 18, 2017
47624dd
Upgrade SampleApp to RN 0.49 (#34)
Oct 30, 2017
6555256
SampleApp: workaround for installation with yarn
Nov 4, 2017
ccb4323
Fix onChange when modal closes (#35)
Nov 22, 2017
bc5bec3
remove bottom border from last item (#38)
terohotti Nov 23, 2017
1e5f2ce
Update npm version to 0.0.22
Nov 23, 2017
410798b
Cleaned up SampleApp
Nov 25, 2017
76bf77c
Bugfix: Android does not have onDismiss prop
Nov 25, 2017
ea97870
Check for onDismiss-prop in a way that works on Expo
Nov 25, 2017
46f9f0e
Version 0.0.23, fixed android-bug introduced in v0.0.22
Nov 25, 2017
a132470
add cancelContainerStyle prop (#41)
antonsivogrivov Nov 29, 2017
6b1993a
Update NPM-version to v0.0.24
Nov 30, 2017
1eacde0
Add `cancelContainerStyle` prop to Readme
peacechen Dec 15, 2017
f995108
Use arrow instead of bind (#40)
Feb 5, 2018
fdbea99
Added accessibility labels (#49)
chriscohoat Feb 9, 2018
993509b
childrenContainerStyle and touchableStyle props added (#51)
eduardojunio Feb 21, 2018
cf05b17
Add test id prop (#48)
anovoselnik Mar 7, 2018
78eba61
Key/Label extractors of data (#56)
bdelville Mar 24, 2018
3686c7a
#44 Add TouchableOpacity activeOpacity option via props (#53)
Mar 24, 2018
73d7ecb
Update NPM-version to v0.0.26
Mar 29, 2018
a5b0c19
Add modal opening/closing event callbacks (#59)
sergey-kozel Apr 10, 2018
1c87ac1
Replace componentWillReceiveProps with componentDidUpdate
peacechen Apr 10, 2018
3f20c37
Readme: Fix formatting of props and code example
Apr 10, 2018
e8d0fd2
Add `visible` prop to control open/close state of modal.
peacechen Apr 10, 2018
e7a3156
Update NPM-version to v0.0.27
peacechen Apr 10, 2018
c9662d4
Add modalOpenerHitSlop prop (#64)
MattyK14 Apr 12, 2018
00f55b3
Change default modalOpenerHitSlop object (#66)
MattyK14 Apr 26, 2018
9569611
Disable accessibility for modal TouchableWithoutFeedback (#73)
jhellman Jun 26, 2018
931de35
Added closeOnChange prop (#74)
LasseSLambertsen Jul 16, 2018
4fa202b
Add prop customSelector (#72)
Jyrno42 Jul 23, 2018
74ab38d
Add prop for custom styling selected element (#82)
mikaello Aug 16, 2018
3b293be
Update NPM-version to v0.0.28
mikaello Aug 16, 2018
b84a591
Upgrade SampleApp to RN 0.56 (#83)
mikaello Aug 16, 2018
92a9089
Add custom component/selector example in README/SampleApp (#84)
mikaello Aug 16, 2018
f9984c1
Add get changed item function (#81)
sampsasaarela Aug 29, 2018
eabb8c0
Update NPM-version to v0.0.29
mikaello Sep 8, 2018
9cdf7c3
Accessibility Flexibility (#89)
jessamp Nov 5, 2018
a3c8b8d
Update NPM-version to v0.0.30
mikaello Nov 7, 2018
7484bda
Update NPM-version to v1.0.0.
mikaello Nov 7, 2018
74c9030
Added pass through props for Text components (#92)
VacuumDecay Nov 19, 2018
7663625
Update SampleApp to RN 0.57.8
peacechen Jan 15, 2019
9439ce5
Add support for custom components in options list (#98).
peacechen Jan 15, 2019
3c651de
Update NPM-version to v1.0.1
peacechen Jan 18, 2019
a5922d5
Update for RN 0.58+ (#99)
dominicrico Feb 5, 2019
2843080
Update NPM-version to v1.0.2
peacechen Feb 5, 2019
24301da
Add selectedKey prop (#102)
JoseVf Feb 27, 2019
834fc45
Update NPM-version to v1.0.3
peacechen Mar 14, 2019
75a31d0
Add initValueTextStyle prop (#106)
kentakang Mar 25, 2019
535d252
Upgrade SampleApp to RN 0.59.3
mikaello Apr 5, 2019
3c5d0b4
Update: Integrated Git-Start into Readme.md (#110)
360disrupt Apr 24, 2019
f2fefd0
Update NPM-version to v1.1.0
mikaello Aug 2, 2019
68f9bf8
Only use TouchableWithoutFeedback if backdropPressToClose is set.
JolivetteSax Aug 8, 2019
ab7a190
Update NPM-version to v1.1.1
peacechen Aug 8, 2019
50ee33c
Typescript typings (#123)
mmarinovic Oct 23, 2019
5626d87
Update NPM-version to v1.1.2
mikaello Oct 23, 2019
1ccbc31
onModalClose returns selected item (#107)
hitchcocknz Dec 12, 2019
21cede1
Updated sample app to the latest RN version.
Nov 26, 2019
8f4b04b
Added auto lint feature on commit and fixed some linting errors.
Nov 26, 2019
f3f5cc7
Fixed auto-lint problem.
Nov 26, 2019
9eb59a0
Changed sample app name.
Nov 26, 2019
66412cf
Feat(#67):
Nov 28, 2019
0cfb11d
feat(#67): Moved checkbox to a user defined function.
Dec 8, 2019
ece3256
feat(#67): Fixed a small glitch.
Dec 8, 2019
4c2299d
feat(#67): More bugfixes
Dec 8, 2019
cc18e96
chore(#67): Changed documentation. Made code more readable.
Dec 22, 2019
d644575
feat(#67): Removed delete operator.
Dec 22, 2019
4aa2809
feat(#68): More general tweaks.
Dec 22, 2019
72b3768
chore(#68): More tweaks and code refinement.
Dec 22, 2019
ac29629
chore(#68): More minor changes.
Dec 22, 2019
f3e4563
Revert "chore(#68): More minor changes."
Dec 23, 2019
4179675
chore(#68): Unified API for android and iOS.
Dec 23, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
Binary file not shown.
2 changes: 2 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
docs
SampleApp
86 changes: 86 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
{
parser: "babel-eslint",
env: {
es6: true,
node: true
},
extends: [
"plugin:react/recommended",
"eslint:recommended",
],
plugins: [
"babel",
"import",
"react",
"react-native",
],
parserOptions: {
ecmaVersion: 8,
ecmaFeatures: {
experimentalObjectRestSpread: true,
restParams: true,
spread: true,
jsx: true
},
sourceType: "module"
},
rules: {
indent: ["error", 4],
semi: ["error", "always"],
no-mixed-spaces-and-tabs: 2,
react/no-unknown-property: 1,
react/jsx-filename-extension: 0,
react/prefer-stateless-function: 0,
react/sort-comp: 0,
no-use-before-define: 0,
no-underscore-dangle: 0,
import/no-extraneous-dependencies: 0,
import/no-unresolved: [2, { ignore: ['react', 'react-native'] }],
no-spaced-func: 2,
space-in-parens: ["error", "never"],
no-var: "error",
no-constant-condition: 2,
eqeqeq: 2,
no-else-return: 2,
no-eval: 2,
no-lone-blocks: 2,
no-loop-func: 2,
no-useless-return: 2,
block-spacing: 2,
no-lonely-if: 2,
no-trailing-spaces: 2,
one-var: ["error", "never"],
arrow-body-style: ["error", "as-needed"],
no-console: 1,
no-unused-vars: 1,
jsx-quotes: ["error", "prefer-double"],
no-unused-expressions: "off",
require-await: 2,
no-irregular-whitespace: 2,
arrow-spacing: "error",
arrow-parens: ["error", "as-needed"],
brace-style: [
"error",
"1tbs",
{ allowSingleLine: false }
],
no-multi-spaces: [
"error", {
exceptions: {ImportDeclaration: true}
}
],
key-spacing: [2, {
beforeColon: false,
afterColon: true,
align: "value"
}],
no-empty-function: [2, {allow: ["arrowFunctions"]}],
comma-dangle: ["error", {
"arrays": "always-multiline",
"objects": "always-multiline",
"imports": "always-multiline",
"exports": "never",
"functions": "ignore",
}],
}
}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
.idea
npm-debug.log
node_modules

# vim
*.sw*
3 changes: 2 additions & 1 deletion .npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ test
.idea
SampleApp
.gitignore
docs
docs
*~
9 changes: 0 additions & 9 deletions BaseComponent.js

This file was deleted.

181 changes: 138 additions & 43 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,34 +1,53 @@
[![npm version](https://badge.fury.io/js/react-native-modal-picker.svg)](https://badge.fury.io/js/react-native-modal-picker)
# 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)

# react-native-modal-picker
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://raw.githubusercontent.com/d-a-n/react-native-modal-picker/master/docs/demo.gif" />
<img src="https://github.com/peacechen/react-native-modal-selector/blob/master/docs/demo.gif" />

## Install

```sh
npm i react-native-modal-picker --save
npm i react-native-modal-selector --save
```


## Live support

### Get help

If you have an urgent problem, hire a mentor for a 1:1 live session on Git-Start:
[![Get 1:1 live support for your issue.](https://git-start.com/assets/git-start-mentee-banner-medium.svg?sanitize=true)](https://git-start.com/help-request/create/peacechen%2Freact-native-modal-selector)

### Provide help

Help others in paid 1:1 live sessions to get started.
[![Give paid 1:1 live support.](https://git-start.com/assets/git-start-mentor-banner-medium.svg?sanitize=true)](https://git-start.com/help-request/overview/peacechen%2Freact-native-modal-selector)

## Breaking changes

Version 2.0.0 onwards support multi-select feature. As such, following properties from the versions before have changed.

1) `selectedKey` is now `initSelectedKeys`. It accepts an array of keys.
2) `getSelectedItem` is now `getSelectedItems`. It returns an array of selected items.

## Usage

You can either use this component as an wrapper around your existing component or use it in its default mode. In default mode a customizable button is rendered.
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 ModalPicker from 'react-native-modal-picker'

[..]
import ModalSelector from 'react-native-modal-selector'

class SampleApp extends Component {

constructor() {
super();
constructor(props) {
super(props);

this.state = {
textInputValue: ''
Expand All @@ -41,59 +60,135 @@ class SampleApp extends Component {
{ key: index++, section: true, label: 'Fruits' },
{ key: index++, label: 'Red Apples' },
{ key: index++, label: 'Cherries' },
{ key: index++, label: 'Cranberries' },
{ key: index++, label: 'Pink Grapefruit' },
{ key: index++, label: 'Raspberries' },
{ key: index++, section: true, label: 'Vegetables' },
{ key: index++, label: 'Beets' },
{ key: index++, label: 'Red Peppers' },
{ key: index++, label: 'Radishes' },
{ key: index++, label: 'Radicchio' },
{ key: index++, label: 'Red Onions' },
{ key: index++, label: 'Red Potatoes' },
{ key: index++, label: 'Rhubarb' },
{ key: index++, label: 'Tomatoes' }
{ 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}}>

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

<ModalPicker
// 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} />

</ModalPicker>

</ModalSelector>

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

## Props

* `data - []` required, array of objects with a unique key and label
* `style - object` optional, style definitions for the root element
* `onChange - function` optional, callback function, when the users has selected an option
* `initValue - string` optional, text that is initially shown on the button
* `cancelText - string` optional, text of the cancel button
* `selectStyle - object` optional, style definitions for the select element (available in default mode only!)
* `selectTextStyle - object` optional, style definitions for the select element (available in default mode only!)
* `overlayStyle - object` optional, style definitions for the overly/background element
* `sectionStyle - object` optional, style definitions for the section element
* `sectionTextStyle - object` optional, style definitions for the select text element
* `optionStyle - object` optional, style definitions for the option element
* `optionTextStyle - object` optional, style definitions for the option text element
* `cancelStyle - object` optional, style definitions for the cancel element
* `cancelTextStyle - object` optional, style definitions for the cancel text element
## 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:
```javascript
[{
key: 5,
label: 'Red Apples',
component: <View style={{backgroundColor: 'red'}}><Text style={{color: 'white'}}>Red Apples custom component ☺</Text></View>
}]
```

<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.
`onChange` | function | Yes | () => {} | callback function, when the users has selected an option. Returns an array of selected item/items.
`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
`animationType` | string | Yes | `slide` | type of animation to be used to show the modal. Must be one of `none`, `slide` or `fade`.
`disabled` | bool | Yes | false | `true` disables opening of the modal
`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
`supportedOrientations` | ['portrait', 'landscape'] | Yes | both | orientations the modal supports
`keyboardShouldPersistTaps`| `string` / `bool` | Yes | `always` | passed to underlying ScrollView
`style` | object | Yes | | style definitions for the root element
`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
`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.
`initSelectedKeys` | array<any> | Yes | [] | Key of the items to be initially selected. Should contain only one key if `multiple` is selected as false.
`multiple` | bool | No | false | Adds the ability to select multiple options.
`renderCheckbox` | function | Yes | (checked, onPress) => {} | Function that returns a checkbox element. Arguments of the function include `checked` state and `onPress` function that gets executed when the element is pressed. Required only if multiple option is selected.

### Methods

`getSelectedItems()`: get current selected items, updated by onChange event.
4 changes: 4 additions & 0 deletions SampleApp/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module.exports = {
root: true,
extends: '@react-native-community',
};
Loading