feat(PinInput): add autofocus / autofocus-delay props

Resolves #3717
This commit is contained in:
Benjamin Canac
2025-03-28 18:52:39 +01:00
parent f05dbd26d1
commit 0456670dac
2 changed files with 31 additions and 2 deletions

View File

@@ -177,6 +177,12 @@ props:
:component-emits :component-emits
When accessing the component via a template ref, you can use the following:
| Name | Type |
| ---- | ---- |
| `inputsRef`{lang="ts-type"} | `Ref<ComponentPublicInstance[]>`{lang="ts-type"} |
## Theme ## Theme
:component-theme :component-theme

View File

@@ -37,6 +37,8 @@ export interface PinInputProps extends Pick<PinInputRootProps, 'defaultValue' |
* @defaultValue 5 * @defaultValue 5
*/ */
length?: number | string length?: number | string
autofocus?: boolean
autofocusDelay?: number
highlight?: boolean highlight?: boolean
class?: any class?: any
ui?: PartialString<typeof pinInput.slots> ui?: PartialString<typeof pinInput.slots>
@@ -50,7 +52,8 @@ export type PinInputEmits = PinInputRootEmits & {
</script> </script>
<script setup lang="ts"> <script setup lang="ts">
import { ref, computed } from 'vue' import type { ComponentPublicInstance } from 'vue'
import { ref, computed, onMounted } from 'vue'
import { PinInputInput, PinInputRoot, useForwardPropsEmits } from 'reka-ui' import { PinInputInput, PinInputRoot, useForwardPropsEmits } from 'reka-ui'
import { reactivePick } from '@vueuse/core' import { reactivePick } from '@vueuse/core'
import { useFormField } from '../composables/useFormField' import { useFormField } from '../composables/useFormField'
@@ -58,7 +61,8 @@ import { looseToNumber } from '../utils'
const props = withDefaults(defineProps<PinInputProps>(), { const props = withDefaults(defineProps<PinInputProps>(), {
type: 'text', type: 'text',
length: 5 length: 5,
autofocusDelay: 0
}) })
const emits = defineEmits<PinInputEmits>() const emits = defineEmits<PinInputEmits>()
@@ -72,6 +76,14 @@ const ui = computed(() => pinInput({
highlight: highlight.value highlight: highlight.value
})) }))
const inputsRef = ref<ComponentPublicInstance[]>([])
function autoFocus() {
if (props.autofocus) {
inputsRef.value[0]?.$el?.focus()
}
}
const completed = ref(false) const completed = ref(false)
function onComplete(value: string[]) { function onComplete(value: string[]) {
// @ts-expect-error - 'target' does not exist in type 'EventInit' // @ts-expect-error - 'target' does not exist in type 'EventInit'
@@ -86,6 +98,16 @@ function onBlur(event: FocusEvent) {
emitFormBlur() emitFormBlur()
} }
} }
defineExpose({
inputsRef
})
onMounted(() => {
setTimeout(() => {
autoFocus()
}, props.autofocusDelay)
})
</script> </script>
<template> <template>
@@ -100,6 +122,7 @@ function onBlur(event: FocusEvent) {
<PinInputInput <PinInputInput
v-for="(ids, index) in looseToNumber(props.length)" v-for="(ids, index) in looseToNumber(props.length)"
:key="ids" :key="ids"
:ref="el => (inputsRef[index] = el as ComponentPublicInstance)"
:index="index" :index="index"
:class="ui.base({ class: props.ui?.base })" :class="ui.base({ class: props.ui?.base })"
:disabled="disabled" :disabled="disabled"