img-upload-kit 1.1.1 → 2.0.1

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.
Files changed (111) hide show
  1. package/CHANGELOG.md +89 -74
  2. package/MIGRATION.md +192 -0
  3. package/README.md +243 -259
  4. package/dist/bin.js +1186 -0
  5. package/dist/bin.js.map +1 -0
  6. package/dist/blur.cjs +40 -412
  7. package/dist/blur.cjs.map +1 -1
  8. package/dist/blur.d.cts +5 -5
  9. package/dist/blur.d.ts +5 -5
  10. package/dist/blur.js +39 -393
  11. package/dist/blur.js.map +1 -1
  12. package/dist/blurDataUtils-DveBRtqE.d.cts +43 -0
  13. package/dist/blurDataUtils-yx9Q6HlU.d.ts +43 -0
  14. package/dist/blurService-D5TpMNji.d.ts +83 -0
  15. package/dist/blurService-DacwylJx.d.cts +83 -0
  16. package/dist/chunk-25GYKQ6J.js +158 -0
  17. package/dist/chunk-25GYKQ6J.js.map +1 -0
  18. package/dist/chunk-34L4TEE3.cjs +226 -0
  19. package/dist/chunk-34L4TEE3.cjs.map +1 -0
  20. package/dist/chunk-DFCSN3X7.cjs +158 -0
  21. package/dist/chunk-DFCSN3X7.cjs.map +1 -0
  22. package/dist/chunk-EWVIL57J.js +294 -0
  23. package/dist/chunk-EWVIL57J.js.map +1 -0
  24. package/dist/chunk-FP5YIWG5.cjs +135 -0
  25. package/dist/chunk-FP5YIWG5.cjs.map +1 -0
  26. package/dist/chunk-HILELQGS.js +226 -0
  27. package/dist/chunk-HILELQGS.js.map +1 -0
  28. package/dist/chunk-IDLLCVGB.js +2370 -0
  29. package/dist/chunk-IDLLCVGB.js.map +1 -0
  30. package/dist/chunk-J6A44Y3W.js +514 -0
  31. package/dist/chunk-J6A44Y3W.js.map +1 -0
  32. package/dist/chunk-LOSVFO56.cjs +145 -0
  33. package/dist/chunk-LOSVFO56.cjs.map +1 -0
  34. package/dist/chunk-MBQJ6NVJ.cjs +294 -0
  35. package/dist/chunk-MBQJ6NVJ.cjs.map +1 -0
  36. package/dist/chunk-MHGQEBPW.js +145 -0
  37. package/dist/chunk-MHGQEBPW.js.map +1 -0
  38. package/dist/chunk-QHU7FUO4.cjs +37 -0
  39. package/dist/chunk-QHU7FUO4.cjs.map +1 -0
  40. package/dist/chunk-S2IFAWJK.js +37 -0
  41. package/dist/chunk-S2IFAWJK.js.map +1 -0
  42. package/dist/chunk-TA5Y64JM.cjs +2370 -0
  43. package/dist/chunk-TA5Y64JM.cjs.map +1 -0
  44. package/dist/chunk-VYVZVUNI.js +135 -0
  45. package/dist/chunk-VYVZVUNI.js.map +1 -0
  46. package/dist/chunk-XKQMCY5Z.cjs +514 -0
  47. package/dist/chunk-XKQMCY5Z.cjs.map +1 -0
  48. package/dist/cli.cjs +273 -76
  49. package/dist/cli.cjs.map +1 -1
  50. package/dist/cli.js +269 -73
  51. package/dist/cli.js.map +1 -1
  52. package/dist/headless.cjs +8 -1880
  53. package/dist/headless.cjs.map +1 -1
  54. package/dist/headless.d.cts +3 -1
  55. package/dist/headless.d.ts +3 -1
  56. package/dist/headless.js +25 -1886
  57. package/dist/headless.js.map +1 -1
  58. package/dist/index-BIdnqtW8.d.ts +234 -0
  59. package/dist/index-Brk_uHs6.d.cts +234 -0
  60. package/dist/{index-FVXXKf2v.d.ts → index-CPMlaQsC.d.ts} +76 -153
  61. package/dist/{index-FVXXKf2v.d.cts → index-DHINe-rA.d.cts} +76 -153
  62. package/dist/index.cjs +64 -532
  63. package/dist/index.cjs.map +1 -1
  64. package/dist/index.d.cts +7 -4
  65. package/dist/index.d.ts +7 -4
  66. package/dist/index.js +63 -504
  67. package/dist/index.js.map +1 -1
  68. package/dist/{memoryAdapter-CBu7_3Pp.d.ts → memoryAdapter-Ck0ccZbF.d.cts} +3 -2
  69. package/dist/{memoryAdapter-BJjyLR-1.d.cts → memoryAdapter-DxEKaG0b.d.ts} +3 -2
  70. package/dist/placeholders-C4ftwaII.d.ts +5 -0
  71. package/dist/placeholders-x_3rt65M.d.cts +5 -0
  72. package/dist/react.cjs +1952 -3257
  73. package/dist/react.cjs.map +1 -1
  74. package/dist/react.d.cts +188 -50
  75. package/dist/react.d.ts +188 -50
  76. package/dist/react.js +1763 -3013
  77. package/dist/react.js.map +1 -1
  78. package/dist/server-handler.cjs +14 -0
  79. package/dist/server-handler.cjs.map +1 -0
  80. package/dist/server-handler.d.cts +3 -0
  81. package/dist/server-handler.d.ts +3 -0
  82. package/dist/server-handler.js +14 -0
  83. package/dist/server-handler.js.map +1 -0
  84. package/dist/server.cjs +1096 -532
  85. package/dist/server.cjs.map +1 -1
  86. package/dist/server.d.cts +77 -154
  87. package/dist/server.d.ts +77 -154
  88. package/dist/server.js +1050 -448
  89. package/dist/server.js.map +1 -1
  90. package/dist/storage.cjs +239 -232
  91. package/dist/storage.cjs.map +1 -1
  92. package/dist/storage.d.cts +21 -5
  93. package/dist/storage.d.ts +21 -5
  94. package/dist/storage.js +227 -207
  95. package/dist/storage.js.map +1 -1
  96. package/dist/styles/animated-image.css +112 -0
  97. package/dist/styles/dropzone-and-tiles.css +247 -0
  98. package/dist/styles/modals-and-dock.css +248 -0
  99. package/dist/styles/primitives.css +197 -0
  100. package/dist/styles/quality-and-inputs.css +184 -0
  101. package/dist/styles/tokens.css +123 -0
  102. package/dist/styles.css +235 -220
  103. package/dist/types-BrP-o9nd.d.cts +85 -0
  104. package/dist/types-sZ3KoFQY.d.ts +85 -0
  105. package/dist/types-yShGNQnW.d.cts +61 -0
  106. package/dist/types-yShGNQnW.d.ts +61 -0
  107. package/dist/{types-CiLY0DwB.d.cts → upload-C5Trd6Dh.d.cts} +27 -53
  108. package/dist/{types-CiLY0DwB.d.ts → upload-C5Trd6Dh.d.ts} +27 -53
  109. package/package.json +92 -32
  110. package/dist/blurService-DqsnfPTd.d.cts +0 -172
  111. package/dist/blurService-DqsnfPTd.d.ts +0 -172
