UNPKG

@react-md/form

Version:

This package is for creating all the different form input types.

405 lines 15 kB
"use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.getSplitFileUploads = exports.getFileParser = exports.isMediaFile = exports.isVideoFile = exports.isAudioFile = exports.isImageFile = exports.isTextFile = exports.validateFiles = exports.isValidFileName = exports.isFileExtensionError = exports.isFileSizeError = exports.isTooManyFilesError = exports.isFileAccessError = exports.isGenericFileError = exports.FileExtensionError = exports.FileSizeError = exports.TooManyFilesError = exports.GenericFileError = exports.FileAccessError = void 0; var nanoid_1 = require("nanoid"); /** * An error that will be created if a user tries dragging and dropping files * from a shared directory that they do not have access to. This error will not * occur much. * * @remarks \@since 2.9.0 */ var FileAccessError = /** @class */ (function (_super) { __extends(FileAccessError, _super); /** * * @param message - An optional message for the error. */ function FileAccessError(message) { var _this = _super.call(this, message) || this; _this.key = (0, nanoid_1.nanoid)(); _this.name = "FileAccessError"; return _this; } return FileAccessError; }(Error)); exports.FileAccessError = FileAccessError; /** * An error that just requires a `File` to be passed as the first argument. * * @remarks \@since 2.9.0 */ var GenericFileError = /** @class */ (function (_super) { __extends(GenericFileError, _super); /** * * @param files - A list of files that caused the error. * @param reason - An optional reason for the error */ function GenericFileError(files, reason) { var _this = _super.call(this, "Invalid files") || this; _this.files = files; _this.reason = reason; _this.key = (0, nanoid_1.nanoid)(); _this.name = "GenericFileError"; return _this; } return GenericFileError; }(Error)); exports.GenericFileError = GenericFileError; /** * An error that is created during the upload process if the number of files * exceeds the {@link FileUploadOptions.maxFiles} amount. * * @remarks \@since 2.9.0 */ var TooManyFilesError = /** @class */ (function (_super) { __extends(TooManyFilesError, _super); /** * * @param files - The list of files that could not be uploaded due to the file * limit defined. * @param limit - The max limit of files allowed. */ function TooManyFilesError(files, limit) { var _this = _super.call(this, files, "file limit") || this; _this.limit = limit; _this.name = "TooManyFilesError"; return _this; } return TooManyFilesError; }(GenericFileError)); exports.TooManyFilesError = TooManyFilesError; /** * An error that will be created if a user tries to upload a file that * is either: * - less than the {@link FileValidationOptions.minFileSize} * - greater than the {@link FileValidationOptions.maxFileSize} * - including the file would be greater than the {@link FileValidationOptions.totalFileSize} * * @remarks \@since 2.9.0 */ var FileSizeError = /** @class */ (function (_super) { __extends(FileSizeError, _super); /** * * @param files - The list of files that have the file size error * @param type - The file size error type * @param limit - The number of bytes allowed based on the type */ function FileSizeError(files, type, limit) { var _this = _super.call(this, files, "file size") || this; _this.type = type; _this.limit = limit; _this.name = "FileSizeError"; return _this; } return FileSizeError; }(GenericFileError)); exports.FileSizeError = FileSizeError; /** * An error that will be created if a user tries to upload a file that does not * end with one of the {@link FileValidationOptions.extensions}. * * @remarks \@since 2.9.0 */ var FileExtensionError = /** @class */ (function (_super) { __extends(FileExtensionError, _super); /** * * @param files - The file that caused the error * @param extensions - The allowed list of file extensions */ function FileExtensionError(files, extensions) { var _this = _super.call(this, files, "extension") || this; _this.extensions = extensions; _this.name = "FileExtensionError"; return _this; } return FileExtensionError; }(GenericFileError)); exports.FileExtensionError = FileExtensionError; /** * A simple type-guard that can be used to check if the * {@link FileValidationError} is the {@link GenericFileError} which can be * useful when displaying the errors to the user. * * @param error - The error to check * @returns true if the error is a {@link FileAccessError} */ function isGenericFileError(error) { return "name" in error && error.name === "GenericFileError"; } exports.isGenericFileError = isGenericFileError; /** * A simple type-guard that can be used to check if the * {@link FileValidationError} is the {@link FileAccessError} which can be * useful when displaying the errors to the user. * * @param error - The error to check * @returns true if the error is a {@link FileAccessError} */ function isFileAccessError(error) { return "name" in error && error.name === "FileAccessError"; } exports.isFileAccessError = isFileAccessError; /** * A simple type-guard that can be used to check if the * {@link FileValidationError} is the {@link TooManyFilesError} which can be * useful when displaying the errors to the user. * * @param error - The error to check * @returns true if the error is a {@link TooManyFilesError} */ function isTooManyFilesError(error) { return "name" in error && error.name === "TooManyFilesError"; } exports.isTooManyFilesError = isTooManyFilesError; /** * A simple type-guard that can be used to check if the * {@link FileValidationError} is the {@link FileSizeError} which can be * useful when displaying the errors to the user. * * @param error - The error to check * @returns true if the error is a {@link FileSizeError} */ function isFileSizeError(error) { return "name" in error && error.name === "FileSizeError"; } exports.isFileSizeError = isFileSizeError; /** * A simple type-guard that can be used to check if the * {@link FileValidationError} is the {@link FileExtensionError} which can be * useful when displaying the errors to the user. * * @param error - The error to check * @returns true if the error is a {@link FileExtensionError} */ function isFileExtensionError(error) { return "name" in error && error.name === "FileExtensionError"; } exports.isFileExtensionError = isFileExtensionError; /** * * @defaultValue `matcher?.test(file.name) ?? true` * @remarks \@since 3.1.0 */ var isValidFileName = function (file, matcher) { var _a; return (_a = matcher === null || matcher === void 0 ? void 0 : matcher.test(file.name)) !== null && _a !== void 0 ? _a : true; }; exports.isValidFileName = isValidFileName; /** * A pretty decent default implementation for validating files with the * {@link useFileUpload} that ensures the {@link FilesValidationOptions} are * enforced before allowing a file to be uploaded. * * @typeparam E - An optional custom file validation error. * @param files - The list of files to check * @param options - The {@link FilesValidationOptions} * @returns the {@link ValidatedFilesResult} * @remarks \@since 2.9.0 */ function validateFiles(files, _a) { var maxFiles = _a.maxFiles, extensions = _a.extensions, minFileSize = _a.minFileSize, maxFileSize = _a.maxFileSize, totalBytes = _a.totalBytes, totalFiles = _a.totalFiles, totalFileSize = _a.totalFileSize, isValidFileName = _a.isValidFileName; var errors = []; var pending = []; var extraFiles = []; var extensionRegExp = extensions.length > 0 ? new RegExp("\\.(".concat(extensions.join("|"), ")$"), "i") : undefined; var maxFilesReached = maxFiles > 0 && totalFiles >= maxFiles; var remainingBytes = totalFileSize - totalBytes; var extensionErrors = []; var minErrors = []; var maxErrors = []; var totalSizeErrors = []; for (var i = 0; i < files.length; i += 1) { var file = files[i]; var valid = true; var size = file.size; if (!isValidFileName(file, extensionRegExp, extensions)) { valid = false; extensionErrors.push(file); } if (minFileSize > 0 && size < minFileSize) { valid = false; minErrors.push(file); } if (maxFileSize > 0 && size > maxFileSize) { valid = false; maxErrors.push(file); } else if (totalFileSize > 0 && remainingBytes - file.size < 0) { // don't want both errors displaying valid = false; totalSizeErrors.push(file); } if (maxFilesReached && valid) { extraFiles.push(file); } else if (!maxFilesReached && valid) { pending.push(file); remainingBytes -= file.size; maxFilesReached = maxFilesReached || (maxFiles > 0 && totalFiles + pending.length >= maxFiles); } } if (extensionErrors.length) { errors.push(new FileExtensionError(extensionErrors, extensions)); } if (minErrors.length) { errors.push(new FileSizeError(minErrors, "min", minFileSize)); } if (maxErrors.length) { errors.push(new FileSizeError(maxErrors, "max", maxFileSize)); } if (totalSizeErrors.length) { errors.push(new FileSizeError(totalSizeErrors, "total", totalFileSize)); } if (extraFiles.length) { errors.push(new TooManyFilesError(extraFiles, maxFiles)); } return { pending: pending, errors: errors }; } exports.validateFiles = validateFiles; /** * This will first check if the mime-type of the file starts with `text/` and * fallback to checking a few file names or extensions that should be considered * text. * * This function is not guaranteed to be 100% correct and is only useful if * trying to generate a preview of files uploaded to the browser. * * @param file - The file to check * @returns `true` if the file should be considered as a text-content file. * @remarks \@since 2.9.0 */ function isTextFile(file) { return /\.((j|t)sx?|json|lock|hbs|ya?ml|log|txt|md)$/i.test(file.name); } exports.isTextFile = isTextFile; /** * This will first check if the mime-type of the file starts with `text\/` and * fallback to checking a few file names or extensions that should be considered * text. * * This function is not guaranteed to be 100% correct and is only useful if * trying to generate a preview of files uploaded to the browser. * * @param file - The file to check * @returns `true` if the file should be considered as a text content file. * @remarks \@since 2.9.0 */ function isImageFile(file) { return /\.(a?png|avif|svg|tiff|gifv?|jpe?g)/i.test(file.name); } exports.isImageFile = isImageFile; /** * This will first check if the mime-type of the file starts with `audio/` and * fallback to checking a few file names or extensions that should be considered * audio. * * This function is not guaranteed to be 100% correct and is only useful if * trying to generate a preview of files uploaded to the browser. * * @param file - The file to check * @returns `true` if the file should be considered as a audio content file. * @remarks \@since 2.9.0 */ function isAudioFile(file) { return /\.(mp3|wav|ogg|m4p|flac)$/i.test(file.name); } exports.isAudioFile = isAudioFile; /** * This will first check if the mime-type of the file starts with `video/` and * fallback to checking a few file names or extensions that should be considered * video. * * This function is not guaranteed to be 100% correct and is only useful if * trying to generate a preview of files uploaded to the browser. * * @param file - The file to check * @returns `true` if the file should be considered as a video content file. * @remarks \@since 2.9.0 */ function isVideoFile(file) { return /\.(mkv|mpe?g|mov|avi|flv|webm|mp4)$/i.test(file.name); } exports.isVideoFile = isVideoFile; /** * This function is not guaranteed to be 100% correct and is only useful if * trying to generate a preview of files uploaded to the browser. * * @param file - The file to check * @returns `true` if the file matches an image, audio, or video file. * @remarks \@since 2.9.0 */ function isMediaFile(file) { return isImageFile(file) || isAudioFile(file) || isVideoFile(file); } exports.isMediaFile = isMediaFile; /** * This function will attempt to read: * - media (image, audio, and video) files as a data url so they can be * previewed in `<img>`, `<audio>`, and `<video>` tags * - text files as plain text * - everything else as an `ArrayBuffer` which can be manually converted into a * data url if needed with `URL.createObjectURL` * * @remarks \@since 2.9.0 */ var getFileParser = function (file) { if (isMediaFile(file)) { return "readAsDataURL"; } if (isTextFile(file)) { return "readAsText"; } return "readAsArrayBuffer"; }; exports.getFileParser = getFileParser; /** * This util will split all the current upload stats by status. * * @param stats - The {@link FileUploadStats} list generally returned by the * {@link useFileUpload} hook. * @returns the {@link SplitFileUploads}. * @remarks \@since 2.9.0 */ function getSplitFileUploads(stats) { var pending = []; var uploading = []; var complete = []; stats.forEach(function (stat) { if (stat.status === "pending") { pending.push(stat); } else if (stat.status === "uploading") { uploading.push(stat); } else if (stat.status === "complete") { complete.push(stat); } else { /* istanbul ignore next */ throw new Error("Invalid upload stat"); } }); return { pending: pending, uploading: uploading, complete: complete }; } exports.getSplitFileUploads = getSplitFileUploads; //# sourceMappingURL=utils.js.map