@props([ 'actions' => false, 'actionsPosition' => null, 'columns', 'extraHeadingColumn' => false, 'groupColumn' => null, 'groupsOnly' => false, 'heading', 'placeholderColumns' => true, 'query', 'selectionEnabled' => false, 'selectedState', 'recordCheckboxPosition' => null, ]) @php use Filament\Support\Enums\Alignment; use Filament\Tables\Columns\Column; use Filament\Tables\Enums\RecordActionsPosition; use Filament\Tables\Enums\RecordCheckboxPosition; if ($groupsOnly && $groupColumn) { $columns = collect($columns) ->reject(fn (Column $column): bool => $column->getName() === $groupColumn) ->all(); } $isStackedOnMobile = $this->getTable()->isStackedOnMobile(); // `$query` is constant for this render, so each column's resolved summarizers are // too. Resolve them once here instead of re-running `getSummarizers($query)` (and // `hasSummary($query)`, which wraps it) in every loop guard below. Keyed by the // `$columns` array key so the heading-span loop and the cell loop share the lookup. $columnsWithSummary = []; foreach ($columns as $summaryColumnKey => $summaryColumn) { $summaryColumnSummarizers = $summaryColumn->getSummarizers($query); $columnsWithSummary[$summaryColumnKey] = [ 'summarizers' => $summaryColumnSummarizers, 'hasSummary' => (bool) count($summaryColumnSummarizers), 'hiddenFrom' => $summaryColumn->getHiddenFrom(), 'visibleFrom' => $summaryColumn->getVisibleFrom(), ]; } $summaryHeadingHiddenAt = []; $summaryHeadingFallbackVisibleAt = []; if ((! $extraHeadingColumn) && (! $groupsOnly) && filled($columns)) { $breakpointOrder = [ 'base' => 0, 'sm' => 1, 'md' => 2, 'lg' => 3, 'xl' => 4, '2xl' => 5, ]; $responsiveBreakpointOrder = array_diff_key($breakpointOrder, ['base' => true]); $isColumnVisibleAt = static function (array $columnState, int $breakpointIndex) use ($responsiveBreakpointOrder): bool { $visibleFromIndex = $responsiveBreakpointOrder[$columnState['visibleFrom']] ?? null; if ($visibleFromIndex !== null) { return $breakpointIndex >= $visibleFromIndex; } $hiddenFromIndex = $responsiveBreakpointOrder[$columnState['hiddenFrom']] ?? null; return ($hiddenFromIndex === null) || ($breakpointIndex < $hiddenFromIndex); }; $firstColumnState = $columnsWithSummary[array_key_first($columns)]; foreach ($breakpointOrder as $breakpoint => $breakpointIndex) { if (($breakpoint === 'base') && $isStackedOnMobile) { continue; } if ($isColumnVisibleAt($firstColumnState, $breakpointIndex)) { continue; } $summaryHeadingHiddenAt[] = $breakpoint; foreach ($columnsWithSummary as $columnKey => $columnState) { if ((! $columnState['hasSummary']) || (! $isColumnVisibleAt($columnState, $breakpointIndex))) { continue; } $summaryHeadingFallbackVisibleAt[$columnKey][] = $breakpoint; break; } } } @endphp class(['fi-ta-row fi-ta-summary-row']) }} > @if ($placeholderColumns && $actions && in_array($actionsPosition, [RecordActionsPosition::BeforeCells, RecordActionsPosition::BeforeColumns])) @endif @if ($placeholderColumns && $selectionEnabled && $recordCheckboxPosition === RecordCheckboxPosition::BeforeCells) @endif @if ($extraHeadingColumn || $groupsOnly) {{ $heading }} @else @php $headingColumnSpan = 1; foreach ($columns as $index => $column) { if ($index === array_key_first($columns)) { if (filled($columnsWithSummary[$index]['hiddenFrom']) || filled($columnsWithSummary[$index]['visibleFrom'])) { break; } continue; } if ( $columnsWithSummary[$index]['hasSummary'] || filled($columnsWithSummary[$index]['hiddenFrom']) || filled($columnsWithSummary[$index]['visibleFrom']) ) { break; } $headingColumnSpan++; } @endphp @endif @foreach ($columns as $columnKey => $column) @if (($loop->first || $extraHeadingColumn || $groupsOnly || ($loop->iteration > $headingColumnSpan)) && ($placeholderColumns || $columnsWithSummary[$columnKey]['hasSummary'])) @php $alignment = $column->getAlignment() ?? Alignment::Start; if (! $alignment instanceof Alignment) { $alignment = filled($alignment) ? (Alignment::tryFrom($alignment) ?? $alignment) : null; } // The leading cell labels the whole summary row, so render it as a row header; the aggregate // value cells stay `` and gain a row association from this ``. $isSummaryRowHeadingCell = $loop->first && (! $extraHeadingColumn) && (! $groupsOnly); $summaryCellTag = $isSummaryRowHeadingCell ? 'th' : 'td'; $columnHiddenFrom = $columnsWithSummary[$columnKey]['hiddenFrom']; $columnVisibleFrom = $columnsWithSummary[$columnKey]['visibleFrom']; @endphp <{{ $summaryCellTag }} @if ($isSummaryRowHeadingCell) scope="row" @endif @if ($isSummaryRowHeadingCell && ($headingColumnSpan > 1)) colspan="{{ $headingColumnSpan }}" @endif @class([ 'fi-ta-cell', ($alignment instanceof Alignment) ? "fi-align-{$alignment->value}" : (is_string($alignment) ? $alignment : ''), 'fi-ta-summary-row-heading-cell' => $isSummaryRowHeadingCell, 'fi-ta-summary-row-heading-cell-responsive' => $isSummaryRowHeadingCell && (filled($columnHiddenFrom) || filled($columnVisibleFrom)), filled($columnHiddenFrom) ? "{$columnHiddenFrom}:fi-hidden" : '', filled($columnVisibleFrom) ? "{$columnVisibleFrom}:fi-visible" : '', ]) > @if ($isSummaryRowHeadingCell) {{ $heading }} @elseif ((! $placeholderColumns) || $columnsWithSummary[$columnKey]['hasSummary']) @if (filled($summaryHeadingHiddenAt) && $columnsWithSummary[$columnKey]['hasSummary'])
{{ $heading }}
@endif @if ($isStackedOnMobile)
{{ $column->getLabel() }}
@endif @foreach ($columnsWithSummary[$columnKey]['summarizers'] as $summarizer) {{ $summarizer->query($query)->selectedState($selectedState) }} @endforeach @endif @endif @endforeach @if ($placeholderColumns && $actions && in_array($actionsPosition, [RecordActionsPosition::AfterColumns, RecordActionsPosition::AfterCells])) @endif @if ($placeholderColumns && $selectionEnabled && $recordCheckboxPosition === RecordCheckboxPosition::AfterCells) @endif