| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 | <?php
namespace App\Filament\Forms\Components;
use Awcodes\TableRepeater\Components\TableRepeater;
use Closure;
use Filament\Forms\Components\Actions\Action;
use Filament\Support\Enums\MaxWidth;
use Illuminate\Contracts\Support\Htmlable;
use Illuminate\Contracts\View\View;
class CustomTableRepeater extends TableRepeater
{
    protected bool | Closure $spreadsheet = false;
    protected bool | Closure $reorderAtStart = false;
    protected View | Htmlable | Closure | null $footerItem = null;
    /**
     * @var array<string> | Closure | null
     */
    protected array | Closure | null $excludedAttributesForCloning = [
        'id',
        'line_number',
        'created_by',
        'updated_by',
        'created_at',
        'updated_at',
    ];
    public function spreadsheet(bool | Closure $condition = true): static
    {
        $this->spreadsheet = $condition;
        return $this;
    }
    public function isSpreadsheet(): bool
    {
        return (bool) $this->evaluate($this->spreadsheet);
    }
    public function reorderAtStart(bool | Closure $condition = true): static
    {
        $this->reorderAtStart = $condition;
        return $this;
    }
    public function isReorderAtStart(): bool
    {
        return $this->evaluate($this->reorderAtStart) && $this->isReorderable();
    }
    public function footerItem(View | Htmlable | Closure | null $footer = null): static
    {
        $this->footerItem = $footer;
        return $this;
    }
    public function getFooterItem(): View | Htmlable | null
    {
        return $this->evaluate($this->footerItem);
    }
    public function hasFooterItem(): bool
    {
        return $this->footerItem !== null;
    }
    /**
     * @param  array<string> | Closure | null  $attributes
     */
    public function excludeAttributesForCloning(array | Closure | null $attributes): static
    {
        $this->excludedAttributesForCloning = $attributes;
        return $this;
    }
    /**
     * @return array<string> | null
     */
    public function getExcludedAttributesForCloning(): ?array
    {
        return $this->evaluate($this->excludedAttributesForCloning);
    }
    protected function setUp(): void
    {
        parent::setUp();
        $this->minItems(1);
        $this->stackAt(MaxWidth::Large);
        $this->extraAttributes(function (): array {
            $attributes = [];
            if ($this->isSpreadsheet()) {
                $attributes['class'] = 'is-spreadsheet';
            }
            return $attributes;
        });
        $this->reorderAction(function (Action $action) {
            if ($this->isReorderAtStart()) {
                $action->icon('heroicon-m-bars-3');
            }
            return $action;
        });
        $this->cloneAction(function (Action $action) {
            return $action
                ->action(function (array $arguments, CustomTableRepeater $component): void {
                    $newUuid = $component->generateUuid();
                    $items = $component->getState();
                    $clone = $items[$arguments['item']];
                    foreach ($component->getExcludedAttributesForCloning() as $attribute) {
                        unset($clone[$attribute]);
                    }
                    if ($newUuid) {
                        $items[$newUuid] = $clone;
                    } else {
                        $items[] = $clone;
                    }
                    $component->state($items);
                    $component->collapsed(false, shouldMakeComponentCollapsible: false);
                    $component->callAfterStateUpdated();
                });
        });
    }
    public function getView(): string
    {
        return 'filament.forms.components.custom-table-repeater';
    }
}
 |