@spaced-out/ui-design-system
Version:
Sense UI components library
265 lines (262 loc) • 7.93 kB
JavaScript
;
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;