CluPilotCloud/resources/views/components/ui/otp-input.blade.php

35 lines
1.4 KiB
PHP

@props([
'name' => 'code',
'length' => 6,
'label' => null,
])
{{-- Segmented one-time-code input. Alpine keeps the visible segments; a hidden
field carries the joined value for the native form POST or, inside a
Livewire form, for wire:model. wire:model needs both the attribute (so
Livewire's directive scan finds it — hence spreading $attributes here) and
a real "input" event: Alpine's :value binding only ever writes the DOM
property, which fires nothing on its own. --}}
<div
x-data="otpInput({ length: {{ (int) $length }} })"
class="flex gap-2"
role="group"
@if ($label) aria-label="{{ $label }}" @endif
>
<input type="hidden" name="{{ $name }}" :value="value" x-effect="$el.dispatchEvent(new Event('input', { bubbles: true }))" {{ $attributes }}>
<template x-for="(digit, i) in digits" :key="i">
<input
type="text"
inputmode="numeric"
autocomplete="one-time-code"
maxlength="1"
class="size-12 rounded border border-line bg-surface text-center font-mono text-lg text-ink"
:aria-label="`{{ $label ?? __('auth.otp_digit') }} ${i + 1}`"
x-model="digits[i]"
x-ref="cell"
@input="onInput(i, $event)"
@keydown.backspace="onBackspace(i, $event)"
@paste.prevent="onPaste($event)"
>
</template>
</div>