first commit
This commit is contained in:
63
resources/views/components/button/basic.blade.php
Normal file
63
resources/views/components/button/basic.blade.php
Normal file
@ -0,0 +1,63 @@
|
||||
@props([
|
||||
'type' => 'button', // Tipo de botón: button, submit, reset (solo para botones)
|
||||
'href' => null, // URL si es un enlace
|
||||
'route' => null, // URL si es un enlace
|
||||
'target' => '_self', // Target del enlace (_self, _blank, etc.)
|
||||
'label' => '', // Texto del botón
|
||||
'size' => 'md', // Tamaño: xs, sm, md, lg, xl
|
||||
'variant' => 'primary', // Color del botón (primary, secondary, success, danger, warning, info, dark)
|
||||
'labelStyle' => false, // Usa `btn-label-*`
|
||||
'outline' => false, // Habilitar estilo outline
|
||||
'textStyle' => false, // Habilitar estilo de texto
|
||||
'rounded' => false, // Habilitar bordes redondeados
|
||||
'block' => false, // Convertir en botón de ancho completo
|
||||
'waves' => true, // Habilitar efecto Vuexy (waves-effect)
|
||||
'icon' => '', // Clases del ícono (ej: 'ti ti-home')
|
||||
'iconOnly' => false, // Botón solo con ícono
|
||||
'iconPosition' => 'left', // Posición del ícono: left, right
|
||||
'active' => false, // Activar estado de botón
|
||||
'disabled' => false, // Deshabilitar botón
|
||||
'attributes' => new \Illuminate\View\ComponentAttributeBag([]), // Atributos adicionales
|
||||
])
|
||||
|
||||
@php
|
||||
// Generar clases dinámicas
|
||||
$classes = [
|
||||
'btn',
|
||||
$labelStyle ? "btn-label-$variant" : '',
|
||||
$outline ? "btn-outline-$variant" : '',
|
||||
$textStyle ? "btn-text-$variant" : '',
|
||||
$labelStyle || $outline || $textStyle ? '' : "btn-$variant",
|
||||
$rounded ? 'rounded-pill' : '',
|
||||
$block ? 'd-block w-100' : '',
|
||||
$waves ? 'waves-effect' : '',
|
||||
$size !== 'md' ? "btn-$size" : '',
|
||||
$active ? 'active' : '',
|
||||
$disabled ? 'disabled' : '',
|
||||
$iconOnly ? 'btn-icon' : '',
|
||||
];
|
||||
@endphp
|
||||
|
||||
@if ($href || $route)
|
||||
{{-- Si es un enlace --}}
|
||||
<a {{ $attributes->merge(['class' => implode(' ', array_filter($classes)), 'href' => ($href?? route($route)), 'target' => $target]) }}>
|
||||
@if ($icon && $iconPosition === 'left')
|
||||
<i class="{{ $icon }} {{ $label ? 'me-2' : '' }}"></i>
|
||||
@endif
|
||||
{{ $label }}
|
||||
@if ($icon && $iconPosition === 'right')
|
||||
<i class="{{ $icon }} {{ $label ? 'ms-2' : '' }}"></i>
|
||||
@endif
|
||||
</a>
|
||||
@else
|
||||
{{-- Si es un botón --}}
|
||||
<button type="{{ $type }}" {{ $attributes->merge(['class' => implode(' ', array_filter($classes))]) }}>
|
||||
@if ($icon && $iconPosition === 'left')
|
||||
<i class="{{ $icon }} {{ $label ? 'me-2' : '' }}"></i>
|
||||
@endif
|
||||
{{ $label }}
|
||||
@if ($icon && $iconPosition === 'right')
|
||||
<i class="{{ $icon }} {{ $label ? 'ms-2' : '' }}"></i>
|
||||
@endif
|
||||
</button>
|
||||
@endif
|
46
resources/views/components/button/group.blade.php
Normal file
46
resources/views/components/button/group.blade.php
Normal file
@ -0,0 +1,46 @@
|
||||
@props([
|
||||
'buttons' => [], // Lista de botones en formato de array
|
||||
'toolbar' => false, // Si es un grupo de botones estilo "toolbar"
|
||||
'nesting' => false, // Si hay un grupo anidado con dropdown
|
||||
'class' => '', // Clases adicionales
|
||||
])
|
||||
|
||||
@php
|
||||
// Determinar si es un toolbar o un grupo simple
|
||||
$groupClass = $toolbar ? 'btn-toolbar' : 'btn-group';
|
||||
@endphp
|
||||
|
||||
<div class="{{ $groupClass }} {{ $class }}" role="group" aria-label="Button group">
|
||||
@foreach($buttons as $button)
|
||||
@if(isset($button['dropdown']))
|
||||
{{-- Botón con dropdown anidado --}}
|
||||
<div class="btn-group" role="group">
|
||||
<button id="btnGroupDrop{{ $loop->index }}" type="button" class="btn {{ $button['variant'] ?? 'btn-outline-secondary' }} dropdown-toggle waves-effect" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
@if(isset($button['icon'])) <i class="{{ $button['icon'] }} ti-md"></i> @endif
|
||||
<span class="d-none d-sm-block">{{ $button['label'] ?? 'Dropdown' }}</span>
|
||||
</button>
|
||||
<div class="dropdown-menu" aria-labelledby="btnGroupDrop{{ $loop->index }}">
|
||||
@foreach($button['dropdown'] as $dropdownItem)
|
||||
<a class="dropdown-item waves-effect" href="{{ $dropdownItem['href'] ?? 'javascript:void(0);' }}">
|
||||
{{ $dropdownItem['label'] }}
|
||||
</a>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
@else
|
||||
{{-- Botón normal o ancla --}}
|
||||
@if(isset($button['href']))
|
||||
<a href="{{ route($button['href']) }}" class="btn {{ $button['variant'] ?? 'btn-outline-secondary' }} waves-effect">
|
||||
@if(isset($button['icon'])) <i class="{{ $button['icon'] }} ti-md"></i> @endif
|
||||
{{ $button['label'] }}
|
||||
</a>
|
||||
@else
|
||||
<button type="{{ $button['type'] ?? 'button' }}" class="btn {{ $button['variant'] ?? 'btn-outline-secondary' }} waves-effect"
|
||||
{{ $button['disabled'] ?? false ? 'disabled' : '' }}>
|
||||
@if(isset($button['icon'])) <i class="{{ $button['icon'] }} ti-md"></i> @endif
|
||||
{{ $button['label'] }}
|
||||
</button>
|
||||
@endif
|
||||
@endif
|
||||
@endforeach
|
||||
</div>
|
30
resources/views/components/button/index-off-canvas.blade.php
Normal file
30
resources/views/components/button/index-off-canvas.blade.php
Normal file
@ -0,0 +1,30 @@
|
||||
@php
|
||||
use Illuminate\Support\Str;
|
||||
@endphp
|
||||
|
||||
@props([
|
||||
'label' => '',
|
||||
'tagName' => '',
|
||||
'icon' => 'ti ti-pencil-plus',
|
||||
])
|
||||
|
||||
@php
|
||||
$tagOffcanvas = ucfirst(Str::camel($tagName));
|
||||
$helperTag = Str::kebab($tagName);
|
||||
|
||||
$ariaControls = "'offcanvas{$tagOffcanvas}";
|
||||
$dataBsToggle = 'offcanvas';
|
||||
$dataBsTarget = "#offcanvas{$tagOffcanvas}";
|
||||
$onclick = "window.formHelpers['{$helperTag}'].reloadOffcanvas('create')";
|
||||
@endphp
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary waves-effect waves-light"
|
||||
tabindex="0"
|
||||
aria-controls='{{ $ariaControls }}'
|
||||
data-bs-toggle="{{ $dataBsToggle }}"
|
||||
data-bs-target="{{ $dataBsTarget }}"
|
||||
onclick="{!! $onclick !!}">
|
||||
<span class="ti-xs {{ $icon }} me-2"></span>{{ ucfirst($label) }}
|
||||
</button>
|
@ -0,0 +1,18 @@
|
||||
@props([
|
||||
'tagName' => '',
|
||||
'mode' => 'create',
|
||||
])
|
||||
|
||||
@php
|
||||
$helperTag = Str::kebab($tagName);
|
||||
|
||||
$onclick = "window.formHelpers['{$helperTag}'].reloadOffcanvas('reset')";
|
||||
@endphp
|
||||
|
||||
<div class="pt-3">
|
||||
<button type="submit" class="btn btn-submit waves-effect waves mr-3 mb-3"></button>
|
||||
<button type="reset" class="btn btn-reset mr-3 mb-3" onclick="{{ $onclick }}" data-bs-dismiss="offcanvas" aria-label="Close">Cancelar</button>
|
||||
</div>
|
||||
@if($mode == 'delete')
|
||||
<x-vuexy-admin::form.checkbox model="confirmDeletion" label="Confirmar eliminación" parentClass="confirm-deletion" data-always-enabled switch switch-type="square" color="danger" size="lg" with-icon />
|
||||
@endif
|
76
resources/views/components/card/basic.blade.php
Normal file
76
resources/views/components/card/basic.blade.php
Normal file
@ -0,0 +1,76 @@
|
||||
@props([
|
||||
'title' => '',
|
||||
'subtitle' => '',
|
||||
'image' => null,
|
||||
'bgColor' => '', // primary, secondary, success, danger, etc.
|
||||
'borderColor' => '', // primary, secondary, etc.
|
||||
'textColor' => 'text-dark',
|
||||
'shadow' => true, // true / false
|
||||
'dropdown' => [], // Opciones para el menú
|
||||
'footer' => '',
|
||||
'footerClass' => '', // Clase CSS personalizada para el footer
|
||||
'footerAlign' => 'start', // Alineación: start, center, end
|
||||
'footerButtons' => [], // Botones de acción
|
||||
'class' => 'mb-6',
|
||||
])
|
||||
|
||||
@php
|
||||
$cardClass = 'card ' . ($shadow ? '' : 'shadow-none') . ' ' . ($bgColor ? "bg-$bgColor text-white" : '') . ' ' . ($borderColor ? "border border-$borderColor" : '') . " $class";
|
||||
$footerAlignment = match ($footerAlign) {
|
||||
'center' => 'text-center',
|
||||
'end' => 'text-end',
|
||||
default => 'text-start'
|
||||
};
|
||||
@endphp
|
||||
|
||||
<div class="{{ $cardClass }}">
|
||||
@if ($image)
|
||||
<img class="card-img-top" src="{{ $image }}" alt="Card image">
|
||||
@endif
|
||||
|
||||
@if ($title || $subtitle || $dropdown)
|
||||
<div class="card-header d-flex justify-content-between">
|
||||
<div class="card-title mb-0">
|
||||
@if ($title)
|
||||
<h5 class="mb-1 {{ $textColor }}">{{ $title }}</h5>
|
||||
@endif
|
||||
@if ($subtitle)
|
||||
<p class="card-subtitle {{ $textColor }}">{{ $subtitle }}</p>
|
||||
@endif
|
||||
</div>
|
||||
@if (!empty($dropdown))
|
||||
<div class="dropdown">
|
||||
<button class="btn btn-text-secondary rounded-pill text-muted border-0 p-2" type="button" data-bs-toggle="dropdown">
|
||||
<i class="ti ti-dots-vertical"></i>
|
||||
</button>
|
||||
<div class="dropdown-menu dropdown-menu-end">
|
||||
@foreach ($dropdown as $item)
|
||||
<a class="dropdown-item" href="{{ $item['href'] ?? 'javascript:void(0);' }}">{{ $item['label'] }}</a>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="card-body">
|
||||
{{ $slot }}
|
||||
</div>
|
||||
|
||||
{{-- Footer flexible --}}
|
||||
@if ($footer || !empty($footerButtons))
|
||||
<div class="card-footer {{ $footerClass }} {{ $footerAlignment }}">
|
||||
{{-- Slot de contenido directo en el footer --}}
|
||||
@if ($footer)
|
||||
{!! $footer !!}
|
||||
@endif
|
||||
|
||||
{{-- Generación dinámica de botones --}}
|
||||
@foreach ($footerButtons as $button)
|
||||
<a href="{{ $button['href'] ?? '#' }}" class="btn btn-{{ $button['type'] ?? 'primary' }} {{ $button['class'] ?? '' }}">
|
||||
{{ $button['label'] }}
|
||||
</a>
|
||||
@endforeach
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
70
resources/views/components/file/dropzone.blade.php
Normal file
70
resources/views/components/file/dropzone.blade.php
Normal file
@ -0,0 +1,70 @@
|
||||
@props([
|
||||
// Identificador único
|
||||
'uid' => uniqid(),
|
||||
|
||||
// Modelo para Livewire
|
||||
'model' => '',
|
||||
|
||||
// Etiqueta y Texto de ayuda
|
||||
'message' => '',
|
||||
'note' => '',
|
||||
|
||||
// Clases generales
|
||||
'size' => 'md', // Tamaño del textarea (xxs, xs, sm, md)
|
||||
'mb0' => false, // Remover margen inferior
|
||||
'parentClass' => '',
|
||||
])
|
||||
|
||||
@php
|
||||
// **Configuración de Name, ID y Model**
|
||||
$livewireModel = $attributes->get('wire:model', $model);
|
||||
$name = $attributes->get('name', $livewireModel);
|
||||
$inputId = $attributes->get('id', $name . '_' . $uid);
|
||||
|
||||
// **Manejo de errores**
|
||||
$errorKey = $livewireModel ?: $name;
|
||||
$hasError = $errors->has($errorKey);
|
||||
$errorClass = $hasError ? 'is-invalid' : '';
|
||||
|
||||
// **Clases dinámicas**
|
||||
$sizeClassDropzone = match ($size) {
|
||||
'sm' => 'dropzone-sm',
|
||||
'xs' => 'dropzone-xs',
|
||||
'md' => 'dropzone-md',
|
||||
default => '',
|
||||
};
|
||||
|
||||
$sizeClassButton = match ($size) {
|
||||
'sm' => 'btn-sm',
|
||||
'xs' => 'btn-xs',
|
||||
default => '',
|
||||
};
|
||||
@endphp
|
||||
|
||||
<!-- Dropzone (se oculta automáticamente después de la carga) -->
|
||||
<div class="{{ $mb0 ? '' : 'mb-4 ' }} {{ $sizeClassDropzone }}">
|
||||
<div class="dropzone" id="dropzone_{{ $inputId }}"">
|
||||
<div class="dz-message">
|
||||
@if ($size == 'sm' || $size == 'xs')
|
||||
<div class="flex items-center">
|
||||
<span class="btn btn-icon {{ $sizeClassButton }} btn-label-secondary mr-2">
|
||||
<i class="ti ti-upload text-base"></i>
|
||||
</span>
|
||||
<span>
|
||||
{{ $message }}
|
||||
<span class="note needsclick">{!! $note !!}</span>
|
||||
</span>
|
||||
</div>
|
||||
@else
|
||||
{{ $message }}
|
||||
<span class="note needsclick">{!! $note !!}</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
<input type="file" wire:model="pdf" {{ $livewireModel ? "wire:model=$livewireModel" : '' }} id="{{ $inputId }}" accept="application/pdf" class="d-none">
|
||||
|
||||
{{-- Mensaje de error --}}
|
||||
@if ($hasError)
|
||||
<span class="text-danger">{{ $errors->first($errorKey) }}</span>
|
||||
@endif
|
||||
</div>
|
148
resources/views/components/form/checkbox-group.blade.php
Normal file
148
resources/views/components/form/checkbox-group.blade.php
Normal file
@ -0,0 +1,148 @@
|
||||
@props([
|
||||
// Identificador único
|
||||
'uid' => uniqid(),
|
||||
|
||||
// Modelos para Livewire
|
||||
'checkboxModel' => '',
|
||||
'textModel' => '',
|
||||
|
||||
// Etiqueta y clases de la etiqueta
|
||||
'label' => '',
|
||||
'labelClass' => '',
|
||||
|
||||
// Clases generales
|
||||
'align' => 'start',
|
||||
'size' => '', // Tamaño del input (sm, lg)
|
||||
'mb0' => false, // Remover margen inferior
|
||||
'parentClass' => '',
|
||||
|
||||
// Elementos opcionales antes/después del input
|
||||
'prefix' => null,
|
||||
'suffix' => null,
|
||||
|
||||
// Íconos dentro del input
|
||||
'icon' => null, // Ícono fijo
|
||||
'clickableIcon' => null, // Ícono con botón
|
||||
|
||||
// Configuración del checkbox
|
||||
'checked' => false,
|
||||
'disabled' => false,
|
||||
|
||||
// Configuración del input de texto
|
||||
'disableOnOffCheckbox' => true, // Deshabilita input hasta que el checkbox esté activo
|
||||
'focusOnCheck' => true, // Hace foco en el input al activar el checkbox
|
||||
|
||||
// Texto de ayuda
|
||||
'helperText' => '',
|
||||
|
||||
// Atributos adicionales para el input de texto
|
||||
'attributes' => new \Illuminate\View\ComponentAttributeBag([]),
|
||||
])
|
||||
|
||||
@php
|
||||
// **Generación de Name, ID y Model**
|
||||
$livewireCheckbox = $checkboxModel ? "wire:model=$checkboxModel" : '';
|
||||
$livewireText = $textModel ? "wire:model=$textModel" : '';
|
||||
|
||||
$nameCheckbox = $checkboxModel;
|
||||
$nameText = $attributes->get('name', $textModel);
|
||||
|
||||
$checkboxId = $attributes->get('id', 'chk_' . $uid);
|
||||
$textInputId = 'txt_' . $uid;
|
||||
|
||||
// **Placeholder del input de texto**
|
||||
$placeholder = $attributes->get('placeholder', 'Ingrese información');
|
||||
|
||||
// **Clases dinámicas**
|
||||
$sizeClass = match ($size) {
|
||||
'sm' => 'form-control-sm',
|
||||
'lg' => 'form-control-lg',
|
||||
default => '',
|
||||
};
|
||||
|
||||
$fullClass = trim("form-control $sizeClass");
|
||||
|
||||
// **Fusionar atributos del input de texto**
|
||||
$inputAttributes = $attributes->merge([
|
||||
'id' => $textInputId,
|
||||
'name' => $nameText,
|
||||
'placeholder' => $placeholder,
|
||||
])->class($fullClass);
|
||||
@endphp
|
||||
|
||||
{{-- ============================ CHECKBOX CON INPUT GROUP ============================ --}}
|
||||
<div class="mb-4 {{ $parentClass }}">
|
||||
@if ($label)
|
||||
<label for="{{ $checkboxId }}" class="{{ $labelClass }}">{{ $label }}</label>
|
||||
@endif
|
||||
|
||||
<div class="input-group">
|
||||
{{-- Checkbox dentro del input-group-text --}}
|
||||
<div class="input-group-text">
|
||||
<input
|
||||
id="{{ $checkboxId }}"
|
||||
name="{{ $nameCheckbox }}"
|
||||
type="checkbox"
|
||||
{{ $livewireCheckbox }}
|
||||
{{ $disabled ? 'disabled' : '' }}
|
||||
class="form-check-input mt-0"
|
||||
onchange="toggleInputState('{{ $checkboxId }}', '{{ $textInputId }}', {{ $focusOnCheck ? 'true' : 'false' }}, {{ $disableOnOffCheckbox ? 'true' : 'false' }})"
|
||||
>
|
||||
</div>
|
||||
|
||||
{{-- Prefijo opcional --}}
|
||||
@isset($prefix)
|
||||
<span class="input-group-text">{{ $prefix }}</span>
|
||||
@endisset
|
||||
|
||||
{{-- Ícono fijo opcional --}}
|
||||
@isset($icon)
|
||||
<span class="input-group-text"><i class="{{ $icon }}"></i></span>
|
||||
@endisset
|
||||
|
||||
{{-- Input de texto dentro del mismo grupo --}}
|
||||
<input
|
||||
{{ $livewireText }}
|
||||
{!! $inputAttributes !!}
|
||||
@if ($disableOnOffCheckbox) disabled @endif
|
||||
aria-label="Text input with checkbox"
|
||||
>
|
||||
|
||||
{{-- Sufijo opcional --}}
|
||||
@isset($suffix)
|
||||
<span class="input-group-text">{{ $suffix }}</span>
|
||||
@endisset
|
||||
|
||||
{{-- Ícono clickeable opcional --}}
|
||||
@isset($clickableIcon)
|
||||
<button type="button" class="input-group-text cursor-pointer">
|
||||
<i class="{{ $clickableIcon }}"></i>
|
||||
</button>
|
||||
@endisset
|
||||
</div>
|
||||
|
||||
{{-- Texto de ayuda opcional --}}
|
||||
@if ($helperText)
|
||||
<div class="form-text">{{ $helperText }}</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
{{-- ============================ JAVASCRIPT PURO ============================ --}}
|
||||
<script>
|
||||
function toggleInputState(checkboxId, inputId, focusOnCheck, disableOnOffCheckbox) {
|
||||
let checkbox = document.getElementById(checkboxId);
|
||||
let textInput = document.getElementById(inputId);
|
||||
|
||||
if (!checkbox || !textInput) return;
|
||||
|
||||
// Deshabilitar o habilitar el input de texto
|
||||
if (disableOnOffCheckbox) {
|
||||
textInput.disabled = !checkbox.checked;
|
||||
}
|
||||
|
||||
// Enfocar automáticamente el input si está habilitado
|
||||
if (focusOnCheck && checkbox.checked) {
|
||||
textInput.focus();
|
||||
}
|
||||
}
|
||||
</script>
|
133
resources/views/components/form/checkbox.blade.php
Normal file
133
resources/views/components/form/checkbox.blade.php
Normal file
@ -0,0 +1,133 @@
|
||||
@props([
|
||||
// Identificador único
|
||||
'uid' => uniqid(),
|
||||
|
||||
// Modelo de Livewire (si aplica)
|
||||
'model' => '',
|
||||
|
||||
// Etiqueta y clases de la etiqueta
|
||||
'label' => '',
|
||||
'labelClass' => '',
|
||||
|
||||
// Clases generales
|
||||
'align' => 'start',
|
||||
'size' => 'md', // Tamaño del checkbox/switch: sm, md, lg
|
||||
'mb0' => false, // Remover margen inferior
|
||||
'parentClass' => '',
|
||||
|
||||
// Estilos del checkbox
|
||||
'switch' => false, // Cambiar a modo switch
|
||||
'switchType' => 'default', // 'default' o 'square'
|
||||
'color' => 'primary', // Bootstrap color: primary, secondary, success, danger, etc.
|
||||
'withIcon' => false, // Si el switch usa íconos en On/Off
|
||||
|
||||
// Diseño de disposición
|
||||
'inline' => false, // Modo inline en lugar de bloque
|
||||
|
||||
// Texto de ayuda
|
||||
'helperText' => '',
|
||||
|
||||
// Atributos adicionales
|
||||
'attributes' => new \Illuminate\View\ComponentAttributeBag([]),
|
||||
])
|
||||
|
||||
@php
|
||||
// **Configuración de valores base**
|
||||
$livewireModel = $attributes->get('wire:model', $model);
|
||||
$name = $attributes->get('name', $livewireModel);
|
||||
$inputId = $attributes->get('id', $name . '_' . $uid);
|
||||
$checked = $attributes->get('checked', false);
|
||||
$disabled = $attributes->get('disabled', false);
|
||||
|
||||
// **Manejo de errores**
|
||||
$errorKey = $livewireModel ?: $name;
|
||||
$hasError = $errors->has($errorKey);
|
||||
$errorClass = $hasError ? 'is-invalid' : '';
|
||||
|
||||
// **Clases dinámicas**
|
||||
$alignClass = match ($align) {
|
||||
'center' => 'text-center',
|
||||
'end' => 'text-end',
|
||||
default => '',
|
||||
};
|
||||
|
||||
$sizeClass = match ($size) {
|
||||
'sm' => 'switch-sm',
|
||||
'lg' => 'switch-lg',
|
||||
default => '',
|
||||
};
|
||||
|
||||
$switchTypeClass = $switchType === 'square' ? 'switch-square' : '';
|
||||
$switchColorClass = "switch-{$color}";
|
||||
$checkColorClass = "form-check-{$color}";
|
||||
|
||||
// **Fusionar atributos con clases dinámicas**
|
||||
$checkboxAttributes = $attributes->merge([
|
||||
'id' => $inputId,
|
||||
'name' => $name,
|
||||
'type' => 'checkbox',
|
||||
]);
|
||||
|
||||
// **Detectar si se usa input-group**
|
||||
$requiresInputGroup = $attributes->get('inline');
|
||||
@endphp
|
||||
|
||||
@if ($switch)
|
||||
{{-- ============================ MODO SWITCH ============================ --}}
|
||||
<div class="{{ $alignClass }} {{ $inline ? 'd-inline-block' : '' }} {{ $parentClass }} {{ $mb0 ? '' : 'mb-2' }}">
|
||||
<label class="switch {{ $switchTypeClass }} {{ $switchColorClass }} {{ $sizeClass }} {{ $labelClass }}">
|
||||
<input
|
||||
{{ $livewireModel ? "wire:model=$livewireModel" : '' }}
|
||||
{{ $disabled ? 'disabled' : '' }}
|
||||
{{ $checked ? 'checked' : '' }}
|
||||
{!! $checkboxAttributes->class("switch-input $errorClass")->toHtml() !!}
|
||||
/>
|
||||
{{-- El Switch Slider --}}
|
||||
<span class="switch-toggle-slider">
|
||||
@if ($withIcon)
|
||||
<span class="switch-on">
|
||||
<i class="ti ti-check"></i>
|
||||
</span>
|
||||
<span class="switch-off">
|
||||
<i class="ti ti-x"></i>
|
||||
</span>
|
||||
@endif
|
||||
</span>
|
||||
{{-- Etiqueta textual a la derecha del switch --}}
|
||||
<span class="switch-label">
|
||||
{{ $label }}
|
||||
</span>
|
||||
</label>
|
||||
|
||||
{{-- Texto de ayuda y error --}}
|
||||
@isset($helperText)
|
||||
<div class="form-text">{{ $helperText }}</div>
|
||||
@endisset
|
||||
@if ($hasError)
|
||||
<span class="text-danger">{{ $errors->first($errorKey) }}</span>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@else
|
||||
{{-- ============================ MODO CHECKBOX ============================ --}}
|
||||
<div class="form-check {{ $checkColorClass }} {{ $alignClass }} {{ $sizeClass }} {{ $inline ? 'form-check-inline' : '' }} {{ $parentClass }} {{ $mb0 ? '' : 'mb-4' }}">
|
||||
<input
|
||||
{{ $livewireModel ? "wire:model=$livewireModel" : '' }}
|
||||
{{ $disabled ? 'disabled' : '' }}
|
||||
{{ $checked ? 'checked' : '' }}
|
||||
{!! $checkboxAttributes->class("form-check-input $errorClass")->toHtml() !!}
|
||||
>
|
||||
|
||||
<label for="{{ $inputId }}" class="form-check-label {{ $labelClass }}">
|
||||
{{ $label }}
|
||||
</label>
|
||||
|
||||
{{-- Texto de ayuda y error --}}
|
||||
@isset($helperText)
|
||||
<div class="form-text">{{ $helperText }}</div>
|
||||
@endisset
|
||||
@if ($hasError)
|
||||
<span class="text-danger">{{ $errors->first($errorKey) }}</span>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
54
resources/views/components/form/custom-option.blade.php
Normal file
54
resources/views/components/form/custom-option.blade.php
Normal file
@ -0,0 +1,54 @@
|
||||
@props([
|
||||
'uid' => uniqid(),
|
||||
'id' => '',
|
||||
'model' => '',
|
||||
'name' => '',
|
||||
'type' => 'checkbox', // checkbox o radio
|
||||
'title' => '',
|
||||
'description' => '',
|
||||
'icon' => null, // Clases de iconos (ej: ti ti-rocket)
|
||||
'image' => null, // URL de imagen
|
||||
'checked' => false,
|
||||
'disabled' => false,
|
||||
'helperText' => '', // Texto de ayuda opcional
|
||||
])
|
||||
|
||||
@php
|
||||
$livewireModel = $attributes->get('wire:model', $model);
|
||||
$name = $name ?: $livewireModel;
|
||||
$inputId = $id ?: ($uid ? $name . '_' . $uid : $name);
|
||||
$errorClass = $errors->has($model) ? 'is-invalid' : '';
|
||||
$checkedAttribute = $checked ? 'checked' : '';
|
||||
$visualContent = $icon
|
||||
? "<i class='{$icon}'></i>"
|
||||
: ($image ? "<img src='{$image}' alt='{$title}' class='img-fluid rounded'>" : '');
|
||||
@endphp
|
||||
|
||||
<div class="mb-4 form-check custom-option custom-option-icon {{ $checked ? 'checked' : '' }}">
|
||||
<label class="form-check-label custom-option-content" for="{{ $inputId }}">
|
||||
<span class="custom-option-body">
|
||||
{!! $visualContent !!}
|
||||
<span class="custom-option-title">{{ $title }}</span>
|
||||
@if($description)
|
||||
<small>{{ $description }}</small>
|
||||
@endif
|
||||
</span>
|
||||
<input
|
||||
type="{{ $type }}"
|
||||
class="form-check-input {{ $errorClass }}"
|
||||
id="{{ $inputId }}"
|
||||
name="{{ $name }}"
|
||||
wire:model="{{ $model }}"
|
||||
{{ $checked ? 'checked' : '' }}
|
||||
{{ $disabled ? 'disabled' : '' }}
|
||||
>
|
||||
</label>
|
||||
|
||||
@if ($helperText)
|
||||
<div class="form-text">{{ $helperText }}</div>
|
||||
@endif
|
||||
|
||||
@error($model)
|
||||
<span class="text-danger">{{ $message }}</span>
|
||||
@enderror
|
||||
</div>
|
48
resources/views/components/form/form.blade.php
Normal file
48
resources/views/components/form/form.blade.php
Normal file
@ -0,0 +1,48 @@
|
||||
@props([
|
||||
'id' => uniqid(), // ID único del formulario
|
||||
'uniqueId' => '', // ID único del formulario
|
||||
'mode' => 'create', // Modo actual ('create', 'edit', 'delete')
|
||||
'method' => 'POST', // Método del formulario (POST, GET, PUT, DELETE)
|
||||
'action' => '', // URL de acción
|
||||
'enctype' => false, // Para envío de archivos
|
||||
'wireSubmit' => false, // Usar wire:submit.prevent
|
||||
'class' => '', // Clases adicionales para el formulario
|
||||
'actionPosition' => 'bottom', // Posición de acciones: top, bottom, both, none
|
||||
])
|
||||
|
||||
@php
|
||||
$formAttributes = [
|
||||
'id' => $id,
|
||||
'method' => $method,
|
||||
'action' => $action,
|
||||
'class' => "fv-plugins-bootstrap5 $class",
|
||||
];
|
||||
|
||||
if ($wireSubmit) {
|
||||
$formAttributes['wire:submit.prevent'] = $wireSubmit;
|
||||
}
|
||||
|
||||
if ($enctype) {
|
||||
$formAttributes['enctype'] = 'multipart/form-data';
|
||||
}
|
||||
@endphp
|
||||
|
||||
<form {{ $attributes->merge($formAttributes) }}>
|
||||
<x-vuexy-admin::form.input :uid="$uniqueId" type="hidden" model="id" />
|
||||
<x-vuexy-admin::form.input :uid="$uniqueId" type="hidden" model="mode" />
|
||||
@if ($mode !== 'delete' && in_array($actionPosition, ['top', 'both']))
|
||||
<div class="notification-container mb-4"></div>
|
||||
<div class="form-actions mb-4">
|
||||
{{ $actions ?? '' }}
|
||||
</div>
|
||||
@endif
|
||||
<div class="form-body">
|
||||
{{ $slot }}
|
||||
</div>
|
||||
@if (in_array($actionPosition, ['bottom', 'both']))
|
||||
<div class="notification-container mb-4"></div>
|
||||
<div class="form-actions mt-4">
|
||||
{{ $actions ?? '' }}
|
||||
</div>
|
||||
@endif
|
||||
</form>
|
184
resources/views/components/form/input.blade copy.php
Normal file
184
resources/views/components/form/input.blade copy.php
Normal file
@ -0,0 +1,184 @@
|
||||
@props([
|
||||
'uid' => uniqid(),
|
||||
|
||||
|
||||
'model' => '',
|
||||
|
||||
|
||||
'label' => '',
|
||||
'labelClass' => '',
|
||||
|
||||
|
||||
'class' => '',
|
||||
|
||||
'align' => 'start',
|
||||
'size' => '',
|
||||
'mb-0' => false,
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
'parentClass' => '',
|
||||
|
||||
|
||||
'prefix' => null,
|
||||
'suffix' => null,
|
||||
|
||||
'icon' => null,
|
||||
'clickableIcon' => null,
|
||||
|
||||
'inline' => false,
|
||||
|
||||
'labelCol' => 4,
|
||||
'inputCol' => 8,
|
||||
|
||||
'floatLabel' => false,
|
||||
'helperText' => '',
|
||||
|
||||
'attributes' => new \Illuminate\View\ComponentAttributeBag([]), // Atributos adicionales
|
||||
])
|
||||
|
||||
@php
|
||||
// Configuración dinámica de atributos y clases CSS
|
||||
$livewireModel = $attributes->get('wire:model', $model); // Permitir uso directo de wire:model en el atributo
|
||||
$name = $name ?: $livewireModel; // Si no se proporciona el nombre, toma el nombre del modelo
|
||||
$inputId = $id ?: ($uid ? $name . '_' . $uid : $name); // ID generado si no se proporciona uno
|
||||
|
||||
|
||||
// Obtener los atributos actuales en un array
|
||||
$attributesArray = array_merge([
|
||||
'type' => $type,
|
||||
'id' => $inputId,
|
||||
'name' => $name,
|
||||
]);
|
||||
|
||||
|
||||
// Agregar wire:model solo si existe
|
||||
if ($livewireModel) {
|
||||
$attributesArray['wire:model'] = $livewireModel;
|
||||
}
|
||||
|
||||
|
||||
$attributesArray = array_merge($attributesArray, $attributes->getAttributes());
|
||||
|
||||
|
||||
// Reconstruir el ComponentAttributeBag con los atributos modificados
|
||||
$inputAttributes = new \Illuminate\View\ComponentAttributeBag($attributesArray);
|
||||
|
||||
dump($inputAttributes);
|
||||
|
||||
|
||||
// Manejo de errores de validación
|
||||
$errorKey = $livewireModel ?: $name;
|
||||
$errorClass = $errors->has($errorKey) ? 'is-invalid' : '';
|
||||
|
||||
// Definir el tamaño del input basado en la clase seleccionada
|
||||
$sizeClass = $size === 'small' ? 'form-control-sm' : ($size === 'large' ? 'form-control-lg' : '');
|
||||
|
||||
// Alineación del texto
|
||||
$alignClass = match ($align) {
|
||||
'center' => 'text-center',
|
||||
'end' => 'text-end',
|
||||
default => ''
|
||||
};
|
||||
|
||||
// Clases combinadas para el input
|
||||
$fullClass = trim("form-control $sizeClass $alignClass $errorClass $class");
|
||||
|
||||
// Detectar si se necesita usar input-group
|
||||
$requiresInputGroup = $prefix || $suffix || $icon || $clickableIcon;
|
||||
@endphp
|
||||
|
||||
{{-- Input oculto sin estilos --}}
|
||||
@if($type === 'hidden')
|
||||
<input type="hidden" id="{{ $inputId }}" name="{{ $name }}" {{ $livewireModel ? "wire:model=$livewireModel" : '' }}
|
||||
/>
|
||||
@elseif($floatLabel)
|
||||
{{-- Input con etiqueta flotante --}}
|
||||
<div class="form-floating mb-4 {{ $parentClass }}">
|
||||
<input
|
||||
type="{{ $type }}"
|
||||
id="{{ $inputId }}"
|
||||
name="{{ $name }}"
|
||||
{{ $livewireModel ? "wire:model=$livewireModel" : '' }}
|
||||
class="{{ $fullClass }}"
|
||||
placeholder="{{ $placeholder ?: 'Ingrese ' . strtolower($label) }}"
|
||||
{{ $step ? "step=$step" : '' }}
|
||||
{{ $max ? "maxlength=$max" : '' }}
|
||||
{{ $min ? "minlength=$min" : '' }}
|
||||
{{ $pattern ? "pattern=$pattern" : '' }}
|
||||
{{ $disabled ? 'disabled' : '' }}
|
||||
{{ $multiple ? 'multiple' : '' }} />
|
||||
<label for="{{ $inputId }}">{{ $label }}</label>
|
||||
|
||||
@if ($helperText)
|
||||
<div class="form-text">{{ $helperText }}</div>
|
||||
@endif
|
||||
|
||||
@if ($errors->has($errorKey))
|
||||
<span class="text-danger">{{ $errors->first($errorKey) }}</span>
|
||||
@endif
|
||||
</div>
|
||||
@else
|
||||
{{-- Input con formato clásico --}}
|
||||
<div class="{{ $inline ? 'row' : '' }} {{ $parentClass }} fv-row mb-4">
|
||||
@isset($label)
|
||||
<label for="{{ $inputId }}" class="{{ $inline ? 'col-form-label col-md-' . $labelCol : 'form-label' }} {{ $labelClass }}">{{ $label }}</label>
|
||||
@endisset
|
||||
<div class="{{ $inline ? 'col-md-' . $inputCol : '' }}">
|
||||
@if ($requiresInputGroup)
|
||||
<div class="input-group input-group-merge">
|
||||
@if ($prefix)
|
||||
<span class="input-group-text">{{ $prefix }}</span>
|
||||
@endif
|
||||
@if ($icon)
|
||||
<span class="input-group-text"><i class="{{ $icon }}"></i></span>
|
||||
@endif
|
||||
<input
|
||||
type="{{ $type }}"
|
||||
id="{{ $inputId }}"
|
||||
name="{{ $name }}"
|
||||
{{ $livewireModel ? "wire:model=$livewireModel" : '' }}
|
||||
class="{{ $fullClass }}"
|
||||
placeholder="{{ $placeholder ?: 'Ingrese ' . strtolower($label) }}"
|
||||
{{ $step ? "step=$step" : '' }}
|
||||
{{ $max ? "maxlength=$max" : '' }}
|
||||
{{ $min ? "minlength=$min" : '' }}
|
||||
{{ $pattern ? "pattern=$pattern" : '' }}
|
||||
{{ $disabled ? 'disabled' : '' }}
|
||||
{{ $multiple ? 'multiple' : '' }} />
|
||||
@if ($suffix)
|
||||
<span class="input-group-text">{{ $suffix }}</span>
|
||||
@endif
|
||||
@if ($clickableIcon)
|
||||
<button type="button" class="input-group-text cursor-pointer">
|
||||
<i class="{{ $clickableIcon }}"></i>
|
||||
</button>
|
||||
@endif
|
||||
</div>
|
||||
@else
|
||||
{{-- Input sin prefijo o íconos --}}
|
||||
<input
|
||||
type="{{ $type }}"
|
||||
id="{{ $inputId }}"
|
||||
name="{{ $name }}"
|
||||
{{ $livewireModel ? "wire:model=$livewireModel" : '' }}
|
||||
class="{{ $fullClass }}"
|
||||
placeholder="{{ $placeholder ?: 'Ingrese ' . strtolower($label) }}"
|
||||
{{ $step ? "step=$step" : '' }}
|
||||
{{ $max ? "maxlength=$max" : '' }}
|
||||
{{ $min ? "minlength=$min" : '' }}
|
||||
{{ $pattern ? "pattern=$pattern" : '' }}
|
||||
{{ $disabled ? 'disabled' : '' }}
|
||||
{{ $multiple ? 'multiple' : '' }} />
|
||||
@endif
|
||||
@if ($helperText)
|
||||
<small class="form-text text-muted">{{ $helperText }}</small>
|
||||
@endif
|
||||
@if ($errors->has($errorKey))
|
||||
<span class="text-danger">{{ $errors->first($errorKey) }}</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
169
resources/views/components/form/input.blade.php
Normal file
169
resources/views/components/form/input.blade.php
Normal file
@ -0,0 +1,169 @@
|
||||
@props([
|
||||
// Identificador único
|
||||
'uid' => uniqid(),
|
||||
|
||||
// Modelo de Livewire
|
||||
'model' => '',
|
||||
|
||||
// Etiqueta y Clases
|
||||
'label' => '',
|
||||
'labelClass' => '',
|
||||
'placeholder' => '',
|
||||
|
||||
// Clases Generales
|
||||
'align' => 'start',
|
||||
'size' => '', // Tamaño del input (sm, lg)
|
||||
'mb0' => false, // Remover margen inferior
|
||||
'parentClass' => '',
|
||||
|
||||
// Elementos opcionales antes/después del input
|
||||
'prefix' => null,
|
||||
'suffix' => null,
|
||||
|
||||
// Íconos dentro del input
|
||||
'icon' => null,
|
||||
'clickableIcon' => null,
|
||||
|
||||
// Configuración especial
|
||||
'phoneMode' => false, // "national", "international", "both"
|
||||
|
||||
// Diseño de disposición (columnas)
|
||||
'inline' => false,
|
||||
'labelCol' => 4,
|
||||
'inputCol' => 8,
|
||||
|
||||
// Configuración de etiquetas flotantes y texto de ayuda
|
||||
'floatLabel' => false,
|
||||
'helperText' => '',
|
||||
|
||||
// Atributos adicionales
|
||||
'attributes' => new \Illuminate\View\ComponentAttributeBag([]),
|
||||
])
|
||||
|
||||
@php
|
||||
// **Configuración de Name, ID y Model**
|
||||
$livewireModel = $attributes->get('wire:model', $model);
|
||||
$name = $attributes->get('name', $livewireModel);
|
||||
$inputId = $attributes->get('id', $name . '_' . $uid);
|
||||
$type = $attributes->get('type', 'text');
|
||||
|
||||
// **Definir formato de teléfono según `phoneMode`**
|
||||
if ($phoneMode) {
|
||||
$type = 'tel';
|
||||
$attributes = $attributes->merge([
|
||||
'autocomplete' => 'tel',
|
||||
'inputmode' => 'tel',
|
||||
]);
|
||||
|
||||
switch ($phoneMode) {
|
||||
case 'national':
|
||||
$attributes = $attributes->merge([
|
||||
'pattern' => '^(?:\D*\d){10,}$',
|
||||
'placeholder' => $placeholder !== false ? ($placeholder ?: 'Ej. (55) 1234-5678') : null,
|
||||
]);
|
||||
break;
|
||||
|
||||
case 'international':
|
||||
$attributes = $attributes->merge([
|
||||
'pattern' => '^\+?[1-9]\d{1,14}$',
|
||||
'placeholder' => $placeholder !== false ? ($placeholder ?: 'Ej. +52 1 55 1234-5678') : null,
|
||||
]);
|
||||
break;
|
||||
|
||||
case 'both':
|
||||
$attributes = $attributes->merge([
|
||||
'pattern' => '(^(?:\D*\d){10,}$)|(^\+?[1-9]\d{1,14}$)',
|
||||
'placeholder' => $placeholder !== false ? ($placeholder ?: 'Ej. (55) 1234-5678 o +52 1 55 1234-5678') : null,
|
||||
]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// **Manejo del Placeholder si no lo estableció `phoneMode`**
|
||||
if (!$attributes->has('placeholder')) {
|
||||
if ($placeholder === false) {
|
||||
// No agregar `placeholder`
|
||||
$placeholderAttr = [];
|
||||
} elseif (empty($placeholder)) {
|
||||
// Generar automáticamente desde el `label`
|
||||
$placeholderAttr = ['placeholder' => 'Ingrese ' . strtolower($label)];
|
||||
} else {
|
||||
// Usar `placeholder` definido manualmente
|
||||
$placeholderAttr = ['placeholder' => $placeholder];
|
||||
}
|
||||
|
||||
// Fusionar el placeholder si no fue definido en `phoneMode`
|
||||
$attributes = $attributes->merge($placeholderAttr);
|
||||
}
|
||||
|
||||
// **Manejo de errores**
|
||||
$errorKey = $livewireModel ?: $name;
|
||||
$hasError = $errors->has($errorKey);
|
||||
$errorClass = $hasError ? 'is-invalid' : '';
|
||||
|
||||
// **Clases dinámicas**
|
||||
$sizeClass = match ($size) {
|
||||
'sm' => 'form-control-sm',
|
||||
'lg' => 'form-control-lg',
|
||||
default => '',
|
||||
};
|
||||
|
||||
$alignClass = match ($align) {
|
||||
'center' => 'text-center',
|
||||
'end' => 'text-end',
|
||||
default => '',
|
||||
};
|
||||
|
||||
// **Fusionar atributos**
|
||||
$inputAttributes = $attributes->merge([
|
||||
'type' => $type,
|
||||
'id' => $inputId,
|
||||
'name' => $name,
|
||||
])->class("form-control $sizeClass $alignClass $errorClass");
|
||||
@endphp
|
||||
|
||||
{{-- Estructura del Input --}}
|
||||
<div class="{{ $mb0 ? '' : 'mb-4' }} {{ $parentClass }}">
|
||||
{{-- Etiqueta --}}
|
||||
@if ($label)
|
||||
<label for="{{ $inputId }}" class="form-label {{ $labelClass }}">{{ $label }}</label>
|
||||
@endif
|
||||
|
||||
{{-- Input con Prefijos, Sufijos o Íconos --}}
|
||||
@if ($prefix || $suffix || $icon || $clickableIcon)
|
||||
<div class="input-group input-group-merge">
|
||||
@isset($prefix)
|
||||
<span class="input-group-text">{{ $prefix }}</span>
|
||||
@endisset
|
||||
|
||||
@isset($icon)
|
||||
<span class="input-group-text"><i class="{{ $icon }}"></i></span>
|
||||
@endisset
|
||||
|
||||
<input {!! $inputAttributes !!} {{ $livewireModel ? "wire:model=$livewireModel" : '' }} />
|
||||
|
||||
@isset($suffix)
|
||||
<span class="input-group-text">{{ $suffix }}</span>
|
||||
@endisset
|
||||
|
||||
@isset($clickableIcon)
|
||||
<button type="button" class="input-group-text cursor-pointer">
|
||||
<i class="{{ $clickableIcon }}"></i>
|
||||
</button>
|
||||
@endisset
|
||||
</div>
|
||||
@else
|
||||
{{-- Input Simple --}}
|
||||
<input {!! $inputAttributes !!} {{ $livewireModel ? "wire:model=$livewireModel" : '' }} />
|
||||
@endif
|
||||
|
||||
{{-- Texto de ayuda --}}
|
||||
@if ($helperText)
|
||||
<div class="form-text">{{ $helperText }}</div>
|
||||
@endif
|
||||
|
||||
{{-- Mensajes de error --}}
|
||||
@if ($hasError)
|
||||
<span class="text-danger">{{ $errors->first($errorKey) }}</span>
|
||||
@endif
|
||||
</div>
|
149
resources/views/components/form/radio-group.blade.php
Normal file
149
resources/views/components/form/radio-group.blade.php
Normal file
@ -0,0 +1,149 @@
|
||||
@props([
|
||||
// Identificador único
|
||||
'uid' => uniqid(),
|
||||
|
||||
// Modelos para Livewire
|
||||
'radioModel' => '',
|
||||
'textModel' => '',
|
||||
|
||||
// Etiqueta y clases de la etiqueta
|
||||
'label' => '',
|
||||
'labelClass' => '',
|
||||
|
||||
// Clases generales
|
||||
'align' => 'start',
|
||||
'size' => '', // Tamaño del input (sm, lg)
|
||||
'mb0' => false, // Remover margen inferior
|
||||
'parentClass' => '',
|
||||
|
||||
// Elementos opcionales antes/después del input
|
||||
'prefix' => null,
|
||||
'suffix' => null,
|
||||
|
||||
// Íconos dentro del input
|
||||
'icon' => null, // Ícono fijo
|
||||
'clickableIcon' => null, // Ícono con botón
|
||||
|
||||
// Configuración del radio
|
||||
'checked' => false,
|
||||
'disabled' => false,
|
||||
'name' => '', // Grupo del radio
|
||||
|
||||
// Configuración del input de texto
|
||||
'disableOnOffRadio' => true, // Deshabilita input hasta que el radio esté seleccionado
|
||||
'focusOnCheck' => true, // Hace foco en el input al seleccionar el radio
|
||||
|
||||
// Texto de ayuda
|
||||
'helperText' => '',
|
||||
|
||||
// Atributos adicionales para el input de texto
|
||||
'attributes' => new \Illuminate\View\ComponentAttributeBag([]),
|
||||
])
|
||||
|
||||
@php
|
||||
// **Generación de Name, ID y Model**
|
||||
$livewireRadio = $radioModel ? "wire:model=$radioModel" : '';
|
||||
$livewireText = $textModel ? "wire:model=$textModel" : '';
|
||||
|
||||
$nameRadio = $attributes->get('name', $radioModel ?: $name);
|
||||
$nameText = $attributes->get('name', $textModel);
|
||||
|
||||
$radioId = $attributes->get('id', 'radio_' . $uid);
|
||||
$textInputId = 'txt_' . $uid;
|
||||
|
||||
// **Placeholder del input de texto**
|
||||
$placeholder = $attributes->get('placeholder', 'Ingrese información');
|
||||
|
||||
// **Clases dinámicas**
|
||||
$sizeClass = match ($size) {
|
||||
'sm' => 'form-control-sm',
|
||||
'lg' => 'form-control-lg',
|
||||
default => '',
|
||||
};
|
||||
|
||||
$fullClass = trim("form-control $sizeClass");
|
||||
|
||||
// **Fusionar atributos del input de texto**
|
||||
$inputAttributes = $attributes->merge([
|
||||
'id' => $textInputId,
|
||||
'name' => $nameText,
|
||||
'placeholder' => $placeholder,
|
||||
])->class($fullClass);
|
||||
@endphp
|
||||
|
||||
{{-- ============================ RADIO BUTTON CON INPUT GROUP ============================ --}}
|
||||
<div class="{{ $mb0 ? '' : 'mb-4' }} {{ $parentClass }}">
|
||||
@if ($label)
|
||||
<label for="{{ $radioId }}" class="{{ $labelClass }}">{{ $label }}</label>
|
||||
@endif
|
||||
|
||||
<div class="input-group">
|
||||
{{-- Radio dentro del input-group-text --}}
|
||||
<div class="input-group-text">
|
||||
<input
|
||||
id="{{ $radioId }}"
|
||||
name="{{ $nameRadio }}"
|
||||
type="radio"
|
||||
{{ $livewireRadio }}
|
||||
{{ $disabled ? 'disabled' : '' }}
|
||||
class="form-check-input mt-0"
|
||||
onchange="toggleRadioInputState('{{ $radioId }}', '{{ $textInputId }}', {{ $focusOnCheck ? 'true' : 'false' }}, {{ $disableOnOffRadio ? 'true' : 'false' }})"
|
||||
>
|
||||
</div>
|
||||
|
||||
{{-- Prefijo opcional --}}
|
||||
@isset($prefix)
|
||||
<span class="input-group-text">{{ $prefix }}</span>
|
||||
@endisset
|
||||
|
||||
{{-- Ícono fijo opcional --}}
|
||||
@isset($icon)
|
||||
<span class="input-group-text"><i class="{{ $icon }}"></i></span>
|
||||
@endisset
|
||||
|
||||
{{-- Input de texto dentro del mismo grupo --}}
|
||||
<input
|
||||
{{ $livewireText }}
|
||||
{!! $inputAttributes !!}
|
||||
@if ($disableOnOffRadio) disabled @endif
|
||||
aria-label="Text input with radio button"
|
||||
>
|
||||
|
||||
{{-- Sufijo opcional --}}
|
||||
@isset($suffix)
|
||||
<span class="input-group-text">{{ $suffix }}</span>
|
||||
@endisset
|
||||
|
||||
{{-- Ícono clickeable opcional --}}
|
||||
@isset($clickableIcon)
|
||||
<button type="button" class="input-group-text cursor-pointer">
|
||||
<i class="{{ $clickableIcon }}"></i>
|
||||
</button>
|
||||
@endisset
|
||||
</div>
|
||||
|
||||
{{-- Texto de ayuda opcional --}}
|
||||
@if ($helperText)
|
||||
<div class="form-text">{{ $helperText }}</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
{{-- ============================ JAVASCRIPT PURO ============================ --}}
|
||||
<script>
|
||||
function toggleRadioInputState(radioId, inputId, focusOnCheck, disableOnOffRadio) {
|
||||
let radio = document.getElementById(radioId);
|
||||
let textInput = document.getElementById(inputId);
|
||||
|
||||
if (!radio || !textInput) return;
|
||||
|
||||
// Deshabilitar o habilitar el input de texto
|
||||
if (disableOnOffRadio) {
|
||||
textInput.disabled = !radio.checked;
|
||||
}
|
||||
|
||||
// Enfocar automáticamente el input si está habilitado
|
||||
if (focusOnCheck && radio.checked) {
|
||||
textInput.focus();
|
||||
}
|
||||
}
|
||||
</script>
|
125
resources/views/components/form/radio.blade.php
Normal file
125
resources/views/components/form/radio.blade.php
Normal file
@ -0,0 +1,125 @@
|
||||
@props([
|
||||
// Identificador único
|
||||
'uid' => uniqid(),
|
||||
|
||||
// Modelo de Livewire (si aplica)
|
||||
'model' => '',
|
||||
|
||||
// Etiqueta y clases de la etiqueta
|
||||
'label' => '',
|
||||
'labelClass' => '',
|
||||
|
||||
// Clases generales
|
||||
'align' => 'start',
|
||||
'size' => '', // Tamaño del radio (sm, lg)
|
||||
'mb0' => false, // Remover margen inferior
|
||||
'parentClass' => '',
|
||||
|
||||
// Modo de visualización
|
||||
'switch' => false, // Convertir en switch
|
||||
'switchType' => 'default', // 'default' o 'square'
|
||||
'color' => 'primary', // Colores personalizados (Bootstrap)
|
||||
'stacked' => false, // Apilar radios en lugar de inline
|
||||
'inline' => false, // Mostrar radios en línea
|
||||
|
||||
// Texto de ayuda
|
||||
'helperText' => '',
|
||||
|
||||
// Atributos adicionales
|
||||
'attributes' => new \Illuminate\View\ComponentAttributeBag([]),
|
||||
])
|
||||
|
||||
@php
|
||||
// **Configuración de valores base**
|
||||
$livewireModel = $attributes->get('wire:model', $model);
|
||||
$name = $attributes->get('name', $livewireModel);
|
||||
$inputId = $attributes->get('id', $name . '_' . $uid);
|
||||
$checked = $attributes->get('checked', false);
|
||||
$disabled = $attributes->get('disabled', false);
|
||||
|
||||
// **Manejo de errores**
|
||||
$errorKey = $livewireModel ?: $name;
|
||||
$hasError = $errors->has($errorKey);
|
||||
$errorClass = $hasError ? 'is-invalid' : '';
|
||||
|
||||
// **Clases dinámicas**
|
||||
$alignClass = match ($align) {
|
||||
'center' => 'text-center',
|
||||
'end' => 'text-end',
|
||||
default => '',
|
||||
};
|
||||
|
||||
$sizeClass = match ($size) {
|
||||
'sm' => 'form-check-sm',
|
||||
'lg' => 'form-check-lg',
|
||||
default => '',
|
||||
};
|
||||
|
||||
$switchTypeClass = $switchType === 'square' ? 'switch-square' : '';
|
||||
$switchColorClass = "switch-{$color}";
|
||||
$radioColorClass = "form-check-{$color}";
|
||||
|
||||
// **Fusionar atributos con clases dinámicas**
|
||||
$radioAttributes = $attributes->merge([
|
||||
'id' => $inputId,
|
||||
'name' => $name,
|
||||
'type' => 'radio',
|
||||
]);
|
||||
|
||||
// **Detectar si se usa `inline` o `stacked`**
|
||||
$layoutClass = $stacked ? 'switches-stacked' : 'form-check';
|
||||
@endphp
|
||||
|
||||
@if ($switch)
|
||||
{{-- ============================ MODO SWITCH ============================ --}}
|
||||
<div class="{{ $alignClass }} {{ $inline ? 'd-inline-block' : '' }} {{ $parentClass }} {{ $mb0 ? '' : 'mb-4' }}">
|
||||
<label class="switch {{ $switchTypeClass }} {{ $switchColorClass }} {{ $sizeClass }} {{ $labelClass }}">
|
||||
<input
|
||||
{{ $livewireModel ? "wire:model=$livewireModel" : '' }}
|
||||
{{ $disabled ? 'disabled' : '' }}
|
||||
{{ $checked ? 'checked' : '' }}
|
||||
{!! $radioAttributes->class("switch-input $errorClass")->toHtml() !!}
|
||||
/>
|
||||
{{-- El Switch Slider --}}
|
||||
<span class="switch-toggle-slider">
|
||||
<span class="switch-on"></span>
|
||||
<span class="switch-off"></span>
|
||||
</span>
|
||||
{{-- Etiqueta textual a la derecha del switch --}}
|
||||
<span class="switch-label">
|
||||
{{ $label }}
|
||||
</span>
|
||||
</label>
|
||||
|
||||
{{-- Texto de ayuda y error --}}
|
||||
@isset($helperText)
|
||||
<div class="form-text">{{ $helperText }}</div>
|
||||
@endisset
|
||||
@if ($hasError)
|
||||
<span class="text-danger">{{ $errors->first($errorKey) }}</span>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@else
|
||||
{{-- ============================ MODO RADIO ============================ --}}
|
||||
<div class="{{ $layoutClass }} {{ $radioColorClass }} {{ $alignClass }} {{ $sizeClass }} {{ $inline ? 'form-check-inline' : '' }} {{ $parentClass }} {{ $mb0 ? '' : 'mb-4' }}">
|
||||
<input
|
||||
{{ $livewireModel ? "wire:model=$livewireModel" : '' }}
|
||||
{{ $disabled ? 'disabled' : '' }}
|
||||
{{ $checked ? 'checked' : '' }}
|
||||
{!! $radioAttributes->class("form-check-input $errorClass")->toHtml() !!}
|
||||
>
|
||||
|
||||
<label for="{{ $inputId }}" class="form-check-label {{ $labelClass }}">
|
||||
{{ $label }}
|
||||
</label>
|
||||
|
||||
{{-- Texto de ayuda y error --}}
|
||||
@isset($helperText)
|
||||
<div class="form-text">{{ $helperText }}</div>
|
||||
@endisset
|
||||
@if ($hasError)
|
||||
<span class="text-danger">{{ $errors->first($errorKey) }}</span>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
86
resources/views/components/form/select.blade copy.php
Normal file
86
resources/views/components/form/select.blade copy.php
Normal file
@ -0,0 +1,86 @@
|
||||
@props([
|
||||
'uid' => uniqid(),
|
||||
'id' => '',
|
||||
'model' => '',
|
||||
'name' => '',
|
||||
'label' => '',
|
||||
'labelClass' => 'form-label',
|
||||
'placeholder' => '',
|
||||
'options' => [],
|
||||
'selected' => null,
|
||||
'class' => '',
|
||||
'parentClass' => '',
|
||||
'multiple' => false,
|
||||
'disabled' => false,
|
||||
'prefixLabel' => null,
|
||||
'suffixLabel' => null,
|
||||
'buttonBefore' => null,
|
||||
'buttonAfter' => null,
|
||||
'inline' => false, // Si es en línea
|
||||
'labelCol' => 2, // Columnas que ocupa el label (Bootstrap grid)
|
||||
'inputCol' => 10, // Columnas que ocupa el input (Bootstrap grid)
|
||||
'helperText' => '', // Texto de ayuda opcional
|
||||
'select2' => false, // Activar Select2 automáticamente
|
||||
])
|
||||
|
||||
@php
|
||||
$name = $name ?: $model;
|
||||
$inputId = $id ?: ($uid ? str_replace('.', '_', $name) . '_' . $uid : $name);
|
||||
$placeholder = $placeholder ?: 'Seleccione ' . strtolower($label);
|
||||
$errorClass = $errors->has($model) ? 'is-invalid' : '';
|
||||
$options = is_array($options) ? collect($options) : $options;
|
||||
$select2Class = $select2 ? 'select2' : ''; // Agrega la clase select2 si está habilitado
|
||||
@endphp
|
||||
|
||||
<div class="{{ $inline ? 'row' : 'mb-4' }} {{ $parentClass }} fv-row">
|
||||
@if($label != null)
|
||||
<label for="{{ $inputId }}" class="{{ $inline ? 'col-md-' . $labelCol : '' }} {{ $labelClass }}">{{ $label }}</label>
|
||||
@endif
|
||||
|
||||
<div class="{{ $inline ? 'col-md-' . $inputCol : '' }}">
|
||||
<div class="input-group {{ $prefixLabel || $suffixLabel || $buttonBefore || $buttonAfter ? 'input-group-merge' : '' }}">
|
||||
@if ($buttonBefore)
|
||||
<button class="btn btn-outline-primary waves-effect" type="button">{{ $buttonBefore }}</button>
|
||||
@endif
|
||||
|
||||
@if ($prefixLabel)
|
||||
<label class="input-group-text" for="{{ $inputId }}">{{ $prefixLabel }}</label>
|
||||
@endif
|
||||
|
||||
<select
|
||||
id="{{ $inputId }}"
|
||||
name="{{ $name }}"
|
||||
class="form-select {{ $errorClass }} {{ $class }} {{ $select2Class }}"
|
||||
{{ $multiple ? 'multiple' : '' }}
|
||||
{{ $disabled ? 'disabled' : '' }}
|
||||
{{ $model ? "wire:model=$model" : '' }}
|
||||
{{ $select2 ? 'data-live-search="true"' : '' }}
|
||||
>
|
||||
@if (!$multiple && $placeholder)
|
||||
<option value="">{{ $placeholder }}</option>
|
||||
@endif
|
||||
@foreach ($options as $key => $value)
|
||||
<option value="{{ $key }}" {{ (string) $key === (string) $selected ? 'selected' : '' }}>
|
||||
{{ $value }}
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
|
||||
@if ($suffixLabel)
|
||||
<label class="input-group-text" for="{{ $inputId }}">{{ $suffixLabel }}</label>
|
||||
@endif
|
||||
|
||||
@if ($buttonAfter)
|
||||
<button class="btn btn-outline-primary waves-effect" type="button">{{ $buttonAfter }}</button>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@if ($helperText)
|
||||
<div class="form-text">{{ $helperText }}</div>
|
||||
@endif
|
||||
|
||||
@if ($errors->has($model))
|
||||
<span class="text-danger">{{ $errors->first($model) }}</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
151
resources/views/components/form/select.blade.php
Normal file
151
resources/views/components/form/select.blade.php
Normal file
@ -0,0 +1,151 @@
|
||||
@props([
|
||||
// Identificador único
|
||||
'uid' => uniqid(),
|
||||
|
||||
// Modelo de Livewire (si aplica)
|
||||
'model' => '',
|
||||
|
||||
// Etiqueta y clases de la etiqueta
|
||||
'label' => '',
|
||||
'labelClass' => '',
|
||||
|
||||
// Clases generales
|
||||
'align' => 'start',
|
||||
'size' => '', // Tamaño del select (small, large)
|
||||
'mb0' => false, // Remover margen inferior
|
||||
'parentClass' => '',
|
||||
|
||||
// Activar Select2 automáticamente
|
||||
'select2' => false,
|
||||
|
||||
// Prefijos y sufijos en input-group
|
||||
'prefixLabel' => null,
|
||||
'suffixLabel' => null,
|
||||
'buttonBefore' => null,
|
||||
'buttonAfter' => null,
|
||||
|
||||
// Diseño de disposición (columnas)
|
||||
'inline' => false,
|
||||
'labelCol' => 4,
|
||||
'inputCol' => 8,
|
||||
|
||||
// Texto de ayuda
|
||||
'helperText' => '',
|
||||
|
||||
// Opciones del select
|
||||
'options' => [],
|
||||
|
||||
// Atributos adicionales
|
||||
'attributes' => new \Illuminate\View\ComponentAttributeBag([]),
|
||||
])
|
||||
|
||||
@php
|
||||
// **Configuración de valores base**
|
||||
$livewireModel = $attributes->get('wire:model', $model);
|
||||
$name = $attributes->get('name', $livewireModel);
|
||||
$inputId = $attributes->get('id', $name . '_' . $uid);
|
||||
$placeholder = $attributes->get('placeholder', 'Seleccione ' . strtolower($label));
|
||||
$selected = $attributes->get('selected', null);
|
||||
|
||||
// **Manejo de errores**
|
||||
$errorKey = $livewireModel ?: $name;
|
||||
$hasError = $errors->has($errorKey);
|
||||
$errorClass = $hasError ? 'is-invalid' : '';
|
||||
|
||||
// **Clases dinámicas**
|
||||
$select2Class = $select2 ? 'select2' : ''; // Agrega la clase `select2` si está habilitado
|
||||
$sizeClass = match ($size) {
|
||||
'sm' => 'form-select-sm',
|
||||
'lg' => 'form-select-lg',
|
||||
default => '',
|
||||
};
|
||||
$alignClass = match ($align) {
|
||||
'center' => 'text-center',
|
||||
'end' => 'text-end',
|
||||
default => '',
|
||||
};
|
||||
|
||||
// **Construcción de clases dinámicas**
|
||||
$fullClass = trim("form-select $select2Class $sizeClass $alignClass $errorClass");
|
||||
$fullLabelClass = trim(($inline ? 'col-form-label col-md-' . $labelCol : 'form-label') . ' ' . $labelClass);
|
||||
$containerClass = trim(($inline ? 'row' : '') . ' fv-row ' . ($mb0 ? '' : 'mb-4') . " $alignClass $parentClass");
|
||||
|
||||
// **Fusionar atributos con clases dinámicas**
|
||||
$selectAttributes = $attributes->merge([
|
||||
'id' => $inputId,
|
||||
'name' => $name,
|
||||
])->class($fullClass);
|
||||
|
||||
// **Detectar si se necesita input-group**
|
||||
$requiresInputGroup = $prefixLabel || $suffixLabel || $buttonBefore || $buttonAfter;
|
||||
@endphp
|
||||
|
||||
<div class="{{ $containerClass }}">
|
||||
{{-- Etiqueta del select --}}
|
||||
@if($label)
|
||||
<label for="{{ $inputId }}" class="{{ $fullLabelClass }}">{{ $label }}</label>
|
||||
@endif
|
||||
|
||||
@if($inline)
|
||||
<div class="col-md-{{ $inputCol }}">
|
||||
@endif
|
||||
|
||||
{{-- Input Group (Si tiene prefijo/sufijo) --}}
|
||||
@if ($requiresInputGroup)
|
||||
<div class="input-group input-group-merge">
|
||||
@isset($buttonBefore)
|
||||
<button class="btn btn-outline-primary waves-effect" type="button">{{ $buttonBefore }}</button>
|
||||
@endisset
|
||||
|
||||
@if($prefixLabel)
|
||||
<label class="input-group-text" for="{{ $inputId }}">{{ $prefixLabel }}</label>
|
||||
@endif
|
||||
|
||||
{{-- Select --}}
|
||||
<select {!! $selectAttributes !!} {{ $attributes->get('multiple') ? 'multiple' : '' }} {{ $attributes->get('disabled') ? 'disabled' : '' }} {{ $livewireModel ? "wire:model=$livewireModel" : '' }} {{ $select2 ? 'data-live-search="true"' : '' }}>
|
||||
@if (!$attributes->get('multiple') && $placeholder)
|
||||
<option value="">{{ $placeholder }}</option>
|
||||
@endif
|
||||
@foreach ($options as $key => $value)
|
||||
<option value="{{ $key }}" {{ (string) $key === (string) $selected ? 'selected' : '' }}>
|
||||
{{ $value }}
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
|
||||
@if($suffixLabel)
|
||||
<label class="input-group-text" for="{{ $inputId }}">{{ $suffixLabel }}</label>
|
||||
@endif
|
||||
|
||||
@isset($buttonAfter)
|
||||
<button class="btn btn-outline-primary waves-effect" type="button">{{ $buttonAfter }}</button>
|
||||
@endisset
|
||||
</div>
|
||||
@else
|
||||
{{-- Select sin prefijo/sufijo --}}
|
||||
<select {!! $selectAttributes !!} {{ $attributes->get('multiple') ? 'multiple' : '' }} {{ $attributes->get('disabled') ? 'disabled' : '' }} {{ $livewireModel ? "wire:model=$livewireModel" : '' }} {{ $select2 ? 'data-live-search="true"' : '' }}>
|
||||
@if (!$attributes->get('multiple') && $placeholder)
|
||||
<option value="">{{ $placeholder }}</option>
|
||||
@endif
|
||||
@foreach ($options as $key => $value)
|
||||
<option value="{{ $key }}" {{ (string) $key === (string) $selected ? 'selected' : '' }}>
|
||||
{{ $value }}
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
@endif
|
||||
|
||||
{{-- Texto de ayuda --}}
|
||||
@isset($helperText)
|
||||
<div class="form-text">{{ $helperText }}</div>
|
||||
@endisset
|
||||
|
||||
{{-- Errores de validación --}}
|
||||
@if ($hasError)
|
||||
<span class="text-danger">{{ $errors->first($errorKey) }}</span>
|
||||
@endif
|
||||
|
||||
@if($inline)
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
178
resources/views/components/form/textarea.blade.php
Normal file
178
resources/views/components/form/textarea.blade.php
Normal file
@ -0,0 +1,178 @@
|
||||
@props([
|
||||
// Identificador único
|
||||
'uid' => uniqid(),
|
||||
|
||||
// Modelo para Livewire
|
||||
'model' => '',
|
||||
|
||||
// Etiqueta y clases de la etiqueta
|
||||
'label' => '',
|
||||
'labelClass' => '',
|
||||
|
||||
// Clases generales
|
||||
'align' => 'start', // Alineación del textarea (start, end)
|
||||
'size' => 'md', // Tamaño del textarea (sm, md, lg)
|
||||
'mb0' => false, // Remover margen inferior
|
||||
'parentClass' => '',
|
||||
|
||||
// Elementos opcionales antes/después del textarea
|
||||
'prefix' => null,
|
||||
'suffix' => null,
|
||||
|
||||
// Íconos dentro del input
|
||||
'prefixIcon' => null, // Ícono fijo a la izquierda
|
||||
'prefixClickableIcon' => null, // Ícono con botón a la izquierda
|
||||
'suffixIcon' => null, // Ícono fijo a la derecha
|
||||
'suffixClickableIcon' => null, // Ícono con botón a la derecha
|
||||
|
||||
// Configuración del textarea
|
||||
'rows' => 3,
|
||||
'maxlength' => null,
|
||||
'autosize' => false, // Autoajuste de altura
|
||||
'resize' => true, // Permitir redimensionar
|
||||
|
||||
// Soporte para etiquetas flotantes
|
||||
'floating' => false, // Si la etiqueta es flotante
|
||||
|
||||
// Texto de ayuda
|
||||
'helperText' => '',
|
||||
|
||||
// Atributos adicionales para el textarea
|
||||
'attributes' => new \Illuminate\View\ComponentAttributeBag([]),
|
||||
])
|
||||
|
||||
@php
|
||||
// **Generación de Name, ID y Model**
|
||||
$livewireModel = $attributes->get('wire:model', $model);
|
||||
$name = $attributes->get('name', $livewireModel);
|
||||
$inputId = $attributes->get('id', $name . '_' . $uid);
|
||||
|
||||
// **Placeholder obligatorio si es flotante**
|
||||
$placeholder = $attributes->get('placeholder', $floating ? ' ' : 'Ingrese ' . strtolower($label));
|
||||
|
||||
// **Manejo de errores**
|
||||
$errorKey = $livewireModel ?: $name;
|
||||
$hasError = $errors->has($errorKey);
|
||||
$errorClass = $hasError ? 'is-invalid' : '';
|
||||
|
||||
// **Clases dinámicas**
|
||||
$sizeClass = match ($size) {
|
||||
'sm' => 'form-control-sm',
|
||||
'lg' => 'form-control-lg',
|
||||
default => '',
|
||||
};
|
||||
|
||||
$alignClass = match ($align) {
|
||||
'center' => 'text-center',
|
||||
'end' => 'text-end',
|
||||
default => '',
|
||||
};
|
||||
|
||||
// **Control de redimensionamiento**
|
||||
$resizeClass = $resize ? '' : 'resize-none';
|
||||
|
||||
// **Fusionar atributos del textarea**
|
||||
$textareaAttributes = $attributes->merge([
|
||||
'id' => $inputId,
|
||||
'name' => $name,
|
||||
'rows' => $rows,
|
||||
'placeholder' => $placeholder,
|
||||
'maxlength' => $maxlength,
|
||||
])->class("form-control $sizeClass $resizeClass $errorClass");
|
||||
|
||||
// **Clases del contenedor flotante**
|
||||
$floatingClass = $floating ? 'form-floating' : '';
|
||||
|
||||
// **Detectar si necesita Input-Group**
|
||||
$requiresInputGroup = $prefix || $suffix || $prefixIcon || $suffixIcon || $prefixClickableIcon || $suffixClickableIcon;
|
||||
@endphp
|
||||
|
||||
{{-- ============================ TEXTAREA ============================ --}}
|
||||
<div class="{{ $mb0 ? '' : 'mb-4' }} {{ $parentClass }} {{ $alignClass }} {{ $floatingClass }}">
|
||||
@if (!$floating && $label)
|
||||
<label for="{{ $inputId }}" class="{{ $labelClass }}">{{ $label }}</label>
|
||||
@endif
|
||||
|
||||
@if ($requiresInputGroup)
|
||||
{{-- Textarea con Input-Group --}}
|
||||
<div class="input-group">
|
||||
{{-- Prefijos (Izquierda) --}}
|
||||
@if ($prefix)
|
||||
<span class="input-group-text">{{ $prefix }}</span>
|
||||
@endif
|
||||
|
||||
@if ($prefixIcon)
|
||||
<span class="input-group-text"><i class="{{ $prefixIcon }}"></i></span>
|
||||
@endif
|
||||
|
||||
@if ($prefixClickableIcon)
|
||||
<button type="button" class="input-group-text cursor-pointer">
|
||||
<i class="{{ $prefixClickableIcon }}"></i>
|
||||
</button>
|
||||
@endif
|
||||
|
||||
{{-- Textarea --}}
|
||||
<textarea
|
||||
{{ $livewireModel ? "wire:model=$livewireModel" : '' }}
|
||||
{!! $textareaAttributes !!}
|
||||
></textarea>
|
||||
|
||||
{{-- Sufijos (Derecha) --}}
|
||||
@if ($suffixClickableIcon)
|
||||
<button type="button" class="input-group-text cursor-pointer">
|
||||
<i class="{{ $suffixClickableIcon }}"></i>
|
||||
</button>
|
||||
@endif
|
||||
|
||||
@if ($suffixIcon)
|
||||
<span class="input-group-text"><i class="{{ $suffixIcon }}"></i></span>
|
||||
@endif
|
||||
|
||||
@if ($suffix)
|
||||
<span class="input-group-text">{{ $suffix }}</span>
|
||||
@endif
|
||||
</div>
|
||||
@else
|
||||
{{-- Textarea simple o flotante --}}
|
||||
<textarea
|
||||
{{ $livewireModel ? "wire:model=$livewireModel" : '' }}
|
||||
{!! $textareaAttributes !!}
|
||||
></textarea>
|
||||
@endif
|
||||
|
||||
{{-- Etiqueta flotante --}}
|
||||
@if ($floating)
|
||||
<label for="{{ $inputId }}">{{ $label }}</label>
|
||||
@endif
|
||||
|
||||
{{-- Longitud máxima permitida --}}
|
||||
@if ($maxlength)
|
||||
<small class="form-text float-end text-muted">Máximo {{ $maxlength }} caracteres</small>
|
||||
@endif
|
||||
|
||||
{{-- Texto de ayuda --}}
|
||||
@if ($helperText)
|
||||
<div class="form-text">{{ $helperText }}</div>
|
||||
@endif
|
||||
|
||||
{{-- Mensaje de error --}}
|
||||
@if ($hasError)
|
||||
<span class="text-danger">{{ $errors->first($errorKey) }}</span>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
{{-- ============================ JAVASCRIPT PARA AUTOSIZE ============================ --}}
|
||||
@if ($autosize)
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
let textarea = document.getElementById('{{ $inputId }}');
|
||||
if (textarea) {
|
||||
textarea.addEventListener('input', function () {
|
||||
this.style.height = 'auto';
|
||||
this.style.height = this.scrollHeight + 'px';
|
||||
});
|
||||
textarea.dispatchEvent(new Event('input')); // Auto-trigger on load
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@endif
|
78
resources/views/components/offcanvas/basic.blade.php
Normal file
78
resources/views/components/offcanvas/basic.blade.php
Normal file
@ -0,0 +1,78 @@
|
||||
@php
|
||||
use Illuminate\Support\Str;
|
||||
@endphp
|
||||
|
||||
@props([
|
||||
'id' => '', // ID único para el offcanvas
|
||||
'title' => '', // Título del offcanvas
|
||||
'position' => 'end', // Posición: 'start', 'end', 'top', 'bottom'
|
||||
'size' => 'md', // Tamaño: sm, md, lg, xl
|
||||
'backdrop' => true, // Si se debe mostrar backdrop
|
||||
'wireIgnore' => true, // Ignorar eventos wire (Livewire)
|
||||
'listener' => '', // Nombre del listener para reload
|
||||
'tagName' => '', // Etiqueta del formHelpers
|
||||
])
|
||||
|
||||
@php
|
||||
$offcanvasClasses = "offcanvas offcanvas-{$position}";
|
||||
|
||||
$offcanvasSize = match ($size) {
|
||||
'sm' => 'offcanvas-sm',
|
||||
'lg' => 'offcanvas-lg',
|
||||
'xl' => 'offcanvas-xl',
|
||||
default => '',
|
||||
};
|
||||
|
||||
$helperTag = Str::kebab($tagName);
|
||||
@endphp
|
||||
|
||||
<div
|
||||
class="{{ $offcanvasClasses }} {{ $offcanvasSize }}"
|
||||
tabindex="-1"
|
||||
id="{{ $id }}"
|
||||
aria-labelledby="{{ $id }}Label"
|
||||
{{ $wireIgnore ? 'wire:ignore.self' : '' }}
|
||||
data-bs-backdrop="{{ $backdrop ? 'true' : 'false' }}">
|
||||
|
||||
{{-- HEADER --}}
|
||||
<div class="offcanvas-header border-bottom">
|
||||
<h5 class="offcanvas-title">{{ $title }}</h5>
|
||||
<button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="Cerrar"></button>
|
||||
</div>
|
||||
|
||||
{{-- BODY --}}
|
||||
<div class="offcanvas-body p-4">
|
||||
{{ $slot }}
|
||||
</div>
|
||||
|
||||
{{-- FOOTER SLOT OPCIONAL --}}
|
||||
@if (isset($footer))
|
||||
<div class="offcanvas-footer border-top p-3">
|
||||
{{ $footer }}
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@push('page-script')
|
||||
<script>
|
||||
// Evento para inicializar el formulario cuando se carga la página
|
||||
window.addEventListener("DOMContentLoaded", () => {
|
||||
const register{{ $tagName }}FormEvents = () => {
|
||||
document.addEventListener("refresh-{{ $helperTag }}-offcanvas", () => {
|
||||
window.formHelpers['{{ $helperTag }}'].refresh();
|
||||
});
|
||||
|
||||
var myOffcanvas = document.getElementById('{{ $id }}')
|
||||
|
||||
myOffcanvas.addEventListener('show.bs.offcanvas', function () {
|
||||
setTimeout(() => window.formHelpers['{{ $helperTag }}'].reloadOffcanvas(), 20);
|
||||
});
|
||||
}
|
||||
|
||||
window.formHelpers = window.formHelpers || {};
|
||||
window.formHelpers['{{ $helperTag }}'] = new FormCanvasHelper('{{ $id }}', @this);
|
||||
|
||||
register{{ $tagName }}FormEvents();
|
||||
});
|
||||
</script>
|
||||
@endpush
|
66
resources/views/components/table/bootstrap/manager.blade.php
Normal file
66
resources/views/components/table/bootstrap/manager.blade.php
Normal file
@ -0,0 +1,66 @@
|
||||
@php
|
||||
use Illuminate\Support\Str;
|
||||
@endphp
|
||||
|
||||
@props([
|
||||
'id' => uniqid(),
|
||||
'tagName' => '',
|
||||
'datatableConfig' => [],
|
||||
'routes' => [],
|
||||
'noFilterButtons' => false
|
||||
])
|
||||
|
||||
@php
|
||||
if($tagName)
|
||||
$id = 'bt-' . Str::kebab($tagName) . 's';
|
||||
@endphp
|
||||
|
||||
<div id="{{ $id }}" wire:ignore>
|
||||
{{-- Contenedor de notificaciones --}}
|
||||
<div class="notification-container"></div>
|
||||
|
||||
{{-- Toolbar con filtros, agrupación y herramientas --}}
|
||||
<div class="bt-toolbar">
|
||||
<div class="d-flex flex-wrap">
|
||||
{{ $tools ?? '' }}
|
||||
|
||||
@isset($filterButtons)
|
||||
{{ $filterButtons }}
|
||||
|
||||
@elseif($noFilterButtons == false)
|
||||
<div class="my-1 pr-2">
|
||||
<x-vuexy-admin::button.basic variant="secondary" class="bt-btn-refresh" icon="ti ti-zoom-reset" size="sm" label="Refrescar" />
|
||||
</div>
|
||||
<div class="my-1 pr-2">
|
||||
<x-vuexy-admin::button.basic variant="secondary" class="bt-btn-filter-edit" label-style icon="ti ti-filter-edit" size="sm" label="Filtros" />
|
||||
</div>
|
||||
<div class="my-1 pr-2">
|
||||
<x-vuexy-admin::button.basic variant="secondary" class="bt-btn-filter-cancel" text-style icon="ti ti-filter-cancel" size="sm" label="Limpiar filtros" />
|
||||
</div>
|
||||
@endisset
|
||||
|
||||
{{ $postTools ?? '' }}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Tabla con Bootstrap Table --}}
|
||||
<table class="bootstrap-table"></table>
|
||||
</div>
|
||||
|
||||
@push('page-script')
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
new BootstrapTableManager('#{{ $id }}', {!! json_encode($datatableConfig) !!});
|
||||
|
||||
document.addEventListener("reload-{{ $id }}", () => {
|
||||
$("#{{ $id }} .bootstrap-table").bootstrapTable("refresh");
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@isset($routes)
|
||||
<script id="app-routes" type="application/json">
|
||||
{!! json_encode($routes) !!}
|
||||
</script>
|
||||
@endisset
|
||||
@endpush
|
Reference in New Issue
Block a user