inengine/tableui

A flexible table ui system for InEngine apps

Maintainers

Package info

github.com/InEngine/TableUI

Homepage

pkg:composer/inengine/tableui

Fund package maintenance!

InEngine

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

1.0.0 2026-05-06 19:44 UTC

This package is auto-updated.

Last update: 2026-05-06 19:47:14 UTC


README

Latest Version on Packagist GitHub Tests Action Status GitHub Code Style Action Status Total Downloads

TableUI is a one-stop package for Laravel and InEngine-based apps for displaying, filtering, and performing actions on data as an interactive table.

Support us

If you find this package helpful please consider supporting us.

Installation

You can install the package via composer:

composer require inengine/tableui

You can publish the config file with:

php artisan vendor:publish --tag="tableui-config"

Tailwind CSS (v4)

Recommended (host app already uses @tailwindcss/vite): import resources/css/tableui.css only — it pulls in partials/tableui-sources.css (@source scanning for this package’s Blade views and inline literals), shared base [x-cloak], filter-panel view transitions, and components/tableui-*.css (@layer components chunks). It does not @import "tailwindcss" again, so Tailwind is loaded a single time from your app entry (e.g. base.css).

@import "tailwindcss";
/* …your @source / @theme … */
@import "./../../vendor/inengine/tableui/resources/css/tableui.css";

Optional publish (copy into your repo):

php artisan vendor:publish --tag="tableui-css"
@import "./vendor/tableui.css"; /* resources/css/vendor/tableui.css */

Standalone bundle: resources/css/tableui-standalone.css imports Tailwind + tableui.css and is the Vite input for maintainers. Building produces public/css/tableui.css for environments that link a precompiled stylesheet instead of merging into the app pipeline:

cd vendor/inengine/tableui   # or this package’s root when developing the package
npm install
npm run build

Release checklist: run npm run build so public/css/tableui.css stays up to date for consumers who use the static file.

The config includes:

  • empty_message — default empty-state copy for the Livewire table when no emptyMessage prop is passed.
  • column_types — package defaults grouped by column kind. For boolean you can set show_false (hide the false-state icon when false), plus true / false branches, each with:
    • icon — Heroicons v2 outline slug (e.g. check, x-mark). Unknown slugs fall back until you extend the icon map.
    • color — Tailwind text colour for the SVG (stroke="currentColor"). Use a shorthand (green-600text-green-600), full classes (text-green-600 dark:text-green-400), arbitrary values, or your own CSS utility classes.
  • column_types.id — optional mono_class wrapper + ulid_suffix_length for shortened ULIDs (see config comments).
  • column_types.numbermax_decimals for non-integer formatting in NumberColumnRenderer.
  • column_types.moneydivisor (default 100 for cents), decimals, prefix, suffix for MoneyColumnRenderer.
  • columns / renderers — optional FQCN lists for app-defined column types and renderers (see comments in the published file).

Column inference (when building Columns from Schema::getColumnType() maps plus sample data) uses the schema type first (boolean, id patterns, timestamps, enums, text, string family, numeric family), then upgrades using key + sample within that family — e.g. string + email + valid address → EmailColumn; numeric + monetary name → MoneyColumn. Without schema, legacy name/sample heuristics apply. See ColumnInference for the full order.

  • ColumnTypes/Column, ColumnFactory, plus subfolders:
    • Primitives/BooleanColumn, StringColumn, TextColumn, EnumColumn, TimestampColumn, NumberColumn, IdColumn
    • Complex/EmailColumn (extends StringColumn), MoneyColumn (extends NumberColumn), PhoneColumn ( extends StringColumn)

See config/tableui.php in this package for full inline documentation.

Optionally, you can publish the views using

php artisan vendor:publish --tag="tableui-views"

Usage

Create a table from an Eloquent collection and render it with the Livewire component:

use App\Models\User;
use InEngine\TableUI\Table;

$table = Table::fromCollection(User::query()->latest()->limit(50)->get());
<livewire:tableui.table-view :table="$table" />

Extending TableUI

TableUI supports app-level extension points through config/tableui.php.

Custom column types

  1. Create a column class that extends InEngine\TableUI\ColumnTypes\Column.
  2. Implement:
    • InEngine\TableUI\Contracts\BuildsColumnFromAttributeKey
    • InEngine\TableUI\Contracts\DefinesColumnRenderers
  3. Register your column and renderer classes in tableui.columns and tableui.renderers.
namespace App\TableUI\Columns;

use InEngine\TableUI\ColumnTypes\Column;
use InEngine\TableUI\Contracts\BuildsColumnFromAttributeKey;
use InEngine\TableUI\Contracts\DefinesColumnRenderers;
use InEngine\TableUI\Contracts\ParticipatesInColumnInference;
use InEngine\TableUI\Rendering\ColumnRendererInterface;

final class SkuColumn extends Column implements BuildsColumnFromAttributeKey, DefinesColumnRenderers, ParticipatesInColumnInference
{
    public static function fromAttributeKey(string $attributeKey): Column
    {
        return new self($attributeKey);
    }

