@cloudflare/ai-search-snippet 0.0.22 → 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}`, {
@@ -94,7 +106,9 @@ class P extends N {
94
106
  messages: [{ role: "user", content: i.query }],
95
107
  stream: i.streaming,
96
108
  max_results: i.maxResults,
97
- ...e === "search" && { retrieval_options: { metadata_only: !0 } }
109
+ ...e === "search" && {
110
+ ai_search_options: { retrieval: { metadata_only: !0 } }
111
+ }
98
112
  }),
99
113
  headers: {
100
114
  "Content-Type": "application/json",
@@ -107,7 +121,7 @@ class P extends N {
107
121
  * Performs a search query with optional streaming
108
122
  */
109
123
  async search(i, e = {}) {
110
- 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;
111
125
  this.registerRequest(t, s);
112
126
  try {
113
127
  const n = await this.request(
@@ -117,7 +131,7 @@ class P extends N {
117
131
  maxResults: 30
118
132
  },
119
133
  "search",
120
- a
134
+ r
121
135
  );
122
136
  if (!n.ok)
123
137
  throw new Error(`HTTP error! status: ${n.status}`);
@@ -127,15 +141,15 @@ class P extends N {
127
141
  if (c.success && c.result) {
128
142
  const h = /* @__PURE__ */ new Map();
129
143
  for (const d of c.result.chunks) {
130
- const g = d.item.key, p = d.scoring_details.vector_score;
131
- (!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 });
132
146
  }
133
- 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(
134
148
  ({ chunk: d }) => ({
135
149
  type: "result",
136
150
  id: d.id,
137
- title: C(d.item.metadata.title),
138
- 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) : "",
139
153
  url: d.item.key,
140
154
  image: d.item.metadata.image || void 0,
141
155
  metadata: d.item.metadata
@@ -148,7 +162,7 @@ class P extends N {
148
162
  }
149
163
  }
150
164
  async *searchStream(i, e) {
151
- 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;
152
166
  this.registerRequest(t, s);
153
167
  const n = await this.request(
154
168
  {
@@ -156,7 +170,7 @@ class P extends N {
156
170
  streaming: !0
157
171
  },
158
172
  "ai-search",
159
- a
173
+ r
160
174
  );
161
175
  if (!n.ok)
162
176
  throw new Error(`HTTP error! status: ${n.status}`);
@@ -165,10 +179,10 @@ class P extends N {
165
179
  let c = "";
166
180
  const h = n.body.getReader(), d = new TextDecoder();
167
181
  for (; ; ) {
168
- const { done: p, value: k } = await h.read();
182
+ const { done: p, value: C } = await h.read();
169
183
  if (p)
170
184
  break;
171
- const B = d.decode(k, { stream: !0 });
185
+ const B = d.decode(C, { stream: !0 });
172
186
  c += B;
173
187
  }
174
188
  yield {
@@ -183,7 +197,7 @@ class P extends N {
183
197
  };
184
198
  }
185
199
  async *chat(i, e) {
186
- 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(
187
201
  {
188
202
  query: i,
189
203
  streaming: !1
@@ -191,13 +205,13 @@ class P extends N {
191
205
  "chat/completions",
192
206
  s
193
207
  );
194
- if (!a.ok)
195
- throw new Error(`HTTP error! status: ${a.status}`);
196
- if (!a.body)
208
+ if (!r.ok)
209
+ throw new Error(`HTTP error! status: ${r.status}`);
210
+ if (!r.body)
197
211
  throw new Error("Response body is empty");
198
212
  yield {
199
213
  type: "text",
200
- message: (await a.json()).choices.map((c) => c.message.content).join("")
214
+ message: (await r.json()).choices.map((c) => c.message.content).join("")
201
215
  };
202
216
  }
203
217
  /**
@@ -237,10 +251,10 @@ class P extends N {
237
251
  return `req-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
238
252
  }
239
253
  }
240
- 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">
241
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"/>
242
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"/>
243
- </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>`, $ = `
244
258
  /* Chat container */
245
259
  .chat-container {
246
260
  display: flex;
@@ -435,6 +449,10 @@ const _ = `<svg width="32" height="10" viewBox="0 0 412 186" xmlns="http://www.w
435
449
  }
436
450
  }
437
451
 
452
+ .chat-streaming .loading-text {
453
+ margin-left: var(--search-snippet-spacing-xs);
454
+ }
455
+
438
456
  /* Input area */
439
457
  .chat-input-area {
440
458
  padding: var(--search-snippet-spacing-md);
@@ -553,7 +571,7 @@ const _ = `<svg width="32" height="10" viewBox="0 0 412 186" xmlns="http://www.w
553
571
  .chat-message-bubble a:hover {
554
572
  text-decoration: none;
555
573
  }
556
- `, x = `
574
+ `, k = `
557
575
  :host {
558
576
  /* Colors - Light Mode */
559
577
  --search-snippet-primary-color: #2563eb;
@@ -888,6 +906,27 @@ const _ = `<svg width="32" height="10" viewBox="0 0 412 186" xmlns="http://www.w
888
906
  to { transform: rotate(360deg); }
889
907
  }
890
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
+
891
930
  /* Error message */
892
931
  .error {
893
932
  padding: var(--search-snippet-spacing-md);
@@ -967,17 +1006,17 @@ const _ = `<svg width="32" height="10" viewBox="0 0 412 186" xmlns="http://www.w
967
1006
  text-align: center;
968
1007
  }
969
1008
  `;
970
- function K(o) {
1009
+ function O(o) {
971
1010
  let i = o;
972
- 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>`);
973
1012
  const e = i.split(`
974
1013
  `), t = [];
