@singlebase/elements 0.3.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/README.md +2 -0
  2. package/dist/{display-8HEcKYR4.js → authui-display-CKfGK5va.js} +519 -502
  3. package/dist/authui-display-CKfGK5va.js.map +1 -0
  4. package/dist/{display-CLDNNZQy.cjs → authui-display-aWNht0cW.cjs} +38 -58
  5. package/dist/authui-display-aWNht0cW.cjs.map +1 -0
  6. package/dist/authui.cjs +1 -1
  7. package/dist/authui.d.ts +9 -9
  8. package/dist/authui.js +2 -2
  9. package/dist/chat-C-gsskho.cjs +3258 -0
  10. package/dist/chat-C-gsskho.cjs.map +1 -0
  11. package/dist/chat-CEh6RygY.js +5746 -0
  12. package/dist/chat-CEh6RygY.js.map +1 -0
  13. package/dist/chat-messages.d.ts +115 -0
  14. package/dist/chat.cjs +2 -0
  15. package/dist/chat.cjs.map +1 -0
  16. package/dist/chat.d.ts +11 -0
  17. package/dist/chat.js +15 -0
  18. package/dist/chat.js.map +1 -0
  19. package/dist/elements/{account-screen.d.ts → authui-account.d.ts} +1 -1
  20. package/dist/elements/{base.d.ts → authui-base.d.ts} +2 -0
  21. package/dist/elements/{buttons.d.ts → authui-buttons.d.ts} +2 -2
  22. package/dist/elements/{display.d.ts → authui-display.d.ts} +2 -2
  23. package/dist/elements/{form-base.d.ts → authui-form-base.d.ts} +1 -1
  24. package/dist/elements/{guard.d.ts → authui-guard.d.ts} +1 -1
  25. package/dist/elements/{auth-screen.d.ts → authui.d.ts} +8 -4
  26. package/dist/elements/chat.d.ts +455 -0
  27. package/dist/elements/uploader.d.ts +14 -0
  28. package/dist/files-DDJWPzZW.js +215 -0
  29. package/dist/files-DDJWPzZW.js.map +1 -0
  30. package/dist/files-DyxcjZsx.cjs +75 -0
  31. package/dist/files-DyxcjZsx.cjs.map +1 -0
  32. package/dist/index.cjs +1 -1
  33. package/dist/index.d.ts +3 -2
  34. package/dist/index.js +34 -21
  35. package/dist/index.js.map +1 -1
  36. package/dist/singlebase-elements.min.js +8044 -2120
  37. package/dist/singlebase-elements.min.js.map +1 -1
  38. package/dist/styles/branding.d.ts +5 -0
  39. package/dist/styles/chat.d.ts +6 -0
  40. package/dist/styles/tokens.d.ts +3 -1
  41. package/dist/{uploader-eFYKpk8b.cjs → uploader-660JIgIN.cjs} +55 -114
  42. package/dist/uploader-660JIgIN.cjs.map +1 -0
  43. package/dist/{uploader-D-Da1trc.js → uploader-vfczkX51.js} +376 -507
  44. package/dist/uploader-vfczkX51.js.map +1 -0
  45. package/dist/uploader.cjs +1 -1
  46. package/dist/uploader.js +5 -4
  47. package/dist/uploader.js.map +1 -1
  48. package/dist/utils/branding.d.ts +8 -0
  49. package/dist/utils/markdown.d.ts +165 -0
  50. package/dist/utils/svg.d.ts +10 -0
  51. package/package.json +13 -5
  52. package/dist/display-8HEcKYR4.js.map +0 -1
  53. package/dist/display-CLDNNZQy.cjs.map +0 -1
  54. package/dist/uploader-D-Da1trc.js.map +0 -1
  55. package/dist/uploader-eFYKpk8b.cjs.map +0 -1
