UNPKG

barneo-file-service

Version:

Комплексная библиотека Vue 3 для работы с файлами в приложениях Barneo. Предоставляет мощную функциональность для загрузки, управления и обработки файлов с валидацией, отслеживанием прогресса и поддержкой localStorage.

212 lines (186 loc) 6.41 kB
import { ref, computed } from "vue"; import type { FileInputOptions, FileInputState } from "../types"; /** * Composable для управления выбором файлов * * Предоставляет функциональность для выбора, валидации и управления файлами * с поддержкой drag & drop, валидации размера и типа файлов * * @param options - Опции для настройки валидации и ограничений * @returns Объект с состоянием и методами для работы с файлами * * @example * ```typescript * const { * selectedFiles, * errors, * selectFiles, * removeFile, * clearFiles, * isFileSelected, * totalSize * } = useFileInput({ * maxFiles: 5, * maxFileSize: 10 * 1024 * 1024, // 10MB * allowedTypes: ['image/jpeg', 'image/png'], * multiple: true * }) * ``` */ export function useFileInput(options: FileInputOptions = {}) { const { maxFiles = 10, maxFileSize = 50 * 1024 * 1024, // 50MB по умолчанию allowedTypes = [], multiple = true, } = options; // Состояние /** Массив выбранных файлов */ const selectedFiles = ref<File[]>([]); /** Массив ошибок валидации */ const errors = ref<string[]>([]); // Computed свойства /** Есть ли выбранные файлы */ const isFileSelected = computed(() => selectedFiles.value.length > 0); /** Общий размер всех выбранных файлов в байтах */ const totalSize = computed(() => selectedFiles.value.reduce((total, file) => total + file.size, 0) ); /** Массив уникальных MIME-типов выбранных файлов */ const fileTypes = computed(() => [ ...new Set(selectedFiles.value.map((file) => file.type)), ]); /** Можно ли выбрать еще файлы */ const canSelectMore = computed( () => multiple && selectedFiles.value.length < maxFiles ); /** * Выбирает файлы с валидацией * * @param files - FileList или массив файлов для выбора */ const selectFiles = (files: FileList | File[]) => { const fileArray = Array.from(files); const newErrors: string[] = []; // Проверяем каждый файл fileArray.forEach((file) => { // Проверка количества файлов if (selectedFiles.value.length >= maxFiles) { newErrors.push(`Максимальное количество файлов: ${maxFiles}`); return; } // Проверка размера файла if (file.size > maxFileSize) { newErrors.push( `Файл ${file.name} превышает максимальный размер ${formatFileSize( maxFileSize )}` ); return; } // Проверка типа файла if (allowedTypes.length > 0 && !allowedTypes.includes(file.type)) { newErrors.push(`Тип файла ${file.name} не поддерживается`); return; } // Добавляем файл если нет ошибок selectedFiles.value.push(file); }); // Обновляем ошибки errors.value = [...errors.value, ...newErrors]; }; /** * Удаляет файл по индексу * * @param index - Индекс файла для удаления */ const removeFile = (index: number) => { if (index >= 0 && index < selectedFiles.value.length) { selectedFiles.value.splice(index, 1); } }; /** * Удаляет файл по имени * * @param fileName - Имя файла для удаления */ const removeFileByName = (fileName: string) => { const index = selectedFiles.value.findIndex( (file) => file.name === fileName ); if (index !== -1) { removeFile(index); } }; /** * Очищает все выбранные файлы и ошибки */ const clearFiles = () => { selectedFiles.value = []; errors.value = []; }; /** * Заменяет файл на новый с валидацией * * @param oldFile - Старый файл для замены * @param newFile - Новый файл * @returns true если замена прошла успешно, false если есть ошибки валидации */ const replaceFile = (oldFile: File, newFile: File) => { const index = selectedFiles.value.findIndex((file) => file === oldFile); if (index !== -1) { // Проверяем новый файл if (newFile.size > maxFileSize) { errors.value.push( `Файл ${newFile.name} превышает максимальный размер ${formatFileSize( maxFileSize )}` ); return false; } if (allowedTypes.length > 0 && !allowedTypes.includes(newFile.type)) { errors.value.push(`Тип файла ${newFile.name} не поддерживается`); return false; } selectedFiles.value[index] = newFile; return true; } return false; }; /** * Очищает все ошибки валидации */ const clearErrors = () => { errors.value = []; }; // Вспомогательные функции const formatFileSize = (bytes: number): string => { if (bytes === 0) return "0 Bytes"; const k = 1024; const sizes = ["Bytes", "KB", "MB", "GB"]; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i]; }; return { // Состояние selectedFiles, errors, // Computed isFileSelected, totalSize, fileTypes, canSelectMore, // Методы selectFiles, removeFile, removeFileByName, clearFiles, replaceFile, clearErrors, // Константы maxFiles, maxFileSize, allowedTypes, multiple, }; }