@cloudflare/ai-search-snippet 0.0.25 → 0.0.27

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
- 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 d = [
1
+ var H = Object.defineProperty;
2
+ var N = (o, i, e) => i in o ? H(o, i, { enumerable: !0, configurable: !0, writable: !0, value: e }) : o[i] = e;
3
+ var a = (o, i, e) => N(o, typeof i != "symbol" ? i + "" : i, e);
4
+ const p = [
5
5
  "Searching...",
6
6
  "Digging through results...",
7
7
  "Scanning the knowledge base...",
@@ -13,7 +13,7 @@ const d = [
13
13
  "Rummaging through pages...",
14
14
  "Hunting down answers..."
15
15
  ];
16
- function A(o, i) {
16
+ function $(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 N(o) {
32
+ function D(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,19 @@ function N(o) {
48
48
  minute: "2-digit"
49
49
  });
50
50
  }
51
- function E(o = "id") {
51
+ function A(o) {
52
+ return new Date(o).toLocaleDateString(void 0, {
53
+ month: "short",
54
+ day: "numeric"
55
+ });
56
+ }
57
+ function M(o = "id") {
52
58
  return `${o}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
53
59
  }
54
- function p(o, i) {
60
+ function d(o, i) {
55
61
  return o !== null ? o : i;
56
62
  }
57
- function m(o, i) {
63
+ function g(o, i) {
58
64
  return o === null ? i : o === "true" || o === "";
59
65
  }
60
66
  function f(o, i) {
@@ -62,7 +68,7 @@ function f(o, i) {
62
68
  const e = Number.parseInt(o, 10);
63
69
  return Number.isNaN(e) ? i : e;
64
70
  }
65
- function g(o, i) {
71
+ function m(o, i) {
66
72
  return new CustomEvent(o, {
67
73
  detail: i,
68
74
  bubbles: !0,
@@ -73,7 +79,7 @@ function g(o, i) {
73
79
  function w(o) {
74
80
  if (!o)
75
81
  throw new Error("API URL is required");
76
- return new P(o);
82
+ return new _(o);
77
83
  }
78
84
  class _ {
79
85
  constructor(i) {
@@ -81,23 +87,6 @@ class _ {
81
87
  a(this, "baseUrl");
82
88
  this.baseUrl = i.replace(/\/$/, "");
83
89
  }
84
- search(i, e) {
85
- throw new Error("Not implemented");
86
- }
87
- searchStream(i, e) {
88
- throw new Error("Not implemented");
89
- }
90
- chat(i, e) {
91
- throw new Error("Not implemented");
92
- }
93
- cancelRequest(i) {
94
- throw new Error("Not implemented");
95
- }
96
- cancelAllRequests() {
97
- throw new Error("Not implemented");
98
- }
99
- }
100
- class P extends _ {
101
90
  request(i = {}, e, t) {
102
91
  const s = e === "search" ? "snippet-search" : "snippet-chat-completions";
103
92
  return fetch(`${this.baseUrl}/${e}`, {
@@ -128,7 +117,7 @@ class P extends _ {
128
117
  {
129
118
  query: i,
130
119
  streaming: !1,
131
- maxResults: 30
120
+ maxResults: e.maxResults || 30
132
121
  },
133
122
  "search",
134
123
  r
@@ -143,10 +132,11 @@ class P extends _ {
143
132
  (l) => ({
144
133
  type: "result",
145
134
  id: l.id,
146
- title: S(l.item.metadata.title),
147
- description: l.item.metadata.description ? S(l.item.metadata.description) : "",
135
+ title: S(l.item.metadata?.title),
136
+ description: l.item.metadata?.description ? S(l.item.metadata?.description) : "",
137
+ timestamp: l.item.timestamp ?? void 0,
148
138
  url: l.item.key,
149
- image: l.item.metadata.image || void 0,
139
+ image: l.item.metadata?.image || void 0,
150
140
  metadata: l.item.metadata
151
141
  })
152
142
  );
@@ -176,8 +166,8 @@ class P extends _ {
176
166
  const { done: u, value: C } = await l.read();
177
167
  if (u)
178
168
  break;
179
- const B = b.decode(C, { stream: !0 });
180
- c += B;
169
+ const R = b.decode(C, { stream: !0 });
170
+ c += R;
181
171
  }
182
172
  yield {
183
173
  type: "result",
@@ -245,10 +235,10 @@ class P extends _ {
245
235
  return `req-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
246
236
  }
247
237
  }
248
- const V = `<svg width="32" height="10" viewBox="0 0 412 186" xmlns="http://www.w3.org/2000/svg" aria-label="Cloudflare" role="img">
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">
249
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"/>
250
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"/>
251
- </svg>`, D = "https://search.ai.cloudflare.com", y = `Powered by <a href="${D}" target="_blank" rel="noopener noreferrer">Cloudflare AI Search ${V}</a>`, $ = `
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 = `
252
242
  /* Chat container */
253
243
  .chat-container {
254
244
  display: flex;
@@ -565,7 +555,7 @@ const V = `<svg width="32" height="10" viewBox="0 0 412 186" xmlns="http://www.w
565
555
  .chat-message-bubble a:hover {
566
556
  text-decoration: none;
567
557
  }
568
- `, x = `
558
+ `, y = `
569
559
  :host {
570
560
  /* Colors - Light Mode */
571
561
  --search-snippet-primary-color: #2563eb;
@@ -1000,9 +990,9 @@ const V = `<svg width="32" height="10" viewBox="0 0 412 186" xmlns="http://www.w
1000
990
  text-align: center;
1001
991
  }
1002
992
  `;
1003
- function O(o) {
993
+ function j(o) {
1004
994
  let i = o;
1005
- i = j(i), i = i.replace(/```([\s\S]*?)```/g, (n, c) => `<pre><code>${c.trim()}</code></pre>`);
995
+ i = O(i), i = i.replace(/```([\s\S]*?)```/g, (n, c) => `<pre><code>${c.trim()}</code></pre>`);
1006
996
  const e = i.split(`
1007
997
  `), t = [];
1008
998
  let s = !1, r = "";
@@ -1048,7 +1038,7 @@ function v(o) {
1048
1038
  '<a href="$2" target="_blank" rel="noopener noreferrer">$1</a>'
1049
1039
  ), i;
1050
1040
  }
1051
- function j(o) {
1041
+ function O(o) {
1052
1042
  const i = {
1053
1043
  "&": "&amp;",
1054
1044
  "<": "&lt;",
@@ -1137,13 +1127,13 @@ class q {
1137
1127
  */
1138
1128
  async sendMessage(i) {
1139
1129
  const e = {
1140
- id: E("msg"),
1130
+ id: M("msg"),
1141
1131
  role: "user",
1142
1132
  content: i,
1143
1133
  timestamp: Date.now()
1144
1134
  };
1145
1135
  this.addMessage(e), this.renderMessages(!0), this.setStreamingState(!0);
1146
- const t = E("msg"), s = {
1136
+ const t = M("msg"), s = {
1147
1137
  id: t,
1148
1138
  role: "assistant",
1149
1139
  content: "",
@@ -1161,10 +1151,10 @@ class q {
1161
1151
  break;
1162
1152
  }
1163
1153
  const c = this.messages.findIndex((l) => l.id === t);
1164
- c !== -1 && (this.messages[c].content = n), this.container.dispatchEvent(g("message", { message: s }));
1154
+ c !== -1 && (this.messages[c].content = n), this.container.dispatchEvent(m("message", { message: s }));
1165
1155
  } catch (r) {
1166
1156
  this.showErrorInMessage(t, r.message), this.container.dispatchEvent(
1167
- g("error", {
1157
+ m("error", {
1168
1158
  error: {
1169
1159
  message: r.message,
1170
1160
  code: "CHAT_ERROR"
@@ -1229,11 +1219,11 @@ class q {
1229
1219
  <div class="chat-message-avatar">${s}</div>
1230
1220
  <div class="chat-message-content">
1231
1221
  <div class="chat-message-bubble">
1232
- ${i.content ? `<div class="chat-message-text">${O(i.content)}</div>` : ""}
1233
- ${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">${d[this.loadingMessageIndex]}</span></div>` : ""}
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>` : ""}
1234
1224
  </div>
1235
1225
  <div class="chat-message-metadata">
1236
- <span class="chat-message-time">${N(i.timestamp)}</span>
1226
+ <span class="chat-message-time">${D(i.timestamp)}</span>
1237
1227
  </div>
1238
1228
  </div>
1239
1229
  </div>
@@ -1254,8 +1244,8 @@ class q {
1254
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();
1255
1245
  }
1256
1246
  startLoadingMessages() {
1257
- this.loadingMessageIndex = Math.floor(Math.random() * d.length), this.loadingMessageInterval = setInterval(() => {
1258
- this.loadingMessageIndex = (this.loadingMessageIndex + 1) % d.length, this.isStreaming && this.renderMessages(!0);
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);
1259
1249
  }, 2500);
1260
1250
  }
1261
1251
  clearLoadingMessages() {
@@ -1286,7 +1276,7 @@ class q {
1286
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;
1287
1277
  }
1288
1278
  }
1289
- const M = "chat-bubble-snippet";
1279
+ const E = "chat-bubble-snippet";
1290
1280
  class K extends HTMLElement {
1291
1281
  constructor() {
1292
1282
  super();
@@ -1307,7 +1297,7 @@ class K extends HTMLElement {
1307
1297
  return ["api-url", "placeholder", "theme", "hide-branding"];
1308
1298
  }
1309
1299
  connectedCallback() {
1310
- this.render(), this.initializeClient(), this.dispatchEvent(g("ready", void 0));
1300
+ this.render(), this.initializeClient(), this.dispatchEvent(m("ready", void 0));
1311
1301
  }
1312
1302
  disconnectedCallback() {
1313
1303
  this.cleanup();
@@ -1317,10 +1307,10 @@ class K extends HTMLElement {
1317
1307
  }
1318
1308
  getProps() {
1319
1309
  return {
1320
- apiUrl: p(this.getAttribute("api-url"), "http://localhost:3000"),
1321
- placeholder: p(this.getAttribute("placeholder"), "Type a message..."),
1322
- theme: p(this.getAttribute("theme"), "auto"),
1323
- hideBranding: m(this.getAttribute("hide-branding"), !1)
1310
+ apiUrl: d(this.getAttribute("api-url"), "http://localhost:3000"),
1311
+ placeholder: d(this.getAttribute("placeholder"), "Type a message..."),
1312
+ theme: d(this.getAttribute("theme"), "auto"),
1313
+ hideBranding: g(this.getAttribute("hide-branding"), !1)
1324
1314
  };
1325
1315
  }
1326
1316
  initializeClient() {
@@ -1337,8 +1327,8 @@ class K extends HTMLElement {
1337
1327
  }
1338
1328
  render() {
1339
1329
  const e = document.createElement("style");
1340
- e.textContent = `${x}
1341
- ${$}
1330
+ e.textContent = `${y}
1331
+ ${B}
1342
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();
1343
1333
  }
1344
1334
  getBubbleStyles() {
@@ -1518,7 +1508,7 @@ ${this.getBubbleStyles()}`, this.container = document.createElement("div"), this
1518
1508
  </div>
1519
1509
  </div>
1520
1510
  <div class="chat-content"></div>
1521
- ${this.getProps().hideBranding ? "" : `<div class="powered-by">${y}</div>`}
1511
+ ${this.getProps().hideBranding ? "" : `<div class="powered-by">${x}</div>`}
1522
1512
  </div>
1523
1513
  `;
1524
1514
  }
@@ -1569,7 +1559,7 @@ ${this.getBubbleStyles()}`, this.container = document.createElement("div"), this
1569
1559
  return this.chatView?.getMessages() || [];
1570
1560
  }
1571
1561
  }
1572
- customElements.get(M) || customElements.define(M, K);
1562
+ customElements.get(E) || customElements.define(E, K);
1573
1563
  const L = "chat-page-snippet", I = "chat-page-sessions";
1574
1564
  class U extends HTMLElement {
1575
1565
  constructor() {
@@ -1593,7 +1583,7 @@ class U extends HTMLElement {
1593
1583
  return ["api-url", "placeholder", "theme", "hide-branding"];
1594
1584
  }
1595
1585
  connectedCallback() {
1596
- this.render(), this.initializeClient(), this.setupView(), this.dispatchEvent(g("ready", void 0));
1586
+ this.render(), this.initializeClient(), this.setupView(), this.dispatchEvent(m("ready", void 0));
1597
1587
  }
1598
1588
  disconnectedCallback() {
1599
1589
  this.saveCurrentSession(), this.cleanup();
@@ -1603,10 +1593,10 @@ class U extends HTMLElement {
1603
1593
  }
1604
1594
  getProps() {
1605
1595
  return {
1606
- apiUrl: p(this.getAttribute("api-url"), "http://localhost:3000"),
1607
- placeholder: p(this.getAttribute("placeholder"), "Type a message..."),
1608
- theme: p(this.getAttribute("theme"), "auto"),
1609
- hideBranding: m(this.getAttribute("hide-branding"), !1)
1596
+ apiUrl: d(this.getAttribute("api-url"), "http://localhost:3000"),
1597
+ placeholder: d(this.getAttribute("placeholder"), "Type a message..."),
1598
+ theme: d(this.getAttribute("theme"), "auto"),
1599
+ hideBranding: g(this.getAttribute("hide-branding"), !1)
1610
1600
  };
1611
1601
  }
1612
1602
  initializeClient() {
@@ -1623,8 +1613,8 @@ class U extends HTMLElement {
1623
1613
  }
1624
1614
  render() {
1625
1615
  const e = document.createElement("style");
1626
- e.textContent = `${x}
1627
- ${$}
1616
+ e.textContent = `${y}
1617
+ ${B}
1628
1618
  ${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();
1629
1619
  }
1630
1620
  getPageStyles() {
@@ -1916,7 +1906,7 @@ ${this.getPageStyles()}`, this.container = document.createElement("div"), this.c
1916
1906
  New Chat
1917
1907
  </button>
1918
1908
  <div class="chat-list"></div>
1919
- ${this.getProps().hideBranding ? "" : `<div class="powered-by">${y}</div>`}
1909
+ ${this.getProps().hideBranding ? "" : `<div class="powered-by">${x}</div>`}
1920
1910
  </div>
1921
1911
  <div class="chat-main">
1922
1912
  <div class="chat-page-header">
@@ -2260,15 +2250,13 @@ a.search-result-item {
2260
2250
  height: 64px;
2261
2251
  border-radius: calc(var(--search-snippet-border-radius) - 4px);
2262
2252
  overflow: hidden;
2263
- background: var(--search-snippet-surface);
2264
- border: var(--search-snippet-border-width) solid var(--search-snippet-border-color);
2265
2253
  position: relative;
2266
2254
  }
2267
2255
 
2268
2256
  .search-result-image {
2269
2257
  width: 100%;
2270
2258
  height: 100%;
2271
- object-fit: cover;
2259
+ object-fit: contain;
2272
2260
  opacity: 0;
2273
2261
  transition: opacity var(--search-snippet-transition);
2274
2262
  }
@@ -2351,12 +2339,36 @@ a.search-result-item:focus-visible {
2351
2339
  overflow: hidden;
2352
2340
  }
2353
2341
 
2342
+ .search-result-metadata {
2343
+ display: flex;
2344
+ align-items: center;
2345
+ gap: var(--search-snippet-spacing-sm);
2346
+ margin-top: var(--search-snippet-spacing-xs);
2347
+ min-width: 0;
2348
+ }
2349
+
2354
2350
  .search-result-url {
2355
2351
  font-size: var(--search-snippet-font-size-sm);
2356
2352
  color: var(--search-snippet-primary-color);
2357
- margin-top: var(--search-snippet-spacing-xs);
2358
2353
  text-decoration: none;
2359
- display: inline-block;
2354
+ display: block;
2355
+ flex: 1;
2356
+ min-width: 0;
2357
+ overflow: hidden;
2358
+ text-overflow: ellipsis;
2359
+ white-space: nowrap;
2360
+ }
2361
+
2362
+ .search-result-url-empty {
2363
+ visibility: hidden;
2364
+ }
2365
+
2366
+ .search-result-date {
2367
+ font-size: 12px;
2368
+ font-weight: var(--search-snippet-font-weight-medium);
2369
+ color: var(--search-snippet-text-secondary);
2370
+ text-align: right;
2371
+ flex-shrink: 0;
2360
2372
  }
2361
2373
 
2362
2374
  .search-result-url:hover {
@@ -2381,13 +2393,29 @@ a.search-result-item:focus-visible {
2381
2393
  /* Search footer */
2382
2394
  .search-footer {
2383
2395
  padding: var(--search-snippet-spacing-md);
2384
- border-top: var(--search-snippet-border-width) solid var(--search-snippet-border-color);
2396
+ padding-bottom: var(--search-snippet-spacing-xs);
2385
2397
  display: flex;
2386
2398
  align-items: center;
2387
2399
  justify-content: center;
2388
2400
  gap: var(--search-snippet-spacing-sm);
2389
2401
  }
2390
2402
 
2403
+ /* See more link */
2404
+ .search-see-more {
2405
+ display: inline-flex;
2406
+ align-items: center;
2407
+ gap: var(--search-snippet-spacing-xs);
2408
+ font-size: var(--search-snippet-font-size-sm);
2409
+ color: var(--search-snippet-primary-color);
2410
+ text-decoration: none;
2411
+ font-weight: var(--search-snippet-font-weight-medium);
2412
+ transition: color var(--search-snippet-transition-fast);
2413
+ }
2414
+
2415
+ .search-see-more:hover {
2416
+ text-decoration: underline;
2417
+ }
2418
+
2391
2419
  /* Loading state for search */
2392
2420
  .search-loading {
2393
2421
  display: flex;
@@ -2464,11 +2492,14 @@ class F extends HTMLElement {
2464
2492
  "debounce-ms",
2465
2493
  "theme",
2466
2494
  "hide-branding",
2467
- "show-url"
2495
+ "show-url",
2496
+ "show-date",
2497
+ "hide-thumbnails",
2498
+ "see-more"
2468
2499
  ];
2469
2500
  }
2470
2501
  connectedCallback() {
2471
- this.initializeClient(), this.render(), this.dispatchEvent(g("ready", void 0));
2502
+ this.initializeClient(), this.render(), this.dispatchEvent(m("ready", void 0));
2472
2503
  }
2473
2504
  disconnectedCallback() {
2474
2505
  this.cleanup();
@@ -2478,13 +2509,16 @@ class F extends HTMLElement {
2478
2509
  }
2479
2510
  getProps() {
2480
2511
  return {
2481
- apiUrl: p(this.getAttribute("api-url"), "http://localhost:3000"),
2482
- placeholder: p(this.getAttribute("placeholder"), "Search..."),
2512
+ apiUrl: d(this.getAttribute("api-url"), "http://localhost:3000"),
2513
+ placeholder: d(this.getAttribute("placeholder"), "Search..."),
2483
2514
  maxResults: f(this.getAttribute("max-results"), 10),
2484
2515
  debounceMs: f(this.getAttribute("debounce-ms"), 300),
2485
- theme: p(this.getAttribute("theme"), "auto"),
2486
- hideBranding: m(this.getAttribute("hide-branding"), !1),
2487
- showUrl: m(this.getAttribute("show-url"), !1)
2516
+ theme: d(this.getAttribute("theme"), "auto"),
2517
+ hideBranding: g(this.getAttribute("hide-branding"), !1),
2518
+ showUrl: g(this.getAttribute("show-url"), !1),
2519
+ showDate: g(this.getAttribute("show-date"), !1),
2520
+ hideThumbnails: g(this.getAttribute("hide-thumbnails"), !1),
2521
+ seeMore: d(this.getAttribute("see-more"), "")
2488
2522
  };
2489
2523
  }
2490
2524
  initializeClient() {
@@ -2501,12 +2535,12 @@ class F extends HTMLElement {
2501
2535
  }
2502
2536
  render() {
2503
2537
  const e = this.getProps(), t = (r) => this.performSearch(r);
2504
- this.debouncedSearch = A(
2538
+ this.debouncedSearch = $(
2505
2539
  t,
2506
2540
  e.debounceMs || 400
2507
2541
  );
2508
2542
  const s = document.createElement("style");
2509
- s.textContent = `${x}
2543
+ s.textContent = `${y}
2510
2544
  ${G}`, this.container = document.createElement("div"), this.container.className = "container", this.container.innerHTML = `
2511
2545
  <div class="search-view">
2512
2546
  <div class="search-input-wrapper">
@@ -2571,7 +2605,12 @@ ${G}`, this.container = document.createElement("div"), this.container.className
2571
2605
  this.showNoResultsState(t);
2572
2606
  return;
2573
2607
  }
2574
- const r = this.getProps().hideBranding ? "" : `<div class="powered-by-inline">${y}</div>`, n = `
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">
2610
+ <span>See more results</span>
2611
+ <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
+ </a>
2613
+ </div>` : "", c = `
2575
2614
  <div class="search-header">
2576
2615
  <div class="search-count">
2577
2616
  Found ${e.length} result${e.length === 1 ? "" : "s"}
@@ -2579,20 +2618,24 @@ ${G}`, this.container = document.createElement("div"), this.container.className
2579
2618
  ${r}
2580
2619
  </div>
2581
2620
  <div class="search-results">
2582
- ${e.map((c) => this.renderResult(c)).join("")}
2621
+ ${e.map((l) => this.renderResult(l)).join("")}
2583
2622
  </div>
2623
+ ${n}
2584
2624
  `;
2585
- this.resultsContainer.innerHTML = n, this.attachResultHandlers();
2625
+ this.resultsContainer.innerHTML = c, this.attachResultHandlers();
2586
2626
  }
2587
2627
  renderResult(e) {
2588
- const t = this.getProps(), s = this.renderResultImage(e.image, e.title);
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">
2629
+ ${t.showUrl && e.url ? `<span class="search-result-url">${h(e.url)}</span>` : '<span class="search-result-url search-result-url-empty"></span>'}
2630
+ ${n}
2631
+ </div>` : "";
2589
2632
  return `
2590
- <a href="${e.url ? h(e.url) : "#"}" class="search-result-item" data-result-id="${h(e.url || "")}">
2633
+ <a href="${r}" class="search-result-item" data-result-id="${h(e.url || "")}">
2591
2634
  ${s}
2592
2635
  <div class="search-result-content">
2593
2636
  <div class="search-result-title">${h(e.title || "")}</div>
2594
2637
  <div class="search-result-snippet">${h(e.description || "")}</div>
2595
- ${t.showUrl && e.url ? `<span class="search-result-url">${h(e.url)}</span>` : ""}
2638
+ ${c}
2596
2639
  </div>
2597
2640
  </a>
2598
2641
  `;
@@ -2637,18 +2680,18 @@ ${G}`, this.container = document.createElement("div"), this.container.className
2637
2680
  });
2638
2681
  }
2639
2682
  showLoadingState() {
2640
- this.resultsContainer && (this.clearLoadingInterval(), this.loadingMessageIndex = Math.floor(Math.random() * d.length), this.resultsContainer.innerHTML = `
2683
+ this.resultsContainer && (this.clearLoadingInterval(), this.loadingMessageIndex = Math.floor(Math.random() * p.length), this.resultsContainer.innerHTML = `
2641
2684
  <div class="search-loading">
2642
2685
  <div class="loading" aria-label="Loading"></div>
2643
- <div class="loading-text loading-text-animate">${d[this.loadingMessageIndex]}</div>
2686
+ <div class="loading-text loading-text-animate">${p[this.loadingMessageIndex]}</div>
2644
2687
  </div>
2645
2688
  `, this.startLoadingInterval());
2646
2689
  }
2647
2690
  startLoadingInterval() {
2648
2691
  this.loadingMessageInterval = setInterval(() => {
2649
- this.loadingMessageIndex = (this.loadingMessageIndex + 1) % d.length;
2692
+ this.loadingMessageIndex = (this.loadingMessageIndex + 1) % p.length;
2650
2693
  const e = this.resultsContainer?.querySelector(".loading-text");
2651
- e && (e.classList.remove("loading-text-animate"), e.offsetWidth, e.textContent = d[this.loadingMessageIndex], e.classList.add("loading-text-animate"));
2694
+ e && (e.classList.remove("loading-text-animate"), e.offsetWidth, e.textContent = p[this.loadingMessageIndex], e.classList.add("loading-text-animate"));
2652
2695
  }, 2500);
2653
2696
  }
2654
2697
  clearLoadingInterval() {
@@ -2859,15 +2902,13 @@ a.modal-result-item {
2859
2902
  height: 48px;
2860
2903
  border-radius: 6px;
2861
2904
  overflow: hidden;
2862
- background: var(--search-snippet-surface);
2863
- border: var(--search-snippet-border-width) solid var(--search-snippet-border-color);
2864
2905
  position: relative;
2865
2906
  }
2866
2907
 
2867
2908
  .modal-result-image {
2868
2909
  width: 100%;
2869
2910
  height: 100%;
2870
- object-fit: cover;
2911
+ object-fit: contain;
2871
2912
  opacity: 0;
2872
2913
  transition: opacity var(--search-snippet-transition);
2873
2914
  }
@@ -2956,17 +2997,37 @@ a.modal-result-item:focus-visible {
2956
2997
  overflow: hidden;
2957
2998
  }
2958
2999
 
3000
+ .modal-result-metadata {
3001
+ display: flex;
3002
+ align-items: center;
3003
+ gap: var(--search-snippet-spacing-sm);
3004
+ min-width: 0;
3005
+ }
3006
+
2959
3007
  .modal-result-url {
2960
3008
  font-size: var(--search-snippet-font-size-sm);
2961
3009
  color: var(--search-snippet-primary-color);
2962
3010
  text-decoration: none;
2963
- display: inline-block;
2964
- max-width: 100%;
3011
+ display: block;
3012
+ flex: 1;
3013
+ min-width: 0;
2965
3014
  overflow: hidden;
2966
3015
  text-overflow: ellipsis;
2967
3016
  white-space: nowrap;
2968
3017
  }
2969
3018
 
3019
+ .modal-result-url-empty {
3020
+ visibility: hidden;
3021
+ }
3022
+
3023
+ .modal-result-date {
3024
+ font-size: 12px;
3025
+ font-weight: var(--search-snippet-font-weight-medium);
3026
+ color: var(--search-snippet-text-secondary);
3027
+ text-align: right;
3028
+ flex-shrink: 0;
3029
+ }
3030
+
2970
3031
  .modal-result-url:hover {
2971
3032
  text-decoration: underline;
2972
3033
  }
@@ -3073,6 +3134,26 @@ a.modal-result-item:focus-visible {
3073
3134
  color: var(--search-snippet-primary-color);
3074
3135
  }
3075
3136
 
3137
+ /* See more link */
3138
+ .modal-see-more {
3139
+ display: flex;
3140
+ align-items: center;
3141
+ justify-content: center;
3142
+ gap: var(--search-snippet-spacing-xs);
3143
+ padding: var(--search-snippet-spacing-md);
3144
+ font-size: var(--search-snippet-font-size-sm);
3145
+ color: var(--search-snippet-primary-color);
3146
+ text-decoration: none;
3147
+ font-weight: var(--search-snippet-font-weight-medium);
3148
+ transition: background var(--search-snippet-transition-fast);
3149
+ padding-bottom: var(--search-snippet-spacing-xs);
3150
+ }
3151
+
3152
+ .modal-see-more:hover {
3153
+ background: var(--search-snippet-hover);
3154
+ text-decoration: underline;
3155
+ }
3156
+
3076
3157
  /* Responsive adjustments */
3077
3158
  @media (max-width: 640px) {
3078
3159
  .modal-container {
@@ -3139,11 +3220,14 @@ class W extends HTMLElement {
3139
3220
  "use-meta-key",
3140
3221
  "debounce-ms",
3141
3222
  "hide-branding",
3142
- "show-url"
3223
+ "show-url",
3224
+ "show-date",
3225
+ "hide-thumbnails",
3226
+ "see-more"
3143
3227
  ];
3144
3228
  }
3145
3229
  connectedCallback() {
3146
- this.initializeClient(), this.render(), this.attachGlobalKeyboardShortcut(), this.dispatchEvent(g("ready", void 0));
3230
+ this.initializeClient(), this.render(), this.attachGlobalKeyboardShortcut(), this.dispatchEvent(m("ready", void 0));
3147
3231
  }
3148
3232
  disconnectedCallback() {
3149
3233
  this.cleanup();
@@ -3153,15 +3237,18 @@ class W extends HTMLElement {
3153
3237
  }
3154
3238
  getProps() {
3155
3239
  return {
3156
- apiUrl: p(this.getAttribute("api-url"), "http://localhost:3000"),
3157
- placeholder: p(this.getAttribute("placeholder"), "Search..."),
3240
+ apiUrl: d(this.getAttribute("api-url"), "http://localhost:3000"),
3241
+ placeholder: d(this.getAttribute("placeholder"), "Search..."),
3158
3242
  maxResults: f(this.getAttribute("max-results"), 10),
3159
3243
  debounceMs: f(this.getAttribute("debounce-ms"), 300),
3160
- theme: p(this.getAttribute("theme"), "auto"),
3161
- shortcut: p(this.getAttribute("shortcut"), "k"),
3244
+ theme: d(this.getAttribute("theme"), "auto"),
3245
+ shortcut: d(this.getAttribute("shortcut"), "k"),
3162
3246
  useMetaKey: this.getAttribute("use-meta-key") !== "false",
3163
- hideBranding: m(this.getAttribute("hide-branding"), !1),
3164
- showUrl: m(this.getAttribute("show-url"), !1)
3247
+ hideBranding: g(this.getAttribute("hide-branding"), !1),
3248
+ showUrl: g(this.getAttribute("show-url"), !1),
3249
+ showDate: g(this.getAttribute("show-date"), !1),
3250
+ hideThumbnails: g(this.getAttribute("hide-thumbnails"), !1),
3251
+ seeMore: d(this.getAttribute("see-more"), "")
3165
3252
  };
3166
3253
  }
3167
3254
  initializeClient() {
@@ -3178,14 +3265,14 @@ class W extends HTMLElement {
3178
3265
  }
3179
3266
  render() {
3180
3267
  const e = this.getProps(), t = (c) => this.performSearch(c);
3181
- this.debouncedSearch = A(
3268
+ this.debouncedSearch = $(
3182
3269
  t,
3183
3270
  e.debounceMs || 300
3184
3271
  );
3185
3272
  const s = document.createElement("style");
3186
- s.textContent = `${x}
3273
+ s.textContent = `${y}
3187
3274
  ${Y}`;
3188
- const r = e.hideBranding ? "" : `<div class="powered-by-inline">${y}</div>`, n = document.createElement("div");
3275
+ const r = e.hideBranding ? "" : `<div class="powered-by-inline">${x}</div>`, n = document.createElement("div");
3189
3276
  n.innerHTML = `
3190
3277
  <div class="modal-backdrop" role="presentation"></div>
3191
3278
  <div class="modal-container" role="dialog" aria-modal="true" aria-labelledby="modal-title">
@@ -3279,7 +3366,7 @@ ${Y}`;
3279
3366
  }
3280
3367
  const e = this.results[this.activeIndex];
3281
3368
  this.dispatchEvent(
3282
- g("result-select", {
3369
+ m("result-select", {
3283
3370
  result: e,
3284
3371
  index: this.activeIndex
3285
3372
  })
@@ -3313,14 +3400,20 @@ ${Y}`;
3313
3400
  this.showNoResultsState(t);
3314
3401
  return;
3315
3402
  }
3316
- const s = e.map((r, n) => this.renderResult(r, n)).join("");
3317
- 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();
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">
3404
+ <span>See more results</span>
3405
+ <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
+ </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();
3318
3408
  }
3319
3409
  renderResult(e, t) {
3320
- const s = this.getProps(), r = this.renderResultImage(e.image, e.title);
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">
3411
+ ${s.showUrl && e.url ? `<span class="modal-result-url">${h(e.url)}</span>` : '<span class="modal-result-url modal-result-url-empty"></span>'}
3412
+ ${c}
3413
+ </div>` : "";
3321
3414
  return `
3322
3415
  <a
3323
- href="${e.url ? h(e.url) : "#"}"
3416
+ href="${n}"
3324
3417
  class="modal-result-item${t === this.activeIndex ? " active" : ""}"
3325
3418
  role="option"
3326
3419
  id="result-${t}"
@@ -3333,7 +3426,7 @@ ${Y}`;
3333
3426
  <div class="modal-result-content">
3334
3427
  <div class="modal-result-title">${h(e.title || "")}</div>
3335
3428
  ${e.description ? `<div class="modal-result-description">${h(e.description)}</div>` : ""}
3336
- ${s.showUrl && e.url ? `<span class="modal-result-url">${h(e.url)}</span>` : ""}
3429
+ ${l}
3337
3430
  </div>
3338
3431
  </a>
3339
3432
  `;
@@ -3394,18 +3487,18 @@ ${Y}`;
3394
3487
  this.clearLoadingInterval(), this.resultsContainer && (this.resultsContainer.innerHTML = this.renderEmptyState(), this.footerCount && (this.footerCount.textContent = ""), this.inputElement && this.inputElement.setAttribute("aria-expanded", "false"));
3395
3488
  }
3396
3489
  showLoadingState() {
3397
- this.resultsContainer && (this.clearLoadingInterval(), this.loadingMessageIndex = Math.floor(Math.random() * d.length), this.resultsContainer.innerHTML = `
3490
+ this.resultsContainer && (this.clearLoadingInterval(), this.loadingMessageIndex = Math.floor(Math.random() * p.length), this.resultsContainer.innerHTML = `
3398
3491
  <div class="modal-loading">
3399
3492
  <div class="loading" aria-label="Loading"></div>
3400
- <div class="loading-text loading-text-animate">${d[this.loadingMessageIndex]}</div>
3493
+ <div class="loading-text loading-text-animate">${p[this.loadingMessageIndex]}</div>
3401
3494
  </div>
3402
- `, this.footerCount && (this.footerCount.textContent = d[this.loadingMessageIndex]), this.startLoadingInterval());
3495
+ `, this.footerCount && (this.footerCount.textContent = p[this.loadingMessageIndex]), this.startLoadingInterval());
3403
3496
  }
3404
3497
  startLoadingInterval() {
3405
3498
  this.loadingMessageInterval = setInterval(() => {
3406
- this.loadingMessageIndex = (this.loadingMessageIndex + 1) % d.length;
3499
+ this.loadingMessageIndex = (this.loadingMessageIndex + 1) % p.length;
3407
3500
  const e = this.resultsContainer?.querySelector(".loading-text");
3408
- e && (e.classList.remove("loading-text-animate"), e.offsetWidth, e.textContent = d[this.loadingMessageIndex], e.classList.add("loading-text-animate")), this.footerCount && (this.footerCount.textContent = d[this.loadingMessageIndex]);
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]);
3409
3502
  }, 2500);
3410
3503
  }
3411
3504
  clearLoadingInterval() {
@@ -3460,13 +3553,13 @@ ${Y}`;
3460
3553
  requestAnimationFrame(() => {
3461
3554
  this.inputElement?.focus();
3462
3555
  });
3463
- }), this.lockBodyScroll(), this.dispatchEvent(g("open", void 0)));
3556
+ }), this.lockBodyScroll(), this.dispatchEvent(m("open", void 0)));
3464
3557
  }
3465
3558
  /**
3466
3559
  * Close the search modal
3467
3560
  */
3468
3561
  close() {
3469
- 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(g("close", void 0)));
3562
+ 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)));
3470
3563
  }
3471
3564
  /**
3472
3565
  * Toggle the search modal open/closed
@@ -3495,7 +3588,7 @@ ${Y}`;
3495
3588
  }
3496
3589
  customElements.get(T) || customElements.define(T, W);
3497
3590
  export {
3498
- P as AISearchClient,
3591
+ _ as AISearchClient,
3499
3592
  K as ChatBubbleSnippet,
3500
3593
  U as ChatPageSnippet,
3501
3594
  F as SearchBarSnippet,