Media Library - v1.1.0
MediaPicker Component
The MediaPicker is a Livewire component designed for embedding in visual editors and CMS platforms. It provides a modal-based media selection interface with support for filtering, keyboard navigation, and contextual events.
Basic Usage
<livewire:media::media-picker
context="featured-image"
:allowed-types="['image']"
:multi-select="false"
/>
Component Properties
| Property | Type | Default | Description |
|---|---|---|---|
context |
string | '' |
Unique identifier for this picker instance |
allowedTypes |
array | ['image', 'video', 'audio', 'document'] |
Allowed media types |
multiSelect |
bool | false |
Enable multi-selection mode |
maxSelections |
int | null |
Maximum items when multi-select enabled |
folderId |
int | null |
Initial folder to display |
showUpload |
bool | true |
Show upload tab |
showFolders |
bool | true |
Show folder sidebar |
quickUploadSelect |
bool | true |
Auto-select newly uploaded media |
Context Parameter
The context parameter is crucial for identifying which picker instance dispatched an event. This allows multiple pickers on the same page to operate independently.
<!-- Featured image picker -->
<livewire:media::media-picker context="featured-image" />
<!-- Gallery picker -->
<livewire:media::media-picker context="gallery" :multi-select="true" />
<!-- Background image picker -->
<livewire:media::media-picker context="background" />
Opening the Picker
Via Livewire Event
// Open a specific picker by context
Livewire.dispatch('open-media-picker', { context: 'featured-image' });
Via Blade Directive
<button @click="$dispatch('open-media-picker', { context: 'featured-image' })">
Select Image
</button>
Via Component Method
<livewire:media::media-picker context="featured-image" wire:ref="featuredPicker" />
<button wire:click="$refs.featuredPicker.open()">
Select Image
</button>
Events
media-picked
Dispatched when the user confirms their selection.
Payload:
{
context: 'featured-image', // The picker's context
media: [ // Array of selected media
{
id: 123,
title: 'My Image',
file_name: 'my-image.jpg',
mime_type: 'image/jpeg',
url: 'https://example.com/storage/media/my-image.jpg',
thumbnail_url: 'https://example.com/storage/media/thumbnails/my-image.jpg',
alt_text: 'Description',
file_size: 102400,
width: 1920,
height: 1080
}
]
}
Listening for events:
// JavaScript
Livewire.on('media-picked', (event) => {
if (event.context === 'featured-image') {
const selectedMedia = event.media;
// Process the selection
}
});
// Livewire Component
#[On('media-picked')]
public function handleMediaPicked(array $media, string $context): void
{
if ($context === 'featured-image') {
$this->featuredImageId = $media[0]['id'];
}
}
media-picker-opened
Dispatched when the picker modal opens.
Livewire.on('media-picker-opened', (event) => {
console.log('Picker opened:', event.context);
});
media-picker-closed
Dispatched when the picker modal closes (without selection).
Livewire.on('media-picker-closed', (event) => {
console.log('Picker closed:', event.context);
});
Keyboard Navigation
The MediaPicker supports full keyboard navigation:
| Key | Action |
|---|---|
Arrow Left |
Move to previous item |
Arrow Right |
Move to next item |
Arrow Up |
Move to item above (in grid) |
Arrow Down |
Move to item below (in grid) |
Enter |
Toggle selection of focused item |
Space |
Toggle selection of focused item |
Escape |
Close the picker |
Home |
Focus first item |
End |
Focus last item |
Enabling Keyboard Navigation
Keyboard navigation is enabled by default when the picker is open. The focus indicator shows which item is currently focused.
Filtering by Type
Restrict the picker to specific media types:
<!-- Images only -->
<livewire:media::media-picker
context="image-picker"
:allowed-types="['image']"
/>
<!-- Videos only -->
<livewire:media::media-picker
context="video-picker"
:allowed-types="['video']"
/>
<!-- Documents only -->
<livewire:media::media-picker
context="document-picker"
:allowed-types="['document']"
/>
<!-- Multiple types -->
<livewire:media::media-picker
context="media-picker"
:allowed-types="['image', 'video']"
/>
Multi-Selection
Enable multi-select mode for galleries or collections:
<livewire:media::media-picker
context="gallery"
:multi-select="true"
:max-selections="20"
/>
Selection Controls
In multi-select mode, the picker shows:
- "Select All" button to select all visible items
- "Deselect All" button to clear selections
- Selection counter showing current/max selections
Recently Used Media
When track_recently_used is enabled in configuration, the picker shows recently selected media for quick access.
// config/artisanpack.php
'media' => [
'visual_editor' => [
'track_recently_used' => true,
'recently_used_limit' => 20,
],
],
Recently used items appear at the top of the media grid when no search/filter is active.
Quick Upload Select
When enabled, newly uploaded media is automatically selected:
<livewire:media::media-picker
context="quick-picker"
:quick-upload-select="true"
/>
Behavior:
- Single-select mode: Upload completes, media selected, picker closes
- Multi-select mode: Upload completes, media added to selection, picker stays open
Block Type Integration
Use block requirements from configuration:
// In your visual editor component
$requirements = config('artisanpack.media.block_requirements.hero', []);
<livewire:media::media-picker
context="hero-block"
:allowed-types="$requirements['allowed_types'] ?? ['image']"
:max-selections="$requirements['max_selections'] ?? 1"
/>
Styling
The MediaPicker uses daisyUI and Tailwind CSS classes. Customize via:
Publishing Views
php artisan vendor:publish --tag=media-views
Views are published to resources/views/vendor/media/.
CSS Variables
:root {
--media-picker-grid-cols: 4;
--media-picker-item-aspect: 1;
--media-picker-selected-ring: theme('colors.primary');
}
Integration Example
Complete example for a blog post editor:
<!-- Blog Post Editor -->
<div>
<!-- Featured Image Field -->
<div class="form-control">
<label class="label">Featured Image</label>
@if($featuredImage)
<div class="relative w-48 h-32">
<img src="{{ $featuredImage->thumbnail_url }}" class="rounded" />
<button wire:click="removeFeaturedImage" class="btn btn-circle btn-xs absolute top-1 right-1">
✕
</button>
</div>
@else
<button
type="button"
@click="$dispatch('open-media-picker', { context: 'featured-image' })"
class="btn btn-outline"
>
Select Featured Image
</button>
@endif
</div>
<!-- Gallery Field -->
<div class="form-control mt-4">
<label class="label">Gallery Images</label>
<div class="flex flex-wrap gap-2">
@foreach($galleryImages as $image)
<div class="relative w-24 h-24">
<img src="{{ $image->thumbnail_url }}" class="rounded" />
<button wire:click="removeGalleryImage({{ $image->id }})" class="btn btn-circle btn-xs absolute top-1 right-1">
✕
</button>
</div>
@endforeach
<button
type="button"
@click="$dispatch('open-media-picker', { context: 'gallery' })"
class="btn btn-outline w-24 h-24"
>
+ Add
</button>
</div>
</div>
<!-- Media Pickers -->
<livewire:media::media-picker
context="featured-image"
:allowed-types="['image']"
/>
<livewire:media::media-picker
context="gallery"
:allowed-types="['image']"
:multi-select="true"
:max-selections="20"
/>
</div>
@script
<script>
Livewire.on('media-picked', (event) => {
if (event.context === 'featured-image') {
$wire.setFeaturedImage(event.media[0].id);
} else if (event.context === 'gallery') {
$wire.addGalleryImages(event.media.map(m => m.id));
}
});
</script>
@endscript
Next Steps
- Block Content Helpers - Working with block content
- Integration Examples - More complete examples
- Configuration - All configuration options