@scaleflex/uploader 0.1.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 (96) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/LICENSE +50 -0
  3. package/README.md +123 -0
  4. package/dist/auth/auth.service.d.ts +25 -0
  5. package/dist/auth/auth.service.d.ts.map +1 -0
  6. package/dist/auth/auth.types.d.ts +24 -0
  7. package/dist/auth/auth.types.d.ts.map +1 -0
  8. package/dist/auth/index.d.ts +3 -0
  9. package/dist/auth/index.d.ts.map +1 -0
  10. package/dist/components/actions-bar.d.ts +17 -0
  11. package/dist/components/actions-bar.d.ts.map +1 -0
  12. package/dist/components/camera-dialog.d.ts +27 -0
  13. package/dist/components/camera-dialog.d.ts.map +1 -0
  14. package/dist/components/drop-zone.d.ts +28 -0
  15. package/dist/components/drop-zone.d.ts.map +1 -0
  16. package/dist/components/file-item.d.ts +12 -0
  17. package/dist/components/file-item.d.ts.map +1 -0
  18. package/dist/components/file-list.d.ts +8 -0
  19. package/dist/components/file-list.d.ts.map +1 -0
  20. package/dist/components/import-divider.d.ts +6 -0
  21. package/dist/components/import-divider.d.ts.map +1 -0
  22. package/dist/components/index.d.ts +9 -0
  23. package/dist/components/index.d.ts.map +1 -0
  24. package/dist/components/provider-browser.d.ts +48 -0
  25. package/dist/components/provider-browser.d.ts.map +1 -0
  26. package/dist/components/screen-cast-dialog.d.ts +29 -0
  27. package/dist/components/screen-cast-dialog.d.ts.map +1 -0
  28. package/dist/components/search-provider-browser.d.ts +36 -0
  29. package/dist/components/search-provider-browser.d.ts.map +1 -0
  30. package/dist/components/source-pills.d.ts +11 -0
  31. package/dist/components/source-pills.d.ts.map +1 -0
  32. package/dist/components/success-card.d.ts +10 -0
  33. package/dist/components/success-card.d.ts.map +1 -0
  34. package/dist/components/url-dialog.d.ts +25 -0
  35. package/dist/components/url-dialog.d.ts.map +1 -0
  36. package/dist/connectors/companion-client.d.ts +58 -0
  37. package/dist/connectors/companion-client.d.ts.map +1 -0
  38. package/dist/connectors/connector.types.d.ts +56 -0
  39. package/dist/connectors/connector.types.d.ts.map +1 -0
  40. package/dist/connectors/index.d.ts +5 -0
  41. package/dist/connectors/index.d.ts.map +1 -0
  42. package/dist/connectors/provider-registry.d.ts +8 -0
  43. package/dist/connectors/provider-registry.d.ts.map +1 -0
  44. package/dist/connectors/token-store.d.ts +10 -0
  45. package/dist/connectors/token-store.d.ts.map +1 -0
  46. package/dist/controllers/store.controller.d.ts +14 -0
  47. package/dist/controllers/store.controller.d.ts.map +1 -0
  48. package/dist/define.cjs +1 -0
  49. package/dist/define.d.ts +2 -0
  50. package/dist/define.d.ts.map +1 -0
  51. package/dist/define.js +15 -0
  52. package/dist/engine/companion-upload.d.ts +23 -0
  53. package/dist/engine/companion-upload.d.ts.map +1 -0
  54. package/dist/engine/index.d.ts +2 -0
  55. package/dist/engine/index.d.ts.map +1 -0
  56. package/dist/engine/upload-engine.d.ts +56 -0
  57. package/dist/engine/upload-engine.d.ts.map +1 -0
  58. package/dist/engine/xhr-upload.d.ts +25 -0
  59. package/dist/engine/xhr-upload.d.ts.map +1 -0
  60. package/dist/events/event-bus.d.ts +38 -0
  61. package/dist/events/event-bus.d.ts.map +1 -0
  62. package/dist/events/public-events.d.ts +23 -0
  63. package/dist/events/public-events.d.ts.map +1 -0
  64. package/dist/index.cjs +1 -0
  65. package/dist/index.d.ts +17 -0
  66. package/dist/index.d.ts.map +1 -0
  67. package/dist/index.js +21 -0
  68. package/dist/provider-browser-C-S_MPrC.js +832 -0
  69. package/dist/provider-browser-CmCwv0ph.cjs +581 -0
  70. package/dist/react.cjs +1 -0
  71. package/dist/react.d.ts +33 -0
  72. package/dist/react.d.ts.map +1 -0
  73. package/dist/react.js +125 -0
  74. package/dist/search-provider-browser-DxmLznEB.cjs +390 -0
  75. package/dist/search-provider-browser-jCOer2Y9.js +537 -0
  76. package/dist/sfx-uploader-BVDK-9xi.cjs +2029 -0
  77. package/dist/sfx-uploader-C2lWIRnU.js +3789 -0
  78. package/dist/sfx-uploader.d.ts +131 -0
  79. package/dist/sfx-uploader.d.ts.map +1 -0
  80. package/dist/store/helpers.d.ts +16 -0
  81. package/dist/store/helpers.d.ts.map +1 -0
  82. package/dist/store/index.d.ts +7 -0
  83. package/dist/store/index.d.ts.map +1 -0
  84. package/dist/store/store.d.ts +14 -0
  85. package/dist/store/store.d.ts.map +1 -0
  86. package/dist/store/store.types.d.ts +77 -0
  87. package/dist/store/store.types.d.ts.map +1 -0
  88. package/dist/test-utils.d.ts +5 -0
  89. package/dist/test-utils.d.ts.map +1 -0
  90. package/dist/types/source.types.d.ts +12 -0
  91. package/dist/types/source.types.d.ts.map +1 -0
  92. package/dist/utils/file-utils.d.ts +14 -0
  93. package/dist/utils/file-utils.d.ts.map +1 -0
  94. package/dist/utils/validate.d.ts +6 -0
  95. package/dist/utils/validate.d.ts.map +1 -0
  96. package/package.json +72 -0
@@ -0,0 +1,2029 @@
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;