UNPKG

@astrify/react-s3-upload

Version:

React file upload system built for S3-compatible storage with shadcn/ui components

2 lines 127 kB
import{CloudUpload as be,FileArchiveIcon as Fe,FileIcon as we,FileSpreadsheetIcon as Re,FileTextIcon as Se,HeadphonesIcon as Ee,ImageIcon as ne,RefreshCwIcon as ze,Trash2 as Ne,UploadIcon as ae,VideoIcon as ke,XIcon as Pe}from"lucide-react";import{useEffect as ie,useRef as Ce,useState as oe}from"react";import{useDropzone as Le}from"react-dropzone";import{Toaster as Ae,toast as Te}from"sonner";import{Slot as ve}from"@radix-ui/react-slot";import{cva as ye}from"class-variance-authority";import{clsx as fe}from"clsx";import{twMerge as he}from"tailwind-merge";function A(...e){return he(fe(e))}import{jsx as Ue}from"react/jsx-runtime";var xe=ye("inline-flex shrink-0 items-center justify-center gap-2 whitespace-nowrap rounded-md font-medium text-sm outline-none transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",{variants:{variant:{default:"bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",destructive:"bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40",outline:"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",secondary:"bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",ghost:"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",link:"text-primary underline-offset-4 hover:underline"},size:{default:"h-9 px-4 py-2 has-[>svg]:px-3",sm:"h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5",lg:"h-10 rounded-md px-6 has-[>svg]:px-4",icon:"size-9"}},defaultVariants:{variant:"default",size:"default"}});function j({className:e,variant:t,size:o,asChild:r=!1,...i}){return Ue(r?ve:"button",{"data-slot":"button",className:A(xe({variant:t,size:o,className:e})),...i})}import{jsx as l,jsxs as y}from"react/jsx-runtime";function Be(e,t,o,r,i){switch(t){case"file-too-large":return{message:"File size exceeded",details:e.name};case"file-invalid-type":return{message:"Invalid file type",details:e.name};case"too-many-files":return{message:"Too many files",details:e.name};default:return{message:o,details:e.name}}}function le(e){if(!e)return!1;let t=Object.keys(e);return t.length>0&&t.every(o=>o.startsWith("image/"))}function Me(e,t){return t||(le(e)?l(ne,{className:"size-4 opacity-60"}):l(ae,{className:"size-4 opacity-60"}))}function je(e){if(!e||Object.keys(e).length===0)return"Any file type";let t=[];for(let o of Object.values(e))o&&o.length>0&&t.push(...o.map(r=>r.toUpperCase().replace(".","")));return t.length>0?t.join(", "):"Any file type"}function De(e,t,o,r,i,c){let n=le(e),a=t||(n?i===1?"Drop your image here":"Drop your images here":i===1?"Drop file here":"Drop files here"),d=o,g="";if(!d){let m=`max. ${_(r,{si:!1,decimalPlaces:0})}`;d=`${je(e)} (${m})`}return i>1&&(g=`${c}/${i}`),{title:a,description:d,fileCountText:g,isImageOnly:n}}function Ie({onDrop:e,maxSize:t,maxFiles:o,accept:r,className:i,emptyIcon:c,emptyTitle:n,emptyDescription:a}){let d=T(),g=t??d.maxFileSize??50*1024*1024,m=o??d.config.maxFiles??10,b=r??d.acceptedFileTypes,z=m>1,w=d.remainingSlots??m,N=k=>{let P=[];for(let I of k){let{file:H,errors:Q}=I;for(let O of Q){let W=Be(H,O.code,O.message,g,m);P.push({type:"validation_error",message:W.message,details:W.details})}}return P.length>0&&d.addErrors(P),P},x=e||(async(k,P)=>{d.clearErrors(),P.length>0&&setTimeout(()=>{N(P)},50),k.length>0&&await d.addFiles(k)}),{getRootProps:$,getInputProps:D,isDragActive:q,open:V}=Le({onDrop:x,accept:b,maxSize:g,maxFiles:w,multiple:z,noClick:!0}),X=m-w,K=Me(b,c),{title:G,description:R,fileCountText:L,isImageOnly:J}=De(b,n,a,g,m,X);return y("div",{...$({className:A("relative rounded-lg border border-dashed p-6 text-center transition-colors",q?"border-primary bg-primary/5":"border-muted-foreground/25 hover:border-muted-foreground/50",i)}),children:[l("input",{...D(),className:"sr-only","aria-label":"Upload file"}),y("div",{className:"flex flex-col items-center justify-center px-4 py-3 text-center",children:[l("div",{className:"mb-2 flex size-10 shrink-0 items-center justify-center rounded-full border bg-background","aria-hidden":"true",children:K}),l("p",{className:"mb-1.5 font-medium text-sm",children:G}),l("p",{className:"text-muted-foreground text-xs",children:R}),y(j,{variant:"outline",className:"mt-4",onClick:k=>{k.stopPropagation(),V()},children:[l(ae,{className:"-ms-1 size-4 opacity-60","aria-hidden":"true"}),"Select"," ",J?m===1?"image":"images":m===1?"file":"files"]})]}),L&&l("div",{className:"absolute right-3 bottom-4 text-muted-foreground text-xs",children:L})]})}function He(){let e=Z(),{clearErrors:t}=T();return ie(()=>{e.length>0&&(e.forEach(o=>{Te.error(o.message,{description:typeof o.details=="string"?o.details:void 0,richColors:!0})}),t())},[e,t]),l(Ae,{expand:!0})}function Oe(e){if(!e)return;let t=[];for(let[o,r]of Object.entries(e))t.push(o),r&&r.length>0&&t.push(...r);return t.join(",")}function We({className:e,title:t="Files",showAddButton:o=!0,showClearButton:r=!0,addButtonText:i="Add files",clearButtonText:c="Remove all"}){let{files:n,removeAll:a,addFiles:d,canAcceptMore:g,config:m}=T(),b=Ce(null);if(n.length===0)return null;let z=()=>{var N;(N=b.current)==null||N.click()},w=async N=>{let x=Array.from(N.target.files||[]);x.length>0&&await d(x),N.target.value=""};return y("div",{className:A("flex items-center justify-between gap-2",e),children:[l("input",{ref:b,type:"file",multiple:(m.maxFiles??10)>1,accept:Oe(m.accept),onChange:w,className:"sr-only","aria-label":"Upload file"}),y("h3",{className:"truncate font-medium text-sm",children:[t," (",n.length,")"]}),y("div",{className:"flex gap-2",children:[o&&y(j,{variant:"outline",size:"sm",onClick:z,disabled:!g,children:[l(be,{className:"-ms-0.5 size-3.5 opacity-60","aria-hidden":"true"}),i]}),r&&n.length>0&&y(j,{variant:"outline",size:"sm",onClick:a,children:[l(Ne,{className:"-ms-0.5 size-3.5 opacity-60","aria-hidden":"true"}),c]})]})]})}function _e({file:e,showPreview:t}){let[o,r]=oe(null),[i,c]=oe(!1);if(ie(()=>{if(t&&e.type.startsWith("image/")){if(e.preview){let a=new Image,d=e.preview;a.onload=()=>{r(d),c(!1)},a.onerror=()=>{c(!0),r(null)},a.src=d}else if(e.file instanceof File){let a=URL.createObjectURL(e.file),d=new Image;return d.onload=()=>{r(a),c(!1)},d.onerror=()=>{c(!0),r(null),URL.revokeObjectURL(a)},d.src=a,()=>{o===a&&URL.revokeObjectURL(a)}}}},[e,t,o]),t&&o&&!i&&e.type.startsWith("image/")){if(e.status==="pending"||e.status==="uploading"){let a=e.status==="pending"?0:e.progress||0;return y("div",{className:"relative size-10 overflow-hidden rounded",children:[l("img",{src:o,alt:e.name,className:"size-10 object-cover opacity-40"}),y("svg",{className:"-rotate-90 absolute inset-0 size-10",viewBox:"0 0 40 40","aria-label":e.status==="pending"?"Pending upload":"Upload progress",children:[l("title",{children:e.status==="pending"?"Pending upload":"Upload progress"}),l("circle",{cx:"20",cy:"20",r:"18",fill:"none",stroke:"currentColor",strokeWidth:"2",className:"text-background/60"}),l("circle",{cx:"20",cy:"20",r:"18",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeDasharray:`${2*Math.PI*18}`,strokeDashoffset:`${2*Math.PI*18*(1-a/100)}`,className:"text-primary transition-all duration-300",strokeLinecap:"round"})]})]})}return l("img",{src:o,alt:e.name,className:"size-10 rounded object-cover"})}let n=l("div",{className:"flex size-10 items-center justify-center",children:$e(e)});return e.status==="pending"?y("div",{className:"relative size-10",children:[n,y("svg",{className:"absolute inset-0 size-10",viewBox:"0 0 40 40","aria-label":"Pending upload",children:[l("title",{children:"Pending upload"}),l("circle",{cx:"20",cy:"20",r:"18",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeDasharray:"4 3",className:"text-muted-foreground/40"})]})]}):e.status==="uploading"&&e.progress>0?y("div",{className:"relative size-10",children:[n,y("svg",{className:"-rotate-90 absolute inset-0 size-10",viewBox:"0 0 40 40","aria-label":"Upload progress",children:[l("title",{children:"Upload progress"}),l("circle",{cx:"20",cy:"20",r:"18",fill:"none",stroke:"currentColor",strokeWidth:"2",className:"text-muted-foreground/20"}),l("circle",{cx:"20",cy:"20",r:"18",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeDasharray:`${2*Math.PI*18}`,strokeDashoffset:`${2*Math.PI*18*(1-e.progress/100)}`,className:"text-primary transition-all duration-300",strokeLinecap:"round"})]})]}):n}function $e(e){let t=(e instanceof File,e.type),o=(e instanceof File,e.name);return t.includes("pdf")||o.endsWith(".pdf")||t.includes("word")||o.endsWith(".doc")||o.endsWith(".docx")?l(Se,{className:"size-4 opacity-60"}):t.includes("zip")||t.includes("archive")||o.endsWith(".zip")||o.endsWith(".rar")?l(Fe,{className:"size-4 opacity-60"}):t.includes("excel")||o.endsWith(".xls")||o.endsWith(".xlsx")?l(Re,{className:"size-4 opacity-60"}):t.includes("video/")?l(ke,{className:"size-4 opacity-60"}):t.includes("audio/")?l(Ee,{className:"size-4 opacity-60"}):t.startsWith("image/")?l(ne,{className:"size-4 opacity-60"}):l(we,{className:"size-4 opacity-60"})}function qe(e){switch(e.status){case"pending":return l("p",{className:"text-muted-foreground text-xs",children:"Queued"});case"uploading":return y("p",{className:"text-muted-foreground text-xs",children:["Uploading ",e.progress?`${Math.round(e.progress)}%`:""]});case"complete":return l("p",{className:"text-muted-foreground text-xs",children:_(e.size)});case"error":return l("p",{className:"text-destructive text-xs",children:e.error||"Upload failed"});default:return null}}function Ve({showActions:e=!0,showImagePreviews:t=!1,className:o}){let{files:r,removeFile:i,retryUpload:c}=T();return r.length===0?null:l("div",{className:A("space-y-2",o),children:r.map(n=>y("div",{className:A("flex items-center justify-between gap-2 rounded-lg border bg-background p-2 pe-3",n.status==="pending"&&"opacity-60",n.duplicateAlert&&"bg-primary/10"),children:[y("div",{className:"flex items-center gap-3 overflow-hidden",children:[l("div",{className:"shrink-0",children:l(_e,{file:n,showPreview:t})}),y("div",{className:"flex min-w-0 flex-col gap-0.5",children:[l("p",{className:"truncate font-medium text-[13px]",children:n.name}),qe(n)]})]}),e&&y("div",{className:"flex items-center",children:[n.status==="error"&&l(j,{size:"icon",variant:"ghost",className:"size-8 text-muted-foreground/80 hover:bg-transparent hover:text-foreground",onClick:()=>c(n.sha256),"aria-label":"Retry upload",children:l(ze,{className:"size-4","aria-hidden":"true"})}),l(j,{size:"icon",variant:"ghost",className:"-me-2 size-8 text-muted-foreground/80 hover:bg-transparent hover:text-foreground",onClick:()=>i(n.sha256),"aria-label":"Remove file",children:l(Pe,{className:"size-4","aria-hidden":"true"})})]})]},n.sha256))})}import{createContext as et,useCallback as E,useContext as tt,useEffect as rt,useMemo as C,useRef as de,useState as se}from"react";async function ee({file:e,signedUrl:t,sha256:o,onProgress:r,signal:i}){try{await ce({file:e,signedUrl:t.url,onProgress:c=>r==null?void 0:r(o,c),signal:i})}catch(c){let n=c instanceof Error?c.message:"Upload failed to S3",a=(c==null?void 0:c.details)||c;throw B("s3_upload",n,a)}}async function te(e){let t=await e.arrayBuffer(),o=await crypto.subtle.digest("SHA-256",t);return Array.from(new Uint8Array(o)).map(c=>c.toString(16).padStart(2,"0")).join("")}function Xe(){var t;let e=(t=document.cookie.split("; ").find(o=>o.startsWith("XSRF-TOKEN=")))==null?void 0:t.split("=")[1];return e?decodeURIComponent(e):null}async function Ke(e){let t=new Headers;t.set("Content-Type","application/json"),t.set("X-Requested-With","XMLHttpRequest"),t.set("Accept","application/json");let o=Xe();if(o&&t.set("X-XSRF-TOKEN",o),e){let r=typeof e=="function"?await e():e;for(let[i,c]of Object.entries(r))i.toLowerCase()!=="content-type"&&i.toLowerCase()!=="accept"&&i.toLowerCase()!=="x-requested-with"&&t.set(i,c)}return t}function Ge(e){if(!e.errors)return null;let t=Object.keys(e.errors).filter(o=>o.startsWith("files.")).flatMap(o=>{var r;return(r=e.errors)==null?void 0:r[o]});return t.length>0?t.join(", "):null}function Je(e){switch(e){case 401:return"User not authenticated";case 403:return"User not authorized";case 404:return"Upload endpoint not found";case 419:return"Session expired. Please refresh the page";case 429:return"Too many requests. Please try again later";case 500:case 502:case 503:case 504:return"Server error. Please try again later";default:return`Server responded with status ${e}`}}async function Qe(e){try{let t=await e.json(),o=Ge(t);if(o)return B("validation_error",o,t);let r=t.message||"Invalid file parameters";return B("validation_error",r,t)}catch{return B("validation_error","Invalid file parameters")}}async function Ye(e,t){if(e.status===422)throw await Qe(e);let o=Je(e.status),r={};try{r=await e.json()}catch{}throw B("server_error",t,{...r,status:e.status,details:o})}async function re(e,t,o){let r=t||"/upload/signed-url",i={files:e.map(({file:n,sha256:a})=>({contentType:n.type||"application/octet-stream",filename:n.name,filesize:n.size,sha256:a}))},c=await Ke(o);try{let n=await fetch(r,{method:"POST",headers:c,body:JSON.stringify(i),credentials:"same-origin"});n.ok||await Ye(n,"Unable to obtain upload URL");let a=await n.json();if(!(a.files&&Array.isArray(a.files)))throw B("invalid_response","Invalid response from server","Expected array of signed URLs");return a.files}catch(n){if(n.type)throw n;let a="";throw navigator.onLine?n instanceof TypeError&&n.message.includes("Failed to fetch")?a="Unable to reach server":a=n instanceof Error?n.message:"Network request failed":a="No internet connection",B("network_error","Unable to obtain upload URL",a)}}async function ce(e){return new Promise((t,o)=>{var c,n;let r=new XMLHttpRequest,i=()=>{r.abort(),o(new Error("Upload aborted"))};if((c=e.signal)!=null&&c.aborted){i();return}if((n=e.signal)==null||n.addEventListener("abort",i),r.onloadend=()=>{var a,d;if((a=e.signal)==null||a.removeEventListener("abort",i),r.readyState===4&&r.status===200)(d=e.onProgress)==null||d.call(e,1),t();else{let g="Upload failed",m="";r.status===403?(g="Upload unauthorized",m="Signed URL may have expired"):r.status===0?(g="Upload failed",m="Network error or CORS issue"):(g="Upload failed",m=`Status ${r.status}`);let b=new Error(g);b.details=m,o(b)}},r.upload.addEventListener("progress",a=>{var d;if(a.lengthComputable){let g=a.loaded/a.total;(d=e.onProgress)==null||d.call(e,g)}}),r.onerror=()=>{var a;(a=e.signal)==null||a.removeEventListener("abort",i),o(new Error("Network error during upload"))},r.open("PUT",e.signedUrl),e.headers)for(let[a,d]of Object.entries(e.headers))r.setRequestHeader(a,d);r.send(e.file)})}function B(e,t,o){return{type:e,message:t,details:o}}function _(e,t={}){let{si:o=!0,decimalPlaces:r=0}=t;if(e===0)return"0 B";let i=o?1e3:1024,c=r<0?0:r,n=o?["B","kB","MB","GB","TB","PB"]:["B","KiB","MiB","GiB","TiB","PiB"],a=Math.floor(Math.log(e)/Math.log(i));if(a===0)return`${e} B`;let d=e/i**a,g=c===0?Math.round(d):Number.parseFloat(d.toFixed(c));return`${c===0?g.toString():g.toFixed(c)} ${n[a]}`}import{jsx as ot}from"react/jsx-runtime";var ue=et(void 0);function st({children:e,config:t={},defaultFiles:o=[]}){let r=C(()=>({maxFiles:t.maxFiles??10,maxSize:t.maxSize??52428800,accept:t.accept,signedUrlEndpoint:t.signedUrlEndpoint??"/upload/signed-url",signedUrlHeaders:t.signedUrlHeaders,onUploadComplete:t.onUploadComplete,onUploadError:t.onUploadError,onFilesChange:t.onFilesChange,uploadLib:t.uploadLib}),[t.maxFiles,t.maxSize,t.accept,t.signedUrlEndpoint,t.signedUrlHeaders,t.onUploadComplete,t.onUploadError,t.onFilesChange,t.uploadLib]),i=C(()=>{var s,u,h;return{calculateSHA256:((s=r.uploadLib)==null?void 0:s.calculateSHA256)??te,requestBatchSignedUrls:((u=r.uploadLib)==null?void 0:u.requestBatchSignedUrls)??re,uploadFile:((h=r.uploadLib)==null?void 0:h.uploadFile)??ee}},[r.uploadLib]),c=C(()=>o.map(s=>({...s,id:s.sha256,status:"complete",progress:100})),[o]),[n,a]=se(new Map(c.map(s=>[s.sha256,s]))),[d,g]=se([]),[m,b]=se(new Set),z=de(new Map),w=de(new Map),N=3,x=C(()=>Array.from(n.values()),[n]),$=m.size>0,D=(r.maxFiles??10)-x.length,q=D>0,V=C(()=>x.some(s=>s.status==="pending"),[x]),X=C(()=>x.some(s=>s.status==="uploading"),[x]),K=C(()=>x.some(s=>s.status==="error")||d.length>0,[x,d]),G=C(()=>x.some(s=>s.status==="complete"),[x]),R=E((s,u)=>{a(h=>{let f=new Map(h),p=f.get(s);return p&&f.set(s,{...p,...u}),f})},[]),L=E(async s=>{let u=[],h=[];try{let f=await i.requestBatchSignedUrls(s.map(p=>({file:w.current.get(p.sha256)||new File([],p.name),sha256:p.sha256})),r.signedUrlEndpoint,r.signedUrlHeaders);s.forEach((p,v)=>{let F=f[v];if(F){let U={id:p.sha256,name:p.name,size:p.size,type:p.type,sha256:p.sha256,url:F.url,status:"pending",progress:0,preview:p.preview,file:w.current.get(p.sha256)};a(S=>{let M=new Map(S);return M.set(p.sha256,U),M}),u.push(p)}})}catch(f){let p=f;h.push(p),s.forEach(v=>{n.has(v.sha256)&&R(v.sha256,{status:"error",error:p.message})})}return{success:u,errors:h}},[r.signedUrlEndpoint,r.signedUrlHeaders,n,R,i]),J=E(s=>{a(u=>{let h=new Map(u),f=h.get(s);if(f){f.preview&&URL.revokeObjectURL(f.preview);let p=z.current.get(s);p&&(p.abort(),z.current.delete(s)),h.delete(s),w.current.delete(s)}return h}),b(u=>{let h=new Set(u);return h.delete(s),h})},[]),k=E(()=>{for(let s of Array.from(z.current.values()))s.abort();z.current.clear(),b(new Set),n.forEach(s=>{s.preview&&URL.revokeObjectURL(s.preview)}),a(new Map),w.current.clear(),g([])},[n]),P=E(async s=>{var f,p;let u=w.current.get(s.sha256);if(!u)return;let h=new AbortController;z.current.set(s.sha256,h),b(v=>new Set(v).add(s.sha256));try{R(s.sha256,{status:"uploading"}),await i.uploadFile({file:u,sha256:s.sha256,signal:h.signal,signedUrl:{sha256:s.sha256,bucket:"",key:"",url:s.url},onProgress:(F,U)=>{R(s.sha256,{progress:U*100})}}),R(s.sha256,{status:"complete",progress:100});let v=n.get(s.sha256);v&&((f=r.onUploadComplete)==null||f.call(r,[v]))}catch(v){let F=v;F.type==="duplicate_file"?(a(U=>{let S=new Map(U);return S.delete(s.sha256),S}),g(U=>[...U,{type:"duplicate_file",message:`${s.name} was not uploaded`,details:"This file already exists on the server"}])):(R(s.sha256,{status:"error",error:F.message}),(p=r.onUploadError)==null||p.call(r,[{file:u,error:F}]))}finally{z.current.delete(s.sha256),b(v=>{let F=new Set(v);return F.delete(s.sha256),F})}},[r.onUploadComplete,r.onUploadError,R,n,i]);rt(()=>{if(m.size>=N)return;let s=x.filter(f=>f.status==="pending"&&!m.has(f.sha256)),u=N-m.size;s.slice(0,u).forEach(f=>{P(f)})},[x,m,P]);let I=E(async s=>{try{let u=await i.calculateSHA256(s);return w.current.set(u,s),{name:s.name,size:s.size,type:s.type,sha256:u,preview:s.type.startsWith("image/")?URL.createObjectURL(s):void 0}}catch{return null}},[i]),H=E(s=>{R(s,{duplicateAlert:!0}),setTimeout(()=>{R(s,{duplicateAlert:!1})},1e3)},[R]),Q=E(async s=>{g([]);let u=r.maxFiles??10,h=n.size,f=u-h;if(f<=0){g([{type:"validation_error",message:"Maximum files reached",details:`Maximum ${u} files allowed`}]);return}let p=s.slice(0,f);s.length>p.length&&g(U=>[...U,{type:"validation_error",message:"File limit exceeded",details:`Only ${f} more file(s) can be added`}]);let v=[],F=[];for(let U of p){let S=await I(U);if(!S){F.push({type:"validation_error",message:"Failed to process file",details:U.name});continue}n.has(S.sha256)?H(S.sha256):v.push(S)}if(F.length>0&&g(U=>[...U,...F]),v.length>0){let{success:U,errors:S}=await L(v);if(S.length>0&&g(M=>[...M,...S]),U.length>0&&r.onFilesChange){let M=U.map(Y=>w.current.get(Y.sha256)).filter(Y=>Y!==void 0);r.onFilesChange(M)}}},[n,r.maxFiles,r.onFilesChange,L,H,I]),O=E(async s=>{let u=n.get(s),h=w.current.get(s);if(!(u&&h)||m.has(s))return;let f={name:u.name,size:u.size,type:u.type,sha256:u.sha256,preview:u.preview},{errors:p}=await L([f]);p.length>0&&g(v=>[...v,...p])},[n,m,L]),W=E(()=>{k()},[k]),pe=E(s=>{s.length>0&&g(u=>[...u,...s])},[]),ge=E(()=>{g([])},[]),me={files:x,errors:d,isUploading:$,remainingSlots:D,config:r,hasPending:V,hasUploading:X,hasErrors:K,hasComplete:G,addFiles:Q,removeFile:J,removeAll:k,retryUpload:O,reset:W,addErrors:pe,clearErrors:ge,canAcceptMore:q,acceptedFileTypes:r.accept,maxFileSize:r.maxSize??50*1024*1024};return ot(ue.Provider,{value:me,children:e})}function T(){let e=tt(ue);if(!e)throw new Error("useFileUpload must be used within FileUploadProvider");return e}function Z(){let{errors:e}=T();return e}export{Ie as Dropzone,He as Errors,st as FileUploadProvider,We as Header,Ve as List,te as calculateSHA256,_ as formatBytes,re as requestBatchSignedUrls,ee as uploadFile,ce as uploadToS3Storage,Z as useFileErrors,T as useFileUpload}; //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL2NvbXBvbmVudHMvYXN0cmlmeS91cGxvYWQudHN4IiwgIi4uL3NyYy9jb21wb25lbnRzL3VpL2J1dHRvbi50c3giLCAiLi4vc3JjL2xpYi91dGlscy50cyIsICIuLi9zcmMvRmlsZVVwbG9hZENvbnRleHQudHN4IiwgIi4uL3NyYy9saWIvdXBsb2FkLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyJpbXBvcnQgdHlwZSB7IEZpbGVUeXBlLCBGaWxlVXBsb2FkIH0gZnJvbSBcIkBhc3RyaWZ5L3JlYWN0LXMzLXVwbG9hZFwiO1xuaW1wb3J0IHtcblx0Zm9ybWF0Qnl0ZXMsXG5cdHVzZUZpbGVFcnJvcnMsXG5cdHVzZUZpbGVVcGxvYWQsXG59IGZyb20gXCJAYXN0cmlmeS9yZWFjdC1zMy11cGxvYWRcIjtcbmltcG9ydCB7XG5cdENsb3VkVXBsb2FkLFxuXHRGaWxlQXJjaGl2ZUljb24sXG5cdEZpbGVJY29uLFxuXHRGaWxlU3ByZWFkc2hlZXRJY29uLFxuXHRGaWxlVGV4dEljb24sXG5cdEhlYWRwaG9uZXNJY29uLFxuXHRJbWFnZUljb24sXG5cdFJlZnJlc2hDd0ljb24sXG5cdFRyYXNoMixcblx0VXBsb2FkSWNvbixcblx0VmlkZW9JY29uLFxuXHRYSWNvbixcbn0gZnJvbSBcImx1Y2lkZS1yZWFjdFwiO1xuaW1wb3J0IHR5cGUgKiBhcyBSZWFjdCBmcm9tIFwicmVhY3RcIjtcbmltcG9ydCB7IHVzZUVmZmVjdCwgdXNlUmVmLCB1c2VTdGF0ZSB9IGZyb20gXCJyZWFjdFwiO1xuaW1wb3J0IHsgdHlwZSBBY2NlcHQsIHR5cGUgRmlsZVJlamVjdGlvbiwgdXNlRHJvcHpvbmUgfSBmcm9tIFwicmVhY3QtZHJvcHpvbmVcIjtcbmltcG9ydCB7IFRvYXN0ZXIsIHRvYXN0IH0gZnJvbSBcInNvbm5lclwiO1xuaW1wb3J0IHsgQnV0dG9uIH0gZnJvbSBcIkAvY29tcG9uZW50cy91aS9idXR0b25cIjtcbmltcG9ydCB7IGNuIH0gZnJvbSBcIkAvbGliL3V0aWxzXCI7XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIERST1BaT05FIENPTVBPTkVOVFxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5pbnRlcmZhY2UgRHJvcHpvbmVQcm9wcyB7XG5cdG9uRHJvcD86IChhY2NlcHRlZEZpbGVzOiBGaWxlW10sIHJlamVjdGVkRmlsZXM6IEZpbGVSZWplY3Rpb25bXSkgPT4gdm9pZDtcblx0bWF4U2l6ZT86IG51bWJlcjtcblx0bWF4RmlsZXM/OiBudW1iZXI7XG5cdGFjY2VwdD86IEFjY2VwdDtcblx0Y2xhc3NOYW1lPzogc3RyaW5nO1xuXHRjaGlsZHJlbj86IFJlYWN0LlJlYWN0Tm9kZTtcblx0aGlkZURlZmF1bHRDb250ZW50PzogYm9vbGVhbjtcblx0ZW1wdHlJY29uPzogUmVhY3QuUmVhY3ROb2RlO1xuXHRlbXB0eVRpdGxlPzogc3RyaW5nO1xuXHRlbXB0eURlc2NyaXB0aW9uPzogc3RyaW5nO1xufVxuXG4vLyBIZWxwZXIgZnVuY3Rpb24gdG8gZm9ybWF0IHJlamVjdGlvbiBlcnJvciBtZXNzYWdlc1xuZnVuY3Rpb24gZm9ybWF0UmVqZWN0aW9uRXJyb3IoXG5cdGZpbGU6IEZpbGUsXG5cdGVycm9yQ29kZTogc3RyaW5nLFxuXHRlcnJvck1lc3NhZ2U6IHN0cmluZyxcblx0X21heFNpemU6IG51bWJlcixcblx0X21heEZpbGVzOiBudW1iZXIsXG4pOiB7IG1lc3NhZ2U6IHN0cmluZzsgZGV0YWlsczogc3RyaW5nIH0ge1xuXHRzd2l0Y2ggKGVycm9yQ29kZSkge1xuXHRcdGNhc2UgXCJmaWxlLXRvby1sYXJnZVwiOlxuXHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0bWVzc2FnZTogXCJGaWxlIHNpemUgZXhjZWVkZWRcIixcblx0XHRcdFx0ZGV0YWlsczogZmlsZS5uYW1lLFxuXHRcdFx0fTtcblx0XHRjYXNlIFwiZmlsZS1pbnZhbGlkLXR5cGVcIjpcblx0XHRcdHJldHVybiB7XG5cdFx0XHRcdG1lc3NhZ2U6IFwiSW52YWxpZCBmaWxlIHR5cGVcIixcblx0XHRcdFx0ZGV0YWlsczogZmlsZS5uYW1lLFxuXHRcdFx0fTtcblx0XHRjYXNlIFwidG9vLW1hbnktZmlsZXNcIjpcblx0XHRcdHJldHVybiB7XG5cdFx0XHRcdG1lc3NhZ2U6IFwiVG9vIG1hbnkgZmlsZXNcIixcblx0XHRcdFx0ZGV0YWlsczogZmlsZS5uYW1lLFxuXHRcdFx0fTtcblx0XHRkZWZhdWx0OlxuXHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0bWVzc2FnZTogZXJyb3JNZXNzYWdlLFxuXHRcdFx0XHRkZXRhaWxzOiBmaWxlLm5hbWUsXG5cdFx0XHR9O1xuXHR9XG59XG5cbi8vIEhlbHBlciBmdW5jdGlvbiB0byBjaGVjayBpZiBhY2NlcHQgb25seSBhbGxvd3MgaW1hZ2VzXG5mdW5jdGlvbiBpc0ltYWdlT25seUFjY2VwdChhY2NlcHQ6IEFjY2VwdCB8IHVuZGVmaW5lZCk6IGJvb2xlYW4ge1xuXHRpZiAoIWFjY2VwdCkge1xuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXHRjb25zdCBtaW1lVHlwZXMgPSBPYmplY3Qua2V5cyhhY2NlcHQpO1xuXHRyZXR1cm4gKFxuXHRcdG1pbWVUeXBlcy5sZW5ndGggPiAwICYmIG1pbWVUeXBlcy5ldmVyeSgodHlwZSkgPT4gdHlwZS5zdGFydHNXaXRoKFwiaW1hZ2UvXCIpKVxuXHQpO1xufVxuXG4vLyBIZWxwZXIgZnVuY3Rpb24gdG8gZ2V0IGRyb3B6b25lIGljb25cbmZ1bmN0aW9uIGdldERyb3B6b25lSWNvbihcblx0YWNjZXB0OiBBY2NlcHQgfCB1bmRlZmluZWQsXG5cdGVtcHR5SWNvbjogUmVhY3QuUmVhY3ROb2RlIHwgdW5kZWZpbmVkLFxuKTogUmVhY3QuUmVhY3ROb2RlIHtcblx0aWYgKGVtcHR5SWNvbikge1xuXHRcdHJldHVybiBlbXB0eUljb247XG5cdH1cblxuXHRjb25zdCBpc0ltYWdlT25seSA9IGlzSW1hZ2VPbmx5QWNjZXB0KGFjY2VwdCk7XG5cdGlmIChpc0ltYWdlT25seSkge1xuXHRcdHJldHVybiA8SW1hZ2VJY29uIGNsYXNzTmFtZT1cInNpemUtNCBvcGFjaXR5LTYwXCIgLz47XG5cdH1cblx0cmV0dXJuIDxVcGxvYWRJY29uIGNsYXNzTmFtZT1cInNpemUtNCBvcGFjaXR5LTYwXCIgLz47XG59XG5cbi8vIEhlbHBlciBmdW5jdGlvbiB0byBnZW5lcmF0ZSBmaWxlIHR5cGUgZGVzY3JpcHRpb24gZnJvbSBBY2NlcHQgb2JqZWN0XG5mdW5jdGlvbiBnZXRBY2NlcHREZXNjcmlwdGlvbihhY2NlcHQ6IEFjY2VwdCB8IHVuZGVmaW5lZCk6IHN0cmluZyB7XG5cdGlmICghYWNjZXB0IHx8IE9iamVjdC5rZXlzKGFjY2VwdCkubGVuZ3RoID09PSAwKSB7XG5cdFx0cmV0dXJuIFwiQW55IGZpbGUgdHlwZVwiO1xuXHR9XG5cblx0Y29uc3QgYWxsRXh0ZW5zaW9uczogc3RyaW5nW10gPSBbXTtcblxuXHRmb3IgKGNvbnN0IGV4dGVuc2lvbnMgb2YgT2JqZWN0LnZhbHVlcyhhY2NlcHQpKSB7XG5cdFx0aWYgKGV4dGVuc2lvbnMgJiYgZXh0ZW5zaW9ucy5sZW5ndGggPiAwKSB7XG5cdFx0XHRhbGxFeHRlbnNpb25zLnB1c2goXG5cdFx0XHRcdC4uLmV4dGVuc2lvbnMubWFwKChleHQpID0+IGV4dC50b1VwcGVyQ2FzZSgpLnJlcGxhY2UoXCIuXCIsIFwiXCIpKSxcblx0XHRcdCk7XG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIGFsbEV4dGVuc2lvbnMubGVuZ3RoID4gMCA/IGFsbEV4dGVuc2lvbnMuam9pbihcIiwgXCIpIDogXCJBbnkgZmlsZSB0eXBlXCI7XG59XG5cbi8vIEhlbHBlciBmdW5jdGlvbiB0byBnZXQgZHJvcHpvbmUgdGV4dCBjb250ZW50XG5mdW5jdGlvbiBnZXREcm9wem9uZVRleHQoXG5cdGFjY2VwdDogQWNjZXB0IHwgdW5kZWZpbmVkLFxuXHRlbXB0eVRpdGxlOiBzdHJpbmcgfCB1bmRlZmluZWQsXG5cdGVtcHR5RGVzY3JpcHRpb246IHN0cmluZyB8IHVuZGVmaW5lZCxcblx0bWF4U2l6ZTogbnVtYmVyLFxuXHRtYXhGaWxlczogbnVtYmVyLFxuXHRjdXJyZW50RmlsZUNvdW50OiBudW1iZXIsXG4pIHtcblx0Y29uc3QgaXNJbWFnZU9ubHkgPSBpc0ltYWdlT25seUFjY2VwdChhY2NlcHQpO1xuXG5cdGNvbnN0IHRpdGxlID1cblx0XHRlbXB0eVRpdGxlIHx8XG5cdFx0KGlzSW1hZ2VPbmx5XG5cdFx0XHQ/IG1heEZpbGVzID09PSAxXG5cdFx0XHRcdD8gXCJEcm9wIHlvdXIgaW1hZ2UgaGVyZVwiXG5cdFx0XHRcdDogXCJEcm9wIHlvdXIgaW1hZ2VzIGhlcmVcIlxuXHRcdFx0OiBtYXhGaWxlcyA9PT0gMVxuXHRcdFx0XHQ/IFwiRHJvcCBmaWxlIGhlcmVcIlxuXHRcdFx0XHQ6IFwiRHJvcCBmaWxlcyBoZXJlXCIpO1xuXG5cdGxldCBkZXNjcmlwdGlvbiA9IGVtcHR5RGVzY3JpcHRpb247XG5cdGxldCBmaWxlQ291bnRUZXh0ID0gXCJcIjtcblxuXHRpZiAoIWRlc2NyaXB0aW9uKSB7XG5cdFx0Y29uc3Qgc2l6ZVRleHQgPSBgbWF4LiAke2Zvcm1hdEJ5dGVzKG1heFNpemUsIHsgc2k6IGZhbHNlLCBkZWNpbWFsUGxhY2VzOiAwIH0pfWA7XG5cdFx0Y29uc3QgZmlsZVR5cGVzID0gZ2V0QWNjZXB0RGVzY3JpcHRpb24oYWNjZXB0KTtcblx0XHRkZXNjcmlwdGlvbiA9IGAke2ZpbGVUeXBlc30gKCR7c2l6ZVRleHR9KWA7XG5cdH1cblxuXHQvLyBBZGQgZmlsZSBjb3VudCBvbiBzZXBhcmF0ZSBsaW5lIGlmIG1heEZpbGVzID4gMVxuXHRpZiAobWF4RmlsZXMgPiAxKSB7XG5cdFx0ZmlsZUNvdW50VGV4dCA9IGAke2N1cnJlbnRGaWxlQ291bnR9LyR7bWF4RmlsZXN9YDtcblx0fVxuXG5cdHJldHVybiB7IHRpdGxlLCBkZXNjcmlwdGlvbiwgZmlsZUNvdW50VGV4dCwgaXNJbWFnZU9ubHkgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIERyb3B6b25lKHtcblx0b25Ecm9wOiBvbkRyb3BQcm9wLFxuXHRtYXhTaXplOiBtYXhTaXplUHJvcCxcblx0bWF4RmlsZXM6IG1heEZpbGVzUHJvcCxcblx0YWNjZXB0OiBhY2NlcHRQcm9wLFxuXHRjbGFzc05hbWUsXG5cdGVtcHR5SWNvbixcblx0ZW1wdHlUaXRsZSxcblx0ZW1wdHlEZXNjcmlwdGlvbixcbn06IERyb3B6b25lUHJvcHMpIHtcblx0Ly8gR2V0IGNvbmZpZyBmcm9tIGNvbnRleHQgKHJlcXVpcmVkKVxuXHRjb25zdCBjb250ZXh0ID0gdXNlRmlsZVVwbG9hZCgpO1xuXG5cdGNvbnN0IG1heFNpemUgPSBtYXhTaXplUHJvcCA/PyBjb250ZXh0Lm1heEZpbGVTaXplID8/IDUwICogMTAyNCAqIDEwMjQ7XG5cdGNvbnN0IG1heEZpbGVzID0gbWF4RmlsZXNQcm9wID8/IGNvbnRleHQuY29uZmlnLm1heEZpbGVzID8/IDEwO1xuXHRjb25zdCBhY2NlcHQgPSBhY2NlcHRQcm9wID8/IGNvbnRleHQuYWNjZXB0ZWRGaWxlVHlwZXM7XG5cdGNvbnN0IG11bHRpcGxlID0gbWF4RmlsZXMgPiAxO1xuXHRjb25zdCByZW1haW5pbmdTbG90cyA9IGNvbnRleHQucmVtYWluaW5nU2xvdHMgPz8gbWF4RmlsZXM7XG5cblx0Ly8gSGFuZGxlIGZpbGUgcmVqZWN0aW9ucyBhbmQgZm9ybWF0IGVycm9yIG1lc3NhZ2VzXG5cdGNvbnN0IGhhbmRsZVJlamVjdGlvbnMgPSAoZmlsZVJlamVjdGlvbnM6IEZpbGVSZWplY3Rpb25bXSkgPT4ge1xuXHRcdGNvbnN0IGVycm9yTWVzc2FnZXM6IEFycmF5PHtcblx0XHRcdHR5cGU6IFwidmFsaWRhdGlvbl9lcnJvclwiO1xuXHRcdFx0bWVzc2FnZTogc3RyaW5nO1xuXHRcdFx0ZGV0YWlsczogc3RyaW5nO1xuXHRcdH0+ID0gW107XG5cblx0XHRmb3IgKGNvbnN0IHJlamVjdGlvbiBvZiBmaWxlUmVqZWN0aW9ucykge1xuXHRcdFx0Y29uc3QgeyBmaWxlLCBlcnJvcnMgfSA9IHJlamVjdGlvbjtcblx0XHRcdGZvciAoY29uc3QgZXJyb3Igb2YgZXJyb3JzKSB7XG5cdFx0XHRcdGNvbnN0IGZvcm1hdHRlZCA9IGZvcm1hdFJlamVjdGlvbkVycm9yKFxuXHRcdFx0XHRcdGZpbGUsXG5cdFx0XHRcdFx0ZXJyb3IuY29kZSxcblx0XHRcdFx0XHRlcnJvci5tZXNzYWdlLFxuXHRcdFx0XHRcdG1heFNpemUsXG5cdFx0XHRcdFx0bWF4RmlsZXMsXG5cdFx0XHRcdCk7XG5cdFx0XHRcdGVycm9yTWVzc2FnZXMucHVzaCh7XG5cdFx0XHRcdFx0dHlwZTogXCJ2YWxpZGF0aW9uX2Vycm9yXCIsXG5cdFx0XHRcdFx0bWVzc2FnZTogZm9ybWF0dGVkLm1lc3NhZ2UsXG5cdFx0XHRcdFx0ZGV0YWlsczogZm9ybWF0dGVkLmRldGFpbHMsXG5cdFx0XHRcdH0pO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIFB1c2ggZXJyb3JzIHRvIGNvbnRleHRcblx0XHRpZiAoZXJyb3JNZXNzYWdlcy5sZW5ndGggPiAwKSB7XG5cdFx0XHRjb250ZXh0LmFkZEVycm9ycyhlcnJvck1lc3NhZ2VzKTtcblx0XHR9XG5cblx0XHRyZXR1cm4gZXJyb3JNZXNzYWdlcztcblx0fTtcblxuXHQvLyBVc2UgY29udGV4dCBhZGRGaWxlcyBhbmQgb3B0aW9uYWwgY3VzdG9tIG9uRHJvcFxuXHRjb25zdCBoYW5kbGVEcm9wID1cblx0XHRvbkRyb3BQcm9wIHx8XG5cdFx0KGFzeW5jIChhY2NlcHRlZEZpbGVzOiBGaWxlW10sIGZpbGVSZWplY3Rpb25zOiBGaWxlUmVqZWN0aW9uW10pID0+IHtcblx0XHRcdC8vIENsZWFyIGFueSBleGlzdGluZyBlcnJvcnMgYXQgdGhlIHN0YXJ0IG9mIGEgbmV3IGRyb3Bcblx0XHRcdGNvbnRleHQuY2xlYXJFcnJvcnMoKTtcblxuXHRcdFx0Ly8gSGFuZGxlIHJlamVjdGlvbnMgd2l0aCBhIHNtYWxsIGRlbGF5IHRvIHRyaWdnZXIgcmUtYW5pbWF0aW9uXG5cdFx0XHRpZiAoZmlsZVJlamVjdGlvbnMubGVuZ3RoID4gMCkge1xuXHRcdFx0XHRzZXRUaW1lb3V0KCgpID0+IHtcblx0XHRcdFx0XHRoYW5kbGVSZWplY3Rpb25zKGZpbGVSZWplY3Rpb25zKTtcblx0XHRcdFx0fSwgNTApO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBUaGVuIGhhbmRsZSBhY2NlcHRlZCBmaWxlc1xuXHRcdFx0aWYgKGFjY2VwdGVkRmlsZXMubGVuZ3RoID4gMCkge1xuXHRcdFx0XHRhd2FpdCBjb250ZXh0LmFkZEZpbGVzKGFjY2VwdGVkRmlsZXMpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXG5cdGNvbnN0IHsgZ2V0Um9vdFByb3BzLCBnZXRJbnB1dFByb3BzLCBpc0RyYWdBY3RpdmUsIG9wZW4gfSA9IHVzZURyb3B6b25lKHtcblx0XHRvbkRyb3A6IGhhbmRsZURyb3AsXG5cdFx0YWNjZXB0LFxuXHRcdG1heFNpemUsXG5cdFx0bWF4RmlsZXM6IHJlbWFpbmluZ1Nsb3RzLFxuXHRcdG11bHRpcGxlLFxuXHRcdG5vQ2xpY2s6IHRydWUsIC8vIFdlJ2xsIGhhbmRsZSBjbGljayBtYW51YWxseVxuXHR9KTtcblxuXHRjb25zdCBjdXJyZW50RmlsZUNvdW50ID0gbWF4RmlsZXMgLSByZW1haW5pbmdTbG90cztcblxuXHRjb25zdCBpY29uID0gZ2V0RHJvcHpvbmVJY29uKGFjY2VwdCwgZW1wdHlJY29uKTtcblxuXHRjb25zdCB7IHRpdGxlLCBkZXNjcmlwdGlvbiwgZmlsZUNvdW50VGV4dCwgaXNJbWFnZU9ubHkgfSA9IGdldERyb3B6b25lVGV4dChcblx0XHRhY2NlcHQsXG5cdFx0ZW1wdHlUaXRsZSxcblx0XHRlbXB0eURlc2NyaXB0aW9uLFxuXHRcdG1heFNpemUsXG5cdFx0bWF4RmlsZXMsXG5cdFx0Y3VycmVudEZpbGVDb3VudCxcblx0KTtcblxuXHRyZXR1cm4gKFxuXHRcdDxkaXZcblx0XHRcdHsuLi5nZXRSb290UHJvcHMoe1xuXHRcdFx0XHRjbGFzc05hbWU6IGNuKFxuXHRcdFx0XHRcdFwicmVsYXRpdmUgcm91bmRlZC1sZyBib3JkZXIgYm9yZGVyLWRhc2hlZCBwLTYgdGV4dC1jZW50ZXIgdHJhbnNpdGlvbi1jb2xvcnNcIixcblx0XHRcdFx0XHRpc0RyYWdBY3RpdmVcblx0XHRcdFx0XHRcdD8gXCJib3JkZXItcHJpbWFyeSBiZy1wcmltYXJ5LzVcIlxuXHRcdFx0XHRcdFx0OiBcImJvcmRlci1tdXRlZC1mb3JlZ3JvdW5kLzI1IGhvdmVyOmJvcmRlci1tdXRlZC1mb3JlZ3JvdW5kLzUwXCIsXG5cdFx0XHRcdFx0Y2xhc3NOYW1lLFxuXHRcdFx0XHQpLFxuXHRcdFx0fSl9XG5cdFx0PlxuXHRcdFx0PGlucHV0XG5cdFx0XHRcdHsuLi5nZXRJbnB1dFByb3BzKCl9XG5cdFx0XHRcdGNsYXNzTmFtZT1cInNyLW9ubHlcIlxuXHRcdFx0XHRhcmlhLWxhYmVsPVwiVXBsb2FkIGZpbGVcIlxuXHRcdFx0Lz5cblxuXHRcdFx0PGRpdiBjbGFzc05hbWU9XCJmbGV4IGZsZXgtY29sIGl0ZW1zLWNlbnRlciBqdXN0aWZ5LWNlbnRlciBweC00IHB5LTMgdGV4dC1jZW50ZXJcIj5cblx0XHRcdFx0PGRpdlxuXHRcdFx0XHRcdGNsYXNzTmFtZT1cIm1iLTIgZmxleCBzaXplLTEwIHNocmluay0wIGl0ZW1zLWNlbnRlciBqdXN0aWZ5LWNlbnRlciByb3VuZGVkLWZ1bGwgYm9yZGVyIGJnLWJhY2tncm91bmRcIlxuXHRcdFx0XHRcdGFyaWEtaGlkZGVuPVwidHJ1ZVwiXG5cdFx0XHRcdD5cblx0XHRcdFx0XHR7aWNvbn1cblx0XHRcdFx0PC9kaXY+XG5cblx0XHRcdFx0PHAgY2xhc3NOYW1lPVwibWItMS41IGZvbnQtbWVkaXVtIHRleHQtc21cIj57dGl0bGV9PC9wPlxuXHRcdFx0XHQ8cCBjbGFzc05hbWU9XCJ0ZXh0LW11dGVkLWZvcmVncm91bmQgdGV4dC14c1wiPntkZXNjcmlwdGlvbn08L3A+XG5cdFx0XHRcdDxCdXR0b25cblx0XHRcdFx0XHR2YXJpYW50PVwib3V0bGluZVwiXG5cdFx0XHRcdFx0Y2xhc3NOYW1lPVwibXQtNFwiXG5cdFx0XHRcdFx0b25DbGljaz17KGUpID0+IHtcblx0XHRcdFx0XHRcdGUuc3RvcFByb3BhZ2F0aW9uKCk7XG5cdFx0XHRcdFx0XHRvcGVuKCk7XG5cdFx0XHRcdFx0fX1cblx0XHRcdFx0PlxuXHRcdFx0XHRcdDxVcGxvYWRJY29uIGNsYXNzTmFtZT1cIi1tcy0xIHNpemUtNCBvcGFjaXR5LTYwXCIgYXJpYS1oaWRkZW49XCJ0cnVlXCIgLz5cblx0XHRcdFx0XHRTZWxlY3R7XCIgXCJ9XG5cdFx0XHRcdFx0e2lzSW1hZ2VPbmx5XG5cdFx0XHRcdFx0XHQ/IG1heEZpbGVzID09PSAxXG5cdFx0XHRcdFx0XHRcdD8gXCJpbWFnZVwiXG5cdFx0XHRcdFx0XHRcdDogXCJpbWFnZXNcIlxuXHRcdFx0XHRcdFx0OiBtYXhGaWxlcyA9PT0gMVxuXHRcdFx0XHRcdFx0XHQ/IFwiZmlsZVwiXG5cdFx0XHRcdFx0XHRcdDogXCJmaWxlc1wifVxuXHRcdFx0XHQ8L0J1dHRvbj5cblx0XHRcdDwvZGl2PlxuXG5cdFx0XHR7ZmlsZUNvdW50VGV4dCAmJiAoXG5cdFx0XHRcdDxkaXYgY2xhc3NOYW1lPVwiYWJzb2x1dGUgcmlnaHQtMyBib3R0b20tNCB0ZXh0LW11dGVkLWZvcmVncm91bmQgdGV4dC14c1wiPlxuXHRcdFx0XHRcdHtmaWxlQ291bnRUZXh0fVxuXHRcdFx0XHQ8L2Rpdj5cblx0XHRcdCl9XG5cdFx0PC9kaXY+XG5cdCk7XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIEVSUk9SUyBDT01QT05FTlRcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuZXhwb3J0IGZ1bmN0aW9uIEVycm9ycygpIHtcblx0Y29uc3QgZXJyb3JzID0gdXNlRmlsZUVycm9ycygpO1xuXHRjb25zdCB7IGNsZWFyRXJyb3JzIH0gPSB1c2VGaWxlVXBsb2FkKCk7XG5cblx0Ly8gU2hvdyBlcnJvcnMgYXMgdG9hc3RzXG5cdHVzZUVmZmVjdCgoKSA9PiB7XG5cdFx0aWYgKGVycm9ycy5sZW5ndGggPiAwKSB7XG5cdFx0XHQvLyBTaG93IHRvYXN0cyBmb3IgYWxsIGVycm9yc1xuXHRcdFx0ZXJyb3JzLmZvckVhY2goKGVycm9yKSA9PiB7XG5cdFx0XHRcdHRvYXN0LmVycm9yKGVycm9yLm1lc3NhZ2UsIHtcblx0XHRcdFx0XHRkZXNjcmlwdGlvbjpcblx0XHRcdFx0XHRcdHR5cGVvZiBlcnJvci5kZXRhaWxzID09PSBcInN0cmluZ1wiID8gZXJyb3IuZGV0YWlscyA6IHVuZGVmaW5lZCxcblx0XHRcdFx0XHRyaWNoQ29sb3JzOiB0cnVlLFxuXHRcdFx0XHR9KTtcblx0XHRcdH0pO1xuXG5cdFx0XHQvLyBDbGVhciBlcnJvcnMgaW1tZWRpYXRlbHkgYWZ0ZXIgc2hvd2luZyB0b2FzdHNcblx0XHRcdGNsZWFyRXJyb3JzKCk7XG5cdFx0fVxuXHR9LCBbZXJyb3JzLCBjbGVhckVycm9yc10pO1xuXG5cdC8vIFJlcGxhY2Ugd2l0aCBudWxsIGlmIHlvdSdyZSBsb2FkaW5nIHRoZSBUb2FzdGVyIGluIGEgZGlmZmVyZW50IGNvbXBvbmVudFxuXHRyZXR1cm4gPFRvYXN0ZXIgZXhwYW5kPXt0cnVlfSAvPjtcbn1cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gSEVBREVSIENPTVBPTkVOVFxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vLyBDb252ZXJ0IEFjY2VwdCBvYmplY3QgdG8gSFRNTCBpbnB1dCBhY2NlcHQgc3RyaW5nXG5mdW5jdGlvbiBhY2NlcHRUb1N0cmluZyhhY2NlcHQ6IEFjY2VwdCB8IHVuZGVmaW5lZCk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG5cdGlmICghYWNjZXB0KSB7XG5cdFx0cmV0dXJuIHVuZGVmaW5lZDtcblx0fVxuXG5cdGNvbnN0IHBhcnRzOiBzdHJpbmdbXSA9IFtdO1xuXHRmb3IgKGNvbnN0IFttaW1lVHlwZSwgZXh0ZW5zaW9uc10gb2YgT2JqZWN0LmVudHJpZXMoYWNjZXB0KSkge1xuXHRcdHBhcnRzLnB1c2gobWltZVR5cGUpO1xuXHRcdGlmIChleHRlbnNpb25zICYmIGV4dGVuc2lvbnMubGVuZ3RoID4gMCkge1xuXHRcdFx0cGFydHMucHVzaCguLi5leHRlbnNpb25zKTtcblx0XHR9XG5cdH1cblx0cmV0dXJuIHBhcnRzLmpvaW4oXCIsXCIpO1xufVxuXG5pbnRlcmZhY2UgSGVhZGVyUHJvcHMge1xuXHRjbGFzc05hbWU/OiBzdHJpbmc7XG5cdHRpdGxlPzogc3RyaW5nO1xuXHRzaG93QWRkQnV0dG9uPzogYm9vbGVhbjtcblx0c2hvd0NsZWFyQnV0dG9uPzogYm9vbGVhbjtcblx0YWRkQnV0dG9uVGV4dD86IHN0cmluZztcblx0Y2xlYXJCdXR0b25UZXh0Pzogc3RyaW5nO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gSGVhZGVyKHtcblx0Y2xhc3NOYW1lLFxuXHR0aXRsZSA9IFwiRmlsZXNcIixcblx0c2hvd0FkZEJ1dHRvbiA9IHRydWUsXG5cdHNob3dDbGVhckJ1dHRvbiA9IHRydWUsXG5cdGFkZEJ1dHRvblRleHQgPSBcIkFkZCBmaWxlc1wiLFxuXHRjbGVhckJ1dHRvblRleHQgPSBcIlJlbW92ZSBhbGxcIixcbn06IEhlYWRlclByb3BzKSB7XG5cdGNvbnN0IHsgZmlsZXMsIHJlbW92ZUFsbCwgYWRkRmlsZXMsIGNhbkFjY2VwdE1vcmUsIGNvbmZpZyB9ID0gdXNlRmlsZVVwbG9hZCgpO1xuXHRjb25zdCBmaWxlSW5wdXRSZWYgPSB1c2VSZWY8SFRNTElucHV0RWxlbWVudD4obnVsbCk7XG5cblx0aWYgKGZpbGVzLmxlbmd0aCA9PT0gMCkge1xuXHRcdHJldHVybiBudWxsO1xuXHR9XG5cblx0Y29uc3Qgb3BlbkZpbGVEaWFsb2cgPSAoKSA9PiB7XG5cdFx0ZmlsZUlucHV0UmVmLmN1cnJlbnQ/LmNsaWNrKCk7XG5cdH07XG5cblx0Y29uc3QgaGFuZGxlRmlsZUlucHV0Q2hhbmdlID0gYXN5bmMgKFxuXHRcdGU6IFJlYWN0LkNoYW5nZUV2ZW50PEhUTUxJbnB1dEVsZW1lbnQ+LFxuXHQpID0+IHtcblx0XHRjb25zdCBuZXdGaWxlcyA9IEFycmF5LmZyb20oZS50YXJnZXQuZmlsZXMgfHwgW10pO1xuXHRcdGlmIChuZXdGaWxlcy5sZW5ndGggPiAwKSB7XG5cdFx0XHRhd2FpdCBhZGRGaWxlcyhuZXdGaWxlcyk7XG5cdFx0fVxuXHRcdGUudGFyZ2V0LnZhbHVlID0gXCJcIjtcblx0fTtcblxuXHRyZXR1cm4gKFxuXHRcdDxkaXYgY2xhc3NOYW1lPXtjbihcImZsZXggaXRlbXMtY2VudGVyIGp1c3RpZnktYmV0d2VlbiBnYXAtMlwiLCBjbGFzc05hbWUpfT5cblx0XHRcdDxpbnB1dFxuXHRcdFx0XHRyZWY9e2ZpbGVJbnB1dFJlZn1cblx0XHRcdFx0dHlwZT1cImZpbGVcIlxuXHRcdFx0XHRtdWx0aXBsZT17KGNvbmZpZy5tYXhGaWxlcyA/PyAxMCkgPiAxfVxuXHRcdFx0XHRhY2NlcHQ9e2FjY2VwdFRvU3RyaW5nKGNvbmZpZy5hY2NlcHQpfVxuXHRcdFx0XHRvbkNoYW5nZT17aGFuZGxlRmlsZUlucHV0Q2hhbmdlfVxuXHRcdFx0XHRjbGFzc05hbWU9XCJzci1vbmx5XCJcblx0XHRcdFx0YXJpYS1sYWJlbD1cIlVwbG9hZCBmaWxlXCJcblx0XHRcdC8+XG5cblx0XHRcdDxoMyBjbGFzc05hbWU9XCJ0cnVuY2F0ZSBmb250LW1lZGl1bSB0ZXh0LXNtXCI+XG5cdFx0XHRcdHt0aXRsZX0gKHtmaWxlcy5sZW5ndGh9KVxuXHRcdFx0PC9oMz5cblxuXHRcdFx0PGRpdiBjbGFzc05hbWU9XCJmbGV4IGdhcC0yXCI+XG5cdFx0XHRcdHtzaG93QWRkQnV0dG9uICYmIChcblx0XHRcdFx0XHQ8QnV0dG9uXG5cdFx0XHRcdFx0XHR2YXJpYW50PVwib3V0bGluZVwiXG5cdFx0XHRcdFx0XHRzaXplPVwic21cIlxuXHRcdFx0XHRcdFx0b25DbGljaz17b3BlbkZpbGVEaWFsb2d9XG5cdFx0XHRcdFx0XHRkaXNhYmxlZD17IWNhbkFjY2VwdE1vcmV9XG5cdFx0XHRcdFx0PlxuXHRcdFx0XHRcdFx0PENsb3VkVXBsb2FkXG5cdFx0XHRcdFx0XHRcdGNsYXNzTmFtZT1cIi1tcy0wLjUgc2l6ZS0zLjUgb3BhY2l0eS02MFwiXG5cdFx0XHRcdFx0XHRcdGFyaWEtaGlkZGVuPVwidHJ1ZVwiXG5cdFx0XHRcdFx0XHQvPlxuXHRcdFx0XHRcdFx0e2FkZEJ1dHRvblRleHR9XG5cdFx0XHRcdFx0PC9CdXR0b24+XG5cdFx0XHRcdCl9XG5cblx0XHRcdFx0e3Nob3dDbGVhckJ1dHRvbiAmJiBmaWxlcy5sZW5ndGggPiAwICYmIChcblx0XHRcdFx0XHQ8QnV0dG9uIHZhcmlhbnQ9XCJvdXRsaW5lXCIgc2l6ZT1cInNtXCIgb25DbGljaz17cmVtb3ZlQWxsfT5cblx0XHRcdFx0XHRcdDxUcmFzaDJcblx0XHRcdFx0XHRcdFx0Y2xhc3NOYW1lPVwiLW1zLTAuNSBzaXplLTMuNSBvcGFjaXR5LTYwXCJcblx0XHRcdFx0XHRcdFx0YXJpYS1oaWRkZW49XCJ0cnVlXCJcblx0XHRcdFx0XHRcdC8+XG5cdFx0XHRcdFx0XHR7Y2xlYXJCdXR0b25UZXh0fVxuXHRcdFx0XHRcdDwvQnV0dG9uPlxuXHRcdFx0XHQpfVxuXHRcdFx0PC9kaXY+XG5cdFx0PC9kaXY+XG5cdCk7XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIExJU1QgQ09NUE9ORU5UXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbmZ1bmN0aW9uIEZpbGVQcmV2aWV3V2l0aFByb2dyZXNzKHtcblx0ZmlsZSxcblx0c2hvd1ByZXZpZXcsXG59OiB7XG5cdGZpbGU6IEZpbGVVcGxvYWQ7XG5cdHNob3dQcmV2aWV3OiBib29sZWFuO1xufSkge1xuXHRjb25zdCBbcHJldmlld1VybCwgc2V0UHJldmlld1VybF0gPSB1c2VTdGF0ZTxzdHJpbmcgfCBudWxsPihudWxsKTtcblx0Y29uc3QgW3ByZXZpZXdGYWlsZWQsIHNldFByZXZpZXdGYWlsZWRdID0gdXNlU3RhdGUoZmFsc2UpO1xuXG5cdHVzZUVmZmVjdCgoKSA9PiB7XG5cdFx0Ly8gQ3JlYXRlIHByZXZpZXcgVVJMIGlmIGl0J3MgYW4gaW1hZ2UgYW5kIHdlIGhhdmUgdGhlIGZpbGUgb3IgYSBwcmV2aWV3IFVSTFxuXHRcdGlmIChzaG93UHJldmlldyAmJiBmaWxlLnR5cGUuc3RhcnRzV2l0aChcImltYWdlL1wiKSkge1xuXHRcdFx0aWYgKGZpbGUucHJldmlldykge1xuXHRcdFx0XHQvLyBGb3IgcHJvdmlkZWQgcHJldmlldyBVUkxzLCB0ZXN0IGlmIHRoZXkgd29ya1xuXHRcdFx0XHRjb25zdCBpbWcgPSBuZXcgSW1hZ2UoKTtcblx0XHRcdFx0Y29uc3QgcHJldmlld1NyYyA9IGZpbGUucHJldmlldztcblx0XHRcdFx0aW1nLm9ubG9hZCA9ICgpID0+IHtcblx0XHRcdFx0XHRzZXRQcmV2aWV3VXJsKHByZXZpZXdTcmMpO1xuXHRcdFx0XHRcdHNldFByZXZpZXdGYWlsZWQoZmFsc2UpO1xuXHRcdFx0XHR9O1xuXHRcdFx0XHRpbWcub25lcnJvciA9ICgpID0+IHtcblx0XHRcdFx0XHRzZXRQcmV2aWV3RmFpbGVkKHRydWUpO1xuXHRcdFx0XHRcdHNldFByZXZpZXdVcmwobnVsbCk7XG5cdFx0XHRcdH07XG5cdFx0XHRcdGltZy5zcmMgPSBwcmV2aWV3U3JjO1xuXHRcdFx0fSBlbHNlIGlmIChmaWxlLmZpbGUgaW5zdGFuY2VvZiBGaWxlKSB7XG5cdFx0XHRcdGNvbnN0IHVybCA9IFVSTC5jcmVhdGVPYmplY3RVUkwoZmlsZS5maWxlKTtcblxuXHRcdFx0XHQvLyBUZXN0IGlmIHRoZSBicm93c2VyIGNhbiBhY3R1YWxseSByZW5kZXIgdGhpcyBpbWFnZVxuXHRcdFx0XHRjb25zdCBpbWcgPSBuZXcgSW1hZ2UoKTtcblx0XHRcdFx0aW1nLm9ubG9hZCA9ICgpID0+IHtcblx0XHRcdFx0XHRzZXRQcmV2aWV3VXJsKHVybCk7XG5cdFx0XHRcdFx0c2V0UHJldmlld0ZhaWxlZChmYWxzZSk7XG5cdFx0XHRcdH07XG5cdFx0XHRcdGltZy5vbmVycm9yID0gKCkgPT4ge1xuXHRcdFx0XHRcdHNldFByZXZpZXdGYWlsZWQodHJ1ZSk7XG5cdFx0XHRcdFx0c2V0UHJldmlld1VybChudWxsKTtcblx0XHRcdFx0XHRVUkwucmV2b2tlT2JqZWN0VVJMKHVybCk7XG5cdFx0XHRcdH07XG5cdFx0XHRcdGltZy5zcmMgPSB1cmw7XG5cblx0XHRcdFx0cmV0dXJuICgpID0+IHtcblx0XHRcdFx0XHRpZiAocHJldmlld1VybCA9PT0gdXJsKSB7XG5cdFx0XHRcdFx0XHRVUkwucmV2b2tlT2JqZWN0VVJMKHVybCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9O1xuXHRcdFx0fVxuXHRcdH1cblx0fSwgW2ZpbGUsIHNob3dQcmV2aWV3LCBwcmV2aWV3VXJsXSk7XG5cblx0Ly8gRm9yIGltYWdlcyB3aXRoIHByZXZpZXcgZW5hYmxlZCwgc2hvdyB3aXRoIGNpcmN1bGFyIHByb2dyZXNzIGluZGljYXRvclxuXHQvLyBPbmx5IHNob3cgaW1hZ2UgcHJldmlldyBpZiB3ZSBoYXZlIGEgdmFsaWQgcHJldmlldyBVUkwgYW5kIGl0IGRpZG4ndCBmYWlsIHRvIGxvYWRcblx0aWYgKFxuXHRcdHNob3dQcmV2aWV3ICYmXG5cdFx0cHJldmlld1VybCAmJlxuXHRcdCFwcmV2aWV3RmFpbGVkICYmXG5cdFx0ZmlsZS50eXBlLnN0YXJ0c1dpdGgoXCJpbWFnZS9cIilcblx0KSB7XG5cdFx0aWYgKGZpbGUuc3RhdHVzID09PSBcInBlbmRpbmdcIiB8fCBmaWxlLnN0YXR1cyA9PT0gXCJ1cGxvYWRpbmdcIikge1xuXHRcdFx0Y29uc3QgcHJvZ3Jlc3MgPSBmaWxlLnN0YXR1cyA9PT0gXCJwZW5kaW5nXCIgPyAwIDogZmlsZS5wcm9ncmVzcyB8fCAwO1xuXHRcdFx0cmV0dXJuIChcblx0XHRcdFx0PGRpdiBjbGFzc05hbWU9XCJyZWxhdGl2ZSBzaXplLTEwIG92ZXJmbG93LWhpZGRlbiByb3VuZGVkXCI+XG5cdFx0XHRcdFx0ey8qIERpbW1lZCBwcmV2aWV3IGltYWdlICovfVxuXHRcdFx0XHRcdDxpbWdcblx0XHRcdFx0XHRcdHNyYz17cHJldmlld1VybH1cblx0XHRcdFx0XHRcdGFsdD17ZmlsZS5uYW1lfVxuXHRcdFx0XHRcdFx0Y2xhc3NOYW1lPVwic2l6ZS0xMCBvYmplY3QtY292ZXIgb3BhY2l0eS00MFwiXG5cdFx0XHRcdFx0Lz5cblx0XHRcdFx0XHR7LyogQ2lyY3VsYXIgcHJvZ3Jlc3MgaW5kaWNhdG9yICovfVxuXHRcdFx0XHRcdDxzdmdcblx0XHRcdFx0XHRcdGNsYXNzTmFtZT1cIi1yb3RhdGUtOTAgYWJzb2x1dGUgaW5zZXQtMCBzaXplLTEwXCJcblx0XHRcdFx0XHRcdHZpZXdCb3g9XCIwIDAgNDAgNDBcIlxuXHRcdFx0XHRcdFx0YXJpYS1sYWJlbD17XG5cdFx0XHRcdFx0XHRcdGZpbGUuc3RhdHVzID09PSBcInBlbmRpbmdcIiA/IFwiUGVuZGluZyB1cGxvYWRcIiA6IFwiVXBsb2FkIHByb2dyZXNzXCJcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHQ+XG5cdFx0XHRcdFx0XHQ8dGl0bGU+XG5cdFx0XHRcdFx0XHRcdHtmaWxlLnN0YXR1cyA9PT0gXCJwZW5kaW5nXCIgPyBcIlBlbmRpbmcgdXBsb2FkXCIgOiBcIlVwbG9hZCBwcm9ncmVzc1wifVxuXHRcdFx0XHRcdFx0PC90aXRsZT5cblx0XHRcdFx0XHRcdHsvKiBCYWNrZ3JvdW5kIGNpcmNsZSAqL31cblx0XHRcdFx0XHRcdDxjaXJjbGVcblx0XHRcdFx0XHRcdFx0Y3g9XCIyMFwiXG5cdFx0XHRcdFx0XHRcdGN5PVwiMjBcIlxuXHRcdFx0XHRcdFx0XHRyPVwiMThcIlxuXHRcdFx0XHRcdFx0XHRmaWxsPVwibm9uZVwiXG5cdFx0XHRcdFx0XHRcdHN0cm9rZT1cImN1cnJlbnRDb2xvclwiXG5cdFx0XHRcdFx0XHRcdHN0cm9rZVdpZHRoPVwiMlwiXG5cdFx0XHRcdFx0XHRcdGNsYXNzTmFtZT1cInRleHQtYmFja2dyb3VuZC82MFwiXG5cdFx0XHRcdFx0XHQvPlxuXHRcdFx0XHRcdFx0ey8qIFByb2dyZXNzIGNpcmNsZSAqL31cblx0XHRcdFx0XHRcdDxjaXJjbGVcblx0XHRcdFx0XHRcdFx0Y3g9XCIyMFwiXG5cdFx0XHRcdFx0XHRcdGN5PVwiMjBcIlxuXHRcdFx0XHRcdFx0XHRyPVwiMThcIlxuXHRcdFx0XHRcdFx0XHRmaWxsPVwibm9uZVwiXG5cdFx0XHRcdFx0XHRcdHN0cm9rZT1cImN1cnJlbnRDb2xvclwiXG5cdFx0XHRcdFx0XHRcdHN0cm9rZVdpZHRoPVwiMlwiXG5cdFx0XHRcdFx0XHRcdHN0cm9rZURhc2hhcnJheT17YCR7MiAqIE1hdGguUEkgKiAxOH1gfVxuXHRcdFx0XHRcdFx0XHRzdHJva2VEYXNob2Zmc2V0PXtgJHsyICogTWF0aC5QSSAqIDE4ICogKDEgLSBwcm9ncmVzcyAvIDEwMCl9YH1cblx0XHRcdFx0XHRcdFx0Y2xhc3NOYW1lPVwidGV4dC1wcmltYXJ5IHRyYW5zaXRpb24tYWxsIGR1cmF0aW9uLTMwMFwiXG5cdFx0XHRcdFx0XHRcdHN0cm9rZUxpbmVjYXA9XCJyb3VuZFwiXG5cdFx0XHRcdFx0XHQvPlxuXHRcdFx0XHRcdDwvc3ZnPlxuXHRcdFx0XHQ8L2Rpdj5cblx0XHRcdCk7XG5cdFx0fVxuXHRcdC8vIENvbXBsZXRlZCBvciBlcnJvciBzdGF0ZSAtIHNob3cgZnVsbCBpbWFnZVxuXHRcdHJldHVybiAoXG5cdFx0XHQ8aW1nXG5cdFx0XHRcdHNyYz17cHJldmlld1VybH1cblx0XHRcdFx0YWx0PXtmaWxlLm5hbWV9XG5cdFx0XHRcdGNsYXNzTmFtZT1cInNpemUtMTAgcm91bmRlZCBvYmplY3QtY292ZXJcIlxuXHRcdFx0Lz5cblx0XHQpO1xuXHR9XG5cblx0Ly8gRm9yIG5vbi1pbWFnZSBmaWxlcywgdXNlIHRoZSBjaXJjdWxhciBwcm9ncmVzcyBpbmRpY2F0b3Jcblx0Y29uc3QgaWNvbkNvbnRlbnQgPSAoXG5cdFx0PGRpdiBjbGFzc05hbWU9XCJmbGV4IHNpemUtMTAgaXRlbXMtY2VudGVyIGp1c3RpZnktY2VudGVyXCI+XG5cdFx0XHR7Z2V0RmlsZUljb24oZmlsZSl9XG5cdFx0PC9kaXY+XG5cdCk7XG5cblx0aWYgKGZpbGUuc3RhdHVzID09PSBcInBlbmRpbmdcIikge1xuXHRcdHJldHVybiAoXG5cdFx0XHQ8ZGl2IGNsYXNzTmFtZT1cInJlbGF0aXZlIHNpemUtMTBcIj5cblx0XHRcdFx0e2ljb25Db250ZW50fVxuXHRcdFx0XHQ8c3ZnXG5cdFx0XHRcdFx0Y2xhc3NOYW1lPVwiYWJzb2x1dGUgaW5zZXQtMCBzaXplLTEwXCJcblx0XHRcdFx0XHR2aWV3Qm94PVwiMCAwIDQwIDQwXCJcblx0XHRcdFx0XHRhcmlhLWxhYmVsPVwiUGVuZGluZyB1cGxvYWRcIlxuXHRcdFx0XHQ+XG5cdFx0XHRcdFx0PHRpdGxlPlBlbmRpbmcgdXBsb2FkPC90aXRsZT5cblx0XHRcdFx0XHQ8Y2lyY2xlXG5cdFx0XHRcdFx0XHRjeD1cIjIwXCJcblx0XHRcdFx0XHRcdGN5PVwiMjBcIlxuXHRcdFx0XHRcdFx0cj1cIjE4XCJcblx0XHRcdFx0XHRcdGZpbGw9XCJub25lXCJcblx0XHRcdFx0XHRcdHN0cm9rZT1cImN1cnJlbnRDb2xvclwiXG5cdFx0XHRcdFx0XHRzdHJva2VXaWR0aD1cIjJcIlxuXHRcdFx0XHRcdFx0c3Ryb2tlRGFzaGFycmF5PVwiNCAzXCJcblx0XHRcdFx0XHRcdGNsYXNzTmFtZT1cInRleHQtbXV0ZWQtZm9yZWdyb3VuZC80MFwiXG5cdFx0XHRcdFx0Lz5cblx0XHRcdFx0PC9zdmc+XG5cdFx0XHQ8L2Rpdj5cblx0XHQpO1xuXHR9XG5cblx0aWYgKGZpbGUuc3RhdHVzID09PSBcInVwbG9hZGluZ1wiICYmIGZpbGUucHJvZ3Jlc3MgPiAwKSB7XG5cdFx0cmV0dXJuIChcblx0XHRcdDxkaXYgY2xhc3NOYW1lPVwicmVsYXRpdmUgc2l6ZS0xMFwiPlxuXHRcdFx0XHR7aWNvbkNvbnRlbnR9XG5cdFx0XHRcdDxzdmdcblx0XHRcdFx0XHRjbGFzc05hbWU9XCItcm90YXRlLTkwIGFic29sdXRlIGluc2V0LTAgc2l6ZS0xMFwiXG5cdFx0XHRcdFx0dmlld0JveD1cIjAgMCA0MCA0MFwiXG5cdFx0XHRcdFx0YXJpYS1sYWJlbD1cIlVwbG9hZCBwcm9ncmVzc1wiXG5cdFx0XHRcdD5cblx0XHRcdFx0XHQ8dGl0bGU+VXBsb2FkIHByb2dyZXNzPC90aXRsZT5cblx0XHRcdFx0XHQ8Y2lyY2xlXG5cdFx0XHRcdFx0XHRjeD1cIjIwXCJcblx0XHRcdFx0XHRcdGN5PVwiMjBcIlxuXHRcdFx0XHRcdFx0cj1cIjE4XCJcblx0XHRcdFx0XHRcdGZpbGw9XCJub25lXCJcblx0XHRcdFx0XHRcdHN0cm9rZT1cImN1cnJlbnRDb2xvclwiXG5cdFx0XHRcdFx0XHRzdHJva2VXaWR0aD1cIjJcIlxuXHRcdFx0XHRcdFx0Y2xhc3NOYW1lPVwidGV4dC1tdXRlZC1mb3JlZ3JvdW5kLzIwXCJcblx0XHRcdFx0XHQvPlxuXHRcdFx0XHRcdDxjaXJjbGVcblx0XHRcdFx0XHRcdGN4PVwiMjBcIlxuXHRcdFx0XHRcdFx0Y3k9XCIyMFwiXG5cdFx0XHRcdFx0XHRyPVwiMThcIlxuXHRcdFx0XHRcdFx0ZmlsbD1cIm5vbmVcIlxuXHRcdFx0XHRcdFx0c3Ryb2tlPVwiY3VycmVudENvbG9yXCJcblx0XHRcdFx0XHRcdHN0cm9rZVdpZHRoPVwiMlwiXG5cdFx0XHRcdFx0XHRzdHJva2VEYXNoYXJyYXk9e2AkezIgKiBNYXRoLlBJICogMTh9YH1cblx0XHRcdFx0XHRcdHN0cm9rZURhc2hvZmZzZXQ9e2AkezIgKiBNYXRoLlBJICogMTggKiAoMSAtIGZpbGUucHJvZ3Jlc3MgLyAxMDApfWB9XG5cdFx0XHRcdFx0XHRjbGFzc05hbWU9XCJ0ZXh0LXByaW1hcnkgdHJhbnNpdGlvbi1hbGwgZHVyYXRpb24tMzAwXCJcblx0XHRcdFx0XHRcdHN0cm9rZUxpbmVjYXA9XCJyb3VuZFwiXG5cdFx0XHRcdFx0Lz5cblx0XHRcdFx0PC9zdmc+XG5cdFx0XHQ8L2Rpdj5cblx0XHQpO1xuXHR9XG5cblx0cmV0dXJuIGljb25Db250ZW50O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0RmlsZUljb24oZmlsZTogRmlsZVR5cGUpIHtcblx0Y29uc3QgdHlwZSA9IGZpbGUgaW5zdGFuY2VvZiBGaWxlID8gZmlsZS50eXBlIDogZmlsZS50eXBlO1xuXHRjb25zdCBuYW1lID0gZmlsZSBpbnN0YW5jZW9mIEZpbGUgPyBmaWxlLm5hbWUgOiBmaWxlLm5hbWU7XG5cblx0aWYgKFxuXHRcdHR5cGUuaW5jbHVkZXMoXCJwZGZcIikgfHxcblx0XHRuYW1lLmVuZHNXaXRoKFwiLnBkZlwiKSB8fFxuXHRcdHR5cGUuaW5jbHVkZXMoXCJ3b3JkXCIpIHx8XG5cdFx0bmFtZS5lbmRzV2l0aChcIi5kb2NcIikgfHxcblx0XHRuYW1lLmVuZHNXaXRoKFwiLmRvY3hcIilcblx0KSB7XG5cdFx0cmV0dXJuIDxGaWxlVGV4dEljb24gY2xhc3NOYW1lPVwic2l6ZS00IG9wYWNpdHktNjBcIiAvPjtcblx0fVxuXHRpZiAoXG5cdFx0dHlwZS5pbmNsdWRlcyhcInppcFwiKSB8fFxuXHRcdHR5cGUuaW5jbHVkZXMoXCJhcmNoaXZlXCIpIHx8XG5cdFx0bmFtZS5lbmRzV2l0aChcIi56aXBcIikgfHxcblx0XHRuYW1lLmVuZHNXaXRoKFwiLnJhclwiKVxuXHQpIHtcblx0XHRyZXR1cm4gPEZpbGVBcmNoaXZlSWNvbiBjbGFzc05hbWU9XCJzaXplLTQgb3BhY2l0eS02MFwiIC8+O1xuXHR9XG5cdGlmIChcblx0XHR0eXBlLmluY2x1ZGVzKFwiZXhjZWxcIikgfHxcblx0XHRuYW1lLmVuZHNXaXRoKFwiLnhsc1wiKSB8fFxuXHRcdG5hbWUuZW5kc1dpdGgoXCIueGxzeFwiKVxuXHQpIHtcblx0XHRyZXR1cm4gPEZpbGVTcHJlYWRzaGVldEljb24gY2xhc3NOYW1lPVwic2l6ZS00IG9wYWNpdHktNjBcIiAvPjtcblx0fVxuXHRpZiAodHlwZS5pbmNsdWRlcyhcInZpZGVvL1wiKSkge1xuXHRcdHJldHVybiA8VmlkZW9JY29uIGNsYXNzTmFtZT1cInNpemUtNCBvcGFjaXR5LTYwXCIgLz47XG5cdH1cblx0aWYgKHR5cGUuaW5jbHVkZXMoXCJhdWRpby9cIikpIHtcblx0XHRyZXR1cm4gPEhlYWRwaG9uZXNJY29uIGNsYXNzTmFtZT1cInNpemUtNCBvcGFjaXR5LTYwXCIgLz47XG5cdH1cblx0aWYgKHR5cGUuc3RhcnRzV2l0aChcImltYWdlL1wiKSkge1xuXHRcdHJldHVybiA8SW1hZ2VJY29uIGNsYXNzTmFtZT1cInNpemUtNCBvcGFjaXR5LTYwXCIgLz47XG5cdH1cblx0cmV0dXJuIDxGaWxlSWNvbiBjbGFzc05hbWU9XCJzaXplLTQgb3BhY2l0eS02MFwiIC8+O1xufVxuXG5mdW5jdGlvbiBnZXRTdGF0dXNEaXNwbGF5KGZpbGU6IEZpbGVVcGxvYWQpIHtcblx0c3dpdGNoIChmaWxlLnN0YXR1cykge1xuXHRcdGNhc2UgXCJwZW5kaW5nXCI6XG5cdFx0XHRyZXR1cm4gPHAgY2xhc3NOYW1lPVwidGV4dC1tdXRlZC1mb3JlZ3JvdW5kIHRleHQteHNcIj5RdWV1ZWQ8L3A+O1xuXHRcdGNhc2UgXCJ1cGxvYWRpbmdcIjpcblx0XHRcdHJldHVybiAoXG5cdFx0XHRcdDxwIGNsYXNzTmFtZT1cInRleHQtbXV0ZWQtZm9yZWdyb3VuZCB0ZXh0LXhzXCI+XG5cdFx0XHRcdFx0VXBsb2FkaW5nIHtmaWxlLnByb2dyZXNzID8gYCR7TWF0aC5yb3VuZChmaWxlLnByb2dyZXNzKX0lYCA6IFwiXCJ9XG5cdFx0XHRcdDwvcD5cblx0XHRcdCk7XG5cdFx0Y2FzZSBcImNvbXBsZXRlXCI6XG5cdFx0XHRyZXR1cm4gKFxuXHRcdFx0XHQ8cCBjbGFzc05hbWU9XCJ0ZXh0LW11dGVkLWZvcmVncm91bmQgdGV4dC14c1wiPlxuXHRcdFx0XHRcdHtmb3JtYXRCeXRlcyhmaWxlLnNpemUpfVxuXHRcdFx0XHQ8L3A+XG5cdFx0XHQpO1xuXHRcdGNhc2UgXCJlcnJvclwiOlxuXHRcdFx0cmV0dXJuIChcblx0XHRcdFx0PHAgY2xhc3NOYW1lPVwidGV4dC1kZXN0cnVjdGl2ZSB0ZXh0LXhzXCI+XG5cdFx0XHRcdFx0e2ZpbGUuZXJyb3IgfHwgXCJVcGxvYWQgZmFpbGVkXCJ9XG5cdFx0XHRcdDwvcD5cblx0XHRcdCk7XG5cdFx0ZGVmYXVsdDpcblx0XHRcdHJldHVybiBudWxsO1xuXHR9XG59XG5cbmludGVyZmFjZSBMaXN0UHJvcHMge1xuXHRzaG93QWN0aW9ucz86IGJvb2xlYW47XG5cdHNob3dJbWFnZVByZXZpZXdzPzogYm9vbGVhbjtcblx0Y2xhc3NOYW1lPzogc3RyaW5nO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gTGlzdCh7XG5cdHNob3dBY3Rpb25zID0gdHJ1ZSxcblx0c2hvd0ltYWdlUHJldmlld3MgPSBmYWxzZSxcblx0Y2xhc3NOYW1lLFxufTogTGlzdFByb3BzKSB7XG5cdGNvbnN0IHsgZmlsZXMsIHJlbW92ZUZpbGUsIHJldHJ5VXBsb2FkIH0gPSB1c2VGaWxlVXBsb2FkKCk7XG5cblx0aWYgKGZpbGVzLmxlbmd0aCA9PT0gMCkge1xuXHRcdHJldHVybiBudWxsO1xuXHR9XG5cblx0cmV0dXJuIChcblx0XHQ8ZGl2IGNsYXNzTmFtZT17Y24oXCJzcGFjZS15LTJcIiwgY2xhc3NOYW1lKX0+XG5cdFx0XHR7ZmlsZXMubWFwKChmaWxlKSA9PiAoXG5cdFx0XHRcdDxkaXZcblx0XHRcdFx0XHRrZXk9e2ZpbGUuc2hhMjU2fVxuXHRcdFx0XHRcdGNsYXNzTmFtZT17Y24oXG5cdFx0XHRcdFx0XHRcImZsZXggaXRlbXMtY2VudGVyIGp1c3RpZnktYmV0d2VlbiBnYXAtMiByb3VuZGVkLWxnIGJvcmRlciBiZy1iYWNrZ3JvdW5kIHAtMiBwZS0zXCIsXG5cdFx0XHRcdFx0XHRmaWxlLnN0YXR1cyA9PT0gXCJwZW5kaW5nXCIgJiYgXCJvcGFjaXR5LTYwXCIsXG5cdFx0XHRcdFx0XHRmaWxlLmR1cGxpY2F0ZUFsZXJ0ICYmIFwiYmctcHJpbWFyeS8xMFwiLFxuXHRcdFx0XHRcdCl9XG5cdFx0XHRcdD5cblx0XHRcdFx0XHQ8ZGl2IGNsYXNzTmFtZT1cImZsZXggaXRlbXMtY2VudGVyIGdhcC0zIG92ZXJmbG93LWhpZGRlblwiPlxuXHRcdFx0XHRcdFx0PGRpdiBjbGFzc05hbWU9XCJzaHJpbmstMFwiPlxuXHRcdFx0XHRcdFx0XHQ8RmlsZVByZXZpZXdXaXRoUHJvZ3Jlc3Ncblx0XHRcdFx0XHRcdFx0XHRmaWxlPXtmaWxlfVxuXHRcdFx0XHRcdFx0XHRcdHNob3dQcmV2aWV3PXtzaG93SW1hZ2VQcmV2aWV3c31cblx0XHRcdFx0XHRcdFx0Lz5cblx0XHRcdFx0XHRcdDwvZGl2PlxuXHRcdFx0XHRcdFx0PGRpdiBjbGFzc05hbWU9XCJmbGV4IG1pbi13LTAgZmxleC1jb2wgZ2FwLTAuNVwiPlxuXHRcdFx0XHRcdFx0XHQ8cCBjbGFzc05hbWU9XCJ0cnVuY2F0ZSBmb250LW1lZGl1bSB0ZXh0LVsxM3B4XVwiPntmaWxlLm5hbWV9PC9wPlxuXHRcdFx0XHRcdFx0XHR7Z2V0U3RhdHVzRGlzcGxheShmaWxlKX1cblx0XHRcdFx0XHRcdDwvZGl2PlxuXHRcdFx0XHRcdDwvZGl2PlxuXG5cdFx0XHRcdFx0e3Nob3dBY3Rpb25zICYmIChcblx0XHRcdFx0XHRcdDxkaXYgY2xhc3NOYW1lPVwiZmxleCBpdGVtcy1jZW50ZXJcIj5cblx0XHRcdFx0XHRcdFx0e2ZpbGUuc3RhdHVzID09PSBcImVycm9yXCIgJiYgKFxuXHRcdFx0XHRcdFx0XHRcdDxCdXR0b25cblx0XHRcdFx0XHRcdFx0XHRcdHNpemU9XCJpY29uXCJcblx0XHRcdFx0XHRcdFx0XHRcdHZhcmlhbnQ9XCJnaG9zdFwiXG5cdFx0XHRcdFx0XHRcdFx0XHRjbGFzc05hbWU9XCJzaXplLTggdGV4dC1tdXRlZC1mb3JlZ3JvdW