@@ -0,0 +1,234 @@
1
+ import { S as StorageAdapter, U as UploadRecordHook } from './types-BrP-o9nd.cjs';
2
+ import { c as ImageOutputFormat, b as ImageDimensions, E as ExplicitOutputFormat, d as ImageUploadOptions, m as UploadedImageData, k as UploadPresetConfig, i as StandardPresetName } from './upload-C5Trd6Dh.cjs';
3
+
4
+ interface OptimizedImageResult {
5
+ buffer: Buffer;
6
+ width: number;
7
+ height: number;
8
+ format: ImageOutputFormat;
9
+ size: number;
10
+ quality?: number;
11
+ }
12
+ interface BlurHashResult {
13
+ dataURL: string;
14
+ color: string;
15
+ blurHash?: string;
16
+ }
17
+ interface OptimizeImageOptions {
18
+ /** Max bounding box dimensions (fit: 'inside', withoutEnlargement: true). Defaults to 1920x1080. */
19
+ maxDimensions?: ImageDimensions;
20
+ /** Explicit output format; omit for smart size-guarded AVIF/WebP selection */
21
+ outputFormat?: ExplicitOutputFormat;
22
+ /** 1–100 compression quality. Defaults to smart photo/graphic heuristic (85–88). */
23
+ quality?: number;
24
+ /** Maximum input pixel count allowed by Sharp (defaults to 50 MP = 50,000,000) */
25
+ limitInputPixels?: number;
26
+ /** AVIF/WebP encoding effort (defaults to 6) */
27
+ effort?: number;
28
+ }
29
+ declare const DEFAULT_LIMIT_INPUT_PIXELS = 50000000;
30
+ interface GenerateBlurOptions {
31
+ width?: number;
32
+ fallbackWidth?: number;
33
+ quality?: number;
34
+ maxDataUrlChars?: number;
35
+ includeBlurHash?: boolean;
36
+ }
37
+ type ColorSamplingMode = 'balanced' | 'edge';
38
+ type EdgeKey = 'top' | 'right' | 'bottom' | 'left';
39
+ type EdgeColorSet = Record<EdgeKey, string>;
40
+ declare const PRIMARY_AVIF_EFFORT = 6;
41
+ declare const RETRY_AVIF_EFFORT = 5;
42
+ declare const BLUR_PLACEHOLDER_WIDTH = 128;
43
+ declare const BLUR_PLACEHOLDER_FALLBACK_WIDTH = 96;
44
+ declare const BLUR_PLACEHOLDER_QUALITY = 80;
45
+ declare const BLUR_PLACEHOLDER_MAX_CHARS = 8000;
46
+ declare const EDGE_COLOR_FALLBACK = "#6B7280";
47
+ declare const EDGE_WHITE_FALLBACK = "#F9FAFB";
48
+ declare const WHITE_DOMINANCE_RATIO = 1.35;
49
+
50
+ interface ProcessedImageBufferResult {
51
+ optimized: OptimizedImageResult;
52
+ blurData: BlurHashResult;
53
+ contentHash: string;
54
+ originalSize: number;
55
+ }
56
+ interface ProcessImageBufferOptions {
57
+ maxDimensions?: ImageDimensions;
58
+ outputFormat?: ExplicitOutputFormat;
59
+ quality?: number;
60
+ includeBlurHash?: boolean;
61
+ optimizationTimeoutMs?: number;
62
+ blurTimeoutMs?: number;
63
+ limitInputPixels?: number;
64
+ effort?: number;
65
+ allowSvg?: boolean;
66
+ signal?: AbortSignal;
67
+ }
68
+ interface StoragePathContext {
69
+ bucket: string;
70
+ folder?: string;
71
+ preset?: string;
72
+ format: ImageOutputFormat;
73
+ extension: string;
74
+ customFilename?: string;
75
+ isClientFilename?: boolean;
76
+ contentHash: string;
77
+ originalName?: string;
78
+ metadata?: Record<string, string>;
79
+ }
80
+ interface GeneratedStorageTarget {
81
+ bucket: string;
82
+ path: string;
83
+ filename: string;
84
+ }
85
+ type StoragePathGenerator = (context: StoragePathContext) => GeneratedStorageTarget;
86
+ interface ImageUploaderOptions<TPresets extends Record<string, UploadPresetConfig> = Record<StandardPresetName, UploadPresetConfig>> {
87
+ /** Pluggable storage backend (Supabase, S3, R2, Local FS, Memory, or custom) */
88
+ storage: StorageAdapter;
89
+ /** Default bucket name when neither `options.bucket` nor `preset.bucket` is provided (defaults to `'images'`) */
90
+ defaultBucket?: string;
91
+ /** Default folder prefix within the bucket (defaults to `''` or preset folder) */
92
+ defaultFolder?: string;
93
+ /** Default max input size in MB (defaults to `10`) */
94
+ defaultMaxSizeMB?: number;
95
+ /** Default allowed MIME formats */
96
+ defaultAllowedFormats?: string[];
97
+ /** Default max bounding box dimensions (defaults to `1920x1080`) */
98
+ defaultMaxDimensions?: ImageDimensions;
99
+ /** Opt-in to allow SVG uploads by default (sanitized before storage). Defaults to `false`. */
100
+ allowSvg?: boolean;
101
+ /** Maximum input pixel count allowed by Sharp (defaults to `50_000_000` = 50 MP) */
102
+ limitInputPixels?: number;
103
+ /** Default AVIF/WebP encoding effort (defaults to `6`) */
104
+ effort?: number;
105
+ /**
106
+ * Project-specific named presets (merged over universal `STANDARD_PRESETS` unless `includeStandardPresets: false`).
107
+ * Preset names are automatically inferred in `uploader.uploadImage(file, { preset })`.
108
+ */
109
+ presets?: TPresets;
110
+ /** Include universal visual role presets (`thumbnail`, `avatar`, `card`, `cover`, `hero`, `logo`, `original`). Defaults to `true`. */
111
+ includeStandardPresets?: boolean;
112
+ /** Custom storage path generator for full control over bucket/folder/filename layout */
113
+ pathGenerator?: StoragePathGenerator;
114
+ /** Optional database/analytics hook invoked after each successful upload */
115
+ onUploadRecord?: UploadRecordHook;
116
+ /** Wait for `onUploadRecord` before returning (defaults to `false` best-effort) */
117
+ awaitRecordHook?: boolean;
118
+ /** Optional error hook invoked when a non-awaited `onUploadRecord` fails */
119
+ onError?: (error: unknown, ctx: {
120
+ action: 'recordHook' | 'mirrorCleanup';
121
+ }) => void;
122
+ /** Max concurrent Sharp + LQIP image processing pipelines (defaults to `2`) */
123
+ concurrency?: number;
124
+ /** Max queued processing jobs waiting for a semaphore slot before rejecting with 503 */
125
+ maxQueue?: number;
126
+ /** Timeout per Sharp optimization job in ms (defaults to `60000`) */
127
+ optimizationTimeoutMs?: number;
128
+ /** Timeout per LQIP/blur generation job in ms (defaults to `30000`) */
129
+ blurTimeoutMs?: number;
130
+ /** Generate compact BlurHash strings by default on every upload */
131
+ includeBlurHash?: boolean;
132
+ }
133
+ type InferredPresetKey<TPresets extends Record<string, UploadPresetConfig>, TIncludeStandard extends boolean = true> = (keyof TPresets & string) | (TIncludeStandard extends false ? never : StandardPresetName) | (string & {});
134
+ interface ImageUploader<TPreset extends string = string> {
135
+ readonly defaultBucket?: string;
136
+ uploadImage(file: File | {
137
+ buffer: Buffer;
138
+ name?: string;
139
+ type: string;
140
+ size?: number;
141
+ }, options?: ImageUploadOptions<TPreset>): Promise<UploadedImageData>;
142
+ processBuffer(buffer: Buffer, options?: ProcessImageBufferOptions): Promise<ProcessedImageBufferResult>;
143
+ deleteImage(path: string, bucket?: string): Promise<void>;
144
+ deleteByUrl(url: string): Promise<boolean>;
145
+ resolvePreset(presetName?: string): UploadPresetConfig | undefined;
146
+ getAllowedBuckets?(): string[];
147
+ getMaxSizeMB?(allowedPresets?: string[]): number;
148
+ parseUrl?(url: string): {
149
+ bucket?: string;
150
+ path: string;
151
+ } | null;
152
+ }
153
+
154
+ interface AuthorizeContext {
155
+ action: 'upload' | 'delete';
156
+ request: Request;
157
+ path?: string;
158
+ bucket?: string;
159
+ preset?: string;
160
+ }
161
+ interface AllowClientOverrides {
162
+ /** Allow client `customFilename` field (always sanitized, forced to output extension, never upserted). */
163
+ filename?: boolean;
164
+ /**
165
+ * Allow client `folder` field. Pass `true` to accept sanitized folder names, or a callback
166
+ * `(folder, ctx) => string | null` that returns the scoped folder (or `null` to reject with 400).
167
+ */
168
+ folder?: boolean | ((folder: string, ctx: AuthorizeContext) => string | null | undefined);
169
+ /** Allow client `maxWidth` / `maxHeight` fields (clamped to the active preset's `maxDimensions`). */
170
+ dimensions?: boolean;
171
+ /** Allow client `outputFormat` field (`jpeg`, `png`, `webp`, `avif`). */
172
+ format?: boolean;
173
+ /** Allow client `quality` field (1–100, clamped to the active preset's `quality` when set). */
174
+ quality?: boolean;
175
+ }
176
+ interface UploadErrorContext {
177
+ action: 'upload' | 'delete';
178
+ request: Request;
179
+ }
180
+ interface UploadHttpHandlerOptions<TPreset extends string = string> {
181
+ uploader: ImageUploader<TPreset>;
182
+ /**
183
+ * Optional authorization check. Return `false` or throw to reject with 401.
184
+ */
185
+ authorize?: (ctx: AuthorizeContext) => boolean | Promise<boolean>;
186
+ /**
187
+ * Optional whitelist of allowed preset names.
188
+ */
189
+ allowedPresets?: TPreset[];
190
+ /**
191
+ * Optional CSRF/CORS origin allowlist (`string[]` of origins or predicate).
192
+ * When set, requests with a missing or disallowed `Origin`/`Referer` are rejected with 403.
193
+ */
194
+ allowedOrigins?: string[] | ((origin: string) => boolean);
195
+ /**
196
+ * Maximum allowed request body size in bytes (enforced via Content-Length precheck and stream cap).
197
+ * Defaults to `1.25 × max(preset.maxSizeMB, defaultMaxSizeMB)` (minimum 1 MB when unset).
198
+ */
199
+ maxBodyBytes?: number;
200
+ /**
201
+ * Opt-in switches for client-supplied FormData overrides. All default to `false` (ignored).
202
+ */
203
+ allowClientOverrides?: AllowClientOverrides;
204
+ /**
205
+ * Allow clients to override `bucket` via FormData or DELETE query params. Defaults to `false`.
206
+ */
207
+ allowClientBucketOverride?: boolean;
208
+ /**
209
+ * Optional explicit allowlist of bucket names permitted for upload and delete operations.
210
+ */
211
+ allowedBuckets?: string[];
212
+ /**
213
+ * Hook invoked when an unexpected 500 internal error occurs. Raw error details are never sent to clients.
214
+ */
215
+ onError?: (error: unknown, ctx: UploadErrorContext) => void;
216
+ }
217
+
218
+ declare class UploadValidationError extends Error {
219
+ readonly status = 400;
220
+ constructor(message: string);
221
+ }
222
+ declare function isClientValidationError(error: unknown): boolean;
223
+
224
+ /**
225
+ * Standard Web Fetch (`Request` -> `Response`) upload & delete route handlers.
226
+ * Works across Next.js App Router, Remix, React Router, SvelteKit, Astro, Hono, and Node Fetch servers.
227
+ */
228
+ declare function createUploadHttpHandler<TPreset extends string = string>(options: UploadHttpHandlerOptions<TPreset>): {
229
+ POST: (request: Request) => Promise<Response>;
230
+ DELETE: (request: Request) => Promise<Response>;
231
+ };
232
+ declare const createUploadHandler: typeof createUploadHttpHandler;
233
+
234
+ export { type AllowClientOverrides as A, type BlurHashResult as B, type ColorSamplingMode as C, DEFAULT_LIMIT_INPUT_PIXELS as D, type EdgeColorSet as E, type GenerateBlurOptions as G, type ImageUploaderOptions as I, type OptimizeImageOptions as O, type ProcessImageBufferOptions as P, RETRY_AVIF_EFFORT as R, type StoragePathGenerator as S, type UploadErrorContext as U, WHITE_DOMINANCE_RATIO as W, type OptimizedImageResult as a, type ProcessedImageBufferResult as b, type ImageUploader as c, type InferredPresetKey as d, type StoragePathContext as e, type GeneratedStorageTarget as f, type AuthorizeContext as g, BLUR_PLACEHOLDER_FALLBACK_WIDTH as h, BLUR_PLACEHOLDER_MAX_CHARS as i, BLUR_PLACEHOLDER_QUALITY as j, BLUR_PLACEHOLDER_WIDTH as k, EDGE_COLOR_FALLBACK as l, EDGE_WHITE_FALLBACK as m, type EdgeKey as n, PRIMARY_AVIF_EFFORT as o, type UploadHttpHandlerOptions as p, UploadValidationError as q, createUploadHandler as r, createUploadHttpHandler as s, isClientValidationError as t };
@@ -1,80 +1,7 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode, HTMLAttributes, CSSProperties, DragEvent, InputHTMLAttributes, Ref, ReactElement } from 'react';
3
-
4
- type UploadLocale = 'en' | 'ar';
5
- type ImageOutputFormat = 'avif' | 'webp' | 'jpeg' | 'png' | 'svg';
6
- type ExplicitOutputFormat = 'avif' | 'webp' | 'jpeg' | 'png';
7
- type QualityLevel = 'low' | 'medium' | 'high' | 'maximum';
8
- interface ImageDimensions {
9
- width: number;
10
- height: number;
11
- }
12
-
13
- /**
14
- * Universal visual role presets (project-agnostic).
15
- * Consumers can define their own presets via `defineUploadPresets` / `createImageUploader({ presets })`
16
- * or augment `UploadKitRegister` for global type-safety.
17
- */
18
- type StandardPresetName = 'thumbnail' | 'avatar' | 'card' | 'cover' | 'hero' | 'logo' | 'original';
19
- /**
20
- * Module augmentation hook for global preset autocomplete across a project:
21
- * ```ts
22
- * declare module 'img-upload-kit' {
23
- * interface UploadKitRegister {
24
- * presets: 'product-main' | 'product-thumb' | 'user-avatar';
25
- * }
26
- * }
27
- * ```
28
- */
29
- interface UploadKitRegister {
30
- }
31
- type UploadPresetName = UploadKitRegister extends {
32
- presets: infer TCustom extends string;
33
- } ? TCustom : StandardPresetName | (string & {});
34
-
35
- interface UploadedImageData {
36
- url: string;
37
- blurDataUrl: string;
38
- blurColor: string;
39
- blurHash?: string;
40
- altText?: string;
41
- width: number;
42
- height: number;
43
- format: ImageOutputFormat;
44
- size: number;
45
- originalSize?: number;
46
- contentHash: string;
47
- storagePath?: string;
48
- bucket?: string;
49
- preset?: string;
50
- folder?: string;
51
- metadata?: Record<string, string>;
52
- uploadedAt: string;
53
- }
54
-
55
- type BlurPlaceholderType = 'default' | 'hero' | 'card' | 'thumbnail';
56
- type BlurSize = 'small' | 'medium';
57
- interface BlurManifestEntry {
58
- hash: string;
59
- variants: {
60
- small: string;
61
- medium?: string;
62
- [key: string]: string | undefined;
63
- };
64
- color: string;
65
- width?: number;
66
- height?: number;
67
- metadata?: Record<string, string>;
68
- }
69
- interface BlurManifestData {
70
- version: string;
71
- generatedAt: string;
72
- totalImages: number;
73
- processedImages?: number;
74
- cachedImages?: number;
75
- failedImages?: number;
76
- hashes: Record<string, BlurManifestEntry>;
77
- }
3
+ import { U as UploadLocale, Q as QualityLevel, m as UploadedImageData, l as UploadPresetName, E as ExplicitOutputFormat, b as ImageDimensions } from './upload-C5Trd6Dh.js';
4
+ import { f as BlurPlaceholderType } from './types-yShGNQnW.js';
78
5
 