    public static function matchesSample(string $attributeKey, mixed $sample): bool
    {
        return str_contains(strtolower($attributeKey), 'sku');
    }

    /**
     * @return list<class-string<ColumnRendererInterface>>
     */
    public static function rendererClassNames(): array
    {
        return [SkuColumnRenderer::class];
    }

    /**
     * @return class-string<ColumnRendererInterface>
     */
    public static function defaultRendererClassName(): string
    {
        return SkuColumnRenderer::class;
    }
}
// config/tableui.php
'columns' => [
    App\TableUI\Columns\SkuColumn::class,
],
'renderers' => [
    App\TableUI\Renderers\SkuColumnRenderer::class,
],

Custom default actions

Add extra default actions for model-backed tables by implementing InEngine\TableUI\Contracts\BuildsDefaultTableAction and registering the class in tableui.actions.

namespace App\TableUI\Actions;

use InEngine\TableUI\ActionTypes\Action;
use InEngine\TableUI\ActionTypes\UpdateAction;
use InEngine\TableUI\Contracts\BuildsDefaultTableAction;
use InEngine\TableUI\Table;

final class ArchiveActionProvider implements BuildsDefaultTableAction
{
    public static function forTable(Table $table): ?Action
    {
        return new UpdateAction(label: 'Archive', target: '/users/{id}/archive');
    }
}
// config/tableui.php
'actions' => [
    App\TableUI\Actions\ArchiveActionProvider::class,
],

Enum filters (multiselect)

When tableui.filters.enum_allow_multiple is true (the package default), enum column filters render as a * multiselect dropdown* (open to pick one or more values; × clears; selected options use the table primary color). Rows match if the value is any of the selected options (OR). Set to false for a classic single <select>. You can also set allowMultiple on a specific FilterDefinition when building filters manually.

Custom filter definitions

Add custom filter mapping for your custom columns by implementing InEngine\TableUI\Contracts\BuildsFilterDefinitionForColumn and registering in tableui.filter_definitions.

namespace App\TableUI\Filters;

use App\TableUI\Columns\SkuColumn;
use InEngine\TableUI\ColumnTypes\Column;
use InEngine\TableUI\Contracts\BuildsFilterDefinitionForColumn;
use InEngine\TableUI\FilterTypes\FilterDefinition;
use InEngine\TableUI\FilterTypes\FilterType;

final class SkuFilterDefinitionProvider implements BuildsFilterDefinitionForColumn
{
    public static function forColumn(Column $column, ?array $enumOptions = null): ?FilterDefinition
    {
        if (! $column instanceof SkuColumn) {
            return null;
        }

        return new FilterDefinition(
            columnKey: $column->key(),
            label: 'SKU',
            type: FilterType::Text,
        );
    }
}
// config/tableui.php
'filter_definitions' => [
    App\TableUI\Filters\SkuFilterDefinitionProvider::class,
],

Pick a FilterType case that matches how TableUiFilterMatcher should interpret stored filter values (Text, Email, Phone, Boolean, Enum, Number, Money, Date, Datetime, Time). Use allowMultiple on the definition when you need OR-style enum/text matching beyond the global tableui.filters.enum_allow_multiple flag.

Custom Blade views and CSS (UI)

Use this path when you need different markup, layout hooks, or styling — without forking the package.

Publish views (copies into resources/views/vendor/tableui/; Laravel resolves these before the package copies):

php artisan vendor:publish --tag="tableui-views"

Typical overrides:

  • livewire/table.blade.php — outer shell, toolbar includes, scroll wrapper.
  • components/table/*.blade.php — thead, body row, toolbar, bulk toolbar, pagination.
  • components/table/filters/*.blade.php — each filter control (text, enum multiselect, range, etc.).

Keep the same Livewire state ($filterDefinitions, $filterValues, wire:model bindings) when you change layout so the PHP side of TableUI continues to hydrate correctly.

Cell rendering vs Blade: body cells go through <livewire:tableui.column>, which delegates to your registered ColumnRendererInterface classes from tableui.renderers. Override appearance for a column type there; use Blade overrides when you need structural changes around the table (toolbar, filter row, wrappers).

Publish the CSS entry (optional — snapshot into your repo if you do not want to reference vendor/):

php artisan vendor:publish --tag="tableui-css"

You still normally @import the single published resources/css/vendor/tableui.css after Tailwind in your Vite entry. That file remains the supported contract; internally it @imports partials/ and components/ so you can vendor only what you touch (for example copy components/tableui-table.css into your app and layer overrides after the package import).

Standalone / CDN stylesheet: maintainers run npm run build in this package so public/css/tableui.css stays in sync for consumers who link the precompiled bundle instead of merging into a Tailwind app pipeline.

Testing

composer test

Changelog

Please see CHANGELOG for more information on what has changed recently.

Contributing

Please see CONTRIBUTING for details.

Security Vulnerabilities

Please review our security policy on how to report security vulnerabilities.

Credits

License

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