@nutui/nutui-react
Version:
京东风格的轻量级移动端 React 组件库,支持一套代码生成 H5 和小程序
171 lines (170 loc) • 6.48 kB
JavaScript
import { _ as __rest } from "./tslib.es6.js";
import React__default, { useState, useRef, useEffect } from "react";
import { Minus, Plus } from "@nutui/icons-react";
import classNames from "classnames";
import { u as usePropsValue } from "./use-props-value.js";
import { C as ComponentDefaults } from "./typings.js";
const defaultProps = Object.assign(Object.assign({}, ComponentDefaults), { disabled: false, readOnly: false, allowEmpty: false, min: 1, max: 9999, step: 1, digits: 0, async: false });
const classPrefix = `nut-inputnumber`;
const InputNumber = (props) => {
const _a = Object.assign(Object.assign({}, defaultProps), props), { children, disabled, min, max, readOnly, value, defaultValue, allowEmpty, digits, step, async, className, style, formatter, onPlus, onMinus, onOverlimit, onBlur, onFocus, onChange } = _a, restProps = __rest(_a, ["children", "disabled", "min", "max", "readOnly", "value", "defaultValue", "allowEmpty", "digits", "step", "async", "className", "style", "formatter", "onPlus", "onMinus", "onOverlimit", "onBlur", "onFocus", "onChange"]);
const classes = classNames(classPrefix, className, {
[`${classPrefix}-disabled`]: disabled
});
const [focused, setFocused] = useState(false);
const inputRef = useRef(null);
useEffect(() => {
var _a2, _b;
if (focused) {
(_b = (_a2 = inputRef.current) === null || _a2 === void 0 ? void 0 : _a2.select) === null || _b === void 0 ? void 0 : _b.call(_a2);
}
}, [focused]);
const [shadowValue, setShadowValue] = usePropsValue({
value: typeof value === "string" ? parseFloat(value) : value,
defaultValue: typeof defaultValue === "string" ? parseFloat(defaultValue) : defaultValue,
finalValue: 0,
onChange: (value2) => {
}
});
const bound = (value2, min2, max2) => {
let res = value2;
if (min2 !== void 0) {
res = Math.max(Number(min2), res);
}
if (max2 !== void 0) {
res = Math.min(Number(max2), res);
}
return res;
};
const format = (value2) => {
if (value2 === null)
return "";
if (typeof value2 === "string")
value2 = parseFloat(value2);
const fixedValue = bound(value2, Number(min), Number(max));
if (formatter) {
return formatter(fixedValue);
}
if (digits) {
return fixedValue.toFixed(digits).toString();
}
return fixedValue.toString();
};
const [inputValue, setInputValue] = useState(format(shadowValue));
useEffect(() => {
if (!focused && !async) {
setShadowValue(bound(Number(shadowValue), Number(min), Number(max)));
setInputValue(format(shadowValue));
}
}, [focused, shadowValue]);
useEffect(() => {
if (async) {
setShadowValue(bound(Number(value), Number(min), Number(max)));
setInputValue(format(value));
}
}, [value]);
const calcNextValue = (current, step2, symbol) => {
const dig = digits + 1;
return (parseFloat(current || "0") * dig + parseFloat(step2) * dig * symbol) / dig;
};
const update = (negative, e) => {
if (step !== void 0) {
const shouldOverBoundary = calcNextValue(shadowValue, step, negative ? -1 : 1);
const nextValue = bound(shouldOverBoundary, Number(min), Number(max));
setShadowValue(nextValue);
if (negative ? shouldOverBoundary < Number(min) : shouldOverBoundary > Number(max)) {
onOverlimit === null || onOverlimit === void 0 ? void 0 : onOverlimit(e);
} else {
onChange === null || onChange === void 0 ? void 0 : onChange(nextValue, e);
}
}
};
const handleReduce = (e) => {
if (disabled)
return;
onMinus === null || onMinus === void 0 ? void 0 : onMinus(e);
update(true, e);
};
const handlePlus = (e) => {
if (disabled)
return;
onPlus === null || onPlus === void 0 ? void 0 : onPlus(e);
update(false, e);
};
const parseValue = (text) => {
if (text === "")
return null;
if (text === "-")
return null;
return text;
};
const clampValue = (valueStr) => {
if (valueStr === null)
return defaultValue;
const val = Number(parseFloat(valueStr || "0").toFixed(digits));
return Math.max(Number(min), Math.min(Number(max), val));
};
const handleValueChange = (valueStr, e) => {
const val = clampValue(valueStr);
if (val !== Number(shadowValue)) {
onChange === null || onChange === void 0 ? void 0 : onChange(val, e);
}
};
const handleInputChange = (e) => {
setInputValue(e.target.value);
const valueStr = parseValue(e.target.value);
if (valueStr === null) {
if (allowEmpty) {
setShadowValue(null);
} else {
setShadowValue(defaultValue);
}
} else {
setShadowValue(clampValue(valueStr));
}
!async && handleValueChange(valueStr, e);
};
const handleFocus = (e) => {
setFocused(true);
setInputValue(shadowValue !== void 0 && shadowValue !== null ? bound(Number(shadowValue), Number(min), Number(max)).toString() : "");
onFocus === null || onFocus === void 0 ? void 0 : onFocus(e);
};
const handleBlur = (e) => {
setFocused(false);
onBlur === null || onBlur === void 0 ? void 0 : onBlur(e);
const valueStr = parseValue(e.target.value);
if (valueStr === null) {
if (allowEmpty) {
setShadowValue(null);
} else {
setShadowValue(defaultValue);
}
} else {
setShadowValue(clampValue(valueStr));
}
async && handleValueChange(valueStr, e);
};
return React__default.createElement(
"div",
Object.assign({ className: classes, style }, restProps),
React__default.createElement(
"div",
{ className: "nut-input-minus", onClick: handleReduce },
React__default.createElement(Minus, { className: classNames("nut-inputnumber-icon icon-minus", {
[`${classPrefix}-icon-disabled`]: shadowValue === min || disabled
}) })
),
React__default.createElement("input", { ref: inputRef, inputMode: "decimal", disabled, readOnly, value: inputValue, onInput: handleInputChange, onBlur: handleBlur, onFocus: handleFocus }),
React__default.createElement(
"div",
{ className: "nut-input-add", onClick: handlePlus },
React__default.createElement(Plus, { className: classNames("nut-inputnumber-icon icon-plus", {
[`${classPrefix}-icon-disabled`]: shadowValue === max || disabled
}) })
)
);
};
InputNumber.displayName = "NutInputNumber";
export {
InputNumber as default
};