UNPKG

use-file-picker

Version:

Simple react hook to open browser file selector.

257 lines (248 loc) 7.92 kB
'use strict'; require('file-selector'); var __defProp$1 = Object.defineProperty; var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField$1 = (obj, key, value) => __defNormalProp$1(obj, key + "" , value); class Validator { constructor() { __publicField$1(this, "invokerHookId"); } /** * lifecycle method called after user selection (regardless of validation result) */ onFilesSelected(_data) { } /** * lifecycle method called after successful validation */ onFilesSuccessfullySelected(_data) { } /** * lifecycle method called after failed validation */ onFilesRejected(_data) { } /** * lifecycle method called after the selection is cleared */ onClear() { } /** * This method is called when file is removed from the list of selected files. * Invoked only by the useImperativeFilePicker hook * @param _removedFile removed file * @param _removedIndex index of removed file */ onFileRemoved(_removedFile, _removedIndex) { } } class FileAmountLimitValidator extends Validator { constructor(limitAmountOfFilesConfig) { super(); this.limitAmountOfFilesConfig = limitAmountOfFilesConfig; } validateBeforeParsing(_config, plainFiles) { const { min, max } = this.limitAmountOfFilesConfig; if (max && plainFiles.length > max) { return Promise.reject({ name: "FileAmountLimitError", reason: "MAX_AMOUNT_OF_FILES_EXCEEDED" }); } if (min && plainFiles.length < min) { return Promise.reject({ name: "FileAmountLimitError", reason: "MIN_AMOUNT_OF_FILES_NOT_REACHED" }); } return Promise.resolve(); } validateAfterParsing() { return Promise.resolve(); } } var __async = (__this, __arguments, generator) => { return new Promise((resolve, reject) => { var fulfilled = (value) => { try { step(generator.next(value)); } catch (e) { reject(e); } }; var rejected = (value) => { try { step(generator.throw(value)); } catch (e) { reject(e); } }; var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected); step((generator = generator.apply(__this, __arguments)).next()); }); }; class FileSizeValidator extends Validator { constructor(fileSizeRestrictions) { super(); this.fileSizeRestrictions = fileSizeRestrictions; } validateBeforeParsing(_config, plainFiles) { return __async(this, null, function* () { const { minFileSize, maxFileSize } = this.fileSizeRestrictions; if (!minFileSize && !maxFileSize) { return Promise.resolve(); } const errors = plainFiles.map((file) => getFileSizeError({ minFileSize, maxFileSize, file })).filter((error) => !!error); return errors.length > 0 ? Promise.reject(errors) : Promise.resolve(); }); } validateAfterParsing(_config, _file) { return __async(this, null, function* () { return Promise.resolve(); }); } } const getFileSizeError = ({ file, maxFileSize, minFileSize }) => { if (minFileSize) { const minBytes = minFileSize; if (file.size < minBytes) { return { name: "FileSizeError", reason: "FILE_SIZE_TOO_SMALL", causedByFile: file }; } } if (maxFileSize) { const maxBytes = maxFileSize; if (file.size > maxBytes) { return { name: "FileSizeError", reason: "FILE_SIZE_TOO_LARGE", causedByFile: file }; } } }; class ImageDimensionsValidator extends Validator { constructor(imageSizeRestrictions) { super(); this.imageSizeRestrictions = imageSizeRestrictions; } validateBeforeParsing() { return Promise.resolve(); } validateAfterParsing(config, file, reader) { const { readAs } = config; if (readAs === "DataURL" && this.imageSizeRestrictions && isImage(file.type)) { return checkImageDimensions(file, reader.result, this.imageSizeRestrictions); } return Promise.resolve(); } } const isImage = (fileType) => fileType.startsWith("image"); const checkImageDimensions = (file, imgDataURL, imageSizeRestrictions) => new Promise((resolve, reject) => { const img = new Image(); const error = { name: "ImageDimensionError", causedByFile: file, reasons: [] }; img.onload = function() { const { maxHeight, maxWidth, minHeight, minWidth } = imageSizeRestrictions; const { width, height } = this; if (maxHeight && maxHeight < height) error.reasons.push("IMAGE_HEIGHT_TOO_BIG"); if (minHeight && minHeight > height) error.reasons.push("IMAGE_HEIGHT_TOO_SMALL"); if (maxWidth && maxWidth < width) error.reasons.push("IMAGE_WIDTH_TOO_BIG"); if (minWidth && minWidth > width) error.reasons.push("IMAGE_WIDTH_TOO_SMALL"); if (error.reasons.length) { reject(error); } else { resolve(); } }; img.onerror = function() { error.reasons.push("IMAGE_NOT_LOADED"); reject(error); }; img.src = imgDataURL; }); var __defProp = Object.defineProperty; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField = (obj, key, value) => __defNormalProp(obj, key + "" , value); class PersistentFileAmountLimitValidator extends Validator { constructor(limitFilesConfig) { super(); this.limitFilesConfig = limitFilesConfig; __publicField(this, "previousPlainFiles", []); } onClear() { this.previousPlainFiles = []; } onFileRemoved(_removedFile, removedIndex) { this.previousPlainFiles.splice(removedIndex, 1); } validateBeforeParsing(_config, plainFiles) { const fileAmount = this.previousPlainFiles.length + plainFiles.length; const { min, max } = this.limitFilesConfig; if (max && fileAmount > max) { return Promise.reject({ name: "FileAmountLimitError", reason: "MAX_AMOUNT_OF_FILES_EXCEEDED" }); } if (min && fileAmount < min) { return Promise.reject({ name: "FileAmountLimitError", reason: "MIN_AMOUNT_OF_FILES_NOT_REACHED" }); } this.previousPlainFiles = [...this.previousPlainFiles, ...plainFiles]; return Promise.resolve(); } validateAfterParsing() { return Promise.resolve(); } } class FileTypeValidator extends Validator { constructor(acceptedFileExtensions) { super(); this.acceptedFileExtensions = acceptedFileExtensions; } validateBeforeParsing(_config, plainFiles) { const fileExtensionErrors = plainFiles.reduce( (errors, currentFile) => { const fileExtension = currentFile.name.split(".").pop(); if (!fileExtension) { return [ ...errors, { name: "FileTypeError", reason: "FILE_EXTENSION_NOT_FOUND", causedByFile: currentFile } ]; } if (!this.acceptedFileExtensions.includes(fileExtension)) { return [ ...errors, { name: "FileTypeError", reason: "FILE_TYPE_NOT_ACCEPTED", causedByFile: currentFile } ]; } return errors; }, [] ); return fileExtensionErrors.length > 0 ? Promise.reject(fileExtensionErrors) : Promise.resolve(); } validateAfterParsing(_config, _file, _reader) { return Promise.resolve(); } } exports.FileAmountLimitValidator = FileAmountLimitValidator; exports.FileSizeValidator = FileSizeValidator; exports.FileTypeValidator = FileTypeValidator; exports.ImageDimensionsValidator = ImageDimensionsValidator; exports.PersistentFileAmountLimitValidator = PersistentFileAmountLimitValidator; exports.Validator = Validator; //# sourceMappingURL=index.cjs.map