UNPKG

react-filezone

Version:

filezone: A Robust, Flexible React File Upload Library with Advanced Features and Seamless User Experience

3 lines (2 loc) 8 kB
import{useState as e,useRef as t,useCallback as r,useEffect as i}from"react";import{v4 as n}from"uuid";import o from"axios";function a(e,t,r,i){return new(r||(r=Promise))((function(n,o){function a(e){try{l(i.next(e))}catch(e){o(e)}}function s(e){try{l(i.throw(e))}catch(e){o(e)}}function l(e){var t;e.done?n(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(a,s)}l((i=i.apply(e,t||[])).next())}))}"function"==typeof SuppressedError&&SuppressedError;const s=({action:s,globalConfig:l={},metadata:d={},onUploadStart:c,onUploadComplete:p,onError:u,headers:g})=>{const{mode:f="multiple",maxFiles:m=3,maxFileSize:v=10737418240,allowedFileTypes:h=["*/*"],maxConcurrentUploads:w=5,disabled:y=!1}=l,[b,O]=e(!1),[j,P]=e([]),[D,U]=e([]),x=t(new Map),$=t([]),E=t(new Set),[S,M]=e(!1),C=r((e=>new Promise(((t,r)=>{const i=e.type||"",n=h.some((e=>{if(e.endsWith("*")){const t=e.slice(0,-1);return i.startsWith(t)}return i===e}));if(n&&(i.startsWith("image/")||h.includes("image/*"))){const i=new FileReader;i.onloadend=()=>{t({imagePreview:i.result})},i.onerror=r,i.readAsDataURL(e)}else if(n&&(h.includes("video/*")||h.includes(i)||h.some((e=>e.startsWith("video/")&&e===i)))){const i=document.createElement("video");i.preload="metadata";const n=URL.createObjectURL(e);i.onloadedmetadata=()=>{const e=document.createElement("canvas");e.width=i.videoWidth||320,e.height=i.videoHeight||240;const r=e.getContext("2d");null==r||r.drawImage(i,0,0,e.width,e.height),URL.revokeObjectURL(n),t({videoPreview:n})},i.onerror=r,i.src=n}else t({})}))),[h]),F=r((e=>h.some((t=>{if(t.endsWith("*")){const r=t.slice(0,-1);return e.type.startsWith(r)}return e.type===t}))?e.size>v?{valid:!1,error:`File too large: ${e.name}. Max size: ${v/1048576}MB`}:"single"===f&&j.length>=1?{valid:!1,error:"Only one file allowed in single mode"}:"multiple"===f&&j.length>=m?{valid:!1,error:`Maximum ${m} files allowed`}:{valid:!0}:{valid:!1,error:`Invalid file type: ${e.type}. Allowed types: ${h.join(", ")}`}),[h,v,f,m,j]),A=(e,t)=>a(void 0,void 0,void 0,(function*(){const{method:r="POST",body:i,headers:n={"Content-Type":"multipart/form-data"},signal:a,startByte:s=0,fileId:l,onUploadProgress:d}=t,c=i instanceof FormData?Array.from(i.values()).reduce(((e,t)=>e+(t instanceof Blob?t.size:new Blob([t]).size)),0):i.size;return o({url:e,method:r,data:i,headers:Object.assign({},n),signal:a&&a.aborted?a:void 0,onUploadProgress:e=>{const t=e.loaded+s,r=Math.min(Math.round(t/c*100),100);P((e=>e.map((e=>e.id===l?Object.assign(Object.assign({},e),{state:Object.assign(Object.assign({},e.state),{progress:r})}):e)))),null==d||d({loaded:t,total:c,progress:r})}}).then((e=>e)).catch((e=>{if(o.isCancel(e))throw new Error("Upload aborted");throw e}))})),z=r((e=>a(void 0,void 0,void 0,(function*(){if(y)return;const t=j.findIndex((t=>t.id===e));if(-1===t)return;const r=j[t];if(["uploading","completed"].includes(r.state.status))return;const i=new AbortController;x.current.set(e,i);try{P((t=>t.map((t=>t.id===e?Object.assign(Object.assign({},t),{state:Object.assign(Object.assign({},t.state),{status:"uploading",progress:0,errors:[]})}):t))));const t=new FormData;t.append("file",r.file);const n=yield A(s,{method:"POST",body:t,headers:Object.assign({},g),signal:i.signal,fileId:e,onUploadProgress:t=>{P((r=>r.map((r=>r.id===e?Object.assign(Object.assign({},r),{state:Object.assign(Object.assign({},r.state),{progress:t.progress,status:100===t.progress?"completed":"uploading"})}):r))))}});if("object"==typeof n&&null!==n&&"status"in n){if(!n)throw new Error(`Upload failed with status: ${n}`)}else if("string"==typeof n)throw new Error("Unexpected response format");return null==p||p(n.data),n}catch(t){throw P((r=>r.map((r=>r.id===e?Object.assign(Object.assign({},r),{state:Object.assign(Object.assign({},r.state),{status:"error",progress:0,errors:[t.message||"Upload failed"]})}):r)))),null==u||u(t,r),t}finally{x.current.delete(e)}}))),[j,s,p,u,A,y]),L=r((()=>a(void 0,void 0,void 0,(function*(){if("single"!==f)for(;$.current.length>0;){const e=$.current.filter((e=>{const t=j.find((t=>t.id===e));return"pending"===(null==t?void 0:t.state.status)&&!E.current.has(e)}));if(0===e.length)break;const t=w-E.current.size;if(t<=0){yield new Promise((e=>setTimeout(e,100)));continue}e.slice(0,t).forEach((e=>a(void 0,void 0,void 0,(function*(){if(!E.current.has(e)){E.current.add(e);try{yield z(e)}catch(e){}finally{E.current.delete(e),$.current=$.current.filter((t=>t!==e))}}})))),yield new Promise((e=>setTimeout(e,100)))}}))),[z,w,j]),R=r((e=>a(void 0,void 0,void 0,(function*(){M(!0);try{const t=e=>`${e.name}-${e.size}-${e.lastModified}`,r=Array.from(new Map(e.map((e=>[t(e),e]))).values()),i=new Set(j.map((e=>t(e.file)))),o=r.filter((e=>!i.has(t(e))));if("single"===f){if(o.length>1)return void U((e=>[...e,"Only one file can be selected in single mode."]));if(j.length>0){const e=j[0].id,t=x.current.get(e);t&&(t.abort(),x.current.delete(e))}if(0===o.length)return;const e=o[0],{imagePreview:t,videoPreview:r}=yield C(e);P([{id:n(),file:e,previewUrl:t,videoPreviewUrl:r,state:{status:"idle",progress:0,errors:[]},metadata:Object.assign({},d)}])}else{if(j.length+o.length>m){const e=o.slice(0,m-j.length);U((t=>[...t,`Maximum ${m} files allowed. Only ${e.length} files were added.`])),o.splice(0,e.length)}const e=yield Promise.all(o.map((e=>a(void 0,void 0,void 0,(function*(){const{imagePreview:t,videoPreview:r}=yield C(e),i=F(e);return i.valid?{fileState:{id:n(),file:e,previewUrl:t,videoPreviewUrl:r,state:{status:"pending",progress:0,errors:[]},metadata:Object.assign({},d)}}:{error:i.error||"Validation failed"}}))))),t=e.filter((e=>void 0!==e.error)).map((e=>e.error)),r=e.filter((e=>void 0!==e.fileState)).map((e=>e.fileState));t.length>0&&U((e=>[...e,...t])),P((e=>($.current=[...$.current,...r.map((e=>e.id))],null==c||c(r),L(),[...e,...r])))}}finally{M(!1)}}))),[F,d,c,L,j,f,m,C]),T=r((e=>{const t=x.current.get(e);if(t){try{t.abort()}catch(t){console.warn(`Error aborting upload for file ${e}:`,t)}x.current.delete(e)}P((t=>t.filter((t=>t.id!==e))))}),[]),W=r((e=>{P((t=>t.map((t=>t.id===e?Object.assign(Object.assign({},t),{state:Object.assign(Object.assign({},t.state),{status:"pending",progress:0,errors:[]})}):t)))),z(e)}),[z]),I=r((()=>y?{onDragEnter:e=>{e.preventDefault(),e.stopPropagation()},onDragLeave:e=>{e.preventDefault(),e.stopPropagation()},onDragOver:e=>{e.preventDefault(),e.stopPropagation()},onDrop:e=>{e.preventDefault(),e.stopPropagation()},onClick:()=>{}}:{onDragEnter:e=>{e.preventDefault(),e.stopPropagation(),O(!0)},onDragLeave:e=>{e.preventDefault(),e.stopPropagation(),O(!1)},onDragOver:e=>{e.preventDefault(),e.stopPropagation(),b||O(!0)},onDrop:e=>{e.preventDefault(),e.stopPropagation(),O(!1);const t=Array.from(e.dataTransfer.files);if("multiple"===f&&t.length+j.length>m){const e=t.slice(0,m-j.length);R(e),U((t=>[...t,`Maximum ${m} files allowed. Only ${e.length} files were added.`]))}else R(t)},onClick:()=>{const e=document.createElement("input");e.type="file",e.multiple="multiple"===f,e.max="multiple"===f?m.toString():"1",e.accept=h.join(","),e.onchange=e=>{const t=e.target;if(t.files){const e=Array.from(t.files);if("multiple"===f&&e.length>m){const t=e.slice(0,m);R(t),U((e=>[...e,`Maximum ${m} files allowed. Only ${t.length} files were added.`]))}else R(e)}},e.click()}}),[R,f,h,m,j,b,y]),k=r((()=>y?{type:"file",multiple:!1,accept:"",max:"0",onChange:()=>{}}:{type:"file",multiple:"multiple"===f,accept:h.join(","),max:"multiple"===f?m.toString():"1",onChange:e=>{const t=e.target;if(t.files){const e=Array.from(t.files);if("multiple"===f&&e.length>m){const t=e.slice(0,m);R(t),U((e=>[...e,`Maximum ${m} files allowed. Only ${t.length} files were added.`]))}else R(e)}}}),[R,f,h,m,y]);return i((()=>{"multiple"===f&&$.current.length>0&&L()}),[f,L,j]),{acceptedFiles:j,errors:D,getRootProps:I,getInputProps:k,removeFile:T,uploadFile:z,isDragActive:b,isValidatingFiles:S,restartUpload:W,disabled:y}};export{s as useUpload}; //# sourceMappingURL=index.mjs.map