@cloudflare/ai-search-snippet 0.0.17 → 0.0.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -97,10 +97,11 @@ These attributes are available on all components:
97
97
 
98
98
  Additional attributes for `<search-bar-snippet>` and `<search-modal-snippet>`:
99
99
 
100
- | Attribute | Type | Default | Description |
101
- | ------------- | ------ | ------- | ------------------------------------ |
102
- | `max-results` | number | `10` | Maximum search results to display |
103
- | `debounce-ms` | number | `300` | Input debounce delay in milliseconds |
100
+ | Attribute | Type | Default | Description |
101
+ | ------------- | ------- | ------- | ------------------------------------ |
102
+ | `max-results` | number | `10` | Maximum search results to display |
103
+ | `debounce-ms` | number | `300` | Input debounce delay in milliseconds |
104
+ | `show-url` | boolean | `false` | Show URL in search results |
104
105
 
105
106
  ### Modal-Specific Attributes
106
107
 
Binary file
package/dist/main.d.ts CHANGED
@@ -198,14 +198,13 @@ declare class SearchBarSnippet extends HTMLElement {
198
198
  private inputElement;
199
199
  private resultsContainer;
200
200
  private searchButton;
201
- private isLoading;
202
- private currentQuery;
203
201
  private debouncedSearch;
202
+ private currentSearchController;
204
203
  private handleInputChange;
205
204
  private handleInputKeydownEnter;
206
205
  private handleInputKeydownEscape;
207
206
  private handleSearchButtonClick;
208
- static get observedAttributes(): readonly ["api-url", "placeholder", "max-results", "debounce-ms", "theme", "hide-branding"];
207
+ static get observedAttributes(): readonly ["api-url", "placeholder", "max-results", "debounce-ms", "theme", "hide-branding", "show-url"];
209
208
  constructor();
210
209
  connectedCallback(): void;
211
210
  disconnectedCallback(): void;
@@ -247,17 +246,17 @@ export declare class SearchModalSnippet extends HTMLElement {
247
246
  private resultsContainer;
248
247
  private footerCount;
249
248
  private isOpen;
250
- private isLoading;
251
249
  private results;
252
250
  private activeIndex;
253
251
  private debouncedSearch;
252
+ private currentSearchController;
254
253
  private handleGlobalKeydown;
255
254
  private handleInputChange;
256
255
  private handleInputKeydown;
257
256
  private handleBackdropClick;
258
257
  private savedBodyStyles;
259
258
  private savedHtmlOverflow;
260
- static get observedAttributes(): readonly ["api-url", "placeholder", "max-results", "theme", "shortcut", "use-meta-key", "debounce-ms", "hide-branding"];
259
+ static get observedAttributes(): readonly ["api-url", "placeholder", "max-results", "theme", "shortcut", "use-meta-key", "debounce-ms", "hide-branding", "show-url"];
261
260
  constructor();
262
261
  connectedCallback(): void;
263
262
  disconnectedCallback(): void;
@@ -349,6 +348,8 @@ export declare interface SearchSnippetProps {
349
348
  theme?: Theme;
350
349
  /** Hide the "Powered by Cloudflare AI Search" branding */
351
350
  hideBranding?: boolean;
351
+ /** Show URL in search results (default: false) */
352
+ showUrl?: boolean;
352
353
  }
353
354
 
354
355
  /**
@@ -42,10 +42,10 @@ function S(o = "id") {
42
42
  function u(o, i) {
43
43
  return o !== null ? o : i;
44
44
  }
45
- function f(o, i) {
45
+ function v(o, i) {
46
46
  return o === null ? i : o === "true" || o === "";
47
47
  }
48
- function b(o, i) {
48
+ function f(o, i) {
49
49
  if (o === null) return i;
50
50
  const e = Number.parseInt(o, 10);
51
51
  return Number.isNaN(e) ? i : e;
@@ -132,7 +132,7 @@ class P extends N {
132
132
  type: "result",
133
133
  id: d.id,
134
134
  title: C(d.item.metadata.title),
135
- description: C(d.item.metadata.description),
135
+ description: d.item.metadata.description ? C(d.item.metadata.description) : "",
136
136
  url: d.item.key,
137
137
  image: d.item.metadata.image || void 0,
138
138
  metadata: d.item.metadata
@@ -556,6 +556,7 @@ const $ = `
556
556
  --search-snippet-surface: #f8f9fa;
557
557
  --search-snippet-text-color: #212529;
558
558
  --search-snippet-text-secondary: #6c757d;
559
+ --search-snippet-text-description: #495057;
559
560
  --search-snippet-border-color: #dee2e6;
560
561
  --search-snippet-hover-background: #f1f3f5;
561
562
  --search-snippet-focus-ring: #0066cc40;
@@ -667,6 +668,7 @@ const $ = `
667
668
  --search-snippet-surface: #f8f9fa;
668
669
  --search-snippet-text-color: #212529;
669
670
  --search-snippet-text-secondary: #6c757d;
671
+ --search-snippet-text-description: #495057;
670
672
  --search-snippet-border-color: #dee2e6;
671
673
  --search-snippet-hover-background: #f1f3f5;
672
674
  --search-snippet-focus-ring: #0066cc40;
@@ -695,6 +697,7 @@ const $ = `
695
697
  --search-snippet-surface: #25262b;
696
698
  --search-snippet-text-color: #c1c2c5;
697
699
  --search-snippet-text-secondary: #909296;
700
+ --search-snippet-text-description: #adb5bd;
698
701
  --search-snippet-border-color: #373a40;
699
702
  --search-snippet-hover-background: #2c2e33;
700
703
  --search-snippet-focus-ring: #4dabf740;
@@ -971,7 +974,7 @@ function V(o) {
971
974
  const c = e[n], h = c.match(/^(#{1,6})\s+(.+)$/);
972
975
  if (h) {
973
976
  const p = h[1].length, k = h[2];
974
- t.push(`<h${p}>${v(k)}</h${p}>`);
977
+ t.push(`<h${p}>${b(k)}</h${p}>`);
975
978
  continue;
976
979
  }
977
980
  if (c.match(/^---+$/)) {
@@ -980,29 +983,29 @@ function V(o) {
980
983
  }
981
984
  if (c.match(/^>\s+/)) {
982
985
  const p = c.replace(/^>\s+/, "");
983
- t.push(`<blockquote>${v(p)}</blockquote>`);
986
+ t.push(`<blockquote>${b(p)}</blockquote>`);
984
987
  continue;
985
988
  }
986
989
  const d = c.match(/^[-*]\s+(.+)$/);
987
990
  if (d) {
988
- (!s || a !== "ul") && (s && t.push(`</${a}>`), t.push("<ul>"), s = !0, a = "ul"), t.push(`<li>${v(d[1])}</li>`);
991
+ (!s || a !== "ul") && (s && t.push(`</${a}>`), t.push("<ul>"), s = !0, a = "ul"), t.push(`<li>${b(d[1])}</li>`);
989
992
  continue;
990
993
  }
991
994
  const g = c.match(/^\d+\.\s+(.+)$/);
992
995
  if (g) {
993
- (!s || a !== "ol") && (s && t.push(`</${a}>`), t.push("<ol>"), s = !0, a = "ol"), t.push(`<li>${v(g[1])}</li>`);
996
+ (!s || a !== "ol") && (s && t.push(`</${a}>`), t.push("<ol>"), s = !0, a = "ol"), t.push(`<li>${b(g[1])}</li>`);
994
997
  continue;
995
998
  }
996
999
  if (s && (t.push(`</${a}>`), s = !1, a = ""), c.trim() === "") {
997
1000
  t.push("<br />");
998
1001
  continue;
999
1002
  }
1000
- t.push(`<p>${v(c)}</p>`);
1003
+ t.push(`<p>${b(c)}</p>`);
1001
1004
  }
1002
1005
  return s && t.push(`</${a}>`), t.join(`
1003
1006
  `);
1004
1007
  }
1005
- function v(o) {
1008
+ function b(o) {
1006
1009
  let i = o;
1007
1010
  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(
1008
1011
  /\[([^\]]+)\]\(([^)]+)\)/g,
@@ -1271,7 +1274,7 @@ class O extends HTMLElement {
1271
1274
  apiUrl: u(this.getAttribute("api-url"), "http://localhost:3000"),
1272
1275
  placeholder: u(this.getAttribute("placeholder"), "Type a message..."),
1273
1276
  theme: u(this.getAttribute("theme"), "auto"),
1274
- hideBranding: f(this.getAttribute("hide-branding"), !1)
1277
+ hideBranding: v(this.getAttribute("hide-branding"), !1)
1275
1278
  };
1276
1279
  }
1277
1280
  initializeClient() {
@@ -1557,7 +1560,7 @@ class D extends HTMLElement {
1557
1560
  apiUrl: u(this.getAttribute("api-url"), "http://localhost:3000"),
1558
1561
  placeholder: u(this.getAttribute("placeholder"), "Type a message..."),
1559
1562
  theme: u(this.getAttribute("theme"), "auto"),
1560
- hideBranding: f(this.getAttribute("hide-branding"), !1)
1563
+ hideBranding: v(this.getAttribute("hide-branding"), !1)
1561
1564
  };
1562
1565
  }
1563
1566
  initializeClient() {
@@ -2189,7 +2192,7 @@ const U = `
2189
2192
  gap: var(--search-snippet-spacing-sm);
2190
2193
  }
2191
2194
 
2192
- .search-result-item {
2195
+ a.search-result-item {
2193
2196
  display: flex;
2194
2197
  flex-direction: row;
2195
2198
  align-items: flex-start;
@@ -2200,6 +2203,8 @@ const U = `
2200
2203
  border-radius: var(--search-snippet-border-radius);
2201
2204
  cursor: pointer;
2202
2205
  transition: var(--search-snippet-transition);
2206
+ text-decoration: none;
2207
+ color: inherit;
2203
2208
  }
2204
2209
 
2205
2210
  /* Image thumbnail container */
@@ -2267,14 +2272,14 @@ const U = `
2267
2272
  min-width: 0;
2268
2273
  }
2269
2274
 
2270
- .search-result-item:hover {
2275
+ a.search-result-item:hover {
2271
2276
  background: var(--search-snippet-hover-background);
2272
2277
  border-color: var(--search-snippet-primary-color);
2273
2278
  transform: translateY(-1px);
2274
2279
  box-shadow: var(--search-snippet-result-item-shadow);
2275
2280
  }
2276
2281
 
2277
- .search-result-item:focus-visible {
2282
+ a.search-result-item:focus-visible {
2278
2283
  outline: 2px solid var(--search-snippet-primary-color);
2279
2284
  outline-offset: 2px;
2280
2285
  }
@@ -2292,7 +2297,7 @@ const U = `
2292
2297
 
2293
2298
  .search-result-snippet {
2294
2299
  font-size: var(--search-snippet-font-size-sm);
2295
- color: var(--search-snippet-text-secondary);
2300
+ color: var(--search-snippet-text-description);
2296
2301
  line-height: 1.6;
2297
2302
  display: -webkit-box;
2298
2303
  -webkit-line-clamp: 3;
@@ -2394,9 +2399,8 @@ class F extends HTMLElement {
2394
2399
  r(this, "inputElement", null);
2395
2400
  r(this, "resultsContainer", null);
2396
2401
  r(this, "searchButton", null);
2397
- r(this, "isLoading", !1);
2398
- r(this, "currentQuery", "");
2399
2402
  r(this, "debouncedSearch", null);
2403
+ r(this, "currentSearchController", null);
2400
2404
  // Event handler references for cleanup
2401
2405
  r(this, "handleInputChange", null);
2402
2406
  r(this, "handleInputKeydownEnter", null);
@@ -2411,7 +2415,8 @@ class F extends HTMLElement {
2411
2415
  "max-results",
2412
2416
  "debounce-ms",
2413
2417
  "theme",
2414
- "hide-branding"
2418
+ "hide-branding",
2419
+ "show-url"
2415
2420
  ];
2416
2421
  }
2417
2422
  connectedCallback() {
@@ -2427,10 +2432,11 @@ class F extends HTMLElement {
2427
2432
  return {
2428
2433
  apiUrl: u(this.getAttribute("api-url"), "http://localhost:3000"),
2429
2434
  placeholder: u(this.getAttribute("placeholder"), "Search..."),
2430
- maxResults: b(this.getAttribute("max-results"), 10),
2431
- debounceMs: b(this.getAttribute("debounce-ms"), 300),
2435
+ maxResults: f(this.getAttribute("max-results"), 10),
2436
+ debounceMs: f(this.getAttribute("debounce-ms"), 300),
2432
2437
  theme: u(this.getAttribute("theme"), "auto"),
2433
- hideBranding: f(this.getAttribute("hide-branding"), !1)
2438
+ hideBranding: v(this.getAttribute("hide-branding"), !1),
2439
+ showUrl: v(this.getAttribute("show-url"), !1)
2434
2440
  };
2435
2441
  }
2436
2442
  initializeClient() {
@@ -2494,15 +2500,20 @@ ${U}`, this.container = document.createElement("div"), this.container.className
2494
2500
  }, this.searchButton.addEventListener("click", this.handleSearchButtonClick)));
2495
2501
  }
2496
2502
  async performSearch(e) {
2497
- if (!(this.isLoading || e === this.currentQuery || !this.client)) {
2498
- this.currentQuery = e, this.isLoading = !0, this.showLoadingState();
2503
+ if (this.client) {
2504
+ this.currentSearchController && (this.currentSearchController.abort(), this.currentSearchController = null), this.currentSearchController = new AbortController(), this.showLoadingState();
2499
2505
  try {
2500
- const t = await this.client.search(e, { streaming: !1 });
2506
+ const t = await this.client.search(e, {
2507
+ streaming: !1,
2508
+ signal: this.currentSearchController.signal
2509
+ });
2501
2510
  this.displayResults(t, e);
2502
2511
  } catch (t) {
2512
+ if (t.name === "AbortError")
2513
+ return;
2503
2514
  this.showErrorState(t.message);
2504
2515
  } finally {
2505
- this.isLoading = !1;
2516
+ this.currentSearchController = null;
2506
2517
  }
2507
2518
  }
2508
2519
  }
@@ -2526,16 +2537,16 @@ ${U}`, this.container = document.createElement("div"), this.container.className
2526
2537
  this.resultsContainer.innerHTML = n, this.attachResultHandlers();
2527
2538
  }
2528
2539
  renderResult(e) {
2529
- const t = this.renderResultImage(e.image, e.title);
2540
+ const t = this.getProps(), s = this.renderResultImage(e.image, e.title);
2530
2541
  return `
2531
- <div class="search-result-item" role="button" tabindex="0" data-result-id="${l(e.url || "")}">
2532
- ${t}
2542
+ <a href="${e.url ? l(e.url) : "#"}" class="search-result-item" data-result-id="${l(e.url || "")}">
2543
+ ${s}
2533
2544
  <div class="search-result-content">
2534
2545
  <div class="search-result-title">${l(e.title || "")}</div>
2535
2546
  <div class="search-result-snippet">${l(e.description || "")}</div>
2536
- ${e.url ? `<a href="${l(e.url)}" class="search-result-url">${l(e.url)}</a>` : ""}
2547
+ ${t.showUrl && e.url ? `<span class="search-result-url">${l(e.url)}</span>` : ""}
2537
2548
  </div>
2538
- </div>
2549
+ </a>
2539
2550
  `;
2540
2551
  }
2541
2552
  renderResultImage(e, t) {
@@ -2561,11 +2572,8 @@ ${U}`, this.container = document.createElement("div"), this.container.className
2561
2572
  const e = this.container?.querySelectorAll(".search-result-item");
2562
2573
  if (!e) return;
2563
2574
  for (const s of e)
2564
- s.addEventListener("click", () => {
2565
- const a = s.getAttribute("data-result-id");
2566
- console.log("Result clicked:", a);
2567
- }), s.addEventListener("keydown", (a) => {
2568
- (a.key === "Enter" || a.key === " ") && s.click();
2575
+ s.getAttribute("href") === "#" && s.addEventListener("click", (n) => {
2576
+ n.preventDefault();
2569
2577
  });
2570
2578
  this.container?.querySelectorAll(".search-result-image")?.forEach((s) => {
2571
2579
  s.addEventListener("load", () => {
@@ -2628,7 +2636,7 @@ ${U}`, this.container = document.createElement("div"), this.container.className
2628
2636
  t === "auto" ? this.removeAttribute("theme") : this.setAttribute("theme", t);
2629
2637
  }
2630
2638
  cleanup() {
2631
- 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;
2639
+ 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;
2632
2640
  }
2633
2641
  // Public API
2634
2642
  async search(e) {
@@ -2771,7 +2779,7 @@ const G = `
2771
2779
  gap: var(--search-snippet-spacing-xs);
2772
2780
  }
2773
2781
 
2774
- .modal-result-item {
2782
+ a.modal-result-item {
2775
2783
  padding: var(--search-snippet-spacing-md);
2776
2784
  background: transparent;
2777
2785
  border: var(--search-snippet-border-width) solid transparent;
@@ -2782,6 +2790,8 @@ const G = `
2782
2790
  flex-direction: row;
2783
2791
  align-items: flex-start;
2784
2792
  gap: var(--search-snippet-spacing-md);
2793
+ text-decoration: none;
2794
+ color: inherit;
2785
2795
  }
2786
2796
 
2787
2797
  /* Image thumbnail container */
@@ -2852,18 +2862,18 @@ const G = `
2852
2862
  gap: var(--search-snippet-spacing-xs);
2853
2863
  }
2854
2864
 
2855
- .modal-result-item:hover,
2856
- .modal-result-item.active {
2865
+ a.modal-result-item:hover,
2866
+ a.modal-result-item.active {
2857
2867
  background: var(--search-snippet-hover-background);
2858
2868
  border-color: var(--search-snippet-border-color);
2859
2869
  }
2860
2870
 
2861
- .modal-result-item.active {
2871
+ a.modal-result-item.active {
2862
2872
  border-color: var(--search-snippet-primary-color);
2863
2873
  background: var(--search-snippet-focus-ring);
2864
2874
  }
2865
2875
 
2866
- .modal-result-item:focus-visible {
2876
+ a.modal-result-item:focus-visible {
2867
2877
  outline: 2px solid var(--search-snippet-primary-color);
2868
2878
  outline-offset: -2px;
2869
2879
  }
@@ -2880,7 +2890,7 @@ const G = `
2880
2890
 
2881
2891
  .modal-result-description {
2882
2892
  font-size: var(--search-snippet-font-size-sm);
2883
- color: var(--search-snippet-text-secondary);
2893
+ color: var(--search-snippet-text-description);
2884
2894
  line-height: 1.5;
2885
2895
  display: -webkit-box;
2886
2896
  -webkit-line-clamp: 2;
@@ -3045,10 +3055,10 @@ class Y extends HTMLElement {
3045
3055
  r(this, "resultsContainer", null);
3046
3056
  r(this, "footerCount", null);
3047
3057
  r(this, "isOpen", !1);
3048
- r(this, "isLoading", !1);
3049
3058
  r(this, "results", []);
3050
3059
  r(this, "activeIndex", -1);
3051
3060
  r(this, "debouncedSearch", null);
3061
+ r(this, "currentSearchController", null);
3052
3062
  // Event handler references for cleanup
3053
3063
  r(this, "handleGlobalKeydown", null);
3054
3064
  r(this, "handleInputChange", null);
@@ -3068,7 +3078,8 @@ class Y extends HTMLElement {
3068
3078
  "shortcut",
3069
3079
  "use-meta-key",
3070
3080
  "debounce-ms",
3071
- "hide-branding"
3081
+ "hide-branding",
3082
+ "show-url"
3072
3083
  ];
3073
3084
  }
3074
3085
  connectedCallback() {
@@ -3084,12 +3095,13 @@ class Y extends HTMLElement {
3084
3095
  return {
3085
3096
  apiUrl: u(this.getAttribute("api-url"), "http://localhost:3000"),
3086
3097
  placeholder: u(this.getAttribute("placeholder"), "Search..."),
3087
- maxResults: b(this.getAttribute("max-results"), 10),
3088
- debounceMs: b(this.getAttribute("debounce-ms"), 300),
3098
+ maxResults: f(this.getAttribute("max-results"), 10),
3099
+ debounceMs: f(this.getAttribute("debounce-ms"), 300),
3089
3100
  theme: u(this.getAttribute("theme"), "auto"),
3090
3101
  shortcut: u(this.getAttribute("shortcut"), "k"),
3091
3102
  useMetaKey: this.getAttribute("use-meta-key") !== "false",
3092
- hideBranding: f(this.getAttribute("hide-branding"), !1)
3103
+ hideBranding: v(this.getAttribute("hide-branding"), !1),
3104
+ showUrl: v(this.getAttribute("show-url"), !1)
3093
3105
  };
3094
3106
  }
3095
3107
  initializeClient() {
@@ -3201,8 +3213,8 @@ ${G}`;
3201
3213
  }
3202
3214
  selectActiveResult() {
3203
3215
  if (this.activeIndex < 0 || this.activeIndex >= this.results.length) {
3204
- const t = this.inputElement?.value.trim();
3205
- t && t.length > 0 && this.performSearch(t);
3216
+ const s = this.inputElement?.value.trim();
3217
+ s && s.length > 0 && this.performSearch(s);
3206
3218
  return;
3207
3219
  }
3208
3220
  const e = this.results[this.activeIndex];
@@ -3211,18 +3223,27 @@ ${G}`;
3211
3223
  result: e,
3212
3224
  index: this.activeIndex
3213
3225
  })
3214
- ), e.url && (window.location.href = e.url), this.close();
3226
+ );
3227
+ const t = this.resultsContainer?.querySelector(
3228
+ `.modal-result-item[data-index="${this.activeIndex}"]`
3229
+ );
3230
+ t && e.url && t.click(), this.close();
3215
3231
  }
3216
3232
  async performSearch(e) {
3217
- if (!(this.isLoading || !this.client)) {
3218
- this.isLoading = !0, this.showLoadingState();
3233
+ if (this.client) {
3234
+ this.currentSearchController && (this.currentSearchController.abort(), this.currentSearchController = null), this.currentSearchController = new AbortController(), this.showLoadingState();
3219
3235
  try {
3220
- const t = await this.client.search(e, { streaming: !1 }), s = this.getProps();
3236
+ const t = await this.client.search(e, {
3237
+ streaming: !1,
3238
+ signal: this.currentSearchController.signal
3239
+ }), s = this.getProps();
3221
3240
  this.results = t.slice(0, s.maxResults || 10), this.activeIndex = this.results.length > 0 ? 0 : -1, this.displayResults(this.results, e);
3222
3241
  } catch (t) {
3242
+ if (t.name === "AbortError")
3243
+ return;
3223
3244
  this.showErrorState(t.message);
3224
3245
  } finally {
3225
- this.isLoading = !1;
3246
+ this.currentSearchController = null;
3226
3247
  }
3227
3248
  }
3228
3249
  }
@@ -3236,9 +3257,10 @@ ${G}`;
3236
3257
  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();
3237
3258
  }
3238
3259
  renderResult(e, t) {
3239
- const s = this.renderResultImage(e.image, e.title);
3260
+ const s = this.getProps(), a = this.renderResultImage(e.image, e.title);
3240
3261
  return `
3241
- <div
3262
+ <a
3263
+ href="${e.url ? l(e.url) : "#"}"
3242
3264
  class="modal-result-item${t === this.activeIndex ? " active" : ""}"
3243
3265
  role="option"
3244
3266
  id="result-${t}"
@@ -3247,13 +3269,13 @@ ${G}`;
3247
3269
  data-index="${t}"
3248
3270
  data-url="${l(e.url || "")}"
3249
3271
  >
3250
- ${s}
3272
+ ${a}
3251
3273
  <div class="modal-result-content">
3252
3274
  <div class="modal-result-title">${l(e.title || "")}</div>
3253
3275
  ${e.description ? `<div class="modal-result-description">${l(e.description)}</div>` : ""}
3254
- ${e.url ? `<a href="${l(e.url)}" class="modal-result-url" tabindex="-1">${l(e.url)}</a>` : ""}
3276
+ ${s.showUrl && e.url ? `<span class="modal-result-url">${l(e.url)}</span>` : ""}
3255
3277
  </div>
3256
- </div>
3278
+ </a>
3257
3279
  `;
3258
3280
  }
3259
3281
  renderResultImage(e, t) {
@@ -3279,8 +3301,8 @@ ${G}`;
3279
3301
  const e = this.resultsContainer?.querySelectorAll(".modal-result-item");
3280
3302
  if (!e) return;
3281
3303
  e.forEach((s, a) => {
3282
- s.addEventListener("click", (n) => {
3283
- n.target.classList.contains("modal-result-url") || (this.activeIndex = a, this.selectActiveResult());
3304
+ s.getAttribute("href") === "#" && s.addEventListener("click", (c) => {
3305
+ c.preventDefault();
3284
3306
  }), s.addEventListener("mouseenter", () => {
3285
3307
  this.activeIndex = a, this.updateActiveResult();
3286
3308
  });
@@ -3357,7 +3379,7 @@ ${G}`;
3357
3379
  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;
3358
3380
  }
3359
3381
  cleanup() {
3360
- 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();
3382
+ 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();
3361
3383
  }
3362
3384
  // Public API
3363
3385
  /**