ultra-image-uploader 0.0.1 → 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/README.md +400 -102
- package/dist/components/ImageUploader.d.ts +58 -4
- package/dist/components/ImageUploader.d.ts.map +1 -0
- package/dist/components/ImageUploader.js +203 -13
- package/dist/components/ImageUploader.js.map +1 -0
- package/dist/index.d.ts +10 -3
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -1
- package/dist/index.js.map +1 -0
- package/dist/providers/BaseProvider.d.ts +19 -0
- package/dist/providers/BaseProvider.d.ts.map +1 -0
- package/dist/providers/BaseProvider.js +48 -0
- package/dist/providers/BaseProvider.js.map +1 -0
- package/dist/providers/CloudinaryProvider.d.ts +17 -0
- package/dist/providers/CloudinaryProvider.d.ts.map +1 -0
- package/dist/providers/CloudinaryProvider.js +123 -0
- package/dist/providers/CloudinaryProvider.js.map +1 -0
- package/dist/providers/ImgBBProvider.d.ts +13 -0
- package/dist/providers/ImgBBProvider.d.ts.map +1 -0
- package/dist/providers/ImgBBProvider.js +68 -0
- package/dist/providers/ImgBBProvider.js.map +1 -0
- package/dist/providers/index.d.ts +20 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +36 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/types/index.d.ts +67 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +5 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/imageUpload.d.ts +1 -0
- package/dist/utils/imageUpload.d.ts.map +1 -0
- package/dist/utils/imageUpload.js +1 -0
- package/dist/utils/imageUpload.js.map +1 -0
- package/dist/utils/upload.d.ts +49 -0
- package/dist/utils/upload.d.ts.map +1 -0
- package/dist/utils/upload.js +62 -0
- package/dist/utils/upload.js.map +1 -0
- package/dist/utils/validation.d.ts +11 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +125 -0
- package/dist/utils/validation.js.map +1 -0
- package/package.json +51 -15
- package/src/components/ImageUploader.tsx +0 -115
- package/src/index.ts +0 -4
- package/src/utils/imageUpload.ts +0 -56
- package/tsconfig.json +0 -17
package/README.md
CHANGED
|
@@ -1,26 +1,40 @@
|
|
|
1
1
|
# Ultra Image Uploader
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
<div align="center">
|
|
4
|
+
|
|
5
|
+
A modern, feature-rich React image upload component with support for multiple hosting providers.
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/ultra-image-uploader)
|
|
8
|
+
[](https://opensource.org/licenses/MIT)
|
|
9
|
+
|
|
10
|
+
**Features** • **Multiple Providers** • **Themeable** • **TypeScript** • **Production Ready**
|
|
11
|
+
|
|
12
|
+
</div>
|
|
13
|
+
|
|
14
|
+
---
|
|
4
15
|
|
|
5
16
|
## Features
|
|
6
17
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
18
|
+
- **Multiple Provider Support** - Built-in support for ImgBB and Cloudinary
|
|
19
|
+
- **Drag & Drop** - Intuitive drag and drop interface
|
|
20
|
+
- **Upload Progress** - Real-time upload progress tracking
|
|
21
|
+
- **File Validation** - Comprehensive file type, size, and dimension validation
|
|
22
|
+
- **Theme System** - 5 built-in themes + custom theme support
|
|
23
|
+
- **Auto Upload** - Optional automatic upload on file selection
|
|
24
|
+
- **Image Preview** - Instant preview with file size display
|
|
25
|
+
- **Error Handling** - Graceful error handling with user feedback
|
|
26
|
+
- **TypeScript** - Fully typed for excellent developer experience
|
|
27
|
+
- **Customizable** - Highly customizable styling and behavior
|
|
28
|
+
- **Tree Shakeable** - Optimized bundle size
|
|
15
29
|
|
|
16
30
|
## Installation
|
|
17
31
|
|
|
18
32
|
```bash
|
|
19
|
-
npm install ultra-image-
|
|
33
|
+
npm install ultra-image-uploader
|
|
20
34
|
# or
|
|
21
|
-
yarn add ultra-image-
|
|
35
|
+
yarn add ultra-image-uploader
|
|
22
36
|
# or
|
|
23
|
-
pnpm add ultra-image-
|
|
37
|
+
pnpm add ultra-image-uploader
|
|
24
38
|
```
|
|
25
39
|
|
|
26
40
|
## Quick Start
|
|
@@ -28,7 +42,7 @@ pnpm add ultra-image-uploaderer
|
|
|
28
42
|
### Basic Usage
|
|
29
43
|
|
|
30
44
|
```tsx
|
|
31
|
-
import { ImageUploader
|
|
45
|
+
import { ImageUploader } from "ultra-image-uploader";
|
|
32
46
|
import { useState } from "react";
|
|
33
47
|
|
|
34
48
|
function App() {
|
|
@@ -38,164 +52,448 @@ function App() {
|
|
|
38
52
|
<ImageUploader
|
|
39
53
|
images={images}
|
|
40
54
|
setImages={setImages}
|
|
41
|
-
mode="add"
|
|
42
55
|
multiple={true}
|
|
56
|
+
theme="light"
|
|
43
57
|
/>
|
|
44
58
|
);
|
|
45
59
|
}
|
|
46
60
|
```
|
|
47
61
|
|
|
48
|
-
### With ImgBB
|
|
62
|
+
### With ImgBB Upload
|
|
49
63
|
|
|
50
64
|
```tsx
|
|
51
|
-
import { ImageUploader,
|
|
65
|
+
import { ImageUploader, uploadImagesToImageBB } from "ultra-image-uploader";
|
|
52
66
|
import { useState } from "react";
|
|
53
67
|
|
|
54
68
|
function ImageUploadForm() {
|
|
55
69
|
const [images, setImages] = useState<File[]>([]);
|
|
70
|
+
const [uploadedUrls, setUploadedUrls] = useState<string[]>([]);
|
|
71
|
+
const [loading, setLoading] = useState(false);
|
|
56
72
|
|
|
57
|
-
const
|
|
73
|
+
const handleUpload = async () => {
|
|
74
|
+
setLoading(true);
|
|
58
75
|
try {
|
|
59
|
-
const
|
|
60
|
-
|
|
76
|
+
const result = await uploadImagesToImageBB(
|
|
77
|
+
images,
|
|
78
|
+
"your-imgbb-api-key-here"
|
|
79
|
+
);
|
|
80
|
+
setUploadedUrls(result.urls);
|
|
81
|
+
console.log("Uploaded URLs:", result.urls);
|
|
61
82
|
} catch (error) {
|
|
62
|
-
console.error("
|
|
83
|
+
console.error("Error uploading images:", error);
|
|
84
|
+
} finally {
|
|
85
|
+
setLoading(false);
|
|
63
86
|
}
|
|
64
87
|
};
|
|
65
88
|
|
|
66
89
|
return (
|
|
67
|
-
<
|
|
90
|
+
<div>
|
|
68
91
|
<ImageUploader
|
|
69
92
|
images={images}
|
|
70
93
|
setImages={setImages}
|
|
71
|
-
mode="add"
|
|
72
94
|
multiple={true}
|
|
95
|
+
theme="modern"
|
|
73
96
|
/>
|
|
74
|
-
<button
|
|
75
|
-
|
|
97
|
+
<button
|
|
98
|
+
onClick={handleUpload}
|
|
99
|
+
disabled={loading || images.length === 0}
|
|
100
|
+
className="bg-blue-500 text-white px-4 py-2 rounded disabled:opacity-50"
|
|
101
|
+
>
|
|
102
|
+
{loading ? "Uploading..." : "Upload to ImgBB"}
|
|
103
|
+
</button>
|
|
104
|
+
|
|
105
|
+
{uploadedUrls.length > 0 && (
|
|
106
|
+
<div>
|
|
107
|
+
<h3>Uploaded Images:</h3>
|
|
108
|
+
{uploadedUrls.map((url) => (
|
|
109
|
+
<img key={url} src={url} alt="Uploaded" />
|
|
110
|
+
))}
|
|
111
|
+
</div>
|
|
112
|
+
)}
|
|
113
|
+
</div>
|
|
76
114
|
);
|
|
77
115
|
}
|
|
78
116
|
```
|
|
79
117
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
| Prop | Type | Default | Description |
|
|
83
|
-
| ----------------------- | ------------------------------------- | ----------------------------- | -------------------------------- |
|
|
84
|
-
| `images` | `File[]` | Required | Array of selected image files |
|
|
85
|
-
| `setImages` | `(images: File[]) => void` | Required | Function to update images array |
|
|
86
|
-
| `mode` | `"add" \| "update"` | Required | Mode of operation |
|
|
87
|
-
| `defaultImages` | `string[]` | `[]` | Array of existing image URLs |
|
|
88
|
-
| `multiple` | `boolean` | `false` | Allow multiple file selection |
|
|
89
|
-
| `maxFileSize` | `number` | `5242880` | Maximum file size in bytes (5MB) |
|
|
90
|
-
| `allowedFileTypes` | `string[]` | `["image/jpeg", "image/png"]` | Allowed MIME types |
|
|
91
|
-
| `containerClassName` | `string` | `""` | Custom container class |
|
|
92
|
-
| `uploadBoxClassName` | `string` | `""` | Custom upload box class |
|
|
93
|
-
| `imageClassName` | `string` | `""` | Custom image preview class |
|
|
94
|
-
| `uploadBoxStyle` | `React.CSSProperties` | `{}` | Custom upload box styles |
|
|
95
|
-
| `imageStyle` | `React.CSSProperties` | `{}` | Custom image preview styles |
|
|
96
|
-
| `uploadIcon` | `React.ReactNode` | `<UploadCloudIcon />` | Custom upload icon |
|
|
97
|
-
| `deleteIcon` | `React.ReactNode` | `<TrashIcon />` | Custom delete icon |
|
|
98
|
-
| `uploadText` | `string` | `"Choose files to upload"` | Upload box text |
|
|
99
|
-
| `dragAndDropText` | `string` | `"Drag and drop files here"` | Drag and drop text |
|
|
100
|
-
| `fileTypeText` | `string` | `"PNG, JPG, or JPEG files"` | File type info text |
|
|
101
|
-
| `onUpload` | `(files: File[]) => void` | - | Upload callback |
|
|
102
|
-
| `onRemove` | `(file: File, index: number) => void` | - | Remove callback |
|
|
103
|
-
| `onFileValidationError` | `(error: string) => void` | - | Validation error callback |
|
|
104
|
-
|
|
105
|
-
## Usage Examples
|
|
106
|
-
|
|
107
|
-
### Add Mode (New Upload)
|
|
118
|
+
### With Cloudinary
|
|
108
119
|
|
|
109
120
|
```tsx
|
|
110
|
-
import { ImageUploader,
|
|
121
|
+
import { ImageUploader, uploadImagesToCloudinary } from "ultra-image-uploader";
|
|
122
|
+
import { useState } from "react";
|
|
111
123
|
|
|
112
|
-
function
|
|
124
|
+
function CloudinaryUpload() {
|
|
113
125
|
const [images, setImages] = useState<File[]>([]);
|
|
126
|
+
const [loading, setLoading] = useState(false);
|
|
114
127
|
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
|
|
128
|
+
const handleUpload = async () => {
|
|
129
|
+
setLoading(true);
|
|
130
|
+
try {
|
|
131
|
+
const results = await uploadImagesToCloudinary(
|
|
132
|
+
images,
|
|
133
|
+
{
|
|
134
|
+
cloudName: "your-cloud-name",
|
|
135
|
+
uploadPreset: "your-upload-preset", // for unsigned uploads
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
onProgress: (progress) => {
|
|
139
|
+
console.log(`Upload: ${progress.percentage}%`);
|
|
140
|
+
},
|
|
141
|
+
transformOptions: {
|
|
142
|
+
width: 800,
|
|
143
|
+
height: 600,
|
|
144
|
+
crop: "limit",
|
|
145
|
+
quality: 80,
|
|
146
|
+
},
|
|
147
|
+
}
|
|
148
|
+
);
|
|
149
|
+
console.log("Uploaded:", results);
|
|
150
|
+
} catch (error) {
|
|
151
|
+
console.error("Error:", error);
|
|
152
|
+
} finally {
|
|
153
|
+
setLoading(false);
|
|
154
|
+
}
|
|
118
155
|
};
|
|
119
156
|
|
|
120
157
|
return (
|
|
121
|
-
<
|
|
158
|
+
<div>
|
|
122
159
|
<ImageUploader
|
|
123
160
|
images={images}
|
|
124
161
|
setImages={setImages}
|
|
125
|
-
mode="add"
|
|
126
162
|
multiple={true}
|
|
127
|
-
|
|
128
|
-
imageClassName="w-20 h-20"
|
|
163
|
+
theme="dark"
|
|
129
164
|
/>
|
|
130
|
-
<button
|
|
131
|
-
|
|
165
|
+
<button onClick={handleUpload} disabled={loading}>
|
|
166
|
+
Upload to Cloudinary
|
|
167
|
+
</button>
|
|
168
|
+
</div>
|
|
132
169
|
);
|
|
133
170
|
}
|
|
134
171
|
```
|
|
135
172
|
|
|
136
|
-
###
|
|
173
|
+
### Auto Upload Mode
|
|
137
174
|
|
|
138
175
|
```tsx
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
const existingImages = ["https://example.com/image1.jpg"];
|
|
176
|
+
import { ImageUploader } from "ultra-image-uploader";
|
|
177
|
+
import { useState } from "react";
|
|
142
178
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
};
|
|
179
|
+
function AutoUploadExample() {
|
|
180
|
+
const [images, setImages] = useState<File[]>([]);
|
|
181
|
+
const [uploadedUrls, setUploadedUrls] = useState<string[]>([]);
|
|
147
182
|
|
|
148
183
|
return (
|
|
149
|
-
<
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
184
|
+
<ImageUploader
|
|
185
|
+
images={images}
|
|
186
|
+
setImages={setImages}
|
|
187
|
+
multiple={true}
|
|
188
|
+
autoUpload={true}
|
|
189
|
+
uploadConfig={{
|
|
190
|
+
provider: "imgbb",
|
|
191
|
+
config: { apiKey: "your-api-key" },
|
|
192
|
+
}}
|
|
193
|
+
onUploadComplete={(urls) => {
|
|
194
|
+
setUploadedUrls(urls);
|
|
195
|
+
console.log("All uploads complete!", urls);
|
|
196
|
+
}}
|
|
197
|
+
onUploadError={(error) => {
|
|
198
|
+
console.error("Upload failed:", error);
|
|
199
|
+
}}
|
|
200
|
+
theme="colorful"
|
|
201
|
+
/>
|
|
161
202
|
);
|
|
162
203
|
}
|
|
163
204
|
```
|
|
164
205
|
|
|
165
|
-
##
|
|
206
|
+
## Theming
|
|
207
|
+
|
|
208
|
+
### Built-in Themes
|
|
209
|
+
|
|
210
|
+
The component comes with 5 beautiful themes:
|
|
211
|
+
|
|
212
|
+
- **`light`** - Clean and modern light theme
|
|
213
|
+
- **`dark`** - Sleek dark theme
|
|
214
|
+
- **`modern`** - Purple-themed modern design
|
|
215
|
+
- **`minimal`** - Minimalist black and white
|
|
216
|
+
- **`colorful`** - Warm amber/yellow theme
|
|
217
|
+
|
|
218
|
+
```tsx
|
|
219
|
+
<ImageUploader images={images} setImages={setImages} theme="dark" />
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Custom Theme
|
|
166
223
|
|
|
167
|
-
|
|
224
|
+
Create your own theme with full customization:
|
|
168
225
|
|
|
169
226
|
```tsx
|
|
227
|
+
import { ImageUploader, type UploaderTheme } from "ultra-image-uploader";
|
|
228
|
+
|
|
229
|
+
const customTheme: UploaderTheme = {
|
|
230
|
+
primary: "#ff6b6b",
|
|
231
|
+
primaryHover: "#ee5a5a",
|
|
232
|
+
background: "#f7f7f7",
|
|
233
|
+
border: "#ddd",
|
|
234
|
+
text: "#333",
|
|
235
|
+
textSecondary: "#666",
|
|
236
|
+
error: "#e74c3c",
|
|
237
|
+
success: "#2ecc71",
|
|
238
|
+
radius: "8px",
|
|
239
|
+
};
|
|
240
|
+
|
|
170
241
|
<ImageUploader
|
|
171
242
|
images={images}
|
|
172
243
|
setImages={setImages}
|
|
173
|
-
|
|
174
|
-
containerClassName="max-w-2xl mx-auto"
|
|
175
|
-
uploadBoxClassName="border-2 border-dashed border-blue-500 rounded-lg"
|
|
176
|
-
imageClassName="rounded-lg shadow-md"
|
|
244
|
+
customTheme={customTheme}
|
|
177
245
|
/>
|
|
178
246
|
```
|
|
179
247
|
|
|
180
|
-
##
|
|
248
|
+
## Component Props
|
|
249
|
+
|
|
250
|
+
| Prop | Type | Default | Description |
|
|
251
|
+
|------|------|---------|-------------|
|
|
252
|
+
| `images` | `File[]` | **Required** | Array of selected image files |
|
|
253
|
+
| `setImages` | `(files: File[]) => void` | **Required** | Function to update images array |
|
|
254
|
+
| `mode` | `'add' \| 'update'` | `'add'` | Component operation mode |
|
|
255
|
+
| `defaultImages` | `string[]` | `[]` | Existing image URLs for update mode |
|
|
256
|
+
| `multiple` | `boolean` | `false` | Allow multiple file selection |
|
|
257
|
+
| `theme` | `ThemePreset` | `'light'` | Built-in theme to use |
|
|
258
|
+
| `customTheme` | `UploaderTheme` | `undefined` | Custom theme configuration |
|
|
259
|
+
| `uploadText` | `string` | `'Drop images here...'` | Upload area text |
|
|
260
|
+
| `typeText` | `string` | `'PNG, JPG,...'` | File type hint text |
|
|
261
|
+
| `maxSize` | `number` | `10485760` | Max file size in bytes (10MB) |
|
|
262
|
+
| `allowedTypes` | `string[]` | `['image/jpeg', ...]` | Allowed MIME types |
|
|
263
|
+
| `showFileSize` | `boolean` | `true` | Show file size on preview |
|
|
264
|
+
| `dragAndDrop` | `boolean` | `true` | Enable drag and drop |
|
|
265
|
+
| `previewWidth` | `number` | `150` | Preview image width in px |
|
|
266
|
+
| `previewHeight` | `number` | `150` | Preview image height in px |
|
|
267
|
+
| `className` | `string` | `''` | Additional CSS classes |
|
|
268
|
+
| `autoUpload` | `boolean` | `false` | Auto-upload on file selection |
|
|
269
|
+
| `uploadConfig` | `{ provider, config }` | `undefined` | Upload configuration |
|
|
270
|
+
| `onUploadComplete` | `(urls: string[]) => void` | `undefined` | Callback on upload success |
|
|
271
|
+
| `onUploadError` | `(error: Error) => void` | `undefined` | Callback on upload error |
|
|
272
|
+
|
|
273
|
+
## Upload Providers
|
|
274
|
+
|
|
275
|
+
### ImgBB
|
|
276
|
+
|
|
277
|
+
Free image hosting with simple API:
|
|
278
|
+
|
|
279
|
+
```tsx
|
|
280
|
+
import { uploadImagesToImageBB } from "ultra-image-uploader";
|
|
281
|
+
|
|
282
|
+
const result = await uploadImagesToImageBB(
|
|
283
|
+
images,
|
|
284
|
+
"your-imgbb-api-key"
|
|
285
|
+
);
|
|
286
|
+
console.log(result.urls);
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
**Get API Key:** [imgbb.com/settings/api](https://imgbb.com/settings/api)
|
|
181
290
|
|
|
182
|
-
|
|
291
|
+
### Cloudinary
|
|
183
292
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
293
|
+
Enterprise-grade image hosting with transformations:
|
|
294
|
+
|
|
295
|
+
```tsx
|
|
296
|
+
import { uploadImagesToCloudinary } from "ultra-image-uploader";
|
|
297
|
+
|
|
298
|
+
const results = await uploadImagesToCloudinary(
|
|
299
|
+
images,
|
|
300
|
+
{
|
|
301
|
+
cloudName: "your-cloud-name",
|
|
302
|
+
uploadPreset: "your-upload-preset", // optional
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
onProgress: (progress) => console.log(progress.percentage),
|
|
306
|
+
transformOptions: {
|
|
307
|
+
width: 800,
|
|
308
|
+
height: 600,
|
|
309
|
+
quality: 85,
|
|
310
|
+
crop: "limit",
|
|
311
|
+
},
|
|
191
312
|
}
|
|
192
|
-
|
|
313
|
+
);
|
|
193
314
|
```
|
|
194
315
|
|
|
316
|
+
**Get Credentials:**
|
|
317
|
+
1. Sign up at [cloudinary.com](https://cloudinary.com)
|
|
318
|
+
2. Get your cloud name from dashboard
|
|
319
|
+
3. Create an upload preset (Settings → Upload → Upload presets)
|
|
320
|
+
|
|
321
|
+
## Advanced Usage
|
|
322
|
+
|
|
323
|
+
### Custom Provider
|
|
324
|
+
|
|
325
|
+
You can create custom upload providers:
|
|
326
|
+
|
|
327
|
+
```tsx
|
|
328
|
+
import { BaseImageProvider } from "ultra-image-uploader";
|
|
329
|
+
|
|
330
|
+
class CustomProvider extends BaseImageProvider {
|
|
331
|
+
name = 'custom' as const;
|
|
332
|
+
|
|
333
|
+
async upload(file: File, config: ProviderConfig) {
|
|
334
|
+
// Your upload logic here
|
|
335
|
+
return {
|
|
336
|
+
url: "https://...",
|
|
337
|
+
provider: "custom",
|
|
338
|
+
originalFile: file,
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
async uploadMultiple(files: File[], config: ProviderConfig) {
|
|
343
|
+
return Promise.all(files.map(f => this.upload(f, config)));
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// Register and use
|
|
348
|
+
import { providerRegistry } from "ultra-image-uploader";
|
|
349
|
+
providerRegistry.register(new CustomProvider());
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
### File Validation
|
|
353
|
+
|
|
354
|
+
```tsx
|
|
355
|
+
import {
|
|
356
|
+
validateImageFile,
|
|
357
|
+
validateFileComplete,
|
|
358
|
+
formatFileSize,
|
|
359
|
+
} from "ultra-image-uploader";
|
|
360
|
+
|
|
361
|
+
// Quick validation
|
|
362
|
+
const validation = validateImageFile(file, {
|
|
363
|
+
maxSize: 5 * 1024 * 1024, // 5MB
|
|
364
|
+
allowedTypes: ["image/jpeg", "image/png"],
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
if (!validation.valid) {
|
|
368
|
+
console.error("Errors:", validation.errors);
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// Complete validation (with dimensions)
|
|
372
|
+
const completeValidation = await validateFileComplete(file, {
|
|
373
|
+
maxSize: 10 * 1024 * 1024,
|
|
374
|
+
minWidth: 800,
|
|
375
|
+
maxWidth: 4000,
|
|
376
|
+
minHeight: 600,
|
|
377
|
+
maxHeight: 3000,
|
|
378
|
+
});
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
### Transforming Cloudinary Images
|
|
382
|
+
|
|
383
|
+
Generate transformed URLs for existing Cloudinary images:
|
|
384
|
+
|
|
385
|
+
```tsx
|
|
386
|
+
import { CloudinaryProvider } from "ultra-image-uploader";
|
|
387
|
+
|
|
388
|
+
const transformedUrl = CloudinaryProvider.generateTransformedUrl(
|
|
389
|
+
"https://res.cloudinary.com/.../image.jpg",
|
|
390
|
+
{
|
|
391
|
+
width: 400,
|
|
392
|
+
height: 300,
|
|
393
|
+
crop: "fill",
|
|
394
|
+
quality: 80,
|
|
395
|
+
format: "webp",
|
|
396
|
+
}
|
|
397
|
+
);
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
## TypeScript Support
|
|
401
|
+
|
|
402
|
+
The package is fully typed. Import types as needed:
|
|
403
|
+
|
|
404
|
+
```tsx
|
|
405
|
+
import type {
|
|
406
|
+
UploadProvider,
|
|
407
|
+
UploadResult,
|
|
408
|
+
ProviderConfig,
|
|
409
|
+
UploadOptions,
|
|
410
|
+
ImageUploaderProps,
|
|
411
|
+
UploaderTheme,
|
|
412
|
+
ValidationResult,
|
|
413
|
+
FileValidationOptions,
|
|
414
|
+
} from "ultra-image-uploader";
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
## Examples
|
|
418
|
+
|
|
419
|
+
### E-commerce Product Image Upload
|
|
420
|
+
|
|
421
|
+
```tsx
|
|
422
|
+
function ProductImageUpload() {
|
|
423
|
+
const [images, setImages] = useState<File[]>([]);
|
|
424
|
+
const [existingImages, setExistingImages] = useState<string[]>([
|
|
425
|
+
"https://example.com/product1.jpg",
|
|
426
|
+
]);
|
|
427
|
+
|
|
428
|
+
return (
|
|
429
|
+
<ImageUploader
|
|
430
|
+
images={images}
|
|
431
|
+
setImages={setImages}
|
|
432
|
+
mode="update"
|
|
433
|
+
defaultImages={existingImages}
|
|
434
|
+
multiple={true}
|
|
435
|
+
maxSize={5 * 1024 * 1024} // 5MB
|
|
436
|
+
allowedTypes={["image/jpeg", "image/webp"]}
|
|
437
|
+
theme="modern"
|
|
438
|
+
previewWidth={200}
|
|
439
|
+
previewHeight={200}
|
|
440
|
+
/>
|
|
441
|
+
);
|
|
442
|
+
}
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
### Profile Picture Upload
|
|
446
|
+
|
|
447
|
+
```tsx
|
|
448
|
+
function ProfilePicUpload() {
|
|
449
|
+
const [avatar, setAvatar] = useState<File[]>([]);
|
|
450
|
+
|
|
451
|
+
return (
|
|
452
|
+
<ImageUploader
|
|
453
|
+
images={avatar}
|
|
454
|
+
setImages={setAvatar}
|
|
455
|
+
multiple={false}
|
|
456
|
+
maxSize={2 * 1024 * 1024} // 2MB
|
|
457
|
+
previewWidth={180}
|
|
458
|
+
previewHeight={180}
|
|
459
|
+
theme="minimal"
|
|
460
|
+
/>
|
|
461
|
+
);
|
|
462
|
+
}
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
## Migration from v0.0.x
|
|
466
|
+
|
|
467
|
+
If you're upgrading from version 0.0.x, the API is backward compatible:
|
|
468
|
+
|
|
469
|
+
```tsx
|
|
470
|
+
// Old API still works
|
|
471
|
+
import { uploadImagesToImageBB } from "ultra-image-uploader";
|
|
472
|
+
const { urls } = await uploadImagesToImageBB(images, apiKey);
|
|
473
|
+
|
|
474
|
+
// But you can now use the new provider-agnostic API
|
|
475
|
+
import { uploadImages } from "ultra-image-uploader";
|
|
476
|
+
const results = await uploadImages(images, "imgbb", { apiKey });
|
|
477
|
+
const urls = results.map(r => r.url);
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
## Browser Support
|
|
481
|
+
|
|
482
|
+
- Chrome/Edge (latest)
|
|
483
|
+
- Firefox (latest)
|
|
484
|
+
- Safari (latest)
|
|
485
|
+
- Mobile browsers
|
|
486
|
+
|
|
195
487
|
## License
|
|
196
488
|
|
|
197
|
-
MIT
|
|
489
|
+
MIT © Digontha Das
|
|
490
|
+
|
|
491
|
+
## Support & Contributing
|
|
492
|
+
|
|
493
|
+
- **Issues:** [GitHub Issues](https://github.com/digontha/ultra-image-uploader/issues)
|
|
494
|
+
- **Contributing:** Pull requests are welcome!
|
|
495
|
+
- **Discussions:** Ask questions and share ideas
|
|
198
496
|
|
|
199
|
-
|
|
497
|
+
---
|
|
200
498
|
|
|
201
|
-
|
|
499
|
+
Made with ❤️ by [Digontha Das](https://github.com/digontha)
|
|
@@ -1,12 +1,66 @@
|
|
|
1
|
+
import type { UploadProvider, ProviderConfig } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Theme configuration for the uploader
|
|
4
|
+
*/
|
|
5
|
+
export interface UploaderTheme {
|
|
6
|
+
primary?: string;
|
|
7
|
+
primaryHover?: string;
|
|
8
|
+
background?: string;
|
|
9
|
+
border?: string;
|
|
10
|
+
text?: string;
|
|
11
|
+
textSecondary?: string;
|
|
12
|
+
error?: string;
|
|
13
|
+
success?: string;
|
|
14
|
+
radius?: string;
|
|
15
|
+
}
|
|
16
|
+
export type ThemePreset = 'light' | 'dark' | 'modern' | 'minimal' | 'colorful';
|
|
17
|
+
/**
|
|
18
|
+
* Props for the ImageUploader component
|
|
19
|
+
*/
|
|
1
20
|
export interface ImageUploaderProps {
|
|
21
|
+
/** Currently selected image files */
|
|
2
22
|
images: File[];
|
|
23
|
+
/** Function to update the images array */
|
|
3
24
|
setImages: (images: File[]) => void;
|
|
4
|
-
|
|
25
|
+
/** Operation mode */
|
|
26
|
+
mode?: 'add' | 'update';
|
|
27
|
+
/** Existing image URLs for update mode */
|
|
5
28
|
defaultImages?: string[];
|
|
29
|
+
/** Allow multiple file selection */
|
|
6
30
|
multiple?: boolean;
|
|
7
|
-
|
|
8
|
-
|
|
31
|
+
/** Custom CSS classes */
|
|
32
|
+
className?: string;
|
|
33
|
+
/** Upload area text */
|
|
9
34
|
uploadText?: string;
|
|
35
|
+
/** File type hint text */
|
|
10
36
|
typeText?: string;
|
|
37
|
+
/** Maximum file size in bytes */
|
|
38
|
+
maxSize?: number;
|
|
39
|
+
/** Allowed file types */
|
|
40
|
+
allowedTypes?: string[];
|
|
41
|
+
/** Theme preset */
|
|
42
|
+
theme?: ThemePreset;
|
|
43
|
+
/** Custom theme object */
|
|
44
|
+
customTheme?: UploaderTheme;
|
|
45
|
+
/** Show file size preview */
|
|
46
|
+
showFileSize?: boolean;
|
|
47
|
+
/** Enable drag and drop */
|
|
48
|
+
dragAndDrop?: boolean;
|
|
49
|
+
/** Image preview width */
|
|
50
|
+
previewWidth?: number;
|
|
51
|
+
/** Image preview height */
|
|
52
|
+
previewHeight?: number;
|
|
53
|
+
/** Callback when upload completes */
|
|
54
|
+
onUploadComplete?: (urls: string[]) => void;
|
|
55
|
+
/** Callback when upload fails */
|
|
56
|
+
onUploadError?: (error: Error) => void;
|
|
57
|
+
/** Auto upload on file selection */
|
|
58
|
+
autoUpload?: boolean;
|
|
59
|
+
/** Upload provider configuration */
|
|
60
|
+
uploadConfig?: {
|
|
61
|
+
provider: UploadProvider;
|
|
62
|
+
config: ProviderConfig;
|
|
63
|
+
};
|
|
11
64
|
}
|
|
12
|
-
export declare function ImageUploader({ images, setImages, mode, defaultImages, multiple,
|
|
65
|
+
export declare function ImageUploader({ images, setImages, mode, defaultImages, multiple, className, uploadText, typeText, maxSize, allowedTypes, theme, customTheme, showFileSize, dragAndDrop, previewWidth, previewHeight, onUploadComplete, onUploadError, autoUpload, uploadConfig, }: ImageUploaderProps): import("react/jsx-runtime").JSX.Element;
|
|
66
|
+
//# sourceMappingURL=ImageUploader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ImageUploader.d.ts","sourceRoot":"","sources":["../../src/components/ImageUploader.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAI/D;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,UAAU,CAAC;AA4D/E;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,qCAAqC;IACrC,MAAM,EAAE,IAAI,EAAE,CAAC;IACf,0CAA0C;IAC1C,SAAS,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;IACpC,qBAAqB;IACrB,IAAI,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC;IACxB,0CAA0C;IAC1C,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,oCAAoC;IACpC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,yBAAyB;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uBAAuB;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0BAA0B;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iCAAiC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yBAAyB;IACzB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,mBAAmB;IACnB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,0BAA0B;IAC1B,WAAW,CAAC,EAAE,aAAa,CAAC;IAC5B,6BAA6B;IAC7B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,2BAA2B;IAC3B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,0BAA0B;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,2BAA2B;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,qCAAqC;IACrC,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IAC5C,iCAAiC;IACjC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACvC,oCAAoC;IACpC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,oCAAoC;IACpC,YAAY,CAAC,EAAE;QACb,QAAQ,EAAE,cAAc,CAAC;QACzB,MAAM,EAAE,cAAc,CAAC;KACxB,CAAC;CACH;AAUD,wBAAgB,aAAa,CAAC,EAC5B,MAAM,EACN,SAAS,EACT,IAAY,EACZ,aAAkB,EAClB,QAAgB,EAChB,SAAc,EACd,UAAkD,EAClD,QAAiD,EACjD,OAA0B,EAC1B,YAAkF,EAClF,KAAe,EACf,WAAW,EACX,YAAmB,EACnB,WAAkB,EAClB,YAAkB,EAClB,aAAmB,EACnB,gBAAgB,EAChB,aAAa,EACb,UAAkB,EAClB,YAAY,GACb,EAAE,kBAAkB,2CAkVpB"}
|