UNPKG

react-native-pretty-pincode

Version:
237 lines (216 loc) 5.36 kB
import React, { Component } from "react"; import { PropTypes } from "prop-types"; import { TextInput, View, Text, TouchableOpacity } from "react-native"; import _ from "lodash"; import Pin from "./pin"; import { codePinStyles } from "./pin-code-style"; class PrettyPin extends Component { constructor(props) { super(props); const codeLength = props.number || props.code.length; this.state = { error: "", number: codeLength, code: new Array(codeLength).fill(""), edit: null, reset: false, value: "", previousLength: 0 }; this.pin = []; this.clean = this.clean.bind(this); this.focus = this.focus.bind(this); this.handleEdit = this.handleEdit.bind(this); this.renderPins = this.renderPins.bind(this); } componentWillReceiveProps(newProps) { const codeLength = newProps.number || newProps.code.length; if (newProps.number !== this.props.number) { this.setState({ number: codeLength, edit: null }); } } renderPins() { const { obfuscation, pinColor, number } = this.props; const { value } = this.state; return value.split("").map((val, key) => ( <View key={key}> <Pin obfuscation={obfuscation} ref={ref => (this.pin[key] = ref)} pinColor={pinColor} value={val} styles={codePinStyles.pin} /> </View> )); } clean() { this.setState(prevState => { return { code: new Array(prevState.number).fill(""), reset: true, value: "", previousLength: 0 }; }, this.focus); this.setState({value: ''}) } focus() { // Check to ensure that input exists. This is important in the case of autofill. if (this.textInputsRefs) this.textInputsRefs.focus(); } async handleEdit(value) { // if (value.length > this.state.previousLength) { // this.pin[value.length - 1].sneak(); // this.pin[value.length - 1].show(); if (value.length > 1) { this.pin[this.state.previousLength].unSneak(); } // } else { // this.pin[this.state.previousLength].hide(); // } await this.setState( { value: value, previousLength: value.length > 0 ? value.length - 1 : 0, error: false }, () => { console.log("Value length", value.length); console.log("Previous length", this.state.previousLength); } ); console.log("Set Value successful"); // // App pass a checkPinCode function if (this.props.checkPinCode) { this.props.checkPinCode(value, (success = true) => { // App say it's different than code if (!success) { if (this.props.fail) { this.props.fail(); } this.setState({ error: this.props.error, code: new Array(this.state.number).fill(""), reset: true }); } else { // Is Okay !!! if (this.props.success) { this.props.success(); } this.setState(prevState => ({ code: value, reset: true })); } this.clean(); }); return; } // // no checkPinCode function // // But it's different than code if (this.props.code !== value) { this.setState({ error: this.props.error, code: new Array(this.state.number).fill(""), reset: true }); return; } } render() { const { text, success, pinStyle, textStyle, errorStyle, obfuscation, containerStyle, containerPinStyle, passwordText, pinColor, ...props } = this.props; const { value, number, reset, edit } = this.state; const error = this.state.error ? ( <Text style={[codePinStyles.error, errorStyle]}> {this.state.error} </Text> ) : null; return ( <View style={[codePinStyles.container, containerStyle]}> {!_.isEmpty(text) && ( <Text style={[codePinStyles.text, textStyle]}>{text}</Text> )} {error} <TouchableOpacity onPress={this.focus}> <View style={[ codePinStyles.containerPin, containerPinStyle, { borderBottomColor: pinColor, borderBottomWidth: 4 } ]} > {this.renderPins()} </View> </TouchableOpacity> <View style={{ opacity: 0, height: 0, margin: 0, padding: 0 }}> <TextInput ref={ref => (this.textInputsRefs = ref)} onChangeText={text => this.handleEdit(text)} value={value} maxLength={number} returnKeyType={"done"} autoCorrect={false} autoFocus={true} {...props} /> </View> </View> ); } } PrettyPin.propTypes = { code: PropTypes.string, success: PropTypes.func, fail: PropTypes.func, number: PropTypes.number, checkPinCode: PropTypes.func, autoFocusFirst: PropTypes.bool, obfuscation: PropTypes.bool, passwordText: PropTypes.string, pinColor: PropTypes.string, pinStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.number]), containerPinStyle: PropTypes.oneOfType([ PropTypes.object, PropTypes.number ]), containerStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.number]), textStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.number]), errorStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.number]) }; PrettyPin.defaultProps = { code: "", number: 4, checkPinCode: null, autoFocusFirst: true, obfuscation: false, passwordText: "*", pinColor: "#000", text: "", error: "Bad pin code.", pinStyle: {}, containerPinStyle: {}, containerStyle: {}, textStyle: {}, errorStyle: {} }; export default PrettyPin;