@props([ 'columns' => [], 'rows' => [], 'sortable' => true, 'paginated' => true, 'perPage' => 15, 'searchable' => false, 'emptyMessage' => 'No records found', ])
merge(['class' => 'bg-white dark:bg-slate-800 rounded-xl shadow-sm border border-slate-200 dark:border-slate-700 overflow-hidden']) }} x-data="{ search: '', sort: '{{ $columns[0]['key'] ?? '' }}', dir: 'asc', page: 1, perPage: {{ $perPage }}, get filteredRows() { let rows = $refs.tableBody ? JSON.parse($refs.tableData.value) : []; if (this.search) { const q = this.search.toLowerCase(); rows = rows.filter(r => Object.values(r).some(v => String(v).toLowerCase().includes(q))); } rows.sort((a, b) => { let va = a[this.sort] ?? '', vb = b[this.sort] ?? ''; if (typeof va === 'number') return this.dir === 'asc' ? va - vb : vb - va; return this.dir === 'asc' ? String(va).localeCompare(String(vb)) : String(vb).localeCompare(String(va)); }); return rows; }, get pagedRows() { const start = (this.page - 1) * this.perPage; return this.filteredRows.slice(start, start + this.perPage); }, get totalPages() { return Math.ceil(this.filteredRows.length / this.perPage) || 1; }, toggleSort(key) { if (this.sort === key) { this.dir = this.dir === 'asc' ? 'desc' : 'asc'; } else { this.sort = key; this.dir = 'asc'; } } }"> {{-- Search --}} @if($searchable)
@endif {{-- Table --}}
@foreach($columns as $col) @endforeach
{{ $col['label'] ?? $col['key'] }} @if($sortable && ($col['sortable'] ?? true)) @endif
{{-- Empty state --}} {{-- Pagination --}} @if($paginated)

{{ __('Showing') }} {{ __('of') }}

@endif