@masters-union/union-stack 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- "use strict";var UnionStack=(()=>{var B=Object.defineProperty,se=Object.defineProperties,ae=Object.getOwnPropertyDescriptor,le=Object.getOwnPropertyDescriptors,de=Object.getOwnPropertyNames,K=Object.getOwnPropertySymbols;var G=Object.prototype.hasOwnProperty,pe=Object.prototype.propertyIsEnumerable;var V=(i,e,t)=>e in i?B(i,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):i[e]=t,T=(i,e)=>{for(var t in e||(e={}))G.call(e,t)&&V(i,t,e[t]);if(K)for(var t of K(e))pe.call(e,t)&&V(i,t,e[t]);return i},D=(i,e)=>se(i,le(e));var j=(i,e)=>()=>(i&&(e=i(i=0)),e);var W=(i,e)=>{for(var t in e)B(i,t,{get:e[t],enumerable:!0})},ce=(i,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of de(e))!G.call(i,o)&&o!==t&&B(i,o,{get:()=>e[o],enumerable:!(r=ae(e,o))||r.enumerable});return i};var ue=i=>ce(B({},"__esModule",{value:!0}),i);function Z(){if(typeof document=="undefined"||document.getElementById(J))return;let i=document.createElement("style");i.id=J,i.textContent=ve,document.head.appendChild(i)}function ee(i){var r,o,n,a,s,l;let t=((i==null?void 0:i.mode)||"light")==="dark"?Pe:ke;return{"--us-primary":(r=i==null?void 0:i.primary)!=null?r:t.primary,"--us-bg":(o=i==null?void 0:i.background)!=null?o:t.background,"--us-fg":(n=i==null?void 0:i.foreground)!=null?n:t.foreground,"--us-muted":(a=i==null?void 0:i.muted)!=null?a:t.muted,"--us-border":(s=i==null?void 0:i.border)!=null?s:t.border,"--us-radius":(l=i==null?void 0:i.radius)!=null?l:"12px"}}var J,ke,Pe,ve,te=j(()=>{"use strict";J="unionstack-picker-styles";ke={primary:"#4f46e5",background:"#ffffff",foreground:"#0f172a",muted:"#64748b",border:"#e2e8f0"},Pe={primary:"#6366f1",background:"#0f172a",foreground:"#f1f5f9",muted:"#94a3b8",border:"#1e293b"},ve=`
1
+ "use strict";var UnionStack=(()=>{var D=Object.defineProperty,se=Object.defineProperties,ae=Object.getOwnPropertyDescriptor,le=Object.getOwnPropertyDescriptors,de=Object.getOwnPropertyNames,K=Object.getOwnPropertySymbols;var W=Object.prototype.hasOwnProperty,pe=Object.prototype.propertyIsEnumerable;var V=(i,e,t)=>e in i?D(i,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):i[e]=t,x=(i,e)=>{for(var t in e||(e={}))W.call(e,t)&&V(i,t,e[t]);if(K)for(var t of K(e))pe.call(e,t)&&V(i,t,e[t]);return i},w=(i,e)=>se(i,le(e));var j=(i,e)=>()=>(i&&(e=i(i=0)),e);var G=(i,e)=>{for(var t in e)D(i,t,{get:e[t],enumerable:!0})},ce=(i,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of de(e))!W.call(i,o)&&o!==t&&D(i,o,{get:()=>e[o],enumerable:!(r=ae(e,o))||r.enumerable});return i};var ue=i=>ce(D({},"__esModule",{value:!0}),i);function Z(){if(typeof document=="undefined"||document.getElementById(J))return;let i=document.createElement("style");i.id=J,i.textContent=ve,document.head.appendChild(i)}function ee(i){var r,o,n,a,s,l;let t=((i==null?void 0:i.mode)||"light")==="dark"?Pe:ke;return{"--us-primary":(r=i==null?void 0:i.primary)!=null?r:t.primary,"--us-bg":(o=i==null?void 0:i.background)!=null?o:t.background,"--us-fg":(n=i==null?void 0:i.foreground)!=null?n:t.foreground,"--us-muted":(a=i==null?void 0:i.muted)!=null?a:t.muted,"--us-border":(s=i==null?void 0:i.border)!=null?s:t.border,"--us-radius":(l=i==null?void 0:i.radius)!=null?l:"12px"}}var J,ke,Pe,ve,te=j(()=>{"use strict";J="unionstack-picker-styles";ke={primary:"#4f46e5",background:"#ffffff",foreground:"#0f172a",muted:"#64748b",border:"#e2e8f0"},Pe={primary:"#6366f1",background:"#0f172a",foreground:"#f1f5f9",muted:"#94a3b8",border:"#1e293b"},ve=`
2
2
  .us-picker-backdrop {
3
3
  position: fixed; inset: 0; z-index: 2147483000;
4
4
  background: rgba(2, 6, 23, 0.55);
@@ -77,5 +77,5 @@
77
77
  padding: 8px 20px; font-size: 11px; color: var(--us-muted); text-align: center;
78
78
  }
79
79
  .us-footer a { color: var(--us-muted); }
80
- `});function Ue(i,e){var n,a,s,l,d,p,h,u,b,$,S,R,F,w,g,k,P,y,v,f;let t=T({},e),r=e.branding||{};t.branding={logoUrl:(a=(n=r.logoUrl)!=null?n:i.branding.logoUrl)!=null?a:void 0,title:(l=(s=r.title)!=null?s:i.branding.title)!=null?l:void 0,hideFooter:(d=r.hideFooter)!=null?d:i.branding.hideFooter};let o=e.theme||{};if(t.theme={primary:(h=(p=o.primary)!=null?p:i.theme.primary)!=null?h:void 0,background:(b=(u=o.background)!=null?u:i.theme.background)!=null?b:void 0,foreground:(S=($=o.foreground)!=null?$:i.theme.foreground)!=null?S:void 0,border:(F=(R=o.border)!=null?R:i.theme.border)!=null?F:void 0,radius:(g=(w=o.radius)!=null?w:i.theme.radius)!=null?g:void 0,mode:(P=(k=o.mode)!=null?k:i.theme.mode)!=null?P:void 0},t.maxFileSize=(y=e.maxFileSize)!=null?y:i.constraints.maxFileSizeBytes,t.maxFiles=(v=e.maxFiles)!=null?v:i.constraints.maxFilesPerUpload,!e.accept&&((f=i.constraints.allowedMimeTypes)!=null&&f.length)){let I=i.constraints.allowedMimeTypes.filter(H=>H!=="*/*");I.length>0&&(t.accept=I.join(","))}return t}function m(i,e,t){let r=document.createElement(i);return e&&(r.className=e),t!==void 0&&(r.textContent=t),r}function ie(i){return i<1024?`${i} B`:i<1024*1024?`${(i/1024).toFixed(1)} KB`:i<1024*1024*1024?`${(i/1024/1024).toFixed(1)} MB`:`${(i/1024/1024/1024).toFixed(2)} GB`}function re(){return typeof crypto!="undefined"&&"randomUUID"in crypto?crypto.randomUUID().replace(/-/g,""):Math.random().toString(36).slice(2)+Date.now().toString(36)}function M(i,e){let t=new x(i,e);return{open:()=>t.open(),close:()=>t.close(),cancel:()=>t.cancel()}}var xe,Ce,x,oe=j(()=>{"use strict";te();xe="Upload files",Ce="https://unionstack.mastersunion.link",x=class{constructor(e,t){this.client=e;this.opts=t;this.$backdrop=null;this.$list=null;this.$confirm=null;this.$cancel=null;this.$closeBtn=null;this.$input=null;this.items=[];this.abortCtrl=new AbortController;this.uploadStarted=!1;this.resolved=!1;this.donePromise=new Promise(r=>{this.resolvePromise=r})}async open(){var e,t;if(typeof document=="undefined")throw new Error("[union-stack] Picker requires a browser environment.");try{let r=await this.client.pickerConfigPromise;r&&(this.opts=Ue(r,this.opts))}catch(r){}return Z(),this.mount(),(t=(e=this.opts).onOpen)==null||t.call(e),this.donePromise}close(){this.unmount(),this.resolved||this.resolveResult()}cancel(){var e,t;this.abortCtrl.abort(),(t=(e=this.opts).onCancel)==null||t.call(e),this.close()}mount(){var s,l,d,p,h;let e=document.createElement("div");e.className="us-picker-backdrop",Object.entries(ee(this.opts.theme)).forEach(([u,b])=>{e.style.setProperty(u,b)}),e.addEventListener("click",u=>{u.target===e&&!this.uploadStarted&&this.cancel()});let t=m("div","us-picker"),r=m("div","us-picker-header");if((s=this.opts.branding)!=null&&s.logoUrl){let u=document.createElement("img");u.src=this.opts.branding.logoUrl,u.alt="logo",r.appendChild(u)}let o=m("div","us-picker-title",(d=(l=this.opts.branding)==null?void 0:l.title)!=null?d:xe);r.appendChild(o),this.$closeBtn=document.createElement("button"),this.$closeBtn.type="button",this.$closeBtn.className="us-picker-close",this.$closeBtn.setAttribute("aria-label","Close"),this.$closeBtn.textContent="\xD7",this.$closeBtn.onclick=()=>this.cancel(),r.appendChild(this.$closeBtn),t.appendChild(r);let n=m("div","us-picker-body");n.appendChild(this.renderDropzone()),this.$list=m("div","us-file-list"),n.appendChild(this.$list),t.appendChild(n);let a=m("div","us-actions");if(this.$cancel=document.createElement("button"),this.$cancel.type="button",this.$cancel.className="us-btn",this.$cancel.textContent="Cancel",this.$cancel.onclick=()=>this.cancel(),this.$confirm=document.createElement("button"),this.$confirm.type="button",this.$confirm.className="us-btn us-btn-primary",this.$confirm.textContent="Upload",this.$confirm.disabled=!0,this.$confirm.onclick=()=>this.startUpload(),a.appendChild(this.$cancel),a.appendChild(this.$confirm),t.appendChild(a),!((p=this.opts.branding)!=null&&p.hideFooter)){let u=m("div","us-footer");u.innerHTML=`Powered by <a href="${Ce}" target="_blank" rel="noopener">UnionStack</a>`,t.appendChild(u)}e.appendChild(t),((h=this.opts.container)!=null?h:document.body).appendChild(e),this.$backdrop=e}renderDropzone(){var r;let e=m("div","us-dropzone");e.setAttribute("role","button"),e.setAttribute("tabindex","0"),e.appendChild(m("div","us-dropzone-title","Drag files here")),e.appendChild(m("div","us-dropzone-hint","or click to browse"));let t=document.createElement("input");return t.type="file",t.multiple=((r=this.opts.maxFiles)!=null?r:10)>1,this.opts.accept&&(t.accept=this.opts.accept),t.style.display="none",t.onchange=()=>{t.files&&this.addFiles(Array.from(t.files)),t.value=""},this.$input=t,e.appendChild(t),e.onclick=()=>t.click(),e.onkeydown=o=>{(o.key==="Enter"||o.key===" ")&&(o.preventDefault(),t.click())},e.addEventListener("dragover",o=>{o.preventDefault(),e.setAttribute("data-drag","over")}),e.addEventListener("dragleave",()=>e.removeAttribute("data-drag")),e.addEventListener("drop",o=>{var a;o.preventDefault(),e.removeAttribute("data-drag");let n=(a=o.dataTransfer)==null?void 0:a.files;n&&this.addFiles(Array.from(n))}),e}unmount(){var e,t,r;(e=this.$backdrop)!=null&&e.parentNode&&this.$backdrop.parentNode.removeChild(this.$backdrop),this.$backdrop=null,(r=(t=this.opts).onClose)==null||r.call(t)}addFiles(e){var n;let r=((n=this.opts.maxFiles)!=null?n:1/0)-this.items.length;if(r<=0)return;let o=e.slice(0,r);for(let a of o){if(this.opts.maxFileSize&&a.size>this.opts.maxFileSize){let l={uploadId:re(),file:a,state:"failed",progress:0,error:`File exceeds ${ie(this.opts.maxFileSize)} limit`};this.items.push(l),this.renderItem(l);continue}let s={uploadId:re(),file:a,state:"queued",progress:0};this.items.push(s),this.renderItem(s)}this.refreshConfirm()}renderItem(e){if(!this.$list)return;let t=m("div","us-file");t.dataset.state=e.state,t.dataset.uploadId=e.uploadId;let r=m("div","","");r.style.flex="1",r.style.minWidth="0",r.appendChild(m("div","us-file-name",e.file.name));let o=m("div","us-file-meta",ie(e.file.size));r.appendChild(o);let n=m("div","us-file-progress"),a=m("div","us-file-progress-bar");n.appendChild(a),r.appendChild(n),t.appendChild(r);let s=m("div","us-file-meta");s.style.minWidth="60px",s.style.textAlign="right",s.textContent=e.state==="failed"?e.error||"failed":e.state==="done"?"done":"0%",t.appendChild(s),e.$row=t,e.$bar=a,e.$status=s,this.$list.appendChild(t)}setItemState(e,t,r){e.state=t,r!==void 0&&(e.progress=r),e.$row&&(e.$row.dataset.state=t),e.$bar&&(e.$bar.style.width=`${e.progress}%`),e.$status&&(t==="failed"?e.$status.textContent=e.error||"failed":t==="done"?e.$status.textContent="done":e.$status.textContent=`${Math.round(e.progress)}%`)}refreshConfirm(){if(!this.$confirm)return;let e=this.items.filter(t=>t.state==="queued").length;this.$confirm.disabled=e===0||this.uploadStarted}async startUpload(){if(this.uploadStarted)return;let e=this.items.filter(o=>o.state==="queued");if(e.length===0)return;this.uploadStarted=!0,this.$confirm&&(this.$confirm.disabled=!0,this.$confirm.textContent="Uploading\u2026"),this.$cancel&&(this.$cancel.textContent="Stop"),this.$closeBtn&&(this.$closeBtn.disabled=!0),this.$input&&(this.$input.disabled=!0);let t=new Map,r=e.map(o=>o.file);try{await this.client.uploadMany(r,D(T({},this.opts),{signal:this.abortCtrl.signal,onUploadStarted:o=>{var n,a;o.forEach((s,l)=>{let d=e[l];d&&(d.uploadId=s.uploadId,d.$row&&(d.$row.dataset.uploadId=s.uploadId),t.set(s.uploadId,d))}),(a=(n=this.opts).onUploadStarted)==null||a.call(n,o)},onFileUploadStarted:o=>{var a,s;let n=t.get(o.uploadId);n&&this.setItemState(n,"uploading",0),(s=(a=this.opts).onFileUploadStarted)==null||s.call(a,o)},onFileUploadProgress:(o,n)=>{var s,l;let a=t.get(o.uploadId);a&&this.setItemState(a,"uploading",n.totalPercent),(l=(s=this.opts).onFileUploadProgress)==null||l.call(s,o,n)},onFileUploadFinished:o=>{var a,s;let n=t.get(o.uploadId);n&&(n.uploaded=o,this.setItemState(n,"done",100)),(s=(a=this.opts).onFileUploadFinished)==null||s.call(a,o)},onFileUploadFailed:(o,n)=>{var s,l;let a=t.get(o.uploadId);a&&(a.error=n.message,this.setItemState(a,"failed")),(l=(s=this.opts).onFileUploadFailed)==null||l.call(s,o,n)},onUploadDone:o=>{var n,a;(a=(n=this.opts).onUploadDone)==null||a.call(n,o),this.resolveResult(o),this.unmount()},onError:o=>{var n,a;(a=(n=this.opts).onError)==null||a.call(n,o),this.resolveResult(),this.unmount()}}))}catch(o){this.resolved||(this.resolveResult(),this.unmount())}}resolveResult(e){if(this.resolved)return;this.resolved=!0;let t=e!=null?e:{filesUploaded:this.items.filter(r=>r.uploaded).map(r=>r.uploaded),filesFailed:this.items.filter(r=>r.state==="failed").map(r=>({file:{uploadId:r.uploadId,filename:r.file.name,mimetype:r.file.type||"application/octet-stream",size:r.file.size,source:"local"},error:{code:"VALIDATION",message:r.error||"failed",retryable:!1}}))};this.resolvePromise(t)}}});var ne={};W(ne,{Picker:()=>x,openPicker:()=>M});var _=j(()=>{"use strict";oe()});var Fe={};W(Fe,{Picker:()=>x,UnionStackClient:()=>C,init:()=>Ee,openPicker:()=>M});function c(i,e,t={}){var r;return{code:i,message:e,status:t.status,retryable:(r=t.retryable)!=null?r:fe(i,t.status),cause:t.cause}}function fe(i,e){return!!(i==="NETWORK"||i==="PART_FAILED"||i==="SERVER"&&e&&e>=500)}function Q(i,e){let t=e==null?void 0:e.error,r=(t==null?void 0:t.message)||`Request failed with status ${i}`,o=((t==null?void 0:t.code)||"").toUpperCase();if(i===401)return c("AUTH",r,{status:i,retryable:!1});if(i===403)return c("AUTH",r,{status:i,retryable:!1});if(i===413)return c("VALIDATION",r,{status:i,retryable:!1});if(i===415)return c("VALIDATION",r,{status:i,retryable:!1});if(i===429){let n=o==="QUOTA_EXCEEDED";return c(n?"QUOTA":"NETWORK",r,{status:i,retryable:!n})}return i>=500?c("SERVER",r,{status:i,retryable:!0}):c("SERVER",r,{status:i,retryable:!1})}var me=3,he=3,X=[400,1200,3600],L=class{constructor(e){this.cfg=e}describe(e,t={}){let r=typeof File!="undefined"&&e instanceof File,o=t.filename||(r?e.name:"untitled"),n=t.mimeType||e.type||"application/octet-stream";return{uploadId:ge(),filename:o,mimetype:n,size:e.size,source:"local"}}async upload(e,t={}){var o,n,a;let r=this.describe(e,{filename:t.filename,mimeType:t.mimeType});(o=t.onFileUploadStarted)==null||o.call(t,r);try{let s=await this.initUpload(r,t),l=await this.uploadAllParts(e,s,r,t),d=await this.completeUpload(s.sessionId,l,t),p=D(T({},r),{handle:d.handle,fileId:d.fileId,url:d.url,size:d.size,mimetype:d.mimetype,filename:d.filename,status:"Stored",etag:d.etag});return(n=t.onFileUploadFinished)==null||n.call(t,p),p}catch(s){let l=Y(s);throw(a=t.onFileUploadFailed)==null||a.call(t,r,l),s!=null&&s.sessionId&&this.abortSilently(s.sessionId).catch(()=>{}),l}}async abort(e){await this.api("POST","/sdk/v1/uploads/abort",{sessionId:e})}async fetchPickerConfig(){return this.api("GET","/sdk/v1/picker-config")}async initUpload(e,t){return this.api("POST","/sdk/v1/uploads/init",{filename:e.filename,mimeType:e.mimetype,size:e.size,metadata:t.metadata},t.signal)}async uploadAllParts(e,t,r,o){var F,w;let n=t.totalParts,a=t.chunkSize,s=Math.max(1,(F=o.concurrency)!=null?F:me),l=(w=o.maxRetriesPerPart)!=null?w:he,d=new Map(t.partUrls.map(g=>[g.partNumber,g.url])),p=new Array(n),h=new Array(n).fill(0),u=1,b=e.size,$=()=>{var y;let g=h.reduce((v,f)=>v+f,0),k=b>0?Math.min(100,Math.round(g/b*100)):100,P={totalBytes:b,loaded:g,totalPercent:k};(y=o.onFileUploadProgress)==null||y.call(o,r,P)},S=async()=>{var g,k,P,y,v;for(;;){if((g=o.signal)!=null&&g.aborted)throw c("ABORTED","Upload aborted by caller.",{retryable:!1});let f=u++;if(f>n)return;let I=(f-1)*a,H=Math.min(I+a,e.size),A=e.slice(I,H),z=0,O;for(;z<=l;){if((k=o.signal)!=null&&k.aborted)throw c("ABORTED","Upload aborted by caller.",{retryable:!1});try{let U=d.get(f);U||(U=(await this.api("POST","/sdk/v1/uploads/sign-part",{sessionId:t.sessionId,partNumber:f},o.signal)).url,d.set(f,U));let E=(v=await((y=(P=this.cfg).fetch)==null?void 0:y.call(P,U,{method:"PUT",body:A,signal:o.signal})))!=null?v:await fetch(U,{method:"PUT",body:A,signal:o.signal});if(!E.ok)throw(E.status===403||E.status===401)&&d.delete(f),c("PART_FAILED",`Part ${f} PUT failed (HTTP ${E.status})`,{status:E.status});let q=E.headers.get("etag");if(!q)throw c("PART_FAILED",`Part ${f}: R2 did not return an ETag.`);p[f-1]={partNumber:f,etag:q,size:A.size},h[f-1]=A.size,$();break}catch(U){if(O=U,z++,z>l)break;await be(X[Math.min(z-1,X.length-1)])}}if(!p[f-1])throw ye(Y(O!=null?O:c("PART_FAILED",`Part ${f} failed after ${l} retries.`)),t.sessionId)}},R=Array.from({length:Math.min(s,n)},S);return await Promise.all(R),p}async completeUpload(e,t,r){return this.api("POST","/sdk/v1/uploads/complete",{sessionId:e,parts:t.map(o=>({partNumber:o.partNumber,etag:o.etag}))},r.signal)}async abortSilently(e){try{await this.abort(e)}catch(t){}}async api(e,t,r,o){var d;let n=(d=this.cfg.fetch)!=null?d:fetch,a=`${this.cfg.apiBase.replace(/\/$/,"")}${t}`,s;try{s=await n(a,{method:e,headers:{Authorization:`Bearer ${this.cfg.apiKey}`,"Content-Type":"application/json"},body:r===void 0?void 0:JSON.stringify(r),signal:o})}catch(p){throw(p==null?void 0:p.name)==="AbortError"?c("ABORTED","Request aborted.",{retryable:!1,cause:p}):c("NETWORK","Network request failed.",{retryable:!0,cause:p})}let l=null;try{l=await s.json()}catch(p){}if(!s.ok)throw Q(s.status,l);return l}};function ge(){return typeof crypto!="undefined"&&"randomUUID"in crypto?crypto.randomUUID().replace(/-/g,""):Math.random().toString(36).slice(2)+Date.now().toString(36)}function be(i){return new Promise(e=>setTimeout(e,i))}function Y(i){if(i&&typeof i=="object"&&"code"in i&&"message"in i&&"retryable"in i)return i;let e=(i==null?void 0:i.message)||"Upload failed.";return c("NETWORK",e,{cause:i})}function ye(i,e){return i&&typeof i=="object"&&(i.sessionId=e),i}var C=class{constructor(e){this.cfg=e;if(!e.apiKey)throw c("CONFIG","apiKey is required.",{retryable:!1});if(!e.apiBase)throw c("CONFIG","apiBase is required.",{retryable:!1});this.uploader=new L(e),this.pickerConfigPromise=e.skipConfigPrefetch?Promise.resolve(null):this.uploader.fetchPickerConfig().catch(()=>null)}upload(e,t={}){return this.uploader.upload(e,t)}async uploadMany(e,t={}){var s,l,d;if(!Array.isArray(e)||e.length===0){let p=c("VALIDATION","uploadMany requires a non-empty array of files.",{retryable:!1});throw(s=t.onError)==null||s.call(t,p),p}let r=e.map(p=>this.uploader.describe(p,{filename:t.filename,mimeType:t.mimeType}));(l=t.onUploadStarted)==null||l.call(t,r);let o=[],n=[];await Promise.all(e.map(async(p,h)=>{try{let u=await this.uploader.upload(p,t);u.uploadId=r[h].uploadId,o.push(u)}catch(u){n.push({file:r[h],error:u})}}));let a={filesUploaded:o,filesFailed:n};return(d=t.onUploadDone)==null||d.call(t,a),a}picker(e={}){let t=null,r=!1,o,n,a=new Promise((s,l)=>{o=s,n=l});return{open:async()=>{if(r)return a;r=!0;try{t=(await Promise.resolve().then(()=>(_(),ne))).openPicker(this,e);let l=await t.open();return o(l),l}catch(s){let l=s!=null&&s.code?s:c("CONFIG","Failed to load picker.",{retryable:!1,cause:s});throw n(l),l}},close:()=>{t==null||t.close()},cancel:()=>{t==null||t.cancel()}}}get config(){return this.cfg}};var N={init(i){return new C(i)}};_();var Ee=N.init.bind(N);(function(){if(typeof document=="undefined")return;let e=document.currentScript;if(!e)return;let t=e.getAttribute("data-unionstack-key"),r=e.getAttribute("data-unionstack-api");if(!(!t||!r))try{let o=N.init({apiKey:t,apiBase:r});queueMicrotask(()=>{window.UnionStack&&(window.UnionStack.client=o)})}catch(o){console.error("[UnionStack] auto-init failed:",o)}})();return ue(Fe);})();
80
+ `});function Ue(i,e){var n,a,s,l,d,p,h,c,b,S,R,A,I,T,g,k,P,y,v,f;let t=x({},e),r=e.branding||{};t.branding={logoUrl:(a=(n=r.logoUrl)!=null?n:i.branding.logoUrl)!=null?a:void 0,title:(l=(s=r.title)!=null?s:i.branding.title)!=null?l:void 0,hideFooter:(d=r.hideFooter)!=null?d:i.branding.hideFooter};let o=e.theme||{};if(t.theme={primary:(h=(p=o.primary)!=null?p:i.theme.primary)!=null?h:void 0,background:(b=(c=o.background)!=null?c:i.theme.background)!=null?b:void 0,foreground:(R=(S=o.foreground)!=null?S:i.theme.foreground)!=null?R:void 0,border:(I=(A=o.border)!=null?A:i.theme.border)!=null?I:void 0,radius:(g=(T=o.radius)!=null?T:i.theme.radius)!=null?g:void 0,mode:(P=(k=o.mode)!=null?k:i.theme.mode)!=null?P:void 0},t.maxFileSize=(y=e.maxFileSize)!=null?y:i.constraints.maxFileSizeBytes,t.maxFiles=(v=e.maxFiles)!=null?v:i.constraints.maxFilesPerUpload,!e.accept&&((f=i.constraints.allowedMimeTypes)!=null&&f.length)){let $=i.constraints.allowedMimeTypes.filter(H=>H!=="*/*");$.length>0&&(t.accept=$.join(","))}return t}function m(i,e,t){let r=document.createElement(i);return e&&(r.className=e),t!==void 0&&(r.textContent=t),r}function ie(i){return i<1024?`${i} B`:i<1024*1024?`${(i/1024).toFixed(1)} KB`:i<1024*1024*1024?`${(i/1024/1024).toFixed(1)} MB`:`${(i/1024/1024/1024).toFixed(2)} GB`}function re(){return typeof crypto!="undefined"&&"randomUUID"in crypto?crypto.randomUUID().replace(/-/g,""):Math.random().toString(36).slice(2)+Date.now().toString(36)}function M(i,e){let t=new C(i,e);return{open:()=>t.open(),close:()=>t.close(),cancel:()=>t.cancel()}}var xe,Ce,C,oe=j(()=>{"use strict";te();xe="Upload files",Ce="https://unionstack.mastersunion.link",C=class{constructor(e,t){this.client=e;this.opts=t;this.$backdrop=null;this.$list=null;this.$confirm=null;this.$cancel=null;this.$closeBtn=null;this.$input=null;this.items=[];this.abortCtrl=new AbortController;this.uploadStarted=!1;this.resolved=!1;this.donePromise=new Promise(r=>{this.resolvePromise=r})}async open(){var e,t;if(typeof document=="undefined")throw new Error("[union-stack] Picker requires a browser environment.");try{let r=await this.client.pickerConfigPromise;r&&(this.opts=Ue(r,this.opts))}catch(r){}return Z(),this.mount(),(t=(e=this.opts).onOpen)==null||t.call(e),this.donePromise}close(){this.unmount(),this.resolved||this.resolveResult()}cancel(){var e,t;this.abortCtrl.abort(),(t=(e=this.opts).onCancel)==null||t.call(e),this.close()}mount(){var s,l,d,p,h;let e=document.createElement("div");e.className="us-picker-backdrop",Object.entries(ee(this.opts.theme)).forEach(([c,b])=>{e.style.setProperty(c,b)}),e.addEventListener("click",c=>{c.target===e&&!this.uploadStarted&&this.cancel()});let t=m("div","us-picker"),r=m("div","us-picker-header");if((s=this.opts.branding)!=null&&s.logoUrl){let c=document.createElement("img");c.src=this.opts.branding.logoUrl,c.alt="logo",r.appendChild(c)}let o=m("div","us-picker-title",(d=(l=this.opts.branding)==null?void 0:l.title)!=null?d:xe);r.appendChild(o),this.$closeBtn=document.createElement("button"),this.$closeBtn.type="button",this.$closeBtn.className="us-picker-close",this.$closeBtn.setAttribute("aria-label","Close"),this.$closeBtn.textContent="\xD7",this.$closeBtn.onclick=()=>this.cancel(),r.appendChild(this.$closeBtn),t.appendChild(r);let n=m("div","us-picker-body");n.appendChild(this.renderDropzone()),this.$list=m("div","us-file-list"),n.appendChild(this.$list),t.appendChild(n);let a=m("div","us-actions");if(this.$cancel=document.createElement("button"),this.$cancel.type="button",this.$cancel.className="us-btn",this.$cancel.textContent="Cancel",this.$cancel.onclick=()=>this.cancel(),this.$confirm=document.createElement("button"),this.$confirm.type="button",this.$confirm.className="us-btn us-btn-primary",this.$confirm.textContent="Upload",this.$confirm.disabled=!0,this.$confirm.onclick=()=>this.startUpload(),a.appendChild(this.$cancel),a.appendChild(this.$confirm),t.appendChild(a),!((p=this.opts.branding)!=null&&p.hideFooter)){let c=m("div","us-footer");c.innerHTML=`Powered by <a href="${Ce}" target="_blank" rel="noopener">UnionStack</a>`,t.appendChild(c)}e.appendChild(t),((h=this.opts.container)!=null?h:document.body).appendChild(e),this.$backdrop=e}renderDropzone(){var r;let e=m("div","us-dropzone");e.setAttribute("role","button"),e.setAttribute("tabindex","0"),e.appendChild(m("div","us-dropzone-title","Drag files here")),e.appendChild(m("div","us-dropzone-hint","or click to browse"));let t=document.createElement("input");return t.type="file",t.multiple=((r=this.opts.maxFiles)!=null?r:10)>1,this.opts.accept&&(t.accept=this.opts.accept),t.style.display="none",t.onchange=()=>{t.files&&this.addFiles(Array.from(t.files)),t.value=""},this.$input=t,e.appendChild(t),e.onclick=()=>t.click(),e.onkeydown=o=>{(o.key==="Enter"||o.key===" ")&&(o.preventDefault(),t.click())},e.addEventListener("dragover",o=>{o.preventDefault(),e.setAttribute("data-drag","over")}),e.addEventListener("dragleave",()=>e.removeAttribute("data-drag")),e.addEventListener("drop",o=>{var a;o.preventDefault(),e.removeAttribute("data-drag");let n=(a=o.dataTransfer)==null?void 0:a.files;n&&this.addFiles(Array.from(n))}),e}unmount(){var e,t,r;(e=this.$backdrop)!=null&&e.parentNode&&this.$backdrop.parentNode.removeChild(this.$backdrop),this.$backdrop=null,(r=(t=this.opts).onClose)==null||r.call(t)}addFiles(e){var n;let r=((n=this.opts.maxFiles)!=null?n:1/0)-this.items.length;if(r<=0)return;let o=e.slice(0,r);for(let a of o){if(this.opts.maxFileSize&&a.size>this.opts.maxFileSize){let l={uploadId:re(),file:a,state:"failed",progress:0,error:`File exceeds ${ie(this.opts.maxFileSize)} limit`};this.items.push(l),this.renderItem(l);continue}let s={uploadId:re(),file:a,state:"queued",progress:0};this.items.push(s),this.renderItem(s)}this.refreshConfirm()}renderItem(e){if(!this.$list)return;let t=m("div","us-file");t.dataset.state=e.state,t.dataset.uploadId=e.uploadId;let r=m("div","","");r.style.flex="1",r.style.minWidth="0",r.appendChild(m("div","us-file-name",e.file.name));let o=m("div","us-file-meta",ie(e.file.size));r.appendChild(o);let n=m("div","us-file-progress"),a=m("div","us-file-progress-bar");n.appendChild(a),r.appendChild(n),t.appendChild(r);let s=m("div","us-file-meta");s.style.minWidth="60px",s.style.textAlign="right",s.textContent=e.state==="failed"?e.error||"failed":e.state==="done"?"done":"0%",t.appendChild(s),e.$row=t,e.$bar=a,e.$status=s,this.$list.appendChild(t)}setItemState(e,t,r){e.state=t,r!==void 0&&(e.progress=r),e.$row&&(e.$row.dataset.state=t),e.$bar&&(e.$bar.style.width=`${e.progress}%`),e.$status&&(t==="failed"?e.$status.textContent=e.error||"failed":t==="done"?e.$status.textContent="done":e.$status.textContent=`${Math.round(e.progress)}%`)}refreshConfirm(){if(!this.$confirm)return;let e=this.items.filter(t=>t.state==="queued").length;this.$confirm.disabled=e===0||this.uploadStarted}async startUpload(){if(this.uploadStarted)return;let e=this.items.filter(o=>o.state==="queued");if(e.length===0)return;this.uploadStarted=!0,this.$confirm&&(this.$confirm.disabled=!0,this.$confirm.textContent="Uploading\u2026"),this.$cancel&&(this.$cancel.textContent="Stop"),this.$closeBtn&&(this.$closeBtn.disabled=!0),this.$input&&(this.$input.disabled=!0);let t=new Map,r=e.map(o=>o.file);try{await this.client.uploadMany(r,w(x({},this.opts),{signal:this.abortCtrl.signal,onUploadStarted:o=>{var n,a;o.forEach((s,l)=>{let d=e[l];d&&(d.uploadId=s.uploadId,d.$row&&(d.$row.dataset.uploadId=s.uploadId),t.set(s.uploadId,d))}),(a=(n=this.opts).onUploadStarted)==null||a.call(n,o)},onFileUploadStarted:o=>{var a,s;let n=t.get(o.uploadId);n&&this.setItemState(n,"uploading",0),(s=(a=this.opts).onFileUploadStarted)==null||s.call(a,o)},onFileUploadProgress:(o,n)=>{var s,l;let a=t.get(o.uploadId);a&&this.setItemState(a,"uploading",n.totalPercent),(l=(s=this.opts).onFileUploadProgress)==null||l.call(s,o,n)},onFileUploadFinished:o=>{var a,s;let n=t.get(o.uploadId);n&&(n.uploaded=o,this.setItemState(n,"done",100)),(s=(a=this.opts).onFileUploadFinished)==null||s.call(a,o)},onFileUploadFailed:(o,n)=>{var s,l;let a=t.get(o.uploadId);a&&(a.error=n.message,this.setItemState(a,"failed")),(l=(s=this.opts).onFileUploadFailed)==null||l.call(s,o,n)},onUploadDone:o=>{var n,a;(a=(n=this.opts).onUploadDone)==null||a.call(n,o),this.resolveResult(o),this.unmount()},onError:o=>{var n,a;(a=(n=this.opts).onError)==null||a.call(n,o),this.resolveResult(),this.unmount()}}))}catch(o){this.resolved||(this.resolveResult(),this.unmount())}}resolveResult(e){if(this.resolved)return;this.resolved=!0;let t=e!=null?e:{filesUploaded:this.items.filter(r=>r.uploaded).map(r=>r.uploaded),filesFailed:this.items.filter(r=>r.state==="failed").map(r=>({file:{uploadId:r.uploadId,filename:r.file.name,mimetype:r.file.type||"application/octet-stream",size:r.file.size,source:"local"},error:{code:"VALIDATION",message:r.error||"failed",retryable:!1}}))};this.resolvePromise(t)}}});var ne={};G(ne,{Picker:()=>C,openPicker:()=>M});var _=j(()=>{"use strict";oe()});var we={};G(we,{Picker:()=>C,UnionStackClient:()=>E,init:()=>Fe,openPicker:()=>M});function u(i,e,t={}){var r;return{code:i,message:e,status:t.status,retryable:(r=t.retryable)!=null?r:fe(i,t.status),cause:t.cause}}function fe(i,e){return!!(i==="NETWORK"||i==="PART_FAILED"||i==="SERVER"&&e&&e>=500)}function Q(i,e){let t=e==null?void 0:e.error,r=(t==null?void 0:t.message)||`Request failed with status ${i}`,o=((t==null?void 0:t.code)||"").toUpperCase();if(i===401)return u("AUTH",r,{status:i,retryable:!1});if(i===403)return u("AUTH",r,{status:i,retryable:!1});if(i===413)return u("VALIDATION",r,{status:i,retryable:!1});if(i===415)return u("VALIDATION",r,{status:i,retryable:!1});if(i===429){let n=o==="QUOTA_EXCEEDED";return u(n?"QUOTA":"NETWORK",r,{status:i,retryable:!n})}return i>=500?u("SERVER",r,{status:i,retryable:!0}):u("SERVER",r,{status:i,retryable:!1})}var me=3,he=3,X=[400,1200,3600],L=class{constructor(e){this.cfg=e}describe(e,t={}){let r=typeof File!="undefined"&&e instanceof File,o=t.filename||(r?e.name:"untitled"),n=t.mimeType||e.type||"application/octet-stream";return{uploadId:ge(),filename:o,mimetype:n,size:e.size,source:"local"}}async upload(e,t={}){var o,n,a;let r=this.describe(e,{filename:t.filename,mimeType:t.mimeType});(o=t.onFileUploadStarted)==null||o.call(t,r);try{let s=await this.initUpload(r,t),l=await this.uploadAllParts(e,s,r,t),d=await this.completeUpload(s.sessionId,l,t),p=w(x({},r),{handle:d.handle,fileId:d.fileId,url:d.url,size:d.size,mimetype:d.mimetype,filename:d.filename,status:"Stored",etag:d.etag});return(n=t.onFileUploadFinished)==null||n.call(t,p),p}catch(s){let l=Y(s);throw(a=t.onFileUploadFailed)==null||a.call(t,r,l),s!=null&&s.sessionId&&this.abortSilently(s.sessionId).catch(()=>{}),l}}async abort(e){await this.api("POST","/sdk/v1/uploads/abort",{sessionId:e})}async fetchPickerConfig(){return this.api("GET","/sdk/v1/picker-config")}async initUpload(e,t){return this.api("POST","/sdk/v1/uploads/init",{filename:e.filename,mimeType:e.mimetype,size:e.size,metadata:t.metadata},t.signal)}async uploadAllParts(e,t,r,o){var I,T;let n=t.totalParts,a=t.chunkSize,s=Math.max(1,(I=o.concurrency)!=null?I:me),l=(T=o.maxRetriesPerPart)!=null?T:he,d=new Map(t.partUrls.map(g=>[g.partNumber,g.url])),p=new Array(n),h=new Array(n).fill(0),c=1,b=e.size,S=()=>{var y;let g=h.reduce((v,f)=>v+f,0),k=b>0?Math.min(100,Math.round(g/b*100)):100,P={totalBytes:b,loaded:g,totalPercent:k};(y=o.onFileUploadProgress)==null||y.call(o,r,P)},R=async()=>{var g,k,P,y,v;for(;;){if((g=o.signal)!=null&&g.aborted)throw u("ABORTED","Upload aborted by caller.",{retryable:!1});let f=c++;if(f>n)return;let $=(f-1)*a,H=Math.min($+a,e.size),z=e.slice($,H),O=0,B;for(;O<=l;){if((k=o.signal)!=null&&k.aborted)throw u("ABORTED","Upload aborted by caller.",{retryable:!1});try{let U=d.get(f);U||(U=(await this.api("POST","/sdk/v1/uploads/sign-part",{sessionId:t.sessionId,partNumber:f},o.signal)).url,d.set(f,U));let F=(v=await((y=(P=this.cfg).fetch)==null?void 0:y.call(P,U,{method:"PUT",body:z,signal:o.signal})))!=null?v:await fetch(U,{method:"PUT",body:z,signal:o.signal});if(!F.ok)throw(F.status===403||F.status===401)&&d.delete(f),u("PART_FAILED",`Part ${f} PUT failed (HTTP ${F.status})`,{status:F.status});let q=F.headers.get("etag");if(!q)throw u("PART_FAILED",`Part ${f}: R2 did not return an ETag.`);p[f-1]={partNumber:f,etag:q,size:z.size},h[f-1]=z.size,S();break}catch(U){if(B=U,O++,O>l)break;await be(X[Math.min(O-1,X.length-1)])}}if(!p[f-1])throw ye(Y(B!=null?B:u("PART_FAILED",`Part ${f} failed after ${l} retries.`)),t.sessionId)}},A=Array.from({length:Math.min(s,n)},R);return await Promise.all(A),p}async completeUpload(e,t,r){return this.api("POST","/sdk/v1/uploads/complete",{sessionId:e,parts:t.map(o=>({partNumber:o.partNumber,etag:o.etag}))},r.signal)}async abortSilently(e){try{await this.abort(e)}catch(t){}}async api(e,t,r,o){var d;let n=(d=this.cfg.fetch)!=null?d:fetch,a=`${this.cfg.apiBase}${t}`,s;try{s=await n(a,{method:e,headers:{Authorization:`Bearer ${this.cfg.apiKey}`,"Content-Type":"application/json"},body:r===void 0?void 0:JSON.stringify(r),signal:o})}catch(p){throw(p==null?void 0:p.name)==="AbortError"?u("ABORTED","Request aborted.",{retryable:!1,cause:p}):u("NETWORK","Network request failed.",{retryable:!0,cause:p})}let l=null;try{l=await s.json()}catch(p){}if(!s.ok)throw Q(s.status,l);return l}};function ge(){return typeof crypto!="undefined"&&"randomUUID"in crypto?crypto.randomUUID().replace(/-/g,""):Math.random().toString(36).slice(2)+Date.now().toString(36)}function be(i){return new Promise(e=>setTimeout(e,i))}function Y(i){if(i&&typeof i=="object"&&"code"in i&&"message"in i&&"retryable"in i)return i;let e=(i==null?void 0:i.message)||"Upload failed.";return u("NETWORK",e,{cause:i})}function ye(i,e){return i&&typeof i=="object"&&(i.sessionId=e),i}var Ee="https://cdn-api.mastersunion.org/cdn-api",E=class{constructor(e){if(!e.apiKey)throw u("CONFIG","apiKey is required.",{retryable:!1});this.resolvedCfg=w(x({},e),{apiBase:Ee}),this.uploader=new L(this.resolvedCfg),this.pickerConfigPromise=this.resolvedCfg.skipConfigPrefetch?Promise.resolve(null):this.uploader.fetchPickerConfig().catch(()=>null)}upload(e,t={}){return this.uploader.upload(e,t)}async uploadMany(e,t={}){var s,l,d;if(!Array.isArray(e)||e.length===0){let p=u("VALIDATION","uploadMany requires a non-empty array of files.",{retryable:!1});throw(s=t.onError)==null||s.call(t,p),p}let r=e.map(p=>this.uploader.describe(p,{filename:t.filename,mimeType:t.mimeType}));(l=t.onUploadStarted)==null||l.call(t,r);let o=[],n=[];await Promise.all(e.map(async(p,h)=>{try{let c=await this.uploader.upload(p,t);c.uploadId=r[h].uploadId,o.push(c)}catch(c){n.push({file:r[h],error:c})}}));let a={filesUploaded:o,filesFailed:n};return(d=t.onUploadDone)==null||d.call(t,a),a}picker(e={}){let t=null,r=!1,o,n,a=new Promise((s,l)=>{o=s,n=l});return{open:async()=>{if(r)return a;r=!0;try{t=(await Promise.resolve().then(()=>(_(),ne))).openPicker(this,e);let l=await t.open();return o(l),l}catch(s){let l=s!=null&&s.code?s:u("CONFIG","Failed to load picker.",{retryable:!1,cause:s});throw n(l),l}},close:()=>{t==null||t.close()},cancel:()=>{t==null||t.cancel()}}}get config(){return this.resolvedCfg}};var N={init(i){return new E(i)}};_();var Fe=N.init.bind(N);(function(){if(typeof document=="undefined")return;let e=document.currentScript;if(!e)return;let t=e.getAttribute("data-unionstack-key");if(t)try{let r=N.init({apiKey:t});queueMicrotask(()=>{window.UnionStack&&(window.UnionStack.client=r)})}catch(r){console.error("[UnionStack] auto-init failed:",r)}})();return ue(we);})();
81
81
  //# sourceMappingURL=loader.v1.global.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/picker/styles.ts","../../src/picker/picker.ts","../../src/picker/index.ts","../../src/loader/index.ts","../../src/errors.ts","../../src/uploader.ts","../../src/client.ts","../../src/index.ts"],"sourcesContent":["import type { PickerTheme } from './types.js';\n\nconst STYLE_ID = 'unionstack-picker-styles';\n\n/** Inject a single <style> tag once. Idempotent — safe to call repeatedly. */\nexport function ensureStyles(): void {\n if (typeof document === 'undefined') return;\n if (document.getElementById(STYLE_ID)) return;\n const el = document.createElement('style');\n el.id = STYLE_ID;\n el.textContent = BASE_CSS;\n document.head.appendChild(el);\n}\n\n/** Resolve a partial theme into CSS variables on the modal root. */\nexport function themeToCssVars(theme: PickerTheme | undefined): Record<string, string> {\n const mode = theme?.mode || 'light';\n const defaults = mode === 'dark' ? DARK_DEFAULTS : LIGHT_DEFAULTS;\n return {\n '--us-primary': theme?.primary ?? defaults.primary,\n '--us-bg': theme?.background ?? defaults.background,\n '--us-fg': theme?.foreground ?? defaults.foreground,\n '--us-muted': theme?.muted ?? defaults.muted,\n '--us-border': theme?.border ?? defaults.border,\n '--us-radius': theme?.radius ?? '12px',\n };\n}\n\nconst LIGHT_DEFAULTS = {\n primary: '#4f46e5',\n background: '#ffffff',\n foreground: '#0f172a',\n muted: '#64748b',\n border: '#e2e8f0',\n};\nconst DARK_DEFAULTS = {\n primary: '#6366f1',\n background: '#0f172a',\n foreground: '#f1f5f9',\n muted: '#94a3b8',\n border: '#1e293b',\n};\n\n// All selectors namespaced under .us-picker to avoid bleed into host page.\nconst BASE_CSS = `\n.us-picker-backdrop {\n position: fixed; inset: 0; z-index: 2147483000;\n background: rgba(2, 6, 23, 0.55);\n display: flex; align-items: center; justify-content: center;\n padding: 16px; font-family: ui-sans-serif, system-ui, sans-serif;\n animation: us-fade 120ms ease-out;\n}\n@keyframes us-fade { from { opacity: 0; } to { opacity: 1; } }\n.us-picker {\n background: var(--us-bg); color: var(--us-fg);\n border-radius: var(--us-radius);\n width: 100%; max-width: 480px; max-height: calc(100vh - 32px);\n display: flex; flex-direction: column;\n box-shadow: 0 25px 50px -12px rgba(0,0,0,0.4);\n overflow: hidden;\n}\n.us-picker * { box-sizing: border-box; }\n.us-picker-header {\n display: flex; align-items: center; gap: 12px;\n padding: 16px 20px; border-bottom: 1px solid var(--us-border);\n}\n.us-picker-header img { height: 24px; }\n.us-picker-title { font-weight: 600; font-size: 16px; flex: 1; }\n.us-picker-close {\n background: none; border: 0; cursor: pointer;\n color: var(--us-muted); font-size: 22px; line-height: 1;\n padding: 4px 8px; border-radius: 6px;\n}\n.us-picker-close:hover { background: var(--us-border); color: var(--us-fg); }\n.us-picker-body { padding: 20px; overflow-y: auto; }\n.us-dropzone {\n border: 2px dashed var(--us-border); border-radius: var(--us-radius);\n padding: 32px 20px; text-align: center; cursor: pointer;\n transition: border-color 120ms, background 120ms;\n}\n.us-dropzone:hover, .us-dropzone[data-drag=\"over\"] {\n border-color: var(--us-primary);\n background: color-mix(in srgb, var(--us-primary) 5%, transparent);\n}\n.us-dropzone-title { font-weight: 500; margin-bottom: 4px; }\n.us-dropzone-hint { color: var(--us-muted); font-size: 13px; }\n.us-file-list { display: flex; flex-direction: column; gap: 8px; margin-top: 16px; }\n.us-file {\n display: flex; align-items: center; gap: 12px;\n padding: 10px 12px; border: 1px solid var(--us-border);\n border-radius: 10px; font-size: 14px;\n}\n.us-file-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.us-file-meta { color: var(--us-muted); font-size: 12px; }\n.us-file-progress {\n height: 4px; background: var(--us-border); border-radius: 999px; overflow: hidden;\n margin-top: 6px;\n}\n.us-file-progress-bar {\n height: 100%; background: var(--us-primary);\n width: 0%; transition: width 200ms;\n}\n.us-file[data-state=\"done\"] .us-file-progress-bar { background: #16a34a; width: 100%; }\n.us-file[data-state=\"failed\"] .us-file-progress-bar { background: #dc2626; }\n.us-actions {\n display: flex; gap: 8px; justify-content: flex-end;\n padding: 14px 20px; border-top: 1px solid var(--us-border);\n}\n.us-btn {\n padding: 8px 14px; border-radius: 8px; border: 1px solid var(--us-border);\n background: transparent; color: var(--us-fg); cursor: pointer; font-size: 14px;\n font-weight: 500;\n}\n.us-btn:hover { background: var(--us-border); }\n.us-btn-primary {\n background: var(--us-primary); color: white; border-color: var(--us-primary);\n}\n.us-btn-primary:hover { filter: brightness(0.95); }\n.us-btn[disabled] { opacity: 0.5; cursor: not-allowed; }\n.us-footer {\n padding: 8px 20px; font-size: 11px; color: var(--us-muted); text-align: center;\n}\n.us-footer a { color: var(--us-muted); }\n`;\n","import type { UnionStackClient } from '../client.js';\nimport type { PickerConfig, UploadError } from '../types.js';\nimport type {\n PickResponse,\n PickedFile,\n PickerHandle,\n PickerOptions,\n UploadedFile,\n} from './types.js';\nimport { ensureStyles, themeToCssVars } from './styles.js';\n\n// Merge server-managed picker config with runtime options. Runtime options\n// always win — they're the explicit dev escape hatch.\nfunction mergeConfig(server: PickerConfig, runtime: PickerOptions): PickerOptions {\n const merged: PickerOptions = { ...runtime };\n\n // Branding: shallow merge, runtime wins per-field.\n const runtimeBranding = runtime.branding || {};\n merged.branding = {\n logoUrl: runtimeBranding.logoUrl ?? server.branding.logoUrl ?? undefined,\n title: runtimeBranding.title ?? server.branding.title ?? undefined,\n hideFooter: runtimeBranding.hideFooter ?? server.branding.hideFooter,\n // PickerBranding has no footerText today — keep server's value internal.\n };\n\n // Theme: shallow merge.\n const runtimeTheme = runtime.theme || {};\n merged.theme = {\n primary: runtimeTheme.primary ?? server.theme.primary ?? undefined,\n background: runtimeTheme.background ?? server.theme.background ?? undefined,\n foreground: runtimeTheme.foreground ?? server.theme.foreground ?? undefined,\n border: runtimeTheme.border ?? server.theme.border ?? undefined,\n radius: runtimeTheme.radius ?? server.theme.radius ?? undefined,\n mode: runtimeTheme.mode ?? server.theme.mode ?? undefined,\n };\n\n // Constraints inform the dropzone (accept attr, size cap).\n merged.maxFileSize = runtime.maxFileSize ?? server.constraints.maxFileSizeBytes;\n merged.maxFiles = runtime.maxFiles ?? server.constraints.maxFilesPerUpload;\n if (!runtime.accept && server.constraints.allowedMimeTypes?.length) {\n const types = server.constraints.allowedMimeTypes.filter(t => t !== '*/*');\n if (types.length > 0) merged.accept = types.join(',');\n }\n return merged;\n}\n\ntype FileItemState = 'queued' | 'uploading' | 'done' | 'failed' | 'cancelled';\n\ninterface FileItem {\n uploadId: string; // matches PickedFile.uploadId once described\n file: File;\n state: FileItemState;\n progress: number; // 0-100\n error?: string;\n uploaded?: UploadedFile;\n // DOM refs we mutate on progress.\n $row?: HTMLElement;\n $bar?: HTMLElement;\n $status?: HTMLElement;\n}\n\nconst DEFAULT_TITLE = 'Upload files';\nconst FOOTER_LINK = 'https://unionstack.mastersunion.link';\n\n/**\n * Single-shot file picker modal. Built imperatively (no framework) so it can\n * be lazy-loaded by either the vanilla SDK or the React wrapper.\n */\nexport class Picker {\n private $backdrop: HTMLElement | null = null;\n private $list: HTMLElement | null = null;\n private $confirm: HTMLButtonElement | null = null;\n private $cancel: HTMLButtonElement | null = null;\n private $closeBtn: HTMLButtonElement | null = null;\n private $input: HTMLInputElement | null = null;\n\n private items: FileItem[] = [];\n private abortCtrl = new AbortController();\n private uploadStarted = false;\n private resolved = false;\n private resolvePromise!: (r: PickResponse) => void;\n private donePromise: Promise<PickResponse>;\n\n constructor(\n private client: UnionStackClient,\n private opts: PickerOptions,\n ) {\n this.donePromise = new Promise<PickResponse>(res => { this.resolvePromise = res; });\n }\n\n // ---- public api ---------------------------------------------------------\n\n async open(): Promise<PickResponse> {\n if (typeof document === 'undefined') {\n throw new Error('[union-stack] Picker requires a browser environment.');\n }\n // Pull server-side branding/theme defaults before painting the modal.\n // Runtime opts win over server config — see mergeConfig below.\n try {\n const serverConfig = await this.client.pickerConfigPromise;\n if (serverConfig) this.opts = mergeConfig(serverConfig, this.opts);\n } catch { /* fall through with whatever opts the caller passed */ }\n\n ensureStyles();\n this.mount();\n this.opts.onOpen?.();\n return this.donePromise;\n }\n\n close(): void {\n this.unmount();\n // Resolve with whatever was collected so callers awaiting open() never hang.\n if (!this.resolved) this.resolveResult();\n }\n\n cancel(): void {\n this.abortCtrl.abort();\n this.opts.onCancel?.();\n this.close();\n }\n\n // ---- mount / dom --------------------------------------------------------\n\n private mount() {\n const root = document.createElement('div');\n root.className = 'us-picker-backdrop';\n Object.entries(themeToCssVars(this.opts.theme)).forEach(([k, v]) => {\n root.style.setProperty(k, v);\n });\n root.addEventListener('click', e => {\n if (e.target === root && !this.uploadStarted) this.cancel();\n });\n\n const panel = el('div', 'us-picker');\n\n // Header\n const header = el('div', 'us-picker-header');\n if (this.opts.branding?.logoUrl) {\n const logo = document.createElement('img');\n logo.src = this.opts.branding.logoUrl;\n logo.alt = 'logo';\n header.appendChild(logo);\n }\n const title = el('div', 'us-picker-title', this.opts.branding?.title ?? DEFAULT_TITLE);\n header.appendChild(title);\n this.$closeBtn = document.createElement('button');\n this.$closeBtn.type = 'button';\n this.$closeBtn.className = 'us-picker-close';\n this.$closeBtn.setAttribute('aria-label', 'Close');\n this.$closeBtn.textContent = '×';\n this.$closeBtn.onclick = () => this.cancel();\n header.appendChild(this.$closeBtn);\n panel.appendChild(header);\n\n // Body\n const body = el('div', 'us-picker-body');\n body.appendChild(this.renderDropzone());\n this.$list = el('div', 'us-file-list');\n body.appendChild(this.$list);\n panel.appendChild(body);\n\n // Actions\n const actions = el('div', 'us-actions');\n this.$cancel = document.createElement('button');\n this.$cancel.type = 'button';\n this.$cancel.className = 'us-btn';\n this.$cancel.textContent = 'Cancel';\n this.$cancel.onclick = () => this.cancel();\n this.$confirm = document.createElement('button');\n this.$confirm.type = 'button';\n this.$confirm.className = 'us-btn us-btn-primary';\n this.$confirm.textContent = 'Upload';\n this.$confirm.disabled = true;\n this.$confirm.onclick = () => this.startUpload();\n actions.appendChild(this.$cancel);\n actions.appendChild(this.$confirm);\n panel.appendChild(actions);\n\n if (!this.opts.branding?.hideFooter) {\n const footer = el('div', 'us-footer');\n footer.innerHTML = `Powered by <a href=\"${FOOTER_LINK}\" target=\"_blank\" rel=\"noopener\">UnionStack</a>`;\n panel.appendChild(footer);\n }\n\n root.appendChild(panel);\n (this.opts.container ?? document.body).appendChild(root);\n this.$backdrop = root;\n }\n\n private renderDropzone(): HTMLElement {\n const dz = el('div', 'us-dropzone');\n dz.setAttribute('role', 'button');\n dz.setAttribute('tabindex', '0');\n dz.appendChild(el('div', 'us-dropzone-title', 'Drag files here'));\n dz.appendChild(el('div', 'us-dropzone-hint', 'or click to browse'));\n\n const input = document.createElement('input');\n input.type = 'file';\n input.multiple = (this.opts.maxFiles ?? 10) > 1;\n if (this.opts.accept) input.accept = this.opts.accept;\n input.style.display = 'none';\n input.onchange = () => {\n if (input.files) this.addFiles(Array.from(input.files));\n input.value = '';\n };\n this.$input = input;\n dz.appendChild(input);\n\n dz.onclick = () => input.click();\n dz.onkeydown = e => {\n if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); input.click(); }\n };\n\n dz.addEventListener('dragover', e => {\n e.preventDefault();\n dz.setAttribute('data-drag', 'over');\n });\n dz.addEventListener('dragleave', () => dz.removeAttribute('data-drag'));\n dz.addEventListener('drop', e => {\n e.preventDefault();\n dz.removeAttribute('data-drag');\n const dropped = e.dataTransfer?.files;\n if (dropped) this.addFiles(Array.from(dropped));\n });\n\n return dz;\n }\n\n private unmount() {\n if (this.$backdrop?.parentNode) this.$backdrop.parentNode.removeChild(this.$backdrop);\n this.$backdrop = null;\n this.opts.onClose?.();\n }\n\n // ---- file selection -----------------------------------------------------\n\n private addFiles(files: File[]) {\n const cap = this.opts.maxFiles ?? Infinity;\n const remaining = cap - this.items.length;\n if (remaining <= 0) return;\n const chosen = files.slice(0, remaining);\n\n for (const file of chosen) {\n if (this.opts.maxFileSize && file.size > this.opts.maxFileSize) {\n // Skip the file but surface a row in the list so the user sees why.\n const item: FileItem = {\n uploadId: cryptoId(),\n file, state: 'failed', progress: 0,\n error: `File exceeds ${formatBytes(this.opts.maxFileSize)} limit`,\n };\n this.items.push(item);\n this.renderItem(item);\n continue;\n }\n\n const item: FileItem = {\n uploadId: cryptoId(),\n file, state: 'queued', progress: 0,\n };\n this.items.push(item);\n this.renderItem(item);\n }\n\n this.refreshConfirm();\n }\n\n private renderItem(item: FileItem) {\n if (!this.$list) return;\n const row = el('div', 'us-file');\n row.dataset.state = item.state;\n row.dataset.uploadId = item.uploadId;\n\n const main = el('div', '', '');\n main.style.flex = '1';\n main.style.minWidth = '0';\n main.appendChild(el('div', 'us-file-name', item.file.name));\n\n const meta = el('div', 'us-file-meta', formatBytes(item.file.size));\n main.appendChild(meta);\n\n const progress = el('div', 'us-file-progress');\n const bar = el('div', 'us-file-progress-bar');\n progress.appendChild(bar);\n main.appendChild(progress);\n row.appendChild(main);\n\n const status = el('div', 'us-file-meta');\n status.style.minWidth = '60px';\n status.style.textAlign = 'right';\n status.textContent = item.state === 'failed'\n ? (item.error || 'failed')\n : item.state === 'done' ? 'done' : '0%';\n row.appendChild(status);\n\n item.$row = row;\n item.$bar = bar;\n item.$status = status;\n\n this.$list.appendChild(row);\n }\n\n private setItemState(item: FileItem, state: FileItemState, progress?: number) {\n item.state = state;\n if (progress !== undefined) item.progress = progress;\n if (item.$row) item.$row.dataset.state = state;\n if (item.$bar) item.$bar.style.width = `${item.progress}%`;\n if (item.$status) {\n if (state === 'failed') item.$status.textContent = item.error || 'failed';\n else if (state === 'done') item.$status.textContent = 'done';\n else item.$status.textContent = `${Math.round(item.progress)}%`;\n }\n }\n\n private refreshConfirm() {\n if (!this.$confirm) return;\n const queued = this.items.filter(i => i.state === 'queued').length;\n this.$confirm.disabled = queued === 0 || this.uploadStarted;\n }\n\n // ---- upload -------------------------------------------------------------\n\n private async startUpload() {\n if (this.uploadStarted) return;\n const queued = this.items.filter(i => i.state === 'queued');\n if (queued.length === 0) return;\n\n this.uploadStarted = true;\n if (this.$confirm) {\n this.$confirm.disabled = true;\n this.$confirm.textContent = 'Uploading…';\n }\n if (this.$cancel) this.$cancel.textContent = 'Stop';\n if (this.$closeBtn) this.$closeBtn.disabled = true;\n if (this.$input) this.$input.disabled = true;\n\n // Map PickedFile.uploadId → FileItem so callbacks update the right row.\n const itemByUploadId = new Map<string, FileItem>();\n const filesToUpload = queued.map(i => i.file);\n\n try {\n await this.client.uploadMany(filesToUpload, {\n ...this.opts,\n signal: this.abortCtrl.signal,\n onUploadStarted: (pickedFiles: PickedFile[]) => {\n // Pair each PickedFile to the queued FileItem in order.\n pickedFiles.forEach((p, idx) => {\n const item = queued[idx];\n if (item) {\n item.uploadId = p.uploadId;\n if (item.$row) item.$row.dataset.uploadId = p.uploadId;\n itemByUploadId.set(p.uploadId, item);\n }\n });\n this.opts.onUploadStarted?.(pickedFiles);\n },\n onFileUploadStarted: p => {\n const item = itemByUploadId.get(p.uploadId);\n if (item) this.setItemState(item, 'uploading', 0);\n this.opts.onFileUploadStarted?.(p);\n },\n onFileUploadProgress: (p, ev) => {\n const item = itemByUploadId.get(p.uploadId);\n if (item) this.setItemState(item, 'uploading', ev.totalPercent);\n this.opts.onFileUploadProgress?.(p, ev);\n },\n onFileUploadFinished: f => {\n const item = itemByUploadId.get(f.uploadId);\n if (item) {\n item.uploaded = f;\n this.setItemState(item, 'done', 100);\n }\n this.opts.onFileUploadFinished?.(f);\n },\n onFileUploadFailed: (p, err) => {\n const item = itemByUploadId.get(p.uploadId);\n if (item) {\n item.error = err.message;\n this.setItemState(item, 'failed');\n }\n this.opts.onFileUploadFailed?.(p, err);\n },\n onUploadDone: r => {\n this.opts.onUploadDone?.(r);\n this.resolveResult(r);\n this.unmount();\n },\n onError: (err: UploadError) => {\n this.opts.onError?.(err);\n this.resolveResult();\n this.unmount();\n },\n });\n } catch {\n // Errors already surfaced via onError / onFileUploadFailed.\n if (!this.resolved) {\n this.resolveResult();\n this.unmount();\n }\n }\n }\n\n private resolveResult(result?: PickResponse) {\n if (this.resolved) return;\n this.resolved = true;\n const fallback: PickResponse = result ?? {\n filesUploaded: this.items.filter(i => i.uploaded).map(i => i.uploaded!),\n filesFailed: this.items\n .filter(i => i.state === 'failed')\n .map(i => ({\n file: {\n uploadId: i.uploadId,\n filename: i.file.name,\n mimetype: i.file.type || 'application/octet-stream',\n size: i.file.size,\n source: 'local',\n },\n error: {\n code: 'VALIDATION',\n message: i.error || 'failed',\n retryable: false,\n },\n })),\n };\n this.resolvePromise(fallback);\n }\n}\n\n// ---- helpers --------------------------------------------------------------\n\nfunction el(tag: string, className: string, text?: string): HTMLElement {\n const node = document.createElement(tag);\n if (className) node.className = className;\n if (text !== undefined) node.textContent = text;\n return node;\n}\n\nfunction formatBytes(n: number): string {\n if (n < 1024) return `${n} B`;\n if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;\n if (n < 1024 * 1024 * 1024) return `${(n / 1024 / 1024).toFixed(1)} MB`;\n return `${(n / 1024 / 1024 / 1024).toFixed(2)} GB`;\n}\n\nfunction cryptoId(): string {\n if (typeof crypto !== 'undefined' && 'randomUUID' in crypto) {\n return (crypto as { randomUUID: () => string }).randomUUID().replace(/-/g, '');\n }\n return Math.random().toString(36).slice(2) + Date.now().toString(36);\n}\n\nexport function openPicker(client: UnionStackClient, opts: PickerOptions): PickerHandle {\n const picker = new Picker(client, opts);\n return {\n open: () => picker.open(),\n close: () => picker.close(),\n cancel: () => picker.cancel(),\n };\n}\n","export { Picker, openPicker } from './picker.js';\nexport type {\n PickerOptions,\n PickerHandle,\n PickerTheme,\n PickerBranding,\n} from './types.js';\n","// IIFE loader entry — bundled as a single drop-in <script>.\n//\n// <script src=\"https://unionstack.mastersunion.link/_sdk/v1/loader.js\"></script>\n// <script>\n// const client = UnionStack.init({ apiKey: 'unionstack_live_…', apiBase: '…' });\n// client.picker({ onUploadDone: r => console.log(r) }).open();\n// </script>\n//\n// Everything (core + picker UI) ships in this single file. The /react entry\n// is intentionally not included here — React users install from npm.\n\nimport { UnionStack, UnionStackClient } from '../index.js';\nimport { Picker, openPicker } from '../picker/index.js';\nimport type { ClientConfig } from '../types.js';\n\n// tsup's IIFE wrapper attaches every named export as a property on the\n// global `UnionStack`. To make `UnionStack.init({...})` work directly (rather\n// than `UnionStack.UnionStack.init(...)`), we flatten `init` to a top-level\n// export and keep the constructor classes available for advanced users.\nconst init = UnionStack.init.bind(UnionStack);\nexport { init, UnionStackClient, Picker, openPicker };\n\nexport type { ClientConfig };\n\n// Auto-init via data attributes — lets non-JS users wire the loader without\n// any inline script:\n//\n// <script src=\".../loader.js\"\n// data-unionstack-key=\"unionstack_live_…\"\n// data-unionstack-api=\"https://api.unionstack.com/cdn-api\">\n// </script>\n//\n// Stash the resulting client on `window.UnionStack.client`.\ndeclare global {\n interface Window {\n UnionStack?: {\n init: typeof UnionStack.init;\n client?: UnionStackClient;\n };\n }\n}\n\n(function autoInit() {\n if (typeof document === 'undefined') return;\n const script = document.currentScript as HTMLScriptElement | null;\n if (!script) return;\n const apiKey = script.getAttribute('data-unionstack-key');\n const apiBase = script.getAttribute('data-unionstack-api');\n if (!apiKey || !apiBase) return;\n try {\n const client = UnionStack.init({ apiKey, apiBase });\n // Defer assignment so it lands after the IIFE has installed `window.UnionStack`.\n queueMicrotask(() => {\n if (window.UnionStack) window.UnionStack.client = client;\n });\n } catch (err) {\n console.error('[UnionStack] auto-init failed:', err);\n }\n})();\n","import type { UploadError, UploadErrorCode } from './types.js';\n\nexport function makeError(\n code: UploadErrorCode,\n message: string,\n opts: { status?: number; retryable?: boolean; cause?: unknown } = {}\n): UploadError {\n return {\n code,\n message,\n status: opts.status,\n retryable: opts.retryable ?? defaultRetryable(code, opts.status),\n cause: opts.cause,\n };\n}\n\nfunction defaultRetryable(code: UploadErrorCode, status?: number): boolean {\n if (code === 'NETWORK' || code === 'PART_FAILED') return true;\n if (code === 'SERVER' && status && status >= 500) return true;\n return false;\n}\n\n/** Map an HTTP error response from the cdn-be API to an UploadError. */\nexport function fromApiResponse(status: number, body: unknown): UploadError {\n const err = (body as { error?: { code?: string; message?: string } } | null)?.error;\n const msg = err?.message || `Request failed with status ${status}`;\n const code = (err?.code || '').toUpperCase();\n\n if (status === 401) {\n return makeError('AUTH', msg, { status, retryable: false });\n }\n if (status === 403) {\n return makeError('AUTH', msg, { status, retryable: false });\n }\n if (status === 413) {\n return makeError('VALIDATION', msg, { status, retryable: false });\n }\n if (status === 415) {\n return makeError('VALIDATION', msg, { status, retryable: false });\n }\n if (status === 429) {\n const isQuota = code === 'QUOTA_EXCEEDED';\n return makeError(isQuota ? 'QUOTA' : 'NETWORK', msg, { status, retryable: !isQuota });\n }\n if (status >= 500) {\n return makeError('SERVER', msg, { status, retryable: true });\n }\n return makeError('SERVER', msg, { status, retryable: false });\n}\n","import type {\n ClientConfig,\n PickedFile,\n PickerConfig,\n UploadedFile,\n UploadOptions,\n ProgressEvent as USProgressEvent,\n} from './types.js';\nimport { fromApiResponse, makeError } from './errors.js';\n\ninterface InitResponse {\n sessionId: string;\n fileId: string;\n chunkSize: number;\n totalParts: number;\n partUrls: Array<{ partNumber: number; url: string }>;\n expiresAt: string;\n}\n\ninterface CompleteResponse {\n handle: string;\n fileId: string;\n url: string;\n filename: string;\n mimetype: string;\n size: number;\n etag?: string;\n}\n\ninterface PartResult {\n partNumber: number;\n etag: string;\n size: number;\n}\n\nconst DEFAULT_CONCURRENCY = 3;\nconst DEFAULT_MAX_RETRIES_PER_PART = 3;\n// Backoff schedule between part retries. Capped — past this we surrender.\nconst BACKOFF_MS = [400, 1200, 3600];\n\nexport class Uploader {\n constructor(private cfg: ClientConfig) {}\n\n /** Returns a stable PickedFile descriptor for the input blob/file. */\n describe(file: File | Blob, opts: { filename?: string; mimeType?: string } = {}): PickedFile {\n const isFile = typeof File !== 'undefined' && file instanceof File;\n const filename =\n opts.filename ||\n (isFile ? (file as File).name : 'untitled');\n const mimetype =\n opts.mimeType || (file as Blob).type || 'application/octet-stream';\n return {\n uploadId: cryptoRandomId(),\n filename,\n mimetype,\n size: file.size,\n source: 'local',\n };\n }\n\n /**\n * Upload a single Blob/File. Returns the persisted UploadedFile.\n * Fires Filestack-style per-file callbacks from `opts`.\n */\n async upload(file: File | Blob, opts: UploadOptions = {}): Promise<UploadedFile> {\n const picked = this.describe(file, { filename: opts.filename, mimeType: opts.mimeType });\n opts.onFileUploadStarted?.(picked);\n\n try {\n const init = await this.initUpload(picked, opts);\n const parts = await this.uploadAllParts(file, init, picked, opts);\n const completed = await this.completeUpload(init.sessionId, parts, opts);\n\n const uploaded: UploadedFile = {\n ...picked,\n handle: completed.handle,\n fileId: completed.fileId,\n url: completed.url,\n size: completed.size,\n mimetype: completed.mimetype,\n filename: completed.filename,\n status: 'Stored',\n etag: completed.etag,\n };\n opts.onFileUploadFinished?.(uploaded);\n return uploaded;\n } catch (rawErr) {\n const err = normalizeError(rawErr);\n opts.onFileUploadFailed?.(picked, err);\n // Best effort: tell the server to clean up the multipart, but ignore failures.\n if ((rawErr as { sessionId?: string })?.sessionId) {\n this.abortSilently((rawErr as { sessionId: string }).sessionId).catch(() => {});\n }\n throw err;\n }\n }\n\n /** Cancel an in-flight session server-side. */\n async abort(sessionId: string): Promise<void> {\n await this.api('POST', '/sdk/v1/uploads/abort', { sessionId });\n }\n\n /** Fetch the server-managed picker config (branding, theme, constraints). */\n async fetchPickerConfig(): Promise<PickerConfig> {\n return this.api<PickerConfig>('GET', '/sdk/v1/picker-config');\n }\n\n private async initUpload(picked: PickedFile, opts: UploadOptions): Promise<InitResponse> {\n return this.api<InitResponse>('POST', '/sdk/v1/uploads/init', {\n filename: picked.filename,\n mimeType: picked.mimetype,\n size: picked.size,\n metadata: opts.metadata,\n }, opts.signal);\n }\n\n private async uploadAllParts(\n file: File | Blob,\n init: InitResponse,\n picked: PickedFile,\n opts: UploadOptions,\n ): Promise<PartResult[]> {\n const totalParts = init.totalParts;\n const chunkSize = init.chunkSize;\n const concurrency = Math.max(1, opts.concurrency ?? DEFAULT_CONCURRENCY);\n const maxRetries = opts.maxRetriesPerPart ?? DEFAULT_MAX_RETRIES_PER_PART;\n\n // Quick lookup: partNumber → presigned URL.\n const urlByPart = new Map(init.partUrls.map(p => [p.partNumber, p.url] as const));\n\n const results: PartResult[] = new Array(totalParts);\n const loadedPerPart: number[] = new Array(totalParts).fill(0);\n let cursor = 1;\n\n const totalBytes = file.size;\n\n const reportProgress = () => {\n const loaded = loadedPerPart.reduce((a, b) => a + b, 0);\n const totalPercent = totalBytes > 0 ? Math.min(100, Math.round((loaded / totalBytes) * 100)) : 100;\n const ev: USProgressEvent = { totalBytes, loaded, totalPercent };\n opts.onFileUploadProgress?.(picked, ev);\n };\n\n const worker = async (): Promise<void> => {\n while (true) {\n if (opts.signal?.aborted) {\n throw makeError('ABORTED', 'Upload aborted by caller.', { retryable: false });\n }\n const partNumber = cursor++;\n if (partNumber > totalParts) return;\n\n const start = (partNumber - 1) * chunkSize;\n const end = Math.min(start + chunkSize, file.size);\n const chunk = file.slice(start, end);\n\n let attempt = 0;\n let lastErr: unknown;\n while (attempt <= maxRetries) {\n if (opts.signal?.aborted) {\n throw makeError('ABORTED', 'Upload aborted by caller.', { retryable: false });\n }\n try {\n let url = urlByPart.get(partNumber);\n if (!url) {\n const refreshed = await this.api<{ url: string }>(\n 'POST', '/sdk/v1/uploads/sign-part',\n { sessionId: init.sessionId, partNumber }, opts.signal,\n );\n url = refreshed.url;\n urlByPart.set(partNumber, url);\n }\n\n const res = await this.cfg.fetch?.(url, {\n method: 'PUT',\n body: chunk,\n signal: opts.signal,\n }) ?? await fetch(url, { method: 'PUT', body: chunk, signal: opts.signal });\n\n if (!res.ok) {\n // If R2 rejects with 403 the URL likely expired — drop it so the\n // next attempt re-signs.\n if (res.status === 403 || res.status === 401) urlByPart.delete(partNumber);\n throw makeError('PART_FAILED', `Part ${partNumber} PUT failed (HTTP ${res.status})`, { status: res.status });\n }\n const etag = res.headers.get('etag');\n if (!etag) {\n throw makeError('PART_FAILED', `Part ${partNumber}: R2 did not return an ETag.`);\n }\n\n results[partNumber - 1] = { partNumber, etag, size: chunk.size };\n loadedPerPart[partNumber - 1] = chunk.size;\n reportProgress();\n break;\n } catch (err) {\n lastErr = err;\n attempt++;\n if (attempt > maxRetries) break;\n await sleep(BACKOFF_MS[Math.min(attempt - 1, BACKOFF_MS.length - 1)]);\n }\n }\n if (!results[partNumber - 1]) {\n throw withSessionId(\n normalizeError(lastErr ?? makeError('PART_FAILED', `Part ${partNumber} failed after ${maxRetries} retries.`)),\n init.sessionId,\n );\n }\n }\n };\n\n const workers = Array.from({ length: Math.min(concurrency, totalParts) }, worker);\n await Promise.all(workers);\n return results;\n }\n\n private async completeUpload(\n sessionId: string,\n parts: PartResult[],\n opts: UploadOptions,\n ): Promise<CompleteResponse> {\n return this.api<CompleteResponse>('POST', '/sdk/v1/uploads/complete', {\n sessionId,\n parts: parts.map(p => ({ partNumber: p.partNumber, etag: p.etag })),\n }, opts.signal);\n }\n\n private async abortSilently(sessionId: string): Promise<void> {\n try { await this.abort(sessionId); } catch { /* ignore */ }\n }\n\n private async api<T>(\n method: 'GET' | 'POST' | 'DELETE',\n path: string,\n body?: unknown,\n signal?: AbortSignal,\n ): Promise<T> {\n const fetchImpl = this.cfg.fetch ?? fetch;\n const url = `${this.cfg.apiBase.replace(/\\/$/, '')}${path}`;\n let res: Response;\n try {\n res = await fetchImpl(url, {\n method,\n headers: {\n Authorization: `Bearer ${this.cfg.apiKey}`,\n 'Content-Type': 'application/json',\n },\n body: body === undefined ? undefined : JSON.stringify(body),\n signal,\n });\n } catch (cause) {\n if ((cause as Error)?.name === 'AbortError') {\n throw makeError('ABORTED', 'Request aborted.', { retryable: false, cause });\n }\n throw makeError('NETWORK', 'Network request failed.', { retryable: true, cause });\n }\n let parsed: unknown = null;\n try { parsed = await res.json(); } catch { /* tolerate empty body */ }\n if (!res.ok) throw fromApiResponse(res.status, parsed);\n return parsed as T;\n }\n}\n\nfunction cryptoRandomId(): string {\n // Cheap unique id for client-side uploadId. Not security-sensitive.\n if (typeof crypto !== 'undefined' && 'randomUUID' in crypto) {\n return (crypto as { randomUUID: () => string }).randomUUID().replace(/-/g, '');\n }\n return Math.random().toString(36).slice(2) + Date.now().toString(36);\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise(r => setTimeout(r, ms));\n}\n\nfunction normalizeError(err: unknown): ReturnType<typeof makeError> {\n if (err && typeof err === 'object' && 'code' in err && 'message' in err && 'retryable' in err) {\n return err as ReturnType<typeof makeError>;\n }\n const msg = (err as Error)?.message || 'Upload failed.';\n return makeError('NETWORK', msg, { cause: err });\n}\n\nfunction withSessionId<T>(err: T, sessionId: string): T {\n if (err && typeof err === 'object') (err as { sessionId?: string }).sessionId = sessionId;\n return err;\n}\n","import type {\n ClientConfig,\n UploadOptions,\n BatchUploadOptions,\n UploadedFile,\n PickResponse,\n PickedFile,\n PickerConfig,\n UploadError,\n} from './types.js';\nimport { Uploader } from './uploader.js';\nimport { makeError } from './errors.js';\n\n// Forward-declared minimal handle so client.ts doesn't pull in the picker bundle.\nexport interface PickerHandleLike {\n open(): Promise<PickResponse>;\n close(): void;\n cancel(): void;\n}\n\nexport class UnionStackClient {\n private uploader: Uploader;\n /**\n * Promise that resolves to the server-managed picker config. Pre-fetched on\n * construction (unless `skipConfigPrefetch: true`) so the picker opens\n * without a network hit. Fails silently — picker falls back to defaults.\n */\n pickerConfigPromise: Promise<PickerConfig | null>;\n\n constructor(private cfg: ClientConfig) {\n if (!cfg.apiKey) throw makeError('CONFIG', 'apiKey is required.', { retryable: false });\n if (!cfg.apiBase) throw makeError('CONFIG', 'apiBase is required.', { retryable: false });\n this.uploader = new Uploader(cfg);\n this.pickerConfigPromise = cfg.skipConfigPrefetch\n ? Promise.resolve(null)\n : this.uploader.fetchPickerConfig().catch(() => null);\n }\n\n /** Upload a single file. Mirrors Filestack's `client.upload()`. */\n upload(file: File | Blob, opts: UploadOptions = {}): Promise<UploadedFile> {\n return this.uploader.upload(file, opts);\n }\n\n /**\n * Upload multiple files concurrently. Mirrors Filestack's batch behavior:\n * onUploadDone fires once even if some files failed — failures land in\n * `filesFailed`, successes in `filesUploaded`. `onError` is reserved for\n * batch-level failures (no files even started).\n */\n async uploadMany(\n files: (File | Blob)[],\n opts: BatchUploadOptions = {},\n ): Promise<PickResponse> {\n if (!Array.isArray(files) || files.length === 0) {\n const err = makeError('VALIDATION', 'uploadMany requires a non-empty array of files.', { retryable: false });\n opts.onError?.(err);\n throw err;\n }\n\n const picked: PickedFile[] = files.map(f =>\n this.uploader.describe(f, { filename: opts.filename, mimeType: opts.mimeType })\n );\n opts.onUploadStarted?.(picked);\n\n const filesUploaded: UploadedFile[] = [];\n const filesFailed: Array<{ file: PickedFile; error: UploadError }> = [];\n\n // Process per-file in parallel; the per-part concurrency from `opts` still\n // applies inside each upload.\n await Promise.all(files.map(async (f, i) => {\n try {\n const uploaded = await this.uploader.upload(f, opts);\n // Sync the uploadId so callers can correlate picked → uploaded.\n uploaded.uploadId = picked[i].uploadId;\n filesUploaded.push(uploaded);\n } catch (err) {\n filesFailed.push({ file: picked[i], error: err as UploadError });\n }\n }));\n\n const result: PickResponse = { filesUploaded, filesFailed };\n opts.onUploadDone?.(result);\n return result;\n }\n\n /**\n * Open the file picker modal. Lazy-loads the picker bundle so the core\n * SDK stays small for callers that only use `upload()` directly.\n */\n picker(opts: import('./picker/types.js').PickerOptions = {}): PickerHandleLike {\n let real: PickerHandleLike | null = null;\n let opened = false;\n let pendingResolve!: (r: PickResponse) => void;\n let pendingReject!: (e: UploadError) => void;\n const donePromise = new Promise<PickResponse>((res, rej) => {\n pendingResolve = res; pendingReject = rej;\n });\n\n return {\n open: async () => {\n if (opened) return donePromise;\n opened = true;\n try {\n const mod = await import('./picker/index.js');\n real = mod.openPicker(this, opts);\n const result = await real.open();\n pendingResolve(result);\n return result;\n } catch (err) {\n const e = (err as UploadError)?.code\n ? (err as UploadError)\n : makeError('CONFIG', 'Failed to load picker.', { retryable: false, cause: err });\n pendingReject(e);\n throw e;\n }\n },\n close: () => { real?.close(); },\n cancel: () => { real?.cancel(); },\n };\n }\n\n /** Read-only accessor used by the React/picker packages. */\n get config(): Readonly<ClientConfig> { return this.cfg; }\n}\n","import { UnionStackClient } from './client.js';\nimport type { ClientConfig } from './types.js';\n\n/**\n * UnionStack — file upload SDK.\n *\n * import { UnionStack } from '@masters-union/union-stack';\n * const client = UnionStack.init({\n * apiKey: 'unionstack_live_…',\n * apiBase: 'https://api.unionstack.com/cdn-api',\n * });\n * const uploaded = await client.upload(file, { onFileUploadProgress: … });\n */\nexport const UnionStack = {\n init(cfg: ClientConfig): UnionStackClient {\n return new UnionStackClient(cfg);\n },\n};\n\nexport { UnionStackClient } from './client.js';\nexport type {\n ClientConfig,\n UploadOptions,\n BatchUploadOptions,\n PickedFile,\n UploadedFile,\n ProgressEvent,\n PickResponse,\n UploadError,\n UploadErrorCode,\n Source,\n} from './types.js';\n"],"mappings":"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","names":["ensureStyles","STYLE_ID","el","BASE_CSS","themeToCssVars","theme","_a","_b","_c","_d","_e","_f","defaults","DARK_DEFAULTS","LIGHT_DEFAULTS","init_styles","__esmMin","mergeConfig","server","runtime","_a","_b","_c","_d","_e","_f","_g","_h","_i","_j","_k","_l","_m","_n","_o","_p","_q","_r","_s","_t","merged","__spreadValues","runtimeBranding","runtimeTheme","types","t","el","tag","className","text","node","formatBytes","n","cryptoId","openPicker","client","opts","picker","Picker","DEFAULT_TITLE","FOOTER_LINK","init_picker","__esmMin","init_styles","res","serverConfig","e","ensureStyles","root","themeToCssVars","k","v","panel","header","logo","title","body","actions","footer","dz","input","dropped","files","remaining","chosen","file","item","row","main","meta","progress","bar","status","state","queued","i","itemByUploadId","filesToUpload","__spreadProps","pickedFiles","p","idx","ev","f","err","r","result","fallback","picker_exports","__export","Picker","openPicker","init_picker","__esmMin","loader_exports","__export","Picker","UnionStackClient","init","openPicker","makeError","code","message","opts","_a","defaultRetryable","status","fromApiResponse","body","err","msg","isQuota","DEFAULT_CONCURRENCY","DEFAULT_MAX_RETRIES_PER_PART","BACKOFF_MS","Uploader","cfg","file","opts","isFile","filename","mimetype","cryptoRandomId","_a","_b","_c","picked","init","parts","completed","uploaded","__spreadProps","__spreadValues","rawErr","err","normalizeError","sessionId","totalParts","chunkSize","concurrency","maxRetries","urlByPart","p","results","loadedPerPart","cursor","totalBytes","reportProgress","loaded","a","b","totalPercent","ev","worker","_d","_e","makeError","partNumber","start","end","chunk","attempt","lastErr","url","res","etag","sleep","withSessionId","workers","e","method","path","body","signal","fetchImpl","cause","parsed","fromApiResponse","ms","r","msg","UnionStackClient","cfg","makeError","Uploader","file","opts","files","_a","_b","_c","err","picked","f","filesUploaded","filesFailed","i","uploaded","result","real","opened","pendingResolve","pendingReject","donePromise","res","rej","e","UnionStack","cfg","UnionStackClient","init_picker","init","UnionStack","script","apiKey","apiBase","client","UnionStack","err"]}