@@ -0,0 +1,215 @@
1
+ import { unsafeCSS as i, css as f, nothing as l, html as p } from "lit";
2
+ const d = {
3
+ font: '"Geist", -apple-system, "Segoe UI", Helvetica, sans-serif',
4
+ mono: '"Geist Mono", ui-monospace, monospace',
5
+ accent: "#111111",
6
+ onAccent: "#ffffff",
7
+ radius: "4px",
8
+ /** Multiplies every corner. The `radius` attribute sets it per element. */
9
+ radiusScale: "1",
10
+ surface: "#ffffff",
11
+ surfaceAlt: "#fafafa",
12
+ ink: "#16181a",
13
+ mutedInk: "#61666c",
14
+ border: "#e4e6e9",
15
+ borderStrong: "#cdd1d6",
16
+ danger: "#b4231a",
17
+ dangerBg: "#fdf1f0",
18
+ dangerBorder: "#f3d6d3",
19
+ dangerOutline: "#e8c4c0",
20
+ dangerPanelBorder: "#efd9d6",
21
+ dangerPanelBg: "#fdf7f6",
22
+ ok: "#0f6b4a",
23
+ okBg: "#f0f7f3",
24
+ okBorder: "#cfe5da",
25
+ gap: "16px",
26
+ pad: "20px",
27
+ fieldPad: "11px 13px"
28
+ }, m = f`
29
+ :host {
30
+ display: block;
31
+ box-sizing: border-box;
32
+ font-family: var(--sb-font, ${i(d.font)});
33
+ color: var(--sb-ink, ${i(d.ink)});
34
+ }
35
+
36
+ :host([theme="dark"]) {
37
+ /* The light default accent is near-black, which disappears on a dark
38
+ surface — primary buttons and links both use it. A host that sets its
39
+ own --sb-accent still wins: outer-page declarations beat :host rules. */
40
+ --sb-accent: #f3f4f5;
41
+ --sb-on-accent: #17181b;
42
+ --sb-surface: #17181b;
43
+ --sb-surface-alt: #202226;
44
+ --sb-ink: #f3f4f5;
45
+ --sb-muted-ink: #a2a8ae;
46
+ --sb-border: #2c2f34;
47
+ --sb-border-strong: #3a3e44;
48
+ --sb-danger: #f08379;
49
+ --sb-danger-bg: rgba(240, 131, 121, 0.1);
50
+ --sb-danger-border: rgba(240, 131, 121, 0.3);
51
+ --sb-danger-outline: rgba(240, 131, 121, 0.4);
52
+ --sb-danger-panel-border: rgba(240, 131, 121, 0.3);
53
+ --sb-danger-panel-bg: rgba(240, 131, 121, 0.06);
54
+ --sb-ok: #6fd1a6;
55
+ --sb-ok-bg: rgba(111, 209, 166, 0.1);
56
+ --sb-ok-border: rgba(111, 209, 166, 0.28);
57
+ }
58
+
59
+ /* Corner presets. They set the scale on this element only, so a page-wide
60
+ :root { --sb-radius-scale } (or --sb-radius) applies to every element
61
+ that doesn't carry the attribute. */
62
+ :host([radius="sharp"]) {
63
+ --sb-radius-scale: 0.35;
64
+ }
65
+
66
+ :host([radius="default"]) {
67
+ --sb-radius-scale: 1;
68
+ }
69
+
70
+ :host([radius="round"]) {
71
+ --sb-radius-scale: 1.8;
72
+ }
73
+
74
+ :host([density="compact"]) {
75
+ --sb-gap: 12px;
76
+ --sb-pad: 16px;
77
+ --sb-field-pad: 9px 11px;
78
+ }
79
+ `, x = f`
80
+ .branding {
81
+ text-align: center;
82
+ font-family: var(--sb-mono, "Geist Mono", ui-monospace, monospace);
83
+ font-size: 10.5px;
84
+ line-height: 1.4;
85
+ letter-spacing: 0.06em;
86
+ color: var(--sb-muted-ink, #61666c);
87
+ }
88
+
89
+ .branding a {
90
+ color: inherit;
91
+ text-decoration: none;
92
+ }
93
+
94
+ .branding a:hover {
95
+ color: var(--sb-ink, #16181a);
96
+ text-decoration: underline;
97
+ text-underline-offset: 3px;
98
+ }
99
+ `, b = "https://singlebase.cloud";
100
+ function k(e, r, a, n) {
101
+ if (!e) return l;
102
+ const t = /^https?:\/\//i.test((n == null ? void 0 : n.trim()) ?? "") ? n.trim() : b;
103
+ return p`<div class="branding" part="branding">
104
+ <a href=${t} target="_blank" rel="noopener noreferrer">${(r == null ? void 0 : r.trim()) || a}</a>
105
+ </div>`;
106
+ }
107
+ const c = {
108
+ heading: "Upload files",
109
+ description: "Add one or more files. You can review the list before uploading.",
110
+ dropTitle: "Drag and drop files here",
111
+ dropSub: "or browse from your device",
112
+ hintUpTo: "up to {size} each",
113
+ chooseFiles: "Choose files",
114
+ chooseFile: "Choose file",
115
+ addMore: "+ Add more files",
116
+ remove: "Remove",
117
+ rename: "Rename",
118
+ retry: "Retry",
119
+ uploadCtaOne: "Upload {n} file",
120
+ uploadCtaMany: "Upload {n} files",
121
+ attachments: "Attachments",
122
+ dropOrChoose: "Drop files or choose",
123
+ checking: "Checking…",
124
+ pagesLabel: "{n} pages",
125
+ countOne: "{n} file of {max}",
126
+ countMany: "{n} files of {max}",
127
+ uploading: "Uploading…",
128
+ uploaded: "Uploaded",
129
+ failedLabel: "Failed",
130
+ errTooMany: "You can upload up to {max} files.",
131
+ errTooLarge: "{name} is larger than {size}.",
132
+ errTooSmall: "{name} is smaller than {size}.",
133
+ errDuplicate: "{name} is already in the list.",
134
+ errType: "{name} isn't an accepted file type.",
135
+ errNoClient: "No Singlebase client found on this page.",
136
+ errUpload: "Upload failed.",
137
+ errProtected: "{name} is password protected.",
138
+ errTooManyPages: "{name} has {pages} pages; the limit is {max}.",
139
+ brandingLabel: "Files by Singlebase"
140
+ };
141
+ function C(e) {
142
+ return e ? { ...c, ...e } : c;
143
+ }
144
+ function y(e, r) {
145
+ return e.replace(
146
+ /\{(\w+)\}/g,
147
+ (a, n) => n in r ? String(r[n]) : a
148
+ );
149
+ }
150
+ const u = {
151
+ b: 1,
152
+ kb: 1024,
153
+ mb: 1024 * 1024,
154
+ gb: 1024 * 1024 * 1024
155
+ };
156
+ function U(e) {
157
+ if (typeof e == "number") return e > 0 ? e : 0;
158
+ if (!e) return 0;
159
+ const r = String(e).trim().toLowerCase().match(/^([\d.]+)\s*(b|kb|mb|gb)?$/);
160
+ if (!r) return 0;
161
+ const a = Number.parseFloat(r[1]);
162
+ return !Number.isFinite(a) || a <= 0 ? 0 : Math.round(a * (u[r[2] ?? "b"] ?? 1));
163
+ }
164
+ function w(e) {
165
+ return e < 1024 ? `${e} B` : e < 1024 * 1024 ? `${Math.round(e / 1024)} KB` : e < 1024 * 1024 * 1024 ? `${(e / (1024 * 1024)).toFixed(1)} MB` : `${(e / (1024 * 1024 * 1024)).toFixed(1)} GB`;
166
+ }
167
+ function g(e) {
168
+ const r = e.lastIndexOf(".");
169
+ return r <= 0 || r === e.length - 1 ? "" : e.slice(r + 1).toLowerCase();
170
+ }
171
+ function S(e) {
172
+ return g(e).toUpperCase().slice(0, 4);
173
+ }
174
+ function T(e, r, a) {
175
+ const n = e.split(",").map((o) => o.trim().toLowerCase()).filter(Boolean);
176
+ if (!n.length) return !0;
177
+ const t = r.toLowerCase(), s = (a || "").toLowerCase();
178
+ return n.some((o) => o.startsWith(".") ? t.endsWith(o) : o.endsWith("/*") ? s.startsWith(o.slice(0, -1)) : s === o);
179
+ }
180
+ function B(e) {
181
+ const r = e.split(",").map((a) => a.trim()).filter(Boolean).map((a) => {
182
+ if (a.startsWith(".")) return a.slice(1).toUpperCase();
183
+ if (a.endsWith("/*")) return a.slice(0, -2).toUpperCase();
184
+ const n = a.indexOf("/");
185
+ return (n >= 0 ? a.slice(n + 1) : a).toUpperCase();
186
+ });
187
+ return [...new Set(r)].join(", ");
188
+ }
189
+ function L(e) {
190
+ return `${e.name}:${e.size}:${e.lastModified ?? 0}`;
191
+ }
192
+ function M(e, r) {
193
+ const a = r.trim().replace(/[/\\]/g, "");
194
+ if (!a) return e;
195
+ const n = e.lastIndexOf("."), t = n > 0 ? e.slice(n) : "";
196
+ return t ? a.toLowerCase().endsWith(t.toLowerCase()) ? a : a + t : a;
197
+ }
198
+ export {
199
+ d as T,
200
+ y as a,
201
+ x as b,
202
+ T as c,
203
+ c as d,
204
+ w as e,
205
+ g as f,
206
+ L as g,
207
+ M as h,
208
+ B as i,
209
+ k as j,
210
+ S as k,
211
+ U as p,
212
+ C as r,
213
+ m as t
214
+ };
215
+ //# sourceMappingURL=files-DDJWPzZW.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"files-DDJWPzZW.js","sources":["../src/styles/tokens.ts","../src/styles/branding.ts","../src/utils/branding.ts","../src/upload-messages.ts","../src/utils/files.ts"],"sourcesContent":["import { css, unsafeCSS } from \"lit\";\n\n/**\n * Default values for every --sb-* design token, ported from the design\n * mock's tokens()/styles() functions. These are consumed as var(--sb-x,\n * DEFAULT) fallbacks at each point of use (see shared.ts) — never assigned\n * unconditionally on :host — so that a value set by a host application, or\n * by a theme/density attribute forwarded down from a composing parent\n * element, actually inherits through\n * nested shadow roots instead of being reset back to these defaults by every\n * descendant's own :host rule.\n */\nexport const TOKEN_DEFAULTS = {\n font: `\"Geist\", -apple-system, \"Segoe UI\", Helvetica, sans-serif`,\n mono: `\"Geist Mono\", ui-monospace, monospace`,\n accent: \"#111111\",\n onAccent: \"#ffffff\",\n radius: \"4px\",\n /** Multiplies every corner. The `radius` attribute sets it per element. */\n radiusScale: \"1\",\n surface: \"#ffffff\",\n surfaceAlt: \"#fafafa\",\n ink: \"#16181a\",\n mutedInk: \"#61666c\",\n border: \"#e4e6e9\",\n borderStrong: \"#cdd1d6\",\n danger: \"#b4231a\",\n dangerBg: \"#fdf1f0\",\n dangerBorder: \"#f3d6d3\",\n dangerOutline: \"#e8c4c0\",\n dangerPanelBorder: \"#efd9d6\",\n dangerPanelBg: \"#fdf7f6\",\n ok: \"#0f6b4a\",\n okBg: \"#f0f7f3\",\n okBorder: \"#cfe5da\",\n gap: \"16px\",\n pad: \"20px\",\n fieldPad: \"11px 13px\"\n} as const;\n\n/**\n * Base host layout plus the theme=\"dark\"/density=\"compact\" attribute\n * overrides. These overrides are legitimate unconditional assignments —\n * they only fire when *this* element carries the attribute — but every\n * composite element (<singlebase-authui>, <singlebase-authui-account>) must forward\n * theme/density/field-style to the singlebase-* children it renders for the\n * override to reach elements that don't carry the attribute directly.\n */\nexport const tokenDefaults = css`\n :host {\n display: block;\n box-sizing: border-box;\n font-family: var(--sb-font, ${unsafeCSS(TOKEN_DEFAULTS.font)});\n color: var(--sb-ink, ${unsafeCSS(TOKEN_DEFAULTS.ink)});\n }\n\n :host([theme=\"dark\"]) {\n /* The light default accent is near-black, which disappears on a dark\n surface — primary buttons and links both use it. A host that sets its\n own --sb-accent still wins: outer-page declarations beat :host rules. */\n --sb-accent: #f3f4f5;\n --sb-on-accent: #17181b;\n --sb-surface: #17181b;\n --sb-surface-alt: #202226;\n --sb-ink: #f3f4f5;\n --sb-muted-ink: #a2a8ae;\n --sb-border: #2c2f34;\n --sb-border-strong: #3a3e44;\n --sb-danger: #f08379;\n --sb-danger-bg: rgba(240, 131, 121, 0.1);\n --sb-danger-border: rgba(240, 131, 121, 0.3);\n --sb-danger-outline: rgba(240, 131, 121, 0.4);\n --sb-danger-panel-border: rgba(240, 131, 121, 0.3);\n --sb-danger-panel-bg: rgba(240, 131, 121, 0.06);\n --sb-ok: #6fd1a6;\n --sb-ok-bg: rgba(111, 209, 166, 0.1);\n --sb-ok-border: rgba(111, 209, 166, 0.28);\n }\n\n /* Corner presets. They set the scale on this element only, so a page-wide\n :root { --sb-radius-scale } (or --sb-radius) applies to every element\n that doesn't carry the attribute. */\n :host([radius=\"sharp\"]) {\n --sb-radius-scale: 0.35;\n }\n\n :host([radius=\"default\"]) {\n --sb-radius-scale: 1;\n }\n\n :host([radius=\"round\"]) {\n --sb-radius-scale: 1.8;\n }\n\n :host([density=\"compact\"]) {\n --sb-gap: 12px;\n --sb-pad: 16px;\n --sb-field-pad: 9px 11px;\n }\n`;\n","import { css } from \"lit\";\n\n/**\n * The \"… by Singlebase\" credit, identical in every element: same font, size,\n * spacing and hover. Each element only decides where it sits.\n */\nexport const brandingStyles = css`\n .branding {\n text-align: center;\n font-family: var(--sb-mono, \"Geist Mono\", ui-monospace, monospace);\n font-size: 10.5px;\n line-height: 1.4;\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","import { html, nothing } from \"lit\";\n\nexport const DEFAULT_BRANDING_URL = \"https://singlebase.cloud\";\n\n/**\n * The credit link. `text` falls back to the element's own label, and `url`\n * to singlebase.cloud; only http(s) URLs are used. It's a plain link: it\n * makes no request until someone clicks it.\n */\nexport function renderBranding(show: boolean, text: string, fallbackText: string, url: string) {\n if (!show) return nothing;\n const href = /^https?:\\/\\//i.test(url?.trim() ?? \"\") ? url.trim() : DEFAULT_BRANDING_URL;\n return html`<div class=\"branding\" part=\"branding\">\n <a href=${href} target=\"_blank\" rel=\"noopener noreferrer\">${text?.trim() || fallbackText}</a>\n </div>`;\n}\n","/**\n * Default copy for <singlebase-uploader>. Same shape and contract as the\n * auth bag in messages.ts: a flat set of strings, overridable in whole or in\n * part through the element's `.messages` property.\n *\n * `{n}`, `{max}`, `{name}` and `{size}` are filled in by `fill()`.\n */\nexport interface SinglebaseUploadMessages {\n heading: string;\n description: string;\n\n // dropzone\n dropTitle: string;\n dropSub: string;\n hintUpTo: string;\n\n // controls\n chooseFiles: string;\n chooseFile: string;\n addMore: string;\n remove: string;\n rename: string;\n retry: string;\n uploadCtaOne: string;\n uploadCtaMany: string;\n\n // compact view\n attachments: string;\n dropOrChoose: string;\n\n // status\n checking: string;\n pagesLabel: string;\n countOne: string;\n countMany: string;\n uploading: string;\n uploaded: string;\n failedLabel: string;\n\n // problems\n errTooMany: string;\n errTooLarge: string;\n errTooSmall: string;\n errDuplicate: string;\n errType: string;\n errNoClient: string;\n errUpload: string;\n errProtected: string;\n errTooManyPages: string;\n\n brandingLabel: string;\n}\n\nexport const defaultUploadMessages: SinglebaseUploadMessages = {\n heading: \"Upload files\",\n description: \"Add one or more files. You can review the list before uploading.\",\n\n dropTitle: \"Drag and drop files here\",\n dropSub: \"or browse from your device\",\n hintUpTo: \"up to {size} each\",\n\n chooseFiles: \"Choose files\",\n chooseFile: \"Choose file\",\n addMore: \"+ Add more files\",\n remove: \"Remove\",\n rename: \"Rename\",\n retry: \"Retry\",\n uploadCtaOne: \"Upload {n} file\",\n uploadCtaMany: \"Upload {n} files\",\n\n attachments: \"Attachments\",\n dropOrChoose: \"Drop files or choose\",\n\n checking: \"Checking…\",\n pagesLabel: \"{n} pages\",\n countOne: \"{n} file of {max}\",\n countMany: \"{n} files of {max}\",\n uploading: \"Uploading…\",\n uploaded: \"Uploaded\",\n failedLabel: \"Failed\",\n\n errTooMany: \"You can upload up to {max} files.\",\n errTooLarge: \"{name} is larger than {size}.\",\n errTooSmall: \"{name} is smaller than {size}.\",\n errDuplicate: \"{name} is already in the list.\",\n errType: \"{name} isn't an accepted file type.\",\n errNoClient: \"No Singlebase client found on this page.\",\n errUpload: \"Upload failed.\",\n errProtected: \"{name} is password protected.\",\n errTooManyPages: \"{name} has {pages} pages; the limit is {max}.\",\n\n brandingLabel: \"Files by Singlebase\"\n};\n\nexport function resolveUploadMessages(\n overrides?: Partial<SinglebaseUploadMessages>\n): SinglebaseUploadMessages {\n return overrides ? { ...defaultUploadMessages, ...overrides } : defaultUploadMessages;\n}\n\n/** Fills `{token}` placeholders. Values are plain text and rendered as text. */\nexport function fill(template: string, values: Record<string, string | number>): string {\n return template.replace(/\\{(\\w+)\\}/g, (match, key) =>\n key in values ? String(values[key]) : match\n );\n}\n","/**\n * Small pure helpers for <singlebase-uploader>: parsing and printing\n * sizes, matching an `accept` list, and the identity a duplicate is judged by.\n * Kept out of the element so they can be tested without a DOM.\n */\n\nconst UNITS: Record<string, number> = {\n b: 1,\n kb: 1024,\n mb: 1024 * 1024,\n gb: 1024 * 1024 * 1024\n};\n\n/** \"25MB\" / \"500 kb\" / \"1048576\" → bytes. 0 means \"no limit\". */\nexport function parseSize(value: string | number | null | undefined): number {\n if (typeof value === \"number\") return value > 0 ? value : 0;\n if (!value) return 0;\n const match = String(value)\n .trim()\n .toLowerCase()\n .match(/^([\\d.]+)\\s*(b|kb|mb|gb)?$/);\n if (!match) return 0;\n const amount = Number.parseFloat(match[1]);\n if (!Number.isFinite(amount) || amount <= 0) return 0;\n return Math.round(amount * (UNITS[match[2] ?? \"b\"] ?? 1));\n}\n\nexport function formatSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024)} KB`;\n if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;\n}\n\n/** The extension in lowercase, without the dot. \"\" when there is none. */\nexport function fileExtension(filename: string): string {\n const dot = filename.lastIndexOf(\".\");\n if (dot <= 0 || dot === filename.length - 1) return \"\";\n return filename.slice(dot + 1).toLowerCase();\n}\n\n/** The extension, uppercased and clipped, for the little type chip. */\nexport function extensionOf(filename: string): string {\n return fileExtension(filename).toUpperCase().slice(0, 4);\n}\n\n/**\n * Matches one file against an `accept` list, using the same vocabulary as the\n * attribute on `<input type=\"file\">`: extensions (\".pdf\"), exact MIME types\n * (\"application/pdf\") and wildcards (\"image/*\"). An empty list accepts\n * everything.\n *\n * This is a convenience, not a security control — the browser's own file\n * dialog filter and this check are both trivially bypassed by a drop, so the\n * server remains the authority on what it will store.\n */\nexport function acceptsFile(accept: string, name: string, type: string): boolean {\n const rules = accept\n .split(\",\")\n .map((rule) => rule.trim().toLowerCase())\n .filter(Boolean);\n if (!rules.length) return true;\n\n const lowerName = name.toLowerCase();\n const lowerType = (type || \"\").toLowerCase();\n\n return rules.some((rule) => {\n if (rule.startsWith(\".\")) return lowerName.endsWith(rule);\n if (rule.endsWith(\"/*\")) return lowerType.startsWith(rule.slice(0, -1));\n return lowerType === rule;\n });\n}\n\n/** Human list of accepted kinds for the hint line: \".pdf,image/png\" → \"PDF, PNG\". */\nexport function acceptSummary(accept: string): string {\n const parts = accept\n .split(\",\")\n .map((rule) => rule.trim())\n .filter(Boolean)\n .map((rule) => {\n if (rule.startsWith(\".\")) return rule.slice(1).toUpperCase();\n if (rule.endsWith(\"/*\")) return rule.slice(0, -2).toUpperCase();\n const slash = rule.indexOf(\"/\");\n return (slash >= 0 ? rule.slice(slash + 1) : rule).toUpperCase();\n });\n return [...new Set(parts)].join(\", \");\n}\n\n/**\n * Two picks are the same file when name, size and mtime all match. Content\n * hashing would be exact but means reading every byte before the user has\n * even pressed upload; this is what a file manager uses, and it is enough to\n * stop the common case of dropping the same batch twice.\n */\nexport function fileKey(file: { name: string; size: number; lastModified?: number }): string {\n return `${file.name}:${file.size}:${file.lastModified ?? 0}`;\n}\n\n/** Replaces the base name, keeping the original extension. */\nexport function renameKeepingExtension(original: string, typed: string): string {\n const clean = typed.trim().replace(/[/\\\\]/g, \"\");\n if (!clean) return original;\n const dot = original.lastIndexOf(\".\");\n const extension = dot > 0 ? original.slice(dot) : \"\";\n if (!extension) return clean;\n return clean.toLowerCase().endsWith(extension.toLowerCase()) ? clean : clean + extension;\n}\n"],"names":["TOKEN_DEFAULTS","tokenDefaults","css","unsafeCSS","brandingStyles","DEFAULT_BRANDING_URL","renderBranding","show","text","fallbackText","url","nothing","href","html","defaultUploadMessages","resolveUploadMessages","overrides","fill","template","values","match","key","UNITS","parseSize","value","amount","formatSize","bytes","fileExtension","filename","dot","extensionOf","acceptsFile","accept","name","type","rules","rule","lowerName","lowerType","acceptSummary","parts","slash","fileKey","file","renameKeepingExtension","original","typed","clean","extension"],"mappings":"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"}
@@ -0,0 +1,75 @@
1
+ "use strict";const s=require("lit"),i={font:'"Geist", -apple-system, "Segoe UI", Helvetica, sans-serif',mono:'"Geist Mono", ui-monospace, monospace',accent:"#111111",onAccent:"#ffffff",radius:"4px",radiusScale:"1",surface:"#ffffff",surfaceAlt:"#fafafa",ink:"#16181a",mutedInk:"#61666c",border:"#e4e6e9",borderStrong:"#cdd1d6",danger:"#b4231a",dangerBg:"#fdf1f0",dangerBorder:"#f3d6d3",dangerOutline:"#e8c4c0",dangerPanelBorder:"#efd9d6",dangerPanelBg:"#fdf7f6",ok:"#0f6b4a",okBg:"#f0f7f3",okBorder:"#cfe5da",gap:"16px",pad:"20px",fieldPad:"11px 13px"},l=s.css`
2
+ :host {
3
+ display: block;
4
+ box-sizing: border-box;
5
+ font-family: var(--sb-font, ${s.unsafeCSS(i.font)});
6
+ color: var(--sb-ink, ${s.unsafeCSS(i.ink)});
7
+ }
8
+
9
+ :host([theme="dark"]) {
10
+ /* The light default accent is near-black, which disappears on a dark
11
+ surface — primary buttons and links both use it. A host that sets its
12
+ own --sb-accent still wins: outer-page declarations beat :host rules. */
13
+ --sb-accent: #f3f4f5;
14
+ --sb-on-accent: #17181b;
15
+ --sb-surface: #17181b;
16
+ --sb-surface-alt: #202226;
17
+ --sb-ink: #f3f4f5;
18
+ --sb-muted-ink: #a2a8ae;
19
+ --sb-border: #2c2f34;
20
+ --sb-border-strong: #3a3e44;
21
+ --sb-danger: #f08379;
22
+ --sb-danger-bg: rgba(240, 131, 121, 0.1);
23
+ --sb-danger-border: rgba(240, 131, 121, 0.3);
24
+ --sb-danger-outline: rgba(240, 131, 121, 0.4);
25
+ --sb-danger-panel-border: rgba(240, 131, 121, 0.3);
26
+ --sb-danger-panel-bg: rgba(240, 131, 121, 0.06);
27
+ --sb-ok: #6fd1a6;
28
+ --sb-ok-bg: rgba(111, 209, 166, 0.1);
29
+ --sb-ok-border: rgba(111, 209, 166, 0.28);
30
+ }
31
+
32
+ /* Corner presets. They set the scale on this element only, so a page-wide
33
+ :root { --sb-radius-scale } (or --sb-radius) applies to every element
34
+ that doesn't carry the attribute. */
35
+ :host([radius="sharp"]) {
36
+ --sb-radius-scale: 0.35;
37
+ }
38
+
39
+ :host([radius="default"]) {
40
+ --sb-radius-scale: 1;
41
+ }
42
+
43
+ :host([radius="round"]) {
44
+ --sb-radius-scale: 1.8;
45
+ }
46
+
47
+ :host([density="compact"]) {
48
+ --sb-gap: 12px;
49
+ --sb-pad: 16px;
50
+ --sb-field-pad: 9px 11px;
51
+ }
52
+ `,p=s.css`
53
+ .branding {
54
+ text-align: center;
55
+ font-family: var(--sb-mono, "Geist Mono", ui-monospace, monospace);
56
+ font-size: 10.5px;
57
+ line-height: 1.4;
58
+ letter-spacing: 0.06em;
59
+ color: var(--sb-muted-ink, #61666c);
60
+ }
61
+
62
+ .branding a {
63
+ color: inherit;
64
+ text-decoration: none;
65
+ }
66
+
67
+ .branding a:hover {
68
+ color: var(--sb-ink, #16181a);
69
+ text-decoration: underline;
70
+ text-underline-offset: 3px;
71
+ }
72
+ `,u="https://singlebase.cloud";function b(e,r,n,t){if(!e)return s.nothing;const a=/^https?:\/\//i.test((t==null?void 0:t.trim())??"")?t.trim():u;return s.html`<div class="branding" part="branding">
73
+ <a href=${a} target="_blank" rel="noopener noreferrer">${(r==null?void 0:r.trim())||n}</a>
74
+ </div>`}const d={heading:"Upload files",description:"Add one or more files. You can review the list before uploading.",dropTitle:"Drag and drop files here",dropSub:"or browse from your device",hintUpTo:"up to {size} each",chooseFiles:"Choose files",chooseFile:"Choose file",addMore:"+ Add more files",remove:"Remove",rename:"Rename",retry:"Retry",uploadCtaOne:"Upload {n} file",uploadCtaMany:"Upload {n} files",attachments:"Attachments",dropOrChoose:"Drop files or choose",checking:"Checking…",pagesLabel:"{n} pages",countOne:"{n} file of {max}",countMany:"{n} files of {max}",uploading:"Uploading…",uploaded:"Uploaded",failedLabel:"Failed",errTooMany:"You can upload up to {max} files.",errTooLarge:"{name} is larger than {size}.",errTooSmall:"{name} is smaller than {size}.",errDuplicate:"{name} is already in the list.",errType:"{name} isn't an accepted file type.",errNoClient:"No Singlebase client found on this page.",errUpload:"Upload failed.",errProtected:"{name} is password protected.",errTooManyPages:"{name} has {pages} pages; the limit is {max}.",brandingLabel:"Files by Singlebase"};function g(e){return e?{...d,...e}:d}function m(e,r){return e.replace(/\{(\w+)\}/g,(n,t)=>t in r?String(r[t]):n)}const h={b:1,kb:1024,mb:1024*1024,gb:1024*1024*1024};function x(e){if(typeof e=="number")return e>0?e:0;if(!e)return 0;const r=String(e).trim().toLowerCase().match(/^([\d.]+)\s*(b|kb|mb|gb)?$/);if(!r)return 0;const n=Number.parseFloat(r[1]);return!Number.isFinite(n)||n<=0?0:Math.round(n*(h[r[2]??"b"]??1))}function k(e){return e<1024?`${e} B`:e<1024*1024?`${Math.round(e/1024)} KB`:e<1024*1024*1024?`${(e/(1024*1024)).toFixed(1)} MB`:`${(e/(1024*1024*1024)).toFixed(1)} GB`}function f(e){const r=e.lastIndexOf(".");return r<=0||r===e.length-1?"":e.slice(r+1).toLowerCase()}function S(e){return f(e).toUpperCase().slice(0,4)}function y(e,r,n){const t=e.split(",").map(o=>o.trim().toLowerCase()).filter(Boolean);if(!t.length)return!0;const a=r.toLowerCase(),c=(n||"").toLowerCase();return t.some(o=>o.startsWith(".")?a.endsWith(o):o.endsWith("/*")?c.startsWith(o.slice(0,-1)):c===o)}function U(e){const r=e.split(",").map(n=>n.trim()).filter(Boolean).map(n=>{if(n.startsWith("."))return n.slice(1).toUpperCase();if(n.endsWith("/*"))return n.slice(0,-2).toUpperCase();const t=n.indexOf("/");return(t>=0?n.slice(t+1):n).toUpperCase()});return[...new Set(r)].join(", ")}function C(e){return`${e.name}:${e.size}:${e.lastModified??0}`}function w(e,r){const n=r.trim().replace(/[/\\]/g,"");if(!n)return e;const t=e.lastIndexOf("."),a=t>0?e.slice(t):"";return a?n.toLowerCase().endsWith(a.toLowerCase())?n:n+a:n}exports.TOKEN_DEFAULTS=i;exports.acceptSummary=U;exports.acceptsFile=y;exports.brandingStyles=p;exports.defaultUploadMessages=d;exports.extensionOf=S;exports.fileExtension=f;exports.fileKey=C;exports.fill=m;exports.formatSize=k;exports.parseSize=x;exports.renameKeepingExtension=w;exports.renderBranding=b;exports.resolveUploadMessages=g;exports.tokenDefaults=l;
75
+ //# sourceMappingURL=files-DyxcjZsx.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"files-DyxcjZsx.cjs","sources":["../src/styles/tokens.ts","../src/styles/branding.ts","../src/utils/branding.ts","../src/upload-messages.ts","../src/utils/files.ts"],"sourcesContent":["import { css, unsafeCSS } from \"lit\";\n\n/**\n * Default values for every --sb-* design token, ported from the design\n * mock's tokens()/styles() functions. These are consumed as var(--sb-x,\n * DEFAULT) fallbacks at each point of use (see shared.ts) — never assigned\n * unconditionally on :host — so that a value set by a host application, or\n * by a theme/density attribute forwarded down from a composing parent\n * element, actually inherits through\n * nested shadow roots instead of being reset back to these defaults by every\n * descendant's own :host rule.\n */\nexport const TOKEN_DEFAULTS = {\n font: `\"Geist\", -apple-system, \"Segoe UI\", Helvetica, sans-serif`,\n mono: `\"Geist Mono\", ui-monospace, monospace`,\n accent: \"#111111\",\n onAccent: \"#ffffff\",\n radius: \"4px\",\n /** Multiplies every corner. The `radius` attribute sets it per element. */\n radiusScale: \"1\",\n surface: \"#ffffff\",\n surfaceAlt: \"#fafafa\",\n ink: \"#16181a\",\n mutedInk: \"#61666c\",\n border: \"#e4e6e9\",\n borderStrong: \"#cdd1d6\",\n danger: \"#b4231a\",\n dangerBg: \"#fdf1f0\",\n dangerBorder: \"#f3d6d3\",\n dangerOutline: \"#e8c4c0\",\n dangerPanelBorder: \"#efd9d6\",\n dangerPanelBg: \"#fdf7f6\",\n ok: \"#0f6b4a\",\n okBg: \"#f0f7f3\",\n okBorder: \"#cfe5da\",\n gap: \"16px\",\n pad: \"20px\",\n fieldPad: \"11px 13px\"\n} as const;\n\n/**\n * Base host layout plus the theme=\"dark\"/density=\"compact\" attribute\n * overrides. These overrides are legitimate unconditional assignments —\n * they only fire when *this* element carries the attribute — but every\n * composite element (<singlebase-authui>, <singlebase-authui-account>) must forward\n * theme/density/field-style to the singlebase-* children it renders for the\n * override to reach elements that don't carry the attribute directly.\n */\nexport const tokenDefaults = css`\n :host {\n display: block;\n box-sizing: border-box;\n font-family: var(--sb-font, ${unsafeCSS(TOKEN_DEFAULTS.font)});\n color: var(--sb-ink, ${unsafeCSS(TOKEN_DEFAULTS.ink)});\n }\n\n :host([theme=\"dark\"]) {\n /* The light default accent is near-black, which disappears on a dark\n surface — primary buttons and links both use it. A host that sets its\n own --sb-accent still wins: outer-page declarations beat :host rules. */\n --sb-accent: #f3f4f5;\n --sb-on-accent: #17181b;\n --sb-surface: #17181b;\n --sb-surface-alt: #202226;\n --sb-ink: #f3f4f5;\n --sb-muted-ink: #a2a8ae;\n --sb-border: #2c2f34;\n --sb-border-strong: #3a3e44;\n --sb-danger: #f08379;\n --sb-danger-bg: rgba(240, 131, 121, 0.1);\n --sb-danger-border: rgba(240, 131, 121, 0.3);\n --sb-danger-outline: rgba(240, 131, 121, 0.4);\n --sb-danger-panel-border: rgba(240, 131, 121, 0.3);\n --sb-danger-panel-bg: rgba(240, 131, 121, 0.06);\n --sb-ok: #6fd1a6;\n --sb-ok-bg: rgba(111, 209, 166, 0.1);\n --sb-ok-border: rgba(111, 209, 166, 0.28);\n }\n\n /* Corner presets. They set the scale on this element only, so a page-wide\n :root { --sb-radius-scale } (or --sb-radius) applies to every element\n that doesn't carry the attribute. */\n :host([radius=\"sharp\"]) {\n --sb-radius-scale: 0.35;\n }\n\n :host([radius=\"default\"]) {\n --sb-radius-scale: 1;\n }\n\n :host([radius=\"round\"]) {\n --sb-radius-scale: 1.8;\n }\n\n :host([density=\"compact\"]) {\n --sb-gap: 12px;\n --sb-pad: 16px;\n --sb-field-pad: 9px 11px;\n }\n`;\n","import { css } from \"lit\";\n\n/**\n * The \"… by Singlebase\" credit, identical in every element: same font, size,\n * spacing and hover. Each element only decides where it sits.\n */\nexport const brandingStyles = css`\n .branding {\n text-align: center;\n font-family: var(--sb-mono, \"Geist Mono\", ui-monospace, monospace);\n font-size: 10.5px;\n line-height: 1.4;\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","import { html, nothing } from \"lit\";\n\nexport const DEFAULT_BRANDING_URL = \"https://singlebase.cloud\";\n\n/**\n * The credit link. `text` falls back to the element's own label, and `url`\n * to singlebase.cloud; only http(s) URLs are used. It's a plain link: it\n * makes no request until someone clicks it.\n */\nexport function renderBranding(show: boolean, text: string, fallbackText: string, url: string) {\n if (!show) return nothing;\n const href = /^https?:\\/\\//i.test(url?.trim() ?? \"\") ? url.trim() : DEFAULT_BRANDING_URL;\n return html`<div class=\"branding\" part=\"branding\">\n <a href=${href} target=\"_blank\" rel=\"noopener noreferrer\">${text?.trim() || fallbackText}</a>\n </div>`;\n}\n","/**\n * Default copy for <singlebase-uploader>. Same shape and contract as the\n * auth bag in messages.ts: a flat set of strings, overridable in whole or in\n * part through the element's `.messages` property.\n *\n * `{n}`, `{max}`, `{name}` and `{size}` are filled in by `fill()`.\n */\nexport interface SinglebaseUploadMessages {\n heading: string;\n description: string;\n\n // dropzone\n dropTitle: string;\n dropSub: string;\n hintUpTo: string;\n\n // controls\n chooseFiles: string;\n chooseFile: string;\n addMore: string;\n remove: string;\n rename: string;\n retry: string;\n uploadCtaOne: string;\n uploadCtaMany: string;\n\n // compact view\n attachments: string;\n dropOrChoose: string;\n\n // status\n checking: string;\n pagesLabel: string;\n countOne: string;\n countMany: string;\n uploading: string;\n uploaded: string;\n failedLabel: string;\n\n // problems\n errTooMany: string;\n errTooLarge: string;\n errTooSmall: string;\n errDuplicate: string;\n errType: string;\n errNoClient: string;\n errUpload: string;\n errProtected: string;\n errTooManyPages: string;\n\n brandingLabel: string;\n}\n\nexport const defaultUploadMessages: SinglebaseUploadMessages = {\n heading: \"Upload files\",\n description: \"Add one or more files. You can review the list before uploading.\",\n\n dropTitle: \"Drag and drop files here\",\n dropSub: \"or browse from your device\",\n hintUpTo: \"up to {size} each\",\n\n chooseFiles: \"Choose files\",\n chooseFile: \"Choose file\",\n addMore: \"+ Add more files\",\n remove: \"Remove\",\n rename: \"Rename\",\n retry: \"Retry\",\n uploadCtaOne: \"Upload {n} file\",\n uploadCtaMany: \"Upload {n} files\",\n\n attachments: \"Attachments\",\n dropOrChoose: \"Drop files or choose\",\n\n checking: \"Checking…\",\n pagesLabel: \"{n} pages\",\n countOne: \"{n} file of {max}\",\n countMany: \"{n} files of {max}\",\n uploading: \"Uploading…\",\n uploaded: \"Uploaded\",\n failedLabel: \"Failed\",\n\n errTooMany: \"You can upload up to {max} files.\",\n errTooLarge: \"{name} is larger than {size}.\",\n errTooSmall: \"{name} is smaller than {size}.\",\n errDuplicate: \"{name} is already in the list.\",\n errType: \"{name} isn't an accepted file type.\",\n errNoClient: \"No Singlebase client found on this page.\",\n errUpload: \"Upload failed.\",\n errProtected: \"{name} is password protected.\",\n errTooManyPages: \"{name} has {pages} pages; the limit is {max}.\",\n\n brandingLabel: \"Files by Singlebase\"\n};\n\nexport function resolveUploadMessages(\n overrides?: Partial<SinglebaseUploadMessages>\n): SinglebaseUploadMessages {\n return overrides ? { ...defaultUploadMessages, ...overrides } : defaultUploadMessages;\n}\n\n/** Fills `{token}` placeholders. Values are plain text and rendered as text. */\nexport function fill(template: string, values: Record<string, string | number>): string {\n return template.replace(/\\{(\\w+)\\}/g, (match, key) =>\n key in values ? String(values[key]) : match\n );\n}\n","/**\n * Small pure helpers for <singlebase-uploader>: parsing and printing\n * sizes, matching an `accept` list, and the identity a duplicate is judged by.\n * Kept out of the element so they can be tested without a DOM.\n */\n\nconst UNITS: Record<string, number> = {\n b: 1,\n kb: 1024,\n mb: 1024 * 1024,\n gb: 1024 * 1024 * 1024\n};\n\n/** \"25MB\" / \"500 kb\" / \"1048576\" → bytes. 0 means \"no limit\". */\nexport function parseSize(value: string | number | null | undefined): number {\n if (typeof value === \"number\") return value > 0 ? value : 0;\n if (!value) return 0;\n const match = String(value)\n .trim()\n .toLowerCase()\n .match(/^([\\d.]+)\\s*(b|kb|mb|gb)?$/);\n if (!match) return 0;\n const amount = Number.parseFloat(match[1]);\n if (!Number.isFinite(amount) || amount <= 0) return 0;\n return Math.round(amount * (UNITS[match[2] ?? \"b\"] ?? 1));\n}\n\nexport function formatSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024)} KB`;\n if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;\n}\n\n/** The extension in lowercase, without the dot. \"\" when there is none. */\nexport function fileExtension(filename: string): string {\n const dot = filename.lastIndexOf(\".\");\n if (dot <= 0 || dot === filename.length - 1) return \"\";\n return filename.slice(dot + 1).toLowerCase();\n}\n\n/** The extension, uppercased and clipped, for the little type chip. */\nexport function extensionOf(filename: string): string {\n return fileExtension(filename).toUpperCase().slice(0, 4);\n}\n\n/**\n * Matches one file against an `accept` list, using the same vocabulary as the\n * attribute on `<input type=\"file\">`: extensions (\".pdf\"), exact MIME types\n * (\"application/pdf\") and wildcards (\"image/*\"). An empty list accepts\n * everything.\n *\n * This is a convenience, not a security control — the browser's own file\n * dialog filter and this check are both trivially bypassed by a drop, so the\n * server remains the authority on what it will store.\n */\nexport function acceptsFile(accept: string, name: string, type: string): boolean {\n const rules = accept\n .split(\",\")\n .map((rule) => rule.trim().toLowerCase())\n .filter(Boolean);\n if (!rules.length) return true;\n\n const lowerName = name.toLowerCase();\n const lowerType = (type || \"\").toLowerCase();\n\n return rules.some((rule) => {\n if (rule.startsWith(\".\")) return lowerName.endsWith(rule);\n if (rule.endsWith(\"/*\")) return lowerType.startsWith(rule.slice(0, -1));\n return lowerType === rule;\n });\n}\n\n/** Human list of accepted kinds for the hint line: \".pdf,image/png\" → \"PDF, PNG\". */\nexport function acceptSummary(accept: string): string {\n const parts = accept\n .split(\",\")\n .map((rule) => rule.trim())\n .filter(Boolean)\n .map((rule) => {\n if (rule.startsWith(\".\")) return rule.slice(1).toUpperCase();\n if (rule.endsWith(\"/*\")) return rule.slice(0, -2).toUpperCase();\n const slash = rule.indexOf(\"/\");\n return (slash >= 0 ? rule.slice(slash + 1) : rule).toUpperCase();\n });\n return [...new Set(parts)].join(\", \");\n}\n\n/**\n * Two picks are the same file when name, size and mtime all match. Content\n * hashing would be exact but means reading every byte before the user has\n * even pressed upload; this is what a file manager uses, and it is enough to\n * stop the common case of dropping the same batch twice.\n */\nexport function fileKey(file: { name: string; size: number; lastModified?: number }): string {\n return `${file.name}:${file.size}:${file.lastModified ?? 0}`;\n}\n\n/** Replaces the base name, keeping the original extension. */\nexport function renameKeepingExtension(original: string, typed: string): string {\n const clean = typed.trim().replace(/[/\\\\]/g, \"\");\n if (!clean) return original;\n const dot = original.lastIndexOf(\".\");\n const extension = dot > 0 ? original.slice(dot) : \"\";\n if (!extension) return clean;\n return clean.toLowerCase().endsWith(extension.toLowerCase()) ? clean : clean + extension;\n}\n"],"names":["TOKEN_DEFAULTS","tokenDefaults","css","unsafeCSS","brandingStyles","DEFAULT_BRANDING_URL","renderBranding","show","text","fallbackText","url","nothing","href","html","defaultUploadMessages","resolveUploadMessages","overrides","fill","template","values","match","key","UNITS","parseSize","value","amount","formatSize","bytes","fileExtension","filename","dot","extensionOf","acceptsFile","accept","name","type","rules","rule","lowerName","lowerType","acceptSummary","parts","slash","fileKey","file","renameKeepingExtension","original","typed","clean","extension"],"mappings":"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"}
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./display-CLDNNZQy.cjs"),t=require("./uploader-eFYKpk8b.cjs"),r=require("@singlebase/core");exports.AuthController=e.AuthController;exports.SettingsController=e.SettingsController;Object.defineProperty(exports,"SinglebaseAccountScreen",{enumerable:!0,get:()=>e.SinglebaseAccountScreen});Object.defineProperty(exports,"SinglebaseAuthButtons",{enumerable:!0,get:()=>e.SinglebaseAuthButtons});Object.defineProperty(exports,"SinglebaseAuthDisplay",{enumerable:!0,get:()=>e.SinglebaseAuthDisplay});Object.defineProperty(exports,"SinglebaseAuthGuard",{enumerable:!0,get:()=>e.SinglebaseAuthGuard});Object.defineProperty(exports,"SinglebaseAuthScreen",{enumerable:!0,get:()=>e.SinglebaseAuthScreen});exports.defaultMessages=e.defaultMessages;exports.fullNameOf=e.fullNameOf;exports.initialsOf=e.initialsOf;exports.isGuestScreen=e.isGuestScreen;exports.isProtectedScreen=e.isProtectedScreen;exports.isScreen=e.isScreen;exports.resolveMessages=e.resolveMessages;Object.defineProperty(exports,"SinglebaseUploader",{enumerable:!0,get:()=>t.SinglebaseUploader});exports.TOKEN_DEFAULTS=t.TOKEN_DEFAULTS;exports.defaultUploadMessages=t.defaultUploadMessages;exports.inspectFile=t.inspectFile;exports.isInspectable=t.isInspectable;exports.resolveRedirectTarget=t.resolveRedirectTarget;exports.resolveUploadMessages=t.resolveUploadMessages;Object.defineProperty(exports,"OPERATORS",{enumerable:!0,get:()=>r.OPERATORS});Object.defineProperty(exports,"matchesPredicate",{enumerable:!0,get:()=>r.matchesPredicate});Object.defineProperty(exports,"validatePredicate",{enumerable:!0,get:()=>r.validatePredicate});
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./authui-display-aWNht0cW.cjs"),r=require("./uploader-660JIgIN.cjs"),s=require("@singlebase/core"),a=require("./files-DyxcjZsx.cjs"),t=require("./chat-C-gsskho.cjs");exports.AuthController=e.AuthController;exports.SettingsController=e.SettingsController;Object.defineProperty(exports,"SinglebaseAccountScreen",{enumerable:!0,get:()=>e.SinglebaseAccountScreen});Object.defineProperty(exports,"SinglebaseAuthButtons",{enumerable:!0,get:()=>e.SinglebaseAuthButtons});Object.defineProperty(exports,"SinglebaseAuthDisplay",{enumerable:!0,get:()=>e.SinglebaseAuthDisplay});Object.defineProperty(exports,"SinglebaseAuthGuard",{enumerable:!0,get:()=>e.SinglebaseAuthGuard});Object.defineProperty(exports,"SinglebaseAuthScreen",{enumerable:!0,get:()=>e.SinglebaseAuthScreen});exports.defaultMessages=e.defaultMessages;exports.fullNameOf=e.fullNameOf;exports.initialsOf=e.initialsOf;exports.isGuestScreen=e.isGuestScreen;exports.isProtectedScreen=e.isProtectedScreen;exports.isScreen=e.isScreen;exports.resolveMessages=e.resolveMessages;Object.defineProperty(exports,"SinglebaseUploader",{enumerable:!0,get:()=>r.SinglebaseUploader});exports.inspectFile=r.inspectFile;exports.isInspectable=r.isInspectable;exports.resolveRedirectTarget=r.resolveRedirectTarget;Object.defineProperty(exports,"OPERATORS",{enumerable:!0,get:()=>s.OPERATORS});Object.defineProperty(exports,"matchesPredicate",{enumerable:!0,get:()=>s.matchesPredicate});Object.defineProperty(exports,"validatePredicate",{enumerable:!0,get:()=>s.validatePredicate});exports.TOKEN_DEFAULTS=a.TOKEN_DEFAULTS;exports.defaultUploadMessages=a.defaultUploadMessages;exports.resolveUploadMessages=a.resolveUploadMessages;Object.defineProperty(exports,"SinglebaseChat",{enumerable:!0,get:()=>t.SinglebaseChat});exports.adaptBlocks=t.adaptBlocks;exports.citedNumbers=t.citedNumbers;exports.defaultChatMessages=t.defaultChatMessages;exports.describeSource=t.describeSource;exports.parseInline=t.parseInline;exports.parseMarkdown=t.parseMarkdown;exports.resolveChatMessages=t.resolveChatMessages;exports.settleStreaming=t.settleStreaming;exports.splitFollowups=t.splitFollowups;exports.svgDataUrl=t.svgDataUrl;
2
2
  //# sourceMappingURL=index.cjs.map
