refactor: input by ts

feat-dayjs
tanjinzhou 2020-10-16 14:24:14 +08:00
parent 20f54950a9
commit 6cb52efbc8
12 changed files with 151 additions and 132 deletions

@ -1 +1 @@
Subproject commit 88970d13f8e2e6f5c96a28697fe0b399eccdcb07 Subproject commit c9c4f31698398d5bafa5ccd80f0cb7c23b1ab608

View File

@ -4,8 +4,10 @@ import { getInputClassName } from './Input';
import PropTypes from '../_util/vue-types'; import PropTypes from '../_util/vue-types';
import { cloneElement } from '../_util/vnode'; import { cloneElement } from '../_util/vnode';
import { getComponent } from '../_util/props-util'; import { getComponent } from '../_util/props-util';
import { defineComponent, VNode } from 'vue';
import { tuple } from '../_util/type';
export function hasPrefixSuffix(instance) { export function hasPrefixSuffix(instance: any) {
return !!( return !!(
getComponent(instance, 'prefix') || getComponent(instance, 'prefix') ||
getComponent(instance, 'suffix') || getComponent(instance, 'suffix') ||
@ -15,27 +17,27 @@ export function hasPrefixSuffix(instance) {
const ClearableInputType = ['text', 'input']; const ClearableInputType = ['text', 'input'];
const ClearableLabeledInput = { const ClearableLabeledInput = defineComponent({
name: 'ClearableLabeledInput', name: 'ClearableLabeledInput',
inheritAttrs: false, inheritAttrs: false,
props: { props: {
prefixCls: PropTypes.string, prefixCls: PropTypes.string,
inputType: PropTypes.oneOf(ClearableInputType), inputType: PropTypes.oneOf(tuple('text', 'input')),
value: PropTypes.any, value: PropTypes.any,
defaultValue: PropTypes.any, defaultValue: PropTypes.any,
allowClear: PropTypes.looseBool, allowClear: PropTypes.looseBool,
element: PropTypes.any, element: PropTypes.VNodeChild,
handleReset: PropTypes.func, handleReset: PropTypes.func,
disabled: PropTypes.looseBool, disabled: PropTypes.looseBool,
size: PropTypes.oneOf(['small', 'large', 'default']), size: PropTypes.oneOf(tuple('small', 'large', 'default')),
suffix: PropTypes.any, suffix: PropTypes.VNodeChild,
prefix: PropTypes.any, prefix: PropTypes.VNodeChild,
addonBefore: PropTypes.any, addonBefore: PropTypes.VNodeChild,
addonAfter: PropTypes.any, addonAfter: PropTypes.VNodeChild,
readonly: PropTypes.looseBool, readonly: PropTypes.looseBool,
}, },
methods: { methods: {
renderClearIcon(prefixCls) { renderClearIcon(prefixCls: string) {
const { allowClear, value, disabled, readonly, inputType, handleReset } = this.$props; const { allowClear, value, disabled, readonly, inputType, handleReset } = this.$props;
if ( if (
!allowClear || !allowClear ||
@ -54,7 +56,7 @@ const ClearableLabeledInput = {
return <CloseCircleFilled onClick={handleReset} class={className} role="button" />; return <CloseCircleFilled onClick={handleReset} class={className} role="button" />;
}, },
renderSuffix(prefixCls) { renderSuffix(prefixCls: string) {
const { suffix, allowClear } = this.$props; const { suffix, allowClear } = this.$props;
if (suffix || allowClear) { if (suffix || allowClear) {
return ( return (
@ -67,7 +69,7 @@ const ClearableLabeledInput = {
return null; return null;
}, },
renderLabeledIcon(prefixCls, element) { renderLabeledIcon(prefixCls: string, element: VNode): VNode {
const props = this.$props; const props = this.$props;
const suffix = this.renderSuffix(prefixCls); const suffix = this.renderSuffix(prefixCls);
if (!hasPrefixSuffix(this)) { if (!hasPrefixSuffix(this)) {
@ -88,7 +90,7 @@ const ClearableLabeledInput = {
}); });
return ( return (
<span class={affixWrapperCls} style={props.style}> <span class={affixWrapperCls} style={this.$attrs?.style}>
{prefix} {prefix}
{cloneElement(element, { {cloneElement(element, {
style: null, style: null,
@ -97,10 +99,10 @@ const ClearableLabeledInput = {
})} })}
{suffix} {suffix}
</span> </span>
); ) as VNode;
}, },
renderInputWithLabel(prefixCls, labeledElement) { renderInputWithLabel(prefixCls: string, labeledElement: VNode) {
const { addonBefore, addonAfter, size } = this.$props; const { addonBefore, addonAfter, size } = this.$props;
const { style, class: className } = this.$attrs; const { style, class: className } = this.$attrs;
// Not wrap when there is not addons // Not wrap when there is not addons
@ -137,7 +139,7 @@ const ClearableLabeledInput = {
); );
}, },
renderTextAreaWithClearIcon(prefixCls, element) { renderTextAreaWithClearIcon(prefixCls: string, element: VNode) {
const { value, allowClear } = this.$props; const { value, allowClear } = this.$props;
const { style, class: className } = this.$attrs; const { style, class: className } = this.$attrs;
if (!allowClear) { if (!allowClear) {
@ -160,7 +162,7 @@ const ClearableLabeledInput = {
}, },
renderClearableLabeledInput() { renderClearableLabeledInput() {
const { prefixCls, inputType, element } = this.$props; const { prefixCls, inputType, element } = this.$props as any;
if (inputType === ClearableInputType[0]) { if (inputType === ClearableInputType[0]) {
return this.renderTextAreaWithClearIcon(prefixCls, element); return this.renderTextAreaWithClearIcon(prefixCls, element);
} }
@ -170,6 +172,6 @@ const ClearableLabeledInput = {
render() { render() {
return this.renderClearableLabeledInput(); return this.renderClearableLabeledInput();
}, },
}; });
export default ClearableLabeledInput; export default ClearableLabeledInput;

View File

@ -1,17 +1,14 @@
import { inject } from 'vue'; import { defineComponent, inject } from 'vue';
import PropTypes from '../_util/vue-types'; import PropTypes from '../_util/vue-types';
import { getSlot } from '../_util/props-util'; import { getSlot } from '../_util/props-util';
import { defaultConfigProvider } from '../config-provider'; import { defaultConfigProvider } from '../config-provider';
import { tuple } from '../_util/type';
export default { export default defineComponent({
name: 'AInputGroup', name: 'AInputGroup',
props: { props: {
prefixCls: PropTypes.string, prefixCls: PropTypes.string,
size: { size: PropTypes.oneOf(tuple('small', 'large', 'default')),
validator(value) {
return ['small', 'large', 'default'].includes(value);
},
},
compact: PropTypes.looseBool, compact: PropTypes.looseBool,
}, },
setup() { setup() {
@ -21,8 +18,8 @@ export default {
}, },
computed: { computed: {
classes() { classes() {
const { prefixCls: customizePrefixCls, size, compact = false } = this; const { prefixCls: customizePrefixCls, size, compact = false, configProvider } = this as any;
const getPrefixCls = this.configProvider.getPrefixCls; const getPrefixCls = configProvider.getPrefixCls;
const prefixCls = getPrefixCls('input-group', customizePrefixCls); const prefixCls = getPrefixCls('input-group', customizePrefixCls);
return { return {
@ -36,4 +33,4 @@ export default {
render() { render() {
return <span class={this.classes}>{getSlot(this)}</span>; return <span class={this.classes}>{getSlot(this)}</span>;
}, },
}; });

View File

@ -1,4 +1,4 @@
import { defineComponent, inject, withDirectives } from 'vue'; import { defineComponent, inject, VNode, withDirectives } from 'vue';
import antInputDirective from '../_util/antInputDirective'; import antInputDirective from '../_util/antInputDirective';
import classNames from '../_util/classNames'; import classNames from '../_util/classNames';
import omit from 'omit.js'; import omit from 'omit.js';
@ -57,6 +57,9 @@ export default defineComponent({
setup() { setup() {
return { return {
configProvider: inject('configProvider', defaultConfigProvider), configProvider: inject('configProvider', defaultConfigProvider),
removePasswordTimeout: undefined,
input: null,
clearableInput: null
}; };
}, },
data() { data() {
@ -98,15 +101,15 @@ export default defineComponent({
this.input.select(); this.input.select();
}, },
saveClearableInput(input) { saveClearableInput(input: any) {
this.clearableInput = input; this.clearableInput = input;
}, },
saveInput(input) { saveInput(input: any) {
this.input = input; this.input = input;
}, },
setValue(value, callback) { setValue(value: any, callback?: Function) {
if (this.stateValue === value) { if (this.stateValue === value) {
return; return;
} }
@ -119,18 +122,18 @@ export default defineComponent({
callback && callback(); callback && callback();
}); });
}, },
triggerChange(e) { triggerChange(e: Event) {
this.$emit('update:value', e.target.value); this.$emit('update:value', (e.target as any).value);
this.$emit('change', e); this.$emit('change', e);
this.$emit('input', e); this.$emit('input', e);
}, },
handleReset(e) { handleReset(e: Event) {
this.setValue('', () => { this.setValue('', () => {
this.focus(); this.focus();
}); });
resolveOnChange(this.input, e, this.triggerChange); resolveOnChange(this.input, e, this.triggerChange);
}, },
renderInput(prefixCls, { addonBefore, addonAfter }) { renderInput(prefixCls: string, { addonBefore, addonAfter }) {
const otherProps = omit(this.$props, [ const otherProps = omit(this.$props, [
'prefixCls', 'prefixCls',
'onPressEnter', 'onPressEnter',
@ -142,19 +145,17 @@ export default defineComponent({
'defaultValue', 'defaultValue',
'lazy', 'lazy',
'size', 'size',
'inputType',
'className',
'inputPrefixCls', 'inputPrefixCls',
'loading', 'loading',
]); ]);
const { handleKeyDown, handleChange, size, disabled, $attrs } = this; const { handleKeyDown, handleChange, size, disabled, $attrs } = this;
const inputProps = { const inputProps: any = {
...otherProps, ...otherProps,
...$attrs, ...$attrs,
onKeydown: handleKeyDown, onKeydown: handleKeyDown,
class: classNames(getInputClassName(prefixCls, size, disabled), { class: classNames(getInputClassName(prefixCls, size, disabled), {
[$attrs.class]: $attrs.class && !addonBefore && !addonAfter, [$attrs.class as string]: $attrs.class && !addonBefore && !addonAfter,
}), }),
ref: this.saveInput, ref: this.saveInput,
key: 'ant-input', key: 'ant-input',
@ -164,7 +165,8 @@ export default defineComponent({
if (!inputProps.autofocus) { if (!inputProps.autofocus) {
delete inputProps.autofocus; delete inputProps.autofocus;
} }
return withDirectives(<input {...inputProps} />, [[antInputDirective]]); const inputNode = <input {...inputProps} />
return withDirectives(inputNode as VNode, [[antInputDirective]]);
}, },
clearPasswordValueAttribute() { clearPasswordValueAttribute() {
// https://github.com/ant-design/ant-design/issues/20541 // https://github.com/ant-design/ant-design/issues/20541
@ -179,14 +181,14 @@ export default defineComponent({
} }
}); });
}, },
handleChange(e) { handleChange(e: Event) {
const { value, composing } = e.target; const { value, composing, isComposing } = e.target as any;
// https://github.com/vueComponent/ant-design-vue/issues/2203 // https://github.com/vueComponent/ant-design-vue/issues/2203
if (((e.isComposing || composing) && this.lazy) || this.stateValue === value) return; if (((isComposing || composing) && this.lazy) || this.stateValue === value) return;
this.setValue(value, this.clearPasswordValueAttribute); this.setValue(value, this.clearPasswordValueAttribute);
resolveOnChange(this.input, e, this.triggerChange); resolveOnChange(this.input, e, this.triggerChange);
}, },
handleKeyDown(e) { handleKeyDown(e: KeyboardEvent) {
if (e.keyCode === 13) { if (e.keyCode === 13) {
this.$emit('pressEnter', e); this.$emit('pressEnter', e);
} }
@ -194,16 +196,6 @@ export default defineComponent({
}, },
}, },
render() { render() {
// if (this.$props.type === 'textarea') {
// const textareaProps = {
// ...this.$props,
// ...this.$attrs,
// onInput: this.handleChange,
// onKeydown: this.handleKeyDown,
// onChange: noop,
// };
// return <TextArea {...textareaProps} ref="input" />;
// }
const { prefixCls: customizePrefixCls } = this.$props; const { prefixCls: customizePrefixCls } = this.$props;
const { stateValue } = this.$data; const { stateValue } = this.$data;
const getPrefixCls = this.configProvider.getPrefixCls; const getPrefixCls = this.configProvider.getPrefixCls;
@ -212,7 +204,7 @@ export default defineComponent({
const addonBefore = getComponent(this, 'addonBefore'); const addonBefore = getComponent(this, 'addonBefore');
const suffix = getComponent(this, 'suffix'); const suffix = getComponent(this, 'suffix');
const prefix = getComponent(this, 'prefix'); const prefix = getComponent(this, 'prefix');
const props = { const props: any = {
...this.$attrs, ...this.$attrs,
...getOptionProps(this), ...getOptionProps(this),
prefixCls, prefixCls,

View File

@ -6,13 +6,14 @@ import EyeInvisibleOutlined from '@ant-design/icons-vue/EyeInvisibleOutlined';
import inputProps from './inputProps'; import inputProps from './inputProps';
import PropTypes from '../_util/vue-types'; import PropTypes from '../_util/vue-types';
import BaseMixin from '../_util/BaseMixin'; import BaseMixin from '../_util/BaseMixin';
import { defineComponent } from 'vue';
const ActionMap = { const ActionMap = {
click: 'onClick', click: 'onClick',
hover: 'onMouseover', hover: 'onMouseover',
}; };
export default { export default defineComponent({
name: 'AInputPassword', name: 'AInputPassword',
mixins: [BaseMixin], mixins: [BaseMixin],
inheritAttrs: false, inheritAttrs: false,
@ -23,13 +24,18 @@ export default {
action: PropTypes.string.def('click'), action: PropTypes.string.def('click'),
visibilityToggle: PropTypes.looseBool.def(true), visibilityToggle: PropTypes.looseBool.def(true),
}, },
setup() {
return {
input: null,
}
},
data() { data() {
return { return {
visible: false, visible: false,
}; };
}, },
methods: { methods: {
saveInput(node) { saveInput(node: any) {
this.input = node; this.input = node;
}, },
focus() { focus() {
@ -101,4 +107,4 @@ export default {
}; };
return <Input {...inputProps} ref={this.saveInput} />; return <Input {...inputProps} ref={this.saveInput} />;
}, },
}; });

View File

@ -1,3 +1,4 @@
import {PropType, VNode} from 'vue';
import ResizeObserver from '../vc-resize-observer'; import ResizeObserver from '../vc-resize-observer';
import omit from 'omit.js'; import omit from 'omit.js';
import classNames from '../_util/classNames'; import classNames from '../_util/classNames';
@ -6,22 +7,28 @@ import raf from '../_util/raf';
import warning from '../_util/warning'; import warning from '../_util/warning';
import BaseMixin from '../_util/BaseMixin'; import BaseMixin from '../_util/BaseMixin';
import inputProps from './inputProps'; import inputProps from './inputProps';
import PropTypes, { withUndefined } from '../_util/vue-types'; import PropTypes from '../_util/vue-types';
import { getOptionProps } from '../_util/props-util'; import { getOptionProps } from '../_util/props-util';
import { withDirectives } from 'vue'; import { defineComponent, withDirectives } from 'vue';
import antInput from '../_util/antInputDirective'; import antInput from '../_util/antInputDirective';
const RESIZE_STATUS_NONE = 0; const RESIZE_STATUS_NONE = 0;
const RESIZE_STATUS_RESIZING = 1; const RESIZE_STATUS_RESIZING = 1;
const RESIZE_STATUS_RESIZED = 2; const RESIZE_STATUS_RESIZED = 2;
export interface AutoSizeType {
minRows?: number;
maxRows?: number;
}
const TextAreaProps = { const TextAreaProps = {
...inputProps, ...inputProps,
autosize: withUndefined(PropTypes.oneOfType([Object, Boolean])), autosize: { type: [Boolean, Object] as PropType<AutoSizeType>, default: undefined},
autoSize: withUndefined(PropTypes.oneOfType([Object, Boolean])), autoSize: {type: [Boolean, Object] as PropType<AutoSizeType>, default: undefined},
onResize: PropTypes.func, onResize: PropTypes.func,
}; };
const ResizableTextArea = {
const ResizableTextArea = defineComponent({
name: 'ResizableTextArea', name: 'ResizableTextArea',
inheritAttrs: false, inheritAttrs: false,
props: TextAreaProps, props: TextAreaProps,
@ -39,6 +46,13 @@ const ResizableTextArea = {
raf.cancel(this.nextFrameActionId); raf.cancel(this.nextFrameActionId);
raf.cancel(this.resizeFrameId); raf.cancel(this.resizeFrameId);
}, },
setup() {
return {
nextFrameActionId: undefined,
textArea: null,
resizeFrameId: undefined,
}
},
watch: { watch: {
value() { value() {
this.$nextTick(() => { this.$nextTick(() => {
@ -47,10 +61,10 @@ const ResizableTextArea = {
}, },
}, },
methods: { methods: {
saveTextArea(textArea) { saveTextArea(textArea: any) {
this.textArea = textArea; this.textArea = textArea;
}, },
handleResize(size) { handleResize(size: any) {
const { resizeStatus } = this.$data; const { resizeStatus } = this.$data;
if (resizeStatus !== RESIZE_STATUS_NONE) { if (resizeStatus !== RESIZE_STATUS_NONE) {
@ -98,7 +112,7 @@ const ResizableTextArea = {
}, },
renderTextArea() { renderTextArea() {
const props = { ...getOptionProps(this), ...this.$attrs }; const props: any = { ...getOptionProps(this), ...this.$attrs };
const { prefixCls, autoSize, autosize, disabled, class: className } = props; const { prefixCls, autoSize, autosize, disabled, class: className } = props;
const { textareaStyles, resizeStatus } = this.$data; const { textareaStyles, resizeStatus } = this.$data;
warning( warning(
@ -131,7 +145,7 @@ const ResizableTextArea = {
? { overflowX: 'hidden', overflowY: 'hidden' } ? { overflowX: 'hidden', overflowY: 'hidden' }
: null), : null),
}; };
const textareaProps = { const textareaProps: any = {
...otherProps, ...otherProps,
style, style,
class: cls, class: cls,
@ -141,7 +155,7 @@ const ResizableTextArea = {
} }
return ( return (
<ResizeObserver onResize={this.handleResize} disabled={!(autoSize || autosize)}> <ResizeObserver onResize={this.handleResize} disabled={!(autoSize || autosize)}>
{withDirectives(<textarea {...textareaProps} ref={this.saveTextArea} />, [[antInput]])} {withDirectives(<textarea {...textareaProps} ref={this.saveTextArea} /> as VNode, [[antInput]])}
</ResizeObserver> </ResizeObserver>
); );
}, },
@ -150,6 +164,6 @@ const ResizableTextArea = {
render() { render() {
return this.renderTextArea(); return this.renderTextArea();
}, },
}; });
export default ResizableTextArea; export default ResizableTextArea;

View File

@ -1,4 +1,4 @@
import { inject } from 'vue'; import { defineComponent, inject } from 'vue';
import classNames from '../_util/classNames'; import classNames from '../_util/classNames';
import { isMobile } from 'is-mobile'; import { isMobile } from 'is-mobile';
import Input from './Input'; import Input from './Input';
@ -12,22 +12,23 @@ import { getOptionProps, getComponent } from '../_util/props-util';
import { defaultConfigProvider } from '../config-provider'; import { defaultConfigProvider } from '../config-provider';
import isPlainObject from 'lodash-es/isPlainObject'; import isPlainObject from 'lodash-es/isPlainObject';
export default { export default defineComponent({
name: 'AInputSearch', name: 'AInputSearch',
inheritAttrs: false, inheritAttrs: false,
props: { props: {
...inputProps, ...inputProps,
// 不能设置默认值 https://github.com/vueComponent/ant-design-vue/issues/1916 // 不能设置默认值 https://github.com/vueComponent/ant-design-vue/issues/1916
enterButton: PropTypes.any, enterButton: PropTypes.VNodeChild,
onSearch: PropTypes.func, onSearch: PropTypes.func,
}, },
setup() { setup() {
return { return {
configProvider: inject('configProvider', defaultConfigProvider), configProvider: inject('configProvider', defaultConfigProvider),
input: null,
}; };
}, },
methods: { methods: {
saveInput(node) { saveInput(node: any) {
this.input = node; this.input = node;
}, },
handleChange(e) { handleChange(e) {
@ -53,7 +54,7 @@ export default {
blur() { blur() {
this.input.blur(); this.input.blur();
}, },
renderLoading(prefixCls) { renderLoading(prefixCls: string) {
const { size } = this.$props; const { size } = this.$props;
let enterButton = getComponent(this, 'enterButton'); let enterButton = getComponent(this, 'enterButton');
// 兼容 <a-input-search enterButton /> 因enterButton类型为 any此类写法 enterButton 为空字符串 // 兼容 <a-input-search enterButton /> 因enterButton类型为 any此类写法 enterButton 为空字符串
@ -67,7 +68,7 @@ export default {
} }
return <LoadingOutlined class={`${prefixCls}-icon`} key="loadingIcon" />; return <LoadingOutlined class={`${prefixCls}-icon`} key="loadingIcon" />;
}, },
renderSuffix(prefixCls) { renderSuffix(prefixCls: string) {
const { loading } = this; const { loading } = this;
const suffix = getComponent(this, 'suffix'); const suffix = getComponent(this, 'suffix');
let enterButton = getComponent(this, 'enterButton'); let enterButton = getComponent(this, 'enterButton');
@ -95,7 +96,7 @@ export default {
return icon; return icon;
}, },
renderAddonAfter(prefixCls) { renderAddonAfter(prefixCls: string) {
const { size, disabled, loading } = this; const { size, disabled, loading } = this;
const btnClassName = `${prefixCls}-button`; const btnClassName = `${prefixCls}-button`;
let enterButton = getComponent(this, 'enterButton'); let enterButton = getComponent(this, 'enterButton');
@ -106,7 +107,7 @@ export default {
} }
if (!enterButton) return addonAfter; if (!enterButton) return addonAfter;
const enterButtonAsElement = Array.isArray(enterButton) ? enterButton[0] : enterButton; const enterButtonAsElement = Array.isArray(enterButton) ? enterButton[0] : enterButton;
let button; let button: any;
const isAntdButton = const isAntdButton =
enterButtonAsElement.type && enterButtonAsElement.type &&
isPlainObject(enterButtonAsElement.type) && isPlainObject(enterButtonAsElement.type) &&
@ -146,7 +147,7 @@ export default {
size, size,
class: className, class: className,
...restProps ...restProps
} = { ...getOptionProps(this), ...this.$attrs }; } = { ...getOptionProps(this), ...this.$attrs } as any;
delete restProps.onSearch; delete restProps.onSearch;
delete restProps.loading; delete restProps.loading;
delete restProps.enterButton; delete restProps.enterButton;
@ -159,7 +160,7 @@ export default {
let enterButton = getComponent(this, 'enterButton'); let enterButton = getComponent(this, 'enterButton');
const addonBefore = getComponent(this, 'addonBefore'); const addonBefore = getComponent(this, 'addonBefore');
enterButton = enterButton || enterButton === ''; enterButton = enterButton || enterButton === '';
let inputClassName; let inputClassName: string;
if (enterButton) { if (enterButton) {
inputClassName = classNames(prefixCls, className, { inputClassName = classNames(prefixCls, className, {
[`${prefixCls}-enter-button`]: !!enterButton, [`${prefixCls}-enter-button`]: !!enterButton,
@ -183,4 +184,4 @@ export default {
}; };
return <Input {...inputProps} ref={this.saveInput} />; return <Input {...inputProps} ref={this.saveInput} />;
}, },
}; });

View File

@ -1,4 +1,4 @@
import { inject } from 'vue'; import { defineComponent, inject } from 'vue';
import ClearableLabeledInput from './ClearableLabeledInput'; import ClearableLabeledInput from './ClearableLabeledInput';
import ResizableTextArea from './ResizableTextArea'; import ResizableTextArea from './ResizableTextArea';
import inputProps from './inputProps'; import inputProps from './inputProps';
@ -13,7 +13,7 @@ const TextAreaProps = {
autoSize: withUndefined(PropTypes.oneOfType([Object, Boolean])), autoSize: withUndefined(PropTypes.oneOfType([Object, Boolean])),
}; };
export default { export default defineComponent({
name: 'ATextarea', name: 'ATextarea',
inheritAttrs: false, inheritAttrs: false,
props: { props: {
@ -22,6 +22,8 @@ export default {
setup() { setup() {
return { return {
configProvider: inject('configProvider', defaultConfigProvider), configProvider: inject('configProvider', defaultConfigProvider),
resizableTextArea: null,
clearableInput: null,
}; };
}, },
data() { data() {
@ -45,7 +47,7 @@ export default {
}); });
}, },
methods: { methods: {
setValue(value, callback) { setValue(value: any, callback?: Function) {
if (!hasProp(this, 'value')) { if (!hasProp(this, 'value')) {
this.stateValue = value; this.stateValue = value;
} else { } else {
@ -55,22 +57,22 @@ export default {
callback && callback(); callback && callback();
}); });
}, },
handleKeyDown(e) { handleKeyDown(e: KeyboardEvent) {
if (e.keyCode === 13) { if (e.keyCode === 13) {
this.$emit('pressEnter', e); this.$emit('pressEnter', e);
} }
this.$emit('keydown', e); this.$emit('keydown', e);
}, },
triggerChange(e) { triggerChange(e: Event) {
this.$emit('update:value', e.target.value); this.$emit('update:value', (e.target as any).value);
this.$emit('change', e); this.$emit('change', e);
this.$emit('input', e); this.$emit('input', e);
}, },
handleChange(e) { handleChange(e: Event) {
const { value, composing } = e.target; const { value, composing, isComposing } = e.target as any;
if (((e.isComposing || composing) && this.lazy) || this.stateValue === value) return; if (((isComposing || composing) && this.lazy) || this.stateValue === value) return;
this.setValue(e.target.value, () => { this.setValue((e.target as any).value, () => {
this.resizableTextArea.resizeTextarea(); this.resizableTextArea.resizeTextarea();
}); });
resolveOnChange(this.resizableTextArea.textArea, e, this.triggerChange); resolveOnChange(this.resizableTextArea.textArea, e, this.triggerChange);
@ -83,14 +85,14 @@ export default {
blur() { blur() {
this.resizableTextArea.textArea.blur(); this.resizableTextArea.textArea.blur();
}, },
saveTextArea(resizableTextArea) { saveTextArea(resizableTextArea: any) {
this.resizableTextArea = resizableTextArea; this.resizableTextArea = resizableTextArea;
}, },
saveClearableInput(clearableInput) { saveClearableInput(clearableInput: any) {
this.clearableInput = clearableInput; this.clearableInput = clearableInput;
}, },
handleReset(e) { handleReset(e: Event) {
this.setValue('', () => { this.setValue('', () => {
this.resizableTextArea.renderTextArea(); this.resizableTextArea.renderTextArea();
this.focus(); this.focus();
@ -98,7 +100,7 @@ export default {
resolveOnChange(this.resizableTextArea.textArea, e, this.triggerChange); resolveOnChange(this.resizableTextArea.textArea, e, this.triggerChange);
}, },
renderTextArea(prefixCls) { renderTextArea(prefixCls: string) {
const props = getOptionProps(this); const props = getOptionProps(this);
const resizeProps = { const resizeProps = {
...props, ...props,
@ -116,7 +118,7 @@ export default {
const getPrefixCls = this.configProvider.getPrefixCls; const getPrefixCls = this.configProvider.getPrefixCls;
const prefixCls = getPrefixCls('input', customizePrefixCls); const prefixCls = getPrefixCls('input', customizePrefixCls);
const props = { const props: any = {
...getOptionProps(this), ...getOptionProps(this),
...this.$attrs, ...this.$attrs,
prefixCls, prefixCls,
@ -127,4 +129,4 @@ export default {
}; };
return <ClearableLabeledInput {...props} ref={this.saveClearableInput} />; return <ClearableLabeledInput {...props} ref={this.saveClearableInput} />;
}, },
}; });

View File

@ -35,12 +35,20 @@ const SIZING_STYLE = [
'box-sizing', 'box-sizing',
]; ];
const computedStyleCache = {}; export interface NodeType {
let hiddenTextarea; sizingStyle: string;
paddingSize: number;
borderSize: number;
boxSizing: string;
}
export function calculateNodeStyling(node, useCache = false) { const computedStyleCache: { [key: string]: NodeType } = {};
const nodeRef = let hiddenTextarea: HTMLTextAreaElement;
node.getAttribute('id') || node.getAttribute('data-reactid') || node.getAttribute('name');
export function calculateNodeStyling(node: HTMLElement, useCache = false) {
const nodeRef = (node.getAttribute('id') ||
node.getAttribute('data-reactid') ||
node.getAttribute('name')) as string;
if (useCache && computedStyleCache[nodeRef]) { if (useCache && computedStyleCache[nodeRef]) {
return computedStyleCache[nodeRef]; return computedStyleCache[nodeRef];
@ -63,7 +71,7 @@ export function calculateNodeStyling(node, useCache = false) {
const sizingStyle = SIZING_STYLE.map(name => `${name}:${style.getPropertyValue(name)}`).join(';'); const sizingStyle = SIZING_STYLE.map(name => `${name}:${style.getPropertyValue(name)}`).join(';');
const nodeInfo = { const nodeInfo: NodeType = {
sizingStyle, sizingStyle,
paddingSize, paddingSize,
borderSize, borderSize,
@ -78,10 +86,10 @@ export function calculateNodeStyling(node, useCache = false) {
} }
export default function calculateNodeHeight( export default function calculateNodeHeight(
uiTextNode, uiTextNode: HTMLTextAreaElement,
useCache = false, useCache = false,
minRows = null, minRows: number | null = null,
maxRows = null, maxRows: number | null = null,
) { ) {
if (!hiddenTextarea) { if (!hiddenTextarea) {
hiddenTextarea = document.createElement('textarea'); hiddenTextarea = document.createElement('textarea');
@ -91,7 +99,7 @@ export default function calculateNodeHeight(
// Fix wrap="off" issue // Fix wrap="off" issue
// https://github.com/ant-design/ant-design/issues/6577 // https://github.com/ant-design/ant-design/issues/6577
if (uiTextNode.getAttribute('wrap')) { if (uiTextNode.getAttribute('wrap')) {
hiddenTextarea.setAttribute('wrap', uiTextNode.getAttribute('wrap')); hiddenTextarea.setAttribute('wrap', uiTextNode.getAttribute('wrap') as string);
} else { } else {
hiddenTextarea.removeAttribute('wrap'); hiddenTextarea.removeAttribute('wrap');
} }
@ -112,7 +120,7 @@ export default function calculateNodeHeight(
let minHeight = Number.MIN_SAFE_INTEGER; let minHeight = Number.MIN_SAFE_INTEGER;
let maxHeight = Number.MAX_SAFE_INTEGER; let maxHeight = Number.MAX_SAFE_INTEGER;
let height = hiddenTextarea.scrollHeight; let height = hiddenTextarea.scrollHeight;
let overflowY; let overflowY: any;
if (boxSizing === 'border-box') { if (boxSizing === 'border-box') {
// border-box: add border, since height = content + padding + border // border-box: add border, since height = content + padding + border

View File

@ -3,6 +3,7 @@ import Group from './Group';
import Search from './Search'; import Search from './Search';
import TextArea from './TextArea'; import TextArea from './TextArea';
import Password from './Password'; import Password from './Password';
import { App } from 'vue';
Input.Group = Group; Input.Group = Group;
Input.Search = Search; Input.Search = Search;
@ -10,7 +11,7 @@ Input.TextArea = TextArea;
Input.Password = Password; Input.Password = Password;
/* istanbul ignore next */ /* istanbul ignore next */
Input.install = function(app) { Input.install = function(app: App) {
app.component(Input.name, Input); app.component(Input.name, Input);
app.component(Input.Group.name, Input.Group); app.component(Input.Group.name, Input.Group);
app.component(Input.Search.name, Input.Search); app.component(Input.Search.name, Input.Search);
@ -19,4 +20,9 @@ Input.install = function(app) {
return app; return app;
}; };
export default Input; export default Input as typeof Input & {
readonly Group: typeof Group;
readonly Search: typeof Search;
readonly TextArea: typeof TextArea;
readonly Password: typeof Password;
};

View File

@ -1,35 +1,26 @@
import { tuple } from '../_util/type';
import { PropType } from 'vue';
import PropTypes from '../_util/vue-types'; import PropTypes from '../_util/vue-types';
export default { export default {
prefixCls: PropTypes.string, prefixCls: PropTypes.string,
inputPrefixCls: PropTypes.string, inputPrefixCls: PropTypes.string,
defaultValue: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), defaultValue: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
placeholder: [String, Number], placeholder: {
type: { type: [String, Number] as PropType<string | number>,
default: 'text',
type: String,
}, },
name: String, type: PropTypes.string.def('text'),
size: PropTypes.oneOf(['small', 'large', 'default']), name: PropTypes.string,
size: PropTypes.oneOf(tuple('small', 'large', 'default')),
disabled: PropTypes.looseBool, disabled: PropTypes.looseBool,
readonly: PropTypes.looseBool, readonly: PropTypes.looseBool,
addonBefore: PropTypes.any, addonBefore: PropTypes.VNodeChild,
addonAfter: PropTypes.any, addonAfter: PropTypes.VNodeChild,
// onPressEnter?: React.FormEventHandler<any>; prefix: PropTypes.VNodeChild,
// onKeyDown?: React.FormEventHandler<any>; suffix: PropTypes.VNodeChild,
// onChange?: React.ChangeEventHandler<HTMLInputElement>;
// onClick?: React.FormEventHandler<any>;
// onFocus?: React.FormEventHandler<any>;
// onBlur?: React.FormEventHandler<any>;
prefix: PropTypes.any,
suffix: PropTypes.any,
// spellCheck: Boolean,
autofocus: PropTypes.looseBool, autofocus: PropTypes.looseBool,
allowClear: PropTypes.looseBool, allowClear: PropTypes.looseBool,
lazy: { lazy: PropTypes.looseBool.def(true),
default: true,
type: Boolean,
},
maxlength: PropTypes.number, maxlength: PropTypes.number,
loading: PropTypes.looseBool, loading: PropTypes.looseBool,
onPressEnter: PropTypes.func, onPressEnter: PropTypes.func,