Skip to content

Commit 792f0d5

Browse files
authored
Merge pull request #2 from codebyray/add_bootstrap_version
Added theme customization with Tailwind and Bootstrap supplied.
2 parents 69232ca + 8e86866 commit 792f0d5

File tree

7 files changed

+1280
-578
lines changed

7 files changed

+1280
-578
lines changed

CHANGELOG.md

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,57 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99
---
1010

1111
## [Unreleased]
12+
1213
### Added
13-
- Docs: environment variable examples for presets (`MEDIA_TYPES_*`, `MEDIA_MIMES_*`, `MEDIA_MAXKB_*`).
14-
- Tests: deterministic duplicate-detection test helper (`TestableMediaUploader`) and event-based assertions.
15-
- Troubleshooting guidance for Testbench/SQLite and Livewire temp upload disk.
14+
1615

1716
### Changed
18-
- Test suite favors Pest; PHPUnit example retained only if desired by consumers.
19-
- Assertions updated to reflect Spatie filename sanitization (spaces → dashes on rename).
2017

2118
### Fixed
22-
- Intermittent test failures: ensured `media` table migration loads under Testbench and configured fake disks (`public`, `local`, `tmp-for-tests`).
19+
2320

2421
---
22+
## [v0.2.0] — 2025-09-01
23+
24+
### Added
25+
- **Theme system** with **Tailwind (default)** and **Bootstrap** themes.
26+
- **Custom themes** support:
27+
1. Create a new folder under `resources/views/vendor/media-uploader/themes`, e.g. `custom/`.
28+
2. Copy `media-uploader.blade.php` from `tailwind/` or `bootstrap/` into `custom/` (keep the filename).
29+
3. Register in config:
30+
```php
31+
'themes' => [
32+
'tailwind' => 'media-uploader::themes.tailwind.media-uploader',
33+
'bootstrap' => 'media-uploader::themes.bootstrap.media-uploader',
34+
'custom' => 'media-uploader::themes.custom.media-uploader',
35+
],
36+
'theme' => 'custom', // to make it default
37+
```
38+
4. Or set per-instance:
39+
```html
40+
<livewire:media-uploader :for="$post" collection="images" theme="custom" />
41+
```
42+
- Configuration docs for each option in `config/media-uploader.php`, including **ENV overrides**, presets (`types`, `mimes`, `max_kb`), and **collection → preset** mapping.
43+
44+
### Changed
45+
- Default view now resolves via the **theme map** (Tailwind by default).
46+
Existing installs continue to render with Tailwind unless you switch themes.
47+
48+
### Compatibility
49+
- **No breaking changes.** Defaults preserve prior behavior.
50+
- If you previously published the old (pre-theme) Blade, it will keep working if you’ve retained the legacy alias. If you want to use the new theme system, publish/move your override to `themes/<your-theme>/media-uploader.blade.php`.
51+
52+
### Migration Notes (only if you customized the old path)
53+
- Minor migration required for users who published the old view (move file to the themed path).
54+
- Move your customized Blade from:
55+
```html
56+
resources/views/vendor/media-uploader/livewire/media-uploader.blade.php
57+
```
58+
to:
59+
```html
60+
resources/views/vendor/media-uploader/themes/tailwind/media-uploader.blade.php
61+
```
62+
(or into your custom theme folder), and register that theme in the config.
2563

2664
## [v0.1.0] — 2025-08-30
2765
### Added

README.md

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Livewire Media Uploader
22

3-
Livewire Media Uploader is a reusable Livewire v3 component that integrates seamlessly with Spatie Laravel Media Library. It ships a clean Tailwind Blade view (fully publishable), Alpine overlays for previews and confirmations, drag-and-drop uploads, per-file metadata (caption/description/order), configurable presets, name-conflict strategies, and optional SHA-256 duplicate detection. Drop it in, point it at a model, and you’re shipping in minutes.
3+
Livewire Media Uploader is a reusable Livewire v3 component that integrates seamlessly with Spatie Laravel Media Library. It ships a clean Tailwind Blade view by default (fully publishable), Bootstrap theme as an option, Alpine overlays for previews/confirmations, drag-and-drop uploads, per-file metadata (caption/description/order), configurable presets, name-conflict strategies, and optional SHA-256 duplicate detection. Drop it in, point it at a model, and you’re shipping in minutes.
44

55
---
66

@@ -25,7 +25,10 @@ Livewire Media Uploader is a reusable Livewire v3 component that integrates seam
2525

2626
## Features
2727

