UNPKG

@mikezimm/fps-library-v2

Version:

Library of reusable typescript/javascript functions, interfaces and constants

148 lines 8.87 kB
import * as React from 'react'; import { useState, useEffect, useRef } from 'react'; import { getMIMETypesFromObjects, getMIMETypesProp, } from '@mikezimm/fps-core-v7/lib/components/atoms/Inputs/FileDropBox/fps-FileDropTypes'; import { getSizeLabel } from "@mikezimm/fps-core-v7/lib/logic/Math/labels"; import { createFileElementList } from './fps-FileDropBoxElements'; // https://github.com/fps-solutions/FPS-Photo-Form/issues/89 // require('@mikezimm/fps-styles/dist/fps-FileDrop.css'); require('@mikezimm/fps-styles/dist/fps-FileDrop.css'); /*** * .d8888. d888888b .d8b. d8888b. d888888b db db .d88b. .d88b. db dD * 88' YP `~~88~~' d8' `8b 88 `8D `~~88~~' 88 88 .8P Y8. .8P Y8. 88 ,8P' * `8bo. 88 88ooo88 88oobY' 88 88ooo88 88 88 88 88 88,8P * `Y8b. 88 88~~~88 88`8b 88 88~~~88 88 88 88 88 88`8b * db 8D 88 88 88 88 `88. 88 88 88 `8b d8' `8b d8' 88 `88. * `8888Y' YP YP YP 88 YD YP YP YP `Y88P' `Y88P' YP YD * * */ const FileDropBox = ({ fileTypes, setParentFilesData, style, maxUploadCount, fileMaxSize = 100000, refreshId, resetId, useDropBox }) => { const [fileMIMETypes, setFileMIMETypes] = useState(getMIMETypesFromObjects(fileTypes)); const [fileMIMELabels, setFileMIMELabels] = useState(getMIMETypesProp(fileTypes, 'name')); const [dragging, setDragging] = useState(false); // Track if files are being dragged over the box const [errorMessage, setErrorMessage] = useState(null); const [invalidFiles, setInvalidFiles] = useState([]); // Track invalid files // Use a ref for the file input const fileInputRef = useRef(null); /*** * db db .d8888. d88888b d88888b d88888b d88888b d88888b .o88b. d888888b * 88 88 88' YP 88' 88' 88' 88' 88' d8P Y8 `~~88~~' * 88 88 `8bo. 88ooooo 88ooooo 88ooo 88ooo 88ooooo 8P 88 * 88 88 `Y8b. 88~~~~~ 88~~~~~ 88~~~ 88~~~ 88~~~~~ 8b 88 * 88b d88 db 8D 88. 88. 88 88 88. Y8b d8 88 * ~Y8888P' `8888Y' Y88888P Y88888P YP YP Y88888P `Y88P' YP * * */ useEffect(() => { // eslint-disable-next-line @typescript-eslint/no-use-before-define handleClear(); }, [resetId]); useEffect(() => { setFileMIMETypes(getMIMETypesFromObjects(fileTypes)); setFileMIMELabels(getMIMETypesProp(fileTypes, 'name')); }, [fileTypes]); // if ( useDropBox === false ) return undefined; /*** * db db .d8b. d8b db d8888b. db d88888b .o88b. db d888888b .o88b. db dD .d8888. * 88 88 d8' `8b 888o 88 88 `8D 88 88' d8P Y8 88 `88' d8P Y8 88 ,8P' 88' YP * 88ooo88 88ooo88 88V8o 88 88 88 88 88ooooo 8P 88 88 8P 88,8P `8bo. * 88~~~88 88~~~88 88 V8o88 88 88 88 88~~~~~ 8b 88 88 8b 88`8b `Y8b. * 88 88 88 88 88 V888 88 .8D 88booo. 88. Y8b d8 88booo. .88. Y8b d8 88 `88. db 8D * YP YP YP YP VP V8P Y8888D' Y88888P Y88888P `Y88P' Y88888P Y888888P `Y88P' YP YD `8888Y' * * */ // Handle the files when dropped const handleDrop = (e) => { e.preventDefault(); setDragging(false); // Reset dragging state // Extract files from the event const files = e.dataTransfer.files; // eslint-disable-next-line @typescript-eslint/no-use-before-define handleFiles(files); }; const handleClear = () => { setInvalidFiles([]); // Track invalid files for feedback setErrorMessage(null); setParentFilesData(null); // Pass valid files to the parent component }; // Handle files dropped or selected const handleFiles = (files) => { const validFiles = []; // https://github.com/fps-solutions/FPS-Photo-Form/issues/88 - retain invalidFiles in history let currentInvalidFiles = invalidFiles; let invalidNames = invalidFiles.map(file => { return file.name; }); // Validate the file types if a fileTypes prop is passed if (fileMIMETypes) { for (let i = 0; i < files.length; i++) { const file = files[i]; if (fileMIMETypes.indexOf(file.type) === -1 || file.size > fileMaxSize) { // Use indexOf instead of includes // https://github.com/fps-solutions/FPS-Photo-Form/issues/88 - retain invalidFiles in history const invalidIdx = invalidNames.indexOf(file.name); if (invalidIdx > -1) { currentInvalidFiles = currentInvalidFiles.filter((_, i) => i !== invalidIdx); invalidNames = invalidNames.filter((_, i) => i !== invalidIdx); } currentInvalidFiles.unshift(file); invalidNames.unshift(file.name); } else { validFiles.push(file); } } } if (validFiles.length > 0) { setParentFilesData(validFiles); // Pass valid files to the parent component } if (currentInvalidFiles.length > 0) { setInvalidFiles(currentInvalidFiles); // Track invalid files for feedback setErrorMessage('Some files are of invalid type.'); } else { setErrorMessage(null); // Clear error if all files are valid } if (validFiles.length === 0) setParentFilesData(validFiles); }; // Handle the drag over event to allow drop and set the dragging state const handleDragOver = (e) => { e.preventDefault(); // Prevent the default handling of the event setDragging(true); // Set dragging state to true when files are over the drop zone }; // Handle when drag leaves the area const handleDragLeave = () => { setDragging(false); // Reset dragging state when drag leaves the drop zone }; /*** * d88888b d888888b d8b db .d8b. db d88888b db d88888b .88b d88. d88888b d8b db d888888b * 88' `88' 888o 88 d8' `8b 88 88' 88 88' 88'YbdP`88 88' 888o 88 `~~88~~' * 88ooo 88 88V8o 88 88ooo88 88 88ooooo 88 88ooooo 88 88 88 88ooooo 88V8o 88 88 * 88~~~ 88 88 V8o88 88~~~88 88 88~~~~~ 88 88~~~~~ 88 88 88 88~~~~~ 88 V8o88 88 * 88 .88. 88 V888 88 88 88booo. 88. 88booo. 88. 88 88 88 88. 88 V888 88 * YP Y888888P VP V8P YP YP Y88888P Y88888P Y88888P Y88888P YP YP YP Y88888P VP V8P YP * * */ console.log(`UploadStatus: FileDropBox ~ 88`); return (React.createElement("div", { className: `file-drop-box ${dragging ? 'dragging' : ''}`, onDragOver: handleDragOver, onDrop: handleDrop, onDragLeave: handleDragLeave, style: { ...style, ...{ display: useDropBox !== true ? 'none' : 'block' } } }, React.createElement("div", { className: `file-drop-box-area`, style: {} }, React.createElement("p", null, "Drag and drop files here ", fileMaxSize ? `< ${getSizeLabel(fileMaxSize)} each` : ''), fileMIMELabels && React.createElement("p", null, React.createElement("strong", null, "Accepted file types: "), fileMIMELabels.join(' | ')), errorMessage && React.createElement("div", { style: { color: 'red' } }, errorMessage), invalidFiles.length > 0 && (React.createElement("div", { style: { color: 'red' } }, React.createElement("strong", null, "Rejected Files: ( ", invalidFiles.length, " )"), createFileElementList(invalidFiles, fileMaxSize, undefined, false, false)))), React.createElement("input", { ref: fileInputRef, type: "file", multiple: maxUploadCount === 1 ? false : true, onChange: (e) => e.target.files ? handleFiles(e.target.files) : null, style: { display: 'none' } }), React.createElement("button", { type: 'button', onClick: () => { var _a; return (_a = fileInputRef.current) === null || _a === void 0 ? void 0 : _a.click(); } }, "Choose files"), React.createElement("button", { type: 'button', onClick: handleClear, className: 'reset', style: { marginLeft: '2em' } }, "Clear files"))); }; export default FileDropBox; //# sourceMappingURL=fps-FileDropBox.js.map