@scaleflex/uploader 0.2.6 → 0.2.8

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 (115) hide show
  1. package/.claude/skills/integrate-uploader/SKILL.md +4 -3
  2. package/CHANGELOG.md +16 -1
  3. package/README.md +3 -3
  4. package/dist/components/actions-bar.d.ts +2 -0
  5. package/dist/components/actions-bar.d.ts.map +1 -1
  6. package/dist/components/drop-zone.d.ts.map +1 -1
  7. package/dist/components/file-item.d.ts +6 -0
  8. package/dist/components/file-item.d.ts.map +1 -1
  9. package/dist/components/file-list.d.ts.map +1 -1
  10. package/dist/components/toast.d.ts +18 -0
  11. package/dist/components/toast.d.ts.map +1 -0
  12. package/dist/define.cjs +1 -1
  13. package/dist/define.js +1 -1
  14. package/dist/engine/index.d.ts +1 -0
  15. package/dist/engine/index.d.ts.map +1 -1
  16. package/dist/engine/tus-upload.d.ts +52 -0
  17. package/dist/engine/tus-upload.d.ts.map +1 -0
  18. package/dist/engine/upload-engine.d.ts +14 -0
  19. package/dist/engine/upload-engine.d.ts.map +1 -1
  20. package/dist/engine/xhr-upload.d.ts.map +1 -1
  21. package/dist/events/public-events.d.ts +2 -0
  22. package/dist/events/public-events.d.ts.map +1 -1
  23. package/dist/index-D7hE18PK.js +3541 -0
  24. package/dist/index-DuX47Oy3.cjs +1625 -0
  25. package/dist/index.cjs +1 -1
  26. package/dist/index.d.ts +3 -2
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +1 -1
  29. package/dist/metadata/bulk/bulk-meta-diff-view.d.ts +17 -0
  30. package/dist/metadata/bulk/bulk-meta-diff-view.d.ts.map +1 -0
  31. package/dist/metadata/bulk/bulk-meta-op-bar.d.ts +38 -0
  32. package/dist/metadata/bulk/bulk-meta-op-bar.d.ts.map +1 -0
  33. package/dist/metadata/bulk/bulk-meta-row.d.ts +35 -0
  34. package/dist/metadata/bulk/bulk-meta-row.d.ts.map +1 -0
  35. package/dist/metadata/bulk/bulk-meta-sidebar.d.ts +20 -0
  36. package/dist/metadata/bulk/bulk-meta-sidebar.d.ts.map +1 -0
  37. package/dist/metadata/bulk/bulk-meta-table.d.ts +20 -0
  38. package/dist/metadata/bulk/bulk-meta-table.d.ts.map +1 -0
  39. package/dist/metadata/bulk/bulk-metadata-modal.d.ts +46 -0
  40. package/dist/metadata/bulk/bulk-metadata-modal.d.ts.map +1 -0
  41. package/dist/metadata/bulk/bulk-metadata.styles.d.ts +7 -0
  42. package/dist/metadata/bulk/bulk-metadata.styles.d.ts.map +1 -0
  43. package/dist/metadata/bulk/bulk-operations.d.ts +14 -0
  44. package/dist/metadata/bulk/bulk-operations.d.ts.map +1 -0
  45. package/dist/metadata/bulk/diff-utils.d.ts +19 -0
  46. package/dist/metadata/bulk/diff-utils.d.ts.map +1 -0
  47. package/dist/metadata/bulk/index.d.ts +3 -0
  48. package/dist/metadata/bulk/index.d.ts.map +1 -0
  49. package/dist/metadata/field-type-icons.d.ts +4 -0
  50. package/dist/metadata/field-type-icons.d.ts.map +1 -0
  51. package/dist/metadata/fields/boolean-field.d.ts +17 -0
  52. package/dist/metadata/fields/boolean-field.d.ts.map +1 -0
  53. package/dist/metadata/fields/date-field.d.ts +10 -0
  54. package/dist/metadata/fields/date-field.d.ts.map +1 -0
  55. package/dist/metadata/fields/field-base.d.ts +14 -0
  56. package/dist/metadata/fields/field-base.d.ts.map +1 -0
  57. package/dist/metadata/fields/geo-point-field.d.ts +10 -0
  58. package/dist/metadata/fields/geo-point-field.d.ts.map +1 -0
  59. package/dist/metadata/fields/multi-select-field.d.ts +23 -0
  60. package/dist/metadata/fields/multi-select-field.d.ts.map +1 -0
  61. package/dist/metadata/fields/number-field.d.ts +10 -0
  62. package/dist/metadata/fields/number-field.d.ts.map +1 -0
  63. package/dist/metadata/fields/select-field.d.ts +21 -0
  64. package/dist/metadata/fields/select-field.d.ts.map +1 -0
  65. package/dist/metadata/fields/tags-field.d.ts +29 -0
  66. package/dist/metadata/fields/tags-field.d.ts.map +1 -0
  67. package/dist/metadata/fields/text-field.d.ts +9 -0
  68. package/dist/metadata/fields/text-field.d.ts.map +1 -0
  69. package/dist/metadata/fields/textarea-field.d.ts +11 -0
  70. package/dist/metadata/fields/textarea-field.d.ts.map +1 -0
  71. package/dist/metadata/index.d.ts +9 -0
  72. package/dist/metadata/index.d.ts.map +1 -0
  73. package/dist/metadata/metadata-field-edit.d.ts +16 -0
  74. package/dist/metadata/metadata-field-edit.d.ts.map +1 -0
  75. package/dist/metadata/metadata-field-view.d.ts +10 -0
  76. package/dist/metadata/metadata-field-view.d.ts.map +1 -0
  77. package/dist/metadata/metadata-field.d.ts +22 -0
  78. package/dist/metadata/metadata-field.d.ts.map +1 -0
  79. package/dist/metadata/metadata-form.d.ts +15 -0
  80. package/dist/metadata/metadata-form.d.ts.map +1 -0
  81. package/dist/metadata/metadata-panel.d.ts +37 -0
  82. package/dist/metadata/metadata-panel.d.ts.map +1 -0
  83. package/dist/metadata/metadata.styles.d.ts +11 -0
  84. package/dist/metadata/metadata.styles.d.ts.map +1 -0
  85. package/dist/metadata/schema/required-fields.d.ts +24 -0
  86. package/dist/metadata/schema/required-fields.d.ts.map +1 -0
  87. package/dist/metadata/schema/schema-parser.d.ts +3 -0
  88. package/dist/metadata/schema/schema-parser.d.ts.map +1 -0
  89. package/dist/metadata/schema/schema-service.d.ts +5 -0
  90. package/dist/metadata/schema/schema-service.d.ts.map +1 -0
  91. package/dist/metadata/schema/schema.types.d.ts +112 -0
  92. package/dist/metadata/schema/schema.types.d.ts.map +1 -0
  93. package/dist/metadata/schema/validation.d.ts +4 -0
  94. package/dist/metadata/schema/validation.d.ts.map +1 -0
  95. package/dist/metadata/schema/value-transforms.d.ts +5 -0
  96. package/dist/metadata/schema/value-transforms.d.ts.map +1 -0
  97. package/dist/metadata/tags/tag-utils.d.ts +6 -0
  98. package/dist/metadata/tags/tag-utils.d.ts.map +1 -0
  99. package/dist/metadata/tags/tags-autocomplete.d.ts +7 -0
  100. package/dist/metadata/tags/tags-autocomplete.d.ts.map +1 -0
  101. package/dist/{provider-browser-B85iISh9.cjs → provider-browser-D9DOIUnq.cjs} +1 -1
  102. package/dist/{provider-browser-DcYDZQos.js → provider-browser-qRo0t4Wt.js} +1 -1
  103. package/dist/{search-provider-browser-Cn0v6Gcq.js → search-provider-browser-DarbREgH.js} +1 -1
  104. package/dist/{search-provider-browser-DqKnNu87.cjs → search-provider-browser-xP28_tO-.cjs} +1 -1
  105. package/dist/sfx-uploader-BqMTQWrE.cjs +4913 -0
  106. package/dist/{sfx-uploader-C3Z9k-Q8.js → sfx-uploader-D9z-E7SI.js} +4248 -1254
  107. package/dist/sfx-uploader.d.ts +53 -6
  108. package/dist/sfx-uploader.d.ts.map +1 -1
  109. package/dist/store/store.types.d.ts +3 -1
  110. package/dist/store/store.types.d.ts.map +1 -1
  111. package/dist/test-utils.d.ts.map +1 -1
  112. package/dist/utils/portal-target.d.ts +4 -2
  113. package/dist/utils/portal-target.d.ts.map +1 -1
  114. package/package.json +3 -2
  115. package/dist/sfx-uploader-C_E3gvgv.cjs +0 -4647