28-
- ✅ Livewire v3 component with Tailwind-only Blade (no UI dependency)
28+
- ✅ Livewire v3 component with themeable Blade UI
29+
- Tailwind (default)
30+
- Bootstrap (optional)
31+
- Fully publishable and overridable
2932
- ✅ Spatie Media Library integration (attach, list, edit meta, delete)
3033
-**Publishable view** for per-project customization
3134
- ✅ Drag & drop uploads + progress bar
@@ -50,6 +53,9 @@ Livewire Media Uploader is a reusable Livewire v3 component that integrates seam
5053
- spatie/laravel-medialibrary **^10.12**
5154
- TailwindCSS (optional but recommended for the default view)
5255
- Alpine.js (used by overlays/progress; see [Overlays & UX Notes](#overlays--ux-notes))
56+
- CSS depending on theme:
57+
- Tailwind theme → TailwindCSS (recommended)
58+
- Bootstrap theme → Bootstrap CSS (no Bootstrap JS required; Alpine drives modals)
5359

5460
---
5561

@@ -90,10 +96,34 @@ php artisan vendor:publish --tag=media-uploader-views
9096

9197
After publishing, customize the Blade at:
9298
```html
93-
resources/views/vendor/media-uploader/livewire/media-uploader.blade.php
99+
resources/views/vendor/media-uploader/themes/tailwind/media-uploader.blade.php
100+
resources/views/vendor/media-uploader/themes/bootstrap/media-uploader.blade.php
94101
```
95-
96-
102+
## Theme System (Tailwind + Bootstrap + custom)
103+
Select the theme in config/media-uploader.php:
104+
```php
105+
// config/media-uploader.php
106+
return [
107+
'theme' => 'tailwind', // 'tailwind' (default) or 'bootstrap'
108+
'themes' => [
109+
'tailwind' => 'media-uploader::themes.tailwind.media-uploader',
110+
'bootstrap' => 'media-uploader::themes.bootstrap.media-uploader',
111+
],
112+
// ...
113+
];
114+
```
115+
### Custom themes
116+
- Copy an existing theme directory (e.g. themes/tailwind) to themes/custom and edit the Blade.
117+
- Register it in the map and select it:
118+
```php
119+
'theme' => 'custom',
120+
'themes' => [
121+
'tailwind' => 'media-uploader::themes.tailwind.media-uploader',
122+
'bootstrap' => 'media-uploader::themes.bootstrap.media-uploader',
123+
'custom' => 'media-uploader::themes.custom.media-uploader',
124+
],
125+
```
126+
> Note: The component’s Livewire + Alpine behavior is identical across themes. Only classes/markup differ. If you use the Bootstrap theme, make sure your layout includes Bootstrap CSS.
97127
## Environment variables (optional)
98128
You can override preset limits and accepted types/mimes via .env. These map directly to config/media-uploader.php:
99129

config/media-uploader.php

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,33 +2,153 @@
22

33
return [
44

5+
/*
6+
|--------------------------------------------------------------------------
7+
| Active UI Theme
8+
|--------------------------------------------------------------------------
9+
| Controls which Blade view is used to render the uploader UI.
10+
| Accepts a key from the "themes" map below.
11+
|
12+
| Set globally via .env:
13+
| MEDIA_UPLOADER_THEME=tailwind
14+
|
15+
| You can override per-instance in your Livewire component usage:
16+
| <livewire:media-uploader
17+
| :for="$post"
18+
| collection="images"
19+
| theme="custom"
20+
| />
21+
|
22+
| Default: 'tailwind'
23+
*/
24+
'theme' => env('MEDIA_UPLOADER_THEME', 'tailwind'),
25+
26+
/*
27+
|--------------------------------------------------------------------------
28+
| Theme View Map
29+
|--------------------------------------------------------------------------
30+
| A list of available uploader themes. Keys are theme identifiers, values
31+
| are the fully qualified Blade view names to render the component.
32+
|
33+
| Custom themes:
34+
| - Create a new folder under the resources/views/vendor/media-uploader/themes directory, e.g. "custom".
35+
| - Copy one of the supplied theme files (media-uploader.blade.php) from "tailwind" or "bootstrap"
36+
| into the new "custom" folder. Keep the file name unchanged
37+
| (e.g. media-uploader.blade.php).
38+
| - Edit the copied file as needed.
39+
| - Register it here using the folder name as the key and the view path as the value:
40+
| 'custom' => 'media-uploader::themes.custom.media-uploader',
41+
| - Make sure to clear your view and config cache after implementing the new theme
42+
|
43+
| Usage:
44+
| - Globally via .env (see MEDIA_UPLOADER_THEME above), or
45+
| - Per instance:
46+
| <livewire:media-uploader
47+
| :for="$post"
48+
| collection="images"
49+
| theme="custom"
50+
| />
51+
*/
52+
'themes' => [
53+
'tailwind' => 'media-uploader::themes.tailwind.media-uploader',
54+
'bootstrap' => 'media-uploader::themes.bootstrap.media-uploader',
55+
// 'custom' => 'media-uploader::themes.custom.media-uploader',
56+
],
57+
58+
/*
59+
|--------------------------------------------------------------------------
60+
| Accept Attribute Source
61+
|--------------------------------------------------------------------------
62+
| When true, the uploader's HTML "accept" attribute is computed from the
63+
| selected preset's "types" or "mimes" defined below. When false, the
64+
| component won't auto-generate the "accept" attribute from config.
65+
*/
566
'accept_from_config' => true,
667

68+
/*
69+
|--------------------------------------------------------------------------
70+
| Collection → Preset Mapping
71+
|--------------------------------------------------------------------------
72+
| Define logical collections (used by your forms/models) and map each one
73+
| to a preset name from the "presets" section below.
74+
| Example: uploading to the "avatars" collection will apply the "images"
75+
| preset's validation constraints.
76+
*/
777
'collections' => [
878
'avatars' => 'images',
979
'images' => 'images',
1080
'attachments' => 'docs',
1181
],
1282

83+
/*
84+
|--------------------------------------------------------------------------
85+
| Presets
86+
|--------------------------------------------------------------------------
87+
| Each preset defines:
88+
| - types: Comma-separated file extensions (used for UI accept lists).
89+
| - mimes: Comma-separated MIME types (useful for strict validation).
90+
| - max_kb: Maximum file size in kilobytes.
91+
|
92+
| All values can be overridden via env variables for environment-specific
93+
| behavior. If an env var is missing, the default value is used.
94+
*/
1395
'presets' => [
96+
/*
97+
|----------------------------------------------------------------------
98+
| Images Preset
99+
|----------------------------------------------------------------------
100+
| Env:
101+
| - MEDIA_TYPES_IMAGES (e.g. "jpg,jpeg,png,webp,avif,gif")
102+
| - MEDIA_MIMES_IMAGES (e.g. "image/jpeg,image/png,...")
103+
| - MEDIA_MAXKB_IMAGES (integer KB, e.g. 10240 for 10 MB)
104+
*/
14105
'images' => [
15106
'types' => env('MEDIA_TYPES_IMAGES', 'jpg,jpeg,png,webp,avif,gif'),
16107
'mimes' => env('MEDIA_MIMES_IMAGES', 'image/jpeg,image/png,image/webp,image/avif,image/gif'),
17108
'max_kb' => (int) env('MEDIA_MAXKB_IMAGES', 10240),
18109
],
19110

111+
// ... existing code ...
112+
/*
113+
|----------------------------------------------------------------------
114+
| Documents Preset
115+
|----------------------------------------------------------------------
116+
| Env:
117+
| - MEDIA_TYPES_DOCS (e.g. "pdf,doc,docx,xls,xlsx,ppt,pptx,txt")
118+
| - MEDIA_MIMES_DOCS (e.g. "application/pdf,application/msword,...")
119+
| - MEDIA_MAXKB_DOCS (integer KB, e.g. 20480 for 20 MB)
120+
*/
20121
'docs' => [
21122
'types' => env('MEDIA_TYPES_DOCS', 'pdf,doc,docx,xls,xlsx,ppt,pptx,txt'),
22123
'mimes' => env('MEDIA_MIMES_DOCS', 'application/pdf,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-powerpoint,application/vnd.openxmlformats-officedocument.presentationml.presentation,text/plain'),
23124
'max_kb' => (int) env('MEDIA_MAXKB_DOCS', 20480),
24125
],
25126

127+
/*
128+
|----------------------------------------------------------------------
129+
| Videos Preset
130+
|----------------------------------------------------------------------
131+
| Env:
132+
| - MEDIA_TYPES_VIDEOS (e.g. "mp4,mov,webm")
133+
| - MEDIA_MIMES_VIDEOS (e.g. "video/mp4,video/quicktime,video/webm")
134+
| - MEDIA_MAXKB_VIDEOS (integer KB, e.g. 102400 for 100 MB)
135+
*/
26136
'videos' => [
27137
'types' => env('MEDIA_TYPES_VIDEOS', 'mp4,mov,webm'),
28138
'mimes' => env('MEDIA_MIMES_VIDEOS', 'video/mp4,video/quicktime,video/webm'),
29139
'max_kb' => (int) env('MEDIA_MAXKB_VIDEOS', 102400),
30140
],
31141

142+
/*
143+
|----------------------------------------------------------------------
144+
| Default Preset
145+
|----------------------------------------------------------------------
146+
| A catch-all preset combining common image and document formats.
147+
| Env:
148+
| - MEDIA_TYPES_DEFAULT
149+
| - MEDIA_MIMES_DEFAULT
150+
| - MEDIA_MAXKB_DEFAULT
151+
*/
32152
'default' => [
33153
'types' => env('MEDIA_TYPES_DEFAULT', 'jpg,jpeg,png,webp,avif,gif,pdf,doc,docx,xls,xlsx,ppt,pptx,txt'),
34154
'mimes' => env('MEDIA_MIMES_DEFAULT', 'image/jpeg,image/png,image/webp,image/avif,image/gif,application/pdf,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-powerpoint,application/vnd.openxmlformats-officedocument.presentationml.presentation,text/plain'),

0 commit comments

Comments
 (0)