goodappr/moonshine-media-fields

Audio, AudioList, Video, VideoList fields for MoonShine 4.x - media with preview and modals

Maintainers

Package info

github.com/GoodAppR/moonshine-media-fields

Language:Blade

pkg:composer/goodappr/moonshine-media-fields

Statistics

Installs: 3

Dependents: 0

Suggesters: 0

Stars: 4

Open Issues: 0

1.1.0 2026-02-13 17:33 UTC

This package is auto-updated.

Last update: 2026-03-14 10:42:43 UTC


README

Audio, AudioList, Video and VideoList fields for MoonShine 4.x with preview, playback modals and custom audio player.

MoonShine Media Fields

Table of Contents

Requirements

  • PHP 8.2+
  • Laravel 11+
  • MoonShine 4.x
  • Alpine.js (included with MoonShine)

Installation

composer require goodappr/moonshine-media-fields

The package auto-registers MediaFieldsServiceProvider.

Configuration

Publish config (optional)

php artisan vendor:publish --tag=moonshine-media-fields-config

Creates config/media_fields.php:

<?php

return [
    'audio' => [
        'extensions' => ['mp3', 'wav', 'ogg', 'm4a', 'aac', 'flac', 'webm'],
        'max_size_kb' => 20480,
        'dir' => 'audio',
        'default_preload' => 'metadata',
    ],

    'video' => [
        'extensions' => ['mp4', 'mov', 'avi', 'mkv', 'webm', 'flv', 'wmv'],
        'max_size_kb' => 102400,
        'dir' => 'video',
        'default_preload' => 'metadata',
    ],
];

Migration example

For storing audio and video in DB (string or json types):

Schema::table('posts', function (Blueprint $table) {
    $table->string('audio')->nullable();
    $table->json('audio_list')->nullable();
    $table->string('video')->nullable();
    $table->json('video_list')->nullable();
    $table->json('video_list_posters')->nullable();
});

Usage

Audio — single audio

Form:

  • File upload
  • showPreview(true) — player and preview (default)
  • showPreview(false) — filename only

Index:

  • Play button → modal with player
  • editOnIndex(true) — edit icon linking to form
  • downloadOnIndex(true) — download icon
  • downloadPreviewModal(true) — download button in modal
  • showFileName(bool) — show filename
use MoonShine\MediaFields\Fields\Audio;

Audio::make('Audio', 'audio')
    ->dir('uploads/audio')
    ->editOnIndex(true)
    ->downloadOnIndex(true)
    ->downloadPreviewModal(true)
    ->showFileName(true)
    ->preload('metadata')
    ->loop(false);

Audio form Audio index

AudioList — multiple audio

Form:

  • Multiple file selection
  • maxFiles(int) — max count
  • maxFileSizeKb(int) — max size per file
  • showPreview(true) — player for each
  • maxHeightContainer(string) — container max-height (e.g. '400px')

Index:

  • Play button + count → modal with list
  • downloadOnIndex(true) — download for each file
use MoonShine\MediaFields\Fields\AudioList;

AudioList::make('Audio list', 'audio_list')
    ->dir('uploads/audio')
    ->maxFiles(10)
    ->maxFileSizeKb(5120)
    ->editOnIndex(true)
    ->downloadOnIndex(true)
    ->maxHeightContainer('400px');

Video — single video

Form:

  • Upload, preview with video player
  • poster(string) — static poster URL
  • posterField(Image $field) — poster as embedded Image field

Index:

  • With poster: thumbnail + play button
  • Without poster: camera icon
  • videoMaxHeight(string) — max-height for video in modal
use MoonShine\MediaFields\Fields\Video;

Video::make('Video', 'video')
    ->dir('uploads/video')
    ->poster('/images/poster.jpg')
    ->editOnIndex(true)
    ->videoMaxHeight('400px');

With poster via separate column:

Video::make('Video', 'video')
    ->dir('uploads/video')
    ->posterColumn('video_poster')
    ->posterDir('uploads/posters');

Video form Video index

VideoList — multiple video

Form:

  • Video carousel or grid
  • maxFiles, maxFileSizeKb
  • gridColumns(2|3|4|null) — 2–4 columns or null for carousel
  • posterField(VideoListPosters $field) — poster per video

Index:

  • Camera icon + count or poster thumbnails
  • videoMaxHeight(string), gridColumns(int|null)
use MoonShine\MediaFields\Fields\VideoList;
use MoonShine\MediaFields\Fields\VideoListPosters;

VideoList::make('Videos', 'videos')
    ->dir('uploads/videos')
    ->maxFiles(5)
    ->editOnIndex(true)
    ->videoMaxHeight('320px')
    ->gridColumns(2)
    ->posterField(
        VideoListPosters::make('Posters', 'video_list_posters')
            ->videosColumn('videos')
    );

VideoListPosters — posters for VideoList

Separate field for uploading posters for each video. Use with VideoList::posterField().

VideoListPosters::make('Video posters', 'video_list_posters')
    ->videosColumn('videos');

Example Resource

<?php

namespace App\MoonShine\Resources;

use App\Models\Post;
use MoonShine\MediaFields\Fields\Audio;
use MoonShine\MediaFields\Fields\AudioList;
use MoonShine\MediaFields\Fields\Video;
use MoonShine\MediaFields\Fields\VideoList;
use MoonShine\MediaFields\Fields\VideoListPosters;
use MoonShine\Resources\ModelResource;

class PostResource extends ModelResource
{
    protected string $model = Post::class;

    public function fields(): array
    {
        return [
            Audio::make('Audio', 'audio')
                ->dir('uploads/audio')
                ->editOnIndex(true)
                ->downloadOnIndex(true),

            AudioList::make('Audio list', 'audio_list')
                ->dir('uploads/audio')
                ->maxFiles(5),

            Video::make('Video', 'video')
                ->dir('uploads/video')
                ->editOnIndex(true)
                ->videoMaxHeight('400px'),

            VideoList::make('Videos', 'videos')
                ->dir('uploads/videos')
                ->maxFiles(5)
                ->gridColumns(2)
                ->posterField(
                    VideoListPosters::make('Posters', 'video_list_posters')
                        ->videosColumn('videos')
                ),
        ];
    }
}

Themes and Styles

Uses MoonShine CSS variables:

  • --color-base, --color-base-text, --color-base-stroke
  • --color-primary, --color-primary-text

Supports light and dark themes via .dark and [data-theme="dark"].

Troubleshooting

403 Forbidden when playing audio/video

Server may block MIME types. Check:

  1. Apache.htaccess or config:
AddType audio/mpeg .mp3
AddType video/mp4 .mp4
  1. ModSecurity — disable or adjust rules for media files.

  2. Nginx — ensure types includes required MIME types.

Clear cache after update

php artisan config:clear
php artisan view:clear

License

MIT. See LICENSE.