import type { IFilesUploaderItem, TMaxSizeTypes } from "../config/types"; const ONE_KB = 1024; /** * Возвращает расширение файла * @param name * @returns */ const getFileExtension = (name: string): string => { return (name.substring(name.lastIndexOf(".") + 1, name.length) || name).toLowerCase(); }; /** * Возвращает ковертацию полного типа файла в сокращенный * @param type - тип файла * @returns * */ const getShortFileType = (type: string): string => { return type.indexOf("/") > -1 ? type.split("/")[1] : type; }; /** * Преобразует объект или массив в формат, принимаемый компонентом * @returns */ const getFilesWithPropsArr = (data: IFilesUploaderItem | IFilesUploaderItem[]): (Required | File)[] => { const getProps = ({ name = "", size = 0, href = null, data = null, }: IFilesUploaderItem): Required => { return { name: typeof name === "string" ? name : "", size: typeof size === "number" ? size : 0, href, data, }; }; switch (true) { case Array.isArray(data): return data.map((item) => item instanceof File ? item : getProps(item)); case !!data && typeof data === "object": return [ getProps(data) ]; default: return []; } }; /** * Возвращает конкатенацию элементов массива форматов для инпута * @param fileTypes - разрешенные типы файлов * @returns * */ const getConvertedFileTypes = (fileTypes: string[]): string => { return !fileTypes.length ? "*" : fileTypes.map((type) => `.${type}`).join(","); }; /** * Сброс дефолтных действий браузера при работе с DnD * @param e - разрешенные форматы * */ const disableEvent = (e: Event): void => { e.preventDefault(); e.stopPropagation(); }; /** * Возвращает конвертацию байтов в мегабайты * @param size - размер файла в байтох * @returns * */ const getFileSizeInMb = (size: number = 0): number => size / Math.pow(ONE_KB, 2); /** * Возвращает результат проверки файлов на соответствие критериям * @returns {Boolean} * */ const getIfFilesValid = ( files: (Required | File)[] = [], maxSize: number = Infinity, fileTypes: string[] = [], maxSizeType: TMaxSizeTypes = "all" ): boolean => { if (!files.length) { return true; } const isTypeValid = files.every((file) => fileTypes.includes(getFileExtension(file?.name))); if (!isTypeValid) { return false; } switch (maxSizeType) { case "every": return files.every((file) => maxSize === 0 || getFileSizeInMb(file.size) <= maxSize); case "all": default: return isFilesSizeValid(files, maxSize); } }; /** * Возвращает конвертацию массива файлов в коллекцию Map, где ключ - имя файла, а значение - сам файл * @param files - массив файлов * @returns * */ const getConvertedFilesArrayToMap = (files: IFilesUploaderItem[] = []): Map | File> => { return new Map(getFilesWithPropsArr(files).map((file) => [ file.name, file ])); }; /** * Возвращает результат проверки файлов на максимальный размер в инпуте * @param files - массив файлов * @param maxSize - максимальное разрешение одного файла * @returns * */ const isFilesSizeValid = (files: (Required | File)[] = [], maxSize: number = Infinity): boolean => { if (!files.length) { return true; } let sizeFiles = 0; files.forEach((file) => { sizeFiles += file.size; }); return maxSize === 0 || getFileSizeInMb(sizeFiles) <= maxSize; }; /** * Присваивание загруженных файлов инпуту * @param files - массив файлов * @param input - инпут * @returns * */ const setEachFileIntoInput = async (files: Array, input: HTMLInputElement | null) => { if (!input) { return Promise.reject(); } const dt = new DataTransfer(); const filesArr = Array.from(files); return await Promise.allSettled(filesArr.map(async (file) => { if (file instanceof File) { dt.items.add(file); return Promise.resolve(); } else { return Promise.reject({ fileName: file.name, size: file.size }); } })) .then((res = []) => { // Only assign to input.files in non-test environments if (process.env.NODE_ENV !== "test") { input.files = dt.files; } const unresolvedFiles = res .filter((result): result is PromiseRejectedResult => result.status === "rejected" && !!result.reason) .map(({ reason = {} }) => ({ fileName: reason.fileName, size: reason.size })).flat(); return { unresolvedFiles }; }); }; export { disableEvent, getConvertedFilesArrayToMap, getConvertedFileTypes, getFileExtension, getFileSizeInMb, getFilesWithPropsArr, getIfFilesValid, getShortFileType, isFilesSizeValid, setEachFileIntoInput, };