-
Notifications
You must be signed in to change notification settings - Fork 10
/
Input.js
134 lines (115 loc) · 2.5 KB
/
Input.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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// This is just `./ReactInput.js` rewritten in Hooks.
import React, { useCallback, useRef } from 'react'
import PropTypes from 'prop-types'
import {
onChange as onInputChange,
onCut as onInputCut,
onPaste as onInputPaste,
onKeyDown as onInputKeyDown
} from '../input control'
// Usage:
//
// <ReactInput
// value={this.state.phone}
// onChange={phone => this.setState({ phone })}
// parse={character => character}
// format={value => ({ text: value, template: 'xxxxxxxx' })}/>
//
function Input({
value,
parse,
format,
inputComponent: InputComponent,
onChange,
onCut,
onPaste,
onKeyDown,
...rest
}, ref) {
const ownRef = useRef()
ref = ref || ownRef
const _onChange = useCallback((event) => {
return onInputChange(
event,
ref.current,
parse,
format,
onChange
)
}, [ref, parse, format, onChange])
const _onPaste = useCallback((event) => {
if (onPaste) {
onPaste(event)
}
return onInputPaste(
event,
ref.current,
parse,
format,
onChange
)
}, [ref, parse, format, onChange, onPaste])
const _onCut = useCallback((event) => {
if (onCut) {
onCut(event)
}
return onInputCut(
event,
ref.current,
parse,
format,
onChange
)
}, [ref, parse, format, onChange, onCut])
const _onKeyDown = useCallback((event) => {
if (onKeyDown) {
onKeyDown(event)
}
return onInputKeyDown(
event,
ref.current,
parse,
format,
onChange
)
}, [ref, parse, format, onChange, onKeyDown])
return (
<InputComponent
{...rest}
ref={ref}
value={format(isEmptyValue(value) ? '' : value).text}
onKeyDown={_onKeyDown}
onChange={_onChange}
onPaste={_onPaste}
onCut={_onCut} />
)
}
Input = React.forwardRef(Input)
Input.propTypes = {
// Parses a single characher of `<input/>` text.
parse: PropTypes.func.isRequired,
// Formats `value` into `<input/>` text.
format: PropTypes.func.isRequired,
// Renders `<input/>` by default.
inputComponent: PropTypes.elementType.isRequired,
// `<input/>` `type` attribute.
type: PropTypes.string.isRequired,
// Is parsed from <input/> text.
value: PropTypes.string,
// This handler is called each time `<input/>` text is changed.
onChange: PropTypes.func.isRequired,
// Passthrough
onKeyDown: PropTypes.func,
onCut: PropTypes.func,
onPaste: PropTypes.func
}
Input.defaultProps = {
// Renders `<input/>` by default.
inputComponent: 'input',
// `<input/>` `type` attribute.
type: 'text'
}
export default Input
function isEmptyValue(value) {
return value === undefined || value === null
}