react-dropzone 19.2.0 → 19.3.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 +4 -0
- package/dist/index.cjs +76 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +21 -3
- package/dist/index.d.ts +21 -3
- package/dist/index.js +76 -10
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/index.tsx +11 -6
- package/src/utils/index.ts +153 -32
package/README.md
CHANGED
|
@@ -293,6 +293,10 @@ React [18](https://react.dev/blog/2022/03/29/react-v18) or above is required bec
|
|
|
293
293
|
Files returned by the hook or passed as arg to the `onDrop` cb won't have the properties `path` or `fullPath`.
|
|
294
294
|
For more inf check [this SO question](https://stackoverflow.com/a/23005925/2275818) and [this issue](https://github.com/react-dropzone/react-dropzone/issues/477).
|
|
295
295
|
|
|
296
|
+
### Tauri (and other native webviews)
|
|
297
|
+
|
|
298
|
+
Inside a [Tauri](https://tauri.app/) webview, OS file drops are intercepted by the native window layer before the webview sees them, so the browser's drag 'n' drop events never fire and the dropzone appears to ignore drops. Disable Tauri's native handling to let `react-dropzone` work unchanged: set `dragDropEnabled: false` (Tauri v2) or `fileDropEnabled: false` (Tauri v1) in `tauri.conf.json`. If you instead need the absolute paths of dropped files, keep native handling on and drive your own state from Tauri's drag-drop event. See the [Using with Tauri](https://react-dropzone.js.org/guide/tauri) guide and [#1316](https://github.com/react-dropzone/react-dropzone/issues/1316).
|
|
299
|
+
|
|
296
300
|
### Not a File Uploader
|
|
297
301
|
|
|
298
302
|
This lib is not a file uploader; as such, it does not process files or provide any way to make HTTP requests to some server; if you're looking for that, checkout [filepond](https://pqina.nl/filepond) or [uppy.io](https://uppy.io/).
|
package/dist/index.cjs
CHANGED
|
@@ -201,27 +201,91 @@ function canUseFileSystemAccessAPI() {
|
|
|
201
201
|
return "showOpenFilePicker" in window;
|
|
202
202
|
}
|
|
203
203
|
/**
|
|
204
|
+
* Coerce an `accept` extension value to an array. `window.showOpenFilePicker` allows a single
|
|
205
|
+
* extension string as well as an array, so we accept both and normalize to an array. Anything
|
|
206
|
+
* else (a malformed value) collapses to an empty list.
|
|
207
|
+
*/
|
|
208
|
+
function toExtensions(ext) {
|
|
209
|
+
if (Array.isArray(ext)) return ext;
|
|
210
|
+
if (typeof ext === "string") return [ext];
|
|
211
|
+
return [];
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Normalize either `accept` form to the internal array of `{description, accept}` groups.
|
|
215
|
+
*
|
|
216
|
+
* - The object form (`{mime: ext}`) becomes a single group; its `description` (which the object
|
|
217
|
+
* form can't express) is derived from the extensions like any other group.
|
|
218
|
+
* - The array form is passed through; entries missing an `accept` map are dropped.
|
|
219
|
+
*
|
|
220
|
+
* In both cases a missing `description` is filled in later from the group's extensions (see
|
|
221
|
+
* {@link describeAccept}), so the picker always gets the non-empty description it requires
|
|
222
|
+
* (https://crbug.com/1264708). Returns `undefined` when no `accept` is provided.
|
|
223
|
+
*/
|
|
224
|
+
function normalizeAcceptGroups(accept) {
|
|
225
|
+
if (!isDefined(accept)) return;
|
|
226
|
+
if (Array.isArray(accept)) return accept.filter((group) => isDefined(group) && isDefined(group.accept));
|
|
227
|
+
return [{ accept }];
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Build a human-readable label for a picker group from its (validated) accept map, used when the
|
|
231
|
+
* caller doesn't supply a `description`. Prefer the file extensions, fall back to the MIME types,
|
|
232
|
+
* then to a generic label - `showOpenFilePicker` requires a non-empty description (crbug 1264708).
|
|
233
|
+
*/
|
|
234
|
+
function describeAccept(accept) {
|
|
235
|
+
const extensions = [];
|
|
236
|
+
const mimeTypes = Object.keys(accept);
|
|
237
|
+
for (const ext of Object.values(accept)) for (const e of toExtensions(ext)) if (!extensions.includes(e)) extensions.push(e);
|
|
238
|
+
if (extensions.length > 0) return extensions.join(", ");
|
|
239
|
+
if (mimeTypes.length > 0) return mimeTypes.join(", ");
|
|
240
|
+
return "Files";
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Merge every `accept` group into a single MIME-type -> extensions map. Duplicate MIME keys union
|
|
244
|
+
* their extensions. This flattened map drives the native `<input accept>` attribute and the
|
|
245
|
+
* drag/drop validators, which have no concept of groups or descriptions.
|
|
246
|
+
*/
|
|
247
|
+
function flattenAccept(accept) {
|
|
248
|
+
const groups = normalizeAcceptGroups(accept);
|
|
249
|
+
if (!isDefined(groups)) return;
|
|
250
|
+
const merged = {};
|
|
251
|
+
for (const group of groups) for (const [mimeType, ext] of Object.entries(group.accept)) {
|
|
252
|
+
const existing = merged[mimeType] ?? (merged[mimeType] = []);
|
|
253
|
+
for (const e of toExtensions(ext)) if (!existing.includes(e)) existing.push(e);
|
|
254
|
+
}
|
|
255
|
+
return merged;
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
204
258
|
* Convert the `{accept}` dropzone prop to the `{types}` option for showOpenFilePicker.
|
|
259
|
+
*
|
|
260
|
+
* Each group becomes one filter row in the picker. Invalid MIME types / extensions are dropped
|
|
261
|
+
* with a warning; a group left with no valid entries is omitted entirely (showOpenFilePicker
|
|
262
|
+
* rejects an empty `accept`). Returns `undefined` when nothing valid remains.
|
|
205
263
|
*/
|
|
206
264
|
function pickerOptionsFromAccept(accept) {
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
265
|
+
const groups = normalizeAcceptGroups(accept);
|
|
266
|
+
if (!isDefined(groups)) return;
|
|
267
|
+
const options = groups.map((group) => {
|
|
268
|
+
const acceptForPicker = Object.entries(group.accept).filter(([mimeType, ext]) => {
|
|
210
269
|
let ok = true;
|
|
211
270
|
if (!isMIMEType(mimeType)) {
|
|
212
271
|
console.warn(`Skipped "${mimeType}" because it is not a valid MIME type. Check https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types for a list of valid MIME types.`);
|
|
213
272
|
ok = false;
|
|
214
273
|
}
|
|
215
|
-
if (!Array.isArray(ext) || !ext.every(isExt)) {
|
|
274
|
+
if (!(Array.isArray(ext) || typeof ext === "string") || !toExtensions(ext).every(isExt)) {
|
|
216
275
|
console.warn(`Skipped "${mimeType}" because an invalid file extension was provided.`);
|
|
217
276
|
ok = false;
|
|
218
277
|
}
|
|
219
278
|
return ok;
|
|
220
279
|
}).reduce((agg, [mimeType, ext]) => {
|
|
221
|
-
agg[mimeType] = ext;
|
|
280
|
+
agg[mimeType] = toExtensions(ext);
|
|
222
281
|
return agg;
|
|
223
|
-
}, {})
|
|
224
|
-
|
|
282
|
+
}, {});
|
|
283
|
+
return {
|
|
284
|
+
description: isDefined(group.description) && group.description !== "" ? group.description : describeAccept(acceptForPicker),
|
|
285
|
+
accept: acceptForPicker
|
|
286
|
+
};
|
|
287
|
+
}).filter((option) => Object.keys(option.accept).length > 0);
|
|
288
|
+
return options.length > 0 ? options : void 0;
|
|
225
289
|
}
|
|
226
290
|
/**
|
|
227
291
|
* Convert the `{accept}` dropzone prop to a comma-separated accept attribute string.
|
|
@@ -236,7 +300,8 @@ function pickerOptionsFromAccept(accept) {
|
|
|
236
300
|
* See https://github.com/react-dropzone/react-dropzone/issues/1220
|
|
237
301
|
*/
|
|
238
302
|
function acceptPropAsAcceptAttr(accept, { omitWildcardMimeTypesWithExtensions = false } = {}) {
|
|
239
|
-
if (isDefined(accept)) return Object.entries(accept).reduce((a, [mimeType,
|
|
303
|
+
if (isDefined(accept)) return Object.entries(accept).reduce((a, [mimeType, extVal]) => {
|
|
304
|
+
const ext = toExtensions(extVal);
|
|
240
305
|
if (omitWildcardMimeTypesWithExtensions && isMIMETypeWildcard(mimeType) && ext.some(isExt)) a.push(...ext);
|
|
241
306
|
else a.push(mimeType, ...ext);
|
|
242
307
|
return a;
|
|
@@ -341,8 +406,9 @@ const initialState = {
|
|
|
341
406
|
*/
|
|
342
407
|
function useDropzone(props = {}) {
|
|
343
408
|
const { accept, disabled = false, getFilesFromEvent = file_selector.fromEvent, maxSize = Number.POSITIVE_INFINITY, minSize = 0, multiple = true, maxFiles = 0, onDragEnter, onDragLeave, onDragOver, onDrop, onDropAccepted, onDropRejected, onFileDialogCancel, onFileDialogOpen, useFsAccessApi = false, autoFocus = false, preventDropOnDocument = true, noClick = false, noKeyboard = false, noDrag = false, noDragEventsBubbling = false, noPaste = false, onError, validator, getErrorMessage } = props;
|
|
344
|
-
const
|
|
345
|
-
const
|
|
409
|
+
const flatAccept = (0, react.useMemo)(() => flattenAccept(accept), [accept]);
|
|
410
|
+
const acceptAttr = (0, react.useMemo)(() => acceptPropAsAcceptAttr(flatAccept), [flatAccept]);
|
|
411
|
+
const inputAcceptAttr = (0, react.useMemo)(() => acceptPropAsAcceptAttr(flatAccept, { omitWildcardMimeTypesWithExtensions: true }), [flatAccept]);
|
|
346
412
|
const pickerTypes = (0, react.useMemo)(() => pickerOptionsFromAccept(accept), [accept]);
|
|
347
413
|
const onFileDialogOpenCb = (0, react.useMemo)(() => typeof onFileDialogOpen === "function" ? onFileDialogOpen : noop, [onFileDialogOpen]);
|
|
348
414
|
const onFileDialogCancelCb = (0, react.useMemo)(() => typeof onFileDialogCancel === "function" ? onFileDialogCancel : noop, [onFileDialogCancel]);
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["attrAccept","fromEvent"],"sources":["../src/utils/index.ts","../src/index.tsx"],"sourcesContent":["import attrAccept from \"attr-accept\";\n\n// attr-accept ships as a CommonJS module (`module.exports = { __esModule: true, default: fn }`).\n// Bundler interop surfaces its default export inconsistently — as the function under Node/Vitest,\n// but as `{ default: fn }` in some browser bundles. Normalize to the function.\nconst accepts =\n typeof attrAccept === \"function\" ? attrAccept : (attrAccept as unknown as {default: typeof attrAccept}).default;\n\n/**\n * A map of accepted MIME types to file extensions, as passed to the `accept` prop.\n */\nexport interface Accept {\n [key: string]: readonly string[];\n}\n\n/**\n * A file rejection error.\n */\nexport interface FileError {\n message: string;\n code: ErrorCode | string;\n}\n\n/**\n * What a custom `validator` returns: a single error, a list of errors, or `null` when the file\n * passes. A validator may return the result directly (synchronous) or wrapped in a `Promise`\n * (asynchronous, e.g. reading image dimensions or calling an external service).\n */\nexport type ValidatorResult = FileError | readonly FileError[] | null;\n\n// Error codes\nexport const FILE_INVALID_TYPE = \"file-invalid-type\";\nexport const FILE_TOO_LARGE = \"file-too-large\";\nexport const FILE_TOO_SMALL = \"file-too-small\";\nexport const TOO_MANY_FILES = \"too-many-files\";\n\nexport enum ErrorCode {\n FileInvalidType = \"file-invalid-type\",\n FileTooLarge = \"file-too-large\",\n FileTooSmall = \"file-too-small\",\n TooManyFiles = \"too-many-files\"\n}\n\nexport function getInvalidTypeRejectionErr(accept: string = \"\"): FileError {\n const acceptArr = accept.split(\",\");\n const msg = acceptArr.length > 1 ? `one of ${acceptArr.join(\", \")}` : acceptArr[0];\n\n return {\n code: FILE_INVALID_TYPE,\n message: `File type must be ${msg}`\n };\n}\n\nconst FILE_SIZE_UNITS = [\"KB\", \"MB\", \"GB\", \"TB\", \"PB\"];\n\n/**\n * Format a byte count into a human-readable string, e.g. `1111` -> `1.08 KB`.\n * Values below 1 KB are kept in bytes to preserve the singular/plural wording.\n */\nfunction formatBytes(bytes: number): string {\n if (bytes < 1024) {\n return `${bytes} ${bytes === 1 ? \"byte\" : \"bytes\"}`;\n }\n\n let size = bytes / 1024;\n let unitIndex = 0;\n while (size >= 1024 && unitIndex < FILE_SIZE_UNITS.length - 1) {\n size /= 1024;\n unitIndex++;\n }\n\n // Round to 2 decimals, then drop trailing zeros (1.00 -> 1, 1.50 -> 1.5).\n return `${Number(size.toFixed(2))} ${FILE_SIZE_UNITS[unitIndex]}`;\n}\n\nexport function getTooLargeRejectionErr(maxSize: number): FileError {\n return {\n code: FILE_TOO_LARGE,\n message: `File is larger than ${formatBytes(maxSize)}`\n };\n}\n\nexport function getTooSmallRejectionErr(minSize: number): FileError {\n return {\n code: FILE_TOO_SMALL,\n message: `File is smaller than ${formatBytes(minSize)}`\n };\n}\n\nexport const TOO_MANY_FILES_REJECTION: FileError = {\n code: TOO_MANY_FILES,\n message: \"Too many files\"\n};\n\n/**\n * Check if the given file is a DataTransferItem with an empty type.\n *\n * During drag events, browsers may return DataTransferItem objects instead of File objects.\n * Some browsers (e.g., Chrome) return an empty MIME type for certain file types (like .md files)\n * on DataTransferItem during drag events, even though the type is correctly set during drop.\n */\nexport function isDataTransferItemWithEmptyType(file: File | DataTransferItem): boolean {\n return file.type === \"\" && typeof (file as DataTransferItem).getAsFile === \"function\";\n}\n\n/**\n * Check if file is accepted.\n *\n * Firefox versions prior to 53 return a bogus MIME type for every file drag,\n * so dragovers with that MIME type will always be accepted.\n *\n * Chrome/other browsers may return an empty MIME type for files during drag events,\n * so we accept those as well (we'll validate properly on drop).\n */\nexport function fileAccepted(file: File, accept?: string): [boolean, FileError | null] {\n const isAcceptable =\n file.type === \"application/x-moz-file\" || accepts(file, accept ?? \"\") || isDataTransferItemWithEmptyType(file);\n return [isAcceptable, isAcceptable ? null : getInvalidTypeRejectionErr(accept)];\n}\n\nexport function fileMatchSize(\n file: {size?: number | null},\n minSize?: number,\n maxSize?: number\n): [boolean, FileError | null] {\n if (isDefined(file.size)) {\n if (isDefined(minSize) && isDefined(maxSize)) {\n if (file.size > maxSize) return [false, getTooLargeRejectionErr(maxSize)];\n if (file.size < minSize) return [false, getTooSmallRejectionErr(minSize)];\n } else if (isDefined(minSize) && file.size < minSize) {\n return [false, getTooSmallRejectionErr(minSize)];\n } else if (isDefined(maxSize) && file.size > maxSize) {\n return [false, getTooLargeRejectionErr(maxSize)];\n }\n }\n return [true, null];\n}\n\nfunction isDefined<T>(value: T): value is NonNullable<T> {\n return value !== undefined && value !== null;\n}\n\n/**\n * Check if a value is thenable (Promise-like), used to tell a synchronous validator result from an\n * asynchronous one.\n */\nexport function isThenable(value: unknown): value is PromiseLike<unknown> {\n return value != null && typeof (value as {then?: unknown}).then === \"function\";\n}\n\nexport function allFilesAccepted({\n files,\n accept,\n minSize,\n maxSize,\n multiple,\n maxFiles = 0,\n validator\n}: {\n files: File[];\n accept?: string;\n minSize?: number;\n maxSize?: number;\n multiple?: boolean;\n maxFiles?: number;\n validator?: (file: File) => FileError | readonly FileError[] | null;\n}): boolean {\n if ((!multiple && files.length > 1) || (multiple && maxFiles >= 1 && files.length > maxFiles)) {\n return false;\n }\n\n return files.every(file => {\n const [accepted] = fileAccepted(file, accept);\n const [sizeMatch] = fileMatchSize(file, minSize, maxSize);\n const customErrors = validator ? validator(file) : null;\n return accepted && sizeMatch && !customErrors;\n });\n}\n\n/**\n * The outcome of the drag-time acceptance check.\n *\n * - `accept` - every file passes the checks we can evaluate during a drag.\n * - `reject` - at least one file confidently fails a check we can fully evaluate during a\n * drag (the file count, or a non-empty MIME type that doesn't match `accept`).\n * - `unknown` - nothing confidently fails, but the outcome can't be confirmed until drop,\n * because a custom `validator` is configured and can't be evaluated yet.\n */\nexport type DragVerdict = \"accept\" | \"reject\" | \"unknown\";\n\n/**\n * Classify a set of dragged files for the `isDragAccept`/`isDragReject`/`isDragUnknown` states.\n *\n * During `dragenter`/`dragover` the browser only exposes `DataTransferItem`s, which carry a MIME\n * `type` but no file name, extension or size (see https://html.spec.whatwg.org/multipage/dnd.html#dndevents).\n * So the drag-time check is deliberately optimistic about anything it can't see:\n *\n * - The custom `validator` is **never** run here. It is typed `(file: File) => ...` and users\n * routinely read `file.name`/`file.size`, which are `undefined` on a `DataTransferItem` - running\n * it would throw and abort the whole drag handler (leaving `isDragActive` stuck at `false`).\n * See https://github.com/react-dropzone/react-dropzone/issues/1408\n * - When a `validator` is configured we therefore can't promise the files are acceptable, so the\n * verdict is `unknown` rather than a misleading `reject` (or a premature `accept`).\n * See https://github.com/react-dropzone/react-dropzone/issues/1244\n *\n * The full check (including the `validator`) still runs on drop in {@link fileAccepted}/`setFiles`.\n */\nexport function getDragVerdict({\n files,\n accept,\n minSize,\n maxSize,\n multiple,\n maxFiles = 0,\n validator\n}: {\n files: Array<File | DataTransferItem>;\n accept?: string;\n minSize?: number;\n maxSize?: number;\n multiple?: boolean;\n maxFiles?: number;\n // The validator is never invoked here (see the note above), so its async variant is accepted\n // purely so the same `validator` prop is assignable during a drag.\n validator?: (file: File) => ValidatorResult | Promise<ValidatorResult>;\n}): DragVerdict {\n // The file count is knowable during a drag, so an over-the-limit selection is a confident reject.\n if ((!multiple && files.length > 1) || (multiple && maxFiles >= 1 && files.length > maxFiles)) {\n return \"reject\";\n }\n\n const confidentlyRejected = files.some(file => {\n const [accepted] = fileAccepted(file as File, accept);\n const [sizeMatch] = fileMatchSize(file as File, minSize, maxSize);\n return !accepted || !sizeMatch;\n });\n if (confidentlyRejected) {\n return \"reject\";\n }\n\n // Built-in checks pass. A custom validator can only ever add rejections on drop, never rescue\n // one - so with a validator present the drag outcome is unknown until we have real Files.\n return validator ? \"unknown\" : \"accept\";\n}\n\n// React's synthetic events has event.isPropagationStopped,\n// but to remain compatibility with other libs (Preact) fall back\n// to check event.cancelBubble\nexport function isPropagationStopped(event: any): boolean {\n if (typeof event.isPropagationStopped === \"function\") {\n return event.isPropagationStopped();\n } else if (typeof event.cancelBubble !== \"undefined\") {\n return event.cancelBubble;\n }\n return false;\n}\n\nexport function isEvtWithFiles(event: any): boolean {\n // A paste (ClipboardEvent) carries its DataTransfer under {clipboardData} rather than\n // {dataTransfer}, so a pasted screenshot is detected the same way as a drop.\n const dataTransfer = event.dataTransfer ?? event.clipboardData;\n if (!dataTransfer) {\n return !!event.target && !!event.target.files;\n }\n // https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/types\n // https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/Recommended_drag_types#file\n // Some Chromium drags omit \"Files\" from types (e.g. reporting only [\"text/plain\"])\n // while still exposing a kind: \"file\" entry in items - the same signal file-selector\n // uses to extract the files. Accept either so detection stays consistent. See #1409.\n return (\n Array.prototype.some.call(\n dataTransfer.types,\n (type: string) => type === \"Files\" || type === \"application/x-moz-file\"\n ) || Array.prototype.some.call(dataTransfer.items ?? [], isKindFile)\n );\n}\n\nexport function isKindFile(item: any): boolean {\n return typeof item === \"object\" && item !== null && item.kind === \"file\";\n}\n\n// allow the entire document to be a drag target\nexport function onDocumentDragOver(event: Event): void {\n event.preventDefault();\n}\n\nfunction isIe(userAgent: string): boolean {\n return userAgent.indexOf(\"MSIE\") !== -1 || userAgent.indexOf(\"Trident/\") !== -1;\n}\n\nfunction isEdge(userAgent: string): boolean {\n return userAgent.indexOf(\"Edge/\") !== -1;\n}\n\nexport function isIeOrEdge(userAgent: string = window.navigator.userAgent): boolean {\n return isIe(userAgent) || isEdge(userAgent);\n}\n\n/**\n * This is intended to be used to compose event handlers.\n * They are executed in order until one of them calls `event.isPropagationStopped()`.\n * Note that the check is done on the first invoke too,\n * meaning that if propagation was stopped before invoking the fns,\n * no handlers will be executed.\n */\nexport function composeEventHandlers(\n ...fns: Array<((event: any, ...args: any[]) => void) | null | undefined>\n): (event: any, ...args: any[]) => boolean {\n return (event: any, ...args: any[]) =>\n fns.some(fn => {\n if (!isPropagationStopped(event) && fn) {\n fn(event, ...args);\n }\n return isPropagationStopped(event);\n });\n}\n\n/**\n * canUseFileSystemAccessAPI checks if the File System Access API is supported by the browser.\n */\nexport function canUseFileSystemAccessAPI(): boolean {\n return \"showOpenFilePicker\" in window;\n}\n\n/**\n * Convert the `{accept}` dropzone prop to the `{types}` option for showOpenFilePicker.\n */\nexport function pickerOptionsFromAccept(accept?: Accept): Array<{description: string; accept: Accept}> | undefined {\n if (isDefined(accept)) {\n const acceptForPicker = Object.entries(accept)\n .filter(([mimeType, ext]) => {\n let ok = true;\n\n if (!isMIMEType(mimeType)) {\n console.warn(\n `Skipped \"${mimeType}\" because it is not a valid MIME type. Check https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types for a list of valid MIME types.`\n );\n ok = false;\n }\n\n if (!Array.isArray(ext) || !ext.every(isExt)) {\n console.warn(`Skipped \"${mimeType}\" because an invalid file extension was provided.`);\n ok = false;\n }\n\n return ok;\n })\n .reduce<Accept>((agg, [mimeType, ext]) => {\n agg[mimeType] = ext;\n return agg;\n }, {});\n return [\n {\n // description is required due to https://crbug.com/1264708\n description: \"Files\",\n accept: acceptForPicker\n }\n ];\n }\n return undefined;\n}\n\n/**\n * Convert the `{accept}` dropzone prop to a comma-separated accept attribute string.\n *\n * When `omitWildcardMimeTypesWithExtensions` is set, a wildcard MIME type (e.g. `image/*`)\n * that is paired with explicit extensions is dropped in favour of those extensions. The\n * accept attribute is an OR list, so leaving `image/*` in would make both the native file\n * picker and the drop-time validator accept ANY file of that type, ignoring the extension\n * restriction. The drag-time `isDragAccept` check keeps the wildcard because file names\n * (and therefore extensions) aren't readable during a drag.\n *\n * See https://github.com/react-dropzone/react-dropzone/issues/1220\n */\nexport function acceptPropAsAcceptAttr(\n accept?: Accept,\n {omitWildcardMimeTypesWithExtensions = false}: {omitWildcardMimeTypesWithExtensions?: boolean} = {}\n): string | undefined {\n if (isDefined(accept)) {\n return (\n Object.entries(accept)\n .reduce<string[]>((a, [mimeType, ext]) => {\n if (omitWildcardMimeTypesWithExtensions && isMIMETypeWildcard(mimeType) && ext.some(isExt)) {\n a.push(...ext);\n } else {\n a.push(mimeType, ...ext);\n }\n return a;\n }, [])\n // Silently discard invalid entries as pickerOptionsFromAccept warns about these\n .filter(v => isMIMEType(v) || isExt(v))\n .join(\",\")\n );\n }\n\n return undefined;\n}\n\n/**\n * Check if v is an exception caused by aborting a request (e.g window.showOpenFilePicker()).\n */\nexport function isAbort(v: any): boolean {\n return v instanceof DOMException && (v.name === \"AbortError\" || v.code === v.ABORT_ERR);\n}\n\n/**\n * Check if v is a security error.\n */\nexport function isSecurityError(v: any): boolean {\n return v instanceof DOMException && (v.name === \"SecurityError\" || v.code === v.SECURITY_ERR);\n}\n\n/**\n * Check if v is a \"not allowed\" error.\n *\n * Some browsers/configurations block `window.showOpenFilePicker()` outright and reject with a\n * `NotAllowedError` instead of showing the picker (e.g. Microsoft Edge for Business, or other\n * restrictive enterprise/security policies). We treat this like a security error and fall back\n * to the native `<input>`. See https://github.com/react-dropzone/react-dropzone/issues/1429\n */\nexport function isNotAllowedError(v: any): boolean {\n return v instanceof DOMException && v.name === \"NotAllowedError\";\n}\n\n/**\n * Check if v is a MIME type string.\n */\nexport function isMIMEType(v: string): boolean {\n return (\n v === \"audio/*\" ||\n v === \"video/*\" ||\n v === \"image/*\" ||\n v === \"text/*\" ||\n v === \"application/*\" ||\n /\\w+\\/[-+.\\w]+/g.test(v)\n );\n}\n\n/**\n * Check if v is a wildcard MIME type (e.g. `image/*`).\n */\nexport function isMIMETypeWildcard(v: string): boolean {\n return v.endsWith(\"/*\");\n}\n\n/**\n * Check if v is a file extension.\n */\nexport function isExt(v: string): boolean {\n return /^.*\\.[\\w]+$/.test(v);\n}\n","import {fromEvent} from \"file-selector\";\nimport type {FileWithPath} from \"file-selector\";\nimport type * as React from \"react\";\nimport {forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useReducer, useRef} from \"react\";\nimport {\n acceptPropAsAcceptAttr,\n canUseFileSystemAccessAPI,\n composeEventHandlers,\n ErrorCode,\n fileAccepted,\n fileMatchSize,\n getDragVerdict,\n isAbort,\n isEvtWithFiles,\n isIeOrEdge,\n isNotAllowedError,\n isThenable,\n isPropagationStopped,\n isSecurityError,\n onDocumentDragOver,\n pickerOptionsFromAccept,\n TOO_MANY_FILES_REJECTION\n} from \"./utils\";\nimport type {Accept, FileError, ValidatorResult} from \"./utils\";\n\nexport type {Accept, FileError, FileWithPath, ValidatorResult};\nexport {ErrorCode};\n\nexport interface DropzoneProps extends DropzoneOptions {\n children?: (state: DropzoneState) => React.ReactElement;\n}\n\nexport interface FileRejection {\n file: FileWithPath;\n errors: readonly FileError[];\n}\n\ntype SharedProps = \"multiple\" | \"onDragEnter\" | \"onDragOver\" | \"onDragLeave\";\n\nexport type DropzoneOptions = Pick<React.HTMLProps<HTMLElement>, SharedProps> & {\n accept?: Accept;\n minSize?: number;\n maxSize?: number;\n maxFiles?: number;\n preventDropOnDocument?: boolean;\n noClick?: boolean;\n noKeyboard?: boolean;\n noDrag?: boolean;\n noDragEventsBubbling?: boolean;\n /**\n * If true, disables paste-to-upload. By default, when the dropzone (or a focused child) receives a\n * paste that carries files - e.g. a screenshot pasted with Ctrl/Cmd+V - those files go through the\n * same `accept`/size/`validator` checks and `onDrop` callbacks as a drop. Pastes with no files\n * (plain text, etc.) are ignored and left untouched. See\n * https://github.com/react-dropzone/react-dropzone/issues/1210\n */\n noPaste?: boolean;\n disabled?: boolean;\n onDrop?: <T extends File>(acceptedFiles: T[], fileRejections: FileRejection[], event: DropEvent) => void;\n onDropAccepted?: <T extends File>(files: T[], event: DropEvent) => void;\n onDropRejected?: (fileRejections: FileRejection[], event: DropEvent) => void;\n getFilesFromEvent?: (event: DropEvent | Array<FileSystemFileHandle>) => Promise<Array<File | DataTransferItem>>;\n onFileDialogCancel?: () => void;\n onFileDialogOpen?: () => void;\n onError?: (err: Error) => void;\n /**\n * Custom validation, run once per file on drop/selection. Return `null` to accept the file, or a\n * {@link FileError} (or array of them) to reject it. May be `async` (return a `Promise`) to support\n * checks that can't run synchronously - e.g. reading image dimensions, inspecting file contents,\n * or calling an external service. While an async validator is pending, {@link DropzoneState.isProcessing}\n * is `true`, and `onDrop`/`onDropAccepted`/`onDropRejected` fire only once it settles. If the\n * validator throws or rejects, `onError` is called and the drop is discarded.\n *\n * Note: the validator never runs during a drag (a `DataTransferItem` has no name/size), so a\n * validator-configured dropzone is `isDragUnknown` until drop.\n */\n validator?: <T extends File>(file: T) => ValidatorResult | Promise<ValidatorResult>;\n /**\n * Override the message of any rejection error (built-in or custom). Called once per error;\n * receives the error and the file it belongs to and returns the message to use. Return\n * `error.message` for codes you don't want to change. Useful for localizing error messages.\n */\n getErrorMessage?: (error: FileError, file: File) => string;\n useFsAccessApi?: boolean;\n autoFocus?: boolean;\n};\n\nexport type DropEvent =\n | React.DragEvent<HTMLElement>\n | React.ChangeEvent<HTMLInputElement>\n | React.ClipboardEvent<HTMLElement>\n | DragEvent\n | ClipboardEvent\n | Event;\n\nexport interface DropzoneRef {\n open: () => void;\n}\n\nexport type DropzoneState = DropzoneRef & {\n isFocused: boolean;\n isDragActive: boolean;\n isDragAccept: boolean;\n isDragReject: boolean;\n isDragUnknown: boolean;\n isDragGlobal: boolean;\n isFileDialogActive: boolean;\n /**\n * `true` while a drop/selection is being processed asynchronously - i.e. while `getFilesFromEvent`\n * reads the files and/or an async {@link DropzoneOptions.validator} runs. Spans the whole pipeline,\n * from when files start being read until validation settles. When both are synchronous (the default\n * `getFilesFromEvent` with no/async-free validator) the work resolves within a microtask, so it's\n * only observable for genuinely async work. Use it to show a spinner or disable UI while processing.\n */\n isProcessing: boolean;\n acceptedFiles: readonly FileWithPath[];\n fileRejections: readonly FileRejection[];\n rootRef: React.RefObject<HTMLElement>;\n inputRef: React.RefObject<HTMLInputElement>;\n getRootProps: <T extends DropzoneRootProps>(props?: T) => T;\n getInputProps: <T extends DropzoneInputProps>(props?: T) => T;\n};\n\nexport interface DropzoneRootProps extends React.HTMLAttributes<HTMLElement> {\n refKey?: string;\n [key: string]: any;\n}\n\nexport interface DropzoneInputProps extends React.InputHTMLAttributes<HTMLInputElement> {\n refKey?: string;\n}\n\n/**\n * Convenience wrapper component for the `useDropzone` hook\n *\n * ```jsx\n * <Dropzone>\n * {({getRootProps, getInputProps}) => (\n * <div {...getRootProps()}>\n * <input {...getInputProps()} />\n * <p>Drag 'n' drop some files here, or click to select files</p>\n * </div>\n * )}\n * </Dropzone>\n * ```\n */\nconst Dropzone: React.ForwardRefExoticComponent<DropzoneProps & React.RefAttributes<DropzoneRef>> = forwardRef<\n DropzoneRef,\n DropzoneProps\n>(({children, ...params}, ref) => {\n const {open, ...props} = useDropzone(params);\n\n useImperativeHandle(ref, () => ({open}), [open]);\n\n return <>{children?.({...props, open})}</>;\n});\n\nDropzone.displayName = \"Dropzone\";\n\nexport default Dropzone;\n\ninterface DropzoneInternalState {\n isFocused: boolean;\n isFileDialogActive: boolean;\n isDragActive: boolean;\n isDragAccept: boolean;\n isDragReject: boolean;\n isDragUnknown: boolean;\n isDragGlobal: boolean;\n isProcessing: boolean;\n acceptedFiles: FileWithPath[];\n fileRejections: FileRejection[];\n}\n\n/**\n * The per-file outcome of the built-in checks plus the (resolved) custom validator, assembled in\n * setFiles before the accepted/rejected split.\n */\ninterface PerFileResult {\n file: FileWithPath;\n accepted: boolean;\n acceptError: FileError | null;\n sizeMatch: boolean;\n sizeError: FileError | null;\n customErrors: ValidatorResult;\n}\n\nconst initialState: DropzoneInternalState = {\n isFocused: false,\n isFileDialogActive: false,\n isDragActive: false,\n isDragAccept: false,\n isDragReject: false,\n isDragUnknown: false,\n isDragGlobal: false,\n isProcessing: false,\n acceptedFiles: [],\n fileRejections: []\n};\n\n/**\n * A React hook that creates a drag 'n' drop area.\n *\n * ```jsx\n * function MyDropzone(props) {\n * const {getRootProps, getInputProps} = useDropzone({\n * onDrop: acceptedFiles => {\n * // do something with the File objects, e.g. upload to some server\n * }\n * });\n * return (\n * <div {...getRootProps()}>\n * <input {...getInputProps()} />\n * <p>Drag and drop some files here, or click to select files</p>\n * </div>\n * )\n * }\n * ```\n */\nexport function useDropzone(props: DropzoneOptions = {}): DropzoneState {\n const {\n accept,\n disabled = false,\n getFilesFromEvent = fromEvent,\n maxSize = Number.POSITIVE_INFINITY,\n minSize = 0,\n multiple = true,\n maxFiles = 0,\n onDragEnter,\n onDragLeave,\n onDragOver,\n onDrop,\n onDropAccepted,\n onDropRejected,\n onFileDialogCancel,\n onFileDialogOpen,\n useFsAccessApi = false,\n autoFocus = false,\n preventDropOnDocument = true,\n noClick = false,\n noKeyboard = false,\n noDrag = false,\n noDragEventsBubbling = false,\n noPaste = false,\n onError,\n validator,\n getErrorMessage\n } = props;\n\n // `acceptAttr` keeps wildcard MIME types (e.g. `image/*`) so the drag-time\n // `isDragAccept`/`isDragReject` check can react to a file's MIME type - file names\n // (hence extensions) aren't readable during a drag.\n const acceptAttr = useMemo(() => acceptPropAsAcceptAttr(accept), [accept]);\n // `inputAcceptAttr` drops a wildcard MIME type when it is paired with extensions, so the\n // native picker and drop-time validation enforce the extensions instead of accepting any\n // file of that type. See https://github.com/react-dropzone/react-dropzone/issues/1220\n const inputAcceptAttr = useMemo(\n () =>\n acceptPropAsAcceptAttr(accept, {\n omitWildcardMimeTypesWithExtensions: true\n }),\n [accept]\n );\n const pickerTypes = useMemo(() => pickerOptionsFromAccept(accept), [accept]);\n\n const onFileDialogOpenCb = useMemo<(...args: any[]) => void>(\n () => (typeof onFileDialogOpen === \"function\" ? onFileDialogOpen : noop),\n [onFileDialogOpen]\n );\n const onFileDialogCancelCb = useMemo<(...args: any[]) => void>(\n () => (typeof onFileDialogCancel === \"function\" ? onFileDialogCancel : noop),\n [onFileDialogCancel]\n );\n\n const rootRef = useRef<HTMLElement>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n\n const [state, dispatch] = useReducer(reducer, initialState);\n const {isFocused, isFileDialogActive} = state;\n\n // Mirror {isFileDialogActive} into a ref so the memoized drag handlers can read the current value\n // without being recreated (and churning getRootProps/getInputProps) every time the dialog toggles.\n const isFileDialogActiveRef = useRef(isFileDialogActive);\n isFileDialogActiveRef.current = isFileDialogActive;\n\n // Tracks the in-flight processing run - reading files (getFilesFromEvent) plus running an async\n // validator. A newer drop/selection aborts the previous run so slow async work can't resolve late\n // and clobber the state with stale results.\n const processingAbortRef = useRef<AbortController | null>(null);\n\n // Begin a processing run: supersede any run still in flight and flip {isProcessing} on. Returns\n // the run's AbortSignal, which downstream async steps check to bail if a newer run took over.\n const beginProcessing = useCallback(() => {\n processingAbortRef.current?.abort();\n const controller = new AbortController();\n processingAbortRef.current = controller;\n dispatch({type: \"setProcessing\", isProcessing: true});\n return controller.signal;\n }, []);\n\n // End a processing run by clearing {isProcessing} - but only if this run is still the active one.\n // A superseded run (signal aborted) leaves the flag to the run that replaced it.\n const endProcessing = useCallback((signal: AbortSignal) => {\n if (!signal.aborted) {\n dispatch({type: \"setProcessing\", isProcessing: false});\n }\n }, []);\n\n const fsAccessApiWorksRef = useRef(\n typeof window !== \"undefined\" && window.isSecureContext && useFsAccessApi && canUseFileSystemAccessAPI()\n );\n\n // Update file dialog active state when the window is focused on\n const onWindowFocus = () => {\n // Execute the timeout only if the file dialog is opened in the browser\n if (!fsAccessApiWorksRef.current && isFileDialogActive) {\n setTimeout(() => {\n if (inputRef.current) {\n const {files} = inputRef.current;\n\n if (!files?.length) {\n dispatch({type: \"closeDialog\"});\n onFileDialogCancelCb();\n }\n }\n }, 300);\n }\n };\n useEffect(() => {\n window.addEventListener(\"focus\", onWindowFocus, false);\n return () => {\n window.removeEventListener(\"focus\", onWindowFocus, false);\n };\n }, [inputRef, isFileDialogActive, onFileDialogCancelCb, fsAccessApiWorksRef]);\n\n const dragTargetsRef = useRef<EventTarget[]>([]);\n const globalDragTargetsRef = useRef<EventTarget[]>([]);\n const onDocumentDrop = (event: DragEvent) => {\n // This is a document-level, bubble-phase listener, so it runs *after* the event has already\n // bubbled through the dropzone root. If the drop landed inside the root and the instance's own\n // onDrop handler already prevented the default, there's nothing left to do.\n //\n // We must NOT bail out on `contains()` alone: when the dropzone is `disabled` or has `noDrag`,\n // the root has no onDrop handler, so nothing prevents the browser's default action and the file\n // is opened in the tab. Falling through to `preventDefault()` here keeps that from happening.\n // See https://github.com/react-dropzone/react-dropzone/issues/1362\n if (rootRef.current && event.target && rootRef.current.contains(event.target as Node) && event.defaultPrevented) {\n return;\n }\n event.preventDefault();\n dragTargetsRef.current = [];\n };\n\n useEffect(() => {\n if (preventDropOnDocument) {\n document.addEventListener(\"dragover\", onDocumentDragOver, false);\n document.addEventListener(\"drop\", onDocumentDrop, false);\n }\n\n return () => {\n if (preventDropOnDocument) {\n document.removeEventListener(\"dragover\", onDocumentDragOver);\n document.removeEventListener(\"drop\", onDocumentDrop);\n }\n };\n }, [rootRef, preventDropOnDocument]);\n\n // Track global drag state for document-level drag events\n useEffect(() => {\n const onDocumentDragEnter = (event: DragEvent) => {\n if (event.target) {\n globalDragTargetsRef.current = [...globalDragTargetsRef.current, event.target];\n }\n\n if (isEvtWithFiles(event)) {\n dispatch({isDragGlobal: true, type: \"setDragGlobal\"});\n }\n };\n\n const onDocumentDragLeave = (event: DragEvent) => {\n // Only deactivate once we've left all children\n globalDragTargetsRef.current = globalDragTargetsRef.current.filter(el => el !== event.target && el !== null);\n\n if (globalDragTargetsRef.current.length > 0) {\n return;\n }\n\n dispatch({isDragGlobal: false, type: \"setDragGlobal\"});\n };\n\n const onDocumentDragEnd = () => {\n globalDragTargetsRef.current = [];\n dispatch({isDragGlobal: false, type: \"setDragGlobal\"});\n };\n\n const onDocumentDropGlobal = () => {\n globalDragTargetsRef.current = [];\n dispatch({isDragGlobal: false, type: \"setDragGlobal\"});\n };\n\n document.addEventListener(\"dragenter\", onDocumentDragEnter, false);\n document.addEventListener(\"dragleave\", onDocumentDragLeave, false);\n document.addEventListener(\"dragend\", onDocumentDragEnd, false);\n document.addEventListener(\"drop\", onDocumentDropGlobal, false);\n\n return () => {\n document.removeEventListener(\"dragenter\", onDocumentDragEnter);\n document.removeEventListener(\"dragleave\", onDocumentDragLeave);\n document.removeEventListener(\"dragend\", onDocumentDragEnd);\n document.removeEventListener(\"drop\", onDocumentDropGlobal);\n };\n }, [rootRef]);\n\n // Auto focus the root when autoFocus is true\n useEffect(() => {\n if (!disabled && autoFocus && rootRef.current) {\n rootRef.current.focus();\n }\n return () => {};\n }, [rootRef, autoFocus, disabled]);\n\n const onErrCb = useCallback(\n (e: Error) => {\n if (onError) {\n onError(e);\n } else {\n // Let the user know something's gone wrong if they haven't provided the onError cb.\n console.error(e);\n }\n },\n [onError]\n );\n\n const onDragEnterCb = useCallback(\n (event: any) => {\n event.preventDefault();\n // Persist here because we need the event later after getFilesFromEvent() is done\n event.persist?.();\n stopPropagation(event);\n\n // Ignore drags onto the dropzone while the file picker dialog is open: the page underneath a\n // live picker shouldn't react to (or accept) dropped files. See #1455. preventDefault() above\n // still runs so the browser doesn't try to open/navigate to a dropped file.\n if (isFileDialogActiveRef.current) {\n return;\n }\n\n dragTargetsRef.current = [...dragTargetsRef.current, event.target];\n\n if (isEvtWithFiles(event)) {\n Promise.resolve(getFilesFromEvent(event))\n .then(files => {\n if (isPropagationStopped(event) && !noDragEventsBubbling) {\n return;\n }\n\n const fileCount = files.length;\n // During a drag we only have DataTransferItems (MIME type, no name/size), so the\n // custom validator can't run yet - a validator-configured dropzone is \"unknown\" until\n // drop rather than a misleading accept/reject. See getDragVerdict for the details.\n const verdict =\n fileCount > 0\n ? getDragVerdict({\n files: files as Array<File | DataTransferItem>,\n accept: acceptAttr,\n minSize,\n maxSize,\n multiple,\n maxFiles,\n validator\n })\n : null;\n\n dispatch({\n isDragAccept: verdict === \"accept\",\n isDragReject: verdict === \"reject\",\n isDragUnknown: verdict === \"unknown\",\n isDragActive: true,\n type: \"setDraggedFiles\"\n });\n\n if (onDragEnter) {\n onDragEnter(event);\n }\n })\n .catch(e => onErrCb(e));\n }\n },\n [\n getFilesFromEvent,\n onDragEnter,\n onErrCb,\n noDragEventsBubbling,\n acceptAttr,\n minSize,\n maxSize,\n multiple,\n maxFiles,\n validator\n ]\n );\n\n const onDragOverCb = useCallback(\n (event: any) => {\n event.preventDefault();\n event.persist?.();\n stopPropagation(event);\n\n // Ignore drags over the dropzone while the file picker dialog is open. See #1455.\n if (isFileDialogActiveRef.current) {\n return false;\n }\n\n const hasFiles = isEvtWithFiles(event);\n if (hasFiles && event.dataTransfer) {\n try {\n event.dataTransfer.dropEffect = \"copy\";\n } catch {\n /* no-op */\n }\n }\n\n if (hasFiles && onDragOver) {\n onDragOver(event);\n }\n\n return false;\n },\n [onDragOver, noDragEventsBubbling]\n );\n\n const onDragLeaveCb = useCallback(\n (event: any) => {\n event.preventDefault();\n event.persist?.();\n stopPropagation(event);\n\n // Only deactivate once the dropzone and all children have been left\n const targets = dragTargetsRef.current.filter(target => rootRef.current?.contains(target as Node));\n // Make sure to remove a target present multiple times only once\n // (Firefox may fire dragenter/dragleave multiple times on the same element)\n const targetIdx = targets.indexOf(event.target);\n if (targetIdx !== -1) {\n targets.splice(targetIdx, 1);\n }\n dragTargetsRef.current = targets;\n if (targets.length > 0) {\n return;\n }\n\n dispatch({\n type: \"setDraggedFiles\",\n isDragActive: false,\n isDragAccept: false,\n isDragReject: false,\n isDragUnknown: false\n });\n\n if (isEvtWithFiles(event) && onDragLeave) {\n onDragLeave(event);\n }\n },\n [rootRef, onDragLeave, noDragEventsBubbling]\n );\n\n const setFiles = useCallback(\n async (files: FileWithPath[], event: any, signal: AbortSignal) => {\n const localizeError = (error: FileError, file: File): FileError =>\n getErrorMessage ? {...error, message: getErrorMessage(error, file)} : error;\n\n // Commit the per-file verdicts: split accepted/rejected, cap the surplus, update state and\n // fire the onDrop callbacks. Runs synchronously so nested-dropzone ordering is preserved on\n // the fast path (an onDrop handler calling stopPropagation must do so before a parent's onDrop\n // check - see the noDragEventsBubbling tests).\n const commit = (results: Array<PerFileResult>) => {\n const acceptedFiles: FileWithPath[] = [];\n const fileRejections: FileRejection[] = [];\n\n results.forEach(({file, accepted, acceptError, sizeMatch, sizeError, customErrors}) => {\n if (accepted && sizeMatch && !customErrors) {\n acceptedFiles.push(file);\n } else {\n let errors: Array<FileError | null> = [acceptError, sizeError];\n\n if (customErrors) {\n errors = errors.concat(customErrors);\n }\n\n fileRejections.push({\n file,\n errors: errors.filter((e): e is FileError => e != null).map(error => localizeError(error, file))\n });\n }\n });\n\n // Cap the accepted files at the configured limit and reject only the surplus (the files past\n // the limit) with a too-many-files error, instead of rejecting the whole batch. The limit is 1\n // when {multiple} is false, and {maxFiles} when {multiple} is true (0 means no limit). Files\n // that already failed the per-file checks above are in {fileRejections} and don't count here.\n // See https://github.com/react-dropzone/react-dropzone/issues/1355\n // and https://github.com/react-dropzone/react-dropzone/issues/1358\n const acceptedFilesLimit = multiple ? (maxFiles >= 1 ? maxFiles : Number.POSITIVE_INFINITY) : 1;\n if (acceptedFiles.length > acceptedFilesLimit) {\n const surplusFiles = acceptedFiles.splice(acceptedFilesLimit);\n surplusFiles.forEach(file => {\n fileRejections.push({file, errors: [localizeError(TOO_MANY_FILES_REJECTION, file)]});\n });\n }\n\n // Clears isProcessing back to false (see the reducer) in the same update that sets the files.\n dispatch({\n acceptedFiles,\n fileRejections,\n type: \"setFiles\"\n });\n\n if (onDrop) {\n onDrop(acceptedFiles, fileRejections, event);\n }\n\n if (fileRejections.length > 0 && onDropRejected) {\n onDropRejected(fileRejections, event);\n }\n\n if (acceptedFiles.length > 0 && onDropAccepted) {\n onDropAccepted(acceptedFiles, event);\n }\n };\n\n // Run the built-in checks synchronously and invoke the validator (which may return a value or\n // a Promise). customErrors is left as-is here so we can tell sync from async below.\n const pending = files.map(file => {\n const [accepted, acceptError] = fileAccepted(file, inputAcceptAttr);\n const [sizeMatch, sizeError] = fileMatchSize(file, minSize, maxSize);\n const customErrors = validator ? validator(file) : null;\n return {file, accepted, acceptError, sizeMatch, sizeError, customErrors};\n });\n\n // Callers check signal.aborted right before invoking setFiles (synchronously, no await in\n // between), so this run is guaranteed live here - the supersession guards below only matter\n // after we await the validator.\n\n // Fast path: no validator, or a synchronous one. Commit synchronously - no extra microtask\n // hop, so nested-dropzone ordering is preserved (an onDrop handler calling stopPropagation\n // must run before a parent's onDrop check - see the noDragEventsBubbling tests). commit's\n // dispatch also clears isProcessing.\n if (!pending.some(({customErrors}) => isThenable(customErrors))) {\n commit(pending as Array<PerFileResult>);\n return;\n }\n\n // Async path: at least one validator returned a Promise. isProcessing is already on (set when\n // the run began, before getFilesFromEvent); keep guarding against supersession while we await.\n let results: Array<PerFileResult>;\n try {\n results = await Promise.all(\n pending.map(async ({customErrors, ...rest}) => ({...rest, customErrors: await customErrors}))\n );\n } catch (e) {\n // A validator threw/rejected. If a newer run already superseded this one, let it own the\n // state; otherwise clear the processing flag and report the error via onError.\n if (!signal.aborted) {\n endProcessing(signal);\n onErrCb(e as Error);\n }\n return;\n }\n\n // A newer drop landed while we were validating - discard these stale results.\n if (signal.aborted) {\n return;\n }\n\n commit(results);\n },\n [\n dispatch,\n multiple,\n inputAcceptAttr,\n minSize,\n maxSize,\n maxFiles,\n onDrop,\n onDropAccepted,\n onDropRejected,\n validator,\n getErrorMessage,\n onErrCb,\n endProcessing\n ]\n );\n\n const onDropCb = useCallback(\n (event: any) => {\n event.preventDefault();\n // Persist here because we need the event later after getFilesFromEvent() is done\n event.persist?.();\n stopPropagation(event);\n\n dragTargetsRef.current = [];\n\n // Ignore a drop landing on the dropzone while the file picker dialog is open (see #1455).\n // Guard on {event.dataTransfer} so only real drag-drops are suppressed: the input's change\n // event (a file picked from the dialog) also runs through here while the dialog is still\n // flagged active, and that path must keep working. Returning before the reset below leaves\n // the dialog flag intact.\n if (isFileDialogActiveRef.current && event.dataTransfer) {\n return;\n }\n\n // Clear drag state before we begin processing so beginProcessing's isProcessing isn't reset.\n dispatch({type: \"reset\"});\n\n if (isEvtWithFiles(event)) {\n // Processing spans reading the files (getFilesFromEvent) and running the validator.\n const signal = beginProcessing();\n Promise.resolve(getFilesFromEvent(event))\n .then(files => {\n // A newer drop superseded this one while reading files - it owns isProcessing now.\n if (signal.aborted) {\n return;\n }\n if (isPropagationStopped(event) && !noDragEventsBubbling) {\n endProcessing(signal);\n return;\n }\n // setFiles handles validator errors internally (routing them to onError); the outer\n // catch here only fires for a getFilesFromEvent failure.\n return setFiles(files as FileWithPath[], event, signal);\n })\n .catch(e => {\n if (!signal.aborted) {\n endProcessing(signal);\n onErrCb(e);\n }\n });\n }\n },\n [getFilesFromEvent, setFiles, onErrCb, noDragEventsBubbling, beginProcessing, endProcessing]\n );\n\n // Cb to add files pasted into the dropzone (e.g. a screenshot pasted with Ctrl/Cmd+V). Fires when\n // the root - or a focused descendant, so a child <textarea> works too - receives a paste. Reuses\n // the same read/validate/onDrop pipeline as a drop.\n const onPasteCb = useCallback(\n (event: any) => {\n // Only act on a paste that carries files. Bail before preventDefault() for text/other pastes\n // so pasting into a child input keeps working normally.\n if (!isEvtWithFiles(event)) {\n return;\n }\n event.preventDefault();\n // Persist here because we need the event later after getFilesFromEvent() is done\n event.persist?.();\n stopPropagation(event);\n\n // Processing spans reading the files (getFilesFromEvent) and running the validator.\n const signal = beginProcessing();\n Promise.resolve(getFilesFromEvent(event))\n .then(files => {\n // A newer drop/paste superseded this one while reading files - it owns isProcessing now.\n if (signal.aborted) {\n return;\n }\n if (isPropagationStopped(event) && !noDragEventsBubbling) {\n endProcessing(signal);\n return;\n }\n return setFiles(files as FileWithPath[], event, signal);\n })\n .catch(e => {\n if (!signal.aborted) {\n endProcessing(signal);\n onErrCb(e);\n }\n });\n },\n [getFilesFromEvent, setFiles, onErrCb, noDragEventsBubbling, beginProcessing, endProcessing]\n );\n\n // Fn for opening the file dialog programmatically\n const openFileDialog = useCallback(() => {\n // No point to use FS access APIs if context is not secure\n // https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts#feature_detection\n if (fsAccessApiWorksRef.current) {\n dispatch({type: \"openDialog\"});\n onFileDialogOpenCb();\n // https://developer.mozilla.org/en-US/docs/Web/API/window/showOpenFilePicker\n const opts = {\n multiple,\n types: pickerTypes\n };\n // Set once the user has picked file(s); processing then spans reading them (getFilesFromEvent)\n // and running the validator. Picker rejections (cancel, security) happen before this, so it\n // stays undefined there and no processing state is touched.\n let signal: AbortSignal | undefined;\n (window as any)\n .showOpenFilePicker(opts)\n .then((handles: any) => {\n signal = beginProcessing();\n return getFilesFromEvent(handles);\n })\n .then((files: Array<File | DataTransferItem>) => {\n // Close the dialog as soon as we have the selection; validation runs afterwards and is\n // reflected by isProcessing rather than by keeping the dialog \"active\".\n dispatch({type: \"closeDialog\"});\n // A drop elsewhere superseded this selection while reading files - it owns isProcessing.\n if (signal!.aborted) {\n return;\n }\n return setFiles(files as FileWithPath[], null, signal!);\n })\n .catch((e: any) => {\n // Clear any processing this run started (e.g. a getFilesFromEvent failure).\n if (signal) {\n endProcessing(signal);\n }\n // AbortError means the user canceled\n if (isAbort(e)) {\n onFileDialogCancelCb(e);\n dispatch({type: \"closeDialog\"});\n } else if (isSecurityError(e) || isNotAllowedError(e)) {\n // The FS access API is unusable here: either the context forbids it (SecurityError,\n // e.g. CORS) or the browser/platform blocked the picker (NotAllowedError, e.g. Edge\n // for Business - see https://github.com/react-dropzone/react-dropzone/issues/1429).\n // Stop using it and fall back to the native <input>.\n fsAccessApiWorksRef.current = false;\n if (inputRef.current) {\n inputRef.current.value = \"\";\n inputRef.current.click();\n } else {\n onErrCb(\n new Error(\n \"Cannot open the file picker because the https://developer.mozilla.org/en-US/docs/Web/API/File_System_Access_API is not supported and no <input> was provided.\"\n )\n );\n }\n } else {\n onErrCb(e);\n }\n });\n return;\n }\n\n if (inputRef.current) {\n dispatch({type: \"openDialog\"});\n onFileDialogOpenCb();\n inputRef.current.value = \"\";\n inputRef.current.click();\n }\n }, [\n dispatch,\n onFileDialogOpenCb,\n onFileDialogCancelCb,\n useFsAccessApi,\n setFiles,\n onErrCb,\n pickerTypes,\n multiple,\n beginProcessing,\n endProcessing\n ]);\n\n // Cb to open the file dialog when SPACE/ENTER occurs on the dropzone\n const onKeyDownCb = useCallback(\n (event: any) => {\n // Ignore keyboard events bubbling up the DOM tree\n if (!rootRef.current?.isEqualNode(event.target)) {\n return;\n }\n\n if (event.key === \" \" || event.key === \"Enter\" || event.keyCode === 32 || event.keyCode === 13) {\n event.preventDefault();\n openFileDialog();\n }\n },\n [rootRef, openFileDialog]\n );\n\n // Update focus state for the dropzone\n const onFocusCb = useCallback(() => {\n dispatch({type: \"focus\"});\n }, []);\n const onBlurCb = useCallback(() => {\n dispatch({type: \"blur\"});\n }, []);\n\n // Cb to open the file dialog when click occurs on the dropzone\n const onClickCb = useCallback(() => {\n if (noClick) {\n return;\n }\n\n // In IE11/Edge the file-browser dialog is blocking, therefore, use setTimeout()\n // to ensure React can handle state changes\n // See: https://github.com/react-dropzone/react-dropzone/issues/450\n if (isIeOrEdge()) {\n setTimeout(openFileDialog, 0);\n } else {\n openFileDialog();\n }\n }, [noClick, openFileDialog]);\n\n const composeHandler = (fn: any) => {\n return disabled ? null : fn;\n };\n\n const composeKeyboardHandler = (fn: any) => {\n return noKeyboard ? null : composeHandler(fn);\n };\n\n const composeDragHandler = (fn: any) => {\n return noDrag ? null : composeHandler(fn);\n };\n\n const composePasteHandler = (fn: any) => {\n return noPaste ? null : composeHandler(fn);\n };\n\n const stopPropagation = (event: any) => {\n if (noDragEventsBubbling) {\n event.stopPropagation();\n }\n };\n\n const getRootProps = useMemo(\n () =>\n ({\n refKey = \"ref\",\n role,\n onKeyDown,\n onFocus,\n onBlur,\n onClick,\n onDragEnter,\n onDragOver,\n onDragLeave,\n onDrop,\n onPaste,\n ...rest\n }: DropzoneRootProps = {}) => ({\n onKeyDown: composeKeyboardHandler(composeEventHandlers(onKeyDown, onKeyDownCb)),\n onFocus: composeKeyboardHandler(composeEventHandlers(onFocus, onFocusCb)),\n onBlur: composeKeyboardHandler(composeEventHandlers(onBlur, onBlurCb)),\n onClick: composeHandler(composeEventHandlers(onClick, onClickCb)),\n onDragEnter: composeDragHandler(composeEventHandlers(onDragEnter, onDragEnterCb)),\n onDragOver: composeDragHandler(composeEventHandlers(onDragOver, onDragOverCb)),\n onDragLeave: composeDragHandler(composeEventHandlers(onDragLeave, onDragLeaveCb)),\n onDrop: composeDragHandler(composeEventHandlers(onDrop, onDropCb)),\n onPaste: composePasteHandler(composeEventHandlers(onPaste, onPasteCb)),\n role: typeof role === \"string\" && role !== \"\" ? role : \"presentation\",\n [refKey]: rootRef,\n ...(!disabled && !noKeyboard ? {tabIndex: 0} : {}),\n ...(disabled ? {\"aria-disabled\": true} : {}),\n ...rest\n }),\n [\n rootRef,\n onKeyDownCb,\n onFocusCb,\n onBlurCb,\n onClickCb,\n onDragEnterCb,\n onDragOverCb,\n onDragLeaveCb,\n onDropCb,\n onPasteCb,\n noKeyboard,\n noDrag,\n noPaste,\n disabled\n ]\n );\n\n const onInputElementClick = useCallback((event: any) => {\n event.stopPropagation();\n }, []);\n\n const getInputProps = useMemo(\n () =>\n ({refKey = \"ref\", onChange, onClick, ...rest}: DropzoneInputProps = {}) => {\n const inputProps = {\n accept: inputAcceptAttr,\n multiple,\n type: \"file\",\n \"aria-label\": \"file upload\",\n // Hide the input without taking it out of flow. A visually-hidden input with\n // {position: absolute} makes the browser scroll the page to it whenever it gets\n // focus (e.g. inside a collapsed accordion), see #1413. Keeping it in flow as a\n // zero-size, transparent block avoids that while staying focusable so a {required}\n // input still triggers form validation, see #1268. Don't use {display: none} or\n // {visibility: hidden}: those make the input unfocusable and reintroduce #1268.\n style: {\n border: 0,\n display: \"block\",\n height: 0,\n margin: 0,\n opacity: 0,\n overflow: \"hidden\",\n padding: 0,\n width: 0\n },\n onChange: composeHandler(composeEventHandlers(onChange, onDropCb)),\n onClick: composeHandler(composeEventHandlers(onClick, onInputElementClick)),\n tabIndex: -1,\n [refKey]: inputRef\n };\n\n return {\n ...inputProps,\n ...rest\n };\n },\n [inputRef, accept, multiple, onDropCb, disabled]\n );\n\n return {\n ...state,\n isFocused: isFocused && !disabled,\n getRootProps,\n getInputProps,\n rootRef,\n inputRef,\n open: composeHandler(openFileDialog)\n } as unknown as DropzoneState;\n}\n\nfunction reducer(state: DropzoneInternalState, action: any): DropzoneInternalState {\n switch (action.type) {\n case \"focus\":\n return {\n ...state,\n isFocused: true\n };\n case \"blur\":\n return {\n ...state,\n isFocused: false\n };\n case \"openDialog\":\n return {\n ...initialState,\n isFileDialogActive: true\n };\n case \"closeDialog\":\n return {\n ...state,\n isFileDialogActive: false\n };\n case \"setDraggedFiles\":\n return {\n ...state,\n isDragActive: action.isDragActive,\n isDragAccept: action.isDragAccept,\n isDragReject: action.isDragReject,\n isDragUnknown: action.isDragUnknown\n };\n case \"setProcessing\":\n return {\n ...state,\n isProcessing: action.isProcessing\n };\n case \"setFiles\":\n return {\n ...state,\n acceptedFiles: action.acceptedFiles,\n fileRejections: action.fileRejections,\n isProcessing: false,\n isDragReject: false,\n isDragUnknown: false\n };\n case \"setDragGlobal\":\n return {\n ...state,\n isDragGlobal: action.isDragGlobal\n };\n case \"reset\":\n return {\n ...initialState\n };\n default:\n return state;\n }\n}\n\nfunction noop() {}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["attrAccept","fromEvent"],"sources":["../src/utils/index.ts","../src/index.tsx"],"sourcesContent":["import attrAccept from \"attr-accept\";\n\n// attr-accept ships as a CommonJS module (`module.exports = { __esModule: true, default: fn }`).\n// Bundler interop surfaces its default export inconsistently — as the function under Node/Vitest,\n// but as `{ default: fn }` in some browser bundles. Normalize to the function.\nconst accepts =\n typeof attrAccept === \"function\" ? attrAccept : (attrAccept as unknown as {default: typeof attrAccept}).default;\n\n/**\n * A map of accepted MIME types to file extensions, as passed to the `accept` prop.\n *\n * An extension value may be a single extension string or an array of them - both are\n * accepted, mirroring the shape of `window.showOpenFilePicker`'s `accept`.\n */\nexport interface Accept {\n [key: string]: string | readonly string[];\n}\n\n/**\n * A labeled group of accepted types, mirroring one entry of `window.showOpenFilePicker`'s\n * `types` option. Passing the `accept` prop as an array of these lets the File System Access\n * picker present multiple named filter rows instead of a single one (see\n * {@link pickerOptionsFromAccept}). The optional `description` labels the row; when omitted it\n * is derived from the group's extensions.\n *\n * Grouping only surfaces when the FS Access picker is actually used (`useFsAccessApi` +\n * a secure context + browser support). The native `<input>` fallback has no concept of groups\n * or descriptions, so every group is flattened into one accept attribute there.\n */\nexport interface AcceptGroup {\n description?: string;\n accept: Accept;\n}\n\n/**\n * A file rejection error.\n */\nexport interface FileError {\n message: string;\n code: ErrorCode | string;\n}\n\n/**\n * What a custom `validator` returns: a single error, a list of errors, or `null` when the file\n * passes. A validator may return the result directly (synchronous) or wrapped in a `Promise`\n * (asynchronous, e.g. reading image dimensions or calling an external service).\n */\nexport type ValidatorResult = FileError | readonly FileError[] | null;\n\n// Error codes\nexport const FILE_INVALID_TYPE = \"file-invalid-type\";\nexport const FILE_TOO_LARGE = \"file-too-large\";\nexport const FILE_TOO_SMALL = \"file-too-small\";\nexport const TOO_MANY_FILES = \"too-many-files\";\n\nexport enum ErrorCode {\n FileInvalidType = \"file-invalid-type\",\n FileTooLarge = \"file-too-large\",\n FileTooSmall = \"file-too-small\",\n TooManyFiles = \"too-many-files\"\n}\n\nexport function getInvalidTypeRejectionErr(accept: string = \"\"): FileError {\n const acceptArr = accept.split(\",\");\n const msg = acceptArr.length > 1 ? `one of ${acceptArr.join(\", \")}` : acceptArr[0];\n\n return {\n code: FILE_INVALID_TYPE,\n message: `File type must be ${msg}`\n };\n}\n\nconst FILE_SIZE_UNITS = [\"KB\", \"MB\", \"GB\", \"TB\", \"PB\"];\n\n/**\n * Format a byte count into a human-readable string, e.g. `1111` -> `1.08 KB`.\n * Values below 1 KB are kept in bytes to preserve the singular/plural wording.\n */\nfunction formatBytes(bytes: number): string {\n if (bytes < 1024) {\n return `${bytes} ${bytes === 1 ? \"byte\" : \"bytes\"}`;\n }\n\n let size = bytes / 1024;\n let unitIndex = 0;\n while (size >= 1024 && unitIndex < FILE_SIZE_UNITS.length - 1) {\n size /= 1024;\n unitIndex++;\n }\n\n // Round to 2 decimals, then drop trailing zeros (1.00 -> 1, 1.50 -> 1.5).\n return `${Number(size.toFixed(2))} ${FILE_SIZE_UNITS[unitIndex]}`;\n}\n\nexport function getTooLargeRejectionErr(maxSize: number): FileError {\n return {\n code: FILE_TOO_LARGE,\n message: `File is larger than ${formatBytes(maxSize)}`\n };\n}\n\nexport function getTooSmallRejectionErr(minSize: number): FileError {\n return {\n code: FILE_TOO_SMALL,\n message: `File is smaller than ${formatBytes(minSize)}`\n };\n}\n\nexport const TOO_MANY_FILES_REJECTION: FileError = {\n code: TOO_MANY_FILES,\n message: \"Too many files\"\n};\n\n/**\n * Check if the given file is a DataTransferItem with an empty type.\n *\n * During drag events, browsers may return DataTransferItem objects instead of File objects.\n * Some browsers (e.g., Chrome) return an empty MIME type for certain file types (like .md files)\n * on DataTransferItem during drag events, even though the type is correctly set during drop.\n */\nexport function isDataTransferItemWithEmptyType(file: File | DataTransferItem): boolean {\n return file.type === \"\" && typeof (file as DataTransferItem).getAsFile === \"function\";\n}\n\n/**\n * Check if file is accepted.\n *\n * Firefox versions prior to 53 return a bogus MIME type for every file drag,\n * so dragovers with that MIME type will always be accepted.\n *\n * Chrome/other browsers may return an empty MIME type for files during drag events,\n * so we accept those as well (we'll validate properly on drop).\n */\nexport function fileAccepted(file: File, accept?: string): [boolean, FileError | null] {\n const isAcceptable =\n file.type === \"application/x-moz-file\" || accepts(file, accept ?? \"\") || isDataTransferItemWithEmptyType(file);\n return [isAcceptable, isAcceptable ? null : getInvalidTypeRejectionErr(accept)];\n}\n\nexport function fileMatchSize(\n file: {size?: number | null},\n minSize?: number,\n maxSize?: number\n): [boolean, FileError | null] {\n if (isDefined(file.size)) {\n if (isDefined(minSize) && isDefined(maxSize)) {\n if (file.size > maxSize) return [false, getTooLargeRejectionErr(maxSize)];\n if (file.size < minSize) return [false, getTooSmallRejectionErr(minSize)];\n } else if (isDefined(minSize) && file.size < minSize) {\n return [false, getTooSmallRejectionErr(minSize)];\n } else if (isDefined(maxSize) && file.size > maxSize) {\n return [false, getTooLargeRejectionErr(maxSize)];\n }\n }\n return [true, null];\n}\n\nfunction isDefined<T>(value: T): value is NonNullable<T> {\n return value !== undefined && value !== null;\n}\n\n/**\n * Check if a value is thenable (Promise-like), used to tell a synchronous validator result from an\n * asynchronous one.\n */\nexport function isThenable(value: unknown): value is PromiseLike<unknown> {\n return value != null && typeof (value as {then?: unknown}).then === \"function\";\n}\n\nexport function allFilesAccepted({\n files,\n accept,\n minSize,\n maxSize,\n multiple,\n maxFiles = 0,\n validator\n}: {\n files: File[];\n accept?: string;\n minSize?: number;\n maxSize?: number;\n multiple?: boolean;\n maxFiles?: number;\n validator?: (file: File) => FileError | readonly FileError[] | null;\n}): boolean {\n if ((!multiple && files.length > 1) || (multiple && maxFiles >= 1 && files.length > maxFiles)) {\n return false;\n }\n\n return files.every(file => {\n const [accepted] = fileAccepted(file, accept);\n const [sizeMatch] = fileMatchSize(file, minSize, maxSize);\n const customErrors = validator ? validator(file) : null;\n return accepted && sizeMatch && !customErrors;\n });\n}\n\n/**\n * The outcome of the drag-time acceptance check.\n *\n * - `accept` - every file passes the checks we can evaluate during a drag.\n * - `reject` - at least one file confidently fails a check we can fully evaluate during a\n * drag (the file count, or a non-empty MIME type that doesn't match `accept`).\n * - `unknown` - nothing confidently fails, but the outcome can't be confirmed until drop,\n * because a custom `validator` is configured and can't be evaluated yet.\n */\nexport type DragVerdict = \"accept\" | \"reject\" | \"unknown\";\n\n/**\n * Classify a set of dragged files for the `isDragAccept`/`isDragReject`/`isDragUnknown` states.\n *\n * During `dragenter`/`dragover` the browser only exposes `DataTransferItem`s, which carry a MIME\n * `type` but no file name, extension or size (see https://html.spec.whatwg.org/multipage/dnd.html#dndevents).\n * So the drag-time check is deliberately optimistic about anything it can't see:\n *\n * - The custom `validator` is **never** run here. It is typed `(file: File) => ...` and users\n * routinely read `file.name`/`file.size`, which are `undefined` on a `DataTransferItem` - running\n * it would throw and abort the whole drag handler (leaving `isDragActive` stuck at `false`).\n * See https://github.com/react-dropzone/react-dropzone/issues/1408\n * - When a `validator` is configured we therefore can't promise the files are acceptable, so the\n * verdict is `unknown` rather than a misleading `reject` (or a premature `accept`).\n * See https://github.com/react-dropzone/react-dropzone/issues/1244\n *\n * The full check (including the `validator`) still runs on drop in {@link fileAccepted}/`setFiles`.\n */\nexport function getDragVerdict({\n files,\n accept,\n minSize,\n maxSize,\n multiple,\n maxFiles = 0,\n validator\n}: {\n files: Array<File | DataTransferItem>;\n accept?: string;\n minSize?: number;\n maxSize?: number;\n multiple?: boolean;\n maxFiles?: number;\n // The validator is never invoked here (see the note above), so its async variant is accepted\n // purely so the same `validator` prop is assignable during a drag.\n validator?: (file: File) => ValidatorResult | Promise<ValidatorResult>;\n}): DragVerdict {\n // The file count is knowable during a drag, so an over-the-limit selection is a confident reject.\n if ((!multiple && files.length > 1) || (multiple && maxFiles >= 1 && files.length > maxFiles)) {\n return \"reject\";\n }\n\n const confidentlyRejected = files.some(file => {\n const [accepted] = fileAccepted(file as File, accept);\n const [sizeMatch] = fileMatchSize(file as File, minSize, maxSize);\n return !accepted || !sizeMatch;\n });\n if (confidentlyRejected) {\n return \"reject\";\n }\n\n // Built-in checks pass. A custom validator can only ever add rejections on drop, never rescue\n // one - so with a validator present the drag outcome is unknown until we have real Files.\n return validator ? \"unknown\" : \"accept\";\n}\n\n// React's synthetic events has event.isPropagationStopped,\n// but to remain compatibility with other libs (Preact) fall back\n// to check event.cancelBubble\nexport function isPropagationStopped(event: any): boolean {\n if (typeof event.isPropagationStopped === \"function\") {\n return event.isPropagationStopped();\n } else if (typeof event.cancelBubble !== \"undefined\") {\n return event.cancelBubble;\n }\n return false;\n}\n\nexport function isEvtWithFiles(event: any): boolean {\n // A paste (ClipboardEvent) carries its DataTransfer under {clipboardData} rather than\n // {dataTransfer}, so a pasted screenshot is detected the same way as a drop.\n const dataTransfer = event.dataTransfer ?? event.clipboardData;\n if (!dataTransfer) {\n return !!event.target && !!event.target.files;\n }\n // https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/types\n // https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/Recommended_drag_types#file\n // Some Chromium drags omit \"Files\" from types (e.g. reporting only [\"text/plain\"])\n // while still exposing a kind: \"file\" entry in items - the same signal file-selector\n // uses to extract the files. Accept either so detection stays consistent. See #1409.\n return (\n Array.prototype.some.call(\n dataTransfer.types,\n (type: string) => type === \"Files\" || type === \"application/x-moz-file\"\n ) || Array.prototype.some.call(dataTransfer.items ?? [], isKindFile)\n );\n}\n\nexport function isKindFile(item: any): boolean {\n return typeof item === \"object\" && item !== null && item.kind === \"file\";\n}\n\n// allow the entire document to be a drag target\nexport function onDocumentDragOver(event: Event): void {\n event.preventDefault();\n}\n\nfunction isIe(userAgent: string): boolean {\n return userAgent.indexOf(\"MSIE\") !== -1 || userAgent.indexOf(\"Trident/\") !== -1;\n}\n\nfunction isEdge(userAgent: string): boolean {\n return userAgent.indexOf(\"Edge/\") !== -1;\n}\n\nexport function isIeOrEdge(userAgent: string = window.navigator.userAgent): boolean {\n return isIe(userAgent) || isEdge(userAgent);\n}\n\n/**\n * This is intended to be used to compose event handlers.\n * They are executed in order until one of them calls `event.isPropagationStopped()`.\n * Note that the check is done on the first invoke too,\n * meaning that if propagation was stopped before invoking the fns,\n * no handlers will be executed.\n */\nexport function composeEventHandlers(\n ...fns: Array<((event: any, ...args: any[]) => void) | null | undefined>\n): (event: any, ...args: any[]) => boolean {\n return (event: any, ...args: any[]) =>\n fns.some(fn => {\n if (!isPropagationStopped(event) && fn) {\n fn(event, ...args);\n }\n return isPropagationStopped(event);\n });\n}\n\n/**\n * canUseFileSystemAccessAPI checks if the File System Access API is supported by the browser.\n */\nexport function canUseFileSystemAccessAPI(): boolean {\n return \"showOpenFilePicker\" in window;\n}\n\n/**\n * Coerce an `accept` extension value to an array. `window.showOpenFilePicker` allows a single\n * extension string as well as an array, so we accept both and normalize to an array. Anything\n * else (a malformed value) collapses to an empty list.\n */\nfunction toExtensions(ext: string | readonly string[] | undefined): readonly string[] {\n if (Array.isArray(ext)) {\n return ext;\n }\n if (typeof ext === \"string\") {\n return [ext];\n }\n return [];\n}\n\n/**\n * Normalize either `accept` form to the internal array of `{description, accept}` groups.\n *\n * - The object form (`{mime: ext}`) becomes a single group; its `description` (which the object\n * form can't express) is derived from the extensions like any other group.\n * - The array form is passed through; entries missing an `accept` map are dropped.\n *\n * In both cases a missing `description` is filled in later from the group's extensions (see\n * {@link describeAccept}), so the picker always gets the non-empty description it requires\n * (https://crbug.com/1264708). Returns `undefined` when no `accept` is provided.\n */\nfunction normalizeAcceptGroups(accept?: Accept | readonly AcceptGroup[]): AcceptGroup[] | undefined {\n if (!isDefined(accept)) {\n return undefined;\n }\n if (Array.isArray(accept)) {\n return (accept as readonly AcceptGroup[]).filter(group => isDefined(group) && isDefined(group.accept));\n }\n return [{accept: accept as Accept}];\n}\n\n/**\n * Build a human-readable label for a picker group from its (validated) accept map, used when the\n * caller doesn't supply a `description`. Prefer the file extensions, fall back to the MIME types,\n * then to a generic label - `showOpenFilePicker` requires a non-empty description (crbug 1264708).\n */\nfunction describeAccept(accept: Accept): string {\n const extensions: string[] = [];\n const mimeTypes = Object.keys(accept);\n for (const ext of Object.values(accept)) {\n for (const e of toExtensions(ext)) {\n if (!extensions.includes(e)) {\n extensions.push(e);\n }\n }\n }\n if (extensions.length > 0) {\n return extensions.join(\", \");\n }\n if (mimeTypes.length > 0) {\n return mimeTypes.join(\", \");\n }\n return \"Files\";\n}\n\n/**\n * Merge every `accept` group into a single MIME-type -> extensions map. Duplicate MIME keys union\n * their extensions. This flattened map drives the native `<input accept>` attribute and the\n * drag/drop validators, which have no concept of groups or descriptions.\n */\nexport function flattenAccept(accept?: Accept | readonly AcceptGroup[]): Accept | undefined {\n const groups = normalizeAcceptGroups(accept);\n if (!isDefined(groups)) {\n return undefined;\n }\n const merged: Record<string, string[]> = {};\n for (const group of groups) {\n for (const [mimeType, ext] of Object.entries(group.accept)) {\n const existing = merged[mimeType] ?? (merged[mimeType] = []);\n for (const e of toExtensions(ext)) {\n if (!existing.includes(e)) {\n existing.push(e);\n }\n }\n }\n }\n return merged;\n}\n\n/**\n * Convert the `{accept}` dropzone prop to the `{types}` option for showOpenFilePicker.\n *\n * Each group becomes one filter row in the picker. Invalid MIME types / extensions are dropped\n * with a warning; a group left with no valid entries is omitted entirely (showOpenFilePicker\n * rejects an empty `accept`). Returns `undefined` when nothing valid remains.\n */\nexport function pickerOptionsFromAccept(\n accept?: Accept | readonly AcceptGroup[]\n): Array<{description: string; accept: Accept}> | undefined {\n const groups = normalizeAcceptGroups(accept);\n if (!isDefined(groups)) {\n return undefined;\n }\n\n const options = groups\n .map(group => {\n const acceptForPicker = Object.entries(group.accept)\n .filter(([mimeType, ext]) => {\n let ok = true;\n\n if (!isMIMEType(mimeType)) {\n console.warn(\n `Skipped \"${mimeType}\" because it is not a valid MIME type. Check https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types for a list of valid MIME types.`\n );\n ok = false;\n }\n\n const isExtInput = Array.isArray(ext) || typeof ext === \"string\";\n if (!isExtInput || !toExtensions(ext).every(isExt)) {\n console.warn(`Skipped \"${mimeType}\" because an invalid file extension was provided.`);\n ok = false;\n }\n\n return ok;\n })\n .reduce<Accept>((agg, [mimeType, ext]) => {\n agg[mimeType] = toExtensions(ext);\n return agg;\n }, {});\n\n return {\n description:\n isDefined(group.description) && group.description !== \"\"\n ? group.description\n : describeAccept(acceptForPicker),\n accept: acceptForPicker\n };\n })\n // Drop groups with no valid entries - showOpenFilePicker rejects an empty accept map.\n .filter(option => Object.keys(option.accept).length > 0);\n\n return options.length > 0 ? options : undefined;\n}\n\n/**\n * Convert the `{accept}` dropzone prop to a comma-separated accept attribute string.\n *\n * When `omitWildcardMimeTypesWithExtensions` is set, a wildcard MIME type (e.g. `image/*`)\n * that is paired with explicit extensions is dropped in favour of those extensions. The\n * accept attribute is an OR list, so leaving `image/*` in would make both the native file\n * picker and the drop-time validator accept ANY file of that type, ignoring the extension\n * restriction. The drag-time `isDragAccept` check keeps the wildcard because file names\n * (and therefore extensions) aren't readable during a drag.\n *\n * See https://github.com/react-dropzone/react-dropzone/issues/1220\n */\nexport function acceptPropAsAcceptAttr(\n accept?: Accept,\n {omitWildcardMimeTypesWithExtensions = false}: {omitWildcardMimeTypesWithExtensions?: boolean} = {}\n): string | undefined {\n if (isDefined(accept)) {\n return (\n Object.entries(accept)\n .reduce<string[]>((a, [mimeType, extVal]) => {\n const ext = toExtensions(extVal);\n if (omitWildcardMimeTypesWithExtensions && isMIMETypeWildcard(mimeType) && ext.some(isExt)) {\n a.push(...ext);\n } else {\n a.push(mimeType, ...ext);\n }\n return a;\n }, [])\n // Silently discard invalid entries as pickerOptionsFromAccept warns about these\n .filter(v => isMIMEType(v) || isExt(v))\n .join(\",\")\n );\n }\n\n return undefined;\n}\n\n/**\n * Check if v is an exception caused by aborting a request (e.g window.showOpenFilePicker()).\n */\nexport function isAbort(v: any): boolean {\n return v instanceof DOMException && (v.name === \"AbortError\" || v.code === v.ABORT_ERR);\n}\n\n/**\n * Check if v is a security error.\n */\nexport function isSecurityError(v: any): boolean {\n return v instanceof DOMException && (v.name === \"SecurityError\" || v.code === v.SECURITY_ERR);\n}\n\n/**\n * Check if v is a \"not allowed\" error.\n *\n * Some browsers/configurations block `window.showOpenFilePicker()` outright and reject with a\n * `NotAllowedError` instead of showing the picker (e.g. Microsoft Edge for Business, or other\n * restrictive enterprise/security policies). We treat this like a security error and fall back\n * to the native `<input>`. See https://github.com/react-dropzone/react-dropzone/issues/1429\n */\nexport function isNotAllowedError(v: any): boolean {\n return v instanceof DOMException && v.name === \"NotAllowedError\";\n}\n\n/**\n * Check if v is a MIME type string.\n */\nexport function isMIMEType(v: string): boolean {\n return (\n v === \"audio/*\" ||\n v === \"video/*\" ||\n v === \"image/*\" ||\n v === \"text/*\" ||\n v === \"application/*\" ||\n /\\w+\\/[-+.\\w]+/g.test(v)\n );\n}\n\n/**\n * Check if v is a wildcard MIME type (e.g. `image/*`).\n */\nexport function isMIMETypeWildcard(v: string): boolean {\n return v.endsWith(\"/*\");\n}\n\n/**\n * Check if v is a file extension.\n */\nexport function isExt(v: string): boolean {\n return /^.*\\.[\\w]+$/.test(v);\n}\n","import {fromEvent} from \"file-selector\";\nimport type {FileWithPath} from \"file-selector\";\nimport type * as React from \"react\";\nimport {forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useReducer, useRef} from \"react\";\nimport {\n acceptPropAsAcceptAttr,\n canUseFileSystemAccessAPI,\n composeEventHandlers,\n ErrorCode,\n fileAccepted,\n fileMatchSize,\n flattenAccept,\n getDragVerdict,\n isAbort,\n isEvtWithFiles,\n isIeOrEdge,\n isNotAllowedError,\n isThenable,\n isPropagationStopped,\n isSecurityError,\n onDocumentDragOver,\n pickerOptionsFromAccept,\n TOO_MANY_FILES_REJECTION\n} from \"./utils\";\nimport type {Accept, AcceptGroup, FileError, ValidatorResult} from \"./utils\";\n\nexport type {Accept, AcceptGroup, FileError, FileWithPath, ValidatorResult};\nexport {ErrorCode};\n\nexport interface DropzoneProps extends DropzoneOptions {\n children?: (state: DropzoneState) => React.ReactElement;\n}\n\nexport interface FileRejection {\n file: FileWithPath;\n errors: readonly FileError[];\n}\n\ntype SharedProps = \"multiple\" | \"onDragEnter\" | \"onDragOver\" | \"onDragLeave\";\n\nexport type DropzoneOptions = Pick<React.HTMLProps<HTMLElement>, SharedProps> & {\n accept?: Accept | AcceptGroup[];\n minSize?: number;\n maxSize?: number;\n maxFiles?: number;\n preventDropOnDocument?: boolean;\n noClick?: boolean;\n noKeyboard?: boolean;\n noDrag?: boolean;\n noDragEventsBubbling?: boolean;\n /**\n * If true, disables paste-to-upload. By default, when the dropzone (or a focused child) receives a\n * paste that carries files - e.g. a screenshot pasted with Ctrl/Cmd+V - those files go through the\n * same `accept`/size/`validator` checks and `onDrop` callbacks as a drop. Pastes with no files\n * (plain text, etc.) are ignored and left untouched. See\n * https://github.com/react-dropzone/react-dropzone/issues/1210\n */\n noPaste?: boolean;\n disabled?: boolean;\n onDrop?: <T extends File>(acceptedFiles: T[], fileRejections: FileRejection[], event: DropEvent) => void;\n onDropAccepted?: <T extends File>(files: T[], event: DropEvent) => void;\n onDropRejected?: (fileRejections: FileRejection[], event: DropEvent) => void;\n getFilesFromEvent?: (event: DropEvent | Array<FileSystemFileHandle>) => Promise<Array<File | DataTransferItem>>;\n onFileDialogCancel?: () => void;\n onFileDialogOpen?: () => void;\n onError?: (err: Error) => void;\n /**\n * Custom validation, run once per file on drop/selection. Return `null` to accept the file, or a\n * {@link FileError} (or array of them) to reject it. May be `async` (return a `Promise`) to support\n * checks that can't run synchronously - e.g. reading image dimensions, inspecting file contents,\n * or calling an external service. While an async validator is pending, {@link DropzoneState.isProcessing}\n * is `true`, and `onDrop`/`onDropAccepted`/`onDropRejected` fire only once it settles. If the\n * validator throws or rejects, `onError` is called and the drop is discarded.\n *\n * Note: the validator never runs during a drag (a `DataTransferItem` has no name/size), so a\n * validator-configured dropzone is `isDragUnknown` until drop.\n */\n validator?: <T extends File>(file: T) => ValidatorResult | Promise<ValidatorResult>;\n /**\n * Override the message of any rejection error (built-in or custom). Called once per error;\n * receives the error and the file it belongs to and returns the message to use. Return\n * `error.message` for codes you don't want to change. Useful for localizing error messages.\n */\n getErrorMessage?: (error: FileError, file: File) => string;\n useFsAccessApi?: boolean;\n autoFocus?: boolean;\n};\n\nexport type DropEvent =\n | React.DragEvent<HTMLElement>\n | React.ChangeEvent<HTMLInputElement>\n | React.ClipboardEvent<HTMLElement>\n | DragEvent\n | ClipboardEvent\n | Event;\n\nexport interface DropzoneRef {\n open: () => void;\n}\n\nexport type DropzoneState = DropzoneRef & {\n isFocused: boolean;\n isDragActive: boolean;\n isDragAccept: boolean;\n isDragReject: boolean;\n isDragUnknown: boolean;\n isDragGlobal: boolean;\n isFileDialogActive: boolean;\n /**\n * `true` while a drop/selection is being processed asynchronously - i.e. while `getFilesFromEvent`\n * reads the files and/or an async {@link DropzoneOptions.validator} runs. Spans the whole pipeline,\n * from when files start being read until validation settles. When both are synchronous (the default\n * `getFilesFromEvent` with no/async-free validator) the work resolves within a microtask, so it's\n * only observable for genuinely async work. Use it to show a spinner or disable UI while processing.\n */\n isProcessing: boolean;\n acceptedFiles: readonly FileWithPath[];\n fileRejections: readonly FileRejection[];\n rootRef: React.RefObject<HTMLElement>;\n inputRef: React.RefObject<HTMLInputElement>;\n getRootProps: <T extends DropzoneRootProps>(props?: T) => T;\n getInputProps: <T extends DropzoneInputProps>(props?: T) => T;\n};\n\nexport interface DropzoneRootProps extends React.HTMLAttributes<HTMLElement> {\n refKey?: string;\n [key: string]: any;\n}\n\nexport interface DropzoneInputProps extends React.InputHTMLAttributes<HTMLInputElement> {\n refKey?: string;\n}\n\n/**\n * Convenience wrapper component for the `useDropzone` hook\n *\n * ```jsx\n * <Dropzone>\n * {({getRootProps, getInputProps}) => (\n * <div {...getRootProps()}>\n * <input {...getInputProps()} />\n * <p>Drag 'n' drop some files here, or click to select files</p>\n * </div>\n * )}\n * </Dropzone>\n * ```\n */\nconst Dropzone: React.ForwardRefExoticComponent<DropzoneProps & React.RefAttributes<DropzoneRef>> = forwardRef<\n DropzoneRef,\n DropzoneProps\n>(({children, ...params}, ref) => {\n const {open, ...props} = useDropzone(params);\n\n useImperativeHandle(ref, () => ({open}), [open]);\n\n return <>{children?.({...props, open})}</>;\n});\n\nDropzone.displayName = \"Dropzone\";\n\nexport default Dropzone;\n\ninterface DropzoneInternalState {\n isFocused: boolean;\n isFileDialogActive: boolean;\n isDragActive: boolean;\n isDragAccept: boolean;\n isDragReject: boolean;\n isDragUnknown: boolean;\n isDragGlobal: boolean;\n isProcessing: boolean;\n acceptedFiles: FileWithPath[];\n fileRejections: FileRejection[];\n}\n\n/**\n * The per-file outcome of the built-in checks plus the (resolved) custom validator, assembled in\n * setFiles before the accepted/rejected split.\n */\ninterface PerFileResult {\n file: FileWithPath;\n accepted: boolean;\n acceptError: FileError | null;\n sizeMatch: boolean;\n sizeError: FileError | null;\n customErrors: ValidatorResult;\n}\n\nconst initialState: DropzoneInternalState = {\n isFocused: false,\n isFileDialogActive: false,\n isDragActive: false,\n isDragAccept: false,\n isDragReject: false,\n isDragUnknown: false,\n isDragGlobal: false,\n isProcessing: false,\n acceptedFiles: [],\n fileRejections: []\n};\n\n/**\n * A React hook that creates a drag 'n' drop area.\n *\n * ```jsx\n * function MyDropzone(props) {\n * const {getRootProps, getInputProps} = useDropzone({\n * onDrop: acceptedFiles => {\n * // do something with the File objects, e.g. upload to some server\n * }\n * });\n * return (\n * <div {...getRootProps()}>\n * <input {...getInputProps()} />\n * <p>Drag and drop some files here, or click to select files</p>\n * </div>\n * )\n * }\n * ```\n */\nexport function useDropzone(props: DropzoneOptions = {}): DropzoneState {\n const {\n accept,\n disabled = false,\n getFilesFromEvent = fromEvent,\n maxSize = Number.POSITIVE_INFINITY,\n minSize = 0,\n multiple = true,\n maxFiles = 0,\n onDragEnter,\n onDragLeave,\n onDragOver,\n onDrop,\n onDropAccepted,\n onDropRejected,\n onFileDialogCancel,\n onFileDialogOpen,\n useFsAccessApi = false,\n autoFocus = false,\n preventDropOnDocument = true,\n noClick = false,\n noKeyboard = false,\n noDrag = false,\n noDragEventsBubbling = false,\n noPaste = false,\n onError,\n validator,\n getErrorMessage\n } = props;\n\n // `accept` may be a MIME->extensions map or an array of labeled groups (for the FS Access\n // picker). Flatten it to a single map for the native `<input>` and the drag/drop validators,\n // which have no concept of groups; the picker keeps the groups via `pickerTypes` below.\n const flatAccept = useMemo(() => flattenAccept(accept), [accept]);\n // `acceptAttr` keeps wildcard MIME types (e.g. `image/*`) so the drag-time\n // `isDragAccept`/`isDragReject` check can react to a file's MIME type - file names\n // (hence extensions) aren't readable during a drag.\n const acceptAttr = useMemo(() => acceptPropAsAcceptAttr(flatAccept), [flatAccept]);\n // `inputAcceptAttr` drops a wildcard MIME type when it is paired with extensions, so the\n // native picker and drop-time validation enforce the extensions instead of accepting any\n // file of that type. See https://github.com/react-dropzone/react-dropzone/issues/1220\n const inputAcceptAttr = useMemo(\n () =>\n acceptPropAsAcceptAttr(flatAccept, {\n omitWildcardMimeTypesWithExtensions: true\n }),\n [flatAccept]\n );\n const pickerTypes = useMemo(() => pickerOptionsFromAccept(accept), [accept]);\n\n const onFileDialogOpenCb = useMemo<(...args: any[]) => void>(\n () => (typeof onFileDialogOpen === \"function\" ? onFileDialogOpen : noop),\n [onFileDialogOpen]\n );\n const onFileDialogCancelCb = useMemo<(...args: any[]) => void>(\n () => (typeof onFileDialogCancel === \"function\" ? onFileDialogCancel : noop),\n [onFileDialogCancel]\n );\n\n const rootRef = useRef<HTMLElement>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n\n const [state, dispatch] = useReducer(reducer, initialState);\n const {isFocused, isFileDialogActive} = state;\n\n // Mirror {isFileDialogActive} into a ref so the memoized drag handlers can read the current value\n // without being recreated (and churning getRootProps/getInputProps) every time the dialog toggles.\n const isFileDialogActiveRef = useRef(isFileDialogActive);\n isFileDialogActiveRef.current = isFileDialogActive;\n\n // Tracks the in-flight processing run - reading files (getFilesFromEvent) plus running an async\n // validator. A newer drop/selection aborts the previous run so slow async work can't resolve late\n // and clobber the state with stale results.\n const processingAbortRef = useRef<AbortController | null>(null);\n\n // Begin a processing run: supersede any run still in flight and flip {isProcessing} on. Returns\n // the run's AbortSignal, which downstream async steps check to bail if a newer run took over.\n const beginProcessing = useCallback(() => {\n processingAbortRef.current?.abort();\n const controller = new AbortController();\n processingAbortRef.current = controller;\n dispatch({type: \"setProcessing\", isProcessing: true});\n return controller.signal;\n }, []);\n\n // End a processing run by clearing {isProcessing} - but only if this run is still the active one.\n // A superseded run (signal aborted) leaves the flag to the run that replaced it.\n const endProcessing = useCallback((signal: AbortSignal) => {\n if (!signal.aborted) {\n dispatch({type: \"setProcessing\", isProcessing: false});\n }\n }, []);\n\n const fsAccessApiWorksRef = useRef(\n typeof window !== \"undefined\" && window.isSecureContext && useFsAccessApi && canUseFileSystemAccessAPI()\n );\n\n // Update file dialog active state when the window is focused on\n const onWindowFocus = () => {\n // Execute the timeout only if the file dialog is opened in the browser\n if (!fsAccessApiWorksRef.current && isFileDialogActive) {\n setTimeout(() => {\n if (inputRef.current) {\n const {files} = inputRef.current;\n\n if (!files?.length) {\n dispatch({type: \"closeDialog\"});\n onFileDialogCancelCb();\n }\n }\n }, 300);\n }\n };\n useEffect(() => {\n window.addEventListener(\"focus\", onWindowFocus, false);\n return () => {\n window.removeEventListener(\"focus\", onWindowFocus, false);\n };\n }, [inputRef, isFileDialogActive, onFileDialogCancelCb, fsAccessApiWorksRef]);\n\n const dragTargetsRef = useRef<EventTarget[]>([]);\n const globalDragTargetsRef = useRef<EventTarget[]>([]);\n const onDocumentDrop = (event: DragEvent) => {\n // This is a document-level, bubble-phase listener, so it runs *after* the event has already\n // bubbled through the dropzone root. If the drop landed inside the root and the instance's own\n // onDrop handler already prevented the default, there's nothing left to do.\n //\n // We must NOT bail out on `contains()` alone: when the dropzone is `disabled` or has `noDrag`,\n // the root has no onDrop handler, so nothing prevents the browser's default action and the file\n // is opened in the tab. Falling through to `preventDefault()` here keeps that from happening.\n // See https://github.com/react-dropzone/react-dropzone/issues/1362\n if (rootRef.current && event.target && rootRef.current.contains(event.target as Node) && event.defaultPrevented) {\n return;\n }\n event.preventDefault();\n dragTargetsRef.current = [];\n };\n\n useEffect(() => {\n if (preventDropOnDocument) {\n document.addEventListener(\"dragover\", onDocumentDragOver, false);\n document.addEventListener(\"drop\", onDocumentDrop, false);\n }\n\n return () => {\n if (preventDropOnDocument) {\n document.removeEventListener(\"dragover\", onDocumentDragOver);\n document.removeEventListener(\"drop\", onDocumentDrop);\n }\n };\n }, [rootRef, preventDropOnDocument]);\n\n // Track global drag state for document-level drag events\n useEffect(() => {\n const onDocumentDragEnter = (event: DragEvent) => {\n if (event.target) {\n globalDragTargetsRef.current = [...globalDragTargetsRef.current, event.target];\n }\n\n if (isEvtWithFiles(event)) {\n dispatch({isDragGlobal: true, type: \"setDragGlobal\"});\n }\n };\n\n const onDocumentDragLeave = (event: DragEvent) => {\n // Only deactivate once we've left all children\n globalDragTargetsRef.current = globalDragTargetsRef.current.filter(el => el !== event.target && el !== null);\n\n if (globalDragTargetsRef.current.length > 0) {\n return;\n }\n\n dispatch({isDragGlobal: false, type: \"setDragGlobal\"});\n };\n\n const onDocumentDragEnd = () => {\n globalDragTargetsRef.current = [];\n dispatch({isDragGlobal: false, type: \"setDragGlobal\"});\n };\n\n const onDocumentDropGlobal = () => {\n globalDragTargetsRef.current = [];\n dispatch({isDragGlobal: false, type: \"setDragGlobal\"});\n };\n\n document.addEventListener(\"dragenter\", onDocumentDragEnter, false);\n document.addEventListener(\"dragleave\", onDocumentDragLeave, false);\n document.addEventListener(\"dragend\", onDocumentDragEnd, false);\n document.addEventListener(\"drop\", onDocumentDropGlobal, false);\n\n return () => {\n document.removeEventListener(\"dragenter\", onDocumentDragEnter);\n document.removeEventListener(\"dragleave\", onDocumentDragLeave);\n document.removeEventListener(\"dragend\", onDocumentDragEnd);\n document.removeEventListener(\"drop\", onDocumentDropGlobal);\n };\n }, [rootRef]);\n\n // Auto focus the root when autoFocus is true\n useEffect(() => {\n if (!disabled && autoFocus && rootRef.current) {\n rootRef.current.focus();\n }\n return () => {};\n }, [rootRef, autoFocus, disabled]);\n\n const onErrCb = useCallback(\n (e: Error) => {\n if (onError) {\n onError(e);\n } else {\n // Let the user know something's gone wrong if they haven't provided the onError cb.\n console.error(e);\n }\n },\n [onError]\n );\n\n const onDragEnterCb = useCallback(\n (event: any) => {\n event.preventDefault();\n // Persist here because we need the event later after getFilesFromEvent() is done\n event.persist?.();\n stopPropagation(event);\n\n // Ignore drags onto the dropzone while the file picker dialog is open: the page underneath a\n // live picker shouldn't react to (or accept) dropped files. See #1455. preventDefault() above\n // still runs so the browser doesn't try to open/navigate to a dropped file.\n if (isFileDialogActiveRef.current) {\n return;\n }\n\n dragTargetsRef.current = [...dragTargetsRef.current, event.target];\n\n if (isEvtWithFiles(event)) {\n Promise.resolve(getFilesFromEvent(event))\n .then(files => {\n if (isPropagationStopped(event) && !noDragEventsBubbling) {\n return;\n }\n\n const fileCount = files.length;\n // During a drag we only have DataTransferItems (MIME type, no name/size), so the\n // custom validator can't run yet - a validator-configured dropzone is \"unknown\" until\n // drop rather than a misleading accept/reject. See getDragVerdict for the details.\n const verdict =\n fileCount > 0\n ? getDragVerdict({\n files: files as Array<File | DataTransferItem>,\n accept: acceptAttr,\n minSize,\n maxSize,\n multiple,\n maxFiles,\n validator\n })\n : null;\n\n dispatch({\n isDragAccept: verdict === \"accept\",\n isDragReject: verdict === \"reject\",\n isDragUnknown: verdict === \"unknown\",\n isDragActive: true,\n type: \"setDraggedFiles\"\n });\n\n if (onDragEnter) {\n onDragEnter(event);\n }\n })\n .catch(e => onErrCb(e));\n }\n },\n [\n getFilesFromEvent,\n onDragEnter,\n onErrCb,\n noDragEventsBubbling,\n acceptAttr,\n minSize,\n maxSize,\n multiple,\n maxFiles,\n validator\n ]\n );\n\n const onDragOverCb = useCallback(\n (event: any) => {\n event.preventDefault();\n event.persist?.();\n stopPropagation(event);\n\n // Ignore drags over the dropzone while the file picker dialog is open. See #1455.\n if (isFileDialogActiveRef.current) {\n return false;\n }\n\n const hasFiles = isEvtWithFiles(event);\n if (hasFiles && event.dataTransfer) {\n try {\n event.dataTransfer.dropEffect = \"copy\";\n } catch {\n /* no-op */\n }\n }\n\n if (hasFiles && onDragOver) {\n onDragOver(event);\n }\n\n return false;\n },\n [onDragOver, noDragEventsBubbling]\n );\n\n const onDragLeaveCb = useCallback(\n (event: any) => {\n event.preventDefault();\n event.persist?.();\n stopPropagation(event);\n\n // Only deactivate once the dropzone and all children have been left\n const targets = dragTargetsRef.current.filter(target => rootRef.current?.contains(target as Node));\n // Make sure to remove a target present multiple times only once\n // (Firefox may fire dragenter/dragleave multiple times on the same element)\n const targetIdx = targets.indexOf(event.target);\n if (targetIdx !== -1) {\n targets.splice(targetIdx, 1);\n }\n dragTargetsRef.current = targets;\n if (targets.length > 0) {\n return;\n }\n\n dispatch({\n type: \"setDraggedFiles\",\n isDragActive: false,\n isDragAccept: false,\n isDragReject: false,\n isDragUnknown: false\n });\n\n if (isEvtWithFiles(event) && onDragLeave) {\n onDragLeave(event);\n }\n },\n [rootRef, onDragLeave, noDragEventsBubbling]\n );\n\n const setFiles = useCallback(\n async (files: FileWithPath[], event: any, signal: AbortSignal) => {\n const localizeError = (error: FileError, file: File): FileError =>\n getErrorMessage ? {...error, message: getErrorMessage(error, file)} : error;\n\n // Commit the per-file verdicts: split accepted/rejected, cap the surplus, update state and\n // fire the onDrop callbacks. Runs synchronously so nested-dropzone ordering is preserved on\n // the fast path (an onDrop handler calling stopPropagation must do so before a parent's onDrop\n // check - see the noDragEventsBubbling tests).\n const commit = (results: Array<PerFileResult>) => {\n const acceptedFiles: FileWithPath[] = [];\n const fileRejections: FileRejection[] = [];\n\n results.forEach(({file, accepted, acceptError, sizeMatch, sizeError, customErrors}) => {\n if (accepted && sizeMatch && !customErrors) {\n acceptedFiles.push(file);\n } else {\n let errors: Array<FileError | null> = [acceptError, sizeError];\n\n if (customErrors) {\n errors = errors.concat(customErrors);\n }\n\n fileRejections.push({\n file,\n errors: errors.filter((e): e is FileError => e != null).map(error => localizeError(error, file))\n });\n }\n });\n\n // Cap the accepted files at the configured limit and reject only the surplus (the files past\n // the limit) with a too-many-files error, instead of rejecting the whole batch. The limit is 1\n // when {multiple} is false, and {maxFiles} when {multiple} is true (0 means no limit). Files\n // that already failed the per-file checks above are in {fileRejections} and don't count here.\n // See https://github.com/react-dropzone/react-dropzone/issues/1355\n // and https://github.com/react-dropzone/react-dropzone/issues/1358\n const acceptedFilesLimit = multiple ? (maxFiles >= 1 ? maxFiles : Number.POSITIVE_INFINITY) : 1;\n if (acceptedFiles.length > acceptedFilesLimit) {\n const surplusFiles = acceptedFiles.splice(acceptedFilesLimit);\n surplusFiles.forEach(file => {\n fileRejections.push({file, errors: [localizeError(TOO_MANY_FILES_REJECTION, file)]});\n });\n }\n\n // Clears isProcessing back to false (see the reducer) in the same update that sets the files.\n dispatch({\n acceptedFiles,\n fileRejections,\n type: \"setFiles\"\n });\n\n if (onDrop) {\n onDrop(acceptedFiles, fileRejections, event);\n }\n\n if (fileRejections.length > 0 && onDropRejected) {\n onDropRejected(fileRejections, event);\n }\n\n if (acceptedFiles.length > 0 && onDropAccepted) {\n onDropAccepted(acceptedFiles, event);\n }\n };\n\n // Run the built-in checks synchronously and invoke the validator (which may return a value or\n // a Promise). customErrors is left as-is here so we can tell sync from async below.\n const pending = files.map(file => {\n const [accepted, acceptError] = fileAccepted(file, inputAcceptAttr);\n const [sizeMatch, sizeError] = fileMatchSize(file, minSize, maxSize);\n const customErrors = validator ? validator(file) : null;\n return {file, accepted, acceptError, sizeMatch, sizeError, customErrors};\n });\n\n // Callers check signal.aborted right before invoking setFiles (synchronously, no await in\n // between), so this run is guaranteed live here - the supersession guards below only matter\n // after we await the validator.\n\n // Fast path: no validator, or a synchronous one. Commit synchronously - no extra microtask\n // hop, so nested-dropzone ordering is preserved (an onDrop handler calling stopPropagation\n // must run before a parent's onDrop check - see the noDragEventsBubbling tests). commit's\n // dispatch also clears isProcessing.\n if (!pending.some(({customErrors}) => isThenable(customErrors))) {\n commit(pending as Array<PerFileResult>);\n return;\n }\n\n // Async path: at least one validator returned a Promise. isProcessing is already on (set when\n // the run began, before getFilesFromEvent); keep guarding against supersession while we await.\n let results: Array<PerFileResult>;\n try {\n results = await Promise.all(\n pending.map(async ({customErrors, ...rest}) => ({...rest, customErrors: await customErrors}))\n );\n } catch (e) {\n // A validator threw/rejected. If a newer run already superseded this one, let it own the\n // state; otherwise clear the processing flag and report the error via onError.\n if (!signal.aborted) {\n endProcessing(signal);\n onErrCb(e as Error);\n }\n return;\n }\n\n // A newer drop landed while we were validating - discard these stale results.\n if (signal.aborted) {\n return;\n }\n\n commit(results);\n },\n [\n dispatch,\n multiple,\n inputAcceptAttr,\n minSize,\n maxSize,\n maxFiles,\n onDrop,\n onDropAccepted,\n onDropRejected,\n validator,\n getErrorMessage,\n onErrCb,\n endProcessing\n ]\n );\n\n const onDropCb = useCallback(\n (event: any) => {\n event.preventDefault();\n // Persist here because we need the event later after getFilesFromEvent() is done\n event.persist?.();\n stopPropagation(event);\n\n dragTargetsRef.current = [];\n\n // Ignore a drop landing on the dropzone while the file picker dialog is open (see #1455).\n // Guard on {event.dataTransfer} so only real drag-drops are suppressed: the input's change\n // event (a file picked from the dialog) also runs through here while the dialog is still\n // flagged active, and that path must keep working. Returning before the reset below leaves\n // the dialog flag intact.\n if (isFileDialogActiveRef.current && event.dataTransfer) {\n return;\n }\n\n // Clear drag state before we begin processing so beginProcessing's isProcessing isn't reset.\n dispatch({type: \"reset\"});\n\n if (isEvtWithFiles(event)) {\n // Processing spans reading the files (getFilesFromEvent) and running the validator.\n const signal = beginProcessing();\n Promise.resolve(getFilesFromEvent(event))\n .then(files => {\n // A newer drop superseded this one while reading files - it owns isProcessing now.\n if (signal.aborted) {\n return;\n }\n if (isPropagationStopped(event) && !noDragEventsBubbling) {\n endProcessing(signal);\n return;\n }\n // setFiles handles validator errors internally (routing them to onError); the outer\n // catch here only fires for a getFilesFromEvent failure.\n return setFiles(files as FileWithPath[], event, signal);\n })\n .catch(e => {\n if (!signal.aborted) {\n endProcessing(signal);\n onErrCb(e);\n }\n });\n }\n },\n [getFilesFromEvent, setFiles, onErrCb, noDragEventsBubbling, beginProcessing, endProcessing]\n );\n\n // Cb to add files pasted into the dropzone (e.g. a screenshot pasted with Ctrl/Cmd+V). Fires when\n // the root - or a focused descendant, so a child <textarea> works too - receives a paste. Reuses\n // the same read/validate/onDrop pipeline as a drop.\n const onPasteCb = useCallback(\n (event: any) => {\n // Only act on a paste that carries files. Bail before preventDefault() for text/other pastes\n // so pasting into a child input keeps working normally.\n if (!isEvtWithFiles(event)) {\n return;\n }\n event.preventDefault();\n // Persist here because we need the event later after getFilesFromEvent() is done\n event.persist?.();\n stopPropagation(event);\n\n // Processing spans reading the files (getFilesFromEvent) and running the validator.\n const signal = beginProcessing();\n Promise.resolve(getFilesFromEvent(event))\n .then(files => {\n // A newer drop/paste superseded this one while reading files - it owns isProcessing now.\n if (signal.aborted) {\n return;\n }\n if (isPropagationStopped(event) && !noDragEventsBubbling) {\n endProcessing(signal);\n return;\n }\n return setFiles(files as FileWithPath[], event, signal);\n })\n .catch(e => {\n if (!signal.aborted) {\n endProcessing(signal);\n onErrCb(e);\n }\n });\n },\n [getFilesFromEvent, setFiles, onErrCb, noDragEventsBubbling, beginProcessing, endProcessing]\n );\n\n // Fn for opening the file dialog programmatically\n const openFileDialog = useCallback(() => {\n // No point to use FS access APIs if context is not secure\n // https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts#feature_detection\n if (fsAccessApiWorksRef.current) {\n dispatch({type: \"openDialog\"});\n onFileDialogOpenCb();\n // https://developer.mozilla.org/en-US/docs/Web/API/window/showOpenFilePicker\n const opts = {\n multiple,\n types: pickerTypes\n };\n // Set once the user has picked file(s); processing then spans reading them (getFilesFromEvent)\n // and running the validator. Picker rejections (cancel, security) happen before this, so it\n // stays undefined there and no processing state is touched.\n let signal: AbortSignal | undefined;\n (window as any)\n .showOpenFilePicker(opts)\n .then((handles: any) => {\n signal = beginProcessing();\n return getFilesFromEvent(handles);\n })\n .then((files: Array<File | DataTransferItem>) => {\n // Close the dialog as soon as we have the selection; validation runs afterwards and is\n // reflected by isProcessing rather than by keeping the dialog \"active\".\n dispatch({type: \"closeDialog\"});\n // A drop elsewhere superseded this selection while reading files - it owns isProcessing.\n if (signal!.aborted) {\n return;\n }\n return setFiles(files as FileWithPath[], null, signal!);\n })\n .catch((e: any) => {\n // Clear any processing this run started (e.g. a getFilesFromEvent failure).\n if (signal) {\n endProcessing(signal);\n }\n // AbortError means the user canceled\n if (isAbort(e)) {\n onFileDialogCancelCb(e);\n dispatch({type: \"closeDialog\"});\n } else if (isSecurityError(e) || isNotAllowedError(e)) {\n // The FS access API is unusable here: either the context forbids it (SecurityError,\n // e.g. CORS) or the browser/platform blocked the picker (NotAllowedError, e.g. Edge\n // for Business - see https://github.com/react-dropzone/react-dropzone/issues/1429).\n // Stop using it and fall back to the native <input>.\n fsAccessApiWorksRef.current = false;\n if (inputRef.current) {\n inputRef.current.value = \"\";\n inputRef.current.click();\n } else {\n onErrCb(\n new Error(\n \"Cannot open the file picker because the https://developer.mozilla.org/en-US/docs/Web/API/File_System_Access_API is not supported and no <input> was provided.\"\n )\n );\n }\n } else {\n onErrCb(e);\n }\n });\n return;\n }\n\n if (inputRef.current) {\n dispatch({type: \"openDialog\"});\n onFileDialogOpenCb();\n inputRef.current.value = \"\";\n inputRef.current.click();\n }\n }, [\n dispatch,\n onFileDialogOpenCb,\n onFileDialogCancelCb,\n useFsAccessApi,\n setFiles,\n onErrCb,\n pickerTypes,\n multiple,\n beginProcessing,\n endProcessing\n ]);\n\n // Cb to open the file dialog when SPACE/ENTER occurs on the dropzone\n const onKeyDownCb = useCallback(\n (event: any) => {\n // Ignore keyboard events bubbling up the DOM tree\n if (!rootRef.current?.isEqualNode(event.target)) {\n return;\n }\n\n if (event.key === \" \" || event.key === \"Enter\" || event.keyCode === 32 || event.keyCode === 13) {\n event.preventDefault();\n openFileDialog();\n }\n },\n [rootRef, openFileDialog]\n );\n\n // Update focus state for the dropzone\n const onFocusCb = useCallback(() => {\n dispatch({type: \"focus\"});\n }, []);\n const onBlurCb = useCallback(() => {\n dispatch({type: \"blur\"});\n }, []);\n\n // Cb to open the file dialog when click occurs on the dropzone\n const onClickCb = useCallback(() => {\n if (noClick) {\n return;\n }\n\n // In IE11/Edge the file-browser dialog is blocking, therefore, use setTimeout()\n // to ensure React can handle state changes\n // See: https://github.com/react-dropzone/react-dropzone/issues/450\n if (isIeOrEdge()) {\n setTimeout(openFileDialog, 0);\n } else {\n openFileDialog();\n }\n }, [noClick, openFileDialog]);\n\n const composeHandler = (fn: any) => {\n return disabled ? null : fn;\n };\n\n const composeKeyboardHandler = (fn: any) => {\n return noKeyboard ? null : composeHandler(fn);\n };\n\n const composeDragHandler = (fn: any) => {\n return noDrag ? null : composeHandler(fn);\n };\n\n const composePasteHandler = (fn: any) => {\n return noPaste ? null : composeHandler(fn);\n };\n\n const stopPropagation = (event: any) => {\n if (noDragEventsBubbling) {\n event.stopPropagation();\n }\n };\n\n const getRootProps = useMemo(\n () =>\n ({\n refKey = \"ref\",\n role,\n onKeyDown,\n onFocus,\n onBlur,\n onClick,\n onDragEnter,\n onDragOver,\n onDragLeave,\n onDrop,\n onPaste,\n ...rest\n }: DropzoneRootProps = {}) => ({\n onKeyDown: composeKeyboardHandler(composeEventHandlers(onKeyDown, onKeyDownCb)),\n onFocus: composeKeyboardHandler(composeEventHandlers(onFocus, onFocusCb)),\n onBlur: composeKeyboardHandler(composeEventHandlers(onBlur, onBlurCb)),\n onClick: composeHandler(composeEventHandlers(onClick, onClickCb)),\n onDragEnter: composeDragHandler(composeEventHandlers(onDragEnter, onDragEnterCb)),\n onDragOver: composeDragHandler(composeEventHandlers(onDragOver, onDragOverCb)),\n onDragLeave: composeDragHandler(composeEventHandlers(onDragLeave, onDragLeaveCb)),\n onDrop: composeDragHandler(composeEventHandlers(onDrop, onDropCb)),\n onPaste: composePasteHandler(composeEventHandlers(onPaste, onPasteCb)),\n role: typeof role === \"string\" && role !== \"\" ? role : \"presentation\",\n [refKey]: rootRef,\n ...(!disabled && !noKeyboard ? {tabIndex: 0} : {}),\n ...(disabled ? {\"aria-disabled\": true} : {}),\n ...rest\n }),\n [\n rootRef,\n onKeyDownCb,\n onFocusCb,\n onBlurCb,\n onClickCb,\n onDragEnterCb,\n onDragOverCb,\n onDragLeaveCb,\n onDropCb,\n onPasteCb,\n noKeyboard,\n noDrag,\n noPaste,\n disabled\n ]\n );\n\n const onInputElementClick = useCallback((event: any) => {\n event.stopPropagation();\n }, []);\n\n const getInputProps = useMemo(\n () =>\n ({refKey = \"ref\", onChange, onClick, ...rest}: DropzoneInputProps = {}) => {\n const inputProps = {\n accept: inputAcceptAttr,\n multiple,\n type: \"file\",\n \"aria-label\": \"file upload\",\n // Hide the input without taking it out of flow. A visually-hidden input with\n // {position: absolute} makes the browser scroll the page to it whenever it gets\n // focus (e.g. inside a collapsed accordion), see #1413. Keeping it in flow as a\n // zero-size, transparent block avoids that while staying focusable so a {required}\n // input still triggers form validation, see #1268. Don't use {display: none} or\n // {visibility: hidden}: those make the input unfocusable and reintroduce #1268.\n style: {\n border: 0,\n display: \"block\",\n height: 0,\n margin: 0,\n opacity: 0,\n overflow: \"hidden\",\n padding: 0,\n width: 0\n },\n onChange: composeHandler(composeEventHandlers(onChange, onDropCb)),\n onClick: composeHandler(composeEventHandlers(onClick, onInputElementClick)),\n tabIndex: -1,\n [refKey]: inputRef\n };\n\n return {\n ...inputProps,\n ...rest\n };\n },\n [inputRef, accept, multiple, onDropCb, disabled]\n );\n\n return {\n ...state,\n isFocused: isFocused && !disabled,\n getRootProps,\n getInputProps,\n rootRef,\n inputRef,\n open: composeHandler(openFileDialog)\n } as unknown as DropzoneState;\n}\n\nfunction reducer(state: DropzoneInternalState, action: any): DropzoneInternalState {\n switch (action.type) {\n case \"focus\":\n return {\n ...state,\n isFocused: true\n };\n case \"blur\":\n return {\n ...state,\n isFocused: false\n };\n case \"openDialog\":\n return {\n ...initialState,\n isFileDialogActive: true\n };\n case \"closeDialog\":\n return {\n ...state,\n isFileDialogActive: false\n };\n case \"setDraggedFiles\":\n return {\n ...state,\n isDragActive: action.isDragActive,\n isDragAccept: action.isDragAccept,\n isDragReject: action.isDragReject,\n isDragUnknown: action.isDragUnknown\n };\n case \"setProcessing\":\n return {\n ...state,\n isProcessing: action.isProcessing\n };\n case \"setFiles\":\n return {\n ...state,\n acceptedFiles: action.acceptedFiles,\n fileRejections: action.fileRejections,\n isProcessing: false,\n isDragReject: false,\n isDragUnknown: false\n };\n case \"setDragGlobal\":\n return {\n ...state,\n isDragGlobal: action.isDragGlobal\n };\n case \"reset\":\n return {\n ...initialState\n };\n default:\n return state;\n }\n}\n\nfunction noop() {}\n"],"mappings":"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"}
|
package/dist/index.d.cts
CHANGED
|
@@ -3,9 +3,27 @@ import * as React from "react";
|
|
|
3
3
|
//#region src/utils/index.d.ts
|
|
4
4
|
/**
|
|
5
5
|
* A map of accepted MIME types to file extensions, as passed to the `accept` prop.
|
|
6
|
+
*
|
|
7
|
+
* An extension value may be a single extension string or an array of them - both are
|
|
8
|
+
* accepted, mirroring the shape of `window.showOpenFilePicker`'s `accept`.
|
|
6
9
|
*/
|
|
7
10
|
interface Accept {
|
|
8
|
-
[key: string]: readonly string[];
|
|
11
|
+
[key: string]: string | readonly string[];
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* A labeled group of accepted types, mirroring one entry of `window.showOpenFilePicker`'s
|
|
15
|
+
* `types` option. Passing the `accept` prop as an array of these lets the File System Access
|
|
16
|
+
* picker present multiple named filter rows instead of a single one (see
|
|
17
|
+
* {@link pickerOptionsFromAccept}). The optional `description` labels the row; when omitted it
|
|
18
|
+
* is derived from the group's extensions.
|
|
19
|
+
*
|
|
20
|
+
* Grouping only surfaces when the FS Access picker is actually used (`useFsAccessApi` +
|
|
21
|
+
* a secure context + browser support). The native `<input>` fallback has no concept of groups
|
|
22
|
+
* or descriptions, so every group is flattened into one accept attribute there.
|
|
23
|
+
*/
|
|
24
|
+
interface AcceptGroup {
|
|
25
|
+
description?: string;
|
|
26
|
+
accept: Accept;
|
|
9
27
|
}
|
|
10
28
|
/**
|
|
11
29
|
* A file rejection error.
|
|
@@ -37,7 +55,7 @@ interface FileRejection {
|
|
|
37
55
|
}
|
|
38
56
|
type SharedProps = "multiple" | "onDragEnter" | "onDragOver" | "onDragLeave";
|
|
39
57
|
type DropzoneOptions = Pick<React.HTMLProps<HTMLElement>, SharedProps> & {
|
|
40
|
-
accept?: Accept;
|
|
58
|
+
accept?: Accept | AcceptGroup[];
|
|
41
59
|
minSize?: number;
|
|
42
60
|
maxSize?: number;
|
|
43
61
|
maxFiles?: number;
|
|
@@ -153,5 +171,5 @@ declare const Dropzone: React.ForwardRefExoticComponent<DropzoneProps & React.Re
|
|
|
153
171
|
*/
|
|
154
172
|
declare function useDropzone(props?: DropzoneOptions): DropzoneState;
|
|
155
173
|
//#endregion
|
|
156
|
-
export { type Accept, DropEvent, DropzoneInputProps, DropzoneOptions, DropzoneProps, DropzoneRef, DropzoneRootProps, DropzoneState, ErrorCode, type FileError, FileRejection, type FileWithPath, type ValidatorResult, Dropzone as default, useDropzone };
|
|
174
|
+
export { type Accept, type AcceptGroup, DropEvent, DropzoneInputProps, DropzoneOptions, DropzoneProps, DropzoneRef, DropzoneRootProps, DropzoneState, ErrorCode, type FileError, FileRejection, type FileWithPath, type ValidatorResult, Dropzone as default, useDropzone };
|
|
157
175
|
//# sourceMappingURL=index.d.cts.map
|
package/dist/index.d.ts
CHANGED
|
@@ -3,9 +3,27 @@ import * as React from "react";
|
|
|
3
3
|
//#region src/utils/index.d.ts
|
|
4
4
|
/**
|
|
5
5
|
* A map of accepted MIME types to file extensions, as passed to the `accept` prop.
|
|
6
|
+
*
|
|
7
|
+
* An extension value may be a single extension string or an array of them - both are
|
|
8
|
+
* accepted, mirroring the shape of `window.showOpenFilePicker`'s `accept`.
|
|
6
9
|
*/
|
|
7
10
|
interface Accept {
|
|
8
|
-
[key: string]: readonly string[];
|
|
11
|
+
[key: string]: string | readonly string[];
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* A labeled group of accepted types, mirroring one entry of `window.showOpenFilePicker`'s
|
|
15
|
+
* `types` option. Passing the `accept` prop as an array of these lets the File System Access
|
|
16
|
+
* picker present multiple named filter rows instead of a single one (see
|
|
17
|
+
* {@link pickerOptionsFromAccept}). The optional `description` labels the row; when omitted it
|
|
18
|
+
* is derived from the group's extensions.
|
|
19
|
+
*
|
|
20
|
+
* Grouping only surfaces when the FS Access picker is actually used (`useFsAccessApi` +
|
|
21
|
+
* a secure context + browser support). The native `<input>` fallback has no concept of groups
|
|
22
|
+
* or descriptions, so every group is flattened into one accept attribute there.
|
|
23
|
+
*/
|
|
24
|
+
interface AcceptGroup {
|
|
25
|
+
description?: string;
|
|
26
|
+
accept: Accept;
|
|
9
27
|
}
|
|
10
28
|
/**
|
|
11
29
|
* A file rejection error.
|
|
@@ -37,7 +55,7 @@ interface FileRejection {
|
|
|
37
55
|
}
|
|
38
56
|
type SharedProps = "multiple" | "onDragEnter" | "onDragOver" | "onDragLeave";
|
|
39
57
|
type DropzoneOptions = Pick<React.HTMLProps<HTMLElement>, SharedProps> & {
|
|
40
|
-
accept?: Accept;
|
|
58
|
+
accept?: Accept | AcceptGroup[];
|
|
41
59
|
minSize?: number;
|
|
42
60
|
maxSize?: number;
|
|
43
61
|
maxFiles?: number;
|
|
@@ -153,5 +171,5 @@ declare const Dropzone: React.ForwardRefExoticComponent<DropzoneProps & React.Re
|
|
|
153
171
|
*/
|
|
154
172
|
declare function useDropzone(props?: DropzoneOptions): DropzoneState;
|
|
155
173
|
//#endregion
|
|
156
|
-
export { type Accept, DropEvent, DropzoneInputProps, DropzoneOptions, DropzoneProps, DropzoneRef, DropzoneRootProps, DropzoneState, ErrorCode, type FileError, FileRejection, type FileWithPath, type ValidatorResult, Dropzone as default, useDropzone };
|
|
174
|
+
export { type Accept, type AcceptGroup, DropEvent, DropzoneInputProps, DropzoneOptions, DropzoneProps, DropzoneRef, DropzoneRootProps, DropzoneState, ErrorCode, type FileError, FileRejection, type FileWithPath, type ValidatorResult, Dropzone as default, useDropzone };
|
|
157
175
|
//# sourceMappingURL=index.d.ts.map
|