Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Filament File View Entry Laravel Package

gheith3/filament-file-view-entry

A Filament package that adds a file view entry for displaying uploaded files in infolists, with preview and download support for images, PDFs, and documents in Laravel admin panels.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package with Composer (it requires PHP 8.2+, Laravel 11/12 and Filament 4 or 5 — verify your panel matches before pulling it into a project):

composer require gheith3/filament-file-view-entry

The plugin ships a service provider that registers the Blade view namespace file-view-entry-plugin. Register the plugin in your panel provider so that namespace is available, even though there is no configuration object to tweak:

use gheith3\FileViewEntryPlugin\FileViewEntryPlugin;

public function panel(Panel $panel): Panel
{
    return $panel
        ->plugin(FileViewEntryPlugin::make());
}

The only class you will touch day-to-day is gheith3\FileViewEntryPlugin\Infolists\Components\FileViewEntry. It is an Entry, so it belongs inside an Infolist schema — a ViewRecord page, a relation manager's infolist, or an action's modal schema. A minimal first use case is showing an uploaded document on a record view page:

use gheith3\FileViewEntryPlugin\Infolists\Components\FileViewEntry;
use Filament\Infolists\Infolist;

public function infolist(Infolist $infolist): Infolist
{
    return $infolist->schema([
        FileViewEntry::make('contract_path')
            ->showPreview()
            ->downloadable(),
    ]);
}

Where to look first when something is off: the published Blade view (resources/views/vendor/file-view-entry-plugin/infolists/components/file-view-entry.blade.php after publishing) is the real source of truth for markup, icons and the Alpine modal. The README and AGENTS.md in the repo cover the method surface; there is no separate docs site.

Implementation Patterns

Single path vs. array vs. relationship. The entry inspects the state and handles all three shapes. A string is treated as a single file path; an array of arrays is rendered as a grid of cards; an Eloquent Collection from a relationship works out of the box because it is iterable. The most common real-world pattern is a hasMany attachments relation:

public function attachments(): HasMany
{
    return $this->hasMany(Attachment::class);
}

// In the infolist
FileViewEntry::make('attachments')
    ->grid(3)
    ->titleKey('original_name')
    ->pathKey('storage_path')
    ->dateKey('created_at')
    ->showPreview()
    ->downloadable(),

Custom key mapping is the main integration knob. Arrays and models are read via titleKey() (default name), pathKey() (default file_path) and dateKey() (default null). Map these to whatever your schema actually stores. If you keep a raw storage path (attachments/invoices/2024-01.pdf) rather than a public URL, pass it as-is and use disk() to tell the entry which filesystem resolves it:

FileViewEntry::make('documents')
    ->grid(4)
    ->pathKey('path')
    ->disk('s3')
    ->showPreview()
    ->downloadable(),

Fixed grid vs. auto grid. grid() takes 1–6 and locks the column count; leaving it null keeps the responsive default (roughly 2 on mobile, 3 on tablet, 4–5 on desktop). For a document sidebar you usually want grid(2); for a media gallery grid(4) reads better. Pair it with ->columnSpanFull() when the entry sits in a two-column infolist and you want the grid to breathe.

Link mode for dense layouts. showAsLink() renders a compact text link instead of square cards. Use it in table-adjacent summaries, relation managers, or when a record has dozens of files and the card grid becomes a wall. You lose the icon preview affordance but keep preview/download behaviour.

Modal preview tuning. showPreview() is on by default; ->showPreview(false) disables it for types you don't want opening a modal. previewHeight() accepts either a string ('420px', '60vh') or an integer, and defaults to '300px'. Bump it for PDFs and video, drop it for audio.

Using it outside a ViewRecord page. Because it extends Entry, it composes into action modals and relation-manager infolists without extra work — a useful pattern for "view attachments" actions on a table row:

Tables\Actions\Action::make('files')
    ->infolist(fn (Record $record) => [
        FileViewEntry::make('attachments')
            ->grid(3)
            ->dateKey('created_at')
            ->downloadable(),
    ])

Gotchas and Tips

  • Dates are hidden by default. dateKey() is null, not 'created_at'. If timestamps never appear, you simply haven't opted in — call ->dateKey('created_at') explicitly.
  • URLs are temporary, not permanent. Non-public disks go through Storage::disk()->temporaryUrl() with a ~5 minute expiry and fall back to url(). Long-lived pages, cached HTML, or users who leave a modal open will see broken previews/downloads. For public assets, put them on a public disk to skip the signed URL path entirely.
  • The disk() default is the filesystem config, not the entry's state. If your paths look correct but every file 404s, check config('filesystems.default') against where the files actually live — this is the single most common misconfiguration.
  • pathKey must be a path, not a URL. If your column is already a fully-qualified URL, the entry will still try to resolve it through the disk. Store the relative path and let the component generate URLs.
  • Preview support is extension-based. Images, video, audio, PDF and plain text (txt, md) open in the modal; everything else (.docx, .xlsx, .zip) falls back to opening a new tab. Don't promise clients inline Office previews — that's a browser/Office-Online problem, not a package one.
  • Grid values are clamped. grid() expects 1–6; passing 0 or 8 silently produces an unexpected layout rather than an exception. Validate at the call site if the value is dynamic.
  • Collections need consistent keys. A heterogeneous array (some entries with name, some without) renders cards with blank titles. Normalise in a getStateUsing() or accessor before the entry sees it.
  • Publishing views is your styling escape hatch. php artisan vendor:publish --tag=file-view-entry-plugin-views drops the template into resources/views/vendor/file-view-entry-plugin/. Override the Tailwind classes there (rounded-2xl, bg-gray-50 dark:bg-gray-800, w-12 h-12 icons) rather than fighting them with extraAttributes(). Note the hard-coded dark: variants — if you use a non-standard grey palette you'll want to rewrite them.
  • Maturity caveat. This is a 5-star, zero-dependent package. Pin the version in composer.json, run vendor/bin/pest in the package itself if you vendor it for patching, and keep the published view in version control so an upstream change can't silently alter a live UI.
  • Debugging blank output. Check three things in order: the plugin is registered in the panel (view namespace), the state is non-empty after Filament's dot-notation resolution (file_path on a nested array needs the right make() key), and the filesystem URL actually resolves in a browser. Nine times out of ten it's the second one.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console