fix(components): [input] lose focus when click suffix icon (#13264)

* feat(hooks): add useFocusController

* fix(components): [input] lose focus when click suffix icon

closed #13153, #13159

* refactor(hooks): use-focus-controller

* test: fix test

* test: update

* fix(theme-chalk): [input] add cursor style to the wrapper
This commit is contained in:
qiang
2023-07-13 16:41:18 +08:00
committed by GitHub
parent a1dd70eead
commit 704399fadd
5 changed files with 140 additions and 21 deletions

View File

@ -15,10 +15,10 @@
<slot name="prepend" />
</div>
<div :class="wrapperKls">
<div ref="wrapperRef" :class="wrapperKls">
<!-- prefix slot -->
<span v-if="$slots.prefix || prefixIcon" :class="nsInput.e('prefix')">
<span :class="nsInput.e('prefix-inner')" @click="focus">
<span :class="nsInput.e('prefix-inner')">
<slot name="prefix" />
<el-icon v-if="prefixIcon" :class="nsInput.e('icon')">
<component :is="prefixIcon" />
@ -54,7 +54,7 @@
<!-- suffix slot -->
<span v-if="suffixVisible" :class="nsInput.e('suffix')">
<span :class="nsInput.e('suffix-inner')" @click="focus">
<span :class="nsInput.e('suffix-inner')">
<template
v-if="!showClear || !showPwdVisible || !isWordLimitVisible"
>
@ -172,7 +172,12 @@ import {
isKorean,
isObject,
} from '@element-plus/utils'
import { useAttrs, useCursor, useNamespace } from '@element-plus/hooks'
import {
useAttrs,
useCursor,
useFocusController,
useNamespace,
} from '@element-plus/hooks'
import { UPDATE_MODEL_EVENT } from '@element-plus/constants'
import { calcTextareaHeight } from './utils'
import { inputEmits, inputProps } from './input'
@ -220,7 +225,7 @@ const containerKls = computed(() => [
const wrapperKls = computed(() => [
nsInput.e('wrapper'),
nsInput.is('focus', focused.value),
nsInput.is('focus', isFocused.value),
])
const attrs = useAttrs({
@ -240,7 +245,6 @@ const nsTextarea = useNamespace('textarea')
const input = shallowRef<HTMLInputElement>()
const textarea = shallowRef<HTMLTextAreaElement>()
const focused = ref(false)
const hovering = ref(false)
const isComposing = ref(false)
const passwordVisible = ref(false)
@ -249,6 +253,17 @@ const textareaCalcStyle = shallowRef(props.inputStyle)
const _ref = computed(() => input.value || textarea.value)
const { wrapperRef, isFocused, handleFocus, handleBlur } = useFocusController(
_ref,
{
afterBlur() {
if (props.validateEvent) {
formItem?.validate?.('blur').catch((err) => debugWarn(err))
}
},
}
)
const needStatusIcon = computed(() => form?.statusIcon ?? false)
const validateState = computed(() => formItem?.validateState || '')
const validateIcon = computed(
@ -275,7 +290,7 @@ const showClear = computed(
!inputDisabled.value &&
!props.readonly &&
!!nativeInputValue.value &&
(focused.value || hovering.value)
(isFocused.value || hovering.value)
)
const showPwdVisible = computed(
() =>
@ -283,7 +298,7 @@ const showPwdVisible = computed(
!inputDisabled.value &&
!props.readonly &&
!!nativeInputValue.value &&
(!!nativeInputValue.value || focused.value)
(!!nativeInputValue.value || isFocused.value)
)
const isWordLimitVisible = computed(
() =>
@ -445,19 +460,6 @@ const focus = async () => {
const blur = () => _ref.value?.blur()
const handleFocus = (event: FocusEvent) => {
focused.value = true
emit('focus', event)
}
const handleBlur = (event: FocusEvent) => {
focused.value = false
emit('blur', event)
if (props.validateEvent) {
formItem?.validate?.('blur').catch((err) => debugWarn(err))
}
}
const handleMouseLeave = (evt: MouseEvent) => {
hovering.value = false
emit('mouseleave', evt)