diff --git a/packages/forms/resources/views/components/field-wrapper/helper-text.blade.php b/packages/forms/resources/views/components/field-wrapper/helper-text.blade.php
index a8e1ec60b5..a7f2fcc5e3 100644
--- a/packages/forms/resources/views/components/field-wrapper/helper-text.blade.php
+++ b/packages/forms/resources/views/components/field-wrapper/helper-text.blade.php
@@ -1,5 +1,5 @@
class(['fi-fo-field-wrp-helper-text break-words text-sm text-gray-500']) }}
+ {{ $attributes->class(['fi-fo-field-wrp-helper-text break-words text-sm text-gray-500 dark:text-gray-400']) }}
>
{{ $slot }}
diff --git a/packages/forms/resources/views/components/field-wrapper/hint.blade.php b/packages/forms/resources/views/components/field-wrapper/hint.blade.php
index 4555abbd56..82ab10d808 100644
--- a/packages/forms/resources/views/components/field-wrapper/hint.blade.php
+++ b/packages/forms/resources/views/components/field-wrapper/hint.blade.php
@@ -17,7 +17,7 @@
@class([
'fi-fo-field-wrp-hint-label',
match ($color) {
- 'gray' => 'text-gray-500',
+ 'gray' => 'text-gray-500 dark:text-gray-400',
default => 'fi-color-custom text-custom-600 dark:text-custom-400',
},
is_string($color) ? "fi-color-{$color}" : null,
diff --git a/packages/infolists/resources/views/components/entry-wrapper/helper-text.blade.php b/packages/infolists/resources/views/components/entry-wrapper/helper-text.blade.php
index b8ea4bea6a..1453669af9 100644
--- a/packages/infolists/resources/views/components/entry-wrapper/helper-text.blade.php
+++ b/packages/infolists/resources/views/components/entry-wrapper/helper-text.blade.php
@@ -1,5 +1,5 @@
class(['fi-in-entry-wrp-helper-text break-words text-sm text-gray-500']) }}
+ {{ $attributes->class(['fi-in-entry-wrp-helper-text break-words text-sm text-gray-500 dark:text-gray-400']) }}
>
{{ $slot }}
diff --git a/packages/infolists/resources/views/components/entry-wrapper/hint.blade.php b/packages/infolists/resources/views/components/entry-wrapper/hint.blade.php
index d13075c9b5..4d43399107 100644
--- a/packages/infolists/resources/views/components/entry-wrapper/hint.blade.php
+++ b/packages/infolists/resources/views/components/entry-wrapper/hint.blade.php
@@ -17,7 +17,7 @@
@class([
'fi-in-entry-wrp-hint-label',
match ($color) {
- 'gray' => 'text-gray-500',
+ 'gray' => 'text-gray-500 dark:text-gray-400',
default => 'fi-color-custom text-custom-600 dark:text-custom-400',
},
is_string($color) ? "fi-color-{$color}" : null,
diff --git a/packages/panels/resources/lang/de/pages/auth/password-reset/request-password-reset.php b/packages/panels/resources/lang/de/pages/auth/password-reset/request-password-reset.php
index 1f3a49b508..95f3f6c41e 100644
--- a/packages/panels/resources/lang/de/pages/auth/password-reset/request-password-reset.php
+++ b/packages/panels/resources/lang/de/pages/auth/password-reset/request-password-reset.php
@@ -31,6 +31,9 @@ return [
],
'notifications' => [
+ 'sent' => [
+ 'body' => 'Wenn Ihr Konto nicht existiert, erhalten Sie keine E-Mail.',
+ ],
'throttled' => [
'title' => 'Zu viele Versuche.',
diff --git a/packages/panels/resources/lang/fa/pages/auth/register.php b/packages/panels/resources/lang/fa/pages/auth/register.php
index 1693f76a7b..303090ead9 100644
--- a/packages/panels/resources/lang/fa/pages/auth/register.php
+++ b/packages/panels/resources/lang/fa/pages/auth/register.php
@@ -10,7 +10,7 @@ return [
'login' => [
'before' => 'یا',
- 'label' => 'وارد حساب خود شوید.',
+ 'label' => 'ورود به حساب کاربری',
],
],
diff --git a/packages/panels/resources/lang/id/pages/auth/password-reset/request-password-reset.php b/packages/panels/resources/lang/id/pages/auth/password-reset/request-password-reset.php
index 4f9bc89eef..7d77e7ab87 100644
--- a/packages/panels/resources/lang/id/pages/auth/password-reset/request-password-reset.php
+++ b/packages/panels/resources/lang/id/pages/auth/password-reset/request-password-reset.php
@@ -32,6 +32,10 @@ return [
'notifications' => [
+ 'sent' => [
+ 'body' => 'Jika akun Anda tidak ada, Anda tidak akan menerima email.',
+ ],
+
'throttled' => [
'title' => 'Terlalu banyak permintaan',
'body' => 'Silakan coba lagi dalam :seconds detik.',
diff --git a/packages/panels/resources/lang/nl/pages/auth/password-reset/request-password-reset.php b/packages/panels/resources/lang/nl/pages/auth/password-reset/request-password-reset.php
index e210600fcd..e9818d100d 100644
--- a/packages/panels/resources/lang/nl/pages/auth/password-reset/request-password-reset.php
+++ b/packages/panels/resources/lang/nl/pages/auth/password-reset/request-password-reset.php
@@ -32,6 +32,10 @@ return [
'notifications' => [
+ 'sent' => [
+ 'body' => 'Als uw account niet bestaat, ontvangt u de e-mail niet.',
+ ],
+
'throttled' => [
'title' => 'Te veel pogingen',
'body' => 'Probeer het opnieuw over :seconds seconden.',
diff --git a/packages/panels/src/Pages/Auth/Register.php b/packages/panels/src/Pages/Auth/Register.php
index 1c52d44af6..f78dc814e7 100644
--- a/packages/panels/src/Pages/Auth/Register.php
+++ b/packages/panels/src/Pages/Auth/Register.php
@@ -70,7 +70,7 @@ class Register extends SimplePage
return null;
}
- $user = $this->wrapInDatabaseTransaction(function () {
+ $user = $this->wrapInDatabaseTransaction(function (): Model {
$this->callHook('beforeValidate');
$data = $this->form->getState();
diff --git a/packages/panels/src/helpers.php b/packages/panels/src/helpers.php
index 1c312932c0..82722a623c 100644
--- a/packages/panels/src/helpers.php
+++ b/packages/panels/src/helpers.php
@@ -6,6 +6,7 @@ use Filament\Facades\Filament;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Auth\Access\Response;
use Illuminate\Database\Eloquent\Model;
+use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Gate;
if (! function_exists('Filament\authorize')) {
@@ -17,7 +18,7 @@ if (! function_exists('Filament\authorize')) {
$user = Filament::auth()->user();
if (! $shouldCheckPolicyExistence) {
- return Gate::forUser($user)->authorize($action, $model);
+ return Gate::forUser($user)->authorize($action, Arr::wrap($model));
}
$policy = Gate::getPolicyFor($model);
@@ -44,6 +45,6 @@ if (! function_exists('Filament\authorize')) {
return $response->authorize();
}
- return Gate::forUser($user)->authorize($action, $model);
+ return Gate::forUser($user)->authorize($action, Arr::wrap($model));
}
}
diff --git a/packages/spatie-laravel-translatable-plugin/README.md b/packages/spatie-laravel-translatable-plugin/README.md
index 48fc07e62b..6c5c72548c 100644
--- a/packages/spatie-laravel-translatable-plugin/README.md
+++ b/packages/spatie-laravel-translatable-plugin/README.md
@@ -1,3 +1,6 @@
+> [!IMPORTANT]
+> This plugin is now maintained by Lara Zeus: https://github.com/lara-zeus/translatable
+
# Filament Spatie Translatable Plugin
## Installation
diff --git a/packages/support/src/helpers.php b/packages/support/src/helpers.php
index e0362a5f6a..05eeb77d59 100644
--- a/packages/support/src/helpers.php
+++ b/packages/support/src/helpers.php
@@ -166,26 +166,38 @@ if (! function_exists('Filament\Support\generate_search_column_expression')) {
$column = match ($driverName) {
'pgsql' => (
str($column)->contains('->')
- ? (
- // Handle `table.field` part with double quotes
- str($column)
- ->before('->')
- ->explode('.')
- ->map(fn (string $part): string => (string) str($part)->wrap('"'))
- ->implode('.')
- ) . collect(str($column)->after('->')->explode('->')) // Handle JSON path parts
- ->map(function ($segment, $index) use ($column): string {
- $totalParts = substr_count($column, '->');
+ ? (
+ // Handle `table.field` part with double quotes
+ str($column)
+ ->before('->')
+ ->explode('.')
+ ->map(fn (string $part): string => (string) str($part)->wrap('"'))
+ ->implode('.')
+ ) . collect(str($column)->after('->')->explode('->')) // Handle JSON path parts
+ ->map(function ($segment, $index) use ($column): string {
+ // If segment already starts with `>` (from `->>` operator), preserve it
+ $isExplicitOperatorPrefixed = str($segment)->startsWith('>');
+ $segment = $isExplicitOperatorPrefixed ? (string) str($segment)->after('>') : $segment;
- return ($index === ($totalParts - 1))
- ? "->>'{$segment}'"
- : "->'{$segment}'";
- })
- ->implode('')
- : str($column)
- ->explode('.')
- ->map(fn (string $part): string => (string) str($part)->wrap('"'))
- ->implode('.')
+ // Remove single quotes from segment if present to avoid redundant quoting
+ $isWrappedWithSingleQuotes = str($segment)->startsWith("'") && str($segment)->endsWith("'");
+ $segment = $isWrappedWithSingleQuotes ? (string) str($segment)->trim("'") : $segment;
+
+ if ($isExplicitOperatorPrefixed) {
+ return "->>'{$segment}'";
+ }
+
+ $totalParts = substr_count($column, '->');
+
+ return ($index === ($totalParts - 1))
+ ? "->>'{$segment}'"
+ : "->'{$segment}'";
+ })
+ ->implode('')
+ : str($column)
+ ->explode('.')
+ ->map(fn (string $part): string => (string) str($part)->wrap('"'))
+ ->implode('.')
) . '::text',
default => $column,
};
diff --git a/packages/tables/src/Actions/EditAction.php b/packages/tables/src/Actions/EditAction.php
index 90f310e6ba..d3d55097b9 100644
--- a/packages/tables/src/Actions/EditAction.php
+++ b/packages/tables/src/Actions/EditAction.php
@@ -33,6 +33,8 @@ class EditAction extends Action
$this->successNotificationTitle(__('filament-actions::edit.single.notifications.saved.title'));
+ $this->defaultColor('primary');
+
$this->icon(FilamentIcon::resolve('actions::edit-action') ?? 'heroicon-m-pencil-square');
$this->fillForm(function (Model $record, Table $table): array {
diff --git a/tests/src/Support/helpersTest.php b/tests/src/Support/helpersTest.php
index fb9f27ba7e..e26449a189 100644
--- a/tests/src/Support/helpersTest.php
+++ b/tests/src/Support/helpersTest.php
@@ -112,3 +112,51 @@ it('will generate a column expression for Postgres with colons in the table name
['blog:posts.title', 'lower("blog:posts"."title"::text)'],
['blog:posts:comments.author.name', 'lower("blog:posts:comments"."author"."name"::text)'],
]);
+
+it('will generate a JSON search column expression for Postgres with explicit ->> operator', function () {
+ $column = 'data->>name';
+ $isSearchForcedCaseInsensitive = true;
+
+ $databaseConnection = Mockery::mock(Connection::class);
+ $databaseConnection->shouldReceive('getDriverName')->andReturn('pgsql');
+ $databaseConnection->shouldReceive('getConfig')->with('search_collation')->andReturn(null);
+
+ $grammar = new PostgresGrammar($databaseConnection);
+
+ $expression = generate_search_column_expression($column, $isSearchForcedCaseInsensitive, $databaseConnection);
+
+ expect($expression->getValue($grammar))
+ ->toBe("lower(\"data\"->>'name'::text)");
+});
+
+it('will generate a nested JSON search column expression for Postgres with explicit ->> operator on the last segment', function () {
+ $column = 'data->name->>ar';
+ $isSearchForcedCaseInsensitive = true;
+
+ $databaseConnection = Mockery::mock(Connection::class);
+ $databaseConnection->shouldReceive('getDriverName')->andReturn('pgsql');
+ $databaseConnection->shouldReceive('getConfig')->with('search_collation')->andReturn(null);
+
+ $grammar = new PostgresGrammar($databaseConnection);
+
+ $expression = generate_search_column_expression($column, $isSearchForcedCaseInsensitive, $databaseConnection);
+
+ expect($expression->getValue($grammar))
+ ->toBe("lower(\"data\"->'name'->>'ar'::text)");
+});
+
+it('will generate a JSON search column expression for Postgres with explicit ->> operator and simple key', function () {
+ $column = 'name->>\'en\'';
+ $isSearchForcedCaseInsensitive = true;
+
+ $databaseConnection = Mockery::mock(Connection::class);
+ $databaseConnection->shouldReceive('getDriverName')->andReturn('pgsql');
+ $databaseConnection->shouldReceive('getConfig')->with('search_collation')->andReturn(null);
+
+ $grammar = new PostgresGrammar($databaseConnection);
+
+ $expression = generate_search_column_expression($column, $isSearchForcedCaseInsensitive, $databaseConnection);
+
+ expect($expression->getValue($grammar))
+ ->toBe("lower(\"name\"->>'en'::text)");
+});