LaravelPackages.net
Acme Inc.
Toggle sidebar
unlab/livewire-table-kit

Reusable Livewire table component kit with search, filters, sorting, pagination, actions, and CSV/XLSX/PDF export.

30
0
v1.3.6
About unlab/livewire-table-kit

unlab/livewire-table-kit is a Laravel package for reusable livewire table component kit with search, filters, sorting, pagination, actions, and csv/xlsx/pdf export.. It currently has 0 GitHub stars and 30 downloads on Packagist (latest version v1.3.6). Install it with composer require unlab/livewire-table-kit. Discover more Laravel packages by unlab or browse all Laravel packages to compare alternatives.

Last updated

unlab/livewire-table-kit

Reusable Livewire table component kit with:

  • search
  • filters
  • sorting
  • pagination
  • row actions
  • bulk delete
  • CSV / XLSX / PDF export

Documentation

Install

composer require unlab/livewire-table-kit

Setup

1. Tailwind Configuration

Add the package path to your Tailwind configuration to ensure styles are compiled.

For Tailwind v4 (app.css):

@source "../../vendor/unlab/livewire-table-kit/resources/views/**/*.blade.php";

For Tailwind v3 (tailwind.config.js):

content: [
    './vendor/unlab/livewire-table-kit/resources/views/**/*.blade.php',
],

Then run: npm run build

2. Publish views (Optional)

php artisan vendor:publish --tag=livewire-table-kit-views

3. Publish config and MCP assets (Optional)

php artisan vendor:publish --tag=livewire-table-kit-config
php artisan vendor:publish --tag=livewire-table-kit-mcp
php artisan vendor:publish --tag=livewire-table-kit-stubs
php artisan vendor:publish --tag=livewire-table-kit-lang

Install AI skills (Optional)

If you want to use the package MCP server or project-local AI skills:

# Install local MCP server config
php artisan livewire-table-kit:install-mcp

# Install skill files for Codex and project-local workflows
php artisan livewire-table-kit:install-skill

Generate a table component

Use the package generator command to scaffold a table component from an Eloquent model:

php artisan make:livewire-table App\\Models\\User UsersTable

The generator uses schema heuristics to automatically determine:

  • Searchable and sortable fields
  • Badge columns for statuses and booleans
  • Sensible labels

Advanced Usage

Full Example

<?php

declare(strict_types=1);

namespace App\Livewire\Tables;

use App\Models\User;
use Illuminate\Database\Eloquent\Builder;
use Unlab\LivewireTableKit\Livewire\Components\Tables\BaseTable;
use Unlab\LivewireTableKit\Livewire\Components\Tables\Columns\Column;
use Unlab\LivewireTableKit\Livewire\Components\Tables\Columns\BadgeColumn;
use Unlab\LivewireTableKit\Livewire\Components\Tables\Columns\ActionColumn;
use Unlab\LivewireTableKit\Livewire\Components\Tables\Columns\Actions\TableAction;
use Unlab\LivewireTableKit\Livewire\Components\Tables\Filters\Filter;

class UsersTable extends BaseTable
{
    public function query(): Builder
    {
        return User::query();
    }

    public function columns(): array
    {
        return [
            Column::make('ID')->field('id')->sortable(),
            
            Column::make('Name')
                ->field('name')
                ->searchable()
                ->sortable(),

            Column::make('Email')
                ->field('email')
                ->searchable()
                ->sortable(),

            BadgeColumn::make('Status')
                ->field('status')
                ->colorMap([
                    'active' => 'success',
                    'pending' => 'warning',
                    'inactive' => 'danger',
                ]),

            ActionColumn::make()->actions([
                TableAction::wire('Edit', fn ($row) => "edit('{$row->id}')", icon: 'pencil'),
                TableAction::link('View', fn ($row) => route('users.show', $row), icon: 'eye'),
            ]),
        ];
    }

    public function filters(): array
    {
        return [
            Filter::select('role', 'Role', [
                'admin' => 'Administrator',
                'user' => 'User',
            ]),

            Filter::radio('status', 'Status', [
                'active' => 'Active',
                'inactive' => 'Inactive',
            ])->placeholder('All statuses')
                ->display('dropdown'),

            Filter::checkbox('department', 'Departments', [
                'engineering' => 'Engineering',
                'product' => 'Product',
                'support' => 'Support',
            ]),
            
            Filter::date('created_at', 'Created After'),
            
            // Custom query filter
            Filter::text('search_bio', 'Search Bio')
                ->query(fn ($query, $value) => $query->where('bio', 'like', "%{$value}%")),
        ];
    }

