react-dropzone
Advanced tools
Comparing version 10.2.2 to 11.0.0
@@ -31,3 +31,3 @@ function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); } | ||
import { fromEvent } from 'file-selector'; | ||
import { allFilesAccepted, composeEventHandlers, fileAccepted, fileMatchSize, isEvtWithFiles, isIeOrEdge, isPropagationStopped, onDocumentDragOver } from './utils/index'; | ||
import { allFilesAccepted, composeEventHandlers, fileAccepted, fileMatchSize, isEvtWithFiles, isIeOrEdge, isPropagationStopped, onDocumentDragOver, TOO_MANY_FILES_REJECTION } from './utils/index'; | ||
/** | ||
@@ -82,3 +82,3 @@ * Convenience wrapper component for the `useDropzone` hook | ||
* @param {File[]} params.acceptedFiles Accepted files | ||
* @param {File[]} params.rejectedFiles Rejected files | ||
* @param {FileRejection[]} params.fileRejections Rejected files and why they were rejected | ||
*/ | ||
@@ -203,3 +203,3 @@ children: PropTypes.func, | ||
* @param {File[]} acceptedFiles | ||
* @param {File[]} rejectedFiles | ||
* @param {FileRejection[]} fileRejections | ||
* @param {(DragEvent|Event)} event A drag event or input change event (if files were selected via the file dialog) | ||
@@ -222,3 +222,3 @@ */ | ||
* | ||
* @param {object[]} files | ||
* @param {FileRejection[]} fileRejections | ||
* @param {(DragEvent|Event)} event | ||
@@ -244,3 +244,3 @@ */ | ||
* @param {File[]} acceptedFiles List of accepted files | ||
* @param {File[]} rejectedFiles List of rejected files | ||
* @param {FileRejection[]} fileRejections List of rejected files and why they were rejected | ||
* @param {(DragEvent|Event)} event A drag event or input change event (if files were selected via the file dialog) | ||
@@ -291,3 +291,3 @@ */ | ||
* @property {File[]} acceptedFiles Accepted files | ||
* @property {File[]} rejectedFiles Rejected files | ||
* @property {FileRejection[]} fileRejections Rejected files and why they were rejected | ||
*/ | ||
@@ -303,3 +303,3 @@ | ||
acceptedFiles: [], | ||
rejectedFiles: [] | ||
fileRejections: [] | ||
}; | ||
@@ -607,8 +607,24 @@ /** | ||
var acceptedFiles = []; | ||
var rejectedFiles = []; | ||
var fileRejections = []; | ||
files.forEach(function (file) { | ||
if (fileAccepted(file, accept) && fileMatchSize(file, minSize, maxSize)) { | ||
var _fileAccepted = fileAccepted(file, accept), | ||
_fileAccepted2 = _slicedToArray(_fileAccepted, 2), | ||
accepted = _fileAccepted2[0], | ||
acceptError = _fileAccepted2[1]; | ||
var _fileMatchSize = fileMatchSize(file, minSize, maxSize), | ||
_fileMatchSize2 = _slicedToArray(_fileMatchSize, 2), | ||
sizeMatch = _fileMatchSize2[0], | ||
sizeError = _fileMatchSize2[1]; | ||
if (accepted && sizeMatch) { | ||
acceptedFiles.push(file); | ||
} else { | ||
rejectedFiles.push(file); | ||
var errors = [acceptError, sizeError].filter(function (e) { | ||
return e; | ||
}); | ||
fileRejections.push({ | ||
file: file, | ||
errors: errors | ||
}); | ||
} | ||
@@ -618,3 +634,10 @@ }); | ||
if (!multiple && acceptedFiles.length > 1) { | ||
rejectedFiles.push.apply(rejectedFiles, _toConsumableArray(acceptedFiles.splice(0))); // Reject everything and empty accepted files | ||
// Reject everything and empty accepted files | ||
acceptedFiles.forEach(function (file) { | ||
fileRejections.push({ | ||
file: file, | ||
errors: [TOO_MANY_FILES_REJECTION] | ||
}); | ||
}); | ||
acceptedFiles.splice(0); | ||
} | ||
@@ -624,3 +647,3 @@ | ||
acceptedFiles: acceptedFiles, | ||
rejectedFiles: rejectedFiles, | ||
fileRejections: fileRejections, | ||
type: 'setFiles' | ||
@@ -630,7 +653,7 @@ }); | ||
if (onDrop) { | ||
onDrop(acceptedFiles, rejectedFiles, event); | ||
onDrop(acceptedFiles, fileRejections, event); | ||
} | ||
if (rejectedFiles.length > 0 && onDropRejected) { | ||
onDropRejected(rejectedFiles, event); | ||
if (fileRejections.length > 0 && onDropRejected) { | ||
onDropRejected(fileRejections, event); | ||
} | ||
@@ -780,3 +803,3 @@ | ||
acceptedFiles: action.acceptedFiles, | ||
rejectedFiles: action.rejectedFiles | ||
fileRejections: action.fileRejections | ||
}); | ||
@@ -790,3 +813,3 @@ | ||
acceptedFiles: [], | ||
rejectedFiles: [] | ||
fileRejections: [] | ||
}); | ||
@@ -793,0 +816,0 @@ |
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } | ||
import accepts from 'attr-accept'; // Firefox versions prior to 53 return a bogus MIME type for every file drag, so dragovers with | ||
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); } | ||
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } | ||
function _iterableToArrayLimit(arr, i) { if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) { return; } var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } | ||
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } | ||
import accepts from 'attr-accept'; // Error codes | ||
export var FILE_INVALID_TYPE = 'file-invalid-type'; | ||
export var FILE_TOO_LARGE = 'file-too-large'; | ||
export var FILE_TOO_SMALL = 'file-too-small'; | ||
export var TOO_MANY_FILES = 'too-many-files'; // File Errors | ||
export var getInvalidTypeRejectionErr = function getInvalidTypeRejectionErr(accept) { | ||
accept = Array.isArray(accept) && accept.length === 1 ? accept[0] : accept; | ||
var messageSuffix = Array.isArray(accept) ? "one of ".concat(accept.join(', ')) : accept; | ||
return { | ||
code: FILE_INVALID_TYPE, | ||
message: "File type must be ".concat(messageSuffix) | ||
}; | ||
}; | ||
export var getTooLargeRejectionErr = function getTooLargeRejectionErr(maxSize) { | ||
return { | ||
code: FILE_TOO_LARGE, | ||
message: "File is larger than ".concat(maxSize, " bytes") | ||
}; | ||
}; | ||
export var getTooSmallRejectionErr = function getTooSmallRejectionErr(minSize) { | ||
return { | ||
code: FILE_TOO_SMALL, | ||
message: "File is smaller than ".concat(minSize, " bytes") | ||
}; | ||
}; | ||
export var TOO_MANY_FILES_REJECTION = { | ||
code: TOO_MANY_FILES, | ||
message: 'Too many files' | ||
}; // Firefox versions prior to 53 return a bogus MIME type for every file drag, so dragovers with | ||
// that MIME type will always be accepted | ||
export function fileAccepted(file, accept) { | ||
return file.type === 'application/x-moz-file' || accepts(file, accept); | ||
var isAcceptable = file.type === 'application/x-moz-file' || accepts(file, accept); | ||
return [isAcceptable, isAcceptable ? null : getInvalidTypeRejectionErr(accept)]; | ||
} | ||
export function fileMatchSize(file, minSize, maxSize) { | ||
if (isDefined(file.size)) { | ||
if (isDefined(minSize) && isDefined(maxSize)) return file.size >= minSize && file.size <= maxSize;else if (isDefined(minSize)) return file.size >= minSize;else if (isDefined(maxSize)) return file.size <= maxSize; | ||
if (isDefined(minSize) && isDefined(maxSize)) { | ||
if (file.size > maxSize) return [false, getTooLargeRejectionErr(maxSize)]; | ||
if (file.size < minSize) return [false, getTooSmallRejectionErr(minSize)]; | ||
} else if (isDefined(minSize) && file.size < minSize) return [false, getTooSmallRejectionErr(minSize)];else if (isDefined(maxSize) && file.size > maxSize) return [false, getTooLargeRejectionErr(maxSize)]; | ||
} | ||
return true; | ||
return [true, null]; | ||
} | ||
@@ -33,3 +75,11 @@ | ||
return files.every(function (file) { | ||
return fileAccepted(file, accept) && fileMatchSize(file, minSize, maxSize); | ||
var _fileAccepted = fileAccepted(file, accept), | ||
_fileAccepted2 = _slicedToArray(_fileAccepted, 1), | ||
accepted = _fileAccepted2[0]; | ||
var _fileMatchSize = fileMatchSize(file, minSize, maxSize), | ||
_fileMatchSize2 = _slicedToArray(_fileMatchSize, 1), | ||
sizeMatch = _fileMatchSize2[0]; | ||
return accepted && sizeMatch; | ||
}); | ||
@@ -36,0 +86,0 @@ } // React's synthetic events has event.isPropagationStopped, |
@@ -168,3 +168,3 @@ { | ||
}, | ||
"version": "10.2.2", | ||
"version": "11.0.0", | ||
"engines": { | ||
@@ -171,0 +171,0 @@ "node": ">= 8" |
@@ -22,3 +22,4 @@ /* eslint prefer-template: 0 */ | ||
isPropagationStopped, | ||
onDocumentDragOver | ||
onDocumentDragOver, | ||
TOO_MANY_FILES_REJECTION | ||
} from './utils/index' | ||
@@ -65,3 +66,3 @@ | ||
* @param {File[]} params.acceptedFiles Accepted files | ||
* @param {File[]} params.rejectedFiles Rejected files | ||
* @param {FileRejection[]} params.fileRejections Rejected files and why they were rejected | ||
*/ | ||
@@ -186,3 +187,3 @@ children: PropTypes.func, | ||
* @param {File[]} acceptedFiles | ||
* @param {File[]} rejectedFiles | ||
* @param {FileRejection[]} fileRejections | ||
* @param {(DragEvent|Event)} event A drag event or input change event (if files were selected via the file dialog) | ||
@@ -205,3 +206,3 @@ */ | ||
* | ||
* @param {object[]} files | ||
* @param {FileRejection[]} fileRejections | ||
* @param {(DragEvent|Event)} event | ||
@@ -229,3 +230,3 @@ */ | ||
* @param {File[]} acceptedFiles List of accepted files | ||
* @param {File[]} rejectedFiles List of rejected files | ||
* @param {FileRejection[]} fileRejections List of rejected files and why they were rejected | ||
* @param {(DragEvent|Event)} event A drag event or input change event (if files were selected via the file dialog) | ||
@@ -276,3 +277,3 @@ */ | ||
* @property {File[]} acceptedFiles Accepted files | ||
* @property {File[]} rejectedFiles Rejected files | ||
* @property {FileRejection[]} fileRejections Rejected files and why they were rejected | ||
*/ | ||
@@ -288,3 +289,3 @@ | ||
acceptedFiles: [], | ||
rejectedFiles: [] | ||
fileRejections: [] | ||
} | ||
@@ -587,9 +588,12 @@ | ||
const acceptedFiles = [] | ||
const rejectedFiles = [] | ||
const fileRejections = [] | ||
files.forEach(file => { | ||
if (fileAccepted(file, accept) && fileMatchSize(file, minSize, maxSize)) { | ||
const [accepted, acceptError] = fileAccepted(file, accept) | ||
const [sizeMatch, sizeError] = fileMatchSize(file, minSize, maxSize) | ||
if (accepted && sizeMatch) { | ||
acceptedFiles.push(file) | ||
} else { | ||
rejectedFiles.push(file) | ||
const errors = [acceptError, sizeError].filter(e => e) | ||
fileRejections.push({ file, errors }) | ||
} | ||
@@ -599,3 +603,7 @@ }) | ||
if (!multiple && acceptedFiles.length > 1) { | ||
rejectedFiles.push(...acceptedFiles.splice(0)) // Reject everything and empty accepted files | ||
// Reject everything and empty accepted files | ||
acceptedFiles.forEach(file => { | ||
fileRejections.push({ file, errors: [TOO_MANY_FILES_REJECTION] }) | ||
}) | ||
acceptedFiles.splice(0) | ||
} | ||
@@ -605,3 +613,3 @@ | ||
acceptedFiles, | ||
rejectedFiles, | ||
fileRejections, | ||
type: 'setFiles' | ||
@@ -611,7 +619,7 @@ }) | ||
if (onDrop) { | ||
onDrop(acceptedFiles, rejectedFiles, event) | ||
onDrop(acceptedFiles, fileRejections, event) | ||
} | ||
if (rejectedFiles.length > 0 && onDropRejected) { | ||
onDropRejected(rejectedFiles, event) | ||
if (fileRejections.length > 0 && onDropRejected) { | ||
onDropRejected(fileRejections, event) | ||
} | ||
@@ -776,3 +784,3 @@ | ||
acceptedFiles: action.acceptedFiles, | ||
rejectedFiles: action.rejectedFiles | ||
fileRejections: action.fileRejections | ||
} | ||
@@ -786,3 +794,3 @@ case 'reset': | ||
acceptedFiles: [], | ||
rejectedFiles: [], | ||
fileRejections: [], | ||
} | ||
@@ -789,0 +797,0 @@ default: |
import accepts from 'attr-accept' | ||
// Error codes | ||
export const FILE_INVALID_TYPE = 'file-invalid-type' | ||
export const FILE_TOO_LARGE = 'file-too-large' | ||
export const FILE_TOO_SMALL = 'file-too-small' | ||
export const TOO_MANY_FILES = 'too-many-files' | ||
// File Errors | ||
export const getInvalidTypeRejectionErr = accept => { | ||
accept = Array.isArray(accept) && accept.length === 1 ? accept[0] : accept | ||
const messageSuffix = Array.isArray(accept) ? `one of ${accept.join(', ')}` : accept | ||
return { | ||
code: FILE_INVALID_TYPE, | ||
message: `File type must be ${messageSuffix}` | ||
} | ||
} | ||
export const getTooLargeRejectionErr = maxSize => { | ||
return { | ||
code: FILE_TOO_LARGE, | ||
message: `File is larger than ${maxSize} bytes` | ||
} | ||
} | ||
export const getTooSmallRejectionErr = minSize => { | ||
return { | ||
code: FILE_TOO_SMALL, | ||
message: `File is smaller than ${minSize} bytes` | ||
} | ||
} | ||
export const TOO_MANY_FILES_REJECTION = { | ||
code: TOO_MANY_FILES, | ||
message: 'Too many files' | ||
} | ||
// Firefox versions prior to 53 return a bogus MIME type for every file drag, so dragovers with | ||
// that MIME type will always be accepted | ||
export function fileAccepted(file, accept) { | ||
return file.type === 'application/x-moz-file' || accepts(file, accept) | ||
const isAcceptable = file.type === 'application/x-moz-file' || accepts(file, accept) | ||
return [isAcceptable, isAcceptable ? null : getInvalidTypeRejectionErr(accept)] | ||
} | ||
@@ -11,10 +47,11 @@ | ||
if (isDefined(file.size)) { | ||
if (isDefined(minSize) && isDefined(maxSize)) | ||
return file.size >= minSize && file.size <= maxSize | ||
else if (isDefined(minSize)) | ||
return file.size >= minSize | ||
else if (isDefined(maxSize)) | ||
return file.size <= maxSize | ||
if (isDefined(minSize) && isDefined(maxSize)) { | ||
if (file.size > maxSize) return [false, getTooLargeRejectionErr(maxSize)] | ||
if (file.size < minSize) return [false, getTooSmallRejectionErr(minSize)] | ||
} else if (isDefined(minSize) && file.size < minSize) | ||
return [false, getTooSmallRejectionErr(minSize)] | ||
else if (isDefined(maxSize) && file.size > maxSize) | ||
return [false, getTooLargeRejectionErr(maxSize)] | ||
} | ||
return true | ||
return [true, null] | ||
} | ||
@@ -32,3 +69,5 @@ | ||
return files.every(file => { | ||
return fileAccepted(file, accept) && fileMatchSize(file, minSize, maxSize) | ||
const [accepted] = fileAccepted(file, accept) | ||
const [sizeMatch] = fileMatchSize(file, minSize, maxSize) | ||
return accepted && sizeMatch | ||
}) | ||
@@ -35,0 +74,0 @@ } |
@@ -14,28 +14,28 @@ beforeEach(() => { | ||
it('should return true if the file object doesn\'t have a {size} property', () => { | ||
expect(utils.fileMatchSize({})).toBe(true) | ||
expect(utils.fileMatchSize({size: null})).toBe(true) | ||
expect(utils.fileMatchSize({})).toEqual([true, null]) | ||
expect(utils.fileMatchSize({size: null})).toEqual([true, null]) | ||
}) | ||
it('should return true if the minSize and maxSize were not provided', () => { | ||
expect(utils.fileMatchSize({size: 100})).toBe(true) | ||
expect(utils.fileMatchSize({size: 100}, undefined, undefined)).toBe(true) | ||
expect(utils.fileMatchSize({size: 100}, null, null)).toBe(true) | ||
expect(utils.fileMatchSize({size: 100})).toEqual([true, null]) | ||
expect(utils.fileMatchSize({size: 100}, undefined, undefined)).toEqual([true, null]) | ||
expect(utils.fileMatchSize({size: 100}, null, null)).toEqual([true, null]) | ||
}) | ||
it('should return true if the file {size} is within the [minSize, maxSize] range', () => { | ||
expect(utils.fileMatchSize({size: 100}, 10, 200)).toBe(true) | ||
expect(utils.fileMatchSize({size: 100}, 10, 99)).toBe(false) | ||
expect(utils.fileMatchSize({size: 100}, 101, 200)).toBe(false) | ||
expect(utils.fileMatchSize({size: 100}, 10, 200)).toEqual([true, null]) | ||
expect(utils.fileMatchSize({size: 100}, 10, 99)).toEqual([false, { code: 'file-too-large', message: 'File is larger than 99 bytes' }]) | ||
expect(utils.fileMatchSize({size: 100}, 101, 200)).toEqual([false, { code: 'file-too-small', message: 'File is smaller than 101 bytes' }]) | ||
}) | ||
it('should return true if the file {size} is more than minSize', () => { | ||
expect(utils.fileMatchSize({size: 100}, 100)).toBe(true) | ||
expect(utils.fileMatchSize({size: 100}, 101)).toBe(false) | ||
expect(utils.fileMatchSize({size: 100}, 100)).toEqual([true, null]) | ||
expect(utils.fileMatchSize({size: 100}, 101)).toEqual([false, { code: 'file-too-small', message: 'File is smaller than 101 bytes' }]) | ||
}) | ||
it('should return true if the file {size} is less than maxSize', () => { | ||
expect(utils.fileMatchSize({size: 100}, undefined, 100)).toBe(true) | ||
expect(utils.fileMatchSize({size: 100}, null, 100)).toBe(true) | ||
expect(utils.fileMatchSize({size: 100}, undefined, 99)).toBe(false) | ||
expect(utils.fileMatchSize({size: 100}, null, 99)).toBe(false) | ||
expect(utils.fileMatchSize({size: 100}, undefined, 100)).toEqual([true, null]) | ||
expect(utils.fileMatchSize({size: 100}, null, 100)).toEqual([true, null]) | ||
expect(utils.fileMatchSize({size: 100}, undefined, 99)).toEqual([false, { code: 'file-too-large', message: 'File is larger than 99 bytes' }]) | ||
expect(utils.fileMatchSize({size: 100}, null, 99)).toEqual([false, { code: 'file-too-large', message: 'File is larger than 99 bytes' }]) | ||
}) | ||
@@ -194,1 +194,51 @@ }) | ||
}) | ||
describe('fileAccepted', () => { | ||
let utils | ||
beforeEach(async done => { | ||
utils = await import('./index') | ||
done() | ||
}) | ||
it('accepts bogus firefox file', () => { | ||
const file = createFile('bogus.png', 100, 'application/x-moz-file'); | ||
expect(utils.fileAccepted(file, '.pdf')).toEqual([true, null]) | ||
}) | ||
it('accepts file when single accept criteria', () => { | ||
const file = createFile('hamster.pdf', 100, 'application/pdf'); | ||
expect(utils.fileAccepted(file, '.pdf')).toEqual([true, null]) | ||
}) | ||
it('accepts file when multiple accept criteria', () => { | ||
const file = createFile('hamster.pdf', 100, 'application/pdf'); | ||
expect(utils.fileAccepted(file, ['.pdf', '.png'])).toEqual([true, null]) | ||
}) | ||
it('rejects file when single accept criteria', () => { | ||
const file = createFile('hamster.pdf', 100, 'application/pdf'); | ||
expect(utils.fileAccepted(file, '.png')).toEqual([false, { code: 'file-invalid-type', message: 'File type must be .png' }]) | ||
}) | ||
it('rejects file when multiple accept criteria', () => { | ||
const file = createFile('hamster.pdf', 100, 'application/pdf'); | ||
expect(utils.fileAccepted(file, ['.gif', '.png'])).toEqual([false, { code: 'file-invalid-type', message: 'File type must be one of .gif, .png' }]) | ||
}) | ||
it('rejects file when single accept criteria as array', () => { | ||
const file = createFile('hamster.pdf', 100, 'application/pdf'); | ||
expect(utils.fileAccepted(file, ['.gif'])).toEqual([false, { code: 'file-invalid-type', message: 'File type must be .gif' }]) | ||
}) | ||
}) | ||
function createFile(name, size, type) { | ||
const file = new File([], name, { type }) | ||
Object.defineProperty(file, 'size', { | ||
get() { | ||
return size | ||
} | ||
}) | ||
return file | ||
} | ||
@@ -11,2 +11,12 @@ import * as React from "react"; | ||
export interface FileError { | ||
message: string; | ||
code: string; | ||
} | ||
export interface FileRejection { | ||
file: File; | ||
errors: FileError[]; | ||
} | ||
export type DropzoneOptions = Pick<React.HTMLProps<HTMLElement>, PropTypes> & { | ||
@@ -22,5 +32,5 @@ accept?: string | string[]; | ||
disabled?: boolean; | ||
onDrop?<T extends File>(acceptedFiles: T[], rejectedFiles: T[], event: DropEvent): void; | ||
onDrop?<T extends File>(acceptedFiles: T[], fileRejections: FileRejection[], event: DropEvent): void; | ||
onDropAccepted?<T extends File>(files: T[], event: DropEvent): void; | ||
onDropRejected?<T extends File>(files: T[], event: DropEvent): void; | ||
onDropRejected?(fileRejections: FileRejection[], event: DropEvent): void; | ||
getFilesFromEvent?(event: DropEvent): Promise<Array<File | DataTransferItem>>; | ||
@@ -40,3 +50,3 @@ onFileDialogCancel?(): void; | ||
acceptedFiles: File[]; | ||
rejectedFiles: File[]; | ||
fileRejections: FileRejection[]; | ||
rootRef: React.RefObject<HTMLElement>; | ||
@@ -43,0 +53,0 @@ inputRef: React.RefObject<HTMLInputElement>; |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
326532
5183