diff --git a/composer.json b/composer.json index 3bd5092ea..12d57d0b5 100644 --- a/composer.json +++ b/composer.json @@ -35,7 +35,7 @@ "laravel/fortify": "^1.21", "laravel/telescope": "^5.0", "league/commonmark": "^2.4", - "livewire/livewire": "^2.12", + "livewire/livewire": "^3.0", "mockery/mockery": "^1.6", "nunomaduro/collision": "^7.0", "nunomaduro/larastan": "^2.6", diff --git a/composer.lock b/composer.lock index fc8d4de33..813c65ae4 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": "910615e21d6e74f9fc1332f9d4e7280a", + "content-hash": "15ff9f610430ef09133332d0962ad3d4", "packages": [ { "name": "bacon/bacon-qr-code", @@ -3604,34 +3604,37 @@ }, { "name": "livewire/livewire", - "version": "v2.12.6", + "version": "v3.5.0", "source": { "type": "git", "url": "https://github.com/livewire/livewire.git", - "reference": "7d3a57b3193299cf1a0639a3935c696f4da2cf92" + "reference": "72e900825c560f0e4e620185b26c5441a8914435" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/livewire/livewire/zipball/7d3a57b3193299cf1a0639a3935c696f4da2cf92", - "reference": "7d3a57b3193299cf1a0639a3935c696f4da2cf92", + "url": "https://api.github.com/repos/livewire/livewire/zipball/72e900825c560f0e4e620185b26c5441a8914435", + "reference": "72e900825c560f0e4e620185b26c5441a8914435", "shasum": "" }, "require": { - "illuminate/database": "^7.0|^8.0|^9.0|^10.0", - "illuminate/support": "^7.0|^8.0|^9.0|^10.0", - "illuminate/validation": "^7.0|^8.0|^9.0|^10.0", + "illuminate/database": "^10.0|^11.0", + "illuminate/routing": "^10.0|^11.0", + "illuminate/support": "^10.0|^11.0", + "illuminate/validation": "^10.0|^11.0", "league/mime-type-detection": "^1.9", - "php": "^7.2.5|^8.0", - "symfony/http-kernel": "^5.0|^6.0" + "php": "^8.1", + "symfony/console": "^6.0|^7.0", + "symfony/http-kernel": "^6.2|^7.0" }, "require-dev": { "calebporzio/sushi": "^2.1", - "laravel/framework": "^7.0|^8.0|^9.0|^10.0", + "laravel/framework": "^10.15.0|^11.0", + "laravel/prompts": "^0.1.6", "mockery/mockery": "^1.3.1", - "orchestra/testbench": "^5.0|^6.0|^7.0|^8.0", - "orchestra/testbench-dusk": "^5.2|^6.0|^7.0|^8.0", - "phpunit/phpunit": "^8.4|^9.0", - "psy/psysh": "@stable" + "orchestra/testbench": "^8.21.0|^9.0", + "orchestra/testbench-dusk": "^8.24|^9.1", + "phpunit/phpunit": "^10.4", + "psy/psysh": "^0.11.22|^0.12" }, "type": "library", "extra": { @@ -3665,7 +3668,7 @@ "description": "A front-end framework for Laravel.", "support": { "issues": "https://github.com/livewire/livewire/issues", - "source": "https://github.com/livewire/livewire/tree/v2.12.6" + "source": "https://github.com/livewire/livewire/tree/v3.5.0" }, "funding": [ { @@ -3673,7 +3676,7 @@ "type": "github" } ], - "time": "2023-08-11T04:02:34+00:00" + "time": "2024-05-21T13:39:04+00:00" }, { "name": "maennchen/zipstream-php", diff --git a/config/livewire.php b/config/livewire.php index 04b3b8f6f..339cbc4ce 100644 --- a/config/livewire.php +++ b/config/livewire.php @@ -5,95 +5,63 @@ return [ /* - |-------------------------------------------------------------------------- + |--------------------------------------------------------------------------- | Class Namespace - |-------------------------------------------------------------------------- + |--------------------------------------------------------------------------- | - | This value sets the root namespace for Livewire component classes in - | your application. This value affects component auto-discovery and - | any Livewire file helper commands, like `artisan make:livewire`. - | - | After changing this item, run: `php artisan livewire:discover`. + | This value sets the root class namespace for Livewire component classes in + | your application. This value will change where component auto-discovery + | finds components. It's also referenced by the file creation commands. | */ 'class_namespace' => 'App\\Http\\Livewire', /* - |-------------------------------------------------------------------------- + |--------------------------------------------------------------------------- | View Path - |-------------------------------------------------------------------------- + |--------------------------------------------------------------------------- | - | This value sets the path for Livewire component views. This affects - | file manipulation helper commands like `artisan make:livewire`. + | This value is used to specify where Livewire component Blade templates are + | stored when running file creation commands like `artisan make:livewire`. + | It is also used if you choose to omit a component's render() method. | */ 'view_path' => resource_path('views/livewire'), /* - |-------------------------------------------------------------------------- + |--------------------------------------------------------------------------- | Layout - |-------------------------------------------------------------------------- - | The default layout view that will be used when rendering a component via - | Route::get('/some-endpoint', SomeComponent::class);. In this case the - | the view returned by SomeComponent will be wrapped in "layouts.app" + |--------------------------------------------------------------------------- + | The view that will be used as the layout when rendering a single component + | as an entire page via `Route::get('/post/create', CreatePost::class);`. + | In this case, the view returned by CreatePost will render into $slot. | */ 'layout' => 'layouts.app', /* - |-------------------------------------------------------------------------- - | Livewire Assets URL - |-------------------------------------------------------------------------- - | - | This value sets the path to Livewire JavaScript assets, for cases where - | your app's domain root is not the correct path. By default, Livewire - | will load its JavaScript assets from the app's "relative root". - | - | Examples: "/assets", "myurl.com/app". - | - */ - - 'asset_url' => null, - - /* - |-------------------------------------------------------------------------- - | Livewire App URL - |-------------------------------------------------------------------------- - | - | This value should be used if livewire assets are served from CDN. - | Livewire will communicate with an app through this url. - | - | Examples: "https://my-app.com", "myurl.com/app". + |--------------------------------------------------------------------------- + | Lazy Loading Placeholder + |--------------------------------------------------------------------------- + | Livewire allows you to lazy load components that would otherwise slow down + | the initial page load. Every component can have a custom placeholder or + | you can define the default placeholder view for all components below. | */ - 'app_url' => null, + 'lazy_placeholder' => null, /* - |-------------------------------------------------------------------------- - | Livewire Endpoint Middleware Group - |-------------------------------------------------------------------------- - | - | This value sets the middleware group that will be applied to the main - | Livewire "message" endpoint (the endpoint that gets hit everytime - | a Livewire component updates). It is set to "web" by default. - | - */ - - 'middleware_group' => 'web', - - /* - |-------------------------------------------------------------------------- - | Livewire Temporary File Uploads Endpoint Configuration - |-------------------------------------------------------------------------- + |--------------------------------------------------------------------------- + | Temporary File Uploads + |--------------------------------------------------------------------------- | | Livewire handles file uploads by storing uploads in a temporary directory - | before the file is validated and stored permanently. All file uploads - | are directed to a global endpoint for temporary storage. The config - | items below are used for customizing the way the endpoint works. + | before the file is stored permanently. All file uploads are directed to + | a global endpoint for temporary storage. You may configure this below: | */ @@ -108,53 +76,88 @@ 'jpg', 'jpeg', 'mpga', 'webp', 'wma', ], 'max_upload_time' => 5, // Max duration (in minutes) before an upload gets invalidated. + 'cleanup' => true, // Should cleanup temporary uploads older than 24 hrs... ], /* - |-------------------------------------------------------------------------- - | Manifest File Path - |-------------------------------------------------------------------------- + |--------------------------------------------------------------------------- + | Render On Redirect + |--------------------------------------------------------------------------- | - | This value sets the path to the Livewire manifest file. - | The default should work for most cases (which is - | "/bootstrap/cache/livewire-components.php"), but for specific - | cases like when hosting on Laravel Vapor, it could be set to a different value. + | This value determines if Livewire will run a component's `render()` method + | after a redirect has been triggered using something like `redirect(...)` + | Setting this to true will render the view once more before redirecting | - | Example: for Laravel Vapor, it would be "/tmp/storage/bootstrap/cache/livewire-components.php". + */ + + 'render_on_redirect' => true, + + /* + |--------------------------------------------------------------------------- + | Eloquent Model Binding + |--------------------------------------------------------------------------- + | + | Previous versions of Livewire supported binding directly to eloquent model + | properties using wire:model by default. However, this behavior has been + | deemed too "magical" and has therefore been put under a feature flag. + | + */ + + 'legacy_model_binding' => false, + + /* + |--------------------------------------------------------------------------- + | Auto-inject Frontend Assets + |--------------------------------------------------------------------------- + | + | By default, Livewire automatically injects its JavaScript and CSS into the + | and of pages containing Livewire components. By disabling + | this behavior, you need to use @livewireStyles and @livewireScripts. | */ - 'manifest_path' => null, + 'inject_assets' => true, /* - |-------------------------------------------------------------------------- - | Back Button Cache - |-------------------------------------------------------------------------- + |--------------------------------------------------------------------------- + | Navigate (SPA mode) + |--------------------------------------------------------------------------- | - | This value determines whether the back button cache will be used on pages - | that contain Livewire. By disabling back button cache, it ensures that - | the back button shows the correct state of components, instead of - | potentially stale, cached data. + | By adding `wire:navigate` to links in your Livewire application, Livewire + | will prevent the default link handling and instead request those pages + | via AJAX, creating an SPA-like effect. Configure this behavior here. | - | Setting it to "false" (default) will disable back button cache. + */ + + 'navigate' => [ + 'show_progress_bar' => true, + 'progress_bar_color' => '#2299dd', + ], + + /* + |--------------------------------------------------------------------------- + | HTML Morph Markers + |--------------------------------------------------------------------------- + | + | Livewire intelligently "morphs" existing HTML into the newly rendered HTML + | after each update. To make this process more reliable, Livewire injects + | "markers" into the rendered Blade surrounding @if, @class & @foreach. | */ - 'back_button_cache' => false, + 'inject_morph_markers' => true, /* - |-------------------------------------------------------------------------- - | Render On Redirect - |-------------------------------------------------------------------------- + |--------------------------------------------------------------------------- + | Pagination Theme + |--------------------------------------------------------------------------- | - | This value determines whether Livewire will render before it's redirected - | or not. Setting it to "false" (default) will mean the render method is - | skipped when redirecting. And "true" will mean the render method is - | run before redirecting. Browsers bfcache can store a potentially - | stale view if render is skipped on redirect. + | When enabling Livewire's pagination feature by using the `WithPagination` + | trait, Livewire will use Tailwind templates to render pagination views + | on the page. If you want Bootstrap CSS, you can specify: "bootstrap" | */ - 'render_on_redirect' => true, + 'pagination_theme' => 'tailwind', ]; diff --git a/examples/ui.md b/examples/ui.md index 52a63109c..9ad1d305a 100644 --- a/examples/ui.md +++ b/examples/ui.md @@ -172,7 +172,7 @@ This file contains basic examples and explains the parameters that can be used f ### Upload Single Image This component renders an input file for a single image upload. ```html - + ``` > It requires the use of a Livewire Component. > There is a trait that can be used with your Livewire Component `\ARKEcosystem\UserInterface\Components\UploadImageSingle`. @@ -227,7 +227,7 @@ laravel([ + ``` > It requires the use of a Livewire Component. > There is a trait that can be used with your Livewire Component `\ARKEcosystem\UserInterface\Components\UploadImageCollection`. @@ -338,7 +338,7 @@ public function imagesReordered(array $ids): void { [...bags].forEach(({ value }) => - Livewire.emit("toastMessage", [ - `${value} - ${file.name}`, - "danger", - ]) + Livewire.dispatch("toastMessage", { + message: `${value} - ${file.name}`, + type: "danger", + }) ); }); }); diff --git a/resources/assets/js/crop-image.js b/resources/assets/js/crop-image.js index 20c6663a7..06b9d0088 100644 --- a/resources/assets/js/crop-image.js +++ b/resources/assets/js/crop-image.js @@ -68,13 +68,13 @@ const CropImage = ( this.uploadEl = document.getElementById($uploadID); Livewire.on("discardCroppedImage", () => { - Livewire.emit("closeModal", $modalID); + Livewire.dispatch("closeModal", $modalID); this.discardImage(); }); Livewire.on("saveCroppedImage", () => { - Livewire.emit("closeModal", $modalID); + Livewire.dispatch("closeModal", $modalID); this.saveCroppedImage(); this.discardImage(); @@ -132,7 +132,10 @@ const CropImage = ( Object.values(errors.getAll()).forEach((bags) => { [...bags].forEach(({ value }) => - Livewire.emit("toastMessage", [value, "danger"]) + Livewire.dispatch("toastMessage", { + message: value, + type: "danger", + }) ); }); }); @@ -193,7 +196,7 @@ const CropImage = ( }, openCropModal() { - Livewire.emit("openModal", $modalID); + Livewire.dispatch("openModal", $modalID); }, }); diff --git a/resources/assets/js/lazy-image-loading.js b/resources/assets/js/lazy-image-loading.js index c5dc93f0d..ba40c1e75 100644 --- a/resources/assets/js/lazy-image-loading.js +++ b/resources/assets/js/lazy-image-loading.js @@ -172,7 +172,11 @@ export default function lazyLoad(selector = "[lazy]") { } function registerLivewireObserver() { - Livewire.hook("message.processed", () => registerLazyElements()); + Livewire.hook("commit", ({ succeed }) => { + succeed(() => { + registerLazyElements(); + }); + }); } } diff --git a/resources/assets/js/markdown-editor/markdown-editor.js b/resources/assets/js/markdown-editor/markdown-editor.js index 7c85a26a4..755e6f0d4 100644 --- a/resources/assets/js/markdown-editor/markdown-editor.js +++ b/resources/assets/js/markdown-editor/markdown-editor.js @@ -204,7 +204,7 @@ const MarkdownEditor = ( } }, openModal(modelName) { - Livewire.emit("openModal", modelName); + Livewire.dispatch("openModal", modelName); }, initModals() { initModalhandler(this.editor, "imageModal", (formData) => { diff --git a/resources/assets/js/markdown-editor/utils/utils.js b/resources/assets/js/markdown-editor/utils/utils.js index 41c65df05..2c511f527 100644 --- a/resources/assets/js/markdown-editor/utils/utils.js +++ b/resources/assets/js/markdown-editor/utils/utils.js @@ -68,7 +68,7 @@ export const initModalhandler = (editor, modalName, getReplacement) => { Alpine.raw(editor).replaceSelection(replacement); - Livewire.emit("closeModal", modalName); + Livewire.dispatch("closeModal", modalName); form.reset(); diff --git a/resources/assets/js/tags.js b/resources/assets/js/tags.js index ce5984b8f..a1be70aea 100644 --- a/resources/assets/js/tags.js +++ b/resources/assets/js/tags.js @@ -174,9 +174,9 @@ const Tags = ( return window.livewire.find(element.getAttribute("wire:id")); }, - displayLivewireToast(validationMessage) { + displayLivewireToast(message) { if (typeof livewire !== "undefined") { - livewire.emit("toastMessage", [validationMessage, "warning"]); + livewire.dispatch("toastMessage", { message, type: "warning" }); } }, hideTooltip() { diff --git a/resources/assets/js/tippy.js b/resources/assets/js/tippy.js index d56290f58..326fe9a45 100644 --- a/resources/assets/js/tippy.js +++ b/resources/assets/js/tippy.js @@ -127,13 +127,19 @@ window.initClipboard = () => { }); }; -if (typeof Livewire !== "undefined") { - Livewire.hook("message.processed", (message, component) => { - destroyOutdatedTippyInstances(component.el); - - initTippy(component.el); - }); -} +document.addEventListener("DOMContentLoaded", function () { + if (typeof Livewire !== "undefined") { + Livewire.hook("commit", ({ component, succeed }) => { + succeed(() => { + Alpine.nextTick(() => { + destroyOutdatedTippyInstances(); + + initTippy(component.el); + }); + }); + }); + } +}); window.tippy = tippy; window.hideAllTooltips = hideAll; diff --git a/resources/views/auth/reset-password-form.blade.php b/resources/views/auth/reset-password-form.blade.php index cb92a6620..6c55553d8 100644 --- a/resources/views/auth/reset-password-form.blade.php +++ b/resources/views/auth/reset-password-form.blade.php @@ -5,7 +5,7 @@
diff --git a/resources/views/components/blog/kiosk/delete-user.blade.php b/resources/views/components/blog/kiosk/delete-user.blade.php index ce3572d7d..6e2555469 100644 --- a/resources/views/components/blog/kiosk/delete-user.blade.php +++ b/resources/views/components/blog/kiosk/delete-user.blade.php @@ -16,7 +16,7 @@
@if ($this->isNotificationSelected($notification->id)) @endif @@ -168,7 +168,7 @@ class="cursor-pointer focus-visible:rounded text-theme-primary-300 dark:text-the @@ -176,7 +176,7 @@ class="sm:mr-2 focus-visible:rounded transition-default" diff --git a/resources/views/external-link-confirm.blade.php b/resources/views/external-link-confirm.blade.php index 5cc7b5e37..f7569e76b 100644 --- a/resources/views/external-link-confirm.blade.php +++ b/resources/views/external-link-confirm.blade.php @@ -125,7 +125,7 @@ function initExternalLinkConfirm() { e.stopPropagation(); - Livewire.emit('openModal', 'external-link-confirm', link.getAttribute('href')); + Livewire.dispatch('openModal', 'external-link-confirm', link.getAttribute('href')); }; link.addEventListener("auxclick", (event) => { @@ -138,8 +138,10 @@ function initExternalLinkConfirm() { }); } - Livewire.hook("message.processed", function (message, component) { - initExternalLinkConfirm(); + Livewire.hook("commit", ({ succeed }) => { + succeed(() => { + initExternalLinkConfirm(); + }); }); initExternalLinkConfirm(); diff --git a/resources/views/inputs/checkbox.blade.php b/resources/views/inputs/checkbox.blade.php index 9662133b9..5b17f9688 100644 --- a/resources/views/inputs/checkbox.blade.php +++ b/resources/views/inputs/checkbox.blade.php @@ -50,13 +50,13 @@ class="focus-visible:ring-2 form-checkbox input-checkbox focus-visible:ring-them @unless ($noLivewire) @if ($deferred) - wire:model.defer="{{ $model ?? $name }}" + wire:model="{{ $model ?? $name }}" @elseif ($debounce === true) wire:model.debounce="{{ $model ?? $name }}" @elseif (is_string($debounce)) wire:model.debounce.{{ $debounce }}="{{ $model ?? $name }}" @else - wire:model="{{ $model ?? $name }}" + wire:model.live="{{ $model ?? $name }}" @endif @endunless diff --git a/resources/views/inputs/includes/input-field.blade.php b/resources/views/inputs/includes/input-field.blade.php index 4b87f7f31..d32f3eee1 100644 --- a/resources/views/inputs/includes/input-field.blade.php +++ b/resources/views/inputs/includes/input-field.blade.php @@ -17,13 +17,13 @@ class="{{ $inputClass }} {{ $inputTypeClass }} @if ($errors) @error($name) {{ $errorClass }} @enderror @endif" @unless ($noModel) @if ($deferred) - wire:model.defer="{{ $model ?? $name }}" + wire:model="{{ $model ?? $name }}" @elseif ($debounce === true) wire:model.debounce="{{ $model ?? $name }}" @elseif (is_string($debounce)) wire:model.debounce.{{ $debounce }}="{{ $model ?? $name }}" @else - wire:model="{{ $model ?? $name }}" + wire:model.live="{{ $model ?? $name }}" @endif @endUnless {{ $attributes->except([ diff --git a/resources/views/inputs/includes/markdown/alert-modal.blade.php b/resources/views/inputs/includes/markdown/alert-modal.blade.php index 417ba3e41..9b1b8a8b7 100644 --- a/resources/views/inputs/includes/markdown/alert-modal.blade.php +++ b/resources/views/inputs/includes/markdown/alert-modal.blade.php @@ -5,7 +5,7 @@ width-class="max-w-lg" > @slot('description') -
+ @slot('description') - + @slot('description') - + @slot('description') - + @slot('description') - + {{-- @TODO: Add file upload --}} {{--
diff --git a/resources/views/inputs/includes/markdown/link-collection-modal.blade.php b/resources/views/inputs/includes/markdown/link-collection-modal.blade.php index fc984dca1..87a56e67d 100644 --- a/resources/views/inputs/includes/markdown/link-collection-modal.blade.php +++ b/resources/views/inputs/includes/markdown/link-collection-modal.blade.php @@ -36,7 +36,7 @@ }" > @slot('description') - +