mirror of
https://github.com/arduino/arduino-ide.git
synced 2025-10-16 14:58:32 +00:00

- update Theia to `1.39.0`, - remove the application packager and fix the security vulnerabilities, - bundle the backed application with `webpack`, and - enhance the developer docs. Co-authored-by: Akos Kitta <a.kitta@arduino.cc> Co-authored-by: per1234 <accounts@perglass.com> Signed-off-by: Akos Kitta <a.kitta@arduino.cc>
140 lines
3.7 KiB
TypeScript
140 lines
3.7 KiB
TypeScript
import React from '@theia/core/shared/react';
|
|
import classnames from 'classnames';
|
|
|
|
interface SettingsStepInputProps {
|
|
initialValue: 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 {
|
|
initialValue,
|
|
setSettingsStateValue,
|
|
step,
|
|
maxValue,
|
|
minValue,
|
|
unitOfMeasure,
|
|
classNames,
|
|
} = props;
|
|
|
|
const [valueState, setValueState] = React.useState<{
|
|
currentValue: number;
|
|
isEmptyString: boolean;
|
|
}>({
|
|
currentValue: initialValue,
|
|
isEmptyString: false,
|
|
});
|
|
const { currentValue, isEmptyString } = valueState;
|
|
|
|
const clamp = (value: number, min: number, max: number): number => {
|
|
return Math.min(Math.max(value, min), max);
|
|
};
|
|
|
|
const resetToInitialState = (): void => {
|
|
setValueState({
|
|
currentValue: initialValue,
|
|
isEmptyString: false,
|
|
});
|
|
};
|
|
|
|
const onStep = (
|
|
roundingOperation: 'ceil' | 'floor',
|
|
stepOperation: (a: number, b: number) => number
|
|
): void => {
|
|
const valueRoundedToScale =
|
|
Math[roundingOperation](currentValue / step) * step;
|
|
const calculatedValue =
|
|
valueRoundedToScale === currentValue
|
|
? stepOperation(currentValue, 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;
|
|
setValueState({
|
|
currentValue: Number(eventValue),
|
|
isEmptyString: eventValue === '',
|
|
});
|
|
};
|
|
|
|
/* Prevent the user from entering invalid values */
|
|
const onBlur = (event: React.FocusEvent): void => {
|
|
if (
|
|
(currentValue === initialValue && !isEmptyString) ||
|
|
event.currentTarget.contains(event.relatedTarget as Node)
|
|
) {
|
|
return;
|
|
}
|
|
|
|
const clampedValue = clamp(currentValue, minValue, maxValue);
|
|
if (clampedValue === initialValue || isNaN(currentValue) || isEmptyString) {
|
|
resetToInitialState();
|
|
return;
|
|
}
|
|
|
|
setSettingsStateValue(clampedValue);
|
|
};
|
|
|
|
const valueIsNotWithinRange =
|
|
currentValue < minValue || currentValue > maxValue;
|
|
const isDisabledException =
|
|
valueIsNotWithinRange || isEmptyString || isNaN(currentValue);
|
|
|
|
const upDisabled = isDisabledException || currentValue >= maxValue;
|
|
const downDisabled = isDisabledException || currentValue <= minValue;
|
|
|
|
return (
|
|
<div className="settings-step-input-container" onBlur={onBlur}>
|
|
<input
|
|
className={classnames('settings-step-input-element', classNames?.input)}
|
|
value={isEmptyString ? '' : String(currentValue)}
|
|
onChange={onUserInput}
|
|
type="number"
|
|
pattern="[0-9]+"
|
|
/>
|
|
<div
|
|
className={classnames(
|
|
'settings-step-input-buttons-container',
|
|
classNames?.buttonsContainer
|
|
)}
|
|
>
|
|
<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;
|