Add stacking to images

This commit is contained in:
Kenneth Sese
2023-05-01 20:57:47 -06:00
parent 2906b96d49
commit 73647296dc
3 changed files with 319 additions and 25 deletions
@@ -76,3 +76,71 @@ use Filament\Tables\Columns\ImageColumn;
ImageColumn::make('logo')
->extraImgAttributes(['title' => 'Company logo']),
```
## Stacking images
You may show a relationship of images as a stack using `stacked()`. The name of the relationship comes first, followed by a period, followed by the name of the column to display:
```php
ImageColumn::make('users.avatar')
->circular()
->stacked()
```
### Using a separator
Instead of using a relationship, you may use a separated string by passing the separator into `separator()`:
```php
ImageColumn::make('product_images')
->separator(',')
->circular()
->stacked()
```
### Setting a limit
You may set a limit to the number of images you want to display by passing `limit()`:
```php
ImageColumn::make('orderItems.image')
->circular()
->stacked()
->limit(3)
```
### Showing the remaining images count
When you set a limit you may also display the count of remaining images by passing `showRemaining()`.
```php
ImageColumn::make('orderItems.image')
->circular()
->stacked()
->limit(3)
->showRemaining()
```
By default, `showRemaining()` will display the count of remaining images as a number stacked on the other images. If you prefer to show the count as a number after the images you may use `showRemainingAfterStack()`. You may also set the text size by using `remainingTextSize('xs')`;
### Customizing the ring width
The default ring width is `ring-3` but you may customize the ring width to be either `0`, `1`, `2`, or `4` which correspond to tailwinds `ring-widths`: `ring-0`, `ring-1`, `ring-2`, and `ring-4` respectively.
```php
ImageColumn::make('users.avatar')
->circular()
->stacked()
->ring(3)
```
### Customizing the overlap
The default overlap is `-space-x-1` but you may customize the overlap to be either `0`, `1`, `2`, `3`, or `4` which correspond to tailwinds `space-x` options: `space-x-0`, `-space-x-1`, `-space-x-2`, `-space-x-3`, and `-space-x-4` respectively.
```php
ImageColumn::make('users.avatar')
->circular()
->stacked()
->overlap(3)
```
@@ -5,29 +5,120 @@
@php
$height = $getHeight();
$width = $getWidth() ?? ($isCircular() || $isSquare() ? $height : null);
$overlap = $getOverlap() ?? 'sm';
$imageCount = 0;
$ring = match ($getRing()) {
0 => 'ring-0',
1 => 'ring-1',
2 => 'ring-2',
4 => 'ring-4',
default => 'ring',
};
$remainingTextSize = match ($getRemainingTextSize()) {
'xs' => 'text-xs',
'sm' => 'text-sm',
'md' => 'text-md',
'lg' => 'text-lg',
default => 'text-sm',
};
@endphp
<div
style="
{!! $height !== null ? "height: {$height};" : null !!}
{!! $width !== null ? "width: {$width};" : null !!}
"
@class([
'overflow-hidden' => $isCircular() || $isSquare(),
'rounded-full' => $isCircular(),
])
>
@if ($path = $getImagePath())
<img
src="{{ $path }}"
style="
{!! $height !== null ? "height: {$height};" : null !!}
{!! $width !== null ? "width: {$width};" : null !!}
"
{{ $getExtraImgAttributeBag()->class([
'object-cover object-center' => $isCircular() || $isSquare(),
]) }}
@if ($isStacked())
<div class="flex items-center space-x-2">
<div
@class([
'flex',
match ($overlap) {
0 => 'space-x-0',
1 => '-space-x-1',
2 => '-space-x-2',
3 => '-space-x-3',
4 => '-space-x-4',
default => '-space-x-1',
},
])
>
@endif
</div>
@foreach (array_slice($getImages(), 0, $getLimit()) as $image)
@if ($path = $getImagePath($image))
@php
$imageCount ++;
@endphp
<img
src="{{ $path }}"
style="
{!! $height !== null ? "height: {$height};" : null !!}
{!! $width !== null ? "width: {$width};" : null !!}
"
{{ $getExtraImgAttributeBag()->class([
'max-w-none ring-white',
'dark:ring-gray-800' => config('tables.dark_mode'),
'rounded-full' => $isCircular(),
$ring,
]) }}
>
@endif
@endforeach
@if ($shouldShowRemaining() && (! $shouldShowRemainingAfterStack()) && ($imageCount < count($getImages())))
<div
style="
{!! $height !== null ? "height: {$height};" : null !!}
{!! $width !== null ? "width: {$width};" : null !!}
"
@class([
'flex items-center justify-center bg-gray-100 text-gray-500 ring-white',
'dark:bg-gray-600 dark:text-gray-300 dark:ring-gray-800' => config('tables.dark_mode'),
'rounded-full' => $isCircular(),
$remainingTextSize,
$ring,
])
>
<span class="-ml-1">
+{{ count($getImages()) - $imageCount }}
</span>
</div>
@endif
</div>
@if ($shouldShowRemaining() && $shouldShowRemainingAfterStack() && ($imageCount < count($getImages())))
<div
@class([
'text-gray-500',
'dark:text-gray-300' => config('tables.dark_mode'),
$remainingTextSize,
])
>
+{{ count($getImages()) - $imageCount }}
</div>
@endif
</div>
@else
<div
style="
{!! $height !== null ? "height: {$height};" : null !!}
{!! $width !== null ? "width: {$width};" : null !!}
"
@class([
'overflow-hidden' => $isCircular() || $isSquare(),
'rounded-full' => $isCircular(),
])
>
@if ($path = $getImagePath())
<img
src="{{ $path }}"
style="
{!! $height !== null ? "height: {$height};" : null !!}
{!! $width !== null ? "width: {$width};" : null !!}
"
{{ $getExtraImgAttributeBag()->class([
'object-cover object-center' => $isCircular() || $isSquare(),
]) }}
>
@endif
</div>
@endif
</div>
+138 -3
View File
@@ -28,6 +28,22 @@ class ImageColumn extends Column
protected array $extraImgAttributes = [];
protected bool | Closure $isStacked = false;
protected string | Closure | null $separator = null;
protected int | Closure | null $overlap = null;
protected int | Closure | null $ring = null;
protected int | Closure | null $limit = null;
protected bool | Closure $shouldShowRemaining = false;
protected bool | Closure $shouldShowRemainingAfterStack = false;
protected string | Closure | null $remainingTextSize = null;
protected function setUp(): void
{
parent::setUp();
@@ -118,10 +134,10 @@ class ImageColumn extends Column
return $height;
}
public function getImagePath(): ?string
public function getImagePath(string | null $image = null): ?string
{
$state = $this->getState();
$state = $image ?: $this->getState();
if (! $state) {
return null;
}
@@ -219,4 +235,123 @@ class ImageColumn extends Column
{
return new ComponentAttributeBag($this->getExtraImgAttributes());
}
public function stacked(bool | Closure $condition = true): static
{
$this->isStacked = $condition;
return $this;
}
public function isStacked(): bool
{
return $this->evaluate($this->isStacked);
}
public function getImages(): array
{
$images = $this->getState();
if (is_array($images)) {
return $images;
}
if (! ($separator = $this->getSeparator())) {
return [];
}
$images = explode($separator, $images);
if (count($images) === 1 && blank($images[0])) {
$images = [];
}
return $images;
}
public function separator(string | Closure | null $separator = ','): static
{
$this->separator = $separator;
return $this;
}
public function getSeparator(): ?string
{
return $this->evaluate($this->separator);
}
public function overlap(int | Closure | null $overlap): static
{
$this->overlap = $overlap;
return $this;
}
public function getOverlap(): ?int
{
return $this->evaluate($this->overlap);
}
public function ring(string | Closure | null $ring): static
{
$this->ring = $ring;
return $this;
}
public function getRing(): ?int
{
return $this->evaluate($this->ring);
}
public function limit(int | Closure | null $limit = 3): static
{
$this->limit = $limit;
return $this;
}
public function getLimit(): ?int
{
return $this->evaluate($this->limit);
}
public function showRemaining(bool | Closure $condition = true, bool | Closure $showRemainingAfterStack = false, string | Closure | null $remainingTextSize = null): static
{
$this->shouldShowRemaining = $condition;
$this->showRemainingAfterStack($showRemainingAfterStack);
$this->remainingTextSize($remainingTextSize);
return $this;
}
public function showRemainingAfterStack(bool | Closure $condition = true): static
{
$this->shouldShowRemainingAfterStack = $condition;
return $this;
}
public function shouldShowRemaining(): bool
{
return $this->evaluate($this->shouldShowRemaining);
}
public function shouldShowRemainingAfterStack(): bool
{
return $this->evaluate($this->shouldShowRemainingAfterStack);
}
public function remainingTextSize(string | Closure | null $remainingTextSize): static
{
$this->remainingTextSize = $remainingTextSize;
return $this;
}
public function getRemainingTextSize(): ?string
{
return $this->evaluate($this->remainingTextSize);
}
}