diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c22916..0496524 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,12 +11,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added - +- **Deferred uploads on create**: You can now queue files before the target model exists and attach them after save by dispatching the `media:attach` event. The uploader accepts `model="post"` (no `id`) on create screens, holds the queue + per-file meta, and attaches once you dispatch. Emits `media-attached` when done. +- **`list-all` view**: Set `:list-all="true"` to show **all collections** for the current model in a single list, grouped by collection name. Items remain fully editable (caption/description/order). +- **Tailwind dark mode docs/snippets**: Added guidance and examples for enabling global light/dark mode with the Tailwind theme. ### Changed +- Graceful “no target yet” behavior on create screens: + - `nextOrder()` now derives order from the local queue if the model isn’t saved yet. + - `uploadFiles()` **queues** when there’s no target (instead of erroring) and flashes: _“Files queued. They will be attached after you save.”_ ### Fixed - +- N/A --- ## [v0.2.0] — 2025-09-01 @@ -95,5 +100,5 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 --- -[Unreleased]: https://github.com/codebyray/livewire-media-uploader/compare/v0.1.0...HEAD +[Unreleased]: https://github.com/codebyray/livewire-media-uploader/compare/v0.2.0...HEAD [v0.1.0]: https://github.com/codebyray/livewire-media-uploader/releases/tag/v0.1.0 diff --git a/README.md b/README.md index 2e0e7ac..3a64da3 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,12 @@ Livewire Media Uploader is a reusable Livewire v3 component that integrates seam - [Requirements](#requirements) - [Installation](#installation) - [Publishing Assets](#publishing-assets) +- [Theme System](#theme-system-tailwind--bootstrap--custom) + - [Dark Mode - Tailwind](#dark-mode-tailwind-theme) + - [Custom Theme](#custom-themes) - [Quick Start](#quick-start) - [Usage Examples](#usage-examples) + - [Create flow (deferred uploads)](#create-flow-deferred-uploads) - [Configuration](#configuration) - [Props](#props) - [Events](#events) @@ -112,6 +116,19 @@ return [ // ... ]; ``` +### Dark mode (Tailwind theme) +This package’s Tailwind theme is dark-ready. Add this tiny snippet in your main layout `` to apply the user’s saved choice / system default: + +```html + +``` ### Custom themes - Copy an existing theme directory (e.g. themes/tailwind) to themes/custom and edit the Blade. - Register it in the map and select it: @@ -293,7 +310,75 @@ MEDIA_MAXKB_DEFAULT=10240 :maxSizeKb="5120" /> ``` +### Create flow (deferred uploads) + +You can let users pick files **before** the model exists, and attach them **after** save. + +**Blade (create page)** +```html + + +``` +#### Livewire component (simplified) +```php +use App\Models\Post; +use Illuminate\Support\Facades\Auth; +use Livewire\Attributes\On; +use Livewire\Component; + +class PostCreate extends Component +{ + public string $title = ''; + public string $body = ''; + public ?int $pendingPostId = null; + + protected function rules(): array + { + return ['title' => 'required|string|max:255', 'body' => 'required|string']; + } + + public function save(): void + { + $post = Post::create([ + 'user_id' => Auth::id(), + 'title' => $this->title, + 'body' => $this->body, + ]); + + // Let uploaders attach everything queued for this collection + $this->pendingPostId = $post->id; + // Fire once per collection rendered on the page + $this->dispatch('media:attach', model: 'post', id: $post->id, collection: 'images'); + } + + #[On('media-attached')] + public function afterMediaAttached(string $model, string|int $id): void + { + if ($this->pendingPostId && (int)$id === (int)$this->pendingPostId) { + $this->pendingPostId = null; + $this->redirectRoute('posts.show', ['post' => $id], navigate: true); + } + } + + public function render() { return view('livewire.posts.post-create'); } +} +``` + +#### How it works +- On create screens, the component accepts model="post" without an id. +- Files and per-file metadata are queued locally. +- After you persist the model, dispatch: + ```php + $this->dispatch('media:attach', model: 'post', id: $post->id, collection: 'images'); + ``` +- The uploader resolves the saved target, attaches any queued files, and emits media-attached. --- ## Configuration @@ -314,7 +399,16 @@ Example: 'attachments' => 'docs', ], ``` +Show all collections together (grouped) +Set `:list-all="true"` to render a grouped list of **every collection** on the target model. Items stay fully editable. +```html + +``` The component decides the active preset in this order: 1. Explicit `$preset` prop 2. Mapping from `collections` @@ -343,6 +437,7 @@ The component decides the active preset in this order: | `namespaces` | `array` | `['App\\Models']` | Namespaces for dotted-path resolution. | | `aliases` | `array` | `[]` | Local alias map, e.g. `['profile' => \App\Models\User::class]`. | | `attachedFilesTitle` | `string` | `"Current gallery"` | Heading text in the list card. | +| `listAll` | `bool` | `false` | When `true`, the attached media list shows **all collections**, grouped by collection name (still editable). | --- @@ -350,9 +445,11 @@ The component decides the active preset in this order: The component dispatches browser events you can listen for: -- `media-uploaded` — after an upload completes -- `media-deleted` — after a deletion (`detail.id` contains the Media ID) -- `media-meta-updated` — after saving inline metadata +- `media:attach` — **incoming** event the component listens for. Arguments: `model` (class/alias), `id`, optional `collection`, optional `disk`. Triggers attaching of any queued files to the now-saved target. +- `media-attached` — emitted after a successful `media:attach`. Payload: `{ model: FQCN, id: string }`. +- `media-uploaded` — emitted after an immediate upload (when a target already exists). +- `media-deleted` — emitted after deletion (`detail.id` contains the Media ID). +- `media-meta-updated` — emitted after inline metadata is saved. Example: ```html diff --git a/resources/views/themes/bootstrap/media-uploader.blade.php b/resources/views/themes/bootstrap/media-uploader.blade.php index b8aa591..a694014 100644 --- a/resources/views/themes/bootstrap/media-uploader.blade.php +++ b/resources/views/themes/bootstrap/media-uploader.blade.php @@ -256,144 +256,242 @@ class="btn btn-outline-secondary btn-sm d-inline-flex align-items-center gap-2"

No gallery images yet.

@else - + @endif + @endif -
No gallery images yet.

@else - + @endif - +