Skip to content

Commit 507249e

Browse files
authored
Merge pull request #5 from devfolioco/feat-error
Error handling and Classes support
2 parents 7d4c013 + 8ead9e8 commit 507249e

File tree

7 files changed

+83
-27
lines changed

7 files changed

+83
-27
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
node_modules
22
/lib
3-
demo
3+
/demo
44

55
# Editor config
66
.vscode

README.md

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -68,38 +68,52 @@ export default class App extends Component {
6868
</tr>
6969
<tr>
7070
<td>containerStyle</td>
71-
<td>style (object)</td>
71+
<td>style (object) / className (string)</td>
7272
<td>false</td>
7373
<td>none</td>
74-
<td>Style applied to container of inputs.</td>
74+
<td>Style applied or class passed to container of inputs.</td>
7575
</tr>
7676
<tr>
7777
<td>inputStyle</td>
78-
<td>style (object)</td>
78+
<td>style (object) / className (string)</td>
7979
<td>false</td>
8080
<td>none</td>
81-
<td>Style applied to each input.</td>
81+
<td>Style applied or class passed to each input.</td>
8282
</tr>
8383
<tr>
8484
<td>focusStyle</td>
85-
<td>style (object)</td>
85+
<td>style (object) / className (string)</td>
8686
<td>false</td>
8787
<td>none</td>
88-
<td>Style applied to inputs on focus.</td>
88+
<td>Style applied or class passed to inputs on focus.</td>
8989
</tr>
9090
<tr>
91-
<td>disabled</td>
91+
<td>isDisabled</td>
9292
<td>boolean</td>
9393
<td>false</td>
9494
<td>false</td>
9595
<td>Disables all the inputs.</td>
9696
</tr>
9797
<tr>
9898
<td>disabledStyle</td>
99-
<td>style (object)</td>
99+
<td>style (object) / className (string)</td>
100100
<td>false</td>
101101
<td>none</td>
102-
<td>Style applied to each input when disabled.</td>
102+
<td>Style applied or class passed to each input when disabled.</td>
103+
</tr>
104+
<tr>
105+
<td>hasErrored</td>
106+
<td>boolean</td>
107+
<td>false</td>
108+
<td>false</td>
109+
<td>Indicates there is an error in the inputs.</td>
110+
</tr>
111+
<tr>
112+
<td>errorStyle</td>
113+
<td>style (object) / className (string)</td>
114+
<td>false</td>
115+
<td>none</td>
116+
<td>Style applied or class passed to each input when errored.</td>
103117
</tr>
104118
<tr>
105119
<td>shouldAutoFocus</td>

src/docs/index.html renamed to src/demo/index.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
<meta charset="UTF-8">
66
<meta name="viewport" content="width=device-width, initial-scale=1.0">
77
<meta http-equiv="X-UA-Compatible" content="ie=edge">
8-
<meta name="description" content="CHANGE THIS">
9-
<title>React component starter</title>
8+
<meta name="description" content="React Component for handling OTP inputs">
9+
<title>react-otp-input</title>
1010

1111
<link href="https://fonts.googleapis.com/css?family=Lato" rel="stylesheet">
1212
<link href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.0/normalize.min.css" rel="stylesheet">

src/docs/index.jsx renamed to src/demo/index.jsx

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ class Demo extends Component {
1111
numInputs: 4,
1212
separator: '-',
1313
isDisabled: false,
14+
hasErrored: false,
1415
};
1516
}
1617

@@ -22,8 +23,9 @@ class Demo extends Component {
2223
this.setState({ [e.target.name]: e.target.value });
2324
};
2425

