├── .gitignore
├── .npmignore
├── README.md
├── example
└── App.js
├── index.d.ts
├── index.js
├── package.json
└── screenshot.png
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .watchmanconfig
3 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | .idea
2 | .github
3 | example/
4 | screenshot.png
5 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # React Native Keycode
2 |
3 | Show the user a input form for a fixed-length code or password.
4 |
5 |
6 |
7 | |
8 |
9 |
10 | ## Installation
11 |
12 | ```
13 | npm i -S react-native-keycode # or: yarn add react-native-keycode
14 | ```
15 |
16 |
17 | ## Usage
18 |
19 | ```
20 | // import statement:
21 | import { KeycodeInput } from 'react-native-keycode'
22 |
23 | // in your render function:
24 | {
26 | alert(value)
27 | }}
28 | />
29 | ```
30 |
31 | ### Complete example
32 | View a more complex example here: [example/App.js](example/App.js).
33 |
34 | ### Props
35 | * number `length`: number of characters in input (default: 4)
36 | * string `textColor`: color string for the color of the characters (default: black)
37 | * string `tintColor`: color string for the color of the active bottom bar (default: iOS blue)
38 | * string `defaultValue`: default ''
39 | * string `value`: default ''
40 | * boolean `uppercase`: default true
41 | * boolean `autoFocus`: default true
42 | * boolean `alphaNumeric`: default true, set to false to allow other characters than 0-9, A-Z
43 | * boolean `numberic`: default false
44 | * object `style`
45 | * function `onComplete`
46 | * function `onChange`
47 | * function `ref`
48 |
49 |
50 | ## Authors
51 |
52 | This library is developed by [Includable](https://includable.com/), a creative app and web platform
53 | development agency based in Amsterdam, The Netherlands.
54 |
55 | * Thomas Schoffelen, [@tschoffelen](https://twitter.com/tschoffelen)
56 |
--------------------------------------------------------------------------------
/example/App.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react';
2 | import { Text, View, StyleSheet, Button } from 'react-native';
3 | import { KeycodeInput } from './index';
4 |
5 | const App = () => {
6 | const [value, setValue] = useState('');
7 | const [numeric, setNumeric] = useState(false);
8 | return (
9 |
10 |
11 | Enter your access code
12 |
13 | setValue(newValue)}
17 | onComplete={(completedValue) => {
18 | alert('Completed! Value: ' + completedValue);
19 | }}/>
20 |
21 |
22 |
38 |
39 |
40 | );
41 | };
42 |
43 | export default App;
44 |
45 | const styles = StyleSheet.create({
46 | container: {
47 | flex: 1,
48 | alignItems: 'center',
49 | justifyContent: 'center',
50 | backgroundColor: '#fff',
51 | paddingBottom: 200
52 | },
53 | text: {
54 | fontSize: 18,
55 | marginBottom: 32
56 | },
57 | button: {
58 | marginTop: 96
59 | }
60 | });
61 |
--------------------------------------------------------------------------------
/index.d.ts:
--------------------------------------------------------------------------------
1 | declare module 'react-native-keycode' {
2 | export interface KeycodeInputProps {
3 | length?: number
4 | tintColor?: string
5 | textColor?: string
6 | onChange?: (value: string) => void
7 | onComplete?: (value: string) => void
8 | autoFocus?: bool
9 | uppercase?: bool
10 | alphaNumeric?: bool
11 | numeric?: bool
12 | value?: string
13 | style?: any
14 | inputRef?: (ref: React.RefObject) => void
15 | }
16 |
17 | export const KeycodeInput: React.FC
18 | }
19 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * React Native Keycode
3 | *
4 | * This file supports both iOS and Android.
5 | */
6 |
7 | import React, { useState, useEffect } from 'react';
8 | import { View, TextInput, Text, StyleSheet, Platform } from 'react-native';
9 | import PropTypes from 'prop-types';
10 |
11 | export const KeycodeInput = (props) => {
12 | const [inputValue, setInputValue] = useState(props.defaultValue);
13 | useEffect(() => {
14 | if (props.value !== undefined && props.value !== inputValue) {
15 | setInputValue(props.value);
16 | }
17 | }, [props.value]);
18 |
19 | if (props.value !== undefined && !props.onChange) {
20 | throw new Error(
21 | 'To use the KeycodeInput as a controlled component, ' +
22 | 'you need to supply both the value and onChange props.'
23 | );
24 | }
25 |
26 | const changeText = (value) => {
27 | if (props.uppercase) {
28 | value = value.toUpperCase();
29 | }
30 | if (props.alphaNumeric) {
31 | value = value.replace('/[^a-z0-9]/i', '');
32 | }
33 |
34 | setInputValue(value);
35 |
36 | if (props.onChange) {
37 | props.onChange(value);
38 | }
39 |
40 | if (value.length < props.length) {
41 | return;
42 | }
43 |
44 | if (props.onComplete) {
45 | props.onComplete(value);
46 | }
47 | };
48 |
49 | const renderBoxes = () => {
50 | let elements = [];
51 | let i = 0;
52 | let vals = inputValue.split('');
53 | while (i < props.length) {
54 | let active = i === inputValue.length;
55 | let barStyles = [styles.bar, active ? [styles.barActive, { backgroundColor: props.tintColor }] : []];
56 |
57 | elements.push(
58 |
59 |
60 | {vals[i] || ""}
61 |
62 |
63 |
64 | );
65 |
66 | i++;
67 | }
68 |
69 | return elements;
70 | };
71 |
72 | let keyboardType = props.numeric ? 'numeric' : (Platform.OS === 'ios' ? 'ascii-capable' : 'default');
73 |
74 | return (
75 |
76 | {renderBoxes()}
77 | {
79 | if (props.inputRef) {
80 | props.inputRef(component);
81 | }
82 | }}
83 | style={[styles.input, { color: props.textColor, width: 42 * props.length }]}
84 | autoFocus={props.autoFocus}
85 | autoCorrect={false}
86 | autoCapitalize='characters'
87 | value={inputValue}
88 | blurOnSubmit={false}
89 | keyboardType={keyboardType}
90 | maxLength={props.length}
91 | disableFullscreenUI
92 | clearButtonMode='never'
93 | spellCheck={false}
94 | returnKeyType='go'
95 | underlineColorAndroid='transparent'
96 | onChangeText={(text) => changeText(text)}
97 | caretHidden/>
98 |
99 | );
100 | };
101 |
102 | KeycodeInput.propTypes = {
103 | length: PropTypes.number,
104 | tintColor: PropTypes.string,
105 | textColor: PropTypes.string,
106 | onChange: PropTypes.func,
107 | onComplete: PropTypes.func,
108 | autoFocus: PropTypes.bool,
109 | uppercase: PropTypes.bool,
110 | alphaNumeric: PropTypes.bool,
111 | numeric: PropTypes.bool,
112 | value: PropTypes.string,
113 | style: PropTypes.any,
114 | inputRef: PropTypes.func
115 | };
116 |
117 | KeycodeInput.defaultProps = {
118 | tintColor: '#007AFF',
119 | textColor: '#000',
120 | length: 4,
121 | autoFocus: true,
122 | numeric: false,
123 | alphaNumeric: true,
124 | uppercase: true,
125 | defaultValue: ''
126 | };
127 |
128 | const styles = StyleSheet.create({
129 | container: {
130 | flexDirection: 'row',
131 | alignItems: 'center',
132 | position: 'relative'
133 | },
134 | input: {
135 | height: 48,
136 | position: 'absolute',
137 | opacity: 0,
138 | zIndex: 100
139 | },
140 | box: {
141 | width: 32,
142 | marginHorizontal: 5
143 | },
144 | bar: {
145 | backgroundColor: '#CED5DB',
146 | height: 1,
147 | width: 32
148 | },
149 | barActive: {
150 | height: 2,
151 | marginTop: -0.5
152 | },
153 | text: {
154 | fontSize: 32,
155 | fontWeight: '600',
156 | lineHeight: 36,
157 | height: 36,
158 | textAlign: 'center',
159 | width: 32,
160 | marginBottom: 8
161 | }
162 | });
163 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-native-keycode",
3 | "version": "1.1.2",
4 | "description": "Show the user a input form for a fixed-length code or password.",
5 | "main": "index.js",
6 | "repository": {
7 | "type": "git",
8 | "url": "git+https://github.com/includable/react-native-keycode.git"
9 | },
10 | "keywords": [
11 | "react-native",
12 | "react-component",
13 | "code",
14 | "password",
15 | "input",
16 | "react",
17 | "ios",
18 | "android"
19 | ],
20 | "author": "Thomas Schoffelen (https://includable.com/)",
21 | "license": "MIT",
22 | "bugs": {
23 | "url": "https://github.com/includable/react-native-keycode/issues"
24 | },
25 | "homepage": "https://github.com/includable/react-native-keycode#readme",
26 | "dependencies": {
27 | "prop-types": "^15.7.2"
28 | },
29 | "peerDependencies": {
30 | "react": ">=16.8.0",
31 | "react-native": ">=0.59.0"
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tschoffelen/react-native-keycode/0a9d60a3dca7a9884391e640e4d5b0d5ad698e8c/screenshot.png
--------------------------------------------------------------------------------