├── 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 | --------------------------------------------------------------------------------