merge($this->getFilterPopoverAttributes)
+ ->merge([
+ 'role' => 'menu',
+ 'aria-orientation' => 'vertical',
+ 'aria-labelledby' => 'filters-menu',
+ 'x-transition:enter' => 'transition ease-out duration-100',
+ 'x-transition:enter-start' => 'transform opacity-0 scale-95',
+ 'x-transition:enter-end' => 'transform opacity-100 scale-100',
+ 'x-transition:leave' => 'transition ease-in duration-75',
+ 'x-transition:leave-start' => 'transform opacity-100 scale-100',
+ 'x-transition:leave-end' => 'transform opacity-0 scale-95',
+ ])
+ ->class([
+ 'w-full md:w-56' => $this->getFilterPopoverAttributes['default-width'] ?? true,
+ 'origin-top-left absolute left-0 mt-2 rounded-md shadow-lg ring-1 ring-opacity-5 divide-y focus:outline-none z-50' => $this->getFilterPopoverAttributes['default-styling'] ?? true,
+ 'bg-white divide-gray-100 ring-black dark:bg-gray-700 dark:text-white dark:divide-gray-600' => $this->getFilterPopoverAttributes['default-colors'] ?? true,
+ ])
+ ->except(['x-cloak', 'x-show', 'default','default-width', 'default-styling','default-colors'])
+ }}>
+
@foreach ($this->getVisibleFilters() as $filter)
-
+
{{ $filter->setGenericDisplayData($this->getFilterGenericData)->render() }}
@@ -68,15 +53,8 @@ class="block px-4 py-2 text-sm text-gray-700 space-y-1"
@if ($this->hasAppliedVisibleFiltersWithValuesThatCanBeCleared())
-
- {{ __($this->getLocalisationPath.'Clear') }}
-
+
@endif
-@endif
+@endif
\ No newline at end of file
diff --git a/resources/views/components/tools/toolbar/items/filter-popover/clear-button.blade.php b/resources/views/components/tools/toolbar/items/filter-popover/clear-button.blade.php
new file mode 100644
index 000000000..6436cd79f
--- /dev/null
+++ b/resources/views/components/tools/toolbar/items/filter-popover/clear-button.blade.php
@@ -0,0 +1,7 @@
+
$this->isTailwind,
+ 'dropdown-item btn text-center' => $this->isBootstrap4,
+ 'dropdown-item text-center' => $this->isBootstrap5,
+ ])>
+ {{ __($this->getLocalisationPath.'Clear') }}
+
\ No newline at end of file
diff --git a/src/Traits/Configuration/FilterConfiguration.php b/src/Traits/Configuration/FilterConfiguration.php
index 5f8a0629f..d17e7bf16 100644
--- a/src/Traits/Configuration/FilterConfiguration.php
+++ b/src/Traits/Configuration/FilterConfiguration.php
@@ -3,7 +3,6 @@
namespace Rappasoft\LaravelLivewireTables\Traits\Configuration;
use Rappasoft\LaravelLivewireTables\DataTransferObjects\FilterGenericData;
-use Rappasoft\LaravelLivewireTables\Exceptions\DataTableConfigurationException;
trait FilterConfiguration
{
@@ -70,52 +69,6 @@ public function setFilterPillsDisabled(): self
return $this;
}
- public function setFilterLayout(string $type): self
- {
- if (! in_array($type, ['popover', 'slide-down'], true)) {
- throw new DataTableConfigurationException('Invalid filter layout type');
- }
-
- $this->filterLayout = $type;
-
- return $this;
- }
-
- public function setFilterLayoutPopover(): self
- {
- $this->setFilterLayout('popover');
-
- return $this;
- }
-
- public function setFilterLayoutSlideDown(): self
- {
- $this->setFilterLayout('slide-down');
-
- return $this;
- }
-
- public function setFilterSlideDownDefaultStatus(bool $status): self
- {
- $this->filterSlideDownDefaultVisible = $status;
-
- return $this;
- }
-
- public function setFilterSlideDownDefaultStatusDisabled(): self
- {
- $this->setFilterSlideDownDefaultStatus(false);
-
- return $this;
- }
-
- public function setFilterSlideDownDefaultStatusEnabled(): self
- {
- $this->setFilterSlideDownDefaultStatus(true);
-
- return $this;
- }
-
public function generateFilterGenericData(): array
{
return (new FilterGenericData($this->getTableName(), $this->getFilterLayout(), $this->isTailwind(), $this->isBootstrap4(), $this->isBootstrap5()))->toArray();
diff --git a/src/Traits/Helpers/FilterHelpers.php b/src/Traits/Helpers/FilterHelpers.php
index c42fdeac2..2ee7ed3db 100644
--- a/src/Traits/Helpers/FilterHelpers.php
+++ b/src/Traits/Helpers/FilterHelpers.php
@@ -63,21 +63,6 @@ public function filtersVisibilityIsDisabled(): bool
return $this->getFiltersVisibilityStatus() === false;
}
- public function getFilterSlideDownDefaultStatus(): bool
- {
- return $this->filterSlideDownDefaultVisible;
- }
-
- public function filtersSlideDownIsDefaultVisible(): bool
- {
- return $this->getFilterSlideDownDefaultStatus() === true;
- }
-
- public function filtersSlideDownIsDefaultHidden(): bool
- {
- return $this->getFilterSlideDownDefaultStatus() === false;
- }
-
public function getFilterPillsStatus(): bool
{
return $this->filterPillsStatus;
@@ -273,31 +258,6 @@ public function resetFilter($filter): void
}
- public function getFilterLayout(): string
- {
- return $this->filterLayout;
- }
-
- public function isFilterLayoutPopover(): bool
- {
- return $this->getFilterLayout() === 'popover';
- }
-
- public function isFilterLayoutSlideDown(): bool
- {
- return $this->getFilterLayout() === 'slide-down';
- }
-
- /**
- * Get whether any filter has a configured slide down row.
- */
- public function hasFiltersWithSlidedownRows(): bool
- {
- return $this->getFilters()
- ->reject(fn (Filter $filter) => ! $filter->hasFilterSlidedownRow())
- ->count() > 0;
- }
-
/**
* Get whether filter has a configured slide down row.
*/
@@ -306,38 +266,6 @@ public function getVisibleFilters(): Collection
return $this->getFilters()->reject(fn (Filter $filter) => $filter->isHiddenFromMenus());
}
- /**
- * Get filters sorted by row
- *
- * @return array
- */
- public function getFiltersByRow(): array
- {
- $orderedFilters = [];
- $filterList = ($this->hasFiltersWithSlidedownRows()) ? $this->getVisibleFilters()->sortBy('filterSlidedownRow') : $this->getVisibleFilters();
- if ($this->hasFiltersWithSlidedownRows()) {
- foreach ($filterList as $filter) {
- $orderedFilters[(string) $filter->getFilterSlidedownRow()][] = $filter;
- }
-
- if (empty($orderedFilters['1'])) {
- $orderedFilters['1'] = (isset($orderedFilters['99']) ? $orderedFilters['99'] : []);
- if (isset($orderedFilters['99'])) {
- unset($orderedFilters['99']);
- }
- }
- } else {
- $orderedFilters = Arr::wrap($filterList);
- $orderedFilters['1'] = $orderedFilters['0'] ?? [];
- if (isset($orderedFilters['0'])) {
- unset($orderedFilters['0']);
- }
- }
- ksort($orderedFilters);
-
- return $orderedFilters;
- }
-
public function hasFilterGenericData(): bool
{
return ! empty($this->filterGenericData);
diff --git a/src/Traits/Styling/Configuration/FilterMenuStylingConfiguration.php b/src/Traits/Styling/Configuration/FilterMenuStylingConfiguration.php
new file mode 100644
index 000000000..92d8ba467
--- /dev/null
+++ b/src/Traits/Styling/Configuration/FilterMenuStylingConfiguration.php
@@ -0,0 +1,64 @@
+filterPopoverAttributes = array_merge($this->filterPopoverAttributes, $filterPopoverAttributes);
+
+ return $this;
+ }
+
+ public function setFilterLayout(string $type): self
+ {
+ if (! in_array($type, ['popover', 'slide-down'], true)) {
+ throw new DataTableConfigurationException('Invalid filter layout type');
+ }
+
+ $this->filterLayout = $type;
+
+ return $this;
+ }
+
+ public function setFilterLayoutPopover(): self
+ {
+ $this->setFilterLayout('popover');
+
+ return $this;
+ }
+
+ public function setFilterLayoutSlideDown(): self
+ {
+ $this->setFilterLayout('slide-down');
+
+ return $this;
+ }
+
+ public function setFilterSlideDownDefaultStatus(bool $status): self
+ {
+ $this->filterSlideDownDefaultVisible = $status;
+
+ return $this;
+ }
+
+ public function setFilterSlideDownDefaultStatusDisabled(): self
+ {
+ $this->setFilterSlideDownDefaultStatus(false);
+
+ return $this;
+ }
+
+ public function setFilterSlideDownDefaultStatusEnabled(): self
+ {
+ $this->setFilterSlideDownDefaultStatus(true);
+
+ return $this;
+ }
+}
diff --git a/src/Traits/Styling/HasFilterMenuStyling.php b/src/Traits/Styling/HasFilterMenuStyling.php
new file mode 100644
index 000000000..c534027e4
--- /dev/null
+++ b/src/Traits/Styling/HasFilterMenuStyling.php
@@ -0,0 +1,21 @@
+ '', 'default-width' => true, 'default-colors' => true, 'default-styling' => true];
+}
diff --git a/src/Traits/Styling/Helpers/FilterMenuStylingHelpers.php b/src/Traits/Styling/Helpers/FilterMenuStylingHelpers.php
new file mode 100644
index 000000000..d5ddf6d6c
--- /dev/null
+++ b/src/Traits/Styling/Helpers/FilterMenuStylingHelpers.php
@@ -0,0 +1,94 @@
+
+ */
+ #[Computed]
+ public function getFilterPopoverAttributes(): array
+ {
+ return $this->filterPopoverAttributes;
+
+ }
+
+ public function getFilterSlideDownDefaultStatus(): bool
+ {
+ return $this->filterSlideDownDefaultVisible;
+ }
+
+ public function filtersSlideDownIsDefaultVisible(): bool
+ {
+ return $this->getFilterSlideDownDefaultStatus() === true;
+ }
+
+ public function filtersSlideDownIsDefaultHidden(): bool
+ {
+ return $this->getFilterSlideDownDefaultStatus() === false;
+ }
+
+ public function getFilterLayout(): string
+ {
+ return $this->filterLayout;
+ }
+
+ public function isFilterLayoutPopover(): bool
+ {
+ return $this->getFilterLayout() === 'popover';
+ }
+
+ public function isFilterLayoutSlideDown(): bool
+ {
+ return $this->getFilterLayout() === 'slide-down';
+ }
+
+ /**
+ * Get whether any filter has a configured slide down row.
+ */
+ public function hasFiltersWithSlidedownRows(): bool
+ {
+ return $this->getFilters()
+ ->reject(fn (Filter $filter) => ! $filter->hasFilterSlidedownRow())
+ ->count() > 0;
+ }
+
+ /**
+ * Get filters sorted by row
+ *
+ * @return array
+ */
+ public function getFiltersByRow(): array
+ {
+ $orderedFilters = [];
+ $filterList = ($this->hasFiltersWithSlidedownRows()) ? $this->getVisibleFilters()->sortBy('filterSlidedownRow') : $this->getVisibleFilters();
+ if ($this->hasFiltersWithSlidedownRows()) {
+ foreach ($filterList as $filter) {
+ $orderedFilters[(string) $filter->getFilterSlidedownRow()][] = $filter;
+ }
+
+ if (empty($orderedFilters['1'])) {
+ $orderedFilters['1'] = (isset($orderedFilters['99']) ? $orderedFilters['99'] : []);
+ if (isset($orderedFilters['99'])) {
+ unset($orderedFilters['99']);
+ }
+ }
+ } else {
+ $orderedFilters = Arr::wrap($filterList);
+ $orderedFilters['1'] = $orderedFilters['0'] ?? [];
+ if (isset($orderedFilters['0'])) {
+ unset($orderedFilters['0']);
+ }
+ }
+ ksort($orderedFilters);
+
+ return $orderedFilters;
+ }
+}
diff --git a/src/Traits/WithFilters.php b/src/Traits/WithFilters.php
index e9469ea44..140ae6d0b 100644
--- a/src/Traits/WithFilters.php
+++ b/src/Traits/WithFilters.php
@@ -9,12 +9,14 @@
use Rappasoft\LaravelLivewireTables\Traits\Configuration\FilterConfiguration;
use Rappasoft\LaravelLivewireTables\Traits\Core\QueryStrings\HasQueryStringForFilter;
use Rappasoft\LaravelLivewireTables\Traits\Helpers\FilterHelpers;
+use Rappasoft\LaravelLivewireTables\Traits\Styling\HasFilterMenuStyling;
trait WithFilters
{
use FilterConfiguration,
FilterHelpers;
use HasQueryStringForFilter;
+ use HasFilterMenuStyling;
#[Locked]
public bool $filtersStatus = true;
@@ -25,12 +27,6 @@ trait WithFilters
#[Locked]
public bool $filterPillsStatus = true;
- // Entangled in JS
- public bool $filterSlideDownDefaultVisible = false;
-
- #[Locked]
- public string $filterLayout = 'popover';
-
#[Locked]
public int $filterCount;
diff --git a/tests/Unit/Traits/Styling/FilterPopoverStylingTest.php b/tests/Unit/Traits/Styling/FilterPopoverStylingTest.php
new file mode 100644
index 000000000..886ae1956
--- /dev/null
+++ b/tests/Unit/Traits/Styling/FilterPopoverStylingTest.php
@@ -0,0 +1,27 @@
+assertSame(['class' => '', 'default-width' => true, 'default-colors' => true, 'default-styling' => true], $this->basicTable->getFilterPopoverAttributes());
+ }
+
+ public function test_filter_popover_attributes_can_be_changed(): void
+ {
+ $this->assertSame(['class' => '', 'default-width' => true, 'default-colors' => true, 'default-styling' => true], $this->basicTable->getFilterPopoverAttributes());
+
+ $this->basicTable->setFilterPopoverAttributes(['class' => 'bg-blue-500']);
+
+ $this->assertSame(['class' => 'bg-blue-500', 'default-width' => true, 'default-colors' => true, 'default-styling' => true], $this->basicTable->getFilterPopoverAttributes());
+
+ $this->basicTable->setFilterPopoverAttributes(['class' => 'bg-red-500', 'default-colors' => false]);
+
+ $this->assertSame(['class' => 'bg-red-500', 'default-width' => true, 'default-colors' => false, 'default-styling' => true], $this->basicTable->getFilterPopoverAttributes());
+
+ }
+}
diff --git a/tests/Unit/Traits/Visuals/FilterVisualsTest.php b/tests/Unit/Traits/Visuals/FilterVisualsTest.php
index 09b27ab9c..d55a00cb0 100644
--- a/tests/Unit/Traits/Visuals/FilterVisualsTest.php
+++ b/tests/Unit/Traits/Visuals/FilterVisualsTest.php
@@ -161,6 +161,66 @@ public function filters(): array
]);
}
+ public function test_filters_popover_menu_is_customisable(): void
+ {
+ Livewire::test(new class extends PetsTable
+ {
+ public function configure(): void
+ {
+ $this->setPrimaryKey('id');
+
+ }
+
+ public function filters(): array
+ {
+ return [
+ \Rappasoft\LaravelLivewireTables\Views\Filters\MultiSelectFilter::make('Breed')
+ ->options(
+ \Rappasoft\LaravelLivewireTables\Tests\Models\Breed::query()
+ ->orderBy('name')
+ ->get()
+ ->keyBy('id')
+ ->map(fn ($breed) => $breed->name)
+ ->toArray()
+ )
+ ->filter(function (\Illuminate\Database\Eloquent\Builder $builder, array $values) {
+ return $builder->whereIn('pets.breed_id', $values);
+ }),
+ \Rappasoft\LaravelLivewireTables\Views\Filters\MultiSelectDropdownFilter::make('Species')
+ ->options(
+ \Rappasoft\LaravelLivewireTables\Tests\Models\Species::query()
+ ->orderBy('name')
+ ->get()
+ ->keyBy('id')
+ ->map(fn ($species) => $species->name)
+ ->toArray()
+ )
+ ->filter(function (\Illuminate\Database\Eloquent\Builder $builder, array $values) {
+ return $builder->whereIn('pets.species_id', $values);
+ })
+ ->setPillsSeparator(' '),
+
+ \Rappasoft\LaravelLivewireTables\Views\Filters\TextFilter::make('Pet Name', 'pet_name_filter')
+ ->filter(function (\Illuminate\Database\Eloquent\Builder $builder, string $value) {
+ return $builder->where('pets.name', '=', $value);
+ }),
+ ];
+ }
+ })
+ ->assertSeeHtmlInOrder([
+ 'class="w-full md:w-56 origin-top-left absolute left-0 mt-2 rounded-md shadow-lg ring-1 ring-opacity-5 divide-y focus:outline-none z-50 bg-white divide-gray-100 ring-black dark:bg-gray-700 dark:text-white dark:divide-gray-600"',
+ ])
+ ->call('setFilterPopoverAttributes', ['class' => 'w-96', 'default-width' => false])
+ ->assertSeeHtmlInOrder([
+ 'class="origin-top-left absolute left-0 mt-2 rounded-md shadow-lg ring-1 ring-opacity-5 divide-y focus:outline-none z-50 bg-white divide-gray-100 ring-black dark:bg-gray-700 dark:text-white dark:divide-gray-600 w-96"',
+ ])
+ ->call('setFilterPopoverAttributes', ['class' => 'w-96', 'default-width' => false, 'default-colors' => false])
+ ->assertSeeHtmlInOrder([
+ 'class="origin-top-left absolute left-0 mt-2 rounded-md shadow-lg ring-1 ring-opacity-5 divide-y focus:outline-none z-50 w-96"',
+ ]);
+
+ }
+
/*public function test_filter_events_apply_correctly(): void
{
Livewire::test(PetsTable::class)