Skip to content

Commit 86e56bf

Browse files
authored
V3 (#386)
* ♻️ Rewrite OTPInput core * ✨ Add new example * πŸ”§ Update build steps * πŸ“ Documentation updates * ♻️ Make text the default type for input * ✨ Add a select input for type in demo * πŸ”₯ Remove unused assets * πŸ› Fix focusing next/previous input not working when using arrow keys * πŸ”– v3.0.0 * πŸ› Hotfix for type error in example * ♻️ Create isInputNum for checking number inputs * πŸ”§ Add newline at end of file * πŸ“ Udpate readme
1 parent 6076cb6 commit 86e56bf

25 files changed

+3739
-11746
lines changed

β€Ž.eslintrc.json

+19-20
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,28 @@
11
{
22
"env": {
3-
"browser": true
3+
"browser": true,
4+
"es2021": true
45
},
5-
"parser": "@babel/eslint-parser",
6+
"extends": [
7+
"eslint:recommended",
8+
"plugin:react/recommended",
9+
"plugin:@typescript-eslint/recommended",
10+
"prettier"
11+
],
12+
"parser": "@typescript-eslint/parser",
613
"parserOptions": {
7-
"ecmaFeatures": {
8-
"jsx": true
9-
},
10-
"sourceType": "module"
14+
"ecmaFeatures": {
15+
"jsx": true
16+
},
17+
"ecmaVersion": "latest",
18+
"sourceType": "module"
1119
},
12-
"settings": {
13-
"react": {
14-
"version": "detect"
15-
}
16-
},
17-
"extends": [
18-
"eslint:recommended",
19-
"plugin:react/recommended",
20-
"plugin:react-hooks/recommended",
21-
"plugin:import/recommended",
22-
"plugin:prettier/recommended",
23-
"prettier"
20+
"plugins": [
21+
"react",
22+
"@typescript-eslint",
23+
"prettier"
2424
],
2525
"rules": {
26-
"no-unused-vars": "off",
27-
"react/prop-types": "off"
26+
"prettier/prettier": ["error"]
2827
}
2928
}

β€Ž.github/workflows/github-page.yml

+4-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: Build Example Site
22
on:
33
push:
44
branches:
5-
- master
5+
- main
66

77
jobs:
88
build-and-deploy:
@@ -15,13 +15,14 @@ jobs:
1515

1616
- name: Install and Build πŸ”§
1717
run: |
18+
cd example
1819
npm install
19-
npm run demo:prod
20+
npm run build
2021
2122
- name: Deploy πŸš€
2223
uses: JamesIves/[email protected]
2324
with:
2425
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
2526
BRANCH: gh-pages
26-
FOLDER: demo
27+
FOLDER: example/dist
2728
CLEAN: true

β€ŽLICENSE

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
The MIT License (MIT)
22

3-
Copyright (c) 2018 - 2020 Ajay NS
3+
Copyright (c) 2018 - 2023, Devfolio
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

β€ŽREADME.md

+48-86
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ A fully customizable, one-time password input component for the web built with R
1010
![see here](https://media.giphy.com/media/lN98dFU6h3oP0wWS5x/giphy.gif)
1111

1212
[Live Demo](https://devfolioco.github.io/react-otp-input)
13-
14-
[CodeSandbox](https://codesandbox.io/s/react-otp-input-demo-v2-1iy52)
13+
<!--
14+
[CodeSandbox](https://codesandbox.io/s/react-otp-input-demo-v2-1iy52) -->
1515

1616
## Installation
1717

@@ -23,27 +23,27 @@ A fully customizable, one-time password input component for the web built with R
2323
npm install --save react-otp-input
2424
```
2525

26+
### Still using v2?
27+
No problem! You can find the documentation for v2 [here](https://github.com/devfolioco/react-otp-input/tree/v2.4.0)
28+
2629
#### Basic usage:
2730

2831
```jsx
29-
import React, { Component } from 'react';
32+
import React, { useState } from 'react';
3033
import OtpInput from 'react-otp-input';
3134

32-
export default class App extends Component {
33-
state = { otp: '' };
34-
35-
handleChange = (otp) => this.setState({ otp });
36-
37-
render() {
38-
return (
39-
<OtpInput
40-
value={this.state.otp}
41-
onChange={this.handleChange}
42-
numInputs={6}
43-
separator={<span>-</span>}
44-
/>
45-
);
46-
}
35+
export default function App() {
36+
const [otp, setOtp] = useState('');
37+
38+
return (
39+
<OtpInput
40+
value={otp}
41+
onChange={setOtp}
42+
numInputs={4}
43+
renderSeparator={<span>-</span>}
44+
renderInput={(props) => <input {...props} />}
45+
/>
46+
);
4747
}
4848
```
4949

@@ -64,6 +64,15 @@ export default class App extends Component {
6464
<td>4</td>
6565
<td>Number of OTP inputs to be rendered.</td>
6666
</tr>
67+
<tr>
68+
<td>renderInput</td>
69+
<td>function</td>
70+
<td>true</td>
71+
<td>none</td>
72+
<td>A function that returns the input that is supposed to be rendered for each of the input fields.
73+
The function will get two arguments: <code>inputProps</code> and <code>index</code>. <code>inputProps</code> is an object that contains all the props <b>that should be passed to the input being rendered</b> (Overriding these props is not recommended because it might lead to some unexpected behaviour). <code>index</code> is the index of the input being rendered.
74+
</td>
75+
</tr>
6776
<tr>
6877
<td>onChange</td>
6978
<td>function</td>
@@ -86,11 +95,11 @@ export default class App extends Component {
8695
<td>Specify an expected value of each input. The length of this string should be equal to <code>numInputs</code>.</td>
8796
</tr>
8897
<tr>
89-
<td>separator</td>
90-
<td>component<br/></td>
98+
<td>renderSeparator</td>
99+
<td>component / function<br/></td>
91100
<td>false</td>
92101
<td>none</td>
93-
<td>Provide a custom separator between inputs by passing a component. For instance, <code>&lt;span&gt;-&lt;/span&gt;</code> would add <code>-</code> between each input.</td>
102+
<td>Provide a custom separator between inputs by passing a component. For instance, <code>&lt;span&gt;-&lt;/span&gt;</code> would add <code>-</code> between each input.</td> You can also pass a function that returns a component, where the function will get the index of the separator being rendered as an argument.
94103
</tr>
95104
<tr>
96105
<td>containerStyle</td>
@@ -107,39 +116,11 @@ export default class App extends Component {
107116
<td>Style applied or class passed to each input.</td>
108117
</tr>
109118
<tr>
110-
<td>focusStyle</td>
111-
<td>style (object) / className (string)</td>
112-
<td>false</td>
113-
<td>none</td>
114-
<td>Style applied or class passed to inputs on focus.</td>
115-
</tr>
116-
<tr>
117-
<td>isDisabled</td>
118-
<td>boolean</td>
119-
<td>false</td>
120-
<td>false</td>
121-
<td>Disables all the inputs.</td>
122-
</tr>
123-
<tr>
124-
<td>disabledStyle</td>
125-
<td>style (object) / className (string)</td>
126-
<td>false</td>
127-
<td>none</td>
128-
<td>Style applied or class passed to each input when disabled.</td>
129-
</tr>
130-
<tr>
131-
<td>hasErrored</td>
132-
<td>boolean</td>
133-
<td>false</td>
134-
<td>false</td>
135-
<td>Indicates there is an error in the inputs.</td>
136-
</tr>
137-
<tr>
138-
<td>errorStyle</td>
139-
<td>style (object) / className (string)</td>
119+
<td>inputType</td>
120+
<td><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Input#input_types">&lt;input&gt; type<a></td>
140121
<td>false</td>
141-
<td>none</td>
142-
<td>Style applied or class passed to each input when errored.</td>
122+
<td>text</td>
123+
<td>The type of the input that will be passed to the input element being rendered. In v2 <code>isInputNum</code> used to set the input type as <code>tel</code> and prevented non numerical entries, so as to avoid the spin buttons added to the inputs with input type <code>number</code>. That behaviour is still supported if you pass <code>tel</code> to the inputType prop.</td>
143124
</tr>
144125
<tr>
145126
<td>shouldAutoFocus</td>
@@ -148,56 +129,37 @@ export default class App extends Component {
148129
<td>false</td>
149130
<td>Auto focuses input on initial page load.</td>
150131
</tr>
151-
<tr>
152-
<td>isInputNum</td>
153-
<td>boolean</td>
154-
<td>false</td>
155-
<td>false</td>
156-
<td>Restrict input to only numbers.</td>
157-
</tr>
158-
<tr>
159-
<td>isInputSecure</td>
160-
<td>boolean</td>
161-
<td>false</td>
162-
<td>false</td>
163-
<td>Masks input characters.</td>
164-
</tr>
165-
<tr>
166-
<td>data-cy</td>
167-
<td>string</td>
168-
<td>false</td>
169-
<td>-</td>
170-
<td>Test attribute passed to the inputs.</td>
171-
</tr>
172-
<tr>
173-
<td>data-testid</td>
174-
<td>string</td>
175-
<td>false</td>
176-
<td>-</td>
177-
<td>Test attribute passed to the inputs.</td>
178-
</tr>
179132
</table>
180133

181-
## Breaking changes when porting to v1.0.0
134+
## Migrating from v2
135+
136+
The v3 of `react-otp-input` is a complete rewrite of the library. Apart from making the API more customizable and flexible, this version is a complete rewrite of the library using TypeScript and React Hooks. Here are the breaking changes that you need to be aware of:
137+
138+
- You now need to pass your own custom input component that will be rendered for each of the input fields via `renderInput` prop. This gives you the flexibility to customize the input fields as you desire. This also means that props like `focusStyle`, `isDisabled`, `disabledStyle`, `hasErrored`, `errorStyle`, `isInputNum`, `isInputSecure`, `data-cy` and `data-testid` are no longer supported. You can achieve the same functionality and more by passing the relevant props directly to the input component that you return from the `renderInput` prop.
139+
140+
- The `separator` prop has now been renamed to `renderSeparator`. This prop now apart from accepting a component that will be rendered as a separator between inputs like it used to, now also accepts a function that returns a component. The function will get the index of the separator being rendered as an argument.
141+
142+
- A new prop called `inputType` has been added to the component. This prop can be used to specify the type of the input that will be passed to the input element being rendered. The default value of this prop is `number`.
143+
144+
## Migrating from v1
182145

183146
`react-otp-input` is now a controlled component to facilitate functionalities that weren't possible before from the application using it, such as clearing or pre-assigning values. For `v1.0.0` and above, a `value` prop needs to be passed in the component for it to function as expected.
184147

185148
## Development
186149

187-
#### To run the development server:
150+
#### To run the vite example:
188151

189152
```
153+
cd example
190154
npm run dev
191155
```
192156

193157
## Checklist
194158

195159
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat&logo=github)](https://github.com/devfolioco/react-otp-input/pulls) [![Open Source Love](https://badges.frapsoft.com/os/v2/open-source.svg?v=103)](https://github.com/devfolioco/react-otp-input)
196160

197-
- [x] Add flowtypes
198-
- [x] Add ESLint, Prettier for code quality
199-
- [x] Add styling support for states including focus/disabled
200161
- [ ] Write tests
162+
- [ ] Add actions for lint checks and tests
201163

202164
## Contributing
203165

β€Žexample/.gitignore

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Logs
2+
logs
3+
*.log
4+
npm-debug.log*
5+
yarn-debug.log*
6+
yarn-error.log*
7+
pnpm-debug.log*
8+
lerna-debug.log*
9+
10+
node_modules
11+
dist
12+
dist-ssr
13+
*.local
14+
15+
# Editor directories and files
16+
.vscode/*
17+
!.vscode/extensions.json
18+
.idea
19+
.DS_Store
20+
*.suo
21+
*.ntvs*
22+
*.njsproj
23+
*.sln
24+
*.sw?
25+
.vercel

β€Žsrc/demo/index.html renamed to β€Žexample/index.html

+3-6
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,12 @@
33
<head>
44
<meta charset="UTF-8" />
55
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6-
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
7-
<meta name="description" content="React Component for handling OTP inputs" />
8-
<title>react-otp-input</title>
9-
6+
<title>react-otp-input demo</title>
107
<link href="https://fonts.googleapis.com/css?family=Lato" rel="stylesheet" />
118
<link href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.0/normalize.min.css" rel="stylesheet" />
129
</head>
13-
1410
<body>
15-
<div id="app"></div>
11+
<div id="root"></div>
12+
<script type="module" src="/src/main.tsx"></script>
1613
</body>
1714
</html>

β€Žexample/package.json

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"name": "example",
3+
"private": true,
4+
"version": "0.0.0",
5+
"type": "module",
6+
"scripts": {
7+
"dev": "vite",
8+
"build": "tsc && vite build",
9+
"preview": "vite preview"
10+
},
11+
"dependencies": {
12+
"react": "^18.2.0",
13+
"react-dom": "^18.2.0"
14+
},
15+
"devDependencies": {
16+
"@types/react": "^18.0.28",
17+
"@types/react-dom": "^18.0.11",
18+
"@vitejs/plugin-react": "^3.1.0",
19+
"typescript": "^4.9.3",
20+
"vite": "^4.2.0"
21+
}
22+
}

0 commit comments

Comments
Β (0)