2020-03-07 11:45:13 +00:00
|
|
|
// based on rc-input-number 4.5.5
|
2019-01-12 03:33:27 +00:00
|
|
|
import PropTypes from '../../_util/vue-types';
|
|
|
|
import BaseMixin from '../../_util/BaseMixin';
|
2020-01-19 08:58:38 +00:00
|
|
|
import { initDefaultProps, hasProp, getOptionProps, getListeners } from '../../_util/props-util';
|
2019-01-12 03:33:27 +00:00
|
|
|
import classNames from 'classnames';
|
|
|
|
import KeyCode from '../../_util/KeyCode';
|
|
|
|
import InputHandler from './InputHandler';
|
2018-04-04 04:04:49 +00:00
|
|
|
|
2019-01-12 03:33:27 +00:00
|
|
|
function noop() {}
|
2018-04-04 01:44:19 +00:00
|
|
|
|
2019-01-12 03:33:27 +00:00
|
|
|
function preventDefault(e) {
|
|
|
|
e.preventDefault();
|
2018-04-04 01:44:19 +00:00
|
|
|
}
|
|
|
|
|
2019-01-12 03:33:27 +00:00
|
|
|
function defaultParser(input) {
|
|
|
|
return input.replace(/[^\w\.-]+/g, '');
|
2018-04-04 01:44:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* When click and hold on a button - the speed of auto changin the value.
|
|
|
|
*/
|
2019-01-12 03:33:27 +00:00
|
|
|
const SPEED = 200;
|
2018-04-04 01:44:19 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* When click and hold on a button - the delay before auto changin the value.
|
|
|
|
*/
|
2019-01-12 03:33:27 +00:00
|
|
|
const DELAY = 600;
|
2018-04-04 01:44:19 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Max Safe Integer -- on IE this is not available, so manually set the number in that case.
|
|
|
|
* The reason this is used, instead of Infinity is because numbers above the MSI are unstable
|
|
|
|
*/
|
2019-01-12 03:33:27 +00:00
|
|
|
const MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || Math.pow(2, 53) - 1;
|
2019-03-01 12:46:26 +00:00
|
|
|
|
|
|
|
const isValidProps = value => value !== undefined && value !== null;
|
|
|
|
|
2020-03-07 11:45:13 +00:00
|
|
|
const isEqual = (oldValue, newValue) =>
|
|
|
|
newValue === oldValue ||
|
|
|
|
(typeof newValue === 'number' &&
|
|
|
|
typeof oldValue === 'number' &&
|
|
|
|
isNaN(newValue) &&
|
|
|
|
isNaN(oldValue));
|
|
|
|
|
2018-04-04 04:04:49 +00:00
|
|
|
const inputNumberProps = {
|
2019-01-12 03:33:27 +00:00
|
|
|
value: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
|
|
|
|
defaultValue: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
|
2018-04-04 04:04:49 +00:00
|
|
|
focusOnUpDown: PropTypes.bool,
|
|
|
|
autoFocus: PropTypes.bool,
|
|
|
|
// onChange: PropTypes.func,
|
|
|
|
// onKeyDown: PropTypes.func,
|
|
|
|
// onKeyUp: PropTypes.func,
|
|
|
|
prefixCls: PropTypes.string,
|
2018-09-05 13:28:54 +00:00
|
|
|
tabIndex: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
2018-05-31 08:36:59 +00:00
|
|
|
placeholder: PropTypes.string,
|
2018-04-04 04:04:49 +00:00
|
|
|
disabled: PropTypes.bool,
|
|
|
|
// onFocus: PropTypes.func,
|
|
|
|
// onBlur: PropTypes.func,
|
|
|
|
readOnly: PropTypes.bool,
|
|
|
|
max: PropTypes.number,
|
|
|
|
min: PropTypes.number,
|
2019-01-12 03:33:27 +00:00
|
|
|
step: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
|
2018-04-04 04:04:49 +00:00
|
|
|
upHandler: PropTypes.any,
|
|
|
|
downHandler: PropTypes.any,
|
|
|
|
useTouch: PropTypes.bool,
|
|
|
|
formatter: PropTypes.func,
|
|
|
|
parser: PropTypes.func,
|
|
|
|
// onMouseEnter: PropTypes.func,
|
|
|
|
// onMouseLeave: PropTypes.func,
|
|
|
|
// onMouseOver: PropTypes.func,
|
|
|
|
// onMouseOut: PropTypes.func,
|
|
|
|
precision: PropTypes.number,
|
|
|
|
required: PropTypes.bool,
|
|
|
|
pattern: PropTypes.string,
|
2018-11-02 13:23:29 +00:00
|
|
|
decimalSeparator: PropTypes.string,
|
2019-01-01 13:19:50 +00:00
|
|
|
autoComplete: PropTypes.string,
|
|
|
|
title: PropTypes.string,
|
2019-11-30 03:49:27 +00:00
|
|
|
name: PropTypes.string,
|
|
|
|
id: PropTypes.string,
|
2019-01-12 03:33:27 +00:00
|
|
|
};
|
2018-04-04 01:44:19 +00:00
|
|
|
|
2018-04-04 04:04:49 +00:00
|
|
|
export default {
|
2020-03-07 11:45:13 +00:00
|
|
|
name: 'VCInputNumber',
|
2018-04-04 04:04:49 +00:00
|
|
|
mixins: [BaseMixin],
|
|
|
|
model: {
|
|
|
|
prop: 'value',
|
|
|
|
event: 'change',
|
|
|
|
},
|
|
|
|
props: initDefaultProps(inputNumberProps, {
|
2018-04-04 01:44:19 +00:00
|
|
|
focusOnUpDown: true,
|
|
|
|
useTouch: false,
|
|
|
|
prefixCls: 'rc-input-number',
|
|
|
|
min: -MAX_SAFE_INTEGER,
|
|
|
|
step: 1,
|
|
|
|
parser: defaultParser,
|
|
|
|
required: false,
|
2019-01-01 13:19:50 +00:00
|
|
|
autoComplete: 'off',
|
2018-04-04 04:04:49 +00:00
|
|
|
}),
|
2019-01-12 03:33:27 +00:00
|
|
|
data() {
|
2020-03-07 11:45:13 +00:00
|
|
|
const props = getOptionProps(this);
|
|
|
|
this.prevProps = { ...props };
|
2019-01-12 03:33:27 +00:00
|
|
|
let value;
|
2020-03-07 11:45:13 +00:00
|
|
|
if ('value' in props) {
|
2019-01-12 03:33:27 +00:00
|
|
|
value = this.value;
|
2018-04-04 01:44:19 +00:00
|
|
|
} else {
|
2019-01-12 03:33:27 +00:00
|
|
|
value = this.defaultValue;
|
2018-04-04 01:44:19 +00:00
|
|
|
}
|
2020-03-07 11:45:13 +00:00
|
|
|
const validValue = this.getValidValue(this.toNumber(value));
|
2018-04-04 04:04:49 +00:00
|
|
|
return {
|
2020-03-07 11:45:13 +00:00
|
|
|
inputValue: this.toPrecisionAsStep(validValue),
|
|
|
|
sValue: validValue,
|
2018-04-04 04:04:49 +00:00
|
|
|
focused: this.autoFocus,
|
2019-01-12 03:33:27 +00:00
|
|
|
};
|
2018-04-04 04:04:49 +00:00
|
|
|
},
|
2019-01-12 03:33:27 +00:00
|
|
|
mounted() {
|
2018-04-04 04:04:49 +00:00
|
|
|
this.$nextTick(() => {
|
2018-06-09 07:48:34 +00:00
|
|
|
if (this.autoFocus && !this.disabled) {
|
2019-01-12 03:33:27 +00:00
|
|
|
this.focus();
|
2018-06-09 07:48:34 +00:00
|
|
|
}
|
2019-01-12 03:33:27 +00:00
|
|
|
this.updatedFunc();
|
|
|
|
});
|
2018-04-04 04:04:49 +00:00
|
|
|
},
|
2019-01-12 03:33:27 +00:00
|
|
|
updated() {
|
2020-03-07 11:45:13 +00:00
|
|
|
const { value, max, min } = this.$props;
|
|
|
|
const { focused } = this.$data;
|
|
|
|
const { prevProps } = this;
|
|
|
|
const props = getOptionProps(this);
|
|
|
|
// Don't trigger in componentDidMount
|
|
|
|
if (prevProps) {
|
|
|
|
if (
|
|
|
|
!isEqual(prevProps.value, value) ||
|
|
|
|
!isEqual(prevProps.max, max) ||
|
|
|
|
!isEqual(prevProps.min, min)
|
|
|
|
) {
|
|
|
|
const validValue = focused ? value : this.getValidValue(value);
|
|
|
|
let nextInputValue;
|
|
|
|
if (this.pressingUpOrDown) {
|
|
|
|
nextInputValue = validValue;
|
|
|
|
} else if (this.inputting) {
|
|
|
|
nextInputValue = this.rawInput;
|
|
|
|
} else {
|
|
|
|
nextInputValue = this.toPrecisionAsStep(validValue);
|
|
|
|
}
|
|
|
|
this.setState({
|
|
|
|
// eslint-disable-line
|
|
|
|
sValue: validValue,
|
|
|
|
inputValue: nextInputValue,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// Trigger onChange when max or min change
|
|
|
|
// https://github.com/ant-design/ant-design/issues/11574
|
|
|
|
const nextValue = 'value' in props ? value : this.sValue;
|
|
|
|
// ref: null < 20 === true
|
|
|
|
// https://github.com/ant-design/ant-design/issues/14277
|
|
|
|
if (
|
|
|
|
'max' in props &&
|
|
|
|
prevProps.max !== max &&
|
|
|
|
typeof nextValue === 'number' &&
|
|
|
|
nextValue > max
|
|
|
|
) {
|
|
|
|
this.$emit('change', max);
|
|
|
|
}
|
|
|
|
if (
|
|
|
|
'min' in props &&
|
|
|
|
prevProps.min !== min &&
|
|
|
|
typeof nextValue === 'number' &&
|
|
|
|
nextValue < min
|
|
|
|
) {
|
|
|
|
this.$emit('change', min);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
this.prevProps = { ...props };
|
2018-04-04 04:04:49 +00:00
|
|
|
this.$nextTick(() => {
|
2019-01-12 03:33:27 +00:00
|
|
|
this.updatedFunc();
|
|
|
|
});
|
2018-04-04 04:04:49 +00:00
|
|
|
},
|
2019-01-12 03:33:27 +00:00
|
|
|
beforeDestroy() {
|
|
|
|
this.stop();
|
2018-04-04 04:04:49 +00:00
|
|
|
},
|
|
|
|
methods: {
|
2019-01-12 03:33:27 +00:00
|
|
|
updatedFunc() {
|
|
|
|
const inputElem = this.$refs.inputRef;
|
2018-09-05 13:28:54 +00:00
|
|
|
// Restore cursor
|
|
|
|
try {
|
2019-01-12 03:33:27 +00:00
|
|
|
// Firefox set the input cursor after it get focused.
|
|
|
|
// This caused that if an input didn't init with the selection,
|
|
|
|
// set will cause cursor not correct when first focus.
|
|
|
|
// Safari will focus input if set selection. We need skip this.
|
2018-09-05 13:28:54 +00:00
|
|
|
if (this.cursorStart !== undefined && this.focused) {
|
2019-01-12 03:33:27 +00:00
|
|
|
// In most cases, the string after cursor is stable.
|
|
|
|
// We can move the cursor before it
|
2018-09-05 13:28:54 +00:00
|
|
|
|
|
|
|
if (
|
2019-01-12 03:33:27 +00:00
|
|
|
// If not match full str, try to match part of str
|
|
|
|
!this.partRestoreByAfter(this.cursorAfter) &&
|
|
|
|
this.sValue !== this.value
|
2018-09-05 13:28:54 +00:00
|
|
|
) {
|
2019-01-12 03:33:27 +00:00
|
|
|
// If not match any of then, let's just keep the position
|
|
|
|
// TODO: Logic should not reach here, need check if happens
|
|
|
|
let pos = this.cursorStart + 1;
|
2018-09-05 13:28:54 +00:00
|
|
|
|
|
|
|
// If not have last string, just position to the end
|
|
|
|
if (!this.cursorAfter) {
|
2019-01-12 03:33:27 +00:00
|
|
|
pos = inputElem.value.length;
|
2018-09-05 13:28:54 +00:00
|
|
|
} else if (this.lastKeyCode === KeyCode.BACKSPACE) {
|
2019-01-12 03:33:27 +00:00
|
|
|
pos = this.cursorStart - 1;
|
2018-09-05 13:28:54 +00:00
|
|
|
} else if (this.lastKeyCode === KeyCode.DELETE) {
|
2019-01-12 03:33:27 +00:00
|
|
|
pos = this.cursorStart;
|
2018-09-05 13:28:54 +00:00
|
|
|
}
|
2019-01-12 03:33:27 +00:00
|
|
|
this.fixCaret(pos, pos);
|
2018-09-05 13:28:54 +00:00
|
|
|
} else if (this.currentValue === inputElem.value) {
|
2019-01-12 03:33:27 +00:00
|
|
|
// Handle some special key code
|
2018-09-05 13:28:54 +00:00
|
|
|
switch (this.lastKeyCode) {
|
|
|
|
case KeyCode.BACKSPACE:
|
2019-01-12 03:33:27 +00:00
|
|
|
this.fixCaret(this.cursorStart - 1, this.cursorStart - 1);
|
|
|
|
break;
|
2018-09-05 13:28:54 +00:00
|
|
|
case KeyCode.DELETE:
|
2019-01-12 03:33:27 +00:00
|
|
|
this.fixCaret(this.cursorStart + 1, this.cursorStart + 1);
|
|
|
|
break;
|
2018-09-05 13:28:54 +00:00
|
|
|
default:
|
2019-01-12 03:33:27 +00:00
|
|
|
// Do nothing
|
2018-09-05 13:28:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (e) {
|
2019-01-12 03:33:27 +00:00
|
|
|
// Do nothing
|
2018-09-05 13:28:54 +00:00
|
|
|
}
|
|
|
|
// Reset last key
|
2019-01-12 03:33:27 +00:00
|
|
|
this.lastKeyCode = null;
|
2018-09-05 13:28:54 +00:00
|
|
|
|
|
|
|
// pressingUpOrDown is true means that someone just click up or down button
|
2018-04-04 04:04:49 +00:00
|
|
|
if (!this.pressingUpOrDown) {
|
2019-01-12 03:33:27 +00:00
|
|
|
return;
|
2018-04-04 01:44:19 +00:00
|
|
|
}
|
2018-04-04 04:04:49 +00:00
|
|
|
if (this.focusOnUpDown && this.focused) {
|
2018-09-05 13:28:54 +00:00
|
|
|
if (document.activeElement !== inputElem) {
|
2019-01-12 03:33:27 +00:00
|
|
|
this.focus();
|
2018-04-04 04:04:49 +00:00
|
|
|
}
|
|
|
|
}
|
2018-09-05 13:28:54 +00:00
|
|
|
|
2019-01-12 03:33:27 +00:00
|
|
|
this.pressingUpOrDown = false;
|
2018-04-04 04:04:49 +00:00
|
|
|
},
|
2019-01-12 03:33:27 +00:00
|
|
|
onKeyDown(e, ...args) {
|
2018-09-05 13:28:54 +00:00
|
|
|
if (e.keyCode === KeyCode.UP) {
|
2019-01-12 03:33:27 +00:00
|
|
|
const ratio = this.getRatio(e);
|
|
|
|
this.up(e, ratio);
|
|
|
|
this.stop();
|
2018-09-05 13:28:54 +00:00
|
|
|
} else if (e.keyCode === KeyCode.DOWN) {
|
2019-01-12 03:33:27 +00:00
|
|
|
const ratio = this.getRatio(e);
|
|
|
|
this.down(e, ratio);
|
|
|
|
this.stop();
|
2020-03-07 11:45:13 +00:00
|
|
|
} else if (e.keyCode === KeyCode.ENTER) {
|
|
|
|
this.$emit('pressEnter', e);
|
2018-04-04 04:04:49 +00:00
|
|
|
}
|
2018-09-05 13:28:54 +00:00
|
|
|
// Trigger user key down
|
2019-01-12 03:33:27 +00:00
|
|
|
this.recordCursorPosition();
|
|
|
|
this.lastKeyCode = e.keyCode;
|
|
|
|
this.$emit('keydown', e, ...args);
|
2018-04-04 04:04:49 +00:00
|
|
|
},
|
2019-01-12 03:33:27 +00:00
|
|
|
onKeyUp(e, ...args) {
|
|
|
|
this.stop();
|
2018-09-05 13:28:54 +00:00
|
|
|
|
2019-01-12 03:33:27 +00:00
|
|
|
this.recordCursorPosition();
|
2018-09-05 13:28:54 +00:00
|
|
|
|
2019-01-12 03:33:27 +00:00
|
|
|
this.$emit('keyup', e, ...args);
|
2018-04-04 04:04:49 +00:00
|
|
|
},
|
2019-01-12 03:33:27 +00:00
|
|
|
onChange(e) {
|
2018-04-04 04:04:49 +00:00
|
|
|
if (this.focused) {
|
2019-01-12 03:33:27 +00:00
|
|
|
this.inputting = true;
|
2018-04-04 04:04:49 +00:00
|
|
|
}
|
2020-03-07 11:45:13 +00:00
|
|
|
this.rawInput = this.parser(this.getValueFromEvent(e));
|
|
|
|
this.setState({ inputValue: this.rawInput });
|
|
|
|
this.$emit('change', this.toNumber(this.rawInput)); // valid number or invalid string
|
2018-04-04 04:04:49 +00:00
|
|
|
},
|
2019-01-12 03:33:27 +00:00
|
|
|
onFocus(...args) {
|
2018-04-04 01:44:19 +00:00
|
|
|
this.setState({
|
2018-04-04 04:04:49 +00:00
|
|
|
focused: true,
|
2019-01-12 03:33:27 +00:00
|
|
|
});
|
|
|
|
this.$emit('focus', ...args);
|
2018-04-04 04:04:49 +00:00
|
|
|
},
|
2020-03-07 11:45:13 +00:00
|
|
|
onBlur(...args) {
|
2019-01-12 03:33:27 +00:00
|
|
|
this.inputting = false;
|
2018-04-04 01:44:19 +00:00
|
|
|
this.setState({
|
2018-04-04 04:04:49 +00:00
|
|
|
focused: false,
|
2019-01-12 03:33:27 +00:00
|
|
|
});
|
|
|
|
const value = this.getCurrentValidValue(this.inputValue);
|
2020-03-07 11:45:13 +00:00
|
|
|
const newValue = this.setValue(value);
|
|
|
|
if (this.$listeners.blur) {
|
|
|
|
const originValue = this.$refs.inputRef.value;
|
|
|
|
const inputValue = this.getInputDisplayValue({ focused: false, sValue: newValue });
|
|
|
|
this.$refs.inputRef.value = inputValue;
|
|
|
|
this.$emit('blur', ...args);
|
|
|
|
this.$refs.inputRef.value = originValue;
|
|
|
|
}
|
2018-04-04 04:04:49 +00:00
|
|
|
},
|
2019-01-12 03:33:27 +00:00
|
|
|
getCurrentValidValue(value) {
|
|
|
|
let val = value;
|
2018-04-04 04:04:49 +00:00
|
|
|
if (val === '') {
|
2019-01-12 03:33:27 +00:00
|
|
|
val = '';
|
2019-01-01 13:19:50 +00:00
|
|
|
} else if (!this.isNotCompleteNumber(parseFloat(val, 10))) {
|
2019-01-12 03:33:27 +00:00
|
|
|
val = this.getValidValue(val);
|
2018-04-04 04:04:49 +00:00
|
|
|
} else {
|
2019-01-12 03:33:27 +00:00
|
|
|
val = this.sValue;
|
2018-04-04 04:04:49 +00:00
|
|
|
}
|
2019-01-12 03:33:27 +00:00
|
|
|
return this.toNumber(val);
|
2018-04-04 04:04:49 +00:00
|
|
|
},
|
2019-01-12 03:33:27 +00:00
|
|
|
getRatio(e) {
|
|
|
|
let ratio = 1;
|
2018-04-04 04:04:49 +00:00
|
|
|
if (e.metaKey || e.ctrlKey) {
|
2019-01-12 03:33:27 +00:00
|
|
|
ratio = 0.1;
|
2018-04-04 04:04:49 +00:00
|
|
|
} else if (e.shiftKey) {
|
2019-01-12 03:33:27 +00:00
|
|
|
ratio = 10;
|
2018-04-04 04:04:49 +00:00
|
|
|
}
|
2019-01-12 03:33:27 +00:00
|
|
|
return ratio;
|
2018-04-04 04:04:49 +00:00
|
|
|
},
|
2019-01-12 03:33:27 +00:00
|
|
|
getValueFromEvent(e) {
|
2018-04-04 04:04:49 +00:00
|
|
|
// optimize for chinese input expierence
|
2019-01-12 03:33:27 +00:00
|
|
|
// https://github.com/ant-design/ant-design/issues/8196
|
|
|
|
let value = e.target.value.trim().replace(/。/g, '.');
|
2018-11-02 13:23:29 +00:00
|
|
|
|
2019-03-01 12:46:26 +00:00
|
|
|
if (isValidProps(this.decimalSeparator)) {
|
2019-01-12 03:33:27 +00:00
|
|
|
value = value.replace(this.decimalSeparator, '.');
|
2018-11-02 13:23:29 +00:00
|
|
|
}
|
|
|
|
|
2019-01-12 03:33:27 +00:00
|
|
|
return value;
|
2018-04-04 04:04:49 +00:00
|
|
|
},
|
2019-01-12 03:33:27 +00:00
|
|
|
getValidValue(value, min = this.min, max = this.max) {
|
|
|
|
let val = parseFloat(value, 10);
|
2018-04-04 04:04:49 +00:00
|
|
|
// https://github.com/ant-design/ant-design/issues/7358
|
|
|
|
if (isNaN(val)) {
|
2019-01-12 03:33:27 +00:00
|
|
|
return value;
|
2018-04-04 04:04:49 +00:00
|
|
|
}
|
|
|
|
if (val < min) {
|
2019-01-12 03:33:27 +00:00
|
|
|
val = min;
|
2018-04-04 04:04:49 +00:00
|
|
|
}
|
|
|
|
if (val > max) {
|
2019-01-12 03:33:27 +00:00
|
|
|
val = max;
|
2018-04-04 04:04:49 +00:00
|
|
|
}
|
2019-01-12 03:33:27 +00:00
|
|
|
return val;
|
2018-04-04 04:04:49 +00:00
|
|
|
},
|
2019-01-12 03:33:27 +00:00
|
|
|
setValue(v, callback) {
|
2018-04-04 04:04:49 +00:00
|
|
|
// trigger onChange
|
2020-03-07 11:45:13 +00:00
|
|
|
const { precision } = this.$props;
|
2019-03-01 12:46:26 +00:00
|
|
|
const newValue = this.isNotCompleteNumber(parseFloat(v, 10)) ? null : parseFloat(v, 10);
|
2020-03-07 11:45:13 +00:00
|
|
|
const { sValue: value = null, inputValue = null } = this.$data;
|
|
|
|
// https://github.com/ant-design/ant-design/issues/7363
|
|
|
|
// https://github.com/ant-design/ant-design/issues/16622
|
|
|
|
const newValueInString =
|
|
|
|
typeof newValue === 'number' ? newValue.toFixed(precision) : `${newValue}`;
|
|
|
|
const changed = newValue !== value || newValueInString !== `${inputValue}`;
|
2018-04-04 04:04:49 +00:00
|
|
|
if (!hasProp(this, 'value')) {
|
2019-01-12 03:33:27 +00:00
|
|
|
this.setState(
|
|
|
|
{
|
|
|
|
sValue: newValue,
|
|
|
|
inputValue: this.toPrecisionAsStep(v),
|
|
|
|
},
|
|
|
|
callback,
|
|
|
|
);
|
2018-04-04 04:04:49 +00:00
|
|
|
} else {
|
|
|
|
// always set input value same as value
|
2019-01-12 03:33:27 +00:00
|
|
|
this.setState(
|
|
|
|
{
|
|
|
|
inputValue: this.toPrecisionAsStep(this.sValue),
|
|
|
|
},
|
|
|
|
callback,
|
|
|
|
);
|
2018-04-04 04:04:49 +00:00
|
|
|
}
|
|
|
|
if (changed) {
|
2019-01-12 03:33:27 +00:00
|
|
|
this.$emit('change', newValue);
|
2018-04-04 04:04:49 +00:00
|
|
|
}
|
2020-03-07 11:45:13 +00:00
|
|
|
return newValue;
|
2018-04-04 04:04:49 +00:00
|
|
|
},
|
2019-01-12 03:33:27 +00:00
|
|
|
getPrecision(value) {
|
2019-03-01 12:46:26 +00:00
|
|
|
if (isValidProps(this.precision)) {
|
2019-01-12 03:33:27 +00:00
|
|
|
return this.precision;
|
2018-04-04 04:04:49 +00:00
|
|
|
}
|
2019-01-12 03:33:27 +00:00
|
|
|
const valueString = value.toString();
|
2018-04-04 04:04:49 +00:00
|
|
|
if (valueString.indexOf('e-') >= 0) {
|
2019-01-12 03:33:27 +00:00
|
|
|
return parseInt(valueString.slice(valueString.indexOf('e-') + 2), 10);
|
2018-04-04 04:04:49 +00:00
|
|
|
}
|
2019-01-12 03:33:27 +00:00
|
|
|
let precision = 0;
|
2018-04-04 04:04:49 +00:00
|
|
|
if (valueString.indexOf('.') >= 0) {
|
2019-01-12 03:33:27 +00:00
|
|
|
precision = valueString.length - valueString.indexOf('.') - 1;
|
2018-04-04 04:04:49 +00:00
|
|
|
}
|
2019-01-12 03:33:27 +00:00
|
|
|
return precision;
|
2018-04-04 04:04:49 +00:00
|
|
|
},
|
|
|
|
// step={1.0} value={1.51}
|
|
|
|
// press +
|
|
|
|
// then value should be 2.51, rather than 2.5
|
2020-03-07 11:45:13 +00:00
|
|
|
// if this.$props.precision is undefined
|
2018-04-04 04:04:49 +00:00
|
|
|
// https://github.com/react-component/input-number/issues/39
|
2019-01-12 03:33:27 +00:00
|
|
|
getMaxPrecision(currentValue, ratio = 1) {
|
2019-03-01 12:46:26 +00:00
|
|
|
if (isValidProps(this.precision)) {
|
2019-01-12 03:33:27 +00:00
|
|
|
return this.precision;
|
2018-04-04 04:04:49 +00:00
|
|
|
}
|
2019-01-12 03:33:27 +00:00
|
|
|
const { step } = this;
|
|
|
|
const ratioPrecision = this.getPrecision(ratio);
|
|
|
|
const stepPrecision = this.getPrecision(step);
|
|
|
|
const currentValuePrecision = this.getPrecision(currentValue);
|
2018-04-04 04:04:49 +00:00
|
|
|
if (!currentValue) {
|
2019-01-12 03:33:27 +00:00
|
|
|
return ratioPrecision + stepPrecision;
|
2018-04-04 04:04:49 +00:00
|
|
|
}
|
2019-01-12 03:33:27 +00:00
|
|
|
return Math.max(currentValuePrecision, ratioPrecision + stepPrecision);
|
2018-04-04 04:04:49 +00:00
|
|
|
},
|
2019-01-12 03:33:27 +00:00
|
|
|
getPrecisionFactor(currentValue, ratio = 1) {
|
|
|
|
const precision = this.getMaxPrecision(currentValue, ratio);
|
|
|
|
return Math.pow(10, precision);
|
2018-04-04 04:04:49 +00:00
|
|
|
},
|
2020-03-07 11:45:13 +00:00
|
|
|
getInputDisplayValue(state) {
|
|
|
|
const { focused, inputValue, sValue } = state || this.$data;
|
2019-01-12 03:33:27 +00:00
|
|
|
let inputDisplayValue;
|
2018-09-05 13:28:54 +00:00
|
|
|
if (focused) {
|
2019-01-12 03:33:27 +00:00
|
|
|
inputDisplayValue = inputValue;
|
2018-09-05 13:28:54 +00:00
|
|
|
} else {
|
2019-01-12 03:33:27 +00:00
|
|
|
inputDisplayValue = this.toPrecisionAsStep(sValue);
|
2018-09-05 13:28:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (inputDisplayValue === undefined || inputDisplayValue === null) {
|
2019-01-12 03:33:27 +00:00
|
|
|
inputDisplayValue = '';
|
2018-09-05 13:28:54 +00:00
|
|
|
}
|
|
|
|
|
2020-03-07 11:45:13 +00:00
|
|
|
let inputDisplayValueFormat = this.formatWrapper(inputDisplayValue);
|
|
|
|
if (isValidProps(this.$props.decimalSeparator)) {
|
|
|
|
inputDisplayValueFormat = inputDisplayValueFormat
|
|
|
|
.toString()
|
|
|
|
.replace('.', this.$props.decimalSeparator);
|
|
|
|
}
|
|
|
|
|
|
|
|
return inputDisplayValueFormat;
|
2018-09-05 13:28:54 +00:00
|
|
|
},
|
2019-01-12 03:33:27 +00:00
|
|
|
recordCursorPosition() {
|
2018-09-05 13:28:54 +00:00
|
|
|
// Record position
|
|
|
|
try {
|
2019-01-12 03:33:27 +00:00
|
|
|
const inputElem = this.$refs.inputRef;
|
|
|
|
this.cursorStart = inputElem.selectionStart;
|
|
|
|
this.cursorEnd = inputElem.selectionEnd;
|
|
|
|
this.currentValue = inputElem.value;
|
|
|
|
this.cursorBefore = inputElem.value.substring(0, this.cursorStart);
|
|
|
|
this.cursorAfter = inputElem.value.substring(this.cursorEnd);
|
2018-09-05 13:28:54 +00:00
|
|
|
} catch (e) {
|
|
|
|
// Fix error in Chrome:
|
|
|
|
// Failed to read the 'selectionStart' property from 'HTMLInputElement'
|
|
|
|
// http://stackoverflow.com/q/21177489/3040605
|
|
|
|
}
|
|
|
|
},
|
2019-01-12 03:33:27 +00:00
|
|
|
fixCaret(start, end) {
|
2020-03-07 11:45:13 +00:00
|
|
|
if (
|
|
|
|
start === undefined ||
|
|
|
|
end === undefined ||
|
|
|
|
!this.$refs.inputRef ||
|
|
|
|
!this.$refs.inputRef.value
|
|
|
|
) {
|
2019-01-12 03:33:27 +00:00
|
|
|
return;
|
2018-09-05 13:28:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
2019-01-12 03:33:27 +00:00
|
|
|
const inputElem = this.$refs.inputRef;
|
|
|
|
const currentStart = inputElem.selectionStart;
|
|
|
|
const currentEnd = inputElem.selectionEnd;
|
2018-09-05 13:28:54 +00:00
|
|
|
|
|
|
|
if (start !== currentStart || end !== currentEnd) {
|
2019-01-12 03:33:27 +00:00
|
|
|
inputElem.setSelectionRange(start, end);
|
2018-09-05 13:28:54 +00:00
|
|
|
}
|
|
|
|
} catch (e) {
|
|
|
|
// Fix error in Chrome:
|
|
|
|
// Failed to read the 'selectionStart' property from 'HTMLInputElement'
|
|
|
|
// http://stackoverflow.com/q/21177489/3040605
|
|
|
|
}
|
|
|
|
},
|
2019-01-12 03:33:27 +00:00
|
|
|
restoreByAfter(str) {
|
|
|
|
if (str === undefined) return false;
|
2018-09-05 13:28:54 +00:00
|
|
|
|
2019-01-12 03:33:27 +00:00
|
|
|
const fullStr = this.$refs.inputRef.value;
|
|
|
|
const index = fullStr.lastIndexOf(str);
|
2018-09-05 13:28:54 +00:00
|
|
|
|
2019-01-12 03:33:27 +00:00
|
|
|
if (index === -1) return false;
|
2018-09-05 13:28:54 +00:00
|
|
|
|
2020-03-07 11:45:13 +00:00
|
|
|
const prevCursorPos = this.cursorBefore.length;
|
|
|
|
if (
|
|
|
|
this.lastKeyCode === KeyCode.DELETE &&
|
|
|
|
this.cursorBefore.charAt(prevCursorPos - 1) === str[0]
|
|
|
|
) {
|
|
|
|
this.fixCaret(prevCursorPos, prevCursorPos);
|
|
|
|
return true;
|
|
|
|
}
|
2018-09-05 13:28:54 +00:00
|
|
|
if (index + str.length === fullStr.length) {
|
2019-01-12 03:33:27 +00:00
|
|
|
this.fixCaret(index, index);
|
2018-09-05 13:28:54 +00:00
|
|
|
|
2019-01-12 03:33:27 +00:00
|
|
|
return true;
|
2018-09-05 13:28:54 +00:00
|
|
|
}
|
2019-01-12 03:33:27 +00:00
|
|
|
return false;
|
2018-09-05 13:28:54 +00:00
|
|
|
},
|
2019-01-12 03:33:27 +00:00
|
|
|
partRestoreByAfter(str) {
|
|
|
|
if (str === undefined) return false;
|
2018-09-05 13:28:54 +00:00
|
|
|
|
|
|
|
// For loop from full str to the str with last char to map. e.g. 123
|
|
|
|
// -> 123
|
|
|
|
// -> 23
|
|
|
|
// -> 3
|
|
|
|
return Array.prototype.some.call(str, (_, start) => {
|
2019-01-12 03:33:27 +00:00
|
|
|
const partStr = str.substring(start);
|
2018-09-05 13:28:54 +00:00
|
|
|
|
2019-01-12 03:33:27 +00:00
|
|
|
return this.restoreByAfter(partStr);
|
|
|
|
});
|
2018-09-05 13:28:54 +00:00
|
|
|
},
|
2019-01-12 03:33:27 +00:00
|
|
|
focus() {
|
|
|
|
this.$refs.inputRef.focus();
|
|
|
|
this.recordCursorPosition();
|
2018-04-04 04:04:49 +00:00
|
|
|
},
|
2019-01-12 03:33:27 +00:00
|
|
|
blur() {
|
|
|
|
this.$refs.inputRef.blur();
|
2018-04-04 04:04:49 +00:00
|
|
|
},
|
2019-01-12 03:33:27 +00:00
|
|
|
formatWrapper(num) {
|
2018-04-04 04:04:49 +00:00
|
|
|
// http://2ality.com/2012/03/signedzero.html
|
|
|
|
// https://github.com/ant-design/ant-design/issues/9439
|
|
|
|
if (this.formatter) {
|
2019-01-12 03:33:27 +00:00
|
|
|
return this.formatter(num);
|
2018-04-04 04:04:49 +00:00
|
|
|
}
|
2019-01-12 03:33:27 +00:00
|
|
|
return num;
|
2018-04-04 04:04:49 +00:00
|
|
|
},
|
2019-01-12 03:33:27 +00:00
|
|
|
toPrecisionAsStep(num) {
|
2018-04-04 04:04:49 +00:00
|
|
|
if (this.isNotCompleteNumber(num) || num === '') {
|
2019-01-12 03:33:27 +00:00
|
|
|
return num;
|
2018-04-04 04:04:49 +00:00
|
|
|
}
|
2019-01-12 03:33:27 +00:00
|
|
|
const precision = Math.abs(this.getMaxPrecision(num));
|
2018-04-04 04:04:49 +00:00
|
|
|
if (!isNaN(precision)) {
|
2019-01-12 03:33:27 +00:00
|
|
|
return Number(num).toFixed(precision);
|
2018-04-04 04:04:49 +00:00
|
|
|
}
|
2019-01-12 03:33:27 +00:00
|
|
|
return num.toString();
|
2018-04-04 04:04:49 +00:00
|
|
|
},
|
|
|
|
// '1.' '1x' 'xx' '' => are not complete numbers
|
2019-01-12 03:33:27 +00:00
|
|
|
isNotCompleteNumber(num) {
|
2018-04-04 04:04:49 +00:00
|
|
|
return (
|
|
|
|
isNaN(num) ||
|
|
|
|
num === '' ||
|
|
|
|
num === null ||
|
|
|
|
(num && num.toString().indexOf('.') === num.toString().length - 1)
|
2019-01-12 03:33:27 +00:00
|
|
|
);
|
2018-04-04 04:04:49 +00:00
|
|
|
},
|
2019-01-12 03:33:27 +00:00
|
|
|
toNumber(num) {
|
2020-03-07 11:45:13 +00:00
|
|
|
const { precision, autoFocus } = this.$props;
|
|
|
|
const { focused = autoFocus } = this;
|
|
|
|
// num.length > 16 => This is to prevent input of large numbers
|
|
|
|
const numberIsTooLarge = num && num.length > 16 && focused;
|
|
|
|
if (this.isNotCompleteNumber(num) || numberIsTooLarge) {
|
2019-01-12 03:33:27 +00:00
|
|
|
return num;
|
2018-04-04 04:04:49 +00:00
|
|
|
}
|
2020-03-07 11:45:13 +00:00
|
|
|
if (isValidProps(precision)) {
|
|
|
|
return Math.round(num * Math.pow(10, precision)) / Math.pow(10, precision);
|
2018-04-04 04:04:49 +00:00
|
|
|
}
|
2019-01-12 03:33:27 +00:00
|
|
|
return Number(num);
|
2018-04-04 04:04:49 +00:00
|
|
|
},
|
2019-01-12 03:33:27 +00:00
|
|
|
upStep(val, rat) {
|
2020-03-07 11:45:13 +00:00
|
|
|
const { step } = this;
|
2019-01-12 03:33:27 +00:00
|
|
|
const precisionFactor = this.getPrecisionFactor(val, rat);
|
|
|
|
const precision = Math.abs(this.getMaxPrecision(val, rat));
|
2020-03-07 11:45:13 +00:00
|
|
|
const result = (
|
|
|
|
(precisionFactor * val + precisionFactor * step * rat) /
|
|
|
|
precisionFactor
|
|
|
|
).toFixed(precision);
|
2019-01-12 03:33:27 +00:00
|
|
|
return this.toNumber(result);
|
2018-04-04 04:04:49 +00:00
|
|
|
},
|
2019-01-12 03:33:27 +00:00
|
|
|
downStep(val, rat) {
|
2020-03-07 11:45:13 +00:00
|
|
|
const { step } = this;
|
2019-01-12 03:33:27 +00:00
|
|
|
const precisionFactor = this.getPrecisionFactor(val, rat);
|
|
|
|
const precision = Math.abs(this.getMaxPrecision(val, rat));
|
2020-03-07 11:45:13 +00:00
|
|
|
const result = (
|
|
|
|
(precisionFactor * val - precisionFactor * step * rat) /
|
|
|
|
precisionFactor
|
|
|
|
).toFixed(precision);
|
2019-01-12 03:33:27 +00:00
|
|
|
return this.toNumber(result);
|
2018-04-04 04:04:49 +00:00
|
|
|
},
|
2019-01-12 03:33:27 +00:00
|
|
|
stepFn(type, e, ratio = 1, recursive) {
|
|
|
|
this.stop();
|
2018-04-04 04:04:49 +00:00
|
|
|
if (e) {
|
|
|
|
// e.persist()
|
2019-01-12 03:33:27 +00:00
|
|
|
e.preventDefault();
|
2018-04-04 04:04:49 +00:00
|
|
|
}
|
|
|
|
if (this.disabled) {
|
2019-01-12 03:33:27 +00:00
|
|
|
return;
|
2018-04-04 04:04:49 +00:00
|
|
|
}
|
2019-01-12 03:33:27 +00:00
|
|
|
const { max, min } = this;
|
|
|
|
const value = this.getCurrentValidValue(this.inputValue) || 0;
|
2018-04-04 04:04:49 +00:00
|
|
|
if (this.isNotCompleteNumber(value)) {
|
2019-01-12 03:33:27 +00:00
|
|
|
return;
|
2018-04-04 04:04:49 +00:00
|
|
|
}
|
2019-01-12 03:33:27 +00:00
|
|
|
let val = this[`${type}Step`](value, ratio);
|
|
|
|
const outOfRange = val > max || val < min;
|
2018-04-04 04:04:49 +00:00
|
|
|
if (val > max) {
|
2019-01-12 03:33:27 +00:00
|
|
|
val = max;
|
2018-04-04 04:04:49 +00:00
|
|
|
} else if (val < min) {
|
2019-01-12 03:33:27 +00:00
|
|
|
val = min;
|
2018-04-04 04:04:49 +00:00
|
|
|
}
|
2019-01-12 03:33:27 +00:00
|
|
|
this.setValue(val);
|
2018-04-04 04:04:49 +00:00
|
|
|
this.setState({
|
|
|
|
focused: true,
|
2019-01-12 03:33:27 +00:00
|
|
|
});
|
2018-04-04 04:04:49 +00:00
|
|
|
if (outOfRange) {
|
2019-01-12 03:33:27 +00:00
|
|
|
return;
|
2018-04-04 04:04:49 +00:00
|
|
|
}
|
2019-01-12 03:33:27 +00:00
|
|
|
this.autoStepTimer = setTimeout(
|
|
|
|
() => {
|
|
|
|
this[type](e, ratio, true);
|
|
|
|
},
|
|
|
|
recursive ? SPEED : DELAY,
|
|
|
|
);
|
2018-04-04 04:04:49 +00:00
|
|
|
},
|
2019-01-12 03:33:27 +00:00
|
|
|
stop() {
|
2018-04-04 04:04:49 +00:00
|
|
|
if (this.autoStepTimer) {
|
2019-01-12 03:33:27 +00:00
|
|
|
clearTimeout(this.autoStepTimer);
|
2018-04-04 04:04:49 +00:00
|
|
|
}
|
|
|
|
},
|
2019-01-12 03:33:27 +00:00
|
|
|
down(e, ratio, recursive) {
|
|
|
|
this.pressingUpOrDown = true;
|
|
|
|
this.stepFn('down', e, ratio, recursive);
|
2018-04-04 04:04:49 +00:00
|
|
|
},
|
2019-01-12 03:33:27 +00:00
|
|
|
up(e, ratio, recursive) {
|
|
|
|
this.pressingUpOrDown = true;
|
|
|
|
this.stepFn('up', e, ratio, recursive);
|
2018-04-04 04:04:49 +00:00
|
|
|
},
|
2019-01-12 03:33:27 +00:00
|
|
|
handleInputClick() {
|
|
|
|
this.$emit('click');
|
2018-04-04 04:04:49 +00:00
|
|
|
},
|
|
|
|
},
|
2019-01-12 03:33:27 +00:00
|
|
|
render() {
|
|
|
|
const {
|
|
|
|
prefixCls,
|
|
|
|
disabled,
|
|
|
|
readOnly,
|
|
|
|
useTouch,
|
|
|
|
autoComplete,
|
|
|
|
upHandler,
|
|
|
|
downHandler,
|
|
|
|
} = this.$props;
|
2018-04-04 01:44:19 +00:00
|
|
|
const classes = classNames({
|
|
|
|
[prefixCls]: true,
|
|
|
|
[`${prefixCls}-disabled`]: disabled,
|
2018-04-04 04:04:49 +00:00
|
|
|
[`${prefixCls}-focused`]: this.focused,
|
2019-01-12 03:33:27 +00:00
|
|
|
});
|
|
|
|
let upDisabledClass = '';
|
|
|
|
let downDisabledClass = '';
|
|
|
|
const { sValue } = this;
|
2018-04-04 04:04:49 +00:00
|
|
|
if (sValue || sValue === 0) {
|
|
|
|
if (!isNaN(sValue)) {
|
2019-01-12 03:33:27 +00:00
|
|
|
const val = Number(sValue);
|
2018-04-04 04:04:49 +00:00
|
|
|
if (val >= this.max) {
|
2019-01-12 03:33:27 +00:00
|
|
|
upDisabledClass = `${prefixCls}-handler-up-disabled`;
|
2018-04-04 01:44:19 +00:00
|
|
|
}
|
2018-04-04 04:04:49 +00:00
|
|
|
if (val <= this.min) {
|
2019-01-12 03:33:27 +00:00
|
|
|
downDisabledClass = `${prefixCls}-handler-down-disabled`;
|
2018-04-04 01:44:19 +00:00
|
|
|
}
|
|
|
|
} else {
|
2019-01-12 03:33:27 +00:00
|
|
|
upDisabledClass = `${prefixCls}-handler-up-disabled`;
|
|
|
|
downDisabledClass = `${prefixCls}-handler-down-disabled`;
|
2018-04-04 01:44:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-12 03:33:27 +00:00
|
|
|
const editable = !this.readOnly && !this.disabled;
|
2018-04-04 01:44:19 +00:00
|
|
|
|
|
|
|
// focus state, show input value
|
|
|
|
// unfocus state, show valid value
|
2020-03-07 11:45:13 +00:00
|
|
|
const inputDisplayValue = this.getInputDisplayValue();
|
2018-04-04 01:44:19 +00:00
|
|
|
|
2019-01-12 03:33:27 +00:00
|
|
|
let upEvents;
|
|
|
|
let downEvents;
|
2018-04-04 01:44:19 +00:00
|
|
|
if (useTouch) {
|
|
|
|
upEvents = {
|
2019-01-12 03:33:27 +00:00
|
|
|
touchstart: editable && !upDisabledClass ? this.up : noop,
|
2018-04-04 04:04:49 +00:00
|
|
|
touchend: this.stop,
|
2019-01-12 03:33:27 +00:00
|
|
|
};
|
2018-04-04 01:44:19 +00:00
|
|
|
downEvents = {
|
2019-01-12 03:33:27 +00:00
|
|
|
touchstart: editable && !downDisabledClass ? this.down : noop,
|
2018-04-04 04:04:49 +00:00
|
|
|
touchend: this.stop,
|
2019-01-12 03:33:27 +00:00
|
|
|
};
|
2018-04-04 01:44:19 +00:00
|
|
|
} else {
|
|
|
|
upEvents = {
|
2019-01-12 03:33:27 +00:00
|
|
|
mousedown: editable && !upDisabledClass ? this.up : noop,
|
2018-04-04 04:04:49 +00:00
|
|
|
mouseup: this.stop,
|
|
|
|
mouseleave: this.stop,
|
2019-01-12 03:33:27 +00:00
|
|
|
};
|
2018-04-04 01:44:19 +00:00
|
|
|
downEvents = {
|
2019-01-12 03:33:27 +00:00
|
|
|
mousedown: editable && !downDisabledClass ? this.down : noop,
|
2018-04-04 04:04:49 +00:00
|
|
|
mouseup: this.stop,
|
|
|
|
mouseleave: this.stop,
|
2019-01-12 03:33:27 +00:00
|
|
|
};
|
2018-04-04 04:04:49 +00:00
|
|
|
}
|
2019-01-12 03:33:27 +00:00
|
|
|
const isUpDisabled = !!upDisabledClass || disabled || readOnly;
|
|
|
|
const isDownDisabled = !!downDisabledClass || disabled || readOnly;
|
|
|
|
const {
|
|
|
|
mouseenter = noop,
|
|
|
|
mouseleave = noop,
|
|
|
|
mouseover = noop,
|
|
|
|
mouseout = noop,
|
2020-01-19 08:58:38 +00:00
|
|
|
} = getListeners(this);
|
2018-04-04 04:04:49 +00:00
|
|
|
const contentProps = {
|
2018-05-07 10:40:25 +00:00
|
|
|
on: { mouseenter, mouseleave, mouseover, mouseout },
|
2018-04-04 04:04:49 +00:00
|
|
|
class: classes,
|
2019-01-01 13:19:50 +00:00
|
|
|
attrs: { title: this.$props.title },
|
2019-01-12 03:33:27 +00:00
|
|
|
};
|
2018-04-04 04:04:49 +00:00
|
|
|
const upHandlerProps = {
|
|
|
|
props: {
|
|
|
|
disabled: isUpDisabled,
|
|
|
|
prefixCls,
|
|
|
|
},
|
|
|
|
attrs: {
|
|
|
|
unselectable: 'unselectable',
|
|
|
|
role: 'button',
|
|
|
|
'aria-label': 'Increase Value',
|
|
|
|
'aria-disabled': !!isUpDisabled,
|
|
|
|
},
|
|
|
|
class: `${prefixCls}-handler ${prefixCls}-handler-up ${upDisabledClass}`,
|
|
|
|
on: upEvents,
|
|
|
|
ref: 'up',
|
2019-01-12 03:33:27 +00:00
|
|
|
};
|
2018-04-04 04:04:49 +00:00
|
|
|
const downHandlerProps = {
|
|
|
|
props: {
|
|
|
|
disabled: isDownDisabled,
|
|
|
|
prefixCls,
|
|
|
|
},
|
|
|
|
attrs: {
|
|
|
|
unselectable: 'unselectable',
|
|
|
|
role: 'button',
|
|
|
|
'aria-label': 'Decrease Value',
|
|
|
|
'aria-disabled': !!isDownDisabled,
|
|
|
|
},
|
|
|
|
class: `${prefixCls}-handler ${prefixCls}-handler-down ${downDisabledClass}`,
|
|
|
|
on: downEvents,
|
|
|
|
ref: 'down',
|
2019-01-12 03:33:27 +00:00
|
|
|
};
|
2018-04-04 01:44:19 +00:00
|
|
|
// ref for test
|
|
|
|
return (
|
2019-01-12 03:33:27 +00:00
|
|
|
<div {...contentProps}>
|
2018-04-04 04:04:49 +00:00
|
|
|
<div class={`${prefixCls}-handler-wrap`}>
|
2019-01-12 03:33:27 +00:00
|
|
|
<InputHandler {...upHandlerProps}>
|
|
|
|
{upHandler || (
|
|
|
|
<span
|
|
|
|
unselectable="unselectable"
|
|
|
|
class={`${prefixCls}-handler-up-inner`}
|
|
|
|
onClick={preventDefault}
|
|
|
|
/>
|
|
|
|
)}
|
2018-04-04 01:44:19 +00:00
|
|
|
</InputHandler>
|
2019-01-12 03:33:27 +00:00
|
|
|
<InputHandler {...downHandlerProps}>
|
|
|
|
{downHandler || (
|
|
|
|
<span
|
|
|
|
unselectable="unselectable"
|
|
|
|
class={`${prefixCls}-handler-down-inner`}
|
|
|
|
onClick={preventDefault}
|
|
|
|
/>
|
|
|
|
)}
|
2018-04-04 01:44:19 +00:00
|
|
|
</InputHandler>
|
|
|
|
</div>
|
2020-03-07 11:45:13 +00:00
|
|
|
<div class={`${prefixCls}-input-wrap`}>
|
2018-04-04 01:44:19 +00:00
|
|
|
<input
|
2020-03-07 11:45:13 +00:00
|
|
|
role="spinbutton"
|
|
|
|
aria-valuemin={this.min}
|
|
|
|
aria-valuemax={this.max}
|
|
|
|
aria-valuenow={sValue}
|
2018-04-04 04:04:49 +00:00
|
|
|
required={this.required}
|
|
|
|
type={this.type}
|
|
|
|
placeholder={this.placeholder}
|
|
|
|
onClick={this.handleInputClick}
|
|
|
|
class={`${prefixCls}-input`}
|
|
|
|
tabIndex={this.tabIndex}
|
2019-01-01 13:19:50 +00:00
|
|
|
autoComplete={autoComplete}
|
2018-04-04 01:44:19 +00:00
|
|
|
onFocus={this.onFocus}
|
|
|
|
onBlur={this.onBlur}
|
2018-04-04 04:04:49 +00:00
|
|
|
onKeydown={editable ? this.onKeyDown : noop}
|
|
|
|
onKeyup={editable ? this.onKeyUp : noop}
|
|
|
|
maxLength={this.maxLength}
|
|
|
|
readOnly={this.readOnly}
|
|
|
|
disabled={this.disabled}
|
|
|
|
max={this.max}
|
|
|
|
min={this.min}
|
|
|
|
step={this.step}
|
|
|
|
name={this.name}
|
2020-03-07 11:45:13 +00:00
|
|
|
title={this.title}
|
2018-04-04 04:04:49 +00:00
|
|
|
id={this.id}
|
2018-05-07 10:40:25 +00:00
|
|
|
onInput={this.onChange}
|
2019-01-12 03:33:27 +00:00
|
|
|
ref="inputRef"
|
2020-03-07 11:45:13 +00:00
|
|
|
value={inputDisplayValue}
|
2018-04-04 04:04:49 +00:00
|
|
|
pattern={this.pattern}
|
2018-04-04 01:44:19 +00:00
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</div>
|
2019-01-12 03:33:27 +00:00
|
|
|
);
|
2018-04-04 04:04:49 +00:00
|
|
|
},
|
2019-01-12 03:33:27 +00:00
|
|
|
};
|