feat: Add image gallery support for ImageColumn and ImageEntry with macros
This commit is contained in:
12
CHANGELOG.md
12
CHANGELOG.md
@@ -2,6 +2,18 @@
|
||||
|
||||
All notable changes to `filament-image-gallery` will be documented in this file.
|
||||
|
||||
## v2.1.0 - 2025-12-13
|
||||
|
||||
### Added
|
||||
- `imageGallery()` macro for `Filament\Tables\Columns\ImageColumn`
|
||||
- `imageGallery()` macro for `Filament\Infolists\Components\ImageEntry`
|
||||
- Support for using standard Filament Image components with the gallery viewer
|
||||
|
||||
## v2.0.6 - 2024-12-12
|
||||
|
||||
### Fixed
|
||||
- Minor bug fixes
|
||||
|
||||
## v2.0.5 - 2024-12-11
|
||||
|
||||
### Fixed
|
||||
|
||||
26
README.md
26
README.md
@@ -42,6 +42,32 @@ A Filament plugin for displaying image galleries with zoom, rotate, flip, and fu
|
||||
composer require al-saloul/filament-image-gallery
|
||||
```
|
||||
|
||||
|
||||
## Quick Usage
|
||||
|
||||
You can use the `imageGallery()` method on any standard Filament `ImageColumn` or `ImageEntry` to enable the gallery viewer.
|
||||
|
||||
### Table Column
|
||||
|
||||
```php
|
||||
use Filament\Tables\Columns\ImageColumn;
|
||||
|
||||
ImageColumn::make('images')
|
||||
->circular()
|
||||
->stacked()
|
||||
->limit(3)
|
||||
->imageGallery() // Enables the gallery viewer
|
||||
```
|
||||
|
||||
### Infolist Entry
|
||||
|
||||
```php
|
||||
use Filament\Infolists\Components\ImageEntry;
|
||||
|
||||
ImageEntry::make('images')
|
||||
->imageGallery() // Enables the gallery viewer
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Table Column
|
||||
|
||||
94
resources/views/columns/image-column-gallery.blade.php
Normal file
94
resources/views/columns/image-column-gallery.blade.php
Normal file
@@ -0,0 +1,94 @@
|
||||
@php
|
||||
$state = $getState();
|
||||
|
||||
if ($state instanceof \Illuminate\Support\Collection) {
|
||||
$state = $state->all();
|
||||
}
|
||||
|
||||
$state = \Illuminate\Support\Arr::wrap($state);
|
||||
|
||||
$limit = $getLimit();
|
||||
$limitedState = $limit ? array_slice($state, 0, $limit) : $state;
|
||||
$remaining = $limit ? max(0, count($state) - $limit) : 0;
|
||||
|
||||
$isCircular = $isCircular();
|
||||
$isSquare = $isSquare();
|
||||
$isStacked = $isStacked();
|
||||
$overlap = $isStacked ? ($getOverlap() ?? 2) : null;
|
||||
|
||||
$defaultWidth = $getWidth();
|
||||
$defaultHeight = $getHeight();
|
||||
|
||||
$defaultWidth = $defaultWidth ? (is_numeric($defaultWidth) ? $defaultWidth . 'px' : $defaultWidth) : '40px';
|
||||
$defaultHeight = $defaultHeight ? (is_numeric($defaultHeight) ? $defaultHeight . 'px' : $defaultHeight) : '40px';
|
||||
|
||||
$galleryId = 'gallery-' . str_replace(['{', '}', '-'], '', (string) \Illuminate\Support\Str::uuid());
|
||||
@endphp
|
||||
|
||||
<div
|
||||
id="{{ $galleryId }}"
|
||||
{{
|
||||
$attributes
|
||||
->merge($getExtraAttributes(), escape: false)
|
||||
->class([
|
||||
'fi-ta-image',
|
||||
'flex items-center',
|
||||
match ($overlap) {
|
||||
1 => '-space-x-1 rtl:space-x-reverse',
|
||||
2 => '-space-x-2 rtl:space-x-reverse',
|
||||
3 => '-space-x-3 rtl:space-x-reverse',
|
||||
4 => '-space-x-4 rtl:space-x-reverse',
|
||||
5 => '-space-x-5 rtl:space-x-reverse',
|
||||
6 => '-space-x-6 rtl:space-x-reverse',
|
||||
7 => '-space-x-7 rtl:space-x-reverse',
|
||||
8 => '-space-x-8 rtl:space-x-reverse',
|
||||
default => 'gap-1.5',
|
||||
},
|
||||
])
|
||||
}}
|
||||
data-viewer-gallery
|
||||
wire:ignore.self
|
||||
>
|
||||
@foreach ($limitedState as $stateItem)
|
||||
<img
|
||||
src="{{ $getImageUrl($stateItem) }}"
|
||||
style="
|
||||
height: {{ $defaultHeight }};
|
||||
width: {{ $defaultWidth }};
|
||||
cursor: pointer;
|
||||
"
|
||||
{{
|
||||
$getExtraImgAttributeBag()
|
||||
->class([
|
||||
'max-w-none object-cover object-center curor',
|
||||
'rounded-full' => $isCircular,
|
||||
'rounded-lg' => $isSquare,
|
||||
'ring-white dark:ring-gray-900' => $isStacked,
|
||||
'ring-2' => $isStacked && ($overlap === null || $overlap > 0),
|
||||
])
|
||||
}}
|
||||
/>
|
||||
@endforeach
|
||||
|
||||
@if ($remaining > 0 && ($limitedRemainingText ?? true))
|
||||
<div
|
||||
style="
|
||||
min-height: {{ $defaultHeight }};
|
||||
min-width: {{ $defaultWidth }};
|
||||
height: {{ $defaultHeight }};
|
||||
width: {{ $defaultWidth }};
|
||||
"
|
||||
@class([
|
||||
'flex items-center justify-center font-medium text-gray-500',
|
||||
])
|
||||
>
|
||||
<span class="-ms-0.5 text-xs">
|
||||
+{{ $remaining }}
|
||||
</span>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@once
|
||||
<x-image-gallery::viewer-script />
|
||||
@endonce
|
||||
@@ -0,0 +1,99 @@
|
||||
@php
|
||||
$state = $getState();
|
||||
|
||||
if ($state instanceof \Illuminate\Support\Collection) {
|
||||
$state = $state->all();
|
||||
}
|
||||
|
||||
$state = \Illuminate\Support\Arr::wrap($state);
|
||||
|
||||
$limit = $getLimit();
|
||||
$limitedState = $limit ? array_slice($state, 0, $limit) : $state;
|
||||
$remaining = $limit ? max(0, count($state) - $limit) : 0;
|
||||
|
||||
$isCircular = $isCircular();
|
||||
$isSquare = $isSquare();
|
||||
$isStacked = $isStacked();
|
||||
$overlap = $isStacked ? ($getOverlap() ?? 2) : null;
|
||||
|
||||
$defaultWidth = $getWidth();
|
||||
$defaultHeight = $getHeight();
|
||||
|
||||
$defaultWidth = $defaultWidth ? (is_numeric($defaultWidth) ? $defaultWidth . 'px' : $defaultWidth) : 'auto';
|
||||
$defaultHeight = $defaultHeight ? (is_numeric($defaultHeight) ? $defaultHeight . 'px' : $defaultHeight) : '150px';
|
||||
|
||||
$galleryId = 'gallery-' . str_replace(['{', '}', '-'], '', (string) \Illuminate\Support\Str::uuid());
|
||||
@endphp
|
||||
|
||||
<x-dynamic-component :component="$getEntryWrapperView()" :entry="$entry">
|
||||
<div
|
||||
id="{{ $galleryId }}"
|
||||
{{
|
||||
$attributes
|
||||
->merge($getExtraAttributes(), escape: false)
|
||||
->class([
|
||||
'fi-in-image',
|
||||
'flex items-center',
|
||||
match ($overlap) {
|
||||
1 => '-space-x-1 rtl:space-x-reverse',
|
||||
2 => '-space-x-2 rtl:space-x-reverse',
|
||||
3 => '-space-x-3 rtl:space-x-reverse',
|
||||
4 => '-space-x-4 rtl:space-x-reverse',
|
||||
5 => '-space-x-5 rtl:space-x-reverse',
|
||||
6 => '-space-x-6 rtl:space-x-reverse',
|
||||
7 => '-space-x-7 rtl:space-x-reverse',
|
||||
8 => '-space-x-8 rtl:space-x-reverse',
|
||||
default => 'gap-1.5',
|
||||
},
|
||||
])
|
||||
}}
|
||||
data-viewer-gallery
|
||||
wire:ignore.self
|
||||
>
|
||||
@foreach ($limitedState as $stateItem)
|
||||
<img
|
||||
src="{{ $getImageUrl($stateItem) }}"
|
||||
style="
|
||||
height: {{ $defaultHeight }};
|
||||
width: {{ $defaultWidth }};
|
||||
cursor: pointer;
|
||||
"
|
||||
{{
|
||||
$getExtraImgAttributeBag()
|
||||
->class([
|
||||
'max-w-none object-cover object-center',
|
||||
'rounded-full' => $isCircular,
|
||||
'rounded-lg' => $isSquare,
|
||||
'ring-white dark:ring-gray-900' => $isStacked,
|
||||
'ring-2' => $isStacked && ($overlap === null || $overlap > 0),
|
||||
])
|
||||
}}
|
||||
/>
|
||||
@endforeach
|
||||
|
||||
@if ($remaining > 0 && ($limitedRemainingText ?? true))
|
||||
<div
|
||||
style="
|
||||
min-height: {{ $defaultHeight }};
|
||||
min-width: {{ $defaultWidth }};
|
||||
height: {{ $defaultHeight }};
|
||||
width: {{ $defaultWidth }};
|
||||
"
|
||||
@class([
|
||||
'flex items-center justify-center bg-gray-100 font-medium text-gray-500 ring-white dark:bg-gray-800 dark:text-gray-400 dark:ring-gray-900',
|
||||
'rounded-full' => $isCircular,
|
||||
'rounded-lg' => $isSquare,
|
||||
'ring-2' => $isStacked && ($overlap === null || $overlap > 0),
|
||||
])
|
||||
>
|
||||
<span class="-ms-0.5 text-xs">
|
||||
+{{ $remaining }}
|
||||
</span>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@once
|
||||
<x-image-gallery::viewer-script />
|
||||
@endonce
|
||||
</x-dynamic-component>
|
||||
@@ -29,6 +29,19 @@ class ImageGalleryServiceProvider extends PackageServiceProvider
|
||||
$this->getAssets(),
|
||||
$this->getAssetPackageName()
|
||||
);
|
||||
|
||||
\Filament\Tables\Columns\ImageColumn::macro('imageGallery', function () {
|
||||
$this->view('image-gallery::columns.image-column-gallery');
|
||||
$this->disabledClick();
|
||||
|
||||
return $this;
|
||||
});
|
||||
|
||||
\Filament\Infolists\Components\ImageEntry::macro('imageGallery', function () {
|
||||
$this->view('image-gallery::infolists.entries.image-entry-gallery');
|
||||
|
||||
return $this;
|
||||
});
|
||||
}
|
||||
|
||||
protected function getAssetPackageName(): ?string
|
||||
|
||||
Reference in New Issue
Block a user