UNPKG

@etsoo/materialui

Version:

TypeScript Material-UI Implementation

128 lines (127 loc) 5.28 kB
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"; import { useCombinedRefs } from "@etsoo/react"; /** * Integer input field (controlled) */ export function IntInputField(props) { // Destruct const { min = 0, step = 1, max = 9999999, inputRef, inputStyle = { textAlign: "right" }, boxProps, buttons, endSymbol, symbol, value, changeDelay = [600], onChangeDelay, onChange, onFocus = (event) => event.currentTarget.select(), onValueChange, required, ...rest } = props; const isControlled = value !== undefined; // State const [localValue, setInnerLocalValue] = React.useState(); const localRef = React.useRef(null); function setLocalValue(value) { if (isControlled) { setInnerLocalValue(value); } else if (localRef.current) { localRef.current.value = value?.toString() ?? ""; } } 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(() => { if (isControlled) setValue(value, undefined, true); }, [value, isControlled]); // Layout const layout = (_jsx(InputField, { type: "number", inputRef: useCombinedRefs(inputRef, localRef), value: isControlled ? localValue == null ? required ? min : "" : localValue : undefined, slotProps: { input: { startAdornment: symbol ? (_jsx(React.Fragment, { children: _jsx(InputAdornment, { position: "start", children: symbol }) })) : undefined, endAdornment: endSymbol ? (_jsx(InputAdornment, { position: "end", children: endSymbol })) : undefined }, htmlInput: { min, step, max, style: inputStyle, inputMode: "numeric" } }, 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; }