diff --git a/docs-assets/app/app/Livewire/TablesDemo.php b/docs-assets/app/app/Livewire/TablesDemo.php index 6ff3bfe7d5..1ede8b1c16 100644 --- a/docs-assets/app/app/Livewire/TablesDemo.php +++ b/docs-assets/app/app/Livewire/TablesDemo.php @@ -41,6 +41,7 @@ use Filament\Tables\Contracts\HasTable; use Filament\Tables\Enums\ActionsPosition; use Filament\Tables\Enums\FiltersLayout; use Filament\Tables\Filters\Filter; +use Filament\Tables\Filters\Indicator; use Filament\Tables\Filters\SelectFilter; use Filament\Tables\Grouping\Group; use Filament\Tables\Table; @@ -709,8 +710,10 @@ class TablesDemo extends Component implements HasForms, HasTable ->filters([ Filter::make('dummy') ->indicateUsing(fn () => [ - 'one' => 'Posted by administrator', - 'two' => 'Less than 1 year old', + Indicator::make('Posted by administrator') + ->removeField('one'), + Indicator::make('Less than 1 year old') + ->removeField('two'), ]), ]); } diff --git a/packages/tables/docs/04-filters.md b/packages/tables/docs/04-filters.md index 38b5b3330b..1f27ed5844 100644 --- a/packages/tables/docs/04-filters.md +++ b/packages/tables/docs/04-filters.md @@ -345,6 +345,7 @@ You may even render multiple indicators at once, by returning an array. If you h ```php use Filament\Forms\Components\DatePicker; use Filament\Tables\Filters\Filter; +use Filament\Tables\Filters\Indicator; Filter::make('created_at') ->form([ @@ -356,11 +357,13 @@ Filter::make('created_at') $indicators = []; if ($data['from'] ?? null) { - $indicators['from'] = 'Created from ' . Carbon::parse($data['from'])->toFormattedDateString(); + $indicators[] = Indicator::make('Created from ' . Carbon::parse($data['from'])->toFormattedDateString()) + ->removeField('from'); } if ($data['until'] ?? null) { - $indicators['until'] = 'Created until ' . Carbon::parse($data['until'])->toFormattedDateString(); + $indicators[] = Indicator::make('Created until ' . Carbon::parse($data['until'])->toFormattedDateString()) + ->removeField('until'); } return $indicators; diff --git a/packages/tables/resources/views/components/filters/indicators.blade.php b/packages/tables/resources/views/components/filters/indicators.blade.php index 1dbb729bc9..929921a562 100644 --- a/packages/tables/resources/views/components/filters/indicators.blade.php +++ b/packages/tables/resources/views/components/filters/indicators.blade.php @@ -13,17 +13,19 @@
- @foreach ($indicators as $wireClickHandler => $label) - - {{ $label }} + @foreach ($indicators as $indicator) + + {{ $indicator->getLabel() }} - + @if ($indicator->isRemovable()) + + @endif @endforeach
diff --git a/packages/tables/resources/views/index.blade.php b/packages/tables/resources/views/index.blade.php index 3ad8ddc7b8..98833dc765 100644 --- a/packages/tables/resources/views/index.blade.php +++ b/packages/tables/resources/views/index.blade.php @@ -14,26 +14,7 @@ $content = $getContent(); $contentGrid = $getContentGrid(); $contentFooter = $getContentFooter(); - $filterIndicators = [ - ...($hasSearch() ? ['resetTableSearch' => $getSearchIndicator()] : []), - ...collect($getColumnSearchIndicators()) - ->mapWithKeys(fn (string $indicator, string $column): array => [ - "resetTableColumnSearch('{$column}')" => $indicator, - ]) - ->all(), - ...array_reduce( - $getFilters(), - fn (array $carry, \Filament\Tables\Filters\BaseFilter $filter): array => [ - ...$carry, - ...collect($filter->getIndicators()) - ->mapWithKeys(fn (string $label, int | string $field) => [ - "removeTableFilter('{$filter->getName()}'" . (is_string($field) ? ' , \'' . $field . '\'' : null) . ')' => $label, - ]) - ->all(), - ], - [], - ), - ]; + $filterIndicators = $getFilterIndicators(); $hasColumnsLayout = $hasColumnsLayout(); $hasSummary = $hasSummary(); $header = $getHeader(); diff --git a/packages/tables/src/Concerns/CanSearchRecords.php b/packages/tables/src/Concerns/CanSearchRecords.php index cdfa1487f6..ea746accb0 100644 --- a/packages/tables/src/Concerns/CanSearchRecords.php +++ b/packages/tables/src/Concerns/CanSearchRecords.php @@ -2,6 +2,7 @@ namespace Filament\Tables\Concerns; +use Filament\Tables\Filters\Indicator; use Illuminate\Database\Eloquent\Builder; use Illuminate\Support\Arr; use RecursiveArrayIterator; @@ -174,13 +175,14 @@ trait CanSearchRecords $this->updatedTableColumnSearches(); } - public function getTableSearchIndicator(): string + public function getTableSearchIndicator(): Indicator { - return __('filament-tables::table.fields.search.indicator') . ': ' . $this->getTableSearch(); + return Indicator::make(__('filament-tables::table.fields.search.indicator') . ': ' . $this->getTableSearch()) + ->removeLivewireClickHandler('resetTableSearch'); } /** - * @return array + * @return array */ public function getTableColumnSearchIndicators(): array { @@ -203,7 +205,8 @@ trait CanSearchRecords continue; } - $indicators[$columnName] = "{$column->getLabel()}: {$search}"; + $indicators[] = Indicator::make("{$column->getLabel()}: {$search}") + ->removeLivewireClickHandler("resetTableColumnSearch('{$columnName}')"); } return $indicators; diff --git a/packages/tables/src/Contracts/HasTable.php b/packages/tables/src/Contracts/HasTable.php index 5c23dff9af..4cbcf61baf 100644 --- a/packages/tables/src/Contracts/HasTable.php +++ b/packages/tables/src/Contracts/HasTable.php @@ -6,6 +6,7 @@ use Filament\Forms\Form; use Filament\Support\Contracts\TranslatableContentDriver; use Filament\Tables\Actions\Action; use Filament\Tables\Actions\BulkAction; +use Filament\Tables\Filters\Indicator; use Filament\Tables\Grouping\Group; use Filament\Tables\Table; use Illuminate\Contracts\Pagination\Paginator; @@ -93,10 +94,10 @@ interface HasTable public function resetTableColumnSearch(string $column): void; - public function getTableSearchIndicator(): string; + public function getTableSearchIndicator(): Indicator; /** - * @return array + * @return array */ public function getTableColumnSearchIndicators(): array; diff --git a/packages/tables/src/Filters/Concerns/HasIndicators.php b/packages/tables/src/Filters/Concerns/HasIndicators.php index 20c4bddd5b..19d3b885c4 100644 --- a/packages/tables/src/Filters/Concerns/HasIndicators.php +++ b/packages/tables/src/Filters/Concerns/HasIndicators.php @@ -3,15 +3,16 @@ namespace Filament\Tables\Filters\Concerns; use Closure; +use Filament\Tables\Filters\Indicator; use Illuminate\Support\Arr; trait HasIndicators { protected string | Closure | null $indicateUsing = null; - protected string | Closure | null $indicator = null; + protected Indicator | string | Closure | null $indicator = null; - public function indicator(string | Closure | null $indicator): static + public function indicator(Indicator | string | Closure | null $indicator): static { $this->indicator = $indicator; @@ -26,7 +27,7 @@ trait HasIndicators } /** - * @return array + * @return array */ public function getIndicators(): array { @@ -41,10 +42,24 @@ trait HasIndicators return []; } - return Arr::wrap($indicators); + $indicators = Arr::wrap($indicators); + + foreach ($indicators as $field => $indicator) { + if (! $indicator instanceof Indicator) { + $indicator = Indicator::make($indicator); + } + + if (is_string($field)) { + $indicator = $indicator->removeField($field); + } + + $indicators[$field] = $indicator; + } + + return $indicators; } - public function getIndicator(): string + public function getIndicator(): Indicator | string { $state = $this->getState(); diff --git a/packages/tables/src/Filters/Filter.php b/packages/tables/src/Filters/Filter.php index 72e64debb0..4412a28b31 100644 --- a/packages/tables/src/Filters/Filter.php +++ b/packages/tables/src/Filters/Filter.php @@ -19,7 +19,13 @@ class Filter extends BaseFilter return []; } - return [$this->getIndicator()]; + $indicator = $this->getIndicator(); + + if (! $indicator instanceof Indicator) { + $indicator = Indicator::make($indicator); + } + + return [$indicator]; }); } diff --git a/packages/tables/src/Filters/Indicator.php b/packages/tables/src/Filters/Indicator.php new file mode 100644 index 0000000000..12102245ab --- /dev/null +++ b/packages/tables/src/Filters/Indicator.php @@ -0,0 +1,78 @@ +label($label); + } + + public static function make(string | Closure | null $label = null): static + { + return app(static::class, ['label' => $label]); + } + + public function label(string $label): static + { + $this->label = $label; + + return $this; + } + + public function getLabel(): string + { + return $this->label; + } + + public function removable(bool | Closure $condition = true): static + { + $this->isRemovable = $condition; + + return $this; + } + + public function isRemovable(): bool + { + return (bool) $this->evaluate($this->isRemovable); + } + + public function removeField(string | Closure | null $name): static + { + $this->removeField = $name; + + return $this; + } + + public function getRemoveField(): ?string + { + return $this->evaluate($this->removeField); + } + + public function removeLivewireClickHandler(string | Closure | null $handler): static + { + $this->removeLivewireClickHandler = $handler; + + return $this; + } + + public function getRemoveLivewireClickHandler(): ?string + { + return $this->evaluate($this->removeLivewireClickHandler); + } +} diff --git a/packages/tables/src/Filters/SelectFilter.php b/packages/tables/src/Filters/SelectFilter.php index 76af930a66..eb1d6cdccb 100644 --- a/packages/tables/src/Filters/SelectFilter.php +++ b/packages/tables/src/Filters/SelectFilter.php @@ -66,7 +66,13 @@ class SelectFilter extends BaseFilter $labels = collect($labels)->join(', ', ' & '); - return ["{$filter->getIndicator()}: {$labels}"]; + $indicator = $filter->getIndicator(); + + if (! $indicator instanceof Indicator) { + $indicator = Indicator::make("{$indicator}: {$labels}"); + } + + return [$indicator]; } if (blank($state['value'] ?? null)) { @@ -86,7 +92,13 @@ class SelectFilter extends BaseFilter return []; } - return ["{$filter->getIndicator()}: {$label}"]; + $indicator = $filter->getIndicator(); + + if (! $indicator instanceof Indicator) { + $indicator = Indicator::make("{$indicator}: {$label}"); + } + + return [$indicator]; }); $this->resetState(['value' => null]); diff --git a/packages/tables/src/Filters/TernaryFilter.php b/packages/tables/src/Filters/TernaryFilter.php index 9858a0a526..a1fc9daac4 100644 --- a/packages/tables/src/Filters/TernaryFilter.php +++ b/packages/tables/src/Filters/TernaryFilter.php @@ -22,16 +22,22 @@ class TernaryFilter extends SelectFilter $this->boolean(); - $this->indicateUsing(function (array $state): array { + $this->indicateUsing(function (TernaryFilter $filter, array $state): array { if (blank($state['value'] ?? null)) { return []; } $stateLabel = $state['value'] ? - $this->getTrueLabel() : - $this->getFalseLabel(); + $filter->getTrueLabel() : + $filter->getFalseLabel(); - return ["{$this->getIndicator()}: {$stateLabel}"]; + $indicator = $filter->getIndicator(); + + if (! $indicator instanceof Indicator) { + $indicator = Indicator::make("{$indicator}: {$stateLabel}"); + } + + return [$indicator]; }); } diff --git a/packages/tables/src/Filters/TrashedFilter.php b/packages/tables/src/Filters/TrashedFilter.php index 17b7235b2c..5aa99f3fb7 100644 --- a/packages/tables/src/Filters/TrashedFilter.php +++ b/packages/tables/src/Filters/TrashedFilter.php @@ -36,14 +36,14 @@ class TrashedFilter extends TernaryFilter $this->indicateUsing(function (array $state): array { if ($state['value'] ?? null) { - return [$this->getTrueLabel()]; + return [Indicator::make($this->getTrueLabel())]; } if (blank($state['value'] ?? null)) { return []; } - return [$this->getFalseLabel()]; + return [Indicator::make($this->getFalseLabel())]; }); } } diff --git a/packages/tables/src/Table.php b/packages/tables/src/Table.php index 46dbf203ab..92fea794a7 100644 --- a/packages/tables/src/Table.php +++ b/packages/tables/src/Table.php @@ -23,6 +23,7 @@ class Table extends ViewComponent use Table\Concerns\HasColumns; use Table\Concerns\HasContent; use Table\Concerns\HasEmptyState; + use Table\Concerns\HasFilterIndicators; use Table\Concerns\HasFilters; use Table\Concerns\HasHeader; use Table\Concerns\HasHeaderActions; diff --git a/packages/tables/src/Table/Concerns/CanSearchRecords.php b/packages/tables/src/Table/Concerns/CanSearchRecords.php index 8634fbbe01..2b9b39d6dd 100644 --- a/packages/tables/src/Table/Concerns/CanSearchRecords.php +++ b/packages/tables/src/Table/Concerns/CanSearchRecords.php @@ -3,6 +3,7 @@ namespace Filament\Tables\Table\Concerns; use Closure; +use Filament\Tables\Filters\Indicator; trait CanSearchRecords { @@ -79,13 +80,13 @@ trait CanSearchRecords return $this->getLivewire()->hasTableSearch(); } - public function getSearchIndicator(): string + public function getSearchIndicator(): Indicator { return $this->getLivewire()->getTableSearchIndicator(); } /** - * @return array + * @return array | array */ public function getColumnSearchIndicators(): array { diff --git a/packages/tables/src/Table/Concerns/HasFilterIndicators.php b/packages/tables/src/Table/Concerns/HasFilterIndicators.php new file mode 100644 index 0000000000..af7c6e6bbb --- /dev/null +++ b/packages/tables/src/Table/Concerns/HasFilterIndicators.php @@ -0,0 +1,34 @@ + + */ + public function getFilterIndicators(): array + { + return [ + ...($this->hasSearch() ? [$this->getSearchIndicator()] : []), + ...$this->getColumnSearchIndicators(), + ...array_reduce( + $this->getFilters(), + fn (array $carry, BaseFilter $filter): array => [ + ...$carry, + ...collect($filter->getIndicators()) + ->map(function (Indicator $indicator) use ($filter): Indicator { + $removeField = $indicator->getRemoveField(); + + return $indicator->removeLivewireClickHandler("removeTableFilter('{$filter->getName()}'" . (filled($removeField) ? ', \'' . $removeField . '\'' : null) . ')'); + }) + ->all(), + ], + [], + ), + ]; + } +}