@cloudflare/ai-search-snippet 0.0.23 → 0.0.24

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.
@@ -1,23 +1,35 @@
1
- var A = Object.defineProperty;
2
- var R = (o, i, e) => i in o ? A(o, i, { enumerable: !0, configurable: !0, writable: !0, value: e }) : o[i] = e;
3
- var r = (o, i, e) => R(o, typeof i != "symbol" ? i + "" : i, e);
4
- function T(o, i) {
1
+ var R = Object.defineProperty;
2
+ var H = (o, i, e) => i in o ? R(o, i, { enumerable: !0, configurable: !0, writable: !0, value: e }) : o[i] = e;
3
+ var a = (o, i, e) => H(o, typeof i != "symbol" ? i + "" : i, e);
4
+ const u = [
5
+ "Searching...",
6
+ "Digging through results...",
7
+ "Scanning the knowledge base...",
8
+ "Finding the best matches...",
9
+ "Sifting through the data...",
10
+ "Almost there...",
11
+ "Looking far and wide...",
12
+ "Connecting the dots...",
13
+ "Rummaging through pages...",
14
+ "Hunting down answers..."
15
+ ];
16
+ function A(o, i) {
5
17
  let e;
6
18
  return function(...s) {
7
- const a = () => {
19
+ const r = () => {
8
20
  clearTimeout(e), o(...s);
9
21
  };
10
- clearTimeout(e), e = setTimeout(a, i);
22
+ clearTimeout(e), e = setTimeout(r, i);
11
23
  };
12
24
  }
13
25
  function l(o) {
14
26
  const i = document.createElement("div");
15
27
  return i.textContent = o, i.innerHTML;
16
28
  }
17
- function C(o) {
29
+ function S(o) {
18
30
  return new DOMParser().parseFromString(o, "text/html").documentElement.textContent || "";
19
31
  }
20
- function H(o) {
32
+ function N(o) {
21
33
  const i = new Date(o), t = (/* @__PURE__ */ new Date()).getTime() - i.getTime();
22
34
  if (t < 6e4)
23
35
  return "Just now";
@@ -36,21 +48,21 @@ function H(o) {
36
48
  minute: "2-digit"
37
49
  });
38
50
  }
39
- function S(o = "id") {
51
+ function E(o = "id") {
40
52
  return `${o}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
41
53
  }
42
- function u(o, i) {
54
+ function g(o, i) {
43
55
  return o !== null ? o : i;
44
56
  }
45
- function v(o, i) {
57
+ function b(o, i) {
46
58
  return o === null ? i : o === "true" || o === "";
47
59
  }
48
- function f(o, i) {
60
+ function w(o, i) {
49
61
  if (o === null) return i;
50
62
  const e = Number.parseInt(o, 10);
51
63
  return Number.isNaN(e) ? i : e;
52
64
  }
53
- function m(o, i) {
65
+ function v(o, i) {
54
66
  return new CustomEvent(o, {
55
67
  detail: i,
56
68
  bubbles: !0,
@@ -58,15 +70,15 @@ function m(o, i) {
58
70
  cancelable: !0
59
71
  });
60
72
  }
61
- function w(o) {
73
+ function y(o) {
62
74
  if (!o)
63
75
  throw new Error("API URL is required");
64
76
  return new P(o);
65
77
  }
66
- class N {
78
+ class _ {
67
79
  constructor(i) {
68
- r(this, "activeRequests", /* @__PURE__ */ new Map());
69
- r(this, "baseUrl");
80
+ a(this, "activeRequests", /* @__PURE__ */ new Map());
81
+ a(this, "baseUrl");
70
82
  this.baseUrl = i.replace(/\/$/, "");
71
83
  }
72
84
  search(i, e) {
@@ -85,7 +97,7 @@ class N {
85
97
  throw new Error("Not implemented");
86
98
  }
87
99
  }
88
- class P extends N {
100
+ class P extends _ {
89
101
  request(i = {}, e, t) {
90
102
  const s = e === "search" ? "snippet-search" : "snippet-chat-completions";
91
103
  return fetch(`${this.baseUrl}/${e}`, {
@@ -109,7 +121,7 @@ class P extends N {
109
121
  * Performs a search query with optional streaming
110
122
  */
111
123
  async search(i, e = {}) {
112
- const t = this.generateRequestId(), s = new AbortController(), a = e.signal || s.signal;
124
+ const t = this.generateRequestId(), s = new AbortController(), r = e.signal || s.signal;
113
125
  this.registerRequest(t, s);
114
126
  try {
115
127
  const n = await this.request(
@@ -119,7 +131,7 @@ class P extends N {
119
131
  maxResults: 30
120
132
  },
121
133
  "search",
122
- a
134
+ r
123
135
  );
124
136
  if (!n.ok)
125
137
  throw new Error(`HTTP error! status: ${n.status}`);
@@ -129,15 +141,15 @@ class P extends N {
129
141
  if (c.success && c.result) {
130
142
  const h = /* @__PURE__ */ new Map();
131
143
  for (const d of c.result.chunks) {
132
- const g = d.item.key, p = d.scoring_details.vector_score;
133
- (!h.has(g) || (h.get(g)?.score ?? 0) < p) && h.set(g, { chunk: d, score: p });
144
+ const m = d.item.key, p = d.scoring_details.vector_score;
145
+ (!h.has(m) || (h.get(m)?.score ?? 0) < p) && h.set(m, { chunk: d, score: p });
134
146
  }
135
- return Array.from(h.values()).sort((d, g) => g.score - d.score).slice(0, 10).map(
147
+ return Array.from(h.values()).sort((d, m) => m.score - d.score).slice(0, 10).map(
136
148
  ({ chunk: d }) => ({
137
149
  type: "result",
138
150
  id: d.id,
139
- title: C(d.item.metadata.title),
140
- description: d.item.metadata.description ? C(d.item.metadata.description) : "",
151
+ title: S(d.item.metadata.title),
152
+ description: d.item.metadata.description ? S(d.item.metadata.description) : "",
141
153
  url: d.item.key,
142
154
  image: d.item.metadata.image || void 0,
143
155
  metadata: d.item.metadata
@@ -150,7 +162,7 @@ class P extends N {
150
162
  }
151
163
  }
152
164
  async *searchStream(i, e) {
153
- const t = this.generateRequestId(), s = new AbortController(), a = e?.signal || s.signal;
165
+ const t = this.generateRequestId(), s = new AbortController(), r = e?.signal || s.signal;
154
166
  this.registerRequest(t, s);
155
167
  const n = await this.request(
156
168
  {
@@ -158,7 +170,7 @@ class P extends N {
158
170
  streaming: !0
159
171
  },
160
172
  "ai-search",
161
- a
173
+ r
162
174
  );
163
175
  if (!n.ok)
164
176
  throw new Error(`HTTP error! status: ${n.status}`);
@@ -167,10 +179,10 @@ class P extends N {
167
179
  let c = "";
168
180
  const h = n.body.getReader(), d = new TextDecoder();
169
181
  for (; ; ) {
170
- const { done: p, value: k } = await h.read();
182
+ const { done: p, value: C } = await h.read();
171
183
  if (p)
172
184
  break;
173
- const B = d.decode(k, { stream: !0 });
185
+ const B = d.decode(C, { stream: !0 });
174
186
  c += B;
175
187
  }
176
188
  yield {
@@ -185,7 +197,7 @@ class P extends N {
185
197
  };
186
198
  }
187
199
  async *chat(i, e) {
188
- const t = new AbortController(), s = e?.signal || t.signal, a = await this.request(
200
+ const t = new AbortController(), s = e?.signal || t.signal, r = await this.request(
189
201
  {
190
202
  query: i,
191
203
  streaming: !1
@@ -193,13 +205,13 @@ class P extends N {
193
205
  "chat/completions",
194
206
  s
195
207
  );
196
- if (!a.ok)
197
- throw new Error(`HTTP error! status: ${a.status}`);
198
- if (!a.body)
208
+ if (!r.ok)
209
+ throw new Error(`HTTP error! status: ${r.status}`);
210
+ if (!r.body)
199
211
  throw new Error("Response body is empty");
200
212
  yield {
201
213
  type: "text",
202
- message: (await a.json()).choices.map((c) => c.message.content).join("")
214
+ message: (await r.json()).choices.map((c) => c.message.content).join("")
203
215
  };
204
216
  }
205
217
  /**
@@ -239,10 +251,10 @@ class P extends N {
239
251
  return `req-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
240
252
  }
241
253
  }
242
- const _ = `<svg width="32" height="10" viewBox="0 0 412 186" xmlns="http://www.w3.org/2000/svg" aria-label="Cloudflare" role="img">
254
+ const V = `<svg width="32" height="10" viewBox="0 0 412 186" xmlns="http://www.w3.org/2000/svg" aria-label="Cloudflare" role="img">
243
255
  <path fill="#f38020" d="m280.8395,183.31456c11,-26 -4,-38 -19,-38l-148,-2c-4,0 -4,-6 1,-7l150,-2c17,-1 37,-15 43,-33c0,0 10,-21 9,-24a97,97 0 0 0 -187,-11c-38,-25 -78,9 -69,46c-48,3 -65,46 -60,72c0,1 1,2 3,2l274,0c1,0 3,-1 3,-3z"/>
244
256
  <path fill="#faae40" d="m330.8395,81.31456c-4,0 -6,-1 -7,1l-5,21c-5,16 3,30 20,31l32,2c4,0 4,6 -1,7l-33,1c-36,4 -46,39 -46,39c0,2 0,3 2,3l113,0l3,-2a81,81 0 0 0 -78,-103"/>
245
- </svg>`, j = "https://search.ai.cloudflare.com", y = `Powered by <a href="${j}" target="_blank" rel="noopener noreferrer">Cloudflare AI Search ${_}</a>`, $ = `
257
+ </svg>`, D = "https://search.ai.cloudflare.com", x = `Powered by <a href="${D}" target="_blank" rel="noopener noreferrer">Cloudflare AI Search ${V}</a>`, $ = `
246
258
  /* Chat container */
247
259
  .chat-container {
248
260
  display: flex;
@@ -437,6 +449,10 @@ const _ = `<svg width="32" height="10" viewBox="0 0 412 186" xmlns="http://www.w
437
449
  }
438
450
  }
439
451
 
452
+ .chat-streaming .loading-text {
453
+ margin-left: var(--search-snippet-spacing-xs);
454
+ }
455
+
440
456
  /* Input area */
441
457
  .chat-input-area {
442
458
  padding: var(--search-snippet-spacing-md);
@@ -555,7 +571,7 @@ const _ = `<svg width="32" height="10" viewBox="0 0 412 186" xmlns="http://www.w
555
571
  .chat-message-bubble a:hover {
556
572
  text-decoration: none;
557
573
  }
558
- `, x = `
574
+ `, k = `
559
575
  :host {
560
576
  /* Colors - Light Mode */
561
577
  --search-snippet-primary-color: #2563eb;
@@ -890,6 +906,27 @@ const _ = `<svg width="32" height="10" viewBox="0 0 412 186" xmlns="http://www.w
890
906
  to { transform: rotate(360deg); }
891
907
  }
892
908
 
909
+ /* Loading message animation */
910
+ @keyframes loading-message-in {
911
+ from {
912
+ opacity: 0;
913
+ transform: translateY(8px);
914
+ }
915
+ to {
916
+ opacity: 1;
917
+ transform: translateY(0);
918
+ }
919
+ }
920
+
921
+ .loading-text {
922
+ font-size: var(--search-snippet-font-size-sm);
923
+ color: var(--search-snippet-text-secondary);
924
+ }
925
+
926
+ .loading-text-animate {
927
+ animation: loading-message-in 0.3s ease-out;
928
+ }
929
+
893
930
  /* Error message */
894
931
  .error {
895
932
  padding: var(--search-snippet-spacing-md);
@@ -969,17 +1006,17 @@ const _ = `<svg width="32" height="10" viewBox="0 0 412 186" xmlns="http://www.w
969
1006
  text-align: center;
970
1007
  }
971
1008
  `;
972
- function K(o) {
1009
+ function O(o) {
973
1010
  let i = o;
974
- i = V(i), i = i.replace(/```([\s\S]*?)```/g, (n, c) => `<pre><code>${c.trim()}</code></pre>`);
1011
+ i = j(i), i = i.replace(/```([\s\S]*?)```/g, (n, c) => `<pre><code>${c.trim()}</code></pre>`);
975
1012
  const e = i.split(`
976
1013
  `), t = [];
977
- let s = !1, a = "";
1014
+ let s = !1, r = "";
978
1015
  for (let n = 0; n < e.length; n++) {
979
1016
  const c = e[n], h = c.match(/^(#{1,6})\s+(.+)$/);
980
1017
  if (h) {
981
- const p = h[1].length, k = h[2];
982
- t.push(`<h${p}>${b(k)}</h${p}>`);
1018
+ const p = h[1].length, C = h[2];
1019
+ t.push(`<h${p}>${f(C)}</h${p}>`);
983
1020
  continue;
984
1021
  }
985
1022
  if (c.match(/^---+$/)) {
@@ -988,36 +1025,36 @@ function K(o) {
988
1025
  }
989
1026
  if (c.match(/^>\s+/)) {
990
1027
  const p = c.replace(/^>\s+/, "");
991
- t.push(`<blockquote>${b(p)}</blockquote>`);
1028
+ t.push(`<blockquote>${f(p)}</blockquote>`);
992
1029
  continue;
993
1030
  }
994
1031
  const d = c.match(/^[-*]\s+(.+)$/);
995
1032
  if (d) {
996
- (!s || a !== "ul") && (s && t.push(`</${a}>`), t.push("<ul>"), s = !0, a = "ul"), t.push(`<li>${b(d[1])}</li>`);
1033
+ (!s || r !== "ul") && (s && t.push(`</${r}>`), t.push("<ul>"), s = !0, r = "ul"), t.push(`<li>${f(d[1])}</li>`);
997
1034
  continue;
998
1035
  }
999
- const g = c.match(/^\d+\.\s+(.+)$/);
1000
- if (g) {
1001
- (!s || a !== "ol") && (s && t.push(`</${a}>`), t.push("<ol>"), s = !0, a = "ol"), t.push(`<li>${b(g[1])}</li>`);
1036
+ const m = c.match(/^\d+\.\s+(.+)$/);
1037
+ if (m) {
1038
+ (!s || r !== "ol") && (s && t.push(`</${r}>`), t.push("<ol>"), s = !0, r = "ol"), t.push(`<li>${f(m[1])}</li>`);
1002
1039
  continue;
1003
1040
  }
1004
- if (s && (t.push(`</${a}>`), s = !1, a = ""), c.trim() === "") {
1041
+ if (s && (t.push(`</${r}>`), s = !1, r = ""), c.trim() === "") {
1005
1042
  t.push("<br />");
1006
1043
  continue;
1007
1044
  }
1008
- t.push(`<p>${b(c)}</p>`);
1045
+ t.push(`<p>${f(c)}</p>`);
1009
1046
  }
1010
- return s && t.push(`</${a}>`), t.join(`
1047
+ return s && t.push(`</${r}>`), t.join(`
1011
1048
  `);
1012
1049
  }
1013
- function b(o) {
1050
+ function f(o) {
1014
1051
  let i = o;
1015
1052
  return i = i.replace(/`([^`]+)`/g, "<code>$1</code>"), i = i.replace(/\*\*\*(.+?)\*\*\*/g, "<strong><em>$1</em></strong>"), i = i.replace(/___(.+?)___/g, "<strong><em>$1</em></strong>"), i = i.replace(/\*\*(.+?)\*\*/g, "<strong>$1</strong>"), i = i.replace(/__(.+?)__/g, "<strong>$1</strong>"), i = i.replace(/\*(.+?)\*/g, "<em>$1</em>"), i = i.replace(/_(.+?)_/g, "<em>$1</em>"), i = i.replace(
1016
1053
  /\[([^\]]+)\]\(([^)]+)\)/g,
1017
1054
  '<a href="$2" target="_blank" rel="noopener noreferrer">$1</a>'
1018
1055
  ), i;
1019
1056
  }
1020
- function V(o) {
1057
+ function j(o) {
1021
1058
  const i = {
1022
1059
  "&": "&amp;",
1023
1060
  "<": "&lt;",
@@ -1029,19 +1066,21 @@ function V(o) {
1029
1066
  }
1030
1067
  class q {
1031
1068
  constructor(i, e, t) {
1032
- r(this, "container");
1033
- r(this, "client");
1034
- r(this, "props");
1035
- r(this, "inputElement", null);
1036
- r(this, "messagesContainer", null);
1037
- r(this, "sendButton", null);
1038
- r(this, "messages", []);
1039
- r(this, "isStreaming", !1);
1040
- r(this, "currentStreamingMessageId", null);
1069
+ a(this, "container");
1070
+ a(this, "client");
1071
+ a(this, "props");
1072
+ a(this, "inputElement", null);
1073
+ a(this, "messagesContainer", null);
1074
+ a(this, "sendButton", null);
1075
+ a(this, "messages", []);
1076
+ a(this, "isStreaming", !1);
1077
+ a(this, "currentStreamingMessageId", null);
1078
+ a(this, "loadingMessageInterval", null);
1079
+ a(this, "loadingMessageIndex", 0);
1041
1080
  // Event handler references for cleanup
1042
- r(this, "handleInputResize", null);
1043
- r(this, "handleInputKeydown", null);
1044
- r(this, "handleSendClick", null);
1081
+ a(this, "handleInputResize", null);
1082
+ a(this, "handleInputKeydown", null);
1083
+ a(this, "handleSendClick", null);
1045
1084
  this.container = i, this.client = e, this.props = t, this.render(), this.attachEventListeners();
1046
1085
  }
1047
1086
  /**
@@ -1104,13 +1143,13 @@ class q {
1104
1143
  */
1105
1144
  async sendMessage(i) {
1106
1145
  const e = {
1107
- id: S("msg"),
1146
+ id: E("msg"),
1108
1147
  role: "user",
1109
1148
  content: i,
1110
1149
  timestamp: Date.now()
1111
1150
  };
1112
1151
  this.addMessage(e), this.renderMessages(!0), this.setStreamingState(!0);
1113
- const t = S("msg"), s = {
1152
+ const t = E("msg"), s = {
1114
1153
  id: t,
1115
1154
  role: "assistant",
1116
1155
  content: "",
@@ -1118,9 +1157,9 @@ class q {
1118
1157
  };
1119
1158
  this.addMessage(s), this.currentStreamingMessageId = t, this.renderMessages(!0);
1120
1159
  try {
1121
- const a = this.client.chat(i);
1160
+ const r = this.client.chat(i);
1122
1161
  let n = "";
1123
- for await (const h of a)
1162
+ for await (const h of r)
1124
1163
  if (h.type === "text" && h.message)
1125
1164
  n += h.message, this.updateStreamingMessage(t, n);
1126
1165
  else if (h.type === "error") {
@@ -1128,12 +1167,12 @@ class q {
1128
1167
  break;
1129
1168
  }
1130
1169
  const c = this.messages.findIndex((h) => h.id === t);
1131
- c !== -1 && (this.messages[c].content = n), this.container.dispatchEvent(m("message", { message: s }));
1132
- } catch (a) {
1133
- this.showErrorInMessage(t, a.message), this.container.dispatchEvent(
1134
- m("error", {
1170
+ c !== -1 && (this.messages[c].content = n), this.container.dispatchEvent(v("message", { message: s }));
1171
+ } catch (r) {
1172
+ this.showErrorInMessage(t, r.message), this.container.dispatchEvent(
1173
+ v("error", {
1135
1174
  error: {
1136
- message: a.message,
1175
+ message: r.message,
1137
1176
  code: "CHAT_ERROR"
1138
1177
  }
1139
1178
  })
@@ -1196,11 +1235,11 @@ class q {
1196
1235
  <div class="chat-message-avatar">${s}</div>
1197
1236
  <div class="chat-message-content">
1198
1237
  <div class="chat-message-bubble">
1199
- ${i.content ? `<div class="chat-message-text">${K(i.content)}</div>` : ""}
1200
- ${e ? '<div class="chat-streaming"><span class="chat-streaming-dot"></span><span class="chat-streaming-dot"></span><span class="chat-streaming-dot"></span></div>' : ""}
1238
+ ${i.content ? `<div class="chat-message-text">${O(i.content)}</div>` : ""}
1239
+ ${e ? `<div class="chat-streaming"><span class="chat-streaming-dot"></span><span class="chat-streaming-dot"></span><span class="chat-streaming-dot"></span><span class="loading-text">${u[this.loadingMessageIndex]}</span></div>` : ""}
1201
1240
  </div>
1202
1241
  <div class="chat-message-metadata">
1203
- <span class="chat-message-time">${H(i.timestamp)}</span>
1242
+ <span class="chat-message-time">${N(i.timestamp)}</span>
1204
1243
  </div>
1205
1244
  </div>
1206
1245
  </div>
@@ -1218,7 +1257,15 @@ class q {
1218
1257
  * Set streaming state
1219
1258
  */
1220
1259
  setStreamingState(i) {
1221
- this.isStreaming = i, this.inputElement && (this.inputElement.disabled = i), this.sendButton && (this.sendButton.disabled = i, this.sendButton.innerHTML = i ? '<div class="loading"></div>' : "<span>Send</span>");
1260
+ this.isStreaming = i, this.inputElement && (this.inputElement.disabled = i), this.sendButton && (this.sendButton.disabled = i, this.sendButton.innerHTML = i ? '<div class="loading"></div>' : "<span>Send</span>"), i ? this.startLoadingMessages() : this.clearLoadingMessages();
1261
+ }
1262
+ startLoadingMessages() {
1263
+ this.loadingMessageIndex = Math.floor(Math.random() * u.length), this.loadingMessageInterval = setInterval(() => {
1264
+ this.loadingMessageIndex = (this.loadingMessageIndex + 1) % u.length, this.isStreaming && this.renderMessages(!0);
1265
+ }, 2500);
1266
+ }
1267
+ clearLoadingMessages() {
1268
+ this.loadingMessageInterval && (clearInterval(this.loadingMessageInterval), this.loadingMessageInterval = null);
1222
1269
  }
1223
1270
  /**
1224
1271
  * Get all messages
@@ -1242,31 +1289,31 @@ class q {
1242
1289
  * Destroy and cleanup
1243
1290
  */
1244
1291
  destroy() {
1245
- this.isStreaming && this.client.cancelAllRequests(), this.inputElement && (this.handleInputResize && this.inputElement.removeEventListener("input", this.handleInputResize), this.handleInputKeydown && this.inputElement.removeEventListener("keydown", this.handleInputKeydown)), this.sendButton && this.handleSendClick && this.sendButton.removeEventListener("click", this.handleSendClick), this.handleInputResize = null, this.handleInputKeydown = null, this.handleSendClick = null;
1292
+ this.clearLoadingMessages(), this.isStreaming && this.client.cancelAllRequests(), this.inputElement && (this.handleInputResize && this.inputElement.removeEventListener("input", this.handleInputResize), this.handleInputKeydown && this.inputElement.removeEventListener("keydown", this.handleInputKeydown)), this.sendButton && this.handleSendClick && this.sendButton.removeEventListener("click", this.handleSendClick), this.handleInputResize = null, this.handleInputKeydown = null, this.handleSendClick = null;
1246
1293
  }
1247
1294
  }
1248
- const E = "chat-bubble-snippet";
1249
- class O extends HTMLElement {
1295
+ const M = "chat-bubble-snippet";
1296
+ class K extends HTMLElement {
1250
1297
  constructor() {
1251
1298
  super();
1252
- r(this, "shadow");
1253
- r(this, "client", null);
1254
- r(this, "chatView", null);
1255
- r(this, "container", null);
1256
- r(this, "isExpanded", !1);
1257
- r(this, "isMinimized", !1);
1299
+ a(this, "shadow");
1300
+ a(this, "client", null);
1301
+ a(this, "chatView", null);
1302
+ a(this, "container", null);
1303
+ a(this, "isExpanded", !1);
1304
+ a(this, "isMinimized", !1);
1258
1305
  // Event handler references for cleanup
1259
- r(this, "handleBubbleClick", null);
1260
- r(this, "handleCloseClick", null);
1261
- r(this, "handleMinimizeClick", null);
1262
- r(this, "handleClearClick", null);
1306
+ a(this, "handleBubbleClick", null);
1307
+ a(this, "handleCloseClick", null);
1308
+ a(this, "handleMinimizeClick", null);
1309
+ a(this, "handleClearClick", null);
1263
1310
  this.shadow = this.attachShadow({ mode: "open" });
1264
1311
  }
1265
1312
  static get observedAttributes() {
1266
1313
  return ["api-url", "placeholder", "theme", "hide-branding"];
1267
1314
  }
1268
1315
  connectedCallback() {
1269
- this.render(), this.initializeClient(), this.dispatchEvent(m("ready", void 0));
1316
+ this.render(), this.initializeClient(), this.dispatchEvent(v("ready", void 0));
1270
1317
  }
1271
1318
  disconnectedCallback() {
1272
1319
  this.cleanup();
@@ -1276,10 +1323,10 @@ class O extends HTMLElement {
1276
1323
  }
1277
1324
  getProps() {
1278
1325
  return {
1279
- apiUrl: u(this.getAttribute("api-url"), "http://localhost:3000"),
1280
- placeholder: u(this.getAttribute("placeholder"), "Type a message..."),
1281
- theme: u(this.getAttribute("theme"), "auto"),
1282
- hideBranding: v(this.getAttribute("hide-branding"), !1)
1326
+ apiUrl: g(this.getAttribute("api-url"), "http://localhost:3000"),
1327
+ placeholder: g(this.getAttribute("placeholder"), "Type a message..."),
1328
+ theme: g(this.getAttribute("theme"), "auto"),
1329
+ hideBranding: b(this.getAttribute("hide-branding"), !1)
1283
1330
  };
1284
1331
  }
1285
1332
  initializeClient() {
@@ -1289,14 +1336,14 @@ class O extends HTMLElement {
1289
1336
  return;
1290
1337
  }
1291
1338
  try {
1292
- this.client = w(e.apiUrl);
1339
+ this.client = y(e.apiUrl);
1293
1340
  } catch (t) {
1294
1341
  console.error("ChatBubbleSnippet:", t);
1295
1342
  }
1296
1343
  }
1297
1344
  render() {
1298
1345
  const e = document.createElement("style");
1299
- e.textContent = `${x}
1346
+ e.textContent = `${k}
1300
1347
  ${$}
1301
1348
  ${this.getBubbleStyles()}`, this.container = document.createElement("div"), this.container.className = "chat-bubble-widget", this.container.innerHTML = this.getBaseHTML(), this.shadow.innerHTML = "", this.shadow.appendChild(e), this.shadow.appendChild(this.container), this.attachEventListeners();
1302
1349
  }
@@ -1477,17 +1524,17 @@ ${this.getBubbleStyles()}`, this.container = document.createElement("div"), this
1477
1524
  </div>
1478
1525
  </div>
1479
1526
  <div class="chat-content"></div>
1480
- ${this.getProps().hideBranding ? "" : `<div class="powered-by">${y}</div>`}
1527
+ ${this.getProps().hideBranding ? "" : `<div class="powered-by">${x}</div>`}
1481
1528
  </div>
1482
1529
  `;
1483
1530
  }
1484
1531
  attachEventListeners() {
1485
- const e = this.shadow.querySelector(".bubble-button"), t = this.shadow.querySelector(".close-button"), s = this.shadow.querySelector(".minimize-button"), a = this.shadow.querySelector(".clear-button");
1486
- this.handleBubbleClick = () => this.toggleChat(), this.handleCloseClick = () => this.closeChat(), this.handleMinimizeClick = () => this.toggleMinimize(), this.handleClearClick = () => this.clearChat(), e?.addEventListener("click", this.handleBubbleClick), t?.addEventListener("click", this.handleCloseClick), s?.addEventListener("click", this.handleMinimizeClick), a?.addEventListener("click", this.handleClearClick);
1532
+ const e = this.shadow.querySelector(".bubble-button"), t = this.shadow.querySelector(".close-button"), s = this.shadow.querySelector(".minimize-button"), r = this.shadow.querySelector(".clear-button");
1533
+ this.handleBubbleClick = () => this.toggleChat(), this.handleCloseClick = () => this.closeChat(), this.handleMinimizeClick = () => this.toggleMinimize(), this.handleClearClick = () => this.clearChat(), e?.addEventListener("click", this.handleBubbleClick), t?.addEventListener("click", this.handleCloseClick), s?.addEventListener("click", this.handleMinimizeClick), r?.addEventListener("click", this.handleClearClick);
1487
1534
  }
1488
1535
  removeEventListeners() {
1489
- const e = this.shadow.querySelector(".bubble-button"), t = this.shadow.querySelector(".close-button"), s = this.shadow.querySelector(".minimize-button"), a = this.shadow.querySelector(".clear-button");
1490
- this.handleBubbleClick && e?.removeEventListener("click", this.handleBubbleClick), this.handleCloseClick && t?.removeEventListener("click", this.handleCloseClick), this.handleMinimizeClick && s?.removeEventListener("click", this.handleMinimizeClick), this.handleClearClick && a?.removeEventListener("click", this.handleClearClick), this.handleBubbleClick = null, this.handleCloseClick = null, this.handleMinimizeClick = null, this.handleClearClick = null;
1536
+ const e = this.shadow.querySelector(".bubble-button"), t = this.shadow.querySelector(".close-button"), s = this.shadow.querySelector(".minimize-button"), r = this.shadow.querySelector(".clear-button");
1537
+ this.handleBubbleClick && e?.removeEventListener("click", this.handleBubbleClick), this.handleCloseClick && t?.removeEventListener("click", this.handleCloseClick), this.handleMinimizeClick && s?.removeEventListener("click", this.handleMinimizeClick), this.handleClearClick && r?.removeEventListener("click", this.handleClearClick), this.handleBubbleClick = null, this.handleCloseClick = null, this.handleMinimizeClick = null, this.handleClearClick = null;
1491
1538
  }
1492
1539
  toggleChat() {
1493
1540
  this.isExpanded = !this.isExpanded;
@@ -1528,31 +1575,31 @@ ${this.getBubbleStyles()}`, this.container = document.createElement("div"), this
1528
1575
  return this.chatView?.getMessages() || [];
1529
1576
  }
1530
1577
  }
1531
- customElements.get(E) || customElements.define(E, O);
1532
- const M = "chat-page-snippet", L = "chat-page-sessions";
1533
- class D extends HTMLElement {
1578
+ customElements.get(M) || customElements.define(M, K);
1579
+ const L = "chat-page-snippet", I = "chat-page-sessions";
1580
+ class U extends HTMLElement {
1534
1581
  constructor() {
1535
1582
  super();
1536
- r(this, "shadow");
1537
- r(this, "client", null);
1538
- r(this, "chatView", null);
1539
- r(this, "container", null);
1540
- r(this, "sessions", []);
1541
- r(this, "currentSessionId", null);
1542
- r(this, "sidebarCollapsed", !1);
1583
+ a(this, "shadow");
1584
+ a(this, "client", null);
1585
+ a(this, "chatView", null);
1586
+ a(this, "container", null);
1587
+ a(this, "sessions", []);
1588
+ a(this, "currentSessionId", null);
1589
+ a(this, "sidebarCollapsed", !1);
1543
1590
  // Event handler references for cleanup
1544
- r(this, "handleClearClick", null);
1545
- r(this, "handleNewChatClick", null);
1546
- r(this, "handleToggleSidebarClick", null);
1547
- r(this, "handleChatListClick", null);
1548
- r(this, "handleMessageEvent", null);
1591
+ a(this, "handleClearClick", null);
1592
+ a(this, "handleNewChatClick", null);
1593
+ a(this, "handleToggleSidebarClick", null);
1594
+ a(this, "handleChatListClick", null);
1595
+ a(this, "handleMessageEvent", null);
1549
1596
  this.shadow = this.attachShadow({ mode: "open" }), this.loadSessions();
1550
1597
  }
1551
1598
  static get observedAttributes() {
1552
1599
  return ["api-url", "placeholder", "theme", "hide-branding"];
1553
1600
  }
1554
1601
  connectedCallback() {
1555
- this.render(), this.initializeClient(), this.setupView(), this.dispatchEvent(m("ready", void 0));
1602
+ this.render(), this.initializeClient(), this.setupView(), this.dispatchEvent(v("ready", void 0));
1556
1603
  }
1557
1604
  disconnectedCallback() {
1558
1605
  this.saveCurrentSession(), this.cleanup();
@@ -1562,10 +1609,10 @@ class D extends HTMLElement {
1562
1609
  }
1563
1610
  getProps() {
1564
1611
  return {
1565
- apiUrl: u(this.getAttribute("api-url"), "http://localhost:3000"),
1566
- placeholder: u(this.getAttribute("placeholder"), "Type a message..."),
1567
- theme: u(this.getAttribute("theme"), "auto"),
1568
- hideBranding: v(this.getAttribute("hide-branding"), !1)
1612
+ apiUrl: g(this.getAttribute("api-url"), "http://localhost:3000"),
1613
+ placeholder: g(this.getAttribute("placeholder"), "Type a message..."),
1614
+ theme: g(this.getAttribute("theme"), "auto"),
1615
+ hideBranding: b(this.getAttribute("hide-branding"), !1)
1569
1616
  };
1570
1617
  }
1571
1618
  initializeClient() {
@@ -1575,14 +1622,14 @@ class D extends HTMLElement {
1575
1622
  return;
1576
1623
  }
1577
1624
  try {
1578
- this.client = w(e.apiUrl);
1625
+ this.client = y(e.apiUrl);
1579
1626
  } catch (t) {
1580
1627
  console.error("ChatPageSnippet:", t);
1581
1628
  }
1582
1629
  }
1583
1630
  render() {
1584
1631
  const e = document.createElement("style");
1585
- e.textContent = `${x}
1632
+ e.textContent = `${k}
1586
1633
  ${$}
1587
1634
  ${this.getPageStyles()}`, this.container = document.createElement("div"), this.container.className = "chat-page-container", this.container.innerHTML = this.getBaseHTML(), this.shadow.innerHTML = "", this.shadow.appendChild(e), this.shadow.appendChild(this.container), this.attachEventListeners();
1588
1635
  }
@@ -1875,7 +1922,7 @@ ${this.getPageStyles()}`, this.container = document.createElement("div"), this.c
1875
1922
  New Chat
1876
1923
  </button>
1877
1924
  <div class="chat-list"></div>
1878
- ${this.getProps().hideBranding ? "" : `<div class="powered-by">${y}</div>`}
1925
+ ${this.getProps().hideBranding ? "" : `<div class="powered-by">${x}</div>`}
1879
1926
  </div>
1880
1927
  <div class="chat-main">
1881
1928
  <div class="chat-page-header">
@@ -1908,12 +1955,12 @@ ${this.getPageStyles()}`, this.container = document.createElement("div"), this.c
1908
1955
  `;
1909
1956
  }
1910
1957
  attachEventListeners() {
1911
- const e = this.shadow.querySelector(".clear-button"), t = this.shadow.querySelector(".new-chat-button"), s = this.shadow.querySelector(".toggle-sidebar-button"), a = this.shadow.querySelector(".chat-list");
1912
- this.handleClearClick = () => this.clearCurrentChat(), this.handleNewChatClick = () => this.createNewChat(), this.handleToggleSidebarClick = () => this.toggleSidebar(), this.handleChatListClick = (n) => this.onChatListClick(n), e?.addEventListener("click", this.handleClearClick), t?.addEventListener("click", this.handleNewChatClick), s?.addEventListener("click", this.handleToggleSidebarClick), a?.addEventListener("click", this.handleChatListClick);
1958
+ const e = this.shadow.querySelector(".clear-button"), t = this.shadow.querySelector(".new-chat-button"), s = this.shadow.querySelector(".toggle-sidebar-button"), r = this.shadow.querySelector(".chat-list");
1959
+ this.handleClearClick = () => this.clearCurrentChat(), this.handleNewChatClick = () => this.createNewChat(), this.handleToggleSidebarClick = () => this.toggleSidebar(), this.handleChatListClick = (n) => this.onChatListClick(n), e?.addEventListener("click", this.handleClearClick), t?.addEventListener("click", this.handleNewChatClick), s?.addEventListener("click", this.handleToggleSidebarClick), r?.addEventListener("click", this.handleChatListClick);
1913
1960
  }
1914
1961
  removeEventListeners() {
1915
- const e = this.shadow.querySelector(".clear-button"), t = this.shadow.querySelector(".new-chat-button"), s = this.shadow.querySelector(".toggle-sidebar-button"), a = this.shadow.querySelector(".chat-list"), n = this.shadow.querySelector(".container");
1916
- this.handleClearClick && e?.removeEventListener("click", this.handleClearClick), this.handleNewChatClick && t?.removeEventListener("click", this.handleNewChatClick), this.handleToggleSidebarClick && s?.removeEventListener("click", this.handleToggleSidebarClick), this.handleChatListClick && a?.removeEventListener("click", this.handleChatListClick), this.handleMessageEvent && n && n.removeEventListener("message", this.handleMessageEvent), this.handleClearClick = null, this.handleNewChatClick = null, this.handleToggleSidebarClick = null, this.handleChatListClick = null, this.handleMessageEvent = null;
1962
+ const e = this.shadow.querySelector(".clear-button"), t = this.shadow.querySelector(".new-chat-button"), s = this.shadow.querySelector(".toggle-sidebar-button"), r = this.shadow.querySelector(".chat-list"), n = this.shadow.querySelector(".container");
1963
+ this.handleClearClick && e?.removeEventListener("click", this.handleClearClick), this.handleNewChatClick && t?.removeEventListener("click", this.handleNewChatClick), this.handleToggleSidebarClick && s?.removeEventListener("click", this.handleToggleSidebarClick), this.handleChatListClick && r?.removeEventListener("click", this.handleChatListClick), this.handleMessageEvent && n && n.removeEventListener("message", this.handleMessageEvent), this.handleClearClick = null, this.handleNewChatClick = null, this.handleToggleSidebarClick = null, this.handleChatListClick = null, this.handleMessageEvent = null;
1917
1964
  }
1918
1965
  setupView() {
1919
1966
  if (!this.client) return;
@@ -1935,7 +1982,7 @@ ${this.getPageStyles()}`, this.container = document.createElement("div"), this.c
1935
1982
  }
1936
1983
  loadSessions() {
1937
1984
  try {
1938
- const e = localStorage.getItem(L);
1985
+ const e = localStorage.getItem(I);
1939
1986
  e && (this.sessions = JSON.parse(e), this.sessions.sort((t, s) => s.updatedAt - t.updatedAt));
1940
1987
  } catch (e) {
1941
1988
  console.error("Failed to load chat sessions:", e);
@@ -1943,7 +1990,7 @@ ${this.getPageStyles()}`, this.container = document.createElement("div"), this.c
1943
1990
  }
1944
1991
  saveSessions() {
1945
1992
  try {
1946
- localStorage.setItem(L, JSON.stringify(this.sessions));
1993
+ localStorage.setItem(I, JSON.stringify(this.sessions));
1947
1994
  } catch (e) {
1948
1995
  console.error("Failed to save chat sessions:", e);
1949
1996
  }
@@ -1998,9 +2045,9 @@ ${this.getPageStyles()}`, this.container = document.createElement("div"), this.c
1998
2045
  n && this.deleteSession(n);
1999
2046
  return;
2000
2047
  }
2001
- const a = t.closest(".chat-list-item");
2002
- if (a) {
2003
- const n = a.getAttribute("data-session-id");
2048
+ const r = t.closest(".chat-list-item");
2049
+ if (r) {
2050
+ const n = r.getAttribute("data-session-id");
2004
2051
  n && this.switchToSession(n);
2005
2052
  }
2006
2053
  }
@@ -2031,7 +2078,7 @@ ${this.getPageStyles()}`, this.container = document.createElement("div"), this.c
2031
2078
  `;
2032
2079
  }
2033
2080
  formatDate(e) {
2034
- const t = new Date(e), a = (/* @__PURE__ */ new Date()).getTime() - t.getTime(), n = Math.floor(a / (1e3 * 60 * 60 * 24));
2081
+ const t = new Date(e), r = (/* @__PURE__ */ new Date()).getTime() - t.getTime(), n = Math.floor(r / (1e3 * 60 * 60 * 24));
2035
2082
  return n === 0 ? t.toLocaleTimeString(void 0, { hour: "2-digit", minute: "2-digit" }) : n === 1 ? "Yesterday" : n < 7 ? t.toLocaleDateString(void 0, { weekday: "long" }) : t.toLocaleDateString(void 0, { month: "short", day: "numeric" });
2036
2083
  }
2037
2084
  escapeHTML(e) {
@@ -2061,8 +2108,8 @@ ${this.getPageStyles()}`, this.container = document.createElement("div"), this.c
2061
2108
  return this.sessions.find((e) => e.id === this.currentSessionId) || null;
2062
2109
  }
2063
2110
  }
2064
- customElements.get(M) || customElements.define(M, D);
2065
- const U = `
2111
+ customElements.get(L) || customElements.define(L, U);
2112
+ const G = `
2066
2113
  /* Search view states */
2067
2114
  .search-view {
2068
2115
  transition: var(--search-snippet-transition-slow);
@@ -2398,19 +2445,21 @@ a.search-result-item:focus-visible {
2398
2445
  class F extends HTMLElement {
2399
2446
  constructor() {
2400
2447
  super();
2401
- r(this, "shadow");
2402
- r(this, "client", null);
2403
- r(this, "container", null);
2404
- r(this, "inputElement", null);
2405
- r(this, "resultsContainer", null);
2406
- r(this, "searchButton", null);
2407
- r(this, "debouncedSearch", null);
2408
- r(this, "currentSearchController", null);
2448
+ a(this, "shadow");
2449
+ a(this, "client", null);
2450
+ a(this, "container", null);
2451
+ a(this, "inputElement", null);
2452
+ a(this, "resultsContainer", null);
2453
+ a(this, "searchButton", null);
2454
+ a(this, "debouncedSearch", null);
2455
+ a(this, "currentSearchController", null);
2456
+ a(this, "loadingMessageInterval", null);
2457
+ a(this, "loadingMessageIndex", 0);
2409
2458
  // Event handler references for cleanup
2410
- r(this, "handleInputChange", null);
2411
- r(this, "handleInputKeydownEnter", null);
2412
- r(this, "handleInputKeydownEscape", null);
2413
- r(this, "handleSearchButtonClick", null);
2459
+ a(this, "handleInputChange", null);
2460
+ a(this, "handleInputKeydownEnter", null);
2461
+ a(this, "handleInputKeydownEscape", null);
2462
+ a(this, "handleSearchButtonClick", null);
2414
2463
  this.shadow = this.attachShadow({ mode: "open" });
2415
2464
  }
2416
2465
  static get observedAttributes() {
@@ -2425,7 +2474,7 @@ class F extends HTMLElement {
2425
2474
  ];
2426
2475
  }
2427
2476
  connectedCallback() {
2428
- this.initializeClient(), this.render(), this.dispatchEvent(m("ready", void 0));
2477
+ this.initializeClient(), this.render(), this.dispatchEvent(v("ready", void 0));
2429
2478
  }
2430
2479
  disconnectedCallback() {
2431
2480
  this.cleanup();
@@ -2435,13 +2484,13 @@ class F extends HTMLElement {
2435
2484
  }
2436
2485
  getProps() {
2437
2486
  return {
2438
- apiUrl: u(this.getAttribute("api-url"), "http://localhost:3000"),
2439
- placeholder: u(this.getAttribute("placeholder"), "Search..."),
2440
- maxResults: f(this.getAttribute("max-results"), 10),
2441
- debounceMs: f(this.getAttribute("debounce-ms"), 300),
2442
- theme: u(this.getAttribute("theme"), "auto"),
2443
- hideBranding: v(this.getAttribute("hide-branding"), !1),
2444
- showUrl: v(this.getAttribute("show-url"), !1)
2487
+ apiUrl: g(this.getAttribute("api-url"), "http://localhost:3000"),
2488
+ placeholder: g(this.getAttribute("placeholder"), "Search..."),
2489
+ maxResults: w(this.getAttribute("max-results"), 10),
2490
+ debounceMs: w(this.getAttribute("debounce-ms"), 300),
2491
+ theme: g(this.getAttribute("theme"), "auto"),
2492
+ hideBranding: b(this.getAttribute("hide-branding"), !1),
2493
+ showUrl: b(this.getAttribute("show-url"), !1)
2445
2494
  };
2446
2495
  }
2447
2496
  initializeClient() {
@@ -2451,20 +2500,20 @@ class F extends HTMLElement {
2451
2500
  return;
2452
2501
  }
2453
2502
  try {
2454
- this.client = w(e.apiUrl);
2503
+ this.client = y(e.apiUrl);
2455
2504
  } catch (t) {
2456
2505
  console.error("SearchBarSnippet:", t);
2457
2506
  }
2458
2507
  }
2459
2508
  render() {
2460
- const e = this.getProps(), t = (a) => this.performSearch(a);
2461
- this.debouncedSearch = T(
2509
+ const e = this.getProps(), t = (r) => this.performSearch(r);
2510
+ this.debouncedSearch = A(
2462
2511
  t,
2463
2512
  e.debounceMs || 400
2464
2513
  );
2465
2514
  const s = document.createElement("style");
2466
- s.textContent = `${x}
2467
- ${U}`, this.container = document.createElement("div"), this.container.className = "container", this.container.innerHTML = `
2515
+ s.textContent = `${k}
2516
+ ${G}`, this.container = document.createElement("div"), this.container.className = "container", this.container.innerHTML = `
2468
2517
  <div class="search-view">
2469
2518
  <div class="search-input-wrapper">
2470
2519
  <svg xmlns="http://www.w3.org/2000/svg" class="search-icon" height="24px" viewBox="0 -960 960 960" width="24px" fill="currentColor"><path d="M784-120 532-372q-30 24-69 38t-83 14q-109 0-184.5-75.5T120-580q0-109 75.5-184.5T380-840q109 0 184.5 75.5T640-580q0 44-14 83t-38 69l252 252-56 56ZM380-400q75 0 127.5-52.5T560-580q0-75-52.5-127.5T380-760q-75 0-127.5 52.5T200-580q0 75 52.5 127.5T380-400Z"/></svg>
@@ -2523,17 +2572,17 @@ ${U}`, this.container = document.createElement("div"), this.container.className
2523
2572
  }
2524
2573
  }
