msdev2 / media-picker
A simple Laravel media picker (file manager) package with a WYSIWYG editor.
Installs: 8
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
Language:JavaScript
Requires
- php: ^8.2
- laravel/framework: ^9.0 || ^10.0 || ^11.0 || ^12.0
- spatie/laravel-glide: ^3.8
Requires (Dev)
- orchestra/testbench: ^6.0 || ^7.0 || ^8.0 || ^9.0
- phpunit/phpunit: ^9.5
This package is auto-updated.
Last update: 2025-10-02 05:41:44 UTC
README
A simple, powerful, and modern file manager package for Laravel, inspired by the WordPress media library. This package provides a rich file management interface, a full-featured WYSIWYG editor, and seamless integration for any Laravel project.
Features
- File & Folder Management: Easily navigate, create folders, upload, rename, move, and delete files.
- Advanced Inline Picker: A full-featured file manager block with a nested folder tree sidebar and an actions panel for selected files.
- Powerful Modal Picker: Trigger a picker from any button to select files. Can be configured with simple data attributes or a global JavaScript event for advanced use cases.
- WYSIWYG Editor: A rich text editor component with a full suite of formatting tools, including custom dialogs for links and media. Double-click on media to edit its attributes.
- Image Resizing: On-the-fly image resizing and manipulation powered by The PHP League's Glide library.
- Configurable: Control allowed file types and max upload sizes via a publishable config file.
- Modern Build: Built with a clean, modular JavaScript and SCSS structure using Laravel Mix for optimal performance.
Installation
This is a step-by-step guide to get the package fully operational in a new or existing Laravel project.
Step 1: Require the Package via Composer
First, add the package to your project's dependencies.
composer require msdev2/media-picker
Step 2: Publish Package Assets
This essential command will publish the package's configuration file to your config
directory, and the compiled CSS and JavaScript to your public/vendor
directory.
php artisan vendor:publish --provider="Msdev2\MediaPicker\MediaPickerServiceProvider" --force
Step 3: Set up Image Resizing (Glide)
This package's image resizing features rely on a self-contained Glide implementation configured in the package's service provider. This makes setup much simpler as you do not need to install or configure a separate Glide package in your main application.
Step 4: Create the Storage Symlink
To ensure that files uploaded to storage/app/public
are publicly accessible, you must create the storage symlink.
php artisan storage:link
If you have already run this command for your project, you do not need to do it again.
Configuration
After publishing in Step 2, you can edit the package's configuration file at config/media-picker.php
.
// config/media-picker.php return [ // The base directory within your 'public' disk where files will be stored. 'base_directory' => 'uploads', // The maximum file size for a single upload in kilobytes (e.g., 2048 = 2MB). 'max_upload_size_kb' => 2048, // A list of all MIME types that are allowed to be uploaded. // It is highly recommended to keep this list as specific as possible for security. 'allowed_mime_types' => [ 'image/jpeg', 'image/png', 'image/gif', 'video/mp4', 'application/pdf', ], ];
Usage
Step 1: Include Assets in Your Layout
Before using any components, you must include the package's assets and a CSRF token in your main Blade layout file.
<!-- resources/views/layouts/app.blade.php --> <!DOCTYPE html> <html> <head> <!-- ... other head tags --> <meta name="csrf-token" content="{{ csrf_token() }}"> <!-- Load the Package's CSS --> <link rel="stylesheet" href="{{ asset('vendor/media-picker/css/media-picker.css') }}"> </head> <body> @yield('content') <!-- Load the Package's JavaScript (before closing </body>) --> <script src="{{ asset('vendor/media-picker/js/media-picker.js') }}"></script> </body> </html>
Use Case 1: Inline File Manager
To display the full file manager directly on a page, use the Blade component with the :inline="true"
attribute.
<h3>My Media Library</h3> <x-ms-media-picker :inline="true" />
Use Case 2: Modal Picker Button (The Easy Way)
This is the recommended method for most situations. The package's JavaScript will automatically handle updating the target element. No custom JS is required.
Add the ms-media-picker
class and two data attributes:
data-target-selector
: A CSS selector for the element to update (e.g.,#my-id
,.my-class
).data-target-type
: How to update the element (input
,image
, orhtml
).
Example: Update an Input Field's Value if data-target-preview then image id we have to pass and if "data-target-preview"+_preview div exist then auto set display:inline-block
<div id="featured_image_preview" style="display:none"><img src="" id="featured_image"></div> <label for="featured_image_url">Featured Image URL</label> <input type="text" id="featured_image_url"> <button type="button" class="ms-media-picker" data-target-selector="#featured_image_url" data-target-preview="#featured_image" data-target-type="input"> Choose Image </button>
Example: Update an Image's src
<img id="profile_preview" src="/placeholder.jpg" style="max-width: 150px;"> <button type="button" class="ms-media-picker" data-target-selector="#profile_preview" data-target-type="image"> Change Picture </button>
Use Case 3: Modal Picker Button (The Advanced Way)
For complex or custom logic, listen for the global ms-media-file-selected
event. This is the most flexible method and allows you to handle multiple, different picker buttons on a single page.
The key is to use the event.detail.triggerElement
to identify which button opened the modal.
1. The HTML: Define Multiple Buttons with Unique IDs
<!-- Example 1: To update an <img> tag --> <img id="profile-preview" src="/placeholder.jpg" style="max-width: 150px;"> <button type="button" id="profile-pic-btn" class="ms-media-picker"> Change Profile Picture </button> <!-- Example 2: To update an <input> field --> <label for="featured-image-input">Featured Image URL:</label> <input type="text" id="featured-image-input" name="featured_image"> <button type="button" id="featured-image-btn" class="ms-media-picker"> Set Featured Image </button>
2. The JavaScript: Create One Smart Event Listener
In your main application's JavaScript, create a single listener that checks the ID of the trigger element and routes the logic accordingly.
document.addEventListener('ms-media-file-selected', (event) => { // Get the selected file object from the event payload const file = event.detail.file; // Get the button element that triggered the modal const trigger = event.detail.triggerElement; // Use the trigger's ID to decide what action to perform if (trigger.id === 'profile-pic-btn') { // Logic for the profile picture button const profileImage = document.getElementById('profile-preview'); if (profileImage) { profileImage.src = file.url; } } else if (trigger.id === 'featured-image-btn') { // Logic for the featured image button const featuredImageInput = document.getElementById('featured-image-input'); if (featuredImageInput) { featuredImageInput.value = file.url; } } });
The file
object contains name
, url
(the public URL), path
, size
, and is_image
. This event-driven approach gives you full control to integrate the media picker anywhere in your application.
Use Case 4: The WYSIWYG Editor
Use the x-ms-media-editor
component for a full-featured rich text editor.
Basic Usage:
<form> <x-ms-media-editor name="post_content" /> </form>
Advanced Usage with Default Content:
@php $existingContent = '<h2>Hello World</h2><p>This is some default content.</p>'; @endphp <form> <x-ms-media-editor name="post_content" height="500px" :value="$existingContent" /> </form>
@php $existingContent = '<h2>Hello World</h2><p>This is some default content.</p>'; @endphp <form> <x-ms-media-editor name="post_content" height="500px"> {!! $existingContent !!} </x-ms-media-editor> </form>
The editor features a full toolbar, including custom dialogs for inserting/editing links and media. Double-clicking an image or video in the editor will open the edit dialog.
Listening for Editor Content Changes:
The editor dispatches a custom event whenever content changes, allowing you to react to updates in real-time:
document.querySelector('.ms-media-editor').addEventListener('ms-editor-content-changed', (event) => { const { content, plainText, codeView } = event.detail; console.log('HTML content:', content); console.log('Plain text:', plainText); console.log('Code view active:', codeView); // Your custom logic here });
Also get complete editor object using window.MSSEditor The event provides:
content
: Full HTML content of the editorplainText
: Plain text without HTML tagscodeView
: Boolean indicating if code view is currently active
Image Resizing (Glide)
The package includes routes for on-the-fly image resizing. You can get resized versions of any image by manipulating the URL structure.
- Base URL:
http://your-app.com/storage/uploads/folder/image.jpg
- Glide Resize URL:
http://your-app.com/uploads/folder/300/200/image.jpg
(300px wide, 200px high crop) - Auto Width:
http://your-app.com/uploads/folder/w/200/image.jpg
(200px high, auto width) - Auto Height:
http://your-app.com/uploads/folder/300/h/image.jpg
(300px wide, auto height)
Development & Customization (Optional)
This package uses Laravel Mix for asset compilation. If you wish to modify the JavaScript or SCSS source files, you must have a compatible Node.js environment (LTS versions like 18.x are recommended).
- Navigate to the package's root directory:
cd vendor/msdev2/media-picker
- Install NPM dependencies:
npm install
- Run the development build:
npm run dev
ornpm run watch
- Run the production build (minified):
npm run prod
The source files are located in src/resources/assets
, and the compiled output is placed in the dist
folder.
License
This package is open-source software licensed under the MIT license.