@scaleflex/uploader 0.1.0 → 0.2.0

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.
Files changed (54) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/README.md +1 -1
  3. package/dist/auth/auth.service.d.ts.map +1 -1
  4. package/dist/components/actions-bar.d.ts +4 -1
  5. package/dist/components/actions-bar.d.ts.map +1 -1
  6. package/dist/components/camera-dialog.d.ts +2 -1
  7. package/dist/components/camera-dialog.d.ts.map +1 -1
  8. package/dist/components/drop-zone.d.ts +17 -0
  9. package/dist/components/drop-zone.d.ts.map +1 -1
  10. package/dist/components/file-item.d.ts.map +1 -1
  11. package/dist/components/file-list.d.ts.map +1 -1
  12. package/dist/components/provider-browser.d.ts +1 -0
  13. package/dist/components/provider-browser.d.ts.map +1 -1
  14. package/dist/components/screen-cast-dialog.d.ts +2 -1
  15. package/dist/components/screen-cast-dialog.d.ts.map +1 -1
  16. package/dist/components/shared-styles.d.ts +5 -0
  17. package/dist/components/shared-styles.d.ts.map +1 -0
  18. package/dist/components/source-pills.d.ts.map +1 -1
  19. package/dist/components/success-card.d.ts +3 -1
  20. package/dist/components/success-card.d.ts.map +1 -1
  21. package/dist/components/url-dialog.d.ts +2 -2
  22. package/dist/components/url-dialog.d.ts.map +1 -1
  23. package/dist/connectors/provider-registry.d.ts.map +1 -1
  24. package/dist/define.cjs +1 -1
  25. package/dist/define.js +1 -1
  26. package/dist/engine/upload-engine.d.ts.map +1 -1
  27. package/dist/events/public-events.d.ts +1 -3
  28. package/dist/events/public-events.d.ts.map +1 -1
  29. package/dist/index.cjs +1 -1
  30. package/dist/index.js +1 -1
  31. package/dist/{provider-browser-C-S_MPrC.js → provider-browser-CUbPlWmj.js} +430 -185
  32. package/dist/provider-browser-D7G2wcFH.cjs +820 -0
  33. package/dist/{search-provider-browser-jCOer2Y9.js → search-provider-browser-D_kyqQ2m.js} +30 -30
  34. package/dist/{search-provider-browser-DxmLznEB.cjs → search-provider-browser-uDZrkDBZ.cjs} +29 -29
  35. package/dist/sfx-uploader-Cxz9YHev.js +5387 -0
  36. package/dist/sfx-uploader-DbaSJxEf.cjs +3298 -0
  37. package/dist/sfx-uploader.d.ts +55 -1
  38. package/dist/sfx-uploader.d.ts.map +1 -1
  39. package/dist/store/store.types.d.ts +1 -1
  40. package/dist/store/store.types.d.ts.map +1 -1
  41. package/dist/types/source.types.d.ts +3 -0
  42. package/dist/types/source.types.d.ts.map +1 -1
  43. package/dist/utils/file-utils.d.ts +2 -0
  44. package/dist/utils/file-utils.d.ts.map +1 -1
  45. package/dist/utils/focus-trap.d.ts +7 -0
  46. package/dist/utils/focus-trap.d.ts.map +1 -0
  47. package/dist/utils/validate.d.ts +11 -0
  48. package/dist/utils/validate.d.ts.map +1 -1
  49. package/package.json +3 -2
  50. package/dist/events/event-bus.d.ts +0 -38
  51. package/dist/events/event-bus.d.ts.map +0 -1
  52. package/dist/provider-browser-CmCwv0ph.cjs +0 -581
  53. package/dist/sfx-uploader-BVDK-9xi.cjs +0 -2029
  54. package/dist/sfx-uploader-C2lWIRnU.js +0 -3789