2525
2574
  displayResults(e, t) {
2526
- if (!this.resultsContainer) return;
2575
+ if (this.clearLoadingInterval(), !this.resultsContainer) return;
2527
2576
  if (e.length === 0) {
2528
2577
  this.showNoResultsState(t);
2529
2578
  return;
2530
2579
  }
2531
- const a = this.getProps().hideBranding ? "" : `<div class="powered-by-inline">${y}</div>`, n = `
2580
+ const r = this.getProps().hideBranding ? "" : `<div class="powered-by-inline">${x}</div>`, n = `
2532
2581
  <div class="search-header">
2533
2582
  <div class="search-count">
2534
2583
  Found ${e.length} result${e.length === 1 ? "" : "s"}
2535
2584
  </div>
2536
- ${a}
2585
+ ${r}
2537
2586
  </div>
2538
2587
  <div class="search-results">
2539
2588
  ${e.map((c) => this.renderResult(c)).join("")}
@@ -2584,9 +2633,9 @@ ${U}`, this.container = document.createElement("div"), this.container.className
2584
2633
  s.addEventListener("load", () => {
2585
2634
  s.classList.add("loaded"), s.closest(".search-result-image-container")?.querySelector(".search-result-image-loading")?.remove();
2586
2635
  }), s.addEventListener("error", () => {
2587
- const a = s.closest(".search-result-image-container");
2588
- a?.querySelector(".search-result-image-loading")?.remove();
2589
- const n = a?.querySelector(
2636
+ const r = s.closest(".search-result-image-container");
2637
+ r?.querySelector(".search-result-image-loading")?.remove();
2638
+ const n = r?.querySelector(
2590
2639
  ".search-result-image-placeholder"
2591
2640
  );
2592
2641
  n && (n.style.display = "flex"), s.style.display = "none";
@@ -2594,15 +2643,25 @@ ${U}`, this.container = document.createElement("div"), this.container.className
2594
2643
  });
