@singlebase/elements 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{authui-display-BCZBP7HR.js → authui-display-BM_F3-5e.js} +426 -436
- package/dist/authui-display-BM_F3-5e.js.map +1 -0
- package/dist/{authui-display-CLGFSqRi.cjs → authui-display-CMVHTNFz.cjs} +45 -65
- package/dist/authui-display-CMVHTNFz.cjs.map +1 -0
- package/dist/authui.cjs +1 -1
- package/dist/authui.js +2 -2
- package/dist/{chat-bXaRWel7.js → chat-BH_3e1jT.js} +2081 -1121
- package/dist/chat-BH_3e1jT.js.map +1 -0
- package/dist/chat-ezUmd9II.cjs +3281 -0
- package/dist/chat-ezUmd9II.cjs.map +1 -0
- package/dist/chat-messages.d.ts +19 -6
- package/dist/chat.cjs +1 -1
- package/dist/chat.d.ts +4 -3
- package/dist/chat.js +8 -6
- package/dist/elements/authui-base.d.ts +2 -0
- package/dist/elements/authui-buttons.d.ts +1 -1
- package/dist/elements/authui-display.d.ts +1 -1
- package/dist/elements/authui.d.ts +1 -1
- package/dist/elements/chat.d.ts +192 -11
- package/dist/elements/uploader.d.ts +8 -0
- package/dist/files-4T62wkwj.cjs +77 -0
- package/dist/files-4T62wkwj.cjs.map +1 -0
- package/dist/{files-BOwtpYyQ.js → files-DS-H-3yN.js} +93 -47
- package/dist/files-DS-H-3yN.js.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.js +24 -22
- package/dist/messages.d.ts +0 -2
- package/dist/singlebase-elements.min.js +3838 -2844
- package/dist/singlebase-elements.min.js.map +1 -1
- package/dist/styles/branding.d.ts +5 -0
- package/dist/styles/tokens.d.ts +2 -0
- package/dist/upload-messages.d.ts +0 -1
- package/dist/{uploader-DGV2y9uT.cjs → uploader-COP8PkJ6.cjs} +53 -76
- package/dist/uploader-COP8PkJ6.cjs.map +1 -0
- package/dist/{uploader-abQoem5q.js → uploader-tdMU9Gxv.js} +249 -253
- package/dist/uploader-tdMU9Gxv.js.map +1 -0
- package/dist/uploader.cjs +1 -1
- package/dist/uploader.js +2 -2
- package/dist/utils/branding.d.ts +8 -0
- package/dist/utils/markdown.d.ts +69 -12
- package/dist/utils/svg.d.ts +10 -0
- package/package.json +3 -3
- package/dist/authui-display-BCZBP7HR.js.map +0 -1
- package/dist/authui-display-CLGFSqRi.cjs.map +0 -1
- package/dist/chat-DRenTJlI.cjs +0 -3001
- package/dist/chat-DRenTJlI.cjs.map +0 -1
- package/dist/chat-bXaRWel7.js.map +0 -1
- package/dist/files-BOwtpYyQ.js.map +0 -1
- package/dist/files-DW8A4Jl-.cjs +0 -38
- package/dist/files-DW8A4Jl-.cjs.map +0 -1
- package/dist/uploader-DGV2y9uT.cjs.map +0 -1
- package/dist/uploader-abQoem5q.js.map +0 -1
package/dist/chat-messages.d.ts
CHANGED
|
@@ -7,26 +7,28 @@
|
|
|
7
7
|
export interface SinglebaseChatMessages {
|
|
8
8
|
eyebrowChat: string;
|
|
9
9
|
eyebrowRag: string;
|
|
10
|
-
eyebrowRich: string;
|
|
11
10
|
headingChat: string;
|
|
12
11
|
headingRag: string;
|
|
13
|
-
headingRich: string;
|
|
14
12
|
descriptionChat: string;
|
|
15
13
|
descriptionRag: string;
|
|
16
|
-
|
|
14
|
+
eyebrowKb: string;
|
|
15
|
+
headingKb: string;
|
|
16
|
+
descriptionKb: string;
|
|
17
17
|
placeholderChat: string;
|
|
18
18
|
placeholderRag: string;
|
|
19
|
-
|
|
19
|
+
placeholderKb: string;
|
|
20
20
|
footnote: string;
|
|
21
21
|
attach: string;
|
|
22
22
|
send: string;
|
|
23
23
|
stop: string;
|
|
24
24
|
removeFile: string;
|
|
25
|
+
inThisChat: string;
|
|
26
|
+
removeFromChat: string;
|
|
27
|
+
attachmentFailed: string;
|
|
25
28
|
dropTitle: string;
|
|
26
29
|
dropSub: string;
|
|
27
30
|
thinking: string;
|
|
28
31
|
searching: string;
|
|
29
|
-
building: string;
|
|
30
32
|
chats: string;
|
|
31
33
|
newChat: string;
|
|
32
34
|
searchChats: string;
|
|
@@ -81,6 +83,17 @@ export interface SinglebaseChatMessages {
|
|
|
81
83
|
copyReference: string;
|
|
82
84
|
alsoCited: string;
|
|
83
85
|
close: string;
|
|
86
|
+
renderingChart: string;
|
|
87
|
+
renderingSvg: string;
|
|
88
|
+
copySvg: string;
|
|
89
|
+
showRaw: string;
|
|
90
|
+
showFormatted: string;
|
|
91
|
+
showingRows: string;
|
|
92
|
+
calloutNote: string;
|
|
93
|
+
calloutTip: string;
|
|
94
|
+
calloutImportant: string;
|
|
95
|
+
calloutWarning: string;
|
|
96
|
+
calloutCaution: string;
|
|
84
97
|
undo: string;
|
|
85
98
|
chatDeleted: string;
|
|
86
99
|
messageDeleted: string;
|
|
@@ -95,6 +108,7 @@ export interface SinglebaseChatMessages {
|
|
|
95
108
|
tooManyFiles: string;
|
|
96
109
|
errGeneric: string;
|
|
97
110
|
errNotFound: string;
|
|
111
|
+
errKbSource: string;
|
|
98
112
|
errNoClient: string;
|
|
99
113
|
errLoad: string;
|
|
100
114
|
retry: string;
|
|
@@ -103,7 +117,6 @@ export interface SinglebaseChatMessages {
|
|
|
103
117
|
openChat: string;
|
|
104
118
|
closeChat: string;
|
|
105
119
|
dismiss: string;
|
|
106
|
-
brandingLabel: string;
|
|
107
120
|
}
|
|
108
121
|
export declare const defaultChatMessages: SinglebaseChatMessages;
|
|
109
122
|
export declare function resolveChatMessages(overrides: Partial<SinglebaseChatMessages> | undefined): SinglebaseChatMessages;
|
package/dist/chat.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./chat-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./chat-ezUmd9II.cjs");Object.defineProperty(exports,"SinglebaseChat",{enumerable:!0,get:()=>e.SinglebaseChat});exports.adaptBlocks=e.adaptBlocks;exports.citedNumbers=e.citedNumbers;exports.defaultChatMessages=e.defaultChatMessages;exports.describeSource=e.describeSource;exports.parseInline=e.parseInline;exports.parseMarkdown=e.parseMarkdown;exports.resolveChatMessages=e.resolveChatMessages;exports.settleStreaming=e.settleStreaming;exports.splitFollowups=e.splitFollowups;exports.svgDataUrl=e.svgDataUrl;
|
|
2
2
|
//# sourceMappingURL=chat.cjs.map
|
package/dist/chat.d.ts
CHANGED
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
* authentication elements or the uploader. Importing it registers the tag.
|
|
4
4
|
*/
|
|
5
5
|
export { SinglebaseChat, describeSource } from "./elements/chat.js";
|
|
6
|
-
export type { ChatAttachment, ChatClient, ChatConfig, ChatEmbed, ChatExportFormat, ChatGlow, ChatMessage, ChatMode, ChatPrompt, ChatSummary } from "./elements/chat.js";
|
|
7
|
-
export { adaptBlocks, citedNumbers, parseInline, parseMarkdown, splitFollowups } from "./utils/markdown.js";
|
|
8
|
-
export
|
|
6
|
+
export type { ChatAfterParse, ChatAttachment, ChatBeforeSend, ChatBlockRenderer, ChatClient, ChatConfig, ChatEmbed, ChatExportFormat, ChatGlow, ChatMessage, ChatMode, ChatPrompt, ChatSavedAttachment, ChatSidebar, ChatSummary } from "./elements/chat.js";
|
|
7
|
+
export { adaptBlocks, citedNumbers, parseInline, parseMarkdown, settleStreaming, splitFollowups } from "./utils/markdown.js";
|
|
8
|
+
export { svgDataUrl } from "./utils/svg.js";
|
|
9
|
+
export type { Block, ChartSpec, ChatFormat, Segment } from "./utils/markdown.js";
|
|
9
10
|
export { defaultChatMessages, resolveChatMessages } from "./chat-messages.js";
|
|
10
11
|
export type { SinglebaseChatMessages } from "./chat-messages.js";
|
package/dist/chat.js
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
import { S as e, a as r, c as
|
|
1
|
+
import { S as e, a as r, c as t, d as l, b as o, p, e as d, r as g, s as i, f as c, g as n } from "./chat-BH_3e1jT.js";
|
|
2
2
|
export {
|
|
3
3
|
e as SinglebaseChat,
|
|
4
4
|
r as adaptBlocks,
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
t as citedNumbers,
|
|
6
|
+
l as defaultChatMessages,
|
|
7
|
+
o as describeSource,
|
|
8
8
|
p as parseInline,
|
|
9
9
|
d as parseMarkdown,
|
|
10
|
-
|
|
11
|
-
i as
|
|
10
|
+
g as resolveChatMessages,
|
|
11
|
+
i as settleStreaming,
|
|
12
|
+
c as splitFollowups,
|
|
13
|
+
n as svgDataUrl
|
|
12
14
|
};
|
|
13
15
|
//# sourceMappingURL=chat.js.map
|
|
@@ -27,6 +27,8 @@ export declare abstract class SinglebaseElementBase extends LitElement {
|
|
|
27
27
|
* same reason as theme/density — the CSS is an attribute selector.
|
|
28
28
|
*/
|
|
29
29
|
accessor fieldStyle: "outline" | "underline" | undefined;
|
|
30
|
+
/** Corner preset for this element: `sharp`, `default` or `round`. */
|
|
31
|
+
accessor radius: "sharp" | "default" | "round" | undefined;
|
|
30
32
|
protected auth: AuthController;
|
|
31
33
|
/**
|
|
32
34
|
* Resolution order: an explicit `.client`, then the page's default
|
|
@@ -36,7 +36,7 @@ export declare class SinglebaseAuthButtons extends SinglebaseFormBase {
|
|
|
36
36
|
private renderLink;
|
|
37
37
|
private onSignOut;
|
|
38
38
|
private renderSignOut;
|
|
39
|
-
protected render(): import("lit").TemplateResult<1
|
|
39
|
+
protected render(): typeof nothing | import("lit").TemplateResult<1>;
|
|
40
40
|
}
|
|
41
41
|
declare global {
|
|
42
42
|
interface HTMLElementTagNameMap {
|
|
@@ -41,7 +41,7 @@ export declare class SinglebaseAuthDisplay extends SinglebaseElementBase {
|
|
|
41
41
|
/** The resolved value as a string, or "" when there is nothing to show. */
|
|
42
42
|
private get textValue();
|
|
43
43
|
private get avatarSrc();
|
|
44
|
-
protected render(): import("lit").TemplateResult<1
|
|
44
|
+
protected render(): typeof nothing | import("lit").TemplateResult<1>;
|
|
45
45
|
private renderAvatar;
|
|
46
46
|
}
|
|
47
47
|
declare global {
|
|
@@ -206,7 +206,7 @@ export declare class SinglebaseAuthScreen extends SinglebaseElementBase {
|
|
|
206
206
|
private onInterstitialSignOut;
|
|
207
207
|
/** The Terms/Privacy consent line, rendered only when the host supplies a link. */
|
|
208
208
|
private renderConsent;
|
|
209
|
-
protected render(): import("lit").TemplateResult<1
|
|
209
|
+
protected render(): typeof nothing | import("lit").TemplateResult<1>;
|
|
210
210
|
}
|
|
211
211
|
declare global {
|
|
212
212
|
interface HTMLElementTagNameMap {
|
package/dist/elements/chat.d.ts
CHANGED
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import { LitElement, type PropertyValues, type TemplateResult } from "lit";
|
|
2
2
|
import { type SinglebaseChatMessages } from "../chat-messages.js";
|
|
3
|
-
import { type
|
|
4
|
-
|
|
3
|
+
import { type Block, type ChatFormat } from "../utils/markdown.js";
|
|
4
|
+
/**
|
|
5
|
+
* How answers use sources: `chat` free-form, `rag` prefers sources and cites
|
|
6
|
+
* them, `kb` answers only from sources (docsets, retrieval, attachments).
|
|
7
|
+
*/
|
|
8
|
+
export type ChatMode = "chat" | "rag" | "kb";
|
|
5
9
|
export type ChatEmbed = "page" | "inline" | "launcher";
|
|
6
10
|
export type ChatGlow = "subtle" | "vivid" | "off";
|
|
7
11
|
export type ChatExportFormat = "md" | "txt" | "json" | "copy";
|
|
12
|
+
/** `auto` docks when there's room; `none` removes the list and its toggle. */
|
|
13
|
+
export type ChatSidebar = "auto" | "open" | "closed" | "none";
|
|
8
14
|
/** What the chat needs from a client: `llm.call`, and nothing else. */
|
|
9
15
|
export type ChatClient = {
|
|
10
16
|
llm: {
|
|
@@ -27,6 +33,16 @@ export interface ChatAttachment {
|
|
|
27
33
|
name: string;
|
|
28
34
|
size: number;
|
|
29
35
|
content: string;
|
|
36
|
+
mime?: string;
|
|
37
|
+
}
|
|
38
|
+
/** A file the service keeps on the chat (attachments-mode="payload"). */
|
|
39
|
+
export interface ChatSavedAttachment {
|
|
40
|
+
id: string;
|
|
41
|
+
name: string;
|
|
42
|
+
type?: string;
|
|
43
|
+
mime?: string;
|
|
44
|
+
size?: number;
|
|
45
|
+
status?: string;
|
|
30
46
|
}
|
|
31
47
|
export interface ChatMessage {
|
|
32
48
|
/** Local identity, stable across renders. */
|
|
@@ -49,31 +65,79 @@ export interface ChatMessage {
|
|
|
49
65
|
execTime?: number;
|
|
50
66
|
model?: string;
|
|
51
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* Draws a fenced block the host knows about, e.g. ```order {"id":"A-1"}```.
|
|
70
|
+
* Return a Lit template, a DOM node or text; return null to fall back to code.
|
|
71
|
+
*/
|
|
72
|
+
export type ChatBlockRenderer = (source: string, context: {
|
|
73
|
+
lang: string;
|
|
74
|
+
message: ChatMessage;
|
|
75
|
+
}) => unknown;
|
|
76
|
+
/**
|
|
77
|
+
* Runs before each message is sent. Return the payload (changed or not), a new
|
|
78
|
+
* payload, or `false` to cancel. Anything else stops the send.
|
|
79
|
+
*/
|
|
80
|
+
export type ChatBeforeSend = (payload: Record<string, unknown>, context: {
|
|
81
|
+
chatId: string | null;
|
|
82
|
+
isNew: boolean;
|
|
83
|
+
message: ChatMessage;
|
|
84
|
+
}) => Record<string, unknown> | false | Promise<Record<string, unknown> | false>;
|
|
85
|
+
/** Runs after a reply is parsed. Return the blocks to draw. */
|
|
86
|
+
export type ChatAfterParse = (blocks: Block[], context: {
|
|
87
|
+
message: ChatMessage;
|
|
88
|
+
format: ChatFormat;
|
|
89
|
+
}) => Block[];
|
|
52
90
|
export interface ChatPrompt {
|
|
53
91
|
label?: string;
|
|
54
92
|
text: string;
|
|
55
93
|
}
|
|
56
94
|
/** Every setting in one object, keyed by property name. */
|
|
57
95
|
export interface ChatConfig {
|
|
96
|
+
/** The client to chat with. Defaults to the page's SinglebaseClient(). */
|
|
97
|
+
client: ChatClient | null;
|
|
98
|
+
/** Opens this saved chat. */
|
|
99
|
+
chatId: string;
|
|
58
100
|
embed: ChatEmbed;
|
|
59
101
|
mode: ChatMode;
|
|
60
|
-
|
|
102
|
+
format: ChatFormat;
|
|
103
|
+
renderers: Record<string, ChatBlockRenderer>;
|
|
104
|
+
beforeSend: ChatBeforeSend | null;
|
|
105
|
+
afterParse: ChatAfterParse | null;
|
|
61
106
|
glow: ChatGlow;
|
|
62
107
|
position: "right" | "left";
|
|
63
|
-
sidebar:
|
|
108
|
+
sidebar: ChatSidebar;
|
|
64
109
|
showTitle: boolean;
|
|
65
110
|
assistantName: string;
|
|
66
111
|
logoUrl: string;
|
|
67
112
|
heading: string;
|
|
68
113
|
description: string;
|
|
114
|
+
eyebrow: string;
|
|
69
115
|
prompts: string | (string | ChatPrompt)[];
|
|
70
116
|
bubbleText: string;
|
|
71
117
|
greetingBubble: boolean;
|
|
72
118
|
unreadBadge: boolean;
|
|
73
119
|
allowUpload: boolean;
|
|
74
120
|
allowExport: boolean;
|
|
121
|
+
allowRaw: boolean;
|
|
122
|
+
allowCopy: boolean;
|
|
123
|
+
allowRegenerate: boolean;
|
|
124
|
+
allowBookmark: boolean;
|
|
125
|
+
allowDelete: boolean;
|
|
126
|
+
allowRename: boolean;
|
|
127
|
+
allowFeedback: boolean;
|
|
128
|
+
showTime: boolean;
|
|
129
|
+
showComposer: boolean;
|
|
130
|
+
footnote: string;
|
|
75
131
|
branding: boolean;
|
|
76
132
|
followups: boolean;
|
|
133
|
+
docsets: string | string[];
|
|
134
|
+
attachmentsMode: "retrieval" | "payload";
|
|
135
|
+
saveAttachments: boolean;
|
|
136
|
+
showFollowups: boolean;
|
|
137
|
+
showSources: boolean;
|
|
138
|
+
showNewChat: boolean;
|
|
139
|
+
showBookmarked: boolean;
|
|
140
|
+
allowSearch: boolean;
|
|
77
141
|
autoTitle: boolean;
|
|
78
142
|
model: string;
|
|
79
143
|
params: Record<string, unknown>;
|
|
@@ -82,11 +146,13 @@ export interface ChatConfig {
|
|
|
82
146
|
metadata: Record<string, unknown>;
|
|
83
147
|
messages: Partial<SinglebaseChatMessages>;
|
|
84
148
|
theme: "light" | "dark";
|
|
149
|
+
radius: "sharp" | "default" | "round";
|
|
85
150
|
}
|
|
86
151
|
/** A readable view of whatever shape the server recorded for a source. */
|
|
87
152
|
export declare function describeSource(source: Record<string, unknown>, n: number): {
|
|
88
153
|
n: number;
|
|
89
154
|
title: string;
|
|
155
|
+
section: string;
|
|
90
156
|
path: string;
|
|
91
157
|
collection: string;
|
|
92
158
|
updated: string;
|
|
@@ -111,13 +177,52 @@ export declare class SinglebaseChat extends LitElement {
|
|
|
111
177
|
accessor client: ChatClient | null;
|
|
112
178
|
accessor messages: Partial<SinglebaseChatMessages>;
|
|
113
179
|
accessor theme: "light" | "dark" | undefined;
|
|
180
|
+
/** Corner preset for this element: `sharp`, `default` or `round`. */
|
|
181
|
+
accessor radius: "sharp" | "default" | "round" | undefined;
|
|
114
182
|
/** `chat` free-form, `rag` grounded with citations, `rich` charts and tables. */
|
|
115
183
|
accessor mode: ChatMode;
|
|
116
|
-
/**
|
|
117
|
-
|
|
184
|
+
/**
|
|
185
|
+
* How much of a reply is formatted: `raw` (the text as written), `plain`
|
|
186
|
+
* (light formatting), `advanced` (+ tables, CSV, JSON and SVG) or `rich`
|
|
187
|
+
* (+ callouts, charts, images and `renderers`). Copy and export always use
|
|
188
|
+
* the original text.
|
|
189
|
+
*/
|
|
190
|
+
accessor format: ChatFormat;
|
|
191
|
+
/** Your own fenced blocks, by language. Drawn at the `rich` level. */
|
|
192
|
+
accessor renderers: Record<string, ChatBlockRenderer>;
|
|
193
|
+
/**
|
|
194
|
+
* Preflight for every message: gets the `llm.chat` payload, returns it
|
|
195
|
+
* (changed or not), or `false` to cancel. May be async.
|
|
196
|
+
*/
|
|
197
|
+
accessor beforeSend: ChatBeforeSend | null;
|
|
198
|
+
/** Rewrites a reply's parsed blocks before they're drawn. Returns the blocks. */
|
|
199
|
+
accessor afterParse: ChatAfterParse | null;
|
|
118
200
|
accessor glow: ChatGlow;
|
|
119
|
-
/**
|
|
201
|
+
/**
|
|
202
|
+
* Docsets to answer from: slugs or ids, comma-separated in markup or an
|
|
203
|
+
* array in JavaScript. Sent as `{ source: "docset", ids }`.
|
|
204
|
+
*/
|
|
205
|
+
accessor docsets: string | string[];
|
|
206
|
+
/**
|
|
207
|
+
* How attached files reach the service: `retrieval` (this message only;
|
|
208
|
+
* works with every service version) or `payload` (as `attachments`, which
|
|
209
|
+
* the service keeps on the chat for later turns).
|
|
210
|
+
*/
|
|
211
|
+
accessor attachmentsMode: "retrieval" | "payload";
|
|
212
|
+
/** With attachments-mode="payload": keep attached files on the chat. */
|
|
213
|
+
accessor saveAttachments: boolean;
|
|
214
|
+
/** Ask the model for follow-up questions with each reply. */
|
|
120
215
|
accessor followups: boolean;
|
|
216
|
+
/** The "Cited sources" cards and the "Searched n sources" row under answers. */
|
|
217
|
+
accessor showSources: boolean;
|
|
218
|
+
/** The New chat button. */
|
|
219
|
+
accessor showNewChat: boolean;
|
|
220
|
+
/** The pinned "Bookmarked" group in the chat list. */
|
|
221
|
+
accessor showBookmarked: boolean;
|
|
222
|
+
/** Show the follow-up questions under the latest reply. */
|
|
223
|
+
accessor showFollowups: boolean;
|
|
224
|
+
/** The search box in the chat list. */
|
|
225
|
+
accessor allowSearch: boolean;
|
|
121
226
|
/** Replace the provisional title with a model-written one after the first reply. */
|
|
122
227
|
accessor autoTitle: boolean;
|
|
123
228
|
/** Model for new turns; empty uses the chat's, then the project default. */
|
|
@@ -132,8 +237,11 @@ export declare class SinglebaseChat extends LitElement {
|
|
|
132
237
|
accessor embed: ChatEmbed;
|
|
133
238
|
/** Launcher side. */
|
|
134
239
|
accessor position: "right" | "left";
|
|
135
|
-
/**
|
|
136
|
-
|
|
240
|
+
/**
|
|
241
|
+
* The chat list: `auto` docks it when there's room, `open` / `closed` set
|
|
242
|
+
* how it starts, `none` removes it and its toggle entirely.
|
|
243
|
+
*/
|
|
244
|
+
accessor sidebar: ChatSidebar;
|
|
137
245
|
accessor showTitle: boolean;
|
|
138
246
|
/** Opens this chat on load. */
|
|
139
247
|
accessor chatIdAttr: string;
|
|
@@ -142,13 +250,44 @@ export declare class SinglebaseChat extends LitElement {
|
|
|
142
250
|
accessor logoUrl: string;
|
|
143
251
|
accessor heading: string;
|
|
144
252
|
accessor description: string;
|
|
145
|
-
/**
|
|
253
|
+
/** The small label above the heading. Unset uses the mode's; `""` hides it. */
|
|
254
|
+
accessor eyebrow: string | undefined;
|
|
255
|
+
/**
|
|
256
|
+
* Suggested prompts: `|`-separated in markup, an array in JavaScript.
|
|
257
|
+
* `"none"` or `[]` shows no suggestions.
|
|
258
|
+
*/
|
|
146
259
|
accessor prompts: string | (string | ChatPrompt)[];
|
|
147
260
|
accessor bubbleText: string;
|
|
148
261
|
accessor greetingBubble: boolean;
|
|
149
262
|
accessor unreadBadge: boolean;
|
|
150
263
|
accessor allowUpload: boolean;
|
|
151
264
|
accessor allowExport: boolean;
|
|
265
|
+
/** Copy buttons on messages. */
|
|
266
|
+
accessor allowCopy: boolean;
|
|
267
|
+
/** Regenerate on the latest reply. */
|
|
268
|
+
accessor allowRegenerate: boolean;
|
|
269
|
+
/** Bookmark buttons for chats and messages. */
|
|
270
|
+
accessor allowBookmark: boolean;
|
|
271
|
+
/** Delete buttons for chats and messages. */
|
|
272
|
+
accessor allowDelete: boolean;
|
|
273
|
+
/** Renaming a chat from its title or the chat list. */
|
|
274
|
+
accessor allowRename: boolean;
|
|
275
|
+
/** The helpful / not helpful buttons on replies. */
|
|
276
|
+
accessor allowFeedback: boolean;
|
|
277
|
+
/**
|
|
278
|
+
* The message box. Off, the chat only shows the conversation — pair it with
|
|
279
|
+
* `chat-id` to display a saved chat read-only.
|
|
280
|
+
*/
|
|
281
|
+
accessor showComposer: boolean;
|
|
282
|
+
/** Message times in the toolbars. */
|
|
283
|
+
accessor showTime: boolean;
|
|
284
|
+
/**
|
|
285
|
+
* The line under the composer. Unset uses the default ("{name} can make
|
|
286
|
+
* mistakes…"); an empty string hides it.
|
|
287
|
+
*/
|
|
288
|
+
accessor footnote: string | undefined;
|
|
289
|
+
/** A per-reply toggle between the formatted answer and the text as written. */
|
|
290
|
+
accessor allowRaw: boolean;
|
|
152
291
|
/** The "Chat by Singlebase" credit. A plain link — it makes no request. */
|
|
153
292
|
accessor branding: boolean;
|
|
154
293
|
private accessor chatList;
|
|
@@ -174,6 +313,10 @@ export declare class SinglebaseChat extends LitElement {
|
|
|
174
313
|
private accessor toast;
|
|
175
314
|
private accessor copiedKey;
|
|
176
315
|
private accessor retrievalOpen;
|
|
316
|
+
private accessor rawKeys;
|
|
317
|
+
private accessor savedFiles;
|
|
318
|
+
private accessor hasSidebarContent;
|
|
319
|
+
private accessor sorts;
|
|
177
320
|
private accessor arrivedKey;
|
|
178
321
|
private accessor dragging;
|
|
179
322
|
private accessor showJump;
|
|
@@ -195,6 +338,7 @@ export declare class SinglebaseChat extends LitElement {
|
|
|
195
338
|
private media;
|
|
196
339
|
private focusNext;
|
|
197
340
|
private bubbleScheduled;
|
|
341
|
+
private pendingChatId;
|
|
198
342
|
get msg(): SinglebaseChatMessages;
|
|
199
343
|
/** An explicit `.client`, else the page default. */
|
|
200
344
|
get resolvedClient(): ChatClient | null;
|
|
@@ -202,9 +346,30 @@ export declare class SinglebaseChat extends LitElement {
|
|
|
202
346
|
get chatId(): string | null;
|
|
203
347
|
/** The open conversation's messages. */
|
|
204
348
|
get thread(): readonly ChatMessage[];
|
|
349
|
+
/** `format`, falling back to the default for anything unknown. */
|
|
350
|
+
/** `docsets` as a clean list of ids. */
|
|
351
|
+
private get docsetIds();
|
|
352
|
+
/** The files this chat keeps on the service. */
|
|
353
|
+
get attachments(): readonly ChatSavedAttachment[];
|
|
354
|
+
private get formatLevel();
|
|
205
355
|
/** The loaded chat list. */
|
|
206
356
|
get chats(): readonly ChatSummary[];
|
|
357
|
+
/**
|
|
358
|
+
* Every setting in one object, keyed by property name:
|
|
359
|
+
*
|
|
360
|
+
* chat.config = { client, mode: "rag", format: "rich", retrieval: [...], chatId: "…" };
|
|
361
|
+
*
|
|
362
|
+
* Unknown keys are ignored. `chatId` opens that chat; reading `config`
|
|
363
|
+
* returns the current settings with `chatId` as the open chat.
|
|
364
|
+
*/
|
|
207
365
|
set config(value: Partial<ChatConfig>);
|
|
366
|
+
/**
|
|
367
|
+
* Changes settings on the fly. Only the keys you pass change; the chat keeps
|
|
368
|
+
* its conversation and re-renders in place. Returns the element, so calls chain.
|
|
369
|
+
*
|
|
370
|
+
* chat.configure({ format: "rich" }).configure({ theme: "dark" });
|
|
371
|
+
*/
|
|
372
|
+
configure(options: Partial<ChatConfig>): this;
|
|
208
373
|
get config(): Partial<ChatConfig>;
|
|
209
374
|
connectedCallback(): void;
|
|
210
375
|
disconnectedCallback(): void;
|
|
@@ -257,13 +422,22 @@ export declare class SinglebaseChat extends LitElement {
|
|
|
257
422
|
private renameChat;
|
|
258
423
|
private fromServer;
|
|
259
424
|
private loadChats;
|
|
425
|
+
/**
|
|
426
|
+
* A new chat goes on top. A chat already in the list is updated where it is,
|
|
427
|
+
* keeping its dates, so opening or using a chat never reorders the list; the
|
|
428
|
+
* next load from the server brings the fresh order.
|
|
429
|
+
*/
|
|
260
430
|
private upsertChat;
|
|
261
|
-
private touchChat;
|
|
262
431
|
private resetViewState;
|
|
263
432
|
private deleteOnServer;
|
|
264
433
|
private regenerate;
|
|
265
434
|
private retry;
|
|
266
435
|
private saveEdit;
|
|
436
|
+
private toggleRaw;
|
|
437
|
+
/** Adds newly saved files, and says which ones the service couldn't read. */
|
|
438
|
+
private applyAttachmentResults;
|
|
439
|
+
/** Removes a file the service keeps on this chat. */
|
|
440
|
+
private removeSavedFile;
|
|
267
441
|
private copy;
|
|
268
442
|
private toggleMessageBookmark;
|
|
269
443
|
private toggleChatBookmark;
|
|
@@ -292,6 +466,7 @@ export declare class SinglebaseChat extends LitElement {
|
|
|
292
466
|
private renderThreadRow;
|
|
293
467
|
private renderHeader;
|
|
294
468
|
private renderExportMenu;
|
|
469
|
+
/** The suggestion cards. `[]` or `"none"` shows none; unset uses the mode's. */
|
|
295
470
|
private promptList;
|
|
296
471
|
private renderWelcome;
|
|
297
472
|
private renderThread;
|
|
@@ -301,6 +476,12 @@ export declare class SinglebaseChat extends LitElement {
|
|
|
301
476
|
private renderAnswer;
|
|
302
477
|
private renderInline;
|
|
303
478
|
private renderBlock;
|
|
479
|
+
private renderList;
|
|
480
|
+
private renderCode;
|
|
481
|
+
/** A host renderer for this language, at the rich level only. */
|
|
482
|
+
private renderCustom;
|
|
483
|
+
private renderTable;
|
|
484
|
+
private renderJsonBlock;
|
|
304
485
|
private renderChart;
|
|
305
486
|
private renderPanel;
|
|
306
487
|
private renderComposer;
|
|
@@ -67,6 +67,7 @@ export interface UploaderConfig {
|
|
|
67
67
|
messages: Partial<SinglebaseUploadMessages>;
|
|
68
68
|
theme: "light" | "dark";
|
|
69
69
|
density: "comfortable" | "compact";
|
|
70
|
+
radius: "sharp" | "default" | "round";
|
|
70
71
|
onComplete: SinglebaseUploader["onComplete"];
|
|
71
72
|
onError: SinglebaseUploader["onError"];
|
|
72
73
|
}
|
|
@@ -93,6 +94,8 @@ export declare class SinglebaseUploader extends LitElement {
|
|
|
93
94
|
accessor messages: Partial<SinglebaseUploadMessages>;
|
|
94
95
|
accessor theme: "light" | "dark" | undefined;
|
|
95
96
|
accessor density: "comfortable" | "compact" | undefined;
|
|
97
|
+
/** Corner preset for this element: `sharp`, `default` or `round`. */
|
|
98
|
+
accessor radius: "sharp" | "default" | "round" | undefined;
|
|
96
99
|
/**
|
|
97
100
|
* `full` is the card with a dropzone and a reviewable list, `compact` the
|
|
98
101
|
* one-line attachments row, `button` a single control that uploads as soon
|
|
@@ -168,6 +171,11 @@ export declare class SinglebaseUploader extends LitElement {
|
|
|
168
171
|
* Unknown keys are ignored. Reading it returns the current settings.
|
|
169
172
|
*/
|
|
170
173
|
set config(value: Partial<UploaderConfig>);
|
|
174
|
+
/**
|
|
175
|
+
* Changes settings on the fly. Only the keys you pass change; staged files
|
|
176
|
+
* stay. Returns the element, so calls chain.
|
|
177
|
+
*/
|
|
178
|
+
configure(options: Partial<UploaderConfig>): this;
|
|
171
179
|
get config(): Partial<UploaderConfig>;
|
|
172
180
|
/** Drops every staged file and any notice. */
|
|
173
181
|
clear(): void;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";const o=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"},f=o.css`
|
|
2
|
+
:host {
|
|
3
|
+
display: block;
|
|
4
|
+
box-sizing: border-box;
|
|
5
|
+
font-family: var(--sb-font, ${o.unsafeCSS(i.font)});
|
|
6
|
+
color: var(--sb-ink, ${o.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=o.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.io",b="Singlebase.io";function g(e,r){return e?o.html`<div class="branding" part="branding">
|
|
73
|
+
<a href=${u} title=${b} target="_blank" rel="noopener noreferrer"
|
|
74
|
+
>${r} by Singlebase</a
|
|
75
|
+
>
|
|
76
|
+
</div>`:o.nothing}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}."};function m(e){return e?{...d,...e}:d}function h(e,r){return e.replace(/\{(\w+)\}/g,(n,t)=>t in r?String(r[t]):n)}const x={b:1,kb:1024,mb:1024*1024,gb:1024*1024*1024};function S(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*(x[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 c(e){const r=e.lastIndexOf(".");return r<=0||r===e.length-1?"":e.slice(r+1).toLowerCase()}function y(e){return c(e).toUpperCase().slice(0,4)}function C(e,r,n){const t=e.split(",").map(a=>a.trim().toLowerCase()).filter(Boolean);if(!t.length)return!0;const s=r.toLowerCase(),l=(n||"").toLowerCase();return t.some(a=>a.startsWith(".")?s.endsWith(a):a.endsWith("/*")?l.startsWith(a.slice(0,-1)):l===a)}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 w(e){return`${e.name}:${e.size}:${e.lastModified??0}`}function T(e,r){const n=r.trim().replace(/[/\\]/g,"");if(!n)return e;const t=e.lastIndexOf("."),s=t>0?e.slice(t):"";return s?n.toLowerCase().endsWith(s.toLowerCase())?n:n+s:n}exports.TOKEN_DEFAULTS=i;exports.acceptSummary=U;exports.acceptsFile=C;exports.brandingStyles=p;exports.defaultUploadMessages=d;exports.extensionOf=y;exports.fileExtension=c;exports.fileKey=w;exports.fill=h;exports.formatSize=k;exports.parseSize=S;exports.renameKeepingExtension=T;exports.renderBranding=g;exports.resolveUploadMessages=m;exports.tokenDefaults=f;
|
|
77
|
+
//# sourceMappingURL=files-4T62wkwj.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"files-4T62wkwj.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 BRANDING_URL = \"https://singlebase.io\";\nexport const BRANDING_TITLE = \"Singlebase.io\";\n\n/**\n * The fixed \"… by Singlebase\" credit. It can be hidden, never changed.\n * It's a plain link: it makes no request until someone clicks it.\n */\nexport function renderBranding(show: boolean, product: \"Auth\" | \"Chat\" | \"Files\") {\n if (!show) return nothing;\n return html`<div class=\"branding\" part=\"branding\">\n <a href=${BRANDING_URL} title=${BRANDING_TITLE} target=\"_blank\" rel=\"noopener noreferrer\"\n >${product} by Singlebase</a\n >\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\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\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","BRANDING_URL","BRANDING_TITLE","renderBranding","show","product","html","nothing","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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"}
|