975
- let s = !1, a = "";
1014
+ let s = !1, r = "";
976
1015
  for (let n = 0; n < e.length; n++) {
977
1016
  const c = e[n], h = c.match(/^(#{1,6})\s+(.+)$/);
978
1017
  if (h) {
979
- const p = h[1].length, k = h[2];
980
- 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}>`);
981
1020
  continue;
982
1021
  }
983
1022
  if (c.match(/^---+$/)) {
@@ -986,36 +1025,36 @@ function K(o) {
986
1025
  }
987
1026
  if (c.match(/^>\s+/)) {
988
1027
  const p = c.replace(/^>\s+/, "");
989
- t.push(`<blockquote>${b(p)}</blockquote>`);
1028
+ t.push(`<blockquote>${f(p)}</blockquote>`);
990
1029
  continue;
991
1030
  }
992
1031
  const d = c.match(/^[-*]\s+(.+)$/);
993
1032
  if (d) {
994
- (!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>`);
995
1034
  continue;
996
1035
  }
997
- const g = c.match(/^\d+\.\s+(.+)$/);
998
- if (g) {
999
- (!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>`);
1000
1039
  continue;
1001
1040
  }
1002
- if (s && (t.push(`</${a}>`), s = !1, a = ""), c.trim() === "") {
1041
+ if (s && (t.push(`</${r}>`), s = !1, r = ""), c.trim() === "") {
1003
1042
  t.push("<br />");
1004
1043
  continue;
1005
1044
  }
1006
- t.push(`<p>${b(c)}</p>`);
1045
+ t.push(`<p>${f(c)}</p>`);
1007
1046
  }
1008
- return s && t.push(`</${a}>`), t.join(`
1047
+ return s && t.push(`</${r}>`), t.join(`
1009
1048
  `);
1010
1049
  }
1011
- function b(o) {
1050
+ function f(o) {
1012
1051
  let i = o;
1013
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(
1014
1053
  /\[([^\]]+)\]\(([^)]+)\)/g,
1015
1054
  '<a href="$2" target="_blank" rel="noopener noreferrer">$1</a>'
1016
1055
  ), i;
1017
1056
  }
1018
- function V(o) {
1057
+ function j(o) {
1019
1058
  const i = {
1020
1059
  "&": "&amp;",
1021
1060
  "<": "&lt;",
@@ -1027,19 +1066,21 @@ function V(o) {
1027
1066
  }
1028
1067
  class q {
1029
1068
  constructor(i, e, t) {
1030
- r(this, "container");
1031
- r(this, "client");
1032
- r(this, "props");
1033
- r(this, "inputElement", null);
1034
- r(this, "messagesContainer", null);
1035
- r(this, "sendButton", null);
1036
- r(this, "messages", []);
1037
- r(this, "isStreaming", !1);
1038
- 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);
1039
1080
  // Event handler references for cleanup
1040
- r(this, "handleInputResize", null);
1041
- r(this, "handleInputKeydown", null);
1042
- r(this, "handleSendClick", null);
1081
+ a(this, "handleInputResize", null);
1082
+ a(this, "handleInputKeydown", null);
1083
+ a(this, "handleSendClick", null);
1043
1084
  this.container = i, this.client = e, this.props = t, this.render(), this.attachEventListeners();
1044
1085
  }
1045
1086
  /**
@@ -1102,13 +1143,13 @@ class q {
1102
1143
  */
1103
1144
  async sendMessage(i) {
1104
1145
  const e = {
1105
- id: S("msg"),
1146
+ id: E("msg"),
1106
1147
  role: "user",
1107
1148
  content: i,
1108
1149
  timestamp: Date.now()
1109
1150
  };
1110
1151
  this.addMessage(e), this.renderMessages(!0), this.setStreamingState(!0);
1111
- const t = S("msg"), s = {
1152
+ const t = E("msg"), s = {
1112
1153
  id: t,
1113
1154
  role: "assistant",
1114
1155
  content: "",
@@ -1116,9 +1157,9 @@ class q {
1116
1157
  };
1117
1158
  this.addMessage(s), this.currentStreamingMessageId = t, this.renderMessages(!0);
1118
1159
  try {
1119
- const a = this.client.chat(i);
1160
+ const r = this.client.chat(i);
1120
1161
  let n = "";
1121
- for await (const h of a)
1162
+ for await (const h of r)
1122
1163
  if (h.type === "text" && h.message)
1123
1164
  n += h.message, this.updateStreamingMessage(t, n);
1124
1165
  else if (h.type === "error") {
@@ -1126,12 +1167,12 @@ class q {
1126
1167
  break;
1127
1168
  }
1128
1169
  const c = this.messages.findIndex((h) => h.id === t);
1129
- c !== -1 && (this.messages[c].content = n), this.container.dispatchEvent(m("message", { message: s }));
1130
- } catch (a) {
1131
- this.showErrorInMessage(t, a.message), this.container.dispatchEvent(
1132
- 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", {
1133
1174
  error: {
1134
- message: a.message,
1175
+ message: r.message,
1135
1176
  code: "CHAT_ERROR"
1136
1177
  }
1137
1178
  })
@@ -1194,11 +1235,11 @@ class q {
1194
1235
  <div class="chat-message-avatar">${s}</div>
1195
1236
  <div class="chat-message-content">
1196
1237
  <div class="chat-message-bubble">
1197
- ${i.content ? `<div class="chat-message-text">${K(i.content)}</div>` : ""}
1198
- ${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>` : ""}
1199
1240
  </div>
1200
1241
  <div class="chat-message-metadata">
1201
- <span class="chat-message-time">${H(i.timestamp)}</span>
1242
+ <span class="chat-message-time">${N(i.timestamp)}</span>
1202
1243
  </div>
1203
1244
  </div>
1204
1245
  </div>
@@ -1216,7 +1257,15 @@ class q {
1216
1257
  * Set streaming state
1217
1258
  */
1218
1259
  setStreamingState(i) {
1219
- 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);
1220
1269
  }
1221
1270
  /**
1222
1271
  * Get all messages
@@ -1240,31 +1289,31 @@ class q {
1240
1289
  * Destroy and cleanup
1241
1290
  */
1242
1291
  destroy() {
1243
- 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;
1244
1293
  }
1245
1294
  }
1246
- const E = "chat-bubble-snippet";
1247
- class O extends HTMLElement {
1295
+ const M = "chat-bubble-snippet";
1296
+ class K extends HTMLElement {
1248
1297
  constructor() {
1249
1298
  super();
1250
- r(this, "shadow");
1251
- r(this, "client", null);
1252
- r(this, "chatView", null);
1253
- r(this, "container", null);
1254
- r(this, "isExpanded", !1);
1255
- 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);
1256
1305
  // Event handler references for cleanup
1257
- r(this, "handleBubbleClick", null);
1258
- r(this, "handleCloseClick", null);
1259
- r(this, "handleMinimizeClick", null);
1260
- r(this, "handleClearClick", null);
1306
+ a(this, "handleBubbleClick", null);
1307
+ a(this, "handleCloseClick", null);
1308
+ a(this, "handleMinimizeClick", null);
1309
+ a(this, "handleClearClick", null);
1261
1310
  this.shadow = this.attachShadow({ mode: "open" });
1262
1311
  }
1263
1312
  static get observedAttributes() {
1264
1313
  return ["api-url", "placeholder", "theme", "hide-branding"];
1265
1314
  }
1266
1315
  connectedCallback() {
1267
- this.render(), this.initializeClient(), this.dispatchEvent(m("ready", void 0));
1316
+ this.render(), this.initializeClient(), this.dispatchEvent(v("ready", void 0));
1268
1317
  }
1269
1318
  disconnectedCallback() {
1270
1319
  this.cleanup();
@@ -1274,10 +1323,10 @@ class O extends HTMLElement {
1274
1323
  }
1275
1324
  getProps() {
1276
1325
  return {
1277
- apiUrl: u(this.getAttribute("api-url"), "http://localhost:3000"),
1278
- placeholder: u(this.getAttribute("placeholder"), "Type a message..."),
1279
- theme: u(this.getAttribute("theme"), "auto"),
1280
- 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)
1281
1330
  };
1282
1331
  }
1283
1332
  initializeClient() {
@@ -1287,14 +1336,14 @@ class O extends HTMLElement {
1287
1336
  return;
1288
1337
  }
1289
1338
  try {
1290
- this.client = w(e.apiUrl);
1339
+ this.client = y(e.apiUrl);
1291
1340
  } catch (t) {
1292
1341
  console.error("ChatBubbleSnippet:", t);
1293
1342
  }
1294
1343
  }
1295
1344
  render() {
1296
1345
  const e = document.createElement("style");
1297
- e.textContent = `${x}
1346
+ e.textContent = `${k}
1298
1347
  ${$}
1299
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();
1300
1349
  }
@@ -1475,17 +1524,17 @@ ${this.getBubbleStyles()}`, this.container = document.createElement("div"), this
1475
1524
  </div>
1476
1525
  </div>
1477
1526
  <div class="chat-content"></div>
1478
- ${this.getProps().hideBranding ? "" : `<div class="powered-by">${y}</div>`}
1527
+ ${this.getProps().hideBranding ? "" : `<div class="powered-by">${x}</div>`}
1479
1528
  </div>
1480
1529
  `;
1481
1530
  }
1482
1531
  attachEventListeners() {
1483
- 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");
1484
- 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);
1485
1534
  }
1486
1535
  removeEventListeners() {
1487
- 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");
1488
- 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;
1489
1538
  }
1490
1539
  toggleChat() {
1491
1540
  this.isExpanded = !this.isExpanded;
@@ -1526,31 +1575,31 @@ ${this.getBubbleStyles()}`, this.container = document.createElement("div"), this
1526
1575
  return this.chatView?.getMessages() || [];
1527
1576
  }
1528
1577
  }
1529
- customElements.get(E) || customElements.define(E, O);
1530
- const M = "chat-page-snippet", L = "chat-page-sessions";
1531
- 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 {
1532
1581
  constructor() {
1533
1582
  super();
1534
- r(this, "shadow");
1535
- r(this, "client", null);
1536
- r(this, "chatView", null);
1537
- r(this, "container", null);
1538
- r(this, "sessions", []);
1539
- r(this, "currentSessionId", null);
1540
- 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);
1541
1590
  // Event handler references for cleanup
1542
- r(this, "handleClearClick", null);
1543
- r(this, "handleNewChatClick", null);
1544
- r(this, "handleToggleSidebarClick", null);
1545
- r(this, "handleChatListClick", null);
1546
- 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);
1547
1596
  this.shadow = this.attachShadow({ mode: "open" }), this.loadSessions();
1548
1597
  }
1549
1598
  static get observedAttributes() {
1550
1599
  return ["api-url", "placeholder", "theme", "hide-branding"];
1551
1600
  }
1552
1601
  connectedCallback() {
1553
- 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));
1554
1603
  }
1555
1604
  disconnectedCallback() {
1556
1605
  this.saveCurrentSession(), this.cleanup();
@@ -1560,10 +1609,10 @@ class D extends HTMLElement {
1560
1609
  }
1561
1610
  getProps() {
1562
1611
  return {
1563
- apiUrl: u(this.getAttribute("api-url"), "http://localhost:3000"),
1564
- placeholder: u(this.getAttribute("placeholder"), "Type a message..."),
1565
- theme: u(this.getAttribute("theme"), "auto"),
1566
- 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)
1567
1616
  };
1568
1617
  }
1569
1618
  initializeClient() {
@@ -1573,14 +1622,14 @@ class D extends HTMLElement {
1573
1622
  return;
1574
1623
  }
1575
1624
  try {
1576
- this.client = w(e.apiUrl);
1625
+ this.client = y(e.apiUrl);
1577
1626
  } catch (t) {
1578
1627
  console.error("ChatPageSnippet:", t);
1579
1628
  }
1580
1629
  }
1581
1630
  render() {
1582
1631
  const e = document.createElement("style");
1583
- e.textContent = `${x}
1632
+ e.textContent = `${k}
1584
1633
  ${$}
1585
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();
1586
1635
  }
@@ -1873,7 +1922,7 @@ ${this.getPageStyles()}`, this.container = document.createElement("div"), this.c
1873
1922
  New Chat
1874
1923
  </button>
1875
1924
  <div class="chat-list"></div>
1876
- ${this.getProps().hideBranding ? "" : `<div class="powered-by">${y}</div>`}
1925
+ ${this.getProps().hideBranding ? "" : `<div class="powered-by">${x}</div>`}
1877
1926
  </div>
1878
1927
  <div class="chat-main">
1879
1928
  <div class="chat-page-header">
@@ -1906,12 +1955,12 @@ ${this.getPageStyles()}`, this.container = document.createElement("div"), this.c
1906
1955
  `;
1907
1956
  }
1908
1957
  attachEventListeners() {
1909
- 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");
1910
- 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);
1911
1960
  }
1912
1961
  removeEventListeners() {
1913
- 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");
1914
- 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;
1915
1964
  }
1916
1965
  setupView() {
1917
1966
  if (!this.client) return;
@@ -1933,7 +1982,7 @@ ${this.getPageStyles()}`, this.container = document.createElement("div"), this.c
1933
1982
  }
1934
1983
  loadSessions() {
1935
1984
  try {
1936
- const e = localStorage.getItem(L);
1985
+ const e = localStorage.getItem(I);
1937
1986
  e && (this.sessions = JSON.parse(e), this.sessions.sort((t, s) => s.updatedAt - t.updatedAt));
1938
1987
  } catch (e) {
1939
1988
  console.error("Failed to load chat sessions:", e);
@@ -1941,7 +1990,7 @@ ${this.getPageStyles()}`, this.container = document.createElement("div"), this.c
1941
1990
  }
1942
1991
  saveSessions() {
1943
1992
  try {
1944
- localStorage.setItem(L, JSON.stringify(this.sessions));
1993
+ localStorage.setItem(I, JSON.stringify(this.sessions));
1945
1994
  } catch (e) {
1946
1995
  console.error("Failed to save chat sessions:", e);
1947
1996
  }
@@ -1996,9 +2045,9 @@ ${this.getPageStyles()}`, this.container = document.createElement("div"), this.c
1996
2045
  n && this.deleteSession(n);
1997
2046
  return;
1998
2047
  }
1999
- const a = t.closest(".chat-list-item");
2000
- if (a) {
2001
- 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");
2002
2051
  n && this.switchToSession(n);
2003
2052
  }
2004
2053
  }
@@ -2029,7 +2078,7 @@ ${this.getPageStyles()}`, this.container = document.createElement("div"), this.c
2029
2078
  `;
2030
2079
  }
2031
2080
  formatDate(e) {
2032
- 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));
2033
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" });
2034
2083
  }
2035
2084
  escapeHTML(e) {
@@ -2059,8 +2108,8 @@ ${this.getPageStyles()}`, this.container = document.createElement("div"), this.c
2059
2108
  return this.sessions.find((e) => e.id === this.currentSessionId) || null;
2060
2109
  }
2061
2110
  }
2062
- customElements.get(M) || customElements.define(M, D);
2063
- const U = `
2111
+ customElements.get(L) || customElements.define(L, U);
2112
+ const G = `
2064
2113
  /* Search view states */
2065
2114
  .search-view {
2066
2115
  transition: var(--search-snippet-transition-slow);
@@ -2396,19 +2445,21 @@ a.search-result-item:focus-visible {
2396
2445
  class F extends HTMLElement {
2397
2446
  constructor() {
2398
2447
  super();
2399
- r(this, "shadow");
2400
- r(this, "client", null);
2401
- r(this, "container", null);
2402
- r(this, "inputElement", null);
2403
- r(this, "resultsContainer", null);
2404
- r(this, "searchButton", null);
2405
- r(this, "debouncedSearch", null);
2406
- 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);
2407
2458
  // Event handler references for cleanup
2408
- r(this, "handleInputChange", null);
2409
- r(this, "handleInputKeydownEnter", null);
2410
- r(this, "handleInputKeydownEscape", null);
2411
- r(this, "handleSearchButtonClick", null);
2459
+ a(this, "handleInputChange", null);
2460
+ a(this, "handleInputKeydownEnter", null);
2461
+ a(this, "handleInputKeydownEscape", null);
2462
+ a(this, "handleSearchButtonClick", null);
2412
2463
  this.shadow = this.attachShadow({ mode: "open" });
2413
2464
  }
2414
2465
  static get observedAttributes() {
@@ -2423,7 +2474,7 @@ class F extends HTMLElement {
2423
2474
  ];
2424
2475
  }
2425
2476
  connectedCallback() {
2426
- this.initializeClient(), this.render(), this.dispatchEvent(m("ready", void 0));
2477
+ this.initializeClient(), this.render(), this.dispatchEvent(v("ready", void 0));
2427
2478
  }
2428
2479
  disconnectedCallback() {
2429
2480
  this.cleanup();
@@ -2433,13 +2484,13 @@ class F extends HTMLElement {
2433
2484
  }
2434
2485
  getProps() {
2435
2486
  return {
2436
- apiUrl: u(this.getAttribute("api-url"), "http://localhost:3000"),
2437
- placeholder: u(this.getAttribute("placeholder"), "Search..."),
2438
- maxResults: f(this.getAttribute("max-results"), 10),
2439
- debounceMs: f(this.getAttribute("debounce-ms"), 300),
2440
- theme: u(this.getAttribute("theme"), "auto"),
2441
- hideBranding: v(this.getAttribute("hide-branding"), !1),
2442
- 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)
2443
2494
  };
2444
2495
  }
2445
2496
  initializeClient() {
@@ -2449,20 +2500,20 @@ class F extends HTMLElement {
2449
2500
  return;
2450
2501
  }
2451
2502
  try {
2452
- this.client = w(e.apiUrl);
2503
+ this.client = y(e.apiUrl);
2453
2504
  } catch (t) {
2454
2505
  console.error("SearchBarSnippet:", t);
2455
2506
  }
2456
2507
  }
2457
2508
  render() {
2458
- const e = this.getProps(), t = (a) => this.performSearch(a);
2459
- this.debouncedSearch = T(
2509
+ const e = this.getProps(), t = (r) => this.performSearch(r);
2510
+ this.debouncedSearch = A(
2460
2511
  t,
2461
2512
  e.debounceMs || 400
2462
2513
  );
2463
2514
  const s = document.createElement("style");
2464
- s.textContent = `${x}
2465
- ${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 = `
2466
2517
  <div class="search-view">
2467
2518
  <div class="search-input-wrapper">
2468
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>
@@ -2521,17 +2572,17 @@ ${U}`, this.container = document.createElement("div"), this.container.className
2521
2572
  }
2522
2573
  }
2523
2574
  displayResults(e, t) {
2524
- if (!this.resultsContainer) return;
2575
+ if (this.clearLoadingInterval(), !this.resultsContainer) return;
2525
2576
  if (e.length === 0) {
2526
2577
  this.showNoResultsState(t);
2527
2578
  return;
2528
2579
  }
2529
- 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 = `
2530
2581
  <div class="search-header">
2531
2582
  <div class="search-count">
2532
2583
  Found ${e.length} result${e.length === 1 ? "" : "s"}
2533
2584
  </div>
2534
- ${a}
2585
+ ${r}
2535
2586
  </div>
2536
2587
  <div class="search-results">
2537
2588
  ${e.map((c) => this.renderResult(c)).join("")}
@@ -2582,9 +2633,9 @@ ${U}`, this.container = document.createElement("div"), this.container.className
2582
2633
  s.addEventListener("load", () => {
2583
2634
  s.classList.add("loaded"), s.closest(".search-result-image-container")?.querySelector(".search-result-image-loading")?.remove();
2584
2635
  }), s.addEventListener("error", () => {
2585
- const a = s.closest(".search-result-image-container");
2586
- a?.querySelector(".search-result-image-loading")?.remove();
2587
- 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(
2588
2639
  ".search-result-image-placeholder"
2589
2640
  );
2590
2641
  n && (n.style.display = "flex"), s.style.display = "none";
@@ -2592,15 +2643,25 @@ ${U}`, this.container = document.createElement("div"), this.container.className
2592
2643
  });
2593
2644
  }
2594
2645
  showLoadingState() {
2595
- this.resultsContainer && (this.resultsContainer.innerHTML = `
2646
+ this.resultsContainer && (this.clearLoadingInterval(), this.loadingMessageIndex = Math.floor(Math.random() * u.length), this.resultsContainer.innerHTML = `
2596
2647
  <div class="search-loading">
2597
2648
  <div class="loading" aria-label="Loading"></div>
2598
- <div>Searching...</div>
2649
+ <div class="loading-text loading-text-animate">${u[this.loadingMessageIndex]}</div>
2599
2650
  </div>
2600
- `);
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);
2601
2662
  }
2602
2663
  showEmptyState() {
2603
- this.resultsContainer && (this.resultsContainer.innerHTML = `
2664
+ this.clearLoadingInterval(), this.resultsContainer && (this.resultsContainer.innerHTML = `
2604
2665
  <div class="search-empty">
2605
2666
  <svg class="search-empty-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
2606
2667
  <circle cx="11" cy="11" r="8"></circle>
@@ -2614,7 +2675,7 @@ ${U}`, this.container = document.createElement("div"), this.container.className
2614
2675
  `);
2615
2676
  }
2616
2677
  showNoResultsState(e) {
2617
- this.resultsContainer && (this.resultsContainer.innerHTML = `
2678
+ this.clearLoadingInterval(), this.resultsContainer && (this.resultsContainer.innerHTML = `
2618
2679
  <div class="search-empty">
2619
2680
  <svg class="search-empty-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
2620
2681
  <circle cx="11" cy="11" r="8"></circle>
@@ -2628,7 +2689,7 @@ ${U}`, this.container = document.createElement("div"), this.container.className
2628
2689
  `);
2629
2690
  }
2630
2691
  showErrorState(e) {
2631
- this.resultsContainer && (this.resultsContainer.innerHTML = `
2692
+ this.clearLoadingInterval(), this.resultsContainer && (this.resultsContainer.innerHTML = `
2632
2693
  <div class="error">
2633
2694
  <strong>Error:</strong> ${l(e)}
2634
2695
  </div>
@@ -2639,7 +2700,7 @@ ${U}`, this.container = document.createElement("div"), this.container.className
2639
2700
  t === "auto" ? this.removeAttribute("theme") : this.setAttribute("theme", t);
2640
2701
  }
2641
2702
  cleanup() {
2642
- 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;
2643
2704
  }
2644
2705
  // Public API
2645
2706
  async search(e) {
@@ -2647,7 +2708,7 @@ ${U}`, this.container = document.createElement("div"), this.container.className
2647
2708
  }
2648
2709
  }
2649
2710
  customElements.get(z) || customElements.define(z, F);
2650
- const G = `
2711
+ const Y = `
2651
2712
  /* Modal backdrop */
2652
2713
  .modal-backdrop {
2653
2714
  position: fixed;
@@ -3046,30 +3107,32 @@ a.modal-result-item:focus-visible {
3046
3107
  .modal-container.open {
3047
3108
  animation: modal-slide-in var(--search-snippet-transition) ease-out;
3048
3109
  }
3049
- `, I = "search-modal-snippet";
3050
- class Y extends HTMLElement {
3110
+ `, T = "search-modal-snippet";
3111
+ class W extends HTMLElement {
3051
3112
  constructor() {
3052
3113
  super();
3053
- r(this, "shadow");
3054
- r(this, "client", null);
3055
- r(this, "backdrop", null);
3056
- r(this, "modal", null);
3057
- r(this, "inputElement", null);
3058
- r(this, "resultsContainer", null);
3059
- r(this, "footerCount", null);
3060
- r(this, "isOpen", !1);
3061
- r(this, "results", []);
3062
- r(this, "activeIndex", -1);
3063
- r(this, "debouncedSearch", null);
3064
- 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);
3065
3128
  // Event handler references for cleanup
3066
- r(this, "handleGlobalKeydown", null);
3067
- r(this, "handleInputChange", null);
3068
- r(this, "handleInputKeydown", null);
3069
- r(this, "handleBackdropClick", null);
3129
+ a(this, "handleGlobalKeydown", null);
3130
+ a(this, "handleInputChange", null);
3131
+ a(this, "handleInputKeydown", null);
3132
+ a(this, "handleBackdropClick", null);
3070
3133
  // Scroll lock state
3071
- r(this, "savedBodyStyles", null);
3072
- r(this, "savedHtmlOverflow", null);
3134
+ a(this, "savedBodyStyles", null);
3135
+ a(this, "savedHtmlOverflow", null);
3073
3136
  this.shadow = this.attachShadow({ mode: "open" });
3074
3137
  }
3075
3138
  static get observedAttributes() {
@@ -3086,7 +3149,7 @@ class Y extends HTMLElement {
3086
3149
  ];
3087
3150
  }
3088
3151
  connectedCallback() {
3089
- 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));
3090
3153
  }
3091
3154
  disconnectedCallback() {
3092
3155
  this.cleanup();
@@ -3096,15 +3159,15 @@ class Y extends HTMLElement {
3096
3159
  }
3097
3160
  getProps() {
3098
3161
  return {
3099
- apiUrl: u(this.getAttribute("api-url"), "http://localhost:3000"),
3100
- placeholder: u(this.getAttribute("placeholder"), "Search..."),
3101
- maxResults: f(this.getAttribute("max-results"), 10),
3102
- debounceMs: f(this.getAttribute("debounce-ms"), 300),
3103
- theme: u(this.getAttribute("theme"), "auto"),
3104
- 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"),
3105
3168
  useMetaKey: this.getAttribute("use-meta-key") !== "false",
3106
- hideBranding: v(this.getAttribute("hide-branding"), !1),
3107
- showUrl: v(this.getAttribute("show-url"), !1)
3169
+ hideBranding: b(this.getAttribute("hide-branding"), !1),
3170
+ showUrl: b(this.getAttribute("show-url"), !1)
3108
3171
  };
3109
3172
  }
3110
3173
  initializeClient() {
@@ -3114,21 +3177,21 @@ class Y extends HTMLElement {
3114
3177
  return;
3115
3178
  }
3116
3179
  try {
3117
- this.client = w(e.apiUrl);
3180
+ this.client = y(e.apiUrl);
3118
3181
  } catch (t) {
3119
3182
  console.error("SearchModalSnippet:", t);
3120
3183
  }
3121
3184
  }
3122
3185
  render() {
3123
3186
  const e = this.getProps(), t = (c) => this.performSearch(c);
3124
- this.debouncedSearch = T(
3187
+ this.debouncedSearch = A(
3125
3188
  t,
3126
3189
  e.debounceMs || 300
3127
3190
  );
3128
3191
  const s = document.createElement("style");
3129
- s.textContent = `${x}
3130
- ${G}`;
3131
- 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");
3132
3195
  n.innerHTML = `
3133
3196
  <div class="modal-backdrop" role="presentation"></div>
3134
3197
  <div class="modal-container" role="dialog" aria-modal="true" aria-labelledby="modal-title">
@@ -3169,7 +3232,7 @@ ${G}`;
3169
3232
  <span>Close</span>
3170
3233
  </div>
3171
3234
  </div>
3172
- ${a}
3235
+ ${r}
3173
3236
  </div>
3174
3237
  </div>
3175
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();
@@ -3222,7 +3285,7 @@ ${G}`;
3222
3285
  }
3223
3286
  const e = this.results[this.activeIndex];
3224
3287
  this.dispatchEvent(
3225
- m("result-select", {
3288
+ v("result-select", {
3226
3289
  result: e,
3227
3290
  index: this.activeIndex
3228
3291
  })
@@ -3251,16 +3314,16 @@ ${G}`;
3251
3314
  }
3252
3315
  }
3253
3316
  displayResults(e, t) {
3254
- if (!this.resultsContainer) return;
3317
+ if (this.clearLoadingInterval(), !this.resultsContainer) return;
3255
3318
  if (e.length === 0) {
3256
3319
  this.showNoResultsState(t);
3257
3320
  return;
3258
3321
  }
3259
- const s = e.map((a, n) => this.renderResult(a, n)).join("");
3322
+ const s = e.map((r, n) => this.renderResult(r, n)).join("");
3260
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();
3261
3324
  }
3262
3325
  renderResult(e, t) {
3263
- const s = this.getProps(), a = this.renderResultImage(e.image, e.title);
3326
+ const s = this.getProps(), r = this.renderResultImage(e.image, e.title);
3264
3327
  return `
3265
3328
  <a
3266
3329
  href="${e.url ? l(e.url) : "#"}"
@@ -3272,7 +3335,7 @@ ${G}`;
3272
3335
  data-index="${t}"
3273
3336
  data-url="${l(e.url || "")}"
3274
3337
  >
3275
- ${a}
3338
+ ${r}
3276
3339
  <div class="modal-result-content">
3277
3340
  <div class="modal-result-title">${l(e.title || "")}</div>
3278
3341
  ${e.description ? `<div class="modal-result-description">${l(e.description)}</div>` : ""}
@@ -3303,19 +3366,19 @@ ${G}`;
3303
3366
  attachResultHandlers() {
3304
3367
  const e = this.resultsContainer?.querySelectorAll(".modal-result-item");
3305
3368
  if (!e) return;
3306
- e.forEach((s, a) => {
3369
+ e.forEach((s, r) => {
3307
3370
  s.getAttribute("href") === "#" && s.addEventListener("click", (c) => {
3308
3371
  c.preventDefault();
3309
3372
  }), s.addEventListener("mouseenter", () => {
3310
- this.activeIndex = a, this.updateActiveResult();
3373
+ this.activeIndex = r, this.updateActiveResult();
3311
3374
  });
3312
3375
  }), this.resultsContainer?.querySelectorAll(".modal-result-image")?.forEach((s) => {
3313
3376
  s.addEventListener("load", () => {
3314
3377
  s.classList.add("loaded"), s.closest(".modal-result-image-container")?.querySelector(".modal-result-image-loading")?.remove();
3315
3378
  }), s.addEventListener("error", () => {
3316
- const a = s.closest(".modal-result-image-container");
3317
- a?.querySelector(".modal-result-image-loading")?.remove();
3318
- 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(
3319
3382
  ".modal-result-image-placeholder"
3320
3383
  );
3321
3384
  n && (n.style.display = "flex"), s.style.display = "none";
@@ -3334,18 +3397,28 @@ ${G}`;
3334
3397
  `;
3335
3398
  }
3336
3399
  showEmptyState() {
3337
- 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"));
3338
3401
  }
3339
3402
  showLoadingState() {
3340
- this.resultsContainer && (this.resultsContainer.innerHTML = `
3403
+ this.resultsContainer && (this.clearLoadingInterval(), this.loadingMessageIndex = Math.floor(Math.random() * u.length), this.resultsContainer.innerHTML = `
3341
3404
  <div class="modal-loading">
3342
3405
  <div class="loading" aria-label="Loading"></div>
3343
- <div>Searching...</div>
3406
+ <div class="loading-text loading-text-animate">${u[this.loadingMessageIndex]}</div>
3344
3407
  </div>
3345
- `, 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);
3346
3419
  }
3347
3420
  showNoResultsState(e) {
3348
- this.resultsContainer && (this.resultsContainer.innerHTML = `
3421
+ this.clearLoadingInterval(), this.resultsContainer && (this.resultsContainer.innerHTML = `
3349
3422
  <div class="modal-empty">
3350
3423
  <svg class="modal-empty-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
3351
3424
  <circle cx="11" cy="11" r="8"></circle>
@@ -3357,7 +3430,7 @@ ${G}`;
3357
3430
  `, this.footerCount && (this.footerCount.textContent = "0 results"), this.inputElement && this.inputElement.setAttribute("aria-expanded", "false"));
3358
3431
  }
3359
3432
  showErrorState(e) {
3360
- this.resultsContainer && (this.resultsContainer.innerHTML = `
3433
+ this.clearLoadingInterval(), this.resultsContainer && (this.resultsContainer.innerHTML = `
3361
3434
  <div class="error">
3362
3435
  <strong>Error:</strong> ${l(e)}
3363
3436
  </div>
@@ -3382,7 +3455,7 @@ ${G}`;
3382
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;
3383
3456
  }
3384
3457
  cleanup() {
3385
- 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();
3386
3459
  }
3387
3460
  // Public API
3388
3461
  /**
@@ -3393,13 +3466,13 @@ ${G}`;
3393
3466
  requestAnimationFrame(() => {
3394
3467
  this.inputElement?.focus();
3395
3468
  });
3396
- }), this.lockBodyScroll(), this.dispatchEvent(m("open", void 0)));
3469
+ }), this.lockBodyScroll(), this.dispatchEvent(v("open", void 0)));
3397
3470
  }
3398
3471
  /**
3399
3472
  * Close the search modal
3400
3473
  */
3401
3474
  close() {
3402
- 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)));
3403
3476
  }
3404
3477
  /**
3405
3478
  * Toggle the search modal open/closed
@@ -3426,13 +3499,13 @@ ${G}`;
3426
3499
  return this.isOpen;
3427
3500
  }
3428
3501
  }
3429
- customElements.get(I) || customElements.define(I, Y);
3502
+ customElements.get(T) || customElements.define(T, W);
3430
3503
  export {
3431
3504
  P as AISearchClient,
3432
- O as ChatBubbleSnippet,
3433
- D as ChatPageSnippet,
3505
+ K as ChatBubbleSnippet,
3506
+ U as ChatPageSnippet,
3434
3507
  F as SearchBarSnippet,
3435
- Y as SearchModalSnippet,
3508
+ W as SearchModalSnippet,
3436
3509
  F as default
3437
3510
  };
3438
3511
  //# sourceMappingURL=search-snippet.es.js.map