├── dropdown-both.gif
├── lib
├── index.js
├── option.js
├── overlay.js
├── items.js
├── select.js
└── optionList.js
├── .gitignore
├── package.json
├── LICENSE
└── README.md
/dropdown-both.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gs-akhan/react-native-select/HEAD/dropdown-both.gif
--------------------------------------------------------------------------------
/lib/index.js:
--------------------------------------------------------------------------------
1 | const Option = require('./option');
2 | const OptionList = require('./optionList');
3 | const Select = require('./select');
4 |
5 | module.exports = {
6 | Option,
7 | OptionList,
8 | Select
9 | };
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 |
5 | # Runtime data
6 | pids
7 | *.pid
8 | *.seed
9 | .DS_Store
10 |
11 | # Directory for instrumented libs generated by jscoverage/JSCover
12 | lib-cov
13 |
14 | # Coverage directory used by tools like istanbul
15 | coverage
16 |
17 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
18 | .grunt
19 |
20 | # node-waf configuration
21 | .lock-wscript
22 |
23 | # Compiled binary addons (http://nodejs.org/api/addons.html)
24 | build/Release
25 |
26 | # Dependency directory
27 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
28 | node_modules
29 |
--------------------------------------------------------------------------------
/lib/option.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import {
3 | StyleSheet,
4 | View,
5 | Text,
6 | } from 'react-native';
7 |
8 | const styles = StyleSheet.create({
9 | container: {
10 | padding: 10
11 | }
12 | });
13 |
14 | class Option extends Component {
15 | constructor(props) {
16 | super(props);
17 | }
18 |
19 | render() {
20 | const { style, styleText } = this.props;
21 |
22 | return (
23 |
24 | {this.props.children}
25 |
26 | );
27 | }
28 | }
29 |
30 | Option.propTypes = {
31 | children: React.PropTypes.string.isRequired
32 | };
33 |
34 | module.exports = Option;
35 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-native-selectme",
3 | "version": "1.2.3",
4 | "description": "A better Select dropdown menu for react-native",
5 | "main": "lib/index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "repository": {
10 | "type": "git",
11 | "url": "git+https://github.com/gs-akhan/react-native-select.git"
12 | },
13 | "keywords": [
14 | "react-component",
15 | "react-native",
16 | "react-native-dropdown",
17 | "ios",
18 | "android"
19 | ],
20 | "author": "akhan (https://github.com/gs-akhan)",
21 | "license": "MIT",
22 | "bugs": {
23 | "url": "https://github.com/gs-akhan/react-native-select/issues"
24 | },
25 | "homepage": "https://github.com/gs-akhan/react-native-select"
26 | }
27 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Akhan
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/lib/overlay.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import {
3 | Dimensions,
4 | StyleSheet,
5 | TouchableWithoutFeedback,
6 | View,
7 | } from 'react-native';
8 |
9 | const window = Dimensions.get('window');
10 |
11 | const styles = StyleSheet.create({
12 | container: {
13 | position: 'absolute',
14 | top: 0,
15 | left: 0,
16 | right: 0,
17 | bottom: 0
18 | },
19 | overlay: {
20 | position: 'absolute',
21 | width: window.width,
22 | height: window.height,
23 | flex : 1,
24 | justifyContent : "center",
25 | alignItems : "center",
26 | backgroundColor : "#ffffff"
27 | }
28 | });
29 |
30 | class Overlay extends Component {
31 | constructor(props) {
32 | super(props);
33 | }
34 |
35 | render() {
36 | const { pageX, pageY, show, onPress, overlayStyles } = this.props;
37 |
38 | if (!show) {
39 | return null
40 | }
41 |
42 | return (
43 |
44 |
45 | {this.props.children}
46 |
47 |
48 | );
49 | }
50 | }
51 |
52 | Overlay.propTypes = {
53 | pageX: React.PropTypes.number,
54 | pageY: React.PropTypes.number,
55 | show: React.PropTypes.bool,
56 | overlayStyles : React.PropTypes.object
57 | };
58 |
59 | Overlay.defaultProps = {
60 | pageX: 0,
61 | pageY: 0,
62 | show: false,
63 | overlayStyles : {}
64 | };
65 |
66 | module.exports = Overlay;
67 |
--------------------------------------------------------------------------------
/lib/items.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import {
3 | Dimensions,
4 | StyleSheet,
5 | View,
6 | ScrollView,
7 | TouchableWithoutFeedback,
8 | Text,
9 | Easing,
10 | Animated,
11 | } from 'react-native';
12 |
13 | const AnimatedScrollView = Animated.createAnimatedComponent(ScrollView);
14 | const window = Dimensions.get('window');
15 |
16 | const styles = StyleSheet.create({
17 | scrollView: {
18 | height: 120,
19 | width: 198 //TODO: this needs to be dynamic
20 | },
21 | container: {
22 | height: 120,
23 | borderColor: '#BDBDC1',
24 | borderWidth: 1,
25 | backgroundColor : "#ffffff"
26 | }
27 | });
28 |
29 | class Items extends Component {
30 | constructor(props) {
31 | super(props);
32 | this.state = {
33 | height : new Animated.Value(0)
34 | };
35 | }
36 |
37 | componentDidMount() {
38 | const { height } = this.props;
39 |
40 | Animated.timing(this.state.height, {
41 | toValue: height * 3,
42 | duration: 200,
43 | easing : Easing.linear
44 | }).start();
45 | }
46 |
47 | render() {
48 | const { items, positionX, positionY, show, onPress, width, height, itemsStyles } = this.props;
49 |
50 | if (!show) {
51 | return null;
52 | }
53 |
54 | const renderedItems = React.Children.map(items, (item) => {
55 |
56 | return (
57 | onPress(item.props.children, item.props.value) }>
58 |
59 | {item}
60 |
61 |
62 | );
63 | });
64 |
65 | return (
66 |
67 |
71 | {renderedItems}
72 |
73 |
74 | );
75 | }
76 | }
77 |
78 | Items.propTypes = {
79 | positionX: React.PropTypes.number,
80 | positionY: React.PropTypes.number,
81 | show: React.PropTypes.bool,
82 | onPress: React.PropTypes.func
83 | };
84 |
85 | Items.defaultProps = {
86 | width: 0,
87 | height: 0,
88 | positionX: 0,
89 | positionY: 0,
90 | show: false,
91 | onPress: () => {}
92 | };
93 |
94 | module.exports = Items;
95 |
--------------------------------------------------------------------------------
/lib/select.js:
--------------------------------------------------------------------------------
1 | const Option = require('./option');
2 |
3 | import React, { Component } from 'react';
4 | import {
5 | Dimensions,
6 | StyleSheet,
7 | TouchableWithoutFeedback,
8 | View,
9 | } from 'react-native';
10 |
11 | const window = Dimensions.get('window');
12 |
13 | const SELECT = 'SELECT';
14 |
15 | const styles = StyleSheet.create({
16 | container: {
17 | borderColor: '#BDBDC1',
18 | borderWidth: 2 / window.scale
19 | }
20 | });
21 |
22 | class Select extends Component {
23 | constructor(props) {
24 | super(props);
25 |
26 | this.pageX = 0;
27 | this.pageY = 0;
28 |
29 | let defaultValue = props.defaultValue;
30 |
31 | if (!defaultValue) {
32 | if (Array.isArray(props.children)) {
33 | defaultValue = props.children[0].props.children;
34 | } else {
35 | defaultValue = props.children.props.children;
36 | }
37 | }
38 |
39 | this.state = {
40 | value: defaultValue
41 | }
42 | }
43 |
44 | reset() {
45 | const { defaultValue } = this.props;
46 | this.setState({ value: defaultValue });
47 | }
48 |
49 | _onPress() {
50 | const { optionListRef, children, onSelect, width, height } = this.props;
51 |
52 | if (!children.length) {
53 | return false;
54 | }
55 |
56 | optionListRef()._show(children, this.pageX, this.pageY, width, height, (item, value=item) => {
57 | if (item) {
58 | onSelect(value);
59 | this.setState({
60 | value: item
61 | });
62 | }
63 | });
64 | }
65 | blur() {
66 | this.props.optionListRef()._blur();
67 | }
68 | render() {
69 | const { width, height, children, defaultValue, style, styleOption, styleText } = this.props;
70 | const dimensions = { width, height };
71 |
72 | return (
73 |
74 |
75 |
76 |
77 |
78 | );
79 | }
80 | }
81 |
82 | Select.propTypes = {
83 | width: React.PropTypes.number,
84 | height: React.PropTypes.number,
85 | optionListRef: React.PropTypes.func.isRequired,
86 | onSelect: React.PropTypes.func
87 | };
88 |
89 | Select.defaultProps = {
90 | width: 200,
91 | height: 40,
92 | onSelect: () => { }
93 | };
94 |
95 | module.exports = Select;
96 |
--------------------------------------------------------------------------------
/lib/optionList.js:
--------------------------------------------------------------------------------
1 | const Overlay = require('./overlay');
2 | const Items = require('./items');
3 |
4 | import React, { Component } from 'react';
5 | import {
6 | Dimensions,
7 | StyleSheet,
8 | View,
9 | } from 'react-native';
10 |
11 | const window = Dimensions.get('window');
12 |
13 | class OptionList extends Component {
14 | constructor(props) {
15 | super(props);
16 |
17 | this.state = {
18 | show: false,
19 |
20 | width: 0,
21 | height: 0,
22 |
23 | pageX: 0,
24 | pageY: 0,
25 |
26 | positionX: 0,
27 | positionY: 0,
28 |
29 | items: [],
30 | onSelect: () => { }
31 | };
32 | }
33 |
34 | _show(items, positionX, positionY, width, height, onSelect) {
35 | positionX = positionX - this.state.pageX;
36 | positionY = positionY - this.state.pageY;
37 |
38 | this.setState({
39 | ...this.state,
40 | positionX,
41 | positionY,
42 | width,
43 | height,
44 | items,
45 | onSelect,
46 | show: true
47 | });
48 | }
49 |
50 | _onOverlayPress() {
51 | const { onSelect } = this.state;
52 | onSelect(null, null);
53 |
54 | this.setState({
55 | ...this.state,
56 | show: false
57 | });
58 | }
59 |
60 | _onItemPress(item, value) {
61 | const { onSelect } = this.state;
62 | onSelect(item, value);
63 |
64 | this.setState({
65 | ...this.state,
66 | show: false
67 | });
68 | }
69 |
70 | _blur() {
71 | this.setState({
72 | ...this.state,
73 | show : false
74 | });
75 | }
76 |
77 | render() {
78 | const {
79 | items,
80 | pageX,
81 | pageY,
82 | positionX,
83 | positionY,
84 | width,
85 | height,
86 | show
87 | } = this.state;
88 | const {
89 | overlayStyles,
90 | itemsStyles
91 | } = this.props;
92 | return (
93 |
99 |
108 |
109 | );
110 | }
111 | }
112 |
113 | OptionList.propTypes = {
114 |
115 | };
116 |
117 | OptionList.defaultProps = {
118 |
119 | };
120 |
121 | module.exports = OptionList;
122 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | # React Native Selectme
3 | Simple DropDown menu for React Native App! Your Select Tag for React Native.
4 |
5 |
6 | ## Alternatives :
7 |
8 | [react-native-chooser](https://github.com/gs-akhan/react-native-chooser) : This is an upgraded and simple-to-use API. You can customize it to fullest.
9 |
10 |
11 | ## Introduction
12 |
13 | React Native Selectme is simple, customizable and easy to use dropdown in React Native. It has been tested on both Android and IOS and works like a charm.
14 |
15 | ## Installation
16 | ```
17 | npm i react-native-selectme --save
18 | ```
19 |
20 | ## Usage
21 | Require it inside your Javascript files. Also supporting components using object-deconstructing.
22 | ```Select``` ```Option``` ```OptionList```.
23 |
24 | `````` Is to be used to append the options. This has to be placed as a last component so that it take the highest Z-Index.
25 |
26 | ## Example
27 |
28 | ```jsx
29 | import React, {
30 | Component,
31 | AppRegistry,
32 | Text,
33 | View,
34 | } from 'react-native';
35 |
36 | import DropDown, {
37 | Select,
38 | Option,
39 | OptionList,
40 | } from 'react-native-selectme';
41 |
42 | class App extends Component {
43 | constructor(props) {
44 | super(props);
45 |
46 | this.state = {
47 | canada: ''
48 | };
49 | }
50 |
51 | _getOptionList() {
52 | return this.refs['OPTIONLIST'];
53 | }
54 |
55 |
56 | _canada(province) {
57 |
58 | this.setState({
59 | ...this.state,
60 | canada: province
61 | });
62 | }
63 |
64 | render() {
65 | return (
66 |
67 |
87 |
88 | Selected Canada's province: {this.state.canada}
89 |
90 |
91 |
92 | );
93 | }
94 | }
95 |
96 | AppRegistry.registerComponent('App', () => App);
97 |
98 |
99 | ```
100 |
101 | ### Configuration
102 |
103 | ##### Select:
104 | | Property | Type | Default | Description |
105 | |---------------|----------|--------------|----------------------------------------------------------------|
106 | | width | number | 400 | Width of the selection |
107 | | onSelect | function(text, value) | null | function to be invoked when option is selected |
108 | | height | number | 50 | Height of the selection |
109 | | optionListRef | function | required | Reference to `````` to display the selection menu |
110 | | style | object | null | Custom styles to be applied if supplied |
111 | | defaultValue | string | first option | The value to be displayed if none of the options are selected. |
112 |
113 | ```blur()``` : close the select by calling blur ```this.refs.SELECT1.blur();```
114 |
115 |
116 | ##### Option:
117 |
118 | | Property | Type | Default | Description |
119 | |-----------|--------|---------|--------------------------------------------|
120 | | value | any | null | value will be passed on callback `onSelect` as second argument |
121 | | style | object | null | Styles to be applied on 'Option' component |
122 | | styleText | object | null | Styles to be applied on text inside of 'Option' |
123 |
124 |
125 | ##### OptionList:
126 |
127 | | Property | Type | Default | Description |
128 | |-----------|--------|---------|--------------------------------------------|
129 | | overlayStyles | object | null | Styles to be applied on 'overlay' backdrop |
130 | | itemsStyles | object | null | Styles to be applied on 'items' dropdown |
131 |
132 |
133 | ## Demo
134 | ##### IOS and Android:
135 |
136 |
137 |
138 |
139 | ## Contributions
140 | Your contributions and suggestions are heartily♡ welcome. (✿◠‿◠)
141 |
--------------------------------------------------------------------------------