@singlebase/elements 0.1.0 → 0.5.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/README.md +2 -0
- package/dist/{display-8HEcKYR4.js → authui-display-BCZBP7HR.js} +11 -10
- package/dist/authui-display-BCZBP7HR.js.map +1 -0
- package/dist/{display-CLDNNZQy.cjs → authui-display-CLGFSqRi.cjs} +21 -21
- package/dist/authui-display-CLGFSqRi.cjs.map +1 -0
- package/dist/authui.cjs +1 -1
- package/dist/authui.d.ts +9 -9
- package/dist/authui.js +2 -2
- package/dist/chat-DRenTJlI.cjs +3001 -0
- package/dist/chat-DRenTJlI.cjs.map +1 -0
- package/dist/chat-bXaRWel7.js +4926 -0
- package/dist/chat-bXaRWel7.js.map +1 -0
- package/dist/chat-messages.d.ts +109 -0
- package/dist/chat.cjs +2 -0
- package/dist/chat.cjs.map +1 -0
- package/dist/chat.d.ts +10 -0
- package/dist/chat.js +13 -0
- package/dist/chat.js.map +1 -0
- package/dist/elements/{account-screen.d.ts → authui-account.d.ts} +1 -1
- package/dist/elements/{buttons.d.ts → authui-buttons.d.ts} +1 -1
- package/dist/elements/{display.d.ts → authui-display.d.ts} +1 -1
- package/dist/elements/{form-base.d.ts → authui-form-base.d.ts} +1 -1
- package/dist/elements/{guard.d.ts → authui-guard.d.ts} +1 -1
- package/dist/elements/{auth-screen.d.ts → authui.d.ts} +3 -3
- package/dist/elements/chat.d.ts +312 -0
- package/dist/files-BOwtpYyQ.js +168 -0
- package/dist/files-BOwtpYyQ.js.map +1 -0
- package/dist/files-DW8A4Jl-.cjs +38 -0
- package/dist/files-DW8A4Jl-.cjs.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +36 -25
- package/dist/index.js.map +1 -1
- package/dist/singlebase-elements.min.js +6845 -1829
- package/dist/singlebase-elements.min.js.map +1 -1
- package/dist/styles/chat.d.ts +6 -0
- package/dist/styles/tokens.d.ts +1 -1
- package/dist/{uploader-eFYKpk8b.cjs → uploader-DGV2y9uT.cjs} +41 -77
- package/dist/uploader-DGV2y9uT.cjs.map +1 -0
- package/dist/{uploader-D-Da1trc.js → uploader-abQoem5q.js} +309 -463
- package/dist/uploader-abQoem5q.js.map +1 -0
- package/dist/uploader.cjs +1 -1
- package/dist/uploader.js +5 -4
- package/dist/uploader.js.map +1 -1
- package/dist/utils/markdown.d.ts +108 -0
- package/package.json +13 -5
- package/dist/display-8HEcKYR4.js.map +0 -1
- package/dist/display-CLDNNZQy.cjs.map +0 -1
- package/dist/uploader-D-Da1trc.js.map +0 -1
- package/dist/uploader-eFYKpk8b.cjs.map +0 -1
- /package/dist/elements/{base.d.ts → authui-base.d.ts} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uploader-abQoem5q.js","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 .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: var(--sb-radius, 4px);\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: var(--sb-radius, 4px);\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: var(--sb-radius, 4px);\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: var(--sb-radius, 4px);\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: var(--sb-radius, 4px);\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: var(--sb-radius, 4px);\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: var(--sb-radius, 4px);\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: var(--sb-radius, 4px);\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: var(--sb-radius, 4px);\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: var(--sb-radius, 4px);\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 { 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 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 \"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 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);\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);\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);\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: var(--sb-radius, 4px);\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);\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 .branding {\n text-align: center;\n font-family: var(--sb-mono, \"Geist Mono\", ui-monospace, monospace);\n font-size: 10.5px;\n letter-spacing: 0.06em;\n color: var(--sb-muted-ink, #61666c);\n }\n\n .branding a {\n color: inherit;\n text-decoration: none;\n }\n\n .branding a:hover {\n color: var(--sb-ink, #16181a);\n text-decoration: underline;\n text-underline-offset: 3px;\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 // ── 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 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 if (!this.branding) return nothing;\n return html`<div class=\"branding\" part=\"branding\">\n <a href=\"https://singlebase.cloud\" target=\"_blank\" rel=\"noopener noreferrer\"\n >${this.msg.brandingLabel}</a\n >\n </div>`;\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","wanted","tailSize","eocd","i","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","_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","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","template","editable","extensionOf","n","showDrop","__publicField","tokenDefaults","__decorateClass","property","state","customElement"],"mappings":";;;;;;;;;AASO,MAAMA,KAAeC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA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"}
|
package/dist/uploader.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./uploader-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./uploader-DGV2y9uT.cjs"),s=require("./files-DW8A4Jl-.cjs");Object.defineProperty(exports,"SinglebaseUploader",{enumerable:!0,get:()=>e.SinglebaseUploader});exports.inspectFile=e.inspectFile;exports.isInspectable=e.isInspectable;exports.defaultUploadMessages=s.defaultUploadMessages;exports.resolveUploadMessages=s.resolveUploadMessages;
|
|
2
2
|
//# sourceMappingURL=uploader.cjs.map
|
package/dist/uploader.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { S as a,
|
|
1
|
+
import { S as a, i as l, a as o } from "./uploader-abQoem5q.js";
|
|
2
|
+
import { d as r, r as d } from "./files-BOwtpYyQ.js";
|
|
2
3
|
export {
|
|
3
4
|
a as SinglebaseUploader,
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
r as defaultUploadMessages,
|
|
6
|
+
l as inspectFile,
|
|
7
|
+
o as isInspectable,
|
|
7
8
|
d as resolveUploadMessages
|
|
8
9
|
};
|
|
9
10
|
//# sourceMappingURL=uploader.js.map
|
package/dist/uploader.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"uploader.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"uploader.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The small Markdown subset <singlebase-chat> renders, parsed into plain
|
|
3
|
+
* blocks. Nothing here produces HTML: the element turns blocks into Lit
|
|
4
|
+
* templates, so model output is always text, never markup.
|
|
5
|
+
*
|
|
6
|
+
* Supported: paragraphs, `#`–`####` headings, `-`/`*`/`1.` lists, `>` quotes,
|
|
7
|
+
* fenced code, ```chart JSON blocks, pipe tables, `` images,
|
|
8
|
+
* `**bold**`, `` `code` ``, `[text](https://…)` links and `[n]` citations.
|
|
9
|
+
*/
|
|
10
|
+
export interface ChartSeries {
|
|
11
|
+
name: string;
|
|
12
|
+
values: number[];
|
|
13
|
+
}
|
|
14
|
+
export interface ChartSpec {
|
|
15
|
+
type: "bar" | "line";
|
|
16
|
+
title: string;
|
|
17
|
+
unit: string;
|
|
18
|
+
labels: string[];
|
|
19
|
+
series: ChartSeries[];
|
|
20
|
+
}
|
|
21
|
+
export interface ImageRef {
|
|
22
|
+
alt: string;
|
|
23
|
+
src: string;
|
|
24
|
+
}
|
|
25
|
+
export type Block = {
|
|
26
|
+
type: "p";
|
|
27
|
+
text: string;
|
|
28
|
+
} | {
|
|
29
|
+
type: "h";
|
|
30
|
+
level: number;
|
|
31
|
+
text: string;
|
|
32
|
+
} | {
|
|
33
|
+
type: "list";
|
|
34
|
+
ordered: boolean;
|
|
35
|
+
items: string[];
|
|
36
|
+
} | {
|
|
37
|
+
type: "quote";
|
|
38
|
+
text: string;
|
|
39
|
+
} | {
|
|
40
|
+
type: "code";
|
|
41
|
+
lang: string;
|
|
42
|
+
text: string;
|
|
43
|
+
} | {
|
|
44
|
+
type: "table";
|
|
45
|
+
head: string[];
|
|
46
|
+
rows: string[][];
|
|
47
|
+
} | {
|
|
48
|
+
type: "chart";
|
|
49
|
+
spec: ChartSpec;
|
|
50
|
+
} | {
|
|
51
|
+
type: "chartPending";
|
|
52
|
+
} | {
|
|
53
|
+
type: "img";
|
|
54
|
+
images: ImageRef[];
|
|
55
|
+
} | {
|
|
56
|
+
type: "raw";
|
|
57
|
+
text: string;
|
|
58
|
+
};
|
|
59
|
+
export type Segment = {
|
|
60
|
+
type: "text";
|
|
61
|
+
text: string;
|
|
62
|
+
} | {
|
|
63
|
+
type: "bold";
|
|
64
|
+
text: string;
|
|
65
|
+
} | {
|
|
66
|
+
type: "code";
|
|
67
|
+
text: string;
|
|
68
|
+
} | {
|
|
69
|
+
type: "link";
|
|
70
|
+
text: string;
|
|
71
|
+
href: string;
|
|
72
|
+
} | {
|
|
73
|
+
type: "cite";
|
|
74
|
+
n: number;
|
|
75
|
+
};
|
|
76
|
+
export type RenderAs = "rich" | "markdown" | "text";
|
|
77
|
+
/** Parses `text` into blocks. An unclosed fence is still streaming. */
|
|
78
|
+
export declare function parseMarkdown(text: string): Block[];
|
|
79
|
+
/** A ```chart body, or null when it is not a usable spec. */
|
|
80
|
+
export declare function parseChart(body: string): ChartSpec | null;
|
|
81
|
+
/**
|
|
82
|
+
* Inline segments of one line. Citations only become chips when `maxCite`
|
|
83
|
+
* is at least the cited number; anything else stays literal text.
|
|
84
|
+
*/
|
|
85
|
+
export declare function parseInline(text: string, maxCite?: number): Segment[];
|
|
86
|
+
/** Every citation number used in `text`. */
|
|
87
|
+
export declare function citedNumbers(text: string): Set<number>;
|
|
88
|
+
/**
|
|
89
|
+
* Applies `render-as`. `rich` keeps everything; `markdown` turns charts into
|
|
90
|
+
* tables and images into a line of text; `text` flattens it all to one block.
|
|
91
|
+
*/
|
|
92
|
+
export declare function adaptBlocks(blocks: Block[], renderAs: RenderAs): Block[];
|
|
93
|
+
/**
|
|
94
|
+
* Splits the `FOLLOWUPS:` tail the model is asked to write off the visible
|
|
95
|
+
* answer. Questions may be `|`-separated or one per line.
|
|
96
|
+
*/
|
|
97
|
+
export declare function splitFollowups(content: string): {
|
|
98
|
+
text: string;
|
|
99
|
+
followups: string[];
|
|
100
|
+
};
|
|
101
|
+
/** A one-line plain rendering, for snippets and search. */
|
|
102
|
+
export declare function plainText(text: string): string;
|
|
103
|
+
/** The first message, cut at a word boundary: a title until a better one lands. */
|
|
104
|
+
export declare function provisionalTitle(text: string, max?: number): string;
|
|
105
|
+
/** A model-written title: no quotes, no trailing punctuation, 80 characters. */
|
|
106
|
+
export declare function cleanTitle(value: unknown): string;
|
|
107
|
+
/** Only these reach an `<img src>` or a link: no javascript:, no stray schemes. */
|
|
108
|
+
export declare function isSafeUrl(url: string, image?: boolean): boolean;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@singlebase/elements",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Singlebase web components — authentication UI
|
|
3
|
+
"version": "0.5.0",
|
|
4
|
+
"description": "Singlebase web components — authentication UI, file uploads and AI chat as custom elements",
|
|
5
5
|
"homepage": "https://singlebase.cloud",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"license": "MIT",
|
|
@@ -29,6 +29,11 @@
|
|
|
29
29
|
"import": "./dist/uploader.js",
|
|
30
30
|
"require": "./dist/uploader.cjs"
|
|
31
31
|
},
|
|
32
|
+
"./chat": {
|
|
33
|
+
"types": "./dist/chat.d.ts",
|
|
34
|
+
"import": "./dist/chat.js",
|
|
35
|
+
"require": "./dist/chat.cjs"
|
|
36
|
+
},
|
|
32
37
|
"./standalone": "./dist/singlebase-elements.min.js",
|
|
33
38
|
"./package.json": "./package.json"
|
|
34
39
|
},
|
|
@@ -37,8 +42,8 @@
|
|
|
37
42
|
"sideEffects": true,
|
|
38
43
|
"dependencies": {
|
|
39
44
|
"lit": "^3.2.0",
|
|
40
|
-
"@singlebase/
|
|
41
|
-
"@singlebase/
|
|
45
|
+
"@singlebase/singlebase-sdk": "0.5.0",
|
|
46
|
+
"@singlebase/core": "0.5.0"
|
|
42
47
|
},
|
|
43
48
|
"devDependencies": {
|
|
44
49
|
"@esm-bundle/chai": "^4.3.4-fix.0",
|
|
@@ -56,7 +61,10 @@
|
|
|
56
61
|
"auth",
|
|
57
62
|
"authentication",
|
|
58
63
|
"upload",
|
|
59
|
-
"files"
|
|
64
|
+
"files",
|
|
65
|
+
"chat",
|
|
66
|
+
"ai",
|
|
67
|
+
"llm"
|
|
60
68
|
],
|
|
61
69
|
"repository": {
|
|
62
70
|
"type": "git",
|