import './echo'; // Segmented OTP input behaviour (used by ). Alpine ships with // Livewire; register on alpine:init. document.addEventListener('alpine:init', () => { window.Alpine.data('otpInput', ({ length = 6 } = {}) => ({ length, digits: Array(length).fill(''), get value() { return this.digits.join(''); }, cells() { return this.$root.querySelectorAll('input[inputmode="numeric"]'); }, focusCell(i) { const cell = this.cells()[i]; if (cell) cell.focus(); }, onInput(i, e) { const digit = e.target.value.replace(/\D/g, '').slice(-1); this.digits[i] = digit; if (digit && i < this.length - 1) this.focusCell(i + 1); this.maybeSubmit(); }, onBackspace(i) { if (!this.digits[i] && i > 0) this.focusCell(i - 1); }, onPaste(e) { const text = (e.clipboardData.getData('text') || '').replace(/\D/g, '').slice(0, this.length); for (let i = 0; i < this.length; i++) this.digits[i] = text[i] || ''; this.focusCell(Math.min(text.length, this.length - 1)); this.maybeSubmit(); }, maybeSubmit() { if (this.value.length === this.length) { // Wait for Alpine to flush :value into the hidden input, otherwise // requestSubmit() can post a stale/short code. this.$nextTick(() => this.$root.closest('form')?.requestSubmit()); } }, })); });