getCollapsibleColumnsLayout() — NOT * $table->getColumns(), which two earlier attempts at this both reached * for. HasColumns::pushColumns() flattens every Panel/Split into leaf * columns at table-build time and stores THAT flat list as * $this->columns (what getColumns() returns); the original nested * Panel/Stack objects actually used for rendering are kept separately — * in $this->columnsLayout for a non-collapsible layout component, or * $this->collapsibleColumnsLayout for one that IS collapsible (this * order-lines Panel is, via ->collapsible()). So `$column instanceof * Panel` over getColumns() can never match anything — Panel/Split * instances simply never appear in that array at all — and a fix built * on that check silently mutated nothing. A first attempt building a * brand new Panel and re-calling $table->columns() on top of the * existing setup fixed nothing either and instead rendered as a stray * empty extra column outside the dropdown (caught by actually opening * the order page). Mutates the found Panel's Stack in place via * Stack::schema(), the one part of both earlier attempts that actually * worked once the right object was found. * * Its own TextColumn rather than reusing the Panel's existing KeyValue: * KeyValue's own Blade view HTML-escapes every value ({{ $value }}), * which can't render a clickable link for a file answer. */ class OrderItemsTableExtension extends BaseExtension { public function extendTable(Table $table): Table { if ($table->getCollapsibleColumnsLayout() instanceof Panel) { $this->addCustomFieldsColumn($table->getCollapsibleColumnsLayout()); } return $table->toolbarActions( array_map( fn ($action) => $action instanceof BulkAction && $action->getName() === 'bulk_refund' ? $this->fixFailureNotification($action) : $action, $table->getToolbarActions(), ), ); } private function addCustomFieldsColumn(Panel $panel): void { $stack = $panel->getComponents()[0] ?? null; if ($stack === null) { return; } $stack->schema([ ...$stack->getComponents(), TextColumn::make('custom_fields') ->label('Custom Fields') ->visible(fn (OrderLine $record) => filled($record->meta['custom_fields'] ?? null)) ->getStateUsing(fn (OrderLine $record) => $this->renderCustomFields($record)) ->html(), ]); } /** * Same table markup/classes as this Panel's own existing KeyValue * component (Lunar\Admin's price_breakdowns, right above this in the * dropdown — see lunarpanel::tables.components.key-value) for visual * consistency, rebuilt here rather than reused: KeyValue's Blade view * HTML-escapes every value ({{ $value }}), which can't render a * thumbnail/download link for a file answer. */ private function renderCustomFields(OrderLine $record): HtmlString { $rows = collect($record->meta['custom_fields'] ?? []) ->map(fn (array $field) => sprintf( '