@cloudflare/ai-search-snippet 0.0.27 → 0.0.29

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,7 +1,7 @@
1
1
  var H = Object.defineProperty;
2
2
  var N = (o, i, e) => i in o ? H(o, i, { enumerable: !0, configurable: !0, writable: !0, value: e }) : o[i] = e;
3
3
  var a = (o, i, e) => N(o, typeof i != "symbol" ? i + "" : i, e);
4
- const p = [
4
+ const u = [
5
5
  "Searching...",
6
6
  "Digging through results...",
7
7
  "Scanning the knowledge base...",
@@ -13,7 +13,7 @@ const p = [
13
13
  "Rummaging through pages...",
14
14
  "Hunting down answers..."
15
15
  ];
16
- function $(o, i) {
16
+ function A(o, i) {
17
17
  let e;
18
18
  return function(...s) {
19
19
  const r = () => {
@@ -29,7 +29,7 @@ function h(o) {
29
29
  function S(o) {
30
30
  return new DOMParser().parseFromString(o, "text/html").documentElement.textContent || "";
31
31
  }
32
- function D(o) {
32
+ function P(o) {
33
33
  const i = new Date(o), t = (/* @__PURE__ */ new Date()).getTime() - i.getTime();
34
34
  if (t < 6e4)
35
35
  return "Just now";
@@ -48,13 +48,13 @@ function D(o) {
48
48
  minute: "2-digit"
49
49
  });
50
50
  }
51
- function A(o) {
51
+ function $(o) {
52
52
  return new Date(o).toLocaleDateString(void 0, {
53
53
  month: "short",
54
54
  day: "numeric"
55
55
  });
56
56
  }
57
- function M(o = "id") {
57
+ function E(o = "id") {
58
58
  return `${o}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
59
59
  }
60
60
  function d(o, i) {
@@ -63,7 +63,7 @@ function d(o, i) {
63
63
  function g(o, i) {
64
64
  return o === null ? i : o === "true" || o === "";
65
65
  }
66
- function f(o, i) {
66
+ function w(o, i) {
67
67
  if (o === null) return i;
68
68
  const e = Number.parseInt(o, 10);
69
69
  return Number.isNaN(e) ? i : e;
@@ -76,7 +76,7 @@ function m(o, i) {
76
76
  cancelable: !0
77
77
  });
78
78
  }
79
- function w(o) {
79
+ function x(o) {
80
80
  if (!o)
81
81
  throw new Error("API URL is required");
82
82
  return new _(o);
@@ -128,7 +128,7 @@ class _ {
128
128
  throw new Error("Response body is empty");
129
129
  const c = await n.json();
130
130
  if (c.success && c.result)
131
- return c.result.chunks.slice(0, 10).map(
131
+ return c.result.chunks.map(
132
132
  (l) => ({
133
133
  type: "result",
134
134
  id: l.id,
@@ -161,12 +161,12 @@ class _ {
161
161
  if (!n.body)
162
162
  throw new Error("Response body is empty");
163
163
  let c = "";
164
- const l = n.body.getReader(), b = new TextDecoder();
164
+ const l = n.body.getReader(), v = new TextDecoder();
165
165
  for (; ; ) {
166
- const { done: u, value: C } = await l.read();
167
- if (u)
166
+ const { done: p, value: C } = await l.read();
167
+ if (p)
168
168
  break;
169
- const R = b.decode(C, { stream: !0 });
169
+ const R = v.decode(C, { stream: !0 });
170
170
  c += R;
171
171
  }
172
172
  yield {
@@ -175,7 +175,7 @@ class _ {
175
175
  title: "",
176
176
  description: c.replaceAll("data: ", "").trim().split(`
177
177
 
178
- `).map((u) => JSON.parse(u)).map((u) => u.response).join(""),
178
+ `).map((p) => JSON.parse(p)).map((p) => p.response).join(""),
179
179
  url: "",
180
180
  metadata: {}
181
181
  };
@@ -235,10 +235,10 @@ class _ {
235
235
  return `req-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
236
236
  }
237
237
  }
238
- const P = `<svg width="32" height="10" viewBox="0 0 412 186" xmlns="http://www.w3.org/2000/svg" aria-label="Cloudflare" role="img">
238
+ const D = `<svg width="32" height="10" viewBox="0 0 412 186" xmlns="http://www.w3.org/2000/svg" aria-label="Cloudflare" role="img">
239
239
  <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"/>
240
240
  <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"/>
241
- </svg>`, V = "https://workers.cloudflare.com/product/ai-search", x = `Powered by <a href="${V}" target="_blank" rel="noopener noreferrer">Cloudflare AI Search ${P}</a>`, B = `
241
+ </svg>`, U = "https://workers.cloudflare.com/product/ai-search", y = `Powered by <a href="${U}" target="_blank" rel="noopener noreferrer">Cloudflare AI Search ${D}</a>`, q = `
242
242
  /* Chat container */
243
243
  .chat-container {
244
244
  display: flex;
@@ -555,7 +555,7 @@ const P = `<svg width="32" height="10" viewBox="0 0 412 186" xmlns="http://www.w
555
555
  .chat-message-bubble a:hover {
556
556
  text-decoration: none;
557
557
  }
558
- `, y = `
558
+ `, k = `
559
559
  :host {
560
560
  /* Colors - Light Mode */
561
561
  --search-snippet-primary-color: #2563eb;
@@ -990,17 +990,17 @@ const P = `<svg width="32" height="10" viewBox="0 0 412 186" xmlns="http://www.w
990
990
  text-align: center;
991
991
  }
992
992
  `;
993
- function j(o) {
993
+ function V(o) {
994
994
  let i = o;
995
- i = O(i), i = i.replace(/```([\s\S]*?)```/g, (n, c) => `<pre><code>${c.trim()}</code></pre>`);
995
+ i = j(i), i = i.replace(/```([\s\S]*?)```/g, (n, c) => `<pre><code>${c.trim()}</code></pre>`);
996
996
  const e = i.split(`
997
997
  `), t = [];
998
998
  let s = !1, r = "";
999
999
  for (let n = 0; n < e.length; n++) {
1000
1000
  const c = e[n], l = c.match(/^(#{1,6})\s+(.+)$/);
1001
1001
  if (l) {
1002
- const u = l[1].length, C = l[2];
1003
- t.push(`<h${u}>${v(C)}</h${u}>`);
1002
+ const p = l[1].length, C = l[2];
1003
+ t.push(`<h${p}>${f(C)}</h${p}>`);
1004
1004
  continue;
1005
1005
  }
1006
1006
  if (c.match(/^---+$/)) {
@@ -1008,37 +1008,37 @@ function j(o) {
1008
1008
  continue;
1009
1009
  }
1010
1010
  if (c.match(/^>\s+/)) {
1011
- const u = c.replace(/^>\s+/, "");
1012
- t.push(`<blockquote>${v(u)}</blockquote>`);
1011
+ const p = c.replace(/^>\s+/, "");
1012
+ t.push(`<blockquote>${f(p)}</blockquote>`);
1013
1013
  continue;
1014
1014
  }
1015
- const b = c.match(/^[-*]\s+(.+)$/);
1016
- if (b) {
1017
- (!s || r !== "ul") && (s && t.push(`</${r}>`), t.push("<ul>"), s = !0, r = "ul"), t.push(`<li>${v(b[1])}</li>`);
1015
+ const v = c.match(/^[-*]\s+(.+)$/);
1016
+ if (v) {
1017
+ (!s || r !== "ul") && (s && t.push(`</${r}>`), t.push("<ul>"), s = !0, r = "ul"), t.push(`<li>${f(v[1])}</li>`);
1018
1018
  continue;
1019
1019
  }
1020
- const k = c.match(/^\d+\.\s+(.+)$/);
1021
- if (k) {
1022
- (!s || r !== "ol") && (s && t.push(`</${r}>`), t.push("<ol>"), s = !0, r = "ol"), t.push(`<li>${v(k[1])}</li>`);
1020
+ const b = c.match(/^\d+\.\s+(.+)$/);
1021
+ if (b) {
1022
+ (!s || r !== "ol") && (s && t.push(`</${r}>`), t.push("<ol>"), s = !0, r = "ol"), t.push(`<li>${f(b[1])}</li>`);
1023
1023
  continue;
1024
1024
  }
1025
1025
  if (s && (t.push(`</${r}>`), s = !1, r = ""), c.trim() === "") {
1026
1026
  t.push("<br />");
1027
1027
  continue;
1028
1028
  }
1029
- t.push(`<p>${v(c)}</p>`);
1029
+ t.push(`<p>${f(c)}</p>`);
1030
1030
  }
1031
1031
  return s && t.push(`</${r}>`), t.join(`
1032
1032
  `);
1033
1033
  }
1034
- function v(o) {
1034
+ function f(o) {
1035
1035
  let i = o;
1036
1036
  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(
1037
1037
  /\[([^\]]+)\]\(([^)]+)\)/g,
1038
1038
  '<a href="$2" target="_blank" rel="noopener noreferrer">$1</a>'
1039
1039
  ), i;
1040
1040
  }
1041
- function O(o) {
1041
+ function j(o) {
1042
1042
  const i = {
1043
1043
  "&": "&amp;",
1044
1044
  "<": "&lt;",
@@ -1048,7 +1048,7 @@ function O(o) {
1048
1048
  };
1049
1049
  return o.replace(/[&<>"']/g, (e) => i[e] || e);
1050
1050
  }
1051
- class q {
1051
+ class B {
1052
1052
  constructor(i, e, t) {
1053
1053
  a(this, "container");
1054
1054
  a(this, "client");
@@ -1127,13 +1127,13 @@ class q {
1127
1127
  */
1128
1128
  async sendMessage(i) {
1129
1129
  const e = {
1130
- id: M("msg"),
1130
+ id: E("msg"),
1131
1131
  role: "user",
1132
1132
  content: i,
1133
1133
  timestamp: Date.now()
1134
1134
  };
1135
1135
  this.addMessage(e), this.renderMessages(!0), this.setStreamingState(!0);
1136
- const t = M("msg"), s = {
1136
+ const t = E("msg"), s = {
1137
1137
  id: t,
1138
1138
  role: "assistant",
1139
1139
  content: "",
@@ -1219,11 +1219,11 @@ class q {
1219
1219
  <div class="chat-message-avatar">${s}</div>
1220
1220
  <div class="chat-message-content">
1221
1221
  <div class="chat-message-bubble">
1222
- ${i.content ? `<div class="chat-message-text">${j(i.content)}</div>` : ""}
1223
- ${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">${p[this.loadingMessageIndex]}</span></div>` : ""}
1222
+ ${i.content ? `<div class="chat-message-text">${V(i.content)}</div>` : ""}
1223
+ ${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>` : ""}
1224
1224
  </div>
1225
1225
  <div class="chat-message-metadata">
1226
- <span class="chat-message-time">${D(i.timestamp)}</span>
1226
+ <span class="chat-message-time">${P(i.timestamp)}</span>
1227
1227
  </div>
1228
1228
  </div>
1229
1229
  </div>
@@ -1244,8 +1244,8 @@ class q {
1244
1244
  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();
1245
1245
  }
1246
1246
  startLoadingMessages() {
1247
- this.loadingMessageIndex = Math.floor(Math.random() * p.length), this.loadingMessageInterval = setInterval(() => {
1248
- this.loadingMessageIndex = (this.loadingMessageIndex + 1) % p.length, this.isStreaming && this.renderMessages(!0);
1247
+ this.loadingMessageIndex = Math.floor(Math.random() * u.length), this.loadingMessageInterval = setInterval(() => {
1248
+ this.loadingMessageIndex = (this.loadingMessageIndex + 1) % u.length, this.isStreaming && this.renderMessages(!0);
1249
1249
  }, 2500);
1250
1250
  }
1251
1251
  clearLoadingMessages() {
@@ -1276,8 +1276,8 @@ class q {
1276
1276
  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;
1277
1277
  }
1278
1278
  }
1279
- const E = "chat-bubble-snippet";
1280
- class K extends HTMLElement {
1279
+ const M = "chat-bubble-snippet";
1280
+ class O extends HTMLElement {
1281
1281
  constructor() {
1282
1282
  super();
1283
1283
  a(this, "shadow");
@@ -1307,7 +1307,7 @@ class K extends HTMLElement {
1307
1307
  }
1308
1308
  getProps() {
1309
1309
  return {
1310
- apiUrl: d(this.getAttribute("api-url"), "http://localhost:3000"),
1310
+ apiUrl: d(this.getAttribute("api-url"), ""),
1311
1311
  placeholder: d(this.getAttribute("placeholder"), "Type a message..."),
1312
1312
  theme: d(this.getAttribute("theme"), "auto"),
1313
1313
  hideBranding: g(this.getAttribute("hide-branding"), !1)
@@ -1316,19 +1316,19 @@ class K extends HTMLElement {
1316
1316
  initializeClient() {
1317
1317
  const e = this.getProps();
1318
1318
  if (!e.apiUrl) {
1319
- console.error("ChatBubbleSnippet: api-url attribute is required");
1319
+ console.error("ChatBubbleSnippet: api-url attribute is required"), this.client = null;
1320
1320
  return;
1321
1321
  }
1322
1322
  try {
1323
- this.client = w(e.apiUrl);
1323
+ this.client = x(e.apiUrl);
1324
1324
  } catch (t) {
1325
1325
  console.error("ChatBubbleSnippet:", t);
1326
1326
  }
1327
1327
  }
1328
1328
  render() {
1329
1329
  const e = document.createElement("style");
1330
- e.textContent = `${y}
1331
- ${B}
1330
+ e.textContent = `${k}
1331
+ ${q}
1332
1332
  ${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();
1333
1333
  }
1334
1334
  getBubbleStyles() {
@@ -1508,7 +1508,7 @@ ${this.getBubbleStyles()}`, this.container = document.createElement("div"), this
1508
1508
  </div>
1509
1509
  </div>
1510
1510
  <div class="chat-content"></div>
1511
- ${this.getProps().hideBranding ? "" : `<div class="powered-by">${x}</div>`}
1511
+ ${this.getProps().hideBranding ? "" : `<div class="powered-by">${y}</div>`}
1512
1512
  </div>
1513
1513
  `;
1514
1514
  }
@@ -1536,11 +1536,19 @@ ${this.getBubbleStyles()}`, this.container = document.createElement("div"), this
1536
1536
  this.isMinimized ? e?.classList.add("minimized") : e?.classList.remove("minimized");
1537
1537
  }
1538
1538
  initializeChatView() {
1539
- if (this.chatView || !this.client) return;
1539
+ if (this.chatView) return;
1540
1540
  const e = this.shadow.querySelector(".chat-content");
1541
1541
  if (!e) return;
1542
+ if (!this.client) {
1543
+ e.innerHTML = `
1544
+ <div style="padding: 16px; color: var(--search-snippet-error-color, #ef4444); font-family: var(--search-snippet-font-family, sans-serif); font-size: var(--search-snippet-font-size-base, 14px);">
1545
+ <strong>Error:</strong> The <code>api-url</code> attribute is required. Please provide a valid API URL.
1546
+ </div>
1547
+ `;
1548
+ return;
1549
+ }
1542
1550
  const t = this.getProps();
1543
- this.chatView = new q(e, this.client, t);
1551
+ this.chatView = new B(e, this.client, t);
1544
1552
  }
1545
1553
  updateTheme(e) {
1546
1554
  (e === "light" || e === "dark" ? e : null) === null && this.hasAttribute("theme") && this.getAttribute("theme") !== "auto" && this.removeAttribute("theme");
@@ -1559,9 +1567,9 @@ ${this.getBubbleStyles()}`, this.container = document.createElement("div"), this
1559
1567
  return this.chatView?.getMessages() || [];
1560
1568
  }
1561
1569
  }
1562
- customElements.get(E) || customElements.define(E, K);
1570
+ customElements.get(M) || customElements.define(M, O);
1563
1571
  const L = "chat-page-snippet", I = "chat-page-sessions";
1564
- class U extends HTMLElement {
1572
+ class K extends HTMLElement {
1565
1573
  constructor() {
1566
1574
  super();
1567
1575
  a(this, "shadow");
@@ -1593,7 +1601,7 @@ class U extends HTMLElement {
1593
1601
  }
1594
1602
  getProps() {
1595
1603
  return {
1596
- apiUrl: d(this.getAttribute("api-url"), "http://localhost:3000"),
1604
+ apiUrl: d(this.getAttribute("api-url"), ""),
1597
1605
  placeholder: d(this.getAttribute("placeholder"), "Type a message..."),
1598
1606
  theme: d(this.getAttribute("theme"), "auto"),
1599
1607
  hideBranding: g(this.getAttribute("hide-branding"), !1)
@@ -1602,19 +1610,19 @@ class U extends HTMLElement {
1602
1610
  initializeClient() {
1603
1611
  const e = this.getProps();
1604
1612
  if (!e.apiUrl) {
1605
- console.error("ChatPageSnippet: api-url attribute is required");
1613
+ console.error("ChatPageSnippet: api-url attribute is required"), this.client = null;
1606
1614
  return;
1607
1615
  }
1608
1616
  try {
1609
- this.client = w(e.apiUrl);
1617
+ this.client = x(e.apiUrl);
1610
1618
  } catch (t) {
1611
1619
  console.error("ChatPageSnippet:", t);
1612
1620
  }
1613
1621
  }
1614
1622
  render() {
1615
1623
  const e = document.createElement("style");
1616
- e.textContent = `${y}
1617
- ${B}
1624
+ e.textContent = `${k}
1625
+ ${q}
1618
1626
  ${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();
1619
1627
  }
1620
1628
  getPageStyles() {
@@ -1906,7 +1914,7 @@ ${this.getPageStyles()}`, this.container = document.createElement("div"), this.c
1906
1914
  New Chat
1907
1915
  </button>
1908
1916
  <div class="chat-list"></div>
1909
- ${this.getProps().hideBranding ? "" : `<div class="powered-by">${x}</div>`}
1917
+ ${this.getProps().hideBranding ? "" : `<div class="powered-by">${y}</div>`}
1910
1918
  </div>
1911
1919
  <div class="chat-main">
1912
1920
  <div class="chat-page-header">
@@ -1947,11 +1955,18 @@ ${this.getPageStyles()}`, this.container = document.createElement("div"), this.c
1947
1955
  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;
1948
1956
  }
1949
1957
  setupView() {
1950
- if (!this.client) return;
1951
1958
  const e = this.shadow.querySelector(".container");
1959
+ if (!this.client) {
1960
+ e && (e.innerHTML = `
1961
+ <div style="padding: 16px; color: var(--search-snippet-error-color, #ef4444); font-family: var(--search-snippet-font-family, sans-serif); font-size: var(--search-snippet-font-size-base, 14px);">
1962
+ <strong>Error:</strong> The <code>api-url</code> attribute is required. Please provide a valid API URL.
1963
+ </div>
1964
+ `);
1965
+ return;
1966
+ }
1952
1967
  if (!e) return;
1953
1968
  const t = this.getProps();
1954
- if (this.chatView = new q(e, this.client, t), this.sessions.length === 0)
1969
+ if (this.chatView = new B(e, this.client, t), this.sessions.length === 0)
1955
1970
  this.createNewChat();
1956
1971
  else {
1957
1972
  const s = this.sessions[0];
@@ -2092,7 +2107,7 @@ ${this.getPageStyles()}`, this.container = document.createElement("div"), this.c
2092
2107
  return this.sessions.find((e) => e.id === this.currentSessionId) || null;
2093
2108
  }
2094
2109
  }
2095
- customElements.get(L) || customElements.define(L, U);
2110
+ customElements.get(L) || customElements.define(L, K);
2096
2111
  const G = `
2097
2112
  /* Search view states */
2098
2113
  .search-view {
@@ -2463,8 +2478,8 @@ a.search-result-item:focus-visible {
2463
2478
  border-radius: 2px;
2464
2479
  font-weight: var(--search-snippet-font-weight-medium);
2465
2480
  }
2466
- `, z = "search-bar-snippet";
2467
- class F extends HTMLElement {
2481
+ `, z = "search-bar-snippet", F = 10, Y = 100;
2482
+ class W extends HTMLElement {
2468
2483
  constructor() {
2469
2484
  super();
2470
2485
  a(this, "shadow");
@@ -2509,10 +2524,10 @@ class F extends HTMLElement {
2509
2524
  }
2510
2525
  getProps() {
2511
2526
  return {
2512
- apiUrl: d(this.getAttribute("api-url"), "http://localhost:3000"),
2527
+ apiUrl: d(this.getAttribute("api-url"), ""),
2513
2528
  placeholder: d(this.getAttribute("placeholder"), "Search..."),
2514
- maxResults: f(this.getAttribute("max-results"), 10),
2515
- debounceMs: f(this.getAttribute("debounce-ms"), 300),
2529
+ maxResults: w(this.getAttribute("max-results"), 10),
2530
+ debounceMs: w(this.getAttribute("debounce-ms"), 300),
2516
2531
  theme: d(this.getAttribute("theme"), "auto"),
2517
2532
  hideBranding: g(this.getAttribute("hide-branding"), !1),
2518
2533
  showUrl: g(this.getAttribute("show-url"), !1),
@@ -2524,23 +2539,23 @@ class F extends HTMLElement {
2524
2539
  initializeClient() {
2525
2540
  const e = this.getProps();
2526
2541
  if (!e.apiUrl) {
2527
- console.error("SearchBarSnippet: api-url attribute is required");
2542
+ console.error("SearchBarSnippet: api-url attribute is required"), this.client = null, this.showMissingApiUrlError();
2528
2543
  return;
2529
2544
  }
2530
2545
  try {
2531
- this.client = w(e.apiUrl);
2546
+ this.client = x(e.apiUrl);
2532
2547
  } catch (t) {
2533
2548
  console.error("SearchBarSnippet:", t);
2534
2549
  }
2535
2550
  }
2536
2551
  render() {
2537
2552
  const e = this.getProps(), t = (r) => this.performSearch(r);
2538
- this.debouncedSearch = $(
2553
+ this.debouncedSearch = A(
2539
2554
  t,
2540
2555
  e.debounceMs || 400
2541
2556
  );
2542
2557
  const s = document.createElement("style");
2543
- s.textContent = `${y}
2558
+ s.textContent = `${k}
2544
2559
  ${G}`, this.container = document.createElement("div"), this.container.className = "container", this.container.innerHTML = `
2545
2560
  <div class="search-view">
2546
2561
  <div class="search-input-wrapper">
@@ -2563,7 +2578,7 @@ ${G}`, this.container = document.createElement("div"), this.container.className
2563
2578
  </div>
2564
2579
  </div>
2565
2580
  </div>
2566
- `, this.shadow.innerHTML = "", this.shadow.appendChild(s), this.shadow.appendChild(this.container), this.inputElement = this.container.querySelector(".search-input"), this.resultsContainer = this.container.querySelector(".search-results-wrapper"), this.searchButton = this.container.querySelector(".search-submit-button"), this.attachEventListeners();
2581
+ `, this.shadow.innerHTML = "", this.shadow.appendChild(s), this.shadow.appendChild(this.container), this.inputElement = this.container.querySelector(".search-input"), this.resultsContainer = this.container.querySelector(".search-results-wrapper"), this.searchButton = this.container.querySelector(".search-submit-button"), this.attachEventListeners(), this.client || this.showMissingApiUrlError();
2567
2582
  }
2568
2583
  attachEventListeners() {
2569
2584
  this.inputElement && (this.handleInputChange = (e) => {
@@ -2582,50 +2597,53 @@ ${G}`, this.container = document.createElement("div"), this.container.className
2582
2597
  }, this.searchButton.addEventListener("click", this.handleSearchButtonClick)));
2583
2598
  }
2584
2599
  async performSearch(e) {
2585
- if (this.client) {
2586
- this.currentSearchController && (this.currentSearchController.abort(), this.currentSearchController = null), this.currentSearchController = new AbortController(), this.showLoadingState();
2587
- try {
2588
- const t = await this.client.search(e, {
2589
- streaming: !1,
2590
- signal: this.currentSearchController.signal
2591
- });
2592
- this.displayResults(t, e);
2593
- } catch (t) {
2594
- if (t.name === "AbortError")
2595
- return;
2596
- this.showErrorState(t.message);
2597
- } finally {
2598
- this.currentSearchController = null;
2599
- }
2600
+ if (!this.client) {
2601
+ this.showMissingApiUrlError();
2602
+ return;
2603
+ }
2604
+ this.currentSearchController && (this.currentSearchController.abort(), this.currentSearchController = null), this.currentSearchController = new AbortController(), this.showLoadingState();
2605
+ try {
2606
+ const t = await this.client.search(e, {
2607
+ streaming: !1,
2608
+ signal: this.currentSearchController.signal,
2609
+ maxResults: Y
2610
+ }), s = this.getProps(), r = t.slice(0, s.maxResults || F);
2611
+ this.displayResults(r, e, t.length);
2612
+ } catch (t) {
2613
+ if (t.name === "AbortError")
2614
+ return;
2615
+ this.showErrorState(t.message);
2616
+ } finally {
2617
+ this.currentSearchController = null;
2600
2618
  }
2601
2619
  }
2602
- displayResults(e, t) {
2620
+ displayResults(e, t, s = e.length) {
2603
2621
  if (this.clearLoadingInterval(), !this.resultsContainer) return;
2604
2622
  if (e.length === 0) {
2605
2623
  this.showNoResultsState(t);
2606
2624
  return;
2607
2625
  }
2608
- const s = this.getProps(), r = s.hideBranding ? "" : `<div class="powered-by-inline">${x}</div>`, n = s.seeMore ? `<div class="search-footer">
2609
- <a href="${h(s.seeMore + encodeURIComponent(t))}" class="search-see-more">
2626
+ const r = this.getProps(), n = r.hideBranding ? "" : `<div class="powered-by-inline">${y}</div>`, c = s > e.length, l = c ? `Showing ${e.length} of ${s} results` : `Found ${s} result${s === 1 ? "" : "s"}`, v = r.seeMore && c ? `<div class="search-footer">
2627
+ <a href="${h(r.seeMore + encodeURIComponent(t))}" class="search-see-more">
2610
2628
  <span>See more results</span>
2611
2629
  <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
2612
2630
  </a>
2613
- </div>` : "", c = `
2631
+ </div>` : "", b = `
2614
2632
  <div class="search-header">
2615
2633
  <div class="search-count">
2616
- Found ${e.length} result${e.length === 1 ? "" : "s"}
2634
+ ${l}
2617
2635
  </div>
2618
- ${r}
2636
+ ${n}
2619
2637
  </div>
2620
2638
  <div class="search-results">
2621
- ${e.map((l) => this.renderResult(l)).join("")}
2639
+ ${e.map((p) => this.renderResult(p)).join("")}
2622
2640
  </div>
2623
- ${n}
2641
+ ${v}
2624
2642
  `;
2625
- this.resultsContainer.innerHTML = c, this.attachResultHandlers();
2643
+ this.resultsContainer.innerHTML = b, this.attachResultHandlers();
2626
2644
  }
2627
2645
  renderResult(e) {
2628
- const t = this.getProps(), s = t.hideThumbnails ? "" : this.renderResultImage(e.image, e.title), r = e.url ? h(e.url) : "#", n = t.showDate && e.timestamp !== void 0 ? `<div class="search-result-date">${h(A(e.timestamp))}</div>` : "", c = t.showUrl && e.url || n ? `<div class="search-result-metadata">
2646
+ const t = this.getProps(), s = t.hideThumbnails ? "" : this.renderResultImage(e.image, e.title), r = e.url ? h(e.url) : "#", n = t.showDate && e.timestamp !== void 0 ? `<div class="search-result-date">${h($(e.timestamp))}</div>` : "", c = t.showUrl && e.url || n ? `<div class="search-result-metadata">
2629
2647
  ${t.showUrl && e.url ? `<span class="search-result-url">${h(e.url)}</span>` : '<span class="search-result-url search-result-url-empty"></span>'}
2630
2648
  ${n}
2631
2649
  </div>` : "";
@@ -2680,18 +2698,18 @@ ${G}`, this.container = document.createElement("div"), this.container.className
2680
2698
  });
2681
2699
  }
2682
2700
  showLoadingState() {
2683
- this.resultsContainer && (this.clearLoadingInterval(), this.loadingMessageIndex = Math.floor(Math.random() * p.length), this.resultsContainer.innerHTML = `
2701
+ this.resultsContainer && (this.clearLoadingInterval(), this.loadingMessageIndex = Math.floor(Math.random() * u.length), this.resultsContainer.innerHTML = `
2684
2702
  <div class="search-loading">
2685
2703
  <div class="loading" aria-label="Loading"></div>
2686
- <div class="loading-text loading-text-animate">${p[this.loadingMessageIndex]}</div>
2704
+ <div class="loading-text loading-text-animate">${u[this.loadingMessageIndex]}</div>
2687
2705
  </div>
2688
2706
  `, this.startLoadingInterval());
2689
2707
  }
2690
2708
  startLoadingInterval() {
2691
2709
  this.loadingMessageInterval = setInterval(() => {
2692
- this.loadingMessageIndex = (this.loadingMessageIndex + 1) % p.length;
2710
+ this.loadingMessageIndex = (this.loadingMessageIndex + 1) % u.length;
2693
2711
  const e = this.resultsContainer?.querySelector(".loading-text");
2694
- e && (e.classList.remove("loading-text-animate"), e.offsetWidth, e.textContent = p[this.loadingMessageIndex], e.classList.add("loading-text-animate"));
2712
+ e && (e.classList.remove("loading-text-animate"), e.offsetWidth, e.textContent = u[this.loadingMessageIndex], e.classList.add("loading-text-animate"));
2695
2713
  }, 2500);
2696
2714
  }
2697
2715
  clearLoadingInterval() {
@@ -2732,6 +2750,9 @@ ${G}`, this.container = document.createElement("div"), this.container.className
2732
2750
  </div>
2733
2751
  `);
2734
2752
  }
2753
+ showMissingApiUrlError() {
2754
+ this.resultsContainer && this.showErrorState("The api-url attribute is required. Please provide a valid API URL.");
2755
+ }
2735
2756
  updateTheme(e) {
2736
2757
  const t = e === "light" || e === "dark" || e === "auto" ? e : "auto";
2737
2758
  t === "auto" ? this.removeAttribute("theme") : this.setAttribute("theme", t);
@@ -2744,8 +2765,8 @@ ${G}`, this.container = document.createElement("div"), this.container.className
2744
2765
  await this.performSearch(e);
2745
2766
  }
2746
2767
  }
2747
- customElements.get(z) || customElements.define(z, F);
2748
- const Y = `
2768
+ customElements.get(z) || customElements.define(z, W);
2769
+ const X = `
2749
2770
  /* Modal backdrop */
2750
2771
  .modal-backdrop {
2751
2772
  position: fixed;
@@ -3182,8 +3203,8 @@ a.modal-result-item:focus-visible {
3182
3203
  .modal-container.open {
3183
3204
  animation: modal-slide-in var(--search-snippet-transition) ease-out;
3184
3205
  }
3185
- `, T = "search-modal-snippet";
3186
- class W extends HTMLElement {
3206
+ `, T = "search-modal-snippet", J = 10, Z = 100;
3207
+ class Q extends HTMLElement {
3187
3208
  constructor() {
3188
3209
  super();
3189
3210
  a(this, "shadow");
@@ -3237,10 +3258,10 @@ class W extends HTMLElement {
3237
3258
  }
3238
3259
  getProps() {
3239
3260
  return {
3240
- apiUrl: d(this.getAttribute("api-url"), "http://localhost:3000"),
3261
+ apiUrl: d(this.getAttribute("api-url"), ""),
3241
3262
  placeholder: d(this.getAttribute("placeholder"), "Search..."),
3242
- maxResults: f(this.getAttribute("max-results"), 10),
3243
- debounceMs: f(this.getAttribute("debounce-ms"), 300),
3263
+ maxResults: w(this.getAttribute("max-results"), 10),
3264
+ debounceMs: w(this.getAttribute("debounce-ms"), 300),
3244
3265
  theme: d(this.getAttribute("theme"), "auto"),
3245
3266
  shortcut: d(this.getAttribute("shortcut"), "k"),
3246
3267
  useMetaKey: this.getAttribute("use-meta-key") !== "false",
@@ -3254,25 +3275,25 @@ class W extends HTMLElement {
3254
3275
  initializeClient() {
3255
3276
  const e = this.getProps();
3256
3277
  if (!e.apiUrl) {
3257
- console.error("SearchModalSnippet: api-url attribute is required");
3278
+ console.error("SearchModalSnippet: api-url attribute is required"), this.client = null, this.showMissingApiUrlError();
3258
3279
  return;
3259
3280
  }
3260
3281
  try {
3261
- this.client = w(e.apiUrl);
3282
+ this.client = x(e.apiUrl);
3262
3283
  } catch (t) {
3263
3284
  console.error("SearchModalSnippet:", t);
3264
3285
  }
3265
3286
  }
3266
3287
  render() {
3267
3288
  const e = this.getProps(), t = (c) => this.performSearch(c);
3268
- this.debouncedSearch = $(
3289
+ this.debouncedSearch = A(
3269
3290
  t,
3270
3291
  e.debounceMs || 300
3271
3292
  );
3272
3293
  const s = document.createElement("style");
3273
- s.textContent = `${y}
3274
- ${Y}`;
3275
- const r = e.hideBranding ? "" : `<div class="powered-by-inline">${x}</div>`, n = document.createElement("div");
3294
+ s.textContent = `${k}
3295
+ ${X}`;
3296
+ const r = e.hideBranding ? "" : `<div class="powered-by-inline">${y}</div>`, n = document.createElement("div");
3276
3297
  n.innerHTML = `
3277
3298
  <div class="modal-backdrop" role="presentation"></div>
3278
3299
  <div class="modal-container" role="dialog" aria-modal="true" aria-labelledby="modal-title">
@@ -3316,7 +3337,7 @@ ${Y}`;
3316
3337
  ${r}
3317
3338
  </div>
3318
3339
  </div>
3319
- `, 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();
3340
+ `, 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(), this.client || this.showMissingApiUrlError();
3320
3341
  }
3321
3342
  attachGlobalKeyboardShortcut() {
3322
3343
  const e = this.getProps(), t = e.shortcut?.toLowerCase() || "k";
@@ -3377,37 +3398,40 @@ ${Y}`;
3377
3398
  t && e.url && t.click(), this.close();
3378
3399
  }
3379
3400
  async performSearch(e) {
3380
- if (this.client) {
3381
- this.currentSearchController && (this.currentSearchController.abort(), this.currentSearchController = null), this.currentSearchController = new AbortController(), this.showLoadingState();
3382
- try {
3383
- const t = await this.client.search(e, {
3384
- streaming: !1,
3385
- signal: this.currentSearchController.signal
3386
- }), s = this.getProps();
3387
- this.results = t.slice(0, s.maxResults || 10), this.activeIndex = this.results.length > 0 ? 0 : -1, this.displayResults(this.results, e);
3388
- } catch (t) {
3389
- if (t.name === "AbortError")
3390
- return;
3391
- this.showErrorState(t.message);
3392
- } finally {
3393
- this.currentSearchController = null;
3394
- }
3401
+ if (!this.client) {
3402
+ this.showMissingApiUrlError();
3403
+ return;
3404
+ }
3405
+ this.currentSearchController && (this.currentSearchController.abort(), this.currentSearchController = null), this.currentSearchController = new AbortController(), this.showLoadingState();
3406
+ try {
3407
+ const t = await this.client.search(e, {
3408
+ streaming: !1,
3409
+ signal: this.currentSearchController.signal,
3410
+ maxResults: Z
3411
+ }), s = this.getProps();
3412
+ this.results = t.slice(0, s.maxResults || J), this.activeIndex = this.results.length > 0 ? 0 : -1, this.displayResults(this.results, e, t.length);
3413
+ } catch (t) {
3414
+ if (t.name === "AbortError")
3415
+ return;
3416
+ this.showErrorState(t.message);
3417
+ } finally {
3418
+ this.currentSearchController = null;
3395
3419
  }
3396
3420
  }
3397
- displayResults(e, t) {
3398
- if (this.clearLoadingInterval(), !this.resultsContainer) return;
3421
+ displayResults(e, t, s = e.length) {
3422
+ if (console.log({ results: e, query: t, totalResults: s }), this.clearLoadingInterval(), !this.resultsContainer) return;
3399
3423
  if (e.length === 0) {
3400
3424
  this.showNoResultsState(t);
3401
3425
  return;
3402
3426
  }
3403
- const s = this.getProps(), r = e.map((c, l) => this.renderResult(c, l)).join(""), n = s.seeMore ? `<a href="${h(s.seeMore + encodeURIComponent(t))}" class="modal-see-more">
3427
+ const r = this.getProps(), n = e.map((b, p) => this.renderResult(b, p)).join(""), c = s > e.length, l = c ? `Showing ${e.length} of ${s} results` : `${s} result${s === 1 ? "" : "s"}`, v = r.seeMore && c ? `<a href="${h(r.seeMore + encodeURIComponent(t))}" class="modal-see-more">
3404
3428
  <span>See more results</span>
3405
3429
  <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
3406
3430
  </a>` : "";
3407
- this.resultsContainer.innerHTML = r + n, this.footerCount && (this.footerCount.textContent = `${e.length} result${e.length === 1 ? "" : "s"}`), this.inputElement && this.inputElement.setAttribute("aria-expanded", "true"), this.attachResultHandlers(), this.updateActiveResult();
3431
+ this.resultsContainer.innerHTML = n + v, this.footerCount && (this.footerCount.textContent = l), this.inputElement && this.inputElement.setAttribute("aria-expanded", "true"), this.attachResultHandlers(), this.updateActiveResult();
3408
3432
  }
3409
3433
  renderResult(e, t) {
3410
- const s = this.getProps(), r = s.hideThumbnails ? "" : this.renderResultImage(e.image, e.title), n = e.url ? h(e.url) : "#", c = s.showDate && e.timestamp !== void 0 ? `<div class="modal-result-date">${h(A(e.timestamp))}</div>` : "", l = s.showUrl && e.url || c ? `<div class="modal-result-metadata">
3434
+ const s = this.getProps(), r = s.hideThumbnails ? "" : this.renderResultImage(e.image, e.title), n = e.url ? h(e.url) : "#", c = s.showDate && e.timestamp !== void 0 ? `<div class="modal-result-date">${h($(e.timestamp))}</div>` : "", l = s.showUrl && e.url || c ? `<div class="modal-result-metadata">
3411
3435
  ${s.showUrl && e.url ? `<span class="modal-result-url">${h(e.url)}</span>` : '<span class="modal-result-url modal-result-url-empty"></span>'}
3412
3436
  ${c}
3413
3437
  </div>` : "";
@@ -3487,18 +3511,18 @@ ${Y}`;
3487
3511
  this.clearLoadingInterval(), this.resultsContainer && (this.resultsContainer.innerHTML = this.renderEmptyState(), this.footerCount && (this.footerCount.textContent = ""), this.inputElement && this.inputElement.setAttribute("aria-expanded", "false"));
3488
3512
  }
3489
3513
  showLoadingState() {
3490
- this.resultsContainer && (this.clearLoadingInterval(), this.loadingMessageIndex = Math.floor(Math.random() * p.length), this.resultsContainer.innerHTML = `
3514
+ this.resultsContainer && (this.clearLoadingInterval(), this.loadingMessageIndex = Math.floor(Math.random() * u.length), this.resultsContainer.innerHTML = `
3491
3515
  <div class="modal-loading">
3492
3516
  <div class="loading" aria-label="Loading"></div>
3493
- <div class="loading-text loading-text-animate">${p[this.loadingMessageIndex]}</div>
3517
+ <div class="loading-text loading-text-animate">${u[this.loadingMessageIndex]}</div>
3494
3518
  </div>
3495
- `, this.footerCount && (this.footerCount.textContent = p[this.loadingMessageIndex]), this.startLoadingInterval());
3519
+ `, this.footerCount && (this.footerCount.textContent = u[this.loadingMessageIndex]), this.startLoadingInterval());
3496
3520
  }
3497
3521
  startLoadingInterval() {
3498
3522
  this.loadingMessageInterval = setInterval(() => {
3499
- this.loadingMessageIndex = (this.loadingMessageIndex + 1) % p.length;
3523
+ this.loadingMessageIndex = (this.loadingMessageIndex + 1) % u.length;
3500
3524
  const e = this.resultsContainer?.querySelector(".loading-text");
3501
- e && (e.classList.remove("loading-text-animate"), e.offsetWidth, e.textContent = p[this.loadingMessageIndex], e.classList.add("loading-text-animate")), this.footerCount && (this.footerCount.textContent = p[this.loadingMessageIndex]);
3525
+ 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]);
3502
3526
  }, 2500);
3503
3527
  }
3504
3528
  clearLoadingInterval() {
@@ -3523,6 +3547,9 @@ ${Y}`;
3523
3547
  </div>
3524
3548
  `, this.footerCount && (this.footerCount.textContent = "Error"));
3525
3549
  }
3550
+ showMissingApiUrlError() {
3551
+ this.resultsContainer && this.showErrorState("The api-url attribute is required. Please provide a valid API URL.");
3552
+ }
3526
3553
  updateTheme(e) {
3527
3554
  const t = e === "light" || e === "dark" || e === "auto" ? e : "auto";
3528
3555
  t === "auto" ? this.removeAttribute("theme") : this.setAttribute("theme", t);
@@ -3586,13 +3613,13 @@ ${Y}`;
3586
3613
  return this.isOpen;
3587
3614
  }
3588
3615
  }
3589
- customElements.get(T) || customElements.define(T, W);
3616
+ customElements.get(T) || customElements.define(T, Q);
3590
3617
  export {
3591
3618
  _ as AISearchClient,
3592
- K as ChatBubbleSnippet,
3593
- U as ChatPageSnippet,
3594
- F as SearchBarSnippet,
3595
- W as SearchModalSnippet,
3596
- F as default
3619
+ O as ChatBubbleSnippet,
3620
+ K as ChatPageSnippet,
3621
+ W as SearchBarSnippet,
3622
+ Q as SearchModalSnippet,
3623
+ W as default
3597
3624
  };
3598
3625
  //# sourceMappingURL=search-snippet.es.js.map