@@ -1,2029 +0,0 @@
1
- "use strict";const l=require("lit"),d=require("lit/decorators.js"),ce=require("lit/directives/unsafe-svg.js");class de{constructor(e){this.listeners=new Set,this._notifying=!1,this._pendingState=null,this.state=e}getState(){return this.state}setState(e){if(this._notifying){this._pendingState={...this._pendingState||{},...e};return}const t=this.state;this.state={...t,...e},this._notifying=!0;try{this.listeners.forEach(r=>r(this.state,t))}finally{this._notifying=!1}if(this._pendingState){const r=this._pendingState;this._pendingState=null,this.setState(r)}}subscribe(e){return this.listeners.add(e),()=>this.listeners.delete(e)}destroy(){this.listeners.clear()}}function x(i,e,t){const r=i.getState().files,s=r.get(e);if(!s)return;const o=new Map(r);o.set(e,{...s,...t}),i.setState({files:o})}function I(i,e){const t=new Map(i.getState().files);t.set(e.id,e),i.setState({files:t})}function me(i,e){const t=i.getState().files;if(!t.has(e))return;const r=new Map(t);r.delete(e),i.setState({files:r})}function pe(){return new de({files:new Map,queueConfig:{concurrency:3,autoProceed:!1,retryConfig:{maxRetries:0,baseDelay:1e3,maxDelay:3e4,backoffFactor:2}},isPaused:!1,restrictions:{maxFileSize:null,maxTotalFilesSize:null,maxNumberOfFiles:null,minNumberOfFiles:null,allowedFileTypes:null,blockedFileTypes:null},targetFolder:"/",totalProgress:0,totalSpeed:0,totalBytesUploaded:0,totalBytes:0,isUploading:!1})}class xe{constructor(e,t){this.host=e,this.store=t,e.addController(this)}get state(){return this.store.getState()}setState(e){this.store.setState(e)}hostConnected(){this.unsubscribe=this.store.subscribe(()=>{this.host.requestUpdate()})}hostDisconnected(){var e;(e=this.unsubscribe)==null||e.call(this)}}function ve(i,e){const t=new XMLHttpRequest;let r=!1;const o=`${e.apiBase.replace(/\/+$/,"")}/v4/files?folder=${encodeURIComponent(e.folder)}`;t.open("POST",o);for(const[a,c]of Object.entries(e.authHeaders))t.setRequestHeader(a,c);t.upload.addEventListener("progress",a=>{a.lengthComputable&&!r&&e.onProgress(a.loaded,a.total)}),t.addEventListener("load",()=>{if(r)return;let a;try{a=JSON.parse(t.responseText)}catch{e.onError(new Error(`Invalid JSON response (HTTP ${t.status})`));return}t.status>=200&&t.status<300&&a.status==="success"?e.onComplete(a):e.onError(new Error(a.msg||`Upload failed (HTTP ${t.status})`))}),t.addEventListener("error",()=>{r||e.onError(new Error("Network error — check your connection"))}),t.addEventListener("timeout",()=>{r||e.onError(new Error("Upload timed out"))});const n=new FormData;if(i.file){const a={name:i.name,type:i.type};Object.keys(i.meta).length>0&&(a.meta=i.meta),i.tags.length>0&&(a.tags=i.tags),n.append("info[files[]]",JSON.stringify(a)),n.append("files[]",i.file,i.name)}return t.timeout=6e4,t.send(n),{abort(){r=!0,t.abort()}}}function ye(i,e){const t=new XMLHttpRequest;let r=!1;const o=`${e.apiBase.replace(/\/+$/,"")}/v4/files/upload_url`;t.open("POST",o);for(const[a,c]of Object.entries(e.authHeaders))t.setRequestHeader(a,c);if(t.setRequestHeader("Content-Type","application/json"),t.addEventListener("load",()=>{if(r)return;let a;try{a=JSON.parse(t.responseText)}catch{e.onError(new Error(`Invalid JSON response (HTTP ${t.status})`));return}t.status>=200&&t.status<300&&a.status==="success"?e.onComplete(a):e.onError(new Error(a.msg||`Upload failed (HTTP ${t.status})`))}),t.addEventListener("error",()=>{r||e.onError(new Error("Network error — check your connection"))}),t.addEventListener("timeout",()=>{r||e.onError(new Error("Upload timed out"))}),!i.remoteUrl)return e.onError(new Error("Remote URL is required for URL upload")),{abort(){}};const n={files_urls:[{url:i.remoteUrl,name:i.name}],dir:e.folder};return t.timeout=6e4,t.send(JSON.stringify(n)),{abort(){r=!0,t.abort()}}}function N(i){return{Accept:"application/json","Content-Type":"application/json","uppy-auth-token":i}}function P(i){return i.replace(/\/+$/,"")}const we={"google-drive":"drive",dropbox:"dropbox",onedrive:"onedrive",box:"box",instagram:"instagram",facebook:"facebook",unsplash:"unsplash"};function D(i){return we[i]??i}function _e(i,e){const t=P(i),r=btoa(JSON.stringify({origin:window.location.origin})),s=D(e);return`${t}/${s}/connect?state=${encodeURIComponent(r)}`}async function ke(i,e,t,r=""){const s=P(i),o=r?`/${r}`:"",n=D(e),a=await fetch(`${s}/${n}/list${o}`,{method:"GET",headers:N(t),credentials:"same-origin"});if(a.status===401)throw new V;if(!a.ok){const c=await a.json().catch(()=>null);throw new Error((c==null?void 0:c.message)||`Companion list failed (HTTP ${a.status})`)}return a.json()}async function Ce(i,e,t){const r=P(i),s=await fetch(`${r}/${t}`,{method:"GET",headers:N(e),credentials:"same-origin"});if(s.status===401)throw new V;if(!s.ok){const o=await s.json().catch(()=>null);throw new Error((o==null?void 0:o.message)||`Companion list failed (HTTP ${s.status})`)}return s.json()}async function Ee(i,e,t,r){const s=P(i),o=D(e),n=r?`q=${encodeURIComponent(t)}&${r}`:`q=${encodeURIComponent(t)}`,a=await fetch(`${s}/search/${o}/list?${n}`,{method:"GET",headers:{Accept:"application/json","Content-Type":"application/json"},credentials:"same-origin"});if(!a.ok){const c=await a.json().catch(()=>null);throw new Error((c==null?void 0:c.message)||`Search failed (HTTP ${a.status})`)}return a.json()}async function Se(i,e,t,r,s,o=!1){const n=P(i),a=D(e),c=o?`${n}/search/${a}/get/${r}`:`${n}/${a}/get/${r}`,u=o?{Accept:"application/json","Content-Type":"application/json"}:N(t),g=await fetch(c,{method:"POST",headers:u,credentials:"same-origin",body:JSON.stringify({...s,httpMethod:s.httpMethod??"POST",useFormData:s.useFormData??!0,fieldname:s.fieldname??"files[]"})});if(g.status===401)throw new V;if(!g.ok){const f=await g.json().catch(()=>null);throw new Error((f==null?void 0:f.message)||`Companion upload failed (HTTP ${g.status})`)}return g.json()}async function $e(i,e,t){const r=P(i),s=D(e),o=await fetch(`${r}/${s}/logout`,{method:"GET",headers:N(t),credentials:"same-origin"});return o.ok?o.json():{ok:!1,revoked:!1}}function Ue(i){var s;const t=((s=/^(?:https?:\/\/|\/\/)?(?:[^@\n]+@)?(?:www\.)?([^\n]+)/i.exec(i))==null?void 0:s[1])??i;return`${location.protocol==="https:"?"wss":"ws"}://${t}`}class V extends Error{constructor(){super("Authentication expired"),this.name="AuthExpiredError"}}function Pe(i,e){const t=i.remoteInfo;if(!t)return e.onError(new Error("remoteInfo is required for companion upload")),{abort(){}};let r=!1,s=null;const n=`${e.apiBase.replace(/\/+$/,"")}/v4/files?folder=${encodeURIComponent(e.folder)}`,a={};i.meta&&Object.keys(i.meta).length>0&&Object.assign(a,i.meta),i.tags&&i.tags.length>0&&(a.tags=i.tags);const c=!t.token;return Se(t.companionUrl,t.provider,t.token,t.requestPath,{fileId:t.fileId,endpoint:n,headers:e.authHeaders,size:t.size,metadata:Object.keys(a).length>0?a:void 0},c).then(u=>{if(r)return;const f=`${Ue(t.companionUrl)}/api/${u.token}`;try{s=new WebSocket(f)}catch{e.onError(new Error("Failed to connect to upload progress channel"));return}s.onmessage=p=>{var m,_,C;if(!r)try{const M=JSON.parse(p.data);switch(M.action){case"progress":{const v=M.payload,y=v.bytesUploaded??0,A=v.bytesTotal??(t.size||1);e.onProgress(y,A);break}case"success":{const v=M.payload;if(s==null||s.close(),(m=v.response)!=null&&m.responseText)try{const y=JSON.parse(v.response.responseText);if(y.status==="success"){e.onComplete(y);return}e.onError(new Error(y.msg||"Upload failed"));return}catch{}e.onError(new Error("Upload completed but no valid response received"));break}case"error":{s==null||s.close();const v=M.payload;let y=((_=v.error)==null?void 0:_.message)||"Upload failed";if((C=v.response)!=null&&C.responseText)try{const A=JSON.parse(v.response.responseText);y=A.hint||A.msg||A.message||y}catch{}e.onError(new Error(y));break}}}catch{}},s.onerror=()=>{r||e.onError(new Error("Upload progress connection failed"))},s.onclose=()=>{s=null}}).catch(u=>{r||e.onError(u instanceof Error?u:new Error(String(u)))}),{abort(){if(r=!0,s){try{s.send(JSON.stringify({action:"cancel",payload:{}}))}catch{}s.close(),s=null}}}}class ue{constructor(e,t){this.activeUploads=new Map,this.retryTimers=new Map,this.unsubscribe=null,this.store=e,this.config=t}start(){this.unsubscribe||(this.unsubscribe=this.store.subscribe(()=>this.processQueue()),this.processQueue())}uploadAll(){const{files:e}=this.store.getState();let t=!1;for(const r of e.values())r.status==="idle"?(x(this.store,r.id,{status:"queued"}),t=!0):r.status==="queued"&&(t=!0);t&&(this.store.setState({isUploading:!0}),this.processQueue())}retryFile(e){const t=this.store.getState().files.get(e);!t||t.status!=="error"&&t.status!=="failed"||(x(this.store,e,{status:"queued",error:null,progress:0,bytesUploaded:0,speed:0}),this.processQueue())}retryAll(){const{files:e}=this.store.getState();for(const t of e.values())(t.status==="error"||t.status==="failed")&&x(this.store,t.id,{status:"queued",error:null,progress:0,bytesUploaded:0,speed:0});this.processQueue()}cancelFile(e){this.abortUpload(e),x(this.store,e,{status:"cancelled"})}cancelAll(){const{files:e}=this.store.getState();for(const t of e.values())Re(t.status)&&(this.abortUpload(t.id),x(this.store,t.id,{status:"cancelled"}));this.store.setState({isUploading:!1})}updateConfig(e){Object.assign(this.config,e)}destroy(){var e;for(const t of this.activeUploads.keys())this.abortUpload(t);for(const t of this.retryTimers.values())clearTimeout(t);this.retryTimers.clear(),(e=this.unsubscribe)==null||e.call(this),this.unsubscribe=null}processQueue(){const e=this.store.getState();if(e.isPaused)return;const{concurrency:t}=e.queueConfig,r=this.activeUploads.size,s=t-r;if(s<=0)return;const n=[...e.files.values()].filter(a=>a.status==="queued").sort((a,c)=>a.retryCount!==c.retryCount?c.retryCount-a.retryCount:a.addedAt-c.addedAt).slice(0,s);for(const a of n)this.startUpload(a)}startUpload(e){x(this.store,e.id,{status:"uploading",error:null});let t=0,r=Date.now();const s={apiBase:this.config.apiBase,authHeaders:this.config.authHeaders,folder:this.store.getState().targetFolder,onComplete:a=>this.handleComplete(e.id,a),onError:a=>this.handleError(e.id,a)},o=(a,c)=>{const u=Date.now(),g=(u-r)/1e3,f=g>0?(a-t)/g:0;t=a,r=u;const p=c>0?a/c*100:0;x(this.store,e.id,{progress:p,bytesUploaded:a,speed:f}),this.updateTotalProgress()};let n;e.remoteInfo?n=Pe(e,{...s,onProgress:o}):e.remoteUrl?n=ye(e,s):n=ve(e,{...s,onProgress:o}),this.activeUploads.set(e.id,n)}handleComplete(e,t){this.activeUploads.delete(e),x(this.store,e,{status:"complete",progress:100,response:t}),this.updateTotalProgress(),this.checkAllComplete(),this.processQueue()}handleError(e,t){this.activeUploads.delete(e);const r=this.store.getState().files.get(e);if(!r)return;const{retryConfig:s}=this.store.getState().queueConfig,o=r.retryCount+1;if(o<=s.maxRetries){const n=Math.min(s.baseDelay*Math.pow(s.backoffFactor,r.retryCount),s.maxDelay);x(this.store,e,{status:"retrying",error:t.message,retryCount:o});const a=setTimeout(()=>{this.retryTimers.delete(e),x(this.store,e,{status:"queued"}),this.processQueue()},n);this.retryTimers.set(e,a)}else x(this.store,e,{status:"failed",error:t.message}),this.checkAllComplete(),this.processQueue()}abortUpload(e){var r;(r=this.activeUploads.get(e))==null||r.abort(),this.activeUploads.delete(e);const t=this.retryTimers.get(e);t&&(clearTimeout(t),this.retryTimers.delete(e))}updateTotalProgress(){const{files:e}=this.store.getState();let t=0,r=0,s=0;for(const o of e.values())(o.status==="uploading"||o.status==="complete")&&(t+=o.size,r+=o.bytesUploaded),o.status==="uploading"&&(s+=o.speed);this.store.setState({totalBytes:t,totalBytesUploaded:r,totalSpeed:s,totalProgress:t>0?r/t*100:0})}checkAllComplete(){const{files:e}=this.store.getState();![...e.values()].some(r=>r.status==="queued"||r.status==="uploading"||r.status==="retrying"||r.status==="preparing")&&this.store.getState().isUploading&&this.store.setState({isUploading:!1})}}function Re(i){return i==="queued"||i==="uploading"||i==="retrying"||i==="preparing"}function Y(i){return`https://api.filerobot.com/${i}`}async function he(i,e){const t=`${Y(i)}/key/${encodeURIComponent(e)}`,r=new AbortController,s=setTimeout(()=>r.abort(),3e4);try{const o=await fetch(t,{signal:r.signal});if(clearTimeout(s),!o.ok)throw new Error(`SASS key exchange failed (HTTP ${o.status})`);const n=await o.json();if(n.status==="error")throw new Error(`SASS key exchange failed: ${n.msg||"Unknown error"}`);return n.key}catch(o){throw clearTimeout(s),o instanceof DOMException&&o.name==="AbortError"?new Error("SASS key exchange timed out"):o}}function j(i,e){const t={};switch(i.mode){case"security-template":t["X-Filerobot-Key"]=e??i.securityTemplateId;break;case"sass-key":t["X-Filerobot-Key"]=i.sassKey;break;case"session":t["X-Filerobot-Session"]=i.sessionToken,i.companyToken&&(t["X-Company-Token"]=i.companyToken),i.projectToken&&(t["X-Project-Token"]=i.projectToken);break}return i.airboxPuid&&(t["X-Filerobot-Airbox-Puid"]=i.airboxPuid),t}async function fe(i){const e=Y(i.container);if(i.mode==="security-template"){const t=await he(i.container,i.securityTemplateId);return{apiBase:e,headers:j(i,t),sassKey:t}}return{apiBase:e,headers:j(i)}}const h={FILE_ADDED:"sfx-file-added",FILE_REMOVED:"sfx-file-removed",FILE_REJECTED:"sfx-file-rejected",UPLOAD_STARTED:"sfx-upload-started",UPLOAD_PROGRESS:"sfx-upload-progress",UPLOAD_COMPLETE:"sfx-upload-complete",UPLOAD_ERROR:"sfx-upload-error",UPLOAD_RETRY:"sfx-upload-retry",ALL_COMPLETE:"sfx-all-complete",TOTAL_PROGRESS:"sfx-total-progress",BEFORE_UPLOAD:"sfx-before-upload",OPEN:"sfx-open",CLOSE:"sfx-close",CANCEL:"sfx-cancel",SOURCE_CHANGE:"sfx-source-change",COMPLETE_ACTION:"sfx-complete-action",CONNECTOR_AUTH:"sfx-connector-auth",CONNECTOR_FILES_ADDED:"sfx-connector-files-added",FILE_PREVIEW:"sfx-file-preview",FILL_METADATA:"sfx-fill-metadata"};let ze=0;function F(){return`file-${Date.now()}-${++ze}`}function Ae(i){if(i===0)return"0 B";const e=["B","KB","MB","GB"],t=Math.min(Math.floor(Math.log(i)/Math.log(1024)),e.length-1),r=i/Math.pow(1024,t);return`${t===0?r:r.toFixed(1)} ${e[t]}`}function Le(i){var t;const e=((t=i.name.split(".").pop())==null?void 0:t.toLowerCase())??"";return i.type.startsWith("image/")?"image":i.type.startsWith("video/")||["mp4","mov","avi","webm","mkv"].includes(e)?"vid":i.type==="application/pdf"||e==="pdf"?"pdf":["doc","docx","xls","xlsx","ppt","pptx","txt","rtf","odt"].includes(e)?"doc":["zip","rar","7z","tar","gz","bz2"].includes(e)?"zip":"gen"}function Oe(i){const e=i.lastIndexOf(".");return e>=0?i.slice(e+1).toUpperCase():""}const De={jpg:"image/jpeg",jpeg:"image/jpeg",png:"image/png",gif:"image/gif",webp:"image/webp",svg:"image/svg+xml",bmp:"image/bmp",ico:"image/x-icon",mp4:"video/mp4",mov:"video/quicktime",avi:"video/x-msvideo",webm:"video/webm",pdf:"application/pdf",zip:"application/zip",doc:"application/msword",docx:"application/vnd.openxmlformats-officedocument.wordprocessingml.document"};function Te(i){var t;const e=((t=i.split(".").pop())==null?void 0:t.toLowerCase())??"";return De[e]||""}function Me(i,e,t){var r,s;if(e.maxFileSize!=null&&i.size>e.maxFileSize)return`File exceeds ${(e.maxFileSize/1048576).toFixed(1)} MB limit`;if(e.maxTotalFilesSize!=null){let o=i.size;for(const n of t.values())o+=n.size;if(o>e.maxTotalFilesSize)return"Total file size limit exceeded"}if(e.maxNumberOfFiles!=null&&t.size>=e.maxNumberOfFiles)return`Maximum ${e.maxNumberOfFiles} files allowed`;if(e.allowedFileTypes!=null){const o=e.allowedFileTypes,n="."+(((r=i.name.split(".").pop())==null?void 0:r.toLowerCase())??"");if(!o.some(c=>c.startsWith(".")?n===c.toLowerCase():c.endsWith("/*")?i.type.startsWith(c.slice(0,-1)):i.type===c))return"File type not allowed"}if(e.blockedFileTypes!=null){const o=e.blockedFileTypes,n="."+(((s=i.name.split(".").pop())==null?void 0:s.toLowerCase())??"");if(o.some(c=>c.startsWith(".")?n===c.toLowerCase():i.type===c))return"File type is blocked"}return null}function Ie(i){return i.allowedFileTypes?i.allowedFileTypes.join(","):""}const ae={"google-drive":{id:"google-drive",label:"Google Drive",fillIcon:!0,icon:'<path d="M7.71 3.5L1.15 15l2.98 5.16h3.46L1.15 8.66 4.13 3.5h3.58zm1.04 0L15.3 15l-2.98 5.16H8.86L15.3 8.66 12.33 3.5H8.75zm7.54 5.16L22.85 15l-2.98 5.16-6.56-11.5h6.56z" fill="currentColor"/>'},dropbox:{id:"dropbox",label:"Dropbox",fillIcon:!0,icon:'<path d="M12 2L6.5 5.75 12 9.5l5.5-3.75L12 2zM6.5 5.75L1 9.5l5.5 3.75L12 9.5 6.5 5.75zM17.5 5.75L12 9.5l5.5 3.75L23 9.5l-5.5-3.75zM1 9.5l5.5 3.75L12 9.5 6.5 5.75 1 9.5zm22 0l-5.5 3.75L12 9.5l5.5-3.75L23 9.5zM6.5 14.5L12 18.25l5.5-3.75L12 10.75 6.5 14.5z" fill="currentColor"/>'},onedrive:{id:"onedrive",label:"OneDrive",fillIcon:!0,icon:'<path d="M10.07 8.82a5.5 5.5 0 0 1 8.6 1.43A4.5 4.5 0 0 1 19.5 19H6a4 4 0 0 1-.67-7.95 5.49 5.49 0 0 1 4.74-2.23z" fill="currentColor"/>'},box:{id:"box",label:"Box",fillIcon:!0,icon:'<path d="M12 2L3 7v10l9 5 9-5V7l-9-5zm0 2.18L18.36 7.5 12 10.82 5.64 7.5 12 4.18zM5 8.82l6 3.33v6.67l-6-3.33V8.82zm14 0v6.67l-6 3.33v-6.67l6-3.33z" fill="currentColor"/>'},instagram:{id:"instagram",label:"Instagram",fillIcon:!0,icon:'<path d="M12 2.16c2.94 0 3.29.01 4.45.06 1.07.05 1.8.22 2.43.46.66.25 1.21.6 1.77 1.16.55.55.9 1.1 1.16 1.77.25.64.41 1.37.46 2.43.05 1.16.06 1.51.06 4.45s-.01 3.29-.06 4.45c-.05 1.07-.22 1.8-.46 2.43a4.9 4.9 0 0 1-1.16 1.77c-.55.55-1.1.9-1.77 1.16-.64.25-1.37.41-2.43.46-1.16.05-1.51.06-4.45.06s-3.29-.01-4.45-.06c-1.07-.05-1.8-.22-2.43-.46a4.9 4.9 0 0 1-1.77-1.16 4.9 4.9 0 0 1-1.16-1.77c-.25-.64-.41-1.37-.46-2.43C2.17 15.29 2.16 14.94 2.16 12s.01-3.29.06-4.45c.05-1.07.22-1.8.46-2.43a4.9 4.9 0 0 1 1.16-1.77A4.9 4.9 0 0 1 5.61 2.2c.64-.25 1.37-.41 2.43-.46C9.21 2.17 9.56 2.16 12 2.16zM12 0C8.97 0 8.6.01 7.43.07 6.26.12 5.45.3 4.73.58a6.9 6.9 0 0 0-2.5 1.63A6.9 6.9 0 0 0 .58 4.73C.3 5.45.12 6.26.07 7.43.01 8.6 0 8.97 0 12s.01 3.4.07 4.57c.05 1.17.23 1.98.51 2.7a6.9 6.9 0 0 0 1.63 2.5 6.9 6.9 0 0 0 2.5 1.63c.72.28 1.53.46 2.7.51C8.6 23.99 8.97 24 12 24s3.4-.01 4.57-.07c1.17-.05 1.98-.23 2.7-.51a6.9 6.9 0 0 0 2.5-1.63 6.9 6.9 0 0 0 1.63-2.5c.28-.72.46-1.53.51-2.7.06-1.17.07-1.54.07-4.57s-.01-3.4-.07-4.57c-.05-1.17-.23-1.98-.51-2.7a6.9 6.9 0 0 0-1.63-2.5A6.9 6.9 0 0 0 19.27.58C18.55.3 17.74.12 16.57.07 15.4.01 15.03 0 12 0zm0 5.84a6.16 6.16 0 1 0 0 12.32 6.16 6.16 0 0 0 0-12.32zM12 16a4 4 0 1 1 0-8 4 4 0 0 1 0 8zm6.4-11.85a1.44 1.44 0 1 0 0 2.88 1.44 1.44 0 0 0 0-2.88z" fill="currentColor"/>'},facebook:{id:"facebook",label:"Facebook",fillIcon:!0,icon:'<path d="M24 12.07C24 5.41 18.63 0 12 0S0 5.41 0 12.07c0 6.02 4.39 11.02 10.12 11.93v-8.44H7.08v-3.49h3.04V9.41c0-3.02 1.79-4.69 4.53-4.69 1.31 0 2.68.24 2.68.24v2.97h-1.51c-1.49 0-1.95.93-1.95 1.89v2.26h3.33l-.53 3.49h-2.8v8.44C19.61 23.09 24 18.09 24 12.07z" fill="currentColor"/>'},unsplash:{id:"unsplash",label:"Unsplash",fillIcon:!0,icon:'<path d="M7.5 6.75V0h9v6.75h-9zM0 24V10.5h7.5v6.75h9V10.5H24V24H0z" fill="currentColor"/>'}};function ge(i){return i.filter(e=>e in ae).map(e=>ae[e])}var Fe=Object.defineProperty,je=(i,e,t,r)=>{for(var s=void 0,o=i.length-1,n;o>=0;o--)(n=i[o])&&(s=n(e,t,s)||s);return s&&Fe(e,t,s),s};const Be='<rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/>',He='<path d="M10 13a5 5 0 007.54.54l3-3a5 5 0 00-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 00-7.54-.54l-3 3a5 5 0 007.07 7.07l1.71-1.71"/>',qe='<path d="M23 19a2 2 0 01-2 2H3a2 2 0 01-2-2V8a2 2 0 012-2h4l2-3h6l2 3h4a2 2 0 012 2z"/><circle cx="12" cy="13" r="4"/>',Ne='<rect x="2" y="3" width="20" height="14" rx="2"/><circle cx="12" cy="10" r="3"/><path d="M7 21h10"/>',L=[{id:"device",label:"My Device",icon:Be},{id:"url",label:"URL link",icon:He},{id:"camera",label:"Camera",icon:qe},{id:"screen-cast",label:"Screen cast",icon:Ne}],X=class X extends l.LitElement{constructor(){super(...arguments),this.sources=L}_handleClick(e){this.dispatchEvent(new CustomEvent("source-click",{detail:{source:e.id},bubbles:!0,composed:!0}))}render(){return l.html`
2
- ${this.sources.map(e=>l.html`
3
- <button @click=${()=>this._handleClick(e)}>
4
- ${l.svg`<svg viewBox="0 0 24 24" class=${e.fillIcon?"fill-icon":""}>${ce.unsafeSVG(e.icon)}</svg>`}
5
- ${e.label}
6
- </button>
7
- `)}
8
- `}};X.styles=l.css`
9
- :host {
10
- display: flex;
11
- flex-wrap: wrap;
12
- gap: 8px;
13
- justify-content: center;
14
- }
15
-
16
- button {
17
- display: inline-flex;
18
- align-items: center;
19
- gap: 9px;
20
- padding: 13px 24px;
21
- border-radius: 50px;
22
- border: 1.5px solid var(--sfx-up-border, #e8edf5);
23
- background: var(--sfx-up-bg, #fff);
24
- font-size: 14px;
25
- font-weight: 500;
26
- color: var(--sfx-up-text-secondary, #475569);
27
- cursor: pointer;
28
- transition: all 0.18s ease;
29
- white-space: nowrap;
30
- box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);
31
- font-family: inherit;
32
- }
33
-
34
- button:hover {
35
- border-color: var(--sfx-up-primary, #2563eb);
36
- color: var(--sfx-up-primary, #2563eb);
37
- background: var(--sfx-up-primary-bg, #eff6ff);
38
- box-shadow: 0 2px 10px var(--sfx-up-primary-glow, rgba(37, 99, 235, 0.18));
39
- transform: translateY(-1px);
40
- }
41
-
42
- button:active {
43
- transform: translateY(0) scale(0.98);
44
- }
45
-
46
- svg {
47
- width: 17px;
48
- height: 17px;
49
- flex-shrink: 0;
50
- fill: none;
51
- stroke: currentColor;
52
- stroke-width: 2;
53
- stroke-linecap: round;
54
- }
55
-
56
- svg.fill-icon {
57
- fill: currentColor;
58
- stroke: none;
59
- stroke-width: 0;
60
- }
61
- `;let B=X;je([d.property({type:Array})],B.prototype,"sources");var Ve=Object.defineProperty,R=(i,e,t,r)=>{for(var s=void 0,o=i.length-1,n;o>=0;o--)(n=i[o])&&(s=n(e,t,s)||s);return s&&Ve(e,t,s),s};const Q=class Q extends l.LitElement{constructor(){super(...arguments),this.compact=!1,this.accept="",this.sources=[],this._dragOver=!1,this._dragCounter=0,this._onDragEnter=e=>{e.preventDefault(),this._dragCounter++,this._dragCounter===1&&(this._dragOver=!0)},this._onDragOver=e=>{e.preventDefault()},this._onDragLeave=e=>{e.preventDefault(),this._dragCounter--,this._dragCounter<=0&&(this._dragCounter=0,this._dragOver=!1)},this._onDrop=e=>{var r;e.preventDefault(),this._dragCounter=0,this._dragOver=!1;const t=Array.from(((r=e.dataTransfer)==null?void 0:r.files)??[]);t.length>0&&this._emitFiles(t)},this._onClick=e=>{const t=this.shadowRoot.querySelector(".drop-zone");if(t&&this._rippleEl){const r=t.getBoundingClientRect();this._rippleEl.style.left=`${e.clientX-r.left}px`,this._rippleEl.style.top=`${e.clientY-r.top}px`,this._rippleEl.classList.remove("go"),this._rippleEl.offsetWidth,this._rippleEl.classList.add("go")}this.browse()},this._onKeyDown=e=>{(e.key==="Enter"||e.key===" ")&&(e.preventDefault(),this.browse())},this._onFileChange=e=>{const t=e.target,r=Array.from(t.files??[]);r.length>0&&this._emitFiles(r),t.value=""},this._onPaste=e=>{var s;if(!this.isConnected||this.offsetWidth===0)return;const t=(s=e.clipboardData)==null?void 0:s.items;if(!t)return;const r=[];for(const o of t)if(o.kind==="file"){const n=o.getAsFile();n&&r.push(n)}r.length>0&&(e.preventDefault(),this._emitFiles(r))}}browse(){var e;(e=this.fileInput)==null||e.click()}_onSourceIconClick(e){this.dispatchEvent(new CustomEvent("source-click",{detail:{source:e.id},bubbles:!0,composed:!0}))}_emitFiles(e){this.dispatchEvent(new CustomEvent("files-selected",{detail:{files:e},bubbles:!0,composed:!0}))}connectedCallback(){super.connectedCallback(),document.addEventListener("paste",this._onPaste)}disconnectedCallback(){super.disconnectedCallback(),document.removeEventListener("paste",this._onPaste)}render(){const e=["drop-zone",this._dragOver?"drag-over":"",this.compact?"compact":""].filter(Boolean).join(" ");return l.html`
62
- <div
63
- class=${e}
64
- role="button"
65
- tabindex="0"
66
- aria-label="Drop files here or click to browse"
67
- @dragenter=${this._onDragEnter}
68
- @dragover=${this._onDragOver}
69
- @dragleave=${this._onDragLeave}
70
- @drop=${this._onDrop}
71
- @click=${this._onClick}
72
- @keydown=${this._onKeyDown}
73
- >
74
- <div class="rings">
75
- <div class="ring"></div>
76
- <div class="ring"></div>
77
- <div class="core">
78
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round">
79
- <polyline points="16 16 12 12 8 16" />
80
- <line x1="12" y1="12" x2="12" y2="21" />
81
- <path d="M20.39 18.39A5 5 0 0018 9h-1.26A8 8 0 103 16.3" />
82
- </svg>
83
- </div>
84
- </div>
85
-
86
- <div class="title">
87
- Drag & Drop or click to <span>browse</span>
88
- </div>
89
- ${this.compact?l.nothing:l.html`<div class="subtitle">Drop files anywhere on this page</div>`}
90
-
91
- ${this.compact&&this.sources.length>0?l.html`
92
- <div class="sources-row">
93
- <span class="src-divider"></span>
94
- ${this.sources.map(t=>l.html`
95
- <button
96
- class="src-ico"
97
- data-tip=${t.label}
98
- @click=${r=>{r.stopPropagation(),this._onSourceIconClick(t)}}
99
- >
100
- ${l.svg`<svg viewBox="0 0 24 24" class=${t.fillIcon?"fill-icon":""}>${ce.unsafeSVG(t.icon)}</svg>`}
101
- </button>
102
- `)}
103
- </div>
104
- `:l.nothing}
105
-
106
- <div class="ripple"></div>
107
- <input
108
- type="file"
109
- multiple
110
- accept=${this.accept||l.nothing}
111
- @change=${this._onFileChange}
112
- />
113
- </div>
114
- `}};Q.styles=l.css`
115
- :host {
116
- display: block;
117
- flex-shrink: 0;
118
- }
119
-
120
- .drop-zone {
121
- border: 1.5px dashed var(--sfx-up-border, #d8d8d8);
122
- border-radius: var(--sfx-up-radius, 16px);
123
- background: var(--sfx-up-bg, #ffffff);
124
- padding: 52px 40px 44px;
125
- display: flex;
126
- flex-direction: column;
127
- align-items: center;
128
- justify-content: center;
129
- text-align: center;
130
- cursor: pointer;
131
- position: relative;
132
- overflow: hidden;
133
- transition: border-color 0.22s, background 0.22s, padding 0.35s ease;
134
- user-select: none;
135
- }
136
-
137
- .drop-zone:hover {
138
- border-color: #bbb;
139
- background: #fafafa;
140
- }
141
-
142
- /* Drag over state */
143
- .drop-zone.drag-over {
144
- border: 2px solid var(--sfx-up-primary, #2563eb);
145
- background: var(--sfx-up-primary-bg, #eff6ff);
146
- box-shadow: 0 0 0 5px rgba(37, 99, 235, 0.06);
147
- }
148
-
149
- /* Compact state when files exist */
150
- .drop-zone.compact {
151
- padding: 14px 24px;
152
- flex-direction: row;
153
- align-items: center;
154
- gap: 12px;
155
- justify-content: flex-start;
156
- overflow: visible;
157
- }
158
-
159
- /* --- Rings --- */
160
- .rings {
161
- width: 110px;
162
- height: 110px;
163
- position: relative;
164
- display: flex;
165
- align-items: center;
166
- justify-content: center;
167
- margin-bottom: 20px;
168
- flex-shrink: 0;
169
- }
170
-
171
- .ring {
172
- position: absolute;
173
- inset: 0;
174
- border-radius: 50%;
175
- border: 1.5px dashed #c4d5ef;
176
- animation: slowSpin 20s linear infinite;
177
- transition: border-color 0.3s;
178
- }
179
-
180
- .ring:nth-child(2) {
181
- inset: 13px;
182
- border-color: #d8e5f5;
183
- border-style: dotted;
184
- animation-direction: reverse;
185
- animation-duration: 14s;
186
- }
187
-
188
- .drag-over .ring {
189
- border-color: var(--sfx-up-primary, #2563eb);
190
- animation-duration: 3s;
191
- }
192
-
193
- .drag-over .ring:nth-child(2) {
194
- border-color: rgba(37, 99, 235, 0.4);
195
- animation-duration: 2s;
196
- }
197
-
198
- .compact .rings {
199
- width: 36px;
200
- height: 36px;
201
- margin-bottom: 0;
202
- }
203
-
204
- .compact .ring {
205
- border-width: 1px;
206
- }
207
-
208
- /* --- Core icon --- */
209
- .core {
210
- width: 54px;
211
- height: 54px;
212
- border-radius: 50%;
213
- background: var(--sfx-up-primary-bg, #eff6ff);
214
- color: var(--sfx-up-primary, #2563eb);
215
- display: flex;
216
- align-items: center;
217
- justify-content: center;
218
- z-index: 1;
219
- transition: all 0.28s cubic-bezier(0.34, 1.4, 0.64, 1);
220
- box-shadow: 0 3px 12px rgba(37, 99, 235, 0.15);
221
- }
222
-
223
- .core svg {
224
- width: 24px;
225
- height: 24px;
226
- }
227
-
228
- .drop-zone:hover .core {
229
- transform: translateY(-2px);
230
- box-shadow: 0 5px 18px rgba(37, 99, 235, 0.22);
231
- }
232
-
233
- .drag-over .core {
234
- background: var(--sfx-up-primary, #2563eb);
235
- color: #fff;
236
- transform: scale(1.12);
237
- box-shadow: 0 8px 24px rgba(37, 99, 235, 0.38);
238
- }
239
-
240
- .compact .core {
241
- width: 36px;
242
- height: 36px;
243
- box-shadow: none;
244
- }
245
-
246
- .compact .core svg {
247
- width: 16px;
248
- height: 16px;
249
- }
250
-
251
- /* --- Text --- */
252
- .title {
253
- font-size: 18px;
254
- font-weight: 700;
255
- color: var(--sfx-up-text, #1e293b);
256
- margin-bottom: 5px;
257
- transition: font-size 0.3s, margin 0.3s;
258
- }
259
-
260
- .title span {
261
- color: var(--sfx-up-primary, #2563eb);
262
- cursor: pointer;
263
- }
264
-
265
- .subtitle {
266
- font-size: 13px;
267
- color: var(--sfx-up-text-muted, #94a3b8);
268
- transition: opacity 0.2s;
269
- }
270
-
271
- .compact .title {
272
- font-size: 13.5px;
273
- font-weight: 600;
274
- margin-bottom: 0;
275
- white-space: nowrap;
276
- overflow: hidden;
277
- text-overflow: ellipsis;
278
- }
279
-
280
- .compact .subtitle {
281
- display: none;
282
- }
283
-
284
- /* --- Source icons row (compact mode) --- */
285
- .sources-row {
286
- display: none;
287
- }
288
-
289
- .compact .sources-row {
290
- display: flex;
291
- align-items: center;
292
- gap: 6px;
293
- margin-left: auto;
294
- flex-shrink: 0;
295
- position: relative;
296
- z-index: 20;
297
- }
298
-
299
- .src-divider {
300
- width: 1px;
301
- height: 20px;
302
- background: #e5e7eb;
303
- margin-right: 2px;
304
- flex-shrink: 0;
305
- }
306
-
307
- .src-ico {
308
- width: 28px;
309
- height: 28px;
310
- border-radius: 50%;
311
- border: none;
312
- background: #f3f4f6;
313
- cursor: pointer;
314
- display: flex;
315
- align-items: center;
316
- justify-content: center;
317
- transition: transform 0.18s ease, box-shadow 0.18s ease, background 0.15s;
318
- position: relative;
319
- flex-shrink: 0;
320
- color: #6b7280;
321
- padding: 0;
322
- font-family: inherit;
323
- }
324
-
325
- .src-ico svg {
326
- width: 14px;
327
- height: 14px;
328
- fill: none;
329
- stroke: currentColor;
330
- stroke-width: 2;
331
- stroke-linecap: round;
332
- }
333
-
334
- .src-ico svg.fill-icon {
335
- fill: currentColor;
336
- stroke: none;
337
- stroke-width: 0;
338
- }
339
-
340
- .src-ico:hover {
341
- transform: scale(1.18);
342
- box-shadow: 0 2px 10px rgba(0, 0, 0, 0.12);
343
- background: #fff;
344
- color: #374151;
345
- }
346
-
347
- .src-ico::after {
348
- content: attr(data-tip);
349
- position: absolute;
350
- bottom: -28px;
351
- left: 50%;
352
- transform: translateX(-50%);
353
- background: #fff;
354
- color: #374151;
355
- font-size: 10px;
356
- font-weight: 500;
357
- border: 1px solid #e5e7eb;
358
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
359
- padding: 3px 8px;
360
- border-radius: 5px;
361
- white-space: nowrap;
362
- opacity: 0;
363
- visibility: hidden;
364
- transition: opacity 0.15s, visibility 0.15s;
365
- pointer-events: none;
366
- z-index: 50;
367
- font-family: inherit;
368
- }
369
-
370
- .src-ico:hover::after {
371
- opacity: 1;
372
- visibility: visible;
373
- }
374
-
375
- /* --- Ripple --- */
376
- .ripple {
377
- position: absolute;
378
- width: 10px;
379
- height: 10px;
380
- border-radius: 50%;
381
- background: var(--sfx-up-primary, #2563eb);
382
- opacity: 0;
383
- pointer-events: none;
384
- transform: translate(-50%, -50%) scale(0);
385
- }
386
-
387
- .ripple.go {
388
- animation: ripple 0.55s ease-out forwards;
389
- }
390
-
391
- /* --- Hidden input --- */
392
- input[type='file'] {
393
- display: none;
394
- }
395
-
396
- @keyframes slowSpin {
397
- to {
398
- transform: rotate(360deg);
399
- }
400
- }
401
-
402
- @keyframes ripple {
403
- from {
404
- transform: translate(-50%, -50%) scale(0);
405
- opacity: 0.18;
406
- }
407
- to {
408
- transform: translate(-50%, -50%) scale(12);
409
- opacity: 0;
410
- }
411
- }
412
-
413
- @media (prefers-reduced-motion: reduce) {
414
- .ring {
415
- animation: none;
416
- }
417
- .ripple.go {
418
- animation: none;
419
- }
420
- }
421
- `;let w=Q;R([d.property({type:Boolean})],w.prototype,"compact");R([d.property({type:String})],w.prototype,"accept");R([d.property({type:Array})],w.prototype,"sources");R([d.state()],w.prototype,"_dragOver");R([d.query(".ripple")],w.prototype,"_rippleEl");R([d.query('input[type="file"]')],w.prototype,"fileInput");const Z=class Z extends l.LitElement{render(){return l.html`
422
- <div class="line"></div>
423
- <div class="label">or import from</div>
424
- <div class="line"></div>
425
- `}};Z.styles=l.css`
426
- :host {
427
- display: flex;
428
- align-items: center;
429
- gap: 14px;
430
- padding: 20px 0;
431
- }
432
-
433
- .line {
434
- flex: 1;
435
- height: 1px;
436
- background: var(--sfx-up-border-light, #f1f5f9);
437
- }
438
-
439
- .label {
440
- font-size: 11px;
441
- font-weight: 600;
442
- color: var(--sfx-up-text-muted, #cbd5e1);
443
- text-transform: uppercase;
444
- letter-spacing: 1px;
445
- white-space: nowrap;
446
- }
447
- `;let G=Z;var Ye=Object.defineProperty,Ke=(i,e,t,r)=>{for(var s=void 0,o=i.length-1,n;o>=0;o--)(n=i[o])&&(s=n(e,t,s)||s);return s&&Ye(e,t,s),s};const ee=class ee extends l.LitElement{constructor(){super(...arguments),this.files=[]}render(){return l.html`
448
- <div class="grid">
449
- ${this.files.map(e=>l.html`<sfx-file-item .file=${e}></sfx-file-item>`)}
450
- </div>
451
- `}};ee.styles=l.css`
452
- :host {
453
- display: block;
454
- flex: 1;
455
- overflow-y: auto;
456
- min-height: 0;
457
- }
458
-
459
- .grid {
460
- display: grid;
461
- grid-template-columns: repeat(auto-fill, minmax(186px, 1fr));
462
- gap: 12px;
463
- }
464
- `;let H=ee;Ke([d.property({attribute:!1})],H.prototype,"files");var Je=Object.defineProperty,We=(i,e,t,r)=>{for(var s=void 0,o=i.length-1,n;o>=0;o--)(n=i[o])&&(s=n(e,t,s)||s);return s&&Je(e,t,s),s};const te=class te extends l.LitElement{_remove(){this.dispatchEvent(new CustomEvent("file-remove",{detail:{fileId:this.file.id},bubbles:!0,composed:!0}))}_retry(){this.dispatchEvent(new CustomEvent("file-retry",{detail:{fileId:this.file.id},bubbles:!0,composed:!0}))}_preview(e){e.stopPropagation(),this.dispatchEvent(new CustomEvent("file-preview",{detail:{fileId:this.file.id},bubbles:!0,composed:!0}))}render(){const e=this.file;if(!e)return l.nothing;const t=Le(e),r=t==="image",s=e.status==="complete",o=e.status==="uploading",n=e.status==="error"||e.status==="failed",a=Oe(e.name),c=["tile",s?"done":"",o?"uploading":""].filter(Boolean).join(" ");return l.html`
465
- <div class=${c}>
466
- <!-- Preview area -->
467
- <div class="preview">
468
- ${r&&e.previewUrl?l.html`<div class="preview-bg" style="background-image:url(${e.previewUrl})"></div>`:l.html`
469
- <div class="preview-bg ${t}"></div>
470
- <div class="type-icon">
471
- <div class="type-icon-inner ${t}">
472
- ${this._renderTypeIcon(t)}
473
- ${a?l.html`<div class="ext-label">${a}</div>`:l.nothing}
474
- </div>
475
- </div>
476
- `}
477
-
478
- <!-- Preview button -->
479
- ${!s&&!o&&!n&&e.status!=="rejected"?l.html`
480
- <button class="preview-btn" @click=${this._preview} aria-label="Preview file">
481
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
482
- <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/>
483
- <circle cx="12" cy="12" r="3"/>
484
- </svg>
485
- Preview
486
- </button>
487
- `:l.nothing}
488
-
489
- <!-- Spinner overlay -->
490
- <div class="spinner-overlay">
491
- <div class="spin-ring"></div>
492
- </div>
493
-
494
- <!-- Done overlay -->
495
- <div class="done-overlay">
496
- <div class="done-check">
497
- <svg viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="2.5" stroke-linecap="round">
498
- <polyline points="20 6 9 17 4 12" />
499
- </svg>
500
- </div>
501
- </div>
502
-
503
- <!-- Progress bar -->
504
- ${e.status==="uploading"||s?l.html`
505
- <div class="progress">
506
- <div class="progress-fill" style="transform:scaleX(${Math.min(e.progress,100)/100})"></div>
507
- </div>
508
- `:l.nothing}
509
-
510
- <!-- Error badge -->
511
- ${n&&e.error?l.html`<div class="error-badge" title=${e.error}>${e.error}</div>`:l.nothing}
512
- </div>
513
-
514
- <!-- Action buttons -->
515
- <div class="actions">
516
- ${n?l.html`
517
- <button class="act-btn retry" @click=${this._retry} title="Retry" aria-label="Retry upload">
518
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round">
519
- <polyline points="23 4 23 10 17 10" />
520
- <path d="M20.49 15a9 9 0 11-2.12-9.36L23 10" />
521
- </svg>
522
- </button>
523
- `:l.nothing}
524
- <button class="act-btn del" @click=${this._remove} title="Remove" aria-label="Remove file">
525
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round">
526
- <line x1="18" y1="6" x2="6" y2="18" />
527
- <line x1="6" y1="6" x2="18" y2="18" />
528
- </svg>
529
- </button>
530
- </div>
531
-
532
- <!-- Info bar -->
533
- <div class="info">
534
- <div class="name" title=${e.name}>${e.name}</div>
535
- <div class="meta">${e.size?Ae(e.size):""}${e.type?`${e.size?" · ":""}${e.type}`:""}</div>
536
- </div>
537
- </div>
538
- `}_renderTypeIcon(e){switch(e){case"pdf":return l.html`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"/><polyline points="14 2 14 8 20 8"/></svg>`;case"doc":return l.html`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/></svg>`;case"vid":return l.html`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><polygon points="23 7 16 12 23 17 23 7"/><rect x="1" y="5" width="15" height="14" rx="2"/></svg>`;case"zip":return l.html`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M21 8v13H3V8"/><path d="M1 3h22v5H1z"/><path d="M10 12h4"/></svg>`;default:return l.html`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M13 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V9z"/><polyline points="13 2 13 9 20 9"/></svg>`}}};te.styles=l.css`
539
- :host {
540
- display: block;
541
- }
542
-
543
- .tile {
544
- border-radius: 6px;
545
- overflow: hidden;
546
- background: var(--sfx-up-bg, #fff);
547
- border: 1px solid #e8eaed;
548
- box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06);
549
- animation: tileIn 0.6s cubic-bezier(0.34, 1.2, 0.64, 1) both;
550
- transition: box-shadow 0.2s, transform 0.2s, border-color 0.2s;
551
- cursor: default;
552
- display: flex;
553
- flex-direction: column;
554
- position: relative;
555
- }
556
-
557
- .tile:hover {
558
- box-shadow: 0 6px 24px rgba(0, 0, 0, 0.11);
559
- transform: translateY(-2px);
560
- border-color: #d1d5db;
561
- }
562
-
563
- /* --- Preview area --- */
564
- .preview {
565
- position: relative;
566
- aspect-ratio: 16 / 10;
567
- overflow: hidden;
568
- flex-shrink: 0;
569
- background: #f3f4f6;
570
- }
571
-
572
- .preview-bg {
573
- position: absolute;
574
- inset: 0;
575
- background-size: cover;
576
- background-position: center;
577
- transition: transform 0.4s ease;
578
- }
579
-
580
- .tile:hover .preview-bg {
581
- transform: scale(1.03);
582
- }
583
-
584
- .preview-bg.pdf { background: linear-gradient(135deg, #fef2f2, #fee2e2); }
585
- .preview-bg.doc { background: linear-gradient(135deg, #eff6ff, #dbeafe); }
586
- .preview-bg.vid { background: linear-gradient(135deg, #f5f3ff, #ede9fe); }
587
- .preview-bg.zip { background: linear-gradient(135deg, #fffbeb, #fef3c7); }
588
- .preview-bg.gen { background: linear-gradient(135deg, #f8fafc, #f1f5f9); }
589
-
590
- /* --- File type icon --- */
591
- .type-icon {
592
- position: absolute;
593
- inset: 0;
594
- display: flex;
595
- align-items: center;
596
- justify-content: center;
597
- pointer-events: none;
598
- }
599
-
600
- .type-icon-inner {
601
- width: 44px;
602
- height: 44px;
603
- border-radius: 12px;
604
- display: flex;
605
- align-items: center;
606
- justify-content: center;
607
- background: rgba(255, 255, 255, 0.9);
608
- box-shadow: 0 2px 10px rgba(0, 0, 0, 0.08);
609
- }
610
-
611
- .type-icon-inner svg {
612
- width: 22px;
613
- height: 22px;
614
- }
615
-
616
- .type-icon-inner.pdf { color: #dc2626; }
617
- .type-icon-inner.doc { color: #1d4ed8; }
618
- .type-icon-inner.vid { color: #7c3aed; }
619
- .type-icon-inner.zip { color: #b45309; }
620
- .type-icon-inner.gen { color: #64748b; }
621
-
622
- .ext-label {
623
- font-size: 9px;
624
- font-weight: 800;
625
- text-transform: uppercase;
626
- margin-top: 2px;
627
- }
628
-
629
- /* --- Info bar --- */
630
- .info {
631
- padding: 9px 11px 10px;
632
- background: var(--sfx-up-bg, #fff);
633
- min-width: 0;
634
- }
635
-
636
- .name {
637
- font-size: 12.5px;
638
- font-weight: 600;
639
- color: #111827;
640
- white-space: nowrap;
641
- overflow: hidden;
642
- text-overflow: ellipsis;
643
- margin-bottom: 2px;
644
- }
645
-
646
- .meta {
647
- font-size: 11px;
648
- font-weight: 400;
649
- color: #9ca3af;
650
- white-space: nowrap;
651
- overflow: hidden;
652
- text-overflow: ellipsis;
653
- }
654
-
655
- .tile.done .info {
656
- opacity: 0.5;
657
- }
658
-
659
- /* --- Action buttons --- */
660
- .actions {
661
- position: absolute;
662
- top: 6px;
663
- right: 6px;
664
- display: flex;
665
- gap: 3px;
666
- opacity: 0;
667
- transition: opacity 0.15s;
668
- z-index: 10;
669
- }
670
-
671
- .tile:hover .actions {
672
- opacity: 1;
673
- }
674
-
675
- .act-btn {
676
- width: 26px;
677
- height: 26px;
678
- border-radius: 6px;
679
- border: none;
680
- background: #fff;
681
- box-shadow: 0 1px 4px rgba(0, 0, 0, 0.15);
682
- cursor: pointer;
683
- display: flex;
684
- align-items: center;
685
- justify-content: center;
686
- transition: background 0.15s, transform 0.12s;
687
- color: #374151;
688
- padding: 0;
689
- }
690
-
691
- .act-btn:hover {
692
- background: #f3f4f6;
693
- transform: scale(1.08);
694
- }
695
-
696
- .act-btn.del:hover {
697
- background: #fee2e2;
698
- color: #dc2626;
699
- }
700
-
701
- .act-btn.retry:hover {
702
- background: #eff6ff;
703
- color: var(--sfx-up-primary, #2563eb);
704
- }
705
-
706
- .act-btn svg {
707
- width: 11px;
708
- height: 11px;
709
- }
710
-
711
- /* --- Preview button --- */
712
- .preview-btn {
713
- position: absolute;
714
- bottom: 50%;
715
- left: 50%;
716
- transform: translate(-50%, 50%);
717
- padding: 6px 16px;
718
- border-radius: 6px;
719
- border: 1.5px solid var(--sfx-up-primary, #2563eb);
720
- background: #fff;
721
- cursor: pointer;
722
- display: flex;
723
- align-items: center;
724
- gap: 5px;
725
- opacity: 0;
726
- transition: all 0.15s ease;
727
- color: var(--sfx-up-primary, #2563eb);
728
- font-family: inherit;
729
- font-size: 11px;
730
- font-weight: 600;
731
- white-space: nowrap;
732
- z-index: 5;
733
- }
734
-
735
- .tile:hover .preview-btn {
736
- opacity: 1;
737
- }
738
-
739
- .preview-btn:hover {
740
- background: var(--sfx-up-primary, #2563eb);
741
- color: #fff;
742
- }
743
-
744
- .preview-btn:hover svg {
745
- stroke: #fff;
746
- }
747
-
748
- .preview-btn svg {
749
- width: 13px;
750
- height: 13px;
751
- }
752
-
753
- /* --- Progress bar --- */
754
- .progress {
755
- position: absolute;
756
- bottom: 0;
757
- left: 0;
758
- right: 0;
759
- height: 2px;
760
- background: rgba(0, 0, 0, 0.06);
761
- }
762
-
763
- .progress-fill {
764
- height: 100%;
765
- background: var(--sfx-up-primary, #2563eb);
766
- transform-origin: left;
767
- transition: transform 0.32s ease;
768
- }
769
-
770
- .tile.done .progress-fill {
771
- background: var(--sfx-up-success, #16a34a);
772
- }
773
-
774
- /* --- Uploading spinner overlay --- */
775
- .spinner-overlay {
776
- position: absolute;
777
- inset: 0;
778
- display: flex;
779
- align-items: center;
780
- justify-content: center;
781
- background: rgba(0, 0, 0, 0.22);
782
- opacity: 0;
783
- transition: opacity 0.2s;
784
- pointer-events: none;
785
- }
786
-
787
- .tile.uploading .spinner-overlay {
788
- opacity: 1;
789
- }
790
-
791
- .spin-ring {
792
- width: 28px;
793
- height: 28px;
794
- border: 2.5px solid rgba(255, 255, 255, 0.22);
795
- border-top-color: #fff;
796
- border-radius: 50%;
797
- animation: spinRing 0.7s linear infinite;
798
- }
799
-
800
- /* --- Done overlay --- */
801
- .done-overlay {
802
- position: absolute;
803
- inset: 0;
804
- background: rgba(5, 150, 105, 0.72);
805
- opacity: 0;
806
- transition: opacity 0.45s cubic-bezier(0.4, 0, 0.2, 1);
807
- pointer-events: none;
808
- display: flex;
809
- align-items: center;
810
- justify-content: center;
811
- }
812
-
813
- .tile.done .done-overlay {
814
- opacity: 1;
815
- pointer-events: auto;
816
- }
817
-
818
- .done-check {
819
- animation: popBounce 0.55s cubic-bezier(0.34, 1.56, 0.64, 1) 0.15s both;
820
- }
821
-
822
- .done-check svg {
823
- width: 28px;
824
- height: 28px;
825
- filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.2));
826
- }
827
-
828
- /* --- Error state --- */
829
- .error-badge {
830
- position: absolute;
831
- bottom: 28px;
832
- left: 6px;
833
- right: 6px;
834
- font-size: 10px;
835
- font-weight: 600;
836
- color: #fff;
837
- background: rgba(220, 38, 38, 0.88);
838
- border-radius: 4px;
839
- padding: 3px 6px;
840
- text-align: center;
841
- white-space: nowrap;
842
- overflow: hidden;
843
- text-overflow: ellipsis;
844
- }
845
-
846
- @keyframes tileIn {
847
- 0% {
848
- opacity: 0;
849
- transform: scale(0.8) translateY(22px);
850
- filter: blur(10px);
851
- }
852
- 55% {
853
- opacity: 1;
854
- filter: blur(0);
855
- }
856
- 80% {
857
- transform: scale(1.03) translateY(-3px);
858
- }
859
- 100% {
860
- opacity: 1;
861
- transform: scale(1) translateY(0);
862
- filter: blur(0);
863
- }
864
- }
865
-
866
- @keyframes popBounce {
867
- 0% { transform: scale(0); opacity: 0; }
868
- 55% { transform: scale(1.2); opacity: 1; }
869
- 75% { transform: scale(0.94); }
870
- 100% { transform: scale(1); }
871
- }
872
-
873
- @keyframes spinRing {
874
- to { transform: rotate(360deg); }
875
- }
876
-
877
- @media (prefers-reduced-motion: reduce) {
878
- .tile { animation: none; }
879
- .done-check { animation: none; }
880
- .spin-ring { animation: none; }
881
- }
882
- `;let q=te;We([d.property({attribute:!1})],q.prototype,"file");var Ge=Object.defineProperty,be=(i,e,t,r)=>{for(var s=void 0,o=i.length-1,n;o>=0;o--)(n=i[o])&&(s=n(e,t,s)||s);return s&&Ge(e,t,s),s};const re=class re extends l.LitElement{constructor(){super(...arguments),this.fileCount=0,this.primaryLabel="Done"}_uploadMore(){this.dispatchEvent(new CustomEvent("upload-more",{bubbles:!0,composed:!0}))}_primaryAction(){this.dispatchEvent(new CustomEvent("primary-action",{bubbles:!0,composed:!0}))}render(){const e=this.fileCount===1?"file has":"files have";return l.html`
883
- <div class="card">
884
- <div class="icon">
885
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round">
886
- <polyline points="20 6 9 17 4 12" />
887
- </svg>
888
- </div>
889
- <div class="title">Uploaded successfully!</div>
890
- <div class="subtitle">
891
- All ${this.fileCount} ${e} been uploaded and are ready for review.
892
- </div>
893
- <div class="actions">
894
- <button class="btn-ghost" @click=${this._uploadMore}>Upload more</button>
895
- <button class="btn-primary" @click=${this._primaryAction}>${this.primaryLabel}</button>
896
- </div>
897
- </div>
898
- `}};re.styles=l.css`
899
- :host {
900
- display: flex;
901
- flex: 1;
902
- justify-content: center;
903
- align-items: center;
904
- }
905
-
906
- .card {
907
- background: var(--sfx-up-bg, #fff);
908
- border-radius: 20px;
909
- border: 1.5px solid #bbf7d0;
910
- padding: 64px 48px;
911
- display: flex;
912
- flex-direction: column;
913
- align-items: center;
914
- text-align: center;
915
- box-shadow: 0 8px 40px rgba(34, 197, 94, 0.08);
916
- animation: fadeUp 0.4s ease both;
917
- }
918
-
919
- .icon {
920
- width: 64px;
921
- height: 64px;
922
- border-radius: 50%;
923
- background: linear-gradient(135deg, #dcfce7, #bbf7d0);
924
- display: flex;
925
- align-items: center;
926
- justify-content: center;
927
- margin-bottom: 18px;
928
- color: var(--sfx-up-success, #16a34a);
929
- box-shadow: 0 4px 18px rgba(22, 163, 74, 0.16);
930
- animation: popBounce 0.6s cubic-bezier(0.34, 1.56, 0.64, 1) 0.1s both;
931
- }
932
-
933
- .icon svg {
934
- width: 30px;
935
- height: 30px;
936
- }
937
-
938
- .title {
939
- font-size: 21px;
940
- font-weight: 800;
941
- color: #0f172a;
942
- letter-spacing: -0.4px;
943
- margin-bottom: 7px;
944
- }
945
-
946
- .subtitle {
947
- font-size: 13.5px;
948
- color: var(--sfx-up-text-muted, #94a3b8);
949
- line-height: 1.6;
950
- max-width: 320px;
951
- margin-bottom: 22px;
952
- }
953
-
954
- .actions {
955
- display: flex;
956
- gap: 9px;
957
- }
958
-
959
- button {
960
- height: 36px;
961
- padding: 0 17px;
962
- border-radius: 9px;
963
- border: none;
964
- font-family: inherit;
965
- font-size: 13px;
966
- font-weight: 600;
967
- cursor: pointer;
968
- display: inline-flex;
969
- align-items: center;
970
- justify-content: center;
971
- gap: 6px;
972
- transition: all 0.18s ease;
973
- white-space: nowrap;
974
- }
975
-
976
- .btn-ghost {
977
- background: none;
978
- color: var(--sfx-up-text-muted, #94a3b8);
979
- border: 1.5px solid var(--sfx-up-border, #e8edf5);
980
- }
981
-
982
- .btn-ghost:hover {
983
- background: #f8faff;
984
- color: #64748b;
985
- border-color: #d1dff0;
986
- }
987
-
988
- .btn-primary {
989
- background: linear-gradient(135deg, var(--sfx-up-primary, #2563eb), var(--sfx-up-primary-mid, #3b82f6));
990
- color: #fff;
991
- box-shadow: 0 2px 10px rgba(37, 99, 235, 0.28);
992
- }
993
-
994
- .btn-primary:hover {
995
- background: linear-gradient(135deg, var(--sfx-up-primary-hover, #1d4ed8), var(--sfx-up-primary, #2563eb));
996
- box-shadow: 0 4px 16px rgba(37, 99, 235, 0.38);
997
- transform: translateY(-1px);
998
- }
999
-
1000
- @keyframes fadeUp {
1001
- from {
1002
- opacity: 0;
1003
- transform: translateY(12px);
1004
- }
1005
- to {
1006
- opacity: 1;
1007
- transform: translateY(0);
1008
- }
1009
- }
1010
-
1011
- @keyframes popBounce {
1012
- 0% { transform: scale(0); opacity: 0; }
1013
- 55% { transform: scale(1.2); opacity: 1; }
1014
- 75% { transform: scale(0.94); }
1015
- 100% { transform: scale(1); }
1016
- }
1017
-
1018
- @media (prefers-reduced-motion: reduce) {
1019
- .card { animation: none; }
1020
- .icon { animation: none; }
1021
- }
1022
- `;let O=re;be([d.property({type:Number})],O.prototype,"fileCount");be([d.property({type:String})],O.prototype,"primaryLabel");var Xe=Object.defineProperty,K=(i,e,t,r)=>{for(var s=void 0,o=i.length-1,n;o>=0;o--)(n=i[o])&&(s=n(e,t,s)||s);return s&&Xe(e,t,s),s};const se=class se extends l.LitElement{constructor(){super(...arguments),this.uploadState="idle",this.fileCount=0,this.failedCount=0,this.showFillMetadata=!1}_clear(){this.dispatchEvent(new CustomEvent("clear-all",{bubbles:!0,composed:!0}))}_addMore(){this.dispatchEvent(new CustomEvent("add-more",{bubbles:!0,composed:!0}))}_fillMetadata(){this.dispatchEvent(new CustomEvent("fill-metadata",{bubbles:!0,composed:!0}))}_upload(){this.dispatchEvent(new CustomEvent("upload-start",{bubbles:!0,composed:!0}))}_retryAll(){this.dispatchEvent(new CustomEvent("retry-all",{bubbles:!0,composed:!0}))}render(){return l.html`
1023
- <div class="left">
1024
- ${this.showFillMetadata&&this.uploadState==="idle"?l.html`
1025
- <button class="btn-sec" @click=${this._fillMetadata}>
1026
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
1027
- <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
1028
- <polyline points="14 2 14 8 20 8"/>
1029
- <line x1="16" y1="13" x2="8" y2="13"/>
1030
- <line x1="16" y1="17" x2="8" y2="17"/>
1031
- <line x1="10" y1="9" x2="8" y2="9"/>
1032
- </svg>
1033
- Fill Metadata
1034
- </button>
1035
- `:l.nothing}
1036
- <div class="count">
1037
- ${this.fileCount} <span>${this.fileCount===1?"file":"files"}</span>
1038
- </div>
1039
- </div>
1040
- <div class="right">
1041
- <button class="btn-ghost" @click=${this._clear}>
1042
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
1043
- <polyline points="3 6 5 6 21 6" />
1044
- <path d="M19 6l-1 14a2 2 0 01-2 2H8a2 2 0 01-2-2L5 6" />
1045
- </svg>
1046
- Clear
1047
- </button>
1048
- <button class="btn-sec" @click=${this._addMore}>
1049
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round">
1050
- <line x1="12" y1="5" x2="12" y2="19" />
1051
- <line x1="5" y1="12" x2="19" y2="12" />
1052
- </svg>
1053
- Add more
1054
- </button>
1055
- ${this.failedCount>0?l.html`
1056
- <button class="btn-retry" @click=${this._retryAll}>
1057
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round">
1058
- <polyline points="23 4 23 10 17 10" />
1059
- <path d="M20.49 15a9 9 0 11-2.12-9.36L23 10" />
1060
- </svg>
1061
- Retry all (${this.failedCount})
1062
- </button>
1063
- `:l.nothing}
1064
- ${this._renderUploadButton()}
1065
- </div>
1066
- `}_renderUploadButton(){const e=this.uploadState==="uploading",t=this.uploadState==="done",r=["btn-primary",t?"done-state":""].filter(Boolean).join(" ");return l.html`
1067
- <button
1068
- class=${r}
1069
- @click=${this._upload}
1070
- ?disabled=${e}
1071
- >
1072
- ${e?l.html`<span class="btn-spin"></span> Uploading\u2026`:t?l.html`
1073
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round">
1074
- <polyline points="20 6 9 17 4 12" />
1075
- </svg>
1076
- Done!
1077
- `:l.html`
1078
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round">
1079
- <polyline points="16 16 12 12 8 16" />
1080
- <line x1="12" y1="12" x2="12" y2="21" />
1081
- <path d="M20.39 18.39A5 5 0 0018 9h-1.26A8 8 0 103 16.3" />
1082
- </svg>
1083
- Upload
1084
- `}
1085
- </button>
1086
- `}};se.styles=l.css`
1087
- :host {
1088
- display: flex;
1089
- align-items: center;
1090
- justify-content: space-between;
1091
- background: var(--sfx-up-bg, #ffffff);
1092
- border-top: 1px solid #ebebeb;
1093
- padding: 14px 24px;
1094
- flex-shrink: 0;
1095
- box-shadow: 0 -4px 16px rgba(0, 0, 0, 0.04);
1096
- }
1097
-
1098
- .left {
1099
- display: flex;
1100
- align-items: center;
1101
- gap: 9px;
1102
- }
1103
-
1104
- .right {
1105
- display: flex;
1106
- align-items: center;
1107
- gap: 9px;
1108
- }
1109
-
1110
- /* --- Buttons --- */
1111
- button {
1112
- height: 36px;
1113
- padding: 0 17px;
1114
- border-radius: 9px;
1115
- border: none;
1116
- font-family: inherit;
1117
- font-size: 13px;
1118
- font-weight: 600;
1119
- cursor: pointer;
1120
- display: inline-flex;
1121
- align-items: center;
1122
- justify-content: center;
1123
- gap: 6px;
1124
- transition: all 0.18s ease;
1125
- white-space: nowrap;
1126
- }
1127
-
1128
- button svg {
1129
- width: 14px;
1130
- height: 14px;
1131
- }
1132
-
1133
- .btn-ghost {
1134
- background: none;
1135
- color: var(--sfx-up-text-muted, #94a3b8);
1136
- border: 1.5px solid var(--sfx-up-border, #e8edf5);
1137
- }
1138
-
1139
- .btn-ghost:hover {
1140
- background: #f8faff;
1141
- color: #64748b;
1142
- border-color: #d1dff0;
1143
- }
1144
-
1145
- .btn-sec {
1146
- background: var(--sfx-up-primary-bg, #eff6ff);
1147
- color: var(--sfx-up-primary, #2563eb);
1148
- border: 1.5px solid rgba(37, 99, 235, 0.15);
1149
- }
1150
-
1151
- .btn-sec:hover {
1152
- background: #dbeafe;
1153
- }
1154
-
1155
- .btn-retry {
1156
- background: #fef2f2;
1157
- color: #dc2626;
1158
- border: 1.5px solid rgba(220, 38, 38, 0.2);
1159
- }
1160
-
1161
- .btn-retry:hover {
1162
- background: #fee2e2;
1163
- color: #b91c1c;
1164
- border-color: rgba(220, 38, 38, 0.35);
1165
- }
1166
-
1167
- .btn-primary {
1168
- background: linear-gradient(135deg, var(--sfx-up-primary, #2563eb), var(--sfx-up-primary-mid, #3b82f6));
1169
- color: #fff;
1170
- box-shadow: 0 2px 10px rgba(37, 99, 235, 0.28);
1171
- min-width: 110px;
1172
- position: relative;
1173
- overflow: hidden;
1174
- }
1175
-
1176
- .btn-primary:hover:not(:disabled) {
1177
- background: linear-gradient(135deg, var(--sfx-up-primary-hover, #1d4ed8), var(--sfx-up-primary, #2563eb));
1178
- box-shadow: 0 4px 16px rgba(37, 99, 235, 0.38);
1179
- transform: translateY(-1px);
1180
- }
1181
-
1182
- .btn-primary:active {
1183
- transform: translateY(0);
1184
- }
1185
-
1186
- .btn-primary:disabled {
1187
- opacity: 0.55;
1188
- cursor: not-allowed;
1189
- }
1190
-
1191
- .btn-primary.done-state {
1192
- background: linear-gradient(135deg, var(--sfx-up-success, #16a34a), #22c55e);
1193
- box-shadow: 0 2px 10px rgba(22, 163, 74, 0.28);
1194
- }
1195
-
1196
- /* --- Spinner --- */
1197
- .btn-spin {
1198
- width: 14px;
1199
- height: 14px;
1200
- border: 2px solid rgba(255, 255, 255, 0.3);
1201
- border-top-color: #fff;
1202
- border-radius: 50%;
1203
- animation: spinRing 0.7s linear infinite;
1204
- }
1205
-
1206
- /* --- Count --- */
1207
- .count {
1208
- font-size: 13.5px;
1209
- font-weight: 700;
1210
- color: var(--sfx-up-text, #1e293b);
1211
- }
1212
-
1213
- .count span {
1214
- font-weight: 400;
1215
- color: var(--sfx-up-text-muted, #94a3b8);
1216
- }
1217
-
1218
- @keyframes spinRing {
1219
- to { transform: rotate(360deg); }
1220
- }
1221
-
1222
- @media (prefers-reduced-motion: reduce) {
1223
- .btn-spin { animation: none; }
1224
- }
1225
- `;let E=se;K([d.property({type:String})],E.prototype,"uploadState");K([d.property({type:Number})],E.prototype,"fileCount");K([d.property({type:Number})],E.prototype,"failedCount");K([d.property({type:Boolean})],E.prototype,"showFillMetadata");var Qe=Object.defineProperty,J=(i,e,t,r)=>{for(var s=void 0,o=i.length-1,n;o>=0;o--)(n=i[o])&&(s=n(e,t,s)||s);return s&&Qe(e,t,s),s};const oe=class oe extends l.LitElement{constructor(){super(...arguments),this._url="",this._name="",this._error="",this._loading=!1,this._onBackdropClick=e=>{e.target===e.currentTarget&&this._cancel()},this._onUrlInput=e=>{this._url=e.target.value,this._error="",this._autoName()},this._onNameInput=e=>{this._name=e.target.value},this._onKeyDown=e=>{e.key==="Escape"&&this._cancel(),e.key==="Enter"&&!this._loading&&this._submit()}}_autoName(){var e;if(!this._name)try{const t=new URL(this._url).pathname.split("/"),r=t[t.length-1];if(r){const s=(e=this.shadowRoot)==null?void 0:e.querySelector("#nameInput");s&&(s.placeholder=r)}}catch{}}_cancel(){this.dispatchEvent(new CustomEvent("url-cancel",{bubbles:!0,composed:!0}))}_submit(){const e=this._url.trim();if(!e){this._error="Please enter a URL";return}try{new URL(e)}catch{this._error="Please enter a valid URL";return}this._error="";let t=this._name.trim();if(!t)try{const r=new URL(e).pathname.split("/");t=r[r.length-1]||"imported-file"}catch{t="imported-file"}this.dispatchEvent(new CustomEvent("url-submit",{detail:{url:e,name:t},bubbles:!0,composed:!0}))}connectedCallback(){super.connectedCallback(),this.updateComplete.then(()=>{var e,t;(t=(e=this.shadowRoot)==null?void 0:e.querySelector("#urlInput"))==null||t.focus()})}render(){return l.html`
1226
- <div class="backdrop" @click=${this._onBackdropClick} @keydown=${this._onKeyDown}>
1227
- <div class="card">
1228
- <div class="head">
1229
- <div class="head-icon">
1230
- <svg viewBox="0 0 24 24">
1231
- <path d="M10 13a5 5 0 007.54.54l3-3a5 5 0 00-7.07-7.07l-1.72 1.71" />
1232
- <path d="M14 11a5 5 0 00-7.54-.54l-3 3a5 5 0 007.07 7.07l1.71-1.71" />
1233
- </svg>
1234
- </div>
1235
- <div class="title">Import from URL</div>
1236
- <button class="close-btn" @click=${this._cancel}>\u2715</button>
1237
- </div>
1238
- <div class="body">
1239
- <div class="field">
1240
- <label>File URL</label>
1241
- <input
1242
- id="urlInput"
1243
- type="url"
1244
- placeholder="https://example.com/file.pdf"
1245
- .value=${this._url}
1246
- @input=${this._onUrlInput}
1247
- />
1248
- </div>
1249
- <div class="field">
1250
- <label>File name <span class="optional">(optional)</span></label>
1251
- <input
1252
- id="nameInput"
1253
- type="text"
1254
- placeholder="document.pdf"
1255
- .value=${this._name}
1256
- @input=${this._onNameInput}
1257
- />
1258
- </div>
1259
- ${this._error?l.html`<div class="error">${this._error}</div>`:""}
1260
- <div class="actions">
1261
- <button class="btn btn-ghost" @click=${this._cancel}>Cancel</button>
1262
- <button class="btn btn-primary" ?disabled=${this._loading} @click=${this._submit}>
1263
- Import file
1264
- </button>
1265
- </div>
1266
- </div>
1267
- </div>
1268
- </div>
1269
- `}};oe.styles=l.css`
1270
- :host {
1271
- display: block;
1272
- }
1273
-
1274
- .backdrop {
1275
- position: fixed;
1276
- inset: 0;
1277
- z-index: 1000;
1278
- background: rgba(0, 0, 0, 0.4);
1279
- backdrop-filter: blur(6px);
1280
- display: flex;
1281
- align-items: center;
1282
- justify-content: center;
1283
- padding: 20px;
1284
- animation: fadeIn 0.18s ease both;
1285
- }
1286
-
1287
- .card {
1288
- background: var(--sfx-up-bg, #fff);
1289
- border-radius: 20px;
1290
- box-shadow: 0 28px 80px rgba(0, 0, 0, 0.18), 0 4px 16px rgba(0, 0, 0, 0.06);
1291
- width: 100%;
1292
- max-width: 480px;
1293
- overflow: hidden;
1294
- display: flex;
1295
- flex-direction: column;
1296
- transform: translateY(18px) scale(0.97);
1297
- animation: slideUp 0.28s cubic-bezier(0.34, 1.2, 0.64, 1) forwards;
1298
- }
1299
-
1300
- .head {
1301
- display: flex;
1302
- align-items: center;
1303
- gap: 10px;
1304
- padding: 18px 20px 0;
1305
- }
1306
-
1307
- .head-icon {
1308
- width: 34px;
1309
- height: 34px;
1310
- border-radius: 10px;
1311
- background: var(--sfx-up-primary-bg, #f5f5f7);
1312
- display: flex;
1313
- align-items: center;
1314
- justify-content: center;
1315
- flex-shrink: 0;
1316
- color: var(--sfx-up-primary, #2563eb);
1317
- }
1318
-
1319
- .head-icon svg {
1320
- width: 18px;
1321
- height: 18px;
1322
- fill: none;
1323
- stroke: currentColor;
1324
- stroke-width: 2;
1325
- stroke-linecap: round;
1326
- }
1327
-
1328
- .title {
1329
- font-size: 15px;
1330
- font-weight: 700;
1331
- color: var(--sfx-up-text, #1a1a1a);
1332
- flex: 1;
1333
- }
1334
-
1335
- .close-btn {
1336
- width: 28px;
1337
- height: 28px;
1338
- border-radius: 8px;
1339
- border: none;
1340
- background: #f0f0f0;
1341
- color: #888;
1342
- font-size: 14px;
1343
- cursor: pointer;
1344
- display: flex;
1345
- align-items: center;
1346
- justify-content: center;
1347
- transition: background 0.15s, color 0.15s;
1348
- flex-shrink: 0;
1349
- line-height: 1;
1350
- }
1351
-
1352
- .close-btn:hover {
1353
- background: #e4e4e4;
1354
- color: #333;
1355
- }
1356
-
1357
- .body {
1358
- padding: 18px 20px 20px;
1359
- }
1360
-
1361
- .field {
1362
- margin-bottom: 14px;
1363
- }
1364
-
1365
- label {
1366
- display: block;
1367
- font-size: 11px;
1368
- font-weight: 600;
1369
- color: #aaa;
1370
- margin-bottom: 5px;
1371
- text-transform: uppercase;
1372
- letter-spacing: 0.7px;
1373
- }
1374
-
1375
- label .optional {
1376
- color: #ccc;
1377
- font-weight: 400;
1378
- text-transform: none;
1379
- letter-spacing: 0;
1380
- }
1381
-
1382
- input {
1383
- width: 100%;
1384
- height: 42px;
1385
- border: 1.5px solid #ebebeb;
1386
- border-radius: 10px;
1387
- padding: 0 14px;
1388
- font-size: 14px;
1389
- font-family: inherit;
1390
- color: #1a1a1a;
1391
- background: #fafafa;
1392
- transition: border-color 0.15s, background 0.15s;
1393
- outline: none;
1394
- box-sizing: border-box;
1395
- }
1396
-
1397
- input:focus {
1398
- border-color: var(--sfx-up-primary, #2563eb);
1399
- background: #fff;
1400
- }
1401
-
1402
- input::placeholder {
1403
- color: #ccc;
1404
- }
1405
-
1406
- .error {
1407
- font-size: 12px;
1408
- color: #dc2626;
1409
- margin-top: -6px;
1410
- margin-bottom: 8px;
1411
- }
1412
-
1413
- .actions {
1414
- display: flex;
1415
- gap: 9px;
1416
- justify-content: flex-end;
1417
- margin-top: 18px;
1418
- }
1419
-
1420
- button.btn {
1421
- height: 36px;
1422
- padding: 0 17px;
1423
- border-radius: 9px;
1424
- border: none;
1425
- font-family: inherit;
1426
- font-size: 13px;
1427
- font-weight: 600;
1428
- cursor: pointer;
1429
- display: inline-flex;
1430
- align-items: center;
1431
- justify-content: center;
1432
- gap: 6px;
1433
- transition: all 0.18s ease;
1434
- white-space: nowrap;
1435
- }
1436
-
1437
- .btn-ghost {
1438
- background: none;
1439
- color: #94a3b8;
1440
- border: 1.5px solid #e8edf5;
1441
- }
1442
-
1443
- .btn-ghost:hover {
1444
- background: #f8faff;
1445
- color: #64748b;
1446
- border-color: #d1dff0;
1447
- }
1448
-
1449
- .btn-primary {
1450
- background: linear-gradient(135deg, var(--sfx-up-primary, #2563eb), #3b82f6);
1451
- color: #fff;
1452
- box-shadow: 0 2px 10px rgba(37, 99, 235, 0.28);
1453
- position: relative;
1454
- overflow: hidden;
1455
- }
1456
-
1457
- .btn-primary:hover:not(:disabled) {
1458
- background: linear-gradient(135deg, #1d4ed8, var(--sfx-up-primary, #2563eb));
1459
- box-shadow: 0 4px 16px rgba(37, 99, 235, 0.38);
1460
- transform: translateY(-1px);
1461
- }
1462
-
1463
- .btn-primary:disabled {
1464
- opacity: 0.55;
1465
- cursor: not-allowed;
1466
- }
1467
-
1468
- .btn-spin {
1469
- width: 14px;
1470
- height: 14px;
1471
- border: 2px solid rgba(255, 255, 255, 0.3);
1472
- border-top-color: #fff;
1473
- border-radius: 50%;
1474
- animation: spin 0.7s linear infinite;
1475
- }
1476
-
1477
- @keyframes fadeIn {
1478
- from { opacity: 0; }
1479
- to { opacity: 1; }
1480
- }
1481
-
1482
- @keyframes slideUp {
1483
- from { transform: translateY(18px) scale(0.97); }
1484
- to { transform: translateY(0) scale(1); }
1485
- }
1486
-
1487
- @keyframes spin {
1488
- to { transform: rotate(360deg); }
1489
- }
1490
- `;let S=oe;J([d.state()],S.prototype,"_url");J([d.state()],S.prototype,"_name");J([d.state()],S.prototype,"_error");J([d.state()],S.prototype,"_loading");var Ze=Object.defineProperty,W=(i,e,t,r)=>{for(var s=void 0,o=i.length-1,n;o>=0;o--)(n=i[o])&&(s=n(e,t,s)||s);return s&&Ze(e,t,s),s};const ie=class ie extends l.LitElement{constructor(){super(...arguments),this._stream=null,this._error="",this._captured=null,this._previewUrl="",this._onBackdropClick=e=>{e.target===e.currentTarget&&this._cancel()},this._onKeyDown=e=>{e.key==="Escape"&&this._cancel()},this._capture=()=>{var s,o;const e=(s=this.shadowRoot)==null?void 0:s.querySelector("video"),t=(o=this.shadowRoot)==null?void 0:o.querySelector("canvas");if(!e||!t)return;t.width=e.videoWidth,t.height=e.videoHeight,t.getContext("2d").drawImage(e,0,0),t.toBlob(n=>{n&&(this._captured=n,this._previewUrl=URL.createObjectURL(n),this._stopStream())},"image/jpeg",.92)},this._retake=()=>{this._previewUrl&&URL.revokeObjectURL(this._previewUrl),this._captured=null,this._previewUrl="",this._startCamera()},this._usePhoto=()=>{if(!this._captured)return;const e=new Date().toISOString().replace(/[:.]/g,"-").slice(0,19),t=new File([this._captured],`camera-${e}.jpg`,{type:"image/jpeg"});this.dispatchEvent(new CustomEvent("camera-capture",{detail:{file:t},bubbles:!0,composed:!0}))}}connectedCallback(){super.connectedCallback(),this._startCamera()}disconnectedCallback(){super.disconnectedCallback(),this._stopStream(),this._previewUrl&&URL.revokeObjectURL(this._previewUrl)}async _startCamera(){var e;try{this._stream=await navigator.mediaDevices.getUserMedia({video:!0,audio:!1}),await this.updateComplete;const t=(e=this.shadowRoot)==null?void 0:e.querySelector("video");t&&(t.srcObject=this._stream)}catch{this._error="Could not access camera. Please check your permissions."}}_stopStream(){var e;(e=this._stream)==null||e.getTracks().forEach(t=>t.stop()),this._stream=null}_cancel(){this._stopStream(),this.dispatchEvent(new CustomEvent("camera-cancel",{bubbles:!0,composed:!0}))}render(){return l.html`
1491
- <div class="backdrop" @click=${this._onBackdropClick} @keydown=${this._onKeyDown}>
1492
- <div class="card">
1493
- <div class="head">
1494
- <div class="head-icon">
1495
- <svg viewBox="0 0 24 24">
1496
- <path d="M23 19a2 2 0 01-2 2H3a2 2 0 01-2-2V8a2 2 0 012-2h4l2-3h6l2 3h4a2 2 0 012 2z"/>
1497
- <circle cx="12" cy="13" r="4"/>
1498
- </svg>
1499
- </div>
1500
- <div class="title">Camera</div>
1501
- <button class="close-btn" @click=${this._cancel}>\u2715</button>
1502
- </div>
1503
- <div class="body">
1504
- ${this._error?l.html`<div class="error">${this._error}</div>`:this._captured?l.html`
1505
- <img class="preview-img" src=${this._previewUrl} alt="Captured photo" />
1506
- <div class="actions">
1507
- <button class="btn btn-ghost" @click=${this._retake}>Retake</button>
1508
- <button class="btn btn-primary" @click=${this._usePhoto}>Use photo</button>
1509
- </div>
1510
- `:l.html`
1511
- <video autoplay playsinline muted></video>
1512
- <canvas></canvas>
1513
- <div class="actions">
1514
- <button class="btn-capture" @click=${this._capture}></button>
1515
- </div>
1516
- `}
1517
- </div>
1518
- </div>
1519
- </div>
1520
- `}};ie.styles=l.css`
1521
- :host { display: block; }
1522
-
1523
- .backdrop {
1524
- position: fixed; inset: 0; z-index: 1000;
1525
- background: rgba(0, 0, 0, 0.4);
1526
- backdrop-filter: blur(6px);
1527
- display: flex; align-items: center; justify-content: center;
1528
- padding: 20px;
1529
- animation: fadeIn 0.18s ease both;
1530
- }
1531
-
1532
- .card {
1533
- background: var(--sfx-up-bg, #fff);
1534
- border-radius: 20px;
1535
- box-shadow: 0 28px 80px rgba(0, 0, 0, 0.18), 0 4px 16px rgba(0, 0, 0, 0.06);
1536
- width: 100%; max-width: 520px;
1537
- height: 520px;
1538
- overflow: hidden; display: flex; flex-direction: column;
1539
- animation: slideUp 0.28s cubic-bezier(0.34, 1.2, 0.64, 1) forwards;
1540
- }
1541
-
1542
- .head {
1543
- display: flex; align-items: center; gap: 10px;
1544
- padding: 18px 20px 0;
1545
- }
1546
-
1547
- .head-icon {
1548
- width: 34px; height: 34px; border-radius: 10px;
1549
- background: var(--sfx-up-primary-bg, #f5f5f7);
1550
- display: flex; align-items: center; justify-content: center;
1551
- flex-shrink: 0; color: var(--sfx-up-primary, #2563eb);
1552
- }
1553
-
1554
- .head-icon svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
1555
-
1556
- .title { font-size: 15px; font-weight: 700; color: var(--sfx-up-text, #1a1a1a); flex: 1; }
1557
-
1558
- .close-btn {
1559
- width: 28px; height: 28px; border-radius: 8px; border: none;
1560
- background: #f0f0f0; color: #888; font-size: 14px; cursor: pointer;
1561
- display: flex; align-items: center; justify-content: center;
1562
- transition: background 0.15s, color 0.15s; flex-shrink: 0; line-height: 1;
1563
- }
1564
- .close-btn:hover { background: #e4e4e4; color: #333; }
1565
-
1566
- .body { padding: 18px 20px 20px; display: flex; flex-direction: column; align-items: center; gap: 16px; flex: 1; min-height: 0; justify-content: center; }
1567
-
1568
- video, canvas {
1569
- width: 100%; flex: 1; min-height: 0; border-radius: 12px;
1570
- background: #000; object-fit: cover;
1571
- }
1572
-
1573
- canvas { display: none; }
1574
-
1575
- .preview-img {
1576
- width: 100%; max-height: 320px; border-radius: 12px;
1577
- object-fit: contain; background: #000;
1578
- }
1579
-
1580
- .error { font-size: 13px; color: #dc2626; text-align: center; padding: 40px 20px; }
1581
-
1582
- .actions { display: flex; gap: 9px; justify-content: center; width: 100%; }
1583
-
1584
- button.btn {
1585
- height: 36px; padding: 0 17px; border-radius: 9px; border: none;
1586
- font-family: inherit; font-size: 13px; font-weight: 600; cursor: pointer;
1587
- display: inline-flex; align-items: center; justify-content: center; gap: 6px;
1588
- transition: all 0.18s ease; white-space: nowrap;
1589
- }
1590
-
1591
- .btn-ghost { background: none; color: #94a3b8; border: 1.5px solid #e8edf5; }
1592
- .btn-ghost:hover { background: #f8faff; color: #64748b; border-color: #d1dff0; }
1593
-
1594
- .btn-primary {
1595
- background: linear-gradient(135deg, var(--sfx-up-primary, #2563eb), #3b82f6);
1596
- color: #fff; box-shadow: 0 2px 10px rgba(37, 99, 235, 0.28);
1597
- }
1598
- .btn-primary:hover { background: linear-gradient(135deg, #1d4ed8, var(--sfx-up-primary, #2563eb)); box-shadow: 0 4px 16px rgba(37, 99, 235, 0.38); transform: translateY(-1px); }
1599
-
1600
- .btn-capture {
1601
- width: 52px; height: 52px; border-radius: 50%; padding: 0;
1602
- background: #dc2626; border: 4px solid #fff;
1603
- box-shadow: 0 0 0 2px #dc2626, 0 4px 12px rgba(220, 38, 38, 0.3);
1604
- cursor: pointer; transition: all 0.15s;
1605
- }
1606
- .btn-capture:hover { background: #b91c1c; transform: scale(1.05); }
1607
-
1608
- @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
1609
- @keyframes slideUp { from { transform: translateY(18px) scale(0.97); } to { transform: translateY(0) scale(1); } }
1610
- `;let $=ie;W([d.state()],$.prototype,"_stream");W([d.state()],$.prototype,"_error");W([d.state()],$.prototype,"_captured");W([d.state()],$.prototype,"_previewUrl");var et=Object.defineProperty,T=(i,e,t,r)=>{for(var s=void 0,o=i.length-1,n;o>=0;o--)(n=i[o])&&(s=n(e,t,s)||s);return s&&et(e,t,s),s};const ne=class ne extends l.LitElement{constructor(){super(...arguments),this._stream=null,this._recording=!1,this._error="",this._recordedBlob=null,this._previewUrl="",this._recorder=null,this._chunks=[],this._onBackdropClick=e=>{e.target===e.currentTarget&&this._cancel()},this._onKeyDown=e=>{e.key==="Escape"&&this._cancel()},this._startRecording=async()=>{var e;try{this._stream=await navigator.mediaDevices.getDisplayMedia({video:{width:1280,height:720,frameRate:5},audio:!0}),this._stream.getVideoTracks()[0].addEventListener("ended",()=>{this._stopRecording()}),this._recording=!0,await this.updateComplete;const t=(e=this.shadowRoot)==null?void 0:e.querySelector("video");t&&(t.srcObject=this._stream),this._chunks=[];const r=MediaRecorder.isTypeSupported("video/webm;codecs=vp9")?"video/webm;codecs=vp9":"video/webm";this._recorder=new MediaRecorder(this._stream,{mimeType:r}),this._recorder.ondataavailable=s=>{s.data.size>0&&this._chunks.push(s.data)},this._recorder.onstop=()=>{var o;const s=new Blob(this._chunks,{type:"video/webm"});this._recordedBlob=s,this._previewUrl=URL.createObjectURL(s),(o=this._stream)==null||o.getTracks().forEach(n=>n.stop()),this._stream=null},this._recorder.start()}catch{this._error="Could not start screen capture. Please check your permissions."}},this._stopRecording=()=>{var e;this._recording=!1,(e=this._recorder)==null||e.stop(),this._recorder=null},this._useRecording=()=>{if(!this._recordedBlob)return;const e=new Date().toISOString().replace(/[:.]/g,"-").slice(0,19),t=new File([this._recordedBlob],`screencap-${e}.webm`,{type:"video/webm"});this.dispatchEvent(new CustomEvent("screencast-capture",{detail:{file:t},bubbles:!0,composed:!0}))},this._discard=()=>{this._previewUrl&&URL.revokeObjectURL(this._previewUrl),this._recordedBlob=null,this._previewUrl=""}}disconnectedCallback(){super.disconnectedCallback(),this._stopAll(),this._previewUrl&&URL.revokeObjectURL(this._previewUrl)}_stopAll(){var e,t;(e=this._recorder)==null||e.stop(),this._recorder=null,(t=this._stream)==null||t.getTracks().forEach(r=>r.stop()),this._stream=null}_cancel(){this._stopAll(),this.dispatchEvent(new CustomEvent("screencast-cancel",{bubbles:!0,composed:!0}))}render(){return l.html`
1611
- <div class="backdrop" @click=${this._onBackdropClick} @keydown=${this._onKeyDown}>
1612
- <div class="card">
1613
- <div class="head">
1614
- <div class="head-icon">
1615
- <svg viewBox="0 0 24 24">
1616
- <rect x="2" y="3" width="20" height="14" rx="2"/>
1617
- <circle cx="12" cy="10" r="3"/>
1618
- <path d="M7 21h10"/>
1619
- </svg>
1620
- </div>
1621
- <div class="title">Screen cast</div>
1622
- <button class="close-btn" @click=${this._cancel}>\u2715</button>
1623
- </div>
1624
- <div class="body">
1625
- ${this._error?l.html`<div class="error">${this._error}</div>`:this._recordedBlob?l.html`
1626
- <video src=${this._previewUrl} controls></video>
1627
- <div class="actions">
1628
- <button class="btn btn-ghost" @click=${this._discard}>Discard</button>
1629
- <button class="btn btn-primary" @click=${this._useRecording}>Use recording</button>
1630
- </div>
1631
- `:this._recording?l.html`
1632
- <video autoplay playsinline muted></video>
1633
- <div class="status"><div class="rec-dot"></div> Recording...</div>
1634
- <div class="actions">
1635
- <button class="btn btn-danger" @click=${this._stopRecording}>Stop recording</button>
1636
- </div>
1637
- `:l.html`
1638
- <div class="start-view">
1639
- <div class="start-icon">
1640
- <svg viewBox="0 0 24 24">
1641
- <rect x="2" y="3" width="20" height="14" rx="2"/>
1642
- <circle cx="12" cy="10" r="3"/>
1643
- <path d="M7 21h10"/>
1644
- </svg>
1645
- </div>
1646
- <div class="start-text">Share your screen to record a video that will be added to your uploads.</div>
1647
- <div class="actions">
1648
- <button class="btn btn-ghost" @click=${this._cancel}>Cancel</button>
1649
- <button class="btn btn-primary" @click=${this._startRecording}>Start recording</button>
1650
- </div>
1651
- </div>
1652
- `}
1653
- </div>
1654
- </div>
1655
- </div>
1656
- `}};ne.styles=l.css`
1657
- :host { display: block; }
1658
-
1659
- .backdrop {
1660
- position: fixed; inset: 0; z-index: 1000;
1661
- background: rgba(0, 0, 0, 0.4);
1662
- backdrop-filter: blur(6px);
1663
- display: flex; align-items: center; justify-content: center;
1664
- padding: 20px;
1665
- animation: fadeIn 0.18s ease both;
1666
- }
1667
-
1668
- .card {
1669
- background: var(--sfx-up-bg, #fff);
1670
- border-radius: 20px;
1671
- box-shadow: 0 28px 80px rgba(0, 0, 0, 0.18), 0 4px 16px rgba(0, 0, 0, 0.06);
1672
- width: 100%; max-width: 560px;
1673
- overflow: hidden; display: flex; flex-direction: column;
1674
- animation: slideUp 0.28s cubic-bezier(0.34, 1.2, 0.64, 1) forwards;
1675
- }
1676
-
1677
- .head {
1678
- display: flex; align-items: center; gap: 10px;
1679
- padding: 18px 20px 0;
1680
- }
1681
-
1682
- .head-icon {
1683
- width: 34px; height: 34px; border-radius: 10px;
1684
- background: var(--sfx-up-primary-bg, #f5f5f7);
1685
- display: flex; align-items: center; justify-content: center;
1686
- flex-shrink: 0; color: var(--sfx-up-primary, #2563eb);
1687
- }
1688
-
1689
- .head-icon svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
1690
-
1691
- .title { font-size: 15px; font-weight: 700; color: var(--sfx-up-text, #1a1a1a); flex: 1; }
1692
-
1693
- .close-btn {
1694
- width: 28px; height: 28px; border-radius: 8px; border: none;
1695
- background: #f0f0f0; color: #888; font-size: 14px; cursor: pointer;
1696
- display: flex; align-items: center; justify-content: center;
1697
- transition: background 0.15s, color 0.15s; flex-shrink: 0; line-height: 1;
1698
- }
1699
- .close-btn:hover { background: #e4e4e4; color: #333; }
1700
-
1701
- .body { padding: 18px 20px 20px; display: flex; flex-direction: column; align-items: center; gap: 16px; }
1702
-
1703
- video {
1704
- width: 100%; max-height: 320px; border-radius: 12px;
1705
- background: #000; object-fit: contain;
1706
- }
1707
-
1708
- .error { font-size: 13px; color: #dc2626; text-align: center; padding: 40px 20px; }
1709
-
1710
- .status {
1711
- font-size: 13px; color: var(--sfx-up-text-secondary, #475569);
1712
- display: flex; align-items: center; gap: 8px;
1713
- }
1714
-
1715
- .rec-dot {
1716
- width: 10px; height: 10px; border-radius: 50%;
1717
- background: #dc2626; animation: pulse 1s ease-in-out infinite;
1718
- }
1719
-
1720
- .actions { display: flex; gap: 9px; justify-content: center; width: 100%; }
1721
-
1722
- button.btn {
1723
- height: 36px; padding: 0 17px; border-radius: 9px; border: none;
1724
- font-family: inherit; font-size: 13px; font-weight: 600; cursor: pointer;
1725
- display: inline-flex; align-items: center; justify-content: center; gap: 6px;
1726
- transition: all 0.18s ease; white-space: nowrap;
1727
- }
1728
-
1729
- .btn-ghost { background: none; color: #94a3b8; border: 1.5px solid #e8edf5; }
1730
- .btn-ghost:hover { background: #f8faff; color: #64748b; border-color: #d1dff0; }
1731
-
1732
- .btn-primary {
1733
- background: linear-gradient(135deg, var(--sfx-up-primary, #2563eb), #3b82f6);
1734
- color: #fff; box-shadow: 0 2px 10px rgba(37, 99, 235, 0.28);
1735
- }
1736
- .btn-primary:hover { background: linear-gradient(135deg, #1d4ed8, var(--sfx-up-primary, #2563eb)); box-shadow: 0 4px 16px rgba(37, 99, 235, 0.38); transform: translateY(-1px); }
1737
-
1738
- .btn-danger {
1739
- background: #dc2626; color: #fff;
1740
- box-shadow: 0 2px 10px rgba(220, 38, 38, 0.28);
1741
- }
1742
- .btn-danger:hover { background: #b91c1c; }
1743
-
1744
- .start-view {
1745
- display: flex; flex-direction: column; align-items: center; gap: 16px;
1746
- padding: 30px 20px; text-align: center;
1747
- }
1748
-
1749
- .start-icon {
1750
- width: 56px; height: 56px; border-radius: 16px;
1751
- background: var(--sfx-up-primary-bg, #eff6ff);
1752
- color: var(--sfx-up-primary, #2563eb);
1753
- display: flex; align-items: center; justify-content: center;
1754
- }
1755
-
1756
- .start-icon svg { width: 28px; height: 28px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
1757
-
1758
- .start-text {
1759
- font-size: 14px; color: var(--sfx-up-text-secondary, #475569); max-width: 300px;
1760
- }
1761
-
1762
- @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
1763
- @keyframes slideUp { from { transform: translateY(18px) scale(0.97); } to { transform: translateY(0) scale(1); } }
1764
- @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.3; } }
1765
- `;let k=ne;T([d.state()],k.prototype,"_stream");T([d.state()],k.prototype,"_recording");T([d.state()],k.prototype,"_error");T([d.state()],k.prototype,"_recordedBlob");T([d.state()],k.prototype,"_previewUrl");var tt=Object.defineProperty,z=(i,e,t,r)=>{for(var s=void 0,o=i.length-1,n;o>=0;o--)(n=i[o])&&(s=n(e,t,s)||s);return s&&tt(e,t,s),s};const le=new Set(["unsplash"]);var b;const U=(b=class extends l.LitElement{constructor(){super(),this.config=null,this._isOpen=!1,this._activeConnector=null,this._showUrlDialog=!1,this._showCameraDialog=!1,this._showScreenCastDialog=!1,this._engine=null,this._cachedSources=L,this._cachedSourcesConfig=void 0,this._apiBase=null,this._authHeaders=null,this._authResolveId=0,this._prevStoreState=null,this._unsubStoreEvents=null,this._onFilesSelected=e=>{this._processIncomingFiles(e.detail.files)},this._onSourceClick=async e=>{var o,n;const t=e.detail.source,r=this._mergedSources.find(a=>a.id===t);if(r!=null&&r.onActivate){try{r.onActivate(this)}catch(a){console.error(`[sfx-uploader] onActivate for custom source "${t}" threw:`,a)}return}if(t==="device"){const a=this.shadowRoot.querySelector("sfx-drop-zone");a==null||a.browse();return}if(t==="url"){this._showUrlDialog=!0;return}if(t==="camera"){this._showCameraDialog=!0;return}if(t==="screen-cast"){this._showScreenCastDialog=!0;return}if((((n=(o=this.config)==null?void 0:o.connectors)==null?void 0:n.providers)??[]).includes(t)){if(le.has(t)){if(!customElements.get("sfx-search-provider-browser")){const{SfxSearchProviderBrowser:c}=await Promise.resolve().then(()=>require("./search-provider-browser-DxmLznEB.cjs"));customElements.define("sfx-search-provider-browser",c)}}else if(!customElements.get("sfx-provider-browser")){const{SfxProviderBrowser:c}=await Promise.resolve().then(()=>require("./provider-browser-CmCwv0ph.cjs"));customElements.define("sfx-provider-browser",c)}this._activeConnector=t}},this._onUrlSubmit=e=>{var a,c,u;this._showUrlDialog=!1;const{url:t,name:r}=e.detail,s=Te(r),o=s.startsWith("image/"),n={id:F(),status:"idle",file:null,remoteUrl:t,name:r,size:0,type:s,previewUrl:o?t:null,progress:0,speed:0,bytesUploaded:0,error:null,retryCount:0,response:null,addedAt:Date.now(),meta:{},tags:[],remoteInfo:null};I(this._store,n),this._dispatchPublic(h.FILE_ADDED,{file:n}),(u=(c=(a=this.config)==null?void 0:a.callbacks)==null?void 0:c.onFileAdded)==null||u.call(c,n),this._store.getState().queueConfig.autoProceed&&this.upload()},this._onUrlCancel=()=>{this._showUrlDialog=!1},this._onCameraCapture=e=>{this._showCameraDialog=!1,this._processIncomingFiles([e.detail.file])},this._onCameraCancel=()=>{this._showCameraDialog=!1},this._onScreenCastCapture=e=>{this._showScreenCastDialog=!1,this._processIncomingFiles([e.detail.file])},this._onScreenCastCancel=()=>{this._showScreenCastDialog=!1},this._onFileRemove=e=>{var r,s,o,n;const t=this._store.getState().files.get(e.detail.fileId);t!=null&&t.previewUrl&&URL.revokeObjectURL(t.previewUrl),t&&(t.status==="uploading"||t.status==="queued")&&((r=this._engine)==null||r.cancelFile(e.detail.fileId)),me(this._store,e.detail.fileId),t&&(this._dispatchPublic(h.FILE_REMOVED,{file:t}),(n=(o=(s=this.config)==null?void 0:s.callbacks)==null?void 0:o.onFileRemoved)==null||n.call(o,t))},this._onFilePreview=e=>{var r,s,o;const t=this._store.getState().files.get(e.detail.fileId);t&&(this._dispatchPublic(h.FILE_PREVIEW,{file:t}),(o=(s=(r=this.config)==null?void 0:r.callbacks)==null?void 0:s.onFilePreview)==null||o.call(s,t))},this._onFillMetadata=()=>{var t,r,s;const e=[...this._store.getState().files.values()].filter(o=>b._MODIFIABLE_STATUSES.has(o.status));this._dispatchPublic(h.FILL_METADATA,{files:e}),(s=(r=(t=this.config)==null?void 0:t.callbacks)==null?void 0:r.onFillMetadata)==null||s.call(r,e)},this._onFileRetry=e=>{var t;this._ensureEngine(),(t=this._engine)==null||t.retryFile(e.detail.fileId)},this._onRetryAll=()=>{var e;this._ensureEngine(),(e=this._engine)==null||e.retryAll()},this._onClearAll=()=>{var t,r,s;const e=(t=this.config)==null?void 0:t.callbacks;for(const o of this._store.getState().files.values())o.previewUrl&&URL.revokeObjectURL(o.previewUrl),this._dispatchPublic(h.FILE_REMOVED,{file:o}),(r=e==null?void 0:e.onFileRemoved)==null||r.call(e,o);(s=this._engine)==null||s.cancelAll(),this._store.setState({files:new Map,isUploading:!1,totalProgress:0,totalSpeed:0,totalBytesUploaded:0,totalBytes:0})},this._onAddMore=()=>{const e=this.shadowRoot.querySelector("sfx-drop-zone");e==null||e.browse()},this._onUploadStart=()=>{if(this._phase==="complete"){this._onClearAll();return}this.upload()},this._onUploadMore=()=>{this._onClearAll()},this._onConnectorFilesSelected=e=>{var r,s;const t=(r=this.config)==null?void 0:r.callbacks;for(const o of e.detail.files){const n={id:F(),status:"idle",file:null,remoteUrl:null,name:o.name,size:o.size,type:o.mimeType,previewUrl:o.thumbnail,progress:0,speed:0,bytesUploaded:0,error:null,retryCount:0,response:null,addedAt:Date.now(),meta:{},tags:[],remoteInfo:o};I(this._store,n),this._dispatchPublic(h.FILE_ADDED,{file:n}),(s=t==null?void 0:t.onFileAdded)==null||s.call(t,n)}this._activeConnector=null,this._store.getState().queueConfig.autoProceed&&this.upload()},this._onConnectorClose=()=>{this._activeConnector=null},this._onConnectorBackdropClick=e=>{e.target===e.currentTarget&&(this._activeConnector=null)},this._onPrimaryAction=()=>{var e;this._dispatchPublic(h.COMPLETE_ACTION,{}),((e=this.config)==null?void 0:e.mode)==="modal"&&this.close()},this._onModalDismiss=()=>{var e,t,r;(r=(t=(e=this.config)==null?void 0:e.callbacks)==null?void 0:t.onCancel)==null||r.call(t),this._dispatchPublic(h.CANCEL,{}),this.close()},this._onModalBackdropClick=e=>{e.target===e.currentTarget&&this._onModalDismiss()},this._onKeyDown=e=>{var t;e.key==="Escape"&&this._isOpen&&((t=this.config)==null?void 0:t.mode)==="modal"&&this._onModalDismiss()},this._store=pe(),this._storeCtrl=new xe(this,this._store)}open(){var e,t,r;this._isOpen||(this._isOpen=!0,(r=(t=(e=this.config)==null?void 0:e.callbacks)==null?void 0:t.onOpen)==null||r.call(t),this._dispatchPublic(h.OPEN,{}),this.requestUpdate())}close(){var e,t,r;this._isOpen&&(this._isOpen=!1,(r=(t=(e=this.config)==null?void 0:e.callbacks)==null?void 0:t.onClose)==null||r.call(t),this._dispatchPublic(h.CLOSE,{}),this.requestUpdate())}upload(){var s,o,n,a,c;if(this._ensureEngine(),!this._engine){console.warn("[sfx-uploader] Cannot upload: auth not resolved yet");return}const e=[...this._store.getState().files.values()].filter(u=>u.status==="idle"||u.status==="queued");if((o=(s=this.config)==null?void 0:s.callbacks)!=null&&o.onBeforeUpload&&this.config.callbacks.onBeforeUpload(e)===!1)return;const t=new CustomEvent(h.BEFORE_UPLOAD,{bubbles:!0,composed:!0,cancelable:!0,detail:{files:e}});this.dispatchEvent(t)&&(this._dispatchPublic(h.UPLOAD_STARTED,{files:e}),(c=(a=(n=this.config)==null?void 0:n.callbacks)==null?void 0:a.onUploadStarted)==null||c.call(a,e),this._engine.uploadAll())}addFiles(e){this._processIncomingFiles(e)}resumeUpload(e){var t;if(e&&e.length>0){const r=this._store.getState().files,s=new Map(r);let o=!1;for(const n of e){const a=r.get(n.id);a&&(s.set(n.id,{...a,...n}),o=!0)}o&&this._store.setState({files:s})}this._ensureEngine(),(t=this._engine)==null||t.uploadAll()}cancelUpload(){var e;(e=this._engine)==null||e.cancelAll()}getFiles(){return[...this._store.getState().files.values()]}getFile(e){return this._store.getState().files.get(e)}updateFileMeta(e,t,r){const s=this._store.getState().files,o=s.get(e);if(!o||!b._MODIFIABLE_STATUSES.has(o.status))return;const n=new Map(s);n.set(e,{...o,meta:t!=null?{...o.meta,...t}:o.meta,tags:r??o.tags}),this._store.setState({files:n})}updateFilesMeta(e){const t=this._store.getState().files,r=new Map(t);let s=!1;for(const{fileId:o,meta:n,tags:a}of e){const c=t.get(o);!c||!b._MODIFIABLE_STATUSES.has(c.status)||(r.set(o,{...c,meta:n!=null?{...c.meta,...n}:c.meta,tags:a??c.tags}),s=!0)}s&&this._store.setState({files:r})}updated(e){e.has("config")&&this.config&&this._applyConfig(this.config)}connectedCallback(){super.connectedCallback(),document.addEventListener("keydown",this._onKeyDown),this._unsubStoreEvents=this._store.subscribe(()=>this._onStoreChange())}disconnectedCallback(){var e,t;super.disconnectedCallback(),document.removeEventListener("keydown",this._onKeyDown),(e=this._unsubStoreEvents)==null||e.call(this),this._unsubStoreEvents=null,this._prevStoreState=null,(t=this._engine)==null||t.destroy(),this._engine=null}_applyConfig(e){const t={};if(e.targetFolder&&(t.targetFolder=e.targetFolder),e.restrictions&&(t.restrictions={...this._store.getState().restrictions,...e.restrictions}),e.concurrency){const r=this._store.getState().queueConfig;t.queueConfig={...r,concurrency:e.concurrency}}if(e.autoProceed!=null){const r=t.queueConfig??this._store.getState().queueConfig;t.queueConfig={...r,autoProceed:e.autoProceed}}Object.keys(t).length>0&&this._store.setState(t),this._resolveAuthAndEngine(e),(e.mode==="inline"||!e.mode)&&(this._isOpen=!0)}async _resolveAuthAndEngine(e){const t=e.auth;if(t.mode==="sass-key"||t.mode==="session"){this._apiBase=Y(t.container),this._authHeaders=j(t),this._ensureEngine(),this._engine.updateConfig({apiBase:this._apiBase,authHeaders:this._authHeaders});return}const r=++this._authResolveId;try{const s=await fe(t);if(r!==this._authResolveId)return;this._apiBase=s.apiBase,this._authHeaders=s.headers,this._ensureEngine(),this._engine.updateConfig({apiBase:this._apiBase,authHeaders:this._authHeaders})}catch(s){if(r!==this._authResolveId)return;console.error("[sfx-uploader] Auth resolution failed:",s)}}_ensureEngine(){!this._engine&&this._apiBase&&this._authHeaders&&(this._engine=new ue(this._store,{apiBase:this._apiBase,authHeaders:this._authHeaders}),this._engine.start())}_dispatchPublic(e,t){this.dispatchEvent(new CustomEvent(e,{bubbles:!0,composed:!0,detail:t}))}_onStoreChange(){var s,o,n,a,c,u,g;const e=this._store.getState(),t=this._prevStoreState;if(this._prevStoreState=e,!t)return;const r=(s=this.config)==null?void 0:s.callbacks;for(const[f,p]of e.files){const m=t.files.get(f);if(m){if(m.status!==p.status)switch(p.status){case"uploading":break;case"complete":p.response&&(this._dispatchPublic(h.UPLOAD_COMPLETE,{file:p,response:p.response}),(o=r==null?void 0:r.onUploadComplete)==null||o.call(r,p,p.response));break;case"error":case"failed":{const _=new Error(p.error??"Upload failed");this._dispatchPublic(h.UPLOAD_ERROR,{file:p,error:_}),(n=r==null?void 0:r.onUploadError)==null||n.call(r,p,_);break}case"retrying":this._dispatchPublic(h.UPLOAD_RETRY,{file:p,attempt:p.retryCount}),(a=r==null?void 0:r.onUploadRetry)==null||a.call(r,p,p.retryCount);break}p.status==="uploading"&&m.progress!==p.progress&&(this._dispatchPublic(h.UPLOAD_PROGRESS,{file:p,progress:p.progress,speed:p.speed}),(c=r==null?void 0:r.onUploadProgress)==null||c.call(r,p,p.progress,p.speed))}}if(e.totalProgress!==t.totalProgress||e.totalSpeed!==t.totalSpeed){const f=e.totalSpeed>0?(e.totalBytes-e.totalBytesUploaded)/e.totalSpeed:0;this._dispatchPublic(h.TOTAL_PROGRESS,{percentage:e.totalProgress,speed:e.totalSpeed,eta:f}),(u=r==null?void 0:r.onTotalProgress)==null||u.call(r,e.totalProgress,e.totalSpeed,f)}if(t.isUploading&&!e.isUploading){const f=[...e.files.values()];if(!f.some(m=>m.status==="cancelled")){const m=f.filter(C=>C.status==="complete"),_=f.filter(C=>C.status==="failed"||C.status==="error");this._dispatchPublic(h.ALL_COMPLETE,{successful:m,failed:_}),(g=r==null?void 0:r.onAllComplete)==null||g.call(r,m,_)}}}get _mergedSources(){var n;const e=(n=this.config)==null?void 0:n.connectors;if(e===this._cachedSourcesConfig)return this._cachedSources;if(this._cachedSourcesConfig=e,!e)return this._cachedSources=L,this._cachedSources;const t=e.providers.length>0?ge(e.providers):[],r=e.customSources??[],s=new Set,o=[];for(const a of[...L,...t,...r])if(!s.has(a.id)){if(b._RESERVED_IDS.has(a.id)&&a.onActivate){console.warn(`[sfx-uploader] Custom source id "${a.id}" conflicts with a built-in source and was skipped.`);continue}s.add(a.id),o.push(a)}return this._cachedSources=o,this._cachedSources}get _phase(){const e=this._storeCtrl.state,t=[...e.files.values()];if(t.length===0)return"empty";if(e.isUploading)return"uploading";const r=new Set(["complete","rejected","cancelled","failed"]);return t.every(s=>r.has(s.status))&&t.some(s=>s.status==="complete")?"complete":"ready"}_processIncomingFiles(e){var r,s,o;const t=(r=this.config)==null?void 0:r.callbacks;for(const n of e){const a=this._store.getState(),c=Me(n,a.restrictions,a.files);if(c){const f={id:F(),status:"rejected",file:n,remoteUrl:null,name:n.name,size:n.size,type:n.type,previewUrl:null,progress:0,speed:0,bytesUploaded:0,error:c,retryCount:0,response:null,addedAt:Date.now(),meta:{},tags:[],remoteInfo:null};I(this._store,f),this._dispatchPublic(h.FILE_REJECTED,{file:f,reason:c}),(s=t==null?void 0:t.onFileRejected)==null||s.call(t,f,c);continue}let u=null;n.type.startsWith("image/")&&(u=URL.createObjectURL(n));const g={id:F(),status:"idle",file:n,remoteUrl:null,name:n.name,size:n.size,type:n.type,previewUrl:u,progress:0,speed:0,bytesUploaded:0,error:null,retryCount:0,response:null,addedAt:Date.now(),meta:{},tags:[],remoteInfo:null};I(this._store,g),this._dispatchPublic(h.FILE_ADDED,{file:g}),(o=t==null?void 0:t.onFileAdded)==null||o.call(t,g)}this._store.getState().queueConfig.autoProceed&&this.upload()}render(){var t;return(((t=this.config)==null?void 0:t.mode)??"modal")==="modal"?this._isOpen?l.html`
1766
- <div class="modal-backdrop" @click=${this._onModalBackdropClick}>
1767
- <div class="modal-card">
1768
- ${this._renderHeader()}
1769
- ${this._renderBody()}
1770
- </div>
1771
- </div>
1772
- `:l.nothing:l.html`
1773
- <div class="inline">
1774
- ${this._renderBody()}
1775
- </div>
1776
- `}_renderHeader(){return l.html`
1777
- <div class="header">
1778
- <div class="header-title">Upload files</div>
1779
- <button class="close-btn" @click=${this._onModalDismiss}>
1780
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
1781
- <line x1="18" y1="6" x2="6" y2="18" />
1782
- <line x1="6" y1="6" x2="18" y2="18" />
1783
- </svg>
1784
- </button>
1785
- </div>
1786
- `}_renderBody(){var n,a;const e=this._storeCtrl.state,t=[...e.files.values()],r=this._phase,s=Ie(e.restrictions),o=t.length>0;return l.html`
1787
- <div class="content"
1788
- @files-selected=${this._onFilesSelected}
1789
- @source-click=${this._onSourceClick}
1790
- @file-remove=${this._onFileRemove}
1791
- @file-preview=${this._onFilePreview}
1792
- @file-retry=${this._onFileRetry}
1793
- @fill-metadata=${this._onFillMetadata}
1794
- @retry-all=${this._onRetryAll}
1795
- @clear-all=${this._onClearAll}
1796
- @add-more=${this._onAddMore}
1797
- @upload-start=${this._onUploadStart}
1798
- @upload-more=${this._onUploadMore}
1799
- @primary-action=${this._onPrimaryAction}
1800
- @connector-files-selected=${this._onConnectorFilesSelected}
1801
- @connector-close=${this._onConnectorClose}
1802
- @url-submit=${this._onUrlSubmit}
1803
- @url-cancel=${this._onUrlCancel}
1804
- @camera-capture=${this._onCameraCapture}
1805
- @camera-cancel=${this._onCameraCancel}
1806
- @screencast-capture=${this._onScreenCastCapture}
1807
- @screencast-cancel=${this._onScreenCastCancel}
1808
- >
1809
- <div class="body">
1810
- ${r==="complete"?l.html`
1811
- <sfx-success-card
1812
- .fileCount=${t.length}
1813
- ></sfx-success-card>
1814
- `:l.html`
1815
- <sfx-drop-zone
1816
- .compact=${o}
1817
- .accept=${s}
1818
- .sources=${this._mergedSources}
1819
- ></sfx-drop-zone>
1820
-
1821
- ${o?l.nothing:l.html`
1822
- <sfx-import-divider></sfx-import-divider>
1823
- <sfx-source-pills .sources=${this._mergedSources}></sfx-source-pills>
1824
- `}
1825
-
1826
- ${o?l.html`
1827
- <sfx-file-list .files=${t}></sfx-file-list>
1828
- `:l.nothing}
1829
- `}
1830
- </div>
1831
-
1832
- ${o?l.html`
1833
- <sfx-actions-bar
1834
- .uploadState=${r==="complete"?"done":r==="uploading"?"uploading":"idle"}
1835
- .fileCount=${t.length}
1836
- .failedCount=${t.filter(c=>c.status==="failed"||c.status==="error").length}
1837
- .showFillMetadata=${!!((n=this.config)!=null&&n.showFillMetadata)}
1838
- ></sfx-actions-bar>
1839
- `:l.nothing}
1840
-
1841
- ${this._showUrlDialog?l.html`<sfx-url-dialog></sfx-url-dialog>`:l.nothing}
1842
- ${this._showCameraDialog?l.html`<sfx-camera-dialog></sfx-camera-dialog>`:l.nothing}
1843
- ${this._showScreenCastDialog?l.html`<sfx-screen-cast-dialog></sfx-screen-cast-dialog>`:l.nothing}
1844
-
1845
- ${this._activeConnector&&((a=this.config)!=null&&a.connectors)?l.html`
1846
- <div class="connector-modal-backdrop" @click=${this._onConnectorBackdropClick}>
1847
- <div class="connector-modal">
1848
- ${le.has(this._activeConnector)?l.html`
1849
- <sfx-search-provider-browser
1850
- .provider=${this._activeConnector}
1851
- .companionUrl=${this.config.connectors.companionUrl}
1852
- ></sfx-search-provider-browser>
1853
- `:l.html`
1854
- <sfx-provider-browser
1855
- .provider=${this._activeConnector}
1856
- .companionUrl=${this.config.connectors.companionUrl}
1857
- ></sfx-provider-browser>
1858
- `}
1859
- </div>
1860
- </div>
1861
- `:l.nothing}
1862
- </div>
1863
- `}},b.styles=l.css`
1864
- :host {
1865
- display: block;
1866
- font-family: var(--sfx-up-font, 'Inter', system-ui, -apple-system, sans-serif);
1867
- color: var(--sfx-up-text, #1e293b);
1868
- --sfx-up-primary: #2563eb;
1869
- --sfx-up-primary-hover: #1d4ed8;
1870
- --sfx-up-primary-mid: #3b82f6;
1871
- --sfx-up-primary-bg: #eff6ff;
1872
- --sfx-up-primary-glow: rgba(37, 99, 235, 0.18);
1873
- --sfx-up-success: #16a34a;
1874
- --sfx-up-error: #dc2626;
1875
- --sfx-up-text: #1e293b;
1876
- --sfx-up-text-secondary: #475569;
1877
- --sfx-up-text-muted: #94a3b8;
1878
- --sfx-up-border: #e8edf5;
1879
- --sfx-up-border-light: #f1f5f9;
1880
- --sfx-up-bg: #ffffff;
1881
- --sfx-up-radius: 16px;
1882
- --sfx-up-font: 'Inter', system-ui, -apple-system, sans-serif;
1883
- }
1884
-
1885
- /* --- Modal overlay --- */
1886
- .modal-backdrop {
1887
- position: fixed;
1888
- inset: 0;
1889
- background: rgba(0, 0, 0, 0.45);
1890
- display: flex;
1891
- align-items: center;
1892
- justify-content: center;
1893
- z-index: 9999;
1894
- animation: fadeIn 0.2s ease;
1895
- }
1896
-
1897
- .modal-card {
1898
- background: var(--sfx-up-bg, #fff);
1899
- border-radius: 20px;
1900
- box-shadow: 0 25px 60px rgba(0, 0, 0, 0.2);
1901
- width: 90vw;
1902
- max-width: 680px;
1903
- max-height: 85vh;
1904
- display: flex;
1905
- flex-direction: column;
1906
- overflow: hidden;
1907
- animation: modalIn 0.25s cubic-bezier(0.34, 1.2, 0.64, 1);
1908
- }
1909
-
1910
- /* --- Header --- */
1911
- .header {
1912
- display: flex;
1913
- align-items: center;
1914
- justify-content: space-between;
1915
- padding: 18px 24px;
1916
- border-bottom: 1px solid var(--sfx-up-border-light, #f1f5f9);
1917
- }
1918
-
1919
- .header-title {
1920
- font-size: 16px;
1921
- font-weight: 700;
1922
- color: var(--sfx-up-text, #1e293b);
1923
- }
1924
-
1925
- .close-btn {
1926
- width: 32px;
1927
- height: 32px;
1928
- border-radius: 8px;
1929
- border: none;
1930
- background: none;
1931
- cursor: pointer;
1932
- display: flex;
1933
- align-items: center;
1934
- justify-content: center;
1935
- color: var(--sfx-up-text-muted, #94a3b8);
1936
- transition: all 0.15s;
1937
- }
1938
-
1939
- .close-btn:hover {
1940
- background: #f1f5f9;
1941
- color: var(--sfx-up-text, #1e293b);
1942
- }
1943
-
1944
- .close-btn svg {
1945
- width: 18px;
1946
- height: 18px;
1947
- }
1948
-
1949
- /* --- Content wrapper (holds body + actions bar) --- */
1950
- .content {
1951
- flex: 1;
1952
- display: flex;
1953
- flex-direction: column;
1954
- min-height: 0;
1955
- }
1956
-
1957
- /* --- Body --- */
1958
- .body {
1959
- flex: 1;
1960
- overflow-y: auto;
1961
- padding: 24px;
1962
- display: flex;
1963
- flex-direction: column;
1964
- gap: 4px;
1965
- min-height: 0;
1966
- }
1967
-
1968
- .body sfx-drop-zone {
1969
- position: relative;
1970
- z-index: 1;
1971
- }
1972
-
1973
- /* --- Inline mode --- */
1974
- .inline {
1975
- border: 1px solid var(--sfx-up-border, #e8edf5);
1976
- border-radius: var(--sfx-up-radius, 16px);
1977
- display: flex;
1978
- flex-direction: column;
1979
- overflow: hidden;
1980
- }
1981
-
1982
- /* --- Connector modal overlay --- */
1983
- .connector-modal-backdrop {
1984
- position: fixed;
1985
- inset: 0;
1986
- z-index: 1000;
1987
- background: rgba(0, 0, 0, 0.4);
1988
- backdrop-filter: blur(6px);
1989
- display: flex;
1990
- align-items: center;
1991
- justify-content: center;
1992
- padding: 20px;
1993
- animation: fadeIn 0.18s ease both;
1994
- }
1995
-
1996
- .connector-modal {
1997
- background: var(--sfx-up-bg, #fff);
1998
- border-radius: 20px;
1999
- box-shadow: 0 28px 80px rgba(0, 0, 0, 0.18), 0 4px 16px rgba(0, 0, 0, 0.06);
2000
- width: 100%;
2001
- max-width: 540px;
2002
- height: 80vh;
2003
- overflow: hidden;
2004
- display: flex;
2005
- flex-direction: column;
2006
- animation: modalIn 0.28s cubic-bezier(0.34, 1.2, 0.64, 1) forwards;
2007
- }
2008
-
2009
- @keyframes fadeIn {
2010
- from { opacity: 0; }
2011
- to { opacity: 1; }
2012
- }
2013
-
2014
- @keyframes modalIn {
2015
- from {
2016
- opacity: 0;
2017
- transform: scale(0.92) translateY(10px);
2018
- }
2019
- to {
2020
- opacity: 1;
2021
- transform: scale(1) translateY(0);
2022
- }
2023
- }
2024
-
2025
- @media (prefers-reduced-motion: reduce) {
2026
- .modal-backdrop { animation: none; }
2027
- .modal-card { animation: none; }
2028
- }
2029
- `,b._MODIFIABLE_STATUSES=new Set(["idle","queued","validating","rejected"]),b._RESERVED_IDS=new Set(["device","camera","screen-cast","url"]),b);z([d.property({attribute:!1})],U.prototype,"config");z([d.state()],U.prototype,"_isOpen");z([d.state()],U.prototype,"_activeConnector");z([d.state()],U.prototype,"_showUrlDialog");z([d.state()],U.prototype,"_showCameraDialog");z([d.state()],U.prototype,"_showScreenCastDialog");let rt=U;exports.AuthExpiredError=V;exports.CORE_SOURCES=L;exports.PublicEvents=h;exports.SfxActionsBar=E;exports.SfxCameraDialog=$;exports.SfxDropZone=w;exports.SfxFileItem=q;exports.SfxFileList=H;exports.SfxImportDivider=G;exports.SfxScreenCastDialog=k;exports.SfxSourcePills=B;exports.SfxSuccessCard=O;exports.SfxUploader=rt;exports.SfxUrlDialog=S;exports.Store=de;exports.UploadEngine=ue;exports.buildAuthHeaders=j;exports.createStore=pe;exports.exchangeSassKey=he;exports.getApiBase=Y;exports.getAuthUrl=_e;exports.getProviderSources=ge;exports.listFiles=ke;exports.listNextPage=Ce;exports.logout=$e;exports.resolveAuth=fe;exports.searchProvider=Ee;