-
-
Notifications
You must be signed in to change notification settings - Fork 435
/
Copy pathsettings-step-input.tsx
102 lines (87 loc) · 2.55 KB
/
settings-step-input.tsx
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
import * as React from '@theia/core/shared/react';
import classnames from 'classnames';
interface SettingsStepInputProps {
value: number;
setSettingsStateValue: (value: number) => void;
step: number;
maxValue: number;
minValue: number;
unitOfMeasure?: string;
classNames?: { [key: string]: string };
}
const SettingsStepInput: React.FC<SettingsStepInputProps> = (
props: SettingsStepInputProps
) => {
const {
value,
setSettingsStateValue,
step,
maxValue,
minValue,
unitOfMeasure,
classNames,
} = props;
const clamp = (value: number, min: number, max: number): number => {
return Math.min(Math.max(value, min), max);
};
const onStep = (
roundingOperation: 'ceil' | 'floor',
stepOperation: (a: number, b: number) => number
): void => {
const valueRoundedToScale = Math[roundingOperation](value / step) * step;
const calculatedValue =
valueRoundedToScale === value
? stepOperation(value, step)
: valueRoundedToScale;
const newValue = clamp(calculatedValue, minValue, maxValue);
setSettingsStateValue(newValue);
};
const onStepUp = (): void => {
onStep('ceil', (a: number, b: number) => a + b);
};
const onStepDown = (): void => {
onStep('floor', (a: number, b: number) => a - b);
};
const onUserInput = (event: React.ChangeEvent<HTMLInputElement>): void => {
const { value: eventValue } = event.target;
if (eventValue === '') {
setSettingsStateValue(0);
}
const number = Number(eventValue);
if (!isNaN(number) && number !== value) {
const newValue = clamp(number, minValue, maxValue);
setSettingsStateValue(newValue);
}
};
const upDisabled = value >= maxValue;
const downDisabled = value <= minValue;
return (
<div className="settings-step-input-container">
<input
className={classnames('settings-step-input-element', classNames?.input)}
value={value.toString()}
onChange={onUserInput}
type="number"
pattern="[0-9]+"
/>
<div className="settings-step-input-buttons-container">
<button
className="settings-step-input-button settings-step-input-up-button"
disabled={upDisabled}
onClick={onStepUp}
>
▾
</button>
<button
className="settings-step-input-button"
disabled={downDisabled}
onClick={onStepDown}
>
▾
</button>
</div>
{unitOfMeasure && `${unitOfMeasure}`}
</div>
);
};
export default SettingsStepInput;