@tradly/asset 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/EXAMPLE_USAGE.jsx +119 -0
- package/MIGRATION_GUIDE.md +236 -0
- package/README.md +292 -0
- package/STYLING_GUIDE.md +210 -0
- package/package.json +40 -0
- package/src/components/FileUpload.jsx +114 -0
- package/src/components/Icons.jsx +23 -0
- package/src/components/ImagesSkeleton.jsx +18 -0
- package/src/components/MediaGallery.jsx +125 -0
- package/src/components/MediaPopup.jsx +101 -0
- package/src/components/MediaTab.jsx +152 -0
- package/src/components/Pagination.jsx +175 -0
- package/src/components/VideosGallery.jsx +121 -0
- package/src/index.js +25 -0
- package/src/services/apiService.js +270 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Example usage of @tradly/media-gallery package
|
|
3
|
+
*
|
|
4
|
+
* This shows how to integrate the media gallery package into your existing project
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import React, { useState } from 'react'
|
|
8
|
+
import { MediaPopup, MediaApiService } from '@tradly/media-gallery'
|
|
9
|
+
import { getAuthKey } from 'constant/functions'
|
|
10
|
+
|
|
11
|
+
function ExampleMediaGalleryUsage() {
|
|
12
|
+
const [isOpen, setIsOpen] = useState(false)
|
|
13
|
+
const [selectedMedia, setSelectedMedia] = useState(null)
|
|
14
|
+
|
|
15
|
+
// Initialize API service with auth key
|
|
16
|
+
// API base URL is automatically detected from ENVIRONMENT:
|
|
17
|
+
// - Dev: https://api.dev.tradly.app
|
|
18
|
+
// - Prod: https://api.tradly.app
|
|
19
|
+
// All API calls go directly to Tradly API (no proxy needed)
|
|
20
|
+
const apiService = new MediaApiService({
|
|
21
|
+
authKey: getAuthKey(), // Get auth key from your existing function (X-Auth-Key header)
|
|
22
|
+
bearerToken: 'your-bearer-token', // Required: Bearer token for Authorization header
|
|
23
|
+
// environment is auto-detected from process.env.ENVIRONMENT
|
|
24
|
+
// apiBaseUrl is auto-set based on environment (can be overridden)
|
|
25
|
+
onError: (error) => {
|
|
26
|
+
console.error('Media API Error:', error)
|
|
27
|
+
// You can show a toast notification here
|
|
28
|
+
},
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
const handleSelect = (mediaUrl) => {
|
|
32
|
+
console.log('Selected media:', mediaUrl)
|
|
33
|
+
setSelectedMedia(mediaUrl)
|
|
34
|
+
setIsOpen(false)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const handleError = (error) => {
|
|
38
|
+
console.error('Media gallery error:', error)
|
|
39
|
+
// Handle error (show toast, etc.)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<div className="p-4">
|
|
44
|
+
<h2 className="text-2xl font-bold mb-4">Media Gallery Example</h2>
|
|
45
|
+
|
|
46
|
+
<div className="mb-4">
|
|
47
|
+
<button
|
|
48
|
+
onClick={() => setIsOpen(true)}
|
|
49
|
+
className="px-4 py-2 bg-primary text-white rounded-lg hover:bg-primary-dark"
|
|
50
|
+
>
|
|
51
|
+
Open Media Gallery
|
|
52
|
+
</button>
|
|
53
|
+
</div>
|
|
54
|
+
|
|
55
|
+
{selectedMedia && (
|
|
56
|
+
<div className="mt-4">
|
|
57
|
+
<p className="font-semibold">Selected Media:</p>
|
|
58
|
+
<img src={selectedMedia} alt="Selected" className="mt-2 max-w-xs rounded" />
|
|
59
|
+
</div>
|
|
60
|
+
)}
|
|
61
|
+
|
|
62
|
+
<MediaPopup
|
|
63
|
+
isOpen={isOpen}
|
|
64
|
+
onClose={() => setIsOpen(false)}
|
|
65
|
+
onSelect={handleSelect}
|
|
66
|
+
currentData={selectedMedia}
|
|
67
|
+
options={['image', 'video']} // Options: 'image', 'video', 'file'
|
|
68
|
+
apiService={apiService}
|
|
69
|
+
onError={handleError}
|
|
70
|
+
title="Select Media"
|
|
71
|
+
/>
|
|
72
|
+
</div>
|
|
73
|
+
)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Example: Using only images
|
|
77
|
+
function ImageOnlyExample() {
|
|
78
|
+
const [isOpen, setIsOpen] = useState(false)
|
|
79
|
+
const apiService = new MediaApiService({
|
|
80
|
+
authKey: getAuthKey(),
|
|
81
|
+
bearerToken: 'your-bearer-token', // Required
|
|
82
|
+
// apiBaseUrl is auto-detected from ENVIRONMENT
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
return (
|
|
86
|
+
<MediaPopup
|
|
87
|
+
isOpen={isOpen}
|
|
88
|
+
onClose={() => setIsOpen(false)}
|
|
89
|
+
onSelect={(url) => console.log('Selected:', url)}
|
|
90
|
+
options={['image']}
|
|
91
|
+
apiService={apiService}
|
|
92
|
+
/>
|
|
93
|
+
)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Example: Using individual components
|
|
97
|
+
function CustomGalleryExample() {
|
|
98
|
+
const apiService = new MediaApiService({
|
|
99
|
+
authKey: getAuthKey(),
|
|
100
|
+
bearerToken: 'your-bearer-token', // Required
|
|
101
|
+
// apiBaseUrl is auto-detected from ENVIRONMENT
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
return (
|
|
105
|
+
<div className="p-4">
|
|
106
|
+
<ImagesGallery
|
|
107
|
+
update_data={(url) => {
|
|
108
|
+
console.log('Image selected:', url)
|
|
109
|
+
}}
|
|
110
|
+
closePopup={() => {
|
|
111
|
+
console.log('Gallery closed')
|
|
112
|
+
}}
|
|
113
|
+
apiService={apiService}
|
|
114
|
+
/>
|
|
115
|
+
</div>
|
|
116
|
+
)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export default ExampleMediaGalleryUsage
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
# Migration Guide: From Existing Media Components to @tradly/media-gallery Package
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
This guide helps you migrate from the existing media components in `src/Shared/fields/MediaSections/` to the new reusable `@tradly/media-gallery` package.
|
|
6
|
+
|
|
7
|
+
## Benefits of Using the Package
|
|
8
|
+
|
|
9
|
+
1. **Reusability**: Use the same media gallery across multiple projects
|
|
10
|
+
2. **Maintainability**: Single source of truth for media gallery functionality
|
|
11
|
+
3. **Flexibility**: Easy to configure with different auth keys and API endpoints
|
|
12
|
+
4. **Separation of Concerns**: Media gallery logic is isolated from your main app
|
|
13
|
+
|
|
14
|
+
## Package Structure
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
packages/media-gallery/
|
|
18
|
+
├── src/
|
|
19
|
+
│ ├── components/
|
|
20
|
+
│ │ ├── MediaPopup.jsx # Main popup component
|
|
21
|
+
│ │ ├── MediaTab.jsx # Tab navigation
|
|
22
|
+
│ │ ├── MediaGallery.jsx # Images gallery
|
|
23
|
+
│ │ ├── VideosGallery.jsx # Videos gallery
|
|
24
|
+
│ │ ├── FileUpload.jsx # File upload component
|
|
25
|
+
│ │ ├── Pagination.jsx # Pagination component
|
|
26
|
+
│ │ ├── ImagesSkeleton.jsx # Loading skeleton
|
|
27
|
+
│ │ └── Icons.jsx # Icon components
|
|
28
|
+
│ ├── services/
|
|
29
|
+
│ │ └── apiService.js # API service layer
|
|
30
|
+
│ └── index.js # Main export
|
|
31
|
+
├── package.json
|
|
32
|
+
├── README.md
|
|
33
|
+
└── EXAMPLE_USAGE.jsx
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Migration Steps
|
|
37
|
+
|
|
38
|
+
### Step 1: Install/Setup the Package
|
|
39
|
+
|
|
40
|
+
Since this is a local package, you can either:
|
|
41
|
+
|
|
42
|
+
**Option A: Use as local package (for now)**
|
|
43
|
+
|
|
44
|
+
```json
|
|
45
|
+
// In your main package.json, add:
|
|
46
|
+
{
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"@tradly/media-gallery": "file:./packages/media-gallery"
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**Option B: Publish to npm (later)**
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
cd packages/media-gallery
|
|
57
|
+
npm publish
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Step 2: Update Your Component
|
|
61
|
+
|
|
62
|
+
**Before (Old way):**
|
|
63
|
+
|
|
64
|
+
```jsx
|
|
65
|
+
import MediaGallery from '@/Shared/fields/MediaSections/MediaPopup'
|
|
66
|
+
|
|
67
|
+
function MyComponent() {
|
|
68
|
+
const [isOpen, setIsOpen] = useState(false)
|
|
69
|
+
|
|
70
|
+
return (
|
|
71
|
+
<MediaGallery
|
|
72
|
+
isOpenPopup={isOpen}
|
|
73
|
+
setIsOpenPopup={setIsOpen}
|
|
74
|
+
current_data={selectedMedia}
|
|
75
|
+
update_data={setSelectedMedia}
|
|
76
|
+
options={['image']}
|
|
77
|
+
/>
|
|
78
|
+
)
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**After (New way):**
|
|
83
|
+
|
|
84
|
+
```jsx
|
|
85
|
+
import { MediaPopup, MediaApiService } from '@tradly/media-gallery'
|
|
86
|
+
import { getAuthKey } from 'constant/functions'
|
|
87
|
+
|
|
88
|
+
function MyComponent() {
|
|
89
|
+
const [isOpen, setIsOpen] = useState(false)
|
|
90
|
+
const [selectedMedia, setSelectedMedia] = useState(null)
|
|
91
|
+
|
|
92
|
+
// Initialize API service with Tradly SDK
|
|
93
|
+
const apiService = new MediaApiService({
|
|
94
|
+
authKey: getAuthKey(),
|
|
95
|
+
baseUrl: '/api',
|
|
96
|
+
tradly: tradly, // Pass Tradly SDK instance (required for uploads)
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
return (
|
|
100
|
+
<MediaPopup
|
|
101
|
+
isOpen={isOpen}
|
|
102
|
+
onClose={() => setIsOpen(false)}
|
|
103
|
+
onSelect={setSelectedMedia}
|
|
104
|
+
currentData={selectedMedia}
|
|
105
|
+
options={['image']}
|
|
106
|
+
apiService={apiService}
|
|
107
|
+
/>
|
|
108
|
+
)
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Step 3: Configure API Service
|
|
113
|
+
|
|
114
|
+
The package handles all upload logic internally using direct API calls. The API base URL is automatically detected from your environment:
|
|
115
|
+
|
|
116
|
+
```jsx
|
|
117
|
+
const apiService = new MediaApiService({
|
|
118
|
+
authKey: getAuthKey(), // X-Auth-Key header
|
|
119
|
+
bearerToken: 'your-bearer-token', // Required: Bearer token
|
|
120
|
+
// environment is auto-detected from process.env.ENVIRONMENT
|
|
121
|
+
// apiBaseUrl is auto-set based on environment:
|
|
122
|
+
// - Dev: https://api.dev.tradly.app
|
|
123
|
+
// - Prod: https://api.tradly.app
|
|
124
|
+
})
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
The package will automatically:
|
|
128
|
+
|
|
129
|
+
1. Detect environment from `process.env.ENVIRONMENT` (or you can pass `environment: 'dev'` or `'production'`)
|
|
130
|
+
2. Set the correct API base URL (`https://api.dev.tradly.app` for dev, `https://api.tradly.app` for prod)
|
|
131
|
+
3. Get S3 signed URLs via API call to `POST /v1/utils/S3signedUploadURL`
|
|
132
|
+
4. Upload files to S3 using the signed URLs
|
|
133
|
+
5. Save media metadata via `POST /v1/media` with `{ media: [...] }` format
|
|
134
|
+
6. Fetch media list via `GET /v1/media?page=1&parent=0&mime_type=...`
|
|
135
|
+
|
|
136
|
+
## Key Differences
|
|
137
|
+
|
|
138
|
+
| Old Component | New Package |
|
|
139
|
+
| --------------------------------------- | -------------------------------- |
|
|
140
|
+
| `isOpenPopup` prop | `isOpen` prop |
|
|
141
|
+
| `setIsOpenPopup` prop | `onClose` callback |
|
|
142
|
+
| `update_data` prop | `onSelect` callback |
|
|
143
|
+
| `current_data` prop | `currentData` prop |
|
|
144
|
+
| Uses `proxy_api_call` directly | Uses `MediaApiService` |
|
|
145
|
+
| Auth key from `getAuthKey()` internally | Auth key passed via `apiService` |
|
|
146
|
+
| Hardcoded API paths | Configurable via `apiService` |
|
|
147
|
+
|
|
148
|
+
## Complete Example
|
|
149
|
+
|
|
150
|
+
Here's a complete example showing how to replace the old component:
|
|
151
|
+
|
|
152
|
+
```jsx
|
|
153
|
+
import React, { useState } from 'react'
|
|
154
|
+
import { MediaPopup, MediaApiService } from '@tradly/media-gallery'
|
|
155
|
+
import { getAuthKey } from 'constant/functions'
|
|
156
|
+
|
|
157
|
+
function MyMediaSelector() {
|
|
158
|
+
const [isOpen, setIsOpen] = useState(false)
|
|
159
|
+
const [selectedImage, setSelectedImage] = useState(null)
|
|
160
|
+
|
|
161
|
+
// Create API service instance
|
|
162
|
+
// API base URL is automatically detected from ENVIRONMENT
|
|
163
|
+
// All API calls go directly to Tradly API (no proxy needed)
|
|
164
|
+
const apiService = React.useMemo(() => {
|
|
165
|
+
return new MediaApiService({
|
|
166
|
+
authKey: getAuthKey(),
|
|
167
|
+
bearerToken: 'your-bearer-token', // Required: Bearer token
|
|
168
|
+
// apiBaseUrl is auto-detected from process.env.ENVIRONMENT
|
|
169
|
+
onError: (error) => {
|
|
170
|
+
console.error('Media API Error:', error)
|
|
171
|
+
// Show error toast, etc.
|
|
172
|
+
},
|
|
173
|
+
})
|
|
174
|
+
}, [])
|
|
175
|
+
|
|
176
|
+
return (
|
|
177
|
+
<div>
|
|
178
|
+
<button onClick={() => setIsOpen(true)}>Select Media</button>
|
|
179
|
+
|
|
180
|
+
{selectedImage && <img src={selectedImage} alt="Selected" />}
|
|
181
|
+
|
|
182
|
+
<MediaPopup
|
|
183
|
+
isOpen={isOpen}
|
|
184
|
+
onClose={() => setIsOpen(false)}
|
|
185
|
+
onSelect={(url) => {
|
|
186
|
+
setSelectedImage(url)
|
|
187
|
+
setIsOpen(false)
|
|
188
|
+
}}
|
|
189
|
+
currentData={selectedImage}
|
|
190
|
+
options={['image', 'video']}
|
|
191
|
+
apiService={apiService}
|
|
192
|
+
onError={(error) => {
|
|
193
|
+
console.error('Gallery error:', error)
|
|
194
|
+
}}
|
|
195
|
+
/>
|
|
196
|
+
</div>
|
|
197
|
+
)
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
export default MyMediaSelector
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
## Testing
|
|
204
|
+
|
|
205
|
+
After migration, test the following:
|
|
206
|
+
|
|
207
|
+
1. ✅ Opening/closing the media gallery
|
|
208
|
+
2. ✅ Uploading new images/videos
|
|
209
|
+
3. ✅ Selecting existing media
|
|
210
|
+
4. ✅ Pagination works correctly
|
|
211
|
+
5. ✅ Error handling works
|
|
212
|
+
6. ✅ Authentication is working
|
|
213
|
+
|
|
214
|
+
## Rollback Plan
|
|
215
|
+
|
|
216
|
+
If you need to rollback:
|
|
217
|
+
|
|
218
|
+
1. Keep the old components in `src/Shared/fields/MediaSections/`
|
|
219
|
+
2. Import from the old location instead of the package
|
|
220
|
+
3. The old components will continue to work as before
|
|
221
|
+
|
|
222
|
+
## Next Steps
|
|
223
|
+
|
|
224
|
+
1. Test the package in a development environment
|
|
225
|
+
2. Gradually migrate components one by one
|
|
226
|
+
3. Once stable, consider removing old components
|
|
227
|
+
4. Optionally publish to npm for use in other projects
|
|
228
|
+
|
|
229
|
+
## Support
|
|
230
|
+
|
|
231
|
+
If you encounter issues during migration:
|
|
232
|
+
|
|
233
|
+
1. Check the `EXAMPLE_USAGE.jsx` file
|
|
234
|
+
2. Review the `README.md` for API documentation
|
|
235
|
+
3. Ensure all peer dependencies are installed
|
|
236
|
+
4. Verify your auth key and API base URL are correct
|
package/README.md
ADDED
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
# @tradly/media-gallery
|
|
2
|
+
|
|
3
|
+
A reusable React component package for uploading and selecting media (images, videos, files) with Tradly authentication support.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 📸 Upload and browse images
|
|
8
|
+
- 🎥 Upload and browse videos
|
|
9
|
+
- 📁 Upload and browse files
|
|
10
|
+
- 🔐 Tradly authentication support
|
|
11
|
+
- 🎨 Customizable UI
|
|
12
|
+
- 📱 Responsive design
|
|
13
|
+
- 🔄 Pagination support
|
|
14
|
+
- ⚡ Lightweight and performant
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install @tradly/media-gallery
|
|
20
|
+
# or
|
|
21
|
+
yarn add @tradly/media-gallery
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Peer Dependencies
|
|
25
|
+
|
|
26
|
+
This package requires the following peer dependencies:
|
|
27
|
+
|
|
28
|
+
- `react` (>=16.8.0)
|
|
29
|
+
- `react-dom` (>=16.8.0)
|
|
30
|
+
- `@headlessui/react` (^1.7.0) - for Tab components
|
|
31
|
+
- `axios` (^0.24.0) - for API calls
|
|
32
|
+
|
|
33
|
+
**Note:**
|
|
34
|
+
|
|
35
|
+
- All pagination logic is built-in, no external pagination library needed!
|
|
36
|
+
- No Tradly SDK dependency - uses direct API calls
|
|
37
|
+
|
|
38
|
+
## Basic Usage
|
|
39
|
+
|
|
40
|
+
```jsx
|
|
41
|
+
import React, { useState } from 'react'
|
|
42
|
+
import { MediaPopup, MediaApiService } from '@tradly/media-gallery'
|
|
43
|
+
|
|
44
|
+
function MyComponent() {
|
|
45
|
+
const [isOpen, setIsOpen] = useState(false)
|
|
46
|
+
const [selectedMedia, setSelectedMedia] = useState(null)
|
|
47
|
+
|
|
48
|
+
// Initialize API service with your auth key
|
|
49
|
+
// API base URL is automatically detected from ENVIRONMENT:
|
|
50
|
+
// - Dev: https://api.dev.tradly.app
|
|
51
|
+
// - Prod: https://api.tradly.app
|
|
52
|
+
const apiService = new MediaApiService({
|
|
53
|
+
authKey: 'your-tradly-auth-key', // Required: X-Auth-Key header
|
|
54
|
+
bearerToken: 'your-bearer-token', // Required: Bearer token for Authorization header
|
|
55
|
+
// environment is auto-detected from process.env.ENVIRONMENT
|
|
56
|
+
// apiBaseUrl is auto-set based on environment (can be overridden)
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
const handleSelect = (mediaUrl) => {
|
|
60
|
+
setSelectedMedia(mediaUrl)
|
|
61
|
+
setIsOpen(false)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return (
|
|
65
|
+
<>
|
|
66
|
+
<button onClick={() => setIsOpen(true)}>Open Media Gallery</button>
|
|
67
|
+
|
|
68
|
+
<MediaPopup
|
|
69
|
+
isOpen={isOpen}
|
|
70
|
+
onClose={() => setIsOpen(false)}
|
|
71
|
+
onSelect={handleSelect}
|
|
72
|
+
options={['image', 'video']} // Options: 'image', 'video', 'file'
|
|
73
|
+
apiService={apiService}
|
|
74
|
+
/>
|
|
75
|
+
</>
|
|
76
|
+
)
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Advanced Usage
|
|
81
|
+
|
|
82
|
+
### Upload Functionality
|
|
83
|
+
|
|
84
|
+
The package includes complete upload functionality using direct API calls. All upload logic is handled internally:
|
|
85
|
+
|
|
86
|
+
1. **Get S3 signed URLs** via API call to `/v1/utils/S3signedUploadURL`
|
|
87
|
+
2. **Upload files to S3** using the signed URLs
|
|
88
|
+
3. **Save media metadata** to your API
|
|
89
|
+
|
|
90
|
+
Configuration:
|
|
91
|
+
|
|
92
|
+
```jsx
|
|
93
|
+
import { MediaApiService } from '@tradly/media-gallery'
|
|
94
|
+
|
|
95
|
+
const apiService = new MediaApiService({
|
|
96
|
+
authKey: 'your-auth-key', // Required: X-Auth-Key header
|
|
97
|
+
bearerToken: 'your-bearer-token', // Required: Bearer token for Authorization header
|
|
98
|
+
environment: 'dev', // Optional: 'dev' or 'production' (auto-detected from process.env.ENVIRONMENT)
|
|
99
|
+
apiBaseUrl: 'https://api.tradly.app', // Optional: Override auto-detected base URL
|
|
100
|
+
})
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
**API Base URL Auto-Detection:**
|
|
104
|
+
|
|
105
|
+
- If `environment` includes 'dev' → `https://api.dev.tradly.app`
|
|
106
|
+
- Otherwise → `https://api.tradly.app`
|
|
107
|
+
- You can override by providing `apiBaseUrl` explicitly
|
|
108
|
+
|
|
109
|
+
### Using Individual Components
|
|
110
|
+
|
|
111
|
+
You can also use the components individually:
|
|
112
|
+
|
|
113
|
+
```jsx
|
|
114
|
+
import { ImagesGallery, MediaApiService } from '@tradly/media-gallery'
|
|
115
|
+
|
|
116
|
+
function CustomGallery() {
|
|
117
|
+
const apiService = new MediaApiService({
|
|
118
|
+
authKey: 'your-auth-key',
|
|
119
|
+
baseUrl: '/api',
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
return (
|
|
123
|
+
<ImagesGallery
|
|
124
|
+
update_data={(url) => console.log('Selected:', url)}
|
|
125
|
+
closePopup={() => console.log('Closed')}
|
|
126
|
+
apiService={apiService}
|
|
127
|
+
/>
|
|
128
|
+
)
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Error Handling
|
|
133
|
+
|
|
134
|
+
```jsx
|
|
135
|
+
<MediaPopup
|
|
136
|
+
isOpen={isOpen}
|
|
137
|
+
onClose={() => setIsOpen(false)}
|
|
138
|
+
onSelect={handleSelect}
|
|
139
|
+
apiService={apiService}
|
|
140
|
+
onError={(error) => {
|
|
141
|
+
console.error('Media gallery error:', error)
|
|
142
|
+
// Handle error (show toast, etc.)
|
|
143
|
+
}}
|
|
144
|
+
/>
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## API Service Configuration
|
|
148
|
+
|
|
149
|
+
### MediaApiService Options
|
|
150
|
+
|
|
151
|
+
```jsx
|
|
152
|
+
const apiService = new MediaApiService({
|
|
153
|
+
authKey: 'string', // Required: Authentication key for X-Auth-Key header
|
|
154
|
+
bearerToken: 'string', // Required: Bearer token for Authorization header
|
|
155
|
+
environment: 'string', // Optional: 'dev' or 'production' (auto-detected from process.env.ENVIRONMENT)
|
|
156
|
+
apiBaseUrl: 'string', // Optional: Override auto-detected base URL (defaults: https://api.dev.tradly.app for dev, https://api.tradly.app for prod)
|
|
157
|
+
onError: (error) => {}, // Optional: Global error handler
|
|
158
|
+
})
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Methods
|
|
162
|
+
|
|
163
|
+
```jsx
|
|
164
|
+
// Update auth key
|
|
165
|
+
apiService.setAuthKey('new-auth-key')
|
|
166
|
+
|
|
167
|
+
// Update API base URL (used for all API calls)
|
|
168
|
+
apiService.setApiBaseUrl('https://api.tradly.app')
|
|
169
|
+
|
|
170
|
+
// Set Bearer token
|
|
171
|
+
apiService.setBearerToken('new-bearer-token')
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## Props
|
|
175
|
+
|
|
176
|
+
### MediaPopup Props
|
|
177
|
+
|
|
178
|
+
| Prop | Type | Default | Description |
|
|
179
|
+
| ------------- | ----------------- | ----------------- | --------------------------------------------------- |
|
|
180
|
+
| `isOpen` | `boolean` | `false` | Controls popup visibility |
|
|
181
|
+
| `onClose` | `function` | - | Callback when popup closes |
|
|
182
|
+
| `onSelect` | `function` | - | Callback when media is selected |
|
|
183
|
+
| `currentData` | `any` | - | Currently selected media data |
|
|
184
|
+
| `options` | `array` | `['image']` | Media types to show: `'image'`, `'video'`, `'file'` |
|
|
185
|
+
| `apiService` | `MediaApiService` | - | **Required**: API service instance |
|
|
186
|
+
| `onError` | `function` | - | Error handler callback |
|
|
187
|
+
| `title` | `string` | `'Media Gallery'` | Popup title |
|
|
188
|
+
|
|
189
|
+
## Styling
|
|
190
|
+
|
|
191
|
+
This package uses Tailwind CSS classes and supports full customization at every component level. All components accept `className` props that allow you to override default styles.
|
|
192
|
+
|
|
193
|
+
### Quick Customization Example
|
|
194
|
+
|
|
195
|
+
```jsx
|
|
196
|
+
<MediaPopup
|
|
197
|
+
isOpen={isOpen}
|
|
198
|
+
onClose={() => setIsOpen(false)}
|
|
199
|
+
onSelect={handleSelect}
|
|
200
|
+
apiService={apiService}
|
|
201
|
+
// Customize popup
|
|
202
|
+
overlayClassName="bg-black/60 backdrop-blur-sm"
|
|
203
|
+
containerClassName="max-w-4xl bg-gray-900 rounded-xl"
|
|
204
|
+
titleClassName="text-2xl font-bold text-white"
|
|
205
|
+
// Customize tabs
|
|
206
|
+
tabButtonActiveClassName="text-blue-400 border-b-2 border-blue-400"
|
|
207
|
+
// Customize gallery
|
|
208
|
+
gridClassName="grid grid-cols-4 gap-4"
|
|
209
|
+
imageItemClassName="rounded-lg border-2 hover:border-blue-500"
|
|
210
|
+
/>
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Available Styling Props
|
|
214
|
+
|
|
215
|
+
**MediaPopup:**
|
|
216
|
+
|
|
217
|
+
- `overlayClassName` - Overlay/backdrop
|
|
218
|
+
- `containerClassName` - Main popup container
|
|
219
|
+
- `headerClassName` - Header container
|
|
220
|
+
- `titleClassName` - Title text
|
|
221
|
+
- `closeButtonClassName` - Close button
|
|
222
|
+
- `tabListClassName` - Tab list (passed to MediaTab)
|
|
223
|
+
- `tabButtonClassName` - Base tab button
|
|
224
|
+
- `tabButtonActiveClassName` - Active tab button
|
|
225
|
+
- `tabButtonInactiveClassName` - Inactive tab button
|
|
226
|
+
- `gridClassName` - Media grid layout
|
|
227
|
+
- `imageItemClassName` - Image item styles
|
|
228
|
+
- `videoItemClassName` - Video item styles
|
|
229
|
+
- `paginationContainerClassName` - Pagination container
|
|
230
|
+
|
|
231
|
+
**Individual Components:**
|
|
232
|
+
You can also style individual components when using them separately. See `STYLING_GUIDE.md` for complete documentation.
|
|
233
|
+
|
|
234
|
+
### Full Styling Guide
|
|
235
|
+
|
|
236
|
+
For detailed styling documentation with examples, see [STYLING_GUIDE.md](./STYLING_GUIDE.md).
|
|
237
|
+
|
|
238
|
+
## Examples
|
|
239
|
+
|
|
240
|
+
### Image Only Gallery
|
|
241
|
+
|
|
242
|
+
```jsx
|
|
243
|
+
<MediaPopup
|
|
244
|
+
isOpen={isOpen}
|
|
245
|
+
onClose={() => setIsOpen(false)}
|
|
246
|
+
onSelect={handleSelect}
|
|
247
|
+
options={['image']}
|
|
248
|
+
apiService={apiService}
|
|
249
|
+
/>
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### Video Only Gallery
|
|
253
|
+
|
|
254
|
+
```jsx
|
|
255
|
+
<MediaPopup
|
|
256
|
+
isOpen={isOpen}
|
|
257
|
+
onClose={() => setIsOpen(false)}
|
|
258
|
+
onSelect={handleSelect}
|
|
259
|
+
options={['video']}
|
|
260
|
+
apiService={apiService}
|
|
261
|
+
/>
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
### All Media Types
|
|
265
|
+
|
|
266
|
+
```jsx
|
|
267
|
+
<MediaPopup
|
|
268
|
+
isOpen={isOpen}
|
|
269
|
+
onClose={() => setIsOpen(false)}
|
|
270
|
+
onSelect={handleSelect}
|
|
271
|
+
options={['image', 'video', 'file']}
|
|
272
|
+
apiService={apiService}
|
|
273
|
+
/>
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
## Development
|
|
277
|
+
|
|
278
|
+
To develop or modify this package:
|
|
279
|
+
|
|
280
|
+
```bash
|
|
281
|
+
cd packages/media-gallery
|
|
282
|
+
npm install
|
|
283
|
+
npm run dev
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
## License
|
|
287
|
+
|
|
288
|
+
MIT
|
|
289
|
+
|
|
290
|
+
## Support
|
|
291
|
+
|
|
292
|
+
For issues and questions, please open an issue on the repository.
|