1
+ {"version":3,"sources":["../../src/picker/styles.ts","../../src/picker/picker.ts","../../src/picker/index.ts","../../src/loader/index.ts","../../src/errors.ts","../../src/uploader.ts","../../src/client.ts","../../src/index.ts"],"sourcesContent":["import type { PickerTheme } from './types.js';\n\nconst STYLE_ID = 'unionstack-picker-styles';\n\n/** Inject a single <style> tag once. Idempotent — safe to call repeatedly. */\nexport function ensureStyles(): void {\n if (typeof document === 'undefined') return;\n if (document.getElementById(STYLE_ID)) return;\n const el = document.createElement('style');\n el.id = STYLE_ID;\n el.textContent = BASE_CSS;\n document.head.appendChild(el);\n}\n\n/** Resolve a partial theme into CSS variables on the modal root. */\nexport function themeToCssVars(theme: PickerTheme | undefined): Record<string, string> {\n const mode = theme?.mode || 'light';\n const defaults = mode === 'dark' ? DARK_DEFAULTS : LIGHT_DEFAULTS;\n return {\n '--us-primary': theme?.primary ?? defaults.primary,\n '--us-bg': theme?.background ?? defaults.background,\n '--us-fg': theme?.foreground ?? defaults.foreground,\n '--us-muted': theme?.muted ?? defaults.muted,\n '--us-border': theme?.border ?? defaults.border,\n '--us-radius': theme?.radius ?? '12px',\n };\n}\n\nconst LIGHT_DEFAULTS = {\n primary: '#4f46e5',\n background: '#ffffff',\n foreground: '#0f172a',\n muted: '#64748b',\n border: '#e2e8f0',\n};\nconst DARK_DEFAULTS = {\n primary: '#6366f1',\n background: '#0f172a',\n foreground: '#f1f5f9',\n muted: '#94a3b8',\n border: '#1e293b',\n};\n\n// All selectors namespaced under .us-picker to avoid bleed into host page.\nconst BASE_CSS = `\n.us-picker-backdrop {\n position: fixed; inset: 0; z-index: 2147483000;\n background: rgba(2, 6, 23, 0.55);\n display: flex; align-items: center; justify-content: center;\n padding: 16px; font-family: ui-sans-serif, system-ui, sans-serif;\n animation: us-fade 120ms ease-out;\n}\n@keyframes us-fade { from { opacity: 0; } to { opacity: 1; } }\n.us-picker {\n background: var(--us-bg); color: var(--us-fg);\n border-radius: var(--us-radius);\n width: 100%; max-width: 480px; max-height: calc(100vh - 32px);\n display: flex; flex-direction: column;\n box-shadow: 0 25px 50px -12px rgba(0,0,0,0.4);\n overflow: hidden;\n}\n.us-picker * { box-sizing: border-box; }\n.us-picker-header {\n display: flex; align-items: center; gap: 12px;\n padding: 16px 20px; border-bottom: 1px solid var(--us-border);\n}\n.us-picker-header img { height: 24px; }\n.us-picker-title { font-weight: 600; font-size: 16px; flex: 1; }\n.us-picker-close {\n background: none; border: 0; cursor: pointer;\n color: var(--us-muted); font-size: 22px; line-height: 1;\n padding: 4px 8px; border-radius: 6px;\n}\n.us-picker-close:hover { background: var(--us-border); color: var(--us-fg); }\n.us-picker-body { padding: 20px; overflow-y: auto; }\n.us-dropzone {\n border: 2px dashed var(--us-border); border-radius: var(--us-radius);\n padding: 32px 20px; text-align: center; cursor: pointer;\n transition: border-color 120ms, background 120ms;\n}\n.us-dropzone:hover, .us-dropzone[data-drag=\"over\"] {\n border-color: var(--us-primary);\n background: color-mix(in srgb, var(--us-primary) 5%, transparent);\n}\n.us-dropzone-title { font-weight: 500; margin-bottom: 4px; }\n.us-dropzone-hint { color: var(--us-muted); font-size: 13px; }\n.us-file-list { display: flex; flex-direction: column; gap: 8px; margin-top: 16px; }\n.us-file {\n display: flex; align-items: center; gap: 12px;\n padding: 10px 12px; border: 1px solid var(--us-border);\n border-radius: 10px; font-size: 14px;\n}\n.us-file-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.us-file-meta { color: var(--us-muted); font-size: 12px; }\n.us-file-progress {\n height: 4px; background: var(--us-border); border-radius: 999px; overflow: hidden;\n margin-top: 6px;\n}\n.us-file-progress-bar {\n height: 100%; background: var(--us-primary);\n width: 0%; transition: width 200ms;\n}\n.us-file[data-state=\"done\"] .us-file-progress-bar { background: #16a34a; width: 100%; }\n.us-file[data-state=\"failed\"] .us-file-progress-bar { background: #dc2626; }\n.us-actions {\n display: flex; gap: 8px; justify-content: flex-end;\n padding: 14px 20px; border-top: 1px solid var(--us-border);\n}\n.us-btn {\n padding: 8px 14px; border-radius: 8px; border: 1px solid var(--us-border);\n background: transparent; color: var(--us-fg); cursor: pointer; font-size: 14px;\n font-weight: 500;\n}\n.us-btn:hover { background: var(--us-border); }\n.us-btn-primary {\n background: var(--us-primary); color: white; border-color: var(--us-primary);\n}\n.us-btn-primary:hover { filter: brightness(0.95); }\n.us-btn[disabled] { opacity: 0.5; cursor: not-allowed; }\n.us-footer {\n padding: 8px 20px; font-size: 11px; color: var(--us-muted); text-align: center;\n}\n.us-footer a { color: var(--us-muted); }\n`;\n","import type { UnionStackClient } from '../client.js';\nimport type { PickerConfig, UploadError } from '../types.js';\nimport type {\n PickResponse,\n PickedFile,\n PickerHandle,\n PickerOptions,\n UploadedFile,\n} from './types.js';\nimport { ensureStyles, themeToCssVars } from './styles.js';\n\n// Merge server-managed picker config with runtime options. Runtime options\n// always win — they're the explicit dev escape hatch.\nfunction mergeConfig(server: PickerConfig, runtime: PickerOptions): PickerOptions {\n const merged: PickerOptions = { ...runtime };\n\n // Branding: shallow merge, runtime wins per-field.\n const runtimeBranding = runtime.branding || {};\n merged.branding = {\n logoUrl: runtimeBranding.logoUrl ?? server.branding.logoUrl ?? undefined,\n title: runtimeBranding.title ?? server.branding.title ?? undefined,\n hideFooter: runtimeBranding.hideFooter ?? server.branding.hideFooter,\n // PickerBranding has no footerText today — keep server's value internal.\n };\n\n // Theme: shallow merge.\n const runtimeTheme = runtime.theme || {};\n merged.theme = {\n primary: runtimeTheme.primary ?? server.theme.primary ?? undefined,\n background: runtimeTheme.background ?? server.theme.background ?? undefined,\n foreground: runtimeTheme.foreground ?? server.theme.foreground ?? undefined,\n border: runtimeTheme.border ?? server.theme.border ?? undefined,\n radius: runtimeTheme.radius ?? server.theme.radius ?? undefined,\n mode: runtimeTheme.mode ?? server.theme.mode ?? undefined,\n };\n\n // Constraints inform the dropzone (accept attr, size cap).\n merged.maxFileSize = runtime.maxFileSize ?? server.constraints.maxFileSizeBytes;\n merged.maxFiles = runtime.maxFiles ?? server.constraints.maxFilesPerUpload;\n if (!runtime.accept && server.constraints.allowedMimeTypes?.length) {\n const types = server.constraints.allowedMimeTypes.filter(t => t !== '*/*');\n if (types.length > 0) merged.accept = types.join(',');\n }\n return merged;\n}\n\ntype FileItemState = 'queued' | 'uploading' | 'done' | 'failed' | 'cancelled';\n\ninterface FileItem {\n uploadId: string; // matches PickedFile.uploadId once described\n file: File;\n state: FileItemState;\n progress: number; // 0-100\n error?: string;\n uploaded?: UploadedFile;\n // DOM refs we mutate on progress.\n $row?: HTMLElement;\n $bar?: HTMLElement;\n $status?: HTMLElement;\n}\n\nconst DEFAULT_TITLE = 'Upload files';\nconst FOOTER_LINK = 'https://unionstack.mastersunion.link';\n\n/**\n * Single-shot file picker modal. Built imperatively (no framework) so it can\n * be lazy-loaded by either the vanilla SDK or the React wrapper.\n */\nexport class Picker {\n private $backdrop: HTMLElement | null = null;\n private $list: HTMLElement | null = null;\n private $confirm: HTMLButtonElement | null = null;\n private $cancel: HTMLButtonElement | null = null;\n private $closeBtn: HTMLButtonElement | null = null;\n private $input: HTMLInputElement | null = null;\n\n private items: FileItem[] = [];\n private abortCtrl = new AbortController();\n private uploadStarted = false;\n private resolved = false;\n private resolvePromise!: (r: PickResponse) => void;\n private donePromise: Promise<PickResponse>;\n\n constructor(\n private client: UnionStackClient,\n private opts: PickerOptions,\n ) {\n this.donePromise = new Promise<PickResponse>(res => { this.resolvePromise = res; });\n }\n\n // ---- public api ---------------------------------------------------------\n\n async open(): Promise<PickResponse> {\n if (typeof document === 'undefined') {\n throw new Error('[union-stack] Picker requires a browser environment.');\n }\n // Pull server-side branding/theme defaults before painting the modal.\n // Runtime opts win over server config — see mergeConfig below.\n try {\n const serverConfig = await this.client.pickerConfigPromise;\n if (serverConfig) this.opts = mergeConfig(serverConfig, this.opts);\n } catch { /* fall through with whatever opts the caller passed */ }\n\n ensureStyles();\n this.mount();\n this.opts.onOpen?.();\n return this.donePromise;\n }\n\n close(): void {\n this.unmount();\n // Resolve with whatever was collected so callers awaiting open() never hang.\n if (!this.resolved) this.resolveResult();\n }\n\n cancel(): void {\n this.abortCtrl.abort();\n this.opts.onCancel?.();\n this.close();\n }\n\n // ---- mount / dom --------------------------------------------------------\n\n private mount() {\n const root = document.createElement('div');\n root.className = 'us-picker-backdrop';\n Object.entries(themeToCssVars(this.opts.theme)).forEach(([k, v]) => {\n root.style.setProperty(k, v);\n });\n root.addEventListener('click', e => {\n if (e.target === root && !this.uploadStarted) this.cancel();\n });\n\n const panel = el('div', 'us-picker');\n\n // Header\n const header = el('div', 'us-picker-header');\n if (this.opts.branding?.logoUrl) {\n const logo = document.createElement('img');\n logo.src = this.opts.branding.logoUrl;\n logo.alt = 'logo';\n header.appendChild(logo);\n }\n const title = el('div', 'us-picker-title', this.opts.branding?.title ?? DEFAULT_TITLE);\n header.appendChild(title);\n this.$closeBtn = document.createElement('button');\n this.$closeBtn.type = 'button';\n this.$closeBtn.className = 'us-picker-close';\n this.$closeBtn.setAttribute('aria-label', 'Close');\n this.$closeBtn.textContent = '×';\n this.$closeBtn.onclick = () => this.cancel();\n header.appendChild(this.$closeBtn);\n panel.appendChild(header);\n\n // Body\n const body = el('div', 'us-picker-body');\n body.appendChild(this.renderDropzone());\n this.$list = el('div', 'us-file-list');\n body.appendChild(this.$list);\n panel.appendChild(body);\n\n // Actions\n const actions = el('div', 'us-actions');\n this.$cancel = document.createElement('button');\n this.$cancel.type = 'button';\n this.$cancel.className = 'us-btn';\n this.$cancel.textContent = 'Cancel';\n this.$cancel.onclick = () => this.cancel();\n this.$confirm = document.createElement('button');\n this.$confirm.type = 'button';\n this.$confirm.className = 'us-btn us-btn-primary';\n this.$confirm.textContent = 'Upload';\n this.$confirm.disabled = true;\n this.$confirm.onclick = () => this.startUpload();\n actions.appendChild(this.$cancel);\n actions.appendChild(this.$confirm);\n panel.appendChild(actions);\n\n if (!this.opts.branding?.hideFooter) {\n const footer = el('div', 'us-footer');\n footer.innerHTML = `Powered by <a href=\"${FOOTER_LINK}\" target=\"_blank\" rel=\"noopener\">UnionStack</a>`;\n panel.appendChild(footer);\n }\n\n root.appendChild(panel);\n (this.opts.container ?? document.body).appendChild(root);\n this.$backdrop = root;\n }\n\n private renderDropzone(): HTMLElement {\n const dz = el('div', 'us-dropzone');\n dz.setAttribute('role', 'button');\n dz.setAttribute('tabindex', '0');\n dz.appendChild(el('div', 'us-dropzone-title', 'Drag files here'));\n dz.appendChild(el('div', 'us-dropzone-hint', 'or click to browse'));\n\n const input = document.createElement('input');\n input.type = 'file';\n input.multiple = (this.opts.maxFiles ?? 10) > 1;\n if (this.opts.accept) input.accept = this.opts.accept;\n input.style.display = 'none';\n input.onchange = () => {\n if (input.files) this.addFiles(Array.from(input.files));\n input.value = '';\n };\n this.$input = input;\n dz.appendChild(input);\n\n dz.onclick = () => input.click();\n dz.onkeydown = e => {\n if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); input.click(); }\n };\n\n dz.addEventListener('dragover', e => {\n e.preventDefault();\n dz.setAttribute('data-drag', 'over');\n });\n dz.addEventListener('dragleave', () => dz.removeAttribute('data-drag'));\n dz.addEventListener('drop', e => {\n e.preventDefault();\n dz.removeAttribute('data-drag');\n const dropped = e.dataTransfer?.files;\n if (dropped) this.addFiles(Array.from(dropped));\n });\n\n return dz;\n }\n\n private unmount() {\n if (this.$backdrop?.parentNode) this.$backdrop.parentNode.removeChild(this.$backdrop);\n this.$backdrop = null;\n this.opts.onClose?.();\n }\n\n // ---- file selection -----------------------------------------------------\n\n private addFiles(files: File[]) {\n const cap = this.opts.maxFiles ?? Infinity;\n const remaining = cap - this.items.length;\n if (remaining <= 0) return;\n const chosen = files.slice(0, remaining);\n\n for (const file of chosen) {\n if (this.opts.maxFileSize && file.size > this.opts.maxFileSize) {\n // Skip the file but surface a row in the list so the user sees why.\n const item: FileItem = {\n uploadId: cryptoId(),\n file, state: 'failed', progress: 0,\n error: `File exceeds ${formatBytes(this.opts.maxFileSize)} limit`,\n };\n this.items.push(item);\n this.renderItem(item);\n continue;\n }\n\n const item: FileItem = {\n uploadId: cryptoId(),\n file, state: 'queued', progress: 0,\n };\n this.items.push(item);\n this.renderItem(item);\n }\n\n this.refreshConfirm();\n }\n\n private renderItem(item: FileItem) {\n if (!this.$list) return;\n const row = el('div', 'us-file');\n row.dataset.state = item.state;\n row.dataset.uploadId = item.uploadId;\n\n const main = el('div', '', '');\n main.style.flex = '1';\n main.style.minWidth = '0';\n main.appendChild(el('div', 'us-file-name', item.file.name));\n\n const meta = el('div', 'us-file-meta', formatBytes(item.file.size));\n main.appendChild(meta);\n\n const progress = el('div', 'us-file-progress');\n const bar = el('div', 'us-file-progress-bar');\n progress.appendChild(bar);\n main.appendChild(progress);\n row.appendChild(main);\n\n const status = el('div', 'us-file-meta');\n status.style.minWidth = '60px';\n status.style.textAlign = 'right';\n status.textContent = item.state === 'failed'\n ? (item.error || 'failed')\n : item.state === 'done' ? 'done' : '0%';\n row.appendChild(status);\n\n item.$row = row;\n item.$bar = bar;\n item.$status = status;\n\n this.$list.appendChild(row);\n }\n\n private setItemState(item: FileItem, state: FileItemState, progress?: number) {\n item.state = state;\n if (progress !== undefined) item.progress = progress;\n if (item.$row) item.$row.dataset.state = state;\n if (item.$bar) item.$bar.style.width = `${item.progress}%`;\n if (item.$status) {\n if (state === 'failed') item.$status.textContent = item.error || 'failed';\n else if (state === 'done') item.$status.textContent = 'done';\n else item.$status.textContent = `${Math.round(item.progress)}%`;\n }\n }\n\n private refreshConfirm() {\n if (!this.$confirm) return;\n const queued = this.items.filter(i => i.state === 'queued').length;\n this.$confirm.disabled = queued === 0 || this.uploadStarted;\n }\n\n // ---- upload -------------------------------------------------------------\n\n private async startUpload() {\n if (this.uploadStarted) return;\n const queued = this.items.filter(i => i.state === 'queued');\n if (queued.length === 0) return;\n\n this.uploadStarted = true;\n if (this.$confirm) {\n this.$confirm.disabled = true;\n this.$confirm.textContent = 'Uploading…';\n }\n if (this.$cancel) this.$cancel.textContent = 'Stop';\n if (this.$closeBtn) this.$closeBtn.disabled = true;\n if (this.$input) this.$input.disabled = true;\n\n // Map PickedFile.uploadId → FileItem so callbacks update the right row.\n const itemByUploadId = new Map<string, FileItem>();\n const filesToUpload = queued.map(i => i.file);\n\n try {\n await this.client.uploadMany(filesToUpload, {\n ...this.opts,\n signal: this.abortCtrl.signal,\n onUploadStarted: (pickedFiles: PickedFile[]) => {\n // Pair each PickedFile to the queued FileItem in order.\n pickedFiles.forEach((p, idx) => {\n const item = queued[idx];\n if (item) {\n item.uploadId = p.uploadId;\n if (item.$row) item.$row.dataset.uploadId = p.uploadId;\n itemByUploadId.set(p.uploadId, item);\n }\n });\n this.opts.onUploadStarted?.(pickedFiles);\n },\n onFileUploadStarted: p => {\n const item = itemByUploadId.get(p.uploadId);\n if (item) this.setItemState(item, 'uploading', 0);\n this.opts.onFileUploadStarted?.(p);\n },\n onFileUploadProgress: (p, ev) => {\n const item = itemByUploadId.get(p.uploadId);\n if (item) this.setItemState(item, 'uploading', ev.totalPercent);\n this.opts.onFileUploadProgress?.(p, ev);\n },\n onFileUploadFinished: f => {\n const item = itemByUploadId.get(f.uploadId);\n if (item) {\n item.uploaded = f;\n this.setItemState(item, 'done', 100);\n }\n this.opts.onFileUploadFinished?.(f);\n },\n onFileUploadFailed: (p, err) => {\n const item = itemByUploadId.get(p.uploadId);\n if (item) {\n item.error = err.message;\n this.setItemState(item, 'failed');\n }\n this.opts.onFileUploadFailed?.(p, err);\n },\n onUploadDone: r => {\n this.opts.onUploadDone?.(r);\n this.resolveResult(r);\n this.unmount();\n },\n onError: (err: UploadError) => {\n this.opts.onError?.(err);\n this.resolveResult();\n this.unmount();\n },\n });\n } catch {\n // Errors already surfaced via onError / onFileUploadFailed.\n if (!this.resolved) {\n this.resolveResult();\n this.unmount();\n }\n }\n }\n\n private resolveResult(result?: PickResponse) {\n if (this.resolved) return;\n this.resolved = true;\n const fallback: PickResponse = result ?? {\n filesUploaded: this.items.filter(i => i.uploaded).map(i => i.uploaded!),\n filesFailed: this.items\n .filter(i => i.state === 'failed')\n .map(i => ({\n file: {\n uploadId: i.uploadId,\n filename: i.file.name,\n mimetype: i.file.type || 'application/octet-stream',\n size: i.file.size,\n source: 'local',\n },\n error: {\n code: 'VALIDATION',\n message: i.error || 'failed',\n retryable: false,\n },\n })),\n };\n this.resolvePromise(fallback);\n }\n}\n\n// ---- helpers --------------------------------------------------------------\n\nfunction el(tag: string, className: string, text?: string): HTMLElement {\n const node = document.createElement(tag);\n if (className) node.className = className;\n if (text !== undefined) node.textContent = text;\n return node;\n}\n\nfunction formatBytes(n: number): string {\n if (n < 1024) return `${n} B`;\n if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;\n if (n < 1024 * 1024 * 1024) return `${(n / 1024 / 1024).toFixed(1)} MB`;\n return `${(n / 1024 / 1024 / 1024).toFixed(2)} GB`;\n}\n\nfunction cryptoId(): string {\n if (typeof crypto !== 'undefined' && 'randomUUID' in crypto) {\n return (crypto as { randomUUID: () => string }).randomUUID().replace(/-/g, '');\n }\n return Math.random().toString(36).slice(2) + Date.now().toString(36);\n}\n\nexport function openPicker(client: UnionStackClient, opts: PickerOptions): PickerHandle {\n const picker = new Picker(client, opts);\n return {\n open: () => picker.open(),\n close: () => picker.close(),\n cancel: () => picker.cancel(),\n };\n}\n","export { Picker, openPicker } from './picker.js';\nexport type {\n PickerOptions,\n PickerHandle,\n PickerTheme,\n PickerBranding,\n} from './types.js';\n","// IIFE loader entry — bundled as a single drop-in <script>.\n//\n// <script src=\"https://unionstack.mastersunion.link/_sdk/v1/loader.js\"></script>\n// <script>\n// const client = UnionStack.init({ apiKey: 'unionstack_live_…', apiBase: '…' });\n// client.picker({ onUploadDone: r => console.log(r) }).open();\n// </script>\n//\n// Everything (core + picker UI) ships in this single file. The /react entry\n// is intentionally not included here — React users install from npm.\n\nimport { UnionStack, UnionStackClient } from '../index.js';\nimport { Picker, openPicker } from '../picker/index.js';\nimport type { ClientConfig } from '../types.js';\n\n// tsup's IIFE wrapper attaches every named export as a property on the\n// global `UnionStack`. To make `UnionStack.init({...})` work directly (rather\n// than `UnionStack.UnionStack.init(...)`), we flatten `init` to a top-level\n// export and keep the constructor classes available for advanced users.\nconst init = UnionStack.init.bind(UnionStack);\nexport { init, UnionStackClient, Picker, openPicker };\n\nexport type { ClientConfig };\n\n// Auto-init via data attribute — wire the loader without any inline script:\n//\n// <script src=\".../loader.js\" data-unionstack-key=\"unionstack_live_…\"></script>\n//\n// The resulting client lands on `window.UnionStack.client`.\ndeclare global {\n interface Window {\n UnionStack?: {\n init: typeof UnionStack.init;\n client?: UnionStackClient;\n };\n }\n}\n\n(function autoInit() {\n if (typeof document === 'undefined') return;\n const script = document.currentScript as HTMLScriptElement | null;\n if (!script) return;\n const apiKey = script.getAttribute('data-unionstack-key');\n if (!apiKey) return;\n try {\n const client = UnionStack.init({ apiKey });\n queueMicrotask(() => {\n if (window.UnionStack) window.UnionStack.client = client;\n });\n } catch (err) {\n console.error('[UnionStack] auto-init failed:', err);\n }\n})();\n","import type { UploadError, UploadErrorCode } from './types.js';\n\nexport function makeError(\n code: UploadErrorCode,\n message: string,\n opts: { status?: number; retryable?: boolean; cause?: unknown } = {}\n): UploadError {\n return {\n code,\n message,\n status: opts.status,\n retryable: opts.retryable ?? defaultRetryable(code, opts.status),\n cause: opts.cause,\n };\n}\n\nfunction defaultRetryable(code: UploadErrorCode, status?: number): boolean {\n if (code === 'NETWORK' || code === 'PART_FAILED') return true;\n if (code === 'SERVER' && status && status >= 500) return true;\n return false;\n}\n\n/** Map an HTTP error response from the cdn-be API to an UploadError. */\nexport function fromApiResponse(status: number, body: unknown): UploadError {\n const err = (body as { error?: { code?: string; message?: string } } | null)?.error;\n const msg = err?.message || `Request failed with status ${status}`;\n const code = (err?.code || '').toUpperCase();\n\n if (status === 401) {\n return makeError('AUTH', msg, { status, retryable: false });\n }\n if (status === 403) {\n return makeError('AUTH', msg, { status, retryable: false });\n }\n if (status === 413) {\n return makeError('VALIDATION', msg, { status, retryable: false });\n }\n if (status === 415) {\n return makeError('VALIDATION', msg, { status, retryable: false });\n }\n if (status === 429) {\n const isQuota = code === 'QUOTA_EXCEEDED';\n return makeError(isQuota ? 'QUOTA' : 'NETWORK', msg, { status, retryable: !isQuota });\n }\n if (status >= 500) {\n return makeError('SERVER', msg, { status, retryable: true });\n }\n return makeError('SERVER', msg, { status, retryable: false });\n}\n","import type {\n ResolvedClientConfig,\n PickedFile,\n PickerConfig,\n UploadedFile,\n UploadOptions,\n ProgressEvent as USProgressEvent,\n} from './types.js';\nimport { fromApiResponse, makeError } from './errors.js';\n\ninterface InitResponse {\n sessionId: string;\n fileId: string;\n chunkSize: number;\n totalParts: number;\n partUrls: Array<{ partNumber: number; url: string }>;\n expiresAt: string;\n}\n\ninterface CompleteResponse {\n handle: string;\n fileId: string;\n url: string;\n filename: string;\n mimetype: string;\n size: number;\n etag?: string;\n}\n\ninterface PartResult {\n partNumber: number;\n etag: string;\n size: number;\n}\n\nconst DEFAULT_CONCURRENCY = 3;\nconst DEFAULT_MAX_RETRIES_PER_PART = 3;\n// Backoff schedule between part retries. Capped — past this we surrender.\nconst BACKOFF_MS = [400, 1200, 3600];\n\nexport class Uploader {\n constructor(private cfg: ResolvedClientConfig) {}\n\n /** Returns a stable PickedFile descriptor for the input blob/file. */\n describe(file: File | Blob, opts: { filename?: string; mimeType?: string } = {}): PickedFile {\n const isFile = typeof File !== 'undefined' && file instanceof File;\n const filename =\n opts.filename ||\n (isFile ? (file as File).name : 'untitled');\n const mimetype =\n opts.mimeType || (file as Blob).type || 'application/octet-stream';\n return {\n uploadId: cryptoRandomId(),\n filename,\n mimetype,\n size: file.size,\n source: 'local',\n };\n }\n\n /**\n * Upload a single Blob/File. Returns the persisted UploadedFile.\n * Fires Filestack-style per-file callbacks from `opts`.\n */\n async upload(file: File | Blob, opts: UploadOptions = {}): Promise<UploadedFile> {\n const picked = this.describe(file, { filename: opts.filename, mimeType: opts.mimeType });\n opts.onFileUploadStarted?.(picked);\n\n try {\n const init = await this.initUpload(picked, opts);\n const parts = await this.uploadAllParts(file, init, picked, opts);\n const completed = await this.completeUpload(init.sessionId, parts, opts);\n\n const uploaded: UploadedFile = {\n ...picked,\n handle: completed.handle,\n fileId: completed.fileId,\n url: completed.url,\n size: completed.size,\n mimetype: completed.mimetype,\n filename: completed.filename,\n status: 'Stored',\n etag: completed.etag,\n };\n opts.onFileUploadFinished?.(uploaded);\n return uploaded;\n } catch (rawErr) {\n const err = normalizeError(rawErr);\n opts.onFileUploadFailed?.(picked, err);\n // Best effort: tell the server to clean up the multipart, but ignore failures.\n if ((rawErr as { sessionId?: string })?.sessionId) {\n this.abortSilently((rawErr as { sessionId: string }).sessionId).catch(() => {});\n }\n throw err;\n }\n }\n\n /** Cancel an in-flight session server-side. */\n async abort(sessionId: string): Promise<void> {\n await this.api('POST', '/sdk/v1/uploads/abort', { sessionId });\n }\n\n /** Fetch the server-managed picker config (branding, theme, constraints). */\n async fetchPickerConfig(): Promise<PickerConfig> {\n return this.api<PickerConfig>('GET', '/sdk/v1/picker-config');\n }\n\n private async initUpload(picked: PickedFile, opts: UploadOptions): Promise<InitResponse> {\n return this.api<InitResponse>('POST', '/sdk/v1/uploads/init', {\n filename: picked.filename,\n mimeType: picked.mimetype,\n size: picked.size,\n metadata: opts.metadata,\n }, opts.signal);\n }\n\n private async uploadAllParts(\n file: File | Blob,\n init: InitResponse,\n picked: PickedFile,\n opts: UploadOptions,\n ): Promise<PartResult[]> {\n const totalParts = init.totalParts;\n const chunkSize = init.chunkSize;\n const concurrency = Math.max(1, opts.concurrency ?? DEFAULT_CONCURRENCY);\n const maxRetries = opts.maxRetriesPerPart ?? DEFAULT_MAX_RETRIES_PER_PART;\n\n // Quick lookup: partNumber → presigned URL.\n const urlByPart = new Map(init.partUrls.map(p => [p.partNumber, p.url] as const));\n\n const results: PartResult[] = new Array(totalParts);\n const loadedPerPart: number[] = new Array(totalParts).fill(0);\n let cursor = 1;\n\n const totalBytes = file.size;\n\n const reportProgress = () => {\n const loaded = loadedPerPart.reduce((a, b) => a + b, 0);\n const totalPercent = totalBytes > 0 ? Math.min(100, Math.round((loaded / totalBytes) * 100)) : 100;\n const ev: USProgressEvent = { totalBytes, loaded, totalPercent };\n opts.onFileUploadProgress?.(picked, ev);\n };\n\n const worker = async (): Promise<void> => {\n while (true) {\n if (opts.signal?.aborted) {\n throw makeError('ABORTED', 'Upload aborted by caller.', { retryable: false });\n }\n const partNumber = cursor++;\n if (partNumber > totalParts) return;\n\n const start = (partNumber - 1) * chunkSize;\n const end = Math.min(start + chunkSize, file.size);\n const chunk = file.slice(start, end);\n\n let attempt = 0;\n let lastErr: unknown;\n while (attempt <= maxRetries) {\n if (opts.signal?.aborted) {\n throw makeError('ABORTED', 'Upload aborted by caller.', { retryable: false });\n }\n try {\n let url = urlByPart.get(partNumber);\n if (!url) {\n const refreshed = await this.api<{ url: string }>(\n 'POST', '/sdk/v1/uploads/sign-part',\n { sessionId: init.sessionId, partNumber }, opts.signal,\n );\n url = refreshed.url;\n urlByPart.set(partNumber, url);\n }\n\n const res = await this.cfg.fetch?.(url, {\n method: 'PUT',\n body: chunk,\n signal: opts.signal,\n }) ?? await fetch(url, { method: 'PUT', body: chunk, signal: opts.signal });\n\n if (!res.ok) {\n // If R2 rejects with 403 the URL likely expired — drop it so the\n // next attempt re-signs.\n if (res.status === 403 || res.status === 401) urlByPart.delete(partNumber);\n throw makeError('PART_FAILED', `Part ${partNumber} PUT failed (HTTP ${res.status})`, { status: res.status });\n }\n const etag = res.headers.get('etag');\n if (!etag) {\n throw makeError('PART_FAILED', `Part ${partNumber}: R2 did not return an ETag.`);\n }\n\n results[partNumber - 1] = { partNumber, etag, size: chunk.size };\n loadedPerPart[partNumber - 1] = chunk.size;\n reportProgress();\n break;\n } catch (err) {\n lastErr = err;\n attempt++;\n if (attempt > maxRetries) break;\n await sleep(BACKOFF_MS[Math.min(attempt - 1, BACKOFF_MS.length - 1)]);\n }\n }\n if (!results[partNumber - 1]) {\n throw withSessionId(\n normalizeError(lastErr ?? makeError('PART_FAILED', `Part ${partNumber} failed after ${maxRetries} retries.`)),\n init.sessionId,\n );\n }\n }\n };\n\n const workers = Array.from({ length: Math.min(concurrency, totalParts) }, worker);\n await Promise.all(workers);\n return results;\n }\n\n private async completeUpload(\n sessionId: string,\n parts: PartResult[],\n opts: UploadOptions,\n ): Promise<CompleteResponse> {\n return this.api<CompleteResponse>('POST', '/sdk/v1/uploads/complete', {\n sessionId,\n parts: parts.map(p => ({ partNumber: p.partNumber, etag: p.etag })),\n }, opts.signal);\n }\n\n private async abortSilently(sessionId: string): Promise<void> {\n try { await this.abort(sessionId); } catch { /* ignore */ }\n }\n\n private async api<T>(\n method: 'GET' | 'POST' | 'DELETE',\n path: string,\n body?: unknown,\n signal?: AbortSignal,\n ): Promise<T> {\n const fetchImpl = this.cfg.fetch ?? fetch;\n const url = `${this.cfg.apiBase}${path}`;\n let res: Response;\n try {\n res = await fetchImpl(url, {\n method,\n headers: {\n Authorization: `Bearer ${this.cfg.apiKey}`,\n 'Content-Type': 'application/json',\n },\n body: body === undefined ? undefined : JSON.stringify(body),\n signal,\n });\n } catch (cause) {\n if ((cause as Error)?.name === 'AbortError') {\n throw makeError('ABORTED', 'Request aborted.', { retryable: false, cause });\n }\n throw makeError('NETWORK', 'Network request failed.', { retryable: true, cause });\n }\n let parsed: unknown = null;\n try { parsed = await res.json(); } catch { /* tolerate empty body */ }\n if (!res.ok) throw fromApiResponse(res.status, parsed);\n return parsed as T;\n }\n}\n\nfunction cryptoRandomId(): string {\n // Cheap unique id for client-side uploadId. Not security-sensitive.\n if (typeof crypto !== 'undefined' && 'randomUUID' in crypto) {\n return (crypto as { randomUUID: () => string }).randomUUID().replace(/-/g, '');\n }\n return Math.random().toString(36).slice(2) + Date.now().toString(36);\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise(r => setTimeout(r, ms));\n}\n\nfunction normalizeError(err: unknown): ReturnType<typeof makeError> {\n if (err && typeof err === 'object' && 'code' in err && 'message' in err && 'retryable' in err) {\n return err as ReturnType<typeof makeError>;\n }\n const msg = (err as Error)?.message || 'Upload failed.';\n return makeError('NETWORK', msg, { cause: err });\n}\n\nfunction withSessionId<T>(err: T, sessionId: string): T {\n if (err && typeof err === 'object') (err as { sessionId?: string }).sessionId = sessionId;\n return err;\n}\n","import type {\n ClientConfig,\n ResolvedClientConfig,\n UploadOptions,\n BatchUploadOptions,\n UploadedFile,\n PickResponse,\n PickedFile,\n PickerConfig,\n UploadError,\n} from './types.js';\nimport { Uploader } from './uploader.js';\nimport { makeError } from './errors.js';\n\n/**\n * UnionStack API URL baked into the SDK. Consumers never see or set this —\n * we ship a new SDK version if the URL ever changes.\n *\n * For local development against a staging backend, change this constant in\n * src/ and rebuild — no consumer-facing override exists by design.\n */\nconst API_BASE = 'https://cdn-api.mastersunion.org/cdn-api';\n\n// Forward-declared minimal handle so client.ts doesn't pull in the picker bundle.\nexport interface PickerHandleLike {\n open(): Promise<PickResponse>;\n close(): void;\n cancel(): void;\n}\n\nexport class UnionStackClient {\n private uploader: Uploader;\n private resolvedCfg: ResolvedClientConfig;\n /**\n * Promise that resolves to the server-managed picker config. Pre-fetched on\n * construction (unless `skipConfigPrefetch: true`) so the picker opens\n * without a network hit. Fails silently — picker falls back to defaults.\n */\n pickerConfigPromise: Promise<PickerConfig | null>;\n\n constructor(cfg: ClientConfig) {\n if (!cfg.apiKey) throw makeError('CONFIG', 'apiKey is required.', { retryable: false });\n this.resolvedCfg = { ...cfg, apiBase: API_BASE };\n this.uploader = new Uploader(this.resolvedCfg);\n this.pickerConfigPromise = this.resolvedCfg.skipConfigPrefetch\n ? Promise.resolve(null)\n : this.uploader.fetchPickerConfig().catch(() => null);\n }\n\n /** Upload a single file. Mirrors Filestack's `client.upload()`. */\n upload(file: File | Blob, opts: UploadOptions = {}): Promise<UploadedFile> {\n return this.uploader.upload(file, opts);\n }\n\n /**\n * Upload multiple files concurrently. Mirrors Filestack's batch behavior:\n * onUploadDone fires once even if some files failed — failures land in\n * `filesFailed`, successes in `filesUploaded`. `onError` is reserved for\n * batch-level failures (no files even started).\n */\n async uploadMany(\n files: (File | Blob)[],\n opts: BatchUploadOptions = {},\n ): Promise<PickResponse> {\n if (!Array.isArray(files) || files.length === 0) {\n const err = makeError('VALIDATION', 'uploadMany requires a non-empty array of files.', { retryable: false });\n opts.onError?.(err);\n throw err;\n }\n\n const picked: PickedFile[] = files.map(f =>\n this.uploader.describe(f, { filename: opts.filename, mimeType: opts.mimeType })\n );\n opts.onUploadStarted?.(picked);\n\n const filesUploaded: UploadedFile[] = [];\n const filesFailed: Array<{ file: PickedFile; error: UploadError }> = [];\n\n // Process per-file in parallel; the per-part concurrency from `opts` still\n // applies inside each upload.\n await Promise.all(files.map(async (f, i) => {\n try {\n const uploaded = await this.uploader.upload(f, opts);\n // Sync the uploadId so callers can correlate picked → uploaded.\n uploaded.uploadId = picked[i].uploadId;\n filesUploaded.push(uploaded);\n } catch (err) {\n filesFailed.push({ file: picked[i], error: err as UploadError });\n }\n }));\n\n const result: PickResponse = { filesUploaded, filesFailed };\n opts.onUploadDone?.(result);\n return result;\n }\n\n /**\n * Open the file picker modal. Lazy-loads the picker bundle so the core\n * SDK stays small for callers that only use `upload()` directly.\n */\n picker(opts: import('./picker/types.js').PickerOptions = {}): PickerHandleLike {\n let real: PickerHandleLike | null = null;\n let opened = false;\n let pendingResolve!: (r: PickResponse) => void;\n let pendingReject!: (e: UploadError) => void;\n const donePromise = new Promise<PickResponse>((res, rej) => {\n pendingResolve = res; pendingReject = rej;\n });\n\n return {\n open: async () => {\n if (opened) return donePromise;\n opened = true;\n try {\n const mod = await import('./picker/index.js');\n real = mod.openPicker(this, opts);\n const result = await real.open();\n pendingResolve(result);\n return result;\n } catch (err) {\n const e = (err as UploadError)?.code\n ? (err as UploadError)\n : makeError('CONFIG', 'Failed to load picker.', { retryable: false, cause: err });\n pendingReject(e);\n throw e;\n }\n },\n close: () => { real?.close(); },\n cancel: () => { real?.cancel(); },\n };\n }\n\n /** Read-only accessor used by the React/picker packages. */\n get config(): Readonly<ResolvedClientConfig> { return this.resolvedCfg; }\n}\n","import { UnionStackClient } from './client.js';\nimport type { ClientConfig } from './types.js';\n\nexport const UnionStack = {\n init(cfg: ClientConfig): UnionStackClient {\n return new UnionStackClient(cfg);\n },\n};\n\nexport { UnionStackClient } from './client.js';\nexport type {\n ClientConfig,\n UploadOptions,\n BatchUploadOptions,\n PickedFile,\n UploadedFile,\n ProgressEvent,\n PickResponse,\n UploadError,\n UploadErrorCode,\n Source,\n} from './types.js';\n"],"mappings":"y0BAKO,SAASA,GAAqB,CAEnC,GADI,OAAO,UAAa,aACpB,SAAS,eAAeC,CAAQ,EAAG,OACvC,IAAMC,EAAK,SAAS,cAAc,OAAO,EACzCA,EAAG,GAAKD,EACRC,EAAG,YAAcC,GACjB,SAAS,KAAK,YAAYD,CAAE,CAC9B,CAGO,SAASE,GAAeC,EAAwD,CAfvF,IAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAiBE,IAAMC,IADOP,GAAA,YAAAA,EAAO,OAAQ,WACF,OAASQ,GAAgBC,GACnD,MAAO,CACL,gBAAmBR,EAAAD,GAAA,YAAAA,EAAO,UAAP,KAAAC,EAAqBM,EAAS,QACjD,WAAmBL,EAAAF,GAAA,YAAAA,EAAO,aAAP,KAAAE,EAAqBK,EAAS,WACjD,WAAmBJ,EAAAH,GAAA,YAAAA,EAAO,aAAP,KAAAG,EAAqBI,EAAS,WACjD,cAAmBH,EAAAJ,GAAA,YAAAA,EAAO,QAAP,KAAAI,EAAqBG,EAAS,MACjD,eAAmBF,EAAAL,GAAA,YAAAA,EAAO,SAAP,KAAAK,EAAqBE,EAAS,OACjD,eAAmBD,EAAAN,GAAA,YAAAA,EAAO,SAAP,KAAAM,EAAqB,MAC1C,CACF,CA1BA,IAEMV,EA0BAa,GAOAD,GASAV,GA5CNY,GAAAC,EAAA,kBAEMf,EAAW,2BA0BXa,GAAiB,CACrB,QAAY,UACZ,WAAY,UACZ,WAAY,UACZ,MAAY,UACZ,OAAY,SACd,EACMD,GAAgB,CACpB,QAAY,UACZ,WAAY,UACZ,WAAY,UACZ,MAAY,UACZ,OAAY,SACd,EAGMV,GAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;IC/BjB,SAASc,GAAYC,EAAsBC,EAAuC,CAblF,IAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAAAC,EAcE,IAAMC,EAAwBC,EAAA,GAAKtB,GAG7BuB,EAAkBvB,EAAQ,UAAY,CAAC,EAC7CqB,EAAO,SAAW,CAChB,SAASnB,GAAAD,EAAAsB,EAAgB,UAAhB,KAAAtB,EAA2BF,EAAO,SAAS,UAA3C,KAAAG,EAAsD,OAC/D,OAAOE,GAAAD,EAAAoB,EAAgB,QAAhB,KAAApB,EAAyBJ,EAAO,SAAS,QAAzC,KAAAK,EAAkD,OACzD,YAAYC,EAAAkB,EAAgB,aAAhB,KAAAlB,EAA8BN,EAAO,SAAS,UAE5D,EAGA,IAAMyB,EAAexB,EAAQ,OAAS,CAAC,EAavC,GAZAqB,EAAO,MAAQ,CACb,SAASd,GAAAD,EAAAkB,EAAa,UAAb,KAAAlB,EAAwBP,EAAO,MAAM,UAArC,KAAAQ,EAAgD,OACzD,YAAYE,GAAAD,EAAAgB,EAAa,aAAb,KAAAhB,EAA2BT,EAAO,MAAM,aAAxC,KAAAU,EAAsD,OAClE,YAAYE,GAAAD,EAAAc,EAAa,aAAb,KAAAd,EAA2BX,EAAO,MAAM,aAAxC,KAAAY,EAAsD,OAClE,QAAQE,GAAAD,EAAAY,EAAa,SAAb,KAAAZ,EAAuBb,EAAO,MAAM,SAApC,KAAAc,EAA8C,OACtD,QAAQE,GAAAD,EAAAU,EAAa,SAAb,KAAAV,EAAuBf,EAAO,MAAM,SAApC,KAAAgB,EAA8C,OACtD,MAAME,GAAAD,EAAAQ,EAAa,OAAb,KAAAR,EAAqBjB,EAAO,MAAM,OAAlC,KAAAkB,EAA0C,MAClD,EAGAI,EAAO,aAAcH,EAAAlB,EAAQ,cAAR,KAAAkB,EAAuBnB,EAAO,YAAY,iBAC/DsB,EAAO,UAAWF,EAAAnB,EAAQ,WAAR,KAAAmB,EAAoBpB,EAAO,YAAY,kBACrD,CAACC,EAAQ,UAAUoB,EAAArB,EAAO,YAAY,mBAAnB,MAAAqB,EAAqC,QAAQ,CAClE,IAAMK,EAAQ1B,EAAO,YAAY,iBAAiB,OAAO2B,GAAKA,IAAM,KAAK,EACrED,EAAM,OAAS,IAAGJ,EAAO,OAASI,EAAM,KAAK,GAAG,EACtD,CACA,OAAOJ,CACT,CAiYA,SAASM,EAAGC,EAAaC,EAAmBC,EAA4B,CACtE,IAAMC,EAAO,SAAS,cAAcH,CAAG,EACvC,OAAIC,IAAWE,EAAK,UAAYF,GAC5BC,IAAS,SAAWC,EAAK,YAAcD,GACpCC,CACT,CAEA,SAASC,GAAYC,EAAmB,CACtC,OAAIA,EAAI,KAAa,GAAGA,CAAC,KACrBA,EAAI,KAAO,KAAa,IAAIA,EAAI,MAAM,QAAQ,CAAC,CAAC,MAChDA,EAAI,KAAO,KAAO,KAAa,IAAIA,EAAI,KAAO,MAAM,QAAQ,CAAC,CAAC,MAC3D,IAAIA,EAAI,KAAO,KAAO,MAAM,QAAQ,CAAC,CAAC,KAC/C,CAEA,SAASC,IAAmB,CAC1B,OAAI,OAAO,QAAW,aAAe,eAAgB,OAC3C,OAAwC,WAAW,EAAE,QAAQ,KAAM,EAAE,EAExE,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,CAAC,EAAI,KAAK,IAAI,EAAE,SAAS,EAAE,CACrE,CAEO,SAASC,EAAWC,EAA0BC,EAAmC,CACtF,IAAMC,EAAS,IAAIC,EAAOH,EAAQC,CAAI,EACtC,MAAO,CACL,KAAM,IAAMC,EAAO,KAAK,EACxB,MAAO,IAAMA,EAAO,MAAM,EAC1B,OAAQ,IAAMA,EAAO,OAAO,CAC9B,CACF,CAzcA,IA6DME,GACAC,GAMOF,EApEbG,GAAAC,EAAA,kBASAC,KAoDMJ,GAAgB,eAChBC,GAAc,uCAMPF,EAAN,KAAa,CAelB,YACUH,EACAC,EACR,CAFQ,YAAAD,EACA,UAAAC,EAhBV,KAAQ,UAAgC,KACxC,KAAQ,MAA4B,KACpC,KAAQ,SAAqC,KAC7C,KAAQ,QAAoC,KAC5C,KAAQ,UAAsC,KAC9C,KAAQ,OAAkC,KAE1C,KAAQ,MAAoB,CAAC,EAC7B,KAAQ,UAAY,IAAI,gBACxB,KAAQ,cAAgB,GACxB,KAAQ,SAAW,GAQjB,KAAK,YAAc,IAAI,QAAsBQ,GAAO,CAAE,KAAK,eAAiBA,CAAK,CAAC,CACpF,CAIA,MAAM,MAA8B,CA5FtC,IAAA5C,EAAAC,EA6FI,GAAI,OAAO,UAAa,YACtB,MAAM,IAAI,MAAM,sDAAsD,EAIxE,GAAI,CACF,IAAM4C,EAAe,MAAM,KAAK,OAAO,oBACnCA,IAAc,KAAK,KAAOhD,GAAYgD,EAAc,KAAK,IAAI,EACnE,OAAQC,EAAA,CAA0D,CAElE,OAAAC,EAAa,EACb,KAAK,MAAM,GACX9C,GAAAD,EAAA,KAAK,MAAK,SAAV,MAAAC,EAAA,KAAAD,GACO,KAAK,WACd,CAEA,OAAc,CACZ,KAAK,QAAQ,EAER,KAAK,UAAU,KAAK,cAAc,CACzC,CAEA,QAAe,CAnHjB,IAAAA,EAAAC,EAoHI,KAAK,UAAU,MAAM,GACrBA,GAAAD,EAAA,KAAK,MAAK,WAAV,MAAAC,EAAA,KAAAD,GACA,KAAK,MAAM,CACb,CAIQ,OAAQ,CA3HlB,IAAAA,EAAAC,EAAAC,EAAAC,EAAAC,EA4HI,IAAM4C,EAAO,SAAS,cAAc,KAAK,EACzCA,EAAK,UAAY,qBACjB,OAAO,QAAQC,GAAe,KAAK,KAAK,KAAK,CAAC,EAAE,QAAQ,CAAC,CAACC,EAAGC,CAAC,IAAM,CAClEH,EAAK,MAAM,YAAYE,EAAGC,CAAC,CAC7B,CAAC,EACDH,EAAK,iBAAiB,QAASF,GAAK,CAC9BA,EAAE,SAAWE,GAAQ,CAAC,KAAK,eAAe,KAAK,OAAO,CAC5D,CAAC,EAED,IAAMI,EAAQ1B,EAAG,MAAO,WAAW,EAG7B2B,EAAS3B,EAAG,MAAO,kBAAkB,EAC3C,IAAI1B,EAAA,KAAK,KAAK,WAAV,MAAAA,EAAoB,QAAS,CAC/B,IAAMsD,EAAO,SAAS,cAAc,KAAK,EACzCA,EAAK,IAAM,KAAK,KAAK,SAAS,QAC9BA,EAAK,IAAM,OACXD,EAAO,YAAYC,CAAI,CACzB,CACA,IAAMC,EAAQ7B,EAAG,MAAO,mBAAmBxB,GAAAD,EAAA,KAAK,KAAK,WAAV,YAAAA,EAAoB,QAApB,KAAAC,EAA6BqC,EAAa,EACrFc,EAAO,YAAYE,CAAK,EACxB,KAAK,UAAY,SAAS,cAAc,QAAQ,EAChD,KAAK,UAAU,KAAO,SACtB,KAAK,UAAU,UAAY,kBAC3B,KAAK,UAAU,aAAa,aAAc,OAAO,EACjD,KAAK,UAAU,YAAc,OAC7B,KAAK,UAAU,QAAU,IAAM,KAAK,OAAO,EAC3CF,EAAO,YAAY,KAAK,SAAS,EACjCD,EAAM,YAAYC,CAAM,EAGxB,IAAMG,EAAO9B,EAAG,MAAO,gBAAgB,EACvC8B,EAAK,YAAY,KAAK,eAAe,CAAC,EACtC,KAAK,MAAQ9B,EAAG,MAAO,cAAc,EACrC8B,EAAK,YAAY,KAAK,KAAK,EAC3BJ,EAAM,YAAYI,CAAI,EAGtB,IAAMC,EAAU/B,EAAG,MAAO,YAAY,EAgBtC,GAfA,KAAK,QAAU,SAAS,cAAc,QAAQ,EAC9C,KAAK,QAAQ,KAAO,SACpB,KAAK,QAAQ,UAAY,SACzB,KAAK,QAAQ,YAAc,SAC3B,KAAK,QAAQ,QAAU,IAAM,KAAK,OAAO,EACzC,KAAK,SAAW,SAAS,cAAc,QAAQ,EAC/C,KAAK,SAAS,KAAO,SACrB,KAAK,SAAS,UAAY,wBAC1B,KAAK,SAAS,YAAc,SAC5B,KAAK,SAAS,SAAW,GACzB,KAAK,SAAS,QAAU,IAAM,KAAK,YAAY,EAC/C+B,EAAQ,YAAY,KAAK,OAAO,EAChCA,EAAQ,YAAY,KAAK,QAAQ,EACjCL,EAAM,YAAYK,CAAO,EAErB,GAACtD,EAAA,KAAK,KAAK,WAAV,MAAAA,EAAoB,YAAY,CACnC,IAAMuD,EAAShC,EAAG,MAAO,WAAW,EACpCgC,EAAO,UAAY,uBAAuBlB,EAAW,kDACrDY,EAAM,YAAYM,CAAM,CAC1B,CAEAV,EAAK,YAAYI,CAAK,IACrBhD,EAAA,KAAK,KAAK,YAAV,KAAAA,EAAuB,SAAS,MAAM,YAAY4C,CAAI,EACvD,KAAK,UAAYA,CACnB,CAEQ,gBAA8B,CA7LxC,IAAAhD,EA8LI,IAAM2D,EAAKjC,EAAG,MAAO,aAAa,EAClCiC,EAAG,aAAa,OAAQ,QAAQ,EAChCA,EAAG,aAAa,WAAY,GAAG,EAC/BA,EAAG,YAAYjC,EAAG,MAAO,oBAAqB,iBAAiB,CAAC,EAChEiC,EAAG,YAAYjC,EAAG,MAAO,mBAAoB,oBAAoB,CAAC,EAElE,IAAMkC,EAAQ,SAAS,cAAc,OAAO,EAC5C,OAAAA,EAAM,KAAO,OACbA,EAAM,WAAY5D,EAAA,KAAK,KAAK,WAAV,KAAAA,EAAsB,IAAM,EAC1C,KAAK,KAAK,SAAQ4D,EAAM,OAAS,KAAK,KAAK,QAC/CA,EAAM,MAAM,QAAU,OACtBA,EAAM,SAAW,IAAM,CACjBA,EAAM,OAAO,KAAK,SAAS,MAAM,KAAKA,EAAM,KAAK,CAAC,EACtDA,EAAM,MAAQ,EAChB,EACA,KAAK,OAASA,EACdD,EAAG,YAAYC,CAAK,EAEpBD,EAAG,QAAU,IAAMC,EAAM,MAAM,EAC/BD,EAAG,UAAYb,GAAK,EACdA,EAAE,MAAQ,SAAWA,EAAE,MAAQ,OAAOA,EAAE,eAAe,EAAGc,EAAM,MAAM,EAC5E,EAEAD,EAAG,iBAAiB,WAAYb,GAAK,CACnCA,EAAE,eAAe,EACjBa,EAAG,aAAa,YAAa,MAAM,CACrC,CAAC,EACDA,EAAG,iBAAiB,YAAa,IAAMA,EAAG,gBAAgB,WAAW,CAAC,EACtEA,EAAG,iBAAiB,OAAQb,GAAK,CA1NrC,IAAA9C,EA2NM8C,EAAE,eAAe,EACjBa,EAAG,gBAAgB,WAAW,EAC9B,IAAME,GAAU7D,EAAA8C,EAAE,eAAF,YAAA9C,EAAgB,MAC5B6D,GAAS,KAAK,SAAS,MAAM,KAAKA,CAAO,CAAC,CAChD,CAAC,EAEMF,CACT,CAEQ,SAAU,CApOpB,IAAA3D,EAAAC,EAAAC,GAqOQF,EAAA,KAAK,YAAL,MAAAA,EAAgB,YAAY,KAAK,UAAU,WAAW,YAAY,KAAK,SAAS,EACpF,KAAK,UAAY,MACjBE,GAAAD,EAAA,KAAK,MAAK,UAAV,MAAAC,EAAA,KAAAD,EACF,CAIQ,SAAS6D,EAAe,CA5OlC,IAAA9D,EA8OI,IAAM+D,IADM/D,EAAA,KAAK,KAAK,WAAV,KAAAA,EAAsB,KACV,KAAK,MAAM,OACnC,GAAI+D,GAAa,EAAG,OACpB,IAAMC,EAASF,EAAM,MAAM,EAAGC,CAAS,EAEvC,QAAWE,KAAQD,EAAQ,CACzB,GAAI,KAAK,KAAK,aAAeC,EAAK,KAAO,KAAK,KAAK,YAAa,CAE9D,IAAMC,EAAiB,CACrB,SAAUjC,GAAS,EACnB,KAAAgC,EAAM,MAAO,SAAU,SAAU,EACjC,MAAO,gBAAgBlC,GAAY,KAAK,KAAK,WAAW,CAAC,QAC3D,EACA,KAAK,MAAM,KAAKmC,CAAI,EACpB,KAAK,WAAWA,CAAI,EACpB,QACF,CAEA,IAAMA,EAAiB,CACrB,SAAUjC,GAAS,EACnB,KAAAgC,EAAM,MAAO,SAAU,SAAU,CACnC,EACA,KAAK,MAAM,KAAKC,CAAI,EACpB,KAAK,WAAWA,CAAI,CACtB,CAEA,KAAK,eAAe,CACtB,CAEQ,WAAWA,EAAgB,CACjC,GAAI,CAAC,KAAK,MAAO,OACjB,IAAMC,EAAMzC,EAAG,MAAO,SAAS,EAC/ByC,EAAI,QAAQ,MAAQD,EAAK,MACzBC,EAAI,QAAQ,SAAWD,EAAK,SAE5B,IAAME,EAAO1C,EAAG,MAAO,GAAI,EAAE,EAC7B0C,EAAK,MAAM,KAAO,IAClBA,EAAK,MAAM,SAAW,IACtBA,EAAK,YAAY1C,EAAG,MAAO,eAAgBwC,EAAK,KAAK,IAAI,CAAC,EAE1D,IAAMG,EAAO3C,EAAG,MAAO,eAAgBK,GAAYmC,EAAK,KAAK,IAAI,CAAC,EAClEE,EAAK,YAAYC,CAAI,EAErB,IAAMC,EAAW5C,EAAG,MAAO,kBAAkB,EACvC6C,EAAM7C,EAAG,MAAO,sBAAsB,EAC5C4C,EAAS,YAAYC,CAAG,EACxBH,EAAK,YAAYE,CAAQ,EACzBH,EAAI,YAAYC,CAAI,EAEpB,IAAMI,EAAS9C,EAAG,MAAO,cAAc,EACvC8C,EAAO,MAAM,SAAW,OACxBA,EAAO,MAAM,UAAY,QACzBA,EAAO,YAAcN,EAAK,QAAU,SAC/BA,EAAK,OAAS,SACfA,EAAK,QAAU,OAAS,OAAS,KACrCC,EAAI,YAAYK,CAAM,EAEtBN,EAAK,KAAOC,EACZD,EAAK,KAAOK,EACZL,EAAK,QAAUM,EAEf,KAAK,MAAM,YAAYL,CAAG,CAC5B,CAEQ,aAAaD,EAAgBO,EAAsBH,EAAmB,CAC5EJ,EAAK,MAAQO,EACTH,IAAa,SAAWJ,EAAK,SAAWI,GACxCJ,EAAK,OAAMA,EAAK,KAAK,QAAQ,MAAQO,GACrCP,EAAK,OAAMA,EAAK,KAAK,MAAM,MAAQ,GAAGA,EAAK,QAAQ,KACnDA,EAAK,UACHO,IAAU,SAAUP,EAAK,QAAQ,YAAcA,EAAK,OAAS,SACxDO,IAAU,OAAQP,EAAK,QAAQ,YAAc,OACjDA,EAAK,QAAQ,YAAc,GAAG,KAAK,MAAMA,EAAK,QAAQ,CAAC,IAEhE,CAEQ,gBAAiB,CACvB,GAAI,CAAC,KAAK,SAAU,OACpB,IAAMQ,EAAS,KAAK,MAAM,OAAOC,GAAKA,EAAE,QAAU,QAAQ,EAAE,OAC5D,KAAK,SAAS,SAAWD,IAAW,GAAK,KAAK,aAChD,CAIA,MAAc,aAAc,CAC1B,GAAI,KAAK,cAAe,OACxB,IAAMA,EAAS,KAAK,MAAM,OAAOC,GAAKA,EAAE,QAAU,QAAQ,EAC1D,GAAID,EAAO,SAAW,EAAG,OAEzB,KAAK,cAAgB,GACjB,KAAK,WACP,KAAK,SAAS,SAAW,GACzB,KAAK,SAAS,YAAc,mBAE1B,KAAK,UAAS,KAAK,QAAQ,YAAc,QACzC,KAAK,YAAW,KAAK,UAAU,SAAW,IAC1C,KAAK,SAAQ,KAAK,OAAO,SAAW,IAGxC,IAAME,EAAiB,IAAI,IACrBC,EAAgBH,EAAO,IAAIC,GAAKA,EAAE,IAAI,EAE5C,GAAI,CACF,MAAM,KAAK,OAAO,WAAWE,EAAeC,EAAAzD,EAAA,GACvC,KAAK,MADkC,CAE1C,OAAQ,KAAK,UAAU,OACvB,gBAAkB0D,GAA8B,CAvVxD,IAAA/E,EAAAC,EAyVU8E,EAAY,QAAQ,CAACC,EAAGC,IAAQ,CAC9B,IAAMf,EAAOQ,EAAOO,CAAG,EACnBf,IACFA,EAAK,SAAWc,EAAE,SACdd,EAAK,OAAMA,EAAK,KAAK,QAAQ,SAAWc,EAAE,UAC9CJ,EAAe,IAAII,EAAE,SAAUd,CAAI,EAEvC,CAAC,GACDjE,GAAAD,EAAA,KAAK,MAAK,kBAAV,MAAAC,EAAA,KAAAD,EAA4B+E,EAC9B,EACA,oBAAqBC,GAAK,CAnWlC,IAAAhF,EAAAC,EAoWU,IAAMiE,EAAOU,EAAe,IAAII,EAAE,QAAQ,EACtCd,GAAM,KAAK,aAAaA,EAAM,YAAa,CAAC,GAChDjE,GAAAD,EAAA,KAAK,MAAK,sBAAV,MAAAC,EAAA,KAAAD,EAAgCgF,EAClC,EACA,qBAAsB,CAACA,EAAGE,IAAO,CAxWzC,IAAAlF,EAAAC,EAyWU,IAAMiE,EAAOU,EAAe,IAAII,EAAE,QAAQ,EACtCd,GAAM,KAAK,aAAaA,EAAM,YAAagB,EAAG,YAAY,GAC9DjF,GAAAD,EAAA,KAAK,MAAK,uBAAV,MAAAC,EAAA,KAAAD,EAAiCgF,EAAGE,EACtC,EACA,qBAAsBC,GAAK,CA7WnC,IAAAnF,EAAAC,EA8WU,IAAMiE,EAAOU,EAAe,IAAIO,EAAE,QAAQ,EACtCjB,IACFA,EAAK,SAAWiB,EAChB,KAAK,aAAajB,EAAM,OAAQ,GAAG,IAErCjE,GAAAD,EAAA,KAAK,MAAK,uBAAV,MAAAC,EAAA,KAAAD,EAAiCmF,EACnC,EACA,mBAAoB,CAACH,EAAGI,IAAQ,CArXxC,IAAApF,EAAAC,EAsXU,IAAMiE,EAAOU,EAAe,IAAII,EAAE,QAAQ,EACtCd,IACFA,EAAK,MAAQkB,EAAI,QACjB,KAAK,aAAalB,EAAM,QAAQ,IAElCjE,GAAAD,EAAA,KAAK,MAAK,qBAAV,MAAAC,EAAA,KAAAD,EAA+BgF,EAAGI,EACpC,EACA,aAAcC,GAAK,CA7X3B,IAAArF,EAAAC,GA8XUA,GAAAD,EAAA,KAAK,MAAK,eAAV,MAAAC,EAAA,KAAAD,EAAyBqF,GACzB,KAAK,cAAcA,CAAC,EACpB,KAAK,QAAQ,CACf,EACA,QAAUD,GAAqB,CAlYvC,IAAApF,EAAAC,GAmYUA,GAAAD,EAAA,KAAK,MAAK,UAAV,MAAAC,EAAA,KAAAD,EAAoBoF,GACpB,KAAK,cAAc,EACnB,KAAK,QAAQ,CACf,CACF,EAAC,CACH,OAAQtC,EAAA,CAED,KAAK,WACR,KAAK,cAAc,EACnB,KAAK,QAAQ,EAEjB,CACF,CAEQ,cAAcwC,EAAuB,CAC3C,GAAI,KAAK,SAAU,OACnB,KAAK,SAAW,GAChB,IAAMC,EAAyBD,GAAA,KAAAA,EAAU,CACvC,cAAe,KAAK,MAAM,OAAOX,GAAKA,EAAE,QAAQ,EAAE,IAAIA,GAAKA,EAAE,QAAS,EACtE,YAAa,KAAK,MACf,OAAOA,GAAKA,EAAE,QAAU,QAAQ,EAChC,IAAIA,IAAM,CACT,KAAM,CACJ,SAAUA,EAAE,SACZ,SAAUA,EAAE,KAAK,KACjB,SAAUA,EAAE,KAAK,MAAQ,2BACzB,KAAMA,EAAE,KAAK,KACb,OAAQ,OACV,EACA,MAAO,CACL,KAAM,aACN,QAASA,EAAE,OAAS,SACpB,UAAW,EACb,CACF,EAAE,CACN,EACA,KAAK,eAAeY,CAAQ,CAC9B,CACF,ICzaA,IAAAC,GAAA,GAAAC,EAAAD,GAAA,YAAAE,EAAA,eAAAC,IAAA,IAAAC,EAAAC,EAAA,kBAAAD,OCAA,IAAAE,GAAA,GAAAC,EAAAD,GAAA,YAAAE,EAAA,qBAAAC,EAAA,SAAAC,GAAA,eAAAC,ICEO,SAASC,EACdC,EACAC,EACAC,EAAkE,CAAC,EACtD,CANf,IAAAC,EAOE,MAAO,CACL,KAAAH,EACA,QAAAC,EACA,OAAQC,EAAK,OACb,WAAWC,EAAAD,EAAK,YAAL,KAAAC,EAAkBC,GAAiBJ,EAAME,EAAK,MAAM,EAC/D,MAAOA,EAAK,KACd,CACF,CAEA,SAASE,GAAiBJ,EAAuBK,EAA0B,CAEzE,MADI,GAAAL,IAAS,WAAaA,IAAS,eAC/BA,IAAS,UAAYK,GAAUA,GAAU,IAE/C,CAGO,SAASC,EAAgBD,EAAgBE,EAA4B,CAC1E,IAAMC,EAAOD,GAAA,YAAAA,EAAiE,MACxEE,GAAMD,GAAA,YAAAA,EAAK,UAAW,8BAA8BH,CAAM,GAC1DL,IAAQQ,GAAA,YAAAA,EAAK,OAAQ,IAAI,YAAY,EAE3C,GAAIH,IAAW,IACb,OAAON,EAAU,OAAQU,EAAK,CAAE,OAAAJ,EAAQ,UAAW,EAAM,CAAC,EAE5D,GAAIA,IAAW,IACb,OAAON,EAAU,OAAQU,EAAK,CAAE,OAAAJ,EAAQ,UAAW,EAAM,CAAC,EAE5D,GAAIA,IAAW,IACb,OAAON,EAAU,aAAcU,EAAK,CAAE,OAAAJ,EAAQ,UAAW,EAAM,CAAC,EAElE,GAAIA,IAAW,IACb,OAAON,EAAU,aAAcU,EAAK,CAAE,OAAAJ,EAAQ,UAAW,EAAM,CAAC,EAElE,GAAIA,IAAW,IAAK,CAClB,IAAMK,EAAUV,IAAS,iBACzB,OAAOD,EAAUW,EAAU,QAAU,UAAWD,EAAK,CAAE,OAAAJ,EAAQ,UAAW,CAACK,CAAQ,CAAC,CACtF,CACA,OAAIL,GAAU,IACLN,EAAU,SAAUU,EAAK,CAAE,OAAAJ,EAAQ,UAAW,EAAK,CAAC,EAEtDN,EAAU,SAAUU,EAAK,CAAE,OAAAJ,EAAQ,UAAW,EAAM,CAAC,CAC9D,CCbA,IAAMM,GAAsB,EACtBC,GAA+B,EAE/BC,EAAa,CAAC,IAAK,KAAM,IAAI,EAEtBC,EAAN,KAAe,CACpB,YAAoBC,EAA2B,CAA3B,SAAAA,CAA4B,CAGhD,SAASC,EAAmBC,EAAiD,CAAC,EAAe,CAC3F,IAAMC,EAAS,OAAO,MAAS,aAAeF,aAAgB,KACxDG,EACJF,EAAK,WACJC,EAAUF,EAAc,KAAO,YAC5BI,EACJH,EAAK,UAAaD,EAAc,MAAQ,2BAC1C,MAAO,CACL,SAAUK,GAAe,EACzB,SAAAF,EACA,SAAAC,EACA,KAAMJ,EAAK,KACX,OAAQ,OACV,CACF,CAMA,MAAM,OAAOA,EAAmBC,EAAsB,CAAC,EAA0B,CAhEnF,IAAAK,EAAAC,EAAAC,EAiEI,IAAMC,EAAS,KAAK,SAAST,EAAM,CAAE,SAAUC,EAAK,SAAU,SAAUA,EAAK,QAAS,CAAC,GACvFK,EAAAL,EAAK,sBAAL,MAAAK,EAAA,KAAAL,EAA2BQ,GAE3B,GAAI,CACF,IAAMC,EAAO,MAAM,KAAK,WAAWD,EAAQR,CAAI,EACzCU,EAAQ,MAAM,KAAK,eAAeX,EAAMU,EAAMD,EAAQR,CAAI,EAC1DW,EAAY,MAAM,KAAK,eAAeF,EAAK,UAAWC,EAAOV,CAAI,EAEjEY,EAAyBC,EAAAC,EAAA,GAC1BN,GAD0B,CAE7B,OAAQG,EAAU,OAClB,OAAQA,EAAU,OAClB,IAAKA,EAAU,IACf,KAAMA,EAAU,KAChB,SAAUA,EAAU,SACpB,SAAUA,EAAU,SACpB,OAAQ,SACR,KAAMA,EAAU,IAClB,GACA,OAAAL,EAAAN,EAAK,uBAAL,MAAAM,EAAA,KAAAN,EAA4BY,GACrBA,CACT,OAASG,EAAQ,CACf,IAAMC,EAAMC,EAAeF,CAAM,EACjC,MAAAR,EAAAP,EAAK,qBAAL,MAAAO,EAAA,KAAAP,EAA0BQ,EAAQQ,GAE7BD,GAAA,MAAAA,EAAmC,WACtC,KAAK,cAAeA,EAAiC,SAAS,EAAE,MAAM,IAAM,CAAC,CAAC,EAE1EC,CACR,CACF,CAGA,MAAM,MAAME,EAAkC,CAC5C,MAAM,KAAK,IAAI,OAAQ,wBAAyB,CAAE,UAAAA,CAAU,CAAC,CAC/D,CAGA,MAAM,mBAA2C,CAC/C,OAAO,KAAK,IAAkB,MAAO,uBAAuB,CAC9D,CAEA,MAAc,WAAWV,EAAoBR,EAA4C,CACvF,OAAO,KAAK,IAAkB,OAAQ,uBAAwB,CAC5D,SAAUQ,EAAO,SACjB,SAAUA,EAAO,SACjB,KAAMA,EAAO,KACb,SAAUR,EAAK,QACjB,EAAGA,EAAK,MAAM,CAChB,CAEA,MAAc,eACZD,EACAU,EACAD,EACAR,EACuB,CAzH3B,IAAAK,EAAAC,EA0HI,IAAMa,EAAaV,EAAK,WAClBW,EAAYX,EAAK,UACjBY,EAAc,KAAK,IAAI,GAAGhB,EAAAL,EAAK,cAAL,KAAAK,EAAoBX,EAAmB,EACjE4B,GAAahB,EAAAN,EAAK,oBAAL,KAAAM,EAA0BX,GAGvC4B,EAAY,IAAI,IAAId,EAAK,SAAS,IAAIe,GAAK,CAACA,EAAE,WAAYA,EAAE,GAAG,CAAU,CAAC,EAE1EC,EAAwB,IAAI,MAAMN,CAAU,EAC5CO,EAA0B,IAAI,MAAMP,CAAU,EAAE,KAAK,CAAC,EACxDQ,EAAS,EAEPC,EAAa7B,EAAK,KAElB8B,EAAiB,IAAM,CAxIjC,IAAAxB,EAyIM,IAAMyB,EAASJ,EAAc,OAAO,CAACK,EAAGC,IAAMD,EAAIC,EAAG,CAAC,EAChDC,EAAeL,EAAa,EAAI,KAAK,IAAI,IAAK,KAAK,MAAOE,EAASF,EAAc,GAAG,CAAC,EAAI,IACzFM,EAAsB,CAAE,WAAAN,EAAY,OAAAE,EAAQ,aAAAG,CAAa,GAC/D5B,EAAAL,EAAK,uBAAL,MAAAK,EAAA,KAAAL,EAA4BQ,EAAQ0B,EACtC,EAEMC,EAAS,SAA2B,CA/I9C,IAAA9B,EAAAC,EAAAC,EAAA6B,EAAAC,EAgJM,OAAa,CACX,IAAIhC,EAAAL,EAAK,SAAL,MAAAK,EAAa,QACf,MAAMiC,EAAU,UAAW,4BAA6B,CAAE,UAAW,EAAM,CAAC,EAE9E,IAAMC,EAAaZ,IACnB,GAAIY,EAAapB,EAAY,OAE7B,IAAMqB,GAASD,EAAa,GAAKnB,EAC3BqB,EAAM,KAAK,IAAID,EAAQpB,EAAWrB,EAAK,IAAI,EAC3C2C,EAAQ3C,EAAK,MAAMyC,EAAOC,CAAG,EAE/BE,EAAU,EACVC,EACJ,KAAOD,GAAWrB,GAAY,CAC5B,IAAIhB,EAAAN,EAAK,SAAL,MAAAM,EAAa,QACf,MAAMgC,EAAU,UAAW,4BAA6B,CAAE,UAAW,EAAM,CAAC,EAE9E,GAAI,CACF,IAAIO,EAAMtB,EAAU,IAAIgB,CAAU,EAC7BM,IAKHA,GAJkB,MAAM,KAAK,IAC3B,OAAQ,4BACR,CAAE,UAAWpC,EAAK,UAAW,WAAA8B,CAAW,EAAGvC,EAAK,MAClD,GACgB,IAChBuB,EAAU,IAAIgB,EAAYM,CAAG,GAG/B,IAAMC,GAAMT,EAAA,OAAMD,GAAA7B,EAAA,KAAK,KAAI,QAAT,YAAA6B,EAAA,KAAA7B,EAAiBsC,EAAK,CACtC,OAAQ,MACR,KAAMH,EACN,OAAQ1C,EAAK,MACf,MAJY,KAAAqC,EAIN,MAAM,MAAMQ,EAAK,CAAE,OAAQ,MAAO,KAAMH,EAAO,OAAQ1C,EAAK,MAAO,CAAC,EAE1E,GAAI,CAAC8C,EAAI,GAGP,MAAIA,EAAI,SAAW,KAAOA,EAAI,SAAW,MAAKvB,EAAU,OAAOgB,CAAU,EACnED,EAAU,cAAe,QAAQC,CAAU,qBAAqBO,EAAI,MAAM,IAAK,CAAE,OAAQA,EAAI,MAAO,CAAC,EAE7G,IAAMC,EAAOD,EAAI,QAAQ,IAAI,MAAM,EACnC,GAAI,CAACC,EACH,MAAMT,EAAU,cAAe,QAAQC,CAAU,8BAA8B,EAGjFd,EAAQc,EAAa,CAAC,EAAI,CAAE,WAAAA,EAAY,KAAAQ,EAAM,KAAML,EAAM,IAAK,EAC/DhB,EAAca,EAAa,CAAC,EAAIG,EAAM,KACtCb,EAAe,EACf,KACF,OAASb,EAAK,CAGZ,GAFA4B,EAAU5B,EACV2B,IACIA,EAAUrB,EAAY,MAC1B,MAAM0B,GAAMpD,EAAW,KAAK,IAAI+C,EAAU,EAAG/C,EAAW,OAAS,CAAC,CAAC,CAAC,CACtE,CACF,CACA,GAAI,CAAC6B,EAAQc,EAAa,CAAC,EACzB,MAAMU,GACJhC,EAAe2B,GAAA,KAAAA,EAAWN,EAAU,cAAe,QAAQC,CAAU,iBAAiBjB,CAAU,WAAW,CAAC,EAC5Gb,EAAK,SACP,CAEJ,CACF,EAEMyC,EAAU,MAAM,KAAK,CAAE,OAAQ,KAAK,IAAI7B,EAAaF,CAAU,CAAE,EAAGgB,CAAM,EAChF,aAAM,QAAQ,IAAIe,CAAO,EAClBzB,CACT,CAEA,MAAc,eACZP,EACAR,EACAV,EAC2B,CAC3B,OAAO,KAAK,IAAsB,OAAQ,2BAA4B,CACpE,UAAAkB,EACA,MAAOR,EAAM,IAAIc,IAAM,CAAE,WAAYA,EAAE,WAAY,KAAMA,EAAE,IAAK,EAAE,CACpE,EAAGxB,EAAK,MAAM,CAChB,CAEA,MAAc,cAAckB,EAAkC,CAC5D,GAAI,CAAE,MAAM,KAAK,MAAMA,CAAS,CAAG,OAAQiC,EAAA,CAAe,CAC5D,CAEA,MAAc,IACZC,EACAC,EACAC,EACAC,EACY,CA1OhB,IAAAlD,EA2OI,IAAMmD,GAAYnD,EAAA,KAAK,IAAI,QAAT,KAAAA,EAAkB,MAC9BwC,EAAM,GAAG,KAAK,IAAI,OAAO,GAAGQ,CAAI,GAClCP,EACJ,GAAI,CACFA,EAAM,MAAMU,EAAUX,EAAK,CACzB,OAAAO,EACA,QAAS,CACP,cAAe,UAAU,KAAK,IAAI,MAAM,GACxC,eAAgB,kBAClB,EACA,KAAME,IAAS,OAAY,OAAY,KAAK,UAAUA,CAAI,EAC1D,OAAAC,CACF,CAAC,CACH,OAASE,EAAO,CACd,MAAKA,GAAA,YAAAA,EAAiB,QAAS,aACvBnB,EAAU,UAAW,mBAAoB,CAAE,UAAW,GAAO,MAAAmB,CAAM,CAAC,EAEtEnB,EAAU,UAAW,0BAA2B,CAAE,UAAW,GAAM,MAAAmB,CAAM,CAAC,CAClF,CACA,IAAIC,EAAkB,KACtB,GAAI,CAAEA,EAAS,MAAMZ,EAAI,KAAK,CAAG,OAAQK,EAAA,CAA4B,CACrE,GAAI,CAACL,EAAI,GAAI,MAAMa,EAAgBb,EAAI,OAAQY,CAAM,EACrD,OAAOA,CACT,CACF,EAEA,SAAStD,IAAyB,CAEhC,OAAI,OAAO,QAAW,aAAe,eAAgB,OAC3C,OAAwC,WAAW,EAAE,QAAQ,KAAM,EAAE,EAExE,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,CAAC,EAAI,KAAK,IAAI,EAAE,SAAS,EAAE,CACrE,CAEA,SAAS4C,GAAMY,EAA2B,CACxC,OAAO,IAAI,QAAQC,GAAK,WAAWA,EAAGD,CAAE,CAAC,CAC3C,CAEA,SAAS3C,EAAeD,EAA4C,CAClE,GAAIA,GAAO,OAAOA,GAAQ,UAAY,SAAUA,GAAO,YAAaA,GAAO,cAAeA,EACxF,OAAOA,EAET,IAAM8C,GAAO9C,GAAA,YAAAA,EAAe,UAAW,iBACvC,OAAOsB,EAAU,UAAWwB,EAAK,CAAE,MAAO9C,CAAI,CAAC,CACjD,CAEA,SAASiC,GAAiBjC,EAAQE,EAAsB,CACtD,OAAIF,GAAO,OAAOA,GAAQ,WAAWA,EAA+B,UAAYE,GACzEF,CACT,CCvQA,IAAM+C,GAAW,2CASJC,EAAN,KAAuB,CAU5B,YAAYC,EAAmB,CAC7B,GAAI,CAACA,EAAI,OAAQ,MAAMC,EAAU,SAAU,sBAAuB,CAAE,UAAW,EAAM,CAAC,EACtF,KAAK,YAAcC,EAAAC,EAAA,GAAKH,GAAL,CAAU,QAASF,EAAS,GAC/C,KAAK,SAAW,IAAIM,EAAS,KAAK,WAAW,EAC7C,KAAK,oBAAsB,KAAK,YAAY,mBACxC,QAAQ,QAAQ,IAAI,EACpB,KAAK,SAAS,kBAAkB,EAAE,MAAM,IAAM,IAAI,CACxD,CAGA,OAAOC,EAAmBC,EAAsB,CAAC,EAA0B,CACzE,OAAO,KAAK,SAAS,OAAOD,EAAMC,CAAI,CACxC,CAQA,MAAM,WACJC,EACAD,EAA2B,CAAC,EACL,CA/D3B,IAAAE,EAAAC,EAAAC,EAgEI,GAAI,CAAC,MAAM,QAAQH,CAAK,GAAKA,EAAM,SAAW,EAAG,CAC/C,IAAMI,EAAMV,EAAU,aAAc,kDAAmD,CAAE,UAAW,EAAM,CAAC,EAC3G,MAAAO,EAAAF,EAAK,UAAL,MAAAE,EAAA,KAAAF,EAAeK,GACTA,CACR,CAEA,IAAMC,EAAuBL,EAAM,IAAIM,GACrC,KAAK,SAAS,SAASA,EAAG,CAAE,SAAUP,EAAK,SAAU,SAAUA,EAAK,QAAS,CAAC,CAChF,GACAG,EAAAH,EAAK,kBAAL,MAAAG,EAAA,KAAAH,EAAuBM,GAEvB,IAAME,EAAgC,CAAC,EACjCC,EAA+D,CAAC,EAItE,MAAM,QAAQ,IAAIR,EAAM,IAAI,MAAOM,EAAGG,IAAM,CAC1C,GAAI,CACF,IAAMC,EAAW,MAAM,KAAK,SAAS,OAAOJ,EAAGP,CAAI,EAEnDW,EAAS,SAAWL,EAAOI,CAAC,EAAE,SAC9BF,EAAc,KAAKG,CAAQ,CAC7B,OAASN,EAAK,CACZI,EAAY,KAAK,CAAE,KAAMH,EAAOI,CAAC,EAAG,MAAOL,CAAmB,CAAC,CACjE,CACF,CAAC,CAAC,EAEF,IAAMO,EAAuB,CAAE,cAAAJ,EAAe,YAAAC,CAAY,EAC1D,OAAAL,EAAAJ,EAAK,eAAL,MAAAI,EAAA,KAAAJ,EAAoBY,GACbA,CACT,CAMA,OAAOZ,EAAkD,CAAC,EAAqB,CAC7E,IAAIa,EAAgC,KAChCC,EAAS,GACTC,EACAC,EACEC,EAAc,IAAI,QAAsB,CAACC,EAAKC,IAAQ,CAC1DJ,EAAiBG,EAAKF,EAAgBG,CACxC,CAAC,EAED,MAAO,CACL,KAAM,SAAY,CAChB,GAAIL,EAAQ,OAAOG,EACnBH,EAAS,GACT,GAAI,CAEFD,GADY,KAAM,uCACP,WAAW,KAAMb,CAAI,EAChC,IAAMY,EAAS,MAAMC,EAAK,KAAK,EAC/B,OAAAE,EAAeH,CAAM,EACdA,CACT,OAASP,EAAK,CACZ,IAAMe,EAAKf,GAAA,MAAAA,EAAqB,KAC3BA,EACDV,EAAU,SAAU,yBAA0B,CAAE,UAAW,GAAO,MAAOU,CAAI,CAAC,EAClF,MAAAW,EAAcI,CAAC,EACTA,CACR,CACF,EACA,MAAO,IAAM,CAAEP,GAAA,MAAAA,EAAM,OAAS,EAC9B,OAAQ,IAAM,CAAEA,GAAA,MAAAA,EAAM,QAAU,CAClC,CACF,CAGA,IAAI,QAAyC,CAAE,OAAO,KAAK,WAAa,CAC1E,ECnIO,IAAMQ,EAAa,CACxB,KAAKC,EAAqC,CACxC,OAAO,IAAIC,EAAiBD,CAAG,CACjC,CACF,EJKAE,IAOA,IAAMC,GAAOC,EAAW,KAAK,KAAKA,CAAU,GAmB3C,UAAoB,CACnB,GAAI,OAAO,UAAa,YAAa,OACrC,IAAMC,EAAS,SAAS,cACxB,GAAI,CAACA,EAAQ,OACb,IAAMC,EAASD,EAAO,aAAa,qBAAqB,EACxD,GAAKC,EACL,GAAI,CACF,IAAMC,EAASC,EAAW,KAAK,CAAE,OAAAF,CAAO,CAAC,EACzC,eAAe,IAAM,CACf,OAAO,aAAY,OAAO,WAAW,OAASC,EACpD,CAAC,CACH,OAASE,EAAK,CACZ,QAAQ,MAAM,iCAAkCA,CAAG,CACrD,CACF,GAAG","names":["ensureStyles","STYLE_ID","el","BASE_CSS","themeToCssVars","theme","_a","_b","_c","_d","_e","_f","defaults","DARK_DEFAULTS","LIGHT_DEFAULTS","init_styles","__esmMin","mergeConfig","server","runtime","_a","_b","_c","_d","_e","_f","_g","_h","_i","_j","_k","_l","_m","_n","_o","_p","_q","_r","_s","_t","merged","__spreadValues","runtimeBranding","runtimeTheme","types","t","el","tag","className","text","node","formatBytes","n","cryptoId","openPicker","client","opts","picker","Picker","DEFAULT_TITLE","FOOTER_LINK","init_picker","__esmMin","init_styles","res","serverConfig","e","ensureStyles","root","themeToCssVars","k","v","panel","header","logo","title","body","actions","footer","dz","input","dropped","files","remaining","chosen","file","item","row","main","meta","progress","bar","status","state","queued","i","itemByUploadId","filesToUpload","__spreadProps","pickedFiles","p","idx","ev","f","err","r","result","fallback","picker_exports","__export","Picker","openPicker","init_picker","__esmMin","loader_exports","__export","Picker","UnionStackClient","init","openPicker","makeError","code","message","opts","_a","defaultRetryable","status","fromApiResponse","body","err","msg","isQuota","DEFAULT_CONCURRENCY","DEFAULT_MAX_RETRIES_PER_PART","BACKOFF_MS","Uploader","cfg","file","opts","isFile","filename","mimetype","cryptoRandomId","_a","_b","_c","picked","init","parts","completed","uploaded","__spreadProps","__spreadValues","rawErr","err","normalizeError","sessionId","totalParts","chunkSize","concurrency","maxRetries","urlByPart","p","results","loadedPerPart","cursor","totalBytes","reportProgress","loaded","a","b","totalPercent","ev","worker","_d","_e","makeError","partNumber","start","end","chunk","attempt","lastErr","url","res","etag","sleep","withSessionId","workers","e","method","path","body","signal","fetchImpl","cause","parsed","fromApiResponse","ms","r","msg","API_BASE","UnionStackClient","cfg","makeError","__spreadProps","__spreadValues","Uploader","file","opts","files","_a","_b","_c","err","picked","f","filesUploaded","filesFailed","i","uploaded","result","real","opened","pendingResolve","pendingReject","donePromise","res","rej","e","UnionStack","cfg","UnionStackClient","init_picker","init","UnionStack","script","apiKey","client","UnionStack","err"]}
@@ -206,7 +206,7 @@ var Uploader = class {
206
206
  }
