@osvi-ai/chat 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/README.md +1 -3
- package/dist/core.js +10 -0
- package/dist/core.js.map +1 -0
- package/dist/index-BsRyQwUM.js +1331 -0
- package/dist/index-BsRyQwUM.js.map +1 -0
- package/dist/types/core/client.d.ts +65 -0
- package/dist/types/core/connection.d.ts +78 -0
- package/dist/types/core/errors.d.ts +14 -0
- package/dist/types/core/http.d.ts +38 -0
- package/dist/types/core/index.d.ts +7 -0
- package/dist/types/core/interactions.d.ts +50 -0
- package/dist/types/core/protocol/envelope.d.ts +2 -0
- package/dist/types/core/protocol/readers.d.ts +14 -0
- package/dist/types/core/protocol/types.d.ts +118 -0
- package/dist/types/core/protocol/validators.d.ts +10 -0
- package/dist/types/core/state.d.ts +23 -0
- package/dist/types/core/storage.d.ts +10 -0
- package/dist/types/core/version.d.ts +1 -0
- package/dist/types/ui/define.d.ts +1 -0
- package/dist/types/ui/index.d.ts +9 -0
- package/dist/types/ui/osvi-chat.d.ts +69 -0
- package/dist/types/ui/panel/attrs.d.ts +6 -0
- package/dist/types/ui/panel/composer.d.ts +10 -0
- package/dist/types/ui/panel/linkify.d.ts +7 -0
- package/dist/types/ui/panel/transcript.d.ts +4 -0
- package/dist/types/ui/strings.d.ts +27 -0
- package/dist/types/ui/styles.d.ts +1 -0
- package/dist/types/ui/theme.d.ts +22 -0
- package/dist/types/ui/tools/base.d.ts +14 -0
- package/dist/types/ui/tools/osvi-buttons.d.ts +10 -0
- package/dist/types/ui/tools/osvi-carousel.d.ts +16 -0
- package/dist/types/ui/tools/osvi-date-picker.d.ts +17 -0
- package/dist/types/widget/config.d.ts +22 -0
- package/dist/types/widget/index.d.ts +1 -0
- package/dist/types/widget/launcher.d.ts +35 -0
- package/dist/types/widget/widget.d.ts +13 -0
- package/dist/ui.js +49 -0
- package/dist/ui.js.map +1 -0
- package/dist/ui.mjs +570 -0
- package/dist/ui.mjs.map +1 -0
- package/dist/widget.js +59 -0
- package/dist/widget.js.map +1 -0
- package/package.json +60 -4
package/dist/ui.mjs
ADDED
|
@@ -0,0 +1,570 @@
|
|
|
1
|
+
import { nothing as d, html as a, LitElement as W, css as X, unsafeCSS as x } from "lit";
|
|
2
|
+
import { property as l, state as b } from "lit/decorators.js";
|
|
3
|
+
import { c as et, i as it, a as st, b as R } from "./index-BsRyQwUM.js";
|
|
4
|
+
import { repeat as nt } from "lit/directives/repeat.js";
|
|
5
|
+
import { live as rt } from "lit/directives/live.js";
|
|
6
|
+
const Y = { primary: "#4f46e5", background: "#ffffff", surface: "#f4f4f5", text: "#18181b", userBubble: "#4f46e5", assistantBubble: "#f4f4f5" }, at = { primary: "#6366f1", background: "#0a0a12", surface: "#1c1c27", text: "#f4f4f5", userBubble: "#6366f1", assistantBubble: "#1f1f2b" }, ot = { none: "0px", sm: "6px", md: "10px", lg: "16px", full: "9999px" }, C = { primary: "--osvi-color-primary", background: "--osvi-color-background", surface: "--osvi-color-surface", text: "--osvi-color-text", userBubble: "--osvi-color-user-bubble", assistantBubble: "--osvi-color-assistant-bubble" }, w = (i) => `var(${C[i]}, ${Y[i]})`;
|
|
7
|
+
function F(i) {
|
|
8
|
+
const t = { ...i?.mode === "dark" ? at : Y, ...i?.colors }, e = {};
|
|
9
|
+
for (const n of Object.keys(C)) e[C[n]] = t[n];
|
|
10
|
+
const s = i?.radius ?? "md";
|
|
11
|
+
return e["--osvi-radius"] = typeof s == "number" ? `${s}px` : ot[s], e;
|
|
12
|
+
}
|
|
13
|
+
function lt(i) {
|
|
14
|
+
if (!i) return {};
|
|
15
|
+
if (i.mode) return F(i);
|
|
16
|
+
const t = F(i), e = {};
|
|
17
|
+
for (const s of Object.keys(i.colors ?? {})) e[C[s]] = t[C[s]];
|
|
18
|
+
return i.radius !== void 0 && (e["--osvi-radius"] = t["--osvi-radius"]), e;
|
|
19
|
+
}
|
|
20
|
+
const M = /* @__PURE__ */ new WeakMap();
|
|
21
|
+
function G(i, t) {
|
|
22
|
+
for (const s of M.get(i) ?? []) i.style.removeProperty(s);
|
|
23
|
+
const e = lt(t);
|
|
24
|
+
for (const [s, n] of Object.entries(e)) i.style.setProperty(s, n);
|
|
25
|
+
M.set(i, Object.keys(e));
|
|
26
|
+
}
|
|
27
|
+
const N = {
|
|
28
|
+
placeholder: "Type your message…",
|
|
29
|
+
send: "Send",
|
|
30
|
+
typing: "Typing…",
|
|
31
|
+
humanJoined: "A team member has joined",
|
|
32
|
+
chooseOption: "Choose an option to continue.",
|
|
33
|
+
typeAnswer: "Type your answer below, then press Send.",
|
|
34
|
+
sending: "Sending your response…",
|
|
35
|
+
pausedForHuman: "Choices are paused while a team member is connected.",
|
|
36
|
+
sendFailed: "Message not sent.",
|
|
37
|
+
retry: "Retry",
|
|
38
|
+
sessionEnded: "Conversation ended",
|
|
39
|
+
reconnecting: "Reconnecting…",
|
|
40
|
+
offline: "You are offline. We will reconnect automatically.",
|
|
41
|
+
unavailable: "This chat is unavailable.",
|
|
42
|
+
originBlocked: "This chat is not enabled for this website.",
|
|
43
|
+
rateLimited: "Too many requests. Please try again in a few minutes.",
|
|
44
|
+
tryAgain: "Try again",
|
|
45
|
+
closeChat: "Close chat",
|
|
46
|
+
poweredBy: "Powered by OSVI",
|
|
47
|
+
newChat: "New chat",
|
|
48
|
+
emptyState: "Send a message to start chatting.",
|
|
49
|
+
defaultTitle: "Chat"
|
|
50
|
+
}, L = /* @__PURE__ */ new Set();
|
|
51
|
+
function Q(i, t) {
|
|
52
|
+
L.has(i) || (L.add(i), console.warn(`[osvi-chat] ${t}`));
|
|
53
|
+
}
|
|
54
|
+
function y(i, t) {
|
|
55
|
+
return i != null && t.includes(i) ? i : void 0;
|
|
56
|
+
}
|
|
57
|
+
function K(i) {
|
|
58
|
+
if (i != null)
|
|
59
|
+
return y(i, ["none", "sm", "md", "lg", "full"]) ?? (/^\d{1,2}(?:px)?$/.test(i) ? Number(i.replace(/px$/, "")) : void 0);
|
|
60
|
+
}
|
|
61
|
+
function H(i) {
|
|
62
|
+
if (i) {
|
|
63
|
+
try {
|
|
64
|
+
const t = new URL(i);
|
|
65
|
+
if (!t.username && !t.password && (t.protocol === "https:" || t.protocol === "http:" && ["localhost", "127.0.0.1"].includes(t.hostname))) return i.replace(/\/+$/, "");
|
|
66
|
+
} catch {
|
|
67
|
+
}
|
|
68
|
+
Q("base-url", "ignored an invalid base-url (https required, http only for localhost)");
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function dt(i) {
|
|
72
|
+
if (i) {
|
|
73
|
+
if (/^data:image\/(png|jpeg|gif|webp);base64,[a-z0-9+/]+={0,2}$/i.test(i)) return i;
|
|
74
|
+
try {
|
|
75
|
+
const t = new URL(i);
|
|
76
|
+
if (t.protocol === "https:" && !t.username && !t.password) return i;
|
|
77
|
+
} catch {
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function J(i, t) {
|
|
82
|
+
if (t) {
|
|
83
|
+
try {
|
|
84
|
+
const e = JSON.parse(t);
|
|
85
|
+
if (e && typeof e == "object" && !Array.isArray(e)) return e;
|
|
86
|
+
} catch {
|
|
87
|
+
}
|
|
88
|
+
Q(i, `ignored invalid JSON in the ${i} attribute`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
const ct = /https?:\/\/[^\s<>"']+/g, S = (i, t) => i.split(t).length - 1;
|
|
92
|
+
function ht(i) {
|
|
93
|
+
for (; ; ) {
|
|
94
|
+
const t = i[i.length - 1];
|
|
95
|
+
if (t && ".,!?;:".includes(t) || t === ")" && S(i, ")") > S(i, "(") || t === "]" && S(i, "]") > S(i, "[")) {
|
|
96
|
+
i = i.slice(0, -1);
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
return i;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
function ut(i) {
|
|
103
|
+
const t = [];
|
|
104
|
+
let e = 0;
|
|
105
|
+
for (const s of i.matchAll(ct)) {
|
|
106
|
+
const n = ht(s[0]), r = s.index;
|
|
107
|
+
try {
|
|
108
|
+
const o = new URL(n);
|
|
109
|
+
if (!["http:", "https:"].includes(o.protocol)) continue;
|
|
110
|
+
} catch {
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
r > e && t.push({ text: i.slice(e, r) }), t.push({ href: n, text: n }), e = r + n.length;
|
|
114
|
+
}
|
|
115
|
+
return e < i.length && t.push({ text: i.slice(e) }), t.length ? t : [{ text: i }];
|
|
116
|
+
}
|
|
117
|
+
function pt(i, t, e, s, n) {
|
|
118
|
+
return a`${i.items.length ? nt(i.items, (r) => r.id, (r) => {
|
|
119
|
+
if (r.kind === "divider") return a`<p class="divider">${t.sessionEnded}</p>`;
|
|
120
|
+
if (r.kind === "message") return a`<article class=${`bubble ${r.role}`}>${r.role === "human" ? a`<small>Team</small>` : d}<p>${ut(r.content).map(($) => "href" in $ ? a`<a href=${$.href} target="_blank" rel="noopener noreferrer">${$.text}</a>` : $.text)}</p>${r.role === "user" && r.status === "failed" ? a`<span>${t.sendFailed}</span><button type="button" @click=${() => n(r.id)}>${t.retry}</button>` : d}</article>`;
|
|
121
|
+
const o = r.interaction, u = o.interaction_id === i.activeInteraction?.interaction_id && o.interaction_status === "pending", _ = !u || i.interactionPending || i.mode === "human";
|
|
122
|
+
switch (o.tool_type) {
|
|
123
|
+
case "ui_buttons":
|
|
124
|
+
return a`<osvi-buttons data-live=${u ? "true" : "false"} .interaction=${o} .disabled=${_} .variant=${e.buttons ?? "chips"} base-url=${s}></osvi-buttons>`;
|
|
125
|
+
case "ui_carousel":
|
|
126
|
+
return a`<osvi-carousel data-live=${u ? "true" : "false"} .interaction=${o} .disabled=${_} .variant=${e.carousel ?? "slider"} base-url=${s}></osvi-carousel>`;
|
|
127
|
+
case "ui_date_picker":
|
|
128
|
+
return a`<osvi-date-picker data-live=${u ? "true" : "false"} .interaction=${o} .disabled=${_} base-url=${s}></osvi-date-picker>`;
|
|
129
|
+
default:
|
|
130
|
+
return a`<p>${o.content}</p>`;
|
|
131
|
+
}
|
|
132
|
+
}) : a`<p>${t.emptyState}</p>`}${i.awaitingReply ? a`<p aria-label=${t.typing}>${t.typing}<span aria-hidden="true"> •••</span></p>` : d}`;
|
|
133
|
+
}
|
|
134
|
+
function ft(i) {
|
|
135
|
+
return a`<div class="composer"><textarea aria-label="Message" placeholder=${i.placeholder} .value=${rt(i.draft)} ?disabled=${i.disabled} @input=${i.input} @keydown=${(t) => {
|
|
136
|
+
t.key === "Enter" && !t.shiftKey && !t.isComposing && !i.disabled && (t.preventDefault(), i.send());
|
|
137
|
+
}}></textarea><button type="button" aria-label=${i.strings.send} ?disabled=${i.disabled || !i.draft.trim()} @click=${i.send}>${i.strings.send}</button></div>`;
|
|
138
|
+
}
|
|
139
|
+
var bt = Object.defineProperty, h = (i, t, e, s) => {
|
|
140
|
+
for (var n = void 0, r = i.length - 1, o; r >= 0; r--)
|
|
141
|
+
(o = i[r]) && (n = o(t, e, n) || n);
|
|
142
|
+
return n && bt(t, e, n), n;
|
|
143
|
+
};
|
|
144
|
+
const z = () => ({ status: "idle", mode: "ai", awaitingReply: !1, items: [], activeInteraction: null, interactionPending: !1, agent: null, error: null }), Z = { fromAttribute: (i) => i !== "false" };
|
|
145
|
+
var f;
|
|
146
|
+
const c = (f = class extends W {
|
|
147
|
+
constructor() {
|
|
148
|
+
super(...arguments), this.agentId = "", this.baseUrl = "", this.client = null, this.theme = {}, this.variants = {}, this.strings = {}, this.poweredBy = !0, this.newChat = !0, this.header = {}, this.closable = !1, this.chatState = z(), this.draft = "", this.busy = !1, this.typed = null, this.ownClient = null, this.boundClient = null, this.ownKey = "", this.generation = 0, this.followBottom = !0, this.focusedInteraction = null, this.send = () => {
|
|
149
|
+
if (this.blocked || !this.draft.trim() || !this.boundClient) return;
|
|
150
|
+
const t = this.boundClient, e = this.draft.trim(), s = this.typed;
|
|
151
|
+
this.draft = "", s && this.restoreDraft(), this.requestUpdate(), this.run(() => s ? t.respond(s.id, { kind: "text", value: e }) : t.send(e));
|
|
152
|
+
}, this.respond = (t) => {
|
|
153
|
+
const e = t.detail, s = this.chatState;
|
|
154
|
+
if (!e || this.busy || s.mode !== "ai" || s.interactionPending || s.activeInteraction?.interaction_status !== "pending" || e.interactionId !== s.activeInteraction.interaction_id) return;
|
|
155
|
+
t.stopPropagation();
|
|
156
|
+
const n = this.boundClient;
|
|
157
|
+
n && this.run(() => n.respond(e.interactionId, e.response));
|
|
158
|
+
}, this.requestInput = (t) => {
|
|
159
|
+
const e = t.detail, s = this.chatState;
|
|
160
|
+
!e || this.busy || s.mode !== "ai" || s.interactionPending || s.activeInteraction?.interaction_status !== "pending" || e.interactionId !== s.activeInteraction.interaction_id || (t.stopPropagation(), this.typed = { id: e.interactionId, placeholder: typeof e.placeholder == "string" ? e.placeholder : void 0, previousDraft: this.typed?.previousDraft ?? this.draft }, this.draft = "", this.requestUpdate(), this.updateComplete.then(() => this.renderRoot.querySelector("textarea")?.focus()));
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
connectedCallback() {
|
|
164
|
+
super.connectedCallback(), this.syncClient();
|
|
165
|
+
}
|
|
166
|
+
disconnectedCallback() {
|
|
167
|
+
super.disconnectedCallback(), this.releaseClient();
|
|
168
|
+
}
|
|
169
|
+
releaseClient() {
|
|
170
|
+
++this.generation, this.unsubscribe?.(), this.unsubscribe = void 0, this.boundClient = null;
|
|
171
|
+
const t = this.ownClient;
|
|
172
|
+
this.ownClient = null, this.ownKey = "", t?.destroy(), this.busy = !1, this.typed = null, this.focusedInteraction = null, this.requestUpdate();
|
|
173
|
+
}
|
|
174
|
+
syncClient() {
|
|
175
|
+
if (!this.isConnected || !this.client && !this.agentId && !this.boundClient) return;
|
|
176
|
+
const t = JSON.stringify([this.agentId, H(this.baseUrl)]);
|
|
177
|
+
if ((this.client ? this.boundClient === this.client && !this.ownClient : this.ownClient && t === this.ownKey) || (this.releaseClient(), this.chatState = z(), !this.client && !this.agentId)) return;
|
|
178
|
+
const e = !this.client, s = this.client ?? f.clientFactory({ agentId: this.agentId, baseUrl: H(this.baseUrl) });
|
|
179
|
+
this.boundClient = s, e && (this.ownClient = s, this.ownKey = t);
|
|
180
|
+
const n = this.generation;
|
|
181
|
+
this.chatState = s.getState(), this.requestUpdate(), this.unsubscribe = s.subscribe((r) => {
|
|
182
|
+
this.generation !== n || this.boundClient !== s || (this.chatState = r, this.requestUpdate(), this.typed && (r.mode === "human" || r.activeInteraction?.interaction_id !== this.typed.id || r.activeInteraction.interaction_status !== "pending") && this.restoreDraft());
|
|
183
|
+
}), e && this.run(() => s.start());
|
|
184
|
+
}
|
|
185
|
+
willUpdate() {
|
|
186
|
+
this.syncClient(), G(this, this.mergedTheme());
|
|
187
|
+
}
|
|
188
|
+
mergedTheme() {
|
|
189
|
+
const t = J("theme", this.themeAttribute), e = {}, s = t?.colors;
|
|
190
|
+
if (s && typeof s == "object" && !Array.isArray(s))
|
|
191
|
+
for (const o of ["primary", "background", "surface", "text", "userBubble", "assistantBubble"]) {
|
|
192
|
+
const u = s[o];
|
|
193
|
+
typeof u == "string" && (e[o] = u);
|
|
194
|
+
}
|
|
195
|
+
typeof this.primaryColor == "string" && (e.primary = this.primaryColor);
|
|
196
|
+
const n = K(this.radius) ?? (typeof t?.radius == "number" && Number.isInteger(t.radius) && t.radius >= 0 && t.radius <= 99 ? t.radius : typeof t?.radius == "string" ? K(t.radius) : void 0), r = y(this.mode, ["light", "dark"]) ?? y(typeof t?.mode == "string" ? t.mode : void 0, ["light", "dark"]);
|
|
197
|
+
return { ...this.theme, colors: { ...this.theme?.colors, ...e }, ...n === void 0 ? {} : { radius: n }, ...r === void 0 ? {} : { mode: r } };
|
|
198
|
+
}
|
|
199
|
+
get labels() {
|
|
200
|
+
const t = { ...N };
|
|
201
|
+
for (const e of [this.strings, J("strings", this.stringsAttribute)])
|
|
202
|
+
for (const s of Object.keys(N)) typeof e?.[s] == "string" && (t[s] = e[s]);
|
|
203
|
+
return t;
|
|
204
|
+
}
|
|
205
|
+
get blocked() {
|
|
206
|
+
const t = this.chatState;
|
|
207
|
+
return !this.boundClient || this.busy || t.status === "connecting" || t.status === "closed" && !!t.error && !t.error.retryable || t.mode === "ai" && (t.interactionPending || t.activeInteraction?.interaction_status === "pending" && !this.typed);
|
|
208
|
+
}
|
|
209
|
+
get sessionBusy() {
|
|
210
|
+
return this.busy || this.chatState.status === "connecting" || this.chatState.interactionPending || this.chatState.items.some((t) => t.kind === "message" && t.status === "sending");
|
|
211
|
+
}
|
|
212
|
+
async run(t) {
|
|
213
|
+
if (this.busy || !this.boundClient) return;
|
|
214
|
+
const e = this.generation;
|
|
215
|
+
this.busy = !0, this.requestUpdate();
|
|
216
|
+
try {
|
|
217
|
+
await t();
|
|
218
|
+
} catch {
|
|
219
|
+
} finally {
|
|
220
|
+
this.generation === e && (this.busy = !1, this.requestUpdate());
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
restoreDraft() {
|
|
224
|
+
this.typed && (this.draft = this.typed.previousDraft, this.typed = null, this.requestUpdate());
|
|
225
|
+
}
|
|
226
|
+
async focusActiveInteraction() {
|
|
227
|
+
if (await this.updateComplete, !this.isConnected || this.chatState.activeInteraction?.interaction_status !== "pending") return;
|
|
228
|
+
const t = this.renderRoot.querySelector('[data-live="true"]');
|
|
229
|
+
if (!t) return;
|
|
230
|
+
const e = this.chatState.activeInteraction.interaction_id;
|
|
231
|
+
await t.updateComplete, !(!this.isConnected || this.chatState.activeInteraction?.interaction_id !== e) && t.shadowRoot?.querySelector('button:not(:disabled),input:not(:disabled),select:not(:disabled),textarea:not(:disabled),[tabindex="0"]')?.focus();
|
|
232
|
+
}
|
|
233
|
+
updated() {
|
|
234
|
+
const t = this.renderRoot.querySelector(".transcript");
|
|
235
|
+
t && this.followBottom && (t.scrollTop = t.scrollHeight);
|
|
236
|
+
const e = this.chatState.activeInteraction?.interaction_status === "pending" ? this.chatState.activeInteraction.interaction_id : null;
|
|
237
|
+
e !== this.focusedInteraction && (this.focusedInteraction = e, e && this.isConnected && !this.hidden && document.visibilityState !== "hidden" && this.focusActiveInteraction());
|
|
238
|
+
}
|
|
239
|
+
statusText(t) {
|
|
240
|
+
const e = this.chatState;
|
|
241
|
+
return e.error?.code === "origin_not_allowed" ? t.originBlocked : e.error && ["agent_inactive", "agent_archived", "agent_not_found"].includes(e.error.code) ? t.unavailable : e.error?.code === "rate_limited" ? t.rateLimited : e.error?.code === "token_failed" ? e.error.message : e.status === "recovering" ? t.reconnecting : e.status === "offline" ? t.offline : e.interactionPending || this.busy && this.typed ? t.sending : e.activeInteraction?.interaction_status === "pending" ? e.mode === "human" ? t.pausedForHuman : this.typed ? t.typeAnswer : t.chooseOption : e.status === "closed" ? t.sessionEnded : "";
|
|
242
|
+
}
|
|
243
|
+
render() {
|
|
244
|
+
const t = this.labels, e = this.chatState, s = this.boundClient, n = dt(this.headerAvatar ?? this.header.avatarUrl), r = { ...this.variants, ...y(this.buttons, ["chips", "list"]) ? { buttons: y(this.buttons, ["chips", "list"]) } : {}, ...y(this.carousel, ["slider", "list"]) ? { carousel: y(this.carousel, ["slider", "list"]) } : {} };
|
|
245
|
+
return a`<header>${n ? a`<img src=${n} alt="" referrerpolicy="no-referrer">` : d}<div class="heading"><h2>${this.headerTitle ?? this.header.title ?? e.agent?.name ?? t.defaultTitle}</h2>${this.headerSubtitle ?? this.header.subtitle ? a`<p>${this.headerSubtitle ?? this.header.subtitle}</p>` : d}${e.mode === "human" ? a`<small>${t.humanJoined}</small>` : d}</div>
|
|
246
|
+
${this.newChat ? a`<button type="button" ?disabled=${!s || this.sessionBusy} @click=${() => s && !this.sessionBusy && void this.run(() => s.newSession())}>${t.newChat}</button>` : d}
|
|
247
|
+
${this.closable ? a`<button type="button" aria-label=${t.closeChat} @click=${() => this.dispatchEvent(new CustomEvent("osvi-close", { bubbles: !0, composed: !0 }))}>×</button>` : d}</header>
|
|
248
|
+
<div class="transcript" role="log" aria-live="polite" aria-label="Conversation" @scroll=${(o) => {
|
|
249
|
+
const u = o.currentTarget;
|
|
250
|
+
this.followBottom = u.scrollHeight - u.scrollTop - u.clientHeight <= 80;
|
|
251
|
+
}} @osvi-respond=${this.respond} @osvi-request-input=${this.requestInput}>${pt(e, t, r, s?.resolveUrl("") ?? "", (o) => {
|
|
252
|
+
s && this.run(() => s.retry(o));
|
|
253
|
+
})}</div>
|
|
254
|
+
<div class="status" role="status">${this.statusText(t)}${e.error?.retryable && (e.status === "idle" || e.status === "closed") ? a`<button type="button" ?disabled=${this.busy || !s} @click=${() => s && void this.run(() => s.start())}>${t.tryAgain}</button>` : d}</div>
|
|
255
|
+
${ft({ strings: t, draft: this.draft, placeholder: this.typed?.placeholder ?? t.placeholder, disabled: this.blocked, input: (o) => {
|
|
256
|
+
this.draft = o.target.value, this.requestUpdate();
|
|
257
|
+
}, send: this.send })}
|
|
258
|
+
${this.poweredBy ? a`<footer><a href="https://osvi.ai" target="_blank" rel="noopener noreferrer">${t.poweredBy}</a></footer>` : d}`;
|
|
259
|
+
}
|
|
260
|
+
}, f.clientFactory = et, f.properties = { themeAttribute: { attribute: "theme" }, stringsAttribute: { attribute: "strings" } }, f.styles = X`
|
|
261
|
+
:host { display:flex; flex-direction:column; height:100%; min-height:260px; color:var(--osvi-color-text,#18181b); background:var(--osvi-color-background,#fff); font:14px/1.5 system-ui,sans-serif; border-radius:var(--osvi-radius,10px); overflow:hidden; }
|
|
262
|
+
header { display:flex; align-items:center; gap:10px; padding:14px; border-bottom:1px solid var(--osvi-color-surface,#f4f4f5); } header img { width:36px; height:36px; border-radius:50%; } .heading { flex:1; } h2,p { margin:0; } h2 { font-size:16px; } small { display:block; }
|
|
263
|
+
.transcript { flex:1; overflow:auto; padding:16px; min-height:0; } .bubble { width:fit-content; max-width:85%; padding:10px 14px; margin:8px 0; border-radius:var(--osvi-radius,10px); background:var(--osvi-color-assistant-bubble,#f4f4f5); overflow-wrap:anywhere; white-space:pre-wrap; } .user { margin-left:auto; color:#fff; background:var(--osvi-color-user-bubble,#4f46e5); } .bubble a { color:inherit; } .divider { text-align:center; } .status { padding:0 14px; } .composer { display:flex; gap:8px; padding:14px; } textarea { flex:1; resize:vertical; min-width:0; } button,textarea { font:inherit; } button { cursor:pointer; } button:disabled { cursor:default; } footer { padding:0 14px 10px; text-align:center; } footer a { color:inherit; } osvi-buttons,osvi-carousel,osvi-date-picker { display:block; margin:8px 0; }
|
|
264
|
+
`, f);
|
|
265
|
+
h([
|
|
266
|
+
l({ attribute: "agent-id" })
|
|
267
|
+
], c.prototype, "agentId");
|
|
268
|
+
h([
|
|
269
|
+
l({ attribute: "base-url" })
|
|
270
|
+
], c.prototype, "baseUrl");
|
|
271
|
+
h([
|
|
272
|
+
l({ attribute: !1 })
|
|
273
|
+
], c.prototype, "client");
|
|
274
|
+
h([
|
|
275
|
+
l({ attribute: !1 })
|
|
276
|
+
], c.prototype, "theme");
|
|
277
|
+
h([
|
|
278
|
+
l({ attribute: !1 })
|
|
279
|
+
], c.prototype, "variants");
|
|
280
|
+
h([
|
|
281
|
+
l({ attribute: !1 })
|
|
282
|
+
], c.prototype, "strings");
|
|
283
|
+
h([
|
|
284
|
+
l({ attribute: "powered-by", converter: Z })
|
|
285
|
+
], c.prototype, "poweredBy");
|
|
286
|
+
h([
|
|
287
|
+
l({ attribute: "new-chat", converter: Z })
|
|
288
|
+
], c.prototype, "newChat");
|
|
289
|
+
h([
|
|
290
|
+
l({ attribute: !1 })
|
|
291
|
+
], c.prototype, "header");
|
|
292
|
+
h([
|
|
293
|
+
l({ type: Boolean })
|
|
294
|
+
], c.prototype, "closable");
|
|
295
|
+
h([
|
|
296
|
+
l({ attribute: "header-title" })
|
|
297
|
+
], c.prototype, "headerTitle");
|
|
298
|
+
h([
|
|
299
|
+
l({ attribute: "header-subtitle" })
|
|
300
|
+
], c.prototype, "headerSubtitle");
|
|
301
|
+
h([
|
|
302
|
+
l({ attribute: "header-avatar" })
|
|
303
|
+
], c.prototype, "headerAvatar");
|
|
304
|
+
h([
|
|
305
|
+
l({ attribute: "primary-color" })
|
|
306
|
+
], c.prototype, "primaryColor");
|
|
307
|
+
h([
|
|
308
|
+
l()
|
|
309
|
+
], c.prototype, "radius");
|
|
310
|
+
h([
|
|
311
|
+
l()
|
|
312
|
+
], c.prototype, "mode");
|
|
313
|
+
h([
|
|
314
|
+
l()
|
|
315
|
+
], c.prototype, "buttons");
|
|
316
|
+
h([
|
|
317
|
+
l()
|
|
318
|
+
], c.prototype, "carousel");
|
|
319
|
+
h([
|
|
320
|
+
b()
|
|
321
|
+
], c.prototype, "chatState");
|
|
322
|
+
h([
|
|
323
|
+
b()
|
|
324
|
+
], c.prototype, "draft");
|
|
325
|
+
h([
|
|
326
|
+
b()
|
|
327
|
+
], c.prototype, "busy");
|
|
328
|
+
h([
|
|
329
|
+
b()
|
|
330
|
+
], c.prototype, "typed");
|
|
331
|
+
let vt = c;
|
|
332
|
+
function A(i, t) {
|
|
333
|
+
typeof customElements > "u" || customElements.get(i) || customElements.define(i, t);
|
|
334
|
+
}
|
|
335
|
+
const B = X`
|
|
336
|
+
:host { display: block; font: inherit; color: ${x(w("text"))}; background: ${x(w("background"))}; }
|
|
337
|
+
* { box-sizing: border-box; }
|
|
338
|
+
button { font: inherit; color: inherit; background: ${x(w("surface"))}; border: 1px solid currentColor; border-radius: var(--osvi-radius, 10px); padding: 10px 14px; cursor: pointer; }
|
|
339
|
+
button:focus-visible { outline: 3px solid ${x(w("primary"))}; outline-offset: 3px; }
|
|
340
|
+
button:disabled { opacity: .5; cursor: default; }
|
|
341
|
+
button[aria-pressed="true"] { outline: 2px solid ${x(w("primary"))}; }
|
|
342
|
+
small { display: block; }
|
|
343
|
+
.chips { display: flex; flex-wrap: wrap; gap: 8px; }
|
|
344
|
+
.list { display: grid; gap: 6px; }
|
|
345
|
+
.list button { width: 100%; text-align: left; }
|
|
346
|
+
.card { background: ${x(w("surface"))}; border-radius: var(--osvi-radius, 10px); padding: 12px; }
|
|
347
|
+
.image { aspect-ratio: 16 / 9; display: grid; place-items: center; overflow: hidden; }
|
|
348
|
+
.image img { width: 100%; height: 100%; object-fit: cover; }
|
|
349
|
+
.navigation { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin: 10px 0; }
|
|
350
|
+
.days, .weekdays { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 4px; text-align: center; }
|
|
351
|
+
.days button { padding: 8px 0; }
|
|
352
|
+
`;
|
|
353
|
+
var yt = Object.defineProperty, P = (i, t, e, s) => {
|
|
354
|
+
for (var n = void 0, r = i.length - 1, o; r >= 0; r--)
|
|
355
|
+
(o = i[r]) && (n = o(t, e, n) || n);
|
|
356
|
+
return n && yt(t, e, n), n;
|
|
357
|
+
};
|
|
358
|
+
class m extends W {
|
|
359
|
+
constructor() {
|
|
360
|
+
super(...arguments), this.interaction = null, this.disabled = !1, this.baseUrl = "";
|
|
361
|
+
}
|
|
362
|
+
get live() {
|
|
363
|
+
return !this.disabled && this.interaction?.interaction_status === "pending";
|
|
364
|
+
}
|
|
365
|
+
get valid() {
|
|
366
|
+
const t = this.interaction;
|
|
367
|
+
return !!t && t.tool_type === this.toolType && it(t, t.presentation);
|
|
368
|
+
}
|
|
369
|
+
respond(t) {
|
|
370
|
+
!this.interaction || !this.live || !this.valid || this.dispatchEvent(new CustomEvent("osvi-respond", { bubbles: !0, composed: !0, detail: { interactionId: this.interaction.interaction_id, response: t } }));
|
|
371
|
+
}
|
|
372
|
+
updated(t) {
|
|
373
|
+
t.has("theme") && G(this, this.theme);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
P([
|
|
377
|
+
l({ attribute: !1 })
|
|
378
|
+
], m.prototype, "interaction");
|
|
379
|
+
P([
|
|
380
|
+
l({ type: Boolean })
|
|
381
|
+
], m.prototype, "disabled");
|
|
382
|
+
P([
|
|
383
|
+
l({ attribute: !1 })
|
|
384
|
+
], m.prototype, "theme");
|
|
385
|
+
P([
|
|
386
|
+
l({ attribute: "base-url" })
|
|
387
|
+
], m.prototype, "baseUrl");
|
|
388
|
+
var gt = Object.defineProperty, mt = (i, t, e, s) => {
|
|
389
|
+
for (var n = void 0, r = i.length - 1, o; r >= 0; r--)
|
|
390
|
+
(o = i[r]) && (n = o(t, e, n) || n);
|
|
391
|
+
return n && gt(t, e, n), n;
|
|
392
|
+
};
|
|
393
|
+
const E = class E extends m {
|
|
394
|
+
constructor() {
|
|
395
|
+
super(...arguments), this.toolType = "ui_buttons", this.variant = "chips";
|
|
396
|
+
}
|
|
397
|
+
render() {
|
|
398
|
+
const t = this.interaction;
|
|
399
|
+
if (!t) return d;
|
|
400
|
+
if (!this.valid) return a`<p>${t.content}</p>`;
|
|
401
|
+
const e = t.presentation, s = t.response_payload?.kind === "text" ? t.response_payload.value : e.options.find((n) => n.id === (t.response_payload?.kind === "selection" ? t.response_payload.value : t.selected_option_id))?.label;
|
|
402
|
+
return a`<p>${e.label}</p>${e.description ? a`<p>${e.description}</p>` : d}
|
|
403
|
+
${this.live ? a`<div role="group" aria-label="Options" class=${this.variant} @keydown=${this.onKey}>
|
|
404
|
+
${e.options.map((n) => a`<button type="button" @click=${() => this.pick(n.id, n.allow_input, n.input_placeholder)}><span>${n.label}</span>${n.description ? a`<small>${n.description}</small>` : d}</button>`)}
|
|
405
|
+
</div>` : s ? a`<p>${s}</p>` : d}`;
|
|
406
|
+
}
|
|
407
|
+
pick(t, e, s) {
|
|
408
|
+
!this.live || !this.valid || !this.interaction || (this.interaction.schema_version === 2 && e ? this.dispatchEvent(new CustomEvent("osvi-request-input", { bubbles: !0, composed: !0, detail: { interactionId: this.interaction.interaction_id, placeholder: s } })) : this.respond({ kind: "selection", value: t }));
|
|
409
|
+
}
|
|
410
|
+
onKey(t) {
|
|
411
|
+
if (!["ArrowDown", "ArrowUp", "ArrowRight", "ArrowLeft"].includes(t.key)) return;
|
|
412
|
+
const e = [...this.renderRoot.querySelectorAll("button")], s = e.indexOf(this.renderRoot.activeElement), n = t.key === "ArrowDown" || t.key === "ArrowRight" ? 1 : -1;
|
|
413
|
+
e[(s + n + e.length) % e.length]?.focus(), t.preventDefault();
|
|
414
|
+
}
|
|
415
|
+
};
|
|
416
|
+
E.styles = B;
|
|
417
|
+
let I = E;
|
|
418
|
+
mt([
|
|
419
|
+
l()
|
|
420
|
+
], I.prototype, "variant");
|
|
421
|
+
var $t = Object.defineProperty, q = (i, t, e, s) => {
|
|
422
|
+
for (var n = void 0, r = i.length - 1, o; r >= 0; r--)
|
|
423
|
+
(o = i[r]) && (n = o(t, e, n) || n);
|
|
424
|
+
return n && $t(t, e, n), n;
|
|
425
|
+
};
|
|
426
|
+
const O = class O extends m {
|
|
427
|
+
constructor() {
|
|
428
|
+
super(...arguments), this.toolType = "ui_carousel", this.variant = "slider", this.index = 0, this.imageFailed = /* @__PURE__ */ new Set(), this.suppressPointerClick = !1;
|
|
429
|
+
}
|
|
430
|
+
willUpdate(t) {
|
|
431
|
+
t.has("interaction") && (this.index = 0, this.imageFailed = /* @__PURE__ */ new Set(), this.pointerStart = void 0, this.suppressPointerClick = !1);
|
|
432
|
+
}
|
|
433
|
+
render() {
|
|
434
|
+
const t = this.interaction;
|
|
435
|
+
if (!t) return d;
|
|
436
|
+
if (!this.valid) return a`<p>${t.content}</p>`;
|
|
437
|
+
const e = t.presentation, s = e.items.find((n) => n.id === (t.response_payload?.kind === "selection" ? t.response_payload.value : t.selected_option_id));
|
|
438
|
+
return a`<p>${e.label}</p>${e.description ? a`<p>${e.description}</p>` : d}
|
|
439
|
+
${this.live ? this.variant === "list" ? a`<div class="list">${e.items.map((n, r) => this.card(n, r))}</div>` : a`<div @pointerdown=${(n) => {
|
|
440
|
+
this.pointerStart = n.clientX, this.suppressPointerClick = !1;
|
|
441
|
+
}} @pointerup=${(n) => {
|
|
442
|
+
this.pointerStart !== void 0 && Math.abs(n.clientX - this.pointerStart) > 40 && (this.suppressPointerClick = !0, this.navigate(n.clientX < this.pointerStart ? 1 : -1, e.items.length)), this.pointerStart = void 0;
|
|
443
|
+
}} @pointercancel=${() => {
|
|
444
|
+
this.pointerStart = void 0;
|
|
445
|
+
}}>${this.card(e.items[this.index], this.index)}</div>
|
|
446
|
+
<div class="navigation"><button type="button" aria-label="Previous card" ?disabled=${this.index === 0} @click=${() => this.navigate(-1, e.items.length)}>Previous</button>
|
|
447
|
+
<span aria-live="polite">${this.index + 1} of ${e.items.length}</span>
|
|
448
|
+
<button type="button" aria-label="Next card" ?disabled=${this.index === e.items.length - 1} @click=${() => this.navigate(1, e.items.length)}>Next</button></div>` : s ? a`<p>${s.title}</p>` : d}`;
|
|
449
|
+
}
|
|
450
|
+
navigate(t, e) {
|
|
451
|
+
this.index = Math.max(0, Math.min(e - 1, this.index + t));
|
|
452
|
+
}
|
|
453
|
+
select(t, e) {
|
|
454
|
+
if (this.suppressPointerClick && t.detail !== 0) {
|
|
455
|
+
this.suppressPointerClick = !1, t.preventDefault(), t.stopPropagation();
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
458
|
+
this.respond({ kind: "selection", value: e });
|
|
459
|
+
}
|
|
460
|
+
card(t, e) {
|
|
461
|
+
const s = t.image;
|
|
462
|
+
return a`<article class="card">${s && st(s.url) ? a`<div class="image">${this.imageFailed.has(e) ? a`<span role="img" aria-label="Image unavailable">Image unavailable</span>` : a`<img src=${this.baseUrl.replace(/\/$/, "") + s.url} alt=${s.alt} referrerpolicy="no-referrer" loading="lazy" @error=${() => {
|
|
463
|
+
this.imageFailed = /* @__PURE__ */ new Set([...this.imageFailed, e]);
|
|
464
|
+
}}>`}</div>` : d}
|
|
465
|
+
<h3>${t.title}</h3>${t.description ? a`<p>${t.description}</p>` : d}
|
|
466
|
+
<button type="button" @click=${(n) => this.select(n, t.id)}>${t.action_label ?? "Select"}</button></article>`;
|
|
467
|
+
}
|
|
468
|
+
};
|
|
469
|
+
O.styles = B;
|
|
470
|
+
let k = O;
|
|
471
|
+
q([
|
|
472
|
+
l()
|
|
473
|
+
], k.prototype, "variant");
|
|
474
|
+
q([
|
|
475
|
+
b()
|
|
476
|
+
], k.prototype, "index");
|
|
477
|
+
q([
|
|
478
|
+
b()
|
|
479
|
+
], k.prototype, "imageFailed");
|
|
480
|
+
var xt = Object.defineProperty, T = (i, t, e, s) => {
|
|
481
|
+
for (var n = void 0, r = i.length - 1, o; r >= 0; r--)
|
|
482
|
+
(o = i[r]) && (n = o(t, e, n) || n);
|
|
483
|
+
return n && xt(t, e, n), n;
|
|
484
|
+
};
|
|
485
|
+
const tt = (i) => `${String(i.getFullYear()).padStart(4, "0")}-${String(i.getMonth() + 1).padStart(2, "0")}-${String(i.getDate()).padStart(2, "0")}`, D = () => tt(/* @__PURE__ */ new Date()), V = (i) => {
|
|
486
|
+
const t = /* @__PURE__ */ new Date(0);
|
|
487
|
+
return t.setHours(0, 0, 0, 0), t.setFullYear(Number(i.slice(0, 4)), Number(i.slice(5, 7)) - 1, Number(i.slice(8, 10))), t;
|
|
488
|
+
}, v = (i) => i.slice(0, 7), j = class j extends m {
|
|
489
|
+
constructor() {
|
|
490
|
+
super(...arguments), this.toolType = "ui_date_picker", this.variant = "grid", this.month = v(D()), this.start = "", this.end = "";
|
|
491
|
+
}
|
|
492
|
+
earliest(t) {
|
|
493
|
+
return t.min_date && t.min_date > D() ? t.min_date : D();
|
|
494
|
+
}
|
|
495
|
+
willUpdate(t) {
|
|
496
|
+
t.has("interaction") && (this.start = "", this.end = "", this.valid && (this.month = v(this.earliest(this.interaction.presentation))));
|
|
497
|
+
}
|
|
498
|
+
render() {
|
|
499
|
+
const t = this.interaction;
|
|
500
|
+
if (!t) return d;
|
|
501
|
+
if (!this.valid) return a`<p>${t.content}</p>`;
|
|
502
|
+
const e = t.presentation, s = t.response_payload, n = s?.kind === "date_range" ? `${s.value.start_date} – ${s.value.end_date}` : s?.kind === "date" || s?.kind === "text" ? s.value : t.selected_option_id;
|
|
503
|
+
if (!this.live) return a`<p>${e.label}</p>${e.description ? a`<p>${e.description}</p>` : d}${n ? a`<p>${n}</p>` : d}`;
|
|
504
|
+
const r = V(`${this.month}-01`), o = new Date(r);
|
|
505
|
+
o.setMonth(o.getMonth() + 1, 0);
|
|
506
|
+
const u = this.earliest(e), _ = Array.from({ length: o.getDate() }, (p, U) => `${this.month}-${String(U + 1).padStart(2, "0")}`), $ = e.selection_mode === "range" ? this.start ? this.end ? `${this.start} – ${this.end}` : `Check-in: ${this.start}. Choose check-out.` : "Choose check-in, then check-out." : this.start;
|
|
507
|
+
return a`<p>${e.label}</p>${e.description ? a`<p>${e.description}</p>` : d}
|
|
508
|
+
<div class="navigation"><button type="button" aria-label="Previous month" ?disabled=${this.month <= v(u)} @click=${() => this.moveMonth(-1, e)}>Previous</button>
|
|
509
|
+
<span aria-live="polite">${r.toLocaleDateString(void 0, { month: "long", year: "numeric" })}</span>
|
|
510
|
+
<button type="button" aria-label="Next month" ?disabled=${!!e.max_date && this.month >= v(e.max_date)} @click=${() => this.moveMonth(1, e)}>Next</button></div>
|
|
511
|
+
<div class="weekdays" aria-hidden="true">${["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"].map((p) => a`<span>${p}</span>`)}</div>
|
|
512
|
+
<div class="days" role="group" aria-label="Choose date" @keydown=${this.onKey}>
|
|
513
|
+
${Array.from({ length: r.getDay() }, () => a`<span></span>`)}
|
|
514
|
+
${_.map((p, U) => a`<button type="button" aria-label=${p} aria-pressed=${p === this.start || p === this.end} ?disabled=${p < u || !!e.max_date && p > e.max_date} @click=${() => this.pick(p, e)}>${U + 1}</button>`)}
|
|
515
|
+
</div><p aria-live="polite">${$}</p>
|
|
516
|
+
<button type="button" ?disabled=${!this.start || e.selection_mode === "range" && (!this.end || this.start >= this.end)} @click=${() => this.confirm(e)}>${e.confirm_label ?? "Confirm date"}</button>`;
|
|
517
|
+
}
|
|
518
|
+
moveMonth(t, e) {
|
|
519
|
+
const s = V(`${this.month}-01`);
|
|
520
|
+
s.setMonth(s.getMonth() + t);
|
|
521
|
+
const n = v(tt(s));
|
|
522
|
+
n >= v(this.earliest(e)) && (!e.max_date || n <= v(e.max_date)) && (this.month = n);
|
|
523
|
+
}
|
|
524
|
+
pick(t, e) {
|
|
525
|
+
!this.live || !this.valid || !R(t) || t < this.earliest(e) || e.max_date && t > e.max_date || (e.selection_mode === "single" || !this.start || this.end || t <= this.start ? (this.start = t, this.end = "") : this.end = t);
|
|
526
|
+
}
|
|
527
|
+
confirm(t) {
|
|
528
|
+
!R(this.start) || this.start < this.earliest(t) || t.max_date && this.start > t.max_date || (t.selection_mode === "single" ? this.respond({ kind: "date", value: this.start }) : R(this.end) && this.start < this.end && (!t.max_date || this.end <= t.max_date) && this.respond({ kind: "date_range", value: { start_date: this.start, end_date: this.end } }));
|
|
529
|
+
}
|
|
530
|
+
onKey(t) {
|
|
531
|
+
const s = { ArrowLeft: -1, ArrowRight: 1, ArrowUp: -7, ArrowDown: 7 }[t.key];
|
|
532
|
+
if (s === void 0) return;
|
|
533
|
+
const n = [...this.renderRoot.querySelectorAll(".days button")], r = n.indexOf(this.renderRoot.activeElement);
|
|
534
|
+
if (r < 0) return;
|
|
535
|
+
let o = r + s;
|
|
536
|
+
for (; o >= 0 && o < n.length && n[o]?.disabled; ) o += s > 0 ? 1 : -1;
|
|
537
|
+
n[o]?.focus(), t.preventDefault();
|
|
538
|
+
}
|
|
539
|
+
};
|
|
540
|
+
j.styles = B;
|
|
541
|
+
let g = j;
|
|
542
|
+
T([
|
|
543
|
+
l()
|
|
544
|
+
], g.prototype, "variant");
|
|
545
|
+
T([
|
|
546
|
+
b()
|
|
547
|
+
], g.prototype, "month");
|
|
548
|
+
T([
|
|
549
|
+
b()
|
|
550
|
+
], g.prototype, "start");
|
|
551
|
+
T([
|
|
552
|
+
b()
|
|
553
|
+
], g.prototype, "end");
|
|
554
|
+
A("osvi-chat", vt);
|
|
555
|
+
A("osvi-buttons", I);
|
|
556
|
+
A("osvi-carousel", k);
|
|
557
|
+
A("osvi-date-picker", g);
|
|
558
|
+
export {
|
|
559
|
+
N as DEFAULT_STRINGS,
|
|
560
|
+
I as OsviButtons,
|
|
561
|
+
k as OsviCarousel,
|
|
562
|
+
vt as OsviChat,
|
|
563
|
+
g as OsviDatePicker,
|
|
564
|
+
G as applyTheme,
|
|
565
|
+
w as cssVar,
|
|
566
|
+
A as defineOnce,
|
|
567
|
+
lt as explicitThemeVariables,
|
|
568
|
+
F as themeVariables
|
|
569
|
+
};
|
|
570
|
+
//# sourceMappingURL=ui.mjs.map
|