    public function supportsExport(): bool => true;
    public function supportsBulkDelete(): bool => true;

    public function actionBulkDelete(array $payload): void
    {
        User::whereIn('id', $payload)->delete();
    }
}

Column Helpers

  • Column::make('Label'): Create a column.
  • ->field('db_column'): Maps to a database column.
  • ->value(fn ($row) => ...): Define a custom value resolver.
  • ->searchable(?string $field = null): Enable search.
  • ->searchableRaw(string $expression): Search using a raw SQL expression (e.g., CONCAT(first_name, ' ', last_name)).
  • ->sortable(?string $field = null): Enable sorting.
  • ->view('custom.cell-view'): Render cells using a custom Blade view.
  • ->align('center'): Set text alignment (left, center, right).
  • ->headerAlign('center'): Set header alignment.
  • ->html(): Treat the value as raw HTML.
  • ->exportable(false): Exclude from exports.

Badge Columns

BadgeColumn uses Flux UI's badge styles.

BadgeColumn::make('Status')
    ->field('status')
    ->colorMap([
        'active' => 'success',   // emerald
        'pending' => 'warning',  // amber
        'inactive' => 'danger',  // rose
        'default' => 'default',  // zinc
    ]);

Available colors: primary, success, warning, danger, default.

Filter Types

  • Filter::select(key, label, options)
  • Filter::radio(key, label, options)
  • Filter::checkbox(key, label, options)
  • Filter::text(key, label, placeholder)
  • Filter::date(key, label)
  • Filter::number(key, label, placeholder)

For select and radio filters, placeholder() is used as the label for the reset or "all" option. Checkbox filters are multi-select, render inside a dropdown in the default toolbar UI, and apply a whereIn-style match by default. Option-based filters can also control their toolbar presentation with ->display('inline') or ->display('dropdown').

At the table level, you can collapse the entire filter set into a single dropdown trigger:

protected function filterToolbarMode(): string
{
    return 'dropdown';
}

Events

The component listens for and dispatches several events:

  • refreshTable: (Inbound) Refreshes the table data and resets pagination.
  • openBulkDeleteConfirm: (Outbound) Triggered when bulk delete is clicked.
  • bulkDeleteConfirmed: (Inbound) Triggered when the user confirms deletion.
  • notify: (Outbound) Standard notification event with type and message.

Customization

BaseTable Hooks

Override these methods in your table class to customize behavior:

| Method | Description | Default | |--------|-------------|---------| | defaultSortField() | Initial sort column | null | | defaultSortDirection() | Initial sort direction | 'asc' | | perPageOptions() | Options for the per-page selector | [10, 25, 50, 100, 'all'] | | emptyState() | Configure the empty state display | Array with title/message | | exportType() | Export processing mode: sync or queued (queue alias accepted) | 'sync' | | exportFilename(ext) | Name of the exported file | Derived from class name | | exportPdfMode() | PDF rendering mode: auto, single, or chunked | 'auto' | | exportPdfChunkSize() | Rows rendered per DomPDF part in chunked PDF mode | 150 | | exportPdfChunkThreshold() | Row count where auto PDF mode switches to chunked rendering | 500 |

Queued Exports

For large exports, queue the export job instead of generating the file during the Livewire request:

protected function exportType(): string
{
    return 'queued';
}

Queued exports store the generated file on the configured disk and dispatch an exportQueued event with format, disk, and path. The table UI shows a Flux-styled loading toast while the request starts, then a pending toast with a percentage progress bar while the worker processes the export. After the file exists, the table shows a permanent ready toast with a Download action. If the job fails, the table shows a permanent failed toast with the cached error message. Ready and failed toasts stay visible until the user closes them.

PDF Customization

protected function exportPdfTitle(): string => 'User Report';
protected function exportPdfOrientation(): string => 'landscape'; // portrait or landscape
protected function exportPdfPaperSize(): string => 'a4';
protected function exportPdfMargins(): array => ['top' => '10mm', ...];
protected function exportPdfFontSize(): string => '9px';
protected function exportPdfMode(): string => 'chunked';
protected function exportPdfChunkSize(): int => 150;

PDF exports use auto mode by default. Small PDF exports render as a single DomPDF document, while larger exports render in smaller parts and merge the parts into the final PDF to reduce peak memory usage.

Requirements

  • PHP 8.4+
  • Laravel 13+
  • Livewire 4+
  • Flux UI 2+ (The UI depends on Flux components)
  • Maatwebsite Excel (For XLSX exports)
  • Barryvdh DomPDF (For PDF exports)
  • iio/libmergepdf (For chunked PDF exports)

License

The MIT License (MIT). Please see LICENSE for more information.

Comments