From 7f691cdce43787120edcc51cb1ec592580b76b6f Mon Sep 17 00:00:00 2001 From: rbruhn Date: Wed, 21 Oct 2026 09:46:37 -0400 Subject: [PATCH] Upgrade Sweet Alert to v8 --- bootstrap/app.php | 11 +- composer.json | 2 +- composer.lock | 47 ++-- config/sweetalert.php | 247 ++++++++++-------- deploy.php | 2 +- deploy/custom.php | 6 +- resources/views/layouts/app.blade.php | 2 +- .../views/vendor/sweetalert/alert.blade.php | 14 - tests/Feature/ContactFormTest.php | 15 ++ 9 files changed, 198 insertions(+), 148 deletions(-) delete mode 100644 resources/views/vendor/sweetalert/alert.blade.php diff --git a/bootstrap/app.php b/bootstrap/app.php index 39ef885..aba7142 100644 --- a/bootstrap/app.php +++ b/bootstrap/app.php @@ -3,6 +3,9 @@ use Illuminate\Foundation\Application; use Illuminate\Foundation\Configuration\Exceptions; use Illuminate\Foundation\Configuration\Middleware; +use RealRashid\SweetAlert\Http\Middleware\ToSweetAlert; +use Spatie\ResponseCache\Middlewares\CacheResponse; +use Spatie\ResponseCache\Middlewares\DoNotCacheResponse; return Application::configure(basePath: dirname(__DIR__)) ->withRouting( @@ -12,13 +15,13 @@ ) ->withMiddleware(function (Middleware $middleware) { $middleware->web(append: [ - \RealRashid\SweetAlert\ToSweetAlert::class, - \Spatie\ResponseCache\Middlewares\CacheResponse::class, + ToSweetAlert::class, + CacheResponse::class, ]); $middleware->alias([ - 'cacheResponse' => \Spatie\ResponseCache\Middlewares\CacheResponse::class, - 'doNotCacheResponse' => \Spatie\ResponseCache\Middlewares\DoNotCacheResponse::class, + 'cacheResponse' => CacheResponse::class, + 'doNotCacheResponse' => DoNotCacheResponse::class, ]); }) ->withExceptions(function (Exceptions $exceptions) { diff --git a/composer.json b/composer.json index 7cf36ee..1546038 100644 --- a/composer.json +++ b/composer.json @@ -21,7 +21,7 @@ "laravel/horizon": "^5.48", "laravel/sanctum": "^v4.0.0", "laravel/tinker": "^3.0", - "realrashid/sweet-alert": "^v7.3.0", + "realrashid/sweet-alert": "^8.0", "spatie/laravel-honeypot": "^4.6", "spatie/laravel-permission": "^8.3", "spatie/laravel-responsecache": "^7.7" diff --git a/composer.lock b/composer.lock index 560b952..c858d57 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "519db01af290e144eac1383fba2fc628", + "content-hash": "0ec91fb2514b20732786ca22fd5308a9", "packages": [ { "name": "anourvalar/eloquent-serialize", @@ -6134,25 +6134,32 @@ }, { "name": "realrashid/sweet-alert", - "version": "v7.3.2", + "version": "v8.0.0", "source": { "type": "git", "url": "https://github.com/realrashid/sweet-alert.git", - "reference": "72754d27de400e5b177c4e066aca8484b9f8bbbe" + "reference": "c89e51836d6295ee20ef260b0670bef3f012b3a5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/realrashid/sweet-alert/zipball/72754d27de400e5b177c4e066aca8484b9f8bbbe", - "reference": "72754d27de400e5b177c4e066aca8484b9f8bbbe", + "url": "https://api.github.com/repos/realrashid/sweet-alert/zipball/c89e51836d6295ee20ef260b0670bef3f012b3a5", + "reference": "c89e51836d6295ee20ef260b0670bef3f012b3a5", "shasum": "" }, "require": { - "laravel/framework": "^5.6|^6.0|^7.0|^8.0|^9.0|^9.11|9.14.*|^10.0|^11.0|^12.0|^13.0", - "php": "^7.2|^8.0|^8.1|^8.2|^8.3" + "laravel/framework": "^11.0|^12.0|^13.0", + "php": "^8.3" }, "require-dev": { - "phpunit/phpunit": "^12.5", - "symfony/thanks": "^1.0" + "inertiajs/inertia-laravel": "^2.0", + "laravel/pint": "^1.18", + "mockery/mockery": "^1.6", + "nunomaduro/collision": "^8.5.0", + "orchestra/testbench": "^9.0.0||^10.0||^11.0", + "pestphp/pest": "^3.0|^4.0", + "pestphp/pest-plugin-arch": "^3.0|^4.0", + "pestphp/pest-plugin-laravel": "^3.0|^4.0", + "phpstan/phpstan": "^2.0" }, "type": "library", "extra": { @@ -6181,18 +6188,18 @@ { "name": "Rashid Ali", "email": "realrashid05@gmail.com", - "homepage": "https://realrashid.com", "role": "Developer" } ], - "description": "Laravel Sweet Alert Is A Package For Laravel Provides An Easy Way To Display Alert Messages Using The SweetAlert2 Library.", + "description": "A beautiful, responsive, customizable, accessible (WAI-ARIA) replacement for JavaScript popup boxes for Laravel - rebuilt with a fluent, Laravel-native API.", "homepage": "https://github.com/realrashid/sweet-alert", "keywords": [ "alert", + "fluent", "laravel", "laravel-package", "notifier", - "noty", + "realrashid", "sweet-alert", "sweet-alert2", "toast" @@ -6205,23 +6212,31 @@ }, "funding": [ { - "url": "https://ko-fi.com/realrashid", + "url": "https://www.buymeacoffee.com/realrashid", "type": "custom" }, { - "url": "https://www.buymeacoffee.com/realrashid", - "type": "custom" + "url": "https://github.com/realrashid", + "type": "github" }, { "url": "https://issuehunt.io/r/realrashid", "type": "issuehunt" }, + { + "url": "https://ko-fi.com/realrashid", + "type": "ko_fi" + }, + { + "url": "https://www.patreon.com/realrashid", + "type": "patreon" + }, { "url": "https://tidelift.com/funding/github/packagist/realrashid/sweet-alert", "type": "tidelift" } ], - "time": "2026-03-29T14:20:34+00:00" + "time": "2026-09-07T22:06:26+00:00" }, { "name": "ryangjchandler/blade-capture-directive", diff --git a/config/sweetalert.php b/config/sweetalert.php index 4385d09..9dc520f 100644 --- a/config/sweetalert.php +++ b/config/sweetalert.php @@ -4,209 +4,240 @@ /* |-------------------------------------------------------------------------- - | CDN LINK + | Default Alert Type |-------------------------------------------------------------------------- - | By default SweetAlert2 use its local sweetalert.all.js - | file. - | However, you can use its cdn if you want. + | + | This value determines the default alert type when none is specified. | */ - 'cdn' => env('SWEET_ALERT_CDN'), + 'default' => env('SWEET_ALERT_DEFAULT', 'alert'), /* |-------------------------------------------------------------------------- - | Always load the sweetalert.all.js + | CDN Link |-------------------------------------------------------------------------- - | There might be situations where you will always want the sweet alert - | js package to be there for you. (for eg. you might use it heavily to - | show notifications or you might want to use the native js) then this - | might be handy. + | + | By default, SweetAlert2 uses its local sweetalert2.min.js file. + | However, you can use a CDN if you prefer. | */ - 'alwaysLoadJS' => env('SWEET_ALERT_ALWAYS_LOAD_JS', false), + 'cdn' => env('SWEET_ALERT_CDN'), /* |-------------------------------------------------------------------------- - | Never load the sweetalert.all.js + | JavaScript Loading Control |-------------------------------------------------------------------------- - | If you want to handle the sweet alert js package by yourself - | (for eg. you might want to use laravel mix) then this can be - | handy. - | If you set always load js to true & never load js to false, - | it's going to prioritize the never load js. | - | alwaysLoadJs = true & neverLoadJs = true => js will not be loaded - | alwaysLoadJs = true & neverLoadJs = false => js will be loaded - | alwaysLoadJs = false & neverLoadJs = false => js will be loaded when - | you set alert/toast by using the facade/helper functions. + | always_load_js: Always include the SweetAlert2 JS on every page. + | never_load_js: Never include the JS (handle it yourself with Mix/Vite). + | + | alwaysLoadJs = true & neverLoadJs = true => JS will NOT be loaded + | alwaysLoadJs = true & neverLoadJs = false => JS will be loaded + | alwaysLoadJs = false & neverLoadJs = false => JS loaded only when alert is set + | */ - 'neverLoadJS' => env('SWEET_ALERT_NEVER_LOAD_JS', false), + 'always_load_js' => env('SWEET_ALERT_ALWAYS_LOAD_JS', false), + 'never_load_js' => env('SWEET_ALERT_NEVER_LOAD_JS', false), /* |-------------------------------------------------------------------------- - | AutoClose Timer + | Default Modal Settings |-------------------------------------------------------------------------- | - | This is for the all Modal windows. - | For specific modal just use the autoClose() helper method. + | These values are used as defaults for all modal windows. + | Override them per-alert using the fluent API methods. | */ 'timer' => env('SWEET_ALERT_TIMER', 5000), /* - |-------------------------------------------------------------------------- - | Width - |-------------------------------------------------------------------------- - | - | Modal window width, including paddings (box-sizing: border-box). - | Can be in px or %. - | The default width is 32rem. - | This is for the all Modal windows. - | for particular modal just use the width() helper method. + | Width, padding and background are sent to SweetAlert2 only when you set + | them. SweetAlert2 turns each one into an inline style on the popup, and an + | inline style beats every stylesheet — so a hard-coded background here + | would override the theme you picked and every alert would stay white. + | Leave them null and the active theme's own CSS decides. */ - - 'width' => env('SWEET_ALERT_WIDTH', '32rem'), + 'width' => env('SWEET_ALERT_WIDTH'), + 'padding' => env('SWEET_ALERT_PADDING'), + 'background' => env('SWEET_ALERT_BACKGROUND'), + 'show_confirm_button' => env('SWEET_ALERT_SHOW_CONFIRM_BUTTON', true), + 'show_close_button' => env('SWEET_ALERT_SHOW_CLOSE_BUTTON', false), /* |-------------------------------------------------------------------------- - | Height Auto + | Button Text |-------------------------------------------------------------------------- - | By default, SweetAlert2 sets html's and body's CSS height to auto !important. - | If this behavior isn't compatible with your project's layout, - | set heightAuto to false. + | + | Default text for the modal buttons. Translations will be handled + | by Laravel at runtime. | */ - 'height_auto' => env('SWEET_ALERT_HEIGHT_AUTO', true), + 'button_text' => [ + 'confirm' => env('SWEET_ALERT_CONFIRM_BUTTON_TEXT', 'OK'), + 'cancel' => env('SWEET_ALERT_CANCEL_BUTTON_TEXT', 'Cancel'), + 'deny' => env('SWEET_ALERT_DENY_BUTTON_TEXT', 'Deny'), + ], /* |-------------------------------------------------------------------------- - | Padding + | Toast Settings |-------------------------------------------------------------------------- | - | Modal window padding. - | Can be in px or %. - | The default padding is 1.25rem. - | This is for the all Modal windows. - | for particular modal just use the padding() helper method. + | Default configuration for toast notifications. + | */ - 'padding' => env('SWEET_ALERT_PADDING', '1.25rem'), + 'toast' => [ + 'position' => env('SWEET_ALERT_TOAST_POSITION', 'top-end'), + 'auto_close' => env('SWEET_ALERT_TOAST_AUTO_CLOSE', 5000), + 'show_close_button' => env('SWEET_ALERT_TOAST_CLOSE_BUTTON', true), + 'show_confirm_button' => false, + 'timer_progress_bar' => env('SWEET_ALERT_TOAST_PROGRESS_BAR', true), + ], /* |-------------------------------------------------------------------------- - | Animation + | Middleware Settings |-------------------------------------------------------------------------- - | Custom animation with [Animate.css](https://daneden.github.io/animate.css/) - | If set to false, modal CSS animation will be use default ones. - | For specific modal just use the animation() helper method. + | + | Configuration for the ToSweetAlert middleware behavior. | */ - 'animation' => [ - 'enable' => env('SWEET_ALERT_ANIMATION_ENABLE', false), + 'middleware' => [ + 'auto_display_errors' => env('SWEET_ALERT_AUTO_DISPLAY_ERRORS', true), + 'toast_position' => env('SWEET_ALERT_MIDDLEWARE_TOAST_POSITION', 'top'), + 'auto_close' => env('SWEET_ALERT_MIDDLEWARE_AUTO_CLOSE', true), + 'timer' => env('SWEET_ALERT_MIDDLEWARE_TIMER', 5000), + 'toast_close_button' => env('SWEET_ALERT_MIDDLEWARE_TOAST_CLOSE_BUTTON', true), ], - 'animatecss' => env('SWEET_ALERT_ANIMATECSS', 'https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css'), - /* |-------------------------------------------------------------------------- - | ShowConfirmButton + | Confirm Dialog Settings |-------------------------------------------------------------------------- - | If set to false, a "Confirm"-button will not be shown. - | It can be useful when you're using custom HTML description. - | This is for the all Modal windows. - | For specific modal just use the showConfirmButton() helper method. + | + | Default configuration for general confirm dialogs, and for the guarded + | links and forms marked with data-confirm. + | + | `auto` emits the small listener that makes data-confirm and + | data-confirm-delete work on every page. Turn it off if you would rather + | wire the confirmation up yourself. | */ - 'show_confirm_button' => env('SWEET_ALERT_CONFIRM_BUTTON', true), + 'confirm' => [ + 'auto' => env('SWEET_ALERT_AUTO_CONFIRM', true), + 'icon' => 'question', + 'title' => 'Are you sure?', + 'text' => '', + 'confirm_button_text' => 'Yes', + 'confirm_button_color' => '#3085d6', + 'cancel_button_text' => 'Cancel', + 'show_cancel_button' => true, + 'show_close_button' => false, + ], /* |-------------------------------------------------------------------------- - | ShowCloseButton + | Confirm Delete Settings |-------------------------------------------------------------------------- - | If set to true, a "Close"-button will be shown, - | which the user can click on to dismiss the modal. - | This is for the all Modal windows. - | For specific modal just use the showCloseButton() helper method. + | + | Default configuration for the confirmDelete() dialog. | */ - 'show_close_button' => env('SWEET_ALERT_CLOSE_BUTTON', false), + 'confirm_delete' => [ + 'icon' => 'warning', + 'title' => 'Are you sure?', + 'text' => 'This cannot be undone.', + 'confirm_button_text' => 'Yes, delete it!', + 'confirm_button_color' => '#d33', + 'cancel_button_text' => 'Cancel', + 'show_close_button' => false, + 'show_cancel_button' => true, + 'show_loader_on_confirm' => true, + ], /* |-------------------------------------------------------------------------- - | Toast position + | Animation Settings |-------------------------------------------------------------------------- - | Modal window or toast position, can be 'top', - | 'top-start', 'top-end', 'center', 'center-start', - | 'center-end', 'bottom', 'bottom-start', or 'bottom-end'. - | For specific modal just use the position() helper method. + | + | Custom animation using Animate.css. | */ - 'toast_position' => env('SWEET_ALERT_TOAST_POSITION', 'top-end'), + 'animation' => [ + 'enabled' => env('SWEET_ALERT_ANIMATION_ENABLE', false), + 'animatecss' => env('SWEET_ALERT_ANIMATECSS'), + ], /* |-------------------------------------------------------------------------- - | Progress Bar + | Theme |-------------------------------------------------------------------------- - | If set to true, a progress bar at the bottom of a popup will be shown. - | It can be useful with toasts. + | + | SweetAlert2 theme. Set to 'default' for the standard theme, + | or use any theme from @sweetalert2/theme-* package. | */ - 'timer_progress_bar' => env('SWEET_ALERT_TIMER_PROGRESS_BAR', false), + 'theme' => env('SWEET_ALERT_THEME', 'light'), /* |-------------------------------------------------------------------------- - | Middleware + | Presets |-------------------------------------------------------------------------- - | Modal window or toast, config for the Middleware + | + | Named presets that can be applied with ->preset('name'). + | Each preset is an array of SweetAlert2 config options that + | are merged onto the current builder configuration. + | + | Example: + | Alert::preset('danger')->title('Oops!')->flash(); | */ - 'middleware' => [ - - 'autoClose' => env('SWEET_ALERT_MIDDLEWARE_AUTO_CLOSE', true), - - 'toast_position' => env('SWEET_ALERT_MIDDLEWARE_TOAST_POSITION', 'top'), - - 'toast_close_button' => env('SWEET_ALERT_MIDDLEWARE_TOAST_CLOSE_BUTTON', true), - - 'timer' => env('SWEET_ALERT_MIDDLEWARE_ALERT_CLOSE_TIME', 5000), - - 'auto_display_error_messages' => env('SWEET_ALERT_AUTO_DISPLAY_ERROR_MESSAGES', true), + 'presets' => [ + // 'danger' => [ + // 'icon' => 'error', + // 'confirmButtonColor' => '#d33', + // 'showCancelButton' => true, + // ], + // 'success-toast' => [ + // 'toast' => true, + // 'position' => 'top-end', + // 'icon' => 'success', + // 'timer' => 3000, + // 'timerProgressBar' => true, + // 'showConfirmButton' => false, + // ], ], /* |-------------------------------------------------------------------------- - | Custom Class + | JavaScript Source Settings |-------------------------------------------------------------------------- - | A custom CSS class for the modal: + | + | source: 'cdn' (default), 'npm' (set never_load_js=true and manage Swal + | yourself via npm), 'manual' (full control, nothing injected). + | version: pinned SweetAlert2 version used when source='cdn'. + | cdn_provider: 'jsdelivr' (default), 'unpkg', 'cdnjs', 'custom'. + | custom_cdn_js: only used when cdn_provider='custom'. | */ - 'customClass' => [ - - 'container' => env('SWEET_ALERT_CONTAINER_CLASS'), - 'popup' => env('SWEET_ALERT_POPUP_CLASS'), - 'header' => env('SWEET_ALERT_HEADER_CLASS'), - 'title' => env('SWEET_ALERT_TITLE_CLASS'), - 'closeButton' => env('SWEET_ALERT_CLOSE_BUTTON_CLASS'), - 'icon' => env('SWEET_ALERT_ICON_CLASS'), - 'image' => env('SWEET_ALERT_IMAGE_CLASS'), - 'content' => env('SWEET_ALERT_CONTENT_CLASS'), - 'input' => env('SWEET_ALERT_INPUT_CLASS'), - 'actions' => env('SWEET_ALERT_ACTIONS_CLASS'), - 'confirmButton' => env('SWEET_ALERT_CONFIRM_BUTTON_CLASS'), - 'cancelButton' => env('SWEET_ALERT_CANCEL_BUTTON_CLASS'), - 'footer' => env('SWEET_ALERT_FOOTER_CLASS'), + 'js' => [ + 'source' => env('SWEET_ALERT_JS_SOURCE', 'cdn'), + 'version' => env('SWEET_ALERT_VERSION', '11'), + 'cdn_provider' => env('SWEET_ALERT_CDN_PROVIDER', 'jsdelivr'), + 'custom_cdn_js' => env('SWEET_ALERT_CDN_JS'), ], ]; diff --git a/deploy.php b/deploy.php index 535ea9a..6938253 100644 --- a/deploy.php +++ b/deploy.php @@ -125,7 +125,7 @@ 'artisan:storage:link', // Create symbolic link for storage directory 'artisan:package:discover', // Run package discovery 'artisan:horizon:publish', // Publish Laravel Horizon assets - 'artisan:sweetalert:publish', // Publish Sweet Alert assets + 'artisan:alert:publish', // Publish the Sweet Alert JavaScript the alert view loads 'artisan:filament:assets', 'artisan:app:deploy-files', // Custom app deployment files diff --git a/deploy/custom.php b/deploy/custom.php index e94ef28..2925759 100644 --- a/deploy/custom.php +++ b/deploy/custom.php @@ -76,10 +76,10 @@ /** * Publish Sweet Alert 2 assets - * Executes the sweetalert:publish artisan command + * Publishes public/vendor/sweetalert/sweet-alert.js, which the Sweet Alert view loads (public/vendor isn't in git) */ -desc('Publish all Sweet Alert 2 assets'); -task('artisan:sweetalert:publish', artisan('sweetalert:publish')); +desc('Publish the Sweet Alert JavaScript'); +task('artisan:alert:publish', artisan('alert:publish --assets --force')); /** * Reload Supervisor configuration diff --git a/resources/views/layouts/app.blade.php b/resources/views/layouts/app.blade.php index 2225d2f..8e05115 100644 --- a/resources/views/layouts/app.blade.php +++ b/resources/views/layouts/app.blade.php @@ -58,7 +58,7 @@ class="back-to-top" @auth @endauth -@include('sweetalert::alert') +@sweetAlert @stack('scripts') diff --git a/resources/views/vendor/sweetalert/alert.blade.php b/resources/views/vendor/sweetalert/alert.blade.php deleted file mode 100644 index 75c97f5..0000000 --- a/resources/views/vendor/sweetalert/alert.blade.php +++ /dev/null @@ -1,14 +0,0 @@ -@if (config('sweetalert.alwaysLoadJS') === true && config('sweetalert.neverLoadJS') === false ) - -@endif -@if (Session::has('alert.config')) - @if(config('sweetalert.animation.enable')) - - @endif - @if (config('sweetalert.alwaysLoadJS') === false && config('sweetalert.neverLoadJS') === false) - - @endif - -@endif diff --git a/tests/Feature/ContactFormTest.php b/tests/Feature/ContactFormTest.php index 6bbc7cd..6d90294 100644 --- a/tests/Feature/ContactFormTest.php +++ b/tests/Feature/ContactFormTest.php @@ -46,6 +46,21 @@ Mail::assertQueued(Contact::class); }); +it('shows the sent message as a Sweet Alert toast after redirecting', function () { + Mail::fake(); + $honeypotFields = getHoneypotFields('/contact'); + $this->travel(config('honeypot.amount_of_seconds') + 1)->seconds(); + + $response = $this->followingRedirects()->from('/contact')->post('/contact', array_merge([ + 'name' => 'John Doe', + 'email' => 'john@example.com', + 'message' => 'Hello, this is a test message.', + ], $honeypotFields)); + + $response->assertOk() + ->assertSee('vendor/sweetalert/sweet-alert.js', false) + ->assertSee('Contact message sent successfully.'); +}); it('cannot submit contact form if honeypot is tripped', function () { Mail::fake();