@@ -1,4647 +0,0 @@
1
- "use strict";const s=require("lit"),c=require("lit/decorators.js"),z=require("lit/directives/unsafe-svg.js"),M=require("lit/directives/unsafe-html.js");class Se{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(o=>o(this.state,t))}finally{this._notifying=!1}if(this._pendingState){const o=this._pendingState;this._pendingState=null,this.setState(o)}}subscribe(e){return this.listeners.add(e),()=>this.listeners.delete(e)}destroy(){this.listeners.clear()}}function S(n,e,t){const o=n.getState().files,r=o.get(e);if(!r)return;const i=new Map(o);i.set(e,{...r,...t}),n.setState({files:i})}function L(n,e){const t=new Map(n.getState().files);t.set(e.id,e),n.setState({files:t})}function me(n,e){const t=n.getState().files;if(!t.has(e))return;const o=new Map(t);o.delete(e),n.setState({files:o})}function Ee(){return new Se({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 je{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 Me(n,e){const t=new XMLHttpRequest;let o=!1;const i=`${e.apiBase.replace(/\/+$/,"")}/v4/files?folder=${encodeURIComponent(e.folder)}`;t.open("POST",i);for(const[l,d]of Object.entries(e.authHeaders))t.setRequestHeader(l,d);t.upload.addEventListener("progress",l=>{l.lengthComputable&&!o&&e.onProgress(l.loaded,l.total)}),t.addEventListener("load",()=>{if(o)return;let l;try{l=JSON.parse(t.responseText)}catch{e.onError(new Error(`Invalid JSON response (HTTP ${t.status})`));return}t.status>=200&&t.status<300&&l.status==="success"?e.onComplete(l):e.onError(new Error(l.hint||l.msg||`Upload failed (HTTP ${t.status})`))}),t.addEventListener("error",()=>{o||e.onError(new Error("Network error — check your connection"))}),t.addEventListener("timeout",()=>{o||e.onError(new Error("Upload timed out"))});const a=new FormData;if(n.file){const l={name:n.name,type:n.type};Object.keys(n.meta).length>0&&(l.meta=n.meta),n.tags.length>0&&(l.tags=n.tags),a.append("info[files[]]",JSON.stringify(l)),a.append("files[]",n.file,n.name)}return t.timeout=6e4,t.send(a),{abort(){o=!0,t.abort()}}}function Oe(n,e){const t=new XMLHttpRequest;let o=!1;const i=`${e.apiBase.replace(/\/+$/,"")}/v4/files/upload_url`;t.open("POST",i);for(const[l,d]of Object.entries(e.authHeaders))t.setRequestHeader(l,d);if(t.setRequestHeader("Content-Type","application/json"),t.addEventListener("load",()=>{if(o)return;let l;try{l=JSON.parse(t.responseText)}catch{e.onError(new Error(`Invalid JSON response (HTTP ${t.status})`));return}t.status>=200&&t.status<300&&l.status==="success"?e.onComplete(l):e.onError(new Error(l.hint||l.msg||`Upload failed (HTTP ${t.status})`))}),t.addEventListener("error",()=>{o||e.onError(new Error("Network error — check your connection"))}),t.addEventListener("timeout",()=>{o||e.onError(new Error("Upload timed out"))}),!n.remoteUrl)return e.onError(new Error("Remote URL is required for URL upload")),{abort(){}};const a={files_urls:[{url:n.remoteUrl,name:n.name}],dir:e.folder};return t.timeout=6e4,t.send(JSON.stringify(a)),{abort(){o=!0,t.abort()}}}function Q(n){return{Accept:"application/json","Content-Type":"application/json","uppy-auth-token":n}}function H(n){return n.replace(/\/+$/,"")}const Re={"google-drive":"drive",dropbox:"dropbox",onedrive:"onedrive",box:"box",instagram:"instagram",facebook:"facebook",unsplash:"unsplash"};function Y(n){return Re[n]??n}function Le(n,e){const t=H(n),o=btoa(JSON.stringify({origin:window.location.origin})),r=Y(e);return`${t}/${r}/connect?state=${encodeURIComponent(o)}`}async function Te(n,e,t,o=""){const r=H(n),i=o?`/${o}`:"",a=Y(e),l=await fetch(`${r}/${a}/list${i}`,{method:"GET",headers:Q(t),credentials:"same-origin"});if(l.status===401)throw new ee;if(!l.ok){const d=await l.json().catch(()=>null);throw new Error((d==null?void 0:d.message)||`Companion list failed (HTTP ${l.status})`)}return l.json()}async function Be(n,e,t){const o=H(n),r=await fetch(`${o}/${t}`,{method:"GET",headers:Q(e),credentials:"same-origin"});if(r.status===401)throw new ee;if(!r.ok){const i=await r.json().catch(()=>null);throw new Error((i==null?void 0:i.message)||`Companion list failed (HTTP ${r.status})`)}return r.json()}async function Ae(n,e,t,o){const r=H(n),i=Y(e),a=o?`q=${encodeURIComponent(t)}&${o}`:`q=${encodeURIComponent(t)}`,l=await fetch(`${r}/search/${i}/list?${a}`,{method:"GET",headers:{Accept:"application/json","Content-Type":"application/json"},credentials:"same-origin"});if(!l.ok){const d=await l.json().catch(()=>null);throw new Error((d==null?void 0:d.message)||`Search failed (HTTP ${l.status})`)}return l.json()}async function Ie(n,e,t,o,r,i=!1){const a=H(n),l=Y(e),d=i?`${a}/search/${l}/get/${o}`:`${a}/${l}/get/${o}`,p=i?{Accept:"application/json","Content-Type":"application/json"}:Q(t),h=await fetch(d,{method:"POST",headers:p,credentials:"same-origin",body:JSON.stringify({...r,httpMethod:r.httpMethod??"POST",useFormData:r.useFormData??!0,fieldname:r.fieldname??"files[]"})});if(h.status===401)throw new ee;if(!h.ok){const u=await h.json().catch(()=>null);throw new Error((u==null?void 0:u.message)||`Companion upload failed (HTTP ${h.status})`)}return h.json()}async function He(n,e,t){const o=H(n),r=Y(e),i=await fetch(`${o}/${r}/logout`,{method:"GET",headers:Q(t),credentials:"same-origin"});return i.ok?i.json():{ok:!1,revoked:!1}}function qe(n){var r;const t=((r=/^(?:https?:\/\/|\/\/)?(?:[^@\n]+@)?(?:www\.)?([^\n]+)/i.exec(n))==null?void 0:r[1])??n;return`${location.protocol==="https:"?"wss":"ws"}://${t}`}class ee extends Error{constructor(){super("Authentication expired"),this.name="AuthExpiredError"}}function Ye(n,e){const t=n.remoteInfo;if(!t)return e.onError(new Error("remoteInfo is required for companion upload")),{abort(){}};let o=!1,r=null;const a=`${e.apiBase.replace(/\/+$/,"")}/v4/files?folder=${encodeURIComponent(e.folder)}`,l={};n.meta&&Object.keys(n.meta).length>0&&Object.assign(l,n.meta),n.tags&&n.tags.length>0&&(l.tags=n.tags);const d=!t.token;return Ie(t.companionUrl,t.provider,t.token,t.requestPath,{fileId:t.fileId,endpoint:a,headers:e.authHeaders,size:t.size,metadata:Object.keys(l).length>0?l:void 0},d).then(p=>{if(o)return;const u=`${qe(t.companionUrl)}/api/${p.token}`;try{r=new WebSocket(u)}catch{e.onError(new Error("Failed to connect to upload progress channel"));return}r.onmessage=x=>{var f,v,w;if(!o)try{const b=JSON.parse(x.data);switch(b.action){case"progress":{const m=b.payload,_=m.bytesUploaded??0,E=m.bytesTotal??(t.size||1);e.onProgress(_,E);break}case"success":{const m=b.payload;if(r==null||r.close(),(f=m.response)!=null&&f.responseText)try{const _=JSON.parse(m.response.responseText);if(_.status==="success"){e.onComplete(_);return}e.onError(new Error(_.msg||"Upload failed"));return}catch{}e.onError(new Error("Upload completed but no valid response received"));break}case"error":{r==null||r.close();const m=b.payload;let _=((v=m.error)==null?void 0:v.message)||"Upload failed";if((w=m.response)!=null&&w.responseText)try{const E=JSON.parse(m.response.responseText);_=E.hint||E.msg||E.message||_}catch{}e.onError(new Error(_));break}}}catch{}},r.onerror=()=>{o||e.onError(new Error("Upload progress connection failed"))},r.onclose=()=>{r=null}}).catch(p=>{o||e.onError(p instanceof Error?p:new Error(String(p)))}),{abort(){if(o=!0,r){try{r.send(JSON.stringify({action:"cancel",payload:{}}))}catch{}r.close(),r=null}}}}class Pe{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 o of e.values())o.status==="idle"?(S(this.store,o.id,{status:"queued"}),t=!0):o.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"||(S(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")&&S(this.store,t.id,{status:"queued",error:null,progress:0,bytesUploaded:0,speed:0});this.processQueue()}cancelFile(e){const t=this.store.getState().files.get(e);!t||!we(t.status)||(this.abortUpload(e),S(this.store,e,{status:"cancelled"}))}cancelAll(){const{files:e}=this.store.getState();for(const t of e.values())we(t.status)&&(this.abortUpload(t.id),S(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,o=this.activeUploads.size,r=t-o;if(r<=0)return;const a=[...e.files.values()].filter(l=>l.status==="queued").sort((l,d)=>l.retryCount!==d.retryCount?d.retryCount-l.retryCount:l.addedAt-d.addedAt).slice(0,r);for(const l of a)this.startUpload(l)}startUpload(e){S(this.store,e.id,{status:"uploading",error:null});let t=0,o=Date.now(),r=0;const i={apiBase:this.config.apiBase,authHeaders:this.config.authHeaders,folder:this.store.getState().targetFolder,onComplete:d=>this.handleComplete(e.id,d),onError:d=>this.handleError(e.id,d)},a=(d,p)=>{const h=Date.now(),u=(h-o)/1e3;if(u>0){const f=(d-t)/u;r=r===0?f:.3*f+.7*r}t=d,o=h;const x=p>0?Math.min(d/p*100,100):0;S(this.store,e.id,{progress:x,bytesUploaded:d,speed:r}),this.updateTotalProgress()};let l;e.remoteInfo?l=Ye(e,{...i,onProgress:a}):e.remoteUrl?l=Oe(e,i):l=Me(e,{...i,onProgress:a}),this.activeUploads.set(e.id,l)}handleComplete(e,t){this.activeUploads.delete(e),S(this.store,e,{status:"complete",progress:100,response:t}),this.updateTotalProgress(),this.checkAllComplete(),this.processQueue()}handleError(e,t){this.activeUploads.delete(e);const o=this.store.getState().files.get(e);if(!o)return;const{retryConfig:r}=this.store.getState().queueConfig,i=o.retryCount+1;if(i<=r.maxRetries){const a=Math.min(r.baseDelay*Math.pow(r.backoffFactor,o.retryCount),r.maxDelay);S(this.store,e,{status:"retrying",error:t.message,retryCount:i});const l=setTimeout(()=>{this.retryTimers.delete(e),S(this.store,e,{status:"queued"}),this.processQueue()},a);this.retryTimers.set(e,l)}else S(this.store,e,{status:"failed",error:t.message}),this.checkAllComplete(),this.processQueue()}abortUpload(e){var o;(o=this.activeUploads.get(e))==null||o.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,o=0,r=0;for(const i of e.values())(i.status==="queued"||i.status==="uploading"||i.status==="retrying"||i.status==="complete"||i.status==="failed")&&(t+=i.size,o+=i.status==="complete"?i.size:i.bytesUploaded),i.status==="uploading"&&(r+=i.speed);this.store.setState({totalBytes:t,totalBytesUploaded:o,totalSpeed:r,totalProgress:t>0?Math.min(o/t*100,100):0})}checkAllComplete(){const{files:e}=this.store.getState();![...e.values()].some(o=>o.status==="queued"||o.status==="uploading"||o.status==="retrying")&&this.store.getState().isUploading&&this.store.setState({isUploading:!1})}}function we(n){return n==="queued"||n==="uploading"||n==="retrying"}function te(n){return`https://api.filerobot.com/${n}`}async function Ue(n,e){const t=`${te(n)}/key/${encodeURIComponent(e)}`,o=new AbortController,r=setTimeout(()=>o.abort(),3e4);try{const i=await fetch(t,{signal:o.signal});if(clearTimeout(r),!i.ok)throw new Error(`SASS key exchange failed (HTTP ${i.status})`);const a=await i.json();if(a.status==="error")throw new Error(`SASS key exchange failed: ${a.msg||"Unknown error"}`);return a.key}catch(i){throw clearTimeout(r),i instanceof DOMException&&i.name==="AbortError"?new Error("SASS key exchange timed out"):i}}function K(n,e){const t={};switch(n.mode){case"security-template":if(!e)throw new Error("[sfx-uploader] Cannot build auth headers for security-template mode: SASS key exchange has not been performed. Call resolveAuth() first or use sass-key mode with a pre-resolved key.");t["X-Filerobot-Key"]=e;break;case"sass-key":t["X-Filerobot-Key"]=n.sassKey;break}return n.airboxPuid&&(t["X-Filerobot-Airbox-Puid"]=n.airboxPuid),t}async function ze(n){const e=te(n.container);if(n.mode==="security-template"){const t=await Ue(n.container,n.securityTemplateId);return{apiBase:e,headers:K(n,t),sassKey:t}}return{apiBase:e,headers:K(n)}}const g={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",COMPLETE_ACTION:"sfx-complete-action",FILE_PREVIEW:"sfx-file-preview",FILL_METADATA:"sfx-fill-metadata"};let Ve=0;function T(){return`file-${Date.now()}-${++Ve}`}function B(n){if(n<=0)return"0 B";const e=["B","KB","MB","GB"],t=Math.min(Math.floor(Math.log(n)/Math.log(1024)),e.length-1),o=n/Math.pow(1024,t);return`${t===0?o:o.toFixed(1)} ${e[t]}`}function oe(n){if(!isFinite(n)||n<=0)return"0s";const e=Math.round(n);if(e<60)return`${e}s`;const t=Math.floor(e/60),o=e%60;return o>0?`${t}m ${o}s`:`${t}m`}function q(n){var t;const e=((t=n.name.split(".").pop())==null?void 0:t.toLowerCase())??"";return n.type.startsWith("image/")?"image":n.type.startsWith("video/")||["mp4","mov","avi","webm","mkv"].includes(e)?"vid":n.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 Ne(n){const e=n.lastIndexOf(".");return e>=0?n.slice(e+1).toUpperCase():""}const Xe={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 We(n){var t;const e=((t=n.split(".").pop())==null?void 0:t.toLowerCase())??"";return Xe[e]||""}function Ge(n){return new Promise(e=>{const t=document.createElement("video");t.preload="metadata",t.muted=!0,t.playsInline=!0;const o=URL.createObjectURL(n);let r=!1;const i=()=>{r||(r=!0,e(null)),t.removeAttribute("src"),t.load(),URL.revokeObjectURL(o)};t.addEventListener("seeked",()=>{try{const a=document.createElement("canvas");a.width=t.videoWidth||320,a.height=t.videoHeight||240;const l=a.getContext("2d");if(l){l.drawImage(t,0,0,a.width,a.height),a.toBlob(d=>{r||(r=!0,e(d?URL.createObjectURL(d):null),t.removeAttribute("src"),t.load(),URL.revokeObjectURL(o))},"image/jpeg",.7);return}}catch{}i()},{once:!0}),t.addEventListener("error",()=>i(),{once:!0}),setTimeout(()=>i(),5e3),t.src=o,t.addEventListener("loadeddata",()=>{t.currentTime=.1},{once:!0})})}function ie(n,e,t){var o,r;if(e.maxFileSize!=null&&n.size>0&&n.size>e.maxFileSize)return`File exceeds ${(e.maxFileSize/1048576).toFixed(1)} MB limit`;if(e.maxTotalFilesSize!=null&&n.size>0){let i=n.size;for(const a of t.values())a.status!=="rejected"&&a.status!=="cancelled"&&(i+=a.size);if(i>e.maxTotalFilesSize)return"Total file size limit exceeded"}if(e.maxNumberOfFiles!=null){let i=0;for(const a of t.values())a.status!=="rejected"&&a.status!=="cancelled"&&i++;if(i>=e.maxNumberOfFiles)return`Maximum ${e.maxNumberOfFiles} files allowed`}if(e.allowedFileTypes!=null){const i=e.allowedFileTypes,a="."+(((o=n.name.split(".").pop())==null?void 0:o.toLowerCase())??"");if(!i.some(d=>d.startsWith(".")?a===d.toLowerCase():d.endsWith("/*")?n.type.startsWith(d.slice(0,-1)):n.type===d))return"File type not allowed"}if(e.blockedFileTypes!=null){const i=e.blockedFileTypes,a="."+(((r=n.name.split(".").pop())==null?void 0:r.toLowerCase())??"");if(i.some(d=>d.startsWith(".")?a===d.toLowerCase():d.endsWith("/*")?n.type.startsWith(d.slice(0,-1)):n.type===d))return"File type is blocked"}return null}function Ke(n,e,t){return ie(n,e,t)}function ye(n){return n.allowedFileTypes?n.allowedFileTypes.join(","):""}const _e={"google-drive":{id:"google-drive",label:"Google Drive",fillIcon:!0,icon:"",brandHtml:'<span class="brand-ico" style="background:transparent"><svg width="16" height="16" viewBox="0 0 87.3 78"><path d="M6.6 66.85l3.85 6.65c.8 1.4 1.95 2.5 3.3 3.3L27.5 53H0c0 1.55.4 3.1 1.2 4.5z" fill="#0066da"/><path d="M43.65 25L29.9 1.2C28.55 2 27.4 3.1 26.6 4.5L1.2 48.5C.4 49.9 0 51.45 0 53h27.5z" fill="#00ac47"/><path d="M73.55 76.8c1.35-.8 2.5-1.9 3.3-3.3l1.6-2.75 7.65-13.25c.8-1.4 1.2-2.95 1.2-4.5H59.8l5.65 10.85z" fill="#ea4335"/><path d="M43.65 25L57.4 1.2C56.05.4 54.5 0 52.9 0H34.4c-1.6 0-3.15.45-4.5 1.2z" fill="#00832d"/><path d="M59.8 53H27.5L13.75 76.8c1.35.8 2.9 1.2 4.5 1.2h50.8c1.6 0 3.15-.45 4.5-1.2z" fill="#2684fc"/><path d="M73.4 26.5l-12.7-22c-.8-1.4-1.95-2.5-3.3-3.3L43.65 25 59.8 53h27.45c0-1.55-.4-3.1-1.2-4.5z" fill="#ffba00"/></svg></span>'},dropbox:{id:"dropbox",label:"Dropbox",fillIcon:!0,icon:"",brandHtml:'<span class="brand-ico" style="background:#0061ff"><svg width="11" height="11" viewBox="0 0 528 512" fill="white"><path d="M264.4 116.3l-132 84.3 132 84.3-132 84.3L0 284.1l132.3-84.3L0 116.3 132.3 32l132.1 84.3zm-132 284.5l132-84.3 132 84.3-132 84.4-132-84.4zm132-116.6l132.3-84.3-132.3-83.9 131.6-84.3L528 116.3l-132.3 84.1L528 284.7l-132.4 83.9-131.2-84.4z"/></svg></span>'},onedrive:{id:"onedrive",label:"OneDrive",fillIcon:!0,icon:"",brandHtml:'<span class="brand-ico" style="background:#0078d4"><svg width="11" height="11" viewBox="0 0 24 24" fill="white"><path d="M10.5 13.5C10.5 11.57 12.07 10 14 10h6.5c.17 0 .34.01.5.02A6 6 0 009.01 11.6 4 4 0 0010.5 13.5zM12 14.5a5 5 0 00-5-5 5 5 0 00-5 5 3 3 0 003 3h9.5A3.5 3.5 0 0018 14c0-.18-.01-.35-.03-.52A5.48 5.48 0 0112 14.5z"/></svg></span>'},box:{id:"box",label:"Box",fillIcon:!0,icon:"",brandHtml:'<span class="brand-ico" style="background:#0e50a0;font-size:9px;font-weight:800;color:#fff">box</span>'},instagram:{id:"instagram",label:"Instagram",fillIcon:!0,icon:"",brandHtml:'<span class="brand-ico" style="background:linear-gradient(45deg,#f09433,#e6683c,#dc2743,#cc2366,#bc1888)"><svg width="12" height="12" viewBox="0 0 24 24" fill="white"><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 01-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 01-1.77-1.16 4.9 4.9 0 01-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 011.16-1.77A4.9 4.9 0 015.61 2.2c.64-.25 1.37-.41 2.43-.46C9.21 2.17 9.56 2.16 12 2.16zM12 16a4 4 0 110-8 4 4 0 010 8zm6.4-9.85a1.44 1.44 0 100 2.88 1.44 1.44 0 000-2.88z"/></svg></span>'},facebook:{id:"facebook",label:"Facebook",fillIcon:!0,icon:"",brandHtml:'<span class="brand-ico" style="background:#1877f2"><svg width="12" height="12" viewBox="0 0 24 24" fill="white"><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"/></svg></span>'},unsplash:{id:"unsplash",label:"Unsplash",fillIcon:!0,icon:"",brandHtml:'<span class="brand-ico" style="background:#111"><svg width="12" height="12" viewBox="0 0 24 24" fill="white"><path d="M8.5 11.5v5h7v-5h5.5V21h-18v-9.5h5.5zm7-8v5h-7v-5h7z"/></svg></span>'}};function De(n){return n.filter(e=>e in _e).map(e=>_e[e])}var Ze=Object.defineProperty,Je=(n,e,t,o)=>{for(var r=void 0,i=n.length-1,a;i>=0;i--)(a=n[i])&&(r=a(e,t,r)||r);return r&&Ze(e,t,r),r};const Qe='<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"/>',et='<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"/>',tt='<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"/>',rt='<rect x="2" y="3" width="20" height="14" rx="2"/><circle cx="12" cy="10" r="1"/><path d="M7 21l5-5 5 5"/>',A=[{id:"device",label:"My Device",icon:Qe,iconColor:"#2563eb"},{id:"url",label:"URL link",icon:et,iconColor:"#16a34a"},{id:"camera",label:"Camera",icon:tt,iconColor:"#7c3aed"},{id:"screen-cast",label:"Screen capture",icon:rt,iconColor:"#ea580c"}],le=class le extends s.LitElement{constructor(){super(...arguments),this.sources=A}_handleClick(e){this.dispatchEvent(new CustomEvent("source-click",{detail:{source:e.id},bubbles:!0,composed:!0}))}render(){return s.html`
2
- ${this.sources.map(e=>s.html`
3
- <button @click=${()=>this._handleClick(e)}>
4
- ${e.brandHtml?M.unsafeHTML(e.brandHtml):s.svg`<svg viewBox="0 0 24 24" class=${e.fillIcon?"fill-icon":""}>${z.unsafeSVG(e.icon)}</svg>`}
5
- ${e.label}
6
- </button>
7
- `)}
8
- `}};le.styles=s.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
- :host > button > 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
- :host > button > svg.fill-icon {
57
- fill: currentColor;
58
- stroke: none;
59
- stroke-width: 0;
60
- }
61
-
62
- .brand-ico {
63
- width: 20px;
64
- height: 20px;
65
- border-radius: 5px;
66
- display: flex;
67
- align-items: center;
68
- justify-content: center;
69
- flex-shrink: 0;
70
- line-height: 1;
71
- }
72
-
73
- .brand-ico svg {
74
- width: auto;
75
- height: auto;
76
- fill: white;
77
- stroke: none;
78
- stroke-width: 0;
79
- }
80
- `;let Z=le;Je([c.property({type:Array})],Z.prototype,"sources");function Fe(n){let e=n;for(;e;){if(e instanceof HTMLDialogElement&&e.open)return e;e instanceof ShadowRoot?e=e.host:e=e.parentNode}return document.body}var ot=Object.defineProperty,U=(n,e,t,o)=>{for(var r=void 0,i=n.length-1,a;i>=0;i--)(a=n[i])&&(r=a(e,t,r)||r);return r&&ot(e,t,r),r};const ke=3,de=class de extends s.LitElement{constructor(){super(...arguments),this.compact=!1,this.externalDragOver=!1,this.accept="",this.sources=[],this.sourcesLayout="pills",this._dragOver=!1,this._moreOpen=!1,this._visiblePills=ke,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 o;e.preventDefault(),e.stopPropagation(),this._dragCounter=0,this._dragOver=!1;const t=Array.from(((o=e.dataTransfer)==null?void 0:o.files)??[]);t.length>0&&this._emitFiles(t)},this._onClick=e=>{const t=this.shadowRoot.querySelector(".drop-zone");if(t&&this._rippleEl){const o=t.getBoundingClientRect();this._rippleEl.style.left=`${e.clientX-o.left}px`,this._rippleEl.style.top=`${e.clientY-o.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,o=Array.from(t.files??[]);o.length>0&&this._emitFiles(o),t.value=""},this._onPaste=e=>{var r;if(!this.isConnected||this.offsetWidth===0)return;const t=(r=e.clipboardData)==null?void 0:r.items;if(!t)return;const o=[];for(const i of t)if(i.kind==="file"){const a=i.getAsFile();a&&o.push(a)}o.length>0&&(e.preventDefault(),this._emitFiles(o))},this._portalContainer=null,this._onDocClick=e=>{var t;this._moreOpen&&((t=this._portalContainer)!=null&&t.contains(e.target)||(this._moreOpen=!1,this._updateDropdownPortal()))},this._onDocKeyDown=e=>{e.key==="Escape"&&this._moreOpen&&(this._moreOpen=!1,this._updateDropdownPortal())},this._resizeTimer=null,this._onScrollOrResize=()=>{this._moreOpen&&this._positionDropdown(),this._resizeTimer&&clearTimeout(this._resizeTimer),this._resizeTimer=setTimeout(()=>this._updateVisiblePills(),100)}}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}))}_toggleMore(e){e.stopPropagation(),this._moreOpen=!this._moreOpen,this._updateDropdownPortal()}_updateDropdownPortal(){if(this._moreOpen){const e=this.sources.slice(this._visiblePills);this._portalContainer||(this._portalContainer=document.createElement("div"),this._portalContainer.setAttribute("data-sfx-more-dropdown",""),this._injectDropdownStyles(),Fe(this).appendChild(this._portalContainer)),s.render(s.html`<div class="sfx-more-dropdown open">
81
- ${e.map(t=>s.html`
82
- <button class="sfx-more-item" @click=${o=>this._onMoreItemClick(t,o)}>
83
- <div class="sfx-more-item-ico">
84
- ${t.brandHtml?M.unsafeHTML(t.brandHtml):t.iconColor?s.html`<svg viewBox="0 0 24 24" style="color:${t.iconColor}">${z.unsafeSVG(t.icon)}</svg>`:s.svg`<svg viewBox="0 0 24 24">${z.unsafeSVG(t.icon)}</svg>`}
85
- </div>
86
- ${t.label}
87
- </button>
88
- `)}
89
- </div>`,this._portalContainer),requestAnimationFrame(()=>this._positionDropdown())}else this._portalContainer&&(s.render(s.nothing,this._portalContainer),this._portalContainer.remove(),this._portalContainer=null)}_injectDropdownStyles(){if(document.querySelector("style[data-sfx-more-dropdown-styles]"))return;const e=document.createElement("style");e.setAttribute("data-sfx-more-dropdown-styles",""),e.textContent=`
90
- [data-sfx-more-dropdown] .sfx-more-dropdown { position:fixed; background:#fff; border-radius:12px; box-shadow:0 12px 40px rgba(0,0,0,0.14),0 2px 8px rgba(0,0,0,0.06); border:1px solid #e8edf5; padding:6px; min-width:210px; max-height:340px; overflow-y:auto; z-index:99999; opacity:0; visibility:hidden; pointer-events:none; transition:opacity .18s ease,visibility .18s ease,transform .18s ease; font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif; }
91
- [data-sfx-more-dropdown] .sfx-more-dropdown.open { opacity:1; visibility:visible; pointer-events:all; }
92
- [data-sfx-more-dropdown] .sfx-more-item { display:flex; align-items:center; gap:10px; padding:10px 14px; border-radius:6px; border:none; background:none; width:100%; font-size:13px; font-weight:500; color:#1e293b; cursor:pointer; transition:background .15s; font-family:inherit; white-space:nowrap; }
93
- [data-sfx-more-dropdown] .sfx-more-item:hover { background:#f5f7fa; }
94
- [data-sfx-more-dropdown] .sfx-more-item-ico { width:32px; height:32px; border-radius:8px; background:#f8fafc; display:flex; align-items:center; justify-content:center; flex-shrink:0; }
95
- [data-sfx-more-dropdown] .sfx-more-item-ico svg { width:16px; height:16px; fill:none; stroke:currentColor; stroke-width:2; stroke-linecap:round; }
96
- [data-sfx-more-dropdown] .sfx-more-item .brand-ico { width:20px; height:20px; border-radius:5px; display:flex; align-items:center; justify-content:center; flex-shrink:0; }
97
- [data-sfx-more-dropdown] .sfx-more-item .brand-ico svg { fill:white; stroke:none; stroke-width:0; }
98
- [data-sfx-more-dropdown] .sfx-more-item .canva-ico { width:22px; height:22px; }
99
- [data-sfx-more-dropdown] .sfx-more-item .canva-ico svg { width:22px; height:22px; }
100
- `,document.head.appendChild(e)}_positionDropdown(){var u,x;const e=(u=this.shadowRoot)==null?void 0:u.querySelector(".more-wrap > button"),t=(x=this._portalContainer)==null?void 0:x.querySelector(".sfx-more-dropdown");if(!e||!t)return;const o=e.getBoundingClientRect(),r=8,i=t.scrollHeight,a=t.offsetWidth,l=o.top,d=window.innerHeight-o.bottom;l>=i+r||l>d?t.style.top=`${o.top-i-r}px`:t.style.top=`${o.bottom+r}px`;let h=o.right-a;h=Math.max(8,Math.min(h,window.innerWidth-a-8)),t.style.left=`${h}px`}_onMoreItemClick(e,t){t.stopPropagation(),this._moreOpen=!1,this._onSourceIconClick(e)}_updateVisiblePills(){const e=window.innerWidth;this.sourcesLayout==="cards"?e<=480?this._visiblePills=2:e<=768?this._visiblePills=3:this._visiblePills=5:e<=480?this._visiblePills=1:e<=768?this._visiblePills=2:this._visiblePills=ke}connectedCallback(){super.connectedCallback(),document.addEventListener("paste",this._onPaste),document.addEventListener("click",this._onDocClick),document.addEventListener("keydown",this._onDocKeyDown),window.addEventListener("scroll",this._onScrollOrResize,!0),window.addEventListener("resize",this._onScrollOrResize),this._updateVisiblePills()}updated(e){e.has("sourcesLayout")&&this._updateVisiblePills()}disconnectedCallback(){super.disconnectedCallback(),document.removeEventListener("paste",this._onPaste),document.removeEventListener("click",this._onDocClick),document.removeEventListener("keydown",this._onDocKeyDown),window.removeEventListener("scroll",this._onScrollOrResize,!0),window.removeEventListener("resize",this._onScrollOrResize),this._resizeTimer&&clearTimeout(this._resizeTimer),this._portalContainer&&(s.render(s.nothing,this._portalContainer),this._portalContainer.remove(),this._portalContainer=null)}_renderPill(e){return s.html`
101
- <button
102
- class="src-pill"
103
- @click=${t=>{t.stopPropagation(),this._onSourceIconClick(e)}}
104
- >
105
- ${e.brandHtml?M.unsafeHTML(e.brandHtml):s.html`<span class="pill-ico" style=${e.iconColor?`color:${e.iconColor}`:""}>
106
- ${s.svg`<svg viewBox="0 0 24 24" class=${e.fillIcon?"fill-icon":""}>${z.unsafeSVG(e.icon)}</svg>`}
107
- </span>`}
108
- ${e.label}
109
- </button>
110
- `}_renderCard(e){return s.html`
111
- <button
112
- class="src-card"
113
- aria-label=${e.label}
114
- @click=${t=>{t.stopPropagation(),this._onSourceIconClick(e)}}
115
- >
116
- ${e.brandHtml?s.html`<span class="card-ico">${M.unsafeHTML(e.brandHtml)}</span>`:s.html`<span class="card-ico" style=${e.iconColor?`color:${e.iconColor}`:""}>
117
- ${s.svg`<svg viewBox="0 0 24 24" class=${e.fillIcon?"fill-icon":""}>${z.unsafeSVG(e.icon)}</svg>`}
118
- </span>`}
119
- <span class="card-label">${e.label}</span>
120
- </button>
121
- `}_renderMoreCard(){return s.html`
122
- <div class="more-wrap ${this._moreOpen?"open":""}">
123
- <button class="src-card" @click=${e=>this._toggleMore(e)}>
124
- <span class="card-ico" style="color: var(--sfx-up-text-muted, #94a3b8)">
125
- <svg viewBox="0 0 24 24" style="fill: currentColor; stroke: none">
126
- <circle cx="5" cy="12" r="2.5"/>
127
- <circle cx="12" cy="12" r="2.5"/>
128
- <circle cx="19" cy="12" r="2.5"/>
129
- </svg>
130
- </span>
131
- <span class="card-label">More</span>
132
- </button>
133
- </div>
134
- `}_renderMoreDropdown(){return s.html`
135
- <div class="more-wrap ${this._moreOpen?"open":""}">
136
- <button class="more-pill" @click=${e=>this._toggleMore(e)}>
137
- More
138
- <svg class="more-chevron" viewBox="0 0 24 24"><polyline points="6 9 12 15 18 9"/></svg>
139
- </button>
140
- </div>
141
- `}render(){const e=["drop-zone",this._dragOver||this.externalDragOver?"drag-over":"",this.compact?"compact":""].filter(Boolean).join(" "),t=this.sources.slice(0,this._visiblePills),o=this.sources.slice(this._visiblePills);return s.html`
142
- <div
143
- class=${e}
144
- role="button"
145
- tabindex="0"
146
- aria-label="Drop files here or click to browse"
147
- @dragenter=${this._onDragEnter}
148
- @dragover=${this._onDragOver}
149
- @dragleave=${this._onDragLeave}
150
- @drop=${this._onDrop}
151
- @click=${this._onClick}
152
- @keydown=${this._onKeyDown}
153
- >
154
- <div class="dz-glow"></div>
155
- <div class="rings">
156
- <div class="ring"></div>
157
- <div class="ring"></div>
158
- <div class="core">
159
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round">
160
- <polyline points="16 16 12 12 8 16" />
161
- <line x1="12" y1="12" x2="12" y2="21" />
162
- <path d="M20.39 18.39A5 5 0 0018 9h-1.26A8 8 0 103 16.3" />
163
- </svg>
164
- </div>
165
- </div>
166
-
167
- <div class="title">
168
- Drag & Drop or click to <span>browse</span>
169
- </div>
170
- ${this.compact?s.nothing:s.html`<div class="subtitle">Drop files anywhere on this page</div>`}
171
-
172
- ${!this.compact&&this.sources.length>0?s.html`
173
- <div class="import-divider"><span>or import from</span></div>
174
- ${this.sourcesLayout==="cards"?s.html`
175
- <div class="sources-cards">
176
- ${t.map(r=>this._renderCard(r))}
177
- ${o.length>0?this._renderMoreCard():s.nothing}
178
- </div>
179
- `:s.html`
180
- <div class="sources-grid">
181
- ${t.map(r=>this._renderPill(r))}
182
- ${o.length>0?this._renderMoreDropdown():s.nothing}
183
- </div>
184
- `}
185
- `:s.nothing}
186
-
187
- ${this.compact&&this.sources.length>0?s.html`
188
- <div class="sources-row">
189
- ${this.sources.map(r=>s.html`
190
- <button
191
- class="src-ico"
192
- style=${r.iconColor&&!r.brandHtml?`color:${r.iconColor}`:""}
193
- data-tip=${r.label}
194
- aria-label=${r.label}
195
- @click=${i=>{i.stopPropagation(),this._onSourceIconClick(r)}}
196
- >
197
- ${r.brandHtml?M.unsafeHTML(r.brandHtml):s.svg`<svg viewBox="0 0 24 24" class=${r.fillIcon?"fill-icon":""}>${z.unsafeSVG(r.icon)}</svg>`}
198
- </button>
199
- `)}
200
- </div>
201
- `:s.nothing}
202
-
203
- <div class="ripple"></div>
204
- <input
205
- type="file"
206
- multiple
207
- accept=${this.accept||s.nothing}
208
- @change=${this._onFileChange}
209
- />
210
- </div>
211
- `}};de.styles=s.css`
212
- :host {
213
- display: flex;
214
- flex-shrink: 0;
215
- flex: 1;
216
- min-height: 0;
217
- }
218
-
219
- :host([compact]) {
220
- flex: 0 0 auto;
221
- }
222
-
223
- .drop-zone {
224
- border: none;
225
- border-radius: 12px;
226
- background: var(--sfx-up-bg, #fff);
227
- padding: 50px 40px 50px;
228
- display: flex;
229
- flex-direction: column;
230
- align-items: center;
231
- justify-content: center;
232
- text-align: center;
233
- cursor: pointer;
234
- position: relative;
235
- overflow: visible;
236
- transition: background 0.22s;
237
- user-select: none;
238
- flex: 1;
239
- }
240
-
241
- .drop-zone:hover {
242
- background: transparent;
243
- }
244
-
245
- /* Drag over state */
246
- .drop-zone.drag-over {
247
- background: var(--sfx-up-primary-bg, #eff6ff);
248
- }
249
-
250
- .drag-over .ring {
251
- border-color: var(--sfx-up-primary, #2563eb);
252
- animation-duration: 3s;
253
- }
254
-
255
- .drag-over .ring:nth-child(2) {
256
- border-color: var(--sfx-up-primary-glow, rgba(37, 99, 235, 0.4));
257
- animation-duration: 2s;
258
- }
259
-
260
- .drag-over .core {
261
- background: var(--sfx-up-primary, #2563eb);
262
- color: var(--sfx-up-bg, #fff);
263
- transform: scale(1.12);
264
- box-shadow: 0 8px 24px var(--sfx-up-primary-glow, rgba(37, 99, 235, 0.38));
265
- }
266
-
267
- /* Compact state when files exist */
268
- .drop-zone.compact {
269
- padding: 14px 16px;
270
- flex-direction: row;
271
- align-items: center;
272
- gap: 12px;
273
- justify-content: flex-start;
274
- overflow: visible;
275
- border: 1.5px dashed var(--sfx-up-ring-color, #c4d5ef);
276
- border-radius: 12px;
277
- animation: compactIn 0.3s ease both;
278
- }
279
-
280
- @keyframes compactIn {
281
- from {
282
- opacity: 0;
283
- transform: translateY(-8px);
284
- }
285
- to {
286
- opacity: 1;
287
- transform: translateY(0);
288
- }
289
- }
290
-
291
- /* --- Radial glow --- */
292
- .dz-glow {
293
- position: absolute;
294
- width: 260px;
295
- height: 260px;
296
- top: 20px;
297
- left: 50%;
298
- transform: translateX(-50%);
299
- background: radial-gradient(circle at center, rgba(37, 99, 235, 0.04) 0%, rgba(37, 99, 235, 0.02) 40%, transparent 70%);
300
- border-radius: 50%;
301
- pointer-events: none;
302
- z-index: 0;
303
- }
304
-
305
- .compact .dz-glow {
306
- display: none;
307
- }
308
-
309
- /* --- Rings --- */
310
- .rings {
311
- width: 120px;
312
- height: 120px;
313
- position: relative;
314
- display: flex;
315
- align-items: center;
316
- justify-content: center;
317
- margin-bottom: 24px;
318
- flex-shrink: 0;
319
- }
320
-
321
- .ring {
322
- position: absolute;
323
- inset: 0;
324
- border-radius: 50%;
325
- border: 1.5px dashed var(--sfx-up-ring-color, #c4d5ef);
326
- animation: slowSpin 20s linear infinite;
327
- transition: border-color 0.3s;
328
- }
329
-
330
- .ring:nth-child(2) {
331
- inset: 13px;
332
- border-color: var(--sfx-up-ring-color-light, #d8e5f5);
333
- border-style: dotted;
334
- animation-direction: reverse;
335
- animation-duration: 14s;
336
- }
337
-
338
- .compact .rings {
339
- display: none;
340
- }
341
-
342
- /* --- Core icon --- */
343
- .core {
344
- width: 58px;
345
- height: 58px;
346
- border-radius: 50%;
347
- background: var(--sfx-up-primary-bg, #eff6ff);
348
- color: var(--sfx-up-primary, #2563eb);
349
- display: flex;
350
- align-items: center;
351
- justify-content: center;
352
- z-index: 1;
353
- transition: all 0.28s cubic-bezier(0.34, 1.4, 0.64, 1);
354
- box-shadow: 0 3px 12px rgba(37, 99, 235, 0.15);
355
- }
356
-
357
- .core svg {
358
- width: 26px;
359
- height: 26px;
360
- }
361
-
362
- .drop-zone:hover .core {
363
- transform: translateY(-2px);
364
- box-shadow: 0 5px 18px rgba(37, 99, 235, 0.22);
365
- }
366
-
367
- /* --- Text --- */
368
- .title {
369
- font-size: 20px;
370
- font-weight: 700;
371
- color: var(--sfx-up-text, #1e293b);
372
- margin-bottom: 6px;
373
- transition: font-size 0.3s, margin 0.3s;
374
- }
375
-
376
- .title span {
377
- color: var(--sfx-up-primary, #2563eb);
378
- cursor: pointer;
379
- }
380
-
381
- .subtitle {
382
- font-size: 14px;
383
- color: var(--sfx-up-text-muted, #94a3b8);
384
- transition: opacity 0.15s;
385
- margin-bottom: 24px;
386
- }
387
-
388
- .compact .title {
389
- font-size: 14px;
390
- font-weight: 600;
391
- margin-bottom: 0;
392
- white-space: nowrap;
393
- overflow: hidden;
394
- text-overflow: ellipsis;
395
- }
396
-
397
- .compact .subtitle {
398
- display: none;
399
- }
400
-
401
- /* --- "or Import From" divider --- */
402
- .import-divider {
403
- display: flex;
404
- align-items: center;
405
- gap: 12px;
406
- width: 100%;
407
- max-width: 420px;
408
- margin-bottom: 20px;
409
- }
410
-
411
- .import-divider::before,
412
- .import-divider::after {
413
- content: '';
414
- flex: 1;
415
- height: 1px;
416
- background: var(--sfx-up-border, #e2e8f0);
417
- }
418
-
419
- .import-divider span {
420
- font-size: 12px;
421
- font-weight: 500;
422
- color: var(--sfx-up-text-muted, #94a3b8);
423
- white-space: nowrap;
424
- letter-spacing: 0.3px;
425
- }
426
-
427
- .compact .import-divider {
428
- display: none;
429
- }
430
-
431
- /* --- Source pills grid (expanded mode) --- */
432
- .sources-grid {
433
- display: flex;
434
- justify-content: center;
435
- align-items: center;
436
- gap: 8px;
437
- flex-wrap: wrap;
438
- min-height: 92px;
439
- }
440
-
441
- .compact .sources-grid {
442
- display: none;
443
- }
444
-
445
- .src-pill {
446
- display: inline-flex;
447
- align-items: center;
448
- gap: 8px;
449
- padding: 9px 18px;
450
- height: 38px;
451
- box-sizing: border-box;
452
- border-radius: 50px;
453
- border: 1.5px solid rgba(226, 232, 240, 0.6);
454
- background: rgba(255, 255, 255, 0.7);
455
- backdrop-filter: blur(8px);
456
- -webkit-backdrop-filter: blur(8px);
457
- font-size: 14px;
458
- font-weight: 500;
459
- color: var(--sfx-up-text-secondary, #475569);
460
- cursor: pointer;
461
- transition: all 0.15s ease;
462
- white-space: nowrap;
463
- box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);
464
- font-family: inherit;
465
- }
466
-
467
- .src-pill:hover {
468
- border-color: var(--sfx-up-primary, #2563eb);
469
- color: var(--sfx-up-primary, #2563eb);
470
- background: rgba(239, 246, 255, 0.85);
471
- box-shadow: 0 2px 10px var(--sfx-up-primary-glow, rgba(37, 99, 235, 0.18));
472
- transform: translateY(-1px);
473
- }
474
-
475
- .src-pill:active {
476
- transform: translateY(0) scale(0.98);
477
- }
478
-
479
- .src-pill .pill-ico {
480
- display: flex;
481
- align-items: center;
482
- justify-content: center;
483
- flex-shrink: 0;
484
- }
485
-
486
- .src-pill .pill-ico svg {
487
- width: 16px;
488
- height: 16px;
489
- flex-shrink: 0;
490
- fill: none;
491
- stroke: currentColor;
492
- stroke-width: 2;
493
- stroke-linecap: round;
494
- }
495
-
496
- .src-pill .pill-ico svg.fill-icon {
497
- fill: currentColor;
498
- stroke: none;
499
- stroke-width: 0;
500
- }
501
-
502
- .src-pill .brand-ico svg {
503
- width: auto;
504
- height: auto;
505
- fill: white;
506
- stroke: none;
507
- stroke-width: 0;
508
- }
509
-
510
- .src-pill .canva-ico {
511
- width: 22px;
512
- height: 22px;
513
- }
514
-
515
- .src-pill .canva-ico svg {
516
- width: 22px;
517
- height: 22px;
518
- }
519
-
520
- /* --- Source cards grid (expanded mode, cards layout) --- */
521
- .sources-cards {
522
- display: flex;
523
- justify-content: center;
524
- gap: 10px;
525
- flex-wrap: wrap;
526
- width: 100%;
527
- max-width: 700px;
528
- }
529
-
530
- .compact .sources-cards {
531
- display: none;
532
- }
533
-
534
- .sources-cards > .more-wrap {
535
- display: contents;
536
- }
537
-
538
- .sources-cards > .more-wrap > .src-card {
539
- /* restore flex item behaviour lost by display:contents on the wrapper */
540
- flex: 1;
541
- min-width: 88px;
542
- max-width: 130px;
543
- }
544
-
545
- .src-card {
546
- display: flex;
547
- flex-direction: column;
548
- align-items: center;
549
- justify-content: center;
550
- gap: 10px;
551
- padding: 20px 12px 16px;
552
- border-radius: 16px;
553
- border: 1.5px solid rgba(226, 232, 240, 0.6);
554
- background: rgba(255, 255, 255, 0.7);
555
- backdrop-filter: blur(8px);
556
- -webkit-backdrop-filter: blur(8px);
557
- cursor: pointer;
558
- transition: all 0.18s ease;
559
- flex: 1;
560
- min-width: 88px;
561
- max-width: 130px;
562
- box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);
563
- font-family: inherit;
564
- }
565
-
566
- .src-card:hover {
567
- border-color: var(--sfx-up-primary, #2563eb);
568
- background: rgba(239, 246, 255, 0.85);
569
- box-shadow: 0 4px 14px var(--sfx-up-primary-glow, rgba(37, 99, 235, 0.18));
570
- transform: translateY(-2px);
571
- }
572
-
573
- .src-card:active {
574
- transform: translateY(0) scale(0.97);
575
- }
576
-
577
- .src-card .card-ico {
578
- display: flex;
579
- align-items: center;
580
- justify-content: center;
581
- flex-shrink: 0;
582
- width: 28px;
583
- height: 28px;
584
- }
585
-
586
- .src-card .card-ico svg {
587
- width: 28px;
588
- height: 28px;
589
- fill: none;
590
- stroke: currentColor;
591
- stroke-width: 2;
592
- stroke-linecap: round;
593
- }
594
-
595
- .src-card .card-ico svg.fill-icon {
596
- fill: currentColor;
597
- stroke: none;
598
- stroke-width: 0;
599
- }
600
-
601
- .src-card .card-label {
602
- font-size: 12px;
603
- font-weight: 500;
604
- color: var(--sfx-up-text-secondary, #475569);
605
- white-space: nowrap;
606
- overflow: hidden;
607
- text-overflow: ellipsis;
608
- max-width: 100%;
609
- }
610
-
611
- .src-card .brand-ico {
612
- width: 28px;
613
- height: 28px;
614
- border-radius: 7px;
615
- }
616
-
617
- .src-card .brand-ico svg {
618
- width: 24px;
619
- height: 24px;
620
- fill: white;
621
- stroke: none;
622
- stroke-width: 0;
623
- }
624
-
625
- /* Google Drive has transparent background — show SVG at full card-ico size */
626
- .src-card .brand-ico[style*="transparent"] {
627
- background: none !important;
628
- width: auto;
629
- height: auto;
630
- }
631
-
632
- .src-card .brand-ico[style*="transparent"] svg {
633
- width: 28px;
634
- height: 28px;
635
- }
636
-
637
- .src-card .canva-ico {
638
- width: 32px;
639
- height: 32px;
640
- }
641
-
642
- .src-card .canva-ico svg {
643
- width: 32px;
644
- height: 32px;
645
- }
646
-
647
- /* --- "More" pill + dropdown --- */
648
- .more-wrap {
649
- position: relative;
650
- }
651
-
652
- .more-pill {
653
- display: inline-flex;
654
- align-items: center;
655
- gap: 6px;
656
- padding: 9px 18px;
657
- border-radius: 50px;
658
- border: 1.5px solid rgba(226, 232, 240, 0.6);
659
- background: rgba(255, 255, 255, 0.7);
660
- backdrop-filter: blur(8px);
661
- -webkit-backdrop-filter: blur(8px);
662
- font-size: 14px;
663
- font-weight: 500;
664
- color: var(--sfx-up-text-secondary, #475569);
665
- cursor: pointer;
666
- transition: all 0.15s ease;
667
- white-space: nowrap;
668
- box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);
669
- font-family: inherit;
670
- }
671
-
672
- .more-pill:hover,
673
- .more-wrap.open .more-pill {
674
- border-color: var(--sfx-up-primary, #2563eb);
675
- color: var(--sfx-up-primary, #2563eb);
676
- background: rgba(239, 246, 255, 0.85);
677
- box-shadow: 0 2px 10px var(--sfx-up-primary-glow, rgba(37, 99, 235, 0.18));
678
- }
679
-
680
- .more-pill:hover {
681
- transform: translateY(-1px);
682
- }
683
-
684
- .more-pill svg {
685
- flex-shrink: 0;
686
- fill: none;
687
- stroke: currentColor;
688
- stroke-width: 2.2;
689
- stroke-linecap: round;
690
- }
691
-
692
- .more-chevron {
693
- width: 12px;
694
- height: 12px;
695
- color: var(--sfx-up-text-muted, #94a3b8);
696
- transition: transform 0.18s ease;
697
- }
698
-
699
- .more-wrap.open .more-chevron {
700
- transform: rotate(180deg);
701
- color: currentColor;
702
- }
703
-
704
- /* Dropdown uses position:fixed to escape overflow:hidden ancestors */
705
- .more-dropdown {
706
- position: fixed;
707
- background: var(--sfx-up-bg, #fff);
708
- border-radius: 12px;
709
- box-shadow: 0 12px 40px rgba(0, 0, 0, 0.14), 0 2px 8px rgba(0, 0, 0, 0.06);
710
- border: 1px solid var(--sfx-up-border, #e8edf5);
711
- padding: 6px;
712
- min-width: 210px;
713
- max-height: 340px;
714
- overflow-y: auto;
715
- z-index: 99999;
716
- opacity: 0;
717
- visibility: hidden;
718
- pointer-events: none;
719
- transition: opacity 0.18s ease, visibility 0.18s ease, transform 0.18s ease;
720
- }
721
-
722
- .more-dropdown.above {
723
- transform: translateY(-6px);
724
- }
725
-
726
- .more-dropdown.below {
727
- transform: translateY(6px);
728
- }
729
-
730
- .more-wrap.open .more-dropdown {
731
- opacity: 1;
732
- visibility: visible;
733
- pointer-events: all;
734
- transform: translateY(0);
735
- }
736
-
737
- .more-item {
738
- display: flex;
739
- align-items: center;
740
- gap: 10px;
741
- padding: 10px 14px;
742
- border-radius: 6px;
743
- border: none;
744
- background: none;
745
- width: 100%;
746
- font-size: 13px;
747
- font-weight: 500;
748
- color: var(--sfx-up-text, #1e293b);
749
- cursor: pointer;
750
- transition: background 0.15s;
751
- font-family: inherit;
752
- white-space: nowrap;
753
- }
754
-
755
- .more-item:hover {
756
- background: var(--sfx-up-primary-bg, #f5f7fa);
757
- }
758
-
759
- .more-item .more-item-ico {
760
- width: 32px;
761
- height: 32px;
762
- border-radius: 8px;
763
- background: var(--sfx-up-surface, #f8fafc);
764
- display: flex;
765
- align-items: center;
766
- justify-content: center;
767
- flex-shrink: 0;
768
- }
769
-
770
- .more-item .more-item-ico svg {
771
- width: 16px;
772
- height: 16px;
773
- fill: none;
774
- stroke: currentColor;
775
- stroke-width: 2;
776
- stroke-linecap: round;
777
- }
778
-
779
- .more-item .brand-ico {
780
- width: 20px;
781
- height: 20px;
782
- border-radius: 5px;
783
- display: flex;
784
- align-items: center;
785
- justify-content: center;
786
- flex-shrink: 0;
787
- }
788
-
789
- .more-item .brand-ico svg {
790
- fill: white;
791
- stroke: none;
792
- stroke-width: 0;
793
- }
794
-
795
- /* --- Brand icon container (for provider logos) --- */
796
- .brand-ico {
797
- width: 20px;
798
- height: 20px;
799
- border-radius: 5px;
800
- display: flex;
801
- align-items: center;
802
- justify-content: center;
803
- flex-shrink: 0;
804
- line-height: 1;
805
- }
806
-
807
- .src-ico .brand-ico {
808
- width: 20px;
809
- height: 20px;
810
- border-radius: 5px;
811
- }
812
-
813
- .src-ico .brand-ico svg {
814
- width: 12px;
815
- height: 12px;
816
- stroke: none;
817
- stroke-width: 0;
818
- }
819
-
820
- .src-ico .canva-ico,
821
- .more-item .canva-ico {
822
- width: 22px;
823
- height: 22px;
824
- }
825
-
826
- .src-ico .canva-ico svg,
827
- .more-item .canva-ico svg {
828
- width: 22px;
829
- height: 22px;
830
- }
831
-
832
- /* --- Source icons row (compact mode) --- */
833
- .sources-row {
834
- display: none;
835
- }
836
-
837
- .compact .sources-row {
838
- display: flex;
839
- align-items: center;
840
- gap: 6px;
841
- margin-left: auto;
842
- flex-shrink: 0;
843
- position: relative;
844
- z-index: 20;
845
- }
846
-
847
- .src-divider {
848
- width: 1px;
849
- height: 24px;
850
- background: var(--sfx-up-border, #e5e7eb);
851
- margin-right: 4px;
852
- flex-shrink: 0;
853
- }
854
-
855
- .src-ico {
856
- width: 36px;
857
- height: 36px;
858
- border-radius: 8px;
859
- border: 1.5px solid var(--sfx-up-border, #e2e8f0);
860
- background: var(--sfx-up-surface, #f8fafc);
861
- cursor: pointer;
862
- display: flex;
863
- align-items: center;
864
- justify-content: center;
865
- transition: all 0.15s ease;
866
- position: relative;
867
- flex-shrink: 0;
868
- color: var(--sfx-up-text-muted, #6b7280);
869
- padding: 0;
870
- font-family: inherit;
871
- }
872
-
873
- .src-ico > svg {
874
- width: 15px;
875
- height: 15px;
876
- fill: none;
877
- stroke: currentColor;
878
- stroke-width: 2;
879
- stroke-linecap: round;
880
- }
881
-
882
- .src-ico > svg.fill-icon {
883
- fill: currentColor;
884
- stroke: none;
885
- stroke-width: 0;
886
- }
887
-
888
- .src-ico:hover {
889
- border-color: var(--sfx-up-primary, #2563eb);
890
- background: var(--sfx-up-primary-bg, #eff6ff);
891
- transform: translateY(-1px);
892
- box-shadow: 0 2px 8px var(--sfx-up-primary-glow, rgba(37, 99, 235, 0.18));
893
- color: var(--sfx-up-primary, #2563eb);
894
- }
895
-
896
- .src-ico::after {
897
- content: attr(data-tip);
898
- position: absolute;
899
- bottom: -28px;
900
- left: 50%;
901
- transform: translateX(-50%);
902
- background: var(--sfx-up-bg, #fff);
903
- color: var(--sfx-up-text, #374151);
904
- font-size: 10px;
905
- font-weight: 500;
906
- border: 1px solid var(--sfx-up-border, #e5e7eb);
907
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
908
- padding: 3px 8px;
909
- border-radius: 5px;
910
- white-space: nowrap;
911
- opacity: 0;
912
- visibility: hidden;
913
- transition: opacity 0.15s, visibility 0.15s;
914
- pointer-events: none;
915
- z-index: 50;
916
- font-family: inherit;
917
- }
918
-
919
- .src-ico:hover::after {
920
- opacity: 1;
921
- visibility: visible;
922
- }
923
-
924
- /* --- Ripple --- */
925
- .ripple {
926
- position: absolute;
927
- width: 10px;
928
- height: 10px;
929
- border-radius: 50%;
930
- background: var(--sfx-up-primary, #2563eb);
931
- opacity: 0;
932
- pointer-events: none;
933
- transform: translate(-50%, -50%) scale(0);
934
- }
935
-
936
- .ripple.go {
937
- animation: ripple 0.55s ease-out forwards;
938
- }
939
-
940
- /* --- Hidden input --- */
941
- input[type='file'] {
942
- display: none;
943
- }
944
-
945
- @keyframes slowSpin {
946
- to {
947
- transform: rotate(360deg);
948
- }
949
- }
950
-
951
- @keyframes ripple {
952
- from {
953
- transform: translate(-50%, -50%) scale(0);
954
- opacity: 0.18;
955
- }
956
- to {
957
- transform: translate(-50%, -50%) scale(12);
958
- opacity: 0;
959
- }
960
- }
961
-
962
- .drop-zone:focus-visible,
963
- .src-pill:focus-visible,
964
- .src-card:focus-visible,
965
- .more-pill:focus-visible,
966
- .src-ico:focus-visible,
967
- .more-item:focus-visible {
968
- outline: 2px solid var(--sfx-up-ring, oklch(0.578 0.198 268.129 / 0.7));
969
- outline-offset: 2px;
970
- }
971
-
972
- @media (max-width: 480px) {
973
- .drop-zone:not(.compact) {
974
- padding: 32px 20px;
975
- }
976
- .title { font-size: 16px; }
977
- .rings { width: 90px; height: 90px; }
978
- .core { width: 44px; height: 44px; }
979
- .core svg { width: 20px; height: 20px; }
980
- }
981
-
982
- @media (prefers-reduced-motion: reduce) {
983
- .ring {
984
- animation: none;
985
- }
986
- .ripple.go {
987
- animation: none;
988
- }
989
- .drop-zone.compact {
990
- animation: none;
991
- }
992
- }
993
- `;let C=de;U([c.property({type:Boolean,reflect:!0})],C.prototype,"compact");U([c.property({type:Boolean,attribute:"external-drag-over"})],C.prototype,"externalDragOver");U([c.property({type:String})],C.prototype,"accept");U([c.property({type:Array})],C.prototype,"sources");U([c.property({type:String,attribute:"sources-layout"})],C.prototype,"sourcesLayout");U([c.state()],C.prototype,"_dragOver");U([c.state()],C.prototype,"_moreOpen");U([c.state()],C.prototype,"_visiblePills");U([c.query(".ripple")],C.prototype,"_rippleEl");U([c.query('input[type="file"]')],C.prototype,"fileInput");const pe=class pe extends s.LitElement{render(){return s.html`
994
- <div class="line"></div>
995
- <div class="label">or import from</div>
996
- <div class="line"></div>
997
- `}};pe.styles=s.css`
998
- :host {
999
- display: flex;
1000
- align-items: center;
1001
- gap: 14px;
1002
- padding: 20px 0;
1003
- }
1004
-
1005
- .line {
1006
- flex: 1;
1007
- height: 1px;
1008
- background: var(--sfx-up-border-light, #f1f5f9);
1009
- }
1010
-
1011
- .label {
1012
- font-size: 11px;
1013
- font-weight: 600;
1014
- color: var(--sfx-up-text-muted, #cbd5e1);
1015
- text-transform: uppercase;
1016
- letter-spacing: 1px;
1017
- white-space: nowrap;
1018
- }
1019
- `;let se=pe;var it=Object.defineProperty,V=(n,e,t,o)=>{for(var r=void 0,i=n.length-1,a;i>=0;i--)(a=n[i])&&(r=a(e,t,r)||r);return r&&it(e,t,r),r};const ce=class ce extends s.LitElement{constructor(){super(...arguments),this.files=[],this.showDropTile=!1,this.sources=[],this.accept="",this._moreOpen=!1,this._portalContainer=null,this._outsideClickHandler=e=>{var r;if((r=this._portalContainer)!=null&&r.contains(e.target))return;const t=this.renderRoot.querySelector(".drop-tile-more-wrap"),o=e.composedPath();t&&o.includes(t)||(this._moreOpen=!1,this._closePortal(),document.removeEventListener("click",this._outsideClickHandler,!0))},this._onScrollOrResize=()=>{this._moreOpen&&this._positionPortal()},this._onKeyDown=e=>{e.key==="Escape"&&this._moreOpen&&(this._moreOpen=!1,this._closePortal(),this._removeGlobalListeners())}}_onDropTileClick(){const e=this.renderRoot.querySelector('input[type="file"]');e==null||e.click()}_onFileInput(e){const t=e.target,o=Array.from(t.files??[]);o.length>0&&this.dispatchEvent(new CustomEvent("files-selected",{detail:{files:o},bubbles:!0,composed:!0})),t.value=""}_onSourceClick(e,t){if(e.stopPropagation(),t.id==="device"){const o=this.renderRoot.querySelector('input[type="file"]');o==null||o.click();return}this.dispatchEvent(new CustomEvent("source-click",{detail:{source:t},bubbles:!0,composed:!0}))}_addGlobalListeners(){requestAnimationFrame(()=>document.addEventListener("click",this._outsideClickHandler,!0)),document.addEventListener("keydown",this._onKeyDown),window.addEventListener("scroll",this._onScrollOrResize,!0),window.addEventListener("resize",this._onScrollOrResize)}_removeGlobalListeners(){document.removeEventListener("click",this._outsideClickHandler,!0),document.removeEventListener("keydown",this._onKeyDown),window.removeEventListener("scroll",this._onScrollOrResize,!0),window.removeEventListener("resize",this._onScrollOrResize)}_toggleMore(e){e.stopPropagation(),this._moreOpen=!this._moreOpen,this._moreOpen?(this._openPortal(),this._addGlobalListeners()):(this._closePortal(),this._removeGlobalListeners())}_openPortal(){const e=this.sources.slice(3);this._portalContainer||(this._portalContainer=document.createElement("div"),this._portalContainer.setAttribute("data-sfx-tile-dropdown",""),this._injectTileDropdownStyles(),Fe(this).appendChild(this._portalContainer)),s.render(s.html`<div class="sfx-tile-dropdown">
1020
- ${e.map(t=>s.html`
1021
- <button
1022
- class="sfx-tile-dropdown-item"
1023
- @click=${o=>this._onMoreSourceClick(o,t)}
1024
- >
1025
- <span class="sfx-tile-dropdown-ico" style=${t.iconColor&&!t.brandHtml?`color:${t.iconColor}`:""}>
1026
- ${t.brandHtml?M.unsafeHTML(t.brandHtml):s.svg`<svg viewBox="0 0 24 24" class=${t.fillIcon?"fill-icon":""}>${z.unsafeSVG(t.icon)}</svg>`}
1027
- </span>
1028
- ${t.label}
1029
- </button>
1030
- `)}
1031
- </div>`,this._portalContainer),requestAnimationFrame(()=>this._positionPortal())}_positionPortal(){var u;const e=this.renderRoot.querySelector(".drop-tile-more"),t=(u=this._portalContainer)==null?void 0:u.querySelector(".sfx-tile-dropdown");if(!e||!t)return;const o=e.getBoundingClientRect(),r=6,i=t.scrollHeight,a=t.offsetWidth,l=o.top,d=window.innerHeight-o.bottom;l>=i+r||l>d?t.style.top=`${o.top-i-r}px`:t.style.top=`${o.bottom+r}px`;let h=o.right-a;h=Math.max(8,Math.min(h,window.innerWidth-a-8)),t.style.left=`${h}px`}_closePortal(){this._portalContainer&&(s.render(s.nothing,this._portalContainer),this._portalContainer.remove(),this._portalContainer=null)}_injectTileDropdownStyles(){if(document.querySelector("style[data-sfx-tile-dropdown-styles]"))return;const e=document.createElement("style");e.setAttribute("data-sfx-tile-dropdown-styles",""),e.textContent=`
1032
- [data-sfx-tile-dropdown] .sfx-tile-dropdown { position:fixed; background:#fff; border:1px solid #e2e8f0; border-radius:10px; box-shadow:0 4px 20px rgba(0,0,0,0.12); padding:6px; z-index:99999; min-width:180px; font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif; animation:sfxTileDropIn .15s ease; }
1033
- [data-sfx-tile-dropdown] .sfx-tile-dropdown-item { display:flex; align-items:center; gap:10px; width:100%; padding:8px 12px; border:none; background:none; border-radius:6px; cursor:pointer; font-size:13px; font-weight:500; color:#1e293b; white-space:nowrap; transition:background .15s; font-family:inherit; }
1034
- [data-sfx-tile-dropdown] .sfx-tile-dropdown-item:hover { background:#f5f7fa; }
1035
- [data-sfx-tile-dropdown] .sfx-tile-dropdown-ico { width:32px; height:32px; border-radius:8px; background:#f8fafc; display:flex; align-items:center; justify-content:center; flex-shrink:0; }
1036
- [data-sfx-tile-dropdown] .sfx-tile-dropdown-ico svg { width:16px; height:16px; fill:none; stroke:currentColor; stroke-width:2; stroke-linecap:round; stroke-linejoin:round; }
1037
- [data-sfx-tile-dropdown] .sfx-tile-dropdown-ico svg.fill-icon { fill:currentColor; stroke:none; }
1038
- [data-sfx-tile-dropdown] .sfx-tile-dropdown-ico .brand-ico { width:20px; height:20px; border-radius:5px; display:flex; align-items:center; justify-content:center; }
1039
- [data-sfx-tile-dropdown] .sfx-tile-dropdown-ico .brand-ico svg { fill:white; stroke:none; stroke-width:0; }
1040
- [data-sfx-tile-dropdown] .sfx-tile-dropdown-ico .canva-ico { width:22px; height:22px; }
1041
- [data-sfx-tile-dropdown] .sfx-tile-dropdown-ico .canva-ico svg { width:22px; height:22px; }
1042
- @keyframes sfxTileDropIn { from{opacity:0;transform:translateY(-4px)} to{opacity:1;transform:translateY(0)} }
1043
- `,document.head.appendChild(e)}disconnectedCallback(){super.disconnectedCallback(),this._moreOpen=!1,this._closePortal(),this._removeGlobalListeners()}_onMoreSourceClick(e,t){this._moreOpen=!1,this._closePortal(),this._removeGlobalListeners(),this._onSourceClick(e,t)}_renderDropTile(){const t=this.sources.slice(0,3),o=this.sources.slice(3);return s.html`
1044
- <div class="drop-tile" @click=${this._onDropTileClick}>
1045
- <div class="drop-tile-rings">
1046
- <div class="drop-tile-ring"></div>
1047
- <div class="drop-tile-ring"></div>
1048
- <div class="drop-tile-core">
1049
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round">
1050
- <polyline points="16 16 12 12 8 16" />
1051
- <line x1="12" y1="12" x2="12" y2="21" />
1052
- <path d="M20.39 18.39A5 5 0 0018 9h-1.26A8 8 0 103 16.3" />
1053
- </svg>
1054
- </div>
1055
- </div>
1056
- <div class="drop-tile-text">Drop files or<br>click to <span>browse</span></div>
1057
- ${t.length>0?s.html`
1058
- <div class="drop-tile-sources">
1059
- ${t.map(r=>s.html`
1060
- <button
1061
- class="drop-tile-src"
1062
- style=${r.iconColor&&!r.brandHtml?`color:${r.iconColor}`:""}
1063
- title=${r.label}
1064
- @click=${i=>this._onSourceClick(i,r)}
1065
- >
1066
- ${r.brandHtml?M.unsafeHTML(r.brandHtml):s.svg`<svg viewBox="0 0 24 24" class=${r.fillIcon?"fill-icon":""}>${z.unsafeSVG(r.icon)}</svg>`}
1067
- </button>
1068
- `)}
1069
- ${o.length>0?s.html`
1070
- <div class="drop-tile-more-wrap">
1071
- <button class="drop-tile-more" title="More sources" @click=${r=>this._toggleMore(r)}>···</button>
1072
- </div>
1073
- `:s.nothing}
1074
- </div>
1075
- `:s.nothing}
1076
- <input type="file" multiple accept=${this.accept||s.nothing} @change=${this._onFileInput} />
1077
- </div>
1078
- `}render(){return s.html`
1079
- <div class="grid">
1080
- ${this.showDropTile?this._renderDropTile():s.nothing}
1081
- ${this.files.map((e,t)=>s.html`<sfx-file-item .file=${e} style="--tile-index:${t}"></sfx-file-item>`)}
1082
- </div>
1083
- `}};ce.styles=s.css`
1084
- :host {
1085
- display: block;
1086
- flex: 1;
1087
- min-height: 0;
1088
- overflow-y: auto;
1089
- padding-bottom: 8px;
1090
- scrollbar-width: thin;
1091
- scrollbar-color: rgba(0, 0, 0, 0.15) transparent;
1092
- scrollbar-gutter: stable;
1093
- }
1094
-
1095
- :host::-webkit-scrollbar {
1096
- width: var(--sfx-scrollbar-w, 12px);
1097
- }
1098
-
1099
- :host::-webkit-scrollbar-track {
1100
- background: transparent;
1101
- margin: 8px 0;
1102
- }
1103
-
1104
- :host::-webkit-scrollbar-thumb {
1105
- background-color: rgba(0, 0, 0, 0.15);
1106
- border-radius: 6px;
1107
- border-left: var(--sfx-scrollbar-inset-left, 3px) solid transparent;
1108
- border-right: var(--sfx-scrollbar-inset-right, 3px) solid transparent;
1109
- background-clip: padding-box;
1110
- }
1111
-
1112
- .grid {
1113
- display: grid;
1114
- grid-template-columns: repeat(auto-fill, minmax(var(--sfx-up-grid-min, max(24%, 140px)), 1fr));
1115
- gap: 12px;
1116
- padding: 0 12px 16px 16px;
1117
- }
1118
-
1119
- @media (max-width: 480px) {
1120
- .grid {
1121
- grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
1122
- gap: 8px;
1123
- }
1124
- }
1125
-
1126
- /* --- Drop tile (first card in grid) --- */
1127
- .drop-tile {
1128
- border-radius: 10px;
1129
- border: 1.5px dashed var(--sfx-up-border, #c4d5ef);
1130
- background: var(--sfx-up-surface, #f8fafc);
1131
- display: flex;
1132
- flex-direction: column;
1133
- align-items: center;
1134
- justify-content: center;
1135
- gap: 6px;
1136
- cursor: pointer;
1137
- transition: all 0.18s ease;
1138
- padding: 12px 10px;
1139
- position: relative;
1140
- z-index: 1;
1141
- min-height: 0;
1142
- overflow: hidden;
1143
- }
1144
-
1145
- .drop-tile:hover {
1146
- border-color: var(--sfx-up-primary, #2563eb);
1147
- background: var(--sfx-up-primary-bg, #eff6ff);
1148
- }
1149
-
1150
- .drop-tile-rings {
1151
- width: clamp(40px, 6vw, 60px);
1152
- height: clamp(40px, 6vw, 60px);
1153
- position: relative;
1154
- display: flex;
1155
- align-items: center;
1156
- justify-content: center;
1157
- flex-shrink: 0;
1158
- }
1159
-
1160
- .drop-tile-ring {
1161
- position: absolute;
1162
- inset: 0;
1163
- border-radius: 50%;
1164
- border: 1px dashed var(--sfx-up-ring-color, #c4d5ef);
1165
- animation: tileSpin 20s linear infinite;
1166
- }
1167
-
1168
- .drop-tile-ring:nth-child(2) {
1169
- inset: 8px;
1170
- border-color: var(--sfx-up-ring-color-light, #d8e5f5);
1171
- border-style: dotted;
1172
- animation-direction: reverse;
1173
- animation-duration: 14s;
1174
- }
1175
-
1176
- @keyframes tileSpin {
1177
- to { transform: rotate(360deg); }
1178
- }
1179
-
1180
- .drop-tile-core {
1181
- width: clamp(24px, 4vw, 34px);
1182
- height: clamp(24px, 4vw, 34px);
1183
- border-radius: 50%;
1184
- background: var(--sfx-up-primary-bg, #eff6ff);
1185
- color: var(--sfx-up-primary, #2563eb);
1186
- display: flex;
1187
- align-items: center;
1188
- justify-content: center;
1189
- z-index: 1;
1190
- box-shadow: 0 2px 8px rgba(37, 99, 235, 0.12);
1191
- transition: all 0.2s ease;
1192
- }
1193
-
1194
- .drop-tile:hover .drop-tile-core {
1195
- transform: translateY(-1px);
1196
- box-shadow: 0 4px 12px rgba(37, 99, 235, 0.2);
1197
- }
1198
-
1199
- .drop-tile-core svg {
1200
- width: 16px;
1201
- height: 16px;
1202
- }
1203
-
1204
- .drop-tile-text {
1205
- font-size: 11px;
1206
- font-weight: 500;
1207
- color: var(--sfx-up-text-secondary, #475569);
1208
- text-align: center;
1209
- line-height: 1.3;
1210
- }
1211
-
1212
- .drop-tile-text span {
1213
- color: var(--sfx-up-primary, #2563eb);
1214
- font-weight: 600;
1215
- }
1216
-
1217
- .drop-tile-sources {
1218
- display: flex;
1219
- gap: 3px;
1220
- margin-top: 2px;
1221
- }
1222
-
1223
- .drop-tile-src {
1224
- width: 28px;
1225
- height: 28px;
1226
- border-radius: 6px;
1227
- border: 1px solid var(--sfx-up-border, #e2e8f0);
1228
- background: var(--sfx-up-bg, #fff);
1229
- display: flex;
1230
- align-items: center;
1231
- justify-content: center;
1232
- cursor: pointer;
1233
- transition: all 0.15s ease;
1234
- padding: 0;
1235
- color: var(--sfx-up-text-muted, #94a3b8);
1236
- }
1237
-
1238
- .drop-tile-src:hover {
1239
- border-color: var(--sfx-up-primary, #2563eb);
1240
- background: var(--sfx-up-primary-bg, #eff6ff);
1241
- transform: translateY(-1px);
1242
- box-shadow: 0 2px 8px rgba(37, 99, 235, 0.15);
1243
- }
1244
-
1245
- .drop-tile-src svg {
1246
- width: 14px;
1247
- height: 14px;
1248
- fill: none;
1249
- stroke: currentColor;
1250
- stroke-width: 2;
1251
- stroke-linecap: round;
1252
- stroke-linejoin: round;
1253
- }
1254
-
1255
- .drop-tile-src svg.fill-icon {
1256
- fill: currentColor;
1257
- stroke: none;
1258
- }
1259
-
1260
- .drop-tile-more-wrap {
1261
- position: relative;
1262
- }
1263
-
1264
- .drop-tile-more {
1265
- width: 28px;
1266
- height: 28px;
1267
- border-radius: 6px;
1268
- border: 1px solid var(--sfx-up-border, #e2e8f0);
1269
- background: var(--sfx-up-bg, #fff);
1270
- display: flex;
1271
- align-items: center;
1272
- justify-content: center;
1273
- cursor: pointer;
1274
- transition: all 0.15s ease;
1275
- padding: 0;
1276
- color: var(--sfx-up-text-muted, #94a3b8);
1277
- font-size: 14px;
1278
- font-weight: 700;
1279
- letter-spacing: 1px;
1280
- }
1281
-
1282
- .drop-tile-more:hover {
1283
- border-color: var(--sfx-up-primary, #2563eb);
1284
- background: var(--sfx-up-primary-bg, #eff6ff);
1285
- transform: translateY(-1px);
1286
- box-shadow: 0 2px 8px rgba(37, 99, 235, 0.15);
1287
- }
1288
-
1289
- .more-dropdown {
1290
- position: absolute;
1291
- top: 36px;
1292
- right: 0;
1293
- background: #fff;
1294
- border: 1px solid var(--sfx-up-border, #e2e8f0);
1295
- border-radius: 10px;
1296
- box-shadow: 0 4px 20px rgba(0, 0, 0, 0.12);
1297
- padding: 6px;
1298
- z-index: 10;
1299
- min-width: 180px;
1300
- animation: dropIn 0.15s ease;
1301
- }
1302
-
1303
- @keyframes dropIn {
1304
- from { opacity: 0; transform: translateY(-4px); }
1305
- to { opacity: 1; transform: translateY(0); }
1306
- }
1307
-
1308
- .more-dropdown-item {
1309
- display: flex;
1310
- align-items: center;
1311
- gap: 10px;
1312
- width: 100%;
1313
- padding: 8px 12px;
1314
- border: none;
1315
- background: none;
1316
- border-radius: 6px;
1317
- cursor: pointer;
1318
- font-size: 13px;
1319
- font-weight: 500;
1320
- color: var(--sfx-up-text, #1e293b);
1321
- white-space: nowrap;
1322
- transition: background 0.15s;
1323
- font-family: inherit;
1324
- }
1325
-
1326
- .more-dropdown-item:hover {
1327
- background: var(--sfx-up-primary-bg, #f5f7fa);
1328
- }
1329
-
1330
- .more-dropdown-ico {
1331
- width: 32px;
1332
- height: 32px;
1333
- border-radius: 8px;
1334
- background: var(--sfx-up-surface, #f8fafc);
1335
- display: flex;
1336
- align-items: center;
1337
- justify-content: center;
1338
- flex-shrink: 0;
1339
- }
1340
-
1341
- .more-dropdown-ico svg {
1342
- width: 16px;
1343
- height: 16px;
1344
- fill: none;
1345
- stroke: currentColor;
1346
- stroke-width: 2;
1347
- stroke-linecap: round;
1348
- stroke-linejoin: round;
1349
- }
1350
-
1351
- .more-dropdown-ico svg.fill-icon {
1352
- fill: currentColor;
1353
- stroke: none;
1354
- }
1355
-
1356
- .more-dropdown-ico .brand-ico {
1357
- width: 20px;
1358
- height: 20px;
1359
- border-radius: 5px;
1360
- display: flex;
1361
- align-items: center;
1362
- justify-content: center;
1363
- }
1364
-
1365
- .more-dropdown-ico .brand-ico svg {
1366
- fill: white;
1367
- stroke: none;
1368
- stroke-width: 0;
1369
- }
1370
-
1371
- .more-dropdown-ico .canva-ico {
1372
- width: 22px;
1373
- height: 22px;
1374
- }
1375
-
1376
- .more-dropdown-ico .canva-ico svg {
1377
- width: 22px;
1378
- height: 22px;
1379
- }
1380
-
1381
- input[type="file"] {
1382
- display: none;
1383
- }
1384
- `;let D=ce;V([c.property({attribute:!1})],D.prototype,"files");V([c.property({type:Boolean})],D.prototype,"showDropTile");V([c.property({attribute:!1})],D.prototype,"sources");V([c.property({type:String})],D.prototype,"accept");V([c.state()],D.prototype,"_moreOpen");var st=Object.defineProperty,at=(n,e,t,o)=>{for(var r=void 0,i=n.length-1,a;i>=0;i--)(a=n[i])&&(r=a(e,t,r)||r);return r&&st(e,t,r),r};const fe=class fe extends s.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 s.nothing;const t=q(e),o=e.status==="complete",r=e.status==="uploading",i=e.status==="error"||e.status==="failed",a=e.status==="rejected",l=Ne(e.name),d=["tile",o?"done":"",r?"uploading":"",a?"rejected":""].filter(Boolean).join(" ");return s.html`
1385
- <div class=${d} tabindex="0">
1386
- <!-- Preview area -->
1387
- <div class="preview">
1388
- ${e.previewUrl?s.html`<div class="preview-bg" style="background-image:url(${e.previewUrl})"></div>`:s.html`
1389
- <div class="preview-bg ${t}"></div>
1390
- <div class="type-icon">
1391
- <div class="type-icon-inner ${t}">
1392
- ${this._renderTypeIcon(t)}
1393
- ${l?s.html`<div class="ext-label">${l}</div>`:s.nothing}
1394
- </div>
1395
- </div>
1396
- `}
1397
-
1398
- <!-- Preview button -->
1399
- ${!o&&!r&&!i&&e.status!=="rejected"?s.html`
1400
- <button class="preview-btn" @click=${this._preview} aria-label="Preview file">
1401
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
1402
- <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/>
1403
- <circle cx="12" cy="12" r="3"/>
1404
- </svg>
1405
- Preview
1406
- </button>
1407
- `:s.nothing}
1408
-
1409
- <!-- Spinner overlay -->
1410
- <div class="spinner-overlay">
1411
- <div class="spin-ring"></div>
1412
- </div>
1413
-
1414
- <!-- Done badge -->
1415
- ${o?s.html`<div class="done-badge">
1416
- <svg viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="3" stroke-linecap="round">
1417
- <polyline points="20 6 9 17 4 12" />
1418
- </svg>
1419
- </div>`:s.nothing}
1420
-
1421
- <!-- Progress bar -->
1422
- ${e.status==="uploading"?s.html`
1423
- <div class="progress">
1424
- <div class="progress-fill" style="transform:scaleX(${Math.min(e.progress,100)/100})"></div>
1425
- </div>
1426
- `:s.nothing}
1427
-
1428
- <!-- Error / rejected badge -->
1429
- ${(i||a)&&e.error?s.html`<div class="error-badge" title=${e.error}>${e.error}</div>`:s.nothing}
1430
-
1431
- <!-- Video duration badge (hidden when error badge is shown to avoid overlap) -->
1432
- ${!(i||a)&&e.duration!=null&&e.duration>0?s.html`<div class="duration-badge">${this._formatDuration(e.duration)}</div>`:s.nothing}
1433
- </div>
1434
-
1435
- <!-- Action buttons -->
1436
- <div class="actions">
1437
- ${i?s.html`
1438
- <button class="act-btn retry" @click=${this._retry} title="Retry" aria-label="Retry upload">
1439
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round">
1440
- <polyline points="23 4 23 10 17 10" />
1441
- <path d="M20.49 15a9 9 0 11-2.12-9.36L23 10" />
1442
- </svg>
1443
- </button>
1444
- `:s.nothing}
1445
- <button class="act-btn del" @click=${this._remove} title="Remove" aria-label="Remove file">
1446
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
1447
- <polyline points="3 6 5 6 21 6" />
1448
- <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6" />
1449
- <path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" />
1450
- <line x1="10" y1="11" x2="10" y2="17" />
1451
- <line x1="14" y1="11" x2="14" y2="17" />
1452
- </svg>
1453
- </button>
1454
- </div>
1455
-
1456
- <!-- Info bar -->
1457
- <div class="info">
1458
- <div class="name" title=${e.name}>${e.name}</div>
1459
- <div class="meta">${l||""}${e.size?` · ${B(e.size)}`:""}</div>
1460
- </div>
1461
- </div>
1462
- `}_formatDuration(e){const t=Math.floor(e/60),o=Math.floor(e%60);return`${t}:${o.toString().padStart(2,"0")}`}_renderTypeIcon(e){switch(e){case"pdf":return s.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 s.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 s.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 s.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 s.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>`}}};fe.styles=s.css`
1463
- :host {
1464
- display: block;
1465
- }
1466
-
1467
- .tile {
1468
- border-radius: 10px;
1469
- background: var(--sfx-up-bg, #fff);
1470
- border: 1px solid #dde3ed;
1471
- box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04), 0 4px 12px rgba(0, 0, 0, 0.06);
1472
- animation: tileIn 0.45s cubic-bezier(0.34, 1.2, 0.64, 1) both;
1473
- animation-delay: calc(min(var(--tile-index, 0), 8) * 0.04s);
1474
- will-change: transform, opacity;
1475
- transition: box-shadow 0.15s, transform 0.15s;
1476
- cursor: default;
1477
- display: flex;
1478
- flex-direction: column;
1479
- position: relative;
1480
- }
1481
-
1482
- .tile:hover {
1483
- box-shadow: 0 2px 6px rgba(0, 0, 0, 0.06), 0 6px 16px rgba(0, 0, 0, 0.08);
1484
- }
1485
-
1486
- /* --- Preview area --- */
1487
- .preview {
1488
- position: relative;
1489
- aspect-ratio: 16 / 10;
1490
- overflow: hidden;
1491
- flex-shrink: 0;
1492
- background-color: var(--sfx-up-checker-bg, #fff);
1493
- background-image:
1494
- linear-gradient(45deg, var(--sfx-up-checker-tile, #f0f0f0) 25%, transparent 25%),
1495
- linear-gradient(-45deg, var(--sfx-up-checker-tile, #f0f0f0) 25%, transparent 25%),
1496
- linear-gradient(45deg, transparent 75%, var(--sfx-up-checker-tile, #f0f0f0) 75%),
1497
- linear-gradient(-45deg, transparent 75%, var(--sfx-up-checker-tile, #f0f0f0) 75%);
1498
- background-size: 16px 16px;
1499
- background-position: 0 0, 0 8px, 8px -8px, -8px 0;
1500
- border-radius: 10px 10px 0 0;
1501
- }
1502
-
1503
- .preview-bg {
1504
- position: absolute;
1505
- inset: 0;
1506
- background-size: contain;
1507
- background-position: center;
1508
- background-repeat: no-repeat;
1509
- transition: transform 0.4s ease;
1510
- }
1511
-
1512
- .tile:hover .preview-bg {
1513
- transform: none;
1514
- }
1515
-
1516
- .preview-bg.pdf { background: linear-gradient(135deg, var(--destructive-10, #fef2f2), var(--destructive-10, #fee2e2)); }
1517
- .preview-bg.doc { background: linear-gradient(135deg, var(--sfx-up-primary-bg, #eff6ff), var(--sfx-up-primary-bg, #dbeafe)); }
1518
- .preview-bg.vid { background: linear-gradient(135deg, #f5f3ff, #ede9fe); }
1519
- .preview-bg.zip { background: linear-gradient(135deg, var(--warning-10, #fffbeb), var(--warning-10, #fef3c7)); }
1520
- .preview-bg.gen { background: linear-gradient(135deg, var(--sfx-up-border-light, #f8fafc), var(--sfx-up-border-light, #f1f5f9)); }
1521
-
1522
- /* --- File type icon --- */
1523
- .type-icon {
1524
- position: absolute;
1525
- inset: 0;
1526
- display: flex;
1527
- align-items: center;
1528
- justify-content: center;
1529
- pointer-events: none;
1530
- }
1531
-
1532
- .type-icon-inner {
1533
- width: 44px;
1534
- height: 44px;
1535
- border-radius: 12px;
1536
- display: flex;
1537
- align-items: center;
1538
- justify-content: center;
1539
- background: rgba(255, 255, 255, 0.9);
1540
- box-shadow: 0 2px 10px var(--sfx-up-shadow, rgba(0, 0, 0, 0.08));
1541
- }
1542
-
1543
- .type-icon-inner svg {
1544
- width: 22px;
1545
- height: 22px;
1546
- }
1547
-
1548
- .type-icon-inner.pdf { color: var(--sfx-up-error, #dc2626); }
1549
- .type-icon-inner.doc { color: var(--sfx-up-primary, #1d4ed8); }
1550
- .type-icon-inner.vid { color: #7c3aed; }
1551
- .type-icon-inner.zip { color: var(--warning-foreground, #b45309); }
1552
- .type-icon-inner.gen { color: var(--sfx-up-text-muted, #64748b); }
1553
-
1554
- .ext-label {
1555
- font-size: 12px;
1556
- font-weight: 800;
1557
- text-transform: uppercase;
1558
- margin-top: 2px;
1559
- }
1560
-
1561
- .duration-badge {
1562
- position: absolute;
1563
- bottom: 6px;
1564
- right: 6px;
1565
- background: rgba(0, 0, 0, 0.65);
1566
- color: #fff;
1567
- font-size: 11px;
1568
- font-weight: 600;
1569
- padding: 2px 6px;
1570
- border-radius: 4px;
1571
- line-height: 1.3;
1572
- pointer-events: none;
1573
- z-index: 2;
1574
- }
1575
-
1576
- /* --- Info bar --- */
1577
- .info {
1578
- padding: 8px 12px;
1579
- min-width: 0;
1580
- }
1581
-
1582
- .name {
1583
- font-size: 14px;
1584
- font-weight: 400;
1585
- color: var(--foreground, var(--sfx-up-text, #111827));
1586
- white-space: nowrap;
1587
- overflow: hidden;
1588
- text-overflow: ellipsis;
1589
- margin-bottom: 2px;
1590
- }
1591
-
1592
- .meta {
1593
- font-size: 12px;
1594
- font-weight: 400;
1595
- color: var(--sfx-up-text-muted, #9ca3af);
1596
- white-space: nowrap;
1597
- overflow: hidden;
1598
- text-overflow: ellipsis;
1599
- }
1600
-
1601
- .tile.done {
1602
- box-shadow: 0 0 0 2px var(--sfx-up-primary, #2563eb);
1603
- }
1604
-
1605
- /* --- Action buttons --- */
1606
- .actions {
1607
- position: absolute;
1608
- top: 6px;
1609
- right: 6px;
1610
- display: flex;
1611
- gap: 4px;
1612
- opacity: 0;
1613
- transition: opacity 0.15s;
1614
- z-index: 10;
1615
- }
1616
-
1617
- .tile:hover .actions,
1618
- .tile:focus-within .actions {
1619
- opacity: 1;
1620
- }
1621
-
1622
- /* Touch devices: always show actions since there is no hover */
1623
- @media (hover: none) {
1624
- .actions { opacity: 1; }
1625
- }
1626
-
1627
- .act-btn {
1628
- width: 26px;
1629
- height: 26px;
1630
- border-radius: 6px;
1631
- border: none;
1632
- background: var(--sfx-up-bg, #fff);
1633
- box-shadow: 0 1px 4px var(--sfx-up-shadow, rgba(0, 0, 0, 0.15));
1634
- cursor: pointer;
1635
- display: flex;
1636
- align-items: center;
1637
- justify-content: center;
1638
- transition: background 0.15s, transform 0.15s;
1639
- color: var(--sfx-up-text-muted, #9ca3af);
1640
- padding: 0;
1641
- }
1642
-
1643
- .act-btn:hover {
1644
- background: var(--sfx-up-border-light, #f3f4f6);
1645
- transform: scale(1.08);
1646
- }
1647
-
1648
- .act-btn.del:hover {
1649
- background: var(--destructive-10, #fee2e2);
1650
- color: var(--sfx-up-error, #dc2626);
1651
- }
1652
-
1653
- .act-btn.retry:hover {
1654
- background: var(--sfx-up-primary-bg, #eff6ff);
1655
- color: var(--sfx-up-primary, #2563eb);
1656
- }
1657
-
1658
- .act-btn svg {
1659
- width: 11px;
1660
- height: 11px;
1661
- }
1662
-
1663
- /* --- Preview button --- */
1664
- .preview-btn {
1665
- position: absolute;
1666
- bottom: 50%;
1667
- left: 50%;
1668
- transform: translate(-50%, 50%);
1669
- padding: 6px 16px;
1670
- border-radius: 6px;
1671
- border: 1.5px solid var(--sfx-up-primary, #2563eb);
1672
- background: var(--sfx-up-bg, #fff);
1673
- cursor: pointer;
1674
- display: flex;
1675
- align-items: center;
1676
- gap: 5px;
1677
- opacity: 0;
1678
- transition: all 0.15s ease;
1679
- color: var(--sfx-up-primary, #2563eb);
1680
- font-family: inherit;
1681
- font-size: 11px;
1682
- font-weight: 600;
1683
- white-space: nowrap;
1684
- z-index: 5;
1685
- }
1686
-
1687
- .tile:hover .preview-btn,
1688
- .tile:focus-within .preview-btn {
1689
- opacity: 1;
1690
- }
1691
-
1692
- @media (hover: none) {
1693
- .preview-btn { opacity: 1; }
1694
- }
1695
-
1696
- .preview-btn:hover {
1697
- background: var(--sfx-up-primary, #2563eb);
1698
- color: var(--sfx-up-bg, #fff);
1699
- }
1700
-
1701
- .preview-btn:hover svg {
1702
- stroke: var(--sfx-up-bg, #fff);
1703
- }
1704
-
1705
- .preview-btn svg {
1706
- width: 13px;
1707
- height: 13px;
1708
- }
1709
-
1710
- /* --- Progress bar --- */
1711
- .progress {
1712
- position: absolute;
1713
- bottom: 0;
1714
- left: 0;
1715
- right: 0;
1716
- height: 2px;
1717
- background: rgba(0, 0, 0, 0.06);
1718
- }
1719
-
1720
- .progress-fill {
1721
- height: 100%;
1722
- background: var(--sfx-up-primary, #2563eb);
1723
- transform-origin: left;
1724
- transition: transform 0.32s ease;
1725
- }
1726
-
1727
- /* --- Uploading spinner overlay --- */
1728
- .spinner-overlay {
1729
- position: absolute;
1730
- inset: 0;
1731
- display: flex;
1732
- align-items: center;
1733
- justify-content: center;
1734
- background: rgba(0, 0, 0, 0.22);
1735
- opacity: 0;
1736
- transition: opacity 0.2s;
1737
- pointer-events: none;
1738
- }
1739
-
1740
- .tile.uploading .spinner-overlay {
1741
- opacity: 1;
1742
- }
1743
-
1744
- .spin-ring {
1745
- width: 28px;
1746
- height: 28px;
1747
- border: 2.5px solid rgba(255, 255, 255, 0.22);
1748
- border-top-color: #fff;
1749
- border-radius: 50%;
1750
- animation: spinRing 0.7s linear infinite;
1751
- }
1752
-
1753
- /* --- Done badge --- */
1754
- .done-badge {
1755
- position: absolute;
1756
- top: 8px;
1757
- left: 8px;
1758
- width: 24px;
1759
- height: 24px;
1760
- border-radius: 50%;
1761
- background: var(--sfx-up-primary, #2563eb);
1762
- display: flex;
1763
- align-items: center;
1764
- justify-content: center;
1765
- pointer-events: none;
1766
- z-index: 10;
1767
- }
1768
-
1769
- .done-badge svg {
1770
- width: 14px;
1771
- height: 14px;
1772
- }
1773
-
1774
- /* --- Error / rejected state --- */
1775
- .error-badge {
1776
- position: absolute;
1777
- bottom: 6px;
1778
- left: 6px;
1779
- right: 6px;
1780
- font-size: 11px;
1781
- font-weight: 500;
1782
- line-height: 1.3;
1783
- color: #fff;
1784
- background: color-mix(in srgb, var(--sfx-up-error, #dc2626) 85%, transparent);
1785
- border-radius: 6px;
1786
- padding: 4px 8px;
1787
- text-align: center;
1788
- display: -webkit-box;
1789
- -webkit-line-clamp: 2;
1790
- line-clamp: 2;
1791
- -webkit-box-orient: vertical;
1792
- overflow: hidden;
1793
- }
1794
-
1795
- .tile.rejected {
1796
- opacity: 0.6;
1797
- box-shadow: 0 0 0 2px var(--sfx-up-error, #dc2626);
1798
- }
1799
-
1800
- @keyframes tileIn {
1801
- 0% {
1802
- opacity: 0;
1803
- transform: scale(0.92) translateY(14px);
1804
- }
1805
- 60% {
1806
- opacity: 1;
1807
- }
1808
- 80% {
1809
- transform: scale(1.02) translateY(-2px);
1810
- }
1811
- 100% {
1812
- opacity: 1;
1813
- transform: scale(1) translateY(0);
1814
- }
1815
- }
1816
-
1817
- @keyframes popBounce {
1818
- 0% { transform: scale(0); opacity: 0; }
1819
- 55% { transform: scale(1.2); opacity: 1; }
1820
- 75% { transform: scale(0.94); }
1821
- 100% { transform: scale(1); }
1822
- }
1823
-
1824
- @keyframes spinRing {
1825
- to { transform: rotate(360deg); }
1826
- }
1827
-
1828
- .tile:focus-visible {
1829
- outline: 2px solid var(--sfx-up-ring, oklch(0.578 0.198 268.129 / 0.7));
1830
- outline-offset: 2px;
1831
- }
1832
-
1833
- .act-btn:focus-visible,
1834
- .preview-btn:focus-visible {
1835
- outline: 2px solid var(--sfx-up-ring, oklch(0.578 0.198 268.129 / 0.7));
1836
- outline-offset: 2px;
1837
- }
1838
-
1839
- @media (prefers-reduced-motion: reduce) {
1840
- .tile { animation: none; }
1841
- .spin-ring { animation: none; }
1842
- }
1843
- `;let J=fe;at([c.property({attribute:!1})],J.prototype,"file");const N=s.css`
1844
- .btn,
1845
- .btn-ghost,
1846
- .btn-primary,
1847
- .btn-sec,
1848
- .btn-retry,
1849
- .btn-upload,
1850
- .btn-danger {
1851
- height: 36px;
1852
- padding: 0 16px;
1853
- border-radius: 6px;
1854
- border: none;
1855
- font-family: inherit;
1856
- font-size: 14px;
1857
- font-weight: 500;
1858
- cursor: pointer;
1859
- display: inline-flex;
1860
- align-items: center;
1861
- justify-content: center;
1862
- gap: 6px;
1863
- transition: all 0.15s ease;
1864
- white-space: nowrap;
1865
- }
1866
-
1867
- .btn svg,
1868
- .btn-ghost svg,
1869
- .btn-primary svg,
1870
- .btn-sec svg,
1871
- .btn-retry svg,
1872
- .btn-upload svg,
1873
- .btn-danger svg {
1874
- width: 14px;
1875
- height: 14px;
1876
- }
1877
-
1878
- .btn-ghost {
1879
- background: none;
1880
- color: var(--sfx-up-text-muted, #94a3b8);
1881
- border: 1.5px solid var(--sfx-up-border, #e2e8f0);
1882
- }
1883
-
1884
- .btn-ghost:hover {
1885
- background: var(--sfx-up-border-light, #f8faff);
1886
- color: var(--sfx-up-text-secondary, #64748b);
1887
- border-color: var(--sfx-up-border, #d1dff0);
1888
- }
1889
-
1890
- .btn-primary {
1891
- background: linear-gradient(135deg, var(--sfx-up-primary, #2563eb), var(--sfx-up-primary-mid, #3b82f6));
1892
- color: var(--primary-foreground, #fff);
1893
- box-shadow: 0 2px 10px var(--sfx-up-primary-glow, rgba(37, 99, 235, 0.28));
1894
- position: relative;
1895
- overflow: hidden;
1896
- }
1897
-
1898
- .btn-primary:hover:not(:disabled) {
1899
- background: linear-gradient(135deg, var(--sfx-up-primary-hover, #1d4ed8), var(--sfx-up-primary, #2563eb));
1900
- box-shadow: 0 4px 16px var(--sfx-up-primary-glow, rgba(37, 99, 235, 0.38));
1901
- transform: translateY(-1px);
1902
- }
1903
-
1904
- .btn-primary:active {
1905
- transform: translateY(0);
1906
- }
1907
-
1908
- .btn-primary:disabled {
1909
- opacity: 0.55;
1910
- cursor: not-allowed;
1911
- }
1912
- `,X=s.css`
1913
- button:focus-visible {
1914
- outline: 2px solid var(--sfx-up-ring, oklch(0.578 0.198 268.129 / 0.7));
1915
- outline-offset: 2px;
1916
- }
1917
- `;var nt=Object.defineProperty,W=(n,e,t,o)=>{for(var r=void 0,i=n.length-1,a;i>=0;i--)(a=n[i])&&(r=a(e,t,r)||r);return r&&nt(e,t,r),r};const Ce=7,he=class he extends s.LitElement{constructor(){super(...arguments),this.fileCount=0,this.totalSize=0,this.thumbnails=[],this.primaryLabel="Done",this.failedFiles=[]}_uploadMore(){this.dispatchEvent(new CustomEvent("upload-more",{bubbles:!0,composed:!0}))}_primaryAction(){this.dispatchEvent(new CustomEvent("primary-action",{bubbles:!0,composed:!0}))}_retryFile(e){this.dispatchEvent(new CustomEvent("file-retry",{bubbles:!0,composed:!0,detail:{fileId:e}}))}_retryAll(){this.dispatchEvent(new CustomEvent("retry-all",{bubbles:!0,composed:!0}))}_close(){this.dispatchEvent(new CustomEvent("close-uploader",{bubbles:!0,composed:!0}))}render(){const e=this.thumbnails.slice(0,Ce),t=this.thumbnails.length-Ce,o=this.fileCount>0,r=this.failedFiles.length>0,i=r&&!o;return s.html`
1918
- <button class="close-btn" title="Close" @click=${this._close}>
1919
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
1920
- </button>
1921
- <div class="card" role="status" aria-live="polite">
1922
- <div class="icon ${i?"error":r?"warning":""}">
1923
- ${i?s.html`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
1924
- <circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/>
1925
- </svg>`:r?s.html`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
1926
- <path d="M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/>
1927
- </svg>`:s.html`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round">
1928
- <polyline points="20 6 9 17 4 12" />
1929
- </svg>`}
1930
- </div>
1931
- <div class="title">${i?"Upload failed":r?"Partially uploaded":"Uploaded successfully!"}</div>
1932
- <div class="subtitle">${i?`${this.failedFiles.length===1?"File":"Files"} could not be uploaded`:r?`${this.fileCount} ${this.fileCount===1?"file":"files"} uploaded, ${this.failedFiles.length} failed`:"All files are ready for use"}</div>
1933
-
1934
- ${e.length>0?s.html`
1935
- <div class="thumbs">
1936
- ${e.map(a=>s.html`<img class="thumb" src=${a} alt="" />`)}
1937
- ${t>0?s.html`<div class="thumb-more">+${t}</div>`:s.nothing}
1938
- </div>
1939
- `:s.nothing}
1940
-
1941
- ${o?s.html`<div class="summary">${this.fileCount} ${this.fileCount===1?"file":"files"} · ${B(this.totalSize)} uploaded</div>`:s.nothing}
1942
-
1943
- ${r?s.html`
1944
- <div class="failed-list">
1945
- ${this.failedFiles.map(a=>s.html`
1946
- <div class="failed-item">
1947
- <svg class="failed-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" role="img" aria-label="Error"><title>Error</title><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>
1948
- <div class="failed-info">
1949
- <div class="failed-name">${a.name}</div>
1950
- <div class="failed-reason">${a.error}</div>
1951
- </div>
1952
- <button class="failed-retry" title="Retry" @click=${()=>this._retryFile(a.id)}>
1953
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 2v6h-6"/><path d="M3 12a9 9 0 0 1 15-6.7L21 8"/><path d="M3 22v-6h6"/><path d="M21 12a9 9 0 0 1-15 6.7L3 16"/></svg>
1954
- </button>
1955
- </div>
1956
- `)}
1957
- </div>
1958
- `:s.nothing}
1959
-
1960
- <div class="actions">
1961
- <button class="btn-ghost" @click=${this._uploadMore}>Upload more</button>
1962
- ${r?s.html`<button class="btn-retry-all" @click=${this._retryAll}>Retry all (${this.failedFiles.length})</button>`:s.nothing}
1963
- <button class="btn-primary" @click=${this._primaryAction}>${this.primaryLabel}</button>
1964
- </div>
1965
- </div>
1966
- `}};he.styles=[N,X,s.css`
1967
- :host {
1968
- display: flex;
1969
- flex: 1;
1970
- justify-content: center;
1971
- align-items: center;
1972
- padding: 24px 0;
1973
- position: relative;
1974
- overflow-y: auto;
1975
- }
1976
-
1977
- .card {
1978
- display: flex;
1979
- flex-direction: column;
1980
- align-items: center;
1981
- text-align: center;
1982
- animation: fadeUp 0.4s ease both;
1983
- }
1984
-
1985
- .icon {
1986
- width: 64px;
1987
- height: 64px;
1988
- border-radius: 50%;
1989
- background: #f0fdf4;
1990
- display: flex;
1991
- align-items: center;
1992
- justify-content: center;
1993
- margin-bottom: 18px;
1994
- color: #22c55e;
1995
- box-shadow: none;
1996
- animation: popBounce 0.6s cubic-bezier(0.34, 1.56, 0.64, 1) 0.1s both;
1997
- }
1998
-
1999
- .icon svg {
2000
- width: 30px;
2001
- height: 30px;
2002
- }
2003
-
2004
- .icon.error {
2005
- background: #fef2f2;
2006
- color: #ef4444;
2007
- }
2008
-
2009
- .icon.warning {
2010
- background: #fffbeb;
2011
- color: #f59e0b;
2012
- }
2013
-
2014
- .title {
2015
- font-size: 20px;
2016
- font-weight: 700;
2017
- color: var(--sfx-up-text, #0f172a);
2018
- letter-spacing: -0.4px;
2019
- margin-bottom: 8px;
2020
- }
2021
-
2022
- .subtitle {
2023
- font-size: 14px;
2024
- color: var(--sfx-up-text-muted, #94a3b8);
2025
- line-height: 1.6;
2026
- max-width: 320px;
2027
- margin-bottom: 20px;
2028
- }
2029
-
2030
- /* --- Thumbnail strip --- */
2031
- .thumbs {
2032
- display: flex;
2033
- justify-content: center;
2034
- gap: 6px;
2035
- margin-bottom: 14px;
2036
- }
2037
-
2038
- .thumb {
2039
- width: 56px;
2040
- height: 56px;
2041
- border-radius: 8px;
2042
- object-fit: cover;
2043
- border: 1px solid var(--sfx-up-border, #e8eaed);
2044
- }
2045
-
2046
- .thumb-more {
2047
- width: 56px;
2048
- height: 56px;
2049
- border-radius: 8px;
2050
- background: var(--sfx-up-surface, #f8fafc);
2051
- border: 1px solid var(--sfx-up-border, #e8eaed);
2052
- display: flex;
2053
- align-items: center;
2054
- justify-content: center;
2055
- font-size: 14px;
2056
- font-weight: 600;
2057
- color: var(--sfx-up-text-muted, #94a3b8);
2058
- }
2059
-
2060
- /* --- Summary chip --- */
2061
- .summary {
2062
- font-size: 14px;
2063
- font-weight: 400;
2064
- color: var(--sfx-up-text, #1e293b);
2065
- background: var(--sfx-up-surface, #f8fafc);
2066
- border-radius: 8px;
2067
- padding: 6px 14px;
2068
- margin-bottom: 22px;
2069
- }
2070
-
2071
- .actions {
2072
- display: flex;
2073
- gap: 8px;
2074
- }
2075
-
2076
- .actions .btn-primary {
2077
- background: linear-gradient(135deg, #22c55e, #16a34a);
2078
- box-shadow: 0 2px 10px rgba(34, 197, 94, 0.28);
2079
- }
2080
-
2081
- .actions .btn-primary:hover:not(:disabled) {
2082
- background: linear-gradient(135deg, #16a34a, #15803d);
2083
- box-shadow: 0 4px 16px rgba(34, 197, 94, 0.38);
2084
- }
2085
-
2086
- /* --- Failed files list --- */
2087
- .failed-list {
2088
- width: 100%;
2089
- max-width: 400px;
2090
- max-height: 200px;
2091
- margin-bottom: 20px;
2092
- border-radius: 8px;
2093
- border: 1px solid var(--sfx-up-border, #e8eaed);
2094
- overflow-y: auto;
2095
- overflow-x: hidden;
2096
- scrollbar-width: thin;
2097
- scrollbar-color: rgba(0,0,0,0.15) transparent;
2098
- }
2099
-
2100
- .failed-list::-webkit-scrollbar {
2101
- width: 6px;
2102
- }
2103
-
2104
- .failed-list::-webkit-scrollbar-track {
2105
- background: transparent;
2106
- margin: 6px 0;
2107
- }
2108
-
2109
- .failed-list::-webkit-scrollbar-thumb {
2110
- background: rgba(0,0,0,0.15);
2111
- border-radius: 3px;
2112
- }
2113
-
2114
- .failed-list::-webkit-scrollbar-thumb:hover {
2115
- background: rgba(0,0,0,0.25);
2116
- }
2117
-
2118
- .failed-item {
2119
- display: flex;
2120
- align-items: center;
2121
- gap: 8px;
2122
- padding: 8px 12px;
2123
- text-align: left;
2124
- border-bottom: 1px solid var(--sfx-up-border, #f1f5f9);
2125
- margin-right: 8px;
2126
- }
2127
-
2128
- .failed-item:last-child {
2129
- border-bottom: none;
2130
- }
2131
-
2132
- .failed-icon {
2133
- width: 16px;
2134
- height: 16px;
2135
- flex-shrink: 0;
2136
- color: #ef4444;
2137
- margin-top: 1px;
2138
- }
2139
-
2140
- .failed-info {
2141
- flex: 1;
2142
- min-width: 0;
2143
- }
2144
-
2145
- .failed-name {
2146
- font-size: 12px;
2147
- font-weight: 500;
2148
- color: var(--sfx-up-text, #1e293b);
2149
- white-space: nowrap;
2150
- overflow: hidden;
2151
- text-overflow: ellipsis;
2152
- }
2153
-
2154
- .failed-reason {
2155
- font-size: 11px;
2156
- color: var(--sfx-up-text-muted, #94a3b8);
2157
- line-height: 1.4;
2158
- }
2159
-
2160
- .failed-retry {
2161
- width: 24px;
2162
- height: 24px;
2163
- border: none;
2164
- background: none;
2165
- color: var(--sfx-up-primary, #2563eb);
2166
- cursor: pointer;
2167
- padding: 4px;
2168
- flex-shrink: 0;
2169
- display: flex;
2170
- align-items: center;
2171
- justify-content: center;
2172
- border-radius: 4px;
2173
- margin-top: -2px;
2174
- }
2175
-
2176
- .failed-retry svg { width: 14px; height: 14px; }
2177
-
2178
- .failed-retry:hover { background: var(--sfx-up-surface, #f8fafc); color: var(--sfx-up-primary-hover, #1d4ed8); }
2179
-
2180
- .close-btn {
2181
- position: absolute;
2182
- top: 12px;
2183
- right: 12px;
2184
- width: 28px;
2185
- height: 28px;
2186
- border: none;
2187
- background: none;
2188
- color: var(--sfx-up-text-muted, #94a3b8);
2189
- cursor: pointer;
2190
- display: flex;
2191
- align-items: center;
2192
- justify-content: center;
2193
- border-radius: 6px;
2194
- padding: 0;
2195
- }
2196
-
2197
- .close-btn svg { width: 16px; height: 16px; }
2198
-
2199
- .close-btn:hover { background: var(--sfx-up-surface, #f8fafc); color: var(--sfx-up-text, #1e293b); }
2200
-
2201
- .btn-retry-all {
2202
- padding: 8px 18px;
2203
- border-radius: 8px;
2204
- font-size: 13px;
2205
- font-weight: 500;
2206
- border: 1px solid var(--sfx-up-primary, #2563eb);
2207
- background: #fff;
2208
- color: var(--sfx-up-primary, #2563eb);
2209
- cursor: pointer;
2210
- }
2211
-
2212
- .btn-retry-all:hover {
2213
- background: var(--sfx-up-primary-bg, #eff6ff);
2214
- }
2215
-
2216
- @keyframes fadeUp {
2217
- from {
2218
- opacity: 0;
2219
- transform: translateY(12px);
2220
- }
2221
- to {
2222
- opacity: 1;
2223
- transform: translateY(0);
2224
- }
2225
- }
2226
-
2227
- @keyframes popBounce {
2228
- 0% { transform: scale(0); opacity: 0; }
2229
- 55% { transform: scale(1.2); opacity: 1; }
2230
- 75% { transform: scale(0.94); }
2231
- 100% { transform: scale(1); }
2232
- }
2233
-
2234
- @media (max-width: 480px) {
2235
- .icon { width: 48px; height: 48px; margin-bottom: 12px; }
2236
- .icon svg { width: 24px; height: 24px; }
2237
- .title { font-size: 18px; }
2238
- .thumb, .thumb-more { width: 44px; height: 44px; }
2239
- }
2240
-
2241
- @media (prefers-reduced-motion: reduce) {
2242
- .card { animation: none; }
2243
- .icon { animation: none; }
2244
- }
2245
- `];let F=he;W([c.property({type:Number})],F.prototype,"fileCount");W([c.property({type:Number})],F.prototype,"totalSize");W([c.property({type:Array})],F.prototype,"thumbnails");W([c.property({type:String})],F.prototype,"primaryLabel");W([c.property({type:Array})],F.prototype,"failedFiles");var lt=Object.defineProperty,R=(n,e,t,o)=>{for(var r=void 0,i=n.length-1,a;i>=0;i--)(a=n[i])&&(r=a(e,t,r)||r);return r&&lt(e,t,r),r};const ue=class ue extends s.LitElement{constructor(){super(...arguments),this.uploadState="idle",this.fileCount=0,this.totalSize=0,this.failedCount=0,this.showFillMetadata=!1,this.completedCount=0,this.uploadProgress=0}_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(){const e=this.uploadState==="uploading";return s.html`
2246
- ${e?s.html`
2247
- <div class="progress-row">
2248
- <div class="progress-track" role="progressbar" aria-valuenow=${Math.round(this.uploadProgress)} aria-valuemin="0" aria-valuemax="100" aria-label="Upload progress">
2249
- <div class="progress-fill" style="width:${this.uploadProgress}%"></div>
2250
- </div>
2251
- <span class="progress-label">${this.completedCount}/${this.fileCount} files</span>
2252
- </div>
2253
- `:s.nothing}
2254
- <div class="buttons-row">
2255
- <div class="left">
2256
- ${this.showFillMetadata&&this.uploadState==="idle"?s.html`
2257
- <button class="btn-sec" @click=${this._fillMetadata}>
2258
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
2259
- <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
2260
- <polyline points="14 2 14 8 20 8"/>
2261
- <line x1="16" y1="13" x2="8" y2="13"/>
2262
- <line x1="16" y1="17" x2="8" y2="17"/>
2263
- <line x1="10" y1="9" x2="8" y2="9"/>
2264
- </svg>
2265
- Fill Metadata
2266
- </button>
2267
- `:s.nothing}
2268
- </div>
2269
- <div class="right">
2270
- <button class="btn-ghost" @click=${this._clear}>
2271
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
2272
- <path d="M3 6h18" />
2273
- <path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6" />
2274
- <path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2" />
2275
- <line x1="10" y1="11" x2="10" y2="17" />
2276
- <line x1="14" y1="11" x2="14" y2="17" />
2277
- </svg>
2278
- Clear
2279
- </button>
2280
- <button class="btn-sec" @click=${this._addMore}>
2281
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round">
2282
- <line x1="12" y1="5" x2="12" y2="19" />
2283
- <line x1="5" y1="12" x2="19" y2="12" />
2284
- </svg>
2285
- Add more
2286
- </button>
2287
- ${this.failedCount>0?s.html`
2288
- <button class="btn-retry" @click=${this._retryAll}>
2289
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round">
2290
- <polyline points="23 4 23 10 17 10" />
2291
- <path d="M20.49 15a9 9 0 11-2.12-9.36L23 10" />
2292
- </svg>
2293
- Retry all (${this.failedCount})
2294
- </button>
2295
- `:s.nothing}
2296
- ${this._renderUploadButton()}
2297
- </div>
2298
- </div>
2299
- `}_renderUploadButton(){const e=this.uploadState==="uploading",t=this.uploadState==="done",o=["btn-primary",t?"done-state":""].filter(Boolean).join(" ");return s.html`
2300
- <button
2301
- class=${o}
2302
- @click=${this._upload}
2303
- ?disabled=${e}
2304
- >
2305
- ${e?s.html`<span class="btn-spin"></span> Uploading\u2026`:t?s.html`
2306
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round">
2307
- <polyline points="20 6 9 17 4 12" />
2308
- </svg>
2309
- Done!
2310
- `:s.html`
2311
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round">
2312
- <polyline points="16 16 12 12 8 16" />
2313
- <line x1="12" y1="12" x2="12" y2="21" />
2314
- <path d="M20.39 18.39A5 5 0 0018 9h-1.26A8 8 0 103 16.3" />
2315
- </svg>
2316
- Upload
2317
- `}
2318
- </button>
2319
- `}};ue.styles=[N,X,s.css`
2320
- :host {
2321
- display: flex;
2322
- flex-direction: column;
2323
- background: var(--sfx-up-bg, #ffffff);
2324
- border-top: 1px solid var(--sfx-up-border, #e2e8f0);
2325
- flex-shrink: 0;
2326
- box-shadow: none;
2327
- animation: barSlideUp 0.3s cubic-bezier(0.34, 1.2, 0.64, 1) both;
2328
- }
2329
-
2330
- @keyframes barSlideUp {
2331
- from {
2332
- opacity: 0;
2333
- transform: translateY(12px);
2334
- }
2335
- to {
2336
- opacity: 1;
2337
- transform: translateY(0);
2338
- }
2339
- }
2340
-
2341
- /* --- Progress row --- */
2342
- .progress-row {
2343
- display: flex;
2344
- align-items: center;
2345
- gap: 12px;
2346
- padding: 10px 24px 0;
2347
- }
2348
-
2349
- .progress-track {
2350
- flex: 1;
2351
- height: 4px;
2352
- background: var(--sfx-up-border, #e2e8f0);
2353
- border-radius: 2px;
2354
- overflow: hidden;
2355
- }
2356
-
2357
- .progress-fill {
2358
- height: 100%;
2359
- background: var(--sfx-up-primary, #2563eb);
2360
- border-radius: 2px;
2361
- transition: width 0.3s ease;
2362
- }
2363
-
2364
- .progress-label {
2365
- font-size: 13px;
2366
- font-weight: 600;
2367
- color: var(--sfx-up-text, #1e293b);
2368
- white-space: nowrap;
2369
- flex-shrink: 0;
2370
- }
2371
-
2372
- /* --- Buttons row --- */
2373
- .buttons-row {
2374
- display: flex;
2375
- align-items: center;
2376
- justify-content: space-between;
2377
- padding: 14px 24px;
2378
- }
2379
-
2380
- .left {
2381
- display: flex;
2382
- align-items: center;
2383
- gap: 8px;
2384
- }
2385
-
2386
- .right {
2387
- display: flex;
2388
- align-items: center;
2389
- gap: 8px;
2390
- }
2391
-
2392
- /* --- Button overrides (base in shared-styles) --- */
2393
-
2394
- .btn-sec {
2395
- background: var(--sfx-up-primary-bg, #eff6ff);
2396
- color: var(--sfx-up-primary, #2563eb);
2397
- border: 1.5px solid var(--sfx-up-primary-glow, rgba(37, 99, 235, 0.15));
2398
- }
2399
-
2400
- .btn-sec:hover {
2401
- background: var(--sfx-up-primary-bg, #dbeafe);
2402
- }
2403
-
2404
- .btn-retry {
2405
- background: var(--destructive-10, #fef2f2);
2406
- color: var(--sfx-up-error, #dc2626);
2407
- border: 1.5px solid var(--sfx-up-error, rgba(220, 38, 38, 0.2));
2408
- }
2409
-
2410
- .btn-retry:hover {
2411
- background: var(--destructive-10, #fee2e2);
2412
- color: var(--destructive-foreground, #b91c1c);
2413
- border-color: var(--sfx-up-error, rgba(220, 38, 38, 0.35));
2414
- }
2415
-
2416
- .btn-primary {
2417
- min-width: 110px;
2418
- }
2419
-
2420
- .btn-primary.done-state {
2421
- background: var(--sfx-up-success, #16a34a);
2422
- box-shadow: 0 2px 10px var(--sfx-up-shadow, rgba(22, 163, 74, 0.28));
2423
- }
2424
-
2425
- /* --- Spinner --- */
2426
- .btn-spin {
2427
- width: 14px;
2428
- height: 14px;
2429
- border: 2px solid rgba(255, 255, 255, 0.3);
2430
- border-top-color: #fff;
2431
- border-radius: 50%;
2432
- animation: spinRing 0.7s linear infinite;
2433
- }
2434
-
2435
- /* --- Count --- */
2436
- .count {
2437
- font-size: 14px;
2438
- font-weight: 700;
2439
- color: var(--sfx-up-text, #1e293b);
2440
- }
2441
-
2442
- .count span {
2443
- font-weight: 400;
2444
- color: var(--sfx-up-text-muted, #94a3b8);
2445
- }
2446
-
2447
- @keyframes spinRing {
2448
- to { transform: rotate(360deg); }
2449
- }
2450
-
2451
- @media (max-width: 480px) {
2452
- .buttons-row {
2453
- padding: 10px 12px;
2454
- flex-wrap: wrap;
2455
- gap: 8px;
2456
- }
2457
- button {
2458
- height: 32px;
2459
- font-size: 12px;
2460
- }
2461
- }
2462
-
2463
- @media (prefers-reduced-motion: reduce) {
2464
- :host { animation: none; }
2465
- .btn-spin { animation: none; }
2466
- }
2467
- `];let P=ue;R([c.property({type:String})],P.prototype,"uploadState");R([c.property({type:Number})],P.prototype,"fileCount");R([c.property({type:Number})],P.prototype,"totalSize");R([c.property({type:Number})],P.prototype,"failedCount");R([c.property({type:Boolean})],P.prototype,"showFillMetadata");R([c.property({type:Number})],P.prototype,"completedCount");R([c.property({type:Number})],P.prototype,"uploadProgress");const dt='button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';function ae(n,e){return t=>{if(t.key!=="Tab")return;const o=n();if(!o)return;const r=o.querySelector(e);if(!r)return;const i=Array.from(r.querySelectorAll(dt));if(i.length===0)return;const a=i[0],l=i[i.length-1],d=o.activeElement;t.shiftKey?(d===a||!r.contains(d))&&(t.preventDefault(),l.focus()):(d===l||!r.contains(d))&&(t.preventDefault(),a.focus())}}var pt=Object.defineProperty,ne=(n,e,t,o)=>{for(var r=void 0,i=n.length-1,a;i>=0;i--)(a=n[i])&&(r=a(e,t,r)||r);return r&&pt(e,t,r),r};const xe=class xe extends s.LitElement{constructor(){super(...arguments),this._url="",this._name="",this._error="",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._focusTrap=ae(()=>this.shadowRoot,".card"),this._onKeyDown=e=>{var t;e.key==="Escape"&&this._cancel(),e.key==="Enter"&&((t=e.target)==null?void 0:t.tagName)==="INPUT"&&this._submit(),this._focusTrap(e)}}_autoName(){var e;if(!this._name)try{const t=new URL(this._url).pathname.split("/"),o=t[t.length-1];if(o){const r=(e=this.shadowRoot)==null?void 0:e.querySelector("#nameInput");r&&(r.placeholder=o)}}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 o=new URL(e).pathname.split("/");t=o[o.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 s.html`
2468
- <div class="backdrop" @click=${this._onBackdropClick} @keydown=${this._onKeyDown}>
2469
- <div class="card">
2470
- <div class="head">
2471
- <div class="head-icon">
2472
- <svg viewBox="0 0 24 24">
2473
- <path d="M10 13a5 5 0 007.54.54l3-3a5 5 0 00-7.07-7.07l-1.72 1.71" />
2474
- <path d="M14 11a5 5 0 00-7.54-.54l-3 3a5 5 0 007.07 7.07l1.71-1.71" />
2475
- </svg>
2476
- </div>
2477
- <div class="title">Import from URL</div>
2478
- <button class="close-btn" aria-label="Close" @click=${this._cancel}>\u2715</button>
2479
- </div>
2480
- <div class="body">
2481
- <div class="field">
2482
- <label for="urlInput">File URL</label>
2483
- <input
2484
- id="urlInput"
2485
- type="url"
2486
- placeholder="https://example.com/file.pdf"
2487
- .value=${this._url}
2488
- @input=${this._onUrlInput}
2489
- />
2490
- </div>
2491
- <div class="field">
2492
- <label for="nameInput">File name <span class="optional">(optional)</span></label>
2493
- <input
2494
- id="nameInput"
2495
- type="text"
2496
- placeholder="document.pdf"
2497
- .value=${this._name}
2498
- @input=${this._onNameInput}
2499
- />
2500
- </div>
2501
- ${this._error?s.html`<div class="error">${this._error}</div>`:""}
2502
- <div class="actions">
2503
- <button class="btn btn-ghost" @click=${this._cancel}>Cancel</button>
2504
- <button class="btn btn-primary" @click=${this._submit}>
2505
- Import file
2506
- </button>
2507
- </div>
2508
- </div>
2509
- </div>
2510
- </div>
2511
- `}};xe.styles=[N,X,s.css`
2512
- :host {
2513
- display: block;
2514
- }
2515
-
2516
- .backdrop {
2517
- position: fixed;
2518
- inset: 0;
2519
- z-index: 1000;
2520
- background: var(--sfx-up-backdrop, rgba(0, 0, 0, 0.45));
2521
- backdrop-filter: blur(6px);
2522
- display: flex;
2523
- align-items: center;
2524
- justify-content: center;
2525
- padding: 20px;
2526
- animation: fadeIn 0.18s ease both;
2527
- }
2528
-
2529
- .card {
2530
- background: var(--sfx-up-bg, #fff);
2531
- border-radius: 12px;
2532
- box-shadow: 0 28px 80px var(--sfx-up-shadow, rgba(0, 0, 0, 0.18)), 0 4px 16px rgba(0, 0, 0, 0.06);
2533
- width: 100%;
2534
- max-width: 480px;
2535
- overflow: hidden;
2536
- display: flex;
2537
- flex-direction: column;
2538
- transform: translateY(18px) scale(0.97);
2539
- animation: slideUp 0.28s cubic-bezier(0.34, 1.2, 0.64, 1) forwards;
2540
- }
2541
-
2542
- .head {
2543
- display: flex;
2544
- align-items: center;
2545
- gap: 10px;
2546
- padding: 18px 20px 0;
2547
- }
2548
-
2549
- .head-icon {
2550
- width: 32px;
2551
- height: 32px;
2552
- border-radius: 8px;
2553
- background: var(--sfx-up-primary-bg, #f5f5f7);
2554
- display: flex;
2555
- align-items: center;
2556
- justify-content: center;
2557
- flex-shrink: 0;
2558
- color: var(--sfx-up-primary, #2563eb);
2559
- }
2560
-
2561
- .head-icon svg {
2562
- width: 18px;
2563
- height: 18px;
2564
- fill: none;
2565
- stroke: currentColor;
2566
- stroke-width: 2;
2567
- stroke-linecap: round;
2568
- }
2569
-
2570
- .title {
2571
- font-size: 16px;
2572
- font-weight: 700;
2573
- color: var(--sfx-up-text, #1a1a1a);
2574
- flex: 1;
2575
- }
2576
-
2577
- .close-btn {
2578
- width: 28px;
2579
- height: 28px;
2580
- border-radius: 8px;
2581
- border: none;
2582
- background: var(--sfx-up-border-light, #f0f0f0);
2583
- color: var(--sfx-up-text-muted, #888);
2584
- font-size: 14px;
2585
- cursor: pointer;
2586
- display: flex;
2587
- align-items: center;
2588
- justify-content: center;
2589
- transition: background 0.15s, color 0.15s;
2590
- flex-shrink: 0;
2591
- line-height: 1;
2592
- }
2593
-
2594
- .close-btn:hover {
2595
- background: var(--sfx-up-border, #e4e4e4);
2596
- color: var(--sfx-up-text, #333);
2597
- }
2598
-
2599
- .body {
2600
- padding: 18px 20px 20px;
2601
- }
2602
-
2603
- .field {
2604
- margin-bottom: 14px;
2605
- }
2606
-
2607
- label {
2608
- display: block;
2609
- font-size: 12px;
2610
- font-weight: 600;
2611
- color: var(--sfx-up-text-muted, #aaa);
2612
- margin-bottom: 5px;
2613
- text-transform: uppercase;
2614
- letter-spacing: 0.7px;
2615
- }
2616
-
2617
- label .optional {
2618
- color: var(--sfx-up-border, #ccc);
2619
- font-weight: 400;
2620
- text-transform: none;
2621
- letter-spacing: 0;
2622
- }
2623
-
2624
- input {
2625
- width: 100%;
2626
- height: 40px;
2627
- border: 1.5px solid var(--sfx-up-border, #ebebeb);
2628
- border-radius: 6px;
2629
- padding: 0 14px;
2630
- font-size: 14px;
2631
- font-family: inherit;
2632
- color: var(--sfx-up-text, #1a1a1a);
2633
- background: var(--sfx-up-border-light, #fafafa);
2634
- transition: border-color 0.15s, background 0.15s;
2635
- outline: none;
2636
- box-sizing: border-box;
2637
- }
2638
-
2639
- input:focus {
2640
- border-color: var(--sfx-up-primary, #2563eb);
2641
- background: var(--sfx-up-bg, #fff);
2642
- }
2643
-
2644
- input::placeholder {
2645
- color: var(--sfx-up-text-muted, #ccc);
2646
- text-align: center;
2647
- }
2648
-
2649
- .error {
2650
- font-size: 12px;
2651
- color: var(--sfx-up-error, #dc2626);
2652
- margin-top: -6px;
2653
- margin-bottom: 8px;
2654
- }
2655
-
2656
- .actions {
2657
- display: flex;
2658
- gap: 8px;
2659
- justify-content: flex-end;
2660
- margin-top: 18px;
2661
- }
2662
-
2663
-
2664
-
2665
- @keyframes fadeIn {
2666
- from { opacity: 0; }
2667
- to { opacity: 1; }
2668
- }
2669
-
2670
- @keyframes slideUp {
2671
- from { transform: translateY(18px) scale(0.97); }
2672
- to { transform: translateY(0) scale(1); }
2673
- }
2674
-
2675
- .close-btn:focus-visible {
2676
- outline: 2px solid var(--sfx-up-primary, #2563eb);
2677
- outline-offset: 2px;
2678
- }
2679
-
2680
- input:focus-visible {
2681
- outline: none;
2682
- }
2683
-
2684
- `];let I=xe;ne([c.state()],I.prototype,"_url");ne([c.state()],I.prototype,"_name");ne([c.state()],I.prototype,"_error");var ct=Object.defineProperty,re=(n,e,t,o)=>{for(var r=void 0,i=n.length-1,a;i>=0;i--)(a=n[i])&&(r=a(e,t,r)||r);return r&&ct(e,t,r),r};const ge=class ge extends s.LitElement{constructor(){super(...arguments),this._stream=null,this._error="",this._captured=null,this._previewUrl="",this._onBackdropClick=e=>{e.target===e.currentTarget&&this._cancel()},this._focusTrap=ae(()=>this.shadowRoot,".card"),this._onKeyDown=e=>{e.key==="Escape"&&this._cancel(),this._focusTrap(e)},this._capture=()=>{var r,i;const e=(r=this.shadowRoot)==null?void 0:r.querySelector("video"),t=(i=this.shadowRoot)==null?void 0:i.querySelector("canvas");if(!e||!t)return;t.width=e.videoWidth,t.height=e.videoHeight,t.getContext("2d").drawImage(e,0,0),t.toBlob(a=>{a&&(this._captured=a,this._previewUrl=URL.createObjectURL(a),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 s.html`
2685
- <div class="backdrop" @click=${this._onBackdropClick} @keydown=${this._onKeyDown}>
2686
- <div class="card">
2687
- <div class="head">
2688
- <div class="head-icon">
2689
- <svg viewBox="0 0 24 24">
2690
- <path d="M23 19a2 2 0 01-2 2H3a2 2 0 01-2-2V8a2 2 0 012-2h4l2-3h6l2 3h4a2 2 0 012 2z"/>
2691
- <circle cx="12" cy="13" r="4"/>
2692
- </svg>
2693
- </div>
2694
- <div class="title">Camera</div>
2695
- <button class="close-btn" aria-label="Close" @click=${this._cancel}>\u2715</button>
2696
- </div>
2697
- <div class="body">
2698
- ${this._error?s.html`<div class="error">${this._error}</div>`:this._captured?s.html`
2699
- <img class="preview-img" src=${this._previewUrl} alt="Captured photo" />
2700
- <div class="actions">
2701
- <button class="btn btn-ghost" @click=${this._retake}>Retake</button>
2702
- <button class="btn btn-primary" @click=${this._usePhoto}>Use photo</button>
2703
- </div>
2704
- `:s.html`
2705
- <video autoplay playsinline muted></video>
2706
- <canvas></canvas>
2707
- <div class="actions">
2708
- <button class="btn-capture" @click=${this._capture}></button>
2709
- </div>
2710
- `}
2711
- </div>
2712
- </div>
2713
- </div>
2714
- `}};ge.styles=[N,X,s.css`
2715
- :host { display: block; }
2716
-
2717
- .backdrop {
2718
- position: fixed; inset: 0; z-index: 1000;
2719
- background: var(--sfx-up-backdrop, rgba(0, 0, 0, 0.45));
2720
- backdrop-filter: blur(6px);
2721
- display: flex; align-items: center; justify-content: center;
2722
- padding: 20px;
2723
- animation: fadeIn 0.18s ease both;
2724
- }
2725
-
2726
- .card {
2727
- background: var(--sfx-up-bg, #fff);
2728
- border-radius: 12px;
2729
- box-shadow: 0 28px 80px rgba(0, 0, 0, 0.18), 0 4px 16px rgba(0, 0, 0, 0.06);
2730
- width: 100%; max-width: 520px;
2731
- height: 520px;
2732
- overflow: hidden; display: flex; flex-direction: column;
2733
- animation: slideUp 0.28s cubic-bezier(0.34, 1.2, 0.64, 1) forwards;
2734
- }
2735
-
2736
- .head {
2737
- display: flex; align-items: center; gap: 10px;
2738
- padding: 18px 20px 0;
2739
- }
2740
-
2741
- .head-icon {
2742
- width: 32px; height: 32px; border-radius: 8px;
2743
- background: var(--sfx-up-primary-bg, #f5f5f7);
2744
- display: flex; align-items: center; justify-content: center;
2745
- flex-shrink: 0; color: var(--sfx-up-primary, #2563eb);
2746
- }
2747
-
2748
- .head-icon svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
2749
-
2750
- .title { font-size: 16px; font-weight: 700; color: var(--sfx-up-text, #1a1a1a); flex: 1; }
2751
-
2752
- .close-btn {
2753
- width: 28px; height: 28px; border-radius: 8px; border: none;
2754
- background: var(--sfx-up-border-light, #f0f0f0); color: var(--sfx-up-text-muted, #888); font-size: 14px; cursor: pointer;
2755
- display: flex; align-items: center; justify-content: center;
2756
- transition: background 0.15s, color 0.15s; flex-shrink: 0; line-height: 1;
2757
- }
2758
- .close-btn:hover { background: var(--sfx-up-border, #e4e4e4); color: var(--sfx-up-text, #333); }
2759
-
2760
- .body { padding: 18px 20px 20px; display: flex; flex-direction: column; align-items: center; gap: 16px; flex: 1; min-height: 0; justify-content: center; }
2761
-
2762
- video, canvas {
2763
- width: 100%; flex: 1; min-height: 0; border-radius: 12px;
2764
- background: #000; object-fit: cover;
2765
- }
2766
-
2767
- canvas { display: none; }
2768
-
2769
- .preview-img {
2770
- width: 100%; max-height: 320px; border-radius: 12px;
2771
- object-fit: contain; background: #000;
2772
- }
2773
-
2774
- .error { font-size: 13px; color: var(--sfx-up-error, #dc2626); text-align: center; padding: 40px 20px; }
2775
-
2776
- .actions { display: flex; gap: 8px; justify-content: center; width: 100%; }
2777
-
2778
- .btn-capture {
2779
- width: 52px; height: 52px; border-radius: 50%; padding: 0;
2780
- background: var(--sfx-up-error, #dc2626); border: 4px solid var(--sfx-up-bg, #fff);
2781
- box-shadow: 0 0 0 2px var(--sfx-up-error, #dc2626), 0 4px 12px var(--sfx-up-shadow, rgba(220, 38, 38, 0.3));
2782
- cursor: pointer; transition: all 0.15s;
2783
- }
2784
- .btn-capture:hover { background: var(--destructive-foreground, #b91c1c); transform: scale(1.05); }
2785
-
2786
- .close-btn:focus-visible,
2787
- .btn-capture:focus-visible {
2788
- outline: 2px solid var(--sfx-up-primary, #2563eb);
2789
- outline-offset: 2px;
2790
- }
2791
-
2792
- @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
2793
- @keyframes slideUp { from { transform: translateY(18px) scale(0.97); } to { transform: translateY(0) scale(1); } }
2794
- `];let O=ge;re([c.state()],O.prototype,"_stream");re([c.state()],O.prototype,"_error");re([c.state()],O.prototype,"_captured");re([c.state()],O.prototype,"_previewUrl");var ft=Object.defineProperty,G=(n,e,t,o)=>{for(var r=void 0,i=n.length-1,a;i>=0;i--)(a=n[i])&&(r=a(e,t,r)||r);return r&&ft(e,t,r),r};const ve=class ve extends s.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._focusTrap=ae(()=>this.shadowRoot,".card"),this._onKeyDown=e=>{e.key==="Escape"&&this._cancel(),this._focusTrap(e)},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 o=MediaRecorder.isTypeSupported("video/webm;codecs=vp9")?"video/webm;codecs=vp9":"video/webm";this._recorder=new MediaRecorder(this._stream,{mimeType:o}),this._recorder.ondataavailable=r=>{r.data.size>0&&this._chunks.push(r.data)},this._recorder.onstop=()=>{var i;const r=new Blob(this._chunks,{type:"video/webm"});this._recordedBlob=r,this._previewUrl=URL.createObjectURL(r),(i=this._stream)==null||i.getTracks().forEach(a=>a.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?void 0:e.state)==="recording"&&this._recorder.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(o=>o.stop()),this._stream=null}_cancel(){this._stopAll(),this.dispatchEvent(new CustomEvent("screencast-cancel",{bubbles:!0,composed:!0}))}render(){return s.html`
2795
- <div class="backdrop" @click=${this._onBackdropClick} @keydown=${this._onKeyDown}>
2796
- <div class="card">
2797
- <div class="head">
2798
- <div class="head-icon">
2799
- <svg viewBox="0 0 24 24">
2800
- <rect x="2" y="3" width="20" height="14" rx="2"/>
2801
- <circle cx="12" cy="10" r="3"/>
2802
- <path d="M7 21h10"/>
2803
- </svg>
2804
- </div>
2805
- <div class="title">Screen cast</div>
2806
- <button class="close-btn" aria-label="Close" @click=${this._cancel}>\u2715</button>
2807
- </div>
2808
- <div class="body">
2809
- ${this._error?s.html`<div class="error">${this._error}</div>`:this._recordedBlob?s.html`
2810
- <video src=${this._previewUrl} controls></video>
2811
- <div class="actions">
2812
- <button class="btn btn-ghost" @click=${this._discard}>Discard</button>
2813
- <button class="btn btn-primary" @click=${this._useRecording}>Use recording</button>
2814
- </div>
2815
- `:this._recording?s.html`
2816
- <video autoplay playsinline muted></video>
2817
- <div class="status"><div class="rec-dot"></div> Recording...</div>
2818
- <div class="actions">
2819
- <button class="btn btn-danger" @click=${this._stopRecording}>Stop recording</button>
2820
- </div>
2821
- `:s.html`
2822
- <div class="start-view">
2823
- <div class="start-icon">
2824
- <svg viewBox="0 0 24 24">
2825
- <rect x="2" y="3" width="20" height="14" rx="2"/>
2826
- <circle cx="12" cy="10" r="3"/>
2827
- <path d="M7 21h10"/>
2828
- </svg>
2829
- </div>
2830
- <div class="start-text">Share your screen to record a video that will be added to your uploads.</div>
2831
- <div class="actions">
2832
- <button class="btn btn-ghost" @click=${this._cancel}>Cancel</button>
2833
- <button class="btn btn-primary" @click=${this._startRecording}>Start recording</button>
2834
- </div>
2835
- </div>
2836
- `}
2837
- </div>
2838
- </div>
2839
- </div>
2840
- `}};ve.styles=[N,X,s.css`
2841
- :host { display: block; }
2842
-
2843
- .backdrop {
2844
- position: fixed; inset: 0; z-index: 1000;
2845
- background: var(--sfx-up-backdrop, rgba(0, 0, 0, 0.45));
2846
- backdrop-filter: blur(6px);
2847
- display: flex; align-items: center; justify-content: center;
2848
- padding: 20px;
2849
- animation: fadeIn 0.18s ease both;
2850
- }
2851
-
2852
- .card {
2853
- background: var(--sfx-up-bg, #fff);
2854
- border-radius: 12px;
2855
- box-shadow: 0 28px 80px rgba(0, 0, 0, 0.18), 0 4px 16px rgba(0, 0, 0, 0.06);
2856
- width: 100%; max-width: 560px;
2857
- overflow: hidden; display: flex; flex-direction: column;
2858
- animation: slideUp 0.28s cubic-bezier(0.34, 1.2, 0.64, 1) forwards;
2859
- }
2860
-
2861
- .head {
2862
- display: flex; align-items: center; gap: 10px;
2863
- padding: 18px 20px 0;
2864
- }
2865
-
2866
- .head-icon {
2867
- width: 32px; height: 32px; border-radius: 8px;
2868
- background: var(--sfx-up-primary-bg, #f5f5f7);
2869
- display: flex; align-items: center; justify-content: center;
2870
- flex-shrink: 0; color: var(--sfx-up-primary, #2563eb);
2871
- }
2872
-
2873
- .head-icon svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
2874
-
2875
- .title { font-size: 16px; font-weight: 700; color: var(--sfx-up-text, #1a1a1a); flex: 1; }
2876
-
2877
- .close-btn {
2878
- width: 28px; height: 28px; border-radius: 8px; border: none;
2879
- background: var(--sfx-up-border-light, #f0f0f0); color: var(--sfx-up-text-muted, #888); font-size: 14px; cursor: pointer;
2880
- display: flex; align-items: center; justify-content: center;
2881
- transition: background 0.15s, color 0.15s; flex-shrink: 0; line-height: 1;
2882
- }
2883
- .close-btn:hover { background: var(--sfx-up-border, #e4e4e4); color: var(--sfx-up-text, #333); }
2884
-
2885
- .body { padding: 18px 20px 20px; display: flex; flex-direction: column; align-items: center; gap: 16px; }
2886
-
2887
- video {
2888
- width: 100%; max-height: 320px; border-radius: 12px;
2889
- background: #000; object-fit: contain;
2890
- }
2891
-
2892
- .error { font-size: 13px; color: var(--sfx-up-error, #dc2626); text-align: center; padding: 40px 20px; }
2893
-
2894
- .status {
2895
- font-size: 13px; color: var(--sfx-up-text-secondary, #475569);
2896
- display: flex; align-items: center; gap: 8px;
2897
- }
2898
-
2899
- .rec-dot {
2900
- width: 10px; height: 10px; border-radius: 50%;
2901
- background: var(--sfx-up-error, #dc2626); animation: pulse 1s ease-in-out infinite;
2902
- }
2903
-
2904
- .actions { display: flex; gap: 8px; justify-content: center; width: 100%; }
2905
-
2906
- .btn-danger {
2907
- background: var(--sfx-up-error, #dc2626); color: var(--primary-foreground, #fff);
2908
- box-shadow: 0 2px 10px var(--sfx-up-shadow, rgba(220, 38, 38, 0.28));
2909
- }
2910
- .btn-danger:hover { background: var(--destructive-foreground, #b91c1c); }
2911
-
2912
- .start-view {
2913
- display: flex; flex-direction: column; align-items: center; gap: 16px;
2914
- padding: 30px 20px; text-align: center;
2915
- }
2916
-
2917
- .start-icon {
2918
- width: 56px; height: 56px; border-radius: 16px;
2919
- background: var(--sfx-up-primary-bg, #eff6ff);
2920
- color: var(--sfx-up-primary, #2563eb);
2921
- display: flex; align-items: center; justify-content: center;
2922
- }
2923
-
2924
- .start-icon svg { width: 28px; height: 28px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
2925
-
2926
- .start-text {
2927
- font-size: 14px; color: var(--sfx-up-text-secondary, #475569); max-width: 300px;
2928
- }
2929
-
2930
- .close-btn:focus-visible {
2931
- outline: 2px solid var(--sfx-up-primary, #2563eb);
2932
- outline-offset: 2px;
2933
- }
2934
-
2935
- @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
2936
- @keyframes slideUp { from { transform: translateY(18px) scale(0.97); } to { transform: translateY(0) scale(1); } }
2937
- @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.3; } }
2938
- `];let j=ve;G([c.state()],j.prototype,"_stream");G([c.state()],j.prototype,"_recording");G([c.state()],j.prototype,"_error");G([c.state()],j.prototype,"_recordedBlob");G([c.state()],j.prototype,"_previewUrl");var ht=Object.defineProperty,k=(n,e,t,o)=>{for(var r=void 0,i=n.length-1,a;i>=0;i--)(a=n[i])&&(r=a(e,t,r)||r);return r&&ht(e,t,r),r};const $e=new Set(["unsplash"]);var $;const y=($=class extends s.LitElement{constructor(){super(),this.config=null,this._isOpen=!1,this._activeConnector=null,this._showUrlDialog=!1,this._showCameraDialog=!1,this._showScreenCastDialog=!1,this._previewFileId=null,this._previewDims="—",this._splitPct=68,this._isResizing=!1,this._splitRafId=0,this._fullscreenPreviewUrl=null,this._fullscreenVideoFile=null,this._fullscreenZoomed=!1,this._fsPanX=0,this._fsPanY=0,this._fsDragging=!1,this._fsDragStartX=0,this._fsDragStartY=0,this._fsPanStartX=0,this._fsPanStartY=0,this._bodyDragOver=!1,this._isMinimized=!1,this._isPillExpanded=!1,this._bodyDragCounter=0,this._videoBlobUrls=new Map,this._engine=null,this._cachedSources=A,this._cachedSourcesConfig=void 0,this._rejectedTimers=new Map,this._closeOnCompleteTimer=null,this._apiBase=null,this._authHeaders=null,this._authResolveId=0,this._prevStoreState=null,this._unsubStoreEvents=null,this._portalContainer=null,this._onFilesSelected=e=>{this._processIncomingFiles(e.detail.files)},this._onDropTileSourceClick=e=>{this._handleSourceActivation(e.detail.source.id)},this._onSourceClick=async e=>{this._handleSourceActivation(e.detail.source)},this._handleSourceActivation=async e=>{var r,i;const t=this._mergedSources.find(a=>a.id===e);if(t!=null&&t.onActivate){try{t.onActivate(this)}catch(a){console.error(`[sfx-uploader] onActivate for custom source "${e}" threw:`,a)}return}if(e==="device"){const a=this.shadowRoot.querySelector("sfx-drop-zone");a==null||a.browse();return}if(e==="url"){this._showUrlDialog=!0;return}if(e==="camera"){this._showCameraDialog=!0;return}if(e==="screen-cast"){this._showScreenCastDialog=!0;return}if((((i=(r=this.config)==null?void 0:r.connectors)==null?void 0:i.providers)??[]).includes(e)){if($e.has(e)){if(!customElements.get("sfx-search-provider-browser")){const{SfxSearchProviderBrowser:l}=await Promise.resolve().then(()=>require("./search-provider-browser-DqKnNu87.cjs"));customElements.define("sfx-search-provider-browser",l)}}else if(!customElements.get("sfx-provider-browser")){const{SfxProviderBrowser:l}=await Promise.resolve().then(()=>require("./provider-browser-B85iISh9.cjs"));customElements.define("sfx-provider-browser",l)}this._activeConnector=e}},this._onUrlSubmit=e=>{var h,u,x;this._showUrlDialog=!1;const{url:t,name:o}=e.detail,r=(h=this.config)==null?void 0:h.callbacks,i=We(o),a=i.startsWith("image/"),l=this._store.getState(),d=ie({name:o,size:0,type:i},l.restrictions,l.files);if(d){const f={id:T(),status:"rejected",file:null,remoteUrl:t,name:o,size:0,type:i,previewUrl:null,duration:null,progress:0,speed:0,bytesUploaded:0,error:d,retryCount:0,response:null,addedAt:Date.now(),meta:{},tags:[],remoteInfo:null};L(this._store,f),this._dispatchPublic(g.FILE_REJECTED,{file:f,reason:d}),(u=r==null?void 0:r.onFileRejected)==null||u.call(r,f,d);return}const p={id:T(),status:"idle",file:null,remoteUrl:t,name:o,size:0,type:i,previewUrl:a?t:null,duration:null,progress:0,speed:0,bytesUploaded:0,error:null,retryCount:0,response:null,addedAt:Date.now(),meta:{},tags:[],remoteInfo:null};L(this._store,p),this._dispatchPublic(g.FILE_ADDED,{file:p}),(x=r==null?void 0:r.onFileAdded)==null||x.call(r,p),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=>{this._removeFile(e.detail.fileId)},this._onFilePreview=e=>{var o,r,i;const t=this._store.getState().files.get(e.detail.fileId);t&&(this._previewFileId=t.id,this._dispatchPublic(g.FILE_PREVIEW,{file:t}),(i=(r=(o=this.config)==null?void 0:o.callbacks)==null?void 0:r.onFilePreview)==null||i.call(r,t))},this._onFillMetadata=()=>{var t,o,r;const e=[...this._store.getState().files.values()].filter(i=>$._MODIFIABLE_STATUSES.has(i.status));this._dispatchPublic(g.FILL_METADATA,{files:e}),(r=(o=(t=this.config)==null?void 0:t.callbacks)==null?void 0:o.onFillMetadata)==null||r.call(o,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 o,r,i;const e=(o=this.config)==null?void 0:o.callbacks;this._closeOnCompleteTimer&&(clearTimeout(this._closeOnCompleteTimer),this._closeOnCompleteTimer=null),(r=this._engine)==null||r.cancelAll();const t=[...this._store.getState().files.values()];for(const a of t)a.previewUrl&&URL.revokeObjectURL(a.previewUrl),this._dispatchPublic(g.FILE_REMOVED,{file:a}),(i=e==null?void 0:e.onFileRemoved)==null||i.call(e,a);this._revokeVideoBlobUrls();for(const a of this._rejectedTimers.values())clearTimeout(a);this._rejectedTimers.clear(),this._dimCache.clear(),this._previewFileId=null,this._fullscreenPreviewUrl=null,this._fullscreenVideoFile=null,this._store.setState({files:new Map,isUploading:!1,totalProgress:0,totalSpeed:0,totalBytesUploaded:0,totalBytes:0})},this._onAddMore=()=>{var r;const e=this.shadowRoot.querySelector("sfx-drop-zone");if(e){e.browse();return}const t=this.shadowRoot.querySelector("sfx-file-list"),o=(r=t==null?void 0:t.shadowRoot)==null?void 0:r.querySelector('input[type="file"]');o==null||o.click()},this._onUploadStart=()=>{var e;if(this._phase==="complete"){((e=this.config)==null?void 0:e.clearOnComplete)!==!1&&this._onClearAll();return}this.upload()},this._onUploadMore=()=>{this._onClearAll()},this._onConnectorFilesSelected=e=>{var o,r,i;const t=(o=this.config)==null?void 0:o.callbacks;for(const a of e.detail.files){const l=this._store.getState(),d=ie({name:a.name,size:a.size,type:a.mimeType},l.restrictions,l.files);if(d){const h={id:T(),status:"rejected",file:null,remoteUrl:null,name:a.name,size:a.size,type:a.mimeType,previewUrl:a.thumbnail,duration:null,progress:0,speed:0,bytesUploaded:0,error:d,retryCount:0,response:null,addedAt:Date.now(),meta:{},tags:[],remoteInfo:a};L(this._store,h),this._dispatchPublic(g.FILE_REJECTED,{file:h,reason:d}),(r=t==null?void 0:t.onFileRejected)==null||r.call(t,h,d);continue}const p={id:T(),status:"idle",file:null,remoteUrl:null,name:a.name,size:a.size,type:a.mimeType,previewUrl:a.thumbnail,duration:null,progress:0,speed:0,bytesUploaded:0,error:null,retryCount:0,response:null,addedAt:Date.now(),meta:{},tags:[],remoteInfo:a};L(this._store,p),this._dispatchPublic(g.FILE_ADDED,{file:p}),(i=t==null?void 0:t.onFileAdded)==null||i.call(t,p)}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,t,o,r,i;this._dispatchPublic(g.COMPLETE_ACTION,{}),(o=(t=(e=this.config)==null?void 0:e.callbacks)==null?void 0:t.onCompleteAction)==null||o.call(t),((r=this.config)==null?void 0:r.mode)==="modal"?this.close():((i=this.config)==null?void 0:i.clearOnComplete)!==!1&&this._onClearAll()},this._onInlineDismiss=()=>{var e,t,o;(o=(t=(e=this.config)==null?void 0:e.callbacks)==null?void 0:t.onCancel)==null||o.call(t),this._dispatchPublic(g.CANCEL,{})},this._onSuccessCardClose=()=>{var e,t,o,r;((e=this.config)==null?void 0:e.mode)==="inline"?(this._dispatchPublic(g.COMPLETE_ACTION,{}),(r=(o=(t=this.config)==null?void 0:t.callbacks)==null?void 0:o.onCompleteAction)==null||r.call(o),this._onClearAll()):this._onModalDismiss()},this._onModalDismiss=()=>{var e,t,o,r;this._phase==="uploading"&&((e=this._engine)==null||e.cancelAll()),(r=(o=(t=this.config)==null?void 0:t.callbacks)==null?void 0:o.onCancel)==null||r.call(o),this._dispatchPublic(g.CANCEL,{}),this.close()},this._onMinimize=()=>{this._isMinimized=!0,this._isPillExpanded=!0,this.requestUpdate()},this._onPillClick=()=>{this._isPillExpanded=!this._isPillExpanded,this.requestUpdate()},this._onPillExpand=()=>{this._isMinimized=!1,this._isPillExpanded=!1,this._isOpen=!0,this.requestUpdate()},this._onPillDismiss=()=>{var e,t,o,r;this._isMinimized=!1,this._isPillExpanded=!1,this._phase==="uploading"&&((e=this._engine)==null||e.cancelAll()),(r=(o=(t=this.config)==null?void 0:t.callbacks)==null?void 0:o.onCancel)==null||r.call(o),this._dispatchPublic(g.CANCEL,{}),this.close()},this._onModalBackdropClick=e=>{e.target===e.currentTarget&&this._onModalDismiss()},this._onBodyDragEnter=e=>{e.preventDefault(),this._bodyDragCounter++,this._bodyDragCounter===1&&(this._bodyDragOver=!0)},this._onBodyDragOver=e=>{e.preventDefault()},this._onBodyDragLeave=e=>{e.preventDefault(),this._bodyDragCounter--,this._bodyDragCounter<=0&&(this._bodyDragCounter=0,this._bodyDragOver=!1)},this._onBodyDrop=e=>{var o;e.preventDefault(),this._bodyDragCounter=0,this._bodyDragOver=!1;const t=Array.from(((o=e.dataTransfer)==null?void 0:o.files)??[]);t.length>0&&this._onFilesSelected(new CustomEvent("files-selected",{detail:{files:t}}))},this._onKeyDown=e=>{var t,o;if(e.key==="Escape"){if(this._fullscreenPreviewUrl||this._fullscreenVideoFile){this._onFsClose();return}this._isOpen&&((t=this.config)==null?void 0:t.mode)==="modal"&&(((o=this.config)==null?void 0:o.headerButton)??"close")!=="none"&&this._onModalDismiss()}},this._dimCache=new Map,this._onSplitPointerDown=e=>{var o;e.preventDefault(),this._isResizing=!0;const t=(o=this.shadowRoot)==null?void 0:o.querySelector(".preview-layout");t==null||t.classList.add("resizing"),e.target.setPointerCapture(e.pointerId)},this._onSplitPointerMove=e=>{if(!this._isResizing||this._splitRafId)return;const t=e.clientX;this._splitRafId=requestAnimationFrame(()=>{var a;this._splitRafId=0;const o=(a=this.shadowRoot)==null?void 0:a.querySelector(".preview-layout");if(!o)return;const r=o.getBoundingClientRect(),i=(t-r.left)/r.width*100;this._splitPct=Math.max(25,Math.min(75,i))})},this._onSplitPointerUp=()=>{var t;this._isResizing=!1,this._splitRafId&&(cancelAnimationFrame(this._splitRafId),this._splitRafId=0);const e=(t=this.shadowRoot)==null?void 0:t.querySelector(".preview-layout");e==null||e.classList.remove("resizing")},this._onFsToggleZoom=e=>{e==null||e.stopPropagation(),this._fullscreenZoomed=!this._fullscreenZoomed,this._fullscreenZoomed||(this._fsPanX=0,this._fsPanY=0)},this._onFsOverlayClick=e=>{this._fsDragDidMove||this._onFsToggleZoom(e)},this._fsDragDidMove=!1,this._onFsPanStart=e=>{this._fullscreenZoomed&&(this._fsDragging=!0,this._fsDragDidMove=!1,this._fsDragStartX=e.clientX,this._fsDragStartY=e.clientY,this._fsPanStartX=this._fsPanX,this._fsPanStartY=this._fsPanY,e.preventDefault())},this._onFsPanMove=e=>{if(!this._fsDragging)return;const t=e.clientX-this._fsDragStartX,o=e.clientY-this._fsDragStartY;(Math.abs(t)>3||Math.abs(o)>3)&&(this._fsDragDidMove=!0),this._fsPanX=this._fsPanStartX+t,this._fsPanY=this._fsPanStartY+o,this.requestUpdate()},this._onFsPanEnd=()=>{this._fsDragging=!1,requestAnimationFrame(()=>{this._fsDragDidMove=!1})},this._onFsTouchStart=e=>{if(!this._fullscreenZoomed||e.touches.length!==1)return;const t=e.touches[0];this._fsDragging=!0,this._fsDragDidMove=!1,this._fsDragStartX=t.clientX,this._fsDragStartY=t.clientY,this._fsPanStartX=this._fsPanX,this._fsPanStartY=this._fsPanY},this._onFsTouchMove=e=>{if(!this._fsDragging||e.touches.length!==1)return;const t=e.touches[0],o=t.clientX-this._fsDragStartX,r=t.clientY-this._fsDragStartY;(Math.abs(o)>3||Math.abs(r)>3)&&(this._fsDragDidMove=!0),this._fsPanX=this._fsPanStartX+o,this._fsPanY=this._fsPanStartY+r,this.requestUpdate(),e.preventDefault()},this._onFsClose=e=>{e==null||e.stopPropagation(),this._fullscreenPreviewUrl=null,this._fullscreenVideoFile=null,this._fullscreenZoomed=!1,this._fsPanX=0,this._fsPanY=0},this._store=Ee(),this._storeCtrl=new je(this,this._store)}open(){var e,t,o;this._isMinimized&&(this._isMinimized=!1,this._isPillExpanded=!1),!this._isOpen&&(this._isOpen=!0,(o=(t=(e=this.config)==null?void 0:e.callbacks)==null?void 0:t.onOpen)==null||o.call(t),this._dispatchPublic(g.OPEN,{}),this.requestUpdate())}close(){var e,t,o,r;this._isOpen&&(this._isOpen=!1,this._closeOnCompleteTimer&&(clearTimeout(this._closeOnCompleteTimer),this._closeOnCompleteTimer=null),((e=this.config)==null?void 0:e.clearOnClose)!==!1&&this._onClearAll(),this._previewFileId=null,(r=(o=(t=this.config)==null?void 0:t.callbacks)==null?void 0:o.onClose)==null||r.call(o),this._dispatchPublic(g.CLOSE,{}),this.requestUpdate())}upload(){var r,i,a,l,d,p,h;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((i=(r=this.config)==null?void 0:r.callbacks)!=null&&i.onBeforeUpload&&this.config.callbacks.onBeforeUpload(e)===!1)return;const t=new CustomEvent(g.BEFORE_UPLOAD,{bubbles:!0,composed:!0,cancelable:!0,detail:{files:e}});this.dispatchEvent(t)&&(this._dispatchPublic(g.UPLOAD_STARTED,{files:e}),(d=(l=(a=this.config)==null?void 0:a.callbacks)==null?void 0:l.onUploadStarted)==null||d.call(l,e),this._engine.uploadAll(),(p=this.config)!=null&&p.minimizeOnUpload&&((h=this.config)==null?void 0:h.mode)!=="inline"&&(this._isMinimized=!0,this._isPillExpanded=!0,this.requestUpdate()))}addFiles(e){this._processIncomingFiles(e)}resumeUpload(e){var t;if(e&&e.length>0){const o=this._store.getState().files,r=new Map(o);let i=!1;for(const a of e){const l=o.get(a.id);l&&(r.set(a.id,{...l,...a}),i=!0)}i&&this._store.setState({files:r})}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,o){const r=this._store.getState().files,i=r.get(e);if(!i||!$._MODIFIABLE_STATUSES.has(i.status))return;const a=new Map(r);a.set(e,{...i,meta:t!=null?{...i.meta,...t}:i.meta,tags:o??i.tags}),this._store.setState({files:a})}updateFilesMeta(e){const t=this._store.getState().files,o=new Map(t);let r=!1;for(const{fileId:i,meta:a,tags:l}of e){const d=t.get(i);!d||!$._MODIFIABLE_STATUSES.has(d.status)||(o.set(i,{...d,meta:a!=null?{...d.meta,...a}:d.meta,tags:l??d.tags}),r=!0)}r&&this._store.setState({files:o})}updated(e){if(e.has("config")&&this.config&&this._applyConfig(this.config),e.has("_previewFileId")&&this._previewFileId){const t=this._previewFileId,o=this._store.getState().files.get(t);o?this._getImageDimensions(o).then(r=>{this._previewFileId===t&&(this._previewDims=r?`${r.w} × ${r.h}`:"—")}):this._previewDims="—"}this._updateFloatingPortal()}_injectFloatStyles(){if(document.querySelector("style[data-sfx-upload-float-styles]"))return;const e=document.createElement("style");e.setAttribute("data-sfx-upload-float-styles",""),e.textContent=`
2939
- [data-sfx-upload-float] .upload-float { position:fixed; bottom:24px; right:24px; z-index:10000; width:470px; border-radius:12px; background:#fff; box-shadow:0 8px 32px rgba(0,0,0,0.12),0 2px 8px rgba(0,0,0,0.06); overflow:hidden; font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif; animation:sfxFloatIn .3s ease both; }
2940
- [data-sfx-upload-float] .float-header { display:flex; align-items:center; justify-content:space-between; padding:10px 14px; border-bottom:1px solid #e8edf5; }
2941
- [data-sfx-upload-float] .float-header-left { display:flex; align-items:center; gap:8px; }
2942
- [data-sfx-upload-float] .float-icon { width:28px; height:28px; border-radius:6px; background:#eff6ff; color:#2563eb; display:flex; align-items:center; justify-content:center; flex-shrink:0; }
2943
- [data-sfx-upload-float] .float-icon svg { width:14px; height:14px; }
2944
- [data-sfx-upload-float] .float-icon.done { background:#f0fdf4; color:#22c55e; }
2945
- [data-sfx-upload-float] .float-icon.warn { background:#fffbeb; color:#f59e0b; }
2946
- [data-sfx-upload-float] .float-icon.error { background:#fef2f2; color:#ef4444; }
2947
- [data-sfx-upload-float] .float-title { font-size:13px; font-weight:600; color:#1e293b; }
2948
- [data-sfx-upload-float] .float-subtitle { font-size:11px; color:#94a3b8; }
2949
- [data-sfx-upload-float] .float-actions { display:flex; gap:4px; }
2950
- [data-sfx-upload-float] .float-actions button { width:26px; height:26px; border:none; background:none; cursor:pointer; border-radius:6px; display:flex; align-items:center; justify-content:center; color:#94a3b8; transition:background .15s; padding:0; }
2951
- [data-sfx-upload-float] .float-actions button:hover { background:#f8fafc; color:#374151; }
2952
- [data-sfx-upload-float] .float-actions button svg { width:14px; height:14px; }
2953
- [data-sfx-upload-float] .float-progress { padding:10px 14px; border-bottom:1px solid #e8edf5; }
2954
- [data-sfx-upload-float] .float-progress-top { display:flex; align-items:center; justify-content:space-between; margin-bottom:6px; }
2955
- [data-sfx-upload-float] .float-progress-label { font-size:12px; color:#475569; }
2956
- [data-sfx-upload-float] .float-progress-pct { font-size:12px; font-weight:600; color:#2563eb; }
2957
- [data-sfx-upload-float] .float-progress-pct.done { color:#22c55e; }
2958
- [data-sfx-upload-float] .float-progress-pct.warn { color:#f59e0b; }
2959
- [data-sfx-upload-float] .float-progress-pct.error { color:#ef4444; }
2960
- [data-sfx-upload-float] .float-bar { height:4px; background:#e8edf5; border-radius:2px; overflow:hidden; }
2961
- [data-sfx-upload-float] .float-bar-fill { height:100%; background:#2563eb; border-radius:2px; transition:width .3s ease; }
2962
- [data-sfx-upload-float] .float-bar-fill.done { background:#22c55e; }
2963
- [data-sfx-upload-float] .float-bar-fill.warn { background:#f59e0b; }
2964
- [data-sfx-upload-float] .float-bar-fill.error { background:#ef4444; }
2965
- [data-sfx-upload-float] .float-items { max-height:200px; overflow-y:auto; }
2966
- [data-sfx-upload-float] .float-item { display:flex; align-items:center; gap:10px; padding:8px 14px; border-bottom:1px solid #f1f5f9; overflow:hidden; }
2967
- [data-sfx-upload-float] .float-item:last-child { border-bottom:none; }
2968
- [data-sfx-upload-float] .float-item-thumb { width:32px; height:32px; border-radius:6px; background:#f8fafc; display:flex; align-items:center; justify-content:center; color:#94a3b8; flex-shrink:0; }
2969
- [data-sfx-upload-float] .float-item-thumb svg { width:16px; height:16px; }
2970
- [data-sfx-upload-float] .float-item-info { flex:1; min-width:0; overflow:hidden; }
2971
- [data-sfx-upload-float] .float-item-name { font-size:12px; font-weight:500; color:#1e293b; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
2972
- [data-sfx-upload-float] .float-item-size { font-size:11px; color:#94a3b8; }
2973
- [data-sfx-upload-float] .float-item-done { width:18px; height:18px; border-radius:50%; background:#f0fdf4; color:#22c55e; display:flex; align-items:center; justify-content:center; flex-shrink:0; }
2974
- [data-sfx-upload-float] .float-item-done svg { width:12px; height:12px; }
2975
- [data-sfx-upload-float] .float-item-spinner { width:16px; height:16px; border:2px solid #e8edf5; border-top-color:#2563eb; border-radius:50%; animation:sfxSpin .8s linear infinite; flex-shrink:0; }
2976
- [data-sfx-upload-float] .float-item-status { display:flex; flex-direction:row; align-items:center; gap:4px; flex-shrink:0; }
2977
- [data-sfx-upload-float] .float-item-error-wrap { position:relative; display:flex; align-items:center; flex-shrink:0; }
2978
- [data-sfx-upload-float] .float-item-error-icon { width:16px; height:16px; color:#ef4444; flex-shrink:0; cursor:pointer; }
2979
- [data-sfx-upload-float] .float-item-tooltip { display:none; position:absolute; right:calc(100% + 8px); top:50%; transform:translateY(-50%); background:#fff; color:#1e293b; font-size:11px; padding:6px 10px; border-radius:6px; white-space:nowrap; pointer-events:none; z-index:10; box-shadow:0 2px 12px rgba(0,0,0,0.12),0 1px 4px rgba(0,0,0,0.08); }
2980
- [data-sfx-upload-float] .float-item-error-wrap:hover .float-item-tooltip { display:block; }
2981
- [data-sfx-upload-float] .float-item-retry { width:24px; height:24px; border:none; background:none; color:#2563eb; cursor:pointer; padding:4px; flex-shrink:0; display:flex; align-items:center; justify-content:center; border-radius:4px; }
2982
- [data-sfx-upload-float] .float-item-retry svg { width:14px; height:14px; }
2983
- [data-sfx-upload-float] .float-item-retry:hover { background:#f1f5f9; color:#1d4ed8; }
2984
- [data-sfx-upload-float] .float-collapsed { display:flex; align-items:center; justify-content:space-between; padding:10px 14px; width:470px; border-radius:12px; }
2985
- [data-sfx-upload-float] .float-collapsed-left { display:flex; align-items:center; gap:8px; }
2986
- [data-sfx-upload-float] .float-collapsed-spinner { width:18px; height:18px; border:2.5px solid #e8edf5; border-top-color:#2563eb; border-radius:50%; animation:sfxSpin .8s linear infinite; flex-shrink:0; }
2987
- [data-sfx-upload-float] .float-collapsed-icon { width:18px; height:18px; flex-shrink:0; }
2988
- [data-sfx-upload-float] .float-collapsed-icon svg { width:18px; height:18px; }
2989
- [data-sfx-upload-float] .float-collapsed-icon.done { color:#22c55e; }
2990
- [data-sfx-upload-float] .float-collapsed-icon.warn { color:#f59e0b; }
2991
- [data-sfx-upload-float] .float-collapsed-icon.error { color:#ef4444; }
2992
- [data-sfx-upload-float] .float-collapsed-text { font-size:13px; font-weight:500; color:#1e293b; white-space:nowrap; }
2993
- [data-sfx-upload-float] .float-collapsed-pct { font-size:13px; font-weight:600; color:#2563eb; }
2994
- [data-sfx-upload-float] .float-collapsed-actions { display:flex; gap:4px; }
2995
- [data-sfx-upload-float] .float-collapsed-actions button { width:26px; height:26px; border:none; background:none; cursor:pointer; border-radius:6px; display:flex; align-items:center; justify-content:center; color:#94a3b8; transition:background .15s; padding:0; }
2996
- [data-sfx-upload-float] .float-collapsed-actions button:hover { background:#f1f5f9; color:#374151; }
2997
- [data-sfx-upload-float] .float-collapsed-actions button svg { width:14px; height:14px; }
2998
- @keyframes sfxFloatIn { from{opacity:0;transform:translateY(20px)} to{opacity:1;transform:translateY(0)} }
2999
- @keyframes sfxSpin { to{transform:rotate(360deg)} }
3000
- `,document.head.appendChild(e)}_updateFloatingPortal(){const e=[...this._storeCtrl.state.files.values()];this._isMinimized&&e.length>0?(this._injectFloatStyles(),this._portalContainer||(this._portalContainer=document.createElement("div"),this._portalContainer.setAttribute("data-sfx-upload-float",""),document.body.appendChild(this._portalContainer)),s.render(this._renderFloatingPill(e),this._portalContainer)):this._portalContainer&&(s.render(s.nothing,this._portalContainer),this._portalContainer.remove(),this._portalContainer=null)}connectedCallback(){super.connectedCallback(),document.addEventListener("keydown",this._onKeyDown),this._prevStoreState=this._store.getState(),this._unsubStoreEvents=this._store.subscribe(()=>this._onStoreChange())}disconnectedCallback(){var e,t,o,r;super.disconnectedCallback(),document.removeEventListener("keydown",this._onKeyDown),(e=this._unsubStoreEvents)==null||e.call(this),this._unsubStoreEvents=null,this._prevStoreState=null,(t=this._portalContainer)==null||t.remove(),this._portalContainer=null,document.querySelector("[data-sfx-upload-float]")||(o=document.querySelector("style[data-sfx-upload-float-styles]"))==null||o.remove(),this._revokeVideoBlobUrls();for(const i of this._rejectedTimers.values())clearTimeout(i);this._rejectedTimers.clear(),this._closeOnCompleteTimer&&(clearTimeout(this._closeOnCompleteTimer),this._closeOnCompleteTimer=null);for(const i of this._store.getState().files.values())i.previewUrl&&URL.revokeObjectURL(i.previewUrl);(r=this._engine)==null||r.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!=null){const o=this._store.getState().queueConfig;t.queueConfig={...o,concurrency:e.concurrency}}if(e.autoProceed!=null){const o=t.queueConfig??this._store.getState().queueConfig;t.queueConfig={...o,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){var r,i;const t=e.auth;if(t.mode==="sass-key"){this._apiBase=te(t.container),this._authHeaders=K(t),this._ensureEngine(),(r=this._engine)==null||r.updateConfig({apiBase:this._apiBase,authHeaders:this._authHeaders});return}const o=++this._authResolveId;try{const a=await ze(t);if(o!==this._authResolveId)return;this._apiBase=a.apiBase,this._authHeaders=a.headers,this._ensureEngine(),(i=this._engine)==null||i.updateConfig({apiBase:this._apiBase,authHeaders:this._authHeaders})}catch(a){if(o!==this._authResolveId)return;console.error("[sfx-uploader] Auth resolution failed:",a)}}_ensureEngine(){!this._engine&&this._apiBase&&this._authHeaders&&(this._engine=new Pe(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 r,i,a,l,d,p,h,u;const e=this._store.getState(),t=this._prevStoreState;if(this._prevStoreState=e,!t)return;const o=(r=this.config)==null?void 0:r.callbacks;for(const[x,f]of e.files){const v=t.files.get(x);if(v){if(v.status!==f.status)switch(f.status){case"uploading":break;case"complete":f.response&&(this._dispatchPublic(g.UPLOAD_COMPLETE,{file:f,response:f.response}),(i=o==null?void 0:o.onUploadComplete)==null||i.call(o,f,f.response));break;case"error":case"failed":{const w=new Error(f.error??"Upload failed");this._dispatchPublic(g.UPLOAD_ERROR,{file:f,error:w}),(a=o==null?void 0:o.onUploadError)==null||a.call(o,f,w);break}case"retrying":this._dispatchPublic(g.UPLOAD_RETRY,{file:f,attempt:f.retryCount}),(l=o==null?void 0:o.onUploadRetry)==null||l.call(o,f,f.retryCount);break}f.status==="uploading"&&v.progress!==f.progress&&(this._dispatchPublic(g.UPLOAD_PROGRESS,{file:f,progress:f.progress,speed:f.speed}),(d=o==null?void 0:o.onUploadProgress)==null||d.call(o,f,f.progress,f.speed))}}if(e.totalProgress!==t.totalProgress||e.totalSpeed!==t.totalSpeed){const x=e.totalSpeed>0?(e.totalBytes-e.totalBytesUploaded)/e.totalSpeed:0;this._dispatchPublic(g.TOTAL_PROGRESS,{percentage:e.totalProgress,speed:e.totalSpeed,eta:x}),(p=o==null?void 0:o.onTotalProgress)==null||p.call(o,e.totalProgress,e.totalSpeed,x)}if(t.isUploading&&!e.isUploading){const x=[...e.files.values()];if(!x.some(v=>v.status==="cancelled")){const v=x.filter(m=>m.status==="complete"),w=x.filter(m=>m.status==="failed"||m.status==="error");this._dispatchPublic(g.ALL_COMPLETE,{successful:v,failed:w}),(h=o==null?void 0:o.onAllComplete)==null||h.call(o,v,w);const b=(u=this.config)==null?void 0:u.closeOnComplete;if(b){const m=typeof b=="number"?b:1500;this._closeOnCompleteTimer=setTimeout(()=>{var _,E,be;this._closeOnCompleteTimer=null,this._phase==="complete"&&(this._dispatchPublic(g.COMPLETE_ACTION,{}),(be=(E=(_=this.config)==null?void 0:_.callbacks)==null?void 0:E.onCompleteAction)==null||be.call(E),this.close())},m)}}}}get _mergedSources(){var d;const e=(d=this.config)==null?void 0:d.connectors;if(e===this._cachedSourcesConfig)return this._cachedSources;if(this._cachedSourcesConfig=e,!e)return this._cachedSources=A,this._cachedSources;const t=e.providers.length>0?De(e.providers):[],o=e.customSources??[],r=A.filter(p=>p.id==="device"||p.id==="url"),i=A.filter(p=>p.id!=="device"&&p.id!=="url"),a=new Set,l=[];for(const p of[...r,...t,...i,...o])if(!a.has(p.id)){if($._RESERVED_IDS.has(p.id)&&p.onActivate){console.warn(`[sfx-uploader] Custom source id "${p.id}" conflicts with a built-in source and was skipped.`);continue}a.add(p.id),l.push(p)}return this._cachedSources=l,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 o=new Set(["complete","rejected","cancelled","failed"]);return t.every(r=>o.has(r.status))&&t.some(r=>r.status==="complete"||r.status==="failed")?"complete":"ready"}_processIncomingFiles(e){var o,r,i,a;const t=(o=this.config)==null?void 0:o.callbacks;for(const l of e){const d=this._store.getState(),p=Ke(l,d.restrictions,d.files);if(p){const x=l.type.startsWith("image/")?URL.createObjectURL(l):null,f={id:T(),status:"rejected",file:l,remoteUrl:null,name:l.name,size:l.size,type:l.type,previewUrl:x,duration:null,progress:0,speed:0,bytesUploaded:0,error:p,retryCount:0,response:null,addedAt:Date.now(),meta:{},tags:[],remoteInfo:null};L(this._store,f),this._dispatchPublic(g.FILE_REJECTED,{file:f,reason:p}),(r=t==null?void 0:t.onFileRejected)==null||r.call(t,f,p);const v=(i=this.config)==null?void 0:i.rejectedFileAutoRemoveDelay,w=v===!1||v===0||v===void 0?0:v;if(w>0){const b=f.id,m=setTimeout(()=>{this._rejectedTimers.delete(b);const _=this._store.getState().files.get(b);_&&_.status==="rejected"&&me(this._store,b)},w);this._rejectedTimers.set(b,m)}continue}let h=null;l.type.startsWith("image/")&&(h=URL.createObjectURL(l));const u={id:T(),status:"idle",file:l,remoteUrl:null,name:l.name,size:l.size,type:l.type,previewUrl:h,duration:null,progress:0,speed:0,bytesUploaded:0,error:null,retryCount:0,response:null,addedAt:Date.now(),meta:{},tags:[],remoteInfo:null};if(L(this._store,u),this._dispatchPublic(g.FILE_ADDED,{file:u}),(a=t==null?void 0:t.onFileAdded)==null||a.call(t,u),l.type.startsWith("video/")){Ge(l).then(f=>{if(!f)return;const v=this._store.getState(),w=v.files.get(u.id);if(w){const b=new Map(v.files);b.set(u.id,{...w,previewUrl:f}),this._store.setState({files:b})}else URL.revokeObjectURL(f)});const x=document.createElement("video");x.preload="metadata",x.src=URL.createObjectURL(l),x.onerror=()=>{URL.revokeObjectURL(x.src)},x.onloadedmetadata=()=>{const f=x.duration;if(URL.revokeObjectURL(x.src),!isFinite(f))return;const v=this._store.getState(),w=v.files.get(u.id);if(w){const b=new Map(v.files);b.set(u.id,{...w,duration:f}),this._store.setState({files:b})}}}}this._store.getState().queueConfig.autoProceed&&this.upload()}_removeFile(e){var i,a,l,d;const t=this._store.getState().files.get(e);if(!t)return;const o={...t};if((this._fullscreenPreviewUrl&&this._fullscreenPreviewUrl===t.previewUrl||this._fullscreenVideoFile&&this._fullscreenVideoFile===t.file)&&(this._fullscreenPreviewUrl=null,this._fullscreenVideoFile=null),t.previewUrl&&URL.revokeObjectURL(t.previewUrl),t.file){const p=this._videoBlobUrls.get(t.file);p&&(URL.revokeObjectURL(p),this._videoBlobUrls.delete(t.file))}(t.status==="uploading"||t.status==="queued"||t.status==="retrying")&&((i=this._engine)==null||i.cancelFile(e)),me(this._store,e),this._dimCache.delete(e);const r=this._rejectedTimers.get(e);if(r&&(clearTimeout(r),this._rejectedTimers.delete(e)),this._previewFileId===e){const p=[...this._store.getState().files.values()];this._previewFileId=p.length>0?p[0].id:null}this._dispatchPublic(g.FILE_REMOVED,{file:o}),(d=(l=(a=this.config)==null?void 0:a.callbacks)==null?void 0:l.onFileRemoved)==null||d.call(l,o)}render(){var t;const e=((t=this.config)==null?void 0:t.mode)??"modal";return[...this._storeCtrl.state.files.values()],e==="modal"?s.html`
3001
- ${this._isOpen&&!this._isMinimized?s.html`
3002
- <div class="modal-backdrop" @click=${this._onModalBackdropClick}>
3003
- <div class="modal-card">
3004
- ${this._renderHeader()}
3005
- ${this._renderBody()}
3006
- </div>
3007
- </div>
3008
- `:s.nothing}
3009
- `:s.html`
3010
- <div class="inline">
3011
- ${this._renderHeader()}
3012
- ${this._renderBody()}
3013
- </div>
3014
- `}_renderHeader(){var a,l;if(this._phase==="complete")return s.nothing;if(this._phase==="uploading"){const d=this._storeCtrl.state,p=[...d.files.values()],h=p.filter(x=>x.status==="complete").length,u=d.totalSpeed>0?(d.totalBytes-d.totalBytesUploaded)/d.totalSpeed:0;return s.html`
3015
- <div class="header upload-header">
3016
- <div class="float-header-left">
3017
- <div class="float-icon">
3018
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"><polyline points="16 16 12 12 8 16"/><line x1="12" y1="12" x2="12" y2="21"/><path d="M20.39 18.39A5 5 0 0018 9h-1.26A8 8 0 103 16.3"/></svg>
3019
- </div>
3020
- <div>
3021
- <div class="float-title">Uploading ${p.length} ${p.length===1?"file":"files"}</div>
3022
- <div class="float-subtitle">${h} of ${p.length}${u>0?` · ~${oe(u)} left`:""}</div>
3023
- </div>
3024
- </div>
3025
- </div>
3026
- `}const e=((a=this.config)==null?void 0:a.mode)??"modal",t=((l=this.config)==null?void 0:l.headerButton)??(e==="modal"?"close":"none"),o=e==="modal"?this._onModalDismiss:this._onInlineDismiss,r=t==="back"?s.html`<button class="header-btn header-btn-back" aria-label="Back to Asset Picker" @click=${o}>
3027
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
3028
- <polyline points="15 18 9 12 15 6"/>
3029
- </svg>
3030
- </button>`:s.nothing,i=t==="close"?s.html`<button class="header-btn header-btn-close" aria-label="Close" @click=${o}>
3031
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
3032
- <line x1="18" y1="6" x2="6" y2="18" />
3033
- <line x1="6" y1="6" x2="18" y2="18" />
3034
- </svg>
3035
- </button>`:s.nothing;return s.html`
3036
- <div class="header">
3037
- ${r}
3038
- ${t!=="back"?s.html`
3039
- <div class="header-icon">
3040
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round">
3041
- <polyline points="16 16 12 12 8 16" />
3042
- <line x1="12" y1="12" x2="12" y2="21" />
3043
- <path d="M20.39 18.39A5 5 0 0018 9h-1.26A8 8 0 103 16.3" />
3044
- </svg>
3045
- </div>`:s.nothing}
3046
- <div class="header-title">Upload Files</div>
3047
- ${i}
3048
- </div>
3049
- `}_getImageDimensions(e){return e.previewUrl?this._dimCache.has(e.id)?Promise.resolve(this._dimCache.get(e.id)):new Promise(t=>{const o=new Image;o.onload=()=>{const r={w:o.naturalWidth,h:o.naturalHeight};this._dimCache.set(e.id,r),t(r)},o.onerror=()=>{this._dimCache.set(e.id,null),t(null)},o.src=e.previewUrl}):Promise.resolve(null)}_renderUploadOverlay(e){var a;const t=this._storeCtrl.state,o=Math.round(t.totalProgress??0),r=e.filter(l=>l.status==="complete").length,i=t.totalSpeed>0?(t.totalBytes-t.totalBytesUploaded)/t.totalSpeed:0;return s.html`
3050
- <div class="upload-overlay">
3051
- <div class="upload-overlay-spinner"></div>
3052
- <div class="upload-overlay-percent">${o}%</div>
3053
- <div class="upload-overlay-title">Uploading ${e.length} ${e.length===1?"file":"files"}</div>
3054
- <div class="upload-overlay-subtitle">${r} of ${e.length} complete${i>0?s.html` · ~${oe(i)} left`:s.nothing}</div>
3055
- <div class="upload-overlay-bar">
3056
- <div class="upload-overlay-bar-fill" style="width:${o}%"></div>
3057
- </div>
3058
- ${(a=this.config)!=null&&a.minimizeOnUpload?s.html`<button class="upload-overlay-minimize" @click=${this._onMinimize}>Minimize & continue in background</button>`:s.nothing}
3059
- </div>
3060
- `}_renderFloatingPill(e){const t=this._storeCtrl.state,o=Math.round(t.totalProgress??0),r=this._phase==="complete",i=e.filter(d=>d.status==="complete").length,a=e.filter(d=>d.status==="failed").length,l=t.totalSpeed>0?(t.totalBytes-t.totalBytesUploaded)/t.totalSpeed:0;return this._isPillExpanded===!1?s.html`
3061
- <div class="upload-float float-collapsed">
3062
- <div class="float-collapsed-left">
3063
- ${r?a>0?i>0?s.html`<div class="float-collapsed-icon warn"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg></div>`:s.html`<div class="float-collapsed-icon error"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg></div>`:s.html`<div class="float-collapsed-icon done"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><polyline points="20 6 9 17 4 12"/></svg></div>`:s.html`<div class="float-collapsed-spinner"></div>`}
3064
- <span class="float-collapsed-text">${r?a>0?i>0?"Partially uploaded":"Upload failed":"Upload complete":`Uploading ${e.length} ${e.length===1?"file":"files"}`}</span>
3065
- ${r?s.nothing:s.html`<span class="float-collapsed-pct">${o}%</span>`}
3066
- </div>
3067
- <div class="float-collapsed-actions">
3068
- <button title="Open uploader" @click=${this._onPillExpand}>
3069
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 3 21 3 21 9"/><polyline points="9 21 3 21 3 15"/><line x1="21" y1="3" x2="14" y2="10"/><line x1="3" y1="21" x2="10" y2="14"/></svg>
3070
- </button>
3071
- <button title="Expand" @click=${this._onPillClick}>
3072
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><polyline points="18 15 12 9 6 15"/></svg>
3073
- </button>
3074
- <button title="Close" @click=${this._onPillDismiss}>
3075
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
3076
- </button>
3077
- </div>
3078
- </div>
3079
- `:s.html`
3080
- <div class="upload-float">
3081
- <div class="float-header">
3082
- <div class="float-header-left">
3083
- <div class="float-icon ${r?a>0?i>0?"warn":"error":"done":""}">
3084
- ${r?a>0?i>0?s.html`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>`:s.html`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>`:s.html`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><polyline points="20 6 9 17 4 12"/></svg>`:s.html`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"><polyline points="16 16 12 12 8 16"/><line x1="12" y1="12" x2="12" y2="21"/><path d="M20.39 18.39A5 5 0 0018 9h-1.26A8 8 0 103 16.3"/></svg>`}
3085
- </div>
3086
- <div>
3087
- <div class="float-title">${r?a>0?i>0?"Partially uploaded":"Upload failed":"Upload complete":`Uploading ${e.length} ${e.length===1?"file":"files"}`}</div>
3088
- <div class="float-subtitle">${r?`${i} ${i===1?"file":"files"} uploaded${a>0?`, ${a} failed`:""}`:`${i} of ${e.length}${l>0?` · ~${oe(l)} left`:""}`}</div>
3089
- </div>
3090
- </div>
3091
- <div class="float-actions">
3092
- <button title="Expand" @click=${this._onPillExpand}>
3093
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 3 21 3 21 9"/><polyline points="9 21 3 21 3 15"/><line x1="21" y1="3" x2="14" y2="10"/><line x1="3" y1="21" x2="10" y2="14"/></svg>
3094
- </button>
3095
- <button title="Collapse" @click=${this._onPillClick}>
3096
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><polyline points="6 9 12 15 18 9"/></svg>
3097
- </button>
3098
- <button title="Close" @click=${this._onPillDismiss}>
3099
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
3100
- </button>
3101
- </div>
3102
- </div>
3103
- <div class="float-progress">
3104
- <div class="float-progress-top">
3105
- <span class="float-progress-label">Overall progress</span>
3106
- <span class="float-progress-pct ${r?a>0?i>0?"warn":"error":"done":""}">${r?"Done":`${o}%`}</span>
3107
- </div>
3108
- <div class="float-bar"><div class="float-bar-fill ${r?a>0?i>0?"warn":"error":"done":""}" style="width:${r?100:o}%"></div></div>
3109
- </div>
3110
- <div class="float-items">
3111
- ${e.map(d=>{const p=d.status==="failed"||d.status==="error";return s.html`
3112
- <div class="float-item">
3113
- <div class="float-item-thumb" style=${d.previewUrl?`background-image:url(${d.previewUrl});background-size:cover;background-position:center`:""}>
3114
- ${d.previewUrl?s.nothing:s.html`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/><path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"/></svg>`}
3115
- </div>
3116
- <div class="float-item-info">
3117
- <div class="float-item-name">${d.name}</div>
3118
- <div class="float-item-size">${B(d.size)}</div>
3119
- </div>
3120
- <div class="float-item-status">
3121
- ${d.status==="complete"?s.html`<div class="float-item-done"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><polyline points="20 6 9 17 4 12"/></svg></div>`:p?s.html`
3122
- <div class="float-item-error-wrap">
3123
- <svg class="float-item-error-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>
3124
- <span class="float-item-tooltip">${d.error||"Upload failed"}</span>
3125
- </div>
3126
- <button class="float-item-retry" @click=${()=>{var h;this._ensureEngine(),(h=this._engine)==null||h.retryFile(d.id)}}>
3127
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 2v6h-6"/><path d="M3 12a9 9 0 0 1 15-6.7L21 8"/><path d="M3 22v-6h6"/><path d="M21 12a9 9 0 0 1-15 6.7L3 16"/></svg>
3128
- </button>`:s.html`<div class="float-item-spinner"></div>`}
3129
- </div>
3130
- </div>
3131
- `})}
3132
- </div>
3133
- </div>
3134
- `}_renderPreviewLayout(e){var l;if(e.length===0)return s.nothing;const t=e.find(d=>d.id===this._previewFileId)??e[0],o=((l=t.name.split(".").pop())==null?void 0:l.toUpperCase())||"",r=new Date(t.addedAt).toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"}),i=this._store.getState().targetFolder,a=e.reduce((d,p)=>d+(p.size||0),0);return s.html`
3135
- <div class="preview-topbar"></div>
3136
- <div class="preview-layout">
3137
- <div class="file-grid-side" style="flex:${this._splitPct}">
3138
- <div class="file-grid-header">
3139
- <span class="file-grid-header-text">${e.length} ${e.length===1?"asset":"assets"} · ${B(a)}</span>
3140
- </div>
3141
- <sfx-file-list
3142
- .files=${e}
3143
- .showDropTile=${!0}
3144
- .sources=${this._mergedSources}
3145
- .accept=${ye(this._storeCtrl.state.restrictions)}
3146
- @source-click=${this._onDropTileSourceClick}
3147
- ></sfx-file-list>
3148
- </div>
3149
- <div class="preview-divider"
3150
- @pointerdown=${this._onSplitPointerDown}
3151
- @pointermove=${this._onSplitPointerMove}
3152
- @pointerup=${this._onSplitPointerUp}
3153
- @lostpointercapture=${this._onSplitPointerUp}
3154
- ></div>
3155
- <div class="preview-panel" style="flex:${100-this._splitPct}">
3156
- <div class="preview-panel-header">
3157
- <span class="preview-panel-filename" title=${t.name}>${t.name}</span>
3158
- <div class="preview-header-actions">
3159
- ${t.previewUrl||t.type.startsWith("video/")&&t.file?s.html`
3160
- <button @click=${()=>{this._fullscreenPreviewUrl=t.previewUrl,this._fullscreenVideoFile=t.type.startsWith("video/")&&t.file?t.file:null,this._fullscreenZoomed=!1}} title="Fullscreen">
3161
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
3162
- <polyline points="15 3 21 3 21 9" />
3163
- <polyline points="9 21 3 21 3 15" />
3164
- <line x1="21" y1="3" x2="14" y2="10" />
3165
- <line x1="3" y1="21" x2="10" y2="14" />
3166
- </svg>
3167
- </button>
3168
- `:s.nothing}
3169
- <button @click=${()=>{this._previewFileId=null}} title="Close">
3170
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round">
3171
- <line x1="18" y1="6" x2="6" y2="18" />
3172
- <line x1="6" y1="6" x2="18" y2="18" />
3173
- </svg>
3174
- </button>
3175
- </div>
3176
- </div>
3177
- ${t.type.startsWith("video/")&&t.file?s.html`
3178
- <div class="preview-img-wrap">
3179
- <video class="preview-image" src=${this._getVideoBlobUrl(t.file)} controls playsinline></video>
3180
- <button class="preview-nav prev" ?disabled=${e.indexOf(t)===0} @click=${()=>this._navigatePreview(e,-1)}>
3181
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><polyline points="15 18 9 12 15 6"/></svg>
3182
- </button>
3183
- <button class="preview-nav next" ?disabled=${e.indexOf(t)===e.length-1} @click=${()=>this._navigatePreview(e,1)}>
3184
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><polyline points="9 6 15 12 9 18"/></svg>
3185
- </button>
3186
- </div>
3187
- `:t.previewUrl?s.html`
3188
- <div class="preview-img-wrap">
3189
- <img class="preview-image" src=${t.previewUrl} alt=${t.name} />
3190
- <button class="preview-nav prev" ?disabled=${e.indexOf(t)===0} @click=${()=>this._navigatePreview(e,-1)}>
3191
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><polyline points="15 18 9 12 15 6"/></svg>
3192
- </button>
3193
- <button class="preview-nav next" ?disabled=${e.indexOf(t)===e.length-1} @click=${()=>this._navigatePreview(e,1)}>
3194
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><polyline points="9 6 15 12 9 18"/></svg>
3195
- </button>
3196
- </div>
3197
- `:s.html`
3198
- <div class="preview-doc-wrap ${q(t)}">
3199
- <div class="preview-doc-icon ${q(t)}">
3200
- ${this._renderDocTypeIcon(q(t))}
3201
- <span class="preview-doc-ext ${q(t)}">${o}</span>
3202
- </div>
3203
- <button class="preview-nav prev" ?disabled=${e.indexOf(t)===0} @click=${()=>this._navigatePreview(e,-1)}>
3204
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><polyline points="15 18 9 12 15 6"/></svg>
3205
- </button>
3206
- <button class="preview-nav next" ?disabled=${e.indexOf(t)===e.length-1} @click=${()=>this._navigatePreview(e,1)}>
3207
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><polyline points="9 6 15 12 9 18"/></svg>
3208
- </button>
3209
- </div>
3210
- `}
3211
- <div class="preview-meta-list">
3212
- <div class="preview-meta-row">
3213
- <span class="preview-meta-label">Type</span>
3214
- <span class="preview-meta-value">${o}</span>
3215
- </div>
3216
- <div class="preview-meta-row">
3217
- <span class="preview-meta-label">Size</span>
3218
- <span class="preview-meta-value">${B(t.size)}</span>
3219
- </div>
3220
- <div class="preview-meta-row">
3221
- <span class="preview-meta-label">Dimensions</span>
3222
- <span class="preview-meta-value">${this._previewDims}</span>
3223
- </div>
3224
- <div class="preview-meta-row">
3225
- <span class="preview-meta-label">Name</span>
3226
- <span class="preview-meta-value truncate" title=${t.name}>${t.name}</span>
3227
- </div>
3228
- ${i?s.html`
3229
- <div class="preview-meta-row">
3230
- <span class="preview-meta-label">Folder</span>
3231
- <span class="preview-meta-value">${i}</span>
3232
- </div>`:s.html`
3233
- <div class="preview-meta-row">
3234
- <span class="preview-meta-label">Added</span>
3235
- <span class="preview-meta-value">${r}</span>
3236
- </div>`}
3237
- </div>
3238
- </div>
3239
- </div>
3240
- `}_renderDocTypeIcon(e){switch(e){case"pdf":return s.html`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" 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 s.html`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" 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 s.html`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" 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 s.html`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><path d="M21 8v13H3V8"/><path d="M1 3h22v5H1z"/><path d="M10 12h4"/></svg>`;default:return s.html`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" 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>`}}_navigatePreview(e,t){var i;const r=e.findIndex(a=>a.id===this._previewFileId)+t;if(r>=0&&r<e.length){const a=(i=this.shadowRoot)==null?void 0:i.querySelector(".preview-image[controls]");a&&(a.pause(),a.removeAttribute("src"),a.load()),this._previewFileId=e[r].id}}_renderBody(){var a,l,d;const e=this._storeCtrl.state,t=[...e.files.values()],o=this._phase,r=ye(e.restrictions),i=t.length>0;return s.html`
3241
- <div class="content"
3242
- @files-selected=${this._onFilesSelected}
3243
- @source-click=${this._onSourceClick}
3244
- @file-remove=${this._onFileRemove}
3245
- @file-preview=${this._onFilePreview}
3246
- @file-retry=${this._onFileRetry}
3247
- @fill-metadata=${this._onFillMetadata}
3248
- @retry-all=${this._onRetryAll}
3249
- @clear-all=${this._onClearAll}
3250
- @add-more=${this._onAddMore}
3251
- @upload-start=${this._onUploadStart}
3252
- @upload-more=${this._onUploadMore}
3253
- @primary-action=${this._onPrimaryAction}
3254
- @connector-files-selected=${this._onConnectorFilesSelected}
3255
- @connector-close=${this._onConnectorClose}
3256
- @url-submit=${this._onUrlSubmit}
3257
- @url-cancel=${this._onUrlCancel}
3258
- @camera-capture=${this._onCameraCapture}
3259
- @camera-cancel=${this._onCameraCancel}
3260
- @screencast-capture=${this._onScreenCastCapture}
3261
- @screencast-cancel=${this._onScreenCastCancel}
3262
- >
3263
- <div
3264
- class="body ${i?"has-files":""} ${this._bodyDragOver?"body-drag-over":""}"
3265
- @dragenter=${i?this._onBodyDragEnter:s.nothing}
3266
- @dragover=${i?this._onBodyDragOver:s.nothing}
3267
- @dragleave=${i?this._onBodyDragLeave:s.nothing}
3268
- @drop=${i?this._onBodyDrop:s.nothing}
3269
- >
3270
- ${o==="complete"?s.html`
3271
- <sfx-success-card
3272
- .fileCount=${t.filter(p=>p.status==="complete").length}
3273
- .totalSize=${t.filter(p=>p.status==="complete").reduce((p,h)=>p+(h.size||0),0)}
3274
- .thumbnails=${t.filter(p=>p.status==="complete"&&p.previewUrl).map(p=>p.previewUrl)}
3275
- .failedFiles=${t.filter(p=>p.status==="failed").map(p=>({id:p.id,name:p.name,error:p.error||"Upload failed"}))}
3276
- @close-uploader=${this._onSuccessCardClose}
3277
- @file-retry=${this._onFileRetry}
3278
- @retry-all=${this._onRetryAll}
3279
- ></sfx-success-card>
3280
- `:o==="uploading"?this._renderUploadOverlay(t):s.html`
3281
- ${i?s.nothing:s.html`<sfx-drop-zone
3282
- .compact=${i}
3283
- .externalDragOver=${this._bodyDragOver}
3284
- .accept=${r}
3285
- .sources=${this._mergedSources}
3286
- .sourcesLayout=${((a=this.config)==null?void 0:a.sourcesLayout)??"pills"}
3287
- ></sfx-drop-zone>`}
3288
-
3289
- ${i?this._previewFileId?this._renderPreviewLayout(t):s.html`
3290
- <div class="asset-count">${t.length} ${t.length===1?"file":"files"} · ${B(t.reduce((p,h)=>p+(h.size||0),0))}</div>
3291
- <sfx-file-list
3292
- .files=${t}
3293
- .showDropTile=${!0}
3294
- .sources=${this._mergedSources}
3295
- .accept=${r}
3296
- @source-click=${this._onDropTileSourceClick}
3297
- ></sfx-file-list>
3298
- `:s.nothing}
3299
- `}
3300
- </div>
3301
-
3302
- ${i&&o!=="complete"&&o!=="uploading"?s.html`
3303
- <sfx-actions-bar
3304
- .uploadState=${"idle"}
3305
- .fileCount=${t.length}
3306
- .totalSize=${t.reduce((p,h)=>p+(h.size||0),0)}
3307
- .failedCount=${t.filter(p=>p.status==="failed"||p.status==="error").length}
3308
- .completedCount=${t.filter(p=>p.status==="complete").length}
3309
- .uploadProgress=${e.totalProgress??0}
3310
- .showFillMetadata=${!!((l=this.config)!=null&&l.showFillMetadata)}
3311
- ></sfx-actions-bar>
3312
- `:s.nothing}
3313
-
3314
- ${this._showUrlDialog?s.html`<sfx-url-dialog></sfx-url-dialog>`:s.nothing}
3315
- ${this._showCameraDialog?s.html`<sfx-camera-dialog></sfx-camera-dialog>`:s.nothing}
3316
- ${this._showScreenCastDialog?s.html`<sfx-screen-cast-dialog></sfx-screen-cast-dialog>`:s.nothing}
3317
- ${this._activeConnector&&((d=this.config)!=null&&d.connectors)?s.html`
3318
- <div class="connector-modal-backdrop" @click=${this._onConnectorBackdropClick}>
3319
- <div class="connector-modal">
3320
- ${$e.has(this._activeConnector)?s.html`
3321
- <sfx-search-provider-browser
3322
- .provider=${this._activeConnector}
3323
- .companionUrl=${this.config.connectors.companionUrl}
3324
- ></sfx-search-provider-browser>
3325
- `:s.html`
3326
- <sfx-provider-browser
3327
- .provider=${this._activeConnector}
3328
- .companionUrl=${this.config.connectors.companionUrl}
3329
- ></sfx-provider-browser>
3330
- `}
3331
- </div>
3332
- </div>
3333
- `:s.nothing}
3334
-
3335
- ${this._fullscreenPreviewUrl||this._fullscreenVideoFile?s.html`
3336
- <div
3337
- class="fs-overlay ${this._fullscreenZoomed?"zoomed":""} ${this._fsDragging?"panning":""}"
3338
- @click=${this._onFsOverlayClick}
3339
- @mousedown=${this._onFsPanStart}
3340
- @mousemove=${this._onFsPanMove}
3341
- @mouseup=${this._onFsPanEnd}
3342
- @mouseleave=${this._onFsPanEnd}
3343
- @touchstart=${this._onFsTouchStart}
3344
- @touchmove=${this._onFsTouchMove}
3345
- @touchend=${this._onFsPanEnd}
3346
- >
3347
- <div class="fs-toolbar" @click=${p=>p.stopPropagation()}>
3348
- <button class="fs-btn" @click=${this._onFsToggleZoom} title="${this._fullscreenZoomed?"Zoom out":"Zoom in"}">
3349
- ${this._fullscreenZoomed?s.html`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/><line x1="8" y1="11" x2="14" y2="11"/></svg>`:s.html`<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/><line x1="11" y1="8" x2="11" y2="14"/><line x1="8" y1="11" x2="14" y2="11"/></svg>`}
3350
- </button>
3351
- <button class="fs-btn" @click=${this._onFsClose} title="Close">
3352
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
3353
- <line x1="18" y1="6" x2="6" y2="18" /><line x1="6" y1="6" x2="18" y2="18" />
3354
- </svg>
3355
- </button>
3356
- </div>
3357
- ${this._fullscreenVideoFile?s.html`<video
3358
- class="fs-img"
3359
- src=${this._getVideoBlobUrl(this._fullscreenVideoFile)}
3360
- controls playsinline
3361
- draggable="false"
3362
- @click=${p=>p.stopPropagation()}
3363
- ></video>`:s.html`<img
3364
- class="fs-img"
3365
- src=${this._fullscreenPreviewUrl}
3366
- alt=""
3367
- style=${this._fullscreenZoomed?`transform: scale(2) translate(${this._fsPanX}px, ${this._fsPanY}px)`:""}
3368
- draggable="false"
3369
- />`}
3370
- <button class="fs-nav prev" @click=${p=>{p.stopPropagation(),this._navigateFs(-1)}}>
3371
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><polyline points="15 18 9 12 15 6"/></svg>
3372
- </button>
3373
- <button class="fs-nav next" @click=${p=>{p.stopPropagation(),this._navigateFs(1)}}>
3374
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><polyline points="9 6 15 12 9 18"/></svg>
3375
- </button>
3376
- </div>
3377
- `:s.nothing}
3378
- </div>
3379
- `}_navigateFs(e){const t=[...this._store.getState().files.values()].filter(i=>i.previewUrl||i.type.startsWith("video/")&&i.file),o=t.findIndex(i=>i.id===this._previewFileId);if(o===-1)return;const r=o+e;if(r>=0&&r<t.length){const i=t[r];this._fullscreenPreviewUrl=i.previewUrl,this._fullscreenVideoFile=i.type.startsWith("video/")&&i.file?i.file:null,this._previewFileId=i.id,this._fullscreenZoomed=!1,this._fsPanX=0,this._fsPanY=0}}_getVideoBlobUrl(e){let t=this._videoBlobUrls.get(e);return t||(t=URL.createObjectURL(e),this._videoBlobUrls.set(e,t)),t}_revokeVideoBlobUrls(){for(const e of this._videoBlobUrls.values())URL.revokeObjectURL(e);this._videoBlobUrls.clear()}},$.styles=s.css`
3380
- :host {
3381
- display: block;
3382
- font-family: var(--sfx-up-font, 'Inter', system-ui, -apple-system, sans-serif);
3383
- color: var(--sfx-up-text, #1e293b);
3384
- /* Bridge to Scaleflex design system with standalone fallbacks */
3385
- --sfx-up-primary: var(--primary, #2563eb);
3386
- --sfx-up-primary-hover: var(--primary-hover, #1d4ed8);
3387
- --sfx-up-primary-mid: var(--primary-mid, #3b82f6);
3388
- --sfx-up-primary-bg: var(--accent, #eff6ff);
3389
- --sfx-up-primary-glow: rgba(37, 99, 235, 0.18);
3390
- --sfx-up-success: var(--success, #16a34a);
3391
- --sfx-up-error: var(--destructive, #dc2626);
3392
- --sfx-up-text: var(--foreground, #1e293b);
3393
- --sfx-up-text-secondary: var(--secondary-foreground, #475569);
3394
- --sfx-up-text-muted: var(--muted-foreground, #94a3b8);
3395
- --sfx-up-border: var(--border, #e8edf5);
3396
- --sfx-up-border-light: var(--muted, #f1f5f9);
3397
- --sfx-up-bg: var(--background, #ffffff);
3398
- --sfx-up-radius: 16px;
3399
- --sfx-up-font: 'Inter', system-ui, -apple-system, sans-serif;
3400
- --sfx-up-shadow: var(--shadow, rgba(0, 0, 0, 0.1));
3401
- --sfx-up-surface: var(--card, #f8fafc);
3402
- --sfx-up-backdrop: rgba(0, 0, 0, 0.45);
3403
- --sfx-up-ring: var(--ring, oklch(0.578 0.198 268.129 / 0.7));
3404
- --sfx-up-max-height: 88vh;
3405
- --sfx-up-checker-bg: #fff;
3406
- --sfx-up-checker-tile: #f0f0f0;
3407
- }
3408
-
3409
- /* --- Modal overlay --- */
3410
- .modal-backdrop {
3411
- position: fixed;
3412
- inset: 0;
3413
- background: var(--sfx-up-backdrop);
3414
- backdrop-filter: blur(6px);
3415
- display: flex;
3416
- align-items: center;
3417
- justify-content: center;
3418
- z-index: 9999;
3419
- padding: 24px;
3420
- animation: fadeIn 0.2s ease;
3421
- }
3422
-
3423
- .modal-card {
3424
- background: var(--sfx-up-bg, #fff);
3425
- border-radius: 16px;
3426
- box-shadow: 0 28px 80px rgba(0, 0, 0, 0.2), 0 4px 16px rgba(0, 0, 0, 0.06);
3427
- width: 100%;
3428
- max-width: 912px;
3429
- min-height: var(--sfx-up-min-height, 660px);
3430
- max-height: var(--sfx-up-max-height, 88vh);
3431
- display: flex;
3432
- flex-direction: column;
3433
- overflow: hidden;
3434
- position: relative;
3435
- animation: modalIn 0.3s cubic-bezier(0.34, 1.2, 0.64, 1);
3436
- }
3437
-
3438
- /* --- Header --- */
3439
- .header {
3440
- display: flex;
3441
- align-items: center;
3442
- padding: 16px 24px;
3443
- background: var(--sfx-up-bg, #fff);
3444
- border-bottom: 1px solid var(--sfx-up-border, #e2e8f0);
3445
- flex-shrink: 0;
3446
- }
3447
-
3448
- .header-icon {
3449
- width: 32px;
3450
- height: 32px;
3451
- border-radius: 8px;
3452
- background: var(--sfx-up-primary-bg, #eff6ff);
3453
- color: var(--sfx-up-primary, #2563eb);
3454
- display: flex;
3455
- align-items: center;
3456
- justify-content: center;
3457
- margin-right: 12px;
3458
- flex-shrink: 0;
3459
- }
3460
-
3461
- .header-icon-done {
3462
- background: var(--sfx-up-primary-bg, #eff6ff);
3463
- color: var(--sfx-up-primary, #2563eb);
3464
- }
3465
-
3466
- .header-icon svg {
3467
- width: 16px;
3468
- height: 16px;
3469
- }
3470
-
3471
- .header-title {
3472
- font-size: 16px;
3473
- font-weight: 700;
3474
- color: var(--sfx-up-text, #111827);
3475
- flex: 1;
3476
- }
3477
-
3478
- .header-btn {
3479
- width: 30px;
3480
- height: 30px;
3481
- border-radius: 8px;
3482
- border: none;
3483
- background: var(--sfx-up-surface, #f8fafc);
3484
- color: var(--sfx-up-text-muted, #94a3b8);
3485
- cursor: pointer;
3486
- display: flex;
3487
- align-items: center;
3488
- justify-content: center;
3489
- transition: background 0.15s, color 0.15s;
3490
- flex-shrink: 0;
3491
- }
3492
-
3493
- .header-btn svg {
3494
- width: 16px;
3495
- height: 16px;
3496
- }
3497
-
3498
- .header-btn:hover {
3499
- background: var(--sfx-up-border, #e2e8f0);
3500
- color: var(--sfx-up-text, #1e293b);
3501
- }
3502
-
3503
- .header-btn:focus-visible {
3504
- outline: 2px solid var(--sfx-up-ring, oklch(0.578 0.198 268.129 / 0.7));
3505
- outline-offset: 2px;
3506
- }
3507
-
3508
- .header-btn-back {
3509
- margin-right: 12px;
3510
- background: var(--sfx-up-primary-bg, #eff6ff);
3511
- color: var(--sfx-up-primary, #2563eb);
3512
- width: 32px;
3513
- height: 32px;
3514
- position: relative;
3515
- }
3516
-
3517
- .header-btn-back:hover {
3518
- background: #dbeafe;
3519
- color: var(--sfx-up-primary, #2563eb);
3520
- box-shadow: 0 2px 8px rgba(37, 99, 235, 0.15);
3521
- }
3522
-
3523
- .header-btn-back::after {
3524
- content: 'Back to Asset Picker';
3525
- position: absolute;
3526
- left: calc(100% + 8px);
3527
- top: 50%;
3528
- transform: translateY(-50%);
3529
- background: #fff;
3530
- color: var(--sfx-up-text, #1e293b);
3531
- font-size: 12px;
3532
- font-weight: 500;
3533
- white-space: nowrap;
3534
- padding: 6px 12px;
3535
- border-radius: 8px;
3536
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
3537
- opacity: 0;
3538
- pointer-events: none;
3539
- transition: opacity 0.15s ease;
3540
- z-index: 10;
3541
- }
3542
-
3543
- .header-btn-back:hover::after {
3544
- opacity: 1;
3545
- }
3546
-
3547
- .header-btn-close {
3548
- margin-left: auto;
3549
- }
3550
-
3551
- /* --- Responsive header buttons --- */
3552
- @media (max-width: 768px) {
3553
- .header-btn { width: 28px; height: 28px; }
3554
- .header-btn svg { width: 14px; height: 14px; }
3555
- }
3556
- @media (max-width: 480px) {
3557
- .header-btn { width: 26px; height: 26px; }
3558
- }
3559
-
3560
- /* --- Content wrapper (holds body + actions bar) --- */
3561
- .content {
3562
- flex: 1;
3563
- display: flex;
3564
- flex-direction: column;
3565
- min-height: 0;
3566
- }
3567
-
3568
- /* --- Body --- */
3569
- .body {
3570
- flex: 1;
3571
- overflow: hidden;
3572
- padding: 24px;
3573
- display: flex;
3574
- flex-direction: column;
3575
- align-items: stretch;
3576
- justify-content: stretch;
3577
- gap: 4px;
3578
- min-height: 0;
3579
- background: var(--sfx-up-bg, #fff);
3580
- }
3581
-
3582
- .body.body-drag-over {
3583
- background: var(--sfx-up-primary-bg, #eff6ff);
3584
- border-radius: 8px;
3585
- position: relative;
3586
- }
3587
-
3588
- .body.body-drag-over::after {
3589
- content: '';
3590
- position: absolute;
3591
- inset: 4px;
3592
- border: 2px dashed var(--sfx-up-primary, #2563eb);
3593
- border-radius: 8px;
3594
- z-index: 100;
3595
- pointer-events: none;
3596
- }
3597
-
3598
- .body.has-files {
3599
- justify-content: flex-start;
3600
- align-items: stretch;
3601
- overflow: hidden;
3602
- gap: 0;
3603
- padding: 0 0 0 8px;
3604
- animation: bodyReveal 0.35s ease both;
3605
- }
3606
-
3607
- .body.has-files:has(.preview-layout) {
3608
- padding-right: 0;
3609
- }
3610
-
3611
- @keyframes bodyReveal {
3612
- from { opacity: 0.5; }
3613
- to { opacity: 1; }
3614
- }
3615
-
3616
- .body.has-files::-webkit-scrollbar-thumb:hover {
3617
- background: rgba(0, 0, 0, 0.25);
3618
- }
3619
-
3620
- .body sfx-drop-zone {
3621
- position: relative;
3622
- z-index: 1;
3623
- overflow: visible;
3624
- }
3625
-
3626
- .asset-count {
3627
- font-size: 14px;
3628
- font-weight: 400;
3629
- color: var(--sfx-up-text-secondary, #64748b);
3630
- padding: 16px;
3631
- min-height: 61px;
3632
- box-sizing: border-box;
3633
- display: flex;
3634
- align-items: center;
3635
- flex-shrink: 0;
3636
- }
3637
-
3638
- /* --- Inline mode --- */
3639
- .inline {
3640
- border: 1px solid var(--sfx-up-border, #e2e8f0);
3641
- border-radius: var(--sfx-up-radius, 16px);
3642
- background: var(--sfx-up-bg, #fff);
3643
- display: flex;
3644
- flex-direction: column;
3645
- overflow: hidden;
3646
- height: 100%;
3647
- min-height: var(--sfx-up-min-height, 660px);
3648
- max-height: var(--sfx-up-max-height, 88vh);
3649
- box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04), 0 1px 2px rgba(0, 0, 0, 0.02);
3650
- transition: box-shadow 0.25s ease;
3651
- animation: inlineIn 0.25s ease;
3652
- }
3653
-
3654
- .inline:hover {
3655
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06), 0 1px 3px rgba(0, 0, 0, 0.03);
3656
- }
3657
-
3658
- /* --- Preview split layout --- */
3659
- .preview-layout {
3660
- display: flex;
3661
- flex: 1;
3662
- min-height: 0;
3663
- overflow: hidden;
3664
- }
3665
-
3666
- .preview-layout .file-grid-side {
3667
- flex: 68;
3668
- min-width: 0;
3669
- min-height: 100%;
3670
- overflow: hidden;
3671
- display: flex;
3672
- flex-direction: column;
3673
- position: relative;
3674
- --sfx-up-grid-min: max(30%, 140px);
3675
- }
3676
-
3677
- .preview-layout .file-grid-side::after {
3678
- display: none;
3679
- }
3680
-
3681
- .preview-layout sfx-file-list {
3682
- padding-right: 6px;
3683
- --sfx-scrollbar-w: 14px;
3684
- --sfx-scrollbar-inset-left: 2px;
3685
- --sfx-scrollbar-inset-right: 6px;
3686
- }
3687
-
3688
- /* NOTE: scrollbar border-radius is hardcoded to 6px in sfx-file-list */
3689
-
3690
- .file-grid-header {
3691
- display: flex;
3692
- align-items: center;
3693
- justify-content: space-between;
3694
- gap: 8px;
3695
- padding: 16px;
3696
- min-height: 61px;
3697
- box-sizing: border-box;
3698
- flex-shrink: 0;
3699
- position: sticky;
3700
- top: 0;
3701
- z-index: 2;
3702
- background: var(--sfx-up-bg, #fff);
3703
- }
3704
-
3705
- .file-grid-header-text {
3706
- font-size: 14px;
3707
- font-weight: 400;
3708
- color: var(--sfx-up-text-secondary, #64748b);
3709
- }
3710
-
3711
- .preview-topbar {
3712
- display: flex;
3713
- align-items: center;
3714
- justify-content: space-between;
3715
- flex-shrink: 0;
3716
- padding: 0;
3717
- }
3718
-
3719
- .preview-divider {
3720
- width: 9px;
3721
- flex-shrink: 0;
3722
- position: relative;
3723
- display: flex;
3724
- align-items: center;
3725
- justify-content: center;
3726
- cursor: col-resize;
3727
- user-select: none;
3728
- -webkit-user-select: none;
3729
- }
3730
-
3731
- .preview-divider::before {
3732
- content: '';
3733
- position: absolute;
3734
- top: 0;
3735
- bottom: 0;
3736
- left: 4px;
3737
- width: 1px;
3738
- background: var(--sfx-up-border, #e8edf5);
3739
- }
3740
-
3741
- .preview-divider::after {
3742
- content: '';
3743
- width: 3px;
3744
- height: 28px;
3745
- border-radius: 2px;
3746
- background: var(--sfx-up-border, #d0d7e2);
3747
- opacity: 0;
3748
- transition: opacity 0.15s;
3749
- z-index: 1;
3750
- }
3751
-
3752
- .preview-divider:hover::after,
3753
- .preview-layout.resizing .preview-divider::after {
3754
- opacity: 1;
3755
- }
3756
-
3757
- .preview-layout.resizing {
3758
- cursor: col-resize;
3759
- user-select: none;
3760
- -webkit-user-select: none;
3761
- }
3762
-
3763
- .preview-layout.resizing * {
3764
- pointer-events: none;
3765
- }
3766
-
3767
- .preview-layout.resizing .preview-divider {
3768
- pointer-events: auto;
3769
- }
3770
-
3771
- .preview-panel {
3772
- flex: 32;
3773
- min-width: 0;
3774
- display: flex;
3775
- flex-direction: column;
3776
- overflow: hidden;
3777
- padding: 0;
3778
- }
3779
-
3780
- .preview-panel::-webkit-scrollbar { width: 5px; }
3781
- .preview-panel::-webkit-scrollbar-track { background: transparent; }
3782
- .preview-panel::-webkit-scrollbar-thumb { background: rgba(0,0,0,0.12); border-radius: 3px; }
3783
-
3784
- .preview-panel-header {
3785
- display: flex;
3786
- align-items: center;
3787
- justify-content: space-between;
3788
- gap: 8px;
3789
- padding: 16px 24px 16px 16px;
3790
- flex-shrink: 0;
3791
- border-bottom: 1px solid var(--sfx-up-border, #e8edf5);
3792
- }
3793
-
3794
- .preview-header-actions {
3795
- display: flex;
3796
- align-items: center;
3797
- gap: 4px;
3798
- flex-shrink: 0;
3799
- }
3800
-
3801
- .preview-panel-filename {
3802
- font-size: 16px;
3803
- font-weight: 400;
3804
- color: var(--sfx-up-text, #1e293b);
3805
- white-space: nowrap;
3806
- overflow: hidden;
3807
- text-overflow: ellipsis;
3808
- min-width: 0;
3809
- }
3810
-
3811
- .preview-panel-header button {
3812
- width: 28px;
3813
- height: 28px;
3814
- border-radius: 6px;
3815
- border: none;
3816
- background: none;
3817
- cursor: pointer;
3818
- display: flex;
3819
- align-items: center;
3820
- justify-content: center;
3821
- color: var(--sfx-up-text-muted, #9ca3af);
3822
- transition: background 0.15s, color 0.15s;
3823
- padding: 0;
3824
- flex-shrink: 0;
3825
- }
3826
-
3827
- .preview-panel-header button:hover {
3828
- background: var(--sfx-up-surface, #f8fafc);
3829
- color: var(--sfx-up-text, #374151);
3830
- }
3831
-
3832
- .preview-panel-header button svg {
3833
- width: 16px;
3834
- height: 16px;
3835
- }
3836
-
3837
- .file-info-header {
3838
- display: flex;
3839
- align-items: center;
3840
- justify-content: space-between;
3841
- padding: 14px 0 10px;
3842
- font-size: 14px;
3843
- font-weight: 600;
3844
- color: var(--sfx-up-text, #1e293b);
3845
- border-top: 1px solid var(--sfx-up-border, #e8edf5);
3846
- margin-top: 4px;
3847
- flex-shrink: 0;
3848
- }
3849
-
3850
- .file-info-header svg {
3851
- width: 16px;
3852
- height: 16px;
3853
- color: var(--sfx-up-text-muted, #9ca3af);
3854
- }
3855
-
3856
- .preview-doc-wrap {
3857
- position: relative;
3858
- flex: 1;
3859
- min-height: 0;
3860
- display: flex;
3861
- align-items: center;
3862
- justify-content: center;
3863
- }
3864
-
3865
- .preview-doc-wrap.pdf { background: linear-gradient(135deg, #fef2f2, #fee2e2); }
3866
- .preview-doc-wrap.doc { background: linear-gradient(135deg, var(--sfx-up-primary-bg, #eff6ff), var(--sfx-up-primary-bg, #dbeafe)); }
3867
- .preview-doc-wrap.vid { background: linear-gradient(135deg, #f5f3ff, #ede9fe); }
3868
- .preview-doc-wrap.zip { background: linear-gradient(135deg, var(--warning-10, #fffbeb), var(--warning-10, #fef3c7)); }
3869
- .preview-doc-wrap.gen { background: linear-gradient(135deg, var(--sfx-up-border-light, #f8fafc), var(--sfx-up-border-light, #f1f5f9)); }
3870
-
3871
- .preview-doc-icon {
3872
- display: flex;
3873
- flex-direction: column;
3874
- align-items: center;
3875
- gap: 8px;
3876
- }
3877
-
3878
- .preview-doc-icon svg {
3879
- width: 48px;
3880
- height: 48px;
3881
- stroke-width: 1.5;
3882
- }
3883
-
3884
- .preview-doc-icon.pdf svg { color: var(--sfx-up-error, #dc2626); }
3885
- .preview-doc-icon.doc svg { color: var(--sfx-up-primary, #1d4ed8); }
3886
- .preview-doc-icon.vid svg { color: #7c3aed; }
3887
- .preview-doc-icon.zip svg { color: var(--warning-foreground, #b45309); }
3888
- .preview-doc-icon.gen svg { color: var(--sfx-up-text-muted, #64748b); }
3889
-
3890
- .preview-doc-ext {
3891
- font-size: 13px;
3892
- font-weight: 700;
3893
- text-transform: uppercase;
3894
- letter-spacing: 0.05em;
3895
- }
3896
-
3897
- .preview-doc-ext.pdf { color: var(--sfx-up-error, #dc2626); }
3898
- .preview-doc-ext.doc { color: var(--sfx-up-primary, #1d4ed8); }
3899
- .preview-doc-ext.vid { color: #7c3aed; }
3900
- .preview-doc-ext.zip { color: var(--warning-foreground, #b45309); }
3901
- .preview-doc-ext.gen { color: var(--sfx-up-text-muted, #64748b); }
3902
-
3903
- .preview-img-wrap {
3904
- position: relative;
3905
- flex: 1;
3906
- min-height: 0;
3907
- background-color: var(--sfx-up-checker-bg);
3908
- background-image:
3909
- linear-gradient(45deg, var(--sfx-up-checker-tile) 25%, transparent 25%),
3910
- linear-gradient(-45deg, var(--sfx-up-checker-tile) 25%, transparent 25%),
3911
- linear-gradient(45deg, transparent 75%, var(--sfx-up-checker-tile) 75%),
3912
- linear-gradient(-45deg, transparent 75%, var(--sfx-up-checker-tile) 75%);
3913
- background-size: 16px 16px;
3914
- background-position: 0 0, 0 8px, 8px -8px, -8px 0;
3915
- }
3916
-
3917
- .preview-image {
3918
- width: 100%;
3919
- height: 100%;
3920
- object-fit: contain;
3921
- display: block;
3922
- border: none;
3923
- }
3924
-
3925
- .preview-nav {
3926
- position: absolute;
3927
- top: 50%;
3928
- transform: translateY(-50%);
3929
- width: 36px;
3930
- height: 36px;
3931
- border-radius: 50%;
3932
- border: none;
3933
- background: #fff;
3934
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
3935
- cursor: pointer;
3936
- display: flex;
3937
- align-items: center;
3938
- justify-content: center;
3939
- color: var(--sfx-up-text, #1e293b);
3940
- transition: all 0.15s;
3941
- z-index: 2;
3942
- padding: 0;
3943
- }
3944
-
3945
- .preview-nav:hover {
3946
- box-shadow: 0 3px 12px rgba(0, 0, 0, 0.18);
3947
- transform: translateY(-50%) scale(1.06);
3948
- }
3949
-
3950
- .preview-nav:active {
3951
- transform: translateY(-50%) scale(0.96);
3952
- }
3953
-
3954
- .preview-nav svg {
3955
- width: 18px;
3956
- height: 18px;
3957
- }
3958
-
3959
- .preview-nav.prev { left: 10px; }
3960
- .preview-nav.next { right: 10px; }
3961
-
3962
- .preview-nav:disabled {
3963
- opacity: 0.35;
3964
- cursor: default;
3965
- box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
3966
- }
3967
-
3968
- .preview-nav:disabled:hover {
3969
- transform: translateY(-50%);
3970
- box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
3971
- }
3972
-
3973
- .preview-meta-list {
3974
- display: flex;
3975
- flex-direction: column;
3976
- flex-shrink: 0;
3977
- padding: 0 16px 12px;
3978
- }
3979
-
3980
- .preview-meta-row {
3981
- display: flex;
3982
- align-items: baseline;
3983
- padding: 12px 0;
3984
- }
3985
-
3986
- .preview-meta-label {
3987
- width: 110px;
3988
- flex-shrink: 0;
3989
- font-size: 14px;
3990
- font-weight: 400;
3991
- color: var(--sfx-up-text-muted, #94a3b8);
3992
- }
3993
-
3994
- .preview-meta-value {
3995
- font-size: 14px;
3996
- font-weight: 400;
3997
- color: var(--foreground, var(--sfx-up-text, #1e293b));
3998
- word-break: break-all;
3999
- min-width: 0;
4000
- }
4001
-
4002
- .preview-meta-value.truncate {
4003
- white-space: nowrap;
4004
- overflow: hidden;
4005
- text-overflow: ellipsis;
4006
- word-break: normal;
4007
- }
4008
-
4009
- /* --- Upload overlay (in-modal) --- */
4010
- .upload-overlay {
4011
- display: flex;
4012
- flex-direction: column;
4013
- align-items: center;
4014
- justify-content: center;
4015
- flex: 1;
4016
- gap: 8px;
4017
- padding: 32px 24px;
4018
- position: relative;
4019
- animation: fadeUp 0.3s ease both;
4020
- }
4021
-
4022
- .upload-overlay-spinner {
4023
- width: 48px;
4024
- height: 48px;
4025
- border: 3px solid var(--sfx-up-border, #e2e8f0);
4026
- border-top-color: var(--sfx-up-primary, #2563eb);
4027
- border-radius: 50%;
4028
- animation: spin 0.8s linear infinite;
4029
- margin-bottom: 8px;
4030
- }
4031
-
4032
- .upload-overlay-percent {
4033
- font-size: 40px;
4034
- font-weight: 700;
4035
- color: var(--sfx-up-primary, #2563eb);
4036
- line-height: 1;
4037
- }
4038
-
4039
- .upload-overlay-title {
4040
- font-size: 16px;
4041
- font-weight: 600;
4042
- color: var(--sfx-up-text, #1e293b);
4043
- }
4044
-
4045
- .upload-overlay-subtitle {
4046
- font-size: 13px;
4047
- color: var(--sfx-up-text-muted, #94a3b8);
4048
- margin-bottom: 8px;
4049
- }
4050
-
4051
- .upload-overlay-bar {
4052
- width: 240px;
4053
- height: 6px;
4054
- background: var(--sfx-up-border, #e2e8f0);
4055
- border-radius: 3px;
4056
- overflow: hidden;
4057
- margin-bottom: 16px;
4058
- }
4059
-
4060
- .upload-overlay-bar-fill {
4061
- height: 100%;
4062
- background: var(--sfx-up-primary, #2563eb);
4063
- border-radius: 3px;
4064
- transition: width 0.3s ease;
4065
- }
4066
-
4067
- .upload-overlay-minimize {
4068
- padding: 8px 20px;
4069
- border: 1px solid var(--sfx-up-border, #e2e8f0);
4070
- background: var(--sfx-up-bg, #fff);
4071
- border-radius: 8px;
4072
- font-size: 13px;
4073
- font-weight: 500;
4074
- color: var(--sfx-up-text-secondary, #475569);
4075
- cursor: pointer;
4076
- transition: all 0.15s;
4077
- font-family: inherit;
4078
- }
4079
-
4080
- .upload-overlay-minimize:hover {
4081
- border-color: var(--sfx-up-primary, #2563eb);
4082
- color: var(--sfx-up-primary, #2563eb);
4083
- }
4084
-
4085
- .upload-header {
4086
- justify-content: space-between;
4087
- }
4088
-
4089
- .upload-header .float-actions button {
4090
- width: 28px;
4091
- height: 28px;
4092
- border: none;
4093
- background: none;
4094
- cursor: pointer;
4095
- border-radius: 6px;
4096
- display: flex;
4097
- align-items: center;
4098
- justify-content: center;
4099
- color: var(--sfx-up-text-muted, #94a3b8);
4100
- transition: background 0.15s;
4101
- padding: 0;
4102
- }
4103
-
4104
- .upload-header .float-actions button:hover {
4105
- background: var(--sfx-up-surface, #f8fafc);
4106
- color: var(--sfx-up-text, #374151);
4107
- }
4108
-
4109
- .upload-header .float-actions button svg { width: 16px; height: 16px; }
4110
-
4111
- @keyframes spin { to { transform: rotate(360deg); } }
4112
- @keyframes fadeUp {
4113
- from { opacity: 0; transform: translateY(12px); }
4114
- to { opacity: 1; transform: translateY(0); }
4115
- }
4116
-
4117
- /* --- Floating upload card (Variant 3 style) --- */
4118
- .upload-float {
4119
- position: fixed;
4120
- bottom: 24px;
4121
- right: 24px;
4122
- z-index: 10000;
4123
- width: 470px;
4124
- border-radius: 12px;
4125
- background: var(--sfx-up-bg, #fff);
4126
- box-shadow: 0 8px 32px rgba(0,0,0,0.12), 0 2px 8px rgba(0,0,0,0.06);
4127
- overflow: hidden;
4128
- font-family: inherit;
4129
- animation: floatSlideIn 0.3s ease both;
4130
- }
4131
-
4132
- .float-header {
4133
- display: flex;
4134
- align-items: center;
4135
- justify-content: space-between;
4136
- padding: 10px 14px;
4137
- border-bottom: 1px solid var(--sfx-up-border, #e8edf5);
4138
- }
4139
-
4140
- .float-header-left {
4141
- display: flex;
4142
- align-items: center;
4143
- gap: 8px;
4144
- }
4145
-
4146
- .float-icon {
4147
- width: 28px;
4148
- height: 28px;
4149
- border-radius: 6px;
4150
- background: var(--sfx-up-primary-bg, #eff6ff);
4151
- color: var(--sfx-up-primary, #2563eb);
4152
- display: flex;
4153
- align-items: center;
4154
- justify-content: center;
4155
- flex-shrink: 0;
4156
- }
4157
-
4158
- .float-icon svg { width: 14px; height: 14px; }
4159
-
4160
- .float-icon.done {
4161
- background: #f0fdf4;
4162
- color: #22c55e;
4163
- }
4164
-
4165
- .float-icon.error {
4166
- background: #fef2f2;
4167
- color: #ef4444;
4168
- }
4169
-
4170
- .float-title {
4171
- font-size: 13px;
4172
- font-weight: 600;
4173
- color: var(--sfx-up-text, #1e293b);
4174
- }
4175
-
4176
- .float-subtitle {
4177
- font-size: 11px;
4178
- color: var(--sfx-up-text-muted, #94a3b8);
4179
- }
4180
-
4181
- .float-actions {
4182
- display: flex;
4183
- gap: 4px;
4184
- }
4185
-
4186
- .float-actions button {
4187
- width: 26px;
4188
- height: 26px;
4189
- border: none;
4190
- background: none;
4191
- cursor: pointer;
4192
- border-radius: 6px;
4193
- display: flex;
4194
- align-items: center;
4195
- justify-content: center;
4196
- color: var(--sfx-up-text-muted, #94a3b8);
4197
- transition: background 0.15s;
4198
- padding: 0;
4199
- }
4200
-
4201
- .float-actions button:hover {
4202
- background: var(--sfx-up-surface, #f8fafc);
4203
- color: var(--sfx-up-text, #374151);
4204
- }
4205
-
4206
- .float-actions button svg { width: 14px; height: 14px; }
4207
-
4208
- .float-progress {
4209
- padding: 10px 14px;
4210
- border-bottom: 1px solid var(--sfx-up-border, #e8edf5);
4211
- }
4212
-
4213
- .float-progress-top {
4214
- display: flex;
4215
- align-items: center;
4216
- justify-content: space-between;
4217
- margin-bottom: 6px;
4218
- }
4219
-
4220
- .float-progress-label {
4221
- font-size: 12px;
4222
- color: var(--sfx-up-text-secondary, #475569);
4223
- }
4224
-
4225
- .float-progress-pct {
4226
- font-size: 12px;
4227
- font-weight: 600;
4228
- color: var(--sfx-up-primary, #2563eb);
4229
- }
4230
-
4231
- .float-progress-pct.done { color: #22c55e; }
4232
- .float-progress-pct.warn { color: #f59e0b; }
4233
- .float-progress-pct.error { color: #ef4444; }
4234
-
4235
- .float-bar {
4236
- height: 4px;
4237
- background: var(--sfx-up-border, #e8edf5);
4238
- border-radius: 2px;
4239
- overflow: hidden;
4240
- }
4241
-
4242
- .float-bar-fill {
4243
- height: 100%;
4244
- background: var(--sfx-up-primary, #2563eb);
4245
- border-radius: 2px;
4246
- transition: width 0.3s ease;
4247
- }
4248
-
4249
- .float-bar-fill.done { background: #22c55e; }
4250
- .float-bar-fill.warn { background: #f59e0b; }
4251
- .float-bar-fill.error { background: #ef4444; }
4252
-
4253
- .float-items {
4254
- max-height: 200px;
4255
- overflow-y: auto;
4256
- overflow-x: hidden;
4257
- scrollbar-width: thin;
4258
- scrollbar-color: rgba(0,0,0,0.1) transparent;
4259
- }
4260
-
4261
- .float-item {
4262
- display: flex;
4263
- align-items: center;
4264
- gap: 10px;
4265
- padding: 8px 14px;
4266
- border-bottom: 1px solid #f1f5f9;
4267
- overflow: hidden;
4268
- }
4269
-
4270
- .float-item:last-child { border-bottom: none; }
4271
-
4272
- .float-item-thumb {
4273
- width: 32px;
4274
- height: 32px;
4275
- border-radius: 6px;
4276
- background: var(--sfx-up-surface, #f8fafc);
4277
- display: flex;
4278
- align-items: center;
4279
- justify-content: center;
4280
- color: var(--sfx-up-text-muted, #94a3b8);
4281
- flex-shrink: 0;
4282
- }
4283
-
4284
- .float-item-thumb svg { width: 16px; height: 16px; }
4285
-
4286
- .float-item-info { flex: 1; min-width: 0; overflow: hidden; }
4287
-
4288
- .float-item-name {
4289
- font-size: 12px;
4290
- font-weight: 500;
4291
- color: var(--sfx-up-text, #1e293b);
4292
- white-space: nowrap;
4293
- overflow: hidden;
4294
- text-overflow: ellipsis;
4295
- }
4296
-
4297
- .float-item-size {
4298
- font-size: 11px;
4299
- color: var(--sfx-up-text-muted, #94a3b8);
4300
- }
4301
-
4302
- .float-item-done {
4303
- width: 18px;
4304
- height: 18px;
4305
- border-radius: 50%;
4306
- background: #f0fdf4;
4307
- color: #22c55e;
4308
- display: flex;
4309
- align-items: center;
4310
- justify-content: center;
4311
- flex-shrink: 0;
4312
- }
4313
-
4314
- .float-item-done svg { width: 12px; height: 12px; }
4315
-
4316
- .float-item-spinner {
4317
- width: 16px;
4318
- height: 16px;
4319
- border: 2px solid var(--sfx-up-border, #e8edf5);
4320
- border-top-color: var(--sfx-up-primary, #2563eb);
4321
- border-radius: 50%;
4322
- animation: spin 0.8s linear infinite;
4323
- flex-shrink: 0;
4324
- }
4325
-
4326
- .float-item-error-wrap {
4327
- position: relative;
4328
- display: flex;
4329
- align-items: center;
4330
- flex-shrink: 0;
4331
- }
4332
-
4333
- .float-item-error-icon {
4334
- width: 16px;
4335
- height: 16px;
4336
- color: #ef4444;
4337
- flex-shrink: 0;
4338
- cursor: pointer;
4339
- }
4340
-
4341
- .float-item-tooltip {
4342
- display: none;
4343
- position: absolute;
4344
- right: calc(100% + 8px);
4345
- top: 50%;
4346
- transform: translateY(-50%);
4347
- background: #fff;
4348
- color: #1e293b;
4349
- font-size: 11px;
4350
- padding: 6px 10px;
4351
- border-radius: 6px;
4352
- white-space: nowrap;
4353
- pointer-events: none;
4354
- z-index: 10;
4355
- box-shadow: 0 2px 12px rgba(0,0,0,0.12), 0 1px 4px rgba(0,0,0,0.08);
4356
- }
4357
-
4358
- .float-item-error-wrap:hover .float-item-tooltip {
4359
- display: block;
4360
- }
4361
-
4362
- .float-item-status {
4363
- display: flex;
4364
- flex-direction: row;
4365
- align-items: center;
4366
- gap: 4px;
4367
- flex-shrink: 0;
4368
- }
4369
-
4370
- .float-item-retry {
4371
- width: 24px;
4372
- height: 24px;
4373
- border: none;
4374
- background: none;
4375
- color: var(--sfx-up-primary, #2563eb);
4376
- cursor: pointer;
4377
- padding: 4px;
4378
- flex-shrink: 0;
4379
- display: flex;
4380
- align-items: center;
4381
- justify-content: center;
4382
- border-radius: 4px;
4383
- }
4384
-
4385
- .float-item-retry svg { width: 16px; height: 16px; }
4386
-
4387
- .float-item-retry:hover { background: var(--sfx-up-surface, #f8fafc); color: var(--sfx-up-primary-hover, #1d4ed8); }
4388
-
4389
- @keyframes floatSlideIn {
4390
- from { opacity: 0; transform: translateY(20px); }
4391
- to { opacity: 1; transform: translateY(0); }
4392
- }
4393
-
4394
- /* --- Connector modal overlay --- */
4395
- .connector-modal-backdrop {
4396
- position: fixed;
4397
- inset: 0;
4398
- z-index: 1000;
4399
- background: var(--sfx-up-backdrop);
4400
- backdrop-filter: blur(6px);
4401
- display: flex;
4402
- align-items: center;
4403
- justify-content: center;
4404
- padding: 20px;
4405
- animation: fadeIn 0.18s ease both;
4406
- }
4407
-
4408
- .connector-modal {
4409
- background: var(--sfx-up-bg, #fff);
4410
- border-radius: 12px;
4411
- box-shadow: 0 28px 80px var(--sfx-up-shadow, rgba(0, 0, 0, 0.18)), 0 4px 16px oklch(0 0 0 / 0.06);
4412
- width: 100%;
4413
- max-width: 520px;
4414
- height: 75vh;
4415
- max-height: 640px;
4416
- min-height: 400px;
4417
- overflow: hidden;
4418
- display: flex;
4419
- flex-direction: column;
4420
- animation: modalIn 0.28s cubic-bezier(0.34, 1.2, 0.64, 1) forwards;
4421
- }
4422
-
4423
- @keyframes fadeIn {
4424
- from { opacity: 0; }
4425
- to { opacity: 1; }
4426
- }
4427
-
4428
- @keyframes modalIn {
4429
- from {
4430
- opacity: 0;
4431
- transform: scale(0.92) translateY(10px);
4432
- }
4433
- to {
4434
- opacity: 1;
4435
- transform: scale(1) translateY(0);
4436
- }
4437
- }
4438
-
4439
- @keyframes inlineIn {
4440
- from { opacity: 0; }
4441
- to { opacity: 1; }
4442
- }
4443
-
4444
- /* --- Fullscreen preview overlay --- */
4445
- .fs-overlay {
4446
- position: fixed;
4447
- inset: 0;
4448
- z-index: 10000;
4449
- background: rgba(0, 0, 0, 0.92);
4450
- display: flex;
4451
- align-items: center;
4452
- justify-content: center;
4453
- animation: fadeIn 0.2s ease;
4454
- cursor: zoom-in;
4455
- }
4456
-
4457
- .fs-overlay.zoomed {
4458
- cursor: grab;
4459
- overflow: hidden;
4460
- }
4461
-
4462
- .fs-overlay.zoomed.panning {
4463
- cursor: grabbing;
4464
- }
4465
-
4466
- .fs-overlay.zoomed .fs-img {
4467
- max-width: none;
4468
- max-height: none;
4469
- width: auto;
4470
- height: auto;
4471
- }
4472
-
4473
- .fs-img {
4474
- max-width: 92vw;
4475
- max-height: 88vh;
4476
- object-fit: contain;
4477
- border-radius: 4px;
4478
- user-select: none;
4479
- -webkit-user-drag: none;
4480
- transition: transform 0.25s ease;
4481
- }
4482
-
4483
- .fs-overlay.panning .fs-img {
4484
- transition: none;
4485
- }
4486
-
4487
- .fs-toolbar {
4488
- position: fixed;
4489
- top: 16px;
4490
- right: 16px;
4491
- display: flex;
4492
- gap: 8px;
4493
- z-index: 10001;
4494
- }
4495
-
4496
- .fs-btn {
4497
- width: 40px;
4498
- height: 40px;
4499
- border-radius: 6px;
4500
- border: none;
4501
- background: rgba(255, 255, 255, 0.12);
4502
- backdrop-filter: blur(8px);
4503
- color: #fff;
4504
- cursor: pointer;
4505
- display: flex;
4506
- align-items: center;
4507
- justify-content: center;
4508
- transition: background 0.15s;
4509
- }
4510
-
4511
- .fs-btn:hover {
4512
- background: rgba(255, 255, 255, 0.25);
4513
- }
4514
-
4515
- .fs-btn svg {
4516
- width: 20px;
4517
- height: 20px;
4518
- }
4519
-
4520
- .fs-nav {
4521
- position: fixed;
4522
- top: 50%;
4523
- transform: translateY(-50%);
4524
- width: 44px;
4525
- height: 44px;
4526
- border-radius: 50%;
4527
- border: none;
4528
- background: rgba(255, 255, 255, 0.15);
4529
- backdrop-filter: blur(8px);
4530
- color: #fff;
4531
- cursor: pointer;
4532
- display: flex;
4533
- align-items: center;
4534
- justify-content: center;
4535
- z-index: 10001;
4536
- transition: background 0.15s;
4537
- padding: 0;
4538
- }
4539
-
4540
- .fs-nav:hover { background: rgba(255, 255, 255, 0.3); }
4541
- .fs-nav:disabled { opacity: 0.3; cursor: default; }
4542
- .fs-nav:disabled:hover { background: rgba(255, 255, 255, 0.15); }
4543
- .fs-nav svg { width: 22px; height: 22px; }
4544
- .fs-nav.prev { left: 20px; }
4545
- .fs-nav.next { right: 20px; }
4546
-
4547
- .fs-filename {
4548
- position: fixed;
4549
- bottom: 20px;
4550
- left: 50%;
4551
- transform: translateX(-50%);
4552
- color: rgba(255, 255, 255, 0.7);
4553
- font-size: 13px;
4554
- font-weight: 500;
4555
- background: rgba(0, 0, 0, 0.4);
4556
- backdrop-filter: blur(8px);
4557
- padding: 6px 16px;
4558
- border-radius: 8px;
4559
- white-space: nowrap;
4560
- z-index: 10001;
4561
- }
4562
-
4563
- .preview-nav:focus-visible,
4564
- .fs-btn:focus-visible {
4565
- outline: 2px solid var(--sfx-up-ring, oklch(0.578 0.198 268.129 / 0.7));
4566
- outline-offset: 2px;
4567
- }
4568
-
4569
- @media (prefers-reduced-motion: reduce) {
4570
- .modal-backdrop { animation: none; }
4571
- .modal-card { animation: none; }
4572
- .inline { animation: none; }
4573
- .fs-overlay { animation: none; }
4574
- .body.has-files { animation: none; }
4575
- }
4576
-
4577
- /* --- Responsive: Tablet (≤ 768px) --- */
4578
- @media (max-width: 768px) {
4579
- .modal-backdrop { padding: 12px; }
4580
- .modal-card { border-radius: 12px; max-height: 92vh; min-height: auto; }
4581
- .header { padding: 12px 16px; }
4582
- .header-icon { width: 28px; height: 28px; margin-right: 10px; }
4583
- .header-icon svg { width: 14px; height: 14px; }
4584
- .header-title { font-size: 14px; }
4585
- .body { padding: 16px; }
4586
- .body.has-files { padding: 0 0 12px 8px; }
4587
-
4588
- .preview-layout { flex-direction: column; }
4589
- .preview-layout .file-grid-side {
4590
- width: 100%;
4591
- max-height: 140px;
4592
- overflow-x: auto;
4593
- overflow-y: hidden;
4594
- flex-shrink: 0;
4595
- }
4596
- .preview-panel { padding: 0 0 16px; }
4597
-
4598
- .preview-topbar { padding: 8px 0; }
4599
-
4600
- .inline { border-radius: 12px; min-height: auto; }
4601
-
4602
- .connector-modal-backdrop { padding: 8px; }
4603
- .connector-modal {
4604
- max-width: 100%;
4605
- height: 85vh;
4606
- max-height: none;
4607
- border-radius: 14px;
4608
- }
4609
- }
4610
-
4611
- /* --- Responsive: Mobile (≤ 480px) --- */
4612
- @media (max-width: 480px) {
4613
- .modal-backdrop { padding: 0; }
4614
- .modal-card {
4615
- border-radius: 0;
4616
- max-height: 100vh;
4617
- max-width: 100%;
4618
- height: 100%;
4619
- }
4620
- .header { padding: 10px 14px; }
4621
- .header-icon { width: 26px; height: 26px; margin-right: 8px; }
4622
- .header-title { font-size: 14px; }
4623
- .body { padding: 12px; }
4624
- .body.has-files { padding: 0 0 8px 8px; }
4625
-
4626
- .preview-layout .file-grid-side { max-height: 100px; }
4627
- .preview-panel { padding: 0 0 12px; }
4628
- .preview-meta-row { padding: 6px 0; }
4629
- .preview-meta-label { width: 90px; font-size: 12px; }
4630
- .preview-meta-value { font-size: 12px; }
4631
-
4632
- .inline { max-height: 100vh; border-radius: 8px; box-shadow: none; }
4633
-
4634
- .connector-modal-backdrop { padding: 0; }
4635
- .connector-modal {
4636
- border-radius: 0;
4637
- height: 100vh;
4638
- min-height: auto;
4639
- }
4640
- }
4641
-
4642
- /* --- Responsive: Landscape / short viewports --- */
4643
- @media (max-height: 700px) {
4644
- .modal-card { min-height: auto; }
4645
- .inline { min-height: auto; }
4646
- }
4647
- `,$._MODIFIABLE_STATUSES=new Set(["idle","queued","rejected"]),$._RESERVED_IDS=new Set(["device","camera","url","screen-cast"]),$);k([c.property({attribute:!1})],y.prototype,"config");k([c.state()],y.prototype,"_isOpen");k([c.state()],y.prototype,"_activeConnector");k([c.state()],y.prototype,"_showUrlDialog");k([c.state()],y.prototype,"_showCameraDialog");k([c.state()],y.prototype,"_showScreenCastDialog");k([c.state()],y.prototype,"_previewFileId");k([c.state()],y.prototype,"_previewDims");k([c.state()],y.prototype,"_splitPct");k([c.state()],y.prototype,"_fullscreenPreviewUrl");k([c.state()],y.prototype,"_fullscreenVideoFile");k([c.state()],y.prototype,"_fullscreenZoomed");k([c.state()],y.prototype,"_bodyDragOver");k([c.state()],y.prototype,"_isMinimized");k([c.state()],y.prototype,"_isPillExpanded");let ut=y;exports.AuthExpiredError=ee;exports.CORE_SOURCES=A;exports.PublicEvents=g;exports.SfxActionsBar=P;exports.SfxCameraDialog=O;exports.SfxDropZone=C;exports.SfxFileItem=J;exports.SfxFileList=D;exports.SfxImportDivider=se;exports.SfxScreenCastDialog=j;exports.SfxSourcePills=Z;exports.SfxSuccessCard=F;exports.SfxUploader=ut;exports.SfxUrlDialog=I;exports.Store=Se;exports.UploadEngine=Pe;exports.buildAuthHeaders=K;exports.createStore=Ee;exports.exchangeSassKey=Ue;exports.getApiBase=te;exports.getAuthUrl=Le;exports.getProviderSources=De;exports.listFiles=Te;exports.listNextPage=Be;exports.logout=He;exports.resolveAuth=ze;exports.searchProvider=Ae;