use-file-picker
Version:
Simple react hook to open browser file selector.
250 lines (242 loc) • 7.73 kB
JavaScript
import '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();
}
}
export { FileAmountLimitValidator, FileSizeValidator, FileTypeValidator, ImageDimensionsValidator, PersistentFileAmountLimitValidator, Validator };
//# sourceMappingURL=index.mjs.map