smart-dropzone-react
Version:
🚀 A production-ready React dropzone component with smart defaults, drag & drop reordering, chunked uploads, resume functionality, and comprehensive provider support (Cloudinary, AWS S3, Supabase)
2 lines • 5.31 kB
JavaScript
var chunkSMFYABWO_cjs=require('./chunk-SMFYABWO.cjs'),chunkBYLIBOAU_cjs=require('./chunk-BYLIBOAU.cjs');var n=class n{constructor(e={}){chunkBYLIBOAU_cjs.a(this,"resumeStates",new Map);chunkBYLIBOAU_cjs.a(this,"options");chunkBYLIBOAU_cjs.a(this,"activeUploads",new Set);chunkBYLIBOAU_cjs.a(this,"chunkQueue",new Map);this.options={chunkSize:chunkSMFYABWO_cjs.a.CHUNK_SIZE,maxConcurrentChunks:chunkSMFYABWO_cjs.e.MAX_CONCURRENT_CHUNKS,retryAttempts:chunkSMFYABWO_cjs.e.MAX_RETRY_ATTEMPTS,retryDelay:chunkSMFYABWO_cjs.b.RETRY_DELAY,enableResume:true,validateChunks:true,checksumAlgorithm:"md5",...e};}static getInstance(){return n.instance||(n.instance=new n),n.instance}async createResumeState(e,t){let s=this.generateFileId(e),a=this.createChunks(e),r=await this.calculateChecksum(e),i={fileId:s,fileName:e.name,totalSize:e.size,uploadedSize:0,chunks:a,status:"paused",lastChunkIndex:-1,checksum:r,metadata:{provider:t,mimeType:e.type,lastModified:e.lastModified,createdAt:Date.now()}};return this.resumeStates.set(s,i),this.chunkQueue.set(s,[...a]),i}async resumeUpload(e,t){let s=this.resumeStates.get(e);if(!s)return {success:false,uploadedSize:0,totalSize:0,chunks:[],error:"Resume state not found"};if(s.status==="completed")return {success:true,uploadedSize:s.totalSize,totalSize:s.totalSize,chunks:s.chunks};s.status="resuming",this.activeUploads.add(e);try{this.options.validateChunks&&await this.validateExistingChunks(s,t);let a=await this.uploadRemainingChunks(s,t);return a.success?(s.status="completed",s.uploadedSize=s.totalSize):s.status="failed",a}catch(a){return s.status="failed",{success:false,uploadedSize:s.uploadedSize,totalSize:s.totalSize,chunks:s.chunks,error:a instanceof Error?a.message:"Unknown error"}}finally{this.activeUploads.delete(e);}}pauseUpload(e){let t=this.resumeStates.get(e);return !t||t.status==="completed"?false:(t.status="paused",true)}cancelUpload(e){let t=this.resumeStates.get(e);return t?(this.chunkQueue.delete(e),this.activeUploads.delete(e),t.status="paused",t.uploadedSize=0,t.chunks.forEach(s=>{s.uploaded=false,s.retryCount=0;}),true):false}getResumeState(e){return this.resumeStates.get(e)}getAllResumeStates(){return Array.from(this.resumeStates.values())}clearResumeState(e){let t=this.resumeStates.delete(e);return this.chunkQueue.delete(e),this.activeUploads.delete(e),t}createChunks(e){let t=[];if(e.size===0)return t.push({id:`${e.name}-chunk-0`,start:0,end:0,data:new Blob,uploaded:false,retryCount:0,maxRetries:this.options.retryAttempts}),t;let s=Math.ceil(e.size/this.options.chunkSize);for(let a=0;a<s;a++){let r=a*this.options.chunkSize,i=Math.min(r+this.options.chunkSize,e.size),d=e.slice(r,i);t.push({id:`${e.name}-chunk-${a}`,start:r,end:i,data:d,uploaded:false,retryCount:0,maxRetries:this.options.retryAttempts});}return t}async calculateChecksum(e){let t=await e.arrayBuffer(),s=await crypto.subtle.digest("SHA-256",t);return Array.from(new Uint8Array(s)).map(r=>r.toString(16).padStart(2,"0")).join("")}async validateExistingChunks(e,t){try{let s=await t.getUploadedChunks?.(e.fileId)||[];e.chunks.forEach((a,r)=>{s.includes(r)&&(a.uploaded=!0,e.uploadedSize+=a.end-a.start,e.lastChunkIndex=Math.max(e.lastChunkIndex,r));});}catch{}}async uploadRemainingChunks(e,t){let s=e.chunks.filter(o=>!o.uploaded);if(s.length===0)return {success:true,uploadedSize:e.totalSize,totalSize:e.totalSize,chunks:e.chunks};let a=[],r=new Set;for(let o of s){r.size>=this.options.maxConcurrentChunks&&(await Promise.race(a),a.splice(0,1));let h=this.uploadChunk(o,e,t);r.add(o.id),h.then(()=>{r.delete(o.id);}),a.push(h);}let d=(await Promise.all(a)).every(o=>o);return {success:d,uploadedSize:e.uploadedSize,totalSize:e.totalSize,chunks:e.chunks,error:d?void 0:"Some chunks failed to upload"}}async uploadChunk(e,t,s){let a=0,r=e.maxRetries+1;for(;a<r;){try{if(await this.uploadChunkToProvider(e,t,s))return e.uploaded=!0,t.uploadedSize+=e.end-e.start,t.lastChunkIndex=Math.max(t.lastChunkIndex,t.chunks.indexOf(e)),this.emitProgressEvent(t,e),!0}catch{e.retryCount++,a<r-1&&await this.delay(this.options.retryDelay*Math.pow(chunkSMFYABWO_cjs.b.RETRY_EXPONENTIAL_BASE,a));}a++;}return false}async uploadChunkToProvider(e,t,s){try{return await this.delay(Math.random()*chunkSMFYABWO_cjs.e.UPLOAD_SIMULATION_DELAY_RANGE+chunkSMFYABWO_cjs.e.UPLOAD_SIMULATION_DELAY_MIN),!0}catch(a){throw new Error(`Failed to upload chunk: ${a}`)}}emitProgressEvent(e,t){let s=e.uploadedSize/e.totalSize*100,a=new CustomEvent("uploadProgress",{detail:{fileId:e.fileId,fileName:e.fileName,progress:s,uploadedSize:e.uploadedSize,totalSize:e.totalSize,chunkId:t.id,chunkProgress:100}});document.dispatchEvent(a);}generateFileId(e){return n.fileIdCounter++,`resume-${e.name}-${e.size}-${e.lastModified}-${Date.now()}-${n.fileIdCounter}`}delay(e){return new Promise(t=>setTimeout(t,e))}getUploadProgress(e){let t=this.resumeStates.get(e);return t?t.uploadedSize/t.totalSize*100:0}isUploadActive(e){return this.activeUploads.has(e)}getActiveUploads(){return Array.from(this.activeUploads)}destroy(){this.resumeStates.clear(),this.chunkQueue.clear(),this.activeUploads.clear();}};chunkBYLIBOAU_cjs.a(n,"instance"),chunkBYLIBOAU_cjs.a(n,"fileIdCounter",0);var m=n;exports.a=m;//# sourceMappingURL=chunk-YGRSDHFI.cjs.map
//# sourceMappingURL=chunk-YGRSDHFI.cjs.map
;