@tarojsx/ui
Version:
We reinvents the UI for Taro3+
74 lines • 3.88 kB
JavaScript
import { __rest } from "tslib";
import React, { useMemo, useCallback } from 'react';
import Taro from '@tarojs/taro';
import classNames from 'classnames';
import { View, Input, Text } from '@tarojs/components';
import { setEventDetail } from './utils';
import '../style/InputNumber.scss';
/**
* 获取数据小数点后面部分长度
*/
const getPrecision = (num) => {
var _a;
return ((_a = String(num).split('.')[1]) === null || _a === void 0 ? void 0 : _a.length) || 0;
};
/**
* 数字加法, 避免 float 数计算误差.
*/
const decimalAdd = (a, b) => {
/** 两个数字转化为整数所需的乘法系数 */
const ratio = Math.pow(10, Math.max(getPrecision(a), getPrecision(b)));
return Math.round((a + b) * ratio) / ratio;
};
/**
* 数字输入框
*
* - 按 "+" 和 "-" 按 step 加减数字.
* - 手动输入数字时调起数字(number)或小数(digit)键盘, 默认距离键盘50px.
* - 失去光标时强制格式化数字.
*/
export const InputNumber = (props) => {
var _a;
const { className, style = {}, customStyle = {}, disabled = false, disabledInput = false, value = 0, type = 'number', width = 0, min = 0, max = 100, step = 1, size = 'normal', cursorSpacing = 50, onChange = () => { }, onBlur = () => { } } = props, rest = __rest(props, ["className", "style", "customStyle", "disabled", "disabledInput", "value", "type", "width", "min", "max", "step", "size", "cursorSpacing", "onChange", "onBlur"]);
const inputValue = useMemo(() => parseFloat(String(value)) || 0, [value]);
const clamp = useCallback((n) => Math.max(min, Math.min(max, n)), [min, max]);
const handleClick = useCallback((e) => {
if (disabled)
return;
e.detail.value = clamp(decimalAdd(inputValue, e.detail.delta));
onChange(e);
}, [disabled, inputValue, clamp, step]);
const handleChange = useCallback((e) => {
const { value } = e.detail;
const num = parseFloat(value) || 0;
if (num.toString() === value) {
e.detail.value = num;
}
onChange(e);
}, [onChange]);
const handleBlur = useCallback((e) => {
const num = parseFloat(e.detail.value);
e.detail.value = isNaN(num) ? '' : clamp(num);
onChange(e);
onBlur(e);
}, [onBlur, onChange, clamp]);
return (React.createElement(View, { className: classNames('at-input-number', { 'at-input-number--lg': size === 'large' }, className), style: Object.assign(Object.assign({}, style), customStyle) },
React.createElement(View, { className: classNames('at-input-number__btn', {
'at-input-number--disabled': inputValue <= min || disabled,
}), onClick: (e) => {
e.preventDefault();
e.stopPropagation();
handleClick && handleClick(setEventDetail(e, { delta: -step }));
} },
React.createElement(Text, { className: "at-icon at-icon-subtract at-input-number__btn-subtract" })),
React.createElement(Input, Object.assign({}, rest, { cursor: String(value).length, cursorSpacing: cursorSpacing, className: "at-input-number__input", style: width ? { width: Taro.pxTransform(width) } : {}, type: type, value: (_a = value) !== null && _a !== void 0 ? _a : '', disabled: disabledInput || disabled, onInput: handleChange, onBlur: handleBlur })),
React.createElement(View, { className: classNames('at-input-number__btn', {
'at-input-number--disabled': inputValue >= max || disabled,
}), onClick: (e) => {
e.preventDefault();
e.stopPropagation();
handleClick && handleClick(setEventDetail(e, { delta: step }));
} },
React.createElement(Text, { className: "at-icon at-icon-add at-input-number__btn-add" }))));
};
//# sourceMappingURL=InputNumber.js.map