2595
2644
  }
2596
2645
  showLoadingState() {
2597
- this.resultsContainer && (this.resultsContainer.innerHTML = `
2646
+ this.resultsContainer && (this.clearLoadingInterval(), this.loadingMessageIndex = Math.floor(Math.random() * u.length), this.resultsContainer.innerHTML = `
2598
2647
  <div class="search-loading">
2599
2648
  <div class="loading" aria-label="Loading"></div>
2600
- <div>Searching...</div>
2649
+ <div class="loading-text loading-text-animate">${u[this.loadingMessageIndex]}</div>
2601
2650
  </div>
2602
- `);
2651
+ `, this.startLoadingInterval());
2652
+ }
2653
+ startLoadingInterval() {
2654
+ this.loadingMessageInterval = setInterval(() => {
2655
+ this.loadingMessageIndex = (this.loadingMessageIndex + 1) % u.length;
2656
+ const e = this.resultsContainer?.querySelector(".loading-text");
2657
+ e && (e.classList.remove("loading-text-animate"), e.offsetWidth, e.textContent = u[this.loadingMessageIndex], e.classList.add("loading-text-animate"));
2658
+ }, 2500);
2659
+ }
2660
+ clearLoadingInterval() {
2661
+ this.loadingMessageInterval && (clearInterval(this.loadingMessageInterval), this.loadingMessageInterval = null);
2603
2662
  }
