diff --git a/packages/actions/docs/04-modals.md b/packages/actions/docs/04-modals.md
index 312bf083260..55ea1b3ee9e 100644
--- a/packages/actions/docs/04-modals.md
+++ b/packages/actions/docs/04-modals.md
@@ -506,6 +506,29 @@ use Filament\Support\View\Components\Modal;
Modal::closedByClickingAway(false);
```
+## Closing the modal by escaping
+
+By default, when you press escape on a modal, it will close itself. If you wish to disable this behavior for a specific action, you can use the `closedByEscaping(false)` method:
+
+```php
+Action::make('updateAuthor')
+ ->form([
+ // ...
+ ])
+ ->action(function (array $data): void {
+ // ...
+ })
+ ->closedByEscaping(false)
+```
+
+If you'd like to change the behaviour for all modals in the application, you can do so by calling `Modal::closedByEscaping()` inside a service provider or middleware:
+
+```php
+use Filament\Support\View\Components\Modal;
+
+Modal::closedByEscaping(false);
+```
+
## Hiding the modal close button
By default, modals have a close button in the top right corner. If you wish to hide the close button, you can use the `modalCloseButton(false)` method:
diff --git a/packages/actions/resources/views/components/modals.blade.php b/packages/actions/resources/views/components/modals.blade.php
index d4e91b82172..4799958ee0e 100644
--- a/packages/actions/resources/views/components/modals.blade.php
+++ b/packages/actions/resources/views/components/modals.blade.php
@@ -8,6 +8,7 @@
:alignment="$action?->getModalAlignment()"
:close-button="$action?->hasModalCloseButton()"
:close-by-clicking-away="$action?->isModalClosedByClickingAway()"
+ :close-by-escaping="$action?->isModalClosedByEscaping()"
:description="$action?->getModalDescription()"
display-classes="block"
:extra-modal-window-attribute-bag="$action?->getExtraModalWindowAttributeBag()"
@@ -68,6 +69,7 @@
:alignment="$action?->getModalAlignment()"
:close-button="$action?->hasModalCloseButton()"
:close-by-clicking-away="$action?->isModalClosedByClickingAway()"
+ :close-by-escaping="$action?->isModalClosedByEscaping()"
:description="$action?->getModalDescription()"
display-classes="block"
:extra-modal-window-attribute-bag="$action?->getExtraModalWindowAttributeBag()"
@@ -122,6 +124,7 @@
:alignment="$action?->getModalAlignment()"
:close-button="$action?->hasModalCloseButton()"
:close-by-clicking-away="$action?->isModalClosedByClickingAway()"
+ :close-by-escaping="$action?->isModalClosedByEscaping()"
:description="$action?->getModalDescription()"
display-classes="block"
:extra-modal-window-attribute-bag="$action?->getExtraModalWindowAttributeBag()"
@@ -182,6 +185,7 @@
:alignment="$action?->getModalAlignment()"
:close-button="$action?->hasModalCloseButton()"
:close-by-clicking-away="$action?->isModalClosedByClickingAway()"
+ :close-by-escaping="$action?->isModalClosedByEscaping()"
:description="$action?->getModalDescription()"
display-classes="block"
:extra-modal-window-attribute-bag="$action?->getExtraModalWindowAttributeBag()"
@@ -242,6 +246,7 @@
:alignment="$action?->getModalAlignment()"
:close-button="$action?->hasModalCloseButton()"
:close-by-clicking-away="$action?->isModalClosedByClickingAway()"
+ :close-by-escaping="$action?->isModalClosedByEscaping()"
:description="$action?->getModalDescription()"
display-classes="block"
:extra-modal-window-attribute-bag="$action?->getExtraModalWindowAttributeBag()"
diff --git a/packages/actions/src/Concerns/CanOpenModal.php b/packages/actions/src/Concerns/CanOpenModal.php
index b36fa69916b..95a00aac307 100644
--- a/packages/actions/src/Concerns/CanOpenModal.php
+++ b/packages/actions/src/Concerns/CanOpenModal.php
@@ -80,6 +80,8 @@ trait CanOpenModal
protected bool | Closure | null $isModalClosedByClickingAway = null;
+ protected bool | Closure | null $isModalClosedByEscaping = null;
+
protected string | Closure | null $modalIcon = null;
/**
@@ -94,6 +96,13 @@ public function closeModalByClickingAway(bool | Closure | null $condition = true
return $this;
}
+ public function closeModalByEscaping(bool | Closure | null $condition = true): static
+ {
+ $this->isModalClosedByEscaping = $condition;
+
+ return $this;
+ }
+
/**
* @deprecated Use `modalAlignment(Alignment::Center)` instead.
*/
@@ -600,6 +609,11 @@ public function isModalClosedByClickingAway(): bool
return (bool) ($this->evaluate($this->isModalClosedByClickingAway) ?? Modal::$isClosedByClickingAway);
}
+ public function isModalClosedByEscaping(): bool
+ {
+ return (bool) ($this->evaluate($this->isModalClosedByEscaping) ?? Modal::$isClosedByEscaping);
+ }
+
/**
* @deprecated Use `makeModalSubmitAction()` instead.
*
diff --git a/packages/forms/resources/views/components/checkbox-list.blade.php b/packages/forms/resources/views/components/checkbox-list.blade.php
index ab4d55557cd..a63d65baafc 100644
--- a/packages/forms/resources/views/components/checkbox-list.blade.php
+++ b/packages/forms/resources/views/components/checkbox-list.blade.php
@@ -123,7 +123,7 @@ class="mb-2"
{{ $getAction('selectAll') }}
@@ -131,7 +131,7 @@ class="mb-2"
{{ $getAction('deselectAll') }}
diff --git a/packages/panels/resources/lang/id/unsaved-changes-alert.php b/packages/panels/resources/lang/id/unsaved-changes-alert.php
new file mode 100644
index 00000000000..9b64dd72d8f
--- /dev/null
+++ b/packages/panels/resources/lang/id/unsaved-changes-alert.php
@@ -0,0 +1,7 @@
+ 'Anda memiliki perubahan yang belum disimpan. Apakah Anda yakin ingin meninggalkan halaman ini?',
+
+];
diff --git a/packages/panels/src/Panel/Concerns/HasComponents.php b/packages/panels/src/Panel/Concerns/HasComponents.php
index 69d2c77747b..8bb668a3b73 100644
--- a/packages/panels/src/Panel/Concerns/HasComponents.php
+++ b/packages/panels/src/Panel/Concerns/HasComponents.php
@@ -505,10 +505,22 @@ protected function registerLivewireComponents(): void
}
}
+ if ($this->hasProfile() && is_subclass_of($profilePageComponent = $this->getProfilePage(), Component::class)) {
+ $this->queueLivewireComponentForRegistration($profilePageComponent);
+ }
+
if ($this->hasRegistration() && is_subclass_of($registrationRouteAction = $this->getRegistrationRouteAction(), Component::class)) {
$this->queueLivewireComponentForRegistration($registrationRouteAction);
}
+ if ($this->hasTenantRegistration() && is_subclass_of($tenantRegistrationComponent = $this->getTenantRegistrationPage(), Component::class)) {
+ $this->queueLivewireComponentForRegistration($tenantRegistrationComponent);
+ }
+
+ if ($this->hasTenantProfile() && is_subclass_of($tenantProfileComponent = $this->getTenantProfilePage(), Component::class)) {
+ $this->queueLivewireComponentForRegistration($tenantProfileComponent);
+ }
+
foreach ($this->getResources() as $resource) {
foreach ($resource::getPages() as $pageRegistration) {
$this->queueLivewireComponentForRegistration($pageRegistration->getPage());
diff --git a/packages/support/resources/views/components/button/index.blade.php b/packages/support/resources/views/components/button/index.blade.php
index 9388814b55f..10d02df0555 100644
--- a/packages/support/resources/views/components/button/index.blade.php
+++ b/packages/support/resources/views/components/button/index.blade.php
@@ -98,7 +98,7 @@
'ring-1 ring-gray-950/10 dark:ring-white/20' => (($color === 'gray') || ($tag === 'label')) && (! $grouped),
'bg-custom-600 text-white hover:bg-custom-500 focus-visible:ring-custom-500/50 dark:bg-custom-500 dark:hover:bg-custom-400 dark:focus-visible:ring-custom-400/50' => ($color !== 'gray') && ($tag !== 'label'),
'[input:checked+&]:bg-custom-600 [input:checked+&]:text-white [input:checked+&]:ring-0 [input:checked+&]:hover:bg-custom-500 dark:[input:checked+&]:bg-custom-500 dark:[input:checked+&]:hover:bg-custom-400 [input:checked:focus-visible+&]:ring-custom-500/50 dark:[input:checked:focus-visible+&]:ring-custom-400/50 [input:focus-visible+&]:z-10 [input:focus-visible+&]:ring-2 [input:focus-visible+&]:ring-gray-950/10 dark:[input:focus-visible+&]:ring-white/20' => ($color !== 'gray') && ($tag === 'label'),
- ]
+ ]
),
]);
diff --git a/packages/support/resources/views/components/modal/index.blade.php b/packages/support/resources/views/components/modal/index.blade.php
index 6a3cc6a1e21..67b1c5edb6b 100644
--- a/packages/support/resources/views/components/modal/index.blade.php
+++ b/packages/support/resources/views/components/modal/index.blade.php
@@ -8,6 +8,7 @@
'ariaLabelledby' => null,
'closeButton' => \Filament\Support\View\Components\Modal::$hasCloseButton,
'closeByClickingAway' => \Filament\Support\View\Components\Modal::$isClosedByClickingAway,
+ 'closeByEscaping' => \Filament\Support\View\Components\Modal::$isClosedByEscaping,
'closeEventName' => 'close-modal',
'description' => null,
'displayClasses' => 'inline-block',
@@ -155,7 +156,9 @@
$watch('isOpen', () => (isShown = isOpen))
})
"
- x-on:keydown.window.escape="{{ $closeEventHandler }}"
+ @if ($closeByEscaping)
+ x-on:keydown.window.escape="{{ $closeEventHandler }}"
+ @endif
x-show="isShown"
x-transition:enter="duration-300"
x-transition:leave="duration-300"
diff --git a/packages/support/src/View/Components/Modal.php b/packages/support/src/View/Components/Modal.php
index 9b905988070..2c6e80c2a27 100644
--- a/packages/support/src/View/Components/Modal.php
+++ b/packages/support/src/View/Components/Modal.php
@@ -8,6 +8,8 @@ class Modal
public static bool $isClosedByClickingAway = true;
+ public static bool $isClosedByEscaping = true;
+
public static function closeButton(bool $condition = true): void
{
static::$hasCloseButton = $condition;
@@ -17,4 +19,9 @@ public static function closedByClickingAway(bool $condition = true): void
{
static::$isClosedByClickingAway = $condition;
}
+
+ public static function closedByEscaping(bool $condition = true): void
+ {
+ static::$isClosedByEscaping = $condition;
+ }
}
diff --git a/packages/tables/docs/08-grouping.md b/packages/tables/docs/08-grouping.md
index 1fc5000c2a5..63f77d91d5a 100644
--- a/packages/tables/docs/08-grouping.md
+++ b/packages/tables/docs/08-grouping.md
@@ -337,3 +337,18 @@ public function table(Table $table): Table
->groupingSettingsHidden();
}
```
+
+### Hiding the grouping direction setting only
+
+You can hide the grouping direction select interface using the `groupingDirectionSettingHidden()` method:
+
+```php
+use Filament\Tables\Table;
+
+public function table(Table $table): Table
+{
+ return $table
+ ->defaultGroup('status');
+ ->groupingDirectionSettingHidden();
+}
+```
diff --git a/packages/tables/resources/views/components/groups.blade.php b/packages/tables/resources/views/components/groups.blade.php
index f875fd43e4d..4cce2a84adb 100644
--- a/packages/tables/resources/views/components/groups.blade.php
+++ b/packages/tables/resources/views/components/groups.blade.php
@@ -1,4 +1,5 @@
@props([
+ 'directionSetting' => false,
'dropdownOnDesktop' => false,
'groups',
'triggerAction',
@@ -71,23 +72,24 @@
-
+ @if (! $directionSetting)
+
+ @endif
@@ -116,23 +118,24 @@
-
+ @if (! $directionSetting)
+
+ @endif
@endif
diff --git a/packages/tables/resources/views/index.blade.php b/packages/tables/resources/views/index.blade.php
index eccee88229a..054d0b8ec4d 100644
--- a/packages/tables/resources/views/index.blade.php
+++ b/packages/tables/resources/views/index.blade.php
@@ -42,6 +42,7 @@
$isReorderable = $isReorderable();
$isReordering = $isReordering();
$areGroupingSettingsVisible = (! $isReordering) && count($groups) && (! $areGroupingSettingsHidden());
+ $isGroupingDirectionSettingHidden = $isGroupingDirectionSettingHidden();
$isColumnSearchVisible = $isSearchableByColumn();
$isGlobalSearchVisible = $isSearchable();
$isSearchOnBlur = $isSearchOnBlur();
@@ -196,6 +197,7 @@ class="fi-ta-header-toolbar flex items-center justify-between gap-x-4 px-4 py-3
@if ($areGroupingSettingsVisible)