import React, { useState, useEffect, FunctionComponent, ChangeEvent, FocusEvent, } from 'react' import { View, TextInput, TouchableOpacity, Platform } from 'react-native'; import Icon from '../icon/index' import { IComponent, ComponentDefaults } from '../utils/typings' import pt from '../utils/pt' import { useConfig } from '../configprovider'; import inputNumberStyles from './styles'; export interface InputNumberProps extends IComponent { disabled: boolean buttonSize: string | number min: string | number max: string | number inputWidth: string | number readonly: boolean modelValue: string | number step: string | number decimalPlaces: string | number isAsync: boolean className: string style: React.CSSProperties onAdd: (e: MouseEvent) => void onReduce: (e: MouseEvent) => void onOverlimit: (e: MouseEvent) => void onBlurFuc: (e: ChangeEvent) => void onFocus: (e: FocusEvent) => void onChangeFuc: ( param: string | number, e: MouseEvent | ChangeEvent ) => void } const defaultProps = { ...ComponentDefaults, disabled: false, buttonSize: '', min: 1, max: 9999, inputWidth: '', readonly: false, modelValue: 0, step: 1, decimalPlaces: 0, isAsync: false, } as InputNumberProps function pxCheck(value: string | number): number { return value ? pt(parseInt(`${value}`)) : 0 } export const InputNumber: FunctionComponent< Partial & React.HTMLAttributes > = (props) => { const { children, disabled, buttonSize, min, max, inputWidth, readonly, modelValue, decimalPlaces, step, isAsync, className, style, onAdd, onReduce, onOverlimit, onBlurFuc, onFocus, onChangeFuc, iconClassPrefix, iconFontClassName, ...restProps } = { ...defaultProps, ...props, } const { theme } = useConfig(); const mStyles = inputNumberStyles(theme); const [inputValue, setInputValue] = useState(modelValue) useEffect(() => { const outputValue: number | string = fixedDecimalPlaces(modelValue) setInputValue(outputValue); }, [modelValue]) const styles = { ...style, } const addAllow = (value = Number(inputValue)) => { return value < Number(max) && !disabled } const reduceAllow = (value = Number(inputValue)) => { return value > Number(min) && !disabled } const fixedDecimalPlaces = (v: string | number): string => { return Number(v).toFixed(Number(decimalPlaces)) } const emitChange = ( value: string | number, e: MouseEvent | ChangeEvent ) => { const outputValue: number | string = fixedDecimalPlaces(value) onChangeFuc && onChangeFuc(outputValue, e) if (!isAsync) { if (Number(outputValue) < Number(min)) { setInputValue(Number(min)) } else if (Number(outputValue) > Number(max)) { setInputValue(Number(max)) } else { setInputValue(outputValue) } } } const reduceNumber = (e: MouseEvent) => { onReduce && onReduce(e) if (reduceAllow()) { const outputValue = Number(inputValue) - Number(step) emitChange(outputValue, e) } else { onOverlimit && onOverlimit(e) } } const addNumber = (e: MouseEvent) => { onAdd && onAdd(e) if (addAllow()) { const outputValue = Number(inputValue) + Number(step) emitChange(outputValue, e) } else { onOverlimit && onOverlimit(e) } } const changeValue = (e: any) => { const value = Number(e?.nativeEvent.text) onChangeFuc && onChangeFuc(value, e) if (!isAsync) { if (Number.isNaN(value)) { setInputValue(inputValue) } else { setInputValue(value) } } } const focusValue = (e: FocusEvent) => { if (disabled) return if (readonly) return onFocus && onFocus(e) } const burValue = (e: any) => { if (disabled) return if (readonly) return let value = Number(e?.nativeEvent.text) if (value < Number(min)) { value = Number(min) } else if (value > Number(max)) { value = Number(max) } emitChange(value, e) onBlurFuc && onBlurFuc(e) } return ( { Platform.OS === 'web' ? : } ) } InputNumber.defaultProps = defaultProps InputNumber.displayName = 'NutInputNumber'