Initial Commit
This commit is contained in:
138
resources/views/components/input-otp.blade.php
Normal file
138
resources/views/components/input-otp.blade.php
Normal file
@@ -0,0 +1,138 @@
|
||||
@props([
|
||||
'digits' => 6,
|
||||
'name' => 'code',
|
||||
])
|
||||
|
||||
<div
|
||||
@focus-2fa-auth-code.window="$refs.input1?.focus()"
|
||||
@clear-2fa-auth-code.window="clearAll()"
|
||||
class="relative"
|
||||
x-data="{
|
||||
totalDigits: @js($digits),
|
||||
digitIndices: @js(range(1, $digits)),
|
||||
init() {
|
||||
$nextTick(() => {
|
||||
this.$refs.input1?.focus();
|
||||
});
|
||||
},
|
||||
getInput(index) {
|
||||
return this.$refs['input' + index];
|
||||
},
|
||||
setValue(index, value) {
|
||||
this.getInput(index).value = value;
|
||||
},
|
||||
getCode() {
|
||||
return this.digitIndices
|
||||
.map(i => this.getInput(i).value)
|
||||
.join('');
|
||||
},
|
||||
updateHiddenField() {
|
||||
this.$refs.code.value = this.getCode();
|
||||
this.$refs.code.dispatchEvent(new Event('input', { bubbles: true }));
|
||||
this.$refs.code.dispatchEvent(new Event('change', { bubbles: true }));
|
||||
},
|
||||
handleNumberKey(index, key) {
|
||||
this.setValue(index, key);
|
||||
|
||||
if (index < this.totalDigits) {
|
||||
this.getInput(index + 1).focus();
|
||||
}
|
||||
|
||||
$nextTick(() => {
|
||||
this.updateHiddenField();
|
||||
});
|
||||
},
|
||||
handleBackspace(index) {
|
||||
const currentInput = this.getInput(index);
|
||||
|
||||
if (currentInput.value !== '') {
|
||||
currentInput.value = '';
|
||||
this.updateHiddenField();
|
||||
return;
|
||||
}
|
||||
|
||||
if (index <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
const previousInput = this.getInput(index - 1);
|
||||
|
||||
previousInput.value = '';
|
||||
previousInput.focus();
|
||||
|
||||
this.updateHiddenField();
|
||||
},
|
||||
handleKeyDown(index, event) {
|
||||
const key = event.key;
|
||||
|
||||
if (/^[0-9]$/.test(key)) {
|
||||
event.preventDefault();
|
||||
this.handleNumberKey(index, key);
|
||||
return;
|
||||
}
|
||||
|
||||
if (key === 'Backspace') {
|
||||
event.preventDefault();
|
||||
this.handleBackspace(index);
|
||||
return;
|
||||
}
|
||||
},
|
||||
handlePaste(event) {
|
||||
event.preventDefault();
|
||||
|
||||
const pastedText = (event.clipboardData || window.clipboardData).getData('text');
|
||||
const numericOnly = pastedText.replace(/[^0-9]/g, '');
|
||||
const digitsToFill = Math.min(numericOnly.length, this.totalDigits);
|
||||
|
||||
this.digitIndices
|
||||
.slice(0, digitsToFill)
|
||||
.forEach(index => {
|
||||
this.setValue(index, numericOnly[index - 1]);
|
||||
});
|
||||
|
||||
if (numericOnly.length >= this.totalDigits) {
|
||||
this.updateHiddenField();
|
||||
}
|
||||
},
|
||||
clearAll() {
|
||||
this.digitIndices.forEach(index => {
|
||||
this.setValue(index, '');
|
||||
});
|
||||
|
||||
this.$refs.code.value = '';
|
||||
this.$refs.input1?.focus();
|
||||
}
|
||||
}"
|
||||
>
|
||||
<div class="flex items-center">
|
||||
@for ($x = 1; $x <= $digits; $x++)
|
||||
<input
|
||||
x-ref="input{{ $x }}"
|
||||
type="text"
|
||||
inputmode="numeric"
|
||||
pattern="[0-9]"
|
||||
maxlength="1"
|
||||
autocomplete="off"
|
||||
@paste="handlePaste"
|
||||
@keydown="handleKeyDown({{ $x }}, $event)"
|
||||
@focus="$el.select()"
|
||||
@input="$el.value = $el.value.replace(/[^0-9]/g, '').slice(0, 1)"
|
||||
@class([
|
||||
'flex size-10 items-center justify-center border border-zinc-300 bg-accent-foreground text-center text-sm font-medium text-accent-content transition-colors focus:border-accent focus:border-2 focus:outline-none focus:relative focus:z-10 dark:border-zinc-700 dark:focus:border-accent',
|
||||
'rounded-l-md' => $x === 1,
|
||||
'rounded-r-md' => $x === $digits,
|
||||
'-ml-px' => $x > 1,
|
||||
])
|
||||
/>
|
||||
@endfor
|
||||
</div>
|
||||
|
||||
<input
|
||||
{{ $attributes->except(['digits']) }}
|
||||
type="hidden"
|
||||
x-ref="code"
|
||||
name="{{ $name }}"
|
||||
minlength="{{ $digits }}"
|
||||
maxlength="{{ $digits }}"
|
||||
/>
|
||||
</div>
|
||||
Reference in New Issue
Block a user