haosheng0211/filament-media-browser

A standalone Filament v3 media browser powered by Laravel Storage — no database required.

Maintainers

Package info

github.com/haosheng0211/filament-media-browser

Language:Blade

pkg:composer/haosheng0211/filament-media-browser

Statistics

Installs: 6

Dependents: 0

Suggesters: 1

Stars: 0

Open Issues: 0

v1.0.0 2026-03-15 14:36 UTC

This package is auto-updated.

Last update: 2026-03-15 14:39:26 UTC


README

Latest Version on Packagist Total Downloads

A standalone Filament v3 media browser powered by Laravel Storage — no database required. Browse, upload, and manage files directly from the filesystem with folder navigation support.

Features

  • Browse files and folders on any Laravel Storage disk
  • Upload, delete files and create/delete folders
  • Breadcrumb navigation with subfolder support
  • Filter by media type (image, video/audio, or all files)
  • Search files by name
  • Filename sanitization and collision handling
  • Path traversal protection
  • Authentication guard on all operations
  • Dark mode support
  • Works with any Filament v3 panel or Livewire component

Installation

composer require haosheng0211/filament-media-browser

Publish the config file:

php artisan vendor:publish --tag="filament-media-browser-config"

Add the package views to your tailwind.config.js content array:

// tailwind.config.js
content: [
    // ...existing paths
    './vendor/haosheng0211/filament-media-browser/resources/views/**/*.blade.php',
]

Then rebuild your assets:

npm run build

Make sure the storage disk is linked (for the public disk):

php artisan storage:link

Configuration

// config/filament-media-browser.php

return [
    // Laravel filesystem disk
    'disk' => 'public',

    // Root directory for browsing
    'directory' => 'media',

    // Allowed upload MIME types
    'accepted_file_types' => ['image/*', 'video/*', 'audio/*'],

    // Max upload size in KB
    'max_file_size' => 10240,
];

Usage

MediaPicker Field

A dedicated form field with image preview, replace and remove buttons. Stores the selected file's URL as a string (single) or array of strings (multiple).

use MrJin\FilamentMediaBrowser\Forms\Components\MediaPicker;

// Basic usage — single image picker with preview
MediaPicker::make('featured_image');

// Multiple images (gallery)
MediaPicker::make('gallery')
    ->multiple()
    ->maxItems(10)
    ->reorderable(); // drag-to-reorder, enabled by default

// File picker (no image preview, shows path instead)
MediaPicker::make('attachment')
    ->mediaType('file');

// Custom disk and directory
MediaPicker::make('hero_image')
    ->mediaDisk('s3')
    ->mediaDirectory('uploads/heroes');

Stored value:

  • Single mode: string URL (e.g. /storage/media/photo.jpg) — use a string column
  • Multiple mode: array of URL strings — use a json column with ->cast('array') on the model

Available Methods

Method Description
->multiple(bool) Enable multi-select mode
->maxItems(int) Maximum number of files (multiple mode)
->reorderable(bool) Enable drag-to-reorder (multiple mode, default: true)
->mediaType(string) 'image' (default), 'media', or 'file'
->mediaDisk(string) Override config disk
->mediaDirectory(string) Override config directory

With Filament Forms TinyMCE

This package works seamlessly with filament-forms-tinymce. Once both packages are installed, TinyMCE's file picker will automatically use the media browser.

use MrJin\FilamentFormsTinymce\TinyMceEditor;

TinyMceEditor::make('content');

// With custom disk/directory per field
TinyMceEditor::make('content')
    ->mediaDisk('s3')
    ->mediaDirectory('uploads/posts');

// Disable the file browser
TinyMceEditor::make('content')
    ->fileBrowser(false);

Standalone Usage via Events

The media browser communicates via Livewire events, so you can integrate it with any component.

Open the browser by dispatching the open-media-browser event:

// From Livewire — single file
$this->dispatch('open-media-browser', statePath: 'data.image', mediaType: 'image');

// Multiple files with custom disk/directory
$this->dispatch('open-media-browser',
    statePath: 'data.files',
    mediaType: 'file',
    multiple: true,
    disk: 's3',
    directory: 'uploads',
);
<!-- From Alpine.js -->
<button x-on:click="Livewire.dispatch('open-media-browser', {
    statePath: 'data.image',
    mediaType: 'image',
})">
    Browse Media
</button>

Listen for file selection via the media-selected event:

// Livewire
#[On('media-selected')]
public function onMediaSelected(
    string $statePath,
    string $url,
    string $alt,
    string $title,
    string $filename,
    string $extension,
    int $size,
    string $mime,
): void {
    // Use the selected media URL and metadata
}
<!-- Alpine.js -->
<div x-on:media-selected.window="handleMedia($event.detail)">

Event Reference

Event Direction Parameters
open-media-browser You → Browser statePath, mediaType (image | media | file), multiple?, disk?, directory?
media-selected Browser → You statePath, url, alt, title, filename, extension, size, mime

Media Types

Value Filters
image image/* only
media video/* and audio/*
file All files (no filter)

Customizing Views

php artisan vendor:publish --tag="filament-media-browser-views"

Testing

composer test

Changelog

Please see CHANGELOG for more information on what has changed recently.

License

The MIT License (MIT). Please see License File for more information.