79
6
  interface BlurModalTranslations {
80
7
  title: string;
@@ -119,9 +46,20 @@ interface UploadTranslations {
119
46
  deselectAll: string;
120
47
  removeSelected: string;
121
48
  uploading: string;
49
+ uploadingCount: string;
122
50
  someUploadsFailed: string;
123
51
  retryFailedUploads: string;
124
52
  needsAltBeforeSave: string;
53
+ networkError: string;
54
+ invalidUploadResponse: string;
55
+ uploadAborted: string;
56
+ uploadStartedLive: string;
57
+ uploadProgressLive: string;
58
+ uploadCompleteLive: string;
59
+ qualityTitle: string;
60
+ qualityLevelAria: string;
61
+ qualitySaved: string;
62
+ qualityRecommended: string;
125
63
  selectFilesAria: string;
126
64
  selectMoreFilesAria: string;
127
65
  selectFolderAria: string;
@@ -164,6 +102,11 @@ interface UploadTranslations {
164
102
  adjustBlurColorAria: string;
165
103
  adjustBlurColorTitle: string;
166
104
  removeImageAria: string;
105
+ pasteHint: string;
106
+ cancelUpload: string;
107
+ retryUpload: string;
108
+ minImagesError: string;
109
+ requiredFieldError: string;
167
110
  blurModal: BlurModalTranslations;
168
111
  }
169
112
 
@@ -206,6 +149,7 @@ interface SinglePreviewRenderContext {
206
149
  disabled: boolean;
207
150
  openFileDialog: () => void;
208
151
  remove: () => void;
152
+ cancel: () => void;
209
153
  openAltTextModal: () => void;
210
154
  openBlurInspector: () => void;
211
155
  download: () => Promise<void>;
@@ -249,6 +193,8 @@ interface MultiTileRenderContext {
249
193
  disabled: boolean;
250
194
  toggleSelect: () => void;
251
195
  remove: () => void;
196
+ cancel: () => void;
197
+ retry: () => void;
252
198
  openAltTextModal: () => void;
253
199
  setAltText: (altText: string) => void;
254
200
  setBlurColor: (hex: string) => void;
@@ -301,9 +247,18 @@ interface ClientUploadRequestParams {
301
247
  quality?: number;
302
248
  maxDimensions?: ImageDimensions;
303
249
  metadata?: Record<string, string>;
250
+ signal?: AbortSignal;
304
251
  onUploadProgress?: (percent: number) => void;
305
252
  }
306
253
  type CustomUploaderFn = (file: File, params: ClientUploadRequestParams) => Promise<UploadedImageData>;
254
+ interface ImageUploadHandle {
255
+ /** Move keyboard focus to the upload dropzone or primary trigger */
256
+ focus: () => void;
257
+ /** Programmatically open the native file picker dialog */
258
+ open: () => void;
259
+ /** Clear the currently selected / uploaded image(s) */
260
+ clear: () => void;
261
+ }
307
262
  interface BaseImageUploadProps<TPreset extends string = UploadPresetName> {
308
263
  /** Optional named preset (e.g. 'avatar', 'hero', or a custom project preset) */
309
264
  preset?: TPreset;
@@ -381,6 +336,18 @@ interface BaseImageUploadProps<TPreset extends string = UploadPresetName> {
381
336
  quality?: number;
382
337
  /** Custom filename target in storage */
383
338
  customFilename?: string;
339
+ /** Camera capture attribute forwarded to `<input type="file" capture={...} />` on mobile devices */
340
+ capture?: 'user' | 'environment';
341
+ /** Enable pasting images from the clipboard (defaults to `true`) */
342
+ enablePaste?: boolean;
343
+ /** Scope for clipboard paste events: focused `'dropzone'` (default) or global `'document'` */
344
+ pasteTarget?: 'dropzone' | 'document';
345
+ /** Form field name; when set, renders a synchronized `<input type="hidden" name={name} />` */
346
+ name?: string;
347
+ /** Serialization format for the hidden form input (`'url'` default for single, `'json'` default for multi) */
348
+ formValue?: 'url' | 'json';
349
+ /** Blur callback invoked when focus leaves the uploader (e.g. for react-hook-form `field.onBlur`) */
350
+ onBlur?: () => void;
384
351
  }
385
352
  interface SingleImageUploadProps<TPreset extends string = UploadPresetName> extends BaseImageUploadProps<TPreset>, SingleCustomRenderers {
386
353
  mode?: 'single';
@@ -397,8 +364,16 @@ interface MultiImageUploadProps<TPreset extends string = UploadPresetName> exten
397
364
  value?: UploadedImageData[];
398
365
  onChange: (images: UploadedImageData[]) => void;
399
366
  maxImages?: number;
367
+ /** Minimum required uploaded images before form submission / modal save */
368
+ minImages?: number;
400
369
  allowFolder?: boolean;
401
370
  maxParallelUploads?: number;
371
+ /** Invoked when a batch or retry upload begins */
372
+ onUploadStart?: (files: File[]) => void;
373
+ /** Invoked when a batch or retry upload finishes with the newly uploaded items */
374
+ onUploadComplete?: (results: UploadedImageData[]) => void;
375
+ /** Invoked when an in-flight tile upload is cancelled */
376
+ onUploadCancel?: (id: string) => void;
402
377
  /** Per-slot custom CSS classes (Tailwind, CSS Modules, BEM) for MultiImageUpload */
403
378
  classNames?: MultiUploadClassNames;
404
379
  /** Per-slot inline CSS styles for MultiImageUpload */
@@ -435,7 +410,7 @@ interface ImageUploadContextValue {
435
410
  uploader?: CustomUploaderFn;
436
411
  headers?: Record<string, string>;
437
412
  withCredentials?: boolean;
438
- locale: UploadLocale;
413
+ locale?: UploadLocale;
439
414
  translations?: Partial<UploadTranslations>;
440
415
  renderImage?: CustomImageRenderer;
441
416
  storageKeyPrefix: string;
@@ -480,70 +455,6 @@ interface ImageUploadProviderProps {
480
455
  declare function ImageUploadProvider({ children, endpoint, uploader, headers, withCredentials, locale, translations, renderImage, storageKeyPrefix, requireAltText, unstyled, singleClassNames, singleStyles, multiClassNames, multiStyles, }: ImageUploadProviderProps): react.JSX.Element;
481
456
  declare function useImageUploadContext(): ImageUploadContextValue;
482
457
 
483
- interface NormalizePathOptions {
484
- cdnPatterns?: RegExp[];
485
- stripPrefixes?: string[];
486
- }
487
-
488
- interface BlurServiceOptions {
489
- cacheSize?: number;
490
- manifest?: BlurManifestData | Record<string, BlurManifestEntry>;
491
- pathOptions?: NormalizePathOptions;
492
- }
493
- declare class BlurService {
494
- private blurData;
495
- private readonly cache;
496
- private readonly pathOptions?;
497
- private metadata;
498
- private metrics;
499
- constructor(options?: BlurServiceOptions);
500
- /**
501
- * Hydrate the service with a generated `blur-hashes.json` manifest or hash map.
502
- */
503
- loadManifest(manifest: BlurManifestData | Record<string, BlurManifestEntry>): void;
504
- /**
505
- * Register or update a single image's blur data at runtime.
506
- */
507
- registerEntry(imagePath: string, entry: BlurManifestEntry): void;
508
- getDefaultPlaceholder(type?: BlurPlaceholderType): string;
509
- private findBlurDataByPath;
510
- getDominantColor(imageSrc: string): string;
511
- getBlurDataURL(imageSrc: string, options?: {
512
- type?: BlurPlaceholderType;
513
- size?: BlurSize;
514
- }): string;
515
- getBulkBlurData(imageSrcs: string[], options?: {
516
- type?: BlurPlaceholderType;
517
- size?: BlurSize;
518
- }): Record<string, string>;
519
- getProgressiveData(imageSrc: string, size?: BlurSize): {
520
- color: string;
521
- blur: string;
522
- hasBlur: boolean;
523
- };
524
- hasBlurHash(imageSrc: string): boolean;
525
- getMetadata(): {
526
- cacheSize: number;
527
- metrics: {
528
- cacheHitRate: string;
529
- totalRequests: number;
530
- cacheHits: number;
531
- cacheMisses: number;
532
- errors: number;
533
- };
534
- version: string;
535
- generatedAt: string;
536
- totalImages: number;
537
- };
538
- clearCache(): void;
539
- getBlurHash(imageSrc: string): string | null;
540
- preloadBlurData(imageSrcs: string[], size?: BlurSize): void;
541
- fetchBlurDataForImage(imageSrc: string, type?: BlurPlaceholderType): Promise<string>;
542
- getAvailableKeys(): string[];
543
- findMatchingKeys(searchTerm: string): string[];
544
- }
545
- declare const blurService: BlurService;
546
-
547
458
  interface UseDragAndDropOptions {
548
459
  disabled?: boolean;
549
460
  onDrop: (files: FileList) => void;
@@ -558,10 +469,19 @@ declare function useDragAndDrop({ disabled, onDrop }: UseDragAndDropOptions): {
558
469
  };
559
470
  };
560
471
 
561
- declare function useFilePreview(): {
472
+ interface UseFilePreviewOptions {
473
+ errorLabel?: string;
474
+ }
475
+ declare function useFilePreview(options?: UseFilePreviewOptions): {
562
476
  createPreview: (file: File) => Promise<string>;
477
+ revokePreview: (url?: string | null) => void;
478
+ revokeAllPreviews: () => void;
563
479
  };
564
480
 
481
+ interface UploadCallOptions {
482
+ uploadId?: string;
483
+ signal?: AbortSignal;
484
+ }
565
485
  interface UseImageUploadOptions {
566
486
  preset?: string;
567
487
  folder?: string;
@@ -578,25 +498,20 @@ interface UseImageUploadOptions {
578
498
  headers?: Record<string, string>;
579
499
  withCredentials?: boolean;
580
500
  locale?: UploadLocale;
581
- onSuccess?: (data: UploadedImageData, file?: File) => void;
582
- onError?: (error: string, file?: File) => void;
583
- onProgress?: (progress: number, message: string, file?: File) => void;
501
+ onSuccess?: (data: UploadedImageData, file?: File, uploadId?: string) => void;
502
+ onError?: (error: string, file?: File, uploadId?: string) => void;
503
+ onProgress?: (progress: number, message: string, file?: File, uploadId?: string) => void;
584
504
  }
585
505
  declare function useImageUpload({ preset, folder, bucket, metadata, altText, outputFormat, quality, maxDimensions, customFilename: defaultCustomFilename, endpoint: propEndpoint, uploader: propUploader, headers: propHeaders, withCredentials: propWithCredentials, locale: propLocale, onSuccess, onError, onProgress, }?: UseImageUploadOptions): {
586
- uploadImage: (file: File, customAltText?: string, overrideCustomFilename?: string) => Promise<UploadedImageData | null>;
506
+ uploadImage: (file: File, customAltText?: string, overrideCustomFilename?: string, callOptions?: UploadCallOptions) => Promise<UploadedImageData | null>;
507
+ abortUpload: (idOrFile: string | File) => boolean;
508
+ abortAll: () => void;
587
509
  isUploading: boolean;
588
510
  progress: number;
589
511
  uploadMessage: string;
590
512
  reset: () => void;
591
513
  };
592
514
 
593
- declare global {
594
- interface Window {
595
- blurService?: typeof blurService;
596
- }
597
- }
598
- declare function BlurServiceDebugger(): null;
599
-
600
515
  interface MultiUploadStats {
601
516
  total: number;
602
517
  completed: number;
@@ -638,6 +553,8 @@ interface SingleUploadController {
638
553
  openFileDialog: () => void;
639
554
  selectFiles: (files: FileList) => Promise<void>;
640
555
  remove: () => void;
556
+ cancel: () => void;
557
+ cancelUpload: () => void;
641
558
  save: () => void;
642
559
  download: () => Promise<void>;
643
560
  setQualityLevel: (level: QualityLevel) => void;
@@ -674,6 +591,12 @@ interface MultiUploadController {
674
591
  selectFiles: (files: FileList) => Promise<void>;
675
592
  remove: (id: string) => void;
676
593
  removeSelected: () => void;
594
+ clear: () => void;
595
+ cancel: (id: string) => void;
596
+ cancelUpload: (id: string) => void;
597
+ retry: (id: string) => Promise<void>;
598
+ retryUpload: (id: string) => Promise<void>;
599
+ retryAll: () => Promise<void>;
677
600
  toggleSelect: (id: string) => void;
678
601
  selectAll: () => void;
679
602
  clearSelection: () => void;
@@ -709,4 +632,4 @@ declare function HeadlessSingleUpload<TPreset extends string = UploadPresetName>
709
632
  */
710
633
  declare function HeadlessMultiUpload<TPreset extends string = UploadPresetName>(props: HeadlessMultiUploadProps<TPreset>): ReactElement;
711
634
 
712
- export { blurService as $, type MultiUploadController as A, type BlurPlaceholderType as B, type CustomImageRenderer as C, type MultiUploadSlot as D, type ExplicitOutputFormat as E, type MultiUploadStats as F, type MultiUploadStyles as G, type HeadlessDropzoneProps as H, type ImageDimensions as I, type SingleCustomRenderers as J, type SingleDropzoneRenderContext as K, type SinglePreviewRenderContext as L, type MultiImageUploadProps as M, type SingleUploadClassNames as N, type SingleUploadController as O, type SingleUploadSlot as P, type QualityLevel as Q, type RenderImageProps as R, type SingleImageUploadProps as S, type SingleUploadStyles as T, type UploadTranslations as U, type SizeInfo as V, type UploadStatus as W, type UseDragAndDropOptions as X, type UseImageUploadOptions as Y, type UseMultiUploadOptions as Z, type UseSingleUploadOptions as _, type UploadLocale as a, useDragAndDrop as a0, useFilePreview as a1, useImageUpload as a2, useImageUploadContext as a3, useMultiUpload as a4, useSingleUpload as a5, type UploadVisualState as b, type BlurSize as c, type UploadedImageData as d, type UploadPresetName as e, type ImageUploadProps as f, type ImagePreview as g, type BaseImageUploadProps as h, type BlurModalTranslations as i, BlurServiceDebugger as j, type ClientUploadRequestParams as k, type CustomUploaderFn as l, type HeadlessFileInputProps as m, HeadlessMultiUpload as n, type HeadlessMultiUploadProps as o, HeadlessSingleUpload as p, type HeadlessSingleUploadProps as q, type ImageUploadContextValue as r, ImageUploadProvider as s, type ImageUploadProviderProps as t, type MultiAddMoreRenderContext as u, type MultiCustomRenderers as v, type MultiEmptyRenderContext as w, type MultiHeaderRenderContext as x, type MultiTileRenderContext as y, type MultiUploadClassNames as z };
635
+ export { type SinglePreviewRenderContext as A, type BaseImageUploadProps as B, type CustomImageRenderer as C, type SingleUploadClassNames as D, type SingleUploadController as E, type SingleUploadSlot as F, type SingleUploadStyles as G, type HeadlessDropzoneProps as H, type ImageUploadProps as I, type SizeInfo as J, type UploadCallOptions as K, type UploadStatus as L, type MultiImageUploadProps as M, type UseDragAndDropOptions as N, type UseFilePreviewOptions as O, type UseImageUploadOptions as P, type UseMultiUploadOptions as Q, type RenderImageProps as R, type SingleImageUploadProps as S, type UseSingleUploadOptions as T, type UploadTranslations as U, useDragAndDrop as V, useFilePreview as W, useImageUpload as X, useImageUploadContext as Y, useMultiUpload as Z, useSingleUpload as _, type UploadVisualState as a, type ImageUploadHandle as b, type ImagePreview as c, type BlurModalTranslations as d, type ClientUploadRequestParams as e, type CustomUploaderFn as f, type HeadlessFileInputProps as g, HeadlessMultiUpload as h, type HeadlessMultiUploadProps as i, HeadlessSingleUpload as j, type HeadlessSingleUploadProps as k, type ImageUploadContextValue as l, ImageUploadProvider as m, type ImageUploadProviderProps as n, type MultiAddMoreRenderContext as o, type MultiCustomRenderers as p, type MultiEmptyRenderContext as q, type MultiHeaderRenderContext as r, type MultiTileRenderContext as s, type MultiUploadClassNames as t, type MultiUploadController as u, type MultiUploadSlot as v, type MultiUploadStats as w, type MultiUploadStyles as x, type SingleCustomRenderers as y, type SingleDropzoneRenderContext as z };