add vc-input-number

pull/9/head
wangxueliang 2018-04-04 12:04:49 +08:00
parent 94e76c2226
commit 460fa4b642
10 changed files with 792 additions and 559 deletions

View File

@ -0,0 +1,56 @@
import InputNumber from '../src/index'
import '../assets/index.less'
export default {
data () {
return {
disabled: false,
readOnly: false,
value: 50000,
}
},
methods: {
onChange (value) {
console.log('onChange:', value)
this.value = value
},
toggleDisabled () {
this.disabled = !this.disabled
},
toggleReadOnly () {
this.readOnly = !this.readOnly
},
numberWithCommas (x) {
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')
},
format (num) {
return `$ ${this.numberWithCommas(num)} boeing737`
},
parser (num) {
return num.toString().split(' ')[1].replace(/,*/g, '')
},
},
render () {
return (
<div style='margin: 10px;'>
<InputNumber
min={-8000}
max={10000000}
value={this.value}
onChange={this.onChange}
style='width: 200px'
readOnly={this.readOnly}
disabled={this.disabled}
autoFocus={false}
step={100}
formatter={this.format}
parser={this.parser}
/>
<p style='padding:10px 0'>
<button onClick={this.toggleDisabled}>toggle Disabled</button>
<button onClick={this.toggleReadOnly}>toggle readOnly</button>
</p>
</div>
)
},
}

View File

@ -0,0 +1,43 @@
import InputNumber from '../src/index'
import '../assets/index.less'
export default {
data () {
return {
disabled: false,
readOnly: false,
value: 5,
}
},
methods: {
onChange (value) {
console.log('onChange:', value)
this.value = value
},
toggleDisabled () {
this.disabled = !this.disabled
},
toggleReadOnly () {
this.readOnly = !this.readOnly
},
},
render () {
const upHandler = (<div style={{ color: 'blue' }}>x</div>)
const downHandler = (<div style={{ color: 'red' }}>V</div>)
return (
<div style='margin: 10px;'>
<InputNumber
min={-8}
max={10}
value={this.value}
onChange={this.onChange}
style='width: 100px'
readOnly={this.readOnly}
disabled={this.disabled}
upHandler={upHandler}
downHandler={downHandler}
/>
</div>
)
},
}

View File

@ -0,0 +1,38 @@
import InputNumber from '../src/index'
import '../assets/index.less'
export default {
data () {
return {
precision: 2,
}
},
methods: {
onChange (value) {
console.log('onChange:', value)
this.value = value
},
changeprecision (e) {
this.precision = parseInt(e.target.value, 10)
},
},
render () {
return (
<div style='margin: 10px;'>
<InputNumber
defaultValue={1}
onChange={this.onChange}
precision={this.precision}
/>
<p style='padding:10px 0'>
precision:
<input
type='number'
onInput={this.changeprecision}
value={this.precision}
/>
</p>
</div>
)
},
}

View File

@ -0,0 +1,44 @@
import InputNumber from '../src/index'
import '../assets/index.less'
export default {
data () {
return {
disabled: false,
readOnly: false,
value: 5,
}
},
methods: {
onChange (value) {
console.log('onChange:', value)
this.value = value
},
toggleDisabled () {
this.disabled = !this.disabled
},
toggleReadOnly () {
this.readOnly = !this.readOnly
},
},
render () {
return (
<div style='margin: 10px;'>
<InputNumber
min={-8}
max={10}
value={this.value}
style='width: 100px'
onChange={this.onChange}
readOnly={this.readOnly}
disabled={this.disabled}
useTouch
/>
<p style='padding:10px 0'>
<button onClick={this.toggleDisabled}>toggle Disabled</button>
<button onClick={this.toggleReadOnly}>toggle readOnly</button>
</p>
</div>
)
},
}

View File

@ -0,0 +1,43 @@
import InputNumber from '../src/index'
import '../assets/index.less'
export default {
data () {
return {
disabled: false,
readOnly: false,
value: 5,
}
},
methods: {
onChange (value) {
console.log('onChange:', value)
this.value = value
},
toggleDisabled () {
this.disabled = !this.disabled
},
toggleReadOnly () {
this.readOnly = !this.readOnly
},
},
render () {
return (
<div style='margin: 10px;'>
<InputNumber
min={-8}
max={10}
value={this.value}
onChange={this.onChange}
style='width: 100px'
readOnly={this.readOnly}
disabled={this.disabled}
/>
<p style='padding:10px 0'>
<button onClick={this.toggleDisabled}>toggle Disabled</button>
<button onClick={this.toggleReadOnly}>toggle readOnly</button>
</p>
</div>
)
},
}

View File

