import React from 'react';
import cx from 'classnames';
import bem from '../utils/bem';
import Input, { InputProps } from '../input/index';
import Button from '../button/index';
import { IconMinus, IconPlus } from '../icon/index';
import { toBeField, FieldProps } from '../form/index';
const b = bem('rdf-input-number');
type InputNumberPropsFromInput = Pick<
InputProps,
| 'defaultValue'
| 'value'
| 'name'
| 'placeholder'
| 'round'
| 'size'
| 'autoFocus'
| 'readOnly'
| 'disabled'
| 'className'
| 'style'
| 'onChange'
>;
export interface InputNumberProps
extends InputNumberPropsFromInput,
FieldProps {
step?: number;
min?: number;
max?: number;
editable?: boolean;
}
export interface InputNumberState {
value: any;
validValue: number | '';
}
class InnerInputNumber extends React.Component<
InputNumberProps,
InputNumberState
> {
static defaultProps: InputNumberProps = {
defaultValue: '',
step: 1,
min: -Infinity,
max: Infinity,
editable: true,
fieldContext: {
onChange: () => {},
onBlur: () => {},
},
};
static getDerivedStateFromProps(props: InputNumberProps) {
if (typeof props.value !== 'undefined') {
return { value: props.value };
}
return null;
}
constructor(props: InputNumberProps) {
super(props);
const { value, defaultValue } = props;
const stateValue = typeof value !== 'undefined' ? value : defaultValue;
this.state = {
value: stateValue,
validValue: this.toValid(stateValue),
};
}
toValid(value: any) {
const { min, max } = this.props;
value = parseFloat(value);
if (Number.isNaN(value) || !Number.isFinite(value)) {
return '';
}
if (value < (min as number)) {
value = min;
} else if (value > (max as number)) {
value = max;
}
return value;
}
toFixed(value: number) {
const { step } = this.props;
const decimalPlaces = (`${step}`.split('.')[1] || '').length;
return +value.toFixed(decimalPlaces);
}
handleChange: InputNumberProps['onChange'] = value => {
const { disabled, readOnly, onChange, fieldContext } = this.props;
if (disabled || readOnly) {
return;
}
this.setState({ validValue: this.toValid(value) });
if (typeof this.props.value === 'undefined') {
this.setState({ value });
}
if (onChange) {
onChange(value, { ...this.props });
fieldContext.onChange();
}
};
handleMinus = () => {
const {
step,
min,
disabled,
readOnly,
onChange,
fieldContext,
} = this.props;
const value = this.toFixed(
Math.max(+this.state.value - (step as number), min as number)
);
if (disabled || readOnly) {
return;
}
this.setState({ validValue: this.toValid(value) });
if (typeof this.props.value === 'undefined') {
this.setState({ value });
}
if (onChange) {
onChange(value, { ...this.props });
fieldContext.onChange();
}
};
handlePlus = () => {
const {
step,
max,
disabled,
readOnly,
onChange,
fieldContext,
} = this.props;
const value = this.toFixed(
Math.min(+this.state.value + (step as number), max as number)
);
if (disabled || readOnly) {
return;
}
this.setState({ validValue: this.toValid(value) });
if (typeof this.props.value === 'undefined') {
this.setState({ value });
}
if (onChange) {
onChange(value, { ...this.props });
fieldContext.onChange();
}
};
handleBlur = () => {
const { onChange, fieldContext } = this.props;
const { value, validValue } = this.state;
if (value === validValue) {
return;
}
if (typeof this.props.value === 'undefined') {
this.setState({ value: validValue });
}
if (onChange) {
onChange(validValue, { ...this.props });
fieldContext.onChange();
}
};
renderMinus() {
const { min, disabled } = this.props;
const { value } = this.state;
return (
);
}
renderPlus() {
const { max, disabled } = this.props;
const { value } = this.state;
return (
);
}
render() {
const {
name,
size,
round,
readOnly,
autoFocus,
editable,
disabled,
className,
style,
} = this.props;
const { value } = this.state;
const cls = cx(b(), className, {
[b(['disabled'])]: disabled,
});
return (
);
}
}
export const InputNumber = toBeField(InnerInputNumber);
export default InputNumber;