@cloudflare/ai-search-snippet 0.0.25 → 0.0.26

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,4 +1,4 @@
1
- (function(p,l){typeof exports=="object"&&typeof module<"u"?l(exports):typeof define=="function"&&define.amd?define(["exports"],l):(p=typeof globalThis<"u"?globalThis:p||self,l(p.SearchSnippet={}))})(this,(function(p){"use strict";var Y=Object.defineProperty;var W=(p,l,b)=>l in p?Y(p,l,{enumerable:!0,configurable:!0,writable:!0,value:b}):p[l]=b;var a=(p,l,b)=>W(p,typeof l!="symbol"?l+"":l,b);const l=["Searching...","Digging through results...","Scanning the knowledge base...","Finding the best matches...","Sifting through the data...","Almost there...","Looking far and wide...","Connecting the dots...","Rummaging through pages...","Hunting down answers..."];function L(o,i){let e;return function(...s){const r=()=>{clearTimeout(e),o(...s)};clearTimeout(e),e=setTimeout(r,i)}}function h(o){const i=document.createElement("div");return i.textContent=o,i.innerHTML}function I(o){return new DOMParser().parseFromString(o,"text/html").documentElement.textContent||""}function V(o){const i=new Date(o),t=new Date().getTime()-i.getTime();if(t<6e4)return"Just now";if(t<36e5){const s=Math.floor(t/6e4);return`${s} ${s===1?"minute":"minutes"} ago`}if(t<864e5){const s=Math.floor(t/36e5);return`${s} ${s===1?"hour":"hours"} ago`}return i.toLocaleString(void 0,{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"})}function z(o="id"){return`${o}-${Date.now()}-${Math.random().toString(36).substr(2,9)}`}function u(o,i){return o!==null?o:i}function v(o,i){return o===null?i:o==="true"||o===""}function w(o,i){if(o===null)return i;const e=Number.parseInt(o,10);return Number.isNaN(e)?i:e}function m(o,i){return new CustomEvent(o,{detail:i,bubbles:!0,composed:!0,cancelable:!0})}function y(o){if(!o)throw new Error("API URL is required");return new T(o)}class D{constructor(i){a(this,"activeRequests",new Map);a(this,"baseUrl");this.baseUrl=i.replace(/\/$/,"")}search(i,e){throw new Error("Not implemented")}searchStream(i,e){throw new Error("Not implemented")}chat(i,e){throw new Error("Not implemented")}cancelRequest(i){throw new Error("Not implemented")}cancelAllRequests(){throw new Error("Not implemented")}}class T extends D{request(i={},e,t){const s=e==="search"?"snippet-search":"snippet-chat-completions";return fetch(`${this.baseUrl}/${e}`,{method:"POST",body:JSON.stringify({messages:[{role:"user",content:i.query}],stream:i.streaming,max_results:i.maxResults,...e==="search"&&{ai_search_options:{retrieval:{metadata_only:!0}}}}),headers:{"Content-Type":"application/json","cf-ai-search-source":s},signal:t})}async search(i,e={}){const t=this.generateRequestId(),s=new AbortController,r=e.signal||s.signal;this.registerRequest(t,s);try{const n=await this.request({query:i,streaming:!1,maxResults:30},"search",r);if(!n.ok)throw new Error(`HTTP error! status: ${n.status}`);if(!n.body)throw new Error("Response body is empty");const c=await n.json();if(c.success&&c.result)return c.result.chunks.slice(0,10).map(d=>({type:"result",id:d.id,title:I(d.item.metadata.title),description:d.item.metadata.description?I(d.item.metadata.description):"",url:d.item.key,image:d.item.metadata.image||void 0,metadata:d.item.metadata}));throw c.success===!1?new Error(c.error):new Error("Unknown error")}finally{this.unregisterRequest(t)}}async*searchStream(i,e){const t=this.generateRequestId(),s=new AbortController,r=e?.signal||s.signal;this.registerRequest(t,s);const n=await this.request({query:i,streaming:!0},"ai-search",r);if(!n.ok)throw new Error(`HTTP error! status: ${n.status}`);if(!n.body)throw new Error("Response body is empty");let c="";const d=n.body.getReader(),C=new TextDecoder;for(;;){const{done:g,value:M}=await d.read();if(g)break;const F=C.decode(M,{stream:!0});c+=F}yield{type:"result",id:"",title:"",description:c.replaceAll("data: ","").trim().split(`
1
+ (function(p,l){typeof exports=="object"&&typeof module<"u"?l(exports):typeof define=="function"&&define.amd?define(["exports"],l):(p=typeof globalThis<"u"?globalThis:p||self,l(p.SearchSnippet={}))})(this,(function(p){"use strict";var Y=Object.defineProperty;var W=(p,l,b)=>l in p?Y(p,l,{enumerable:!0,configurable:!0,writable:!0,value:b}):p[l]=b;var a=(p,l,b)=>W(p,typeof l!="symbol"?l+"":l,b);const l=["Searching...","Digging through results...","Scanning the knowledge base...","Finding the best matches...","Sifting through the data...","Almost there...","Looking far and wide...","Connecting the dots...","Rummaging through pages...","Hunting down answers..."];function L(o,i){let e;return function(...s){const r=()=>{clearTimeout(e),o(...s)};clearTimeout(e),e=setTimeout(r,i)}}function d(o){const i=document.createElement("div");return i.textContent=o,i.innerHTML}function I(o){return new DOMParser().parseFromString(o,"text/html").documentElement.textContent||""}function j(o){const i=new Date(o),t=new Date().getTime()-i.getTime();if(t<6e4)return"Just now";if(t<36e5){const s=Math.floor(t/6e4);return`${s} ${s===1?"minute":"minutes"} ago`}if(t<864e5){const s=Math.floor(t/36e5);return`${s} ${s===1?"hour":"hours"} ago`}return i.toLocaleString(void 0,{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"})}function z(o="id"){return`${o}-${Date.now()}-${Math.random().toString(36).substr(2,9)}`}function u(o,i){return o!==null?o:i}function v(o,i){return o===null?i:o==="true"||o===""}function w(o,i){if(o===null)return i;const e=Number.parseInt(o,10);return Number.isNaN(e)?i:e}function m(o,i){return new CustomEvent(o,{detail:i,bubbles:!0,composed:!0,cancelable:!0})}function y(o){if(!o)throw new Error("API URL is required");return new T(o)}class V{constructor(i){a(this,"activeRequests",new Map);a(this,"baseUrl");this.baseUrl=i.replace(/\/$/,"")}search(i,e){throw new Error("Not implemented")}searchStream(i,e){throw new Error("Not implemented")}chat(i,e){throw new Error("Not implemented")}cancelRequest(i){throw new Error("Not implemented")}cancelAllRequests(){throw new Error("Not implemented")}}class T extends V{request(i={},e,t){const s=e==="search"?"snippet-search":"snippet-chat-completions";return fetch(`${this.baseUrl}/${e}`,{method:"POST",body:JSON.stringify({messages:[{role:"user",content:i.query}],stream:i.streaming,max_results:i.maxResults,...e==="search"&&{ai_search_options:{retrieval:{metadata_only:!0}}}}),headers:{"Content-Type":"application/json","cf-ai-search-source":s},signal:t})}async search(i,e={}){const t=this.generateRequestId(),s=new AbortController,r=e.signal||s.signal;this.registerRequest(t,s);try{const n=await this.request({query:i,streaming:!1,maxResults:30},"search",r);if(!n.ok)throw new Error(`HTTP error! status: ${n.status}`);if(!n.body)throw new Error("Response body is empty");const c=await n.json();if(c.success&&c.result)return c.result.chunks.slice(0,10).map(h=>({type:"result",id:h.id,title:I(h.item.metadata?.title),description:h.item.metadata?.description?I(h.item.metadata?.description):"",url:h.item.key,image:h.item.metadata?.image||void 0,metadata:h.item.metadata}));throw c.success===!1?new Error(c.error):new Error("Unknown error")}finally{this.unregisterRequest(t)}}async*searchStream(i,e){const t=this.generateRequestId(),s=new AbortController,r=e?.signal||s.signal;this.registerRequest(t,s);const n=await this.request({query:i,streaming:!0},"ai-search",r);if(!n.ok)throw new Error(`HTTP error! status: ${n.status}`);if(!n.body)throw new Error("Response body is empty");let c="";const h=n.body.getReader(),C=new TextDecoder;for(;;){const{done:g,value:M}=await h.read();if(g)break;const F=C.decode(M,{stream:!0});c+=F}yield{type:"result",id:"",title:"",description:c.replaceAll("data: ","").trim().split(`
2
2
 
3
3
  `).map(g=>JSON.parse(g)).map(g=>g.response).join(""),url:"",metadata:{}}}async*chat(i,e){const t=new AbortController,s=e?.signal||t.signal,r=await this.request({query:i,streaming:!1},"chat/completions",s);if(!r.ok)throw new Error(`HTTP error! status: ${r.status}`);if(!r.body)throw new Error("Response body is empty");yield{type:"text",message:(await r.json()).choices.map(c=>c.message.content).join("")}}cancelRequest(i){const e=this.activeRequests.get(i);e&&(e.controller.abort(),this.unregisterRequest(i))}cancelAllRequests(){for(const[i]of this.activeRequests)this.cancelRequest(i)}registerRequest(i,e){this.activeRequests.set(i,{id:i,controller:e,timestamp:Date.now()})}unregisterRequest(i){this.activeRequests.delete(i)}generateRequestId(){return`req-${Date.now()}-${Math.random().toString(36).substr(2,9)}`}}const x=`Powered by <a href="https://search.ai.cloudflare.com" target="_blank" rel="noopener noreferrer">Cloudflare AI Search <svg width="32" height="10" viewBox="0 0 412 186" xmlns="http://www.w3.org/2000/svg" aria-label="Cloudflare" role="img">
4
4
  <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"/>
@@ -754,8 +754,8 @@
754
754
  padding: var(--search-snippet-spacing-xs) 0;
755
755
  text-align: center;
756
756
  }
757
- `;function j(o){let i=o;i=K(i),i=i.replace(/```([\s\S]*?)```/g,(n,c)=>`<pre><code>${c.trim()}</code></pre>`);const e=i.split(`
758
- `),t=[];let s=!1,r="";for(let n=0;n<e.length;n++){const c=e[n],d=c.match(/^(#{1,6})\s+(.+)$/);if(d){const g=d[1].length,M=d[2];t.push(`<h${g}>${f(M)}</h${g}>`);continue}if(c.match(/^---+$/)){t.push("<hr />");continue}if(c.match(/^>\s+/)){const g=c.replace(/^>\s+/,"");t.push(`<blockquote>${f(g)}</blockquote>`);continue}const C=c.match(/^[-*]\s+(.+)$/);if(C){(!s||r!=="ul")&&(s&&t.push(`</${r}>`),t.push("<ul>"),s=!0,r="ul"),t.push(`<li>${f(C[1])}</li>`);continue}const E=c.match(/^\d+\.\s+(.+)$/);if(E){(!s||r!=="ol")&&(s&&t.push(`</${r}>`),t.push("<ol>"),s=!0,r="ol"),t.push(`<li>${f(E[1])}</li>`);continue}if(s&&(t.push(`</${r}>`),s=!1,r=""),c.trim()===""){t.push("<br />");continue}t.push(`<p>${f(c)}</p>`)}return s&&t.push(`</${r}>`),t.join(`
757
+ `;function D(o){let i=o;i=K(i),i=i.replace(/```([\s\S]*?)```/g,(n,c)=>`<pre><code>${c.trim()}</code></pre>`);const e=i.split(`
758
+ `),t=[];let s=!1,r="";for(let n=0;n<e.length;n++){const c=e[n],h=c.match(/^(#{1,6})\s+(.+)$/);if(h){const g=h[1].length,M=h[2];t.push(`<h${g}>${f(M)}</h${g}>`);continue}if(c.match(/^---+$/)){t.push("<hr />");continue}if(c.match(/^>\s+/)){const g=c.replace(/^>\s+/,"");t.push(`<blockquote>${f(g)}</blockquote>`);continue}const C=c.match(/^[-*]\s+(.+)$/);if(C){(!s||r!=="ul")&&(s&&t.push(`</${r}>`),t.push("<ul>"),s=!0,r="ul"),t.push(`<li>${f(C[1])}</li>`);continue}const E=c.match(/^\d+\.\s+(.+)$/);if(E){(!s||r!=="ol")&&(s&&t.push(`</${r}>`),t.push("<ol>"),s=!0,r="ol"),t.push(`<li>${f(E[1])}</li>`);continue}if(s&&(t.push(`</${r}>`),s=!1,r=""),c.trim()===""){t.push("<br />");continue}t.push(`<p>${f(c)}</p>`)}return s&&t.push(`</${r}>`),t.join(`
759
759
  `)}function f(o){let i=o;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(/\[([^\]]+)\]\(([^)]+)\)/g,'<a href="$2" target="_blank" rel="noopener noreferrer">$1</a>'),i}function K(o){const i={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"};return o.replace(/[&<>"']/g,e=>i[e]||e)}class ${constructor(i,e,t){a(this,"container");a(this,"client");a(this,"props");a(this,"inputElement",null);a(this,"messagesContainer",null);a(this,"sendButton",null);a(this,"messages",[]);a(this,"isStreaming",!1);a(this,"currentStreamingMessageId",null);a(this,"loadingMessageInterval",null);a(this,"loadingMessageIndex",0);a(this,"handleInputResize",null);a(this,"handleInputKeydown",null);a(this,"handleSendClick",null);this.container=i,this.client=e,this.props=t,this.render(),this.attachEventListeners()}render(){this.container.innerHTML=`
760
760
  <div class="chat-container">
761
761
  <div class="chat-messages">
@@ -773,7 +773,7 @@
773
773
  <div class="chat-input-wrapper">
774
774
  <textarea
775
775
  class="chat-input"
776
- placeholder="${h(this.props.placeholder||"Type a message...")}"
776
+ placeholder="${d(this.props.placeholder||"Type a message...")}"
777
777
  aria-label="Chat message input"
778
778
  style="height: 40px;"
779
779
  rows="1"
@@ -784,7 +784,7 @@
784
784
  </div>
785
785
  </div>
786
786
  </div>
787
- `,this.messagesContainer=this.container.querySelector(".chat-messages"),this.inputElement=this.container.querySelector(".chat-input"),this.sendButton=this.container.querySelector(".chat-send-button")}attachEventListeners(){!this.inputElement||!this.sendButton||(this.handleInputResize=i=>{const e=i.target;e.style.height="auto",e.style.height=`${e.scrollHeight}px`},this.inputElement.addEventListener("input",this.handleInputResize),this.handleInputKeydown=i=>{i.key==="Enter"&&!i.shiftKey&&(i.preventDefault(),this.handleSendMessage())},this.inputElement.addEventListener("keydown",this.handleInputKeydown),this.handleSendClick=()=>{this.handleSendMessage()},this.sendButton.addEventListener("click",this.handleSendClick))}async handleSendMessage(){if(!this.inputElement||this.isStreaming)return;const i=this.inputElement.value.trim();i.length!==0&&(this.inputElement.value="",this.inputElement.style.height="auto",await this.sendMessage(i))}async sendMessage(i){const e={id:z("msg"),role:"user",content:i,timestamp:Date.now()};this.addMessage(e),this.renderMessages(!0),this.setStreamingState(!0);const t=z("msg"),s={id:t,role:"assistant",content:"",timestamp:Date.now()};this.addMessage(s),this.currentStreamingMessageId=t,this.renderMessages(!0);try{const r=this.client.chat(i);let n="";for await(const d of r)if(d.type==="text"&&d.message)n+=d.message,this.updateStreamingMessage(t,n);else if(d.type==="error"){this.showErrorInMessage(t,d.message||"Unknown error");break}const c=this.messages.findIndex(d=>d.id===t);c!==-1&&(this.messages[c].content=n),this.container.dispatchEvent(m("message",{message:s}))}catch(r){this.showErrorInMessage(t,r.message),this.container.dispatchEvent(m("error",{error:{message:r.message,code:"CHAT_ERROR"}}))}finally{this.setStreamingState(!1),this.renderMessages(),this.currentStreamingMessageId=null}}addMessage(i){this.messages.push(i),this.renderMessages()}updateStreamingMessage(i,e){const t=this.messages.findIndex(s=>s.id===i);t!==-1&&(this.messages[t].content=e,this.renderMessages(!0))}showErrorInMessage(i,e){const t=this.messages.findIndex(s=>s.id===i);t!==-1&&(this.messages[t].content=`Error: ${e}`,this.renderMessages())}renderMessages(i=!1){if(!this.messagesContainer)return;if(this.messages.length===0){this.messagesContainer.innerHTML=`
787
+ `,this.messagesContainer=this.container.querySelector(".chat-messages"),this.inputElement=this.container.querySelector(".chat-input"),this.sendButton=this.container.querySelector(".chat-send-button")}attachEventListeners(){!this.inputElement||!this.sendButton||(this.handleInputResize=i=>{const e=i.target;e.style.height="auto",e.style.height=`${e.scrollHeight}px`},this.inputElement.addEventListener("input",this.handleInputResize),this.handleInputKeydown=i=>{i.key==="Enter"&&!i.shiftKey&&(i.preventDefault(),this.handleSendMessage())},this.inputElement.addEventListener("keydown",this.handleInputKeydown),this.handleSendClick=()=>{this.handleSendMessage()},this.sendButton.addEventListener("click",this.handleSendClick))}async handleSendMessage(){if(!this.inputElement||this.isStreaming)return;const i=this.inputElement.value.trim();i.length!==0&&(this.inputElement.value="",this.inputElement.style.height="auto",await this.sendMessage(i))}async sendMessage(i){const e={id:z("msg"),role:"user",content:i,timestamp:Date.now()};this.addMessage(e),this.renderMessages(!0),this.setStreamingState(!0);const t=z("msg"),s={id:t,role:"assistant",content:"",timestamp:Date.now()};this.addMessage(s),this.currentStreamingMessageId=t,this.renderMessages(!0);try{const r=this.client.chat(i);let n="";for await(const h of r)if(h.type==="text"&&h.message)n+=h.message,this.updateStreamingMessage(t,n);else if(h.type==="error"){this.showErrorInMessage(t,h.message||"Unknown error");break}const c=this.messages.findIndex(h=>h.id===t);c!==-1&&(this.messages[c].content=n),this.container.dispatchEvent(m("message",{message:s}))}catch(r){this.showErrorInMessage(t,r.message),this.container.dispatchEvent(m("error",{error:{message:r.message,code:"CHAT_ERROR"}}))}finally{this.setStreamingState(!1),this.renderMessages(),this.currentStreamingMessageId=null}}addMessage(i){this.messages.push(i),this.renderMessages()}updateStreamingMessage(i,e){const t=this.messages.findIndex(s=>s.id===i);t!==-1&&(this.messages[t].content=e,this.renderMessages(!0))}showErrorInMessage(i,e){const t=this.messages.findIndex(s=>s.id===i);t!==-1&&(this.messages[t].content=`Error: ${e}`,this.renderMessages())}renderMessages(i=!1){if(!this.messagesContainer)return;if(this.messages.length===0){this.messagesContainer.innerHTML=`
788
788
  <div class="chat-empty">
789
789
  <svg class="chat-empty-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
790
790
  <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path>
@@ -799,11 +799,11 @@
799
799
  <div class="chat-message-avatar">${s}</div>
800
800
  <div class="chat-message-content">
801
801
  <div class="chat-message-bubble">
802
- ${i.content?`<div class="chat-message-text">${j(i.content)}</div>`:""}
802
+ ${i.content?`<div class="chat-message-text">${D(i.content)}</div>`:""}
803
803
  ${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">${l[this.loadingMessageIndex]}</span></div>`:""}
804
804
  </div>
805
805
  <div class="chat-message-metadata">
806
- <span class="chat-message-time">${V(i.timestamp)}</span>
806
+ <span class="chat-message-time">${j(i.timestamp)}</span>
807
807
  </div>
808
808
  </div>
809
809
  </div>
@@ -1470,15 +1470,13 @@ a.search-result-item {
1470
1470
  height: 64px;
1471
1471
  border-radius: calc(var(--search-snippet-border-radius) - 4px);
1472
1472
  overflow: hidden;
1473
- background: var(--search-snippet-surface);
1474
- border: var(--search-snippet-border-width) solid var(--search-snippet-border-color);
1475
1473
  position: relative;
1476
1474
  }
1477
1475
 
1478
1476
  .search-result-image {
1479
1477
  width: 100%;
1480
1478
  height: 100%;
1481
- object-fit: cover;
1479
+ object-fit: contain;
1482
1480
  opacity: 0;
1483
1481
  transition: opacity var(--search-snippet-transition);
1484
1482
  }
@@ -1591,13 +1589,29 @@ a.search-result-item:focus-visible {
1591
1589
  /* Search footer */
1592
1590
  .search-footer {
1593
1591
  padding: var(--search-snippet-spacing-md);
1594
- border-top: var(--search-snippet-border-width) solid var(--search-snippet-border-color);
1592
+ padding-bottom: var(--search-snippet-spacing-xs);
1595
1593
  display: flex;
1596
1594
  align-items: center;
1597
1595
  justify-content: center;
1598
1596
  gap: var(--search-snippet-spacing-sm);
1599
1597
  }
1600
1598
 
1599
+ /* See more link */
1600
+ .search-see-more {
1601
+ display: inline-flex;
1602
+ align-items: center;
1603
+ gap: var(--search-snippet-spacing-xs);
1604
+ font-size: var(--search-snippet-font-size-sm);
1605
+ color: var(--search-snippet-primary-color);
1606
+ text-decoration: none;
1607
+ font-weight: var(--search-snippet-font-weight-medium);
1608
+ transition: color var(--search-snippet-transition-fast);
1609
+ }
1610
+
1611
+ .search-see-more:hover {
1612
+ text-decoration: underline;
1613
+ }
1614
+
1601
1615
  /* Loading state for search */
1602
1616
  .search-loading {
1603
1617
  display: flex;
@@ -1645,7 +1659,7 @@ a.search-result-item:focus-visible {
1645
1659
  border-radius: 2px;
1646
1660
  font-weight: var(--search-snippet-font-weight-medium);
1647
1661
  }
1648
- `,_="search-bar-snippet";class S extends HTMLElement{constructor(){super();a(this,"shadow");a(this,"client",null);a(this,"container",null);a(this,"inputElement",null);a(this,"resultsContainer",null);a(this,"searchButton",null);a(this,"debouncedSearch",null);a(this,"currentSearchController",null);a(this,"loadingMessageInterval",null);a(this,"loadingMessageIndex",0);a(this,"handleInputChange",null);a(this,"handleInputKeydownEnter",null);a(this,"handleInputKeydownEscape",null);a(this,"handleSearchButtonClick",null);this.shadow=this.attachShadow({mode:"open"})}static get observedAttributes(){return["api-url","placeholder","max-results","debounce-ms","theme","hide-branding","show-url"]}connectedCallback(){this.initializeClient(),this.render(),this.dispatchEvent(m("ready",void 0))}disconnectedCallback(){this.cleanup()}attributeChangedCallback(e,t,s){t!==s&&(e==="api-url"?this.initializeClient():e==="theme"&&this.updateTheme(s))}getProps(){return{apiUrl:u(this.getAttribute("api-url"),"http://localhost:3000"),placeholder:u(this.getAttribute("placeholder"),"Search..."),maxResults:w(this.getAttribute("max-results"),10),debounceMs:w(this.getAttribute("debounce-ms"),300),theme:u(this.getAttribute("theme"),"auto"),hideBranding:v(this.getAttribute("hide-branding"),!1),showUrl:v(this.getAttribute("show-url"),!1)}}initializeClient(){const e=this.getProps();if(!e.apiUrl){console.error("SearchBarSnippet: api-url attribute is required");return}try{this.client=y(e.apiUrl)}catch(t){console.error("SearchBarSnippet:",t)}}render(){const e=this.getProps(),t=r=>this.performSearch(r);this.debouncedSearch=L(t,e.debounceMs||400);const s=document.createElement("style");s.textContent=`${k}
1662
+ `,_="search-bar-snippet";class S extends HTMLElement{constructor(){super();a(this,"shadow");a(this,"client",null);a(this,"container",null);a(this,"inputElement",null);a(this,"resultsContainer",null);a(this,"searchButton",null);a(this,"debouncedSearch",null);a(this,"currentSearchController",null);a(this,"loadingMessageInterval",null);a(this,"loadingMessageIndex",0);a(this,"handleInputChange",null);a(this,"handleInputKeydownEnter",null);a(this,"handleInputKeydownEscape",null);a(this,"handleSearchButtonClick",null);this.shadow=this.attachShadow({mode:"open"})}static get observedAttributes(){return["api-url","placeholder","max-results","debounce-ms","theme","hide-branding","show-url","hide-thumbnails","see-more"]}connectedCallback(){this.initializeClient(),this.render(),this.dispatchEvent(m("ready",void 0))}disconnectedCallback(){this.cleanup()}attributeChangedCallback(e,t,s){t!==s&&(e==="api-url"?this.initializeClient():e==="theme"&&this.updateTheme(s))}getProps(){return{apiUrl:u(this.getAttribute("api-url"),"http://localhost:3000"),placeholder:u(this.getAttribute("placeholder"),"Search..."),maxResults:w(this.getAttribute("max-results"),10),debounceMs:w(this.getAttribute("debounce-ms"),300),theme:u(this.getAttribute("theme"),"auto"),hideBranding:v(this.getAttribute("hide-branding"),!1),showUrl:v(this.getAttribute("show-url"),!1),hideThumbnails:v(this.getAttribute("hide-thumbnails"),!1),seeMore:u(this.getAttribute("see-more"),"")}}initializeClient(){const e=this.getProps();if(!e.apiUrl){console.error("SearchBarSnippet: api-url attribute is required");return}try{this.client=y(e.apiUrl)}catch(t){console.error("SearchBarSnippet:",t)}}render(){const e=this.getProps(),t=r=>this.performSearch(r);this.debouncedSearch=L(t,e.debounceMs||400);const s=document.createElement("style");s.textContent=`${k}
1649
1663
  ${U}`,this.container=document.createElement("div"),this.container.className="container",this.container.innerHTML=`
1650
1664
  <div class="search-view">
1651
1665
  <div class="search-input-wrapper">
@@ -1654,7 +1668,7 @@ ${U}`,this.container=document.createElement("div"),this.container.className="con
1654
1668
  type="text"
1655
1669
  name="search-input"
1656
1670
  class="search-input"
1657
- placeholder="${h(e.placeholder||"Search...")}"
1671
+ placeholder="${d(e.placeholder||"Search...")}"
1658
1672
  aria-label="Search input"
1659
1673
  autocomplete="off"
1660
1674
  />
@@ -1668,7 +1682,12 @@ ${U}`,this.container=document.createElement("div"),this.container.className="con
1668
1682
  </div>
1669
1683
  </div>
1670
1684
  </div>
1671
- `,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()}attachEventListeners(){this.inputElement&&(this.handleInputChange=e=>{const s=e.target.value.trim();s.length>0&&this.debouncedSearch?this.debouncedSearch(s):this.showEmptyState()},this.inputElement.addEventListener("input",this.handleInputChange),this.handleInputKeydownEnter=e=>{if(e.key==="Enter"){const t=e.target.value.trim();t.length>0&&this.performSearch(t)}},this.inputElement.addEventListener("keydown",this.handleInputKeydownEnter),this.handleInputKeydownEscape=e=>{e.key==="Escape"&&this.inputElement&&(this.inputElement.value="")},window.addEventListener("keydown",this.handleInputKeydownEscape),this.searchButton&&(this.handleSearchButtonClick=()=>{const e=this.inputElement?.value.trim()||"";e.length>0&&this.performSearch(e)},this.searchButton.addEventListener("click",this.handleSearchButtonClick)))}async performSearch(e){if(this.client){this.currentSearchController&&(this.currentSearchController.abort(),this.currentSearchController=null),this.currentSearchController=new AbortController,this.showLoadingState();try{const t=await this.client.search(e,{streaming:!1,signal:this.currentSearchController.signal});this.displayResults(t,e)}catch(t){if(t.name==="AbortError")return;this.showErrorState(t.message)}finally{this.currentSearchController=null}}}displayResults(e,t){if(this.clearLoadingInterval(),!this.resultsContainer)return;if(e.length===0){this.showNoResultsState(t);return}const r=this.getProps().hideBranding?"":`<div class="powered-by-inline">${x}</div>`,n=`
1685
+ `,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()}attachEventListeners(){this.inputElement&&(this.handleInputChange=e=>{const s=e.target.value.trim();s.length>0&&this.debouncedSearch?this.debouncedSearch(s):this.showEmptyState()},this.inputElement.addEventListener("input",this.handleInputChange),this.handleInputKeydownEnter=e=>{if(e.key==="Enter"){const t=e.target.value.trim();t.length>0&&this.performSearch(t)}},this.inputElement.addEventListener("keydown",this.handleInputKeydownEnter),this.handleInputKeydownEscape=e=>{e.key==="Escape"&&this.inputElement&&(this.inputElement.value="")},window.addEventListener("keydown",this.handleInputKeydownEscape),this.searchButton&&(this.handleSearchButtonClick=()=>{const e=this.inputElement?.value.trim()||"";e.length>0&&this.performSearch(e)},this.searchButton.addEventListener("click",this.handleSearchButtonClick)))}async performSearch(e){if(this.client){this.currentSearchController&&(this.currentSearchController.abort(),this.currentSearchController=null),this.currentSearchController=new AbortController,this.showLoadingState();try{const t=await this.client.search(e,{streaming:!1,signal:this.currentSearchController.signal});this.displayResults(t,e)}catch(t){if(t.name==="AbortError")return;this.showErrorState(t.message)}finally{this.currentSearchController=null}}}displayResults(e,t){if(this.clearLoadingInterval(),!this.resultsContainer)return;if(e.length===0){this.showNoResultsState(t);return}const s=this.getProps(),r=s.hideBranding?"":`<div class="powered-by-inline">${x}</div>`,n=s.seeMore?`<div class="search-footer">
1686
+ <a href="${d(s.seeMore+encodeURIComponent(t))}" class="search-see-more">
1687
+ <span>See more results</span>
1688
+ <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>
1689
+ </a>
1690
+ </div>`:"",c=`
1672
1691
  <div class="search-header">
1673
1692
  <div class="search-count">
1674
1693
  Found ${e.length} result${e.length===1?"":"s"}
@@ -1676,15 +1695,16 @@ ${U}`,this.container=document.createElement("div"),this.container.className="con
1676
1695
  ${r}
1677
1696
  </div>
1678
1697
  <div class="search-results">
1679
- ${e.map(c=>this.renderResult(c)).join("")}
1698
+ ${e.map(h=>this.renderResult(h)).join("")}
1680
1699
  </div>
1681
- `;this.resultsContainer.innerHTML=n,this.attachResultHandlers()}renderResult(e){const t=this.getProps(),s=this.renderResultImage(e.image,e.title);return`
1682
- <a href="${e.url?h(e.url):"#"}" class="search-result-item" data-result-id="${h(e.url||"")}">
1700
+ ${n}
1701
+ `;this.resultsContainer.innerHTML=c,this.attachResultHandlers()}renderResult(e){const t=this.getProps(),s=t.hideThumbnails?"":this.renderResultImage(e.image,e.title);return`
1702
+ <a href="${e.url?d(e.url):"#"}" class="search-result-item" data-result-id="${d(e.url||"")}">
1683
1703
  ${s}
1684
1704
  <div class="search-result-content">
1685
- <div class="search-result-title">${h(e.title||"")}</div>
1686
- <div class="search-result-snippet">${h(e.description||"")}</div>
1687
- ${t.showUrl&&e.url?`<span class="search-result-url">${h(e.url)}</span>`:""}
1705
+ <div class="search-result-title">${d(e.title||"")}</div>
1706
+ <div class="search-result-snippet">${d(e.description||"")}</div>
1707
+ ${t.showUrl&&e.url?`<span class="search-result-url">${d(e.url)}</span>`:""}
1688
1708
  </div>
1689
1709
  </a>
1690
1710
  `}renderResultImage(e,t){const s='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/><polyline points="10 9 9 9 8 9"/></svg>';return e?`
@@ -1693,8 +1713,8 @@ ${U}`,this.container=document.createElement("div"),this.container.className="con
1693
1713
  <div class="search-result-image-placeholder" style="display: none;">${s}</div>
1694
1714
  <img
1695
1715
  class="search-result-image"
1696
- src="${h(e)}"
1697
- alt="${h(t)}"
1716
+ src="${d(e)}"
1717
+ alt="${d(t)}"
1698
1718
  loading="lazy"
1699
1719
  />
1700
1720
  </div>
@@ -1726,12 +1746,12 @@ ${U}`,this.container=document.createElement("div"),this.container.className="con
1726
1746
  </svg>
1727
1747
  <div class="search-empty-title">No Results Found</div>
1728
1748
  <div class="search-empty-description">
1729
- No results found for "${h(e)}"
1749
+ No results found for "${d(e)}"
1730
1750
  </div>
1731
1751
  </div>
1732
1752
  `)}showErrorState(e){this.clearLoadingInterval(),this.resultsContainer&&(this.resultsContainer.innerHTML=`
1733
1753
  <div class="error">
1734
- <strong>Error:</strong> ${h(e)}
1754
+ <strong>Error:</strong> ${d(e)}
1735
1755
  </div>
1736
1756
  `)}updateTheme(e){const t=e==="light"||e==="dark"||e==="auto"?e:"auto";t==="auto"?this.removeAttribute("theme"):this.setAttribute("theme",t)}cleanup(){this.clearLoadingInterval(),this.currentSearchController&&(this.currentSearchController.abort(),this.currentSearchController=null),this.client&&this.client.cancelAllRequests(),this.inputElement&&(this.handleInputChange&&this.inputElement.removeEventListener("input",this.handleInputChange),this.handleInputKeydownEnter&&this.inputElement.removeEventListener("keydown",this.handleInputKeydownEnter),this.handleInputKeydownEscape&&window.removeEventListener("keydown",this.handleInputKeydownEscape)),this.searchButton&&this.handleSearchButtonClick&&this.searchButton.removeEventListener("click",this.handleSearchButtonClick),this.handleInputChange=null,this.handleInputKeydownEnter=null,this.handleInputKeydownEscape=null,this.handleSearchButtonClick=null}async search(e){await this.performSearch(e)}}customElements.get(_)||customElements.define(_,S);const G=`
1737
1757
  /* Modal backdrop */
@@ -1890,15 +1910,13 @@ a.modal-result-item {
1890
1910
  height: 48px;
1891
1911
  border-radius: 6px;
1892
1912
  overflow: hidden;
1893
- background: var(--search-snippet-surface);
1894
- border: var(--search-snippet-border-width) solid var(--search-snippet-border-color);
1895
1913
  position: relative;
1896
1914
  }
1897
1915
 
1898
1916
  .modal-result-image {
1899
1917
  width: 100%;
1900
1918
  height: 100%;
1901
- object-fit: cover;
1919
+ object-fit: contain;
1902
1920
  opacity: 0;
1903
1921
  transition: opacity var(--search-snippet-transition);
1904
1922
  }
@@ -2104,6 +2122,26 @@ a.modal-result-item:focus-visible {
2104
2122
  color: var(--search-snippet-primary-color);
2105
2123
  }
2106
2124
 
2125
+ /* See more link */
2126
+ .modal-see-more {
2127
+ display: flex;
2128
+ align-items: center;
2129
+ justify-content: center;
2130
+ gap: var(--search-snippet-spacing-xs);
2131
+ padding: var(--search-snippet-spacing-md);
2132
+ font-size: var(--search-snippet-font-size-sm);
2133
+ color: var(--search-snippet-primary-color);
2134
+ text-decoration: none;
2135
+ font-weight: var(--search-snippet-font-weight-medium);
2136
+ transition: background var(--search-snippet-transition-fast);
2137
+ padding-bottom: var(--search-snippet-spacing-xs);
2138
+ }
2139
+
2140
+ .modal-see-more:hover {
2141
+ background: var(--search-snippet-hover);
2142
+ text-decoration: underline;
2143
+ }
2144
+
2107
2145
  /* Responsive adjustments */
2108
2146
  @media (max-width: 640px) {
2109
2147
  .modal-container {
@@ -2132,7 +2170,7 @@ a.modal-result-item:focus-visible {
2132
2170
  .modal-container.open {
2133
2171
  animation: modal-slide-in var(--search-snippet-transition) ease-out;
2134
2172
  }
2135
- `,O="search-modal-snippet";class P extends HTMLElement{constructor(){super();a(this,"shadow");a(this,"client",null);a(this,"backdrop",null);a(this,"modal",null);a(this,"inputElement",null);a(this,"resultsContainer",null);a(this,"footerCount",null);a(this,"isOpen",!1);a(this,"results",[]);a(this,"activeIndex",-1);a(this,"debouncedSearch",null);a(this,"currentSearchController",null);a(this,"loadingMessageInterval",null);a(this,"loadingMessageIndex",0);a(this,"handleGlobalKeydown",null);a(this,"handleInputChange",null);a(this,"handleInputKeydown",null);a(this,"handleBackdropClick",null);a(this,"savedBodyStyles",null);a(this,"savedHtmlOverflow",null);this.shadow=this.attachShadow({mode:"open"})}static get observedAttributes(){return["api-url","placeholder","max-results","theme","shortcut","use-meta-key","debounce-ms","hide-branding","show-url"]}connectedCallback(){this.initializeClient(),this.render(),this.attachGlobalKeyboardShortcut(),this.dispatchEvent(m("ready",void 0))}disconnectedCallback(){this.cleanup()}attributeChangedCallback(e,t,s){t!==s&&(e==="api-url"?this.initializeClient():e==="theme"&&this.updateTheme(s))}getProps(){return{apiUrl:u(this.getAttribute("api-url"),"http://localhost:3000"),placeholder:u(this.getAttribute("placeholder"),"Search..."),maxResults:w(this.getAttribute("max-results"),10),debounceMs:w(this.getAttribute("debounce-ms"),300),theme:u(this.getAttribute("theme"),"auto"),shortcut:u(this.getAttribute("shortcut"),"k"),useMetaKey:this.getAttribute("use-meta-key")!=="false",hideBranding:v(this.getAttribute("hide-branding"),!1),showUrl:v(this.getAttribute("show-url"),!1)}}initializeClient(){const e=this.getProps();if(!e.apiUrl){console.error("SearchModalSnippet: api-url attribute is required");return}try{this.client=y(e.apiUrl)}catch(t){console.error("SearchModalSnippet:",t)}}render(){const e=this.getProps(),t=c=>this.performSearch(c);this.debouncedSearch=L(t,e.debounceMs||300);const s=document.createElement("style");s.textContent=`${k}
2173
+ `,O="search-modal-snippet";class P extends HTMLElement{constructor(){super();a(this,"shadow");a(this,"client",null);a(this,"backdrop",null);a(this,"modal",null);a(this,"inputElement",null);a(this,"resultsContainer",null);a(this,"footerCount",null);a(this,"isOpen",!1);a(this,"results",[]);a(this,"activeIndex",-1);a(this,"debouncedSearch",null);a(this,"currentSearchController",null);a(this,"loadingMessageInterval",null);a(this,"loadingMessageIndex",0);a(this,"handleGlobalKeydown",null);a(this,"handleInputChange",null);a(this,"handleInputKeydown",null);a(this,"handleBackdropClick",null);a(this,"savedBodyStyles",null);a(this,"savedHtmlOverflow",null);this.shadow=this.attachShadow({mode:"open"})}static get observedAttributes(){return["api-url","placeholder","max-results","theme","shortcut","use-meta-key","debounce-ms","hide-branding","show-url","hide-thumbnails","see-more"]}connectedCallback(){this.initializeClient(),this.render(),this.attachGlobalKeyboardShortcut(),this.dispatchEvent(m("ready",void 0))}disconnectedCallback(){this.cleanup()}attributeChangedCallback(e,t,s){t!==s&&(e==="api-url"?this.initializeClient():e==="theme"&&this.updateTheme(s))}getProps(){return{apiUrl:u(this.getAttribute("api-url"),"http://localhost:3000"),placeholder:u(this.getAttribute("placeholder"),"Search..."),maxResults:w(this.getAttribute("max-results"),10),debounceMs:w(this.getAttribute("debounce-ms"),300),theme:u(this.getAttribute("theme"),"auto"),shortcut:u(this.getAttribute("shortcut"),"k"),useMetaKey:this.getAttribute("use-meta-key")!=="false",hideBranding:v(this.getAttribute("hide-branding"),!1),showUrl:v(this.getAttribute("show-url"),!1),hideThumbnails:v(this.getAttribute("hide-thumbnails"),!1),seeMore:u(this.getAttribute("see-more"),"")}}initializeClient(){const e=this.getProps();if(!e.apiUrl){console.error("SearchModalSnippet: api-url attribute is required");return}try{this.client=y(e.apiUrl)}catch(t){console.error("SearchModalSnippet:",t)}}render(){const e=this.getProps(),t=c=>this.performSearch(c);this.debouncedSearch=L(t,e.debounceMs||300);const s=document.createElement("style");s.textContent=`${k}
2136
2174
  ${G}`;const r=e.hideBranding?"":`<div class="powered-by-inline">${x}</div>`,n=document.createElement("div");n.innerHTML=`
2137
2175
  <div class="modal-backdrop" role="presentation"></div>
2138
2176
  <div class="modal-container" role="dialog" aria-modal="true" aria-labelledby="modal-title">
@@ -2143,7 +2181,7 @@ ${G}`;const r=e.hideBranding?"":`<div class="powered-by-inline">${x}</div>`,n=do
2143
2181
  <input
2144
2182
  type="text"
2145
2183
  class="modal-search-input"
2146
- placeholder="${h(e.placeholder||"Search...")}"
2184
+ placeholder="${d(e.placeholder||"Search...")}"
2147
2185
  aria-label="Search"
2148
2186
  aria-autocomplete="list"
2149
2187
  aria-controls="modal-results-list"
@@ -2176,22 +2214,25 @@ ${G}`;const r=e.hideBranding?"":`<div class="powered-by-inline">${x}</div>`,n=do
2176
2214
  ${r}
2177
2215
  </div>
2178
2216
  </div>
2179
- `,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()}attachGlobalKeyboardShortcut(){const e=this.getProps(),t=e.shortcut?.toLowerCase()||"k";this.handleGlobalKeydown=s=>{(e.useMetaKey&&s.metaKey||s.ctrlKey)&&s.key.toLowerCase()===t&&!this.isOpen&&(s.preventDefault(),this.open())},document.addEventListener("keydown",this.handleGlobalKeydown)}attachEventListeners(){!this.inputElement||!this.backdrop||(this.handleInputChange=e=>{const s=e.target.value.trim();s.length>0&&this.debouncedSearch?this.debouncedSearch(s):(this.results=[],this.activeIndex=-1,this.showEmptyState())},this.inputElement.addEventListener("input",this.handleInputChange),this.handleInputKeydown=e=>{switch(e.key){case"ArrowDown":e.preventDefault(),this.navigateResults(1);break;case"ArrowUp":e.preventDefault(),this.navigateResults(-1);break;case"Enter":e.preventDefault(),this.selectActiveResult();break;case"Escape":e.preventDefault(),this.close();break}},this.inputElement.addEventListener("keydown",this.handleInputKeydown),this.handleBackdropClick=e=>{e.target===this.backdrop&&this.close()},this.backdrop.addEventListener("click",this.handleBackdropClick))}navigateResults(e){if(this.results.length===0)return;const t=this.activeIndex+e;t<0?this.activeIndex=this.results.length-1:t>=this.results.length?this.activeIndex=0:this.activeIndex=t,this.updateActiveResult()}updateActiveResult(){const e=this.resultsContainer?.querySelectorAll(".modal-result-item");e&&(e.forEach((t,s)=>{s===this.activeIndex?(t.classList.add("active"),t.setAttribute("aria-selected","true"),t.scrollIntoView({block:"nearest"})):(t.classList.remove("active"),t.setAttribute("aria-selected","false"))}),this.inputElement&&this.activeIndex>=0?this.inputElement.setAttribute("aria-activedescendant",`result-${this.activeIndex}`):this.inputElement&&this.inputElement.removeAttribute("aria-activedescendant"))}selectActiveResult(){if(this.activeIndex<0||this.activeIndex>=this.results.length){const s=this.inputElement?.value.trim();s&&s.length>0&&this.performSearch(s);return}const e=this.results[this.activeIndex];this.dispatchEvent(m("result-select",{result:e,index:this.activeIndex}));const t=this.resultsContainer?.querySelector(`.modal-result-item[data-index="${this.activeIndex}"]`);t&&e.url&&t.click(),this.close()}async performSearch(e){if(this.client){this.currentSearchController&&(this.currentSearchController.abort(),this.currentSearchController=null),this.currentSearchController=new AbortController,this.showLoadingState();try{const t=await this.client.search(e,{streaming:!1,signal:this.currentSearchController.signal}),s=this.getProps();this.results=t.slice(0,s.maxResults||10),this.activeIndex=this.results.length>0?0:-1,this.displayResults(this.results,e)}catch(t){if(t.name==="AbortError")return;this.showErrorState(t.message)}finally{this.currentSearchController=null}}}displayResults(e,t){if(this.clearLoadingInterval(),!this.resultsContainer)return;if(e.length===0){this.showNoResultsState(t);return}const s=e.map((r,n)=>this.renderResult(r,n)).join("");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()}renderResult(e,t){const s=this.getProps(),r=this.renderResultImage(e.image,e.title);return`
2217
+ `,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()}attachGlobalKeyboardShortcut(){const e=this.getProps(),t=e.shortcut?.toLowerCase()||"k";this.handleGlobalKeydown=s=>{(e.useMetaKey&&s.metaKey||s.ctrlKey)&&s.key.toLowerCase()===t&&!this.isOpen&&(s.preventDefault(),this.open())},document.addEventListener("keydown",this.handleGlobalKeydown)}attachEventListeners(){!this.inputElement||!this.backdrop||(this.handleInputChange=e=>{const s=e.target.value.trim();s.length>0&&this.debouncedSearch?this.debouncedSearch(s):(this.results=[],this.activeIndex=-1,this.showEmptyState())},this.inputElement.addEventListener("input",this.handleInputChange),this.handleInputKeydown=e=>{switch(e.key){case"ArrowDown":e.preventDefault(),this.navigateResults(1);break;case"ArrowUp":e.preventDefault(),this.navigateResults(-1);break;case"Enter":e.preventDefault(),this.selectActiveResult();break;case"Escape":e.preventDefault(),this.close();break}},this.inputElement.addEventListener("keydown",this.handleInputKeydown),this.handleBackdropClick=e=>{e.target===this.backdrop&&this.close()},this.backdrop.addEventListener("click",this.handleBackdropClick))}navigateResults(e){if(this.results.length===0)return;const t=this.activeIndex+e;t<0?this.activeIndex=this.results.length-1:t>=this.results.length?this.activeIndex=0:this.activeIndex=t,this.updateActiveResult()}updateActiveResult(){const e=this.resultsContainer?.querySelectorAll(".modal-result-item");e&&(e.forEach((t,s)=>{s===this.activeIndex?(t.classList.add("active"),t.setAttribute("aria-selected","true"),t.scrollIntoView({block:"nearest"})):(t.classList.remove("active"),t.setAttribute("aria-selected","false"))}),this.inputElement&&this.activeIndex>=0?this.inputElement.setAttribute("aria-activedescendant",`result-${this.activeIndex}`):this.inputElement&&this.inputElement.removeAttribute("aria-activedescendant"))}selectActiveResult(){if(this.activeIndex<0||this.activeIndex>=this.results.length){const s=this.inputElement?.value.trim();s&&s.length>0&&this.performSearch(s);return}const e=this.results[this.activeIndex];this.dispatchEvent(m("result-select",{result:e,index:this.activeIndex}));const t=this.resultsContainer?.querySelector(`.modal-result-item[data-index="${this.activeIndex}"]`);t&&e.url&&t.click(),this.close()}async performSearch(e){if(this.client){this.currentSearchController&&(this.currentSearchController.abort(),this.currentSearchController=null),this.currentSearchController=new AbortController,this.showLoadingState();try{const t=await this.client.search(e,{streaming:!1,signal:this.currentSearchController.signal}),s=this.getProps();this.results=t.slice(0,s.maxResults||10),this.activeIndex=this.results.length>0?0:-1,this.displayResults(this.results,e)}catch(t){if(t.name==="AbortError")return;this.showErrorState(t.message)}finally{this.currentSearchController=null}}}displayResults(e,t){if(this.clearLoadingInterval(),!this.resultsContainer)return;if(e.length===0){this.showNoResultsState(t);return}const s=this.getProps(),r=e.map((c,h)=>this.renderResult(c,h)).join(""),n=s.seeMore?`<a href="${d(s.seeMore+encodeURIComponent(t))}" class="modal-see-more">
2218
+ <span>See more results</span>
2219
+ <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>
2220
+ </a>`:"";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()}renderResult(e,t){const s=this.getProps(),r=s.hideThumbnails?"":this.renderResultImage(e.image,e.title);return`
2180
2221
  <a
2181
- href="${e.url?h(e.url):"#"}"
2222
+ href="${e.url?d(e.url):"#"}"
2182
2223
  class="modal-result-item${t===this.activeIndex?" active":""}"
2183
2224
  role="option"
2184
2225
  id="result-${t}"
2185
2226
  aria-selected="${t===this.activeIndex}"
2186
2227
  tabindex="-1"
2187
2228
  data-index="${t}"
2188
- data-url="${h(e.url||"")}"
2229
+ data-url="${d(e.url||"")}"
2189
2230
  >
2190
2231
  ${r}
2191
2232
  <div class="modal-result-content">
2192
- <div class="modal-result-title">${h(e.title||"")}</div>
2193
- ${e.description?`<div class="modal-result-description">${h(e.description)}</div>`:""}
2194
- ${s.showUrl&&e.url?`<span class="modal-result-url">${h(e.url)}</span>`:""}
2233
+ <div class="modal-result-title">${d(e.title||"")}</div>
2234
+ ${e.description?`<div class="modal-result-description">${d(e.description)}</div>`:""}
2235
+ ${s.showUrl&&e.url?`<span class="modal-result-url">${d(e.url)}</span>`:""}
2195
2236
  </div>
2196
2237
  </a>
2197
2238
  `}renderResultImage(e,t){const s='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/><polyline points="10 9 9 9 8 9"/></svg>';return e?`
@@ -2200,8 +2241,8 @@ ${G}`;const r=e.hideBranding?"":`<div class="powered-by-inline">${x}</div>`,n=do
2200
2241
  <div class="modal-result-image-placeholder" style="display: none;">${s}</div>
2201
2242
  <img
2202
2243
  class="modal-result-image"
2203
- src="${h(e)}"
2204
- alt="${h(t)}"
2244
+ src="${d(e)}"
2245
+ alt="${d(t)}"
2205
2246
  loading="lazy"
2206
2247
  />
2207
2248
  </div>
@@ -2229,11 +2270,11 @@ ${G}`;const r=e.hideBranding?"":`<div class="powered-by-inline">${x}</div>`,n=do
2229
2270
  <line x1="21" y1="21" x2="16.65" y2="16.65"></line>
2230
2271
  </svg>
2231
2272
  <div class="modal-empty-title">No results found</div>
2232
- <div class="modal-empty-description">No results for "${h(e)}"</div>
2273
+ <div class="modal-empty-description">No results for "${d(e)}"</div>
2233
2274
  </div>
2234
2275
  `,this.footerCount&&(this.footerCount.textContent="0 results"),this.inputElement&&this.inputElement.setAttribute("aria-expanded","false"))}showErrorState(e){this.clearLoadingInterval(),this.resultsContainer&&(this.resultsContainer.innerHTML=`
2235
2276
  <div class="error">
2236
- <strong>Error:</strong> ${h(e)}
2277
+ <strong>Error:</strong> ${d(e)}
2237
2278
  </div>
2238
2279
  `,this.footerCount&&(this.footerCount.textContent="Error"))}updateTheme(e){const t=e==="light"||e==="dark"||e==="auto"?e:"auto";t==="auto"?this.removeAttribute("theme"):this.setAttribute("theme",t)}lockBodyScroll(){const e=window.scrollY;this.savedBodyStyles={overflow:document.body.style.overflow,position:document.body.style.position,top:document.body.style.top,width:document.body.style.width},this.savedHtmlOverflow=document.documentElement.style.overflow,document.documentElement.style.overflow="hidden",document.body.style.overflow="hidden",document.body.style.position="fixed",document.body.style.top=`-${e}px`,document.body.style.width="100%"}unlockBodyScroll(){if(!this.savedBodyStyles)return;const e=Math.abs(Number.parseInt(document.body.style.top||"0",10));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}cleanup(){this.clearLoadingInterval(),this.currentSearchController&&(this.currentSearchController.abort(),this.currentSearchController=null),this.handleGlobalKeydown&&(document.removeEventListener("keydown",this.handleGlobalKeydown),this.handleGlobalKeydown=null),this.inputElement&&(this.handleInputChange&&this.inputElement.removeEventListener("input",this.handleInputChange),this.handleInputKeydown&&this.inputElement.removeEventListener("keydown",this.handleInputKeydown)),this.backdrop&&this.handleBackdropClick&&this.backdrop.removeEventListener("click",this.handleBackdropClick),this.handleInputChange=null,this.handleInputKeydown=null,this.handleBackdropClick=null,this.client&&this.client.cancelAllRequests()}open(){this.isOpen||(this.isOpen=!0,this.backdrop?.classList.add("open"),this.modal?.classList.add("open"),requestAnimationFrame(()=>{requestAnimationFrame(()=>{this.inputElement?.focus()})}),this.lockBodyScroll(),this.dispatchEvent(m("open",void 0)))}close(){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)))}toggle(){this.isOpen?this.close():this.open()}async search(e){this.isOpen||this.open(),this.inputElement&&(this.inputElement.value=e),await this.performSearch(e)}getResults(){return[...this.results]}isModalOpen(){return this.isOpen}}customElements.get(O)||customElements.define(O,P),p.AISearchClient=T,p.ChatBubbleSnippet=B,p.ChatPageSnippet=N,p.SearchBarSnippet=S,p.SearchModalSnippet=P,p.default=S,Object.defineProperties(p,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}));
2239
2280
  //# sourceMappingURL=search-snippet.umd.js.map