207
207
  async api(method, path, body, signal) {
208
208
  const fetchImpl = this.cfg.fetch ?? fetch;
209
- const url = `${this.cfg.apiBase.replace(/\/$/, "")}${path}`;
209
+ const url = `${this.cfg.apiBase}${path}`;
210
210
  let res;
211
211
  try {
212
212
  res = await fetchImpl(url, {
@@ -255,13 +255,13 @@ function withSessionId(err, sessionId) {
255
255
  }
256
256
 
257
257
  // src/client.ts
258
+ var API_BASE = "https://cdn-api.mastersunion.org/cdn-api";
258
259
  var UnionStackClient = class {
259
260
  constructor(cfg) {
260
- this.cfg = cfg;
261
261
  if (!cfg.apiKey) throw makeError("CONFIG", "apiKey is required.", { retryable: false });
262
- if (!cfg.apiBase) throw makeError("CONFIG", "apiBase is required.", { retryable: false });
263
- this.uploader = new Uploader(cfg);
264
- this.pickerConfigPromise = cfg.skipConfigPrefetch ? Promise.resolve(null) : this.uploader.fetchPickerConfig().catch(() => null);
262
+ this.resolvedCfg = { ...cfg, apiBase: API_BASE };
263
+ this.uploader = new Uploader(this.resolvedCfg);
264
+ this.pickerConfigPromise = this.resolvedCfg.skipConfigPrefetch ? Promise.resolve(null) : this.uploader.fetchPickerConfig().catch(() => null);
265
265
  }
266
266
  /** Upload a single file. Mirrors Filestack's `client.upload()`. */
267
267
  upload(file, opts = {}) {
@@ -337,10 +337,10 @@ var UnionStackClient = class {
337
337
  }
338
338
  /** Read-only accessor used by the React/picker packages. */
339
339
  get config() {
340
- return this.cfg;
340
+ return this.resolvedCfg;
341
341
  }
342
342
  };
343
343
 
344
344
  exports.UnionStackClient = UnionStackClient;
345
- //# sourceMappingURL=chunk-QE2P5WH4.cjs.map
346
- //# sourceMappingURL=chunk-QE2P5WH4.cjs.map
345
+ //# sourceMappingURL=chunk-445C5G3Q.cjs.map
346
+ //# sourceMappingURL=chunk-445C5G3Q.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/errors.ts","../src/uploader.ts","../src/client.ts"],"names":[],"mappings":";;;AAEO,SAAS,SAAA,CACd,IAAA,EACA,OAAA,EACA,IAAA,GAAkE,EAAC,EACtD;AACb,EAAA,OAAO;AAAA,IACL,IAAA;AAAA,IACA,OAAA;AAAA,IACA,QAAQ,IAAA,CAAK,MAAA;AAAA,IACb,WAAW,IAAA,CAAK,SAAA,IAAa,gBAAA,CAAiB,IAAA,EAAM,KAAK,MAAM,CAAA;AAAA,IAC/D,OAAO,IAAA,CAAK;AAAA,GACd;AACF;AAEA,SAAS,gBAAA,CAAiB,MAAuB,MAAA,EAA0B;AACzE,EAAA,IAAI,IAAA,KAAS,SAAA,IAAa,IAAA,KAAS,aAAA,EAAe,OAAO,IAAA;AACzD,EAAA,IAAI,IAAA,KAAS,QAAA,IAAY,MAAA,IAAU,MAAA,IAAU,KAAK,OAAO,IAAA;AACzD,EAAA,OAAO,KAAA;AACT;AAGO,SAAS,eAAA,CAAgB,QAAgB,IAAA,EAA4B;AAC1E,EAAA,MAAM,MAAO,IAAA,EAAiE,KAAA;AAC9E,EAAA,MAAM,GAAA,GAAM,GAAA,EAAK,OAAA,IAAW,CAAA,2BAAA,EAA8B,MAAM,CAAA,CAAA;AAChE,EAAA,MAAM,IAAA,GAAA,CAAQ,GAAA,EAAK,IAAA,IAAQ,EAAA,EAAI,WAAA,EAAY;AAE3C,EAAA,IAAI,WAAW,GAAA,EAAK;AAClB,IAAA,OAAO,UAAU,MAAA,EAAQ,GAAA,EAAK,EAAE,MAAA,EAAQ,SAAA,EAAW,OAAO,CAAA;AAAA,EAC5D;AACA,EAAA,IAAI,WAAW,GAAA,EAAK;AAClB,IAAA,OAAO,UAAU,MAAA,EAAQ,GAAA,EAAK,EAAE,MAAA,EAAQ,SAAA,EAAW,OAAO,CAAA;AAAA,EAC5D;AACA,EAAA,IAAI,WAAW,GAAA,EAAK;AAClB,IAAA,OAAO,UAAU,YAAA,EAAc,GAAA,EAAK,EAAE,MAAA,EAAQ,SAAA,EAAW,OAAO,CAAA;AAAA,EAClE;AACA,EAAA,IAAI,WAAW,GAAA,EAAK;AAClB,IAAA,OAAO,UAAU,YAAA,EAAc,GAAA,EAAK,EAAE,MAAA,EAAQ,SAAA,EAAW,OAAO,CAAA;AAAA,EAClE;AACA,EAAA,IAAI,WAAW,GAAA,EAAK;AAClB,IAAA,MAAM,UAAU,IAAA,KAAS,gBAAA;AACzB,IAAA,OAAO,SAAA,CAAU,OAAA,GAAU,OAAA,GAAU,SAAA,EAAW,GAAA,EAAK,EAAE,MAAA,EAAQ,SAAA,EAAW,CAAC,OAAA,EAAS,CAAA;AAAA,EACtF;AACA,EAAA,IAAI,UAAU,GAAA,EAAK;AACjB,IAAA,OAAO,UAAU,QAAA,EAAU,GAAA,EAAK,EAAE,MAAA,EAAQ,SAAA,EAAW,MAAM,CAAA;AAAA,EAC7D;AACA,EAAA,OAAO,UAAU,QAAA,EAAU,GAAA,EAAK,EAAE,MAAA,EAAQ,SAAA,EAAW,OAAO,CAAA;AAC9D;;;ACbA,IAAM,mBAAA,GAAsB,CAAA;AAC5B,IAAM,4BAAA,GAA+B,CAAA;AAErC,IAAM,UAAA,GAAa,CAAC,GAAA,EAAK,IAAA,EAAM,IAAI,CAAA;AAE5B,IAAM,WAAN,MAAe;AAAA,EACpB,YAAoB,GAAA,EAA2B;AAA3B,IAAA,IAAA,CAAA,GAAA,GAAA,GAAA;AAAA,EAA4B;AAAA;AAAA,EAGhD,QAAA,CAAS,IAAA,EAAmB,IAAA,GAAiD,EAAC,EAAe;AAC3F,IAAA,MAAM,MAAA,GAAS,OAAO,IAAA,KAAS,WAAA,IAAe,IAAA,YAAgB,IAAA;AAC9D,IAAA,MAAM,QAAA,GACJ,IAAA,CAAK,QAAA,KACJ,MAAA,GAAU,KAAc,IAAA,GAAO,UAAA,CAAA;AAClC,IAAA,MAAM,QAAA,GACJ,IAAA,CAAK,QAAA,IAAa,IAAA,CAAc,IAAA,IAAQ,0BAAA;AAC1C,IAAA,OAAO;AAAA,MACL,UAAU,cAAA,EAAe;AAAA,MACzB,QAAA;AAAA,MACA,QAAA;AAAA,MACA,MAAM,IAAA,CAAK,IAAA;AAAA,MACX,MAAA,EAAQ;AAAA,KACV;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,MAAA,CAAO,IAAA,EAAmB,IAAA,GAAsB,EAAC,EAA0B;AAC/E,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,QAAA,CAAS,IAAA,EAAM,EAAE,QAAA,EAAU,IAAA,CAAK,QAAA,EAAU,QAAA,EAAU,IAAA,CAAK,QAAA,EAAU,CAAA;AACvF,IAAA,IAAA,CAAK,sBAAsB,MAAM,CAAA;AAEjC,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,UAAA,CAAW,QAAQ,IAAI,CAAA;AAC/C,MAAA,MAAM,QAAQ,MAAM,IAAA,CAAK,eAAe,IAAA,EAAM,IAAA,EAAM,QAAQ,IAAI,CAAA;AAChE,MAAA,MAAM,YAAY,MAAM,IAAA,CAAK,eAAe,IAAA,CAAK,SAAA,EAAW,OAAO,IAAI,CAAA;AAEvE,MAAA,MAAM,QAAA,GAAyB;AAAA,QAC7B,GAAG,MAAA;AAAA,QACH,QAAQ,SAAA,CAAU,MAAA;AAAA,QAClB,QAAQ,SAAA,CAAU,MAAA;AAAA,QAClB,KAAK,SAAA,CAAU,GAAA;AAAA,QACf,MAAM,SAAA,CAAU,IAAA;AAAA,QAChB,UAAU,SAAA,CAAU,QAAA;AAAA,QACpB,UAAU,SAAA,CAAU,QAAA;AAAA,QACpB,MAAA,EAAQ,QAAA;AAAA,QACR,MAAM,SAAA,CAAU;AAAA,OAClB;AACA,MAAA,IAAA,CAAK,uBAAuB,QAAQ,CAAA;AACpC,MAAA,OAAO,QAAA;AAAA,IACT,SAAS,MAAA,EAAQ;AACf,MAAA,MAAM,GAAA,GAAM,eAAe,MAAM,CAAA;AACjC,MAAA,IAAA,CAAK,kBAAA,GAAqB,QAAQ,GAAG,CAAA;AAErC,MAAA,IAAK,QAAmC,SAAA,EAAW;AACjD,QAAA,IAAA,CAAK,aAAA,CAAe,MAAA,CAAiC,SAAS,CAAA,CAAE,MAAM,MAAM;AAAA,QAAC,CAAC,CAAA;AAAA,MAChF;AACA,MAAA,MAAM,GAAA;AAAA,IACR;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,MAAM,SAAA,EAAkC;AAC5C,IAAA,MAAM,KAAK,GAAA,CAAI,MAAA,EAAQ,uBAAA,EAAyB,EAAE,WAAW,CAAA;AAAA,EAC/D;AAAA;AAAA,EAGA,MAAM,iBAAA,GAA2C;AAC/C,IAAA,OAAO,IAAA,CAAK,GAAA,CAAkB,KAAA,EAAO,uBAAuB,CAAA;AAAA,EAC9D;AAAA,EAEA,MAAc,UAAA,CAAW,MAAA,EAAoB,IAAA,EAA4C;AACvF,IAAA,OAAO,IAAA,CAAK,GAAA,CAAkB,MAAA,EAAQ,sBAAA,EAAwB;AAAA,MAC5D,UAAU,MAAA,CAAO,QAAA;AAAA,MACjB,UAAU,MAAA,CAAO,QAAA;AAAA,MACjB,MAAM,MAAA,CAAO,IAAA;AAAA,MACb,UAAU,IAAA,CAAK;AAAA,KACjB,EAAG,KAAK,MAAM,CAAA;AAAA,EAChB;AAAA,EAEA,MAAc,cAAA,CACZ,IAAA,EACA,IAAA,EACA,QACA,IAAA,EACuB;AACvB,IAAA,MAAM,aAAa,IAAA,CAAK,UAAA;AACxB,IAAA,MAAM,YAAY,IAAA,CAAK,SAAA;AACvB,IAAA,MAAM,cAAc,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,eAAe,mBAAmB,CAAA;AACvE,IAAA,MAAM,UAAA,GAAa,KAAK,iBAAA,IAAqB,4BAAA;AAG7C,IAAA,MAAM,SAAA,GAAY,IAAI,GAAA,CAAI,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,CAAA,CAAA,KAAK,CAAC,CAAA,CAAE,UAAA,EAAY,CAAA,CAAE,GAAG,CAAU,CAAC,CAAA;AAEhF,IAAA,MAAM,OAAA,GAAwB,IAAI,KAAA,CAAM,UAAU,CAAA;AAClD,IAAA,MAAM,gBAA0B,IAAI,KAAA,CAAM,UAAU,CAAA,CAAE,KAAK,CAAC,CAAA;AAC5D,IAAA,IAAI,MAAA,GAAS,CAAA;AAEb,IAAA,MAAM,aAAa,IAAA,CAAK,IAAA;AAExB,IAAA,MAAM,iBAAiB,MAAM;AAC3B,MAAA,MAAM,MAAA,GAAS,cAAc,MAAA,CAAO,CAAC,GAAG,CAAA,KAAM,CAAA,GAAI,GAAG,CAAC,CAAA;AACtD,MAAA,MAAM,YAAA,GAAe,UAAA,GAAa,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,GAAA,EAAK,IAAA,CAAK,KAAA,CAAO,MAAA,GAAS,UAAA,GAAc,GAAG,CAAC,CAAA,GAAI,GAAA;AAC/F,MAAA,MAAM,EAAA,GAAsB,EAAE,UAAA,EAAY,MAAA,EAAQ,YAAA,EAAa;AAC/D,MAAA,IAAA,CAAK,oBAAA,GAAuB,QAAQ,EAAE,CAAA;AAAA,IACxC,CAAA;AAEA,IAAA,MAAM,SAAS,YAA2B;AACxC,MAAA,OAAO,IAAA,EAAM;AACX,QAAA,IAAI,IAAA,CAAK,QAAQ,OAAA,EAAS;AACxB,UAAA,MAAM,UAAU,SAAA,EAAW,2BAAA,EAA6B,EAAE,SAAA,EAAW,OAAO,CAAA;AAAA,QAC9E;AACA,QAAA,MAAM,UAAA,GAAa,MAAA,EAAA;AACnB,QAAA,IAAI,aAAa,UAAA,EAAY;AAE7B,QAAA,MAAM,KAAA,GAAA,CAAS,aAAa,CAAA,IAAK,SAAA;AACjC,QAAA,MAAM,MAAM,IAAA,CAAK,GAAA,CAAI,KAAA,GAAQ,SAAA,EAAW,KAAK,IAAI,CAAA;AACjD,QAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,KAAA,EAAO,GAAG,CAAA;AAEnC,QAAA,IAAI,OAAA,GAAU,CAAA;AACd,QAAA,IAAI,OAAA;AACJ,QAAA,OAAO,WAAW,UAAA,EAAY;AAC5B,UAAA,IAAI,IAAA,CAAK,QAAQ,OAAA,EAAS;AACxB,YAAA,MAAM,UAAU,SAAA,EAAW,2BAAA,EAA6B,EAAE,SAAA,EAAW,OAAO,CAAA;AAAA,UAC9E;AACA,UAAA,IAAI;AACF,YAAA,IAAI,GAAA,GAAM,SAAA,CAAU,GAAA,CAAI,UAAU,CAAA;AAClC,YAAA,IAAI,CAAC,GAAA,EAAK;AACR,cAAA,MAAM,SAAA,GAAY,MAAM,IAAA,CAAK,GAAA;AAAA,gBAC3B,MAAA;AAAA,gBAAQ,2BAAA;AAAA,gBACR,EAAE,SAAA,EAAW,IAAA,CAAK,SAAA,EAAW,UAAA,EAAW;AAAA,gBAAG,IAAA,CAAK;AAAA,eAClD;AACA,cAAA,GAAA,GAAM,SAAA,CAAU,GAAA;AAChB,cAAA,SAAA,CAAU,GAAA,CAAI,YAAY,GAAG,CAAA;AAAA,YAC/B;AAEA,YAAA,MAAM,GAAA,GAAM,MAAM,IAAA,CAAK,GAAA,CAAI,QAAQ,GAAA,EAAK;AAAA,cACtC,MAAA,EAAQ,KAAA;AAAA,cACR,IAAA,EAAM,KAAA;AAAA,cACN,QAAQ,IAAA,CAAK;AAAA,aACd,CAAA,IAAK,MAAM,KAAA,CAAM,GAAA,EAAK,EAAE,MAAA,EAAQ,KAAA,EAAO,IAAA,EAAM,KAAA,EAAO,MAAA,EAAQ,IAAA,CAAK,QAAQ,CAAA;AAE1E,YAAA,IAAI,CAAC,IAAI,EAAA,EAAI;AAGX,cAAA,IAAI,GAAA,CAAI,WAAW,GAAA,IAAO,GAAA,CAAI,WAAW,GAAA,EAAK,SAAA,CAAU,OAAO,UAAU,CAAA;AACzE,cAAA,MAAM,SAAA,CAAU,aAAA,EAAe,CAAA,KAAA,EAAQ,UAAU,CAAA,kBAAA,EAAqB,GAAA,CAAI,MAAM,CAAA,CAAA,CAAA,EAAK,EAAE,MAAA,EAAQ,GAAA,CAAI,MAAA,EAAQ,CAAA;AAAA,YAC7G;AACA,YAAA,MAAM,IAAA,GAAO,GAAA,CAAI,OAAA,CAAQ,GAAA,CAAI,MAAM,CAAA;AACnC,YAAA,IAAI,CAAC,IAAA,EAAM;AACT,cAAA,MAAM,SAAA,CAAU,aAAA,EAAe,CAAA,KAAA,EAAQ,UAAU,CAAA,4BAAA,CAA8B,CAAA;AAAA,YACjF;AAEA,YAAA,OAAA,CAAQ,UAAA,GAAa,CAAC,CAAA,GAAI,EAAE,YAAY,IAAA,EAAM,IAAA,EAAM,MAAM,IAAA,EAAK;AAC/D,YAAA,aAAA,CAAc,UAAA,GAAa,CAAC,CAAA,GAAI,KAAA,CAAM,IAAA;AACtC,YAAA,cAAA,EAAe;AACf,YAAA;AAAA,UACF,SAAS,GAAA,EAAK;AACZ,YAAA,OAAA,GAAU,GAAA;AACV,YAAA,OAAA,EAAA;AACA,YAAA,IAAI,UAAU,UAAA,EAAY;AAC1B,YAAA,MAAM,KAAA,CAAM,UAAA,CAAW,IAAA,CAAK,GAAA,CAAI,OAAA,GAAU,GAAG,UAAA,CAAW,MAAA,GAAS,CAAC,CAAC,CAAC,CAAA;AAAA,UACtE;AAAA,QACF;AACA,QAAA,IAAI,CAAC,OAAA,CAAQ,UAAA,GAAa,CAAC,CAAA,EAAG;AAC5B,UAAA,MAAM,aAAA;AAAA,YACJ,cAAA,CAAe,WAAW,SAAA,CAAU,aAAA,EAAe,QAAQ,UAAU,CAAA,cAAA,EAAiB,UAAU,CAAA,SAAA,CAAW,CAAC,CAAA;AAAA,YAC5G,IAAA,CAAK;AAAA,WACP;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAA;AAEA,IAAA,MAAM,OAAA,GAAU,KAAA,CAAM,IAAA,CAAK,EAAE,MAAA,EAAQ,IAAA,CAAK,GAAA,CAAI,WAAA,EAAa,UAAU,CAAA,EAAE,EAAG,MAAM,CAAA;AAChF,IAAA,MAAM,OAAA,CAAQ,IAAI,OAAO,CAAA;AACzB,IAAA,OAAO,OAAA;AAAA,EACT;AAAA,EAEA,MAAc,cAAA,CACZ,SAAA,EACA,KAAA,EACA,IAAA,EAC2B;AAC3B,IAAA,OAAO,IAAA,CAAK,GAAA,CAAsB,MAAA,EAAQ,0BAAA,EAA4B;AAAA,MACpE,SAAA;AAAA,MACA,KAAA,EAAO,KAAA,CAAM,GAAA,CAAI,CAAA,CAAA,MAAM,EAAE,UAAA,EAAY,CAAA,CAAE,UAAA,EAAY,IAAA,EAAM,CAAA,CAAE,IAAA,EAAK,CAAE;AAAA,KACpE,EAAG,KAAK,MAAM,CAAA;AAAA,EAChB;AAAA,EAEA,MAAc,cAAc,SAAA,EAAkC;AAC5D,IAAA,IAAI;AAAE,MAAA,MAAM,IAAA,CAAK,MAAM,SAAS,CAAA;AAAA,IAAG,CAAA,CAAA,MAAQ;AAAA,IAAe;AAAA,EAC5D;AAAA,EAEA,MAAc,GAAA,CACZ,MAAA,EACA,IAAA,EACA,MACA,MAAA,EACY;AACZ,IAAA,MAAM,SAAA,GAAY,IAAA,CAAK,GAAA,CAAI,KAAA,IAAS,KAAA;AACpC,IAAA,MAAM,MAAM,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,OAAO,GAAG,IAAI,CAAA,CAAA;AACtC,IAAA,IAAI,GAAA;AACJ,IAAA,IAAI;AACF,MAAA,GAAA,GAAM,MAAM,UAAU,GAAA,EAAK;AAAA,QACzB,MAAA;AAAA,QACA,OAAA,EAAS;AAAA,UACP,aAAA,EAAe,CAAA,OAAA,EAAU,IAAA,CAAK,GAAA,CAAI,MAAM,CAAA,CAAA;AAAA,UACxC,cAAA,EAAgB;AAAA,SAClB;AAAA,QACA,MAAM,IAAA,KAAS,KAAA,CAAA,GAAY,KAAA,CAAA,GAAY,IAAA,CAAK,UAAU,IAAI,CAAA;AAAA,QAC1D;AAAA,OACD,CAAA;AAAA,IACH,SAAS,KAAA,EAAO;AACd,MAAA,IAAK,KAAA,EAAiB,SAAS,YAAA,EAAc;AAC3C,QAAA,MAAM,UAAU,SAAA,EAAW,kBAAA,EAAoB,EAAE,SAAA,EAAW,KAAA,EAAO,OAAO,CAAA;AAAA,MAC5E;AACA,MAAA,MAAM,UAAU,SAAA,EAAW,yBAAA,EAA2B,EAAE,SAAA,EAAW,IAAA,EAAM,OAAO,CAAA;AAAA,IAClF;AACA,IAAA,IAAI,MAAA,GAAkB,IAAA;AACtB,IAAA,IAAI;AAAE,MAAA,MAAA,GAAS,MAAM,IAAI,IAAA,EAAK;AAAA,IAAG,CAAA,CAAA,MAAQ;AAAA,IAA4B;AACrE,IAAA,IAAI,CAAC,GAAA,CAAI,EAAA,QAAU,eAAA,CAAgB,GAAA,CAAI,QAAQ,MAAM,CAAA;AACrD,IAAA,OAAO,MAAA;AAAA,EACT;AACF,CAAA;AAEA,SAAS,cAAA,GAAyB;AAEhC,EAAA,IAAI,OAAO,MAAA,KAAW,WAAA,IAAe,YAAA,IAAgB,MAAA,EAAQ;AAC3D,IAAA,OAAQ,MAAA,CAAwC,UAAA,EAAW,CAAE,OAAA,CAAQ,MAAM,EAAE,CAAA;AAAA,EAC/E;AACA,EAAA,OAAO,IAAA,CAAK,MAAA,EAAO,CAAE,QAAA,CAAS,EAAE,CAAA,CAAE,KAAA,CAAM,CAAC,CAAA,GAAI,IAAA,CAAK,GAAA,EAAI,CAAE,SAAS,EAAE,CAAA;AACrE;AAEA,SAAS,MAAM,EAAA,EAA2B;AACxC,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAA,CAAA,KAAK,UAAA,CAAW,CAAA,EAAG,EAAE,CAAC,CAAA;AAC3C;AAEA,SAAS,eAAe,GAAA,EAA4C;AAClE,EAAA,IAAI,GAAA,IAAO,OAAO,GAAA,KAAQ,QAAA,IAAY,UAAU,GAAA,IAAO,SAAA,IAAa,GAAA,IAAO,WAAA,IAAe,GAAA,EAAK;AAC7F,IAAA,OAAO,GAAA;AAAA,EACT;AACA,EAAA,MAAM,GAAA,GAAO,KAAe,OAAA,IAAW,gBAAA;AACvC,EAAA,OAAO,UAAU,SAAA,EAAW,GAAA,EAAK,EAAE,KAAA,EAAO,KAAK,CAAA;AACjD;AAEA,SAAS,aAAA,CAAiB,KAAQ,SAAA,EAAsB;AACtD,EAAA,IAAI,OAAO,OAAO,GAAA,KAAQ,QAAA,EAAW,IAA+B,SAAA,GAAY,SAAA;AAChF,EAAA,OAAO,GAAA;AACT;;;ACvQA,IAAM,QAAA,GAAW,0CAAA;AASV,IAAM,mBAAN,MAAuB;AAAA,EAU5B,YAAY,GAAA,EAAmB;AAC7B,IAAA,IAAI,CAAC,GAAA,CAAI,MAAA,EAAQ,MAAM,SAAA,CAAU,UAAU,qBAAA,EAAuB,EAAE,SAAA,EAAW,KAAA,EAAO,CAAA;AACtF,IAAA,IAAA,CAAK,WAAA,GAAc,EAAE,GAAG,GAAA,EAAK,SAAS,QAAA,EAAS;AAC/C,IAAA,IAAA,CAAK,QAAA,GAAW,IAAI,QAAA,CAAS,IAAA,CAAK,WAAW,CAAA;AAC7C,IAAA,IAAA,CAAK,mBAAA,GAAsB,IAAA,CAAK,WAAA,CAAY,kBAAA,GACxC,QAAQ,OAAA,CAAQ,IAAI,CAAA,GACpB,IAAA,CAAK,QAAA,CAAS,iBAAA,EAAkB,CAAE,KAAA,CAAM,MAAM,IAAI,CAAA;AAAA,EACxD;AAAA;AAAA,EAGA,MAAA,CAAO,IAAA,EAAmB,IAAA,GAAsB,EAAC,EAA0B;AACzE,IAAA,OAAO,IAAA,CAAK,QAAA,CAAS,MAAA,CAAO,IAAA,EAAM,IAAI,CAAA;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,UAAA,CACJ,KAAA,EACA,IAAA,GAA2B,EAAC,EACL;AACvB,IAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,IAAK,KAAA,CAAM,WAAW,CAAA,EAAG;AAC/C,MAAA,MAAM,MAAM,SAAA,CAAU,YAAA,EAAc,mDAAmD,EAAE,SAAA,EAAW,OAAO,CAAA;AAC3G,MAAA,IAAA,CAAK,UAAU,GAAG,CAAA;AAClB,MAAA,MAAM,GAAA;AAAA,IACR;AAEA,IAAA,MAAM,SAAuB,KAAA,CAAM,GAAA;AAAA,MAAI,CAAA,CAAA,KACrC,IAAA,CAAK,QAAA,CAAS,QAAA,CAAS,CAAA,EAAG,EAAE,QAAA,EAAU,IAAA,CAAK,QAAA,EAAU,QAAA,EAAU,IAAA,CAAK,QAAA,EAAU;AAAA,KAChF;AACA,IAAA,IAAA,CAAK,kBAAkB,MAAM,CAAA;AAE7B,IAAA,MAAM,gBAAgC,EAAC;AACvC,IAAA,MAAM,cAA+D,EAAC;AAItE,IAAA,MAAM,QAAQ,GAAA,CAAI,KAAA,CAAM,GAAA,CAAI,OAAO,GAAG,CAAA,KAAM;AAC1C,MAAA,IAAI;AACF,QAAA,MAAM,WAAW,MAAM,IAAA,CAAK,QAAA,CAAS,MAAA,CAAO,GAAG,IAAI,CAAA;AAEnD,QAAA,QAAA,CAAS,QAAA,GAAW,MAAA,CAAO,CAAC,CAAA,CAAE,QAAA;AAC9B,QAAA,aAAA,CAAc,KAAK,QAAQ,CAAA;AAAA,MAC7B,SAAS,GAAA,EAAK;AACZ,QAAA,WAAA,CAAY,IAAA,CAAK,EAAE,IAAA,EAAM,MAAA,CAAO,CAAC,CAAA,EAAG,KAAA,EAAO,KAAoB,CAAA;AAAA,MACjE;AAAA,IACF,CAAC,CAAC,CAAA;AAEF,IAAA,MAAM,MAAA,GAAuB,EAAE,aAAA,EAAe,WAAA,EAAY;AAC1D,IAAA,IAAA,CAAK,eAAe,MAAM,CAAA;AAC1B,IAAA,OAAO,MAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAA,CAAO,IAAA,GAAkD,EAAC,EAAqB;AAC7E,IAAA,IAAI,IAAA,GAAgC,IAAA;AACpC,IAAA,IAAI,MAAA,GAAS,KAAA;AACb,IAAA,IAAI,cAAA;AACJ,IAAA,IAAI,aAAA;AACJ,IAAA,MAAM,WAAA,GAAc,IAAI,OAAA,CAAsB,CAAC,KAAK,GAAA,KAAQ;AAC1D,MAAA,cAAA,GAAiB,GAAA;AAAK,MAAA,aAAA,GAAgB,GAAA;AAAA,IACxC,CAAC,CAAA;AAED,IAAA,OAAO;AAAA,MACL,MAAM,YAAY;AAChB,QAAA,IAAI,QAAQ,OAAO,WAAA;AACnB,QAAA,MAAA,GAAS,IAAA;AACT,QAAA,IAAI;AACF,UAAA,MAAM,GAAA,GAAM,MAAM,OAAO,cAAmB,CAAA;AAC5C,UAAA,IAAA,GAAO,GAAA,CAAI,UAAA,CAAW,IAAA,EAAM,IAAI,CAAA;AAChC,UAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,IAAA,EAAK;AAC/B,UAAA,cAAA,CAAe,MAAM,CAAA;AACrB,UAAA,OAAO,MAAA;AAAA,QACT,SAAS,GAAA,EAAK;AACZ,UAAA,MAAM,CAAA,GAAK,GAAA,EAAqB,IAAA,GAC3B,GAAA,GACD,SAAA,CAAU,QAAA,EAAU,wBAAA,EAA0B,EAAE,SAAA,EAAW,KAAA,EAAO,KAAA,EAAO,GAAA,EAAK,CAAA;AAClF,UAAA,aAAA,CAAc,CAAC,CAAA;AACf,UAAA,MAAM,CAAA;AAAA,QACR;AAAA,MACF,CAAA;AAAA,MACA,OAAO,MAAM;AAAE,QAAA,IAAA,EAAM,KAAA,EAAM;AAAA,MAAG,CAAA;AAAA,MAC9B,QAAQ,MAAM;AAAE,QAAA,IAAA,EAAM,MAAA,EAAO;AAAA,MAAG;AAAA,KAClC;AAAA,EACF;AAAA;AAAA,EAGA,IAAI,MAAA,GAAyC;AAAE,IAAA,OAAO,IAAA,CAAK,WAAA;AAAA,EAAa;AAC1E","file":"chunk-445C5G3Q.cjs","sourcesContent":["import type { UploadError, UploadErrorCode } from './types.js';\n\nexport function makeError(\n code: UploadErrorCode,\n message: string,\n opts: { status?: number; retryable?: boolean; cause?: unknown } = {}\n): UploadError {\n return {\n code,\n message,\n status: opts.status,\n retryable: opts.retryable ?? defaultRetryable(code, opts.status),\n cause: opts.cause,\n };\n}\n\nfunction defaultRetryable(code: UploadErrorCode, status?: number): boolean {\n if (code === 'NETWORK' || code === 'PART_FAILED') return true;\n if (code === 'SERVER' && status && status >= 500) return true;\n return false;\n}\n\n/** Map an HTTP error response from the cdn-be API to an UploadError. */\nexport function fromApiResponse(status: number, body: unknown): UploadError {\n const err = (body as { error?: { code?: string; message?: string } } | null)?.error;\n const msg = err?.message || `Request failed with status ${status}`;\n const code = (err?.code || '').toUpperCase();\n\n if (status === 401) {\n return makeError('AUTH', msg, { status, retryable: false });\n }\n if (status === 403) {\n return makeError('AUTH', msg, { status, retryable: false });\n }\n if (status === 413) {\n return makeError('VALIDATION', msg, { status, retryable: false });\n }\n if (status === 415) {\n return makeError('VALIDATION', msg, { status, retryable: false });\n }\n if (status === 429) {\n const isQuota = code === 'QUOTA_EXCEEDED';\n return makeError(isQuota ? 'QUOTA' : 'NETWORK', msg, { status, retryable: !isQuota });\n }\n if (status >= 500) {\n return makeError('SERVER', msg, { status, retryable: true });\n }\n return makeError('SERVER', msg, { status, retryable: false });\n}\n","import type {\n ResolvedClientConfig,\n PickedFile,\n PickerConfig,\n UploadedFile,\n UploadOptions,\n ProgressEvent as USProgressEvent,\n} from './types.js';\nimport { fromApiResponse, makeError } from './errors.js';\n\ninterface InitResponse {\n sessionId: string;\n fileId: string;\n chunkSize: number;\n totalParts: number;\n partUrls: Array<{ partNumber: number; url: string }>;\n expiresAt: string;\n}\n\ninterface CompleteResponse {\n handle: string;\n fileId: string;\n url: string;\n filename: string;\n mimetype: string;\n size: number;\n etag?: string;\n}\n\ninterface PartResult {\n partNumber: number;\n etag: string;\n size: number;\n}\n\nconst DEFAULT_CONCURRENCY = 3;\nconst DEFAULT_MAX_RETRIES_PER_PART = 3;\n// Backoff schedule between part retries. Capped — past this we surrender.\nconst BACKOFF_MS = [400, 1200, 3600];\n\nexport class Uploader {\n constructor(private cfg: ResolvedClientConfig) {}\n\n /** Returns a stable PickedFile descriptor for the input blob/file. */\n describe(file: File | Blob, opts: { filename?: string; mimeType?: string } = {}): PickedFile {\n const isFile = typeof File !== 'undefined' && file instanceof File;\n const filename =\n opts.filename ||\n (isFile ? (file as File).name : 'untitled');\n const mimetype =\n opts.mimeType || (file as Blob).type || 'application/octet-stream';\n return {\n uploadId: cryptoRandomId(),\n filename,\n mimetype,\n size: file.size,\n source: 'local',\n };\n }\n\n /**\n * Upload a single Blob/File. Returns the persisted UploadedFile.\n * Fires Filestack-style per-file callbacks from `opts`.\n */\n async upload(file: File | Blob, opts: UploadOptions = {}): Promise<UploadedFile> {\n const picked = this.describe(file, { filename: opts.filename, mimeType: opts.mimeType });\n opts.onFileUploadStarted?.(picked);\n\n try {\n const init = await this.initUpload(picked, opts);\n const parts = await this.uploadAllParts(file, init, picked, opts);\n const completed = await this.completeUpload(init.sessionId, parts, opts);\n\n const uploaded: UploadedFile = {\n ...picked,\n handle: completed.handle,\n fileId: completed.fileId,\n url: completed.url,\n size: completed.size,\n mimetype: completed.mimetype,\n filename: completed.filename,\n status: 'Stored',\n etag: completed.etag,\n };\n opts.onFileUploadFinished?.(uploaded);\n return uploaded;\n } catch (rawErr) {\n const err = normalizeError(rawErr);\n opts.onFileUploadFailed?.(picked, err);\n // Best effort: tell the server to clean up the multipart, but ignore failures.\n if ((rawErr as { sessionId?: string })?.sessionId) {\n this.abortSilently((rawErr as { sessionId: string }).sessionId).catch(() => {});\n }\n throw err;\n }\n }\n\n /** Cancel an in-flight session server-side. */\n async abort(sessionId: string): Promise<void> {\n await this.api('POST', '/sdk/v1/uploads/abort', { sessionId });\n }\n\n /** Fetch the server-managed picker config (branding, theme, constraints). */\n async fetchPickerConfig(): Promise<PickerConfig> {\n return this.api<PickerConfig>('GET', '/sdk/v1/picker-config');\n }\n\n private async initUpload(picked: PickedFile, opts: UploadOptions): Promise<InitResponse> {\n return this.api<InitResponse>('POST', '/sdk/v1/uploads/init', {\n filename: picked.filename,\n mimeType: picked.mimetype,\n size: picked.size,\n metadata: opts.metadata,\n }, opts.signal);\n }\n\n private async uploadAllParts(\n file: File | Blob,\n init: InitResponse,\n picked: PickedFile,\n opts: UploadOptions,\n ): Promise<PartResult[]> {\n const totalParts = init.totalParts;\n const chunkSize = init.chunkSize;\n const concurrency = Math.max(1, opts.concurrency ?? DEFAULT_CONCURRENCY);\n const maxRetries = opts.maxRetriesPerPart ?? DEFAULT_MAX_RETRIES_PER_PART;\n\n // Quick lookup: partNumber → presigned URL.\n const urlByPart = new Map(init.partUrls.map(p => [p.partNumber, p.url] as const));\n\n const results: PartResult[] = new Array(totalParts);\n const loadedPerPart: number[] = new Array(totalParts).fill(0);\n let cursor = 1;\n\n const totalBytes = file.size;\n\n const reportProgress = () => {\n const loaded = loadedPerPart.reduce((a, b) => a + b, 0);\n const totalPercent = totalBytes > 0 ? Math.min(100, Math.round((loaded / totalBytes) * 100)) : 100;\n const ev: USProgressEvent = { totalBytes, loaded, totalPercent };\n opts.onFileUploadProgress?.(picked, ev);\n };\n\n const worker = async (): Promise<void> => {\n while (true) {\n if (opts.signal?.aborted) {\n throw makeError('ABORTED', 'Upload aborted by caller.', { retryable: false });\n }\n const partNumber = cursor++;\n if (partNumber > totalParts) return;\n\n const start = (partNumber - 1) * chunkSize;\n const end = Math.min(start + chunkSize, file.size);\n const chunk = file.slice(start, end);\n\n let attempt = 0;\n let lastErr: unknown;\n while (attempt <= maxRetries) {\n if (opts.signal?.aborted) {\n throw makeError('ABORTED', 'Upload aborted by caller.', { retryable: false });\n }\n try {\n let url = urlByPart.get(partNumber);\n if (!url) {\n const refreshed = await this.api<{ url: string }>(\n 'POST', '/sdk/v1/uploads/sign-part',\n { sessionId: init.sessionId, partNumber }, opts.signal,\n );\n url = refreshed.url;\n urlByPart.set(partNumber, url);\n }\n\n const res = await this.cfg.fetch?.(url, {\n method: 'PUT',\n body: chunk,\n signal: opts.signal,\n }) ?? await fetch(url, { method: 'PUT', body: chunk, signal: opts.signal });\n\n if (!res.ok) {\n // If R2 rejects with 403 the URL likely expired — drop it so the\n // next attempt re-signs.\n if (res.status === 403 || res.status === 401) urlByPart.delete(partNumber);\n throw makeError('PART_FAILED', `Part ${partNumber} PUT failed (HTTP ${res.status})`, { status: res.status });\n }\n const etag = res.headers.get('etag');\n if (!etag) {\n throw makeError('PART_FAILED', `Part ${partNumber}: R2 did not return an ETag.`);\n }\n\n results[partNumber - 1] = { partNumber, etag, size: chunk.size };\n loadedPerPart[partNumber - 1] = chunk.size;\n reportProgress();\n break;\n } catch (err) {\n lastErr = err;\n attempt++;\n if (attempt > maxRetries) break;\n await sleep(BACKOFF_MS[Math.min(attempt - 1, BACKOFF_MS.length - 1)]);\n }\n }\n if (!results[partNumber - 1]) {\n throw withSessionId(\n normalizeError(lastErr ?? makeError('PART_FAILED', `Part ${partNumber} failed after ${maxRetries} retries.`)),\n init.sessionId,\n );\n }\n }\n };\n\n const workers = Array.from({ length: Math.min(concurrency, totalParts) }, worker);\n await Promise.all(workers);\n return results;\n }\n\n private async completeUpload(\n sessionId: string,\n parts: PartResult[],\n opts: UploadOptions,\n ): Promise<CompleteResponse> {\n return this.api<CompleteResponse>('POST', '/sdk/v1/uploads/complete', {\n sessionId,\n parts: parts.map(p => ({ partNumber: p.partNumber, etag: p.etag })),\n }, opts.signal);\n }\n\n private async abortSilently(sessionId: string): Promise<void> {\n try { await this.abort(sessionId); } catch { /* ignore */ }\n }\n\n private async api<T>(\n method: 'GET' | 'POST' | 'DELETE',\n path: string,\n body?: unknown,\n signal?: AbortSignal,\n ): Promise<T> {\n const fetchImpl = this.cfg.fetch ?? fetch;\n const url = `${this.cfg.apiBase}${path}`;\n let res: Response;\n try {\n res = await fetchImpl(url, {\n method,\n headers: {\n Authorization: `Bearer ${this.cfg.apiKey}`,\n 'Content-Type': 'application/json',\n },\n body: body === undefined ? undefined : JSON.stringify(body),\n signal,\n });\n } catch (cause) {\n if ((cause as Error)?.name === 'AbortError') {\n throw makeError('ABORTED', 'Request aborted.', { retryable: false, cause });\n }\n throw makeError('NETWORK', 'Network request failed.', { retryable: true, cause });\n }\n let parsed: unknown = null;\n try { parsed = await res.json(); } catch { /* tolerate empty body */ }\n if (!res.ok) throw fromApiResponse(res.status, parsed);\n return parsed as T;\n }\n}\n\nfunction cryptoRandomId(): string {\n // Cheap unique id for client-side uploadId. Not security-sensitive.\n if (typeof crypto !== 'undefined' && 'randomUUID' in crypto) {\n return (crypto as { randomUUID: () => string }).randomUUID().replace(/-/g, '');\n }\n return Math.random().toString(36).slice(2) + Date.now().toString(36);\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise(r => setTimeout(r, ms));\n}\n\nfunction normalizeError(err: unknown): ReturnType<typeof makeError> {\n if (err && typeof err === 'object' && 'code' in err && 'message' in err && 'retryable' in err) {\n return err as ReturnType<typeof makeError>;\n }\n const msg = (err as Error)?.message || 'Upload failed.';\n return makeError('NETWORK', msg, { cause: err });\n}\n\nfunction withSessionId<T>(err: T, sessionId: string): T {\n if (err && typeof err === 'object') (err as { sessionId?: string }).sessionId = sessionId;\n return err;\n}\n","import type {\n ClientConfig,\n ResolvedClientConfig,\n UploadOptions,\n BatchUploadOptions,\n UploadedFile,\n PickResponse,\n PickedFile,\n PickerConfig,\n UploadError,\n} from './types.js';\nimport { Uploader } from './uploader.js';\nimport { makeError } from './errors.js';\n\n/**\n * UnionStack API URL baked into the SDK. Consumers never see or set this —\n * we ship a new SDK version if the URL ever changes.\n *\n * For local development against a staging backend, change this constant in\n * src/ and rebuild — no consumer-facing override exists by design.\n */\nconst API_BASE = 'https://cdn-api.mastersunion.org/cdn-api';\n\n// Forward-declared minimal handle so client.ts doesn't pull in the picker bundle.\nexport interface PickerHandleLike {\n open(): Promise<PickResponse>;\n close(): void;\n cancel(): void;\n}\n\nexport class UnionStackClient {\n private uploader: Uploader;\n private resolvedCfg: ResolvedClientConfig;\n /**\n * Promise that resolves to the server-managed picker config. Pre-fetched on\n * construction (unless `skipConfigPrefetch: true`) so the picker opens\n * without a network hit. Fails silently — picker falls back to defaults.\n */\n pickerConfigPromise: Promise<PickerConfig | null>;\n\n constructor(cfg: ClientConfig) {\n if (!cfg.apiKey) throw makeError('CONFIG', 'apiKey is required.', { retryable: false });\n this.resolvedCfg = { ...cfg, apiBase: API_BASE };\n this.uploader = new Uploader(this.resolvedCfg);\n this.pickerConfigPromise = this.resolvedCfg.skipConfigPrefetch\n ? Promise.resolve(null)\n : this.uploader.fetchPickerConfig().catch(() => null);\n }\n\n /** Upload a single file. Mirrors Filestack's `client.upload()`. */\n upload(file: File | Blob, opts: UploadOptions = {}): Promise<UploadedFile> {\n return this.uploader.upload(file, opts);\n }\n\n /**\n * Upload multiple files concurrently. Mirrors Filestack's batch behavior:\n * onUploadDone fires once even if some files failed — failures land in\n * `filesFailed`, successes in `filesUploaded`. `onError` is reserved for\n * batch-level failures (no files even started).\n */\n async uploadMany(\n files: (File | Blob)[],\n opts: BatchUploadOptions = {},\n ): Promise<PickResponse> {\n if (!Array.isArray(files) || files.length === 0) {\n const err = makeError('VALIDATION', 'uploadMany requires a non-empty array of files.', { retryable: false });\n opts.onError?.(err);\n throw err;\n }\n\n const picked: PickedFile[] = files.map(f =>\n this.uploader.describe(f, { filename: opts.filename, mimeType: opts.mimeType })\n );\n opts.onUploadStarted?.(picked);\n\n const filesUploaded: UploadedFile[] = [];\n const filesFailed: Array<{ file: PickedFile; error: UploadError }> = [];\n\n // Process per-file in parallel; the per-part concurrency from `opts` still\n // applies inside each upload.\n await Promise.all(files.map(async (f, i) => {\n try {\n const uploaded = await this.uploader.upload(f, opts);\n // Sync the uploadId so callers can correlate picked → uploaded.\n uploaded.uploadId = picked[i].uploadId;\n filesUploaded.push(uploaded);\n } catch (err) {\n filesFailed.push({ file: picked[i], error: err as UploadError });\n }\n }));\n\n const result: PickResponse = { filesUploaded, filesFailed };\n opts.onUploadDone?.(result);\n return result;\n }\n\n /**\n * Open the file picker modal. Lazy-loads the picker bundle so the core\n * SDK stays small for callers that only use `upload()` directly.\n */\n picker(opts: import('./picker/types.js').PickerOptions = {}): PickerHandleLike {\n let real: PickerHandleLike | null = null;\n let opened = false;\n let pendingResolve!: (r: PickResponse) => void;\n let pendingReject!: (e: UploadError) => void;\n const donePromise = new Promise<PickResponse>((res, rej) => {\n pendingResolve = res; pendingReject = rej;\n });\n\n return {\n open: async () => {\n if (opened) return donePromise;\n opened = true;\n try {\n const mod = await import('./picker/index.js');\n real = mod.openPicker(this, opts);\n const result = await real.open();\n pendingResolve(result);\n return result;\n } catch (err) {\n const e = (err as UploadError)?.code\n ? (err as UploadError)\n : makeError('CONFIG', 'Failed to load picker.', { retryable: false, cause: err });\n pendingReject(e);\n throw e;\n }\n },\n close: () => { real?.close(); },\n cancel: () => { real?.cancel(); },\n };\n }\n\n /** Read-only accessor used by the React/picker packages. */\n get config(): Readonly<ResolvedClientConfig> { return this.resolvedCfg; }\n}\n"]}
@@ -204,7 +204,7 @@ var Uploader = class {
204
204
  }
205
205
  async api(method, path, body, signal) {
206
206
  const fetchImpl = this.cfg.fetch ?? fetch;
207
- const url = `${this.cfg.apiBase.replace(/\/$/, "")}${path}`;
207
+ const url = `${this.cfg.apiBase}${path}`;
208
208
  let res;
209
209
  try {
210
210
  res = await fetchImpl(url, {
@@ -253,13 +253,13 @@ function withSessionId(err, sessionId) {
253
253
  }
254
254
 
255
255
  // src/client.ts
256
+ var API_BASE = "https://cdn-api.mastersunion.org/cdn-api";
256
257
  var UnionStackClient = class {
257
258
  constructor(cfg) {
258
- this.cfg = cfg;
259
259
  if (!cfg.apiKey) throw makeError("CONFIG", "apiKey is required.", { retryable: false });
260
- if (!cfg.apiBase) throw makeError("CONFIG", "apiBase is required.", { retryable: false });
261
- this.uploader = new Uploader(cfg);
262
- this.pickerConfigPromise = cfg.skipConfigPrefetch ? Promise.resolve(null) : this.uploader.fetchPickerConfig().catch(() => null);
260
+ this.resolvedCfg = { ...cfg, apiBase: API_BASE };
261
+ this.uploader = new Uploader(this.resolvedCfg);
262
+ this.pickerConfigPromise = this.resolvedCfg.skipConfigPrefetch ? Promise.resolve(null) : this.uploader.fetchPickerConfig().catch(() => null);
263
263
  }
264
264
  /** Upload a single file. Mirrors Filestack's `client.upload()`. */
265
265
  upload(file, opts = {}) {
@@ -335,10 +335,10 @@ var UnionStackClient = class {
335
335
  }
336
336
  /** Read-only accessor used by the React/picker packages. */
337
337
  get config() {
338
- return this.cfg;
338
+ return this.resolvedCfg;
339
339
  }
340
340
  };
341
341
 
342
342
  export { UnionStackClient };
343
- //# sourceMappingURL=chunk-5Q2UADFS.js.map
344
- //# sourceMappingURL=chunk-5Q2UADFS.js.map
343
+ //# sourceMappingURL=chunk-I4NHLGGL.js.map
344
+ //# sourceMappingURL=chunk-I4NHLGGL.js.map