@ -0,0 +1,36 @@
import InputNumber from '../src/index'
import '../assets/index.less'
export default {
data () {
return {
value: 0.000000001,
}
},
methods: {
onChange (value) {
console.log('onChange:', value)
this.value = value
},
toggleDisabled () {
this.disabled = !this.disabled
},
toggleReadOnly () {
this.readOnly = !this.readOnly
},
},
render () {
return (
<div style='margin: 10px;'>
<InputNumber
min={-10}
max={10}
step={0.000000001}
style='width: 100px'
value={this.value}
onChange={this.onChange}
/>
</div>
)
},
}

View File

@ -1,37 +1,33 @@
import React, { Component } from 'react'; import PropTypes from '../../_util/vue-types'
import PropTypes from 'prop-types'; import Touchable from '../../vc-m-feedback'
import Touchable from 'rmc-feedback';
class InputHandler extends Component { const InputHandler = {
render() { props: {
const {
prefixCls, disabled, onTouchStart, onTouchEnd,
onMouseDown, onMouseUp, onMouseLeave, ...otherProps,
} = this.props;
return (
<Touchable
disabled={disabled}
onTouchStart={onTouchStart}
onTouchEnd={onTouchEnd}
onMouseDown={onMouseDown}
onMouseUp={onMouseUp}
onMouseLeave={onMouseLeave}
activeClassName={`${prefixCls}-handler-active`}
>
<span {...otherProps} />
</Touchable>
);
}
}
InputHandler.propTypes = {
prefixCls: PropTypes.string, prefixCls: PropTypes.string,
disabled: PropTypes.bool, disabled: PropTypes.bool,
onTouchStart: PropTypes.func, },
onTouchEnd: PropTypes.func, render () {
onMouseDown: PropTypes.func, const { prefixCls, disabled } = this.$props
onMouseUp: PropTypes.func, const touchableProps = {
onMouseLeave: PropTypes.func, props: {
}; disabled,
activeClassName: `${prefixCls}-handler-active`,
},
on: this.$listeners,
}
const spanProps = {
attrs: this.$attrs,
}
return (
<Touchable
{...touchableProps}
>
<span {...spanProps}>
{this.$slots.default}
</span>
</Touchable>
)
},
}
export default InputHandler; export default InputHandler

View File

