feat: update inputnumber
parent
a0c08a599a
commit
93bde3fb67
|
@ -1 +1 @@
|
|||
Subproject commit 6cde2f94ca4a1dbbb260a4436369e2084ff467ed
|
||||
Subproject commit d680625687a695a9b9a06a131e12f9611a480d5b
|
|
@ -1,11 +1,11 @@
|
|||
import { inject } from 'vue';
|
||||
import PropTypes from '../_util/vue-types';
|
||||
import { initDefaultProps, getOptionProps, getListeners } from '../_util/props-util';
|
||||
import { initDefaultProps, getOptionProps } from '../_util/props-util';
|
||||
import classNames from 'classnames';
|
||||
import UpOutlined from '@ant-design/icons-vue/UpOutlined';
|
||||
import DownOutlined from '@ant-design/icons-vue/DownOutlined';
|
||||
import VcInputNumber from '../vc-input-number/src';
|
||||
import { ConfigConsumerProps } from '../config-provider';
|
||||
import Base from '../base';
|
||||
|
||||
export const InputNumberProps = {
|
||||
prefixCls: PropTypes.string,
|
||||
|
@ -29,56 +29,59 @@ export const InputNumberProps = {
|
|||
|
||||
const InputNumber = {
|
||||
name: 'AInputNumber',
|
||||
model: {
|
||||
prop: 'value',
|
||||
event: 'change',
|
||||
},
|
||||
inheritAttrs: false,
|
||||
props: initDefaultProps(InputNumberProps, {
|
||||
step: 1,
|
||||
}),
|
||||
inject: {
|
||||
configProvider: { default: () => ConfigConsumerProps },
|
||||
setup() {
|
||||
return {
|
||||
configProvider: inject('configProvider', ConfigConsumerProps),
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
saveInputNumber(inputNumberRef) {
|
||||
this.inputNumberRef = inputNumberRef;
|
||||
},
|
||||
focus() {
|
||||
this.$refs.inputNumberRef.focus();
|
||||
this.inputNumberRef.focus();
|
||||
},
|
||||
blur() {
|
||||
this.$refs.inputNumberRef.blur();
|
||||
this.inputNumberRef.blur();
|
||||
},
|
||||
},
|
||||
|
||||
render() {
|
||||
const { prefixCls: customizePrefixCls, size, ...others } = getOptionProps(this);
|
||||
const { prefixCls: customizePrefixCls, size, class: className, ...others } = {
|
||||
...getOptionProps(this),
|
||||
...this.$attrs,
|
||||
};
|
||||
const getPrefixCls = this.configProvider.getPrefixCls;
|
||||
const prefixCls = getPrefixCls('input-number', customizePrefixCls);
|
||||
|
||||
const inputNumberClass = classNames({
|
||||
[`${prefixCls}-lg`]: size === 'large',
|
||||
[`${prefixCls}-sm`]: size === 'small',
|
||||
});
|
||||
const inputNumberClass = classNames(
|
||||
{
|
||||
[`${prefixCls}-lg`]: size === 'large',
|
||||
[`${prefixCls}-sm`]: size === 'small',
|
||||
},
|
||||
className,
|
||||
);
|
||||
const upIcon = <UpOutlined class={`${prefixCls}-handler-up-inner`} />;
|
||||
const downIcon = <DownOutlined class={`${prefixCls}-handler-down-inner`} />;
|
||||
|
||||
const vcInputNumberprops = {
|
||||
props: {
|
||||
prefixCls,
|
||||
upHandler: upIcon,
|
||||
downHandler: downIcon,
|
||||
...others,
|
||||
},
|
||||
prefixCls,
|
||||
upHandler: upIcon,
|
||||
downHandler: downIcon,
|
||||
...others,
|
||||
class: inputNumberClass,
|
||||
ref: 'inputNumberRef',
|
||||
on: getListeners(this),
|
||||
};
|
||||
return <VcInputNumber {...vcInputNumberprops} />;
|
||||
return <VcInputNumber {...vcInputNumberprops} ref={this.saveInputNumber} />;
|
||||
},
|
||||
};
|
||||
|
||||
/* istanbul ignore next */
|
||||
InputNumber.install = function(Vue) {
|
||||
Vue.use(Base);
|
||||
Vue.component(InputNumber.name, InputNumber);
|
||||
InputNumber.install = function(app) {
|
||||
app.component(InputNumber.name, InputNumber);
|
||||
};
|
||||
|
||||
export default InputNumber;
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import PropTypes from '../../_util/vue-types';
|
||||
import Touchable from '../../vc-m-feedback';
|
||||
import { getListeners } from '../../_util/props-util';
|
||||
import { getSlot } from '../../_util/props-util';
|
||||
|
||||
const InputHandler = {
|
||||
name: 'InputHandler',
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
prefixCls: PropTypes.string,
|
||||
disabled: PropTypes.bool,
|
||||
|
@ -11,15 +12,12 @@ const InputHandler = {
|
|||
render() {
|
||||
const { prefixCls, disabled } = this.$props;
|
||||
const touchableProps = {
|
||||
props: {
|
||||
disabled,
|
||||
activeClassName: `${prefixCls}-handler-active`,
|
||||
},
|
||||
on: getListeners(this),
|
||||
disabled,
|
||||
activeClassName: `${prefixCls}-handler-active`,
|
||||
};
|
||||
return (
|
||||
<Touchable {...touchableProps}>
|
||||
<span>{this.$slots.default}</span>
|
||||
<span {...this.$attrs}>{getSlot(this)}</span>
|
||||
</Touchable>
|
||||
);
|
||||
},
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// based on rc-input-number 4.5.5
|
||||
import PropTypes from '../../_util/vue-types';
|
||||
import BaseMixin from '../../_util/BaseMixin';
|
||||
import { initDefaultProps, hasProp, getOptionProps, getListeners } from '../../_util/props-util';
|
||||
import { initDefaultProps, hasProp, getOptionProps } from '../../_util/props-util';
|
||||
import classNames from 'classnames';
|
||||
import KeyCode from '../../_util/KeyCode';
|
||||
import InputHandler from './InputHandler';
|
||||
|
@ -76,15 +76,17 @@ const inputNumberProps = {
|
|||
title: PropTypes.string,
|
||||
name: PropTypes.string,
|
||||
id: PropTypes.string,
|
||||
type: PropTypes.string,
|
||||
};
|
||||
|
||||
export default {
|
||||
name: 'VCInputNumber',
|
||||
mixins: [BaseMixin],
|
||||
model: {
|
||||
prop: 'value',
|
||||
event: 'change',
|
||||
},
|
||||
inheritAttrs: false,
|
||||
// model: {
|
||||
// prop: 'value',
|
||||
// event: 'change',
|
||||
// },
|
||||
props: initDefaultProps(inputNumberProps, {
|
||||
focusOnUpDown: true,
|
||||
useTouch: false,
|
||||
|
@ -158,6 +160,7 @@ export default {
|
|||
typeof nextValue === 'number' &&
|
||||
nextValue > max
|
||||
) {
|
||||
this.$emit('update:value', max);
|
||||
this.$emit('change', max);
|
||||
}
|
||||
if (
|
||||
|
@ -166,6 +169,7 @@ export default {
|
|||
typeof nextValue === 'number' &&
|
||||
nextValue < min
|
||||
) {
|
||||
this.$emit('update:value', min);
|
||||
this.$emit('change', min);
|
||||
}
|
||||
}
|
||||
|
@ -179,7 +183,7 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
updatedFunc() {
|
||||
const inputElem = this.$refs.inputRef;
|
||||
const inputElem = this.inputRef;
|
||||
// Restore cursor
|
||||
try {
|
||||
// Firefox set the input cursor after it get focused.
|
||||
|
@ -270,7 +274,9 @@ export default {
|
|||
}
|
||||
this.rawInput = this.parser(this.getValueFromEvent(e));
|
||||
this.setState({ inputValue: this.rawInput });
|
||||
this.$emit('change', this.toNumber(this.rawInput)); // valid number or invalid string
|
||||
const num = this.toNumber(this.rawInput); // valid number or invalid string
|
||||
this.$emit('update:value', num);
|
||||
this.$emit('change', num);
|
||||
},
|
||||
onFocus(...args) {
|
||||
this.setState({
|
||||
|
@ -285,12 +291,12 @@ export default {
|
|||
});
|
||||
const value = this.getCurrentValidValue(this.inputValue);
|
||||
const newValue = this.setValue(value);
|
||||
if (this.$listeners.blur) {
|
||||
const originValue = this.$refs.inputRef.value;
|
||||
if (this.$attrs.onBlur) {
|
||||
const originValue = this.inputRef.value;
|
||||
const inputValue = this.getInputDisplayValue({ focused: false, sValue: newValue });
|
||||
this.$refs.inputRef.value = inputValue;
|
||||
this.inputRef.value = inputValue;
|
||||
this.$emit('blur', ...args);
|
||||
this.$refs.inputRef.value = originValue;
|
||||
this.inputRef.value = originValue;
|
||||
}
|
||||
},
|
||||
getCurrentValidValue(value) {
|
||||
|
@ -366,6 +372,7 @@ export default {
|
|||
);
|
||||
}
|
||||
if (changed) {
|
||||
this.$emit('update:value', newValue);
|
||||
this.$emit('change', newValue);
|
||||
}
|
||||
return newValue;
|
||||
|
@ -431,7 +438,7 @@ export default {
|
|||
recordCursorPosition() {
|
||||
// Record position
|
||||
try {
|
||||
const inputElem = this.$refs.inputRef;
|
||||
const inputElem = this.inputRef;
|
||||
this.cursorStart = inputElem.selectionStart;
|
||||
this.cursorEnd = inputElem.selectionEnd;
|
||||
this.currentValue = inputElem.value;
|
||||
|
@ -444,17 +451,12 @@ export default {
|
|||
}
|
||||
},
|
||||
fixCaret(start, end) {
|
||||
if (
|
||||
start === undefined ||
|
||||
end === undefined ||
|
||||
!this.$refs.inputRef ||
|
||||
!this.$refs.inputRef.value
|
||||
) {
|
||||
if (start === undefined || end === undefined || !this.inputRef || !this.inputRef.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const inputElem = this.$refs.inputRef;
|
||||
const inputElem = this.inputRef;
|
||||
const currentStart = inputElem.selectionStart;
|
||||
const currentEnd = inputElem.selectionEnd;
|
||||
|
||||
|
@ -470,7 +472,7 @@ export default {
|
|||
restoreByAfter(str) {
|
||||
if (str === undefined) return false;
|
||||
|
||||
const fullStr = this.$refs.inputRef.value;
|
||||
const fullStr = this.inputRef.value;
|
||||
const index = fullStr.lastIndexOf(str);
|
||||
|
||||
if (index === -1) return false;
|
||||
|
@ -504,11 +506,11 @@ export default {
|
|||
});
|
||||
},
|
||||
focus() {
|
||||
this.$refs.inputRef.focus();
|
||||
this.inputRef.focus();
|
||||
this.recordCursorPosition();
|
||||
},
|
||||
blur() {
|
||||
this.$refs.inputRef.blur();
|
||||
this.inputRef.blur();
|
||||
},
|
||||
formatWrapper(num) {
|
||||
// http://2ality.com/2012/03/signedzero.html
|
||||
|
@ -621,8 +623,20 @@ export default {
|
|||
handleInputClick() {
|
||||
this.$emit('click');
|
||||
},
|
||||
saveUp(node) {
|
||||
this.upHandlerRef = node;
|
||||
},
|
||||
|
||||
saveDown(node) {
|
||||
this.downHandlerRef = node;
|
||||
},
|
||||
|
||||
saveInput(node) {
|
||||
this.inputRef = node;
|
||||
},
|
||||
},
|
||||
render() {
|
||||
const props = { ...this.$props, ...this.$attrs };
|
||||
const {
|
||||
prefixCls,
|
||||
disabled,
|
||||
|
@ -631,8 +645,10 @@ export default {
|
|||
autoComplete,
|
||||
upHandler,
|
||||
downHandler,
|
||||
} = this.$props;
|
||||
class: className,
|
||||
} = props;
|
||||
const classes = classNames({
|
||||
[className]: className,
|
||||
[prefixCls]: true,
|
||||
[`${prefixCls}-disabled`]: disabled,
|
||||
[`${prefixCls}-focused`]: this.focused,
|
||||
|
@ -655,6 +671,16 @@ export default {
|
|||
}
|
||||
}
|
||||
|
||||
const dataOrAriaAttributeProps = {};
|
||||
for (const key in props) {
|
||||
if (
|
||||
props.hasOwnProperty(key) &&
|
||||
(key.substr(0, 5) === 'data-' || key.substr(0, 5) === 'aria-' || key === 'role')
|
||||
) {
|
||||
dataOrAriaAttributeProps[key] = props[key];
|
||||
}
|
||||
}
|
||||
|
||||
const editable = !this.readOnly && !this.disabled;
|
||||
|
||||
// focus state, show input value
|
||||
|
@ -665,71 +691,61 @@ export default {
|
|||
let downEvents;
|
||||
if (useTouch) {
|
||||
upEvents = {
|
||||
touchstart: editable && !upDisabledClass ? this.up : noop,
|
||||
touchend: this.stop,
|
||||
onTouchstart: editable && !upDisabledClass ? this.up : noop,
|
||||
onTouchend: this.stop,
|
||||
};
|
||||
downEvents = {
|
||||
touchstart: editable && !downDisabledClass ? this.down : noop,
|
||||
touchend: this.stop,
|
||||
onTouchstart: editable && !downDisabledClass ? this.down : noop,
|
||||
onTouchend: this.stop,
|
||||
};
|
||||
} else {
|
||||
upEvents = {
|
||||
mousedown: editable && !upDisabledClass ? this.up : noop,
|
||||
mouseup: this.stop,
|
||||
mouseleave: this.stop,
|
||||
onMousedown: editable && !upDisabledClass ? this.up : noop,
|
||||
onMouseup: this.stop,
|
||||
onMouseleave: this.stop,
|
||||
};
|
||||
downEvents = {
|
||||
mousedown: editable && !downDisabledClass ? this.down : noop,
|
||||
mouseup: this.stop,
|
||||
mouseleave: this.stop,
|
||||
onMousedown: editable && !downDisabledClass ? this.down : noop,
|
||||
onMouseup: this.stop,
|
||||
onMouseleave: this.stop,
|
||||
};
|
||||
}
|
||||
const isUpDisabled = !!upDisabledClass || disabled || readOnly;
|
||||
const isDownDisabled = !!downDisabledClass || disabled || readOnly;
|
||||
const {
|
||||
mouseenter = noop,
|
||||
mouseleave = noop,
|
||||
mouseover = noop,
|
||||
mouseout = noop,
|
||||
} = getListeners(this);
|
||||
const contentProps = {
|
||||
on: { mouseenter, mouseleave, mouseover, mouseout },
|
||||
class: classes,
|
||||
attrs: { title: this.$props.title },
|
||||
};
|
||||
|
||||
const upHandlerProps = {
|
||||
props: {
|
||||
disabled: isUpDisabled,
|
||||
prefixCls,
|
||||
},
|
||||
attrs: {
|
||||
unselectable: 'unselectable',
|
||||
role: 'button',
|
||||
'aria-label': 'Increase Value',
|
||||
'aria-disabled': !!isUpDisabled,
|
||||
},
|
||||
disabled: isUpDisabled,
|
||||
prefixCls,
|
||||
unselectable: 'unselectable',
|
||||
role: 'button',
|
||||
'aria-label': 'Increase Value',
|
||||
'aria-disabled': !!isUpDisabled,
|
||||
class: `${prefixCls}-handler ${prefixCls}-handler-up ${upDisabledClass}`,
|
||||
on: upEvents,
|
||||
ref: 'up',
|
||||
...upEvents,
|
||||
ref: this.saveUp,
|
||||
};
|
||||
const downHandlerProps = {
|
||||
props: {
|
||||
disabled: isDownDisabled,
|
||||
prefixCls,
|
||||
},
|
||||
attrs: {
|
||||
unselectable: 'unselectable',
|
||||
role: 'button',
|
||||
'aria-label': 'Decrease Value',
|
||||
'aria-disabled': !!isDownDisabled,
|
||||
},
|
||||
disabled: isDownDisabled,
|
||||
prefixCls,
|
||||
unselectable: 'unselectable',
|
||||
role: 'button',
|
||||
'aria-label': 'Decrease Value',
|
||||
'aria-disabled': !!isDownDisabled,
|
||||
class: `${prefixCls}-handler ${prefixCls}-handler-down ${downDisabledClass}`,
|
||||
on: downEvents,
|
||||
ref: 'down',
|
||||
...downEvents,
|
||||
ref: this.saveDown,
|
||||
};
|
||||
// ref for test
|
||||
|
||||
return (
|
||||
<div {...contentProps}>
|
||||
<div
|
||||
class={classes}
|
||||
style={props.style}
|
||||
title={props.title}
|
||||
onMouseenter={props.onMouseenter}
|
||||
onMouseleave={props.onMouseleave}
|
||||
onMouseover={props.onMouseover}
|
||||
onMouseout={props.onMouseout}
|
||||
>
|
||||
<div class={`${prefixCls}-handler-wrap`}>
|
||||
<InputHandler {...upHandlerProps}>
|
||||
{upHandler || (
|
||||
|
@ -757,7 +773,7 @@ export default {
|
|||
aria-valuemax={this.max}
|
||||
aria-valuenow={sValue}
|
||||
required={this.required}
|
||||
type={this.type}
|
||||
type={props.type}
|
||||
placeholder={this.placeholder}
|
||||
onClick={this.handleInputClick}
|
||||
class={`${prefixCls}-input`}
|
||||
|
@ -767,7 +783,7 @@ export default {
|
|||
onBlur={this.onBlur}
|
||||
onKeydown={editable ? this.onKeyDown : noop}
|
||||
onKeyup={editable ? this.onKeyUp : noop}
|
||||
maxLength={this.maxLength}
|
||||
maxlength={props.maxLength}
|
||||
readOnly={this.readOnly}
|
||||
disabled={this.disabled}
|
||||
max={this.max}
|
||||
|
@ -777,9 +793,10 @@ export default {
|
|||
title={this.title}
|
||||
id={this.id}
|
||||
onInput={this.onChange}
|
||||
ref="inputRef"
|
||||
ref={this.saveInput}
|
||||
value={inputDisplayValue}
|
||||
pattern={this.pattern}
|
||||
{...dataOrAriaAttributeProps}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { initDefaultProps } from '../../_util/props-util';
|
||||
import classNames from 'classnames';
|
||||
import { initDefaultProps, getSlot } from '../../_util/props-util';
|
||||
import { cloneElement } from '../../_util/vnode';
|
||||
import warning from '../../_util/warning';
|
||||
import BaseMixin from '../../_util/BaseMixin';
|
||||
|
@ -7,10 +8,12 @@ import { ITouchProps } from './PropTypes';
|
|||
export default {
|
||||
name: 'TouchFeedback',
|
||||
mixins: [BaseMixin],
|
||||
inheritAttrs: false,
|
||||
props: initDefaultProps(ITouchProps, {
|
||||
disabled: false,
|
||||
}),
|
||||
data() {
|
||||
this.child = null;
|
||||
return {
|
||||
active: false,
|
||||
};
|
||||
|
@ -26,8 +29,12 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
triggerEvent(type, isActive, ev) {
|
||||
// 暂时仅有input-number用到,事件直接到挂载到Touchable上,不需要像antd那样从子组件触发
|
||||
this.$emit(type, ev);
|
||||
const eventType = `on${type}`;
|
||||
const { child } = this;
|
||||
|
||||
if (child.props[eventType]) {
|
||||
child.props[eventType](ev);
|
||||
}
|
||||
if (isActive !== this.active) {
|
||||
this.setState({
|
||||
active: isActive,
|
||||
|
@ -35,60 +42,66 @@ export default {
|
|||
}
|
||||
},
|
||||
onTouchStart(e) {
|
||||
this.triggerEvent('touchstart', true, e);
|
||||
this.triggerEvent('Touchstart', true, e);
|
||||
},
|
||||
onTouchMove(e) {
|
||||
this.triggerEvent('touchmove', false, e);
|
||||
this.triggerEvent('Touchmove', false, e);
|
||||
},
|
||||
onTouchEnd(e) {
|
||||
this.triggerEvent('touchend', false, e);
|
||||
this.triggerEvent('Touchend', false, e);
|
||||
},
|
||||
onTouchCancel(e) {
|
||||
this.triggerEvent('touchcancel', false, e);
|
||||
this.triggerEvent('Touchcancel', false, e);
|
||||
},
|
||||
onMouseDown(e) {
|
||||
// pc simulate mobile
|
||||
this.triggerEvent('mousedown', true, e);
|
||||
this.triggerEvent('Mousedown', true, e);
|
||||
},
|
||||
onMouseUp(e) {
|
||||
this.triggerEvent('mouseup', false, e);
|
||||
this.triggerEvent('Mouseup', false, e);
|
||||
},
|
||||
onMouseLeave(e) {
|
||||
this.triggerEvent('mouseleave', false, e);
|
||||
this.triggerEvent('Mouseleave', false, e);
|
||||
},
|
||||
},
|
||||
render() {
|
||||
const { disabled, activeClassName = '', activeStyle = {} } = this.$props;
|
||||
|
||||
const child = this.$slots.default;
|
||||
let child = getSlot(this);
|
||||
if (child.length !== 1) {
|
||||
warning(false, 'm-feedback组件只能包含一个子元素');
|
||||
return null;
|
||||
}
|
||||
let childProps = {
|
||||
on: disabled
|
||||
? {}
|
||||
: {
|
||||
touchstart: this.onTouchStart,
|
||||
touchmove: this.onTouchMove,
|
||||
touchend: this.onTouchEnd,
|
||||
touchcancel: this.onTouchCancel,
|
||||
mousedown: this.onMouseDown,
|
||||
mouseup: this.onMouseUp,
|
||||
mouseleave: this.onMouseLeave,
|
||||
},
|
||||
};
|
||||
const events = disabled
|
||||
? undefined
|
||||
: {
|
||||
onTouchstart: this.onTouchStart,
|
||||
onTouchmove: this.onTouchMove,
|
||||
onTouchend: this.onTouchEnd,
|
||||
onTouchcancel: this.onTouchCancel,
|
||||
onMousedown: this.onMouseDown,
|
||||
onMouseup: this.onMouseUp,
|
||||
onMouseleave: this.onMouseLeave,
|
||||
};
|
||||
|
||||
child = child[0];
|
||||
this.child = child;
|
||||
if (!disabled && this.active) {
|
||||
childProps = {
|
||||
...childProps,
|
||||
...{
|
||||
style: activeStyle,
|
||||
class: activeClassName,
|
||||
},
|
||||
};
|
||||
let { style, class: className } = child.props;
|
||||
|
||||
if (activeStyle !== false) {
|
||||
if (activeStyle) {
|
||||
style = { ...style, ...activeStyle };
|
||||
}
|
||||
className = classNames(className, activeClassName);
|
||||
}
|
||||
return cloneElement(child, {
|
||||
class: className,
|
||||
style,
|
||||
...events,
|
||||
});
|
||||
}
|
||||
|
||||
return cloneElement(child, childProps);
|
||||
return cloneElement(child, events);
|
||||
},
|
||||
};
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import demo from '../antdv-demo/docs/input/demo/tooltip';
|
||||
import demo from '../antdv-demo/docs/input-number/demo/index';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
|
|
@ -3,6 +3,7 @@ import { createApp } from 'vue';
|
|||
import App from './App.vue';
|
||||
import {
|
||||
Input,
|
||||
InputNumber,
|
||||
Rate,
|
||||
Button,
|
||||
Upload,
|
||||
|
@ -41,4 +42,5 @@ app
|
|||
.use(Tooltip)
|
||||
.use(Col)
|
||||
.use(Row)
|
||||
.use(InputNumber)
|
||||
.mount('#app');
|
||||
|
|
Loading…
Reference in New Issue