Merge branch '4.x' into pr/17180

This commit is contained in:
Dan Harrin
2025-08-04 09:06:35 +01:00
12 changed files with 83 additions and 7 deletions
+18
View File
@@ -552,6 +552,24 @@ public function panel(Panel $panel): Panel
}
```
### Replacing the sidebar and topbar Livewire components
You may completely replace the Livewire components that are used to render the sidebar and topbar, passing your own Livewire component class name into the `sidebarLivewireComponent()` or `topbarLivewireComponent()` method:
```php
use App\Livewire\Sidebar;
use App\Livewire\Topbar;
use Filament\Panel;
public function panel(Panel $panel): Panel
{
return $panel
// ...
->sidebarLivewireComponent(Sidebar::class)
->topbarLivewireComponent(Topbar::class);
}
```
## Disabling breadcrumbs
The default layout will show breadcrumbs to indicate the location of the current page within the hierarchy of the app.
@@ -10,7 +10,7 @@ return [
'login' => [
'before' => 'یا',
'label' => 'وارد حساب خود شوید.',
'label' => 'ورود به حساب کاربری',
],
],
@@ -28,7 +28,7 @@
@if ($hasTopbar)
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::TOPBAR_BEFORE, scopes: $renderHookScopes) }}
@livewire(\Filament\Livewire\Topbar::class)
@livewire(filament()->getTopbarLivewireComponent())
{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::TOPBAR_AFTER, scopes: $renderHookScopes) }}
@endif
+1 -1
View File
@@ -73,7 +73,7 @@ class Register extends SimplePage
return null;
}
$user = $this->wrapInDatabaseTransaction(function () {
$user = $this->wrapInDatabaseTransaction(function (): Model {
$this->callHook('beforeValidate');
$data = $this->form->getState();
+2
View File
@@ -26,6 +26,7 @@ use Illuminate\Contracts\Auth\StatefulGuard;
use Illuminate\Contracts\Support\Htmlable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Facade;
use Livewire\Component;
/**
* @method static bool arePasswordsRevealable()
@@ -105,6 +106,7 @@ use Illuminate\Support\Facades\Facade;
* @method static string | null getTenantProfileUrl(array<string, mixed> $parameters = [])
* @method static string | null getTenantRegistrationUrl(array<string, mixed> $parameters = [])
* @method static Theme getTheme()
* @method static class-string<Component> getTopbarLivewireComponent()
* @method static ThemeMode getDefaultThemeMode()
* @method static string | null getUserAvatarUrl(Model | Authenticatable $user)
* @method static Model | null getUserDefaultTenant(HasTenants | Model | Authenticatable $user)
+12
View File
@@ -34,6 +34,7 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Event;
use Livewire\Component;
class FilamentManager
{
@@ -488,11 +489,22 @@ class FilamentManager
return $this->getCurrentOrDefaultPanel()->getProfilePage();
}
/**
* @return class-string<Component>
*/
public function getSidebarLivewireComponent(): string
{
return $this->getCurrentOrDefaultPanel()->getSidebarLivewireComponent();
}
/**
* @return class-string<Component>
*/
public function getTopbarLivewireComponent(): string
{
return $this->getCurrentOrDefaultPanel()->getTopbarLivewireComponent();
}
public function getTenantProfilePage(): ?string
{
return $this->getCurrentOrDefaultPanel()->getTenantProfilePage();
@@ -8,7 +8,6 @@ use Filament\Clusters\Cluster;
use Filament\Livewire\GlobalSearch;
use Filament\Livewire\Notifications;
use Filament\Livewire\SimpleUserMenu;
use Filament\Livewire\Topbar;
use Filament\Pages\Page;
use Filament\Resources\Pages\Page as ResourcePage;
use Filament\Resources\RelationManagers\RelationGroup;
@@ -492,7 +491,7 @@ trait HasComponents
$this->queueLivewireComponentForRegistration(Notifications::class);
$this->queueLivewireComponentForRegistration($this->getSidebarLivewireComponent());
$this->queueLivewireComponentForRegistration(SimpleUserMenu::class);
$this->queueLivewireComponentForRegistration(Topbar::class);
$this->queueLivewireComponentForRegistration($this->getTopbarLivewireComponent());
if ($this->hasEmailVerification() && is_subclass_of($emailVerificationPromptRouteAction = $this->getEmailVerificationPromptRouteAction(), Component::class)) {
$this->queueLivewireComponentForRegistration($emailVerificationPromptRouteAction);
@@ -3,11 +3,15 @@
namespace Filament\Panel\Concerns;
use Closure;
use Filament\Livewire\Topbar;
use Livewire\Component;
trait HasTopbar
{
protected bool | Closure $hasTopbar = true;
protected string | Closure | null $topbarLivewireComponent = null;
public function topbar(bool | Closure $condition = true): static
{
$this->hasTopbar = $condition;
@@ -15,8 +19,26 @@ trait HasTopbar
return $this;
}
/**
* @param class-string<Component> | Closure | null $component
*/
public function topbarLivewireComponent(string | Closure | null $component): static
{
$this->topbarLivewireComponent = $component;
return $this;
}
public function hasTopbar(): bool
{
return (bool) $this->evaluate($this->hasTopbar);
}
/**
* @return class-string<Component>
*/
public function getTopbarLivewireComponent(): string
{
return $this->evaluate($this->topbarLivewireComponent) ?? Topbar::class;
}
}
+12
View File
@@ -387,6 +387,18 @@ public function table(Table $table): Table
}
```
You can pass a `direction` parameter as `desc` to reorder the records in descending order instead of ascending:
```php
use Filament\Tables\Table;
public function table(Table $table): Table
{
return $table
->reorderable('sort', direction: 'desc');
}
```
### Enabling pagination while reordering
Pagination will be disabled in reorder mode to allow you to move records between pages. It is generally a bad experience to have pagination while reordering, but if would like to override this use `$table->paginatedWhileReordering()`:
@@ -4,6 +4,7 @@ namespace Filament\Tables\Concerns;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Query\Expression;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
trait CanReorderRecords
@@ -45,6 +46,7 @@ trait CanReorderRecords
->update([
$orderColumn => new Expression(
'case ' . collect($order)
->when($this->getTable()->getReorderDirection() === 'desc', fn (Collection $order) => $order->reverse()->values())
->map(fn ($recordKey, int $recordIndex): string => 'when ' . $wrappedModelKeyName . ' = ' . DB::getPdo()->quote($recordKey) . ' then ' . ($recordIndex + 1))
->implode(' ') . ' end'
),
@@ -74,7 +74,7 @@ trait CanSortRecords
}
if ($this->isTableReordering()) {
return $query->orderBy($this->getTable()->getReorderColumn());
return $query->orderBy($this->getTable()->getReorderColumn(), $this->getTable()->getReorderDirection());
}
if (
@@ -19,6 +19,8 @@ trait CanReorderRecords
protected string | Closure | null $reorderColumn = null;
protected string | Closure | null $reorderDirection = null;
protected ?Closure $modifyReorderRecordsTriggerActionUsing = null;
public function reorderRecordsTriggerAction(?Closure $callback): static
@@ -28,7 +30,7 @@ trait CanReorderRecords
return $this;
}
public function reorderable(string | Closure | null $column = null, bool | Closure | null $condition = null): static
public function reorderable(string | Closure | null $column = null, bool | Closure | null $condition = null, string | Closure | null $direction = null): static
{
$this->reorderColumn = $column;
@@ -36,6 +38,8 @@ trait CanReorderRecords
$this->isReorderable = $condition;
}
$this->reorderDirection = $direction;
return $this;
}
@@ -72,6 +76,11 @@ trait CanReorderRecords
return $this->evaluate($this->reorderColumn);
}
public function getReorderDirection(): string
{
return $this->evaluate($this->reorderDirection) ?? 'asc';
}
public function isReorderable(): bool
{
return filled($this->getReorderColumn()) && $this->evaluate($this->isReorderable) && $this->isReorderAuthorized();