UNPKG

@spaced-out/ui-design-system

Version:
265 lines (262 loc) 7.93 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.useFileUpload = void 0; var React = _interopRequireWildcard(require("react")); var _reactDropzone = require("react-dropzone"); var _helpers = require("../../utils/helpers"); function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); } // useFileUpload hook returns these props const initialState = { validFiles: [], rejectedFiles: [] }; const reducer = (state, action) => { switch (action.type) { case 'ADD_VALID_FILES': return { ...state, validFiles: [...state.validFiles, ...action.files] }; case 'ADD_REJECTED_FILES': return { ...state, rejectedFiles: [...state.rejectedFiles, ...action.files] }; case 'REMOVE_FILE': return { ...state, validFiles: state.validFiles.filter(file => file.id !== action.id), rejectedFiles: state.rejectedFiles.filter(file => file.id !== action.id) }; case 'CLEAR_FILES': return { validFiles: [], rejectedFiles: [] }; case 'UPDATE_FILE_PROGRESS': return { ...state, validFiles: state.validFiles.map(file => file.id === action.id ? { ...file, progress: action.progress, showReUpload: false, successMessage: undefined, rejectReason: undefined } : file), rejectedFiles: state.rejectedFiles.map(file => file.id === action.id ? { ...file, progress: action.progress, showReUpload: false, successMessage: undefined, rejectReason: undefined } : file) }; case 'SET_FILE_RE_UPLOAD': return { ...state, validFiles: state.validFiles.map(file => file.id === action.id ? { ...file, progress: undefined, showReUpload: action.showReUpload } : file), rejectedFiles: state.rejectedFiles.map(file => file.id === action.id ? { ...file, progress: undefined, showReUpload: action.showReUpload } : file) }; case 'SET_FILE_SUCCESS': { // Note: When a file is accepted manually we would move a file from rejected files(if found) to valid files first const fileIndex = state.rejectedFiles.findIndex(file => file.id === action.id); let validFiles = [...state.validFiles]; const rejectedFiles = [...state.rejectedFiles]; if (fileIndex !== -1) { const file = rejectedFiles[fileIndex]; rejectedFiles.splice(fileIndex, 1); validFiles = [...validFiles, { ...file }]; } validFiles = validFiles.map(file => file.id === action.id ? { ...file, success: true, successMessage: action.successMessage, reject: false, rejectReason: undefined, progress: undefined, showReUpload: false } : file); return { ...state, validFiles, rejectedFiles }; } case 'SET_FILE_REJECT': { // Note: When a file is rejected manually we would move a file from valid files(if found) to rejected files first const fileIndex = state.validFiles.findIndex(file => file.id === action.id); const validFiles = [...state.validFiles]; let rejectedFiles = [...state.rejectedFiles]; if (fileIndex !== -1) { const file = validFiles[fileIndex]; validFiles.splice(fileIndex, 1); rejectedFiles = [...rejectedFiles, { ...file }]; } rejectedFiles = rejectedFiles.map(file => file.id === action.id ? { ...file, reject: true, rejectReason: action.rejectReason, success: false, successMessage: undefined, progress: undefined, showReUpload: false } : file); return { ...state, validFiles, rejectedFiles }; } default: return state; } }; // This is a map of error codes returned by react-dropzone and their corresponding error messages const DROPZONE_ERROR_MESSAGES = { 'file-too-large': 'File exceeds maximum size', 'file-invalid-type': 'Wrong file type', 'too-many-files': 'Too many files', 'file-too-small': 'File is too small' }; const useFileUpload = _ref => { let { maxFiles = 1, maxSize, accept, disabled, onValidFilesDrop, onRejectedFilesDrop, onFileClear, onClear } = _ref; const [state, dispatch] = React.useReducer(reducer, initialState); const handleDropAccepted = acceptedFiles => { const validFiles = acceptedFiles.map(file => ({ file, id: (0, _helpers.uuid)(), reject: false, rejectReason: undefined, success: true, successMessage: undefined, progress: undefined, showReUpload: false })); dispatch({ type: 'ADD_VALID_FILES', files: validFiles }); onValidFilesDrop?.(validFiles); }; const handleDropRejected = fileRejections => { const rejectedFiles = fileRejections.map(_ref2 => { let { file, errors } = _ref2; return { file, id: (0, _helpers.uuid)(), reject: true, rejectReason: DROPZONE_ERROR_MESSAGES[errors[0]?.code] ?? 'Some error occurred uploading this file', success: false, successMessage: undefined, progress: undefined, showReUpload: false }; }); dispatch({ type: 'ADD_REJECTED_FILES', files: rejectedFiles }); onRejectedFilesDrop?.(rejectedFiles); }; const handleFileClear = id => { dispatch({ type: 'REMOVE_FILE', id }); onFileClear?.(id); }; const handleClear = () => { dispatch({ type: 'CLEAR_FILES' }); onClear?.(); }; const moveFileToProgress = (id, progress) => { dispatch({ type: 'UPDATE_FILE_PROGRESS', id, progress }); }; const moveFileToSuccess = (id, successMessage) => { dispatch({ type: 'SET_FILE_SUCCESS', id, successMessage }); }; const moveFileToReject = (id, rejectReason) => { dispatch({ type: 'SET_FILE_REJECT', id, rejectReason }); }; const setShowReUpload = (id, showReUpload) => { dispatch({ type: 'SET_FILE_RE_UPLOAD', id, showReUpload }); }; const totalFiles = state.validFiles.length + state.rejectedFiles.length; const shouldAcceptFiles = !disabled && (maxFiles === 0 || totalFiles < maxFiles); const { isDragActive, getRootProps, getInputProps } = (0, _reactDropzone.useDropzone)({ maxFiles, multiple: maxFiles > 1 || maxFiles === 0, maxSize, accept, disabled, noClick: !shouldAcceptFiles, noDrag: !shouldAcceptFiles, onDropAccepted: handleDropAccepted, onDropRejected: (rejections, _evt) => handleDropRejected(rejections) }); return { validFiles: state.validFiles, rejectedFiles: state.rejectedFiles, shouldAcceptFiles, isDragActive, getRootProps, getInputProps, handleFileClear, handleClear, moveFileToProgress, moveFileToSuccess, moveFileToReject, setShowReUpload }; }; exports.useFileUpload = useFileUpload;