UNPKG

react-filezone

Version:

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

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