diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 00000000..1e66ada7 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +github: [arm092] diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b9d8b92..fd895a6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,16 @@ All notable changes to `livewire-datatables` will be documented in this file +## 3.2.4 ( 2026-09-26 ) + +### What's Changed + +- Reset select filter controls after applying a value, removing a value, or clearing all filters. +- Use the Apricode orange accent for the filter panel so active filter badges remain distinct. +- Restyle table actions as clear, icon-led outline buttons with inverted brand colors on hover. +- Add GitHub Sponsors discovery through the README and repository funding metadata. +- Keep the security regression suite compatible with the HTTP exception handling introduced in Livewire 4.4. + ## 3.2.3 ( 2026-08-11 ) ### What's Changed diff --git a/README.md b/README.md index f05451ee..9e055eea 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ Build searchable, sortable, filterable and editable admin tables with Laravel, Livewire and Tailwind CSS. +[](https://github.com/sponsors/arm092) +  [](https://packagist.org/packages/arm092/livewire-datatables) diff --git a/resources/views/icons/columns.blade.php b/resources/views/icons/columns.blade.php new file mode 100644 index 00000000..9ce6b863 --- /dev/null +++ b/resources/views/icons/columns.blade.php @@ -0,0 +1,3 @@ +merge(['class' => 'h-5 w-5 stroke-current']) }} fill="none" viewBox="0 0 24 24" stroke="currentColor"> + + diff --git a/resources/views/livewire/datatables/datatable.blade.php b/resources/views/livewire/datatables/datatable.blade.php index 2daf0657..91fa2eb1 100644 --- a/resources/views/livewire/datatables/datatable.blade.php +++ b/resources/views/livewire/datatables/datatable.blade.php @@ -32,8 +32,9 @@ @if($this->activeFilters) - {{ __('Reset') }} - + + + {{ __('Reset filters') }} @endif @@ -67,8 +68,10 @@ class="ld-button ld-button--success flex items-center px-4 py-2 text-xs font-med - {{ __('Export') }} - + + + {{ __('Export') }} + @endif @@ -137,7 +140,7 @@ class="ld-button ld-button--success px-3 py-2 text-xs font-medium tracking-wider @if($column['filterable']) @if( is_iterable($column['filterable']) ) - + @include('datatables::filters.select', ['index' => $index, 'name' => $column['label'], 'options' => $column['filterable']]) @else diff --git a/resources/views/livewire/datatables/filters/select.blade.php b/resources/views/livewire/datatables/filters/select.blade.php index b06b2a0a..181450f3 100644 --- a/resources/views/livewire/datatables/filters/select.blade.php +++ b/resources/views/livewire/datatables/filters/select.blade.php @@ -1,11 +1,9 @@ - + @foreach($options as $value => $label) @@ -24,7 +22,7 @@ class="w-full m-1 text-sm leading-4 block rounded-md border-gray-300 shadow-sm f @foreach($this->activeSelectFilters[$index] ?? [] as $key => $value) - {{ $this->getDisplayValue($index, $value) }} diff --git a/resources/views/livewire/datatables/hide-column-multiselect.blade.php b/resources/views/livewire/datatables/hide-column-multiselect.blade.php index 4173e23c..2e6701d6 100644 --- a/resources/views/livewire/datatables/hide-column-multiselect.blade.php +++ b/resources/views/livewire/datatables/hide-column-multiselect.blade.php @@ -1,6 +1,7 @@ - + + {{ __('Show / Hide Columns')}} diff --git a/resources/views/livewire/datatables/theme.blade.php b/resources/views/livewire/datatables/theme.blade.php index af9fa23c..330de418 100644 --- a/resources/views/livewire/datatables/theme.blade.php +++ b/resources/views/livewire/datatables/theme.blade.php @@ -74,24 +74,40 @@ .ld-table .ld-button:hover { border-color: var(--ld-primary) !important; - background: rgb(253 151 31 / 10%) !important; + background: var(--ld-primary) !important; color: var(--ld-ink) !important; } + .ld-table .ld-button--primary { + border-color: var(--ld-primary) !important; + color: var(--ld-primary) !important; + } + + .ld-table .ld-button--primary:hover { + background: var(--ld-primary) !important; + color: var(--ld-white) !important; + } + + .ld-table .ld-button--success { + border-color: var(--ld-success) !important; + color: var(--ld-success) !important; + } + .ld-table .ld-button--success:hover { border-color: var(--ld-success) !important; - background: rgb(166 226 46 / 14%) !important; + background: var(--ld-success) !important; + color: var(--ld-white) !important; } .ld-table .ld-button--danger { - border-color: rgb(249 38 114 / 40%) !important; - color: #bb1d56 !important; + border-color: var(--ld-danger) !important; + color: var(--ld-danger) !important; } .ld-table .ld-button--danger:hover { border-color: var(--ld-danger) !important; - background: rgb(249 38 114 / 10%) !important; - color: #951744 !important; + background: var(--ld-danger) !important; + color: var(--ld-white) !important; } .ld-table .ld-panel { @@ -144,8 +160,8 @@ .ld-table .ld-filter-row, .ld-table .ld-filter-cell { - background: var(--ld-paper) !important; - border-color: var(--ld-border) !important; + background: var(--ld-primary) !important; + border-color: #d37b12 !important; } .ld-table .ld-data-row > .table-cell { @@ -218,7 +234,7 @@ } .ld-table .ld-filter-active { - color: #985b13 !important; + color: var(--ld-primary) !important; } .ld-table .ld-button.bg-blue-500 { diff --git a/src/LivewireDatatablesServiceProvider.php b/src/LivewireDatatablesServiceProvider.php index 0a5f2d88..c040aa39 100644 --- a/src/LivewireDatatablesServiceProvider.php +++ b/src/LivewireDatatablesServiceProvider.php @@ -39,6 +39,7 @@ public function boot(): void Blade::component('icons::trash', 'icons.trash'); Blade::component('icons::copy', 'icons.copy'); Blade::component('icons::excel', 'icons.excel'); + Blade::component('icons::columns', 'icons.columns'); Blade::component('icons::x-circle', 'icons.x-circle'); Blade::component('icons::check-circle', 'icons.check-circle'); diff --git a/tests/LivewireDatatableSecurityTest.php b/tests/LivewireDatatableSecurityTest.php index c6c7faa0..a977f167 100644 --- a/tests/LivewireDatatableSecurityTest.php +++ b/tests/LivewireDatatableSecurityTest.php @@ -39,10 +39,10 @@ public function it_updates_only_configured_editable_columns_inside_the_builder_s $this->assertSame('Updated', $allowed->fresh()->subject); - $this->expectException(ModelNotFoundException::class); - - Livewire::test(SecureDummyTable::class) - ->call('edited', 'Not allowed', 1, $excluded->getKey()); + $this->assertModelNotFound(function () use ($excluded) { + return Livewire::test(SecureDummyTable::class) + ->call('edited', 'Not allowed', 1, $excluded->getKey()); + }); } #[Test] @@ -50,10 +50,10 @@ public function it_deletes_only_records_inside_the_builder_scope(): void { $excluded = factory(DummyModel::class)->create(['category' => 'excluded']); - $this->expectException(ModelNotFoundException::class); - - Livewire::test(SecureDummyTable::class) - ->call('delete', $excluded->getKey()); + $this->assertModelNotFound(function () use ($excluded) { + return Livewire::test(SecureDummyTable::class) + ->call('delete', $excluded->getKey()); + }); } #[Test] @@ -103,4 +103,13 @@ public function it_exports_formula_like_strings_as_text(): void $this->assertSame(DataType::TYPE_STRING, $cell->getDataType()); $this->assertSame('=HYPERLINK("https://example.test")', $cell->getValue()); } + + private function assertModelNotFound(callable $callback): void + { + try { + $callback()->assertStatus(404); + } catch (ModelNotFoundException) { + $this->addToAssertionCount(1); + } + } }