@props([ 'name' => 'otp', 'length' => 6, 'mode' => 'numeric', // numeric | alphanumeric 'size' => 'md', // xs | sm | md | lg | xl 'value' => '', 'disabled' => false, 'centered' => false, ]) @php $size = in_array($size, ['xs', 'sm', 'md', 'lg', 'xl'], true) ? $size : 'md'; /** Fixed cell sizes (flex / wrap layout) */ $fixedSizeClasses = [ 'xs' => 'h-9 w-9 text-sm rounded-lg sm:h-10 sm:w-10 sm:rounded-xl', 'sm' => 'h-10 w-10 text-sm rounded-lg sm:h-11 sm:w-11 sm:rounded-xl', 'md' => 'h-10 w-10 text-base rounded-xl sm:h-11 sm:w-11 md:h-12 md:w-12', 'lg' => 'h-10 w-10 text-base rounded-xl sm:h-12 sm:w-12 md:h-14 md:w-14 lg:h-16 lg:w-16 lg:text-2xl', 'xl' => 'h-11 w-11 text-lg rounded-xl sm:h-14 sm:w-14 md:h-16 md:w-16 lg:h-[4.5rem] lg:w-[4.5rem] lg:text-3xl', ]; /** Fluid cells (grid layout — scale with container width, cap height per size) */ $fluidSizeClasses = [ 'xs' => 'max-h-9 text-sm rounded-lg sm:max-h-10 sm:rounded-xl', 'sm' => 'max-h-10 text-sm rounded-lg sm:max-h-11 sm:rounded-xl', 'md' => 'max-h-10 text-base rounded-xl sm:max-h-11 md:max-h-12', 'lg' => 'max-h-10 text-base rounded-xl sm:max-h-12 sm:text-lg md:max-h-14 md:text-xl lg:max-h-16 lg:text-2xl sm:rounded-2xl', 'xl' => 'max-h-11 text-lg rounded-xl sm:max-h-14 md:max-h-16 lg:max-h-[4.5rem] lg:text-3xl sm:rounded-2xl', ]; $gapClasses = [ 'xs' => 'gap-1 sm:gap-1.5 md:gap-2', 'sm' => 'gap-1 sm:gap-1.5 md:gap-2', 'md' => 'gap-1.5 sm:gap-2 md:gap-2.5', 'lg' => 'gap-1.5 sm:gap-2 md:gap-2.5 lg:gap-3', 'xl' => 'gap-2 sm:gap-2.5 md:gap-3 lg:gap-3.5', ]; $groupGap = $gapClasses[$size]; $gridColsClasses = [ 1 => 'grid-cols-1', 2 => 'grid-cols-2', 3 => 'grid-cols-3', 4 => 'grid-cols-4', 5 => 'grid-cols-5', 6 => 'grid-cols-6', 7 => 'grid-cols-7', 8 => 'grid-cols-8', 9 => 'grid-cols-9', 10 => 'grid-cols-10', 11 => 'grid-cols-11', 12 => 'grid-cols-12', ]; $gridCols = $gridColsClasses[max(1, min(12, (int) $length))] ?? 'grid-cols-6'; $fieldBase = 'otp-field border border-border bg-card text-center font-semibold tracking-widest text-foreground shadow-sm outline-none transition-all duration-200 placeholder:font-normal placeholder:text-muted-foreground/35 hover:border-brand/35 focus:border-brand focus:bg-card focus:ring-4 focus:ring-ring/15 dark:focus:ring-ring/25'; if ($centered) { $inputClasses = trim(implode(' ', [ $fieldBase, $fluidSizeClasses[$size], 'aspect-square h-auto w-full min-h-0 min-w-0', ])); } else { $inputClasses = trim($fieldBase . ' shrink-0 ' . $fixedSizeClasses[$size]); } @endphp
merge(['class' => trim('relative ' . ($centered ? 'w-full min-w-0' : ''))]) }} data-otp-field x-data="otpFieldComponent({ length: {{ $length }}, mode: '{{ $mode }}', initialValue: '{{ $value }}' })" >
$centered, $gridCols => $centered, 'flex flex-nowrap items-center justify-center' => ! $centered, ]) x-ref="otpFieldGroup" >
@once @push('before-app-js') @vite(['resources/js/components/otp-input.js']) @endpush @endonce