<main></main>
.char {
display: inline-block;
vertical-align: top;
height: 100px;
width: 100px;
border: 1px solid;
margin: 5px 5px;
text-align: center;
line-height: 100px;
font-size: 32px;
}
.char:focus {
background: #ccc;
}
class CustomInput extends React.Component {
constructor(props) {
super(props);
this.state = { val: ' ' };
this.el = [];
}
componentDidUpdate(prevProps, prevState) {
if (!prevProps.active && this.props.active) {
this.el[0].focus();
}
}
keyPressed = (index, e) => {
const charcode = e.charCode;
const char = String.fromCharCode(charcode);
if (char.match(/[0-9a-zA-Z]/)) {
e.preventDefault();
const arr = this.state.val.split('');
arr[index] = char;
this.setState(() => ({ val: arr.join('') }));
if (index === arr.length - 1) {
this.props.done();
} else {
this.el[(index + 1) % arr.length].focus();
}
}
}
render() {
return (
<div>
{this.state.val.split('').map((val, index) => (
<div
tabindex='1'
className='char'
key={index}
onKeyPress={e => this.keyPressed(index, e)}
ref={(el) => this.el[index] = el}
>
{val}
</div>
))}
</div>
);
}
}
class App extends React.Component {
constructor(props) {
super(props);
this.state = { active: 0 };
}
done = () => {
this.setState((oldState => ({ active: (oldState.active + 1) % 3 })));
};
render() {
return (
<div>
<CustomInput active={this.state.active === 0} done={this.done} />
<CustomInput active={this.state.active === 1} done={this.done} />
<CustomInput active={this.state.active === 2} done={this.done} />
</div>
);
}
}
ReactDOM.render(<App />, document.querySelector('main'));
View Compiled
This Pen doesn't use any external CSS resources.