2604
2663
  showEmptyState() {
2605
- this.resultsContainer && (this.resultsContainer.innerHTML = `
2664
+ this.clearLoadingInterval(), this.resultsContainer && (this.resultsContainer.innerHTML = `
2606
2665
  <div class="search-empty">
2607
2666
  <svg class="search-empty-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
2608
2667
  <circle cx="11" cy="11" r="8"></circle>
@@ -2616,7 +2675,7 @@ ${U}`, this.container = document.createElement("div"), this.container.className
2616
2675
  `);
2617
2676
  }
2618
2677
  showNoResultsState(e) {
2619
- this.resultsContainer && (this.resultsContainer.innerHTML = `
2678
+ this.clearLoadingInterval(), this.resultsContainer && (this.resultsContainer.innerHTML = `
2620
2679
  <div class="search-empty">
2621
2680
  <svg class="search-empty-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
2622
2681
  <circle cx="11" cy="11" r="8"></circle>
@@ -2630,7 +2689,7 @@ ${U}`, this.container = document.createElement("div"), this.container.className
2630
2689
  `);
2631
2690
  }
2632
2691
  showErrorState(e) {
2633
- this.resultsContainer && (this.resultsContainer.innerHTML = `
2692
+ this.clearLoadingInterval(), this.resultsContainer && (this.resultsContainer.innerHTML = `
2634
2693
  <div class="error">
2635
2694
  <strong>Error:</strong> ${l(e)}
2636
2695
  </div>
@@ -2641,7 +2700,7 @@ ${U}`, this.container = document.createElement("div"), this.container.className
2641
2700
  t === "auto" ? this.removeAttribute("theme") : this.setAttribute("theme", t);
2642
2701
  }
2643
2702
  cleanup() {
2644
- this.currentSearchController && (this.currentSearchController.abort(), this.currentSearchController = null), this.client && this.client.cancelAllRequests(), this.inputElement && (this.handleInputChange && this.inputElement.removeEventListener("input", this.handleInputChange), this.handleInputKeydownEnter && this.inputElement.removeEventListener("keydown", this.handleInputKeydownEnter), this.handleInputKeydownEscape && window.removeEventListener("keydown", this.handleInputKeydownEscape)), this.searchButton && this.handleSearchButtonClick && this.searchButton.removeEventListener("click", this.handleSearchButtonClick), this.handleInputChange = null, this.handleInputKeydownEnter = null, this.handleInputKeydownEscape = null, this.handleSearchButtonClick = null;
2703
+ this.clearLoadingInterval(), this.currentSearchController && (this.currentSearchController.abort(), this.currentSearchController = null), this.client && this.client.cancelAllRequests(), this.inputElement && (this.handleInputChange && this.inputElement.removeEventListener("input", this.handleInputChange), this.handleInputKeydownEnter && this.inputElement.removeEventListener("keydown", this.handleInputKeydownEnter), this.handleInputKeydownEscape && window.removeEventListener("keydown", this.handleInputKeydownEscape)), this.searchButton && this.handleSearchButtonClick && this.searchButton.removeEventListener("click", this.handleSearchButtonClick), this.handleInputChange = null, this.handleInputKeydownEnter = null, this.handleInputKeydownEscape = null, this.handleSearchButtonClick = null;
2645
2704
  }
2646
2705
  // Public API
2647
2706
  async search(e) {
@@ -2649,7 +2708,7 @@ ${U}`, this.container = document.createElement("div"), this.container.className
2649
2708
  }
2650
2709
  }
