/
withNextInputAutoFocus.js
108 lines (91 loc) · 2.96 KB
/
withNextInputAutoFocus.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import React from "react";
import PropTypes from "prop-types";
import withFormik from "./withFormik";
const withNextInputAutoFocusContextType = {
setInput: PropTypes.func,
handleSubmitEditing: PropTypes.func,
getReturnKeyType: PropTypes.func
};
const getInputs = children =>
React.Children.toArray(children).reduce((partialInputs, child) => {
if (child && child.props && child.props.children) {
return partialInputs.concat(getInputs(child.props.children));
}
if (child && child.props && !!child.props.name)
return partialInputs.concat(child);
return partialInputs;
}, []);
export const withNextInputAutoFocusForm = (
WrappedComponent,
{ submitAfterLastInput } = { submitAfterLastInput: true }
) => {
class WithNextInputAutoFocusForm extends React.PureComponent {
static childContextTypes = withNextInputAutoFocusContextType;
constructor(props) {
super(props);
const { children } = props;
this.inputs = getInputs(children || []);
}
inputs;
inputNameMap;
inputRefs = {};
getInputPosition = name =>
this.inputs.findIndex(input => input.props.name === name);
getChildContext = () => ({
setInput: (name, component) => {
this.inputRefs[name] = component;
},
handleSubmitEditing: name => {
const inputPosition = this.getInputPosition(name);
const nextInputs = this.inputs.slice(inputPosition + 1);
const nextFocusableInput = nextInputs.find(
element =>
this.inputRefs[element.props.name] &&
this.inputRefs[element.props.name].focus
);
if (nextFocusableInput) {
this.inputRefs[nextFocusableInput.props.name].focus();
} else {
if (submitAfterLastInput) this.props.formik.submitForm();
}
},
getReturnKeyType: name => {
const inputPosition = this.getInputPosition(name);
const isLastInput = inputPosition === this.inputs.length - 1;
return isLastInput ? "done" : "next";
}
});
render() {
return <WrappedComponent {...this.props} />;
}
}
return withFormik(WithNextInputAutoFocusForm);
};
export const withNextInputAutoFocusInput = Input => {
class WithNextInputAutoFocusInput extends React.Component<
$FlowFixMeProps,
$FlowFixMeState
> {
static contextTypes = withNextInputAutoFocusContextType;
setInput = component => {
this.context.setInput(this.props.name, component);
};
onSubmitEditing = () => {
this.context.handleSubmitEditing(this.props.name);
if (this.props.onSubmitEditing) this.props.onSubmitEditing();
};
render() {
const { getReturnKeyType } = this.context;
const { name } = this.props;
return (
<Input
returnKeyType={getReturnKeyType(name)}
{...this.props}
ref={this.setInput}
onSubmitEditing={this.onSubmitEditing}
/>
);
}
}
return WithNextInputAutoFocusInput;
};