diff --git a/README.md b/README.md
index 799fe11..9fded2b 100644
--- a/README.md
+++ b/README.md
@@ -80,6 +80,7 @@ This component uses the same props as [](https://facebook.github.io/
Prop | Type | Default | Description
---------- | ------- | ---------- | -----------------------
`codeLength` | number | 5 | length of confirmation code -> number of cells
+`keyboardType` | string | `default` | determines which keyboard to open
`compareWithCode` | string | | code to compare. if null, onFulfill callback return inputted code to check later
`inputPosition` | string | `center` | position of code input in its container: `left`, `right`, `center`, `full-width`
`size` | number | 40 | size of input cells
diff --git a/components/ConfirmationCodeInput.js b/components/ConfirmationCodeInput.js
index 239c85a..fa21ff0 100644
--- a/components/ConfirmationCodeInput.js
+++ b/components/ConfirmationCodeInput.js
@@ -1,4 +1,4 @@
-import React, {Component} from 'react';
+import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { View, TextInput, StyleSheet, Dimensions, ViewPropTypes } from 'react-native';
import _ from 'lodash';
@@ -7,290 +7,292 @@ import _ from 'lodash';
const viewPropTypes = ViewPropTypes || View.propTypes;
export default class ConfirmationCodeInput extends Component {
- static propTypes = {
- codeLength: PropTypes.number,
- compareWithCode: PropTypes.string,
- inputPosition: PropTypes.string,
- size: PropTypes.number,
- space: PropTypes.number,
- className: PropTypes.string,
- cellBorderWidth: PropTypes.number,
- activeColor: PropTypes.string,
- inactiveColor: PropTypes.string,
- ignoreCase: PropTypes.bool,
- autoFocus: PropTypes.bool,
- codeInputStyle: TextInput.propTypes.style,
- containerStyle: viewPropTypes.style,
- onFulfill: PropTypes.func,
- };
-
- static defaultProps = {
- codeLength: 5,
- inputPosition: 'center',
- autoFocus: true,
- size: 40,
- className: 'border-box',
- cellBorderWidth: 1,
- activeColor: 'rgba(255, 255, 255, 1)',
- inactiveColor: 'rgba(255, 255, 255, 0.2)',
- space: 8,
- compareWithCode: '',
- ignoreCase: false
- };
-
- constructor(props) {
- super(props);
-
- this.state = {
- codeArr: new Array(this.props.codeLength).fill(''),
- currentIndex: 0
+ static propTypes = {
+ codeLength: PropTypes.number,
+ compareWithCode: PropTypes.string,
+ inputPosition: PropTypes.string,
+ size: PropTypes.number,
+ space: PropTypes.number,
+ className: PropTypes.string,
+ cellBorderWidth: PropTypes.number,
+ activeColor: PropTypes.string,
+ inactiveColor: PropTypes.string,
+ ignoreCase: PropTypes.bool,
+ autoFocus: PropTypes.bool,
+ codeInputStyle: TextInput.propTypes.style,
+ containerStyle: viewPropTypes.style,
+ onFulfill: PropTypes.func,
+ keyboardType: PropTypes.string
};
-
- this.codeInputRefs = [];
- }
-
- componentDidMount() {
- const { compareWithCode, codeLength, inputPosition } = this.props;
- if (compareWithCode && compareWithCode.length !== codeLength) {
- console.error("Invalid props: compareWith length is not equal to codeLength");
+
+ static defaultProps = {
+ codeLength: 5,
+ inputPosition: 'center',
+ autoFocus: true,
+ size: 40,
+ className: 'border-box',
+ cellBorderWidth: 1,
+ activeColor: 'rgba(255, 255, 255, 1)',
+ inactiveColor: 'rgba(255, 255, 255, 0.2)',
+ space: 8,
+ compareWithCode: '',
+ ignoreCase: false
+ };
+
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ codeArr: new Array(this.props.codeLength).fill(''),
+ currentIndex: 0
+ };
+
+ this.codeInputRefs = [];
}
-
- if (_.indexOf(['center', 'left', 'right', 'full-width'], inputPosition) === -1) {
- console.error('Invalid input position. Must be in: center, left, right, full');
+
+ componentDidMount() {
+ const { compareWithCode, codeLength, inputPosition } = this.props;
+ if (compareWithCode && compareWithCode.length !== codeLength) {
+ console.error("Invalid props: compareWith length is not equal to codeLength");
+ }
+
+ if (_.indexOf(['center', 'left', 'right', 'full-width'], inputPosition) === -1) {
+ console.error('Invalid input position. Must be in: center, left, right, full');
+ }
}
- }
-
- clear() {
- this.setState({
- codeArr: new Array(this.props.codeLength).fill(''),
- currentIndex: 0
- });
- this._setFocus(0);
- }
-
- _setFocus(index) {
- this.codeInputRefs[index].focus();
- }
-
- _blur(index) {
- this.codeInputRefs[index].blur();
- }
-
- _onFocus(index) {
- let newCodeArr = _.clone(this.state.codeArr);
- const currentEmptyIndex = _.findIndex(newCodeArr, c => !c);
- if (currentEmptyIndex !== -1 && currentEmptyIndex < index) {
- return this._setFocus(currentEmptyIndex);
+
+ clear() {
+ this.setState({
+ codeArr: new Array(this.props.codeLength).fill(''),
+ currentIndex: 0
+ });
+ this._setFocus(0);
}
- for (const i in newCodeArr) {
- if (i >= index) {
- newCodeArr[i] = '';
- }
+
+ _setFocus(index) {
+ this.codeInputRefs[index].focus();
}
-
- this.setState({
- codeArr: newCodeArr,
- currentIndex: index
- })
- }
-
- _isMatchingCode(code, compareWithCode, ignoreCase = false) {
- if (ignoreCase) {
- return code.toLowerCase() == compareWithCode.toLowerCase();
+
+ _blur(index) {
+ this.codeInputRefs[index].blur();
}
- return code == compareWithCode;
- }
-
- _getContainerStyle(size, position) {
- switch (position) {
- case 'left':
- return {
- justifyContent: 'flex-start',
- height: size
- };
- case 'center':
- return {
- justifyContent: 'center',
- height: size
- };
- case 'right':
- return {
- justifyContent: 'flex-end',
- height: size
- };
- default:
- return {
- justifyContent: 'space-between',
- height: size
+
+ _onFocus(index) {
+ let newCodeArr = _.clone(this.state.codeArr);
+ const currentEmptyIndex = _.findIndex(newCodeArr, c => !c);
+ if (currentEmptyIndex !== -1 && currentEmptyIndex < index) {
+ return this._setFocus(currentEmptyIndex);
+ }
+ for (const i in newCodeArr) {
+ if (i >= index) {
+ newCodeArr[i] = '';
+ }
}
+
+ this.setState({
+ codeArr: newCodeArr,
+ currentIndex: index
+ })
}
- }
-
- _getInputSpaceStyle(space) {
- const { inputPosition } = this.props;
- switch (inputPosition) {
- case 'left':
- return {
- marginRight: space
- };
- case 'center':
- return {
- marginRight: space/2,
- marginLeft: space/2
- };
- case 'right':
- return {
- marginLeft: space
- };
- default:
- return {
- marginRight: 0,
- marginLeft: 0
- };
+
+ _isMatchingCode(code, compareWithCode, ignoreCase = false) {
+ if (ignoreCase) {
+ return code.toLowerCase() == compareWithCode.toLowerCase();
+ }
+ return code == compareWithCode;
}
- }
-
- _getClassStyle(className, active) {
- const { cellBorderWidth, activeColor, inactiveColor, space } = this.props;
- let classStyle = {
- ...this._getInputSpaceStyle(space),
- color: activeColor
- };
-
- switch (className) {
- case 'clear':
- return _.merge(classStyle, { borderWidth: 0 });
- case 'border-box':
- return _.merge(classStyle, {
- borderWidth: cellBorderWidth,
- borderColor: (active ? activeColor : inactiveColor)
- });
- case 'border-circle':
- return _.merge(classStyle, {
- borderWidth: cellBorderWidth,
- borderRadius: 50,
- borderColor: (active ? activeColor : inactiveColor)
- });
- case 'border-b':
- return _.merge(classStyle, {
- borderBottomWidth: cellBorderWidth,
- borderColor: (active ? activeColor : inactiveColor),
- });
- case 'border-b-t':
- return _.merge(classStyle, {
- borderTopWidth: cellBorderWidth,
- borderBottomWidth: cellBorderWidth,
- borderColor: (active ? activeColor : inactiveColor)
- });
- case 'border-l-r':
- return _.merge(classStyle, {
- borderLeftWidth: cellBorderWidth,
- borderRightWidth: cellBorderWidth,
- borderColor: (active ? activeColor : inactiveColor)
- });
- default:
- return className;
+
+ _getContainerStyle(size, position) {
+ switch (position) {
+ case 'left':
+ return {
+ justifyContent: 'flex-start',
+ height: size
+ };
+ case 'center':
+ return {
+ justifyContent: 'center',
+ height: size
+ };
+ case 'right':
+ return {
+ justifyContent: 'flex-end',
+ height: size
+ };
+ default:
+ return {
+ justifyContent: 'space-between',
+ height: size
+ }
+ }
}
- }
-
- _onKeyPress(e) {
- if (e.nativeEvent.key === 'Backspace') {
- const { currentIndex } = this.state;
- const nextIndex = currentIndex > 0 ? currentIndex - 1 : 0;
- this._setFocus(nextIndex);
+
+ _getInputSpaceStyle(space) {
+ const { inputPosition } = this.props;
+ switch (inputPosition) {
+ case 'left':
+ return {
+ marginRight: space
+ };
+ case 'center':
+ return {
+ marginRight: space / 2,
+ marginLeft: space / 2
+ };
+ case 'right':
+ return {
+ marginLeft: space
+ };
+ default:
+ return {
+ marginRight: 0,
+ marginLeft: 0
+ };
+ }
}
- }
-
- _onInputCode(character, index) {
- const { codeLength, onFulfill, compareWithCode, ignoreCase } = this.props;
- let newCodeArr = _.clone(this.state.codeArr);
- newCodeArr[index] = character;
-
- if (index == codeLength - 1) {
- const code = newCodeArr.join('');
-
- if (compareWithCode) {
- const isMatching = this._isMatchingCode(code, compareWithCode, ignoreCase);
- onFulfill(isMatching, code);
- !isMatching && this.clear();
- } else {
- onFulfill(code);
- }
- this._blur(this.state.currentIndex);
- } else {
- this._setFocus(this.state.currentIndex + 1);
+
+ _getClassStyle(className, active) {
+ const { cellBorderWidth, activeColor, inactiveColor, space } = this.props;
+ let classStyle = {
+ ...this._getInputSpaceStyle(space),
+ color: activeColor
+ };
+
+ switch (className) {
+ case 'clear':
+ return _.merge(classStyle, { borderWidth: 0 });
+ case 'border-box':
+ return _.merge(classStyle, {
+ borderWidth: cellBorderWidth,
+ borderColor: (active ? activeColor : inactiveColor)
+ });
+ case 'border-circle':
+ return _.merge(classStyle, {
+ borderWidth: cellBorderWidth,
+ borderRadius: 50,
+ borderColor: (active ? activeColor : inactiveColor)
+ });
+ case 'border-b':
+ return _.merge(classStyle, {
+ borderBottomWidth: cellBorderWidth,
+ borderColor: (active ? activeColor : inactiveColor),
+ });
+ case 'border-b-t':
+ return _.merge(classStyle, {
+ borderTopWidth: cellBorderWidth,
+ borderBottomWidth: cellBorderWidth,
+ borderColor: (active ? activeColor : inactiveColor)
+ });
+ case 'border-l-r':
+ return _.merge(classStyle, {
+ borderLeftWidth: cellBorderWidth,
+ borderRightWidth: cellBorderWidth,
+ borderColor: (active ? activeColor : inactiveColor)
+ });
+ default:
+ return className;
+ }
}
-
- this.setState(prevState => {
- return {
- codeArr: newCodeArr,
- currentIndex: prevState.currentIndex + 1
- };
- });
- }
-
- render() {
- const {
- codeLength,
- codeInputStyle,
- containerStyle,
- inputPosition,
- autoFocus,
- className,
- size,
- activeColor
- } = this.props;
-
- const initialCodeInputStyle = {
- width: size,
- height: size
- };
-
- let codeInputs = [];
- for (let i = 0; i < codeLength; i++) {
- const id = i;
- codeInputs.push(
- (this.codeInputRefs[id] = ref)}
- style={[
- styles.codeInput,
- initialCodeInputStyle,
- this._getClassStyle(className, this.state.currentIndex == id),
- codeInputStyle
- ]}
- underlineColorAndroid="transparent"
- selectionColor={activeColor}
- keyboardType={'name-phone-pad'}
- returnKeyType={'done'}
- {...this.props}
- autoFocus={autoFocus && id == 0}
- onFocus={() => this._onFocus(id)}
- value={this.state.codeArr[id] ? this.state.codeArr[id].toString() : ''}
- onChangeText={text => this._onInputCode(text, id)}
- onKeyPress={(e) => this._onKeyPress(e)}
- maxLength={1}
- />
- )
+
+ _onKeyPress(e) {
+ if (e.nativeEvent.key === 'Backspace') {
+ const { currentIndex } = this.state;
+ const nextIndex = currentIndex > 0 ? currentIndex - 1 : 0;
+ this._setFocus(nextIndex);
+ }
+ }
+
+ _onInputCode(character, index) {
+ const { codeLength, onFulfill, compareWithCode, ignoreCase } = this.props;
+ let newCodeArr = _.clone(this.state.codeArr);
+ newCodeArr[index] = character;
+
+ if (index == codeLength - 1) {
+ const code = newCodeArr.join('');
+
+ if (compareWithCode) {
+ const isMatching = this._isMatchingCode(code, compareWithCode, ignoreCase);
+ onFulfill(isMatching, code);
+ !isMatching && this.clear();
+ } else {
+ onFulfill(code);
+ }
+ this._blur(this.state.currentIndex);
+ } else {
+ this._setFocus(this.state.currentIndex + 1);
+ }
+
+ this.setState(prevState => {
+ return {
+ codeArr: newCodeArr,
+ currentIndex: prevState.currentIndex + 1
+ };
+ });
+ }
+
+ render() {
+ const {
+ codeLength,
+ codeInputStyle,
+ containerStyle,
+ inputPosition,
+ autoFocus,
+ className,
+ size,
+ activeColor,
+ keyboardType
+ } = this.props;
+
+ const initialCodeInputStyle = {
+ width: size,
+ height: size
+ };
+
+ let codeInputs = [];
+ for (let i = 0; i < codeLength; i++) {
+ const id = i;
+ codeInputs.push(
+ (this.codeInputRefs[id] = ref)}
+ style={[
+ styles.codeInput,
+ initialCodeInputStyle,
+ this._getClassStyle(className, this.state.currentIndex == id),
+ codeInputStyle
+ ]}
+ underlineColorAndroid="transparent"
+ selectionColor={activeColor}
+ keyboardType={keyboardType}
+ returnKeyType={'done'}
+ {...this.props}
+ autoFocus={autoFocus && id == 0}
+ onFocus={() => this._onFocus(id)}
+ value={this.state.codeArr[id] ? this.state.codeArr[id].toString() : ''}
+ onChangeText={text => this._onInputCode(text, id)}
+ onKeyPress={(e) => this._onKeyPress(e)}
+ maxLength={1}
+ />
+ )
+ }
+
+ return (
+
+ {codeInputs}
+
+ );
}
-
- return (
-
- {codeInputs}
-
- );
- }
}
const styles = StyleSheet.create({
- container: {
- flex: 1,
- flexDirection: 'row',
- marginTop: 20
- },
- codeInput: {
- backgroundColor: 'transparent',
- textAlign: 'center',
- padding: 0
- }
+ container: {
+ flex: 1,
+ flexDirection: 'row',
+ marginTop: 20
+ },
+ codeInput: {
+ backgroundColor: 'transparent',
+ textAlign: 'center',
+ padding: 0
+ }
});
diff --git a/index.d.ts b/index.d.ts
index 3473a5d..12f8e89 100644
--- a/index.d.ts
+++ b/index.d.ts
@@ -8,6 +8,7 @@ declare module "react-native-confirmation-code-input" {
interface CodeInputProps extends ReactNative.TextInputProperties {
codeLength?: number;
+ keyboardType?: ReactNative.KeyboardType;
compareWithCode?: string;
inputPosition?: InputPositions;
size?: number;