@singlebase/elements 0.6.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/authui-display-C2o9gApg.cjs +961 -0
- package/dist/authui-display-C2o9gApg.cjs.map +1 -0
- package/dist/{authui-display-CKfGK5va.js → authui-display-CRUABt43.js} +1034 -913
- package/dist/authui-display-CRUABt43.js.map +1 -0
- package/dist/authui.cjs +1 -1
- package/dist/authui.js +2 -2
- package/dist/{chat-C-gsskho.cjs → chat-BWcGH9lr.cjs} +310 -287
- package/dist/chat-BWcGH9lr.cjs.map +1 -0
- package/dist/chat-messages.d.ts +8 -1
- package/dist/{chat-CEh6RygY.js → chat-t4o5FsxM.js} +796 -656
- package/dist/chat-t4o5FsxM.js.map +1 -0
- package/dist/chat.cjs +1 -1
- package/dist/chat.d.ts +1 -1
- package/dist/chat.js +1 -1
- package/dist/elements/authui-account.d.ts +0 -1
- package/dist/elements/authui-buttons.d.ts +1 -1
- package/dist/elements/authui.d.ts +25 -5
- package/dist/elements/chat.d.ts +46 -8
- package/dist/elements/uploader.d.ts +0 -6
- package/dist/files-4T62wkwj.cjs +77 -0
- package/dist/files-4T62wkwj.cjs.map +1 -0
- package/dist/{files-DDJWPzZW.js → files-DS-H-3yN.js} +56 -57
- package/dist/files-DS-H-3yN.js.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.js +4 -4
- package/dist/messages.d.ts +34 -5
- package/dist/singlebase-elements.min.js +2555 -2292
- package/dist/singlebase-elements.min.js.map +1 -1
- package/dist/upload-messages.d.ts +0 -1
- package/dist/{uploader-660JIgIN.cjs → uploader-C57vgFME.cjs} +33 -7
- package/dist/uploader-C57vgFME.cjs.map +1 -0
- package/dist/{uploader-vfczkX51.js → uploader-Cz9yfzfV.js} +261 -262
- package/dist/uploader-Cz9yfzfV.js.map +1 -0
- package/dist/uploader.cjs +1 -1
- package/dist/uploader.js +2 -2
- package/dist/utils/auth-errors.d.ts +7 -0
- package/dist/utils/branding.d.ts +5 -5
- package/dist/utils/oauth.d.ts +24 -0
- package/dist/utils/password.d.ts +16 -0
- package/package.json +3 -3
- package/dist/authui-display-CKfGK5va.js.map +0 -1
- package/dist/authui-display-aWNht0cW.cjs +0 -956
- package/dist/authui-display-aWNht0cW.cjs.map +0 -1
- package/dist/chat-C-gsskho.cjs.map +0 -1
- package/dist/chat-CEh6RygY.js.map +0 -1
- package/dist/files-DDJWPzZW.js.map +0 -1
- package/dist/files-DyxcjZsx.cjs +0 -75
- package/dist/files-DyxcjZsx.cjs.map +0 -1
- package/dist/uploader-660JIgIN.cjs.map +0 -1
- package/dist/uploader-vfczkX51.js.map +0 -1
|
@@ -37,7 +37,6 @@ export interface SinglebaseUploadMessages {
|
|
|
37
37
|
errUpload: string;
|
|
38
38
|
errProtected: string;
|
|
39
39
|
errTooManyPages: string;
|
|
40
|
-
brandingLabel: string;
|
|
41
40
|
}
|
|
42
41
|
export declare const defaultUploadMessages: SinglebaseUploadMessages;
|
|
43
42
|
export declare function resolveUploadMessages(overrides?: Partial<SinglebaseUploadMessages>): SinglebaseUploadMessages;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var le=r=>{throw TypeError(r)};var de=(r,a,e)=>a.has(r)||le("Cannot "+e);var l=(r,a,e)=>(de(r,a,"read from private field"),e?e.call(r):a.get(r)),d=(r,a,e)=>a.has(r)?le("Cannot add the same private member more than once"):a instanceof WeakSet?a.add(r):a.set(r,e),c=(r,a,e,t)=>(de(r,a,"write to private field"),t?t.call(r,e):a.set(r,e),e);const s=require("lit"),p=require("lit/decorators.js"),ke=require("@singlebase/core"),f=require("./files-4T62wkwj.cjs"),fe=s.css`
|
|
2
2
|
/* ── layout primitives ───────────────────────────────────── */
|
|
3
3
|
.stack {
|
|
4
4
|
display: flex;
|
|
@@ -84,6 +84,32 @@
|
|
|
84
84
|
text-wrap: pretty;
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
+
.pw-rules {
|
|
88
|
+
margin-top: 6px;
|
|
89
|
+
font-size: 12px;
|
|
90
|
+
line-height: 1.5;
|
|
91
|
+
color: var(--sb-muted-ink, #61666c);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.pw-rules summary {
|
|
95
|
+
cursor: pointer;
|
|
96
|
+
width: fit-content;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.pw-rules summary:hover {
|
|
100
|
+
color: var(--sb-ink, #16181a);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.pw-rules ul {
|
|
104
|
+
margin: 4px 0 0;
|
|
105
|
+
padding-left: 18px;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.consent {
|
|
109
|
+
text-align: center;
|
|
110
|
+
text-wrap: balance;
|
|
111
|
+
}
|
|
112
|
+
|
|
87
113
|
.sub-label {
|
|
88
114
|
font-family: var(--sb-mono, "Geist Mono", ui-monospace, monospace);
|
|
89
115
|
font-size: 11px;
|
|
@@ -974,8 +1000,8 @@
|
|
|
974
1000
|
color: var(--sb-muted-ink, #61666c);
|
|
975
1001
|
font-style: italic;
|
|
976
1002
|
}
|
|
977
|
-
`;function
|
|
978
|
-
`||a[m-1]==="\r");)m-=1;t+=1;try{const o=await ke(r.subarray(g,m),"deflate");e+=re(o)}catch{}}return e?we(e):null}async function je(r,a){const e=await te(r.slice(0,8));if(Ee(e))return{pages:null,encrypted:!0};if(e[0]!==80||e[1]!==75)return me;const t=await Fe(r,"docProps/app.xml");if(!t)return{pages:null,encrypted:!1};const i=a==="pptx"?"Slides":"Pages",g=new TextDecoder().decode(t).match(new RegExp(`<${i}>(\\d+)</${i}>`));return{pages:g?Number(g[1]):null,encrypted:!1}}function Ee(r){return[208,207,17,224,161,177,26,225].every((e,t)=>r[t]===e)}async function Fe(r,a){const e=Math.min(r.size,66e3),t=new DataView(await r.slice(r.size-e).arrayBuffer());let i=-1;for(let h=t.byteLength-22;h>=0;h--)if(t.getUint32(h,!0)===101010256){i=h;break}if(i<0)return null;const g=t.getUint32(i+12,!0),m=t.getUint32(i+16,!0);if(!g||m===4294967295)return null;const o=new DataView(await r.slice(m,m+g).arrayBuffer()),n=new TextDecoder;let b=0;for(;b+46<=o.byteLength&&o.getUint32(b,!0)===33639248;){const h=o.getUint16(b+10,!0),x=o.getUint32(b+20,!0),v=o.getUint16(b+28,!0),ee=o.getUint16(b+30,!0),ie=o.getUint16(b+32,!0),ae=o.getUint32(b+42,!0);if(n.decode(new Uint8Array(o.buffer,o.byteOffset+b+46,v))===a){const ne=new DataView(await r.slice(ae,ae+30).arrayBuffer()),le=ae+30+ne.getUint16(26,!0)+ne.getUint16(28,!0),de=await te(r.slice(le,le+x));return h===0?de:h===8&&typeof DecompressionStream<"u"?await ke(de,"deflate-raw"):null}b+=46+v+ee+ie}return null}async function te(r){return new Uint8Array(await r.arrayBuffer())}async function ke(r,a){const e=new Blob([r]).stream().pipeThrough(new DecompressionStream(a));return new Uint8Array(await new Response(e).arrayBuffer())}function re(r){let a="";for(let t=0;t<r.length;t+=32768)a+=String.fromCharCode(...r.subarray(t,t+32768));return a}var ze=Object.defineProperty,Oe=Object.getOwnPropertyDescriptor,De=(r,a,e)=>a in r?ze(r,a,{enumerable:!0,configurable:!0,writable:!0,value:e}):r[a]=e,u=(r,a,e,t)=>{for(var i=t>1?void 0:t?Oe(a,e):a,g=r.length-1,m;g>=0;g--)(m=r[g])&&(i=(t?m(a,e,i):m(i))||i);return t&&i&&ze(a,e,i),i},Le=(r,a,e)=>De(r,a+"",e);const se={fromAttribute:r=>{if(!r)return{};try{const a=JSON.parse(r);return a&&typeof a=="object"?a:{}}catch{return console.warn("[singlebase-uploader] an attribute holds invalid JSON; ignoring it"),{}}},toAttribute:r=>JSON.stringify(r??{})},oe={fromAttribute:r=>r===null?!0:r!=="false",toAttribute:r=>r?null:"false"},fe=["view","dropzone","allowRename","autoUpload","branding","brandingText","brandingUrl","logoUrl","logoText","heading","description","maxFiles","maxSize","minSize","accept","rules","bucket","publicRead","redirectUrl","metadata","options","messages","theme","density","radius","onComplete","onError"];var w,k,z,U,$,S,M,C,T,j,E,F,O,D,L,A,N,P,R,B,I,G,_,q,K,V,Y,H,J,X,W,Z,Q,ge;exports.SinglebaseUploader=(ge=class extends s.LitElement{constructor(){super(...arguments);d(this,w,null);d(this,k,{});d(this,z);d(this,U);d(this,$);d(this,S,"full");d(this,M,!0);d(this,C,!0);d(this,T,!1);d(this,j,!0);d(this,E,"");d(this,F,"");d(this,O,"");d(this,D,"");d(this,L,"");d(this,A,"");d(this,N,10);d(this,P,"25MB");d(this,R,0);d(this,B,"");d(this,I,{});d(this,G,"default");d(this,_,{});d(this,q,{});d(this,K,!1);d(this,V,"");d(this,Y,null);d(this,H,null);d(this,J,[]);d(this,X,"");d(this,W,!1);d(this,Z,!1);d(this,Q,"")}get client(){return l(this,w)}set client(e){c(this,w,e)}get messages(){return l(this,k)}set messages(e){c(this,k,e)}get theme(){return l(this,z)}set theme(e){c(this,z,e)}get density(){return l(this,U)}set density(e){c(this,U,e)}get radius(){return l(this,$)}set radius(e){c(this,$,e)}get view(){return l(this,S)}set view(e){c(this,S,e)}get dropzone(){return l(this,M)}set dropzone(e){c(this,M,e)}get allowRename(){return l(this,C)}set allowRename(e){c(this,C,e)}get autoUpload(){return l(this,T)}set autoUpload(e){c(this,T,e)}get branding(){return l(this,j)}set branding(e){c(this,j,e)}get brandingText(){return l(this,E)}set brandingText(e){c(this,E,e)}get brandingUrl(){return l(this,F)}set brandingUrl(e){c(this,F,e)}get logoUrl(){return l(this,O)}set logoUrl(e){c(this,O,e)}get logoText(){return l(this,D)}set logoText(e){c(this,D,e)}get heading(){return l(this,L)}set heading(e){c(this,L,e)}get description(){return l(this,A)}set description(e){c(this,A,e)}get maxFiles(){return l(this,N)}set maxFiles(e){c(this,N,e)}get maxSize(){return l(this,P)}set maxSize(e){c(this,P,e)}get minSize(){return l(this,R)}set minSize(e){c(this,R,e)}get accept(){return l(this,B)}set accept(e){c(this,B,e)}get rules(){return l(this,I)}set rules(e){c(this,I,e)}get bucket(){return l(this,G)}set bucket(e){c(this,G,e)}get metadata(){return l(this,_)}set metadata(e){c(this,_,e)}get options(){return l(this,q)}set options(e){c(this,q,e)}get publicRead(){return l(this,K)}set publicRead(e){c(this,K,e)}get redirectUrl(){return l(this,V)}set redirectUrl(e){c(this,V,e)}get onComplete(){return l(this,Y)}set onComplete(e){c(this,Y,e)}get onError(){return l(this,H)}set onError(e){c(this,H,e)}get items(){return l(this,J)}set items(e){c(this,J,e)}get notice(){return l(this,X)}set notice(e){c(this,X,e)}get busy(){return l(this,W)}set busy(e){c(this,W,e)}get dragging(){return l(this,Z)}set dragging(e){c(this,Z,e)}get editing(){return l(this,Q)}set editing(e){c(this,Q,e)}get msg(){return f.resolveUploadMessages(this.messages)}get resolvedClient(){return this.client??Ue.getDefaultClient()??null}get files(){return this.items}get percent(){const e=this.items.filter(t=>t.status!=="ready");return e.length?Math.round(e.reduce((t,i)=>t+i.percent,0)/e.length):0}open(){var e;(e=this.renderRoot.querySelector("input[type=file]"))==null||e.click()}set config(e){const t=this;for(const i of fe)e&&i in e&&(t[i]=e[i])}configure(e){return this.config=e,this}get config(){const e=this;return Object.fromEntries(fe.map(t=>[t,e[t]]))}clear(){this.items.forEach(y),this.items=[],this.notice=""}disconnectedCallback(){super.disconnectedCallback(),this.items.forEach(y)}async upload(){var m;if(this.busy)return;const e=this.items.filter(o=>o.status==="ready"||o.status==="error");if(!e.length)return;const t=this.resolvedClient;if(!t){this.fail(this.msg.errNoClient);return}this.busy=!0,this.notice="";for(const o of e)o.status="uploading",o.percent=0,o.error="";this.items=[...this.items];const i=new Map,g=e.map(o=>{const n={file:o.file,filename:o.file.name};return this.bucket&&(n.bucket=this.bucket),this.publicRead&&(n.publicRead=!0),o.name!==o.file.name&&(n.newName=o.name),Object.keys(this.metadata??{}).length&&(n.metadata={...this.metadata}),Object.keys(this.options??{}).length&&(n.options={...this.options}),i.set(n,o),n});try{const o=await t.files.upload(g,{onProgress:h=>{const x=i.get(h.input);x&&(x.percent=h.percent,this.items=[...this.items],this.emit("singlebase-upload-progress",{file:x,percent:this.percent}))}});for(const h of o.completed){const x=i.get(h.input);x&&(x.status="done",x.percent=100,x.record=h.file)}for(const h of o.failed){const x=i.get(h.input);x&&(x.status="error",x.error=h.error.message||h.error.code)}this.items=[...this.items];const n=o.completed.map(h=>i.get(h.input)).filter(Boolean),b=o.failed.map(h=>i.get(h.input)).filter(Boolean);this.emit("singlebase-upload-complete",{completed:n,failed:b}),(m=this.onComplete)==null||m.call(this,{completed:n,failed:b}),b.length?this.notice=this.msg.errUpload:this.redirect()}catch(o){for(const n of e)n.status="error",n.error="";this.items=[...this.items],this.fail(Ne(o)||this.msg.errUpload)}finally{this.busy=!1}}ruleFor(e){const t=f.fileExtension(e);if(!t)return null;for(const[i,g]of Object.entries(this.rules??{}))if(i.toLowerCase().replace(/^\./,"")===t)return g;return null}async add(e){if(this.view==="button"){const n=this.items.filter(b=>b.status==="done"||b.status==="error");n.forEach(y),this.items=this.items.filter(b=>!n.includes(b))}const t=this.maxFiles>0?this.maxFiles:Number.POSITIVE_INFINITY,i=[...this.items],g=i.length,m=[];let o="";for(const n of Array.from(e)){if(i.length>=t){o=f.fill(this.msg.errTooMany,{max:t});break}if(this.accept&&!f.acceptsFile(this.accept,n.name,n.type)){o=f.fill(this.msg.errType,{name:n.name});continue}const b=this.ruleFor(n.name),h=f.parseSize((b==null?void 0:b.maxSize)??this.maxSize),x=f.parseSize((b==null?void 0:b.minSize)??this.minSize);if(h&&n.size>h){o=f.fill(this.msg.errTooLarge,{name:n.name,size:f.formatSize(h)});continue}if(x&&n.size<x){o=f.fill(this.msg.errTooSmall,{name:n.name,size:f.formatSize(x)});continue}const v=f.fileKey(n);if(i.some(ie=>ie.key===v)){o=f.fill(this.msg.errDuplicate,{name:n.name});continue}const ee={key:v,file:n,name:n.name,status:this.needsInspection(b,n.name)?"checking":"ready",percent:0,error:"",record:null,pages:null,encrypted:null,preview:Ae(n)};i.push(ee),m.push(ee)}this.notice=o,o&&this.emit("singlebase-upload-rejected",{message:o}),i.length!==g&&(this.items=i,this.emit("singlebase-upload-selected",{files:this.items}),await Promise.all(m.filter(n=>n.status==="checking").map(n=>this.inspect(n,this.ruleFor(n.file.name)))),(this.autoUpload||this.view==="button")&&this.upload())}needsInspection(e,t){return!e||!ye(f.fileExtension(t))?!1:e.maxPages!==void 0||e.allowProtected===!1}async inspect(e,t){const i=await ve(e.file,f.fileExtension(e.file.name));e.pages=i.pages,e.encrypted=i.encrypted;let g="";t.allowProtected===!1&&i.encrypted===!0?g=f.fill(this.msg.errProtected,{name:e.name}):t.maxPages&&i.pages!==null&&i.pages>t.maxPages&&(g=f.fill(this.msg.errTooManyPages,{name:e.name,pages:i.pages,max:t.maxPages})),g?(y(e),this.items=this.items.filter(m=>m!==e),this.notice=g,this.emit("singlebase-upload-rejected",{message:g})):(e.status="ready",this.items=[...this.items])}removeItem(e){this.items.filter(t=>t.key===e).forEach(y),this.items=this.items.filter(t=>t.key!==e),this.notice=""}commitRename(e,t){e.name=f.renameKeepingExtension(e.file.name,t),this.editing="",this.items=[...this.items]}fail(e){var t;this.notice=e,this.emit("singlebase-upload-error",{message:e}),(t=this.onError)==null||t.call(this,{message:e})}emit(e,t){this.dispatchEvent(new CustomEvent(e,{detail:t,bubbles:!0,composed:!0}))}redirect(){if(!this.redirectUrl||typeof location>"u")return;const e=he(this.redirectUrl,location.href,t=>console.warn(`[singlebase-uploader] ${t}`));e&&location.assign(e)}onPick(e){var i;const t=e.target;(i=t.files)!=null&&i.length&&this.add(t.files),t.value=""}onDrop(e){var i;e.preventDefault(),this.dragging=!1;const t=(i=e.dataTransfer)==null?void 0:i.files;t!=null&&t.length&&this.add(t)}onDragOver(e){e.preventDefault(),this.dragging=!0}onDragLeave(){this.dragging=!1}get canAddMore(){return this.maxFiles<=0||this.items.length<this.maxFiles}get checking(){return this.items.some(e=>e.status==="checking")}get pendingCount(){return this.items.filter(e=>e.status==="ready"||e.status==="error").length}get hint(){const e=f.acceptSummary(this.accept),t=f.parseSize(this.maxSize),i=t?f.fill(this.msg.hintUpTo,{size:f.formatSize(t)}):"";return[e,i].filter(Boolean).join(" · ")}renderInput(){return s.html`<input
|
|
1003
|
+
`;function ge(r,a,e){if(!r||!a)return null;let t;try{t=new URL(a)}catch{return null}let i;try{i=new URL(r,t.href)}catch{return e==null||e(`"${r}" is not a valid URL`),null}return i.protocol!=="http:"&&i.protocol!=="https:"?(e==null||e(`refusing redirect to unsupported scheme "${i.protocol}"`),null):i.origin!==t.origin?(e==null||e(`refusing cross-origin redirect to ${i.origin}; same-origin only`),null):i.href===t.href?null:i.href}const be={pages:null,encrypted:null},ce=16*1024*1024,ze=2*1024*1024,$e=40,Ue=4*1024*1024,he=new Set(["docx","pptx","xlsx"]);async function me(r,a){try{if(a==="pdf")return await Se(r);if(he.has(a))return await Ce(r,a)}catch{}return be}function xe(r){return r==="pdf"||he.has(r)}async function Se(r){const a=await Q(r.slice(0,ce)),e=r.size>ce?await Q(r.slice(Math.max(0,r.size-ze))):null,t=ee(a)+(e?ee(e):""),i=/\/Encrypt[\s/<>\]]/.test(t);let g=ve(t);return g===null&&(g=await Me(a)),{pages:g,encrypted:i}}function ve(r){if(/\/Type\s*\/Pages/.test(r)){let e=0;for(const t of r.matchAll(/\/Count\s+(\d+)/g))e=Math.max(e,Number(t[1]));if(e>0)return e}const a=r.match(/\/Type\s*\/Page[^s]/g);return a!=null&&a.length?a.length:null}async function Me(r){if(typeof DecompressionStream>"u")return null;const a=ee(r);let e="",t=0;for(const i of a.matchAll(/stream\r?\n/g)){if(t>=$e||e.length>=Ue)break;const g=i.index+i[0].length;let m=a.indexOf("endstream",g);if(m<0)break;for(;m>g&&(a[m-1]===`
|
|
1004
|
+
`||a[m-1]==="\r");)m-=1;t+=1;try{const o=await ye(r.subarray(g,m),"deflate");e+=ee(o)}catch{}}return e?ve(e):null}async function Ce(r,a){const e=await Q(r.slice(0,8));if(je(e))return{pages:null,encrypted:!0};if(e[0]!==80||e[1]!==75)return be;const t=await Fe(r,"docProps/app.xml");if(!t)return{pages:null,encrypted:!1};const i=a==="pptx"?"Slides":"Pages",g=new TextDecoder().decode(t).match(new RegExp(`<${i}>(\\d+)</${i}>`));return{pages:g?Number(g[1]):null,encrypted:!1}}function je(r){return[208,207,17,224,161,177,26,225].every((e,t)=>r[t]===e)}async function Fe(r,a){const e=Math.min(r.size,66e3),t=new DataView(await r.slice(r.size-e).arrayBuffer());let i=-1;for(let h=t.byteLength-22;h>=0;h--)if(t.getUint32(h,!0)===101010256){i=h;break}if(i<0)return null;const g=t.getUint32(i+12,!0),m=t.getUint32(i+16,!0);if(!g||m===4294967295)return null;const o=new DataView(await r.slice(m,m+g).arrayBuffer()),n=new TextDecoder;let b=0;for(;b+46<=o.byteLength&&o.getUint32(b,!0)===33639248;){const h=o.getUint16(b+10,!0),x=o.getUint32(b+20,!0),v=o.getUint16(b+28,!0),Z=o.getUint16(b+30,!0),te=o.getUint16(b+32,!0),re=o.getUint32(b+42,!0);if(n.decode(new Uint8Array(o.buffer,o.byteOffset+b+46,v))===a){const se=new DataView(await r.slice(re,re+30).arrayBuffer()),oe=re+30+se.getUint16(26,!0)+se.getUint16(28,!0),ne=await Q(r.slice(oe,oe+x));return h===0?ne:h===8&&typeof DecompressionStream<"u"?await ye(ne,"deflate-raw"):null}b+=46+v+Z+te}return null}async function Q(r){return new Uint8Array(await r.arrayBuffer())}async function ye(r,a){const e=new Blob([r]).stream().pipeThrough(new DecompressionStream(a));return new Uint8Array(await new Response(e).arrayBuffer())}function ee(r){let a="";for(let t=0;t<r.length;t+=32768)a+=String.fromCharCode(...r.subarray(t,t+32768));return a}var we=Object.defineProperty,Ee=Object.getOwnPropertyDescriptor,Oe=(r,a,e)=>a in r?we(r,a,{enumerable:!0,configurable:!0,writable:!0,value:e}):r[a]=e,u=(r,a,e,t)=>{for(var i=t>1?void 0:t?Ee(a,e):a,g=r.length-1,m;g>=0;g--)(m=r[g])&&(i=(t?m(a,e,i):m(i))||i);return t&&i&&we(a,e,i),i},De=(r,a,e)=>Oe(r,a+"",e);const ie={fromAttribute:r=>{if(!r)return{};try{const a=JSON.parse(r);return a&&typeof a=="object"?a:{}}catch{return console.warn("[singlebase-uploader] an attribute holds invalid JSON; ignoring it"),{}}},toAttribute:r=>JSON.stringify(r??{})},ae={fromAttribute:r=>r===null?!0:r!=="false",toAttribute:r=>r?null:"false"},pe=["view","dropzone","allowRename","autoUpload","branding","logoUrl","logoText","heading","description","maxFiles","maxSize","minSize","accept","rules","bucket","publicRead","redirectUrl","metadata","options","messages","theme","density","radius","onComplete","onError"];var w,k,z,$,U,S,M,C,j,F,E,O,D,T,L,A,N,P,R,B,I,G,_,q,K,V,Y,H,J,X,W,ue;exports.SinglebaseUploader=(ue=class extends s.LitElement{constructor(){super(...arguments);d(this,w,null);d(this,k,{});d(this,z);d(this,$);d(this,U);d(this,S,"full");d(this,M,!0);d(this,C,!0);d(this,j,!1);d(this,F,!0);d(this,E,"");d(this,O,"");d(this,D,"");d(this,T,"");d(this,L,10);d(this,A,"25MB");d(this,N,0);d(this,P,"");d(this,R,{});d(this,B,"default");d(this,I,{});d(this,G,{});d(this,_,!1);d(this,q,"");d(this,K,null);d(this,V,null);d(this,Y,[]);d(this,H,"");d(this,J,!1);d(this,X,!1);d(this,W,"")}get client(){return l(this,w)}set client(e){c(this,w,e)}get messages(){return l(this,k)}set messages(e){c(this,k,e)}get theme(){return l(this,z)}set theme(e){c(this,z,e)}get density(){return l(this,$)}set density(e){c(this,$,e)}get radius(){return l(this,U)}set radius(e){c(this,U,e)}get view(){return l(this,S)}set view(e){c(this,S,e)}get dropzone(){return l(this,M)}set dropzone(e){c(this,M,e)}get allowRename(){return l(this,C)}set allowRename(e){c(this,C,e)}get autoUpload(){return l(this,j)}set autoUpload(e){c(this,j,e)}get branding(){return l(this,F)}set branding(e){c(this,F,e)}get logoUrl(){return l(this,E)}set logoUrl(e){c(this,E,e)}get logoText(){return l(this,O)}set logoText(e){c(this,O,e)}get heading(){return l(this,D)}set heading(e){c(this,D,e)}get description(){return l(this,T)}set description(e){c(this,T,e)}get maxFiles(){return l(this,L)}set maxFiles(e){c(this,L,e)}get maxSize(){return l(this,A)}set maxSize(e){c(this,A,e)}get minSize(){return l(this,N)}set minSize(e){c(this,N,e)}get accept(){return l(this,P)}set accept(e){c(this,P,e)}get rules(){return l(this,R)}set rules(e){c(this,R,e)}get bucket(){return l(this,B)}set bucket(e){c(this,B,e)}get metadata(){return l(this,I)}set metadata(e){c(this,I,e)}get options(){return l(this,G)}set options(e){c(this,G,e)}get publicRead(){return l(this,_)}set publicRead(e){c(this,_,e)}get redirectUrl(){return l(this,q)}set redirectUrl(e){c(this,q,e)}get onComplete(){return l(this,K)}set onComplete(e){c(this,K,e)}get onError(){return l(this,V)}set onError(e){c(this,V,e)}get items(){return l(this,Y)}set items(e){c(this,Y,e)}get notice(){return l(this,H)}set notice(e){c(this,H,e)}get busy(){return l(this,J)}set busy(e){c(this,J,e)}get dragging(){return l(this,X)}set dragging(e){c(this,X,e)}get editing(){return l(this,W)}set editing(e){c(this,W,e)}get msg(){return f.resolveUploadMessages(this.messages)}get resolvedClient(){return this.client??ke.getDefaultClient()??null}get files(){return this.items}get percent(){const e=this.items.filter(t=>t.status!=="ready");return e.length?Math.round(e.reduce((t,i)=>t+i.percent,0)/e.length):0}open(){var e;(e=this.renderRoot.querySelector("input[type=file]"))==null||e.click()}set config(e){const t=this;for(const i of pe)e&&i in e&&(t[i]=e[i])}configure(e){return this.config=e,this}get config(){const e=this;return Object.fromEntries(pe.map(t=>[t,e[t]]))}clear(){this.items.forEach(y),this.items=[],this.notice=""}disconnectedCallback(){super.disconnectedCallback(),this.items.forEach(y)}async upload(){var m;if(this.busy)return;const e=this.items.filter(o=>o.status==="ready"||o.status==="error");if(!e.length)return;const t=this.resolvedClient;if(!t){this.fail(this.msg.errNoClient);return}this.busy=!0,this.notice="";for(const o of e)o.status="uploading",o.percent=0,o.error="";this.items=[...this.items];const i=new Map,g=e.map(o=>{const n={file:o.file,filename:o.file.name};return this.bucket&&(n.bucket=this.bucket),this.publicRead&&(n.publicRead=!0),o.name!==o.file.name&&(n.newName=o.name),Object.keys(this.metadata??{}).length&&(n.metadata={...this.metadata}),Object.keys(this.options??{}).length&&(n.options={...this.options}),i.set(n,o),n});try{const o=await t.files.upload(g,{onProgress:h=>{const x=i.get(h.input);x&&(x.percent=h.percent,this.items=[...this.items],this.emit("singlebase-upload-progress",{file:x,percent:this.percent}))}});for(const h of o.completed){const x=i.get(h.input);x&&(x.status="done",x.percent=100,x.record=h.file)}for(const h of o.failed){const x=i.get(h.input);x&&(x.status="error",x.error=h.error.message||h.error.code)}this.items=[...this.items];const n=o.completed.map(h=>i.get(h.input)).filter(Boolean),b=o.failed.map(h=>i.get(h.input)).filter(Boolean);this.emit("singlebase-upload-complete",{completed:n,failed:b}),(m=this.onComplete)==null||m.call(this,{completed:n,failed:b}),b.length?this.notice=this.msg.errUpload:this.redirect()}catch(o){for(const n of e)n.status="error",n.error="";this.items=[...this.items],this.fail(Le(o)||this.msg.errUpload)}finally{this.busy=!1}}ruleFor(e){const t=f.fileExtension(e);if(!t)return null;for(const[i,g]of Object.entries(this.rules??{}))if(i.toLowerCase().replace(/^\./,"")===t)return g;return null}async add(e){if(this.view==="button"){const n=this.items.filter(b=>b.status==="done"||b.status==="error");n.forEach(y),this.items=this.items.filter(b=>!n.includes(b))}const t=this.maxFiles>0?this.maxFiles:Number.POSITIVE_INFINITY,i=[...this.items],g=i.length,m=[];let o="";for(const n of Array.from(e)){if(i.length>=t){o=f.fill(this.msg.errTooMany,{max:t});break}if(this.accept&&!f.acceptsFile(this.accept,n.name,n.type)){o=f.fill(this.msg.errType,{name:n.name});continue}const b=this.ruleFor(n.name),h=f.parseSize((b==null?void 0:b.maxSize)??this.maxSize),x=f.parseSize((b==null?void 0:b.minSize)??this.minSize);if(h&&n.size>h){o=f.fill(this.msg.errTooLarge,{name:n.name,size:f.formatSize(h)});continue}if(x&&n.size<x){o=f.fill(this.msg.errTooSmall,{name:n.name,size:f.formatSize(x)});continue}const v=f.fileKey(n);if(i.some(te=>te.key===v)){o=f.fill(this.msg.errDuplicate,{name:n.name});continue}const Z={key:v,file:n,name:n.name,status:this.needsInspection(b,n.name)?"checking":"ready",percent:0,error:"",record:null,pages:null,encrypted:null,preview:Te(n)};i.push(Z),m.push(Z)}this.notice=o,o&&this.emit("singlebase-upload-rejected",{message:o}),i.length!==g&&(this.items=i,this.emit("singlebase-upload-selected",{files:this.items}),await Promise.all(m.filter(n=>n.status==="checking").map(n=>this.inspect(n,this.ruleFor(n.file.name)))),(this.autoUpload||this.view==="button")&&this.upload())}needsInspection(e,t){return!e||!xe(f.fileExtension(t))?!1:e.maxPages!==void 0||e.allowProtected===!1}async inspect(e,t){const i=await me(e.file,f.fileExtension(e.file.name));e.pages=i.pages,e.encrypted=i.encrypted;let g="";t.allowProtected===!1&&i.encrypted===!0?g=f.fill(this.msg.errProtected,{name:e.name}):t.maxPages&&i.pages!==null&&i.pages>t.maxPages&&(g=f.fill(this.msg.errTooManyPages,{name:e.name,pages:i.pages,max:t.maxPages})),g?(y(e),this.items=this.items.filter(m=>m!==e),this.notice=g,this.emit("singlebase-upload-rejected",{message:g})):(e.status="ready",this.items=[...this.items])}removeItem(e){this.items.filter(t=>t.key===e).forEach(y),this.items=this.items.filter(t=>t.key!==e),this.notice=""}commitRename(e,t){e.name=f.renameKeepingExtension(e.file.name,t),this.editing="",this.items=[...this.items]}fail(e){var t;this.notice=e,this.emit("singlebase-upload-error",{message:e}),(t=this.onError)==null||t.call(this,{message:e})}emit(e,t){this.dispatchEvent(new CustomEvent(e,{detail:t,bubbles:!0,composed:!0}))}redirect(){if(!this.redirectUrl||typeof location>"u")return;const e=ge(this.redirectUrl,location.href,t=>console.warn(`[singlebase-uploader] ${t}`));e&&location.assign(e)}onPick(e){var i;const t=e.target;(i=t.files)!=null&&i.length&&this.add(t.files),t.value=""}onDrop(e){var i;e.preventDefault(),this.dragging=!1;const t=(i=e.dataTransfer)==null?void 0:i.files;t!=null&&t.length&&this.add(t)}onDragOver(e){e.preventDefault(),this.dragging=!0}onDragLeave(){this.dragging=!1}get canAddMore(){return this.maxFiles<=0||this.items.length<this.maxFiles}get checking(){return this.items.some(e=>e.status==="checking")}get pendingCount(){return this.items.filter(e=>e.status==="ready"||e.status==="error").length}get hint(){const e=f.acceptSummary(this.accept),t=f.parseSize(this.maxSize),i=t?f.fill(this.msg.hintUpTo,{size:f.formatSize(t)}):"";return[e,i].filter(Boolean).join(" · ")}renderInput(){return s.html`<input
|
|
979
1005
|
class="sr-only"
|
|
980
1006
|
type="file"
|
|
981
1007
|
?multiple=${this.maxFiles!==1}
|
|
@@ -986,7 +1012,7 @@
|
|
|
986
1012
|
src=${this.logoUrl}
|
|
987
1013
|
alt=${this.logoText||"Logo"}
|
|
988
1014
|
part="logo"
|
|
989
|
-
/>`:this.logoText?s.html`<div class="brand-mark" part="logo">${this.logoText}</div>`:s.nothing}renderBranding(){return f.renderBranding(this.branding,
|
|
1015
|
+
/>`:this.logoText?s.html`<div class="brand-mark" part="logo">${this.logoText}</div>`:s.nothing}renderBranding(){return f.renderBranding(this.branding,"Files")}renderNotice(){return this.notice?s.html`<div class="banner" role="alert" part="error">${this.notice}</div>`:s.nothing}renderCount(){if(!this.items.length)return s.nothing;const e=this.items.length===1?this.msg.countOne:this.msg.countMany;return s.html`<div class="count" part="count">
|
|
990
1016
|
${f.fill(e,{n:this.items.length,max:this.maxFiles})}
|
|
991
1017
|
</div>`}renderStatus(e){const t=f.formatSize(e.file.size);if(e.status==="checking")return`${t} · ${this.msg.checking}`;if(e.status==="uploading")return`${t} · ${this.msg.uploading}`;if(e.status==="done")return`${t} · ${this.msg.uploaded}`;if(e.status==="error")return`${t} · ${e.error||this.msg.failedLabel}`;const i=e.pages?` · ${f.fill(this.msg.pagesLabel,{n:e.pages})}`:"";return t+i}renderRow(e){const t=this.allowRename&&e.status==="ready";return e.status==="uploading"||e.status,s.html`<div class="row" part="file">
|
|
992
1018
|
<div class="chip" part="file-type">
|
|
@@ -1076,7 +1102,7 @@
|
|
|
1076
1102
|
</button>
|
|
1077
1103
|
${e&&e.status!=="ready"?s.html`<div class="sz" data-state=${e.status}>${this.renderStatus(e)}</div>`:s.nothing}
|
|
1078
1104
|
${this.renderNotice()}
|
|
1079
|
-
</div>`}render(){return s.html`${this.renderInput()}${this.view==="button"?this.renderButton():this.view==="compact"?this.renderCompact():this.renderFull()}`}},w=new WeakMap,k=new WeakMap,z=new WeakMap,U=new WeakMap
|
|
1105
|
+
</div>`}render(){return s.html`${this.renderInput()}${this.view==="button"?this.renderButton():this.view==="compact"?this.renderCompact():this.renderFull()}`}},w=new WeakMap,k=new WeakMap,z=new WeakMap,$=new WeakMap,U=new WeakMap,S=new WeakMap,M=new WeakMap,C=new WeakMap,j=new WeakMap,F=new WeakMap,E=new WeakMap,O=new WeakMap,D=new WeakMap,T=new WeakMap,L=new WeakMap,A=new WeakMap,N=new WeakMap,P=new WeakMap,R=new WeakMap,B=new WeakMap,I=new WeakMap,G=new WeakMap,_=new WeakMap,q=new WeakMap,K=new WeakMap,V=new WeakMap,Y=new WeakMap,H=new WeakMap,J=new WeakMap,X=new WeakMap,W=new WeakMap,ue);De(exports.SinglebaseUploader,"styles",[f.tokenDefaults,fe,f.brandingStyles,s.css`
|
|
1080
1106
|
.card {
|
|
1081
1107
|
display: flex;
|
|
1082
1108
|
flex-direction: column;
|
|
@@ -1327,5 +1353,5 @@
|
|
|
1327
1353
|
flex-direction: column;
|
|
1328
1354
|
gap: 8px;
|
|
1329
1355
|
}
|
|
1330
|
-
`]);u([p.property({attribute:!1})],exports.SinglebaseUploader.prototype,"client",1);u([p.property({attribute:!1})],exports.SinglebaseUploader.prototype,"messages",1);u([p.property({reflect:!0})],exports.SinglebaseUploader.prototype,"theme",1);u([p.property({reflect:!0})],exports.SinglebaseUploader.prototype,"density",1);u([p.property({reflect:!0})],exports.SinglebaseUploader.prototype,"radius",1);u([p.property({reflect:!0})],exports.SinglebaseUploader.prototype,"view",1);u([p.property({converter:
|
|
1331
|
-
//# sourceMappingURL=uploader-
|
|
1356
|
+
`]);u([p.property({attribute:!1})],exports.SinglebaseUploader.prototype,"client",1);u([p.property({attribute:!1})],exports.SinglebaseUploader.prototype,"messages",1);u([p.property({reflect:!0})],exports.SinglebaseUploader.prototype,"theme",1);u([p.property({reflect:!0})],exports.SinglebaseUploader.prototype,"density",1);u([p.property({reflect:!0})],exports.SinglebaseUploader.prototype,"radius",1);u([p.property({reflect:!0})],exports.SinglebaseUploader.prototype,"view",1);u([p.property({converter:ae})],exports.SinglebaseUploader.prototype,"dropzone",1);u([p.property({converter:ae,attribute:"allow-rename"})],exports.SinglebaseUploader.prototype,"allowRename",1);u([p.property({type:Boolean,attribute:"auto-upload"})],exports.SinglebaseUploader.prototype,"autoUpload",1);u([p.property({converter:ae})],exports.SinglebaseUploader.prototype,"branding",1);u([p.property({attribute:"logo-url"})],exports.SinglebaseUploader.prototype,"logoUrl",1);u([p.property({attribute:"logo-text"})],exports.SinglebaseUploader.prototype,"logoText",1);u([p.property()],exports.SinglebaseUploader.prototype,"heading",1);u([p.property()],exports.SinglebaseUploader.prototype,"description",1);u([p.property({type:Number,attribute:"max-files"})],exports.SinglebaseUploader.prototype,"maxFiles",1);u([p.property({attribute:"max-size"})],exports.SinglebaseUploader.prototype,"maxSize",1);u([p.property({attribute:"min-size"})],exports.SinglebaseUploader.prototype,"minSize",1);u([p.property()],exports.SinglebaseUploader.prototype,"accept",1);u([p.property({converter:ie})],exports.SinglebaseUploader.prototype,"rules",1);u([p.property()],exports.SinglebaseUploader.prototype,"bucket",1);u([p.property({converter:ie})],exports.SinglebaseUploader.prototype,"metadata",1);u([p.property({converter:ie})],exports.SinglebaseUploader.prototype,"options",1);u([p.property({type:Boolean,attribute:"public-read"})],exports.SinglebaseUploader.prototype,"publicRead",1);u([p.property({attribute:"redirect-url"})],exports.SinglebaseUploader.prototype,"redirectUrl",1);u([p.property({attribute:!1})],exports.SinglebaseUploader.prototype,"onComplete",1);u([p.property({attribute:!1})],exports.SinglebaseUploader.prototype,"onError",1);u([p.state()],exports.SinglebaseUploader.prototype,"items",1);u([p.state()],exports.SinglebaseUploader.prototype,"notice",1);u([p.state()],exports.SinglebaseUploader.prototype,"busy",1);u([p.state()],exports.SinglebaseUploader.prototype,"dragging",1);u([p.state()],exports.SinglebaseUploader.prototype,"editing",1);exports.SinglebaseUploader=u([p.customElement("singlebase-uploader")],exports.SinglebaseUploader);function Te(r){return!r.type.startsWith("image/")||typeof URL.createObjectURL!="function"?"":URL.createObjectURL(r)}function y(r){r.preview&&URL.revokeObjectURL(r.preview)}function Le(r){return r instanceof Error?r.message:""}exports.inspectFile=me;exports.isInspectable=xe;exports.resolveRedirectTarget=ge;exports.sharedStyles=fe;
|
|
1357
|
+
//# sourceMappingURL=uploader-C57vgFME.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uploader-C57vgFME.cjs","sources":["../src/styles/shared.ts","../src/utils/redirect.ts","../src/utils/inspect.ts","../src/elements/uploader.ts"],"sourcesContent":["import { css } from \"lit\";\n\n/**\n * Shared internal styles, ported value-for-value from the design mock's\n * styles(t) / acc(t, open, bare) functions in project/AuthWidget.dc.html.\n * The mock computed these as inline style objects per render; here they are\n * static Shadow DOM CSS driven by the --sb-* tokens, with part hooks so\n * hosts can reach internals via ::part().\n */\nexport const sharedStyles = css`\n /* ── layout primitives ───────────────────────────────────── */\n .stack {\n display: flex;\n flex-direction: column;\n gap: var(--sb-gap, 16px);\n }\n\n .fields {\n display: flex;\n flex-direction: column;\n gap: var(--sb-gap, 16px);\n }\n\n .head {\n display: flex;\n flex-direction: column;\n gap: 6px;\n }\n\n .two-up {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: var(--sb-gap, 16px);\n }\n\n .actions {\n display: flex;\n flex-direction: column;\n gap: 8px;\n }\n\n .rule {\n height: 1px;\n background: var(--sb-border, #e4e6e9);\n }\n\n .between {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 16px;\n }\n\n /* ── type ────────────────────────────────────────────────── */\n .logo-dot {\n font-family: var(--sb-mono, \"Geist Mono\", ui-monospace, monospace);\n font-size: 12px;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: var(--sb-muted-ink, #61666c);\n margin-bottom: 6px;\n }\n\n .title {\n margin: 0;\n font-size: 20px;\n font-weight: 600;\n letter-spacing: -0.015em;\n color: var(--sb-ink, #16181a);\n }\n\n .sub {\n margin: 0;\n font-size: 13.5px;\n line-height: 1.5;\n color: var(--sb-muted-ink, #61666c);\n text-wrap: pretty;\n }\n\n .sec-title {\n margin: 0;\n font-size: 14px;\n font-weight: 600;\n letter-spacing: -0.01em;\n color: var(--sb-ink, #16181a);\n }\n\n .hint {\n margin: 0;\n font-size: 12.5px;\n line-height: 1.5;\n color: var(--sb-muted-ink, #61666c);\n text-wrap: pretty;\n }\n\n .pw-rules {\n margin-top: 6px;\n font-size: 12px;\n line-height: 1.5;\n color: var(--sb-muted-ink, #61666c);\n }\n\n .pw-rules summary {\n cursor: pointer;\n width: fit-content;\n }\n\n .pw-rules summary:hover {\n color: var(--sb-ink, #16181a);\n }\n\n .pw-rules ul {\n margin: 4px 0 0;\n padding-left: 18px;\n }\n\n .consent {\n text-align: center;\n text-wrap: balance;\n }\n\n .sub-label {\n font-family: var(--sb-mono, \"Geist Mono\", ui-monospace, monospace);\n font-size: 11px;\n letter-spacing: 0.07em;\n text-transform: uppercase;\n color: var(--sb-muted-ink, #61666c);\n }\n\n /* ── fields ──────────────────────────────────────────────── */\n .field {\n display: flex;\n flex-direction: column;\n gap: 6px;\n }\n\n .label-row {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: 8px;\n }\n\n label,\n .label {\n font-size: 12.5px;\n font-weight: 500;\n color: var(--sb-muted-ink, #61666c);\n letter-spacing: 0.01em;\n }\n\n input {\n width: 100%;\n box-sizing: border-box;\n font: inherit;\n font-size: 14px;\n color: var(--sb-ink, #16181a);\n background: var(--sb-surface-alt, #fafafa);\n border: 1px solid var(--sb-border, #e4e6e9);\n border-radius: calc(var(--sb-radius, 4px) * var(--sb-radius-scale, 1));\n padding: var(--sb-field-pad, 11px 13px);\n outline: none;\n }\n\n input:focus {\n border-color: var(--sb-accent, #111111);\n }\n\n input[aria-invalid=\"true\"] {\n border-color: var(--sb-danger, #b4231a);\n }\n\n /* field-style=\"underline\" — code boxes keep their box, they read as cells */\n :host([field-style=\"underline\"]) *:not(.code-row):not(.code-row-sm) > input {\n background: transparent;\n border: none;\n border-bottom: 1px solid var(--sb-border-strong, #cdd1d6);\n border-radius: 0;\n padding: 9px 2px;\n }\n\n p.err {\n margin: 0;\n font-size: 12.5px;\n color: var(--sb-danger, #b4231a);\n }\n\n /* ── code entry ──────────────────────────────────────────── */\n .code-row {\n display: grid;\n grid-template-columns: repeat(6, 1fr);\n gap: 8px;\n }\n\n .code-row input {\n text-align: center;\n font-family: var(--sb-mono, \"Geist Mono\", ui-monospace, monospace);\n font-size: 18px;\n padding: 12px 0;\n }\n\n .code-row-sm {\n display: grid;\n grid-template-columns: repeat(6, 1fr);\n gap: 6px;\n }\n\n .code-row-sm input {\n text-align: center;\n font-family: var(--sb-mono, \"Geist Mono\", ui-monospace, monospace);\n font-size: 14px;\n padding: 8px 0;\n }\n\n .resend-row {\n display: flex;\n align-items: baseline;\n gap: 8px;\n }\n\n /* ── buttons ─────────────────────────────────────────────── */\n button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n font: inherit;\n font-size: 13.5px;\n font-weight: 500;\n border-radius: calc(var(--sb-radius, 4px) * var(--sb-radius-scale, 1));\n cursor: pointer;\n padding: 9px 14px;\n border: 1px solid transparent;\n transition:\n background 0.15s,\n border-color 0.15s,\n filter 0.15s,\n color 0.15s;\n }\n\n button:disabled {\n cursor: not-allowed;\n }\n\n button.primary {\n background: var(--sb-accent, #111111);\n color: var(--sb-on-accent, #ffffff);\n width: 100%;\n }\n\n button.primary:hover:not(:disabled) {\n filter: brightness(0.92);\n }\n\n button.primary-sm {\n background: var(--sb-accent, #111111);\n color: var(--sb-on-accent, #ffffff);\n padding: 7px 12px;\n }\n\n button.primary-sm:hover:not(:disabled) {\n filter: brightness(0.92);\n }\n\n button.ghost {\n background: transparent;\n color: var(--sb-muted-ink, #61666c);\n border: 1px solid var(--sb-border, #e4e6e9);\n width: 100%;\n }\n\n button.ghost-sm {\n background: transparent;\n color: var(--sb-muted-ink, #61666c);\n border: 1px solid var(--sb-border, #e4e6e9);\n padding: 7px 12px;\n }\n\n button.ghost:hover:not(:disabled),\n button.ghost-sm:hover:not(:disabled) {\n background: var(--sb-surface-alt, #fafafa);\n color: var(--sb-ink, #16181a);\n }\n\n button.secondary {\n background: var(--sb-surface, #ffffff);\n color: var(--sb-ink, #16181a);\n border: 1px solid var(--sb-border-strong, #cdd1d6);\n padding: 7px 12px;\n }\n\n button.secondary:hover:not(:disabled) {\n background: var(--sb-surface-alt, #fafafa);\n }\n\n button.link {\n font: inherit;\n font-size: 13px;\n font-weight: 500;\n color: var(--sb-accent, #111111);\n background: none;\n border: none;\n padding: 0;\n cursor: pointer;\n text-decoration: underline;\n text-underline-offset: 3px;\n }\n\n button.link-sm {\n font: inherit;\n font-size: 12.5px;\n font-weight: 400;\n color: var(--sb-muted-ink, #61666c);\n background: none;\n border: none;\n padding: 0;\n cursor: pointer;\n text-decoration: underline;\n text-underline-offset: 3px;\n }\n\n /* the mock's editLink: a muted underlined affordance that inks on hover */\n button.edit-link {\n align-self: flex-start;\n font: inherit;\n font-size: 12.5px;\n font-weight: 400;\n color: var(--sb-muted-ink, #61666c);\n background: none;\n border: none;\n padding: 0;\n cursor: pointer;\n text-decoration: underline;\n text-underline-offset: 3px;\n transition: color 0.15s;\n }\n\n button.edit-link:hover:not(:disabled) {\n color: var(--sb-ink, #16181a);\n }\n\n button.edit-link:disabled {\n opacity: 0.4;\n }\n\n button.danger-link {\n align-self: flex-start;\n font: inherit;\n font-size: 12.5px;\n font-weight: 400;\n color: var(--sb-muted-ink, #61666c);\n background: none;\n border: none;\n padding: 0;\n cursor: pointer;\n text-decoration: underline;\n text-underline-offset: 3px;\n transition: color 0.15s;\n }\n\n button.danger-link:hover:not(:disabled) {\n color: var(--sb-danger, #b4231a);\n }\n\n button.danger {\n padding: 7px 12px;\n background: transparent;\n color: var(--sb-danger, #b4231a);\n border: 1px solid var(--sb-danger-outline, #e8c4c0);\n }\n\n button.danger:hover:not(:disabled) {\n background: var(--sb-danger-bg, #fdf1f0);\n }\n\n button.danger:disabled {\n opacity: 0.45;\n }\n\n .btn-row {\n display: flex;\n align-items: center;\n gap: 8px;\n flex-wrap: wrap;\n }\n\n .btn-row-end {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: 12px;\n flex-wrap: wrap;\n }\n\n .edit-actions {\n display: flex;\n gap: 8px;\n padding-top: 2px;\n }\n\n /* ── feedback ────────────────────────────────────────────── */\n .banner,\n .notice {\n font-size: 13px;\n line-height: 1.45;\n border-radius: calc(var(--sb-radius, 4px) * var(--sb-radius-scale, 1));\n padding: 10px 12px;\n }\n\n .banner {\n color: var(--sb-danger, #b4231a);\n background: var(--sb-danger-bg, #fdf1f0);\n border: 1px solid var(--sb-danger-border, #f3d6d3);\n }\n\n .notice {\n color: var(--sb-ok, #0f6b4a);\n background: var(--sb-ok-bg, #f0f7f3);\n border: 1px solid var(--sb-ok-border, #cfe5da);\n }\n\n .saved-note {\n font-size: 12.5px;\n font-weight: 500;\n color: var(--sb-ok, #0f6b4a);\n }\n\n .spinner {\n width: 13px;\n height: 13px;\n border: 2px solid rgba(255, 255, 255, 0.4);\n border-top-color: var(--sb-on-accent, #ffffff);\n border-radius: 50%;\n animation: sb-spin 0.7s linear infinite;\n }\n\n @keyframes sb-spin {\n to {\n transform: rotate(360deg);\n }\n }\n\n .sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n overflow: hidden;\n clip: rect(0 0 0 0);\n white-space: nowrap;\n }\n\n /* ── step bar ────────────────────────────────────────────── */\n .step-bar {\n height: 3px;\n background: var(--sb-border, #e4e6e9);\n border-radius: 99px;\n overflow: hidden;\n }\n\n .step-fill {\n height: 100%;\n background: var(--sb-accent, #111111);\n transition: width 0.3s;\n }\n\n /* ── footer link row ─────────────────────────────────────── */\n .foot {\n margin: 0;\n display: flex;\n gap: 6px;\n justify-content: center;\n font-size: 13px;\n color: var(--sb-muted-ink, #61666c);\n }\n\n /* ── oauth ───────────────────────────────────────────────── */\n .oauth-primary {\n background: var(--sb-surface, #ffffff);\n color: var(--sb-ink, #16181a);\n border: 1px solid var(--sb-border-strong, #cdd1d6);\n width: 100%;\n }\n\n .oauth-primary:hover:not(:disabled) {\n background: var(--sb-surface-alt, #fafafa);\n }\n\n .g-mark {\n font-family: var(--sb-mono, \"Geist Mono\", ui-monospace, monospace);\n font-weight: 500;\n font-size: 13px;\n color: var(--sb-muted-ink, #61666c);\n }\n\n .icon-row {\n display: grid;\n grid-template-columns: repeat(3, 1fr);\n gap: 8px;\n }\n\n .icon-btn {\n padding: 7px 0;\n background: var(--sb-surface, #ffffff);\n color: var(--sb-muted-ink, #61666c);\n border: 1px solid var(--sb-border, #e4e6e9);\n font-family: var(--sb-mono, \"Geist Mono\", ui-monospace, monospace);\n font-size: 13px;\n }\n\n .icon-btn:hover:not(:disabled) {\n background: var(--sb-surface-alt, #fafafa);\n color: var(--sb-ink, #16181a);\n }\n\n /* ── accordion (method picker) ───────────────────────────── */\n .acc-wrap {\n display: flex;\n flex-direction: column;\n gap: 8px;\n }\n\n .acc-item {\n border: 1px solid var(--sb-border, #e4e6e9);\n border-radius: calc(var(--sb-radius, 4px) * var(--sb-radius-scale, 1));\n overflow: hidden;\n background: transparent;\n transition:\n border-color 0.2s,\n background 0.2s;\n }\n\n .acc-item.open {\n border-color: var(--sb-border-strong, #cdd1d6);\n background: var(--sb-surface, #ffffff);\n }\n\n .acc-item.bare {\n border: none;\n background: transparent;\n }\n\n .acc-head {\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n box-sizing: border-box;\n font: inherit;\n text-align: left;\n background: transparent;\n border: none;\n border-radius: 0;\n padding: 11px 12px;\n cursor: pointer;\n color: var(--sb-ink, #16181a);\n transition: background 0.15s;\n }\n\n .acc-head:hover {\n background: var(--sb-surface-alt, #fafafa);\n }\n\n .chev {\n font-family: var(--sb-mono, \"Geist Mono\", ui-monospace, monospace);\n font-size: 13px;\n color: var(--sb-muted-ink, #61666c);\n line-height: 1;\n transform: rotate(0deg);\n transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n }\n\n .acc-item.open .chev {\n transform: rotate(90deg);\n }\n\n .acc-title {\n font-size: 13.5px;\n font-weight: 500;\n color: var(--sb-ink, #16181a);\n letter-spacing: -0.005em;\n }\n\n .acc-meta {\n font-size: 12px;\n color: var(--sb-muted-ink, #61666c);\n margin-left: auto;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .acc-body {\n display: grid;\n grid-template-rows: 0fr;\n opacity: 0;\n transition:\n grid-template-rows 0.28s cubic-bezier(0.32, 0.72, 0, 1),\n opacity 0.16s ease;\n }\n\n .acc-item.open .acc-body {\n grid-template-rows: 1fr;\n opacity: 1;\n transition:\n grid-template-rows 0.34s cubic-bezier(0.32, 0.72, 0, 1),\n opacity 0.26s ease 0.06s;\n }\n\n .acc-clip {\n overflow: hidden;\n min-height: 0;\n }\n\n .acc-inner {\n display: flex;\n flex-direction: column;\n gap: var(--sb-gap, 16px);\n padding: 2px 12px 14px;\n transform: translateY(-4px);\n transition: transform 0.3s cubic-bezier(0.32, 0.72, 0, 1);\n }\n\n .acc-item.open .acc-inner {\n transform: translateY(0);\n }\n\n .acc-item.bare .acc-inner {\n padding: 0;\n }\n\n /* ── invite ──────────────────────────────────────────────── */\n .invite-box {\n display: flex;\n flex-direction: column;\n gap: 2px;\n padding: 10px 12px;\n background: var(--sb-surface-alt, #fafafa);\n border: 1px solid var(--sb-border, #e4e6e9);\n border-radius: calc(var(--sb-radius, 4px) * var(--sb-radius-scale, 1));\n }\n\n .invite-label {\n font-size: 11.5px;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n font-family: var(--sb-mono, \"Geist Mono\", ui-monospace, monospace);\n color: var(--sb-muted-ink, #61666c);\n }\n\n .invite-email {\n font-size: 14px;\n color: var(--sb-ink, #16181a);\n }\n\n /* ── account ─────────────────────────────────────────────── */\n .acct-root {\n display: flex;\n flex-direction: column;\n gap: 22px;\n width: 100%;\n }\n\n .acct-nav {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 16px;\n padding-bottom: 18px;\n border-bottom: 1px solid var(--sb-border, #e4e6e9);\n }\n\n .acct-who {\n display: flex;\n align-items: center;\n gap: 10px;\n }\n\n .avatar-col {\n flex: 0 0 auto;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 6px;\n }\n\n .avatar {\n flex: 0 0 auto;\n width: 42px;\n height: 42px;\n border-radius: 50%;\n background: var(--sb-surface-alt, #fafafa);\n border: 1px dashed var(--sb-border, #e4e6e9);\n display: flex;\n align-items: center;\n justify-content: center;\n font-family: var(--sb-mono, \"Geist Mono\", ui-monospace, monospace);\n font-size: 13px;\n color: var(--sb-muted-ink, #61666c);\n }\n\n .avatar.has-photo {\n border-style: solid;\n overflow: hidden;\n }\n .avatar img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n }\n\n .avatar-lg {\n width: 56px;\n height: 56px;\n border-radius: 50%;\n background: var(--sb-surface-alt, #fafafa);\n border: 1px dashed var(--sb-border-strong, #cdd1d6);\n display: flex;\n align-items: center;\n justify-content: center;\n font-family: var(--sb-mono, \"Geist Mono\", ui-monospace, monospace);\n font-size: 13px;\n color: var(--sb-muted-ink, #61666c);\n }\n\n .avatar-row {\n display: flex;\n align-items: center;\n gap: 14px;\n }\n\n .avatar-actions {\n display: flex;\n flex-direction: column;\n gap: 6px;\n }\n\n .acct-who-text {\n min-width: 0;\n }\n\n .acct-name {\n font-size: 14px;\n font-weight: 600;\n color: var(--sb-ink, #16181a);\n letter-spacing: -0.01em;\n }\n\n .acct-email {\n font-size: 12.5px;\n color: var(--sb-muted-ink, #61666c);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .acct-body {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 22px;\n }\n\n .section {\n display: flex;\n flex-direction: column;\n gap: 14px;\n }\n\n .sum-list {\n display: flex;\n flex-direction: column;\n }\n\n .sum-row {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: 16px;\n padding: 15px 0;\n border-bottom: 1px solid var(--sb-border, #e4e6e9);\n }\n\n .sum-label {\n flex: 0 0 auto;\n font-size: 12.5px;\n color: var(--sb-muted-ink, #61666c);\n }\n\n .sum-value {\n min-width: 0;\n font-size: 13.5px;\n color: var(--sb-ink, #16181a);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .edit-card {\n display: flex;\n flex-direction: column;\n gap: var(--sb-gap, 16px);\n padding: 14px;\n background: var(--sb-surface-alt, #fafafa);\n border: 1px solid var(--sb-border, #e4e6e9);\n border-radius: calc(var(--sb-radius, 4px) * var(--sb-radius-scale, 1));\n }\n\n /* 2FA switch */\n .switch {\n flex: 0 0 auto;\n width: 42px;\n height: 24px;\n border-radius: 99px;\n border: 1px solid var(--sb-border-strong, #cdd1d6);\n background: var(--sb-surface-alt, #fafafa);\n cursor: pointer;\n padding: 2px;\n display: flex;\n justify-content: flex-start;\n align-items: center;\n transition:\n background 0.15s,\n border-color 0.15s;\n }\n\n .switch[aria-pressed=\"true\"] {\n border-color: var(--sb-accent, #111111);\n background: var(--sb-accent, #111111);\n justify-content: flex-end;\n }\n\n .knob {\n width: 18px;\n height: 18px;\n border-radius: 50%;\n background: var(--sb-muted-ink, #61666c);\n display: block;\n }\n\n .switch[aria-pressed=\"true\"] .knob {\n background: var(--sb-on-accent, #ffffff);\n }\n\n .qr-row {\n display: flex;\n gap: 14px;\n align-items: flex-start;\n }\n\n .qr-box {\n flex: 0 0 auto;\n width: 74px;\n height: 74px;\n border-radius: calc(var(--sb-radius, 4px) * var(--sb-radius-scale, 1));\n background: var(--sb-surface-alt, #fafafa);\n border: 1px dashed var(--sb-border-strong, #cdd1d6);\n display: flex;\n align-items: center;\n justify-content: center;\n font-family: var(--sb-mono, \"Geist Mono\", ui-monospace, monospace);\n font-size: 12px;\n color: var(--sb-muted-ink, #61666c);\n }\n\n .qr-text {\n display: flex;\n flex-direction: column;\n gap: 10px;\n min-width: 0;\n }\n\n /* connected accounts */\n .list {\n display: flex;\n flex-direction: column;\n gap: 8px;\n }\n\n .conn-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n padding: 10px 12px;\n border: 1px solid var(--sb-border, #e4e6e9);\n border-radius: calc(var(--sb-radius, 4px) * var(--sb-radius-scale, 1));\n background: var(--sb-surface-alt, #fafafa);\n }\n\n .conn-left {\n display: flex;\n align-items: center;\n gap: 10px;\n min-width: 0;\n }\n\n .conn-mark {\n flex: 0 0 auto;\n width: 28px;\n height: 28px;\n border-radius: 50%;\n background: var(--sb-surface, #ffffff);\n border: 1px solid var(--sb-border, #e4e6e9);\n display: flex;\n align-items: center;\n justify-content: center;\n font-family: var(--sb-mono, \"Geist Mono\", ui-monospace, monospace);\n font-size: 11px;\n color: var(--sb-muted-ink, #61666c);\n }\n\n .conn-name {\n font-size: 13.5px;\n font-weight: 500;\n color: var(--sb-ink, #16181a);\n }\n\n .meta-row {\n display: flex;\n align-items: center;\n gap: 6px;\n }\n\n .dot {\n flex: 0 0 auto;\n width: 5px;\n height: 5px;\n border-radius: 50%;\n background: var(--sb-ok, #0f6b4a);\n }\n\n .conn-meta {\n font-size: 12px;\n color: var(--sb-muted-ink, #61666c);\n }\n\n .tile-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(118px, 1fr));\n gap: 8px;\n }\n\n .tile {\n display: flex;\n align-items: center;\n gap: 8px;\n font: inherit;\n text-align: left;\n padding: 10px 11px;\n border-radius: calc(var(--sb-radius, 4px) * var(--sb-radius-scale, 1));\n border: 1px dashed var(--sb-border-strong, #cdd1d6);\n background: transparent;\n cursor: pointer;\n transition:\n background 0.15s,\n border-color 0.15s,\n color 0.15s;\n }\n\n .tile:hover:not(:disabled) {\n background: var(--sb-surface-alt, #fafafa);\n border-color: var(--sb-accent, #111111);\n border-style: solid;\n }\n\n .tile-mark {\n flex: 0 0 auto;\n width: 22px;\n height: 22px;\n border-radius: 50%;\n background: var(--sb-surface-alt, #fafafa);\n display: flex;\n align-items: center;\n justify-content: center;\n font-family: var(--sb-mono, \"Geist Mono\", ui-monospace, monospace);\n font-size: 10.5px;\n color: var(--sb-muted-ink, #61666c);\n }\n\n .tile-name {\n font-size: 13px;\n color: var(--sb-ink, #16181a);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .tile-plus {\n margin-left: auto;\n font-family: var(--sb-mono, \"Geist Mono\", ui-monospace, monospace);\n font-size: 14px;\n line-height: 1;\n color: var(--sb-muted-ink, #61666c);\n }\n\n .delete-panel {\n display: flex;\n flex-direction: column;\n gap: 12px;\n padding: 14px;\n border: 1px solid var(--sb-danger-panel-border, #efd9d6);\n border-radius: calc(var(--sb-radius, 4px) * var(--sb-radius-scale, 1));\n background: var(--sb-danger-panel-bg, #fdf7f6);\n }\n\n .disabled-note {\n font-size: 12px;\n color: var(--sb-muted-ink, #61666c);\n font-style: italic;\n }\n`;\n","/**\n * Resolves a post-login destination, or null when there isn't a safe one.\n *\n * The candidate usually comes from a `?redirect=` parameter, which is\n * attacker-controllable: anyone can send a victim a link to your own login\n * page carrying `?redirect=https://evil.example`. If the widget followed it,\n * the victim would sign in on a page they trust and then be handed to a site\n * they don't — a textbook open redirect, and a convincing one precisely\n * because the login step was genuine.\n *\n * So the rule is same-origin only. Relative paths resolve against the current\n * page; anything landing on another origin is refused, and the caller is told\n * why rather than left wondering where the redirect went.\n */\nexport function resolveRedirectTarget(\n candidate: string | null | undefined,\n currentHref: string | null | undefined,\n onRefused?: (reason: string) => void\n): string | null {\n if (!candidate || !currentHref) return null;\n\n let here: URL;\n try {\n here = new URL(currentHref);\n } catch {\n return null;\n }\n\n let target: URL;\n try {\n target = new URL(candidate, here.href);\n } catch {\n onRefused?.(`\"${candidate}\" is not a valid URL`);\n return null;\n }\n\n // Only ever http(s). A `javascript:` or `data:` candidate resolves to a URL\n // object quite happily, and assigning it would execute script.\n if (target.protocol !== \"http:\" && target.protocol !== \"https:\") {\n onRefused?.(`refusing redirect to unsupported scheme \"${target.protocol}\"`);\n return null;\n }\n\n if (target.origin !== here.origin) {\n onRefused?.(`refusing cross-origin redirect to ${target.origin}; same-origin only`);\n return null;\n }\n\n // Already there — redirecting would just reload, and can loop.\n if (target.href === here.href) return null;\n\n return target.href;\n}\n","/**\n * Reads a few facts out of a file before it is uploaded: how many pages it\n * has, and whether it is encrypted. Everything here runs in the browser on\n * the bytes the user picked — no upload, no dependency, no worker.\n *\n * Two honest caveats, both of which the documentation repeats:\n *\n * - **This is a convenience, not a security control.** Anyone can bypass it.\n * The server still has to enforce whatever actually matters.\n * - **Facts can be unknown.** A page count is `null` when the structure\n * can't be read, and callers treat unknown as \"rule doesn't apply\" rather\n * than rejecting a file they simply failed to parse.\n */\n\nexport interface FileFacts {\n /** Pages for PDF and DOCX, slides for PPTX. Null when undeterminable. */\n pages: number | null;\n /** True when encrypted, false when plainly not, null when unknown. */\n encrypted: boolean | null;\n}\n\nconst UNKNOWN: FileFacts = { pages: null, encrypted: null };\n\n/** How much of a large PDF to look at, from each end. */\nconst PDF_HEAD = 16 * 1024 * 1024;\nconst PDF_TAIL = 2 * 1024 * 1024;\n\n/** Ceilings for the compressed-PDF fallback, so a hostile file can't stall the tab. */\nconst MAX_STREAMS = 40;\nconst MAX_INFLATED = 4 * 1024 * 1024;\n\nconst OOXML = new Set([\"docx\", \"pptx\", \"xlsx\"]);\n\n/** Inspects one file. Never throws — an unreadable file is simply unknown. */\nexport async function inspectFile(file: Blob, extension: string): Promise<FileFacts> {\n try {\n if (extension === \"pdf\") return await inspectPdf(file);\n if (OOXML.has(extension)) return await inspectOoxml(file, extension);\n } catch {\n // A corrupt or surprising file is not a rejection reason on its own.\n }\n return UNKNOWN;\n}\n\n/** True when this extension has anything worth reading bytes for. */\nexport function isInspectable(extension: string): boolean {\n return extension === \"pdf\" || OOXML.has(extension);\n}\n\n// ── PDF ──────────────────────────────────────────────────────\n\nasync function inspectPdf(file: Blob): Promise<FileFacts> {\n const head = await bytesOf(file.slice(0, PDF_HEAD));\n const tail =\n file.size > PDF_HEAD ? await bytesOf(file.slice(Math.max(0, file.size - PDF_TAIL))) : null;\n\n const text = latin1(head) + (tail ? latin1(tail) : \"\");\n\n // An encrypted PDF names /Encrypt in its trailer. The whole file is still\n // readable — it is the content streams that are encrypted — so this is a\n // reliable marker rather than a guess.\n const encrypted = /\\/Encrypt[\\s/<>\\]]/.test(text);\n\n let pages = pageCountIn(text);\n if (pages === null) pages = await pageCountInStreams(head);\n\n return { pages, encrypted };\n}\n\n/**\n * The page tree's root node carries `/Count` with the document total, so the\n * largest `/Count` next to a `/Pages` node is the answer. Files that write\n * the tree without counts fall back to counting `/Type /Page` objects.\n */\nfunction pageCountIn(text: string): number | null {\n if (/\\/Type\\s*\\/Pages/.test(text)) {\n let max = 0;\n for (const match of text.matchAll(/\\/Count\\s+(\\d+)/g)) {\n max = Math.max(max, Number(match[1]));\n }\n if (max > 0) return max;\n }\n const direct = text.match(/\\/Type\\s*\\/Page[^s]/g);\n return direct?.length ? direct.length : null;\n}\n\n/**\n * PDF 1.5 and later may pack the page tree into compressed object streams,\n * where a plain scan sees nothing. Inflating the streams and scanning the\n * result recovers the count, using only DecompressionStream.\n */\nasync function pageCountInStreams(bytes: Uint8Array): Promise<number | null> {\n if (typeof DecompressionStream === \"undefined\") return null;\n\n const text = latin1(bytes);\n let inflated = \"\";\n let streams = 0;\n\n for (const match of text.matchAll(/stream\\r?\\n/g)) {\n if (streams >= MAX_STREAMS || inflated.length >= MAX_INFLATED) break;\n const start = match.index! + match[0].length;\n let end = text.indexOf(\"endstream\", start);\n if (end < 0) break;\n // Writers put an EOL between the data and the keyword. It has to come off:\n // the decompressor rejects anything trailing the compressed data.\n while (end > start && (text[end - 1] === \"\\n\" || text[end - 1] === \"\\r\")) end -= 1;\n streams += 1;\n try {\n const out = await inflate(bytes.subarray(start, end), \"deflate\");\n inflated += latin1(out);\n } catch {\n // Not a zlib stream (an image, or a different filter). Skip it.\n }\n }\n\n return inflated ? pageCountIn(inflated) : null;\n}\n\n// ── OOXML (docx / pptx / xlsx) ───────────────────────────────\n\nasync function inspectOoxml(file: Blob, extension: string): Promise<FileFacts> {\n const magic = await bytesOf(file.slice(0, 8));\n\n // A password-protected Office file is not a zip at all: Office encrypts the\n // package and wraps it in an OLE compound file. The magic bytes say so\n // outright, which makes this the one exact check in this module.\n if (isCompoundFile(magic)) return { pages: null, encrypted: true };\n if (magic[0] !== 0x50 || magic[1] !== 0x4b) return UNKNOWN;\n\n const app = await readZipEntry(file, \"docProps/app.xml\");\n if (!app) return { pages: null, encrypted: false };\n\n // Word records Pages, PowerPoint records Slides. Excel records neither.\n const tag = extension === \"pptx\" ? \"Slides\" : \"Pages\";\n const match = new TextDecoder().decode(app).match(new RegExp(`<${tag}>(\\\\d+)</${tag}>`));\n return { pages: match ? Number(match[1]) : null, encrypted: false };\n}\n\nfunction isCompoundFile(magic: Uint8Array): boolean {\n const SIGNATURE = [0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1];\n return SIGNATURE.every((byte, i) => magic[i] === byte);\n}\n\n/**\n * Pulls one entry out of a zip by walking the central directory. Enough of\n * the format to find a small known file, and no more: zip64 archives return\n * null, which reads as \"unknown\" upstream.\n */\nasync function readZipEntry(file: Blob, wanted: string): Promise<Uint8Array | null> {\n const tailSize = Math.min(file.size, 66_000);\n const tail = new DataView(await file.slice(file.size - tailSize).arrayBuffer());\n\n let eocd = -1;\n for (let i = tail.byteLength - 22; i >= 0; i--) {\n if (tail.getUint32(i, true) === 0x06054b50) {\n eocd = i;\n break;\n }\n }\n if (eocd < 0) return null;\n\n const size = tail.getUint32(eocd + 12, true);\n const offset = tail.getUint32(eocd + 16, true);\n if (!size || offset === 0xffffffff) return null;\n\n const cd = new DataView(await file.slice(offset, offset + size).arrayBuffer());\n const decoder = new TextDecoder();\n let p = 0;\n\n while (p + 46 <= cd.byteLength && cd.getUint32(p, true) === 0x02014b50) {\n const method = cd.getUint16(p + 10, true);\n const compressed = cd.getUint32(p + 20, true);\n const nameLength = cd.getUint16(p + 28, true);\n const extraLength = cd.getUint16(p + 30, true);\n const commentLength = cd.getUint16(p + 32, true);\n const localOffset = cd.getUint32(p + 42, true);\n const name = decoder.decode(new Uint8Array(cd.buffer, cd.byteOffset + p + 46, nameLength));\n\n if (name === wanted) {\n // The central directory's name/extra lengths may differ from the local\n // header's, so the data offset has to come from the local header.\n const local = new DataView(await file.slice(localOffset, localOffset + 30).arrayBuffer());\n const start = localOffset + 30 + local.getUint16(26, true) + local.getUint16(28, true);\n const data = await bytesOf(file.slice(start, start + compressed));\n if (method === 0) return data;\n if (method === 8 && typeof DecompressionStream !== \"undefined\") {\n return await inflate(data, \"deflate-raw\");\n }\n return null;\n }\n\n p += 46 + nameLength + extraLength + commentLength;\n }\n return null;\n}\n\n// ── plumbing ─────────────────────────────────────────────────\n\nasync function bytesOf(blob: Blob): Promise<Uint8Array> {\n return new Uint8Array(await blob.arrayBuffer());\n}\n\nasync function inflate(data: Uint8Array, format: \"deflate\" | \"deflate-raw\"): Promise<Uint8Array> {\n const stream = new Blob([data as BlobPart]).stream().pipeThrough(new DecompressionStream(format));\n return new Uint8Array(await new Response(stream).arrayBuffer());\n}\n\n/** Bytes as one char each, so PDF structure can be matched with a regex. */\nfunction latin1(bytes: Uint8Array): string {\n let out = \"\";\n const CHUNK = 32_768;\n for (let i = 0; i < bytes.length; i += CHUNK) {\n out += String.fromCharCode(...bytes.subarray(i, i + CHUNK));\n }\n return out;\n}\n","import { LitElement, css, html, nothing } from \"lit\";\nimport { customElement, property, state } from \"lit/decorators.js\";\nimport { getDefaultClient } from \"@singlebase/core\";\nimport type {\n FileUploadInput,\n FilesUploadApi,\n SinglebaseClientInstance,\n UploadProgress\n} from \"@singlebase/singlebase-sdk\";\n\n/** What the uploader needs from a client: `files.upload`, and nothing else. */\nexport type UploaderClient = { files: Pick<FilesUploadApi, \"upload\"> };\nimport { tokenDefaults } from \"../styles/tokens.js\";\nimport { sharedStyles } from \"../styles/shared.js\";\nimport { brandingStyles } from \"../styles/branding.js\";\nimport { renderBranding } from \"../utils/branding.js\";\nimport { fill, resolveUploadMessages, type SinglebaseUploadMessages } from \"../upload-messages.js\";\nimport { resolveRedirectTarget } from \"../utils/redirect.js\";\nimport {\n acceptSummary,\n acceptsFile,\n extensionOf,\n fileExtension,\n fileKey,\n formatSize,\n parseSize,\n renameKeepingExtension\n} from \"../utils/files.js\";\nimport { inspectFile, isInspectable } from \"../utils/inspect.js\";\n\n/** JSON in markup, an object in JavaScript. Bad JSON is ignored, not thrown. */\nconst jsonAttr = {\n fromAttribute: (value: string | null) => {\n if (!value) return {};\n try {\n const parsed = JSON.parse(value);\n return parsed && typeof parsed === \"object\" ? parsed : {};\n } catch {\n console.warn(\"[singlebase-uploader] an attribute holds invalid JSON; ignoring it\");\n return {};\n }\n },\n toAttribute: (value: unknown) => JSON.stringify(value ?? {})\n};\n\n/** Present-but-empty means true, so `dropzone` and `dropzone=\"false\"` both read. */\nconst flagAttr = {\n fromAttribute: (value: string | null) => (value === null ? true : value !== \"false\"),\n toAttribute: (value: boolean) => (value ? null : \"false\")\n};\n\nexport type UploadView = \"full\" | \"compact\" | \"button\";\nexport type UploadItemStatus = \"checking\" | \"ready\" | \"uploading\" | \"done\" | \"error\";\n\n/**\n * Per-format limits, keyed by extension: `{ pdf: { maxPages: 10 } }`.\n *\n * `maxPages` and `allowProtected` need the file's bytes read, which only\n * works for `pdf`, `docx`, `pptx` and `xlsx`; the size bounds apply to any\n * extension and override the element-wide ones for that kind.\n */\nexport interface FileRule {\n maxPages?: number;\n maxSize?: string | number;\n minSize?: string | number;\n /** Set false to refuse password-protected files. Default: allowed. */\n allowProtected?: boolean;\n}\n\nexport type FileRules = Record<string, FileRule>;\n\nexport interface UploadItem {\n /** Identity for de-duplication: name, size and mtime. */\n key: string;\n file: File;\n /** The saved name, which the user may have edited. */\n name: string;\n status: UploadItemStatus;\n percent: number;\n error: string;\n /** The stored file record, once the upload completes. */\n record: unknown;\n /** Pages (slides for pptx) when they could be read, else null. */\n pages: number | null;\n /** Whether the file is encrypted, when that could be determined. */\n encrypted: boolean | null;\n /** A local object URL for image thumbnails; \"\" for everything else. */\n preview: string;\n}\n\n/**\n * Every setting in one object, for configuring an element from script. Keys\n * are the element's property names.\n */\nexport interface UploaderConfig {\n view: UploadView;\n dropzone: boolean;\n allowRename: boolean;\n autoUpload: boolean;\n branding: boolean;\n logoUrl: string;\n logoText: string;\n heading: string;\n description: string;\n maxFiles: number;\n maxSize: string | number;\n minSize: string | number;\n accept: string;\n rules: FileRules;\n bucket: string;\n publicRead: boolean;\n redirectUrl: string;\n metadata: Record<string, unknown>;\n options: Record<string, unknown>;\n messages: Partial<SinglebaseUploadMessages>;\n theme: \"light\" | \"dark\";\n density: \"comfortable\" | \"compact\";\n radius: \"sharp\" | \"default\" | \"round\";\n onComplete: SinglebaseUploader[\"onComplete\"];\n onError: SinglebaseUploader[\"onError\"];\n}\n\nconst CONFIG_KEYS: readonly (keyof UploaderConfig)[] = [\n \"view\",\n \"dropzone\",\n \"allowRename\",\n \"autoUpload\",\n \"branding\",\n \"logoUrl\",\n \"logoText\",\n \"heading\",\n \"description\",\n \"maxFiles\",\n \"maxSize\",\n \"minSize\",\n \"accept\",\n \"rules\",\n \"bucket\",\n \"publicRead\",\n \"redirectUrl\",\n \"metadata\",\n \"options\",\n \"messages\",\n \"theme\",\n \"density\",\n \"radius\",\n \"onComplete\",\n \"onError\"\n];\n\n/**\n * A file picker that uploads straight to storage.\n *\n * <singlebase-uploader></singlebase-uploader>\n * <singlebase-uploader view=\"compact\" accept=\".pdf,image/*\"></singlebase-uploader>\n * <singlebase-uploader view=\"button\" max-files=\"1\"></singlebase-uploader>\n *\n * It owns the staging list — picking, renaming, removing, validating, and the\n * progress of each file — and nothing else. When the batch finishes it emits\n * the stored records and stops; what the application does with them (attach\n * them to a record, show a gallery, save an avatar) is the application's\n * decision, not the widget's.\n *\n * Failures are per file. One rejected upload leaves the rest completed and\n * offers that row a retry, mirroring the SDK's own behaviour.\n */\n@customElement(\"singlebase-uploader\")\nexport class SinglebaseUploader extends LitElement {\n static styles = [\n tokenDefaults,\n sharedStyles,\n brandingStyles,\n css`\n .card {\n display: flex;\n flex-direction: column;\n gap: 14px;\n box-sizing: border-box;\n padding: var(--sb-pad, 20px);\n background: var(--sb-surface, #ffffff);\n color: var(--sb-ink, #16181a);\n border: 1px solid var(--sb-border, #e4e6e9);\n border-radius: calc((var(--sb-radius, 4px) + 4px) * var(--sb-radius-scale, 1));\n }\n\n .logo-img {\n display: block;\n align-self: flex-start;\n height: var(--sb-logo-height, 20px);\n width: auto;\n max-width: 100%;\n }\n\n .brand-mark {\n font-family: var(--sb-mono, \"Geist Mono\", ui-monospace, monospace);\n font-size: 13px;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: var(--sb-ink, #16181a);\n }\n\n .head-block {\n display: flex;\n flex-direction: column;\n gap: 6px;\n }\n\n .count {\n font-family: var(--sb-mono, \"Geist Mono\", ui-monospace, monospace);\n font-size: 11.5px;\n letter-spacing: 0.06em;\n text-transform: uppercase;\n color: var(--sb-muted-ink, #61666c);\n }\n\n /* ── dropzone ─────────────────────────────────────── */\n .drop {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 6px;\n padding: 30px 20px;\n text-align: center;\n border: 1px dashed var(--sb-border-strong, #cdd1d6);\n border-radius: calc((var(--sb-radius, 4px) + 2px) * var(--sb-radius-scale, 1));\n background: var(--sb-surface, #ffffff);\n transition:\n border-color 0.15s,\n background 0.15s;\n }\n\n .drop[data-drag=\"true\"] {\n border-color: var(--sb-accent, #111111);\n background: var(--sb-surface-alt, #fafafa);\n }\n\n .arrow {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 42px;\n height: 42px;\n margin-bottom: 4px;\n font-size: 18px;\n line-height: 1;\n border: 1px solid var(--sb-border, #e4e6e9);\n border-radius: 50%;\n color: var(--sb-ink, #16181a);\n }\n\n .drop-title {\n font-size: 14px;\n font-weight: 600;\n color: var(--sb-ink, #16181a);\n }\n\n /* the compact single-line dropzone */\n .strip {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n padding: 10px 12px;\n border: 1px solid var(--sb-border, #e4e6e9);\n border-radius: calc((var(--sb-radius, 4px) + 2px) * var(--sb-radius-scale, 1));\n background: var(--sb-surface-alt, #fafafa);\n transition:\n border-color 0.15s,\n background 0.15s;\n }\n\n .strip[data-drag=\"true\"] {\n border-color: var(--sb-accent, #111111);\n }\n\n .strip-label {\n font-size: 14px;\n color: var(--sb-muted-ink, #61666c);\n }\n\n /* ── file rows ────────────────────────────────────── */\n .rows {\n display: flex;\n flex-direction: column;\n }\n\n .row {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 12px 0;\n border-top: 1px solid var(--sb-border, #e4e6e9);\n }\n\n .rows .row:first-child {\n border-top: none;\n }\n\n .chip {\n display: flex;\n align-items: center;\n justify-content: center;\n flex: 0 0 auto;\n width: 46px;\n height: 46px;\n font-family: var(--sb-mono, \"Geist Mono\", ui-monospace, monospace);\n font-size: 10.5px;\n letter-spacing: 0.04em;\n color: var(--sb-muted-ink, #61666c);\n background: var(--sb-surface-alt, #fafafa);\n border: 1px solid var(--sb-border, #e4e6e9);\n border-radius: calc(var(--sb-radius, 4px) * var(--sb-radius-scale, 1));\n overflow: hidden;\n }\n\n .thumb {\n display: block;\n width: 100%;\n height: 100%;\n object-fit: cover;\n }\n\n .meta {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 4px;\n }\n\n .name {\n font-size: 14px;\n font-weight: 500;\n color: var(--sb-ink, #16181a);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n button.name {\n align-self: flex-start;\n max-width: 100%;\n padding: 0;\n border: none;\n background: none;\n text-align: left;\n border-radius: 0;\n }\n\n button.name:hover {\n text-decoration: underline;\n text-underline-offset: 3px;\n }\n\n .name-input {\n font-size: 14px;\n padding: 6px 8px;\n }\n\n .sz {\n font-size: 12px;\n color: var(--sb-muted-ink, #61666c);\n }\n\n .sz[data-state=\"error\"] {\n color: var(--sb-danger, #b4231a);\n }\n\n .sz[data-state=\"done\"] {\n color: var(--sb-ok, #0f6b4a);\n }\n\n .bar {\n height: 3px;\n margin-top: 2px;\n border-radius: 999px;\n background: var(--sb-border, #e4e6e9);\n overflow: hidden;\n }\n\n .bar-fill {\n height: 100%;\n background: var(--sb-accent, #111111);\n transition: width 0.2s linear;\n }\n\n .row-act {\n flex: 0 0 auto;\n display: flex;\n align-items: center;\n gap: 10px;\n }\n\n /* ── the dashed \"add more\" affordance ─────────────── */\n button.add-more {\n width: 100%;\n padding: 14px;\n color: var(--sb-ink, #16181a);\n background: none;\n border: 1px dashed var(--sb-border-strong, #cdd1d6);\n border-radius: calc((var(--sb-radius, 4px) + 2px) * var(--sb-radius-scale, 1));\n }\n\n button.add-more:hover:not(:disabled) {\n background: var(--sb-surface-alt, #fafafa);\n }\n\n button.wide {\n width: 100%;\n padding: 13px;\n font-size: 14px;\n }\n\n /* the button view is just a control, not a card */\n :host([view=\"button\"]) {\n display: inline-block;\n }\n\n .button-view {\n display: flex;\n flex-direction: column;\n gap: 8px;\n }\n `\n ];\n\n // ── wiring ────────────────────────────────────────────────\n /** An explicit client. Omit it and the page's SinglebaseClient() is used. */\n @property({ attribute: false })\n accessor client: UploaderClient | null = null;\n\n @property({ attribute: false })\n accessor messages: Partial<SinglebaseUploadMessages> = {};\n\n @property({ reflect: true })\n accessor theme: \"light\" | \"dark\" | undefined = undefined;\n\n @property({ reflect: true })\n accessor density: \"comfortable\" | \"compact\" | undefined = undefined;\n\n /** Corner preset for this element: `sharp`, `default` or `round`. */\n @property({ reflect: true })\n accessor radius: \"sharp\" | \"default\" | \"round\" | undefined = undefined;\n\n // ── shape ─────────────────────────────────────────────────\n /**\n * `full` is the card with a dropzone and a reviewable list, `compact` the\n * one-line attachments row, `button` a single control that uploads as soon\n * as a file is chosen.\n */\n @property({ reflect: true })\n accessor view: UploadView = \"full\";\n\n /** Show the drop target. Off leaves the picker button on its own. */\n @property({ converter: flagAttr })\n accessor dropzone = true;\n\n /** Let the user edit the saved filename before uploading. */\n @property({ converter: flagAttr, attribute: \"allow-rename\" })\n accessor allowRename = true;\n\n /** Upload as soon as files are picked, with no review step. */\n @property({ type: Boolean, attribute: \"auto-upload\" })\n accessor autoUpload = false;\n\n /** The \"Files by Singlebase\" credit. A plain link — it makes no request. */\n @property({ converter: flagAttr })\n accessor branding = true;\n\n @property({ attribute: \"logo-url\" }) accessor logoUrl = \"\";\n @property({ attribute: \"logo-text\" }) accessor logoText = \"\";\n @property() accessor heading = \"\";\n @property() accessor description = \"\";\n\n // ── limits ────────────────────────────────────────────────\n @property({ type: Number, attribute: \"max-files\" }) accessor maxFiles = 10;\n\n /** Bytes, or a human size like \"25MB\". 0 or \"\" means no limit. */\n @property({ attribute: \"max-size\" }) accessor maxSize: string | number = \"25MB\";\n @property({ attribute: \"min-size\" }) accessor minSize: string | number = 0;\n\n /** Same vocabulary as `<input type=\"file\" accept>`. */\n @property() accessor accept = \"\";\n\n /**\n * Per-format limits, as JSON in markup or an object in JavaScript:\n *\n * rules='{\"pdf\":{\"maxPages\":10,\"allowProtected\":false}}'\n *\n * Checking pages and encryption means reading the file in the browser, so\n * it is a convenience for the person picking files — never a substitute\n * for the server enforcing the same limits.\n */\n @property({ converter: jsonAttr })\n accessor rules: FileRules = {};\n\n // ── destination ───────────────────────────────────────────\n @property() accessor bucket = \"default\";\n\n /** Metadata attached to every file this element uploads. */\n @property({ converter: jsonAttr })\n accessor metadata: Record<string, unknown> = {};\n\n /**\n * `options` sent with every file's upload request — for instance\n * `{ profile_photo: true }`, which makes the upload the account's photo.\n */\n @property({ converter: jsonAttr })\n accessor options: Record<string, unknown> = {};\n @property({ type: Boolean, attribute: \"public-read\" }) accessor publicRead = false;\n\n /** Where to go once every file has uploaded. Same-origin only. */\n @property({ attribute: \"redirect-url\" }) accessor redirectUrl = \"\";\n\n /** Callback forms of the two events, for frameworks that prefer props. */\n @property({ attribute: false })\n accessor onComplete:\n ((detail: { completed: UploadItem[]; failed: UploadItem[] }) => void) | null = null;\n\n @property({ attribute: false })\n accessor onError: ((detail: { message: string }) => void) | null = null;\n\n // ── state ─────────────────────────────────────────────────\n @state() private accessor items: UploadItem[] = [];\n @state() private accessor notice = \"\";\n @state() private accessor busy = false;\n @state() private accessor dragging = false;\n @state() private accessor editing = \"\";\n\n get msg(): SinglebaseUploadMessages {\n return resolveUploadMessages(this.messages);\n }\n\n /** An explicit `.client`, else the page default. */\n get resolvedClient(): UploaderClient | null {\n return this.client ?? getDefaultClient<SinglebaseClientInstance>() ?? null;\n }\n\n /** The staging list, for host code that wants to inspect or persist it. */\n get files(): readonly UploadItem[] {\n return this.items;\n }\n\n /** Overall progress across the current batch, 0–100. */\n get percent(): number {\n const active = this.items.filter((item) => item.status !== \"ready\");\n if (!active.length) return 0;\n return Math.round(active.reduce((sum, item) => sum + item.percent, 0) / active.length);\n }\n\n // ── public API ────────────────────────────────────────────\n /** Opens the file picker. */\n open(): void {\n this.renderRoot.querySelector<HTMLInputElement>(\"input[type=file]\")?.click();\n }\n\n /**\n * Applies several settings at once:\n *\n * document.getElementById(\"docs\").config = { maxFiles: 5, metadata: { folder: \"q3\" } };\n *\n * Unknown keys are ignored. Reading it returns the current settings.\n */\n set config(value: Partial<UploaderConfig>) {\n const target = this as unknown as Record<string, unknown>;\n for (const key of CONFIG_KEYS) {\n if (value && key in value) target[key] = value[key];\n }\n }\n\n /**\n * Changes settings on the fly. Only the keys you pass change; staged files\n * stay. Returns the element, so calls chain.\n */\n configure(options: Partial<UploaderConfig>): this {\n this.config = options;\n return this;\n }\n\n get config(): Partial<UploaderConfig> {\n const source = this as unknown as Record<string, unknown>;\n return Object.fromEntries(CONFIG_KEYS.map((key) => [key, source[key]]));\n }\n\n /** Drops every staged file and any notice. */\n clear(): void {\n this.items.forEach(releasePreview);\n this.items = [];\n this.notice = \"\";\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.items.forEach(releasePreview);\n }\n\n /** Uploads everything staged. Rows that already succeeded are left alone. */\n async upload(): Promise<void> {\n if (this.busy) return;\n const pending = this.items.filter((item) => item.status === \"ready\" || item.status === \"error\");\n if (!pending.length) return;\n\n const client = this.resolvedClient;\n if (!client) {\n this.fail(this.msg.errNoClient);\n return;\n }\n\n this.busy = true;\n this.notice = \"\";\n for (const item of pending) {\n item.status = \"uploading\";\n item.percent = 0;\n item.error = \"\";\n }\n this.items = [...this.items];\n\n // The SDK hands each progress and result entry back the very input object\n // it was given, so identity is all that is needed to find the row again.\n const rowOf = new Map<FileUploadInput, UploadItem>();\n const inputs = pending.map((item) => {\n const input: FileUploadInput = { file: item.file, filename: item.file.name };\n if (this.bucket) input.bucket = this.bucket;\n if (this.publicRead) input.publicRead = true;\n if (item.name !== item.file.name) input.newName = item.name;\n if (Object.keys(this.metadata ?? {}).length) input.metadata = { ...this.metadata };\n if (Object.keys(this.options ?? {}).length) input.options = { ...this.options };\n rowOf.set(input, item);\n return input;\n });\n\n try {\n const result = await client.files.upload(inputs, {\n onProgress: (progress: UploadProgress) => {\n const row = rowOf.get(progress.input);\n if (!row) return;\n row.percent = progress.percent;\n this.items = [...this.items];\n this.emit(\"singlebase-upload-progress\", { file: row, percent: this.percent });\n }\n });\n\n for (const entry of result.completed) {\n const row = rowOf.get(entry.input);\n if (!row) continue;\n row.status = \"done\";\n row.percent = 100;\n row.record = entry.file;\n }\n for (const entry of result.failed) {\n const row = rowOf.get(entry.input);\n if (!row) continue;\n row.status = \"error\";\n row.error = entry.error.message || entry.error.code;\n }\n this.items = [...this.items];\n\n const completed = result.completed\n .map((entry) => rowOf.get(entry.input))\n .filter(Boolean) as UploadItem[];\n const failed = result.failed\n .map((entry) => rowOf.get(entry.input))\n .filter(Boolean) as UploadItem[];\n\n this.emit(\"singlebase-upload-complete\", { completed, failed });\n this.onComplete?.({ completed, failed });\n\n if (failed.length) {\n this.notice = this.msg.errUpload;\n } else {\n this.redirect();\n }\n } catch (error) {\n // Initiation failed for the whole batch — nothing reached storage.\n for (const item of pending) {\n item.status = \"error\";\n item.error = \"\";\n }\n this.items = [...this.items];\n this.fail(errorMessage(error) || this.msg.errUpload);\n } finally {\n this.busy = false;\n }\n }\n\n // ── staging ───────────────────────────────────────────────\n /** The rule for this filename's extension, if the host set one. */\n private ruleFor(filename: string): FileRule | null {\n const extension = fileExtension(filename);\n if (!extension) return null;\n for (const [key, rule] of Object.entries(this.rules ?? {})) {\n if (key.toLowerCase().replace(/^\\./, \"\") === extension) return rule;\n }\n return null;\n }\n\n private async add(list: ArrayLike<File>): Promise<void> {\n // The button view is a one-shot control: a new pick replaces whatever\n // finished last time, so a max-files=\"1\" button can be used again.\n if (this.view === \"button\") {\n const finished = this.items.filter((i) => i.status === \"done\" || i.status === \"error\");\n finished.forEach(releasePreview);\n this.items = this.items.filter((i) => !finished.includes(i));\n }\n const limit = this.maxFiles > 0 ? this.maxFiles : Number.POSITIVE_INFINITY;\n const next = [...this.items];\n const before = next.length;\n const staged: UploadItem[] = [];\n let problem = \"\";\n\n for (const file of Array.from(list)) {\n if (next.length >= limit) {\n problem = fill(this.msg.errTooMany, { max: limit });\n break;\n }\n if (this.accept && !acceptsFile(this.accept, file.name, file.type)) {\n problem = fill(this.msg.errType, { name: file.name });\n continue;\n }\n\n // A rule's own size bounds win over the element-wide ones for its kind.\n const rule = this.ruleFor(file.name);\n const maxBytes = parseSize(rule?.maxSize ?? this.maxSize);\n const minBytes = parseSize(rule?.minSize ?? this.minSize);\n if (maxBytes && file.size > maxBytes) {\n problem = fill(this.msg.errTooLarge, { name: file.name, size: formatSize(maxBytes) });\n continue;\n }\n if (minBytes && file.size < minBytes) {\n problem = fill(this.msg.errTooSmall, { name: file.name, size: formatSize(minBytes) });\n continue;\n }\n const key = fileKey(file);\n if (next.some((item) => item.key === key)) {\n problem = fill(this.msg.errDuplicate, { name: file.name });\n continue;\n }\n\n const item: UploadItem = {\n key,\n file,\n name: file.name,\n // Reading bytes takes a moment, so the row appears immediately as\n // \"checking\" rather than the widget freezing on a picked file.\n status: this.needsInspection(rule, file.name) ? \"checking\" : \"ready\",\n percent: 0,\n error: \"\",\n record: null,\n pages: null,\n encrypted: null,\n preview: previewFor(file)\n };\n next.push(item);\n staged.push(item);\n }\n\n this.notice = problem;\n if (problem) this.emit(\"singlebase-upload-rejected\", { message: problem });\n if (next.length === before) return;\n\n this.items = next;\n this.emit(\"singlebase-upload-selected\", { files: this.items });\n\n await Promise.all(\n staged\n .filter((item) => item.status === \"checking\")\n .map((item) => this.inspect(item, this.ruleFor(item.file.name)!))\n );\n\n if (this.autoUpload || this.view === \"button\") void this.upload();\n }\n\n private needsInspection(rule: FileRule | null, filename: string): boolean {\n if (!rule) return false;\n if (!isInspectable(fileExtension(filename))) return false;\n return rule.maxPages !== undefined || rule.allowProtected === false;\n }\n\n /**\n * Reads the file and applies the rule. A fact the reader could not\n * determine is not grounds for rejection — an unreadable page count means\n * the page rule simply doesn't apply to that file.\n */\n private async inspect(item: UploadItem, rule: FileRule): Promise<void> {\n const facts = await inspectFile(item.file, fileExtension(item.file.name));\n item.pages = facts.pages;\n item.encrypted = facts.encrypted;\n\n let problem = \"\";\n if (rule.allowProtected === false && facts.encrypted === true) {\n problem = fill(this.msg.errProtected, { name: item.name });\n } else if (rule.maxPages && facts.pages !== null && facts.pages > rule.maxPages) {\n problem = fill(this.msg.errTooManyPages, {\n name: item.name,\n pages: facts.pages,\n max: rule.maxPages\n });\n }\n\n if (problem) {\n releasePreview(item);\n this.items = this.items.filter((staged) => staged !== item);\n this.notice = problem;\n this.emit(\"singlebase-upload-rejected\", { message: problem });\n } else {\n item.status = \"ready\";\n this.items = [...this.items];\n }\n }\n\n /** Drops one staged file. Named for the row action, not Element.remove(). */\n private removeItem(key: string): void {\n this.items.filter((item) => item.key === key).forEach(releasePreview);\n this.items = this.items.filter((item) => item.key !== key);\n this.notice = \"\";\n }\n\n private commitRename(item: UploadItem, typed: string): void {\n item.name = renameKeepingExtension(item.file.name, typed);\n this.editing = \"\";\n this.items = [...this.items];\n }\n\n private fail(message: string): void {\n this.notice = message;\n this.emit(\"singlebase-upload-error\", { message });\n this.onError?.({ message });\n }\n\n private emit(name: string, detail: unknown): void {\n this.dispatchEvent(new CustomEvent(name, { detail, bubbles: true, composed: true }));\n }\n\n private redirect(): void {\n if (!this.redirectUrl || typeof location === \"undefined\") return;\n const target = resolveRedirectTarget(this.redirectUrl, location.href, (reason) =>\n console.warn(`[singlebase-uploader] ${reason}`)\n );\n if (target) location.assign(target);\n }\n\n // ── events ────────────────────────────────────────────────\n private onPick(event: Event): void {\n const input = event.target as HTMLInputElement;\n if (input.files?.length) this.add(input.files);\n // Reset, or picking the same file twice in a row fires no change event.\n input.value = \"\";\n }\n\n private onDrop(event: DragEvent): void {\n event.preventDefault();\n this.dragging = false;\n const dropped = event.dataTransfer?.files;\n if (dropped?.length) this.add(dropped);\n }\n\n private onDragOver(event: DragEvent): void {\n event.preventDefault();\n this.dragging = true;\n }\n\n private onDragLeave(): void {\n this.dragging = false;\n }\n\n // ── rendering ─────────────────────────────────────────────\n private get canAddMore(): boolean {\n return this.maxFiles <= 0 || this.items.length < this.maxFiles;\n }\n\n /** True while any staged file is still being read. */\n private get checking(): boolean {\n return this.items.some((item) => item.status === \"checking\");\n }\n\n private get pendingCount(): number {\n return this.items.filter((item) => item.status === \"ready\" || item.status === \"error\").length;\n }\n\n private get hint(): string {\n const kinds = acceptSummary(this.accept);\n const maxBytes = parseSize(this.maxSize);\n const size = maxBytes ? fill(this.msg.hintUpTo, { size: formatSize(maxBytes) }) : \"\";\n return [kinds, size].filter(Boolean).join(\" · \");\n }\n\n private renderInput() {\n return html`<input\n class=\"sr-only\"\n type=\"file\"\n ?multiple=${this.maxFiles !== 1}\n accept=${this.accept || nothing}\n @change=${this.onPick}\n />`;\n }\n\n private renderLogo() {\n if (this.logoUrl) {\n return html`<img\n class=\"logo-img\"\n src=${this.logoUrl}\n alt=${this.logoText || \"Logo\"}\n part=\"logo\"\n />`;\n }\n if (this.logoText) return html`<div class=\"brand-mark\" part=\"logo\">${this.logoText}</div>`;\n return nothing;\n }\n\n private renderBranding() {\n return renderBranding(this.branding, \"Files\");\n }\n\n private renderNotice() {\n if (!this.notice) return nothing;\n return html`<div class=\"banner\" role=\"alert\" part=\"error\">${this.notice}</div>`;\n }\n\n private renderCount() {\n if (!this.items.length) return nothing;\n const template = this.items.length === 1 ? this.msg.countOne : this.msg.countMany;\n return html`<div class=\"count\" part=\"count\">\n ${fill(template, { n: this.items.length, max: this.maxFiles })}\n </div>`;\n }\n\n private renderStatus(item: UploadItem): string {\n const size = formatSize(item.file.size);\n if (item.status === \"checking\") return `${size} · ${this.msg.checking}`;\n if (item.status === \"uploading\") return `${size} · ${this.msg.uploading}`;\n if (item.status === \"done\") return `${size} · ${this.msg.uploaded}`;\n if (item.status === \"error\") {\n return `${size} · ${item.error || this.msg.failedLabel}`;\n }\n // A page count is only shown once it has actually been read.\n const pages = item.pages ? ` · ${fill(this.msg.pagesLabel, { n: item.pages })}` : \"\";\n return size + pages;\n }\n\n private renderRow(item: UploadItem) {\n const editable = this.allowRename && item.status === \"ready\";\n const busyRow = item.status === \"uploading\" || item.status === \"done\";\n return html`<div class=\"row\" part=\"file\">\n <div class=\"chip\" part=\"file-type\">\n ${\n item.preview\n ? html`<img class=\"thumb\" src=${item.preview} alt=\"\" part=\"preview\" />`\n : extensionOf(item.name) || \"FILE\"\n }\n </div>\n <div class=\"meta\">\n ${\n this.editing === item.key\n ? html`<input\n class=\"name-input\"\n .value=${item.name}\n autofocus\n @keydown=${(event: KeyboardEvent) => {\n if (event.key === \"Enter\") {\n this.commitRename(item, (event.target as HTMLInputElement).value);\n } else if (event.key === \"Escape\") {\n this.editing = \"\";\n }\n }}\n @blur=${(event: FocusEvent) =>\n this.commitRename(item, (event.target as HTMLInputElement).value)}\n />`\n : editable\n ? html`<button\n class=\"name\"\n title=${this.msg.rename}\n @click=${() => {\n this.editing = item.key;\n }}\n >\n ${item.name}\n </button>`\n : html`<div class=\"name\">${item.name}</div>`\n }\n <div class=\"sz\" data-state=${item.status}>${this.renderStatus(item)}</div>\n ${\n item.status === \"uploading\"\n ? html`<div class=\"bar\" part=\"progress\">\n <div class=\"bar-fill\" style=\"width:${item.percent}%\"></div>\n </div>`\n : nothing\n }\n </div>\n <div class=\"row-act\">\n ${\n item.status === \"error\"\n ? html`<button class=\"link-sm\" @click=${() => void this.upload()}>\n ${this.msg.retry}\n </button>`\n : nothing\n }\n ${\n item.status === \"uploading\" || item.status === \"done\"\n ? nothing\n : html`<button class=\"link-sm\" @click=${() => this.removeItem(item.key)}>\n ${this.msg.remove}\n </button>`\n }\n </div>\n </div>`;\n }\n\n private renderRows() {\n if (!this.items.length) return nothing;\n return html`<div class=\"rows\" part=\"files\">\n ${this.items.map((item) => this.renderRow(item))}\n </div>`;\n }\n\n private renderDropzone() {\n return html`<div class=\"drop\" part=\"dropzone\" data-drag=${String(this.dragging)}>\n <div class=\"arrow\" aria-hidden=\"true\">↑</div>\n <div class=\"drop-title\">${this.msg.dropTitle}</div>\n <button class=\"link\" @click=${this.open}>${this.msg.dropSub}</button>\n ${this.hint ? html`<div class=\"hint\">${this.hint}</div>` : nothing}\n </div>`;\n }\n\n private renderUploadCta() {\n const n = this.pendingCount;\n // Kept on screen while busy: a primary button that vanishes mid-upload\n // makes the card jump just as the user is watching it.\n if (this.autoUpload || (!n && !this.busy)) return nothing;\n const template = n === 1 ? this.msg.uploadCtaOne : this.msg.uploadCtaMany;\n return html`<button\n class=\"primary wide\"\n part=\"submit\"\n ?disabled=${this.busy || this.checking}\n @click=${() => void this.upload()}\n >\n ${this.busy ? this.msg.uploading : fill(template, { n })}\n </button>`;\n }\n\n /**\n * The whole card is the drop surface. Once files are staged the big zone is\n * replaced by the \"add more\" control, and a drop should still land.\n */\n private renderFull() {\n const showDrop = this.dropzone && !this.items.length && this.canAddMore;\n return html`<div\n class=\"card\"\n part=\"card\"\n @dragover=${this.onDragOver}\n @dragleave=${this.onDragLeave}\n @drop=${this.onDrop}\n >\n ${\n this.logoUrl || this.logoText || this.heading || this.description\n ? html`<div class=\"head-block\">\n ${this.renderLogo()}\n ${this.heading ? html`<div class=\"title\">${this.heading}</div>` : nothing}\n ${this.description ? html`<div class=\"sub\">${this.description}</div>` : nothing}\n </div>`\n : nothing\n }\n ${this.renderCount()} ${this.renderNotice()} ${this.renderRows()}\n ${showDrop ? this.renderDropzone() : nothing}\n ${\n !showDrop && this.canAddMore\n ? html`<button class=\"add-more\" @click=${this.open}>${this.msg.addMore}</button>`\n : nothing\n }\n ${this.renderUploadCta()} ${this.renderBranding()}\n </div>`;\n }\n\n private renderCompact() {\n return html`<div\n class=\"card\"\n part=\"card\"\n @dragover=${this.onDragOver}\n @dragleave=${this.onDragLeave}\n @drop=${this.onDrop}\n >\n <div class=\"between\">\n <span class=\"sec-title\">${this.heading || this.msg.attachments}</span>\n <span class=\"count\">${this.items.length} / ${this.maxFiles}</span>\n </div>\n ${\n this.dropzone\n ? html`<div class=\"strip\" part=\"dropzone\" data-drag=${String(this.dragging)}>\n <span class=\"strip-label\">${this.msg.dropOrChoose}</span>\n <button class=\"secondary\" ?disabled=${!this.canAddMore} @click=${this.open}>\n ${this.msg.chooseFiles}\n </button>\n </div>`\n : html`<button class=\"secondary\" ?disabled=${!this.canAddMore} @click=${this.open}>\n ${this.msg.chooseFiles}\n </button>`\n }\n ${this.hint ? html`<div class=\"hint\">${this.hint}</div>` : nothing} ${this.renderNotice()}\n ${this.renderRows()} ${this.renderUploadCta()} ${this.renderBranding()}\n </div>`;\n }\n\n private renderButton() {\n const active = this.items[this.items.length - 1];\n return html`<div class=\"button-view\">\n <button class=\"primary\" ?disabled=${this.busy || !this.canAddMore} @click=${this.open}>\n ${this.busy ? this.msg.uploading : this.msg.chooseFile}\n </button>\n ${\n active && active.status !== \"ready\"\n ? html`<div class=\"sz\" data-state=${active.status}>${this.renderStatus(active)}</div>`\n : nothing\n }\n ${this.renderNotice()}\n </div>`;\n }\n\n override render() {\n return html`${this.renderInput()}${\n this.view === \"button\"\n ? this.renderButton()\n : this.view === \"compact\"\n ? this.renderCompact()\n : this.renderFull()\n }`;\n }\n}\n\n/**\n * A local thumbnail for images. The object URL points at the bytes already in\n * memory — nothing is uploaded to draw it — and it is revoked when the row\n * goes away so a long session doesn't leak blobs.\n */\nfunction previewFor(file: File): string {\n if (!file.type.startsWith(\"image/\") || typeof URL.createObjectURL !== \"function\") return \"\";\n return URL.createObjectURL(file);\n}\n\nfunction releasePreview(item: UploadItem): void {\n if (item.preview) URL.revokeObjectURL(item.preview);\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : \"\";\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"singlebase-uploader\": SinglebaseUploader;\n }\n}\n"],"names":["sharedStyles","css","resolveRedirectTarget","candidate","currentHref","onRefused","here","target","UNKNOWN","PDF_HEAD","PDF_TAIL","MAX_STREAMS","MAX_INFLATED","OOXML","inspectFile","file","extension","inspectPdf","inspectOoxml","isInspectable","head","bytesOf","tail","text","latin1","encrypted","pages","pageCountIn","pageCountInStreams","max","match","direct","bytes","inflated","streams","start","end","out","inflate","magic","isCompoundFile","app","readZipEntry","tag","byte","i","wanted","tailSize","eocd","size","offset","cd","decoder","p","method","compressed","nameLength","extraLength","commentLength","localOffset","local","data","blob","format","stream","jsonAttr","value","parsed","flagAttr","CONFIG_KEYS","SinglebaseUploader","_a","LitElement","__privateAdd","_client","_messages","_theme","_density","_radius","_view","_dropzone","_allowRename","_autoUpload","_branding","_logoUrl","_logoText","_heading","_description","_maxFiles","_maxSize","_minSize","_accept","_rules","_bucket","_metadata","_options","_publicRead","_redirectUrl","_onComplete","_onError","_items","_notice","_busy","_dragging","_editing","__privateGet","_","__privateSet","resolveUploadMessages","getDefaultClient","active","item","sum","key","options","source","releasePreview","pending","client","rowOf","inputs","input","result","progress","row","entry","completed","failed","error","errorMessage","filename","fileExtension","rule","list","finished","limit","next","before","staged","problem","fill","acceptsFile","maxBytes","parseSize","minBytes","formatSize","fileKey","previewFor","facts","typed","renameKeepingExtension","message","name","detail","reason","event","dropped","kinds","acceptSummary","html","nothing","renderBranding","template","editable","extensionOf","n","showDrop","__publicField","tokenDefaults","brandingStyles","__decorateClass","property","state","customElement"],"mappings":"qdASaA,GAAeC,EAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA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AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;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"}
|