@etsoo/materialui
Version:
TypeScript Material-UI Implementation
113 lines (112 loc) • 4.74 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import AddIcon from "@mui/icons-material/Add";
import RemoveIcon from "@mui/icons-material/Remove";
import React from "react";
import { NumberUtils } from "@etsoo/shared";
import { InputField } from "./InputField";
import Box from "@mui/material/Box";
import InputAdornment from "@mui/material/InputAdornment";
import IconButton from "@mui/material/IconButton";
/**
* Integer input field (controlled)
*/
export const IntInputField = React.forwardRef((props, ref) => {
// Destruct
const { min = 0, step = 1, max = 9999999, inputStyle = { textAlign: "right" }, boxProps, buttons, endSymbol, symbol, value, changeDelay = 600, onChangeDelay, onChange, onFocus = (event) => event.currentTarget.select(), onValueChange, required, ...rest } = props;
// State
const [localValue, setLocalValue] = React.useState();
const setValue = (value, source, init = false) => {
if (onValueChange) {
const newValue = onValueChange(value, source, init);
if (newValue === false)
return;
if (newValue === null) {
setLocalValue(undefined);
return;
}
if (newValue === true || newValue === undefined)
setLocalValue(value);
else
setLocalValue(newValue);
}
else {
setLocalValue(value);
}
};
React.useEffect(() => {
setValue(value, undefined, true);
}, [value]);
// Layout
const layout = (_jsx(InputField, { ref: ref, type: "number", value: localValue == null ? (required ? min : "") : localValue, inputProps: {
min,
step,
max,
style: inputStyle,
inputMode: "numeric"
}, InputProps: {
startAdornment: symbol ? (_jsx(React.Fragment, { children: _jsx(InputAdornment, { position: "start", children: symbol }) })) : undefined,
endAdornment: endSymbol ? (_jsx(InputAdornment, { position: "end", children: endSymbol })) : undefined
}, sx: buttons
? {
"& input[type=number]::-webkit-inner-spin-button": {
WebkitAppearance: "none",
margin: 0
},
"& input[type=number]::-webkit-outer-spin-button": {
WebkitAppearance: "none",
margin: 0
}
}
: undefined, onChange: (event) => {
const source = event.target.value;
setLocalValue(source);
if (onChange)
onChange(event);
}, changeDelay: changeDelay, onChangeDelay: (event) => {
const source = event.target.value;
const value = parseFloat(source);
if (isNaN(value))
setValue(undefined, source);
else if (value > max)
setValue(max, source);
else if (value < min)
setValue(value === 0 ? undefined : min, source);
// 0 is a special case
else
setValue(value, source);
if (onChangeDelay)
onChangeDelay(event);
}, onFocus: onFocus, required: required, ...rest }));
if (buttons)
return (_jsxs(Box, { sx: {
display: "flex",
alignItems: "center",
width: "100%",
gap: 0.5,
...boxProps
}, children: [_jsx(IconButton, { size: "small", onClick: () => {
if (localValue == null)
return;
const value = NumberUtils.parse(localValue);
if (value == null)
return;
if (value <= min)
setValue(undefined, "SUB");
else
setValue(value - step, "SUB");
}, children: _jsx(RemoveIcon, {}) }), layout, _jsx(IconButton, { size: "small", onClick: () => {
if (localValue == null) {
setValue(min, "ADD");
return;
}
const value = NumberUtils.parse(localValue);
if (value == null)
return;
if (value >= max)
return;
else
setValue(value + step, "ADD");
}, children: _jsx(AddIcon, { color: localValue == null ? undefined : "primary" }) })] }));
else
return layout;
});