diff --git a/packages/components/form/__tests__/form.spec.ts b/packages/components/form/__tests__/form.spec.ts index 4868b4c353..aebd57fa05 100644 --- a/packages/components/form/__tests__/form.spec.ts +++ b/packages/components/form/__tests__/form.spec.ts @@ -3,7 +3,7 @@ import { mount } from '@vue/test-utils' import installStyle from '@element-plus/test-utils/style-plugin' import Checkbox from '@element-plus/components/checkbox/src/checkbox.vue' import CheckboxGroup from '@element-plus/components/checkbox/src/checkbox-group.vue' -import Input from '@element-plus/components/input/src/index.vue' +import Input from '@element-plus/components/input' import Form from '../src/form.vue' import FormItem from '../src/form-item.vue' import type { VueWrapper } from '@vue/test-utils' diff --git a/packages/components/input/__tests__/input.spec.ts b/packages/components/input/__tests__/input.spec.ts index 23000c3091..694b12c235 100644 --- a/packages/components/input/__tests__/input.spec.ts +++ b/packages/components/input/__tests__/input.spec.ts @@ -1,7 +1,7 @@ import { nextTick, ref } from 'vue' import { mount } from '@vue/test-utils' import { sleep, defineGetter } from '@element-plus/test-utils' -import Input from '../src/index.vue' +import Input from '../src/input.vue' const _mount = (options) => mount({ @@ -84,17 +84,17 @@ describe('Input.vue', () => { const elCount = wrapper.find('.el-input__count-inner') expect(elCount.exists()).toBe(true) - expect(elCount.text()).toBe('3/4') + expect(elCount.text()).toBe('3 / 4') vm.inputVal = '1👌3😄' await sleep() expect(nativeInput.value).toBe('1👌3😄') - expect(elCount.text()).toBe('4/4') + expect(elCount.text()).toBe('4 / 4') vm.inputVal = '哈哈1👌3😄' await sleep() expect(nativeInput.value).toBe('哈哈1👌3😄') - expect(elCount.text()).toBe('6/4') + expect(elCount.text()).toBe('6 / 4') expect(vm.$el.classList.contains('is-exceed')).toBe(true) }) @@ -113,12 +113,12 @@ describe('Input.vue', () => { const elCount = wrapper.find('.el-input__count') expect(elCount.exists()).toBe(true) - expect(elCount.text()).toBe('3/4') + expect(elCount.text()).toBe('3 / 4') vm.inputVal = '哈哈1👌3😄' await sleep() expect(nativeInput.value).toBe('哈哈1👌3😄') - expect(elCount.text()).toBe('6/4') + expect(elCount.text()).toBe('6 / 4') expect(vm.$el.classList.contains('is-exceed')).toBe(true) }) }) @@ -343,7 +343,7 @@ describe('Input.vue', () => { ref.autosize.minRows = 5 ref.resizeTextarea() // Atfer this textarea min-height (style) will change - const nowMinHeight = ref.computedTextareaStyle.minHeight + const nowMinHeight = ref.computedTextareaStyle[1].minHeight expect(originMinHeight).not.toEqual(nowMinHeight) }) }) diff --git a/packages/components/input/index.ts b/packages/components/input/index.ts index 709ef36758..8ed5c890cc 100644 --- a/packages/components/input/index.ts +++ b/packages/components/input/index.ts @@ -1,13 +1,8 @@ -import Input from './src/index.vue' +import { withInstall } from '@element-plus/utils/with-install' -import type { App } from 'vue' -import type { SFCWithInstall } from '@element-plus/utils/types' +import Input from './src/input.vue' -Input.install = (app: App): void => { - app.component(Input.name, Input) -} +export const ElInput = withInstall(Input) +export default ElInput -const _Input = Input as SFCWithInstall - -export default _Input -export const ElInput = _Input +export * from './src/input' diff --git a/packages/components/input/src/calcTextareaHeight.ts b/packages/components/input/src/calc-textarea-height.ts similarity index 89% rename from packages/components/input/src/calcTextareaHeight.ts rename to packages/components/input/src/calc-textarea-height.ts index 166d53c981..075afa011b 100644 --- a/packages/components/input/src/calcTextareaHeight.ts +++ b/packages/components/input/src/calc-textarea-height.ts @@ -1,4 +1,6 @@ -let hiddenTextarea: HTMLTextAreaElement +import { isNumber } from '@element-plus/utils/util' + +let hiddenTextarea: HTMLTextAreaElement | undefined = undefined const HIDDEN_STYLE = ` height:0 !important; @@ -60,10 +62,10 @@ function calculateNodeStyling(targetElement: Element): NodeStyle { return { contextStyle, paddingSize, borderSize, boxSizing } } -export default function calcTextareaHeight( - targetElement: HTMLInputElement, +export function calcTextareaHeight( + targetElement: HTMLTextAreaElement, minRows = 1, - maxRows = null + maxRows?: number ): TextAreaHeight { if (!hiddenTextarea) { hiddenTextarea = document.createElement('textarea') @@ -88,7 +90,7 @@ export default function calcTextareaHeight( hiddenTextarea.value = '' const singleRowHeight = hiddenTextarea.scrollHeight - paddingSize - if (minRows !== null) { + if (isNumber(minRows)) { let minHeight = singleRowHeight * minRows if (boxSizing === 'border-box') { minHeight = minHeight + paddingSize + borderSize @@ -96,7 +98,7 @@ export default function calcTextareaHeight( height = Math.max(minHeight, height) result.minHeight = `${minHeight}px` } - if (maxRows !== null) { + if (isNumber(maxRows)) { let maxHeight = singleRowHeight * maxRows if (boxSizing === 'border-box') { maxHeight = maxHeight + paddingSize + borderSize @@ -105,7 +107,7 @@ export default function calcTextareaHeight( } result.height = `${height}px` hiddenTextarea.parentNode?.removeChild(hiddenTextarea) - hiddenTextarea = null + hiddenTextarea = undefined return result } diff --git a/packages/components/input/src/input.ts b/packages/components/input/src/input.ts new file mode 100644 index 0000000000..54e4112c86 --- /dev/null +++ b/packages/components/input/src/input.ts @@ -0,0 +1,97 @@ +import { isString } from '@vue/shared' +import { useFormItemProps } from '@element-plus/hooks' +import { buildProps, definePropType, mutable } from '@element-plus/utils/props' +import { UPDATE_MODEL_EVENT } from '@element-plus/utils/constants' +import type { StyleValue } from '@element-plus/utils/types' +import type { ExtractPropTypes } from 'vue' + +type AutoSize = { minRows?: number; maxRows?: number } | boolean + +export const inputProps = buildProps({ + ...useFormItemProps, + modelValue: { + type: definePropType(undefined), + default: '', + }, + type: { + type: String, + default: 'text', + }, + resize: { + type: String, + values: ['none', 'both', 'horizontal', 'vertical'], + }, + autosize: { + type: definePropType([Boolean, Object]), + default: false, + }, + autocomplete: { + type: String, + default: 'off', + }, + placeholder: { + type: String, + }, + form: { + type: String, + default: '', + }, + readonly: { + type: Boolean, + default: false, + }, + clearable: { + type: Boolean, + default: false, + }, + showPassword: { + type: Boolean, + default: false, + }, + showWordLimit: { + type: Boolean, + default: false, + }, + suffixIcon: { + type: String, + default: '', + }, + prefixIcon: { + type: String, + default: '', + }, + label: { + type: String, + }, + tabindex: { + type: [Number, String], + }, + validateEvent: { + type: Boolean, + default: true, + }, + inputStyle: { + type: definePropType([Object, Array, String]), + default: () => mutable({} as const), + }, + maxlength: { + type: [Number, String], + }, +} as const) +export type InputProps = ExtractPropTypes + +export const inputEmits = { + [UPDATE_MODEL_EVENT]: (value: string) => isString(value), + input: (value: string) => isString(value), + change: (value: string) => isString(value), + focus: (evt: FocusEvent) => evt instanceof FocusEvent, + blur: (evt: FocusEvent) => evt instanceof FocusEvent, + clear: () => true, + mouseleave: (evt: MouseEvent) => evt instanceof MouseEvent, + mouseenter: (evt: MouseEvent) => evt instanceof MouseEvent, + keydown: (evt: KeyboardEvent) => evt instanceof KeyboardEvent, + compositionstart: (evt: CompositionEvent) => evt instanceof CompositionEvent, + compositionupdate: (evt: CompositionEvent) => evt instanceof CompositionEvent, + compositionend: (evt: CompositionEvent) => evt instanceof CompositionEvent, +} +export type InputEmits = typeof inputEmits diff --git a/packages/components/input/src/index.vue b/packages/components/input/src/input.vue similarity index 58% rename from packages/components/input/src/index.vue rename to packages/components/input/src/input.vue index 25ef7a8310..3e3eb88295 100644 --- a/packages/components/input/src/index.vue +++ b/packages/components/input/src/input.vue @@ -16,17 +16,18 @@ }, $attrs.class, ]" - :style="$attrs.style" + :style="containerStyle" @mouseenter="onMouseEnter" @mouseleave="onMouseLeave" > + - - {{ textLength }}/{{ maxlength }} + + +