claudius-chat-widget 1.8.2 → 1.9.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/claudius.js CHANGED
@@ -1,8 +1,8 @@
1
- var ye = Object.defineProperty;
2
- var we = (t, e, r) => e in t ? ye(t, e, { enumerable: !0, configurable: !0, writable: !0, value: r }) : t[e] = r;
3
- var $ = (t, e, r) => we(t, typeof e != "symbol" ? e + "" : e, r);
4
- import { jsx as i, jsxs as d, Fragment as ve } from "react/jsx-runtime";
5
- import { useMemo as F, useState as C, useRef as N, useCallback as R, useEffect as k, forwardRef as Ee, memo as K, useId as Re } from "react";
1
+ var Ee = Object.defineProperty;
2
+ var Re = (e, t, r) => t in e ? Ee(e, t, { enumerable: !0, configurable: !0, writable: !0, value: r }) : e[t] = r;
3
+ var G = (e, t, r) => Re(e, typeof t != "symbol" ? t + "" : t, r);
4
+ import { jsx as i, jsxs as h, Fragment as Te } from "react/jsx-runtime";
5
+ import { useMemo as Y, useState as k, useRef as C, useCallback as M, useEffect as H, forwardRef as Me, memo as J, useId as Ce } from "react";
6
6
  class U extends Error {
7
7
  /**
8
8
  * Create a {@link ChatApiError}.
@@ -12,31 +12,31 @@ class U extends Error {
12
12
  * @param code - Optional machine-readable error code (e.g. `"TIMEOUT"`, `"NETWORK_ERROR"`).
13
13
  * @param retryAfter - Seconds to wait before retrying, from the `Retry-After` header.
14
14
  */
15
- constructor(e, r, s, n) {
16
- super(e), this.status = r, this.code = s, this.retryAfter = n, this.name = "ChatApiError";
15
+ constructor(t, r, s, n) {
16
+ super(t), this.status = r, this.code = s, this.retryAfter = n, this.name = "ChatApiError";
17
17
  }
18
18
  }
19
- class se extends Error {
19
+ class ae extends Error {
20
20
  /** Creates a `DebounceError` with a fixed message. */
21
21
  constructor() {
22
22
  super("Request debounced"), this.name = "DebounceError";
23
23
  }
24
24
  }
25
- const Te = 3e4;
26
- class Me {
25
+ const Ne = 3e4;
26
+ class Se {
27
27
  /**
28
28
  * Create a chat client for the given Worker base URL.
29
29
  *
30
30
  * @param baseUrl - Base URL of the Worker. Requests post to `${baseUrl}/api/chat`.
31
31
  * @param options - Optional retry, debounce, and timeout settings.
32
32
  */
33
- constructor(e, r) {
34
- $(this, "baseUrl");
35
- $(this, "maxRetries");
36
- $(this, "debounceMs");
37
- $(this, "timeoutMs");
38
- $(this, "lastSendTime", 0);
39
- this.baseUrl = e, this.maxRetries = (r == null ? void 0 : r.maxRetries) ?? 2, this.debounceMs = (r == null ? void 0 : r.debounceMs) ?? 300, this.timeoutMs = (r == null ? void 0 : r.timeoutMs) ?? Te;
33
+ constructor(t, r) {
34
+ G(this, "baseUrl");
35
+ G(this, "maxRetries");
36
+ G(this, "debounceMs");
37
+ G(this, "timeoutMs");
38
+ G(this, "lastSendTime", 0);
39
+ this.baseUrl = t, this.maxRetries = (r == null ? void 0 : r.maxRetries) ?? 2, this.debounceMs = (r == null ? void 0 : r.debounceMs) ?? 300, this.timeoutMs = (r == null ? void 0 : r.timeoutMs) ?? Ne;
40
40
  }
41
41
  /**
42
42
  * Send the conversation to the chat endpoint and return the assistant's
@@ -48,27 +48,27 @@ class Me {
48
48
  * @throws {@link DebounceError} when called within the debounce window.
49
49
  * @throws {@link ChatApiError} when the request fails after all retries.
50
50
  */
51
- async sendMessage(e) {
51
+ async sendMessage(t) {
52
52
  if (this.debounceMs > 0 && Date.now() - this.lastSendTime < this.debounceMs)
53
- throw new se();
53
+ throw new ae();
54
54
  this.lastSendTime = Date.now();
55
55
  let r;
56
56
  for (let s = 0; s <= this.maxRetries; s++)
57
57
  try {
58
- const n = await this.fetchWithTimeout(e);
58
+ const n = await this.fetchWithTimeout(t);
59
59
  if (n.ok)
60
60
  return await n.json();
61
- const o = await n.json().catch(() => ({})), a = n.headers.get("Retry-After"), l = a ? Number(a) : void 0;
61
+ const o = await n.json().catch(() => ({})), c = n.headers.get("Retry-After"), a = c ? Number(c) : void 0;
62
62
  if (r = new U(
63
63
  o.error ?? `Request failed with status ${n.status}`,
64
64
  n.status,
65
65
  o.code,
66
- l
66
+ a
67
67
  ), !this.isRetryable(n.status))
68
68
  throw r;
69
69
  if (s < this.maxRetries) {
70
- const c = this.getRetryDelay(n, s);
71
- await this.delay(c);
70
+ const u = this.getRetryDelay(n, s);
71
+ await this.delay(u);
72
72
  }
73
73
  } catch (n) {
74
74
  if (n instanceof U) {
@@ -89,19 +89,19 @@ class Me {
89
89
  }
90
90
  throw r;
91
91
  }
92
- async fetchWithTimeout(e) {
92
+ async fetchWithTimeout(t) {
93
93
  if (this.timeoutMs <= 0)
94
94
  return fetch(`${this.baseUrl}/api/chat`, {
95
95
  method: "POST",
96
96
  headers: { "Content-Type": "application/json" },
97
- body: JSON.stringify({ messages: e })
97
+ body: JSON.stringify({ messages: t })
98
98
  });
99
99
  const r = new AbortController(), s = setTimeout(() => r.abort(), this.timeoutMs);
100
100
  try {
101
101
  return await fetch(`${this.baseUrl}/api/chat`, {
102
102
  method: "POST",
103
103
  headers: { "Content-Type": "application/json" },
104
- body: JSON.stringify({ messages: e }),
104
+ body: JSON.stringify({ messages: t }),
105
105
  signal: r.signal
106
106
  });
107
107
  } catch (n) {
@@ -114,12 +114,12 @@ class Me {
114
114
  clearTimeout(s);
115
115
  }
116
116
  }
117
- isRetryable(e, r) {
118
- return r === "TIMEOUT" || r === "NETWORK_ERROR" ? !0 : e === 429 || e === 503;
117
+ isRetryable(t, r) {
118
+ return r === "TIMEOUT" || r === "NETWORK_ERROR" ? !0 : t === 429 || t === 503;
119
119
  }
120
- getRetryDelay(e, r) {
121
- if (e && e.status === 429) {
122
- const s = e.headers.get("Retry-After");
120
+ getRetryDelay(t, r) {
121
+ if (t && t.status === 429) {
122
+ const s = t.headers.get("Retry-After");
123
123
  if (s) {
124
124
  const n = Number(s);
125
125
  return Math.min(n * 1e3, 6e4);
@@ -127,32 +127,96 @@ class Me {
127
127
  }
128
128
  return r === 0 ? 1e3 : 3e3;
129
129
  }
130
- delay(e) {
131
- return new Promise((r) => setTimeout(r, e));
130
+ delay(t) {
131
+ return new Promise((r) => setTimeout(r, t));
132
132
  }
133
133
  }
134
- const Ce = 200, Ne = "claudius:messages";
135
- function Le(t, e) {
134
+ function ue(e) {
135
+ return typeof e == "string" ? { content: e } : e;
136
+ }
137
+ function Q(e, t, r) {
138
+ console.error(`[claudius] plugin "${e.name}" failed in ${t}:`, r);
139
+ }
140
+ async function Le(e, t, r) {
141
+ let s = t;
142
+ for (const n of e) {
143
+ if (!n.onBeforeSend) continue;
144
+ let o = null;
145
+ const c = {
146
+ ...r,
147
+ respondWith(a) {
148
+ o = {
149
+ type: "respond",
150
+ message: s,
151
+ reply: ue(a)
152
+ };
153
+ },
154
+ abort(a) {
155
+ o = { type: "abort", reason: a };
156
+ }
157
+ };
158
+ try {
159
+ const a = await n.onBeforeSend(s, c);
160
+ if (o) return o;
161
+ a && (s = a);
162
+ } catch (a) {
163
+ Q(n, "onBeforeSend", a);
164
+ }
165
+ }
166
+ return { type: "send", message: s };
167
+ }
168
+ async function ke(e, t, r) {
169
+ let s = t;
170
+ for (const n of e)
171
+ if (n.onAfterReceive)
172
+ try {
173
+ const o = await n.onAfterReceive(s, r);
174
+ o && (s = o);
175
+ } catch (o) {
176
+ Q(n, "onAfterReceive", o);
177
+ }
178
+ return s;
179
+ }
180
+ async function Ae(e, t, r) {
181
+ for (const s of e) {
182
+ if (!s.onError) continue;
183
+ let n = null;
184
+ const o = {
185
+ ...r,
186
+ respondWith(c) {
187
+ n = ue(c);
188
+ }
189
+ };
190
+ try {
191
+ if (await s.onError(t, o), n) return n;
192
+ } catch (c) {
193
+ Q(s, "onError", c);
194
+ }
195
+ }
196
+ return null;
197
+ }
198
+ const Oe = 200, Ie = "claudius:messages";
199
+ function De(e, t) {
136
200
  let r;
137
201
  try {
138
- r = new URL(e).host;
202
+ r = new URL(t).host;
139
203
  } catch {
140
- r = e;
204
+ r = t;
141
205
  }
142
- return `${t}:${r}`;
206
+ return `${e}:${r}`;
143
207
  }
144
- function V() {
208
+ function Z() {
145
209
  try {
146
210
  return typeof sessionStorage < "u" ? sessionStorage : null;
147
211
  } catch {
148
212
  return null;
149
213
  }
150
214
  }
151
- function Se(t) {
152
- const e = V();
153
- if (!e) return [];
215
+ function _e(e) {
216
+ const t = Z();
217
+ if (!t) return [];
154
218
  try {
155
- const r = e.getItem(t);
219
+ const r = t.getItem(e);
156
220
  if (!r) return [];
157
221
  const s = JSON.parse(r);
158
222
  return Array.isArray(s) ? s : [];
@@ -160,189 +224,246 @@ function Se(t) {
160
224
  return [];
161
225
  }
162
226
  }
163
- function ke({
164
- apiUrl: t,
165
- persistMessages: e = !0,
166
- storageKeyPrefix: r = Ne,
227
+ function He({
228
+ apiUrl: e,
229
+ persistMessages: t = !0,
230
+ storageKeyPrefix: r = Ie,
167
231
  timeoutMs: s,
168
- translations: n
232
+ translations: n,
233
+ plugins: o
169
234
  }) {
170
- const o = F(
171
- () => new Me(t, { debounceMs: 0, timeoutMs: s }),
172
- [t, s]
173
- ), a = Le(r, t), l = e ? Se(a) : [], [c, u] = C(l), [h, E] = C(!1), [g, x] = C(null), [f, w] = C(!1), v = N(l.length), y = N(!1), T = N(l), O = R(
174
- (m) => {
175
- if (!e) return;
176
- const p = V();
177
- if (p)
235
+ const c = Y(
236
+ () => new Se(e, { debounceMs: 0, timeoutMs: s }),
237
+ [e, s]
238
+ ), a = De(r, e), u = t ? _e(a) : [], [l, d] = k(u), [R, p] = k(!1), [w, y] = k(null), [b, x] = k(!1), v = C(u.length), N = C(!1), E = C(u), I = C(o ?? []);
239
+ I.current = o ?? [];
240
+ const A = M(
241
+ (f) => {
242
+ if (!t) return;
243
+ const g = Z();
244
+ if (g)
178
245
  try {
179
- const H = m.slice(-Ce);
180
- p.setItem(a, JSON.stringify(H));
246
+ const L = f.slice(-Oe);
247
+ g.setItem(a, JSON.stringify(L));
181
248
  } catch {
182
249
  }
183
250
  },
184
- [e, a]
185
- ), A = () => (v.current += 1, `msg-${v.current}`), I = R(
186
- (m, p) => {
251
+ [t, a]
252
+ ), D = () => (v.current += 1, `msg-${v.current}`), S = M(
253
+ (f, g) => {
187
254
  if (!n)
188
- return p ?? "Something went wrong. Please try again.";
189
- switch (m) {
255
+ return g ?? "Something went wrong. Please try again.";
256
+ switch (f) {
190
257
  case "TIMEOUT":
191
258
  return n.errorTimeout;
192
259
  case "NETWORK_ERROR":
193
260
  return n.errorConnection;
194
261
  case "RATE_LIMITED":
195
- return p != null && p.includes("minute") ? n.errorRateLimitMinute : n.errorRateLimitHour;
262
+ return g != null && g.includes("minute") ? n.errorRateLimitMinute : n.errorRateLimitHour;
196
263
  case "VALIDATION_ERROR":
197
264
  case "CONFIG_ERROR":
198
265
  case "SERVICE_ERROR":
199
266
  case "UNKNOWN_ERROR":
200
267
  default:
201
- return p ?? n.errorGeneric;
268
+ return g ?? n.errorGeneric;
202
269
  }
203
270
  },
204
271
  [n]
205
- ), M = R((m) => !(m instanceof U) || m.code === "TIMEOUT" || m.code === "NETWORK_ERROR" || m.code === "RATE_LIMITED" || m.code === "SERVICE_ERROR" || m.code === "UNKNOWN_ERROR" || m.status >= 500 || m.status === 0, []), D = R(
206
- async (m) => {
207
- E(!0), y.current = !0, x(null), w(!1);
272
+ ), j = M((f) => !(f instanceof U) || f.code === "TIMEOUT" || f.code === "NETWORK_ERROR" || f.code === "RATE_LIMITED" || f.code === "SERVICE_ERROR" || f.code === "UNKNOWN_ERROR" || f.status >= 500 || f.status === 0, []), m = M(
273
+ async (f) => {
274
+ p(!0), N.current = !0, y(null), x(!1);
208
275
  try {
209
- const p = await o.sendMessage(m), H = {
210
- id: A(),
276
+ const g = await c.sendMessage(f);
277
+ let L = {
278
+ id: D(),
211
279
  role: "assistant",
212
- content: p.reply,
213
- sources: p.sources
214
- }, L = [...m, H];
215
- T.current = L, u(L), O(L);
216
- } catch (p) {
217
- if (p instanceof se) return;
218
- p instanceof U ? x(I(p.code, p.message)) : x(
280
+ content: g.reply,
281
+ sources: g.sources
282
+ };
283
+ I.current.length > 0 && (L = await ke(
284
+ I.current,
285
+ L,
286
+ { messages: f, apiUrl: e }
287
+ ));
288
+ const T = [...f, L];
289
+ E.current = T, d(T), A(T);
290
+ } catch (g) {
291
+ if (g instanceof ae) return;
292
+ if (I.current.length > 0) {
293
+ const L = g instanceof Error ? g : new Error(String(g)), T = await Ae(I.current, L, {
294
+ messages: f,
295
+ apiUrl: e
296
+ });
297
+ if (T) {
298
+ const B = {
299
+ id: D(),
300
+ role: "assistant",
301
+ content: T.content,
302
+ sources: T.sources
303
+ }, O = [...f, B];
304
+ E.current = O, d(O), A(O), y(null), x(!1);
305
+ return;
306
+ }
307
+ }
308
+ g instanceof U ? y(S(g.code, g.message)) : y(
219
309
  (n == null ? void 0 : n.errorConnection) ?? "Failed to connect. Please try again."
220
- ), w(M(p));
310
+ ), x(j(g));
221
311
  } finally {
222
- E(!1), y.current = !1;
312
+ p(!1), N.current = !1;
223
313
  }
224
314
  },
225
- [o, I, M, O, n]
226
- ), _ = R(
227
- async (m) => {
228
- const p = m.trim();
229
- if (!p || y.current) return;
230
- const H = {
231
- id: A(),
315
+ [
316
+ e,
317
+ c,
318
+ S,
319
+ j,
320
+ A,
321
+ n
322
+ ]
323
+ ), P = M(
324
+ async (f) => {
325
+ const g = f.trim();
326
+ if (!g || N.current) return;
327
+ const L = {
328
+ id: D(),
232
329
  role: "user",
233
- content: p
234
- }, L = [...T.current, H];
235
- T.current = L, u(L), O(L), await D(L);
330
+ content: g
331
+ };
332
+ let T = L;
333
+ if (I.current.length > 0) {
334
+ const O = await Le(I.current, L, {
335
+ messages: E.current,
336
+ apiUrl: e
337
+ });
338
+ if (O.type === "abort") return;
339
+ if (O.type === "respond") {
340
+ const z = {
341
+ id: D(),
342
+ role: "assistant",
343
+ content: O.reply.content,
344
+ sources: O.reply.sources
345
+ }, $ = [
346
+ ...E.current,
347
+ O.message,
348
+ z
349
+ ];
350
+ E.current = $, d($), A($), y(null), x(!1);
351
+ return;
352
+ }
353
+ T = O.message;
354
+ }
355
+ const B = [...E.current, T];
356
+ E.current = B, d(B), A(B), await m(B);
236
357
  },
237
- [O, D]
238
- ), b = R(async () => {
239
- if (y.current) return;
240
- const m = T.current[T.current.length - 1];
241
- !m || m.role !== "user" || await D(T.current);
242
- }, [D]), j = R(() => {
243
- if (T.current = [], u([]), x(null), w(!1), e) {
244
- const m = V();
245
- if (!m) return;
358
+ [e, A, m]
359
+ ), V = M(async () => {
360
+ if (N.current) return;
361
+ const f = E.current[E.current.length - 1];
362
+ !f || f.role !== "user" || await m(E.current);
363
+ }, [m]), K = M(() => {
364
+ if (E.current = [], d([]), y(null), x(!1), t) {
365
+ const f = Z();
366
+ if (!f) return;
246
367
  try {
247
- m.removeItem(a);
368
+ f.removeItem(a);
248
369
  } catch {
249
370
  }
250
371
  }
251
- }, [e, a]);
372
+ }, [t, a]);
252
373
  return {
253
- messages: c,
254
- isLoading: h,
255
- error: g,
256
- canRetry: f,
257
- sendMessage: _,
258
- retry: b,
259
- clearMessages: j
374
+ messages: l,
375
+ isLoading: R,
376
+ error: w,
377
+ canRetry: b,
378
+ sendMessage: P,
379
+ retry: V,
380
+ clearMessages: K
260
381
  };
261
382
  }
262
- function Oe(t) {
263
- const [e, r] = C(() => typeof window > "u" ? !1 : window.matchMedia(t).matches);
264
- return k(() => {
265
- const s = window.matchMedia(t);
383
+ function Be(e) {
384
+ const [t, r] = k(() => typeof window > "u" ? !1 : window.matchMedia(e).matches);
385
+ return H(() => {
386
+ const s = window.matchMedia(e);
266
387
  r(s.matches);
267
388
  const n = (o) => r(o.matches);
268
389
  return s.addEventListener("change", n), () => s.removeEventListener("change", n);
269
- }, [t]), e;
390
+ }, [e]), t;
270
391
  }
271
- function W(t, e) {
272
- return t instanceof RegExp ? t.test(e) : e.toLowerCase().includes(t.toLowerCase());
392
+ function F(e, t) {
393
+ return e instanceof RegExp ? e.test(t) : t.toLowerCase().includes(e.toLowerCase());
273
394
  }
274
- function Ae() {
275
- const t = document.documentElement, e = document.body, r = t.scrollTop || e.scrollTop || 0, s = Math.max(t.scrollHeight, e.scrollHeight), n = t.clientHeight || window.innerHeight, o = s - n;
395
+ function $e() {
396
+ const e = document.documentElement, t = document.body, r = e.scrollTop || t.scrollTop || 0, s = Math.max(e.scrollHeight, t.scrollHeight), n = e.clientHeight || window.innerHeight, o = s - n;
276
397
  return o <= 0 ? 100 : r / o * 100;
277
398
  }
278
- function Ie({
279
- triggers: t,
280
- enabled: e,
399
+ function je({
400
+ triggers: e,
401
+ enabled: t,
281
402
  onOpen: r,
282
403
  onGreeting: s
283
404
  }) {
284
- k(() => {
285
- if (!e || !t || t.length === 0) return;
286
- const n = /* @__PURE__ */ new Set(), o = [], a = typeof window < "u" ? window.location.href : "", l = (c, u) => {
287
- n.has(c) || (n.add(c), u === "open" ? r() : s(u.greeting));
405
+ H(() => {
406
+ if (!t || !e || e.length === 0) return;
407
+ const n = /* @__PURE__ */ new Set(), o = [], c = typeof window < "u" ? window.location.href : "", a = (u, l) => {
408
+ n.has(u) || (n.add(u), l === "open" ? r() : s(l.greeting));
288
409
  };
289
- return t.forEach((c, u) => {
290
- switch (c.on) {
410
+ return e.forEach((u, l) => {
411
+ switch (u.on) {
291
412
  case "url": {
292
- W(c.pattern, a) && l(u, c.action);
413
+ F(u.pattern, c) && a(l, u.action);
293
414
  break;
294
415
  }
295
416
  case "time": {
296
- if (c.matchUrl && !W(c.matchUrl, a))
417
+ if (u.matchUrl && !F(u.matchUrl, c))
297
418
  return;
298
- const h = window.setTimeout(
299
- () => l(u, c.action),
300
- Math.max(0, c.seconds * 1e3)
419
+ const d = window.setTimeout(
420
+ () => a(l, u.action),
421
+ Math.max(0, u.seconds * 1e3)
301
422
  );
302
- o.push(() => window.clearTimeout(h));
423
+ o.push(() => window.clearTimeout(d));
303
424
  break;
304
425
  }
305
426
  case "scroll": {
306
- if (c.matchUrl && !W(c.matchUrl, a))
427
+ if (u.matchUrl && !F(u.matchUrl, c))
307
428
  return;
308
- const h = () => {
309
- Ae() >= c.percent && l(u, c.action);
429
+ const d = () => {
430
+ $e() >= u.percent && a(l, u.action);
310
431
  };
311
- h(), window.addEventListener("scroll", h, { passive: !0 }), o.push(() => window.removeEventListener("scroll", h));
432
+ d(), window.addEventListener("scroll", d, { passive: !0 }), o.push(() => window.removeEventListener("scroll", d));
312
433
  break;
313
434
  }
314
435
  case "exit-intent": {
315
- if (c.matchUrl && !W(c.matchUrl, a))
436
+ if (u.matchUrl && !F(u.matchUrl, c))
316
437
  return;
317
- const h = (E) => {
318
- E.clientY <= 0 && l(u, c.action);
438
+ const d = (R) => {
439
+ R.clientY <= 0 && a(l, u.action);
319
440
  };
320
- document.addEventListener("mouseleave", h), o.push(
321
- () => document.removeEventListener("mouseleave", h)
441
+ document.addEventListener("mouseleave", d), o.push(
442
+ () => document.removeEventListener("mouseleave", d)
322
443
  );
323
444
  break;
324
445
  }
325
446
  }
326
447
  }), () => {
327
- o.forEach((c) => c());
448
+ o.forEach((u) => u());
328
449
  };
329
- }, [t, e, r, s]);
450
+ }, [e, t, r, s]);
330
451
  }
331
- const De = {
452
+ const Pe = {
332
453
  "bottom-right": "bottom-6 right-6",
333
454
  "bottom-left": "bottom-6 left-6",
334
455
  "top-right": "top-6 right-6",
335
456
  "top-left": "top-6 left-6"
336
- }, He = Ee(function({ isOpen: e, onClick: r, position: s = "bottom-right", translations: n }, o) {
337
- const a = e ? (n == null ? void 0 : n.closeChat) ?? "Close chat" : (n == null ? void 0 : n.openChat) ?? "Open chat";
457
+ }, Ge = Me(function({ isOpen: t, onClick: r, position: s = "bottom-right", translations: n }, o) {
458
+ const c = t ? (n == null ? void 0 : n.closeChat) ?? "Close chat" : (n == null ? void 0 : n.openChat) ?? "Open chat";
338
459
  return /* @__PURE__ */ i(
339
460
  "button",
340
461
  {
341
462
  ref: o,
342
463
  onClick: r,
343
- "aria-label": a,
344
- className: `fixed ${De[s]} z-50 flex h-14 w-14 items-center justify-center rounded-claudius-full bg-claudius-accent text-claudius-accent-text shadow-claudius-floating transition-transform hover:scale-105 focus:outline-none focus:ring-2 focus:ring-claudius-accent focus:ring-offset-2`,
345
- children: e ? /* @__PURE__ */ d(
464
+ "aria-label": c,
465
+ className: `fixed ${Pe[s]} z-50 flex h-14 w-14 items-center justify-center rounded-claudius-full bg-claudius-accent text-claudius-accent-text shadow-claudius-floating transition-transform hover:scale-105 focus:outline-none focus:ring-2 focus:ring-claudius-accent focus:ring-offset-2`,
466
+ children: t ? /* @__PURE__ */ h(
346
467
  "svg",
347
468
  {
348
469
  width: "24",
@@ -376,12 +497,12 @@ const De = {
376
497
  )
377
498
  }
378
499
  );
379
- }), _e = K(function({
380
- count: e,
500
+ }), Ue = J(function({
501
+ count: t,
381
502
  isActive: r,
382
503
  onClick: s
383
504
  }) {
384
- return /* @__PURE__ */ d(
505
+ return /* @__PURE__ */ h(
385
506
  "button",
386
507
  {
387
508
  onClick: s,
@@ -389,7 +510,7 @@ const De = {
389
510
  title: "View sources",
390
511
  className: `group relative flex h-7 w-7 items-center justify-center rounded-claudius-full transition-colors ${r ? "bg-claudius-accent text-claudius-accent-text" : "text-claudius-text-muted hover:bg-claudius-surface-muted hover:text-claudius-text"}`,
391
512
  children: [
392
- /* @__PURE__ */ d(
513
+ /* @__PURE__ */ h(
393
514
  "svg",
394
515
  {
395
516
  width: "14",
@@ -409,29 +530,29 @@ const De = {
409
530
  ]
410
531
  }
411
532
  ),
412
- /* @__PURE__ */ i("span", { className: "absolute -right-1 -top-1 flex h-4 min-w-4 items-center justify-center rounded-claudius-full bg-claudius-accent px-1 text-[10px] font-bold text-claudius-accent-text", children: e })
533
+ /* @__PURE__ */ i("span", { className: "absolute -right-1 -top-1 flex h-4 min-w-4 items-center justify-center rounded-claudius-full bg-claudius-accent px-1 text-[10px] font-bold text-claudius-accent-text", children: t })
413
534
  ]
414
535
  }
415
536
  );
416
- }), je = ["http:", "https:"];
417
- function oe(t) {
418
- if (!t || typeof t != "string")
537
+ }), We = ["http:", "https:"];
538
+ function le(e) {
539
+ if (!e || typeof e != "string")
419
540
  return null;
420
- const e = t.trim();
421
- if (!e)
541
+ const t = e.trim();
542
+ if (!t)
422
543
  return null;
423
544
  try {
424
- const r = new URL(e);
425
- return je.includes(r.protocol) ? e : null;
545
+ const r = new URL(t);
546
+ return We.includes(r.protocol) ? t : null;
426
547
  } catch {
427
548
  return null;
428
549
  }
429
550
  }
430
- const Q = /(https?:\/\/[^\s)]+)/, ee = /(\*\*[^*]+\*\*)/, te = /(\*[^*]+\*)/;
431
- function $e(t, e) {
432
- const r = t.match(/[.,;:!?'"]+$/), s = r ? t.slice(0, -r[0].length) : t, n = r ? r[0] : "", o = oe(s);
433
- return o ? /* @__PURE__ */ d(ve, { children: [
434
- /* @__PURE__ */ d(
551
+ const ne = /(https?:\/\/[^\s)]+)/, se = /(\*\*[^*]+\*\*)/, oe = /(\*[^*]+\*)/;
552
+ function ze(e, t) {
553
+ const r = e.match(/[.,;:!?'"]+$/), s = r ? e.slice(0, -r[0].length) : e, n = r ? r[0] : "", o = le(s);
554
+ return o ? /* @__PURE__ */ h(Te, { children: [
555
+ /* @__PURE__ */ h(
435
556
  "a",
436
557
  {
437
558
  href: o,
@@ -443,57 +564,57 @@ function $e(t, e) {
443
564
  /* @__PURE__ */ i("span", { className: "sr-only", children: " (opens in a new tab)" })
444
565
  ]
445
566
  },
446
- e
567
+ t
447
568
  ),
448
569
  n
449
- ] }) : t;
570
+ ] }) : e;
450
571
  }
451
- function Ue(t, e) {
452
- const r = t.split(ee), s = [];
572
+ function Fe(e, t) {
573
+ const r = e.split(se), s = [];
453
574
  return r.forEach((n, o) => {
454
- if (ee.test(n)) {
455
- const a = n.slice(2, -2);
456
- s.push(/* @__PURE__ */ i("strong", { children: a }, `${e}-b${o}`));
575
+ if (se.test(n)) {
576
+ const c = n.slice(2, -2);
577
+ s.push(/* @__PURE__ */ i("strong", { children: c }, `${t}-b${o}`));
457
578
  } else
458
- n.split(te).forEach((l, c) => {
459
- if (te.test(l)) {
460
- const u = l.slice(1, -1);
461
- s.push(/* @__PURE__ */ i("em", { children: u }, `${e}-b${o}-i${c}`));
579
+ n.split(oe).forEach((a, u) => {
580
+ if (oe.test(a)) {
581
+ const l = a.slice(1, -1);
582
+ s.push(/* @__PURE__ */ i("em", { children: l }, `${t}-b${o}-i${u}`));
462
583
  } else
463
- l.split(Q).forEach((h, E) => {
464
- Q.test(h) ? s.push(
465
- $e(h, `${e}-b${o}-i${c}-u${E}`)
466
- ) : h && s.push(h);
584
+ a.split(ne).forEach((d, R) => {
585
+ ne.test(d) ? s.push(
586
+ ze(d, `${t}-b${o}-i${u}-u${R}`)
587
+ ) : d && s.push(d);
467
588
  });
468
589
  });
469
590
  }), s;
470
591
  }
471
- function Be(t) {
472
- const e = t.split(`
592
+ function Ye(e) {
593
+ const t = e.split(`
473
594
  `);
474
- return e.map((r, s) => /* @__PURE__ */ d("span", { children: [
475
- Ue(r, `l${s}`),
476
- s < e.length - 1 && /* @__PURE__ */ i("br", {})
595
+ return t.map((r, s) => /* @__PURE__ */ h("span", { children: [
596
+ Fe(r, `l${s}`),
597
+ s < t.length - 1 && /* @__PURE__ */ i("br", {})
477
598
  ] }, s));
478
599
  }
479
- const Ge = K(function({
480
- role: e,
600
+ const Ve = J(function({
601
+ role: t,
481
602
  content: r,
482
603
  sources: s,
483
604
  onSourceClick: n,
484
605
  isSourceActive: o
485
606
  }) {
486
- const a = e === "user";
487
- return /* @__PURE__ */ d("div", { className: `${a ? "ml-auto" : "mr-auto"} max-w-[85%]`, children: [
607
+ const c = t === "user";
608
+ return /* @__PURE__ */ h("div", { className: `${c ? "ml-auto" : "mr-auto"} max-w-[85%]`, children: [
488
609
  /* @__PURE__ */ i(
489
610
  "div",
490
611
  {
491
- className: `rounded-claudius-bubble px-4 py-2.5 text-sm leading-relaxed font-body ${a ? "bg-claudius-user-bubble text-claudius-user-bubble-text rounded-br-claudius-tail" : "bg-claudius-assistant-bubble text-claudius-assistant-bubble-text rounded-bl-claudius-tail"}`,
492
- children: Be(r)
612
+ className: `rounded-claudius-bubble px-4 py-2.5 text-sm leading-relaxed font-body ${c ? "bg-claudius-user-bubble text-claudius-user-bubble-text rounded-br-claudius-tail" : "bg-claudius-assistant-bubble text-claudius-assistant-bubble-text rounded-bl-claudius-tail"}`,
613
+ children: Ye(r)
493
614
  }
494
615
  ),
495
- !a && s && s.length > 0 && n && /* @__PURE__ */ i("div", { className: "mt-1", children: /* @__PURE__ */ i(
496
- _e,
616
+ !c && s && s.length > 0 && n && /* @__PURE__ */ i("div", { className: "mt-1", children: /* @__PURE__ */ i(
617
+ Ue,
497
618
  {
498
619
  count: s.length,
499
620
  isActive: o ?? !1,
@@ -501,42 +622,42 @@ const Ge = K(function({
501
622
  }
502
623
  ) })
503
624
  ] });
504
- }), z = 2e3, Pe = 1800;
505
- function We({
506
- onSend: t,
507
- isLoading: e,
625
+ }), X = 2e3, Ke = 1800;
626
+ function qe({
627
+ onSend: e,
628
+ isLoading: t,
508
629
  placeholder: r,
509
630
  translations: s
510
631
  }) {
511
- const [n, o] = C(""), a = N(null), l = n.length, c = l >= Pe, u = l >= z, h = r ?? (s == null ? void 0 : s.placeholder) ?? "Type your message...", E = (s == null ? void 0 : s.sendMessage) ?? "Send message", g = (s == null ? void 0 : s.typeYourMessage) ?? "Type your message";
512
- return k(() => {
513
- var w;
514
- e || (w = a.current) == null || w.focus();
515
- }, [e]), /* @__PURE__ */ d(
632
+ const [n, o] = k(""), c = C(null), a = n.length, u = a >= Ke, l = a >= X, d = r ?? (s == null ? void 0 : s.placeholder) ?? "Type your message...", R = (s == null ? void 0 : s.sendMessage) ?? "Send message", p = (s == null ? void 0 : s.typeYourMessage) ?? "Type your message";
633
+ return H(() => {
634
+ var b;
635
+ t || (b = c.current) == null || b.focus();
636
+ }, [t]), /* @__PURE__ */ h(
516
637
  "form",
517
638
  {
518
- onSubmit: (w) => {
519
- w.preventDefault();
520
- const v = n.trim();
521
- !v || u || (t(v), o(""));
639
+ onSubmit: (b) => {
640
+ b.preventDefault();
641
+ const x = n.trim();
642
+ !x || l || (e(x), o(""));
522
643
  },
523
644
  className: "border-t border-claudius-border bg-claudius-surface p-3",
524
645
  children: [
525
- /* @__PURE__ */ d("div", { className: "flex gap-2", children: [
646
+ /* @__PURE__ */ h("div", { className: "flex gap-2", children: [
526
647
  /* @__PURE__ */ i(
527
648
  "input",
528
649
  {
529
- ref: a,
650
+ ref: c,
530
651
  type: "text",
531
652
  value: n,
532
- onChange: (w) => {
533
- const v = w.target.value;
534
- v.length <= z && o(v);
653
+ onChange: (b) => {
654
+ const x = b.target.value;
655
+ x.length <= X && o(x);
535
656
  },
536
- placeholder: h,
537
- disabled: e,
538
- "aria-label": g,
539
- "aria-describedby": c ? "char-count" : void 0,
657
+ placeholder: d,
658
+ disabled: t,
659
+ "aria-label": p,
660
+ "aria-describedby": u ? "char-count" : void 0,
540
661
  className: "flex-1 rounded-claudius-sm border border-claudius-border bg-claudius-field px-3 py-2 text-sm font-body text-claudius-text placeholder:text-claudius-text-muted focus:border-claudius-accent focus:outline-none focus:ring-1 focus:ring-claudius-accent disabled:opacity-50"
541
662
  }
542
663
  ),
@@ -544,10 +665,10 @@ function We({
544
665
  "button",
545
666
  {
546
667
  type: "submit",
547
- disabled: e || u,
548
- "aria-label": E,
668
+ disabled: t || l,
669
+ "aria-label": R,
549
670
  className: "flex h-11 w-11 shrink-0 items-center justify-center rounded-claudius-sm bg-claudius-accent text-claudius-accent-text transition-colors hover:opacity-90 disabled:opacity-50",
550
- children: /* @__PURE__ */ d(
671
+ children: /* @__PURE__ */ h(
551
672
  "svg",
552
673
  {
553
674
  width: "16",
@@ -568,16 +689,16 @@ function We({
568
689
  }
569
690
  )
570
691
  ] }),
571
- c && /* @__PURE__ */ d(
692
+ u && /* @__PURE__ */ h(
572
693
  "div",
573
694
  {
574
695
  id: "char-count",
575
- className: `mt-1 text-xs text-right ${u ? "text-claudius-error" : "text-claudius-text-muted"}`,
696
+ className: `mt-1 text-xs text-right ${l ? "text-claudius-error" : "text-claudius-text-muted"}`,
576
697
  "aria-live": "polite",
577
698
  children: [
578
- l,
699
+ a,
579
700
  "/",
580
- z
701
+ X
581
702
  ]
582
703
  }
583
704
  )
@@ -585,30 +706,30 @@ function We({
585
706
  }
586
707
  );
587
708
  }
588
- const Fe = ["blog", "page", "external"], Ye = {
709
+ const Xe = ["blog", "page", "external"], Ze = {
589
710
  blog: "Blog",
590
711
  page: "Page",
591
712
  external: "External"
592
713
  };
593
- function ze(t) {
714
+ function Je(e) {
594
715
  try {
595
- return new URL(t).hostname;
716
+ return new URL(e).hostname;
596
717
  } catch {
597
- return t;
718
+ return e;
598
719
  }
599
720
  }
600
- const Ve = K(function({
601
- sources: e,
721
+ const Qe = J(function({
722
+ sources: t,
602
723
  onClose: r
603
724
  }) {
604
- const s = Fe.map((o) => ({
725
+ const s = Xe.map((o) => ({
605
726
  type: o,
606
- label: Ye[o],
607
- items: e.filter((a) => a.type === o)
608
- })).filter((o) => o.items.length > 0), n = e.length === 1 ? "1 source found" : `${e.length} sources found`;
609
- return /* @__PURE__ */ d("div", { className: "absolute inset-y-0 left-0 z-10 flex w-[280px] flex-col border-r-2 border-claudius-border bg-claudius-surface rounded-r-claudius-lg transition-transform duration-200 ease-out", children: [
610
- /* @__PURE__ */ d("div", { className: "flex items-center justify-between border-b border-claudius-border px-4 py-3", children: [
611
- /* @__PURE__ */ d("div", { children: [
727
+ label: Ze[o],
728
+ items: t.filter((c) => c.type === o)
729
+ })).filter((o) => o.items.length > 0), n = t.length === 1 ? "1 source found" : `${t.length} sources found`;
730
+ return /* @__PURE__ */ h("div", { className: "absolute inset-y-0 left-0 z-10 flex w-[280px] flex-col border-r-2 border-claudius-border bg-claudius-surface rounded-r-claudius-lg transition-transform duration-200 ease-out", children: [
731
+ /* @__PURE__ */ h("div", { className: "flex items-center justify-between border-b border-claudius-border px-4 py-3", children: [
732
+ /* @__PURE__ */ h("div", { children: [
612
733
  /* @__PURE__ */ i("h3", { className: "text-sm font-heading font-semibold text-claudius-text", children: "Sources" }),
613
734
  /* @__PURE__ */ i("p", { className: "text-xs text-claudius-text-muted", children: n })
614
735
  ] }),
@@ -618,7 +739,7 @@ const Ve = K(function({
618
739
  onClick: r,
619
740
  "aria-label": "Close sources",
620
741
  className: "flex h-7 w-7 items-center justify-center rounded-claudius-full text-claudius-text-muted transition-colors hover:bg-claudius-surface-muted hover:text-claudius-text",
621
- children: /* @__PURE__ */ d(
742
+ children: /* @__PURE__ */ h(
622
743
  "svg",
623
744
  {
624
745
  width: "14",
@@ -639,54 +760,54 @@ const Ve = K(function({
639
760
  }
640
761
  )
641
762
  ] }),
642
- /* @__PURE__ */ i("div", { className: "flex-1 overflow-y-auto px-3 py-3 space-y-4", children: s.map((o) => /* @__PURE__ */ d("div", { children: [
763
+ /* @__PURE__ */ i("div", { className: "flex-1 overflow-y-auto px-3 py-3 space-y-4", children: s.map((o) => /* @__PURE__ */ h("div", { children: [
643
764
  /* @__PURE__ */ i("h4", { className: "mb-2 text-xs font-semibold uppercase tracking-wide text-claudius-text-muted", children: o.label }),
644
- /* @__PURE__ */ i("div", { className: "space-y-2", children: o.items.map((a) => {
645
- const l = oe(a.url);
646
- return l ? /* @__PURE__ */ d(
765
+ /* @__PURE__ */ i("div", { className: "space-y-2", children: o.items.map((c) => {
766
+ const a = le(c.url);
767
+ return a ? /* @__PURE__ */ h(
647
768
  "a",
648
769
  {
649
- href: l,
770
+ href: a,
650
771
  target: "_blank",
651
772
  rel: "noopener noreferrer",
652
773
  className: "block rounded-claudius-md border-2 border-claudius-border bg-claudius-surface-muted p-3 transition-colors hover:bg-claudius-border",
653
774
  children: [
654
- /* @__PURE__ */ i("p", { className: "truncate text-sm font-medium text-claudius-text", children: a.title }),
655
- /* @__PURE__ */ i("p", { className: "mt-0.5 text-xs text-claudius-text-muted", children: ze(l) })
775
+ /* @__PURE__ */ i("p", { className: "truncate text-sm font-medium text-claudius-text", children: c.title }),
776
+ /* @__PURE__ */ i("p", { className: "mt-0.5 text-xs text-claudius-text-muted", children: Je(a) })
656
777
  ]
657
778
  },
658
- l
779
+ a
659
780
  ) : null;
660
781
  }) })
661
782
  ] }, o.type)) })
662
783
  ] });
663
784
  });
664
- function Ke({
665
- title: t,
666
- subtitle: e,
785
+ function et({
786
+ title: e,
787
+ subtitle: t,
667
788
  titleId: r,
668
789
  closeLabel: s,
669
790
  onClose: n
670
791
  }) {
671
- return /* @__PURE__ */ d("div", { className: "flex items-center gap-3 bg-claudius-accent px-5 py-4", children: [
792
+ return /* @__PURE__ */ h("div", { className: "flex items-center gap-3 bg-claudius-accent px-5 py-4", children: [
672
793
  /* @__PURE__ */ i(
673
794
  "div",
674
795
  {
675
796
  "aria-hidden": "true",
676
797
  className: "flex h-8 w-8 items-center justify-center rounded-claudius-full bg-claudius-accent-soft text-sm font-bold text-claudius-accent-text",
677
- children: t.charAt(0).toUpperCase()
798
+ children: e.charAt(0).toUpperCase()
678
799
  }
679
800
  ),
680
- /* @__PURE__ */ d("div", { className: "flex-1", children: [
801
+ /* @__PURE__ */ h("div", { className: "flex-1", children: [
681
802
  /* @__PURE__ */ i(
682
803
  "h2",
683
804
  {
684
805
  id: r,
685
806
  className: "text-sm font-heading font-semibold text-claudius-accent-text",
686
- children: t
807
+ children: e
687
808
  }
688
809
  ),
689
- /* @__PURE__ */ i("p", { className: "text-xs text-claudius-accent-text", children: e })
810
+ /* @__PURE__ */ i("p", { className: "text-xs text-claudius-accent-text", children: t })
690
811
  ] }),
691
812
  /* @__PURE__ */ i(
692
813
  "button",
@@ -694,7 +815,7 @@ function Ke({
694
815
  onClick: n,
695
816
  "aria-label": s,
696
817
  className: "flex h-10 w-10 items-center justify-center rounded-claudius-full text-claudius-accent-text-muted transition-colors hover:bg-claudius-accent-soft hover:text-claudius-accent-text",
697
- children: /* @__PURE__ */ d(
818
+ children: /* @__PURE__ */ h(
698
819
  "svg",
699
820
  {
700
821
  width: "18",
@@ -716,40 +837,40 @@ function Ke({
716
837
  )
717
838
  ] });
718
839
  }
719
- function qe({
720
- message: t,
721
- retryLabel: e,
840
+ function tt({
841
+ message: e,
842
+ retryLabel: t,
722
843
  onRetry: r
723
844
  }) {
724
- return /* @__PURE__ */ d(
845
+ return /* @__PURE__ */ h(
725
846
  "div",
726
847
  {
727
848
  role: "alert",
728
849
  className: "mx-auto flex max-w-[90%] flex-col items-center gap-2 rounded-claudius-sm bg-claudius-error-surface px-3 py-2 text-center text-xs text-claudius-error",
729
850
  children: [
730
- /* @__PURE__ */ i("span", { children: t }),
851
+ /* @__PURE__ */ i("span", { children: e }),
731
852
  r && /* @__PURE__ */ i(
732
853
  "button",
733
854
  {
734
855
  type: "button",
735
856
  onClick: r,
736
857
  className: "rounded-claudius-md bg-claudius-error px-3 py-1 text-xs font-semibold text-claudius-error-text transition-opacity hover:opacity-90 focus:outline-none focus-visible:ring-2 focus-visible:ring-claudius-error focus-visible:ring-offset-1",
737
- children: e
858
+ children: t
738
859
  }
739
860
  )
740
861
  ]
741
862
  }
742
863
  );
743
864
  }
744
- function Xe({ label: t }) {
865
+ function rt({ label: e }) {
745
866
  return /* @__PURE__ */ i(
746
867
  "div",
747
868
  {
748
869
  role: "status",
749
870
  "aria-live": "polite",
750
- "aria-label": t,
871
+ "aria-label": e,
751
872
  className: "mr-auto flex max-w-[85%]",
752
- children: /* @__PURE__ */ d("div", { className: "flex gap-1 rounded-claudius-bubble rounded-bl-claudius-tail bg-claudius-assistant-bubble px-4 py-3", children: [
873
+ children: /* @__PURE__ */ h("div", { className: "flex gap-1 rounded-claudius-bubble rounded-bl-claudius-tail bg-claudius-assistant-bubble px-4 py-3", children: [
753
874
  /* @__PURE__ */ i("span", { className: "h-2 w-2 motion-safe:animate-bounce rounded-claudius-full bg-claudius-text-muted [animation-delay:0ms]" }),
754
875
  /* @__PURE__ */ i("span", { className: "h-2 w-2 motion-safe:animate-bounce rounded-claudius-full bg-claudius-text-muted [animation-delay:150ms]" }),
755
876
  /* @__PURE__ */ i("span", { className: "h-2 w-2 motion-safe:animate-bounce rounded-claudius-full bg-claudius-text-muted [animation-delay:300ms]" })
@@ -757,162 +878,162 @@ function Xe({ label: t }) {
757
878
  }
758
879
  );
759
880
  }
760
- function Je(t, e, r) {
761
- const [s, n] = C(0), o = N(0), a = N(0), l = N(0), c = N(!1);
762
- return k(() => {
763
- const u = t.current;
764
- if (!r || !u) return;
765
- const h = (x) => {
766
- if (u.scrollTop > 0) {
767
- c.current = !1;
881
+ function nt(e, t, r) {
882
+ const [s, n] = k(0), o = C(0), c = C(0), a = C(0), u = C(!1);
883
+ return H(() => {
884
+ const l = e.current;
885
+ if (!r || !l) return;
886
+ const d = (w) => {
887
+ if (l.scrollTop > 0) {
888
+ u.current = !1;
768
889
  return;
769
890
  }
770
- c.current = !0, a.current = x.touches[0].clientY, l.current = Date.now();
771
- }, E = (x) => {
772
- if (!c.current) return;
773
- let f = x.touches[0].clientY - a.current;
774
- f < 0 && (f = f * 0.3), o.current = f, n(f);
775
- }, g = () => {
776
- if (!c.current) return;
777
- c.current = !1;
778
- const x = o.current, f = (Date.now() - l.current) / 1e3, w = u.getBoundingClientRect().height, v = f > 0.05 && x > 0 && x / f > 500, y = x > w * 0.3;
779
- v || y ? e() : (o.current = 0, n(0));
891
+ u.current = !0, c.current = w.touches[0].clientY, a.current = Date.now();
892
+ }, R = (w) => {
893
+ if (!u.current) return;
894
+ let y = w.touches[0].clientY - c.current;
895
+ y < 0 && (y = y * 0.3), o.current = y, n(y);
896
+ }, p = () => {
897
+ if (!u.current) return;
898
+ u.current = !1;
899
+ const w = o.current, y = (Date.now() - a.current) / 1e3, b = l.getBoundingClientRect().height, x = y > 0.05 && w > 0 && w / y > 500, v = w > b * 0.3;
900
+ x || v ? t() : (o.current = 0, n(0));
780
901
  };
781
- return u.addEventListener("touchstart", h, { passive: !0 }), u.addEventListener("touchmove", E, { passive: !0 }), u.addEventListener("touchend", g), () => {
782
- u.removeEventListener("touchstart", h), u.removeEventListener("touchmove", E), u.removeEventListener("touchend", g);
902
+ return l.addEventListener("touchstart", d, { passive: !0 }), l.addEventListener("touchmove", R, { passive: !0 }), l.addEventListener("touchend", p), () => {
903
+ l.removeEventListener("touchstart", d), l.removeEventListener("touchmove", R), l.removeEventListener("touchend", p);
783
904
  };
784
- }, [t, e, r]), { offsetY: s };
905
+ }, [e, t, r]), { offsetY: s };
785
906
  }
786
- const Ze = 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';
787
- function Qe(t, e) {
788
- k(() => {
789
- const r = t.current;
907
+ const st = 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';
908
+ function ot(e, t) {
909
+ H(() => {
910
+ const r = e.current;
790
911
  if (!r) return;
791
912
  const s = (n) => {
792
913
  if (n.key !== "Tab") return;
793
914
  const o = Array.from(
794
- r.querySelectorAll(Ze)
795
- ).filter((u) => !u.hasAttribute("aria-hidden"));
915
+ r.querySelectorAll(st)
916
+ ).filter((l) => !l.hasAttribute("aria-hidden"));
796
917
  if (o.length === 0) return;
797
- const a = o[0], l = o[o.length - 1], c = document.activeElement;
798
- n.shiftKey && c === a ? (n.preventDefault(), l.focus()) : !n.shiftKey && c === l && (n.preventDefault(), a.focus());
918
+ const c = o[0], a = o[o.length - 1], u = document.activeElement;
919
+ n.shiftKey && u === c ? (n.preventDefault(), a.focus()) : !n.shiftKey && u === a && (n.preventDefault(), c.focus());
799
920
  };
800
921
  return r.addEventListener("keydown", s), () => r.removeEventListener("keydown", s);
801
- }, [t, e]);
922
+ }, [e, t]);
802
923
  }
803
- const et = /\*\*([^*]+)\*\*/g, tt = /\*([^*]+)\*/g, rt = /https?:\/\/[^\s)]+/g;
804
- function nt(t) {
805
- return t.replace(et, "$1").replace(tt, "$1").replace(rt, (e) => {
924
+ const it = /\*\*([^*]+)\*\*/g, ct = /\*([^*]+)\*/g, at = /https?:\/\/[^\s)]+/g;
925
+ function ut(e) {
926
+ return e.replace(it, "$1").replace(ct, "$1").replace(at, (t) => {
806
927
  try {
807
- return new URL(e).hostname;
928
+ return new URL(t).hostname;
808
929
  } catch {
809
- return e;
930
+ return t;
810
931
  }
811
932
  });
812
933
  }
813
- const st = {
934
+ const lt = {
814
935
  "bottom-right": "bottom-24 right-3 sm:right-6",
815
936
  "bottom-left": "bottom-24 left-3 sm:left-6",
816
937
  "top-right": "top-24 right-3 sm:right-6",
817
938
  "top-left": "top-24 left-3 sm:left-6"
818
939
  };
819
- function ot({
820
- messages: t,
821
- isLoading: e,
940
+ function dt({
941
+ messages: e,
942
+ isLoading: t,
822
943
  error: r,
823
944
  canRetry: s = !1,
824
945
  onSend: n,
825
946
  onRetry: o,
826
- onClose: a,
827
- title: l = "Chat",
828
- subtitle: c = "Ask me anything",
829
- welcomeMessage: u = "Hi! How can I help you today?",
830
- placeholder: h,
831
- position: E = "bottom-right",
832
- translations: g,
833
- isMobile: x = !1
947
+ onClose: c,
948
+ title: a = "Chat",
949
+ subtitle: u = "Ask me anything",
950
+ welcomeMessage: l = "Hi! How can I help you today?",
951
+ placeholder: d,
952
+ position: R = "bottom-right",
953
+ translations: p,
954
+ isMobile: w = !1
834
955
  }) {
835
- const f = Re(), w = N(null), v = N(null), [y, T] = C(null);
836
- Qe(w, !0);
837
- const { offsetY: O } = Je(
838
- v,
839
- a,
840
- x
841
- ), A = O !== 0, I = typeof window < "u" && typeof window.matchMedia == "function" ? window.matchMedia("(prefers-reduced-motion: reduce)").matches : !1;
842
- k(() => {
843
- const b = v.current;
844
- b && (b.scrollTop = b.scrollHeight);
845
- }, [t, e]), k(() => {
846
- const b = (j) => {
847
- j.key === "Escape" && !j.isComposing && a();
956
+ const y = Ce(), b = C(null), x = C(null), [v, N] = k(null);
957
+ ot(b, !0);
958
+ const { offsetY: E } = nt(
959
+ x,
960
+ c,
961
+ w
962
+ ), I = E !== 0, A = typeof window < "u" && typeof window.matchMedia == "function" ? window.matchMedia("(prefers-reduced-motion: reduce)").matches : !1;
963
+ H(() => {
964
+ const m = x.current;
965
+ m && (m.scrollTop = m.scrollHeight);
966
+ }, [e, t]), H(() => {
967
+ const m = (P) => {
968
+ P.key === "Escape" && !P.isComposing && c();
848
969
  };
849
- return document.addEventListener("keydown", b), () => document.removeEventListener("keydown", b);
850
- }, [a]);
851
- const M = (g == null ? void 0 : g.closeChat) ?? "Close chat", D = (g == null ? void 0 : g.chatMessages) ?? "Chat messages", _ = [...t].reverse().find((b) => b.role === "assistant");
852
- return /* @__PURE__ */ d(
970
+ return document.addEventListener("keydown", m), () => document.removeEventListener("keydown", m);
971
+ }, [c]);
972
+ const D = (p == null ? void 0 : p.closeChat) ?? "Close chat", S = (p == null ? void 0 : p.chatMessages) ?? "Chat messages", j = [...e].reverse().find((m) => m.role === "assistant");
973
+ return /* @__PURE__ */ h(
853
974
  "div",
854
975
  {
855
- ref: w,
976
+ ref: b,
856
977
  role: "dialog",
857
- "aria-modal": x ? "true" : void 0,
858
- "aria-labelledby": f,
859
- className: x ? "claudius-bottom-sheet fixed inset-x-0 bottom-0 z-50 flex h-[90vh] w-full flex-col overflow-hidden rounded-t-claudius-lg bg-claudius-surface shadow-claudius-elevated font-body" : `fixed ${st[E]} z-50 flex h-[min(500px,calc(100vh-7rem))] w-[calc(100vw-1.5rem)] max-w-[380px] sm:max-w-[400px] md:max-w-[440px] flex-col overflow-hidden rounded-claudius-lg bg-claudius-surface shadow-claudius-elevated font-body`,
860
- style: x && !I ? { transform: `translateY(${Math.max(0, O)}px)` } : void 0,
861
- "data-dragging": A || void 0,
978
+ "aria-modal": w ? "true" : void 0,
979
+ "aria-labelledby": y,
980
+ className: w ? "claudius-bottom-sheet fixed inset-x-0 bottom-0 z-50 flex h-[90vh] w-full flex-col overflow-hidden rounded-t-claudius-lg bg-claudius-surface shadow-claudius-elevated font-body" : `fixed ${lt[R]} z-50 flex h-[min(500px,calc(100vh-7rem))] w-[calc(100vw-1.5rem)] max-w-[380px] sm:max-w-[400px] md:max-w-[440px] flex-col overflow-hidden rounded-claudius-lg bg-claudius-surface shadow-claudius-elevated font-body`,
981
+ style: w && !A ? { transform: `translateY(${Math.max(0, E)}px)` } : void 0,
982
+ "data-dragging": I || void 0,
862
983
  children: [
863
- x && /* @__PURE__ */ i("div", { className: "flex justify-center py-2", "aria-hidden": "true", children: /* @__PURE__ */ i("div", { className: "h-1 w-8 rounded-claudius-full bg-claudius-border" }) }),
984
+ w && /* @__PURE__ */ i("div", { className: "flex justify-center py-2", "aria-hidden": "true", children: /* @__PURE__ */ i("div", { className: "h-1 w-8 rounded-claudius-full bg-claudius-border" }) }),
864
985
  /* @__PURE__ */ i(
865
- Ke,
986
+ et,
866
987
  {
867
- title: l,
868
- subtitle: c,
869
- titleId: f,
870
- closeLabel: M,
871
- onClose: a
988
+ title: a,
989
+ subtitle: u,
990
+ titleId: y,
991
+ closeLabel: D,
992
+ onClose: c
872
993
  }
873
994
  ),
874
- /* @__PURE__ */ d("div", { className: "relative flex-1 overflow-hidden", children: [
875
- y && /* @__PURE__ */ i(
876
- Ve,
995
+ /* @__PURE__ */ h("div", { className: "relative flex-1 overflow-hidden", children: [
996
+ v && /* @__PURE__ */ i(
997
+ Qe,
877
998
  {
878
- sources: y.sources,
879
- onClose: () => T(null)
999
+ sources: v.sources,
1000
+ onClose: () => N(null)
880
1001
  }
881
1002
  ),
882
- /* @__PURE__ */ d(
1003
+ /* @__PURE__ */ h(
883
1004
  "div",
884
1005
  {
885
- ref: v,
1006
+ ref: x,
886
1007
  role: "log",
887
- "aria-label": D,
1008
+ "aria-label": S,
888
1009
  className: "h-full space-y-3 overflow-y-auto px-4 py-4",
889
1010
  children: [
890
- t.length === 0 && !r && /* @__PURE__ */ i("div", { className: "mr-auto flex max-w-[85%]", children: /* @__PURE__ */ i("div", { className: "rounded-claudius-bubble rounded-bl-claudius-tail bg-claudius-assistant-bubble px-4 py-2.5 text-sm leading-relaxed text-claudius-assistant-bubble-text", children: u }) }),
891
- t.map((b) => /* @__PURE__ */ i(
892
- Ge,
1011
+ e.length === 0 && !r && /* @__PURE__ */ i("div", { className: "mr-auto flex max-w-[85%]", children: /* @__PURE__ */ i("div", { className: "rounded-claudius-bubble rounded-bl-claudius-tail bg-claudius-assistant-bubble px-4 py-2.5 text-sm leading-relaxed text-claudius-assistant-bubble-text", children: l }) }),
1012
+ e.map((m) => /* @__PURE__ */ i(
1013
+ Ve,
893
1014
  {
894
- role: b.role,
895
- content: b.content,
896
- sources: b.sources,
897
- isSourceActive: (y == null ? void 0 : y.messageId) === b.id,
1015
+ role: m.role,
1016
+ content: m.content,
1017
+ sources: m.sources,
1018
+ isSourceActive: (v == null ? void 0 : v.messageId) === m.id,
898
1019
  onSourceClick: () => {
899
- (y == null ? void 0 : y.messageId) === b.id ? T(null) : b.sources && b.sources.length > 0 && T({ messageId: b.id, sources: b.sources });
1020
+ (v == null ? void 0 : v.messageId) === m.id ? N(null) : m.sources && m.sources.length > 0 && N({ messageId: m.id, sources: m.sources });
900
1021
  }
901
1022
  },
902
- b.id
1023
+ m.id
903
1024
  )),
904
- e && /* @__PURE__ */ i(
905
- Xe,
1025
+ t && /* @__PURE__ */ i(
1026
+ rt,
906
1027
  {
907
- label: (g == null ? void 0 : g.typingIndicator) ?? "Assistant is typing"
1028
+ label: (p == null ? void 0 : p.typingIndicator) ?? "Assistant is typing"
908
1029
  }
909
1030
  ),
910
1031
  r && /* @__PURE__ */ i(
911
- qe,
1032
+ tt,
912
1033
  {
913
1034
  message: r,
914
- retryLabel: (g == null ? void 0 : g.errorRetry) ?? "Retry",
915
- onRetry: s && o && !e ? o : void 0
1035
+ retryLabel: (p == null ? void 0 : p.errorRetry) ?? "Retry",
1036
+ onRetry: s && o && !t ? o : void 0
916
1037
  }
917
1038
  )
918
1039
  ]
@@ -926,51 +1047,51 @@ function ot({
926
1047
  "aria-live": "polite",
927
1048
  "aria-atomic": "true",
928
1049
  className: "sr-only",
929
- children: _ ? nt(_.content) : ""
1050
+ children: j ? ut(j.content) : ""
930
1051
  }
931
1052
  ),
932
1053
  /* @__PURE__ */ i(
933
- We,
1054
+ qe,
934
1055
  {
935
1056
  onSend: n,
936
- isLoading: e,
937
- placeholder: h,
938
- translations: g
1057
+ isLoading: t,
1058
+ placeholder: d,
1059
+ translations: p
939
1060
  }
940
1061
  )
941
1062
  ]
942
1063
  }
943
1064
  );
944
1065
  }
945
- function it({
946
- message: t,
947
- position: e,
1066
+ function ft({
1067
+ message: e,
1068
+ position: t,
948
1069
  onOpen: r,
949
1070
  onDismiss: s,
950
1071
  dismissLabel: n
951
1072
  }) {
952
- const o = e.startsWith("bottom"), a = e.endsWith("right"), l = [
1073
+ const o = t.startsWith("bottom"), c = t.endsWith("right"), a = [
953
1074
  "claudius-greeting-bubble",
954
1075
  "fixed z-40 max-w-xs",
955
1076
  o ? "bottom-20" : "top-20",
956
- a ? "right-4" : "left-4"
1077
+ c ? "right-4" : "left-4"
957
1078
  ].join(" ");
958
- return /* @__PURE__ */ d("div", { className: l, role: "status", "aria-live": "polite", children: [
1079
+ return /* @__PURE__ */ h("div", { className: a, role: "status", "aria-live": "polite", children: [
959
1080
  /* @__PURE__ */ i(
960
1081
  "button",
961
1082
  {
962
1083
  type: "button",
963
1084
  onClick: r,
964
1085
  className: "block w-full rounded-claudius-lg bg-claudius-surface p-4 pr-8 text-left text-sm font-body text-claudius-text shadow-claudius-floating ring-1 ring-claudius-border transition hover:shadow-claudius-floating-hover focus:outline-none focus:ring-2 focus:ring-claudius-accent",
965
- children: t
1086
+ children: e
966
1087
  }
967
1088
  ),
968
1089
  /* @__PURE__ */ i(
969
1090
  "button",
970
1091
  {
971
1092
  type: "button",
972
- onClick: (c) => {
973
- c.stopPropagation(), s();
1093
+ onClick: (u) => {
1094
+ u.stopPropagation(), s();
974
1095
  },
975
1096
  "aria-label": n,
976
1097
  className: "absolute right-1 top-1 flex h-6 w-6 items-center justify-center rounded-claudius-full text-claudius-text-muted hover:bg-claudius-surface-muted focus:outline-none focus:ring-2 focus:ring-claudius-accent",
@@ -979,7 +1100,7 @@ function it({
979
1100
  )
980
1101
  ] });
981
1102
  }
982
- const ie = {
1103
+ const de = {
983
1104
  // ChatWindow
984
1105
  title: "Chat",
985
1106
  subtitle: "Ask me anything",
@@ -1002,11 +1123,11 @@ const ie = {
1002
1123
  errorRateLimitMinute: "Too many requests. Please wait a minute.",
1003
1124
  errorRateLimitHour: "Hourly limit reached. Please try again later.",
1004
1125
  errorRetry: "Retry"
1005
- }, at = ie;
1006
- function St(t) {
1007
- return { ...at, ...t };
1126
+ }, ht = de;
1127
+ function $t(e) {
1128
+ return { ...ht, ...e };
1008
1129
  }
1009
- const ct = {
1130
+ const mt = {
1010
1131
  // ChatWindow
1011
1132
  title: "Chat",
1012
1133
  subtitle: "Pregúntame lo que quieras",
@@ -1029,7 +1150,7 @@ const ct = {
1029
1150
  errorRateLimitMinute: "Demasiadas solicitudes. Espera un minuto.",
1030
1151
  errorRateLimitHour: "Has alcanzado el límite por hora. Inténtalo más tarde.",
1031
1152
  errorRetry: "Reintentar"
1032
- }, ut = {
1153
+ }, gt = {
1033
1154
  // ChatWindow
1034
1155
  title: "Chat",
1035
1156
  subtitle: "Posez-moi vos questions",
@@ -1052,7 +1173,7 @@ const ct = {
1052
1173
  errorRateLimitMinute: "Trop de requêtes. Veuillez patienter une minute.",
1053
1174
  errorRateLimitHour: "Limite horaire atteinte. Veuillez réessayer plus tard.",
1054
1175
  errorRetry: "Réessayer"
1055
- }, lt = {
1176
+ }, pt = {
1056
1177
  // ChatWindow
1057
1178
  title: "Chat",
1058
1179
  subtitle: "Fragen Sie mich alles",
@@ -1075,28 +1196,28 @@ const ct = {
1075
1196
  errorRateLimitMinute: "Zu viele Anfragen. Bitte warten Sie eine Minute.",
1076
1197
  errorRateLimitHour: "Stündliches Limit erreicht. Bitte versuchen Sie es später erneut.",
1077
1198
  errorRetry: "Erneut versuchen"
1078
- }, ae = {
1079
- en: ie,
1080
- es: ct,
1081
- fr: ut,
1082
- de: lt
1199
+ }, fe = {
1200
+ en: de,
1201
+ es: mt,
1202
+ fr: gt,
1203
+ de: pt
1083
1204
  };
1084
- function re(t) {
1085
- if (!t) return;
1086
- const e = t.toLowerCase().split("-")[0];
1087
- return Object.prototype.hasOwnProperty.call(ae, e) ? e : void 0;
1205
+ function ie(e) {
1206
+ if (!e) return;
1207
+ const t = e.toLowerCase().split("-")[0];
1208
+ return Object.prototype.hasOwnProperty.call(fe, t) ? t : void 0;
1088
1209
  }
1089
- function dt() {
1090
- const t = typeof document < "u" ? re(document.documentElement.lang) : void 0;
1091
- if (t) return t;
1092
- const e = typeof navigator < "u" ? re(navigator.language) : void 0;
1093
- return e || "en";
1210
+ function bt() {
1211
+ const e = typeof document < "u" ? ie(document.documentElement.lang) : void 0;
1212
+ if (e) return e;
1213
+ const t = typeof navigator < "u" ? ie(navigator.language) : void 0;
1214
+ return t || "en";
1094
1215
  }
1095
- function ht(t = {}) {
1096
- const { locale: e, translations: r } = t, s = ae[e ?? dt()];
1216
+ function yt(e = {}) {
1217
+ const { locale: t, translations: r } = e, s = fe[t ?? bt()];
1097
1218
  return r ? { ...s, ...r } : { ...s };
1098
1219
  }
1099
- const ne = [
1220
+ const ce = [
1100
1221
  "accent",
1101
1222
  "accentText",
1102
1223
  "accentSoft",
@@ -1116,11 +1237,11 @@ const ne = [
1116
1237
  "errorText",
1117
1238
  "link",
1118
1239
  "scrim"
1119
- ], ft = ["sm", "md", "lg", "full", "tail"], mt = [
1240
+ ], xt = ["sm", "md", "lg", "full", "tail"], wt = [
1120
1241
  "elevated",
1121
1242
  "floating",
1122
1243
  "floatingHover"
1123
- ], gt = ["heading", "body"], ce = {
1244
+ ], vt = ["heading", "body"], he = {
1124
1245
  default: {
1125
1246
  name: "default"
1126
1247
  },
@@ -1205,226 +1326,311 @@ const ne = [
1205
1326
  }
1206
1327
  }
1207
1328
  };
1208
- function bt(t) {
1209
- return Object.prototype.hasOwnProperty.call(ce, t);
1329
+ function Et(e) {
1330
+ return Object.prototype.hasOwnProperty.call(he, e);
1210
1331
  }
1211
- const pt = /* @__PURE__ */ new Set(["light", "dark", "auto"]);
1212
- function xt(t) {
1213
- if (t === void 0)
1332
+ const Rt = /* @__PURE__ */ new Set(["light", "dark", "auto"]);
1333
+ function Tt(e) {
1334
+ if (e === void 0)
1214
1335
  return { mode: "light" };
1215
- if (typeof t == "string") {
1216
- if (pt.has(t))
1217
- return { mode: t };
1218
- if (bt(t)) {
1219
- const e = ce[t];
1220
- return { mode: e.colorScheme ?? "light", theme: e };
1336
+ if (typeof e == "string") {
1337
+ if (Rt.has(e))
1338
+ return { mode: e };
1339
+ if (Et(e)) {
1340
+ const t = he[e];
1341
+ return { mode: t.colorScheme ?? "light", theme: t };
1221
1342
  }
1222
- return { mode: "light", url: t };
1343
+ return { mode: "light", url: e };
1223
1344
  }
1224
- return { mode: t.colorScheme ?? "light", theme: t };
1345
+ return { mode: e.colorScheme ?? "light", theme: e };
1225
1346
  }
1226
- function yt(t) {
1227
- return t.replace(/[A-Z]/g, (e) => `-${e.toLowerCase()}`);
1347
+ function Mt(e) {
1348
+ return e.replace(/[A-Z]/g, (t) => `-${t.toLowerCase()}`);
1228
1349
  }
1229
- function wt(t, e) {
1350
+ function Ct(e, t) {
1230
1351
  console.warn(
1231
- `[Claudius] Ignoring unknown theme token "${e}" in "${t}"`
1352
+ `[Claudius] Ignoring unknown theme token "${t}" in "${e}"`
1232
1353
  );
1233
1354
  }
1234
- function B(t, e, r, s, n, o = "") {
1355
+ function W(e, t, r, s, n, o = "") {
1235
1356
  if (n)
1236
- for (const [a, l] of Object.entries(n)) {
1237
- if (!s.includes(a)) {
1238
- wt(e, a);
1357
+ for (const [c, a] of Object.entries(n)) {
1358
+ if (!s.includes(c)) {
1359
+ Ct(t, c);
1239
1360
  continue;
1240
1361
  }
1241
- typeof l == "string" && (t[`${r}${yt(a)}${o}`] = l);
1362
+ typeof a == "string" && (e[`${r}${Mt(c)}${o}`] = a);
1242
1363
  }
1243
1364
  }
1244
- function vt(t) {
1245
- const e = {};
1246
- B(e, "colors", "--cl-color-", ne, t.colors);
1247
- for (const [r, s] of Object.entries({ ...e }))
1248
- e[`${r}-dark`] = s;
1249
- return B(
1250
- e,
1365
+ function Nt(e) {
1366
+ const t = {};
1367
+ W(t, "colors", "--cl-color-", ce, e.colors);
1368
+ for (const [r, s] of Object.entries({ ...t }))
1369
+ t[`${r}-dark`] = s;
1370
+ return W(
1371
+ t,
1251
1372
  "colorsDark",
1252
1373
  "--cl-color-",
1253
- ne,
1254
- t.colorsDark,
1374
+ ce,
1375
+ e.colorsDark,
1255
1376
  "-dark"
1256
- ), B(e, "radii", "--cl-radius-", ft, t.radii), B(e, "shadows", "--cl-shadow-", mt, t.shadows), B(e, "fonts", "--cl-font-", gt, t.fonts), e;
1377
+ ), W(t, "radii", "--cl-radius-", xt, e.radii), W(t, "shadows", "--cl-shadow-", wt, e.shadows), W(t, "fonts", "--cl-font-", vt, e.fonts), t;
1257
1378
  }
1258
- function Et(t) {
1259
- return typeof t == "object" && t !== null && !Array.isArray(t);
1379
+ function St(e) {
1380
+ return typeof e == "object" && e !== null && !Array.isArray(e);
1260
1381
  }
1261
- function Rt(t) {
1262
- const e = F(() => xt(t), [t]), [r, s] = C(null), n = e.url;
1263
- k(() => {
1382
+ function Lt(e) {
1383
+ const t = Y(() => Tt(e), [e]), [r, s] = k(null), n = t.url;
1384
+ H(() => {
1264
1385
  if (s(null), !n) return;
1265
- const c = new AbortController();
1266
- return fetch(n, { signal: c.signal }).then((u) => {
1267
- if (!u.ok)
1268
- throw new Error(`HTTP ${u.status}`);
1269
- return u.json();
1270
- }).then((u) => {
1271
- if (!Et(u))
1386
+ const u = new AbortController();
1387
+ return fetch(n, { signal: u.signal }).then((l) => {
1388
+ if (!l.ok)
1389
+ throw new Error(`HTTP ${l.status}`);
1390
+ return l.json();
1391
+ }).then((l) => {
1392
+ if (!St(l))
1272
1393
  throw new Error("theme JSON must be an object");
1273
- s(u);
1274
- }).catch((u) => {
1275
- c.signal.aborted || console.error(`[Claudius] Failed to load theme from ${n}:`, u);
1276
- }), () => c.abort();
1394
+ s(l);
1395
+ }).catch((l) => {
1396
+ u.signal.aborted || console.error(`[Claudius] Failed to load theme from ${n}:`, l);
1397
+ }), () => u.abort();
1277
1398
  }, [n]);
1278
- const o = e.theme ?? r ?? null, a = (r == null ? void 0 : r.colorScheme) ?? e.mode, l = F(
1279
- () => o ? vt(o) : {},
1399
+ const o = t.theme ?? r ?? null, c = (r == null ? void 0 : r.colorScheme) ?? t.mode, a = Y(
1400
+ () => o ? Nt(o) : {},
1280
1401
  [o]
1281
1402
  );
1282
- return { mode: a, cssVars: l };
1403
+ return { mode: c, cssVars: a };
1283
1404
  }
1284
- const ue = "claudius:triggers:dismissed";
1285
- function Tt() {
1405
+ const me = "claudius:triggers:dismissed";
1406
+ function kt() {
1286
1407
  if (typeof window > "u") return !1;
1287
1408
  try {
1288
- return window.sessionStorage.getItem(ue) === "1";
1409
+ return window.sessionStorage.getItem(me) === "1";
1289
1410
  } catch {
1290
1411
  return !1;
1291
1412
  }
1292
1413
  }
1293
- function Mt() {
1414
+ function At() {
1294
1415
  if (!(typeof window > "u"))
1295
1416
  try {
1296
- window.sessionStorage.setItem(ue, "1");
1417
+ window.sessionStorage.setItem(me, "1");
1297
1418
  } catch {
1298
1419
  }
1299
1420
  }
1300
- function kt({
1301
- apiUrl: t,
1302
- title: e,
1421
+ function jt({
1422
+ apiUrl: e,
1423
+ title: t,
1303
1424
  subtitle: r,
1304
1425
  welcomeMessage: s,
1305
1426
  placeholder: n,
1306
1427
  persistMessages: o,
1307
- storageKeyPrefix: a,
1308
- requestTimeoutMs: l,
1309
- theme: c = "light",
1310
- accentColor: u,
1311
- position: h = "bottom-right",
1312
- locale: E,
1313
- translations: g,
1314
- triggers: x
1428
+ storageKeyPrefix: c,
1429
+ requestTimeoutMs: a,
1430
+ theme: u = "light",
1431
+ accentColor: l,
1432
+ position: d = "bottom-right",
1433
+ locale: R,
1434
+ translations: p,
1435
+ triggers: w,
1436
+ plugins: y
1315
1437
  }) {
1316
- const [f, w] = C(!1), [v, y] = C(null), [T, O] = C(Tt), A = N(!1), I = Oe("(max-width: 639px)"), M = F(
1317
- () => ht({ locale: E, translations: g }),
1318
- [E, g]
1319
- ), { messages: D, isLoading: _, error: b, canRetry: j, sendMessage: m, retry: p } = ke({
1320
- apiUrl: t,
1438
+ const [b, x] = k(!1), [v, N] = k(null), [E, I] = k(kt), A = C(!1), D = Be("(max-width: 639px)"), S = Y(
1439
+ () => yt({ locale: R, translations: p }),
1440
+ [R, p]
1441
+ ), { messages: j, isLoading: m, error: P, canRetry: V, sendMessage: K, retry: f } = He({
1442
+ apiUrl: e,
1321
1443
  persistMessages: o,
1322
- storageKeyPrefix: a,
1323
- timeoutMs: l,
1324
- translations: M
1325
- }), H = N(null), L = N(f), { mode: G, cssVars: le } = Rt(c), [de, q] = C(!1);
1326
- k(() => {
1327
- if (G !== "auto") return;
1328
- const S = window.matchMedia("(prefers-color-scheme: dark)");
1329
- q(S.matches);
1330
- const Z = (xe) => q(xe.matches);
1331
- return S.addEventListener("change", Z), () => S.removeEventListener("change", Z);
1332
- }, [G]), k(() => {
1333
- var S;
1334
- L.current && !f && ((S = H.current) == null || S.focus()), L.current = f;
1335
- }, [f]);
1336
- const P = R(() => {
1337
- O(!0), Mt();
1338
- }, []), X = R(() => {
1339
- w(!1), A.current && (A.current = !1, P());
1340
- }, [P]), he = R(() => {
1341
- w((S) => !S);
1342
- }, []), Y = R(() => {
1343
- A.current = !0, y(null), w(!0);
1344
- }, []), fe = R((S) => {
1345
- y(S);
1346
- }, []), me = R(() => {
1347
- y(null), Y();
1348
- }, [Y]), ge = R(() => {
1349
- y(null), P();
1350
- }, [P]);
1351
- Ie({
1352
- triggers: x,
1353
- enabled: !T && !f,
1354
- onOpen: Y,
1355
- onGreeting: fe
1444
+ storageKeyPrefix: c,
1445
+ timeoutMs: a,
1446
+ translations: S,
1447
+ plugins: y
1448
+ }), g = C(null), L = C(b), { mode: T, cssVars: B } = Lt(u), [O, z] = k(!1);
1449
+ H(() => {
1450
+ if (T !== "auto") return;
1451
+ const _ = window.matchMedia("(prefers-color-scheme: dark)");
1452
+ z(_.matches);
1453
+ const re = (ve) => z(ve.matches);
1454
+ return _.addEventListener("change", re), () => _.removeEventListener("change", re);
1455
+ }, [T]), H(() => {
1456
+ var _;
1457
+ L.current && !b && ((_ = g.current) == null || _.focus()), L.current = b;
1458
+ }, [b]);
1459
+ const $ = M(() => {
1460
+ I(!0), At();
1461
+ }, []), ee = M(() => {
1462
+ x(!1), A.current && (A.current = !1, $());
1463
+ }, [$]), ge = M(() => {
1464
+ x((_) => !_);
1465
+ }, []), q = M(() => {
1466
+ A.current = !0, N(null), x(!0);
1467
+ }, []), pe = M((_) => {
1468
+ N(_);
1469
+ }, []), be = M(() => {
1470
+ N(null), q();
1471
+ }, [q]), ye = M(() => {
1472
+ N(null), $();
1473
+ }, [$]);
1474
+ je({
1475
+ triggers: w,
1476
+ enabled: !E && !b,
1477
+ onOpen: q,
1478
+ onGreeting: pe
1356
1479
  });
1357
- const be = G === "dark" || G === "auto" && de, J = {
1358
- ...le,
1359
- ...u ? {
1360
- "--cl-color-accent": u,
1361
- "--cl-color-accent-dark": u
1480
+ const xe = T === "dark" || T === "auto" && O, te = {
1481
+ ...B,
1482
+ ...l ? {
1483
+ "--cl-color-accent": l,
1484
+ "--cl-color-accent-dark": l
1362
1485
  } : {}
1363
- }, pe = Object.keys(J).length > 0 ? J : void 0;
1486
+ }, we = Object.keys(te).length > 0 ? te : void 0;
1364
1487
  return (
1365
1488
  // Outer div carries theme token vars; the inner div carries the dark-mode
1366
1489
  // attribute so the [data-claudius-dark] token reassignments in styles.css
1367
1490
  // beat inherited (inline) light values.
1368
- /* @__PURE__ */ i("div", { className: "claudius-root", style: pe, children: /* @__PURE__ */ d("div", { "data-claudius-dark": be ? "true" : "false", children: [
1369
- f && I && /* @__PURE__ */ i(
1491
+ /* @__PURE__ */ i("div", { className: "claudius-root", style: we, children: /* @__PURE__ */ h("div", { "data-claudius-dark": xe ? "true" : "false", children: [
1492
+ b && D && /* @__PURE__ */ i(
1370
1493
  "div",
1371
1494
  {
1372
1495
  className: "claudius-scrim fixed inset-0 z-40 bg-claudius-scrim",
1373
- onClick: X,
1496
+ onClick: ee,
1374
1497
  "aria-hidden": "true"
1375
1498
  }
1376
1499
  ),
1377
- f && /* @__PURE__ */ i(
1378
- ot,
1500
+ b && /* @__PURE__ */ i(
1501
+ dt,
1379
1502
  {
1380
- messages: D,
1381
- isLoading: _,
1382
- error: b,
1383
- canRetry: j,
1384
- onSend: m,
1385
- onRetry: p,
1386
- onClose: X,
1387
- title: e ?? M.title,
1388
- subtitle: r ?? M.subtitle,
1389
- welcomeMessage: s ?? M.welcomeMessage,
1390
- placeholder: n ?? M.placeholder,
1391
- position: h,
1392
- translations: M,
1393
- isMobile: I
1503
+ messages: j,
1504
+ isLoading: m,
1505
+ error: P,
1506
+ canRetry: V,
1507
+ onSend: K,
1508
+ onRetry: f,
1509
+ onClose: ee,
1510
+ title: t ?? S.title,
1511
+ subtitle: r ?? S.subtitle,
1512
+ welcomeMessage: s ?? S.welcomeMessage,
1513
+ placeholder: n ?? S.placeholder,
1514
+ position: d,
1515
+ translations: S,
1516
+ isMobile: D
1394
1517
  }
1395
1518
  ),
1396
- !(f && I) && /* @__PURE__ */ i(
1397
- He,
1519
+ !(b && D) && /* @__PURE__ */ i(
1520
+ Ge,
1398
1521
  {
1399
- ref: H,
1400
- isOpen: f,
1401
- onClick: he,
1402
- position: h,
1403
- translations: M
1522
+ ref: g,
1523
+ isOpen: b,
1524
+ onClick: ge,
1525
+ position: d,
1526
+ translations: S
1404
1527
  }
1405
1528
  ),
1406
- !f && v && /* @__PURE__ */ i(
1407
- it,
1529
+ !b && v && /* @__PURE__ */ i(
1530
+ ft,
1408
1531
  {
1409
1532
  message: v,
1410
- position: h,
1411
- onOpen: me,
1412
- onDismiss: ge,
1413
- dismissLabel: M.dismissGreeting
1533
+ position: d,
1534
+ onOpen: be,
1535
+ onDismiss: ye,
1536
+ dismissLabel: S.dismissGreeting
1414
1537
  }
1415
1538
  )
1416
1539
  ] }) })
1417
1540
  );
1418
1541
  }
1542
+ function Pt(e) {
1543
+ const { onEvent: t, includeContent: r = !0 } = e, s = (n) => r ? n : "";
1544
+ return {
1545
+ name: "analytics",
1546
+ onBeforeSend(n) {
1547
+ t({
1548
+ type: "message_sent",
1549
+ role: "user",
1550
+ content: s(n.content),
1551
+ chars: n.content.length
1552
+ });
1553
+ },
1554
+ onAfterReceive(n) {
1555
+ t({
1556
+ type: "message_received",
1557
+ role: "assistant",
1558
+ content: s(n.content),
1559
+ chars: n.content.length
1560
+ });
1561
+ },
1562
+ onError(n) {
1563
+ t({
1564
+ type: "chat_error",
1565
+ message: n.message,
1566
+ code: n.code
1567
+ });
1568
+ }
1569
+ };
1570
+ }
1571
+ const Ot = [
1572
+ // Email
1573
+ /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/g,
1574
+ // US SSN (before the looser card pattern so it wins on 9-digit groups)
1575
+ /\b\d{3}-\d{2}-\d{4}\b/g,
1576
+ // Card-like: 13–16 digits, optionally separated by spaces or hyphens
1577
+ /\b(?:\d[ -]?){13,16}\b/g,
1578
+ // Phone: optional +1, area code, 7 digits with common separators
1579
+ /\b(?:\+?1[-.\s]?)?\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}\b/g
1580
+ ];
1581
+ function It(e, t, r) {
1582
+ return t.reduce(
1583
+ // Reset lastIndex defensively: a shared global regex is stateful.
1584
+ (s, n) => (n.lastIndex = 0, s.replace(n, r)),
1585
+ e
1586
+ );
1587
+ }
1588
+ function Gt(e = {}) {
1589
+ const {
1590
+ patterns: t = Ot,
1591
+ replacement: r = "[redacted]",
1592
+ redactReplies: s = !1
1593
+ } = e, n = (o) => {
1594
+ const c = It(o.content, t, r);
1595
+ if (c !== o.content)
1596
+ return { ...o, content: c };
1597
+ };
1598
+ return {
1599
+ name: "redact-pii",
1600
+ onBeforeSend: n,
1601
+ onAfterReceive: s ? n : void 0
1602
+ };
1603
+ }
1604
+ function Dt(e, t, r) {
1605
+ return typeof e == "function" ? e(t) : e instanceof RegExp ? e.test(t) : r ? t.includes(e) : t.toLowerCase().includes(e.toLowerCase());
1606
+ }
1607
+ function Ut(e) {
1608
+ const { rules: t, caseSensitive: r = !1 } = e;
1609
+ return {
1610
+ name: "canned-responses",
1611
+ onBeforeSend(s, n) {
1612
+ for (const o of t)
1613
+ if (Dt(o.match, s.content, r)) {
1614
+ n.respondWith(o.reply);
1615
+ return;
1616
+ }
1617
+ }
1618
+ };
1619
+ }
1419
1620
  export {
1420
- Me as ChatApiClient,
1621
+ Se as ChatApiClient,
1421
1622
  U as ChatApiError,
1422
- kt as ChatWidget,
1423
- se as DebounceError,
1424
- ce as builtinThemes,
1425
- St as createTranslations,
1426
- at as defaultTranslations,
1427
- dt as detectLocale,
1428
- ae as locales,
1429
- ht as resolveTranslations
1623
+ jt as ChatWidget,
1624
+ Ot as DEFAULT_PII_PATTERNS,
1625
+ ae as DebounceError,
1626
+ he as builtinThemes,
1627
+ $t as createTranslations,
1628
+ ht as defaultTranslations,
1629
+ bt as detectLocale,
1630
+ fe as locales,
1631
+ Pt as pluginAnalytics,
1632
+ Ut as pluginCannedResponses,
1633
+ Gt as pluginRedactPII,
1634
+ It as redactText,
1635
+ yt as resolveTranslations
1430
1636
  };