@tradly/asset 1.0.0 → 1.0.2
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 +102 -93
- package/MIGRATION_GUIDE.md +109 -96
- package/README.md +116 -108
- package/STYLING_GUIDE.md +109 -100
- package/package.json +2 -4
- package/src/index.js +12 -11
package/EXAMPLE_USAGE.jsx
CHANGED
|
@@ -1,119 +1,128 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Example usage of @tradly/
|
|
2
|
+
* Example usage of @tradly/asset package
|
|
3
3
|
*
|
|
4
4
|
* This shows how to integrate the media gallery package into your existing project
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import React, { useState } from
|
|
8
|
-
import { MediaPopup, MediaApiService } from
|
|
9
|
-
import { getAuthKey } from
|
|
7
|
+
import React, { useState } from "react";
|
|
8
|
+
import { MediaPopup, MediaApiService } from "@tradly/asset";
|
|
9
|
+
import { getAuthKey } from "constant/functions";
|
|
10
10
|
|
|
11
11
|
function ExampleMediaGalleryUsage() {
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
13
|
+
const [selectedMedia, setSelectedMedia] = useState(null);
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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
30
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
const handleSelect = (mediaUrl) => {
|
|
32
|
+
console.log("Selected media:", mediaUrl);
|
|
33
|
+
setSelectedMedia(mediaUrl);
|
|
34
|
+
setIsOpen(false);
|
|
35
|
+
};
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
const handleError = (error) => {
|
|
38
|
+
console.error("Media gallery error:", error);
|
|
39
|
+
// Handle error (show toast, etc.)
|
|
40
|
+
};
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
return (
|
|
43
|
+
<div className="p-4">
|
|
44
|
+
<h2 className="text-2xl font-bold mb-4">
|
|
45
|
+
Media Gallery Example
|
|
46
|
+
</h2>
|
|
45
47
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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>
|
|
54
56
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
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
|
+
)}
|
|
61
69
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
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
|
+
);
|
|
74
82
|
}
|
|
75
83
|
|
|
76
84
|
// Example: Using only images
|
|
77
85
|
function ImageOnlyExample() {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
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
|
+
});
|
|
84
92
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
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
|
+
);
|
|
94
102
|
}
|
|
95
103
|
|
|
96
104
|
// Example: Using individual components
|
|
97
105
|
function CustomGalleryExample() {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
106
|
+
const apiService = new MediaApiService({
|
|
107
|
+
authKey: getAuthKey(),
|
|
108
|
+
bearerToken: "your-bearer-token", // Required
|
|
109
|
+
// apiBaseUrl is auto-detected from ENVIRONMENT
|
|
110
|
+
});
|
|
103
111
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
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
|
+
);
|
|
117
125
|
}
|
|
118
126
|
|
|
119
|
-
export default ExampleMediaGalleryUsage
|
|
127
|
+
export default ExampleMediaGalleryUsage;
|
|
128
|
+
|
package/MIGRATION_GUIDE.md
CHANGED
|
@@ -1,20 +1,22 @@
|
|
|
1
|
-
# Migration Guide: From Existing Media Components to @tradly/
|
|
1
|
+
# Migration Guide: From Existing Media Components to @tradly/asset Package
|
|
2
2
|
|
|
3
3
|
## Overview
|
|
4
4
|
|
|
5
|
-
This guide helps you migrate from the existing media components in
|
|
5
|
+
This guide helps you migrate from the existing media components in
|
|
6
|
+
`src/Shared/fields/MediaSections/` to the new reusable `@tradly/asset` package.
|
|
6
7
|
|
|
7
8
|
## Benefits of Using the Package
|
|
8
9
|
|
|
9
10
|
1. **Reusability**: Use the same media gallery across multiple projects
|
|
10
11
|
2. **Maintainability**: Single source of truth for media gallery functionality
|
|
11
12
|
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
|
|
13
|
+
4. **Separation of Concerns**: Media gallery logic is isolated from your main
|
|
14
|
+
app
|
|
13
15
|
|
|
14
16
|
## Package Structure
|
|
15
17
|
|
|
16
18
|
```
|
|
17
|
-
packages/
|
|
19
|
+
packages/asset/
|
|
18
20
|
├── src/
|
|
19
21
|
│ ├── components/
|
|
20
22
|
│ │ ├── MediaPopup.jsx # Main popup component
|
|
@@ -44,16 +46,16 @@ Since this is a local package, you can either:
|
|
|
44
46
|
```json
|
|
45
47
|
// In your main package.json, add:
|
|
46
48
|
{
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
49
|
+
"dependencies": {
|
|
50
|
+
"@tradly/asset": "file:./packages/asset"
|
|
51
|
+
}
|
|
50
52
|
}
|
|
51
53
|
```
|
|
52
54
|
|
|
53
55
|
**Option B: Publish to npm (later)**
|
|
54
56
|
|
|
55
57
|
```bash
|
|
56
|
-
cd packages/
|
|
58
|
+
cd packages/asset
|
|
57
59
|
npm publish
|
|
58
60
|
```
|
|
59
61
|
|
|
@@ -62,72 +64,75 @@ npm publish
|
|
|
62
64
|
**Before (Old way):**
|
|
63
65
|
|
|
64
66
|
```jsx
|
|
65
|
-
import MediaGallery from
|
|
67
|
+
import MediaGallery from "@/Shared/fields/MediaSections/MediaPopup";
|
|
66
68
|
|
|
67
69
|
function MyComponent() {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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
|
+
);
|
|
79
81
|
}
|
|
80
82
|
```
|
|
81
83
|
|
|
82
84
|
**After (New way):**
|
|
83
85
|
|
|
84
86
|
```jsx
|
|
85
|
-
import { MediaPopup, MediaApiService } from
|
|
86
|
-
import { getAuthKey } from
|
|
87
|
+
import { MediaPopup, MediaApiService } from "@tradly/asset";
|
|
88
|
+
import { getAuthKey } from "constant/functions";
|
|
87
89
|
|
|
88
90
|
function MyComponent() {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
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
|
+
);
|
|
109
111
|
}
|
|
110
112
|
```
|
|
111
113
|
|
|
112
114
|
### Step 3: Configure API Service
|
|
113
115
|
|
|
114
|
-
The package handles all upload logic internally using direct API calls. The API
|
|
116
|
+
The package handles all upload logic internally using direct API calls. The API
|
|
117
|
+
base URL is automatically detected from your environment:
|
|
115
118
|
|
|
116
119
|
```jsx
|
|
117
120
|
const apiService = new MediaApiService({
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
})
|
|
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
|
+
});
|
|
125
128
|
```
|
|
126
129
|
|
|
127
130
|
The package will automatically:
|
|
128
131
|
|
|
129
|
-
1. Detect environment from `process.env.ENVIRONMENT` (or you can pass
|
|
130
|
-
|
|
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)
|
|
131
136
|
3. Get S3 signed URLs via API call to `POST /v1/utils/S3signedUploadURL`
|
|
132
137
|
4. Upload files to S3 using the signed URLs
|
|
133
138
|
5. Save media metadata via `POST /v1/media` with `{ media: [...] }` format
|
|
@@ -150,54 +155,61 @@ The package will automatically:
|
|
|
150
155
|
Here's a complete example showing how to replace the old component:
|
|
151
156
|
|
|
152
157
|
```jsx
|
|
153
|
-
import React, { useState } from
|
|
154
|
-
import { MediaPopup, MediaApiService } from
|
|
155
|
-
import { getAuthKey } from
|
|
158
|
+
import React, { useState } from "react";
|
|
159
|
+
import { MediaPopup, MediaApiService } from "@tradly/asset";
|
|
160
|
+
import { getAuthKey } from "constant/functions";
|
|
156
161
|
|
|
157
162
|
function MyMediaSelector() {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
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
|
+
);
|
|
198
210
|
}
|
|
199
211
|
|
|
200
|
-
export default MyMediaSelector
|
|
212
|
+
export default MyMediaSelector;
|
|
201
213
|
```
|
|
202
214
|
|
|
203
215
|
## Testing
|
|
@@ -234,3 +246,4 @@ If you encounter issues during migration:
|
|
|
234
246
|
2. Review the `README.md` for API documentation
|
|
235
247
|
3. Ensure all peer dependencies are installed
|
|
236
248
|
4. Verify your auth key and API base URL are correct
|
|
249
|
+
|
package/README.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
# @tradly/
|
|
1
|
+
# @tradly/asset
|
|
2
2
|
|
|
3
|
-
A reusable React component package for uploading and selecting media (images,
|
|
3
|
+
A reusable React component package for uploading and selecting media (images,
|
|
4
|
+
videos, files) with Tradly authentication support.
|
|
4
5
|
|
|
5
6
|
## Features
|
|
6
7
|
|
|
@@ -16,9 +17,9 @@ A reusable React component package for uploading and selecting media (images, vi
|
|
|
16
17
|
## Installation
|
|
17
18
|
|
|
18
19
|
```bash
|
|
19
|
-
npm install @tradly/
|
|
20
|
+
npm install @tradly/asset
|
|
20
21
|
# or
|
|
21
|
-
yarn add @tradly/
|
|
22
|
+
yarn add @tradly/asset
|
|
22
23
|
```
|
|
23
24
|
|
|
24
25
|
## Peer Dependencies
|
|
@@ -38,42 +39,44 @@ This package requires the following peer dependencies:
|
|
|
38
39
|
## Basic Usage
|
|
39
40
|
|
|
40
41
|
```jsx
|
|
41
|
-
import React, { useState } from
|
|
42
|
-
import { MediaPopup, MediaApiService } from
|
|
42
|
+
import React, { useState } from "react";
|
|
43
|
+
import { MediaPopup, MediaApiService } from "@tradly/asset";
|
|
43
44
|
|
|
44
45
|
function MyComponent() {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
46
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
47
|
+
const [selectedMedia, setSelectedMedia] = useState(null);
|
|
48
|
+
|
|
49
|
+
// Initialize API service with your auth key
|
|
50
|
+
// API base URL is automatically detected from ENVIRONMENT:
|
|
51
|
+
// - Dev: https://api.dev.tradly.app
|
|
52
|
+
// - Prod: https://api.tradly.app
|
|
53
|
+
const apiService = new MediaApiService({
|
|
54
|
+
authKey: "your-tradly-auth-key", // Required: X-Auth-Key header
|
|
55
|
+
bearerToken: "your-bearer-token", // Required: Bearer token for Authorization header
|
|
56
|
+
// environment is auto-detected from process.env.ENVIRONMENT
|
|
57
|
+
// apiBaseUrl is auto-set based on environment (can be overridden)
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const handleSelect = (mediaUrl) => {
|
|
61
|
+
setSelectedMedia(mediaUrl);
|
|
62
|
+
setIsOpen(false);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
return (
|
|
66
|
+
<>
|
|
67
|
+
<button onClick={() => setIsOpen(true)}>
|
|
68
|
+
Open Media Gallery
|
|
69
|
+
</button>
|
|
70
|
+
|
|
71
|
+
<MediaPopup
|
|
72
|
+
isOpen={isOpen}
|
|
73
|
+
onClose={() => setIsOpen(false)}
|
|
74
|
+
onSelect={handleSelect}
|
|
75
|
+
options={["image", "video"]} // Options: 'image', 'video', 'file'
|
|
76
|
+
apiService={apiService}
|
|
77
|
+
/>
|
|
78
|
+
</>
|
|
79
|
+
);
|
|
77
80
|
}
|
|
78
81
|
```
|
|
79
82
|
|
|
@@ -81,7 +84,8 @@ function MyComponent() {
|
|
|
81
84
|
|
|
82
85
|
### Upload Functionality
|
|
83
86
|
|
|
84
|
-
The package includes complete upload functionality using direct API calls. All
|
|
87
|
+
The package includes complete upload functionality using direct API calls. All
|
|
88
|
+
upload logic is handled internally:
|
|
85
89
|
|
|
86
90
|
1. **Get S3 signed URLs** via API call to `/v1/utils/S3signedUploadURL`
|
|
87
91
|
2. **Upload files to S3** using the signed URLs
|
|
@@ -90,14 +94,14 @@ The package includes complete upload functionality using direct API calls. All u
|
|
|
90
94
|
Configuration:
|
|
91
95
|
|
|
92
96
|
```jsx
|
|
93
|
-
import { MediaApiService } from
|
|
97
|
+
import { MediaApiService } from "@tradly/asset";
|
|
94
98
|
|
|
95
99
|
const apiService = new MediaApiService({
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
})
|
|
100
|
+
authKey: "your-auth-key", // Required: X-Auth-Key header
|
|
101
|
+
bearerToken: "your-bearer-token", // Required: Bearer token for Authorization header
|
|
102
|
+
environment: "dev", // Optional: 'dev' or 'production' (auto-detected from process.env.ENVIRONMENT)
|
|
103
|
+
apiBaseUrl: "https://api.tradly.app", // Optional: Override auto-detected base URL
|
|
104
|
+
});
|
|
101
105
|
```
|
|
102
106
|
|
|
103
107
|
**API Base URL Auto-Detection:**
|
|
@@ -111,21 +115,21 @@ const apiService = new MediaApiService({
|
|
|
111
115
|
You can also use the components individually:
|
|
112
116
|
|
|
113
117
|
```jsx
|
|
114
|
-
import { ImagesGallery, MediaApiService } from
|
|
118
|
+
import { ImagesGallery, MediaApiService } from "@tradly/asset";
|
|
115
119
|
|
|
116
120
|
function CustomGallery() {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
121
|
+
const apiService = new MediaApiService({
|
|
122
|
+
authKey: "your-auth-key",
|
|
123
|
+
baseUrl: "/api",
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
return (
|
|
127
|
+
<ImagesGallery
|
|
128
|
+
update_data={(url) => console.log("Selected:", url)}
|
|
129
|
+
closePopup={() => console.log("Closed")}
|
|
130
|
+
apiService={apiService}
|
|
131
|
+
/>
|
|
132
|
+
);
|
|
129
133
|
}
|
|
130
134
|
```
|
|
131
135
|
|
|
@@ -133,14 +137,14 @@ function CustomGallery() {
|
|
|
133
137
|
|
|
134
138
|
```jsx
|
|
135
139
|
<MediaPopup
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
140
|
+
isOpen={isOpen}
|
|
141
|
+
onClose={() => setIsOpen(false)}
|
|
142
|
+
onSelect={handleSelect}
|
|
143
|
+
apiService={apiService}
|
|
144
|
+
onError={(error) => {
|
|
145
|
+
console.error("Media gallery error:", error);
|
|
146
|
+
// Handle error (show toast, etc.)
|
|
147
|
+
}}
|
|
144
148
|
/>
|
|
145
149
|
```
|
|
146
150
|
|
|
@@ -150,25 +154,25 @@ function CustomGallery() {
|
|
|
150
154
|
|
|
151
155
|
```jsx
|
|
152
156
|
const apiService = new MediaApiService({
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
})
|
|
157
|
+
authKey: "string", // Required: Authentication key for X-Auth-Key header
|
|
158
|
+
bearerToken: "string", // Required: Bearer token for Authorization header
|
|
159
|
+
environment: "string", // Optional: 'dev' or 'production' (auto-detected from process.env.ENVIRONMENT)
|
|
160
|
+
apiBaseUrl: "string", // Optional: Override auto-detected base URL (defaults: https://api.dev.tradly.app for dev, https://api.tradly.app for prod)
|
|
161
|
+
onError: (error) => {}, // Optional: Global error handler
|
|
162
|
+
});
|
|
159
163
|
```
|
|
160
164
|
|
|
161
165
|
### Methods
|
|
162
166
|
|
|
163
167
|
```jsx
|
|
164
168
|
// Update auth key
|
|
165
|
-
apiService.setAuthKey(
|
|
169
|
+
apiService.setAuthKey("new-auth-key");
|
|
166
170
|
|
|
167
171
|
// Update API base URL (used for all API calls)
|
|
168
|
-
apiService.setApiBaseUrl(
|
|
172
|
+
apiService.setApiBaseUrl("https://api.tradly.app");
|
|
169
173
|
|
|
170
174
|
// Set Bearer token
|
|
171
|
-
apiService.setBearerToken(
|
|
175
|
+
apiService.setBearerToken("new-bearer-token");
|
|
172
176
|
```
|
|
173
177
|
|
|
174
178
|
## Props
|
|
@@ -188,25 +192,27 @@ apiService.setBearerToken('new-bearer-token')
|
|
|
188
192
|
|
|
189
193
|
## Styling
|
|
190
194
|
|
|
191
|
-
This package uses Tailwind CSS classes and supports full customization at every
|
|
195
|
+
This package uses Tailwind CSS classes and supports full customization at every
|
|
196
|
+
component level. All components accept `className` props that allow you to
|
|
197
|
+
override default styles.
|
|
192
198
|
|
|
193
199
|
### Quick Customization Example
|
|
194
200
|
|
|
195
201
|
```jsx
|
|
196
202
|
<MediaPopup
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
203
|
+
isOpen={isOpen}
|
|
204
|
+
onClose={() => setIsOpen(false)}
|
|
205
|
+
onSelect={handleSelect}
|
|
206
|
+
apiService={apiService}
|
|
207
|
+
// Customize popup
|
|
208
|
+
overlayClassName="bg-black/60 backdrop-blur-sm"
|
|
209
|
+
containerClassName="max-w-4xl bg-gray-900 rounded-xl"
|
|
210
|
+
titleClassName="text-2xl font-bold text-white"
|
|
211
|
+
// Customize tabs
|
|
212
|
+
tabButtonActiveClassName="text-blue-400 border-b-2 border-blue-400"
|
|
213
|
+
// Customize gallery
|
|
214
|
+
gridClassName="grid grid-cols-4 gap-4"
|
|
215
|
+
imageItemClassName="rounded-lg border-2 hover:border-blue-500"
|
|
210
216
|
/>
|
|
211
217
|
```
|
|
212
218
|
|
|
@@ -228,12 +234,13 @@ This package uses Tailwind CSS classes and supports full customization at every
|
|
|
228
234
|
- `videoItemClassName` - Video item styles
|
|
229
235
|
- `paginationContainerClassName` - Pagination container
|
|
230
236
|
|
|
231
|
-
**Individual Components:**
|
|
232
|
-
|
|
237
|
+
**Individual Components:** You can also style individual components when using
|
|
238
|
+
them separately. See `STYLING_GUIDE.md` for complete documentation.
|
|
233
239
|
|
|
234
240
|
### Full Styling Guide
|
|
235
241
|
|
|
236
|
-
For detailed styling documentation with examples, see
|
|
242
|
+
For detailed styling documentation with examples, see
|
|
243
|
+
[STYLING_GUIDE.md](./STYLING_GUIDE.md).
|
|
237
244
|
|
|
238
245
|
## Examples
|
|
239
246
|
|
|
@@ -241,11 +248,11 @@ For detailed styling documentation with examples, see [STYLING_GUIDE.md](./STYLI
|
|
|
241
248
|
|
|
242
249
|
```jsx
|
|
243
250
|
<MediaPopup
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
251
|
+
isOpen={isOpen}
|
|
252
|
+
onClose={() => setIsOpen(false)}
|
|
253
|
+
onSelect={handleSelect}
|
|
254
|
+
options={["image"]}
|
|
255
|
+
apiService={apiService}
|
|
249
256
|
/>
|
|
250
257
|
```
|
|
251
258
|
|
|
@@ -253,11 +260,11 @@ For detailed styling documentation with examples, see [STYLING_GUIDE.md](./STYLI
|
|
|
253
260
|
|
|
254
261
|
```jsx
|
|
255
262
|
<MediaPopup
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
263
|
+
isOpen={isOpen}
|
|
264
|
+
onClose={() => setIsOpen(false)}
|
|
265
|
+
onSelect={handleSelect}
|
|
266
|
+
options={["video"]}
|
|
267
|
+
apiService={apiService}
|
|
261
268
|
/>
|
|
262
269
|
```
|
|
263
270
|
|
|
@@ -265,11 +272,11 @@ For detailed styling documentation with examples, see [STYLING_GUIDE.md](./STYLI
|
|
|
265
272
|
|
|
266
273
|
```jsx
|
|
267
274
|
<MediaPopup
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
275
|
+
isOpen={isOpen}
|
|
276
|
+
onClose={() => setIsOpen(false)}
|
|
277
|
+
onSelect={handleSelect}
|
|
278
|
+
options={["image", "video", "file"]}
|
|
279
|
+
apiService={apiService}
|
|
273
280
|
/>
|
|
274
281
|
```
|
|
275
282
|
|
|
@@ -278,7 +285,7 @@ For detailed styling documentation with examples, see [STYLING_GUIDE.md](./STYLI
|
|
|
278
285
|
To develop or modify this package:
|
|
279
286
|
|
|
280
287
|
```bash
|
|
281
|
-
cd packages/
|
|
288
|
+
cd packages/asset
|
|
282
289
|
npm install
|
|
283
290
|
npm run dev
|
|
284
291
|
```
|
|
@@ -290,3 +297,4 @@ MIT
|
|
|
290
297
|
## Support
|
|
291
298
|
|
|
292
299
|
For issues and questions, please open an issue on the repository.
|
|
300
|
+
|
package/STYLING_GUIDE.md
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
# Styling Guide - Customizing Media Gallery with Tailwind CSS
|
|
2
2
|
|
|
3
|
-
The `@tradly/
|
|
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.
|
|
4
6
|
|
|
5
7
|
## Overview
|
|
6
8
|
|
|
7
|
-
All components accept `className` props that allow you to override default
|
|
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.
|
|
8
12
|
|
|
9
13
|
## MediaPopup Styling Props
|
|
10
14
|
|
|
@@ -12,12 +16,12 @@ The main popup component supports these styling props:
|
|
|
12
16
|
|
|
13
17
|
```jsx
|
|
14
18
|
<MediaPopup
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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
|
|
21
25
|
/>
|
|
22
26
|
```
|
|
23
27
|
|
|
@@ -25,14 +29,14 @@ The main popup component supports these styling props:
|
|
|
25
29
|
|
|
26
30
|
```jsx
|
|
27
31
|
<MediaPopup
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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"
|
|
36
40
|
/>
|
|
37
41
|
```
|
|
38
42
|
|
|
@@ -42,13 +46,13 @@ Customize the tab navigation:
|
|
|
42
46
|
|
|
43
47
|
```jsx
|
|
44
48
|
<MediaTab
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
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
|
|
52
56
|
/>
|
|
53
57
|
```
|
|
54
58
|
|
|
@@ -56,12 +60,12 @@ Customize the tab navigation:
|
|
|
56
60
|
|
|
57
61
|
```jsx
|
|
58
62
|
<MediaTab
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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"
|
|
65
69
|
/>
|
|
66
70
|
```
|
|
67
71
|
|
|
@@ -71,11 +75,11 @@ Customize the media grid and items:
|
|
|
71
75
|
|
|
72
76
|
```jsx
|
|
73
77
|
<ImagesGallery
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
78
|
+
// ... other props
|
|
79
|
+
className="..." // Container
|
|
80
|
+
gridClassName="..." // Grid layout
|
|
81
|
+
imageItemClassName="..." // Individual image item
|
|
82
|
+
paginationContainerClassName="..." // Pagination container
|
|
79
83
|
/>
|
|
80
84
|
```
|
|
81
85
|
|
|
@@ -83,10 +87,10 @@ Customize the media grid and items:
|
|
|
83
87
|
|
|
84
88
|
```jsx
|
|
85
89
|
<ImagesGallery
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
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"
|
|
90
94
|
/>
|
|
91
95
|
```
|
|
92
96
|
|
|
@@ -96,12 +100,12 @@ Customize the upload button:
|
|
|
96
100
|
|
|
97
101
|
```jsx
|
|
98
102
|
<FileUpload
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
103
|
+
// ... other props
|
|
104
|
+
className="..." // Container
|
|
105
|
+
buttonClassName="..." // Upload button
|
|
106
|
+
iconContainerClassName="..." // Icon container
|
|
107
|
+
titleClassName="..." // Title text
|
|
108
|
+
loadingClassName="..." // Loading state
|
|
105
109
|
/>
|
|
106
110
|
```
|
|
107
111
|
|
|
@@ -109,13 +113,13 @@ Customize the upload button:
|
|
|
109
113
|
|
|
110
114
|
```jsx
|
|
111
115
|
<FileUpload
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
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"
|
|
119
123
|
/>
|
|
120
124
|
```
|
|
121
125
|
|
|
@@ -125,14 +129,14 @@ Customize pagination controls:
|
|
|
125
129
|
|
|
126
130
|
```jsx
|
|
127
131
|
<Pagination
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
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 (...)
|
|
136
140
|
/>
|
|
137
141
|
```
|
|
138
142
|
|
|
@@ -140,14 +144,14 @@ Customize pagination controls:
|
|
|
140
144
|
|
|
141
145
|
```jsx
|
|
142
146
|
<Pagination
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
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"
|
|
151
155
|
/>
|
|
152
156
|
```
|
|
153
157
|
|
|
@@ -156,55 +160,60 @@ Customize pagination controls:
|
|
|
156
160
|
Here's a fully customized example:
|
|
157
161
|
|
|
158
162
|
```jsx
|
|
159
|
-
import { MediaPopup, MediaApiService } from
|
|
163
|
+
import { MediaPopup, MediaApiService } from "@tradly/asset";
|
|
160
164
|
|
|
161
165
|
function CustomStyledGallery() {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
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
|
+
);
|
|
190
194
|
}
|
|
191
195
|
```
|
|
192
196
|
|
|
193
197
|
## Styling Tips
|
|
194
198
|
|
|
195
199
|
1. **Use Tailwind's responsive prefixes**: `md:`, `lg:`, etc.
|
|
196
|
-
2. **Combine with your design system**: Use your existing color palette and
|
|
200
|
+
2. **Combine with your design system**: Use your existing color palette and
|
|
201
|
+
spacing
|
|
197
202
|
3. **Maintain accessibility**: Keep contrast ratios and focus states
|
|
198
203
|
4. **Test hover states**: Ensure interactive elements have clear hover feedback
|
|
199
|
-
5. **Use transitions**: Add `transition-all` or `transition-colors` for smooth
|
|
204
|
+
5. **Use transitions**: Add `transition-all` or `transition-colors` for smooth
|
|
205
|
+
animations
|
|
200
206
|
|
|
201
207
|
## Default Classes Reference
|
|
202
208
|
|
|
203
|
-
If you want to see the default classes, check the component source files. All
|
|
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.
|
|
204
211
|
|
|
205
212
|
## Notes
|
|
206
213
|
|
|
207
214
|
- All className props are optional
|
|
208
215
|
- If not provided, sensible defaults are used
|
|
209
216
|
- You can override individual parts without affecting others
|
|
210
|
-
- Classes are merged/applied using the `||` operator, so your custom classes
|
|
217
|
+
- Classes are merged/applied using the `||` operator, so your custom classes
|
|
218
|
+
completely replace defaults
|
|
219
|
+
|
package/package.json
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tradly/asset",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "A reusable media gallery component for uploading and selecting images, videos, and files with Tradly authentication",
|
|
5
|
-
"main": "
|
|
6
|
-
"module": "dist/index.esm.js",
|
|
7
|
-
"types": "dist/index.d.ts",
|
|
5
|
+
"main": "src/index.js",
|
|
8
6
|
"scripts": {
|
|
9
7
|
"build": "echo 'Build script - configure with your bundler'",
|
|
10
8
|
"dev": "echo 'Dev script - configure with your bundler'"
|
package/src/index.js
CHANGED
|
@@ -1,25 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @tradly/
|
|
2
|
+
* @tradly/asset
|
|
3
3
|
*
|
|
4
4
|
* A reusable media gallery component for uploading and selecting
|
|
5
5
|
* images, videos, and files with Tradly authentication
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import MediaPopup from
|
|
9
|
-
import MediaTab from
|
|
10
|
-
import ImagesGallery from
|
|
11
|
-
import VideosGallery from
|
|
12
|
-
import FileUpload from
|
|
13
|
-
import MediaApiService from
|
|
8
|
+
import MediaPopup from "./components/MediaPopup";
|
|
9
|
+
import MediaTab from "./components/MediaTab";
|
|
10
|
+
import ImagesGallery from "./components/MediaGallery";
|
|
11
|
+
import VideosGallery from "./components/VideosGallery";
|
|
12
|
+
import FileUpload from "./components/FileUpload";
|
|
13
|
+
import MediaApiService from "./services/apiService";
|
|
14
14
|
|
|
15
15
|
// Export main component
|
|
16
|
-
export { MediaPopup }
|
|
16
|
+
export { MediaPopup };
|
|
17
17
|
|
|
18
18
|
// Export sub-components for advanced usage
|
|
19
|
-
export { MediaTab, ImagesGallery, VideosGallery, FileUpload }
|
|
19
|
+
export { MediaTab, ImagesGallery, VideosGallery, FileUpload };
|
|
20
20
|
|
|
21
21
|
// Export API service
|
|
22
|
-
export { MediaApiService }
|
|
22
|
+
export { MediaApiService };
|
|
23
23
|
|
|
24
24
|
// Export default as MediaPopup for convenience
|
|
25
|
-
export default MediaPopup
|
|
25
|
+
export default MediaPopup;
|
|
26
|
+
|