@tradly/asset 1.0.2 → 1.0.4
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/dist/components/FileUpload.js +155 -0
- package/dist/components/Icons.js +32 -0
- package/dist/components/ImagesSkeleton.js +14 -0
- package/dist/components/MediaGallery.js +144 -0
- package/dist/components/MediaPopup.js +97 -0
- package/dist/components/MediaTab.js +132 -0
- package/dist/components/Pagination.js +134 -0
- package/dist/components/VideosGallery.js +144 -0
- package/dist/services/apiService.js +373 -0
- package/package.json +17 -5
- package/EXAMPLE_USAGE.jsx +0 -128
- package/MIGRATION_GUIDE.md +0 -249
- package/STYLING_GUIDE.md +0 -219
- package/src/components/FileUpload.jsx +0 -114
- package/src/components/Icons.jsx +0 -23
- package/src/components/ImagesSkeleton.jsx +0 -18
- package/src/components/MediaGallery.jsx +0 -125
- package/src/components/MediaPopup.jsx +0 -101
- package/src/components/MediaTab.jsx +0 -152
- package/src/components/Pagination.jsx +0 -175
- package/src/components/VideosGallery.jsx +0 -121
- package/src/services/apiService.js +0 -270
- /package/{src → dist}/index.js +0 -0
package/package.json
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tradly/asset",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "A reusable media gallery component for uploading and selecting images, videos, and files with Tradly authentication",
|
|
5
|
-
"main": "
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.js",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist",
|
|
9
|
+
"README.md",
|
|
10
|
+
"LICENSE"
|
|
11
|
+
],
|
|
6
12
|
"scripts": {
|
|
7
|
-
"build": "
|
|
8
|
-
"
|
|
13
|
+
"build": "node build.js",
|
|
14
|
+
"prepublishOnly": "npm run build",
|
|
15
|
+
"dev": "npm run build"
|
|
9
16
|
},
|
|
10
17
|
"keywords": [
|
|
11
18
|
"media",
|
|
@@ -34,5 +41,10 @@
|
|
|
34
41
|
"@headlessui/react": "^1.7.0",
|
|
35
42
|
"axios": "^0.24.0"
|
|
36
43
|
},
|
|
37
|
-
"devDependencies": {
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@babel/cli": "^7.28.3",
|
|
46
|
+
"@babel/core": "^7.28.5",
|
|
47
|
+
"@babel/preset-env": "^7.28.5",
|
|
48
|
+
"@babel/preset-react": "^7.28.5"
|
|
49
|
+
}
|
|
38
50
|
}
|
package/EXAMPLE_USAGE.jsx
DELETED
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Example usage of @tradly/asset 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/asset";
|
|
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">
|
|
45
|
-
Media Gallery Example
|
|
46
|
-
</h2>
|
|
47
|
-
|
|
48
|
-
<div className="mb-4">
|
|
49
|
-
<button
|
|
50
|
-
onClick={() => setIsOpen(true)}
|
|
51
|
-
className="px-4 py-2 bg-primary text-white rounded-lg hover:bg-primary-dark"
|
|
52
|
-
>
|
|
53
|
-
Open Media Gallery
|
|
54
|
-
</button>
|
|
55
|
-
</div>
|
|
56
|
-
|
|
57
|
-
{selectedMedia && (
|
|
58
|
-
<div className="mt-4">
|
|
59
|
-
<p className="font-semibold">
|
|
60
|
-
Selected Media:
|
|
61
|
-
</p>
|
|
62
|
-
<img
|
|
63
|
-
src={selectedMedia}
|
|
64
|
-
alt="Selected"
|
|
65
|
-
className="mt-2 max-w-xs rounded"
|
|
66
|
-
/>
|
|
67
|
-
</div>
|
|
68
|
-
)}
|
|
69
|
-
|
|
70
|
-
<MediaPopup
|
|
71
|
-
isOpen={isOpen}
|
|
72
|
-
onClose={() => setIsOpen(false)}
|
|
73
|
-
onSelect={handleSelect}
|
|
74
|
-
currentData={selectedMedia}
|
|
75
|
-
options={["image", "video"]} // Options: 'image', 'video', 'file'
|
|
76
|
-
apiService={apiService}
|
|
77
|
-
onError={handleError}
|
|
78
|
-
title="Select Media"
|
|
79
|
-
/>
|
|
80
|
-
</div>
|
|
81
|
-
);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// Example: Using only images
|
|
85
|
-
function ImageOnlyExample() {
|
|
86
|
-
const [isOpen, setIsOpen] = useState(false);
|
|
87
|
-
const apiService = new MediaApiService({
|
|
88
|
-
authKey: getAuthKey(),
|
|
89
|
-
bearerToken: "your-bearer-token", // Required
|
|
90
|
-
// apiBaseUrl is auto-detected from ENVIRONMENT
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
return (
|
|
94
|
-
<MediaPopup
|
|
95
|
-
isOpen={isOpen}
|
|
96
|
-
onClose={() => setIsOpen(false)}
|
|
97
|
-
onSelect={(url) => console.log("Selected:", url)}
|
|
98
|
-
options={["image"]}
|
|
99
|
-
apiService={apiService}
|
|
100
|
-
/>
|
|
101
|
-
);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// Example: Using individual components
|
|
105
|
-
function CustomGalleryExample() {
|
|
106
|
-
const apiService = new MediaApiService({
|
|
107
|
-
authKey: getAuthKey(),
|
|
108
|
-
bearerToken: "your-bearer-token", // Required
|
|
109
|
-
// apiBaseUrl is auto-detected from ENVIRONMENT
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
return (
|
|
113
|
-
<div className="p-4">
|
|
114
|
-
<ImagesGallery
|
|
115
|
-
update_data={(url) => {
|
|
116
|
-
console.log("Image selected:", url);
|
|
117
|
-
}}
|
|
118
|
-
closePopup={() => {
|
|
119
|
-
console.log("Gallery closed");
|
|
120
|
-
}}
|
|
121
|
-
apiService={apiService}
|
|
122
|
-
/>
|
|
123
|
-
</div>
|
|
124
|
-
);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
export default ExampleMediaGalleryUsage;
|
|
128
|
-
|
package/MIGRATION_GUIDE.md
DELETED
|
@@ -1,249 +0,0 @@
|
|
|
1
|
-
# Migration Guide: From Existing Media Components to @tradly/asset Package
|
|
2
|
-
|
|
3
|
-
## Overview
|
|
4
|
-
|
|
5
|
-
This guide helps you migrate from the existing media components in
|
|
6
|
-
`src/Shared/fields/MediaSections/` to the new reusable `@tradly/asset` package.
|
|
7
|
-
|
|
8
|
-
## Benefits of Using the Package
|
|
9
|
-
|
|
10
|
-
1. **Reusability**: Use the same media gallery across multiple projects
|
|
11
|
-
2. **Maintainability**: Single source of truth for media gallery functionality
|
|
12
|
-
3. **Flexibility**: Easy to configure with different auth keys and API endpoints
|
|
13
|
-
4. **Separation of Concerns**: Media gallery logic is isolated from your main
|
|
14
|
-
app
|
|
15
|
-
|
|
16
|
-
## Package Structure
|
|
17
|
-
|
|
18
|
-
```
|
|
19
|
-
packages/asset/
|
|
20
|
-
├── src/
|
|
21
|
-
│ ├── components/
|
|
22
|
-
│ │ ├── MediaPopup.jsx # Main popup component
|
|
23
|
-
│ │ ├── MediaTab.jsx # Tab navigation
|
|
24
|
-
│ │ ├── MediaGallery.jsx # Images gallery
|
|
25
|
-
│ │ ├── VideosGallery.jsx # Videos gallery
|
|
26
|
-
│ │ ├── FileUpload.jsx # File upload component
|
|
27
|
-
│ │ ├── Pagination.jsx # Pagination component
|
|
28
|
-
│ │ ├── ImagesSkeleton.jsx # Loading skeleton
|
|
29
|
-
│ │ └── Icons.jsx # Icon components
|
|
30
|
-
│ ├── services/
|
|
31
|
-
│ │ └── apiService.js # API service layer
|
|
32
|
-
│ └── index.js # Main export
|
|
33
|
-
├── package.json
|
|
34
|
-
├── README.md
|
|
35
|
-
└── EXAMPLE_USAGE.jsx
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
## Migration Steps
|
|
39
|
-
|
|
40
|
-
### Step 1: Install/Setup the Package
|
|
41
|
-
|
|
42
|
-
Since this is a local package, you can either:
|
|
43
|
-
|
|
44
|
-
**Option A: Use as local package (for now)**
|
|
45
|
-
|
|
46
|
-
```json
|
|
47
|
-
// In your main package.json, add:
|
|
48
|
-
{
|
|
49
|
-
"dependencies": {
|
|
50
|
-
"@tradly/asset": "file:./packages/asset"
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
**Option B: Publish to npm (later)**
|
|
56
|
-
|
|
57
|
-
```bash
|
|
58
|
-
cd packages/asset
|
|
59
|
-
npm publish
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
### Step 2: Update Your Component
|
|
63
|
-
|
|
64
|
-
**Before (Old way):**
|
|
65
|
-
|
|
66
|
-
```jsx
|
|
67
|
-
import MediaGallery from "@/Shared/fields/MediaSections/MediaPopup";
|
|
68
|
-
|
|
69
|
-
function MyComponent() {
|
|
70
|
-
const [isOpen, setIsOpen] = useState(false);
|
|
71
|
-
|
|
72
|
-
return (
|
|
73
|
-
<MediaGallery
|
|
74
|
-
isOpenPopup={isOpen}
|
|
75
|
-
setIsOpenPopup={setIsOpen}
|
|
76
|
-
current_data={selectedMedia}
|
|
77
|
-
update_data={setSelectedMedia}
|
|
78
|
-
options={["image"]}
|
|
79
|
-
/>
|
|
80
|
-
);
|
|
81
|
-
}
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
**After (New way):**
|
|
85
|
-
|
|
86
|
-
```jsx
|
|
87
|
-
import { MediaPopup, MediaApiService } from "@tradly/asset";
|
|
88
|
-
import { getAuthKey } from "constant/functions";
|
|
89
|
-
|
|
90
|
-
function MyComponent() {
|
|
91
|
-
const [isOpen, setIsOpen] = useState(false);
|
|
92
|
-
const [selectedMedia, setSelectedMedia] = useState(null);
|
|
93
|
-
|
|
94
|
-
// Initialize API service with Tradly SDK
|
|
95
|
-
const apiService = new MediaApiService({
|
|
96
|
-
authKey: getAuthKey(),
|
|
97
|
-
baseUrl: "/api",
|
|
98
|
-
tradly: tradly, // Pass Tradly SDK instance (required for uploads)
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
return (
|
|
102
|
-
<MediaPopup
|
|
103
|
-
isOpen={isOpen}
|
|
104
|
-
onClose={() => setIsOpen(false)}
|
|
105
|
-
onSelect={setSelectedMedia}
|
|
106
|
-
currentData={selectedMedia}
|
|
107
|
-
options={["image"]}
|
|
108
|
-
apiService={apiService}
|
|
109
|
-
/>
|
|
110
|
-
);
|
|
111
|
-
}
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
### Step 3: Configure API Service
|
|
115
|
-
|
|
116
|
-
The package handles all upload logic internally using direct API calls. The API
|
|
117
|
-
base URL is automatically detected from your environment:
|
|
118
|
-
|
|
119
|
-
```jsx
|
|
120
|
-
const apiService = new MediaApiService({
|
|
121
|
-
authKey: getAuthKey(), // X-Auth-Key header
|
|
122
|
-
bearerToken: "your-bearer-token", // Required: Bearer token
|
|
123
|
-
// environment is auto-detected from process.env.ENVIRONMENT
|
|
124
|
-
// apiBaseUrl is auto-set based on environment:
|
|
125
|
-
// - Dev: https://api.dev.tradly.app
|
|
126
|
-
// - Prod: https://api.tradly.app
|
|
127
|
-
});
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
The package will automatically:
|
|
131
|
-
|
|
132
|
-
1. Detect environment from `process.env.ENVIRONMENT` (or you can pass
|
|
133
|
-
`environment: 'dev'` or `'production'`)
|
|
134
|
-
2. Set the correct API base URL (`https://api.dev.tradly.app` for dev,
|
|
135
|
-
`https://api.tradly.app` for prod)
|
|
136
|
-
3. Get S3 signed URLs via API call to `POST /v1/utils/S3signedUploadURL`
|
|
137
|
-
4. Upload files to S3 using the signed URLs
|
|
138
|
-
5. Save media metadata via `POST /v1/media` with `{ media: [...] }` format
|
|
139
|
-
6. Fetch media list via `GET /v1/media?page=1&parent=0&mime_type=...`
|
|
140
|
-
|
|
141
|
-
## Key Differences
|
|
142
|
-
|
|
143
|
-
| Old Component | New Package |
|
|
144
|
-
| --------------------------------------- | -------------------------------- |
|
|
145
|
-
| `isOpenPopup` prop | `isOpen` prop |
|
|
146
|
-
| `setIsOpenPopup` prop | `onClose` callback |
|
|
147
|
-
| `update_data` prop | `onSelect` callback |
|
|
148
|
-
| `current_data` prop | `currentData` prop |
|
|
149
|
-
| Uses `proxy_api_call` directly | Uses `MediaApiService` |
|
|
150
|
-
| Auth key from `getAuthKey()` internally | Auth key passed via `apiService` |
|
|
151
|
-
| Hardcoded API paths | Configurable via `apiService` |
|
|
152
|
-
|
|
153
|
-
## Complete Example
|
|
154
|
-
|
|
155
|
-
Here's a complete example showing how to replace the old component:
|
|
156
|
-
|
|
157
|
-
```jsx
|
|
158
|
-
import React, { useState } from "react";
|
|
159
|
-
import { MediaPopup, MediaApiService } from "@tradly/asset";
|
|
160
|
-
import { getAuthKey } from "constant/functions";
|
|
161
|
-
|
|
162
|
-
function MyMediaSelector() {
|
|
163
|
-
const [isOpen, setIsOpen] = useState(false);
|
|
164
|
-
const [selectedImage, setSelectedImage] = useState(null);
|
|
165
|
-
|
|
166
|
-
// Create API service instance
|
|
167
|
-
// API base URL is automatically detected from ENVIRONMENT
|
|
168
|
-
// All API calls go directly to Tradly API (no proxy needed)
|
|
169
|
-
const apiService = React.useMemo(() => {
|
|
170
|
-
return new MediaApiService({
|
|
171
|
-
authKey: getAuthKey(),
|
|
172
|
-
bearerToken: "your-bearer-token", // Required: Bearer token
|
|
173
|
-
// apiBaseUrl is auto-detected from process.env.ENVIRONMENT
|
|
174
|
-
onError: (error) => {
|
|
175
|
-
console.error("Media API Error:", error);
|
|
176
|
-
// Show error toast, etc.
|
|
177
|
-
},
|
|
178
|
-
});
|
|
179
|
-
}, []);
|
|
180
|
-
|
|
181
|
-
return (
|
|
182
|
-
<div>
|
|
183
|
-
<button onClick={() => setIsOpen(true)}>
|
|
184
|
-
Select Media
|
|
185
|
-
</button>
|
|
186
|
-
|
|
187
|
-
{selectedImage && (
|
|
188
|
-
<img
|
|
189
|
-
src={selectedImage}
|
|
190
|
-
alt="Selected"
|
|
191
|
-
/>
|
|
192
|
-
)}
|
|
193
|
-
|
|
194
|
-
<MediaPopup
|
|
195
|
-
isOpen={isOpen}
|
|
196
|
-
onClose={() => setIsOpen(false)}
|
|
197
|
-
onSelect={(url) => {
|
|
198
|
-
setSelectedImage(url);
|
|
199
|
-
setIsOpen(false);
|
|
200
|
-
}}
|
|
201
|
-
currentData={selectedImage}
|
|
202
|
-
options={["image", "video"]}
|
|
203
|
-
apiService={apiService}
|
|
204
|
-
onError={(error) => {
|
|
205
|
-
console.error("Gallery error:", error);
|
|
206
|
-
}}
|
|
207
|
-
/>
|
|
208
|
-
</div>
|
|
209
|
-
);
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
export default MyMediaSelector;
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
## Testing
|
|
216
|
-
|
|
217
|
-
After migration, test the following:
|
|
218
|
-
|
|
219
|
-
1. ✅ Opening/closing the media gallery
|
|
220
|
-
2. ✅ Uploading new images/videos
|
|
221
|
-
3. ✅ Selecting existing media
|
|
222
|
-
4. ✅ Pagination works correctly
|
|
223
|
-
5. ✅ Error handling works
|
|
224
|
-
6. ✅ Authentication is working
|
|
225
|
-
|
|
226
|
-
## Rollback Plan
|
|
227
|
-
|
|
228
|
-
If you need to rollback:
|
|
229
|
-
|
|
230
|
-
1. Keep the old components in `src/Shared/fields/MediaSections/`
|
|
231
|
-
2. Import from the old location instead of the package
|
|
232
|
-
3. The old components will continue to work as before
|
|
233
|
-
|
|
234
|
-
## Next Steps
|
|
235
|
-
|
|
236
|
-
1. Test the package in a development environment
|
|
237
|
-
2. Gradually migrate components one by one
|
|
238
|
-
3. Once stable, consider removing old components
|
|
239
|
-
4. Optionally publish to npm for use in other projects
|
|
240
|
-
|
|
241
|
-
## Support
|
|
242
|
-
|
|
243
|
-
If you encounter issues during migration:
|
|
244
|
-
|
|
245
|
-
1. Check the `EXAMPLE_USAGE.jsx` file
|
|
246
|
-
2. Review the `README.md` for API documentation
|
|
247
|
-
3. Ensure all peer dependencies are installed
|
|
248
|
-
4. Verify your auth key and API base URL are correct
|
|
249
|
-
|
package/STYLING_GUIDE.md
DELETED
|
@@ -1,219 +0,0 @@
|
|
|
1
|
-
# Styling Guide - Customizing Media Gallery with Tailwind CSS
|
|
2
|
-
|
|
3
|
-
The `@tradly/asset` package supports full customization of all components using
|
|
4
|
-
Tailwind CSS class names. You can customize styles at every level of the
|
|
5
|
-
component hierarchy.
|
|
6
|
-
|
|
7
|
-
## Overview
|
|
8
|
-
|
|
9
|
-
All components accept `className` props that allow you to override default
|
|
10
|
-
styles. The package uses sensible Tailwind defaults, but you can customize
|
|
11
|
-
everything to match your design system.
|
|
12
|
-
|
|
13
|
-
## MediaPopup Styling Props
|
|
14
|
-
|
|
15
|
-
The main popup component supports these styling props:
|
|
16
|
-
|
|
17
|
-
```jsx
|
|
18
|
-
<MediaPopup
|
|
19
|
-
// ... other props
|
|
20
|
-
overlayClassName="..." // Overlay/backdrop styles
|
|
21
|
-
containerClassName="..." // Main popup container
|
|
22
|
-
headerClassName="..." // Header container
|
|
23
|
-
titleClassName="..." // Title text
|
|
24
|
-
closeButtonClassName="..." // Close button
|
|
25
|
-
/>
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
### Example
|
|
29
|
-
|
|
30
|
-
```jsx
|
|
31
|
-
<MediaPopup
|
|
32
|
-
isOpen={isOpen}
|
|
33
|
-
onClose={() => setIsOpen(false)}
|
|
34
|
-
onSelect={handleSelect}
|
|
35
|
-
apiService={apiService}
|
|
36
|
-
overlayClassName="fixed inset-0 bg-black bg-opacity-50 backdrop-blur-sm"
|
|
37
|
-
containerClassName="max-w-4xl bg-gray-900 text-white rounded-xl shadow-2xl"
|
|
38
|
-
titleClassName="text-3xl font-extrabold text-blue-400"
|
|
39
|
-
closeButtonClassName="text-white hover:text-red-400 hover:bg-red-900/20"
|
|
40
|
-
/>
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
## MediaTab Styling Props
|
|
44
|
-
|
|
45
|
-
Customize the tab navigation:
|
|
46
|
-
|
|
47
|
-
```jsx
|
|
48
|
-
<MediaTab
|
|
49
|
-
// ... other props
|
|
50
|
-
className="..." // Tab group container
|
|
51
|
-
tabListClassName="..." // Tab list container
|
|
52
|
-
tabButtonClassName="..." // Base tab button styles
|
|
53
|
-
tabButtonActiveClassName="..." // Active tab button styles
|
|
54
|
-
tabButtonInactiveClassName="..." // Inactive tab button styles
|
|
55
|
-
tabPanelClassName="..." // Tab panel container
|
|
56
|
-
/>
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
### Example
|
|
60
|
-
|
|
61
|
-
```jsx
|
|
62
|
-
<MediaTab
|
|
63
|
-
options={["image", "video"]}
|
|
64
|
-
apiService={apiService}
|
|
65
|
-
tabListClassName="bg-gray-800 border-b-2 border-blue-500"
|
|
66
|
-
tabButtonClassName="text-gray-300 hover:text-white px-6 py-3 transition-all"
|
|
67
|
-
tabButtonActiveClassName="text-blue-400 border-b-4 border-blue-400 font-bold"
|
|
68
|
-
tabButtonInactiveClassName="text-gray-400"
|
|
69
|
-
/>
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
## MediaGallery / VideosGallery Styling Props
|
|
73
|
-
|
|
74
|
-
Customize the media grid and items:
|
|
75
|
-
|
|
76
|
-
```jsx
|
|
77
|
-
<ImagesGallery
|
|
78
|
-
// ... other props
|
|
79
|
-
className="..." // Container
|
|
80
|
-
gridClassName="..." // Grid layout
|
|
81
|
-
imageItemClassName="..." // Individual image item
|
|
82
|
-
paginationContainerClassName="..." // Pagination container
|
|
83
|
-
/>
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
### Example
|
|
87
|
-
|
|
88
|
-
```jsx
|
|
89
|
-
<ImagesGallery
|
|
90
|
-
apiService={apiService}
|
|
91
|
-
gridClassName="grid grid-cols-2 md:grid-cols-4 lg:grid-cols-6 gap-4"
|
|
92
|
-
imageItemClassName="rounded-lg border-2 border-gray-300 hover:border-blue-500 transition-all cursor-pointer transform hover:scale-105"
|
|
93
|
-
paginationContainerClassName="bg-gray-100 p-6 rounded-lg mt-4"
|
|
94
|
-
/>
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
## FileUpload Styling Props
|
|
98
|
-
|
|
99
|
-
Customize the upload button:
|
|
100
|
-
|
|
101
|
-
```jsx
|
|
102
|
-
<FileUpload
|
|
103
|
-
// ... other props
|
|
104
|
-
className="..." // Container
|
|
105
|
-
buttonClassName="..." // Upload button
|
|
106
|
-
iconContainerClassName="..." // Icon container
|
|
107
|
-
titleClassName="..." // Title text
|
|
108
|
-
loadingClassName="..." // Loading state
|
|
109
|
-
/>
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
### Example
|
|
113
|
-
|
|
114
|
-
```jsx
|
|
115
|
-
<FileUpload
|
|
116
|
-
accept="image/*"
|
|
117
|
-
title="Upload Image"
|
|
118
|
-
apiService={apiService}
|
|
119
|
-
buttonClassName="border-2 border-dashed border-blue-500 bg-blue-50 hover:bg-blue-100 rounded-xl p-8"
|
|
120
|
-
iconContainerClassName="bg-blue-500 p-4 rounded-full"
|
|
121
|
-
titleClassName="text-blue-600 font-semibold mt-4"
|
|
122
|
-
loadingClassName="bg-blue-100 border-2 border-blue-300 rounded-xl"
|
|
123
|
-
/>
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
## Pagination Styling Props
|
|
127
|
-
|
|
128
|
-
Customize pagination controls:
|
|
129
|
-
|
|
130
|
-
```jsx
|
|
131
|
-
<Pagination
|
|
132
|
-
// ... other props
|
|
133
|
-
className="..." // Container
|
|
134
|
-
navClassName="..." // Nav element
|
|
135
|
-
previousButtonClassName="..." // Previous button
|
|
136
|
-
nextButtonClassName="..." // Next button
|
|
137
|
-
pageButtonClassName="..." // Page number buttons
|
|
138
|
-
pageButtonActiveClassName="..." // Active page button
|
|
139
|
-
ellipsisClassName="..." // Ellipsis (...)
|
|
140
|
-
/>
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
### Example
|
|
144
|
-
|
|
145
|
-
```jsx
|
|
146
|
-
<Pagination
|
|
147
|
-
nextPage={handlePageChange}
|
|
148
|
-
current_page={currentPage}
|
|
149
|
-
pageCount={totalPages}
|
|
150
|
-
navClassName="flex items-center space-x-2"
|
|
151
|
-
previousButtonClassName="px-4 py-2 bg-gray-200 hover:bg-gray-300 rounded-lg"
|
|
152
|
-
nextButtonClassName="px-4 py-2 bg-gray-200 hover:bg-gray-300 rounded-lg"
|
|
153
|
-
pageButtonClassName="px-4 py-2 bg-white border border-gray-300 hover:bg-gray-100 rounded"
|
|
154
|
-
pageButtonActiveClassName="px-4 py-2 bg-blue-500 text-white font-bold rounded"
|
|
155
|
-
/>
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
## Complete Customization Example
|
|
159
|
-
|
|
160
|
-
Here's a fully customized example:
|
|
161
|
-
|
|
162
|
-
```jsx
|
|
163
|
-
import { MediaPopup, MediaApiService } from "@tradly/asset";
|
|
164
|
-
|
|
165
|
-
function CustomStyledGallery() {
|
|
166
|
-
const apiService = new MediaApiService({
|
|
167
|
-
authKey: "your-key",
|
|
168
|
-
bearerToken: "your-token",
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
return (
|
|
172
|
-
<MediaPopup
|
|
173
|
-
isOpen={isOpen}
|
|
174
|
-
onClose={() => setIsOpen(false)}
|
|
175
|
-
onSelect={handleSelect}
|
|
176
|
-
apiService={apiService}
|
|
177
|
-
// Popup styles
|
|
178
|
-
overlayClassName="fixed inset-0 bg-black/60 backdrop-blur-sm"
|
|
179
|
-
containerClassName="max-w-5xl bg-gradient-to-br from-gray-900 to-gray-800 rounded-2xl shadow-2xl border border-gray-700"
|
|
180
|
-
headerClassName="flex items-center justify-between p-6 border-b border-gray-700"
|
|
181
|
-
titleClassName="text-2xl font-bold text-white"
|
|
182
|
-
closeButtonClassName="text-gray-400 hover:text-white hover:bg-gray-700 rounded-full p-2 transition-all"
|
|
183
|
-
// Tab styles (passed to MediaTab internally)
|
|
184
|
-
tabListClassName="bg-gray-800/50 border-b border-gray-700"
|
|
185
|
-
tabButtonClassName="text-gray-400 hover:text-white px-6 py-4 transition-colors"
|
|
186
|
-
tabButtonActiveClassName="text-blue-400 border-b-2 border-blue-400 font-semibold"
|
|
187
|
-
tabButtonInactiveClassName="text-gray-500"
|
|
188
|
-
// Gallery styles (passed to MediaGallery internally)
|
|
189
|
-
gridClassName="grid grid-cols-3 md:grid-cols-5 gap-4 p-6"
|
|
190
|
-
imageItemClassName="rounded-xl border-2 border-gray-700 hover:border-blue-500 cursor-pointer transition-all hover:scale-105 shadow-lg"
|
|
191
|
-
paginationContainerClassName="bg-gray-800/50 p-4 border-t border-gray-700"
|
|
192
|
-
/>
|
|
193
|
-
);
|
|
194
|
-
}
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
## Styling Tips
|
|
198
|
-
|
|
199
|
-
1. **Use Tailwind's responsive prefixes**: `md:`, `lg:`, etc.
|
|
200
|
-
2. **Combine with your design system**: Use your existing color palette and
|
|
201
|
-
spacing
|
|
202
|
-
3. **Maintain accessibility**: Keep contrast ratios and focus states
|
|
203
|
-
4. **Test hover states**: Ensure interactive elements have clear hover feedback
|
|
204
|
-
5. **Use transitions**: Add `transition-all` or `transition-colors` for smooth
|
|
205
|
-
animations
|
|
206
|
-
|
|
207
|
-
## Default Classes Reference
|
|
208
|
-
|
|
209
|
-
If you want to see the default classes, check the component source files. All
|
|
210
|
-
default classes use Tailwind utility classes and can be completely overridden.
|
|
211
|
-
|
|
212
|
-
## Notes
|
|
213
|
-
|
|
214
|
-
- All className props are optional
|
|
215
|
-
- If not provided, sensible defaults are used
|
|
216
|
-
- You can override individual parts without affecting others
|
|
217
|
-
- Classes are merged/applied using the `||` operator, so your custom classes
|
|
218
|
-
completely replace defaults
|
|
219
|
-
|