├── README.md
├── index.js
├── package.json
└── src
├── InputCountrySelector.js
├── InputSwitch.js
├── InputText.js
└── styles
├── styles.js
└── variables.js
/README.md:
--------------------------------------------------------------------------------
1 | # React Native Input List Components
2 |
3 | A React Native library with input components.
4 |
5 |
6 |
7 |
8 |
9 | ## Components
10 |
11 | * InputText - Text/Numeric input field
12 | * InputCountrySelector - Country selector input field
13 | * InputSwitch - Switch input field
14 |
15 | ## Install
16 |
17 | ```bash
18 | npm install --save react-native-input-list
19 | ```
20 |
21 | ## Usage
22 |
23 | ```js
24 | import React, { Component } from 'react';
25 | import { StyleSheet, Text, View, TouchableOpacity, Alert } from 'react-native';
26 | import { InputText, InputCountrySelector, InputSwitch } from 'react-native-input-list';
27 |
28 | export default class App extends Component {
29 |
30 | showValues = () => {
31 | const firstValue = `First input: ${this.refs.firstInput.value()}\n`;
32 | const secondValue = `Second input: ${this.refs.secondInput.value()}\n`;
33 | const thirdValue = `Third input: ${this.refs.thirdInput.value()}\n`;
34 | const fourthValue = `Fourth input: ${this.refs.fourthInput.value()}\n`;
35 | const fifthValue = `Fifth input: ${this.refs.fifthInput.value()}\n`;
36 | const sixthValue = `Sixth input: ${this.refs.sixthInput.value()}\n`;
37 |
38 | const text = firstValue + secondValue + thirdValue + fourthValue + fifthValue + sixthValue;
39 |
40 | Alert.alert(
41 | 'Values',
42 | text
43 | );
44 | }
45 |
46 | areValid = () => {
47 | const firstValid = `First input: ${!!this.refs.firstInput.valid()}\n`;
48 | const secondValid = `Second input: ${!!this.refs.secondInput.valid()}\n`;
49 | const thirdValid = `Third input: ${!!this.refs.thirdInput.valid()}\n`;
50 | const fourthValid = `Fourth input: ${!!this.refs.fourthInput.valid()}\n`;
51 | const fifthValid = `Fifth input: ${!!this.refs.fifthInput.valid()}\n`;
52 |
53 | const text = firstValid + secondValid + thirdValid + fourthValid + fifthValid;
54 |
55 | Alert.alert(
56 | 'Valid?',
57 | text
58 | );
59 | }
60 |
61 | showErrors = () => {
62 | this.refs.firstInput.showError();
63 | this.refs.secondInput.showError();
64 | this.refs.thirdInput.showError();
65 | this.refs.fourthInput.showError();
66 | this.refs.fifthInput.showError();
67 | }
68 |
69 | switchChanged = (value) => {
70 | alert(value);
71 | }
72 |
73 | render() {
74 | return (
75 |
76 | Inputs
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 | SHOW VALUES
88 |
89 |
90 | VALID?
91 |
92 |
93 | SHOW ERRORS
94 |
95 |
96 |
97 | );
98 | }
99 | }
100 |
101 | const styles = StyleSheet.create({
102 | container: {
103 | flex: 1,
104 | flexDirection: 'column',
105 | marginVertical: 40
106 | },
107 | title: {
108 | fontSize: 20,
109 | textAlign: 'center',
110 | margin: 10
111 | },
112 | action: {
113 | fontSize: 18,
114 | textAlign: 'center',
115 | margin: 10,
116 | color: 'blue'
117 | },
118 | inputStyles: {
119 | backgroundColor: 'green'
120 | }
121 | });
122 | ```
123 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | export { default as InputText } from './src/InputText';
2 | export { default as InputCountrySelector } from './src/InputCountrySelector';
3 | export { default as InputSwitch } from './src/InputSwitch';
4 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-native-input-list",
3 | "version": "1.6.8",
4 | "description": "A Input components library for React Native",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "Gaspard+Bruno ",
10 | "license": "ISC",
11 | "repository": {
12 | "type": "git",
13 | "url": "git+https://github.com/etudes-gaspardbruno/react-native-input-list.git"
14 | },
15 | "dependencies": {
16 | "react-native-country-picker-modal": "^0.6.0",
17 | "babel-preset-react-native-stage-0": "^1.0.1"
18 | },
19 | "peerDependencies": {
20 | "react": ">=15.4.0",
21 | "react-native": ">=0.40"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/InputCountrySelector.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import PropTypes from 'prop-types';
3 | import {
4 | Text,
5 | TouchableWithoutFeedback,
6 | View
7 | } from 'react-native';
8 | import CountryPicker from 'react-native-country-picker-modal';
9 |
10 | import generateStyles from './styles/styles';
11 | import defaultVariables from './styles/variables';
12 |
13 | let styles, variables;
14 |
15 | export default class InputCountrySelector extends Component {
16 |
17 | static propTypes = {
18 | // Config
19 | required: PropTypes.bool,
20 | type: PropTypes.string,
21 | keyboardType: PropTypes.string,
22 | excludeCountries: PropTypes.array,
23 |
24 | // Label & placeholder
25 | label: PropTypes.string,
26 | defaultValue: PropTypes.string,
27 |
28 | // Styles
29 | containerStyles: PropTypes.any,
30 | labelContainerStyles: PropTypes.any,
31 | labelStyles: PropTypes.any,
32 | valueContainerStyles: PropTypes.any,
33 | placeholderStyles: PropTypes.any,
34 | valueStyles: PropTypes.any,
35 | errorColor: PropTypes.string,
36 | }
37 |
38 | constructor(props) {
39 | variables = Object.assign({}, defaultVariables, props.styleVariables);
40 | styles = generateStyles(variables);
41 |
42 | super(props);
43 |
44 | this.state = {
45 | value: this.props.defaultValue || '',
46 | error: false,
47 | errorColor: props.errorColor || variables.red
48 | }
49 | }
50 |
51 | value() {
52 | return this.state.value;
53 | }
54 |
55 | valid() {
56 | return this.state.value && this.state.value.length > 0;
57 | }
58 |
59 | showError() {
60 | this.setState({ error: true });
61 | }
62 |
63 | _focusInput = () => {
64 | this.refs.input.openModal();
65 | }
66 |
67 | _updateInput = (value) => {
68 | this.setState({
69 | value: value.name,
70 | error: false
71 | });
72 | }
73 |
74 |
75 | render() {
76 | const { label, required, type, containerStyles, labelContainerStyles,
77 | labelStyles, valueContainerStyles, placeholderStyles, valueStyles,
78 | placeholderColor, excludeCountries } = this.props;
79 | const { value, error, errorColor } = this.state;
80 |
81 | const labelText = required ? `${label} *` : label;
82 | const placeholder = type === 'withLabel' ? '' : label;
83 | const valueText = value || placeholder;
84 |
85 | const containerStyle = [styles.formContainer, styles.countrySelectorContainer, containerStyles];
86 |
87 | const labelContainerStyle = [styles.formLabelContainer, labelContainerStyles];
88 | const labelStyle = error ? [styles.formLabel, labelStyles, styles.error] : [styles.formLabel, labelStyles];
89 |
90 | const valueContainerStyle = [styles.formValueContainer, valueContainerStyles];
91 | const placeholderStyle = error ? [styles.formValuePlaceholder, placeholderStyles, styles.error] : [styles.formValuePlaceholder, placeholderStyles];
92 | const valueStyle = value ? [styles.formValue, valueStyles] : [styles.formValue, valueStyles, placeholderStyle];
93 |
94 | const countryPickerStyle = styles.countryPicker;
95 |
96 | return (
97 |
98 | { type === 'withLabel' &&
99 |
100 |
101 | {labelText}
102 |
103 |
104 | }
105 |
106 |
107 |
108 | {valueText}
109 |
110 |
111 |
112 |
113 |
120 |
121 |
122 | );
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/src/InputSwitch.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import PropTypes from 'prop-types';
3 | import { Text, Switch, View } from 'react-native';
4 |
5 | import generateStyles from './styles/styles';
6 | import defaultVariables from './styles/variables';
7 |
8 | let styles, variables;
9 |
10 | export default class InputSwitch extends Component {
11 |
12 | static propTypes = {
13 | // Label & default value
14 | label: PropTypes.string,
15 | defaultValue: PropTypes.bool,
16 |
17 | // Styles
18 | containerStyles: PropTypes.any,
19 | labelContainerStyles: PropTypes.any,
20 | labelStyles: PropTypes.any,
21 | switchContainerStyles: PropTypes.any,
22 | tintColor: PropTypes.string,
23 |
24 | // Callback
25 | onChange: PropTypes.func
26 | }
27 |
28 | constructor(props) {
29 | variables = Object.assign({}, defaultVariables, props.styleVariables);
30 | styles = generateStyles(variables);
31 |
32 | super(props);
33 |
34 | this.state = {
35 | value: this.props.defaultValue || false,
36 | tintColor: props.tintColor || variables.yellow
37 | }
38 | }
39 |
40 | value() {
41 | return this.state.value;
42 | }
43 |
44 | valid() {
45 | return this.state.value && this.state.value.length > 0;
46 | }
47 |
48 | showError() {
49 | return;
50 | }
51 |
52 | _updateInput = (value) => {
53 | if (this.props.onChange) {
54 | this.props.onChange(value);
55 | }
56 |
57 | this.setState({
58 | value: value
59 | })
60 | }
61 |
62 | render() {
63 | const { label, containerStyles, labelContainerStyles, labelStyles,
64 | switchContainerStyles } = this.props;
65 | const { value, tintColor } = this.state;
66 |
67 | const containerStyle = [styles.formContainer, containerStyles];
68 | const labelContainerStyle = [styles.formLabelContainer, labelContainerStyles];
69 | const labelStyle = [styles.formSwitchLabel, labelStyles];
70 | const switchContainerStyle = [styles.switchContainer, switchContainerStyles];
71 |
72 | return (
73 |
74 |
75 | {label}
76 |
77 |
78 |
82 |
83 |
84 | );
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/src/InputText.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import PropTypes from 'prop-types';
3 | import {
4 | Text,
5 | TextInput,
6 | TouchableWithoutFeedback,
7 | View
8 | } from 'react-native';
9 |
10 | import generateStyles from './styles/styles';
11 | import defaultVariables from './styles/variables';
12 |
13 | let styles, variables;
14 |
15 | export default class InputText extends Component {
16 |
17 | static propTypes = {
18 | // Config
19 | required: PropTypes.bool,
20 | type: PropTypes.string,
21 | keyboardType: PropTypes.string,
22 | password: PropTypes.bool,
23 |
24 | // Label & placeholder
25 | label: PropTypes.string,
26 | defaultValue: PropTypes.string,
27 |
28 | // Styles
29 | containerStyles: PropTypes.any,
30 | labelContainerStyles: PropTypes.any,
31 | labelStyles: PropTypes.any,
32 | inputStyles: PropTypes.any,
33 | errorColor: PropTypes.string,
34 | placeholderColor: PropTypes.string
35 | }
36 |
37 | constructor(props) {
38 | variables = Object.assign({}, defaultVariables, props.styleVariables);
39 | styles = generateStyles(variables);
40 |
41 | super(props);
42 |
43 | this.state = {
44 | value: this.props.defaultValue || '',
45 | error: false,
46 | errorColor: props.errorColor || variables.red,
47 | placeholderColor: props.placeholderColor || variables.gray
48 | }
49 | }
50 |
51 | value() {
52 | return this.state.value;
53 | }
54 |
55 | valid() {
56 | return this.state.value && this.state.value.length > 0;
57 | }
58 |
59 | showError() {
60 | this.setState({ error: true });
61 | }
62 |
63 | _focusInput = () => {
64 | this.refs.input.focus();
65 | }
66 |
67 | _updateInput = (value) => {
68 | if (this.props.keyboardType === 'numeric') {
69 | value = this.parseNumericInput(value);
70 | }
71 |
72 | this.setState({
73 | value: value,
74 | error: false
75 | });
76 | }
77 |
78 | parseNumericInput(value) {
79 | let newValue = '';
80 | let numbers = '0123456789';
81 |
82 | for (var i = 0; i < value.length; i++) {
83 | if ( numbers.indexOf(value[i]) > -1 ) {
84 | newValue = newValue + value[i];
85 | }
86 | }
87 |
88 | return newValue;
89 | }
90 |
91 | render() {
92 | const { label, keyboardType, required, type, containerStyles, labelContainerStyles,
93 | labelStyles, inputStyles, password } = this.props;
94 | const { value, error, errorColor, placeholderColor } = this.state;
95 |
96 | const labelText = required ? `${label} *` : label;
97 | const placeholder = type === 'withLabel' ? '' : label;
98 | const secureTextEntry = password ? password : false;
99 |
100 | const containerStyle = [styles.formContainer, containerStyles];
101 | const labelContainerStyle = [styles.formLabelContainer, labelContainerStyles];
102 | const labelStyle = error ? [styles.formLabel, labelStyles, styles.error] : [styles.formLabel, labelStyles];
103 | const inputStyle = [styles.formInput, inputStyles];
104 | const placeholderTextColor = error ? errorColor : placeholderColor;
105 |
106 |
107 |
108 | return (
109 |
110 | { type === 'withLabel' &&
111 |
112 |
113 | {labelText}
114 |
115 |
116 | }
117 |
118 | this._updateInput(value)}
125 | underlineColorAndroid="transparent"
126 | value={value}
127 | placeholder={placeholder}
128 | placeholderTextColor={placeholderTextColor}
129 | secureTextEntry={secureTextEntry}
130 | {...this.props}
131 | />
132 |
133 | );
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/src/styles/styles.js:
--------------------------------------------------------------------------------
1 | import { StyleSheet, Dimensions, Platform } from 'react-native';
2 |
3 | const height = Dimensions.get('window').height;
4 | const width = Dimensions.get('window').width;
5 |
6 | export default function generateStyles(variables) {
7 | return StyleSheet.create({
8 | formContainer: {
9 | height: 52,
10 | backgroundColor: 'white',
11 | borderBottomWidth: 2,
12 | paddingHorizontal: 20,
13 | paddingVertical: Platform.OS === 'ios' ? 16 : 0,
14 | borderBottomColor: variables.lightestGray,
15 | flexDirection: 'row',
16 | justifyContent: 'space-between'
17 | },
18 | formLabelContainer: {
19 | flex: 1,
20 | justifyContent: 'center'
21 | },
22 | formLabel: {
23 | fontSize: 15,
24 | fontFamily: variables.font,
25 | color: variables.gray
26 | },
27 | formInput: {
28 | flex: 2,
29 | height: Platform.OS === 'ios' ? 18 : 50,
30 | paddingBottom: Platform.OS === 'ios' ? 0 : 10,
31 | fontSize: 16,
32 | fontFamily: variables.font,
33 | textAlign: 'left',
34 | alignItems: 'flex-start'
35 | },
36 | error: {
37 | color: variables.red
38 | },
39 | formValueContainer: {
40 | height: 18,
41 | flexDirection: 'row',
42 | justifyContent: 'space-between',
43 | alignItems: 'center'
44 | },
45 | formValue: {
46 | height: 18,
47 | lineHeight: 20,
48 | fontSize: 16,
49 | fontFamily: variables.font,
50 | },
51 | formValuePlaceholder: {
52 | color: variables.gray
53 | },
54 | countrySelectorContainer: {
55 | paddingVertical: 16,
56 | },
57 | countryPicker: {
58 | top: -height,
59 | opacity: 0
60 | },
61 | formSwitchLabel: {
62 | color: 'black',
63 | height: 18,
64 | lineHeight: 20,
65 | fontSize: 16,
66 | fontFamily: variables.font,
67 | },
68 | switchContainer: {
69 | flexDirection: 'row',
70 | justifyContent: 'space-between',
71 | alignItems: 'center'
72 | }
73 | });
74 | }
75 |
--------------------------------------------------------------------------------
/src/styles/variables.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | gray: '#AAAAAA',
3 | lightestGray: '#FAFAFA',
4 | red: '#D21A09',
5 | yellow: '#FFCC00',
6 |
7 | font: 'AvenirNext-Regular'
8 | }
9 |
--------------------------------------------------------------------------------