2651
2710
  customElements.get(z) || customElements.define(z, F);
2652
- const G = `
2711
+ const Y = `
2653
2712
  /* Modal backdrop */
2654
2713
  .modal-backdrop {
2655
2714
  position: fixed;
@@ -3048,30 +3107,32 @@ a.modal-result-item:focus-visible {
3048
3107
  .modal-container.open {
3049
3108
  animation: modal-slide-in var(--search-snippet-transition) ease-out;
3050
3109
  }
3051
- `, I = "search-modal-snippet";
3052
- class Y extends HTMLElement {
3110
+ `, T = "search-modal-snippet";
3111
+ class W extends HTMLElement {
3053
3112
  constructor() {
3054
3113
  super();
3055
- r(this, "shadow");
3056
- r(this, "client", null);
3057
- r(this, "backdrop", null);
3058
- r(this, "modal", null);
3059
- r(this, "inputElement", null);
3060
- r(this, "resultsContainer", null);
3061
- r(this, "footerCount", null);
3062
- r(this, "isOpen", !1);
3063
- r(this, "results", []);
3064
- r(this, "activeIndex", -1);
3065
- r(this, "debouncedSearch", null);
3066
- r(this, "currentSearchController", null);
3114
+ a(this, "shadow");
3115
+ a(this, "client", null);
3116
+ a(this, "backdrop", null);
3117
+ a(this, "modal", null);
3118
+ a(this, "inputElement", null);
3119
+ a(this, "resultsContainer", null);
3120
+ a(this, "footerCount", null);
3121
+ a(this, "isOpen", !1);
3122
+ a(this, "results", []);
3123
+ a(this, "activeIndex", -1);
3124
+ a(this, "debouncedSearch", null);
3125
+ a(this, "currentSearchController", null);
3126
+ a(this, "loadingMessageInterval", null);
3127
+ a(this, "loadingMessageIndex", 0);
3067
3128
  // Event handler references for cleanup
3068
- r(this, "handleGlobalKeydown", null);
3069
- r(this, "handleInputChange", null);
3070
- r(this, "handleInputKeydown", null);
3071
- r(this, "handleBackdropClick", null);
3129
+ a(this, "handleGlobalKeydown", null);
3130
+ a(this, "handleInputChange", null);
3131
+ a(this, "handleInputKeydown", null);
3132
+ a(this, "handleBackdropClick", null);
3072
3133
  // Scroll lock state
3073
- r(this, "savedBodyStyles", null);
3074
- r(this, "savedHtmlOverflow", null);
3134
+ a(this, "savedBodyStyles", null);
3135
+ a(this, "savedHtmlOverflow", null);
3075
3136
  this.shadow = this.attachShadow({ mode: "open" });
3076
3137
  }
3077
3138
  static get observedAttributes() {
@@ -3088,7 +3149,7 @@ class Y extends HTMLElement {
3088
3149
  ];
3089
3150
  }
3090
3151
  connectedCallback() {
3091
- this.initializeClient(), this.render(), this.attachGlobalKeyboardShortcut(), this.dispatchEvent(m("ready", void 0));
3152
+ this.initializeClient(), this.render(), this.attachGlobalKeyboardShortcut(), this.dispatchEvent(v("ready", void 0));
3092
3153
  }
3093
3154
  disconnectedCallback() {
3094
3155
  this.cleanup();
@@ -3098,15 +3159,15 @@ class Y extends HTMLElement {
3098
3159
  }
3099
3160
  getProps() {
3100
3161
  return {
3101
- apiUrl: u(this.getAttribute("api-url"), "http://localhost:3000"),
3102
- placeholder: u(this.getAttribute("placeholder"), "Search..."),
3103
- maxResults: f(this.getAttribute("max-results"), 10),
3104
- debounceMs: f(this.getAttribute("debounce-ms"), 300),
3105
- theme: u(this.getAttribute("theme"), "auto"),
3106
- shortcut: u(this.getAttribute("shortcut"), "k"),
3162
+ apiUrl: g(this.getAttribute("api-url"), "http://localhost:3000"),
3163
+ placeholder: g(this.getAttribute("placeholder"), "Search..."),
3164
+ maxResults: w(this.getAttribute("max-results"), 10),
3165
+ debounceMs: w(this.getAttribute("debounce-ms"), 300),
3166
+ theme: g(this.getAttribute("theme"), "auto"),
3167
+ shortcut: g(this.getAttribute("shortcut"), "k"),
3107
3168
  useMetaKey: this.getAttribute("use-meta-key") !== "false",
3108
- hideBranding: v(this.getAttribute("hide-branding"), !1),
3109
- showUrl: v(this.getAttribute("show-url"), !1)
3169
+ hideBranding: b(this.getAttribute("hide-branding"), !1),
3170
+ showUrl: b(this.getAttribute("show-url"), !1)
3110
3171
  };
3111
3172
  }
3112
3173
  initializeClient() {
@@ -3116,21 +3177,21 @@ class Y extends HTMLElement {
3116
3177
  return;
3117
3178
  }
3118
3179
  try {
3119
- this.client = w(e.apiUrl);
3180
+ this.client = y(e.apiUrl);
3120
3181
  } catch (t) {
3121
3182
  console.error("SearchModalSnippet:", t);
3122
3183
  }
3123
3184
  }
3124
3185
  render() {
3125
3186
  const e = this.getProps(), t = (c) => this.performSearch(c);
3126
- this.debouncedSearch = T(
3187
+ this.debouncedSearch = A(
3127
3188
  t,
3128
3189
  e.debounceMs || 300
3129
3190
  );
3130
3191
  const s = document.createElement("style");
3131
- s.textContent = `${x}
3132
- ${G}`;
3133
- const a = e.hideBranding ? "" : `<div class="powered-by-inline">${y}</div>`, n = document.createElement("div");
3192
+ s.textContent = `${k}
3193
+ ${Y}`;
3194
+ const r = e.hideBranding ? "" : `<div class="powered-by-inline">${x}</div>`, n = document.createElement("div");
3134
3195
  n.innerHTML = `
3135
3196
  <div class="modal-backdrop" role="presentation"></div>
3136
3197
  <div class="modal-container" role="dialog" aria-modal="true" aria-labelledby="modal-title">
@@ -3171,7 +3232,7 @@ ${G}`;
3171
3232
  <span>Close</span>
3172
3233
  </div>
3173
3234
  </div>
3174
- ${a}
3235
+ ${r}
3175
3236
  </div>
3176
3237
  </div>
3177
3238
  `, this.shadow.innerHTML = "", this.shadow.appendChild(s), this.shadow.appendChild(n), this.backdrop = this.shadow.querySelector(".modal-backdrop"), this.modal = this.shadow.querySelector(".modal-container"), this.inputElement = this.shadow.querySelector(".modal-search-input"), this.resultsContainer = this.shadow.querySelector(".modal-results"), this.footerCount = this.shadow.querySelector(".modal-results-count"), this.attachEventListeners();
@@ -3224,7 +3285,7 @@ ${G}`;
3224
3285
  }
3225
3286
  const e = this.results[this.activeIndex];
3226
3287
  this.dispatchEvent(
3227
- m("result-select", {
3288
+ v("result-select", {
3228
3289
  result: e,
3229
3290
  index: this.activeIndex
3230
3291
  })
@@ -3253,16 +3314,16 @@ ${G}`;
3253
3314
  }
3254
3315
  }
3255
3316
  displayResults(e, t) {
3256
- if (!this.resultsContainer) return;
3317
+ if (this.clearLoadingInterval(), !this.resultsContainer) return;
3257
3318
  if (e.length === 0) {
3258
3319
  this.showNoResultsState(t);
3259
3320
  return;
3260
3321
  }
3261
- const s = e.map((a, n) => this.renderResult(a, n)).join("");
3322
+ const s = e.map((r, n) => this.renderResult(r, n)).join("");
3262
3323
  this.resultsContainer.innerHTML = s, this.footerCount && (this.footerCount.textContent = `${e.length} result${e.length === 1 ? "" : "s"}`), this.inputElement && this.inputElement.setAttribute("aria-expanded", "true"), this.attachResultHandlers(), this.updateActiveResult();
3263
3324
  }
3264
3325
  renderResult(e, t) {
3265
- const s = this.getProps(), a = this.renderResultImage(e.image, e.title);
3326
+ const s = this.getProps(), r = this.renderResultImage(e.image, e.title);
3266
3327
  return `
3267
3328
  <a
3268
3329
  href="${e.url ? l(e.url) : "#"}"
@@ -3274,7 +3335,7 @@ ${G}`;
3274
3335
  data-index="${t}"
3275
3336
  data-url="${l(e.url || "")}"
3276
3337
  >
3277
- ${a}
3338
+ ${r}
3278
3339
  <div class="modal-result-content">
3279
3340
  <div class="modal-result-title">${l(e.title || "")}</div>
3280
3341
  ${e.description ? `<div class="modal-result-description">${l(e.description)}</div>` : ""}
@@ -3305,19 +3366,19 @@ ${G}`;
3305
3366
  attachResultHandlers() {
3306
3367
  const e = this.resultsContainer?.querySelectorAll(".modal-result-item");
3307
3368
  if (!e) return;
3308
- e.forEach((s, a) => {
3369
+ e.forEach((s, r) => {
3309
3370
  s.getAttribute("href") === "#" && s.addEventListener("click", (c) => {
3310
3371
  c.preventDefault();
3311
3372
  }), s.addEventListener("mouseenter", () => {
3312
- this.activeIndex = a, this.updateActiveResult();
3373
+ this.activeIndex = r, this.updateActiveResult();
3313
3374
  });
3314
3375
  }), this.resultsContainer?.querySelectorAll(".modal-result-image")?.forEach((s) => {
3315
3376
  s.addEventListener("load", () => {
3316
3377
  s.classList.add("loaded"), s.closest(".modal-result-image-container")?.querySelector(".modal-result-image-loading")?.remove();
3317
3378
  }), s.addEventListener("error", () => {
3318
- const a = s.closest(".modal-result-image-container");
3319
- a?.querySelector(".modal-result-image-loading")?.remove();
3320
- const n = a?.querySelector(
3379
+ const r = s.closest(".modal-result-image-container");
3380
+ r?.querySelector(".modal-result-image-loading")?.remove();
3381
+ const n = r?.querySelector(
3321
3382
  ".modal-result-image-placeholder"
3322
3383
  );
3323
3384
  n && (n.style.display = "flex"), s.style.display = "none";
@@ -3336,18 +3397,28 @@ ${G}`;
3336
3397
  `;
3337
3398
  }
3338
3399
  showEmptyState() {
3339
- this.resultsContainer && (this.resultsContainer.innerHTML = this.renderEmptyState(), this.footerCount && (this.footerCount.textContent = ""), this.inputElement && this.inputElement.setAttribute("aria-expanded", "false"));
3400
+ this.clearLoadingInterval(), this.resultsContainer && (this.resultsContainer.innerHTML = this.renderEmptyState(), this.footerCount && (this.footerCount.textContent = ""), this.inputElement && this.inputElement.setAttribute("aria-expanded", "false"));
3340
3401
  }
3341
3402
  showLoadingState() {
3342
- this.resultsContainer && (this.resultsContainer.innerHTML = `
3403
+ this.resultsContainer && (this.clearLoadingInterval(), this.loadingMessageIndex = Math.floor(Math.random() * u.length), this.resultsContainer.innerHTML = `
3343
3404
  <div class="modal-loading">
3344
3405
  <div class="loading" aria-label="Loading"></div>
3345
- <div>Searching...</div>
3406
+ <div class="loading-text loading-text-animate">${u[this.loadingMessageIndex]}</div>
3346
3407
  </div>
3347
- `, this.footerCount && (this.footerCount.textContent = "Searching..."));
3408
+ `, this.footerCount && (this.footerCount.textContent = u[this.loadingMessageIndex]), this.startLoadingInterval());
3409
+ }
3410
+ startLoadingInterval() {
3411
+ this.loadingMessageInterval = setInterval(() => {
3412
+ this.loadingMessageIndex = (this.loadingMessageIndex + 1) % u.length;
3413
+ const e = this.resultsContainer?.querySelector(".loading-text");
3414
+ e && (e.classList.remove("loading-text-animate"), e.offsetWidth, e.textContent = u[this.loadingMessageIndex], e.classList.add("loading-text-animate")), this.footerCount && (this.footerCount.textContent = u[this.loadingMessageIndex]);
3415
+ }, 2500);
3416
+ }
3417
+ clearLoadingInterval() {
3418
+ this.loadingMessageInterval && (clearInterval(this.loadingMessageInterval), this.loadingMessageInterval = null);
3348
3419
  }
3349
3420
  showNoResultsState(e) {
3350
- this.resultsContainer && (this.resultsContainer.innerHTML = `
3421
+ this.clearLoadingInterval(), this.resultsContainer && (this.resultsContainer.innerHTML = `
3351
3422
  <div class="modal-empty">
3352
3423
  <svg class="modal-empty-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
3353
3424
  <circle cx="11" cy="11" r="8"></circle>
@@ -3359,7 +3430,7 @@ ${G}`;
3359
3430
  `, this.footerCount && (this.footerCount.textContent = "0 results"), this.inputElement && this.inputElement.setAttribute("aria-expanded", "false"));
3360
3431
  }
3361
3432
  showErrorState(e) {
3362
- this.resultsContainer && (this.resultsContainer.innerHTML = `
3433
+ this.clearLoadingInterval(), this.resultsContainer && (this.resultsContainer.innerHTML = `
3363
3434
  <div class="error">
3364
3435
  <strong>Error:</strong> ${l(e)}
3365
3436
  </div>
@@ -3384,7 +3455,7 @@ ${G}`;
3384
3455
  document.documentElement.style.overflow = this.savedHtmlOverflow || "", document.body.style.overflow = this.savedBodyStyles.overflow, document.body.style.position = this.savedBodyStyles.position, document.body.style.top = this.savedBodyStyles.top, document.body.style.width = this.savedBodyStyles.width, window.scrollTo(0, e), this.savedBodyStyles = null, this.savedHtmlOverflow = null;
3385
3456
  }
3386
3457
  cleanup() {
3387
- this.currentSearchController && (this.currentSearchController.abort(), this.currentSearchController = null), this.handleGlobalKeydown && (document.removeEventListener("keydown", this.handleGlobalKeydown), this.handleGlobalKeydown = null), this.inputElement && (this.handleInputChange && this.inputElement.removeEventListener("input", this.handleInputChange), this.handleInputKeydown && this.inputElement.removeEventListener("keydown", this.handleInputKeydown)), this.backdrop && this.handleBackdropClick && this.backdrop.removeEventListener("click", this.handleBackdropClick), this.handleInputChange = null, this.handleInputKeydown = null, this.handleBackdropClick = null, this.client && this.client.cancelAllRequests();
3458
+ this.clearLoadingInterval(), this.currentSearchController && (this.currentSearchController.abort(), this.currentSearchController = null), this.handleGlobalKeydown && (document.removeEventListener("keydown", this.handleGlobalKeydown), this.handleGlobalKeydown = null), this.inputElement && (this.handleInputChange && this.inputElement.removeEventListener("input", this.handleInputChange), this.handleInputKeydown && this.inputElement.removeEventListener("keydown", this.handleInputKeydown)), this.backdrop && this.handleBackdropClick && this.backdrop.removeEventListener("click", this.handleBackdropClick), this.handleInputChange = null, this.handleInputKeydown = null, this.handleBackdropClick = null, this.client && this.client.cancelAllRequests();
3388
3459
  }
3389
3460
  // Public API
3390
3461
  /**
@@ -3395,13 +3466,13 @@ ${G}`;
3395
3466
  requestAnimationFrame(() => {
3396
3467
  this.inputElement?.focus();
3397
3468
  });
3398
- }), this.lockBodyScroll(), this.dispatchEvent(m("open", void 0)));
3469
+ }), this.lockBodyScroll(), this.dispatchEvent(v("open", void 0)));
3399
3470
  }
3400
3471
  /**
3401
3472
  * Close the search modal
3402
3473
  */
3403
3474
  close() {
3404
- this.isOpen && (this.isOpen = !1, this.backdrop?.classList.remove("open"), this.modal?.classList.remove("open"), this.inputElement && (this.inputElement.value = ""), this.results = [], this.activeIndex = -1, this.showEmptyState(), this.unlockBodyScroll(), this.dispatchEvent(m("close", void 0)));
3475
+ this.isOpen && (this.isOpen = !1, this.backdrop?.classList.remove("open"), this.modal?.classList.remove("open"), this.inputElement && (this.inputElement.value = ""), this.results = [], this.activeIndex = -1, this.showEmptyState(), this.unlockBodyScroll(), this.dispatchEvent(v("close", void 0)));
3405
3476
  }
3406
3477
  /**
3407
3478
  * Toggle the search modal open/closed
@@ -3428,13 +3499,13 @@ ${G}`;
3428
3499
  return this.isOpen;
3429
3500
  }
3430
3501
  }
3431
- customElements.get(I) || customElements.define(I, Y);
3502
+ customElements.get(T) || customElements.define(T, W);
3432
3503
  export {
3433
3504
  P as AISearchClient,
3434
- O as ChatBubbleSnippet,
3435
- D as ChatPageSnippet,
3505
+ K as ChatBubbleSnippet,
3506
+ U as ChatPageSnippet,
3436
3507
  F as SearchBarSnippet,
3437
- Y as SearchModalSnippet,
3508
+ W as SearchModalSnippet,
3438
3509
  F as default
3439
3510
  };
3440
3511
  //# sourceMappingURL=search-snippet.es.js.map