forked from regentmarkets-repo-archive/binary-components
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathNumericInput.js
More file actions
124 lines (104 loc) · 3.46 KB
/
Copy pathNumericInput.js
File metadata and controls
124 lines (104 loc) · 3.46 KB
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
import React, { PureComponent } from 'react';
type Props = {
className: string,
decimals?: number,
min: number,
max: number,
integer: boolean,
defaultValue: number,
step: number,
value: string,
valueList: number[],
onChange: (newValue: number) => void,
}
export default class NumericInput extends PureComponent {
props: Props;
state: {
value: string,
}
static defaultProps = {
defaultValue: 0,
decimals: 2,
step: 0,
};
constructor(props: Props) {
super(props);
this.state = {
value: props.value || props.defaultValue.toString(),
};
}
step = () => {
const { value } = this.state;
const notInt = +value % 1 !== 0;
return notInt || value === '0' ?
0.1 :
10 ** (value.length - 1);
}
// this function will perform checks on new value and change it automatically
addDiffWithChecks = (diff: number) => {
const { decimals, min, max } = this.props;
const value = +this.state.value;
let newValue = +((value + diff).toFixed(decimals));
if (newValue > max) {
newValue = max;
} else if (newValue < min) {
newValue = min;
}
this.changeValue(newValue);
}
onStepUp = () => {
const step = this.props.step || this.step();
this.addDiffWithChecks(step);
}
onStepDown = () => {
let { step } = this.props;
if (!step) {
const smallerStepDown = (this.state.value).toString()[0] === '1';
step = smallerStepDown ? this.step() / 10 : this.step();
}
this.addDiffWithChecks(-step);
}
// this function should not check and change input value automatically!!
// as invalid value could be intermediate value of valid value
// eg. empty value
changeValue = (newValue: number) => {
const { integer } = this.props;
const value = (newValue && integer) ? Math.floor(newValue) : newValue;
this.setState({ value: typeof value !== 'undefined' ? value.toString() : undefined });
const { onChange } = this.props;
if (onChange) onChange(+value);
}
onChange = (e: any) =>
this.changeValue(e.target.value);
componentWillReceiveProps(nextProps: Props) {
const { value } = nextProps;
if (value) this.setState({ value });
}
render() {
const { integer, className, min, max, valueList } = this.props;
const { value } = this.state;
const iosHackEnabled = integer && navigator && navigator.userAgent.match(/iP(ad|hone)/i);
return (
<div className={className}>
<button className="btn-flat step-down" onClick={this.onStepDown}>–</button>
<input
type={iosHackEnabled ? 'tel' : 'number'}
value={value}
min={min}
max={max}
step={this.step()}
list="values"
onChange={this.onChange}
/>
<button className="btn-flat step-up" onClick={this.onStepUp}>+</button>
{valueList &&
<datalist id="values">
{valueList.map((x: number) => (
<option key={x} value={x} />
))}
</datalist>
}
</div>
);
}
}