Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@

All notable changes to `livewire-datatables` will be documented in this file

## 3.2.2 ( 2026-08-11 )

### What's Changed

- Keep the default theme inside the datatable's single Livewire root so Livewire 4 attaches `wire:id` and `wire:snapshot` to `.ld-table` instead of the preceding `<style>` element.
- Keep the column picker styles inside its own container rather than emitting a sibling after the partial.
- Add a Laravel 13 / Livewire 4 regression covering the root DOM, sort, search, and pagination interactions.
- Document the view refresh required for applications with published package templates.

## 3.2.1 ( 2026-08-09 )

### What's Changed
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ This will enable you to modify the blade views and apply your own styling, the d

The default table views include a self-contained Apricode theme with graphite headers, warm paper surfaces, orange primary accents, green success states, pink destructive states, and cyan informational accents. The theme is scoped to the package's own controls, requires no Tailwind configuration, and does not override HTML returned by custom callbacks or column views. Publishing the views remains the supported way to replace or customize the theme.

Livewire 4 requires every component to render one root element. Keep the theme include inside the root ```<div class="ld-table">``` and keep partial-specific styles inside their partial container. After upgrading from 3.2.1 or earlier, applications with published views must refresh ```datatable.blade.php``` and ```hide-column-multiselect.blade.php``` (or move those style blocks manually); avoid overwriting unrelated customized views with a blanket ```vendor:publish --force```.

Several of the built-in dynamic components use Alpine JS, so to remove flickers on page load, make sure you have
```css
[x-cloak] {
Expand Down
4 changes: 2 additions & 2 deletions resources/views/livewire/datatables/datatable.blade.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
@include('datatables::theme')

<div class="ld-table">
@include('datatables::theme')

@includeIf($beforeTableSlot)
<div class="relative">
<div class="ld-toolbar flex items-center justify-between mb-1">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
</div>
</div>
</div>
</div>

<style>
.top-100 {
Expand All @@ -52,3 +51,4 @@
}

</style>
</div>
46 changes: 46 additions & 0 deletions tests/LivewireDatatableTemplateTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,58 @@
namespace Arm092\LivewireDatatables\Tests;

use Arm092\LivewireDatatables\Livewire\LivewireDatatable;
use Arm092\LivewireDatatables\Tests\Classes\SecureDummyTable;
use Arm092\LivewireDatatables\Tests\Models\DummyModel;
use DOMDocument;
use DOMXPath;
use Livewire\Livewire;
use PHPUnit\Framework\Attributes\Test;

class LivewireDatatableTemplateTest extends TestCase
{
#[Test]
public function the_theme_and_column_picker_styles_stay_inside_the_livewire_root(): void
{
factory(DummyModel::class, 12)->create([
'category' => 'allowed',
]);

$component = Livewire::test(SecureDummyTable::class, [
'hideable' => 'select',
]);

$document = new DOMDocument;
$previous = libxml_use_internal_errors(true);
$document->loadHTML('<body>'.$component->html().'</body>', LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
libxml_clear_errors();
libxml_use_internal_errors($previous);

$body = $document->getElementsByTagName('body')->item(0);
$roots = array_values(array_filter(
iterator_to_array($body->childNodes),
static fn ($node) => $node->nodeType === XML_ELEMENT_NODE,
));

$this->assertCount(1, $roots);
$this->assertSame('div', $roots[0]->tagName);
$this->assertStringContainsString('ld-table', $roots[0]->getAttribute('class'));
$this->assertNotSame('', $roots[0]->getAttribute('wire:id'));
$this->assertNotSame('', $roots[0]->getAttribute('wire:snapshot'));

$xpath = new DOMXPath($document);
$this->assertGreaterThan(0, $xpath->query('.//*[name() = "style"]', $roots[0])->count());
$this->assertGreaterThan(0, $xpath->query('.//*[@*[name() = "wire:click"]]', $roots[0])->count());
$this->assertGreaterThan(0, $xpath->query('.//*[@*[name() = "wire:model.live"]]', $roots[0])->count());

$component->call('sort', 1, 'asc')
->assertSet('sortIndex', 1)
->set('search', 'definitely absent')
->assertSee("There's Nothing to show at the moment")
->set('search', null)
->call('gotoPage', 2)
->assertSet('paginators.page', 2);
}

#[Test]
public function the_default_template_includes_the_scoped_apricode_theme()
{
Expand Down