package/dist/index.d.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  /**
2
- * `@singlebase/elements` — every element. Import `./authui` or `./uploader`
3
- * instead to take only one family.
2
+ * `@singlebase/elements` — every element. Import `./authui`, `./uploader` or
3
+ * `./chat` instead to take only one family.
4
4
  */
5
5
  export * from "./authui.js";
6
6
  export * from "./uploader.js";
7
+ export * from "./chat.js";
7
8
  export { TOKEN_DEFAULTS } from "./styles/tokens.js";
package/dist/index.js CHANGED
@@ -1,30 +1,43 @@
1
- import { A as a, S as t, a as r, b as l, c as i, d as n, e as o, f as S, g as c, i as d, h as g, j as u, k as b, r as f } from "./display-8HEcKYR4.js";
2
- import { S as A, T as h, d as m, i as O, a as T, r as v, b as M } from "./uploader-D-Da1trc.js";
3
- import { OPERATORS as U, matchesPredicate as x, validatePredicate as E } from "@singlebase/core";
1
+ import { A as a, S as r, a as t, b as l, c as i, d as o, e as n, f as c, g as S, i as d, h as g, j as p, k as u, r as f } from "./authui-display-CKfGK5va.js";
2
+ import { S as h, i as m, a as A, r as M } from "./uploader-vfczkX51.js";
3
+ import { OPERATORS as x, matchesPredicate as C, validatePredicate as O } from "@singlebase/core";
4
+ import { T as U, d as P, r as k } from "./files-DDJWPzZW.js";
5
+ import { S as E, a as F, c as N, d as R, b as w, p as B, e as G, r as I, s as j, f as y, g as K } from "./chat-CEh6RygY.js";
4
6
  export {
5
7
  a as AuthController,
6
- U as OPERATORS,
7
- t as SettingsController,
8
- r as SinglebaseAccountScreen,
8
+ x as OPERATORS,
9
+ r as SettingsController,
10
+ t as SinglebaseAccountScreen,
9
11
  l as SinglebaseAuthButtons,
10
12
  i as SinglebaseAuthDisplay,
11
- n as SinglebaseAuthGuard,
12
- o as SinglebaseAuthScreen,
13
- A as SinglebaseUploader,
14
- h as TOKEN_DEFAULTS,
15
- S as defaultMessages,
16
- m as defaultUploadMessages,
17
- c as fullNameOf,
13
+ o as SinglebaseAuthGuard,
14
+ n as SinglebaseAuthScreen,
15
+ E as SinglebaseChat,
16
+ h as SinglebaseUploader,
17
+ U as TOKEN_DEFAULTS,
18
+ F as adaptBlocks,
19
+ N as citedNumbers,
20
+ R as defaultChatMessages,
21
+ c as defaultMessages,
22
+ P as defaultUploadMessages,
23
+ w as describeSource,
24
+ S as fullNameOf,
18
25
  d as initialsOf,
19
- O as inspectFile,
26
+ m as inspectFile,
20
27
  g as isGuestScreen,
21
- T as isInspectable,
22
- u as isProtectedScreen,
23
- b as isScreen,
24
- x as matchesPredicate,
28
+ A as isInspectable,
29
+ p as isProtectedScreen,
30
+ u as isScreen,
31
+ C as matchesPredicate,
32
+ B as parseInline,
33
+ G as parseMarkdown,
34
+ I as resolveChatMessages,
25
35
  f as resolveMessages,
26
- v as resolveRedirectTarget,
27
- M as resolveUploadMessages,
28
- E as validatePredicate
36
+ M as resolveRedirectTarget,
37
+ k as resolveUploadMessages,
38
+ j as settleStreaming,
39
+ y as splitFollowups,
40
+ K as svgDataUrl,
41
+ O as validatePredicate
29
42
  };
30
43
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;"}