diff --git a/packages/vuetify/src/components/VField/VField.tsx b/packages/vuetify/src/components/VField/VField.tsx index b12b064782e..4288e46d4b0 100644 --- a/packages/vuetify/src/components/VField/VField.tsx +++ b/packages/vuetify/src/components/VField/VField.tsx @@ -211,15 +211,6 @@ export const VField = genericComponent( } } - function onKeydownClear (e: KeyboardEvent) { - if (e.key !== 'Enter' && e.key !== ' ') return - - e.preventDefault() - e.stopPropagation() - - props['onClick:clear']?.(new MouseEvent('click')) - } - useRender(() => { const isOutlined = props.variant === 'outlined' const hasPrepend = !!(slots['prepend-inner'] || props.prependInnerIcon) @@ -282,7 +273,10 @@ export const VField = genericComponent( { hasPrepend && (
{ props.prependInnerIcon && ( - + )} { slots['prepend-inner']?.(slotProps.value) } @@ -342,7 +336,6 @@ export const VField = genericComponent( ? slots.clear({ ...slotProps.value, props: { - onKeydown: onKeydownClear, onFocus: focus, onBlur: blur, onClick: props['onClick:clear'], @@ -351,7 +344,6 @@ export const VField = genericComponent( : ( @@ -366,7 +358,10 @@ export const VField = genericComponent( { slots['append-inner']?.(slotProps.value) } { props.appendInnerIcon && ( - + )}
)} diff --git a/packages/vuetify/src/components/VInput/InputIcon.tsx b/packages/vuetify/src/components/VInput/InputIcon.tsx index de317956e76..0ae9c6e87e5 100644 --- a/packages/vuetify/src/components/VInput/InputIcon.tsx +++ b/packages/vuetify/src/components/VInput/InputIcon.tsx @@ -4,12 +4,15 @@ import { VIcon } from '@/components/VIcon' // Composables import { useLocale } from '@/composables/locale' +// Utilities +import { callEvent } from '@/util' + // Types import type { IconValue } from '@/composables/icons' +import type { EventProp } from '@/util' type names = 'clear' | 'prepend' | 'append' | 'appendInner' | 'prependInner' -type EventProp any> = T | T[] type InputIconProps = { label: string | undefined } & { @@ -31,7 +34,16 @@ export function useInputIcon> (prop appendInner: 'appendAction', clear: 'clear', }[name] - const listener = props[`onClick:${name}`] + const listener = props[`onClick:${name}`] as EventProp | undefined + + function onKeydown (e: KeyboardEvent) { + if (e.key !== 'Enter' && e.key !== ' ') return + + e.preventDefault() + e.stopPropagation() + callEvent(listener, new PointerEvent('click', e)) + } + const label = listener && localeKey ? t(`$vuetify.input.${localeKey}`, props.label ?? '') : undefined @@ -41,6 +53,7 @@ export function useInputIcon> (prop icon={ props[`${name}Icon`] } aria-label={ label } onClick={ listener } + onKeydown={ onKeydown } /> ) } diff --git a/packages/vuetify/src/util/helpers.ts b/packages/vuetify/src/util/helpers.ts index bd8eddea62e..01e719fde54 100644 --- a/packages/vuetify/src/util/helpers.ts +++ b/packages/vuetify/src/util/helpers.ts @@ -616,6 +616,7 @@ export function eventName (propName: string) { return propName[2].toLowerCase() + propName.slice(3) } +// TODO: this should be an array but vue's types don't accept arrays: vuejs/core#8025 export type EventProp void> = F export const EventProp = () => [Function, Array] as PropType> @@ -624,7 +625,7 @@ export function hasEvent (props: Record, name: string) { return !!(props[name] || props[`${name}Once`] || props[`${name}Capture`] || props[`${name}OnceCapture`] || props[`${name}CaptureOnce`]) } -export function callEvent (handler: EventProp | undefined, ...args: T) { +export function callEvent (handler: EventProp | EventProp[] | undefined, ...args: T) { if (Array.isArray(handler)) { for (const h of handler) { h(...args)