@ -1,38 +1,37 @@
import React from 'react'; import PropTypes from '../../_util/vue-types'
import PropTypes from 'prop-types'; import BaseMixin from '../../_util/BaseMixin'
import classNames from 'classnames'; import { initDefaultProps, hasProp } from '../../_util/props-util'
import isNegativeZero from 'is-negative-zero'; import classNames from 'classnames'
import InputHandler from './InputHandler'; import isNegativeZero from 'is-negative-zero'
import InputHandler from './InputHandler'
function noop() { function noop () {
} }
function preventDefault(e) { function preventDefault (e) {
e.preventDefault(); e.preventDefault()
} }
function defaultParser(input) { function defaultParser (input) {
return input.replace(/[^\w\.-]+/g, ''); return input.replace(/[^\w\.-]+/g, '')
} }
/** /**
* When click and hold on a button - the speed of auto changin the value. * When click and hold on a button - the speed of auto changin the value.
*/ */
const SPEED = 200; const SPEED = 200
/** /**
* When click and hold on a button - the delay before auto changin the value. * When click and hold on a button - the delay before auto changin the value.
*/ */
const DELAY = 600; const DELAY = 600
/** /**
* Max Safe Integer -- on IE this is not available, so manually set the number in that case. * 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 * The reason this is used, instead of Infinity is because numbers above the MSI are unstable
*/ */
const MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || Math.pow(2, 53) - 1; const MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || Math.pow(2, 53) - 1
const inputNumberProps = {
export default class InputNumber extends React.Component {
static propTypes = {
value: PropTypes.oneOfType([ value: PropTypes.oneOfType([
PropTypes.number, PropTypes.number,
PropTypes.string, PropTypes.string,
@ -43,14 +42,14 @@ export default class InputNumber extends React.Component {
]), ]),
focusOnUpDown: PropTypes.bool, focusOnUpDown: PropTypes.bool,
autoFocus: PropTypes.bool, autoFocus: PropTypes.bool,
onChange: PropTypes.func, // onChange: PropTypes.func,
onKeyDown: PropTypes.func, // onKeyDown: PropTypes.func,
onKeyUp: PropTypes.func, // onKeyUp: PropTypes.func,
prefixCls: PropTypes.string, prefixCls: PropTypes.string,
tabIndex: PropTypes.string, tabIndex: PropTypes.string,
disabled: PropTypes.bool, disabled: PropTypes.bool,
onFocus: PropTypes.func, // onFocus: PropTypes.func,
onBlur: PropTypes.func, // onBlur: PropTypes.func,
readOnly: PropTypes.bool, readOnly: PropTypes.bool,
max: PropTypes.number, max: PropTypes.number,
min: PropTypes.number, min: PropTypes.number,
@ -58,553 +57,534 @@ export default class InputNumber extends React.Component {
PropTypes.number, PropTypes.number,
PropTypes.string, PropTypes.string,
]), ]),
upHandler: PropTypes.node, upHandler: PropTypes.any,
downHandler: PropTypes.node, downHandler: PropTypes.any,
useTouch: PropTypes.bool, useTouch: PropTypes.bool,
formatter: PropTypes.func, formatter: PropTypes.func,
parser: PropTypes.func, parser: PropTypes.func,
onMouseEnter: PropTypes.func, // onMouseEnter: PropTypes.func,
onMouseLeave: PropTypes.func, // onMouseLeave: PropTypes.func,
onMouseOver: PropTypes.func, // onMouseOver: PropTypes.func,
onMouseOut: PropTypes.func, // onMouseOut: PropTypes.func,
precision: PropTypes.number, precision: PropTypes.number,
required: PropTypes.bool, required: PropTypes.bool,
pattern: PropTypes.string, pattern: PropTypes.string,
} }
static defaultProps = { export default {
name: 'InputNumber',
mixins: [BaseMixin],
model: {
prop: 'value',
event: 'change',
},
props: initDefaultProps(inputNumberProps, {
focusOnUpDown: true, focusOnUpDown: true,
useTouch: false, useTouch: false,
prefixCls: 'rc-input-number', prefixCls: 'rc-input-number',
min: -MAX_SAFE_INTEGER, min: -MAX_SAFE_INTEGER,
step: 1, step: 1,
style: {},
onChange: noop,
onKeyDown: noop,
onFocus: noop,
onBlur: noop,
parser: defaultParser, parser: defaultParser,
required: false, required: false,
} }),
data () {
constructor(props) { let value
super(props); if (hasProp(this, 'value')) {
value = this.value
let value;
if ('value' in props) {
value = props.value;
} else { } else {
value = props.defaultValue; value = this.defaultValue
} }
value = this.toNumber(value); value = this.toNumber(value)
this.state = { return {
inputValue: this.toPrecisionAsStep(value), inputValue: this.toPrecisionAsStep(value),
value, sValue: value,
focused: props.autoFocus, focused: this.autoFocus,
};
} }
},
componentDidMount() { mounted () {
this.componentDidUpdate(); this.$nextTick(() => {
} this.updatedFunc()
})
componentWillReceiveProps(nextProps) { },
if ('value' in nextProps) { beforeUpdate () {
const value = this.state.focused this.$nextTick(() => {
? nextProps.value : this.getValidValue(nextProps.value, nextProps.min, nextProps.max);
this.setState({
value,
inputValue: this.inputting ? value : this.toPrecisionAsStep(value),
});
}
}
componentWillUpdate() {
try { try {
this.start = this.input.selectionStart; this.start = this.$refs.inputRef.selectionStart
this.end = this.input.selectionEnd; this.end = this.$refs.inputRef.selectionEnd
} catch (e) { } catch (e) {
// Fix error in Chrome: // Fix error in Chrome:
// Failed to read the 'selectionStart' property from 'HTMLInputElement' // Failed to read the 'selectionStart' property from 'HTMLInputElement'
// http://stackoverflow.com/q/21177489/3040605 // http://stackoverflow.com/q/21177489/3040605
} }
} })
},
componentDidUpdate() { updated () {
// pressingUpOrDown is true means that someone just click up or down button this.$nextTick(() => {
// https://github.com/ant-design/ant-design/issues/9204 this.updatedFunc()
})
},
beforeDestroy () {
this.stop()
},
watch: {
value (val) {
const value = this.focused
? val : this.getValidValue(val, this.min, this.max)
this.setState({
sValue: val,
inputValue: this.inputting ? value : this.toPrecisionAsStep(value),
})
},
},
methods: {
updatedFunc () {
if (!this.pressingUpOrDown) { if (!this.pressingUpOrDown) {
return; return
} }
if (this.props.focusOnUpDown && this.state.focused) { if (this.focusOnUpDown && this.focused) {
const selectionRange = this.input.setSelectionRange; const selectionRange = this.$refs.inputRef.setSelectionRange
if (selectionRange && if (selectionRange &&
typeof selectionRange === 'function' && typeof selectionRange === 'function' &&
this.start !== undefined && this.start !== undefined &&
this.end !== undefined) { this.end !== undefined) {
this.input.setSelectionRange(this.start, this.end); this.$refs.inputRef.setSelectionRange(this.start, this.end)
} else { } else {
this.focus(); this.focus()
} }
this.pressingUpOrDown = false; this.pressingUpOrDown = false
} }
} },
onKeyDown (e, ...args) {
componentWillUnmount() {
this.stop();
}
onKeyDown = (e, ...args) => {
if (e.keyCode === 38) { if (e.keyCode === 38) {
const ratio = this.getRatio(e); const ratio = this.getRatio(e)
this.up(e, ratio); this.up(e, ratio)
this.stop(); this.stop()
} else if (e.keyCode === 40) { } else if (e.keyCode === 40) {
const ratio = this.getRatio(e); const ratio = this.getRatio(e)
this.down(e, ratio); this.down(e, ratio)
this.stop(); this.stop()
} }
const { onKeyDown } = this.props; this.$emit('keydown', e, ...args)
if (onKeyDown) { },
onKeyDown(e, ...args); onKeyUp (e, ...args) {
this.stop()
this.$emit('keyup', e, ...args)
},
onChange (e) {
if (this.focused) {
this.inputting = true
} }
} const input = this.parser(this.getValueFromEvent(e))
this.setState({ inputValue: input })
onKeyUp = (e, ...args) => { this.$emit('change', this.toNumberWhenUserInput(input)) // valid number or invalid string
this.stop(); },
const { onKeyUp } = this.props; onFocus (...args) {
if (onKeyUp) {
onKeyUp(e, ...args);
}
}
onChange = (e) => {
if (this.state.focused) {
this.inputting = true;
}
const input = this.props.parser(this.getValueFromEvent(e));
this.setState({ inputValue: input });
this.props.onChange(this.toNumberWhenUserInput(input)); // valid number or invalid string
}
onFocus = (...args) => {
this.setState({ this.setState({
focused: true, focused: true,
}); })
this.props.onFocus(...args); this.$emit('focus', ...args)
} },
onBlur (e, ...args) {
onBlur = (e, ...args) => { this.inputting = false
this.inputting = false;
this.setState({ this.setState({
focused: false, focused: false,
}); })
const value = this.getCurrentValidValue(this.state.inputValue); const value = this.getCurrentValidValue(this.inputValue)
e.persist(); // fix https://github.com/react-component/input-number/issues/51 // todo
// e.persist() // fix https://github.com/react-component/input-number/issues/51
this.setValue(value, () => { this.setValue(value, () => {
this.props.onBlur(e, ...args); this.$emit('blur', e, ...args)
}); })
} },
getCurrentValidValue (value) {
getCurrentValidValue(value) { let val = value
let val = value;
if (val === '') { if (val === '') {
val = ''; val = ''
} else if (!this.isNotCompleteNumber(val)) { } else if (!this.isNotCompleteNumber(val)) {
val = this.getValidValue(val); val = this.getValidValue(val)
} else { } else {
val = this.state.value; val = this.sValue
} }
return this.toNumber(val); return this.toNumber(val)
} },
getRatio (e) {
getRatio(e) { let ratio = 1
let ratio = 1;
if (e.metaKey || e.ctrlKey) { if (e.metaKey || e.ctrlKey) {
ratio = 0.1; ratio = 0.1
} else if (e.shiftKey) { } else if (e.shiftKey) {
ratio = 10; ratio = 10
} }
return ratio; return ratio
} },
getValueFromEvent (e) {
getValueFromEvent(e) {
// optimize for chinese input expierence // optimize for chinese input expierence
// https://github.com/ant-design/ant-design/issues/8196 // https://github.com/ant-design/ant-design/issues/8196
return e.target.value.trim().replace(/。/g, '.'); return e.target.value.trim().replace(/。/g, '.')
} },
getValidValue (value, min = this.min, max = this.max) {
getValidValue(value, min = this.props.min, max = this.props.max) { let val = parseFloat(value, 10)
let val = parseFloat(value, 10);
// https://github.com/ant-design/ant-design/issues/7358 // https://github.com/ant-design/ant-design/issues/7358
if (isNaN(val)) { if (isNaN(val)) {
return value; return value
} }
if (val < min) { if (val < min) {
val = min; val = min
} }
if (val > max) { if (val > max) {
val = max; val = max
} }
return val; return val
} },
setValue (v, callback) {
setValue(v, callback) {
// trigger onChange // trigger onChange
const newValue = this.isNotCompleteNumber(parseFloat(v, 10)) ? undefined : parseFloat(v, 10); const newValue = this.isNotCompleteNumber(parseFloat(v, 10)) ? undefined : parseFloat(v, 10)
const changed = newValue !== this.state.value || const changed = newValue !== this.sValue ||
`${newValue}` !== `${this.state.inputValue}`; // https://github.com/ant-design/ant-design/issues/7363 `${newValue}` !== `${this.inputValue}` // https://github.com/ant-design/ant-design/issues/7363
if (!('value' in this.props)) { if (!hasProp(this, 'value')) {
this.setState({ this.setState({
value: newValue, sValue: newValue,
inputValue: this.toPrecisionAsStep(v), inputValue: this.toPrecisionAsStep(v),
}, callback); }, callback)
} else { } else {
// always set input value same as value // always set input value same as value
this.setState({ this.setState({
inputValue: this.toPrecisionAsStep(this.state.value), inputValue: this.toPrecisionAsStep(this.sValue),
}, callback); }, callback)
} }
if (changed) { if (changed) {
this.props.onChange(newValue); this.$emit('change', newValue)
} }
},
getPrecision (value) {
if (hasProp(this, 'precision')) {
return this.precision
} }
const valueString = value.toString()
getPrecision(value) {
if ('precision' in this.props) {
return this.props.precision;
}
const valueString = value.toString();
if (valueString.indexOf('e-') >= 0) { if (valueString.indexOf('e-') >= 0) {
return parseInt(valueString.slice(valueString.indexOf('e-') + 2), 10); return parseInt(valueString.slice(valueString.indexOf('e-') + 2), 10)
} }
let precision = 0; let precision = 0
if (valueString.indexOf('.') >= 0) { if (valueString.indexOf('.') >= 0) {
precision = valueString.length - valueString.indexOf('.') - 1; precision = valueString.length - valueString.indexOf('.') - 1
} }
return precision; return precision
} },
// step={1.0} value={1.51} // step={1.0} value={1.51}
// press + // press +
// then value should be 2.51, rather than 2.5 // then value should be 2.51, rather than 2.5
// if this.props.precision is undefined // if this.props.precision is undefined
// https://github.com/react-component/input-number/issues/39 // https://github.com/react-component/input-number/issues/39
getMaxPrecision(currentValue, ratio = 1) { getMaxPrecision (currentValue, ratio = 1) {
if ('precision' in this.props) { if (hasProp(this, 'precision')) {
return this.props.precision; return this.precision
} }
const { step } = this.props; const { step } = this
const ratioPrecision = this.getPrecision(ratio); const ratioPrecision = this.getPrecision(ratio)
const stepPrecision = this.getPrecision(step); const stepPrecision = this.getPrecision(step)
const currentValuePrecision = this.getPrecision(currentValue); const currentValuePrecision = this.getPrecision(currentValue)
if (!currentValue) { if (!currentValue) {
return ratioPrecision + stepPrecision; return ratioPrecision + stepPrecision
} }
return Math.max(currentValuePrecision, ratioPrecision + stepPrecision); return Math.max(currentValuePrecision, ratioPrecision + stepPrecision)
} },
getPrecisionFactor (currentValue, ratio = 1) {
getPrecisionFactor(currentValue, ratio = 1) { const precision = this.getMaxPrecision(currentValue, ratio)
const precision = this.getMaxPrecision(currentValue, ratio); return Math.pow(10, precision)
return Math.pow(10, precision); },
} focus () {
this.$refs.inputRef.focus()
focus() { },
this.input.focus(); blur () {
} this.$refs.inputRef.blur()
},
blur() { formatWrapper (num) {
this.input.blur();
}
formatWrapper(num) {
// http://2ality.com/2012/03/signedzero.html // http://2ality.com/2012/03/signedzero.html
// https://github.com/ant-design/ant-design/issues/9439 // https://github.com/ant-design/ant-design/issues/9439
if (isNegativeZero(num)) { if (isNegativeZero(num)) {
return '-0'; return '-0'
} }
if (this.props.formatter) { if (this.formatter) {
return this.props.formatter(num); return this.formatter(num)
} }
return num; return num
} },
toPrecisionAsStep (num) {
toPrecisionAsStep(num) {
if (this.isNotCompleteNumber(num) || num === '') { if (this.isNotCompleteNumber(num) || num === '') {
return num; return num
} }
const precision = Math.abs(this.getMaxPrecision(num)); const precision = Math.abs(this.getMaxPrecision(num))
if (precision === 0) { if (precision === 0) {
return num.toString(); return num.toString()
} }
if (!isNaN(precision)) { if (!isNaN(precision)) {
return Number(num).toFixed(precision); return Number(num).toFixed(precision)
} }
return num.toString(); return num.toString()
} },
// '1.' '1x' 'xx' '' => are not complete numbers // '1.' '1x' 'xx' '' => are not complete numbers
isNotCompleteNumber(num) { isNotCompleteNumber (num) {
return ( return (
isNaN(num) || isNaN(num) ||
num === '' || num === '' ||
num === null || num === null ||
(num && num.toString().indexOf('.') === num.toString().length - 1) (num && num.toString().indexOf('.') === num.toString().length - 1)
); )
} },
toNumber (num) {
toNumber(num) {
if (this.isNotCompleteNumber(num)) { if (this.isNotCompleteNumber(num)) {
return num; return num
} }
if ('precision' in this.props) { if (hasProp(this, 'precision')) {
return Number(Number(num).toFixed(this.props.precision)); return Number(Number(num).toFixed(this.precision))
} }
return Number(num); return Number(num)
} },
// '1.0' '1.00' => may be a inputing number // '1.0' '1.00' => may be a inputing number
toNumberWhenUserInput(num) { toNumberWhenUserInput (num) {
// num.length > 16 => prevent input large number will became Infinity // num.length > 16 => prevent input large number will became Infinity
if ((/\.\d*0$/.test(num) || num.length > 16) && this.state.focused) { if ((/\.\d*0$/.test(num) || num.length > 16) && this.focused) {
return num; return num
} }
return this.toNumber(num); return this.toNumber(num)
} },
upStep (val, rat) {
upStep(val, rat) { const { step, min } = this
const { step, min } = this.props; const precisionFactor = this.getPrecisionFactor(val, rat)
const precisionFactor = this.getPrecisionFactor(val, rat); const precision = Math.abs(this.getMaxPrecision(val, rat))
const precision = Math.abs(this.getMaxPrecision(val, rat)); let result
let result;
if (typeof val === 'number') { if (typeof val === 'number') {
result = result =
((precisionFactor * val + precisionFactor * step * rat) / ((precisionFactor * val + precisionFactor * step * rat) /
precisionFactor).toFixed(precision); precisionFactor).toFixed(precision)
} else { } else {
result = min === -Infinity ? step : min; result = min === -Infinity ? step : min
} }
return this.toNumber(result); return this.toNumber(result)
} },
downStep (val, rat) {
downStep(val, rat) { const { step, min } = this
const { step, min } = this.props; const precisionFactor = this.getPrecisionFactor(val, rat)
const precisionFactor = this.getPrecisionFactor(val, rat); const precision = Math.abs(this.getMaxPrecision(val, rat))
const precision = Math.abs(this.getMaxPrecision(val, rat)); let result
let result;
if (typeof val === 'number') { if (typeof val === 'number') {
result = result =
((precisionFactor * val - precisionFactor * step * rat) / ((precisionFactor * val - precisionFactor * step * rat) /
precisionFactor).toFixed(precision); precisionFactor).toFixed(precision)
} else { } else {
result = min === -Infinity ? -step : min; result = min === -Infinity ? -step : min
} }
return this.toNumber(result); return this.toNumber(result)
} },
stepFn (type, e, ratio = 1, recursive) {
step(type, e, ratio = 1, recursive) { this.stop()
this.stop();
if (e) { if (e) {
e.persist(); // e.persist()
e.preventDefault(); e.preventDefault()
} }
const props = this.props; if (this.disabled) {
if (props.disabled) { return
return;
} }
const value = this.getCurrentValidValue(this.state.inputValue) || 0; const { max, min } = this
const value = this.getCurrentValidValue(this.inputValue) || 0
if (this.isNotCompleteNumber(value)) { if (this.isNotCompleteNumber(value)) {
return; return
} }
let val = this[`${type}Step`](value, ratio); let val = this[`${type}Step`](value, ratio)
const outOfRange = val > props.max || val < props.min; const outOfRange = val > max || val < min
if (val > props.max) { if (val > max) {
val = props.max; val = max
} else if (val < props.min) { } else if (val < min) {
val = props.min; val = min
} }
this.setValue(val); this.setValue(val)
this.setState({ this.setState({
focused: true, focused: true,
}); })
if (outOfRange) { if (outOfRange) {
return; return
} }
this.autoStepTimer = setTimeout(() => { this.autoStepTimer = setTimeout(() => {
this[type](e, ratio, true); this[type](e, ratio, true)
}, recursive ? SPEED : DELAY); }, recursive ? SPEED : DELAY)
} },
stop () {
stop = () => {
if (this.autoStepTimer) { if (this.autoStepTimer) {
clearTimeout(this.autoStepTimer); clearTimeout(this.autoStepTimer)
} }
} },
down (e, ratio, recursive) {
down = (e, ratio, recursive) => { this.pressingUpOrDown = true
this.pressingUpOrDown = true; this.stepFn('down', e, ratio, recursive)
this.step('down', e, ratio, recursive); },
} up (e, ratio, recursive) {
this.pressingUpOrDown = true
up = (e, ratio, recursive) => { this.stepFn('up', e, ratio, recursive)
this.pressingUpOrDown = true; },
this.step('up', e, ratio, recursive); handleInputClick () {
} this.$emit('click')
},
saveInput = (node) => { },
this.input = node; render () {
} const { prefixCls, disabled, readOnly, useTouch } = this.$props
render() {
const props = { ...this.props };
const { prefixCls, disabled, readOnly, useTouch } = props;
const classes = classNames({ const classes = classNames({
[prefixCls]: true, [prefixCls]: true,
[props.className]: !!props.className,
[`${prefixCls}-disabled`]: disabled, [`${prefixCls}-disabled`]: disabled,
[`${prefixCls}-focused`]: this.state.focused, [`${prefixCls}-focused`]: this.focused,
}); })
let upDisabledClass = ''; let upDisabledClass = ''
let downDisabledClass = ''; let downDisabledClass = ''
const { value } = this.state; const { sValue } = this
if (value || value === 0) { if (sValue || sValue === 0) {
if (!isNaN(value)) { if (!isNaN(sValue)) {
const val = Number(value); const val = Number(sValue)
if (val >= props.max) { if (val >= this.max) {
upDisabledClass = `${prefixCls}-handler-up-disabled`; upDisabledClass = `${prefixCls}-handler-up-disabled`
} }
if (val <= props.min) { if (val <= this.min) {
downDisabledClass = `${prefixCls}-handler-down-disabled`; downDisabledClass = `${prefixCls}-handler-down-disabled`
} }
} else { } else {
upDisabledClass = `${prefixCls}-handler-up-disabled`; upDisabledClass = `${prefixCls}-handler-up-disabled`
downDisabledClass = `${prefixCls}-handler-down-disabled`; downDisabledClass = `${prefixCls}-handler-down-disabled`
} }
} }
const editable = !props.readOnly && !props.disabled; const editable = !this.readOnly && !this.disabled
// focus state, show input value // focus state, show input value
// unfocus state, show valid value // unfocus state, show valid value
let inputDisplayValue; let inputDisplayValue
if (this.state.focused) { if (this.focused) {
inputDisplayValue = this.state.inputValue; inputDisplayValue = this.inputValue
} else { } else {
inputDisplayValue = this.toPrecisionAsStep(this.state.value); inputDisplayValue = this.toPrecisionAsStep(this.sValue)
} }
if (inputDisplayValue === undefined || inputDisplayValue === null) { if (inputDisplayValue === undefined || inputDisplayValue === null) {
inputDisplayValue = ''; inputDisplayValue = ''
} }
let upEvents; let upEvents
let downEvents; let downEvents
if (useTouch) { if (useTouch) {
upEvents = { upEvents = {
onTouchStart: (editable && !upDisabledClass) ? this.up : noop, touchstart: (editable && !upDisabledClass) ? this.up : noop,
onTouchEnd: this.stop, touchend: this.stop,
}; }
downEvents = { downEvents = {
onTouchStart: (editable && !downDisabledClass) ? this.down : noop, touchstart: (editable && !downDisabledClass) ? this.down : noop,
onTouchEnd: this.stop, touchend: this.stop,
}; }
} else { } else {
upEvents = { upEvents = {
onMouseDown: (editable && !upDisabledClass) ? this.up : noop, mousedown: (editable && !upDisabledClass) ? this.up : noop,
onMouseUp: this.stop, mouseup: this.stop,
onMouseLeave: this.stop, mouseleave: this.stop,
}; }
downEvents = { downEvents = {
onMouseDown: (editable && !downDisabledClass) ? this.down : noop, mousedown: (editable && !downDisabledClass) ? this.down : noop,
onMouseUp: this.stop, mouseup: this.stop,
onMouseLeave: this.stop, mouseleave: this.stop,
}; }
}
const inputDisplayValueFormat = this.formatWrapper(inputDisplayValue)
const isUpDisabled = !!upDisabledClass || disabled || readOnly
const isDownDisabled = !!downDisabledClass || disabled || readOnly
const contentProps = {
on: this.$listeners,
class: classes,
}
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',
}
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',
} }
const inputDisplayValueFormat = this.formatWrapper(inputDisplayValue);
const isUpDisabled = !!upDisabledClass || disabled || readOnly;
const isDownDisabled = !!downDisabledClass || disabled || readOnly;
// ref for test // ref for test
return ( return (
<div <div
className={classes} {...contentProps}
style={props.style}
onMouseEnter={props.onMouseEnter}
onMouseLeave={props.onMouseLeave}
onMouseOver={props.onMouseOver}
onMouseOut={props.onMouseOut}
> >
<div className={`${prefixCls}-handler-wrap`}> <div class={`${prefixCls}-handler-wrap`}>
<InputHandler <InputHandler
ref="up" {...upHandlerProps}
disabled={isUpDisabled}
prefixCls={prefixCls}
unselectable="unselectable"
{...upEvents}
role="button"
aria-label="Increase Value"
aria-disabled={!!isUpDisabled}
className={`${prefixCls}-handler ${prefixCls}-handler-up ${upDisabledClass}`}
> >
{this.props.upHandler || <span {this.upHandler || <span
unselectable="unselectable" unselectable='unselectable'
className={`${prefixCls}-handler-up-inner`} class={`${prefixCls}-handler-up-inner`}
onClick={preventDefault} onClick={preventDefault}
/>} />}
</InputHandler> </InputHandler>
<InputHandler <InputHandler
ref="down" {...downHandlerProps}
disabled={isDownDisabled}
prefixCls={prefixCls}
unselectable="unselectable"
{...downEvents}
role="button"
aria-label="Decrease Value"
aria-disabled={!!isDownDisabled}
className={`${prefixCls}-handler ${prefixCls}-handler-down ${downDisabledClass}`}
> >
{this.props.downHandler || <span {this.downHandler || <span
unselectable="unselectable" unselectable='unselectable'
className={`${prefixCls}-handler-down-inner`} class={`${prefixCls}-handler-down-inner`}
onClick={preventDefault} onClick={preventDefault}
/>} />}
</InputHandler> </InputHandler>
</div> </div>
<div <div
className={`${prefixCls}-input-wrap`} class={`${prefixCls}-input-wrap`}
role="spinbutton" role='spinbutton'
aria-valuemin={props.min} aria-valuemin={this.min}
aria-valuemax={props.max} aria-valuemax={this.max}
aria-valuenow={value} aria-valuenow={sValue}
> >
<input <input
required={props.required} required={this.required}
type={props.type} type={this.type}
placeholder={props.placeholder} placeholder={this.placeholder}
onClick={props.onClick} onClick={this.handleInputClick}
className={`${prefixCls}-input`} class={`${prefixCls}-input`}
tabIndex={props.tabIndex} tabIndex={this.tabIndex}
autoComplete="off" autoComplete='off'
onFocus={this.onFocus} onFocus={this.onFocus}
onBlur={this.onBlur} onBlur={this.onBlur}
onKeyDown={editable ? this.onKeyDown : noop} onKeydown={editable ? this.onKeyDown : noop}
onKeyUp={editable ? this.onKeyUp : noop} onKeyup={editable ? this.onKeyUp : noop}
autoFocus={props.autoFocus} autoFocus={this.autoFocus}
maxLength={props.maxLength} maxLength={this.maxLength}
readOnly={props.readOnly} readOnly={this.readOnly}
disabled={props.disabled} disabled={this.disabled}
max={props.max} max={this.max}
min={props.min} min={this.min}
step={props.step} step={this.step}
name={props.name} name={this.name}
id={props.id} id={this.id}
onChange={this.onChange} onChange={this.onChange}
ref={this.saveInput} ref='inputRef'
value={inputDisplayValueFormat} value={inputDisplayValueFormat}
pattern={props.pattern} pattern={this.pattern}
/> />
</div> </div>
</div> </div>
); )
} },
} }

View File

@ -3,11 +3,7 @@ const AsyncComp = () => {
const hashs = window.location.hash.split('/') const hashs = window.location.hash.split('/')
const d = hashs[hashs.length - 1] const d = hashs[hashs.length - 1]
return { return {
<<<<<<< HEAD component: import(`../components/vc-input-number/demo/${d}`),
component: import(`../components/vc-m-feedback/demo/${d}`),
=======
component: import(`../components/table/demo/${d}`),
>>>>>>> 5d2271a131c74d672cc0cfada07e256752160b41
} }
} }
export default [ export default [

View File

@ -136,6 +136,7 @@
"dom-scroll-into-view": "^1.2.1", "dom-scroll-into-view": "^1.2.1",
"enquire.js": "^2.1.6", "enquire.js": "^2.1.6",
"eslint-plugin-vue": "^3.13.0", "eslint-plugin-vue": "^3.13.0",
"is-negative-zero": "^2.0.0",
"lodash": "^4.17.5", "lodash": "^4.17.5",
"moment": "^2.21.0", "moment": "^2.21.0",
"omit.js": "^1.0.0", "omit.js": "^1.0.0",