al-saloul/filament-image-gallery
Installation
composer require al-saloul/filament-image-gallery
Publish the config (if needed):
php artisan vendor:publish --provider="AlSaloul\FilamentImageGallery\FilamentImageGalleryServiceProvider"
Register the Plugin
Add to app/Providers/Filament/AdminPanelProvider.php:
public function panel(Panel $panel): Panel
{
return $panel
->plugins([
\AlSaloul\FilamentImageGallery\FilamentImageGalleryPlugin::make(),
]);
}
First Use Case: Table Column
use AlSaloul\FilamentImageGallery\Columns\ImageGalleryColumn;
ImageGalleryColumn::make('images')
->images(fn ($record) => $record->images) // Array of image URLs
->thumbnailWidth(100) // Optional: Set thumbnail dimensions
->thumbnailHeight(100);
First Use Case: Infolist Entry
use AlSaloul\FilamentImageGallery\Widgets\ImageGalleryWidget;
ImageGalleryWidget::make('images')
->images(fn ($record) => $record->images)
->columns(3); // Optional: Set columns for thumbnail grid
Leverage closures for dynamic image paths:
ImageGalleryColumn::make('gallery')
->images(fn ($record) => [
Storage::disk('public')->url($record->image1),
Storage::disk('public')->url($record->image2),
]);
Configure Viewer.js options via config (config/filament-image-gallery.php):
'viewer_options' => [
'zoomRatio' => 0.5, // Default zoom increment
'button' => true, // Show/hide buttons
'toolbar' => true, // Show/hide toolbar
],
Use in Custom Fields for uploads:
use AlSaloul\FilamentImageGallery\Fields\ImageGalleryField;
ImageGalleryField::make('gallery')
->images(fn ($record) => $record->images)
->addAction(
Action::make('edit')
->action(fn ($record) => $this->edit($record))
),
booted() method:
public function booted()
{
Cache::remember('image-gallery-thumbs', now()->addHours(1), function () {
return Image::whereIn('id', [1, 2, 3])->get()->pluck('thumbnail_path');
});
}
loading="lazy" in blade templates if extending manually.Override default labels in config:
'translations' => [
'zoom_in' => __('Zoom In'),
'zoom_out' => __('Zoom Out'),
'rotate_left' => __('Rotate Left'),
'rotate_right' => __('Rotate Right'),
],
ImageGalleryColumn::make('media')
->images(fn ($record) => $record->getMedia('images')->pluck('full_url')),
Pass data via props:
public $images = [];
public function mount()
{
$this->images = $record->images->pluck('url')->toArray();
}
Then render the gallery in Blade:
<x-filament-image-gallery :images="$images" />
Override CSS via resources/css/filament-image-gallery.css:
.viewerjs {
--thumbnail-width: 120px;
--thumbnail-height: 120px;
}
/storage/image.jpg) or missing http://.https://example.com/storage/image.jpg) or Laravel’s Storage::url().http://localhost), ensure:
http:// (not https://) for local URLs to avoid mixed-content warnings.thumbnailWidth/Height if images aren’t pre-processed.Image facade to generate thumbnails:
$thumbs = $record->images->map(fn ($image) => Image::make($image)->resize(100, 100)->path());
AdminPanelProvider).->plugins([]).storage/logs/laravel.log.// In a custom JS file, initialize Viewer.js only once:
document.addEventListener('DOMContentLoaded', function() {
new Viewer(document.getElementById('gallery'), {
// Options here
});
});
Inspect the rendered HTML for:
<div id="gallery" class="viewerjs"></div>
Check browser console for errors like:
Uncaught ReferenceError: Viewer is not defined
→ Fix: Ensure viewer.js is loaded (check public/vendor/filament-image-gallery/).
Debug dynamic image sources:
->images(fn ($record) => {
\Log::debug('Gallery images:', $record->images->toArray());
return $record->images->pluck('url');
}),
Clear Filament cache:
php artisan filament:cache:clear
Force options via JavaScript:
document.addEventListener('filament-image-gallery-ready', function(e) {
e.detail.viewer.options.zoomRatio = 0.25;
});
Extend Viewer.js toolbar:
// In a custom JS file:
document.addEventListener('filament-image-gallery-ready', function(e) {
e.detail.viewer.toolbar.addButton({
id: 'custom-button',
text: 'Custom Action',
action: () => alert('Custom action triggered!')
});
});
Hook into ImageGalleryColumn to process images before display:
use AlSaloul\FilamentImageGallery\Columns\ImageGalleryColumn;
ImageGalleryColumn::make('processed_gallery')
->images(fn ($record) => {
return $record->images->map(function ($image) {
return Image::make($image->path)
->resize(800, 600)
->encode()
->path;
});
}),
For non-public storage (e.g., S3 private files), use signed URLs:
->images(fn ($record) => $record->images->map(fn ($image) =>
Storage::disk('s3')->temporaryUrl(
$image->path,
now()->addMinutes(30),
['ResponseContentDisposition' => 'inline']
)
)),
Listen for gallery interactions:
// In a service provider:
event(new FilamentImageGalleryEvent($images, $record));
(Note: Requires extending the package or using JavaScript events.)
Extend translations in resources/lang/en/filament-image-gallery.php:
return [
'zoom_in' => 'Ampliar',
'zoom_out' => 'Reducir',
// ... other keys
];
How can I help you explore Laravel packages today?