25-
handleCheck = () => {
26-
this.setState(prevState => ({ isDisabled: !prevState.isDisabled }));
26+
handleCheck = e => {
27+
const { name } = e.target;
28+
this.setState(prevState => ({ [name]: !prevState[name] }));
2729
};
2830

2931
handleSubmit = e => {
@@ -32,7 +34,7 @@ class Demo extends Component {
3234
};
3335

3436
render() {
35-
const { otp, numInputs, separator, isDisabled } = this.state;
37+
const { otp, numInputs, separator, isDisabled, hasErrored } = this.state;
3638

3739
return (
3840
<div className="container">
@@ -79,6 +81,18 @@ class Demo extends Component {
7981
Disabled
8082
</label>
8183
</div>
84+
<div className="side-bar__segment">
85+
<label htmlFor="hasErrored">
86+
<input
87+
id="hasErrored"
88+
name="hasErrored"
89+
type="checkbox"
90+
checked={hasErrored}
91+
onChange={this.handleCheck}
92+
/>
93+
Error
94+
</label>
95+
</div>
8296
<div className="side-bar__segment side-bar__segment--bottom">
8397
<a href="https://github.com/ajayns/react-otp-input">
8498
Documentation and Source
@@ -100,7 +114,9 @@ class Demo extends Component {
100114
border: '1px solid rgba(0,0,0,0.3)',
101115
}}
102116
numInputs={numInputs}
103-
disabled={isDisabled}
117+
isDisabled={isDisabled}
118+
hasErrored={hasErrored}
119+
errorStyle="error"
104120
onChange={this.handleOtpChange}
105121
separator={<span>{separator}</span>}
106122
shouldAutoFocus

src/docs/styles.css renamed to src/demo/styles.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,3 +107,7 @@ a {
107107
.margin-top--large {
108108
margin-top: 4rem;
109109
}
110+
111+
.error {
112+
border: 1px solid red !important;
113+
}

src/lib/index.jsx

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@ type Props = {
1414
containerStyle?: Object,
1515
inputStyle?: Object,
1616
focusStyle?: Object,
17-
disabled?: boolean,
17+
isDisabled?: boolean,
1818
disabledStyle?: Object,
19+
hasErrored?: boolean,
20+
errorStyle?: Object,
1921
shouldAutoFocus?: boolean,
2022
};
2123

@@ -24,6 +26,12 @@ type State = {
2426
otp: string[],
2527
};
2628

29+
// Doesn't really check if it's a style Object
30+
// Basic implemenetation to check if it's not a string
31+
// of classNames and is an Object
32+
// TODO: Better implementation
33+
const isStyleObject = obj => typeof obj === 'object';
34+
2735
class SingleOtpInput extends PureComponent<*> {
2836
input: ?HTMLInputElement;
2937

@@ -54,13 +62,17 @@ class SingleOtpInput extends PureComponent<*> {
5462
}
5563
}
5664

65+
getClasses = (...classes) => classes.filter(c => !isStyleObject(c) && c !== false).join(' ');
66+
5767
render() {
5868
const {
5969
separator,
6070
isLastChild,
6171
inputStyle,
6272
focus,
63-
disabled,
73+
isDisabled,
74+
hasErrored,
75+
errorStyle,
6476
focusStyle,
6577
disabledStyle,
6678
...rest
@@ -72,15 +84,21 @@ class SingleOtpInput extends PureComponent<*> {
7284
style={Object.assign(
7385
{ width: '1em', textAlign: 'center' },
7486
inputStyle,
87+
focus && isStyleObject(focusStyle) && focusStyle,
88+
isDisabled && isStyleObject(disabledStyle) && disabledStyle,
89+
hasErrored && isStyleObject(errorStyle) && errorStyle
90+
)}
91+
className={this.getClasses(
7592
focus && focusStyle,
76-
disabled && disabledStyle
93+
isDisabled && disabledStyle,
94+
hasErrored && errorStyle
7795
)}
7896
type="tel"
7997
maxLength="1"
8098
ref={input => {
8199
this.input = input;
82100
}}
83-
disabled={disabled}
101+
disabled={isDisabled}
84102
{...rest}
85103
/>
86104
{!isLastChild && separator}
@@ -93,7 +111,7 @@ class OtpInput extends Component<Props, State> {
93111
static defaultProps = {
94112
numInputs: 4,
95113
onChange: (otp: number): void => console.log(otp),
96-
disabled: false,
114+
isDisabled: false,
97115
shouldAutoFocus: false,
98116
};
99117

@@ -203,8 +221,10 @@ class OtpInput extends Component<Props, State> {
203221
inputStyle,
204222
focusStyle,
205223
separator,
206-
disabled,
224+
isDisabled,
207225
disabledStyle,
226+
hasErrored,
227+
errorStyle,
208228
shouldAutoFocus,
209229
} = this.props;
210230
const inputs = [];
@@ -228,8 +248,10 @@ class OtpInput extends Component<Props, State> {
228248
inputStyle={inputStyle}
229249
focusStyle={focusStyle}
230250
isLastChild={i === numInputs - 1}
231-
disabled={disabled}
251+
isDisabled={isDisabled}
232252
disabledStyle={disabledStyle}
253+
hasErrored={hasErrored}
254+
errorStyle={errorStyle}
233255
shouldAutoFocus={shouldAutoFocus}
234256
/>
235257
);
@@ -242,7 +264,7 @@ class OtpInput extends Component<Props, State> {
242264
const { containerStyle } = this.props;
243265

244266
return (
245-
<div style={{ display: 'flex', ...containerStyle }}>
267+
<div style={Object.assign({ display: 'flex' }, isStyleObject(containerStyle) && containerStyle )} className={!isStyleObject(containerStyle) && containerStyle}>
246268
{this.renderInputs()}
247269
</div>
248270
);

webpack.config.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ const path = require('path');
22
const HtmlWebpackPlugin = require('html-webpack-plugin');
33

44
module.exports = {
5-
entry: path.join(__dirname, 'src/docs'),
5+
entry: path.join(__dirname, 'src/demo'),
66
output: {
77
path: path.join(__dirname, 'demo'),
88
filename: 'bundle.js',
@@ -22,14 +22,14 @@ module.exports = {
2222
},
2323
plugins: [
2424
new HtmlWebpackPlugin({
25-
template: path.join(__dirname, 'src/docs/index.html'),
25+
template: path.join(__dirname, 'src/demo/index.html'),
2626
}),
2727
],
2828
resolve: {
2929
extensions: ['.js', '.jsx'],
3030
},
3131
devServer: {
32-
contentBase: path.join(__dirname, 'docs'),
32+
contentBase: path.join(__dirname, 'demo'),
3333
port: 8000,
3434
stats: 'minimal',
3535
},

0 commit comments

Comments
 (0)