@mixpeek/react-searchkit 0.1.2

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.
@@ -0,0 +1,3 @@
1
+ (function(k,e){typeof exports=="object"&&typeof module<"u"?e(exports,require("react/jsx-runtime"),require("react"),require("react-dom")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime","react","react-dom"],e):(k=typeof globalThis<"u"?globalThis:k||self,e(k.SearchKit={},k.jsxRuntime,k.React,k.ReactDOM))})(this,function(k,e,l,Te){"use strict";function Ae(){return typeof navigator>"u"?"Ctrl K":navigator.platform.toUpperCase().indexOf("MAC")>=0?"⌘K":"Ctrl K"}const ne=({onClick:r,placeholder:t,keyboardShortcut:s})=>{const a=l.useMemo(()=>Ae(),[]);return e.jsxs("button",{className:"mixpeek-search-button",onClick:r,type:"button","aria-label":"Open search",children:[e.jsxs("svg",{className:"mixpeek-search-button-icon",width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[e.jsx("circle",{cx:"11",cy:"11",r:"8"}),e.jsx("line",{x1:"21",y1:"21",x2:"16.65",y2:"16.65"})]}),e.jsx("span",{className:"mixpeek-search-button-text",children:t}),s&&e.jsx("kbd",{className:"mixpeek-search-button-kbd",children:a})]})},le=({value:r,onChange:t,placeholder:s,isLoading:a,onClear:i})=>{const n=l.useRef(null);return l.useEffect(()=>{const c=setTimeout(()=>{var f;(f=n.current)==null||f.focus()},50);return()=>clearTimeout(c)},[]),e.jsxs("div",{className:"mixpeek-search-input-wrapper",children:[e.jsx("div",{className:"mixpeek-search-input-icon",children:e.jsxs("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[e.jsx("circle",{cx:"11",cy:"11",r:"8"}),e.jsx("line",{x1:"21",y1:"21",x2:"16.65",y2:"16.65"})]})}),e.jsx("input",{ref:n,type:"text",className:"mixpeek-search-input",value:r,onChange:c=>t(c.target.value),placeholder:s,autoComplete:"off",autoCorrect:"off",autoCapitalize:"off",spellCheck:!1,role:"combobox","aria-expanded":"true","aria-haspopup":"listbox","aria-label":"Search"}),a&&e.jsx("div",{className:"mixpeek-search-spinner","aria-label":"Loading",children:e.jsx("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",children:e.jsx("path",{d:"M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83"})})}),r&&!a&&e.jsx("button",{className:"mixpeek-search-clear",onClick:i,"aria-label":"Clear search",type:"button",children:e.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[e.jsx("line",{x1:"18",y1:"6",x2:"6",y2:"18"}),e.jsx("line",{x1:"6",y1:"6",x2:"18",y2:"18"})]})})]})},ie=({data:r,onCitationClick:t})=>r.answer?e.jsxs("div",{className:"mixpeek-ai-answer",role:"region","aria-label":"AI Answer",children:[e.jsxs("div",{className:"mixpeek-ai-answer-header",children:[e.jsx("div",{className:"mixpeek-ai-answer-icon",children:e.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[e.jsx("path",{d:"M12 2L2 7l10 5 10-5-10-5z"}),e.jsx("path",{d:"M2 17l10 5 10-5"}),e.jsx("path",{d:"M2 12l10 5 10-5"})]})}),e.jsx("span",{className:"mixpeek-ai-answer-label",children:"AI Answer"}),r.isStreaming&&e.jsx("span",{className:"mixpeek-ai-answer-streaming",children:"Generating..."})]}),e.jsx("div",{className:"mixpeek-ai-answer-text",children:r.answer}),r.citations&&r.citations.length>0&&e.jsxs("div",{className:"mixpeek-ai-answer-citations",children:[e.jsx("span",{className:"mixpeek-ai-answer-citations-label",children:"Sources:"}),r.citations.map((s,a)=>e.jsxs("button",{className:"mixpeek-ai-answer-citation",onClick:()=>t==null?void 0:t(s.resultIndex),type:"button",title:s.text,children:[e.jsx("span",{className:"mixpeek-citation-index",children:s.resultIndex+1}),e.jsx("span",{className:"mixpeek-citation-text",children:s.text})]},a))]})]}):null;function oe(r,t){if(!t.trim()||!r)return r;const s=t.trim().split(/\s+/).filter(n=>n.length>2).map(n=>n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"));if(s.length===0)return r;const a=new RegExp(`(${s.join("|")})`,"gi");return r.split(a).map((n,c)=>a.test(n)?e.jsx("mark",{className:"mixpeek-highlight",children:n},c):n)}function $e(r){if(r.title)return r.title;if(r.page_url)try{const t=new URL(r.page_url);return t.pathname==="/"?t.hostname:t.pathname.split("/").pop()||t.hostname}catch{return r.page_url}return r.content?r.content.slice(0,80):"Untitled"}function je(r){if(r.content)return r.content;for(const t of["description","snippet","summary","text","body"])if(typeof r[t]=="string"&&r[t])return r[t];return""}function Ke(r){return r>=0&&r<=1?`${Math.round(r*100)}%`:r.toFixed(1)}function De(r){return typeof r=="string"?r:typeof r=="number"||typeof r=="boolean"?String(r):r==null?"":JSON.stringify(r)}const Fe=new Set(["id","title","content","page_url","image_url","score","document_id","collection_id","namespace_id"]),ce=({result:r,index:t,query:s,onResultClick:a})=>{const[i,n]=l.useState(!1),[c,f]=l.useState(!1),o=$e(r),h=je(r),d=h.length>200?h.slice(0,200)+"...":h,p=r.document_id||r.id||null,b=l.useMemo(()=>{const x=[];for(const[g,v]of Object.entries(r)){if(Fe.has(g)||g.startsWith("_")||g.startsWith("__")||v==null)continue;const N=De(v);N&&x.push([g,N])}return x},[r]),C=l.useCallback(x=>{a==null||a(r,t),r.page_url&&a&&x.preventDefault()},[r,t,a]),_=l.useCallback(x=>{(x.key==="Enter"||x.key===" ")&&(x.preventDefault(),a==null||a(r,t),r.page_url&&!a&&window.open(r.page_url,"_blank","noopener,noreferrer"))},[r,t,a]),K=l.useCallback(x=>{x.stopPropagation(),x.preventDefault();const g=`${o}${r.page_url?`
2
+ `+r.page_url:""}`;navigator.clipboard.writeText(g).then(()=>{n(!0),setTimeout(()=>n(!1),2e3)}).catch(()=>{})},[o,r.page_url]),E=l.useCallback(x=>{x.stopPropagation(),x.preventDefault(),f(g=>!g)},[]),D=r.page_url?"a":"div",T=r.page_url?{href:r.page_url,target:"_blank",rel:"noopener noreferrer"}:{};return e.jsxs(D,{className:"mixpeek-result-card",onClick:C,onKeyDown:_,tabIndex:0,...T,role:"option","aria-selected":!1,"data-index":t,children:[r.image_url&&e.jsx("div",{className:"mixpeek-result-thumbnail",children:e.jsx("img",{src:r.image_url,alt:"",loading:"lazy",onError:x=>{x.target.style.display="none"}})}),e.jsxs("div",{className:"mixpeek-result-body",children:[e.jsxs("div",{className:"mixpeek-result-header",children:[e.jsx("div",{className:"mixpeek-result-title",children:oe(o,s)}),typeof r.score=="number"&&e.jsx("span",{className:"mixpeek-result-score",children:Ke(r.score)})]}),r.page_url&&e.jsx("div",{className:"mixpeek-result-url",children:r.page_url}),d&&e.jsx("div",{className:"mixpeek-result-content",children:oe(d,s)}),e.jsxs("div",{className:"mixpeek-result-footer",children:[p&&e.jsx("span",{className:"mixpeek-result-ref",title:p,children:p}),b.length>0&&e.jsxs("button",{className:"mixpeek-meta-toggle",onClick:E,type:"button","aria-expanded":c,"aria-label":c?"Hide details":"Show details",children:[e.jsx("svg",{className:`mixpeek-meta-chevron ${c?"mixpeek-meta-chevron-open":""}`,width:"12",height:"12",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:e.jsx("polyline",{points:"9 18 15 12 9 6"})}),"Details"]})]}),c&&b.length>0&&e.jsx("div",{className:"mixpeek-result-metadata",children:b.map(([x,g])=>e.jsxs("div",{className:"mixpeek-meta-row",children:[e.jsx("span",{className:"mixpeek-meta-key",children:x}),e.jsx("span",{className:"mixpeek-meta-value",children:g})]},x))})]}),e.jsx("div",{className:"mixpeek-result-actions",children:e.jsx("button",{className:"mixpeek-result-copy",onClick:K,"aria-label":"Copy link",title:"Copy link",type:"button",children:i?e.jsx("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:e.jsx("polyline",{points:"20 6 9 17 4 12"})}):e.jsxs("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[e.jsx("rect",{x:"9",y:"9",width:"13",height:"13",rx:"2",ry:"2"}),e.jsx("path",{d:"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"})]})})})]})},Be={feature_search:"Search",attribute_filter:"Filter",sort_attribute:"Sort",llm_filter:"LLM Filter",rerank:"Rerank",llm_enrich:"Enrich",mmr:"Diversify",group_by:"Group",limit:"Limit",json_transform:"Transform",agent_search:"Agent",rag_prepare:"RAG",reduce:"Reduce"};function Y(r){return Be[r]||r.replace(/_/g," ").replace(/\b\w/g,t=>t.toUpperCase())}function Ie(r){return r<1e3?`${Math.round(r)}ms`:`${(r/1e3).toFixed(1)}s`}const Oe=({stages:r,isStreaming:t})=>r.length===0?null:e.jsxs("div",{className:"mixpeek-pipeline",role:"status","aria-label":"Pipeline progress",children:[r.map((s,a)=>{var i;return e.jsxs(l.Fragment,{children:[a>0&&e.jsx("div",{className:"mixpeek-pipeline-connector"}),e.jsxs("div",{className:"mixpeek-pipeline-stage","data-status":s.status,title:(i=s.statistics)!=null&&i.duration_ms?`${Y(s.name)}: ${s.documents.length} results in ${Ie(s.statistics.duration_ms)}`:Y(s.name),children:[e.jsxs("div",{className:"mixpeek-pipeline-dot",children:[s.status==="complete"&&e.jsx("svg",{width:"10",height:"10",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"3",strokeLinecap:"round",strokeLinejoin:"round",children:e.jsx("polyline",{points:"20 6 9 17 4 12"})}),s.status==="error"&&e.jsxs("svg",{width:"10",height:"10",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"3",strokeLinecap:"round",strokeLinejoin:"round",children:[e.jsx("line",{x1:"18",y1:"6",x2:"6",y2:"18"}),e.jsx("line",{x1:"6",y1:"6",x2:"18",y2:"18"})]})]}),e.jsx("span",{className:"mixpeek-pipeline-label",children:Y(s.name)}),s.status==="complete"&&e.jsx("span",{className:"mixpeek-pipeline-count",children:s.documents.length})]})]},s.index)}),t&&e.jsx("div",{className:"mixpeek-pipeline-connector mixpeek-pipeline-connector-active"})]}),de=({results:r,stages:t,isStreaming:s,query:a,isLoading:i,onResultClick:n,renderResult:c})=>{const f=l.useRef(null),o=l.useCallback(d=>{if(!f.current)return;const p=f.current.querySelectorAll(".mixpeek-result-card");p[d]&&p[d].scrollIntoView({behavior:"smooth",block:"nearest"})},[]);l.useImperativeHandle(l.createRef(),()=>({scrollToResult:o}),[o]);const h=t.length>0;return i&&r.length===0&&t.length===0?e.jsx("div",{className:"mixpeek-results-loading",children:e.jsx("div",{className:"mixpeek-results-skeleton",children:Array.from({length:3}).map((d,p)=>e.jsxs("div",{className:"mixpeek-skeleton-card",children:[e.jsx("div",{className:"mixpeek-skeleton-line mixpeek-skeleton-title"}),e.jsx("div",{className:"mixpeek-skeleton-line mixpeek-skeleton-url"}),e.jsx("div",{className:"mixpeek-skeleton-line mixpeek-skeleton-content"}),e.jsx("div",{className:"mixpeek-skeleton-line mixpeek-skeleton-content-short"})]},p))})}):r.length===0&&!h?null:e.jsxs("div",{ref:f,children:[h&&e.jsx(Oe,{stages:t,isStreaming:s}),r.length>0&&e.jsx("div",{className:"mixpeek-results-list",role:"listbox","aria-label":"Search results",children:r.map((d,p)=>c?e.jsx("div",{className:"mixpeek-result-custom",role:"option",children:c(d,p)},d.id||p):e.jsx(ce,{result:d,index:p,query:a,onResultClick:n},d.id||p))}),s&&r.length===0&&e.jsx("div",{className:"mixpeek-results-loading",children:e.jsx("div",{className:"mixpeek-results-skeleton",children:Array.from({length:2}).map((d,p)=>e.jsxs("div",{className:"mixpeek-skeleton-card",children:[e.jsx("div",{className:"mixpeek-skeleton-line mixpeek-skeleton-title"}),e.jsx("div",{className:"mixpeek-skeleton-line mixpeek-skeleton-content"}),e.jsx("div",{className:"mixpeek-skeleton-line mixpeek-skeleton-content-short"})]},p))})})]})},he=({query:r})=>e.jsxs("div",{className:"mixpeek-zero-results",role:"status",children:[e.jsx("div",{className:"mixpeek-zero-results-icon",children:e.jsxs("svg",{width:"48",height:"48",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round",children:[e.jsx("circle",{cx:"11",cy:"11",r:"8"}),e.jsx("line",{x1:"21",y1:"21",x2:"16.65",y2:"16.65"}),e.jsx("line",{x1:"8",y1:"11",x2:"14",y2:"11"})]})}),e.jsx("div",{className:"mixpeek-zero-results-title",children:"No results found"}),e.jsxs("div",{className:"mixpeek-zero-results-text",children:["No results for “",e.jsx("strong",{children:r}),"”. Try different keywords or check for typos."]})]}),pe=({theme:r})=>e.jsxs("a",{className:`mixpeek-powered-by${r?` mixpeek-powered-by--${r}`:""}`,href:"https://mxp.co/searchkit",target:"_blank",rel:"noopener noreferrer","aria-label":"Search powered by Mixpeek",children:[e.jsx("span",{className:"mixpeek-powered-by__text",children:"Search by"}),e.jsxs("svg",{className:"mixpeek-powered-by__logo",width:"14",height:"14",viewBox:"0 0 32 32",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",children:[e.jsx("rect",{width:"32",height:"32",rx:"6",fill:"currentColor",fillOpacity:"0.15"}),e.jsx("path",{d:"M8 22V10l5 6 5-6v12",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round"}),e.jsx("path",{d:"M22 10v12",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round"})]}),e.jsx("span",{className:"mixpeek-powered-by__wordmark",children:"Mixpeek"})]}),fe=({query:r})=>{const[t,s]=l.useState(!1),a=l.useCallback(()=>{if(!r.trim())return;const i=new URL(window.location.href);i.searchParams.set("mixpeek_q",r),navigator.clipboard.writeText(i.toString()).then(()=>{s(!0),setTimeout(()=>s(!1),2500)})},[r]);return r.trim()?e.jsx("button",{className:"mixpeek-share-link",onClick:a,type:"button","aria-label":"Copy shareable link",title:"Copy shareable search link",children:t?e.jsxs(e.Fragment,{children:[e.jsx("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:e.jsx("polyline",{points:"20 6 9 17 4 12"})}),e.jsx("span",{children:"Copied!"})]}):e.jsxs(e.Fragment,{children:[e.jsxs("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[e.jsx("path",{d:"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"}),e.jsx("path",{d:"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"})]}),e.jsx("span",{children:"Share"})]})}):null},ue=({config:r})=>e.jsxs("div",{className:"mixpeek-intent-cta",role:"banner",children:[e.jsx("div",{className:"mixpeek-intent-cta-message",children:r.message}),e.jsx("a",{className:"mixpeek-intent-cta-button",href:r.buttonUrl,target:"_blank",rel:"noopener noreferrer",children:r.buttonText})]}),ke=({isOpen:r,onClose:t,query:s,onQueryChange:a,results:i,stages:n,isStreaming:c,isLoading:f,error:o,aiAnswer:h,metadata:d,placeholder:p,showPoweredBy:b,enableShareLinks:C,enableAIAnswer:_,recentSearches:K,onClearRecent:E,onResultClick:D,renderResult:T,ctaConfig:x,theme:g="light"})=>{const v=l.useRef(null),N=l.useRef(null);l.useEffect(()=>{if(!r)return;const y=m=>{if(m.key==="Escape"){m.preventDefault(),t();return}if(m.key==="Tab"&&v.current){const $=v.current.querySelectorAll('input, button, a[href], [tabindex]:not([tabindex="-1"])');if($.length===0)return;const z=$[0],P=$[$.length-1];m.shiftKey&&document.activeElement===z?(m.preventDefault(),P.focus()):!m.shiftKey&&document.activeElement===P&&(m.preventDefault(),z.focus())}};return document.addEventListener("keydown",y),()=>document.removeEventListener("keydown",y)},[r,t]),l.useEffect(()=>{if(r){const y=document.body.style.overflow;return document.body.style.overflow="hidden",()=>{document.body.style.overflow=y}}},[r]);const O=l.useCallback(y=>{y.target===N.current&&t()},[t]),W=l.useCallback(()=>{a("")},[a]),S=l.useCallback(y=>{a(y)},[a]),F=l.useCallback(y=>{var $;const m=($=v.current)==null?void 0:$.querySelector(`[data-index="${y}"]`);m&&(m.scrollIntoView({behavior:"smooth",block:"nearest"}),m.classList.add("mixpeek-result-highlighted"),setTimeout(()=>{m.classList.remove("mixpeek-result-highlighted")},1500))},[]),L=!s&&K.length>0,B=!s&&K.length===0,I=s.trim()&&!f&&!c&&i.length===0&&!o,A=i.length>0||n.length>0,w=_&&h&&h.answer,u=x||(d==null?void 0:d.cta);if(!r)return null;const j=e.jsx("div",{ref:N,className:`mixpeek-search mixpeek-theme-${g} mixpeek-modal-backdrop`,onClick:O,role:"dialog","aria-modal":"true","aria-label":"Search",children:e.jsxs("div",{ref:v,className:"mixpeek-modal",children:[e.jsx("div",{className:"mixpeek-modal-header",children:e.jsx(le,{value:s,onChange:a,placeholder:p,isLoading:f,onClear:W})}),e.jsxs("div",{className:"mixpeek-modal-body",children:[o&&e.jsxs("div",{className:"mixpeek-error",role:"alert",children:[e.jsx("div",{className:"mixpeek-error-icon",children:e.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[e.jsx("circle",{cx:"12",cy:"12",r:"10"}),e.jsx("line",{x1:"12",y1:"8",x2:"12",y2:"12"}),e.jsx("line",{x1:"12",y1:"16",x2:"12.01",y2:"16"})]})}),e.jsx("span",{children:o})]}),B&&e.jsxs("div",{className:"mixpeek-empty-state",children:[e.jsx("div",{className:"mixpeek-empty-state-icon",children:e.jsxs("svg",{width:"32",height:"32",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round",children:[e.jsx("circle",{cx:"11",cy:"11",r:"8"}),e.jsx("line",{x1:"21",y1:"21",x2:"16.65",y2:"16.65"})]})}),e.jsxs("div",{className:"mixpeek-empty-state-text",children:["Type to search or press"," ",e.jsx("kbd",{className:"mixpeek-empty-state-kbd",children:"Esc"})," to close"]})]}),L&&e.jsxs("div",{className:"mixpeek-recent-searches",children:[e.jsxs("div",{className:"mixpeek-recent-header",children:[e.jsx("span",{className:"mixpeek-recent-title",children:"Recent searches"}),e.jsx("button",{className:"mixpeek-recent-clear",onClick:E,type:"button",children:"Clear"})]}),e.jsx("div",{className:"mixpeek-recent-list",children:K.map((y,m)=>e.jsxs("button",{className:"mixpeek-recent-item",onClick:()=>S(y),type:"button",children:[e.jsxs("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[e.jsx("circle",{cx:"12",cy:"12",r:"10"}),e.jsx("polyline",{points:"12 6 12 12 16 14"})]}),e.jsx("span",{children:y})]},m))})]}),w&&e.jsx(ie,{data:h,onCitationClick:F}),A&&e.jsx(de,{results:i,stages:n,isStreaming:c,query:s,isLoading:f,onResultClick:D,renderResult:T}),I&&e.jsx(he,{query:s}),u&&e.jsx(ue,{config:u})]}),e.jsxs("div",{className:"mixpeek-modal-footer",children:[e.jsx("div",{className:"mixpeek-modal-footer-left",children:C&&e.jsx(fe,{query:s})}),e.jsxs("div",{className:"mixpeek-modal-footer-right",children:[e.jsxs("div",{className:"mixpeek-modal-footer-hints",children:[e.jsx("kbd",{className:"mixpeek-kbd-hint",children:"Esc"}),e.jsx("span",{children:"to close"})]}),b&&e.jsx(pe,{})]})]})]})});return Te.createPortal(j,document.body)},We="https://api.mixpeek.com";class me{constructor(t){this.abortController=null,this.projectKey=t.projectKey,this.baseUrl=(t.baseUrl||We).replace(/\/+$/,""),this.retrieverSlug=t.retrieverSlug,this.bearerToken=t.bearerToken}isApiKey(){return this.projectKey.startsWith("ret_sk_")}getHeaders(){const t={"Content-Type":"application/json"};return this.bearerToken?t.Authorization=`Bearer ${this.bearerToken}`:this.isApiKey()&&(t["X-Public-API-Key"]=this.projectKey),t}getEndpoint(){return this.bearerToken?`${this.baseUrl}/v1/retrievers/${encodeURIComponent(this.projectKey)}/execute`:this.isApiKey()?this.retrieverSlug?`${this.baseUrl}/v1/public/retrievers/${encodeURIComponent(this.retrieverSlug)}/execute`:`${this.baseUrl}/v1/public/retrievers/execute`:`${this.baseUrl}/v1/public/retrievers/${encodeURIComponent(this.projectKey)}/execute`}cancel(){this.abortController&&(this.abortController.abort(),this.abortController=null)}async search(t){this.cancel(),this.abortController=new AbortController;const s={inputs:{query:t.query,...t.inputs},settings:{limit:t.limit||10}};t.stream&&(s.stream=!0);const a=await fetch(this.getEndpoint(),{method:"POST",headers:this.getHeaders(),body:JSON.stringify(s),signal:this.abortController.signal});if(!a.ok){const c=await a.text();let f=`Search request failed (${a.status})`;try{const o=JSON.parse(c);o.detail&&(f=typeof o.detail=="string"?o.detail:JSON.stringify(o.detail))}catch{}throw new Error(f)}const i=await a.json();return{results:i.results||i.documents||[],ai_answer:i.ai_answer||null,metadata:i.metadata||null}}async*searchStream(t){this.cancel(),this.abortController=new AbortController;const s={inputs:{query:t.query,...t.inputs},settings:{limit:t.limit||10},stream:!0},a=await fetch(this.getEndpoint(),{method:"POST",headers:{...this.getHeaders(),Accept:"text/event-stream"},body:JSON.stringify(s),signal:this.abortController.signal});if(!a.ok)throw new Error(`Search request failed (${a.status})`);if(!a.body)throw new Error("Streaming not supported");const i=a.body.getReader(),n=new TextDecoder;let c="";try{for(;;){const{done:f,value:o}=await i.read();if(f)break;c+=n.decode(o,{stream:!0});const h=c.split(`
3
+ `);c=h.pop()||"";for(const d of h){const p=d.trim();if(!p||!p.startsWith("data: "))continue;const b=p.slice(6);if(b==="[DONE]")return;try{const C=JSON.parse(b);C.event_type&&(yield C)}catch{}}}}finally{i.releaseLock()}}}const G=new Map,Ue=5*60*1e3;function Pe(r,t,s,a){const i=a&&Object.keys(a).length>0?`:${JSON.stringify(a)}`:"";return`${r}:${t}:${s}${i}`}function ze(){const r=Date.now();for(const[t,s]of G.entries())r-s.timestamp>Ue&&G.delete(t)}function xe(r){const{config:t,filterInputs:s,onSearch:a,onSearchExecuted:i,onZeroResults:n,transformResults:c}=r,[f,o]=l.useState([]),[h,d]=l.useState([]),[p,b]=l.useState(!1),[C,_]=l.useState(!1),[K,E]=l.useState(null),[D,T]=l.useState(null),[x,g]=l.useState(null),v=l.useRef(null),N=l.useRef(null);l.useEffect(()=>(v.current=new me({projectKey:t.projectKey,baseUrl:t.apiBaseUrl,retrieverSlug:t.retrieverSlug,bearerToken:t.bearerToken}),()=>{var S;(S=v.current)==null||S.cancel()}),[t.projectKey,t.apiBaseUrl,t.retrieverSlug,t.bearerToken]);const O=l.useCallback(async S=>{const F=v.current;if(!F)return;const L=S.trim();if(!L){o([]),d([]),E(null),T(null),g(null),b(!1),_(!1);return}const B=Pe(t.projectKey,L,t.maxResults,s);ze();const I=G.get(B);if(I){const A=c?c(I.results):I.results;o(A),T(I.aiAnswer),g(I.metadata),d([]),E(null),b(!1),_(!1);return}b(!0),_(!0),E(null),d([]),o([]),T(null);try{a==null||a(L);let A=[];for await(const u of F.searchStream({query:L,limit:t.maxResults,inputs:s}))switch(u.event_type){case"stage_start":d(j=>{const y=[...j];return y[u.stage_index]={name:u.stage_name||`Stage ${u.stage_index}`,index:u.stage_index,status:"running",documents:[]},y});break;case"stage_complete":d(j=>{const y=[...j],m=y[u.stage_index];return y[u.stage_index]={name:(m==null?void 0:m.name)||u.stage_name||`Stage ${u.stage_index}`,index:u.stage_index,status:"complete",documents:u.documents||[],statistics:u.statistics},y}),u.documents&&o(c?c(u.documents):u.documents);break;case"stage_error":d(j=>{const y=[...j],m=y[u.stage_index];return y[u.stage_index]={name:(m==null?void 0:m.name)||u.stage_name||`Stage ${u.stage_index}`,index:u.stage_index,status:"error",documents:(m==null?void 0:m.documents)||[],error:u.error},y});break;case"execution_complete":A=u.documents||[];break;case"execution_error":E(u.error||"Execution failed"),_(!1),b(!1);return}const w=c?c(A):A;o(w),_(!1),b(!1),E(null),G.set(B,{results:A,aiAnswer:null,metadata:null,timestamp:Date.now()}),i==null||i(L),w.length===0&&(n==null||n(L))}catch(A){if(A instanceof Error&&A.name==="AbortError")return;_(!1),d([]);try{const w=await F.search({query:L,limit:t.maxResults,inputs:s}),u=w.results||[],j=c?c(u):u;o(j),T(w.ai_answer||null),g(w.metadata||null),E(null),G.set(B,{results:u,aiAnswer:w.ai_answer||null,metadata:w.metadata||null,timestamp:Date.now()}),i==null||i(L),j.length===0&&(n==null||n(L))}catch(w){if(w instanceof Error&&w.name==="AbortError")return;const u=w instanceof Error?w.message:"Search failed";E(u),o([]),T(null)}}finally{b(!1),_(!1)}},[t.projectKey,t.maxResults,t.apiBaseUrl,s,a,i,n,c]),W=l.useCallback(async S=>{var F;return N.current&&clearTimeout(N.current),(F=v.current)==null||F.cancel(),new Promise(L=>{N.current=setTimeout(async()=>{await O(S),L()},300)})},[O]);return l.useEffect(()=>()=>{N.current&&clearTimeout(N.current)},[]),{results:f,stages:h,isLoading:p,isStreaming:C,error:K,aiAnswer:D,metadata:x,search:W}}function ge(r){const[t,s]=l.useState(r||{}),a=l.useCallback((o,h)=>{s(d=>{if(h==null||h===""||Array.isArray(h)&&h.length===0){const p={...d};return delete p[o],p}return{...d,[o]:h}})},[]),i=l.useCallback(o=>{s(h=>{const d={...h};return delete d[o],d})},[]),n=l.useCallback(()=>{s({})},[]),c=l.useMemo(()=>Object.keys(t).length>0,[t]),f=l.useCallback(o=>t[o],[t]);return{filterInputs:t,setFilter:a,removeFilter:i,clearFilters:n,hasActiveFilters:c,getFilter:f}}function ye(r){const{enabled:t,onTrigger:s}=r,a=l.useCallback(i=>{if(!t)return;(navigator.platform.toUpperCase().indexOf("MAC")>=0?i.metaKey:i.ctrlKey)&&i.key==="k"&&(i.preventDefault(),i.stopPropagation(),s())},[t,s]);l.useEffect(()=>{if(t)return document.addEventListener("keydown",a),()=>{document.removeEventListener("keydown",a)}},[t,a])}const be="mixpeek_recent_searches",qe=10;function Je(){try{const r=localStorage.getItem(be);if(!r)return[];const t=JSON.parse(r);return Array.isArray(t)?t.filter(s=>typeof s=="object"&&s!==null&&"query"in s&&"timestamp"in s&&typeof s.query=="string"&&typeof s.timestamp=="number"):[]}catch{return[]}}function ve(r){try{localStorage.setItem(be,JSON.stringify(r))}catch{}}function we(){const[r,t]=l.useState([]);l.useEffect(()=>{t(Je())},[]);const s=l.useCallback(i=>{const n=i.trim();n&&t(c=>{const f=c.filter(h=>h.query.toLowerCase()!==n.toLowerCase()),o=[{query:n,timestamp:Date.now()},...f].slice(0,qe);return ve(o),o})},[]),a=l.useCallback(()=>{t([]),ve([])},[]);return{recentSearches:r.map(i=>i.query),addSearch:s,clearRecentSearches:a}}const Z=l.createContext(null);function Ne(){const r=l.useContext(Z);if(!r)throw new Error("useSearchKit must be used within a SearchKit component");return r}const He=Ne,Q=({projectKey:r,placeholder:t="Search...",maxResults:s=10,theme:a="auto",accentColor:i="#6366f1",position:n="modal",keyboardShortcut:c=!0,showPoweredBy:f=!0,enableShareLinks:o=!1,enableAIAnswer:h=!1,onSearch:d,onResultClick:p,onZeroResults:b,transformResults:C,renderResult:_,retrieverSlug:K,bearerToken:E,apiBaseUrl:D="https://api.mixpeek.com",className:T,defaultOpen:x=!1,ctaConfig:g,defaultFilters:v,onFilterChange:N})=>{const[O,W]=l.useState(x),[S,F]=l.useState(""),L=l.useMemo(()=>({projectKey:r,retrieverSlug:K,bearerToken:E,apiBaseUrl:D,maxResults:s,theme:a,accentColor:i,placeholder:t,showPoweredBy:f,enableShareLinks:o,enableAIAnswer:h,position:n}),[r,K,E,D,s,a,i,t,f,o,h,n]),{recentSearches:B,addSearch:I,clearRecentSearches:A}=we(),{filterInputs:w,setFilter:u,removeFilter:j,clearFilters:y,hasActiveFilters:m}=ge(v),{results:$,stages:z,isLoading:P,isStreaming:ee,error:q,aiAnswer:J,metadata:re,search:H}=xe({config:L,filterInputs:w,onSearch:d,onSearchExecuted:I,onZeroResults:b,transformResults:C});l.useEffect(()=>{S.trim()&&H(S)},[w]),l.useEffect(()=>{N==null||N(w)},[w]);const te=l.useCallback(()=>W(!0),[]),se=l.useCallback(()=>W(!1),[]),ae=l.useCallback(()=>W(M=>!M),[]);ye({enabled:c,onTrigger:ae});const V=l.useCallback(M=>{F(M),M.trim()&&H(M)},[H]);l.useEffect(()=>{if(typeof window>"u")return;const U=new URLSearchParams(window.location.search).get("mixpeek_q");U&&(F(U),W(!0),H(U))},[]);const X=l.useMemo(()=>a==="auto"?typeof window>"u"?"light":window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light":a,[a]),Me=l.useMemo(()=>({"--mixpeek-accent":i,"--mixpeek-accent-rgb":Ge(i)}),[i]),Ee=l.useMemo(()=>({query:S,setQuery:V,results:$,stages:z,isLoading:P,isStreaming:ee,error:q,aiAnswer:J,metadata:re,isOpen:O,open:te,close:se,toggle:ae,search:H,recentSearches:B,clearRecentSearches:A,config:L,filterInputs:w,setFilter:u,removeFilter:j,clearFilters:y,hasActiveFilters:m}),[S,V,$,z,P,ee,q,J,re,O,te,se,ae,H,B,A,L,w,u,j,y,m]);return n==="inline"?e.jsx(Z.Provider,{value:Ee,children:e.jsx("div",{className:`mixpeek-search mixpeek-theme-${X} mixpeek-inline ${T||""}`,style:Me,"data-theme":X,children:e.jsxs("div",{className:"mixpeek-inline-container",children:[e.jsx("div",{className:"mixpeek-modal-header",children:e.jsxs("div",{className:"mixpeek-search-input-wrapper",children:[e.jsx("div",{className:"mixpeek-search-input-icon",children:e.jsxs("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[e.jsx("circle",{cx:"11",cy:"11",r:"8"}),e.jsx("line",{x1:"21",y1:"21",x2:"16.65",y2:"16.65"})]})}),e.jsx("input",{type:"text",className:"mixpeek-search-input",value:S,onChange:M=>V(M.target.value),placeholder:t,autoComplete:"off",autoCorrect:"off",autoCapitalize:"off",spellCheck:!1,"aria-label":"Search"}),S&&e.jsx("button",{className:"mixpeek-search-clear",onClick:()=>V(""),"aria-label":"Clear search",type:"button",children:e.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[e.jsx("line",{x1:"18",y1:"6",x2:"6",y2:"18"}),e.jsx("line",{x1:"6",y1:"6",x2:"18",y2:"18"})]})})]})}),e.jsxs("div",{className:"mixpeek-modal-body",children:[q&&e.jsx("div",{className:"mixpeek-error",role:"alert",children:q}),h&&J&&J.answer&&e.jsx("div",{className:"mixpeek-ai-answer",children:e.jsx("div",{className:"mixpeek-ai-answer-text",children:J.answer})}),$.length>0&&e.jsx("div",{className:"mixpeek-results-list",role:"listbox",children:$.map((M,U)=>_?e.jsx("div",{role:"option",children:_(M,U)},M.id||U):e.jsx("div",{children:e.jsx("a",{className:"mixpeek-result-card",href:M.page_url,target:"_blank",rel:"noopener noreferrer",onClick:()=>p==null?void 0:p(M,U),role:"option",children:e.jsxs("div",{className:"mixpeek-result-body",children:[e.jsx("div",{className:"mixpeek-result-title",children:M.title||"Untitled"}),M.content&&e.jsx("div",{className:"mixpeek-result-content",children:M.content.slice(0,200)})]})})},M.id||U))}),S.trim()&&!P&&$.length===0&&!q&&e.jsxs("div",{className:"mixpeek-zero-results",children:[e.jsx("div",{className:"mixpeek-zero-results-title",children:"No results found"}),e.jsxs("div",{className:"mixpeek-zero-results-text",children:["No results for “",S,"”"]})]})]}),f&&e.jsxs("div",{className:"mixpeek-modal-footer",children:[e.jsx("div",{className:"mixpeek-modal-footer-left"}),e.jsx("div",{className:"mixpeek-modal-footer-right",children:e.jsxs("a",{className:"mixpeek-powered-by",href:"https://mxp.co/searchkit",target:"_blank",rel:"noopener noreferrer",children:[e.jsx("span",{className:"mixpeek-powered-by-text",children:"Search by"}),e.jsx("strong",{children:"Mixpeek"})]})})]})]})})}):e.jsx(Z.Provider,{value:Ee,children:e.jsxs("div",{className:`mixpeek-search mixpeek-theme-${X} ${T||""}`,style:Me,"data-theme":X,children:[e.jsx(ne,{onClick:te,placeholder:t,keyboardShortcut:c}),e.jsx(ke,{isOpen:O,onClose:se,query:S,onQueryChange:V,results:$,stages:z,isStreaming:ee,isLoading:P,error:q,aiAnswer:J,metadata:re,placeholder:t,showPoweredBy:f,enableShareLinks:o,enableAIAnswer:h,recentSearches:B,onClearRecent:A,onResultClick:p,renderResult:_,ctaConfig:g,theme:X})]})})};function Ge(r){const t=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(r);return t?`${parseInt(t[1],16)}, ${parseInt(t[2],16)}, ${parseInt(t[3],16)}`:"99, 102, 241"}const Ve=Q,_e=({config:r,value:t,onChange:s})=>{const{field:a,options:i,multiple:n}=r,c=o=>n&&Array.isArray(t)?t.includes(o):t===o,f=o=>{if(n){const h=Array.isArray(t)?t:[];h.includes(o)?s(a,h.filter(d=>d!==o)):s(a,[...h,o])}else s(a,t===o?null:o)};return e.jsx("div",{className:"mixpeek-facet-filter",children:i.map(o=>e.jsxs("label",{className:`mixpeek-facet-filter__option${c(o.value)?" mixpeek-facet-filter__option--active":""}`,children:[e.jsx("input",{type:"checkbox",className:"mixpeek-facet-filter__checkbox",checked:c(o.value),onChange:()=>f(o.value)}),e.jsx("span",{className:"mixpeek-facet-filter__label",children:o.label}),o.count!==void 0&&e.jsx("span",{className:"mixpeek-facet-filter__count",children:o.count})]},o.value))})},Se=({config:r,minValue:t,maxValue:s,onChange:a})=>{const{field:i,min:n,max:c,step:f=1,unit:o=""}=r,[h,d]=l.useState(t??n),[p,b]=l.useState(s??c),C=l.useRef(null);l.useEffect(()=>{d(t??n)},[t,n]),l.useEffect(()=>{b(s??c)},[s,c]);const _=l.useCallback((g,v)=>{C.current&&clearTimeout(C.current),C.current=setTimeout(()=>{a(`min_${i}`,g>n?g:null),a(`max_${i}`,v<c?v:null)},300)},[i,n,c,a]);l.useEffect(()=>()=>{C.current&&clearTimeout(C.current)},[]);const K=g=>{const v=Number(g.target.value),N=Math.min(v,p-f);d(N),_(N,p)},E=g=>{const v=Number(g.target.value),N=Math.max(v,h+f);b(N),_(h,N)},D=g=>`${o}${g}`,T=(h-n)/(c-n)*100,x=(p-n)/(c-n)*100;return e.jsxs("div",{className:"mixpeek-range-filter",children:[e.jsxs("div",{className:"mixpeek-range-filter__values",children:[e.jsx("span",{className:"mixpeek-range-filter__value",children:D(h)}),e.jsx("span",{className:"mixpeek-range-filter__separator",children:"–"}),e.jsx("span",{className:"mixpeek-range-filter__value",children:D(p)})]}),e.jsxs("div",{className:"mixpeek-range-filter__track",children:[e.jsx("div",{className:"mixpeek-range-filter__fill",style:{left:`${T}%`,width:`${x-T}%`}}),e.jsx("input",{type:"range",className:"mixpeek-range-filter__input mixpeek-range-filter__input--min",min:n,max:c,step:f,value:h,onChange:K,"aria-label":`Minimum ${r.label}`}),e.jsx("input",{type:"range",className:"mixpeek-range-filter__input mixpeek-range-filter__input--max",min:n,max:c,step:f,value:p,onChange:E,"aria-label":`Maximum ${r.label}`})]})]})},Ce=({config:r,value:t,onChange:s})=>{const[a,i]=l.useState(t||""),n=l.useRef(null);l.useEffect(()=>{i(t||"")},[t]),l.useEffect(()=>()=>{n.current&&clearTimeout(n.current)},[]);const c=f=>{const o=f.target.value;i(o),n.current&&clearTimeout(n.current),n.current=setTimeout(()=>{s("smart_filter",o||null)},500)};return e.jsxs("div",{className:"mixpeek-smart-filter",children:[e.jsxs("div",{className:"mixpeek-smart-filter__header",children:[e.jsx("svg",{className:"mixpeek-smart-filter__icon",width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:e.jsx("path",{d:"M12 2L9 9l-7 1 5 5-1.5 7L12 18l6.5 4L17 15l5-5-7-1z"})}),e.jsx("span",{className:"mixpeek-smart-filter__label",children:"AI Filter"})]}),e.jsx("input",{type:"text",className:"mixpeek-smart-filter__input",value:a,onChange:c,placeholder:r.placeholder||"Describe what you're looking for...","aria-label":"Smart filter"}),e.jsx("p",{className:"mixpeek-smart-filter__hint",children:"AI will interpret your description to filter results"})]})},R=({label:r,defaultOpen:t=!0,children:s})=>{const[a,i]=l.useState(t);return e.jsxs("div",{className:"mixpeek-filter-section",children:[e.jsxs("button",{className:"mixpeek-filter-section__header",onClick:()=>i(n=>!n),type:"button","aria-expanded":a,children:[e.jsx("span",{className:"mixpeek-filter-section__label",children:r}),e.jsx("svg",{className:`mixpeek-filter-section__chevron${a?" mixpeek-filter-section__chevron--open":""}`,width:"12",height:"12",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:e.jsx("polyline",{points:"9 18 15 12 9 6"})})]}),a&&e.jsx("div",{className:"mixpeek-filter-section__body",children:s})]})},Xe=({config:r,filterInputs:t,onFilterChange:s,onClearAll:a,hasActiveFilters:i})=>e.jsxs("div",{className:"mixpeek-filter-panel",children:[e.jsxs("div",{className:"mixpeek-filter-panel__header",children:[e.jsx("span",{className:"mixpeek-filter-panel__title",children:r.title||"Filters"}),i&&a&&e.jsx("button",{className:"mixpeek-filter-panel__clear",onClick:a,type:"button",children:"Clear all"})]}),e.jsx("div",{className:"mixpeek-filter-panel__body",children:r.filters.map((n,c)=>{switch(n.type){case"facet":return e.jsx(R,{label:n.label,children:e.jsx(_e,{config:n,value:t[n.field],onChange:s})},n.field);case"range":return e.jsx(R,{label:n.label,children:e.jsx(Se,{config:n,minValue:t[`min_${n.field}`],maxValue:t[`max_${n.field}`],onChange:s})},n.field);case"smart":return e.jsx(R,{label:n.label||"Smart Filter",children:e.jsx(Ce,{config:n,value:t.smart_filter,onChange:s})},`smart-${c}`);default:return null}})})]});function Le(){if(typeof document>"u"||typeof window>"u")return;const r=document.querySelectorAll("script[data-project-key]");if(r.length===0)return;const t=window,s=t.React,a=t.ReactDOM;if(!s||!a){console.warn("[@mixpeek/react-searchkit] Auto-init requires React and ReactDOM as globals. Include React before the SearchKit script, or use the npm package instead.");return}r.forEach(i=>{var b;const n=i.getAttribute("data-project-key");if(!n)return;const c=i.getAttribute("data-theme")||"auto",f=i.getAttribute("data-placeholder")||void 0,o=i.getAttribute("data-container")||"mixpeek-search",h=i.getAttribute("data-accent-color")||void 0;let d=document.getElementById(o);d||(d=document.createElement("div"),d.id=o,(b=i.parentNode)==null||b.insertBefore(d,i));const p={projectKey:n,theme:c};f&&(p.placeholder=f),h&&(p.accentColor=h),a.createRoot&&a.createRoot(d).render(s.createElement(Q,p))})}typeof document<"u"&&(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",Le):setTimeout(Le,0)),k.AIAnswer=ie,k.FacetFilter=_e,k.FilterPanel=Xe,k.IntentCTA=ue,k.MixpeekClient=me,k.MixpeekSearch=Ve,k.PoweredBy=pe,k.RangeFilter=Se,k.ResultCard=ce,k.SearchButton=ne,k.SearchInput=le,k.SearchKit=Q,k.SearchModal=ke,k.SearchResults=de,k.ShareLink=fe,k.SmartFilter=Ce,k.ZeroResults=he,k.useFilters=ge,k.useKeyboardShortcut=ye,k.useMixpeekSearch=He,k.useRecentSearches=we,k.useSearch=xe,k.useSearchKit=Ne,Object.defineProperty(k,Symbol.toStringTag,{value:"Module"})});
package/dist/style.css ADDED
@@ -0,0 +1 @@
1
+ .mixpeek-search{--mixpeek-accent: #6366f1;--mixpeek-accent-rgb: 99, 102, 241;--mixpeek-bg: #ffffff;--mixpeek-bg-secondary: #f9fafb;--mixpeek-bg-tertiary: #f3f4f6;--mixpeek-border: #e5e7eb;--mixpeek-border-focus: var(--mixpeek-accent);--mixpeek-text: #111827;--mixpeek-text-secondary: #4b5563;--mixpeek-text-tertiary: #6b7280;--mixpeek-shadow: rgba(0, 0, 0, .2) 0px 12px 28px 0px, rgba(0, 0, 0, .1) 0px 2px 4px 0px, rgba(255, 255, 255, .05) 0px 0px 0px 1px inset;--mixpeek-shadow-sm: 0 1px 3px rgba(0, 0, 0, .1);--mixpeek-radius: 12px;--mixpeek-radius-sm: 8px;--mixpeek-radius-xs: 6px;--mixpeek-backdrop: rgba(15, 23, 42, .6);--mixpeek-highlight-bg: rgba(var(--mixpeek-accent-rgb), .15);--mixpeek-highlight-text: var(--mixpeek-accent);--mixpeek-skeleton-bg: #e5e7eb;--mixpeek-skeleton-shine: #f3f4f6;--mixpeek-error-bg: #fef2f2;--mixpeek-error-text: #dc2626;--mixpeek-error-border: #fecaca;--mixpeek-cta-bg: rgba(var(--mixpeek-accent-rgb), .06);--mixpeek-cta-border: rgba(var(--mixpeek-accent-rgb), .2);font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:14px;line-height:1.5;color:var(--mixpeek-text);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.mixpeek-theme-dark{--mixpeek-bg: #1f2937;--mixpeek-bg-secondary: #111827;--mixpeek-bg-tertiary: #374151;--mixpeek-border: #374151;--mixpeek-text: #f9fafb;--mixpeek-text-secondary: #d1d5db;--mixpeek-text-tertiary: #9ca3af;--mixpeek-shadow: inset 1px 1px 0 0 rgba(255, 255, 255, .06), 0 3px 8px 0 rgba(0, 3, 9, .8);--mixpeek-shadow-sm: 0 1px 3px rgba(0, 0, 0, .3);--mixpeek-backdrop: rgba(0, 0, 0, .6);--mixpeek-skeleton-bg: #374151;--mixpeek-skeleton-shine: #4b5563;--mixpeek-error-bg: #451a1a;--mixpeek-error-text: #f87171;--mixpeek-error-border: #7f1d1d;--mixpeek-cta-bg: rgba(var(--mixpeek-accent-rgb), .1);--mixpeek-cta-border: rgba(var(--mixpeek-accent-rgb), .3)}.mixpeek-search-button{display:inline-flex;align-items:center;gap:8px;padding:8px 14px;min-width:200px;background:var(--mixpeek-bg);border:1px solid var(--mixpeek-border);border-radius:var(--mixpeek-radius-sm);color:var(--mixpeek-text-tertiary);cursor:pointer;font-size:14px;font-family:inherit;transition:border-color .15s ease,box-shadow .15s ease;box-shadow:var(--mixpeek-shadow-sm)}.mixpeek-search-button:hover{border-color:var(--mixpeek-border-focus);box-shadow:0 0 0 3px rgba(var(--mixpeek-accent-rgb),.1)}.mixpeek-search-button:focus-visible{outline:none;border-color:var(--mixpeek-border-focus);box-shadow:0 0 0 3px rgba(var(--mixpeek-accent-rgb),.2)}.mixpeek-search-button:active{transform:scale(.98)}.mixpeek-search-button-icon{flex-shrink:0;opacity:.65}.mixpeek-search-button-text{flex:1;text-align:left}.mixpeek-search-button-kbd{display:inline-flex;align-items:center;justify-content:center;padding:2px 6px;font-size:11px;font-family:inherit;font-weight:500;background:var(--mixpeek-bg-tertiary);border:1px solid var(--mixpeek-border);border-radius:4px;color:var(--mixpeek-text-tertiary);line-height:1.4}.mixpeek-modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:999999;display:flex;align-items:flex-start;justify-content:center;padding-top:min(120px,15vh);background:var(--mixpeek-backdrop);backdrop-filter:none;-webkit-backdrop-filter:none;animation:mixpeek-backdrop-in .15s ease-out}@keyframes mixpeek-backdrop-in{0%{opacity:0}to{opacity:1}}.mixpeek-modal{width:100%;max-width:640px;max-height:min(70vh,600px);margin:0 16px;background:var(--mixpeek-bg);border:1px solid var(--mixpeek-border);border-radius:var(--mixpeek-radius);box-shadow:var(--mixpeek-shadow);display:flex;flex-direction:column;overflow:hidden;animation:mixpeek-modal-in .15s ease-out}@keyframes mixpeek-modal-in{0%{opacity:0;transform:translateY(-8px) scale(.98)}to{opacity:1;transform:translateY(0) scale(1)}}.mixpeek-modal-header{flex-shrink:0;border-bottom:1px solid var(--mixpeek-border)}.mixpeek-search-input-wrapper{display:flex;align-items:center;gap:8px;padding:12px 16px}.mixpeek-search-input-icon{flex-shrink:0;color:var(--mixpeek-text-tertiary);display:flex;align-items:center}.mixpeek-search-input{flex:1;border:none;outline:none;background:transparent;color:var(--mixpeek-text);font-size:16px;font-family:inherit;padding:0;line-height:1.5}.mixpeek-search-input::placeholder{color:var(--mixpeek-text-tertiary)}.mixpeek-search-clear{flex-shrink:0;display:flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;background:var(--mixpeek-bg-tertiary);border:none;border-radius:var(--mixpeek-radius-xs);color:var(--mixpeek-text-secondary);cursor:pointer;transition:background .1s ease,color .1s ease}.mixpeek-search-clear:hover{background:var(--mixpeek-border);color:var(--mixpeek-text)}.mixpeek-search-spinner{flex-shrink:0;display:flex;align-items:center;color:var(--mixpeek-accent);animation:mixpeek-spin 1s linear infinite}@keyframes mixpeek-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.mixpeek-modal-body{flex:1;overflow-y:auto;padding:8px 0;overscroll-behavior:contain}.mixpeek-modal-body::-webkit-scrollbar{width:6px}.mixpeek-modal-body::-webkit-scrollbar-track{background:transparent}.mixpeek-modal-body::-webkit-scrollbar-thumb{background:var(--mixpeek-border);border-radius:3px}.mixpeek-modal-body::-webkit-scrollbar-thumb:hover{background:var(--mixpeek-text-tertiary)}.mixpeek-error{display:flex;align-items:center;gap:8px;margin:8px 16px;padding:10px 14px;background:var(--mixpeek-error-bg);border:1px solid var(--mixpeek-error-border);border-radius:var(--mixpeek-radius-sm);color:var(--mixpeek-error-text);font-size:13px}.mixpeek-error-icon{flex-shrink:0;display:flex}.mixpeek-recent-searches{padding:8px 0}.mixpeek-recent-header{display:flex;align-items:center;justify-content:space-between;padding:4px 16px 8px}.mixpeek-recent-title{font-size:12px;font-weight:500;color:var(--mixpeek-text-tertiary);text-transform:uppercase;letter-spacing:.05em}.mixpeek-recent-clear{padding:2px 8px;background:none;border:none;color:var(--mixpeek-text-tertiary);font-size:12px;font-family:inherit;cursor:pointer;border-radius:var(--mixpeek-radius-xs);transition:color .1s ease,background .1s ease}.mixpeek-recent-clear:hover{color:var(--mixpeek-text);background:var(--mixpeek-bg-tertiary)}.mixpeek-recent-list{display:flex;flex-direction:column}.mixpeek-recent-item{display:flex;align-items:center;gap:10px;width:100%;padding:8px 16px;background:none;border:none;color:var(--mixpeek-text-secondary);font-size:14px;font-family:inherit;text-align:left;cursor:pointer;transition:background .1s ease,color .1s ease}.mixpeek-recent-item:hover{background:var(--mixpeek-bg-secondary);color:var(--mixpeek-text)}.mixpeek-recent-item svg{flex-shrink:0;opacity:.5}.mixpeek-ai-answer{margin:8px 16px;padding:14px 16px;background:var(--mixpeek-cta-bg);border:1px solid var(--mixpeek-cta-border);border-radius:var(--mixpeek-radius-sm)}.mixpeek-ai-answer-header{display:flex;align-items:center;gap:6px;margin-bottom:8px}.mixpeek-ai-answer-icon{display:flex;color:var(--mixpeek-accent)}.mixpeek-ai-answer-label{font-size:12px;font-weight:600;color:var(--mixpeek-accent);text-transform:uppercase;letter-spacing:.05em}.mixpeek-ai-answer-streaming{font-size:12px;color:var(--mixpeek-text-tertiary);animation:mixpeek-pulse 1.5s ease-in-out infinite}@keyframes mixpeek-pulse{0%,to{opacity:1}50%{opacity:.5}}.mixpeek-ai-answer-text{font-size:14px;line-height:1.6;color:var(--mixpeek-text)}.mixpeek-ai-answer-citations{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-top:10px;padding-top:10px;border-top:1px solid var(--mixpeek-cta-border)}.mixpeek-ai-answer-citations-label{font-size:12px;color:var(--mixpeek-text-tertiary);font-weight:500}.mixpeek-ai-answer-citation{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;background:var(--mixpeek-bg);border:1px solid var(--mixpeek-border);border-radius:9999px;font-size:12px;font-family:inherit;color:var(--mixpeek-text-secondary);cursor:pointer;transition:border-color .1s ease,color .1s ease;max-width:200px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mixpeek-ai-answer-citation:hover{border-color:var(--mixpeek-accent);color:var(--mixpeek-accent)}.mixpeek-citation-index{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;background:var(--mixpeek-accent);color:#fff;font-size:10px;font-weight:600;border-radius:50%;flex-shrink:0}.mixpeek-citation-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mixpeek-results-list{padding:0 8px}.mixpeek-results-list>*+*{border-top:1px solid var(--mixpeek-border)}.mixpeek-result-card{display:flex;align-items:flex-start;gap:12px;padding:10px 12px;margin:0;border-radius:var(--mixpeek-radius-sm);text-decoration:none;color:inherit;cursor:pointer;transition:background .1s ease}.mixpeek-result-card:hover{background:var(--mixpeek-bg-secondary)}.mixpeek-result-card:focus-visible{outline:none;background:var(--mixpeek-bg-secondary);box-shadow:inset 0 0 0 2px rgba(var(--mixpeek-accent-rgb),.3)}.mixpeek-result-card.mixpeek-result-highlighted{background:var(--mixpeek-highlight-bg);transition:background .3s ease}.mixpeek-result-thumbnail{flex-shrink:0;width:48px;height:48px;border-radius:var(--mixpeek-radius-xs);overflow:hidden;background:var(--mixpeek-bg-tertiary)}.mixpeek-result-thumbnail img{width:100%;height:100%;object-fit:cover}.mixpeek-result-body{flex:1;min-width:0}.mixpeek-result-title{font-size:14px;font-weight:500;color:var(--mixpeek-text);line-height:1.4;overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}.mixpeek-result-url{font-size:12px;color:var(--mixpeek-accent);margin-top:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mixpeek-result-content{font-size:13px;color:var(--mixpeek-text-secondary);margin-top:4px;line-height:1.5;overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;white-space:pre-line}.mixpeek-result-actions{flex-shrink:0;opacity:0;transition:opacity .1s ease}.mixpeek-result-card:hover .mixpeek-result-actions,.mixpeek-result-card:focus-within .mixpeek-result-actions{opacity:1}@media (hover: none){.mixpeek-result-actions{opacity:1}}.mixpeek-result-copy{display:flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;background:var(--mixpeek-bg-tertiary);border:none;border-radius:var(--mixpeek-radius-xs);color:var(--mixpeek-text-tertiary);cursor:pointer;transition:background .1s ease,color .1s ease}.mixpeek-result-copy:hover{background:var(--mixpeek-border);color:var(--mixpeek-text)}.mixpeek-result-copy:focus-visible{outline:none;box-shadow:0 0 0 2px rgba(var(--mixpeek-accent-rgb),.3)}.mixpeek-highlight{background:var(--mixpeek-highlight-bg);color:var(--mixpeek-highlight-text);padding:1px 2px;border-radius:2px;font-weight:500}.mixpeek-results-loading{padding:8px 16px}.mixpeek-skeleton-card{padding:12px 0}.mixpeek-skeleton-card+.mixpeek-skeleton-card{border-top:1px solid var(--mixpeek-border)}.mixpeek-skeleton-line{height:12px;border-radius:6px;background:linear-gradient(90deg,var(--mixpeek-skeleton-bg) 25%,var(--mixpeek-skeleton-shine) 50%,var(--mixpeek-skeleton-bg) 75%);background-size:200% 100%;animation:mixpeek-shimmer 1.5s ease-in-out infinite}.mixpeek-skeleton-title{width:70%;margin-bottom:8px}.mixpeek-skeleton-url{width:40%;height:10px;margin-bottom:10px}.mixpeek-skeleton-content{width:100%;margin-bottom:6px}.mixpeek-skeleton-content-short{width:60%}@keyframes mixpeek-shimmer{0%{background-position:200% 0}to{background-position:-200% 0}}.mixpeek-empty-state{display:flex;flex-direction:column;align-items:center;text-align:center;padding:40px 16px;color:var(--mixpeek-text-tertiary)}.mixpeek-empty-state-icon{margin-bottom:12px;opacity:.4}.mixpeek-empty-state-text{font-size:14px;line-height:1.5}.mixpeek-empty-state-kbd{display:inline-flex;align-items:center;justify-content:center;padding:2px 6px;font-size:11px;font-weight:500;background:var(--mixpeek-bg-tertiary);border:1px solid var(--mixpeek-border);border-radius:4px;margin:0 2px;vertical-align:middle}.mixpeek-zero-results{display:flex;flex-direction:column;align-items:center;text-align:center;padding:32px 16px}.mixpeek-zero-results-icon{color:var(--mixpeek-text-tertiary);margin-bottom:12px;opacity:.5}.mixpeek-zero-results-title{font-size:15px;font-weight:600;color:var(--mixpeek-text);margin-bottom:4px}.mixpeek-zero-results-text{font-size:13px;color:var(--mixpeek-text-secondary);max-width:300px}.mixpeek-zero-results-text strong{color:var(--mixpeek-text)}.mixpeek-intent-cta{display:flex;align-items:center;justify-content:space-between;gap:12px;margin:8px 16px;padding:12px 16px;background:var(--mixpeek-cta-bg);border:1px solid var(--mixpeek-cta-border);border-radius:var(--mixpeek-radius-sm)}.mixpeek-intent-cta-message{font-size:13px;color:var(--mixpeek-text);flex:1}.mixpeek-intent-cta-button{flex-shrink:0;display:inline-flex;align-items:center;padding:6px 14px;background:var(--mixpeek-accent);color:#fff;font-size:13px;font-weight:500;font-family:inherit;text-decoration:none;border-radius:var(--mixpeek-radius-xs);transition:opacity .15s ease;white-space:nowrap}.mixpeek-intent-cta-button:hover{opacity:.9}.mixpeek-intent-cta-button:focus-visible{outline:none;box-shadow:0 0 0 3px rgba(var(--mixpeek-accent-rgb),.3)}.mixpeek-intent-cta-button:active{transform:scale(.97)}.mixpeek-modal-footer{flex-shrink:0;display:flex;align-items:center;justify-content:space-between;padding:8px 16px;border-top:1px solid var(--mixpeek-border);background:var(--mixpeek-bg-secondary)}.mixpeek-modal-footer-left{display:flex;align-items:center;gap:8px}.mixpeek-modal-footer-right{display:flex;align-items:center;gap:12px}.mixpeek-modal-footer-hints{display:flex;align-items:center;gap:4px;font-size:12px;color:var(--mixpeek-text-tertiary)}.mixpeek-kbd-hint{display:inline-flex;align-items:center;justify-content:center;padding:1px 5px;font-size:11px;font-family:inherit;font-weight:500;background:var(--mixpeek-bg-tertiary);border:1px solid var(--mixpeek-border);border-radius:4px;color:var(--mixpeek-text-tertiary)}.mixpeek-share-link{display:inline-flex;align-items:center;gap:4px;padding:4px 10px;background:none;border:1px solid var(--mixpeek-border);border-radius:var(--mixpeek-radius-xs);color:var(--mixpeek-text-secondary);font-size:12px;font-family:inherit;cursor:pointer;transition:border-color .1s ease,color .1s ease}.mixpeek-share-link:hover{border-color:var(--mixpeek-accent);color:var(--mixpeek-accent)}.mixpeek-share-link:focus-visible{outline:none;box-shadow:0 0 0 2px rgba(var(--mixpeek-accent-rgb),.3)}.mixpeek-powered-by{display:inline-flex;align-items:center;gap:4px;text-decoration:none;font-size:11px;color:var(--mixpeek-text-tertiary);opacity:.7;transition:opacity .15s ease,color .15s ease;padding:4px 6px;margin:-4px -6px;border-radius:var(--mixpeek-radius-xs)}.mixpeek-powered-by:hover{opacity:1;color:var(--mixpeek-text-secondary)}.mixpeek-powered-by:focus-visible{outline:none;opacity:1;box-shadow:0 0 0 2px rgba(var(--mixpeek-accent-rgb),.3)}.mixpeek-powered-by__text{font-weight:400}.mixpeek-powered-by__logo{display:flex;align-items:center;color:var(--mixpeek-text-secondary);flex-shrink:0}.mixpeek-powered-by__wordmark{font-weight:600;color:var(--mixpeek-text-secondary)}.mixpeek-powered-by--dark{color:#ffffff73}.mixpeek-powered-by--dark:hover{color:#ffffffb3}.mixpeek-powered-by--dark .mixpeek-powered-by__logo,.mixpeek-powered-by--dark .mixpeek-powered-by__wordmark{color:#fff9}.mixpeek-powered-by--light{color:#00000059}.mixpeek-powered-by--light:hover{color:#0000008c}.mixpeek-powered-by--light .mixpeek-powered-by__logo,.mixpeek-powered-by--light .mixpeek-powered-by__wordmark{color:#00000080}.mixpeek-filter-panel{border:1px solid var(--mixpeek-border);border-radius:var(--mixpeek-radius-sm);background:var(--mixpeek-bg);overflow:hidden}.mixpeek-filter-panel__header{display:flex;align-items:center;justify-content:space-between;padding:10px 14px;border-bottom:1px solid var(--mixpeek-border);background:var(--mixpeek-bg-secondary)}.mixpeek-filter-panel__title{font-size:12px;font-weight:600;color:var(--mixpeek-text);text-transform:uppercase;letter-spacing:.05em}.mixpeek-filter-panel__clear{padding:2px 8px;background:none;border:none;color:var(--mixpeek-accent);font-size:12px;font-family:inherit;cursor:pointer;border-radius:var(--mixpeek-radius-xs);transition:background .1s ease}.mixpeek-filter-panel__clear:hover{background:rgba(var(--mixpeek-accent-rgb),.08)}.mixpeek-filter-panel__body{padding:0}.mixpeek-filter-section{border-bottom:1px solid var(--mixpeek-border)}.mixpeek-filter-section:last-child{border-bottom:none}.mixpeek-filter-section__header{display:flex;align-items:center;justify-content:space-between;width:100%;padding:10px 14px;background:none;border:none;color:var(--mixpeek-text);font-size:13px;font-weight:500;font-family:inherit;cursor:pointer;transition:background .1s ease;text-align:left}.mixpeek-filter-section__header:hover{background:var(--mixpeek-bg-secondary)}.mixpeek-filter-section__label{flex:1}.mixpeek-filter-section__chevron{flex-shrink:0;color:var(--mixpeek-text-tertiary);transition:transform .15s ease}.mixpeek-filter-section__chevron--open{transform:rotate(90deg)}.mixpeek-filter-section__body{padding:4px 14px 12px}.mixpeek-facet-filter{display:flex;flex-direction:column;gap:2px}.mixpeek-facet-filter__option{display:flex;align-items:center;gap:8px;padding:5px 8px;border-radius:var(--mixpeek-radius-xs);cursor:pointer;transition:background .1s ease;font-size:13px;color:var(--mixpeek-text-secondary)}.mixpeek-facet-filter__option:hover{background:var(--mixpeek-bg-secondary)}.mixpeek-facet-filter__option--active{color:var(--mixpeek-text)}.mixpeek-facet-filter__checkbox{width:16px;height:16px;margin:0;accent-color:var(--mixpeek-accent);cursor:pointer;flex-shrink:0}.mixpeek-facet-filter__label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mixpeek-facet-filter__count{flex-shrink:0;font-size:11px;font-weight:500;color:var(--mixpeek-text-tertiary);padding:0 6px;background:var(--mixpeek-bg-tertiary);border-radius:9999px;line-height:1.6}.mixpeek-range-filter{padding:4px 0}.mixpeek-range-filter__values{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}.mixpeek-range-filter__value{font-size:13px;font-weight:500;color:var(--mixpeek-text);font-variant-numeric:tabular-nums}.mixpeek-range-filter__separator{font-size:12px;color:var(--mixpeek-text-tertiary)}.mixpeek-range-filter__track{position:relative;height:20px;display:flex;align-items:center}.mixpeek-range-filter__fill{position:absolute;top:50%;transform:translateY(-50%);height:4px;background:var(--mixpeek-accent);border-radius:2px;pointer-events:none}.mixpeek-range-filter__input{position:absolute;width:100%;height:20px;margin:0;padding:0;background:transparent;pointer-events:none;-webkit-appearance:none;-moz-appearance:none;appearance:none}.mixpeek-range-filter__input::-webkit-slider-runnable-track{height:4px;background:var(--mixpeek-border);border-radius:2px}.mixpeek-range-filter__input--min::-webkit-slider-runnable-track{background:transparent}.mixpeek-range-filter__input::-webkit-slider-thumb{-webkit-appearance:none;width:16px;height:16px;border-radius:50%;background:var(--mixpeek-accent);border:2px solid var(--mixpeek-bg);box-shadow:0 1px 3px #0003;cursor:pointer;pointer-events:all;margin-top:-6px;position:relative;z-index:1}.mixpeek-range-filter__input::-moz-range-track{height:4px;background:var(--mixpeek-border);border-radius:2px;border:none}.mixpeek-range-filter__input--min::-moz-range-track{background:transparent}.mixpeek-range-filter__input::-moz-range-thumb{width:16px;height:16px;border-radius:50%;background:var(--mixpeek-accent);border:2px solid var(--mixpeek-bg);box-shadow:0 1px 3px #0003;cursor:pointer;pointer-events:all}.mixpeek-smart-filter{padding:2px 0}.mixpeek-smart-filter__header{display:flex;align-items:center;gap:5px;margin-bottom:8px}.mixpeek-smart-filter__icon{color:var(--mixpeek-accent);flex-shrink:0}.mixpeek-smart-filter__label{font-size:11px;font-weight:600;color:var(--mixpeek-accent);text-transform:uppercase;letter-spacing:.05em}.mixpeek-smart-filter__input{width:100%;padding:8px 10px;background:var(--mixpeek-bg-secondary);border:1px solid var(--mixpeek-border);border-radius:var(--mixpeek-radius-xs);color:var(--mixpeek-text);font-size:13px;font-family:inherit;transition:border-color .15s ease,box-shadow .15s ease;outline:none;box-sizing:border-box}.mixpeek-smart-filter__input::placeholder{color:var(--mixpeek-text-tertiary)}.mixpeek-smart-filter__input:focus{border-color:var(--mixpeek-accent);box-shadow:0 0 0 3px rgba(var(--mixpeek-accent-rgb),.1)}.mixpeek-smart-filter__hint{margin:6px 0 0;font-size:11px;color:var(--mixpeek-text-tertiary);line-height:1.4}.mixpeek-inline .mixpeek-inline-container{background:var(--mixpeek-bg);border:1px solid var(--mixpeek-border);border-radius:var(--mixpeek-radius);overflow:hidden;box-shadow:var(--mixpeek-shadow-sm)}.mixpeek-inline .mixpeek-modal-body{max-height:400px;overflow-y:auto}@media (max-width: 640px){.mixpeek-modal-backdrop{padding-top:0;align-items:stretch}.mixpeek-modal{max-width:100%;max-height:100vh;margin:0;border-radius:0;border:none}.mixpeek-search-button{min-width:0}.mixpeek-search-button-text,.mixpeek-search-button-kbd{display:none}.mixpeek-intent-cta{flex-direction:column;text-align:center}}.mixpeek-pipeline{display:flex;align-items:center;gap:0;padding:8px 16px 4px;overflow-x:auto;scrollbar-width:none}.mixpeek-pipeline::-webkit-scrollbar{display:none}.mixpeek-pipeline-stage{display:flex;align-items:center;gap:5px;flex-shrink:0;padding:3px 8px;border-radius:9999px;font-size:11px;font-weight:500;color:var(--mixpeek-text-tertiary);background:var(--mixpeek-bg-secondary);border:1px solid var(--mixpeek-border);transition:all .2s ease}.mixpeek-pipeline-stage[data-status=complete]{color:var(--mixpeek-accent);border-color:rgba(var(--mixpeek-accent-rgb),.25);background:rgba(var(--mixpeek-accent-rgb),.06)}.mixpeek-pipeline-stage[data-status=running]{color:var(--mixpeek-accent);border-color:rgba(var(--mixpeek-accent-rgb),.3);background:rgba(var(--mixpeek-accent-rgb),.08)}.mixpeek-pipeline-stage[data-status=error]{color:var(--mixpeek-error-text);border-color:var(--mixpeek-error-border);background:var(--mixpeek-error-bg)}.mixpeek-pipeline-dot{display:flex;align-items:center;justify-content:center;width:14px;height:14px;border-radius:50%;flex-shrink:0}.mixpeek-pipeline-stage[data-status=running] .mixpeek-pipeline-dot{background:var(--mixpeek-accent);animation:mixpeek-pulse 1.5s ease-in-out infinite}.mixpeek-pipeline-stage[data-status=complete] .mixpeek-pipeline-dot{color:var(--mixpeek-accent)}.mixpeek-pipeline-stage[data-status=error] .mixpeek-pipeline-dot{color:var(--mixpeek-error-text)}.mixpeek-pipeline-stage[data-status=pending] .mixpeek-pipeline-dot{background:var(--mixpeek-border)}.mixpeek-pipeline-label{white-space:nowrap}.mixpeek-pipeline-count{font-size:10px;font-weight:600;padding:0 5px;background:rgba(var(--mixpeek-accent-rgb),.12);color:var(--mixpeek-accent);border-radius:9999px;line-height:1.6}.mixpeek-pipeline-connector{width:16px;height:1px;background:var(--mixpeek-border);flex-shrink:0}.mixpeek-pipeline-connector-active{background:linear-gradient(90deg,rgba(var(--mixpeek-accent-rgb),.4),transparent);animation:mixpeek-pulse 1.5s ease-in-out infinite}.mixpeek-result-header{display:flex;align-items:flex-start;justify-content:space-between;gap:8px}.mixpeek-result-header .mixpeek-result-title{flex:1;min-width:0}.mixpeek-result-score{flex-shrink:0;display:inline-flex;align-items:center;padding:1px 7px;font-size:11px;font-weight:600;font-variant-numeric:tabular-nums;color:var(--mixpeek-accent);background:rgba(var(--mixpeek-accent-rgb),.1);border-radius:9999px;line-height:1.6;white-space:nowrap}.mixpeek-result-footer{display:flex;align-items:center;gap:8px;margin-top:4px}.mixpeek-result-ref{font-size:11px;font-family:ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,monospace;color:var(--mixpeek-text-tertiary);opacity:.7;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:180px}.mixpeek-meta-toggle{display:inline-flex;align-items:center;gap:3px;padding:1px 6px;margin:0;background:none;border:none;font-size:11px;font-family:inherit;color:var(--mixpeek-text-tertiary);cursor:pointer;border-radius:var(--mixpeek-radius-xs);transition:color .1s ease,background .1s ease;flex-shrink:0}.mixpeek-meta-toggle:hover{color:var(--mixpeek-text-secondary);background:var(--mixpeek-bg-tertiary)}.mixpeek-meta-chevron{transition:transform .15s ease}.mixpeek-meta-chevron-open{transform:rotate(90deg)}.mixpeek-result-metadata{margin-top:6px;padding:8px 10px;background:var(--mixpeek-bg-secondary);border:1px solid var(--mixpeek-border);border-radius:var(--mixpeek-radius-xs);animation:mixpeek-meta-expand .15s ease-out}@keyframes mixpeek-meta-expand{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}.mixpeek-meta-row{display:flex;gap:8px;padding:2px 0;font-size:11px;line-height:1.5}.mixpeek-meta-row+.mixpeek-meta-row{border-top:1px solid var(--mixpeek-border);padding-top:3px;margin-top:1px}.mixpeek-meta-key{flex-shrink:0;font-weight:500;color:var(--mixpeek-text-tertiary);min-width:80px;font-family:ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,monospace}.mixpeek-meta-value{color:var(--mixpeek-text-secondary);word-break:break-all;overflow:hidden;text-overflow:ellipsis;max-height:60px}.mixpeek-results-list .mixpeek-result-card{animation:mixpeek-result-in .2s ease-out both}@keyframes mixpeek-result-in{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}.mixpeek-results-list .mixpeek-result-card:nth-child(1){animation-delay:0s}.mixpeek-results-list .mixpeek-result-card:nth-child(2){animation-delay:.03s}.mixpeek-results-list .mixpeek-result-card:nth-child(3){animation-delay:.06s}.mixpeek-results-list .mixpeek-result-card:nth-child(4){animation-delay:.09s}.mixpeek-results-list .mixpeek-result-card:nth-child(5){animation-delay:.12s}.mixpeek-results-list .mixpeek-result-card:nth-child(n+6){animation-delay:.15s}@media print{.mixpeek-modal-backdrop{display:none}}
@@ -0,0 +1,250 @@
1
+ import { ReactNode } from 'react';
2
+
3
+ export type ThemeMode = "light" | "dark" | "auto";
4
+ export type Position = "modal" | "inline";
5
+ export interface FacetOption {
6
+ /** Display label */
7
+ label: string;
8
+ /** Value sent to the API */
9
+ value: string;
10
+ /** Optional count badge */
11
+ count?: number;
12
+ }
13
+ export interface FacetFilterConfig {
14
+ type: "facet";
15
+ /** Field name used as the input key (e.g. "category") */
16
+ field: string;
17
+ /** Display label */
18
+ label: string;
19
+ /** Available options */
20
+ options: FacetOption[];
21
+ /** Allow multiple selections (default: false) */
22
+ multiple?: boolean;
23
+ }
24
+ export interface RangeFilterConfig {
25
+ type: "range";
26
+ /** Field name prefix — emits min_<field> and max_<field> */
27
+ field: string;
28
+ /** Display label */
29
+ label: string;
30
+ /** Minimum value */
31
+ min: number;
32
+ /** Maximum value */
33
+ max: number;
34
+ /** Step increment (default: 1) */
35
+ step?: number;
36
+ /** Unit prefix for display (e.g. "$") */
37
+ unit?: string;
38
+ }
39
+ export interface SmartFilterConfig {
40
+ type: "smart";
41
+ /** Display label */
42
+ label?: string;
43
+ /** Placeholder text */
44
+ placeholder?: string;
45
+ }
46
+ export type FilterConfig = FacetFilterConfig | RangeFilterConfig | SmartFilterConfig;
47
+ export interface FilterPanelConfig {
48
+ /** Panel title */
49
+ title?: string;
50
+ /** Filter definitions */
51
+ filters: FilterConfig[];
52
+ }
53
+ export interface SearchKitProps {
54
+ /** Project key: either a `ret_sk_` API key or a public retriever slug name */
55
+ projectKey: string;
56
+ /** Placeholder text for the search input */
57
+ placeholder?: string;
58
+ /** Maximum number of results to show */
59
+ maxResults?: number;
60
+ /** Color theme */
61
+ theme?: ThemeMode;
62
+ /** Accent color for highlights and interactive elements */
63
+ accentColor?: string;
64
+ /** Whether to display as a modal or inline */
65
+ position?: Position;
66
+ /** Keyboard shortcut to open search. Set false to disable. Default: true (Cmd+K / Ctrl+K) */
67
+ keyboardShortcut?: boolean;
68
+ /** Show "Search by Mixpeek" badge */
69
+ showPoweredBy?: boolean;
70
+ /** Enable shareable search links via query params */
71
+ enableShareLinks?: boolean;
72
+ /** Enable AI answer panel (requires agent_search stage in retriever) */
73
+ enableAIAnswer?: boolean;
74
+ /** Callback when a search is performed */
75
+ onSearch?: (query: string) => void;
76
+ /** Callback when a result is clicked */
77
+ onResultClick?: (result: SearchResult, index: number) => void;
78
+ /** Callback when zero results are returned */
79
+ onZeroResults?: (query: string) => void;
80
+ /** Transform results before rendering */
81
+ transformResults?: (results: SearchResult[]) => SearchResult[];
82
+ /** Custom result renderer */
83
+ renderResult?: (result: SearchResult, index: number) => ReactNode;
84
+ /** When using a ret_sk_ key, the public retriever slug for the endpoint URL */
85
+ retrieverSlug?: string;
86
+ /**
87
+ * Bearer token for private API access (local dev / self-hosted).
88
+ * When set, `projectKey` must be a retriever ID (e.g. `ret_9a8a8d76062f87`).
89
+ * Requests go to `/v1/retrievers/{projectKey}/execute` with `Authorization: Bearer <bearerToken>`.
90
+ */
91
+ bearerToken?: string;
92
+ /** Custom API base URL */
93
+ apiBaseUrl?: string;
94
+ /** Additional CSS class name */
95
+ className?: string;
96
+ /** Whether the modal starts open */
97
+ defaultOpen?: boolean;
98
+ /** CTA configuration for enterprise intent capture */
99
+ ctaConfig?: CTAConfig;
100
+ /** Default filter values to apply on mount */
101
+ defaultFilters?: Record<string, unknown>;
102
+ /** Callback when filter inputs change */
103
+ onFilterChange?: (filterInputs: Record<string, unknown>) => void;
104
+ }
105
+ export interface SearchResult {
106
+ /** Unique identifier for the result */
107
+ id?: string;
108
+ /** Display title */
109
+ title?: string;
110
+ /** URL to navigate to on click */
111
+ page_url?: string;
112
+ /** Content snippet or description */
113
+ content?: string;
114
+ /** Image URL for thumbnail */
115
+ image_url?: string;
116
+ /** Relevance score */
117
+ score?: number;
118
+ /** Any additional fields from the retriever */
119
+ [key: string]: unknown;
120
+ }
121
+ export interface AIAnswerData {
122
+ /** The AI-generated answer text */
123
+ answer: string;
124
+ /** Citation references to search results */
125
+ citations?: AIAnswerCitation[];
126
+ /** Whether the answer is still streaming */
127
+ isStreaming?: boolean;
128
+ }
129
+ export interface AIAnswerCitation {
130
+ /** Index of the referenced result in the results array */
131
+ resultIndex: number;
132
+ /** The cited text snippet */
133
+ text: string;
134
+ }
135
+ export interface SearchResponse {
136
+ /** Array of search results */
137
+ results?: SearchResult[];
138
+ /** Alias for results (some endpoints use this) */
139
+ documents?: SearchResult[];
140
+ /** AI-generated answer data */
141
+ ai_answer?: AIAnswerData;
142
+ /** Response metadata */
143
+ metadata?: SearchResponseMetadata;
144
+ }
145
+ export interface SearchResponseMetadata {
146
+ /** Total number of results available */
147
+ total?: number;
148
+ /** Time taken for the search in milliseconds */
149
+ took_ms?: number;
150
+ /** CTA configuration from server */
151
+ cta?: CTAConfig;
152
+ }
153
+ export interface CTAConfig {
154
+ /** CTA message text */
155
+ message: string;
156
+ /** CTA button text */
157
+ buttonText: string;
158
+ /** CTA button link */
159
+ buttonUrl: string;
160
+ }
161
+ export interface SearchContextValue {
162
+ /** Current search query */
163
+ query: string;
164
+ /** Set the search query */
165
+ setQuery: (query: string) => void;
166
+ /** Search results */
167
+ results: SearchResult[];
168
+ /** Whether a search is in progress */
169
+ isLoading: boolean;
170
+ /** Error message if search failed */
171
+ error: string | null;
172
+ /** AI answer data */
173
+ aiAnswer: AIAnswerData | null;
174
+ /** Response metadata */
175
+ metadata: SearchResponseMetadata | null;
176
+ /** Whether the search modal is open */
177
+ isOpen: boolean;
178
+ /** Open the search modal */
179
+ open: () => void;
180
+ /** Close the search modal */
181
+ close: () => void;
182
+ /** Toggle the search modal */
183
+ toggle: () => void;
184
+ /** Perform a search */
185
+ search: (query: string) => Promise<void>;
186
+ /** Pipeline stages (populated during streaming) */
187
+ stages: StageGroup[];
188
+ /** Whether results are currently streaming */
189
+ isStreaming: boolean;
190
+ /** Recent search queries */
191
+ recentSearches: string[];
192
+ /** Clear recent searches */
193
+ clearRecentSearches: () => void;
194
+ /** Configuration */
195
+ config: SearchKitConfig;
196
+ /** Current filter inputs */
197
+ filterInputs: Record<string, unknown>;
198
+ /** Set a filter value (pass null/undefined to remove) */
199
+ setFilter: (field: string, value: unknown) => void;
200
+ /** Remove a filter by field name */
201
+ removeFilter: (field: string) => void;
202
+ /** Clear all active filters */
203
+ clearFilters: () => void;
204
+ /** Whether any filters are currently active */
205
+ hasActiveFilters: boolean;
206
+ }
207
+ export interface SearchKitConfig {
208
+ projectKey: string;
209
+ retrieverSlug?: string;
210
+ bearerToken?: string;
211
+ apiBaseUrl: string;
212
+ maxResults: number;
213
+ theme: ThemeMode;
214
+ accentColor: string;
215
+ placeholder: string;
216
+ showPoweredBy: boolean;
217
+ enableShareLinks: boolean;
218
+ enableAIAnswer: boolean;
219
+ position: Position;
220
+ }
221
+ export interface RecentSearch {
222
+ query: string;
223
+ timestamp: number;
224
+ }
225
+ export interface StageEvent {
226
+ event_type: "stage_start" | "stage_complete" | "stage_error" | "execution_complete" | "execution_error";
227
+ execution_id: string;
228
+ stage_name?: string;
229
+ stage_index?: number;
230
+ total_stages?: number;
231
+ statistics?: StageStatistics;
232
+ documents?: SearchResult[];
233
+ budget_used?: Record<string, unknown>;
234
+ pagination?: Record<string, unknown>;
235
+ error?: string;
236
+ }
237
+ export interface StageStatistics {
238
+ input_count?: number;
239
+ output_count?: number;
240
+ duration_ms?: number;
241
+ efficiency?: number;
242
+ }
243
+ export interface StageGroup {
244
+ name: string;
245
+ index: number;
246
+ status: "pending" | "running" | "complete" | "error";
247
+ documents: SearchResult[];
248
+ statistics?: StageStatistics;
249
+ error?: string;
250
+ }
package/package.json ADDED
@@ -0,0 +1,71 @@
1
+ {
2
+ "name": "@mixpeek/react-searchkit",
3
+ "version": "0.1.2",
4
+ "description": "React component library for multimodal search — stages streaming, AI answers, and composable search UI",
5
+ "main": "dist/searchkit.cjs.js",
6
+ "module": "dist/searchkit.esm.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/searchkit.esm.js",
11
+ "require": "./dist/searchkit.cjs.js",
12
+ "types": "./dist/index.d.ts"
13
+ },
14
+ "./styles.css": "./dist/style.css"
15
+ },
16
+ "bin": {
17
+ "mixpeek-bootstrap": "./scripts/bootstrap.mjs",
18
+ "mixpeek-index": "./scripts/index.mjs"
19
+ },
20
+ "files": [
21
+ "dist",
22
+ "scripts"
23
+ ],
24
+ "sideEffects": [
25
+ "**/*.css"
26
+ ],
27
+ "scripts": {
28
+ "dev": "vite",
29
+ "build": "tsc && vite build",
30
+ "lint": "eslint src --ext .ts,.tsx",
31
+ "typecheck": "tsc --noEmit"
32
+ },
33
+ "peerDependencies": {
34
+ "react": ">=18.0.0",
35
+ "react-dom": ">=18.0.0"
36
+ },
37
+ "devDependencies": {
38
+ "@types/react": "^18.2.0",
39
+ "@types/react-dom": "^18.2.0",
40
+ "@vitejs/plugin-react": "^4.2.0",
41
+ "react": "^18.2.0",
42
+ "react-dom": "^18.2.0",
43
+ "typescript": "^5.3.0",
44
+ "vite": "^5.0.0",
45
+ "vite-plugin-css-injected-by-js": "^3.3.0",
46
+ "vite-plugin-dts": "^3.7.0"
47
+ },
48
+ "keywords": [
49
+ "mixpeek",
50
+ "searchkit",
51
+ "react-searchkit",
52
+ "react",
53
+ "multimodal-search",
54
+ "ai-search",
55
+ "search-component",
56
+ "streaming-search",
57
+ "site-search",
58
+ "cmd-k",
59
+ "semantic-search"
60
+ ],
61
+ "license": "MIT",
62
+ "author": "Mixpeek <hello@mixpeek.com> (https://mixpeek.com)",
63
+ "repository": {
64
+ "type": "git",
65
+ "url": "https://github.com/mixpeek/searchkit.git"
66
+ },
67
+ "homepage": "https://mxp.co/searchkit",
68
+ "bugs": {
69
+ "url": "https://github.com/mixpeek/searchkit/issues"
70
+ }
71
+ }
@@ -0,0 +1,149 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { parseArgs } from "node:util";
4
+
5
+ const USAGE = `
6
+ mixpeek-bootstrap — Scaffold a production retriever with search, filter & RAG stages.
7
+
8
+ Usage:
9
+ mixpeek-bootstrap --api-key <KEY> [--namespace <ns>] [--slug <slug>]
10
+
11
+ Options:
12
+ --api-key Mixpeek API key (required)
13
+ --namespace Namespace for the retriever (default: "default")
14
+ --slug Custom retriever slug (default: "search-widget-<timestamp>")
15
+ --help Show this help message
16
+
17
+ Example:
18
+ mixpeek-bootstrap --api-key sk_proj_abc123 --slug my-site-search
19
+ `;
20
+
21
+ let args;
22
+ try {
23
+ args = parseArgs({
24
+ options: {
25
+ "api-key": { type: "string" },
26
+ namespace: { type: "string", default: "default" },
27
+ slug: { type: "string" },
28
+ help: { type: "boolean", default: false },
29
+ },
30
+ strict: true,
31
+ });
32
+ } catch {
33
+ console.error(USAGE);
34
+ process.exit(1);
35
+ }
36
+
37
+ if (args.values.help) {
38
+ console.log(USAGE);
39
+ process.exit(0);
40
+ }
41
+
42
+ const apiKey = args.values["api-key"];
43
+ if (!apiKey) {
44
+ console.error("Error: --api-key is required.\n");
45
+ console.error(USAGE);
46
+ process.exit(1);
47
+ }
48
+
49
+ const namespace = args.values.namespace || "default";
50
+ const slug = args.values.slug || `search-widget-${Date.now()}`;
51
+
52
+ const retrieverPayload = {
53
+ name: slug,
54
+ namespace,
55
+ stages: [
56
+ {
57
+ name: "feature_search",
58
+ type: "search",
59
+ config: {
60
+ query: "{{INPUT.query}}",
61
+ search_type: "semantic",
62
+ top_k: 20,
63
+ filters: {},
64
+ },
65
+ },
66
+ {
67
+ name: "attribute_filter",
68
+ type: "filter",
69
+ config: {
70
+ conditions: [
71
+ {
72
+ field: "domain",
73
+ operator: "eq",
74
+ value: "{{INPUT.domain}}",
75
+ optional: true,
76
+ },
77
+ {
78
+ field: "category",
79
+ operator: "in",
80
+ value: "{{INPUT.category}}",
81
+ optional: true,
82
+ },
83
+ {
84
+ field: "price",
85
+ operator: "gte",
86
+ value: "{{INPUT.min_price}}",
87
+ optional: true,
88
+ },
89
+ {
90
+ field: "price",
91
+ operator: "lte",
92
+ value: "{{INPUT.max_price}}",
93
+ optional: true,
94
+ },
95
+ {
96
+ field: "_llm_filter",
97
+ operator: "llm",
98
+ value: "{{INPUT.smart_filter}}",
99
+ optional: true,
100
+ },
101
+ ],
102
+ },
103
+ },
104
+ {
105
+ name: "rag_prepare",
106
+ type: "transform",
107
+ config: {
108
+ format: "markdown",
109
+ include_citations: true,
110
+ max_tokens: 4000,
111
+ },
112
+ },
113
+ ],
114
+ };
115
+
116
+ const BASE_URL = "https://api.mixpeek.com";
117
+
118
+ async function createRetriever() {
119
+ console.log(`Creating retriever "${slug}" in namespace "${namespace}"...`);
120
+
121
+ const response = await fetch(`${BASE_URL}/v1/retrievers`, {
122
+ method: "POST",
123
+ headers: {
124
+ "Content-Type": "application/json",
125
+ Authorization: `Bearer ${apiKey}`,
126
+ },
127
+ body: JSON.stringify(retrieverPayload),
128
+ });
129
+
130
+ if (!response.ok) {
131
+ const body = await response.text();
132
+ console.error(`Failed to create retriever (${response.status}):`);
133
+ console.error(body);
134
+ process.exit(1);
135
+ }
136
+
137
+ const data = await response.json();
138
+ const retrieverSlug = data.slug || data.name || slug;
139
+
140
+ console.log("\nRetriever created successfully!");
141
+ console.log(` Slug: ${retrieverSlug}`);
142
+ console.log(` Namespace: ${namespace}`);
143
+ console.log(` Stages: feature_search → attribute_filter → rag_prepare`);
144
+ console.log(`\nUsage with SearchKit:\n`);
145
+ console.log(` <SearchKit projectKey="${retrieverSlug}" />`);
146
+ console.log("");
147
+ }
148
+
149
+ createRetriever();