{{-- ShiftBridge Input Component Usage: Props: - name: string (required) - label: string - type: string (text, password, email, number, tel, url, date, time, datetime-local, color, search) - placeholder: string - value: string - helper: string (helper text below input) - error: string (error message) - state: string (default, error, success) - size: string (sm, md, lg) - disabled: boolean - readonly: boolean - required: boolean - autofocus: boolean - icon: string (Lucide icon name) - iconPosition: string (left, right) - id: string (defaults to name) - class: string (additional CSS classes) --}} @props([ 'name' => null, 'label' => null, 'type' => 'text', 'placeholder' => null, 'value' => null, 'helper' => null, 'error' => null, 'state' => 'default', 'size' => 'md', 'disabled' => false, 'readonly' => false, 'required' => false, 'autofocus' => false, 'icon' => null, 'iconPosition' => 'left', 'id' => null, ]) @php // Auto-detect error state from $error prop or $errors bag $hasError = $error || ($name && $errors && $errors->has($name)); if ($hasError) { $state = 'error'; } // ID defaults to name $inputId = $id ?? $name; // Size classes $sizeClasses = match($size) { 'sm' => 'px-2.5 py-1.5 text-sm', 'md' => 'px-3 py-2 text-sm', 'lg' => 'px-4 py-3 text-base', default => 'px-3 py-2 text-sm', }; // State classes $stateClasses = match($state) { 'error' => 'border-red-500 focus:border-red-500 focus:ring-red-500/20 bg-white text-red-900 placeholder-red-300', 'success' => 'border-green-500 focus:border-green-500 focus:ring-green-500/20 bg-white text-green-900', default => 'border-[var(--sb-border)] focus:border-[var(--sb-primary)] focus:ring-[var(--sb-primary)]/20 bg-white text-[var(--sb-text-primary)]', }; // Icon sizing $iconSize = match($size) { 'sm' => 'w-4 h-4', 'md' => 'w-5 h-5', 'lg' => 'w-5 h-5', default => 'w-5 h-5', }; // Icon padding adjustment $iconPadding = match($size) { 'sm' => $iconPosition === 'left' ? 'pl-8' : 'pr-8', 'md' => $iconPosition === 'left' ? 'pl-10' : 'pr-10', 'lg' => $iconPosition === 'left' ? 'pl-11' : 'pr-11', default => $iconPosition === 'left' ? 'pl-10' : 'pr-10', }; // Icon positioning classes $iconPositionClasses = match($size) { 'sm' => $iconPosition === 'left' ? 'left-2.5' : 'right-2.5', 'md' => $iconPosition === 'left' ? 'left-3' : 'right-3', 'lg' => $iconPosition === 'left' ? 'left-3.5' : 'right-3.5', default => $iconPosition === 'left' ? 'left-3' : 'right-3', }; // Base input classes $inputClasses = implode(' ', [ 'block w-full rounded-md transition-all duration-150', 'border focus:outline-none focus:ring-2', 'disabled:opacity-60 disabled:cursor-not-allowed disabled:bg-slate-100', 'read-only:bg-slate-50 read-only:cursor-default', $sizeClasses, $stateClasses, $icon ? $iconPadding : '', ]); // Label classes $labelClasses = 'block text-sm font-medium text-[var(--sb-text-secondary)] mb-1.5'; // Helper text classes $helperClasses = 'mt-1.5 text-xs text-[var(--sb-text-secondary)]'; // Error text classes $errorClasses = 'mt-1.5 text-xs text-red-600 flex items-center gap-1'; // Icon SVG mapping (Lucide icons) $iconSvg = match($icon) { 'search' => '', 'mail' => '', 'lock' => '', 'user' => '', 'phone' => '', 'dollar-sign' => '', 'percent' => '', 'calendar' => '', 'clock' => '', 'map-pin' => '', 'link' => '', 'file' => '', 'eye' => '', 'eye-off' => '', 'alert-circle' => '', 'check-circle' => '', default => null, }; @endphp
merge(['class' => 'w-full']) }}> {{-- Label --}} @if($label) @endif {{-- Input wrapper --}}
{{-- Left Icon --}} @if($icon && $iconPosition === 'left')
{!! $iconSvg !!}
@endif {{-- Input element --}} {{-- Right Icon --}} @if($icon && $iconPosition === 'right')
{!! $iconSvg !!}
@endif
{{-- Helper text --}} @if($helper && !$hasError)

{{ $helper }}

@endif {{-- Error message --}} @if($hasError)

{{ $error ?? ($errors && $name ? $errors->first($name) : '') }}

@endif