// Utils import { formatNumber } from './utils'; import { isIOS } from '../utils/validate/system'; import { preventDefault } from '../utils/dom/event'; import { resetScroll } from '../utils/dom/reset-scroll'; import { createNamespace, isObject, isDef, addUnit } from '../utils'; // Components import Icon from '../icon'; import Cell from '../cell'; import { cellProps } from '../cell/shared'; const [createComponent, bem] = createNamespace('field'); export default createComponent({ inheritAttrs: false, props: { ...cellProps, error: Boolean, disabled: Boolean, readonly: Boolean, autosize: [Boolean, Object], leftIcon: String, rightIcon: String, clearable: Boolean, formatter: Function, maxlength: [Number, String], labelWidth: [Number, String], labelClass: null, labelAlign: String, inputAlign: String, placeholder: String, errorMessage: String, errorMessageAlign: String, showWordLimit: Boolean, type: { type: String, default: 'text', }, }, data() { return { focused: false, }; }, watch: { value() { this.$nextTick(this.adjustSize); }, }, mounted() { this.format(); this.$nextTick(this.adjustSize); }, computed: { showClear() { return ( this.clearable && this.focused && this.value !== '' && isDef(this.value) && !this.readonly ); }, listeners() { const listeners = { ...this.$listeners, input: this.onInput, keypress: this.onKeypress, focus: this.onFocus, blur: this.onBlur, }; delete listeners.click; return listeners; }, labelStyle() { const { labelWidth } = this; if (labelWidth) { return { width: addUnit(labelWidth) }; } }, }, methods: { // @exposed-api focus() { if (this.$refs.input) { this.$refs.input.focus(); } }, // @exposed-api blur() { if (this.$refs.input) { this.$refs.input.blur(); } }, format(target = this.$refs.input) { if (!target) { return; } let { value } = target; const { maxlength } = this; // native maxlength not work when type is number if (isDef(maxlength) && value.length > maxlength) { value = value.slice(0, maxlength); target.value = value; } if (this.type === 'number' || this.type === 'digit') { const originValue = value; const allowDot = this.type === 'number'; value = formatNumber(value, allowDot); if (value !== originValue) { target.value = value; } } if (this.formatter) { const originValue = value; value = this.formatter(value); if (value !== originValue) { target.value = value; } } return value; }, onInput(event) { // not update v-model when composing if (event.target.composing) { return; } this.$emit('input', this.format(event.target)); }, onFocus(event) { this.focused = true; this.$emit('focus', event); // hack for safari /* istanbul ignore if */ if (this.readonly) { this.blur(); } }, onBlur(event) { this.focused = false; this.$emit('blur', event); resetScroll(); }, onClick(event) { this.$emit('click', event); }, onClickLeftIcon(event) { this.$emit('click-left-icon', event); }, onClickRightIcon(event) { this.$emit('click-right-icon', event); }, onClear(event) { preventDefault(event); this.$emit('input', ''); this.$emit('clear', event); }, onKeypress(event) { // trigger blur after click keyboard search button /* istanbul ignore next */ if (this.type === 'search' && event.keyCode === 13) { this.blur(); } this.$emit('keypress', event); }, adjustSize() { const { input } = this.$refs; if (!(this.type === 'textarea' && this.autosize) || !input) { return; } input.style.height = 'auto'; let height = input.scrollHeight; if (isObject(this.autosize)) { const { maxHeight, minHeight } = this.autosize; if (maxHeight) { height = Math.min(height, maxHeight); } if (minHeight) { height = Math.max(height, minHeight); } } if (height) { input.style.height = height + 'px'; } }, genInput() { const { type } = this; const inputSlot = this.slots('input'); if (inputSlot) { return