@magicx-eng/ai-autocomplete-react 0.1.12 → 0.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +6 -6
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +5 -5
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var xe=Object.defineProperty;var tt=Object.getOwnPropertyDescriptor;var ot=Object.getOwnPropertyNames;var nt=Object.prototype.hasOwnProperty;var rt=(e,n)=>{for(var t in n)xe(e,t,{get:n[t],enumerable:!0})},it=(e,n,t,o)=>{if(n&&typeof n=="object"||typeof n=="function")for(let r of ot(n))!nt.call(e,r)&&r!==t&&xe(e,r,{get:()=>n[r],enumerable:!(o=tt(n,r))||o.enumerable});return e};var at=e=>it(xe({},"__esModule",{value:!0}),e);var bt={};rt(bt,{AIAutocomplete:()=>Be,AIAutocompleteDropdown:()=>se,useAIAutocomplete:()=>pe});module.exports=at(bt);var F=require("react");if(typeof document<"u"&&!document.getElementById("ac-style-cc65f4cc")){let e=document.createElement("style");e.id="ac-style-cc65f4cc",e.textContent=`.AIAutocomplete-module_container_KKjFU {
|
|
2
2
|
position: relative;
|
|
3
3
|
font-family: "IBM Plex Sans", sans-serif;
|
|
4
4
|
}
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
.AIAutocomplete-module_submitButton_sl1Mi:hover {
|
|
87
87
|
opacity: 0.85;
|
|
88
88
|
}
|
|
89
|
-
`,document.head.appendChild(e)}var
|
|
89
|
+
`,document.head.appendChild(e)}var Q={container:"AIAutocomplete-module_container_KKjFU",inputWrapper:"AIAutocomplete-module_inputWrapper_FLq1b",editorArea:"AIAutocomplete-module_editorArea_7rBWq",sizerContent:"AIAutocomplete-module_sizerContent_DQgmV",sizerText:"AIAutocomplete-module_sizerText_iZIMK",placeholderText:"AIAutocomplete-module_placeholderText_K3ayy",textarea:"AIAutocomplete-module_textarea_eyn6A",submitButton:"AIAutocomplete-module_submitButton_sl1Mi"};if(typeof document<"u"&&!document.getElementById("ac-style-2eef895d")){let e=document.createElement("style");e.id="ac-style-2eef895d",e.textContent=`.AIAutocompleteDropdown-module_dropdown_yz2KC {
|
|
90
90
|
position: absolute;
|
|
91
91
|
left: 0;
|
|
92
92
|
right: 0;
|
|
@@ -105,7 +105,7 @@
|
|
|
105
105
|
opacity: 1;
|
|
106
106
|
pointer-events: auto;
|
|
107
107
|
}
|
|
108
|
-
`,document.head.appendChild(e)}var
|
|
108
|
+
`,document.head.appendChild(e)}var Ae={dropdown:"AIAutocompleteDropdown-module_dropdown_yz2KC",visible:"AIAutocompleteDropdown-module_visible_QCoXj"};if(typeof document<"u"&&!document.getElementById("ac-style-d91f2b06")){let e=document.createElement("style");e.id="ac-style-d91f2b06",e.textContent=`.SuggestionGrid-module_grid_jvaPb {
|
|
109
109
|
display: grid;
|
|
110
110
|
grid-template-columns: 1fr 1fr;
|
|
111
111
|
gap: 12px 18px;
|
|
@@ -128,7 +128,7 @@
|
|
|
128
128
|
background: rgba(255, 255, 255, 0.3);
|
|
129
129
|
border-radius: 3px;
|
|
130
130
|
}
|
|
131
|
-
`,document.head.appendChild(e)}var
|
|
131
|
+
`,document.head.appendChild(e)}var Te={grid:"SuggestionGrid-module_grid_jvaPb"};if(typeof document<"u"&&!document.getElementById("ac-style-f6bdc634")){let e=document.createElement("style");e.id="ac-style-f6bdc634",e.textContent=`.SuggestionItem-module_item_d4vpD {
|
|
132
132
|
display: flex;
|
|
133
133
|
align-items: center;
|
|
134
134
|
font-family: "IBM Plex Sans", sans-serif;
|
|
@@ -169,7 +169,7 @@
|
|
|
169
169
|
margin-left: 6px;
|
|
170
170
|
opacity: 0.5;
|
|
171
171
|
}
|
|
172
|
-
`,document.head.appendChild(e)}var
|
|
172
|
+
`,document.head.appendChild(e)}var J={item:"SuggestionItem-module_item_d4vpD",fadeIn:"SuggestionItem-module_fadeIn_I8u35",tappable:"SuggestionItem-module_tappable_70KcX",nonTappable:"SuggestionItem-module_nonTappable_xSZM-",highlighted:"SuggestionItem-module_highlighted_Hb0SU",tag:"SuggestionItem-module_tag_e3Fwe"};var ae=require("react/jsx-runtime");function Ee({option:e,isHighlighted:n,onSelect:t,onHighlight:o,id:r}){let i=[J.item,n?J.highlighted:"",e.is_tappable?J.tappable:J.nonTappable].filter(Boolean).join(" ");return(0,ae.jsxs)("div",{id:r,role:"option","aria-selected":n,className:i,tabIndex:e.is_tappable?0:-1,onClick:()=>e.is_tappable&&t(e),onKeyDown:s=>{e.is_tappable&&(s.key==="Enter"||s.key===" ")&&(s.preventDefault(),t(e))},onMouseEnter:o,children:[e.icon?`${e.icon} ${e.text}`:e.text,e.tag&&(0,ae.jsx)("span",{className:J.tag,children:e.tag})]})}var _e=require("react/jsx-runtime");function Le({options:e,activeIndex:n,onSelect:t,onHighlight:o,listboxId:r}){return(0,_e.jsx)("div",{className:Te.grid,children:e.map((i,s)=>(0,_e.jsx)(Ee,{option:i,isHighlighted:s===n,onSelect:t,onHighlight:()=>o(s),id:`${r}-option-${s}`},i.text))})}var ve=require("react/jsx-runtime");function se({suggestions:e,activeIndex:n,onSelect:t,onHighlight:o,isOpen:r,id:i,className:s}){let m=e[0]?.options??[],c=r&&m.length>0;return(0,ve.jsx)("div",{id:i,role:"listbox",className:`${Ae.dropdown} ${c?Ae.visible:""} ${s??""}`,onMouseDown:u=>u.preventDefault(),children:m.length>0&&(0,ve.jsx)(Le,{options:m,activeIndex:n,onSelect:t,onHighlight:o,listboxId:i})})}if(typeof document<"u"&&!document.getElementById("ac-style-b745b4fb")){let e=document.createElement("style");e.id="ac-style-b745b4fb",e.textContent=`.PillList-module_list_qvLqO {
|
|
173
173
|
position: relative;
|
|
174
174
|
z-index: 1;
|
|
175
175
|
pointer-events: auto;
|
|
@@ -211,5 +211,5 @@
|
|
|
211
211
|
opacity: 0;
|
|
212
212
|
}
|
|
213
213
|
}
|
|
214
|
-
`,document.head.appendChild(e)}var ie={list:"PillList-module_list_qvLqO",pill:"PillList-module_pill_osSyz",fadeIn:"PillList-module_fadeIn_Aezob",active:"PillList-module_active_Oll--"};var _e=require("react/jsx-runtime");function it(e){return e===0?.4:e===1?.3:.15}function Ee({pills:e,activePillIndex:r,onSelectPill:t}){return(0,_e.jsx)("span",{className:ie.list,children:e.map((n,o)=>(0,_e.jsx)("button",{type:"button",className:`${ie.pill} ${o===r?ie.active:""}`,style:{opacity:it(o)},onClick:()=>t(o),children:n.text},`${n.type}-${n.text}`))})}var p=require("react");function ae(e,r){if(!e)return[];let t=r.trimStart();if(!t)return e;let n=t.toLowerCase();return e.filter(o=>!o.is_tappable||o.text.toLowerCase().includes(n))}function Y(e,r){if(!e)return null;let t=r.trim();if(!t)return null;let n=t.toLowerCase();return e.find(o=>o.is_tappable&&o.text.toLowerCase()===n)??null}function Le(e,r){let t=[],n=0;for(let i of r){let s=e.indexOf(i.text,n);s!==-1&&(s>n&&t.push({type:"text",value:e.slice(n,s)}),t.push({type:"completed",value:i.text,param:i}),n=s+i.text.length)}let o=e.slice(n);return o&&t.push({type:"text",value:o}),t}function Ue(e,r){let t=[],n=[],o=0;for(let i of r){let s=e.indexOf(i.text,o);s===-1?n.push(i):(t.push(i),o=s+i.text.length)}return{valid:t,invalid:n}}var R=require("react");var at="0.1.12",Ke=!1;function st(){return crypto.randomUUID()}function lt(e,r){return{placeholder:e.placeholder,type:e.type,...r&&{text:e.text},kind:e.kind}}async function De(e,r,t){let n=t?.apiConfig,o=n?.apiKey??"";!o&&!Ke&&(Ke=!0,console.warn("[AIAutocomplete] No apiKey in apiConfig. Requests will be sent without an Authorization header."));let i=n?.authScheme??"Bearer",s=!t?.maskCompletedText,b=r.find(u=>u.type==="contact"&&u.metadata?.contact_account_count)?.metadata?.contact_account_count,d=typeof b=="number"?b:void 0,f={data:{raw_query:e,completed_params:r.map(u=>lt(u,s)),...d!=null&&{contact_account_count:d}},meta:{request_id:st(),request_at:new Date().toISOString(),language:typeof navigator<"u"?navigator.language:"en-US",client_version:at}},c={"Content-Type":"application/json",...n?.appIdentifier&&{"X-App-Identifier":n.appIdentifier},...n?.headers};o&&(c.Authorization=i==="Basic"?`Basic ${btoa(o)}`:`Bearer ${o}`);let h=await fetch(n?.endpoint??"/ac/suggest",{method:"POST",headers:c,body:JSON.stringify(f),signal:t?.signal});if(!h.ok)throw new Error(`API error: ${h.status} ${h.statusText}`);return h.json()}function J(e,r){let t=e,n={},o=[];for(let i of r){let s=(n[i.type]??0)+1;n[i.type]=s;let d=`{{${i.type.toUpperCase().replace(/\s+/g,"_")}_${s}}}`,f=t.indexOf(i.text);f!==-1&&(t=t.slice(0,f)+d+t.slice(f+i.text.length)),o.push({...i,placeholder:d})}return{rawQuery:t,completedParams:o}}function ze(e,r){return r?e.map(t=>{let n=r[t.type];if(!n)return t;let o=n("");if(o.length===0)return t;let i=new Set(o.map(b=>b.text)),s=(t.options??[]).filter(b=>!i.has(b.text));return{...t,options:[...o,...s]}}):e}var ct=100,ut=300,pt=2;function je({textRef:e,suggestionsRef:r,filterBaseRef:t,maskCompletedTextRef:n,apiConfigRef:o,optionOverridesRef:i,onErrorRef:s,setCompletedParams:b,setSuggestions:d,setActiveDropdownIndex:f}){let[c,h]=(0,R.useState)(!1),[u,S]=(0,R.useState)(null),[w,y]=(0,R.useState)(!1),P=(0,R.useRef)(0),k=(0,R.useRef)(null),g=(0,R.useRef)(""),m=(0,R.useCallback)(async(a,l)=>{k.current?.abort();let A=new AbortController;k.current=A;let C=++P.current,z=e.current.length;r.current.some(I=>I.type!=="placeholder")||h(!0),S(null);try{let I=await De(a,l,{maskCompletedText:n.current,signal:A.signal,apiConfig:o.current});if(C!==P.current)return;let K=ze(I.data.suggestions??[],i.current);y(I.data.is_ready??!1),g.current=a;let B=I.data.input??[],E=B[B.length-1],M=e.current;if(E?.state==="in_progress"){let N=M.toLowerCase().lastIndexOf(E.text.toLowerCase());N!==-1?t.current=N:t.current=z}else t.current=z;let L=K.filter(N=>N.type!=="placeholder")[0];if(L){let N=M.slice(t.current),H=Y(L.options,N);H&&(b(W=>[...W,{id:crypto.randomUUID(),placeholder:"",type:L.type,text:H.text,kind:H.kind,suggestionType:L.type,suggestionPlaceholder:L.text,options:L.options??[],metadata:H.metadata}]),K=K.filter(W=>W!==L))}d(K),h(!1),f(-1)}catch(I){if(C===P.current){let K=I instanceof Error?I:new Error(String(I));S(K),h(!1),s.current?.(K)}}},[e,r,t,n,o,i,s,b,d,f]);return(0,R.useEffect)(()=>(m("",[]),()=>{k.current?.abort()}),[m]),{doFetch:m,isLoading:c,error:u,isReady:w,lastRawQueryRef:g}}function Fe({text:e,completedParams:r,doFetch:t,filterBaseRef:n,skipNextFetchRef:o,suggestionsRef:i,lastRawQueryRef:s}){let b=(0,R.useRef)(null),d=(0,R.useRef)(null),f=(0,R.useRef)(!0);(0,R.useEffect)(()=>{b.current&&clearTimeout(b.current),d.current&&clearTimeout(d.current);let c=h=>{if(o.current)return o.current=!1,!1;if(!e&&r.length===0)return f.current?(t("",[]),!0):(f.current=!0,!1);let u=e.slice(n.current),y=i.current.filter(z=>z.type!=="placeholder")[0],k=(y?ae(y.options,u):[]).filter(z=>z.is_tappable),g=y?Y(y.options,u)!==null:!1,m=u.trim().length>0;if(k.length>0&&!g&&m)return!1;let{rawQuery:a,completedParams:l}=J(e,r),A=a.length<s.current.length,C=Math.abs(a.length-s.current.length);return A||C>=h?(t(a,l),!0):!1};return b.current=setTimeout(()=>{c(pt)&&d.current&&clearTimeout(d.current)},ct),d.current=setTimeout(()=>c(1),ut),()=>{b.current&&clearTimeout(b.current),d.current&&clearTimeout(d.current)}},[e,r,t,n,o,i,s])}var Pe=require("react");function qe({activeDropdownIndex:e,setActiveDropdownIndex:r,filteredOptions:t,selectOption:n,onSubmitRef:o,text:i,completedParams:s,isDropdownOpen:b,hasPlaceholder:d,placeholderText:f,suggestions:c,filterBaseRef:h,columns:u,setText:S,setCompletedParams:w,setSuggestions:y}){let P=(0,Pe.useCallback)(()=>{let g=t.map((a,l)=>a.is_tappable?l:-1).filter(a=>a!==-1),m=Array.from({length:u},()=>[]);for(let a of g)m[a%u].push(a);return m.flat()},[t,u]);return{handleKeyDown:(0,Pe.useCallback)(g=>{let m=P();switch(g.key){case"ArrowDown":{if(g.preventDefault(),m.length===0)return;let a=m.indexOf(e),l=a<m.length-1?a+1:0;r(m[l]);break}case"ArrowUp":{if(g.preventDefault(),m.length===0)return;let a=m.indexOf(e),l=a>0?a-1:m.length-1;r(m[l]);break}case"ArrowRight":{if(e<0)break;if(e%u<u-1){let l=e+1;l<t.length&&t[l]?.is_tappable&&(g.preventDefault(),r(l))}break}case"ArrowLeft":{if(e<0)break;if(e%u>0){let a=e-1;a>=0&&t[a]?.is_tappable&&(g.preventDefault(),r(a))}break}case"Enter":{if(g.preventDefault(),e>=0&&t[e]?.is_tappable)n(t[e]);else if(o.current){let{rawQuery:a,completedParams:l}=J(i,s),A={query:i.trim(),raw_query:a,completed_params:l};o.current(A)}break}case"Tab":{if(e>=0&&t[e]?.is_tappable)g.preventDefault(),n(t[e]);else if(b){let a=t.find(l=>l.is_tappable);a&&(g.preventDefault(),n(a))}else if(!i&&d){g.preventDefault();let a=c.find(l=>l.type==="placeholder");a?(S(f),h.current=f.length,w(l=>[...l,{id:crypto.randomUUID(),placeholder:"",type:a.type,text:f,kind:null,suggestionType:a.type,suggestionPlaceholder:a.text,options:a.options??[]}]),y(l=>l.filter(A=>A!==a))):(S(f),h.current=f.length)}break}case"Escape":r(-1);break}},[e,u,s,t,h,P,d,b,o,f,n,r,w,y,S,c,i]),getTappableIndices:P}}var se=require("react");function Ne({completedParams:e,suggestions:r,setCompletedParams:t,setSuggestions:n,setActiveDropdownIndex:o,filterBaseRef:i,pillTappedRef:s}){let b=(0,se.useCallback)(c=>{let h=r.filter(y=>y.type!=="placeholder");if(c<0||c>=h.length)return;let u=h[c],S=h.filter((y,P)=>P!==c),w=r.filter(y=>y.type==="placeholder");n([...w,u,...S]),s.current=!0,o(-1)},[r,n,o,s]),d=(0,se.useCallback)(()=>{if(e.length===0)return;let c=e[e.length-1],h={type:c.suggestionType,text:c.suggestionPlaceholder,required:!0,options:c.options};t(u=>u.slice(0,-1)),n(u=>[h,...u]),o(-1)},[e,t,n,o]),f=(0,se.useCallback)(c=>{let h={type:c.suggestionType,text:c.suggestionPlaceholder,required:!0,options:c.options};return{apply:u=>{u(S=>{let w=0;for(let y of e){let P=S.indexOf(y.text,w);if(P!==-1){if(y.id===c.id){let k=S.slice(0,P),g=S.slice(P+c.text.length),m=(k+g).replace(/ {2,}/g," ");return i.current=Math.min(i.current,m.length),m}w=P+y.text.length}}return S}),t(S=>S.filter(w=>w.id!==c.id)),n(S=>[h,...S]),o(-1),s.current=!0}}},[e,t,n,o,i,s]);return{setActivePill:b,removeLastParam:d,reEditParam:f}}var dt=0;function mt(){let e=(0,p.useRef)(null);return e.current===null&&(e.current=`:ac-${++dt}:`),e.current}function le({onSubmit:e,onError:r,optionOverrides:t,maskCompletedText:n,placeholder:o,apiConfig:i,columns:s=2,eagerSuggestions:b=!0,value:d,completedParams:f,onChange:c,onParamsChange:h}){let u=d!==void 0,S=f!==void 0,[w,y]=(0,p.useState)(""),[P,k]=(0,p.useState)([]),[g,m]=(0,p.useState)([]),[a,l]=(0,p.useState)(-1),A=u?d:w,C=S?f:P,z=(0,p.useRef)(e);z.current=e;let q=(0,p.useRef)(c);q.current=c;let I=(0,p.useRef)(h);I.current=h;let K=(0,p.useRef)(d);K.current=d;let B=(0,p.useRef)(f);B.current=f;let E=(0,p.useCallback)(x=>{if(typeof x=="function")if(u){let v=x(K.current??"");q.current?.(v)}else y(v=>{let Q=x(v);return q.current?.(Q),Q});else u||y(x),q.current?.(x)},[u]),M=(0,p.useCallback)(x=>{if(typeof x=="function")if(S){let v=x(B.current??[]);I.current?.(v)}else k(v=>{let Q=x(v);return I.current?.(Q),Q});else S||k(x),I.current?.(x)},[S]),D=(0,p.useRef)(r);D.current=r;let L=(0,p.useRef)(t);L.current=t;let N=(0,p.useRef)(n);N.current=n;let H=(0,p.useRef)(i);H.current=i;let W=(0,p.useRef)(A);W.current=A;let ce=(0,p.useRef)(g);ce.current=g;let j=(0,p.useRef)(0),ee=(0,p.useRef)(!1),ve=(0,p.useRef)(!1),ue=mt(),{doFetch:pe,isLoading:Ce,error:Be,isReady:Qe,lastRawQueryRef:de}=je({textRef:W,suggestionsRef:ce,filterBaseRef:j,maskCompletedTextRef:N,apiConfigRef:H,optionOverridesRef:L,onErrorRef:D,setCompletedParams:M,setSuggestions:m,setActiveDropdownIndex:l});Fe({text:A,completedParams:C,doFetch:pe,filterBaseRef:j,skipNextFetchRef:ve,suggestionsRef:ce,lastRawQueryRef:de});let He=(0,p.useMemo)(()=>Le(A,C),[A,C]);j.current=Math.min(j.current,A.length);let me=A.slice(j.current),ge=(0,p.useMemo)(()=>g.filter(v=>v.type==="placeholder").map(v=>v.text).join(" ")||o||"",[g,o]),te=(0,p.useMemo)(()=>g.filter(x=>x.type!=="placeholder"),[g]),_=te[0],Ie=_?t?.[_.type]:void 0,we=_?Ie?Ie(me.trim()):_.options??[]:[],fe=(0,p.useMemo)(()=>ae(we,me),[we,me]),Oe=ge.length>0,be=!Ce&&fe.length>0&&(!!A||ee.current||!Oe),Re=(0,p.useCallback)(x=>{if(!_)return;let v={id:crypto.randomUUID(),placeholder:"",type:_.type,text:x.text,kind:x.kind,suggestionType:_.type,suggestionPlaceholder:_.text,options:_.options??[],metadata:x.metadata},Q=j.current,U=W.current.slice(0,Q);if(U.length>0&&!U.endsWith(" ")){let O=U.split(/\s+/).pop()??"";O&&x.text.toLowerCase().startsWith(O.toLowerCase())&&(U=U.slice(0,U.length-O.length))}let he=U.length>0&&U[U.length-1]!==" ",X=U+(he?" ":"")+x.text+" ";E(X),j.current=X.length,M(O=>[...O,v]),ee.current=!1,l(-1);let V=te.length-1;b&&V>0?(m(O=>O.filter(G=>G!==_)),ve.current=!0):m(O=>O.filter(G=>G.type==="placeholder"))},[_,te,b,E,M]),We=(0,p.useCallback)(x=>{let v=x.target.value,U=v.length>0&&!x.nativeEvent?.isComposing&&v[0]!==v[0].toUpperCase()?v[0].toUpperCase()+v.slice(1):v;E(U),ee.current=!1,l(-1);let{valid:he,invalid:X}=Ue(U,C);if(X.length>0){M(()=>he);for(let V of X)m(O=>[{type:V.suggestionType,text:V.suggestionPlaceholder,required:!0,options:V.options},...O])}if(_&&X.length===0){let V=U.slice(j.current),O=Y(_.options,V);O&&(M(G=>[...G,{id:crypto.randomUUID(),placeholder:"",type:_.type,text:O.text,kind:O.kind,suggestionType:_.type,suggestionPlaceholder:_.text,options:_.options??[],metadata:O.metadata}]),m(G=>G.filter(Je=>Je!==_)))}},[C,_,E,M]),{handleKeyDown:Ve}=qe({activeDropdownIndex:a,setActiveDropdownIndex:l,filteredOptions:fe,selectOption:Re,onSubmitRef:z,text:A,completedParams:C,isDropdownOpen:be,hasPlaceholder:Oe,placeholderText:ge,suggestions:g,filterBaseRef:j,columns:s,setText:E,setCompletedParams:M,setSuggestions:m}),oe=Ne({completedParams:C,suggestions:g,setCompletedParams:M,setSuggestions:m,setActiveDropdownIndex:l,filterBaseRef:j,pillTappedRef:ee}),Ge=(0,p.useCallback)(x=>{oe.reEditParam(x).apply(E)},[oe,E]),Xe=(0,p.useCallback)(()=>{E(""),M(()=>[]),m([]),l(-1),j.current=0,de.current="",pe("",[])},[pe,E,M,de]),Ze=a>=0?`${ue}-option-${a}`:void 0;return{completedParams:C,suggestionPills:te,setActivePill:oe.setActivePill,removeLastParam:oe.removeLastParam,reEditParam:Ge,segments:He,suggestions:g,activeIndex:a,isReady:Qe,isLoading:Ce,error:Be,inputProps:{value:A,placeholder:ge||void 0,onChange:We,onKeyDown:Ve,role:"combobox","aria-expanded":be,"aria-activedescendant":Ze,"aria-autocomplete":"list","aria-controls":ue},reset:Xe,dropdownProps:{suggestions:_?[{..._,options:fe}]:[],activeIndex:a,onSelect:Re,onHighlight:l,isOpen:be,id:ue}}}var T=require("react/jsx-runtime"),$e=(0,F.forwardRef)(function({onSubmit:r,onError:t,optionOverrides:n,maskCompletedText:o,placeholder:i,className:s,apiConfig:b,columns:d,eagerSuggestions:f,value:c,completedParams:h,onChange:u,onParamsChange:S},w){let y=(0,F.useRef)(null),P=(0,F.useRef)(()=>{});(0,F.useEffect)(()=>{y.current?.focus()},[]);let{completedParams:k,suggestionPills:g,setActivePill:m,segments:a,inputProps:l,dropdownProps:A,reset:C}=le({onSubmit:D=>P.current(D),onError:t,optionOverrides:n,maskCompletedText:o,placeholder:i,apiConfig:b,columns:d,eagerSuggestions:f,value:c,completedParams:h,onChange:u,onParamsChange:S});(0,F.useImperativeHandle)(w,()=>({focus:()=>y.current?.focus(),reset:C}),[C]);let z=()=>{y.current?.focus()},q=!!l.value||k.length>0,I=(0,F.useCallback)(()=>{if(!q)return;let{rawQuery:D,completedParams:L}=J(l.value,k);r({query:l.value.trim(),raw_query:D,completed_params:L}),C()},[q,l.value,k,r,C]);P.current=I;let{onChange:K,placeholder:B,...E}=l,M=!l.value;return(0,T.jsxs)("div",{className:`${$.container} ${s??""}`,children:[(0,T.jsx)(re,{...A}),(0,T.jsxs)("div",{className:$.inputWrapper,onClick:z,children:[(0,T.jsxs)("div",{className:$.editorArea,children:[(0,T.jsxs)("div",{className:$.sizerContent,"aria-hidden":"true",children:[M&&B?(0,T.jsxs)("span",{className:$.placeholderText,children:[B," "]}):(0,T.jsxs)("span",{className:$.sizerText,children:[a.map((D,L)=>(0,T.jsx)("span",{children:D.value},`${L}-${D.type}`)),a.length===0&&"\xA0"]})," ",(0,T.jsx)(Ee,{pills:g,activePillIndex:0,onSelectPill:m})]}),(0,T.jsx)("textarea",{ref:y,className:$.textarea,rows:1,onChange:K,...E})]}),(0,T.jsx)("button",{type:"button",className:$.submitButton,disabled:!q,onClick:D=>{D.stopPropagation(),I()},"aria-label":"Submit",children:(0,T.jsx)("svg",{width:"18",height:"18",viewBox:"0 0 18 18",fill:"none",role:"img","aria-label":"Submit",children:(0,T.jsx)("path",{d:"M9 14V4M9 4L4 9M9 4L14 9",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})})]})]})});0&&(module.exports={AIAutocomplete,AIAutocompleteDropdown,useAIAutocomplete});
|
|
214
|
+
`,document.head.appendChild(e)}var le={list:"PillList-module_list_qvLqO",pill:"PillList-module_pill_osSyz",fadeIn:"PillList-module_fadeIn_Aezob",active:"PillList-module_active_Oll--"};var Pe=require("react/jsx-runtime");function st(e){return e===0?.4:e===1?.3:.15}function Ue({pills:e,activePillIndex:n,onSelectPill:t}){return(0,Pe.jsx)("span",{className:le.list,children:e.map((o,r)=>(0,Pe.jsx)("button",{type:"button",className:`${le.pill} ${r===n?le.active:""}`,style:{opacity:st(r)},onClick:()=>t(r),children:o.text},`${o.type}-${o.text}`))})}var p=require("react");function Y(e,n,t){let o=e.slice(n);if(t||n===0||e[n-1]===" ")return o;let r=o.indexOf(" ");return r===-1?"":o.slice(r+1)}function ce(e,n){if(!e)return[];let t=n.trimStart();if(!t)return e;let o=t.toLowerCase();return e.filter(r=>!r.is_tappable||r.text.toLowerCase().includes(o))}function re(e,n){if(!e)return null;let t=n.trim();if(!t)return null;let o=t.toLowerCase();return e.find(r=>r.is_tappable&&r.text.toLowerCase()===o)??null}function De(e,n){let t=[],o=0;for(let i of n){let s=e.indexOf(i.text,o);s!==-1&&(s>o&&t.push({type:"text",value:e.slice(o,s)}),t.push({type:"completed",value:i.text,param:i}),o=s+i.text.length)}let r=e.slice(o);return r&&t.push({type:"text",value:r}),t}function Ke(e,n){let t=[],o=[],r=0;for(let i of n){let s=e.indexOf(i.text,r);s===-1?o.push(i):(t.push(i),r=s+i.text.length)}return{valid:t,invalid:o}}var R=require("react");var lt="0.1.13",je=!1;function ct(){return crypto.randomUUID()}function ut(e,n){return{placeholder:e.placeholder,type:e.type,...n&&{text:e.text},kind:e.kind}}async function ze(e,n,t){let o=t?.apiConfig,r=o?.apiKey??"";!r&&!je&&(je=!0,console.warn("[AIAutocomplete] No apiKey in apiConfig. Requests will be sent without an Authorization header."));let i=o?.authScheme??"Bearer",s=!t?.maskCompletedText,h=n.find(g=>g.type==="contact"&&g.metadata?.contact_account_count)?.metadata?.contact_account_count,m=typeof h=="number"?h:void 0,c={data:{raw_query:e,completed_params:n.map(g=>ut(g,s)),...m!=null&&{contact_account_count:m}},meta:{request_id:ct(),request_at:new Date().toISOString(),language:typeof navigator<"u"?navigator.language:"en-US",client_version:lt}},u={"Content-Type":"application/json",...o?.appIdentifier&&{"X-App-Identifier":o.appIdentifier},...o?.headers};r&&(u.Authorization=i==="Basic"?`Basic ${btoa(r)}`:`Bearer ${r}`);let y=await fetch(o?.endpoint??"/ac/suggest",{method:"POST",headers:u,body:JSON.stringify(c),signal:t?.signal});if(!y.ok)throw new Error(`API error: ${y.status} ${y.statusText}`);return y.json()}function ee(e,n){let t=e,o={},r=[];for(let i of n){let s=(o[i.type]??0)+1;o[i.type]=s;let m=`{{${i.type.toUpperCase().replace(/\s+/g,"_")}_${s}}}`,c=t.indexOf(i.text);c!==-1&&(t=t.slice(0,c)+m+t.slice(c+i.text.length)),r.push({...i,placeholder:m})}return{rawQuery:t,completedParams:r}}function Fe(e,n){return n?e.map(t=>{let o=n[t.type];if(!o)return t;let r=o("");if(r.length===0)return t;let i=new Set(r.map(h=>h.text)),s=(t.options??[]).filter(h=>!i.has(h.text));return{...t,options:[...r,...s]}}):e}var pt=100,dt=300,mt=2;function qe({textRef:e,suggestionsRef:n,filterBaseRef:t,filterInProgressRef:o,maskCompletedTextRef:r,apiConfigRef:i,optionOverridesRef:s,onErrorRef:h,setCompletedParams:m,setSuggestions:c,setActiveDropdownIndex:u}){let[y,g]=(0,R.useState)(!1),[f,_]=(0,R.useState)(null),[x,v]=(0,R.useState)(!1),w=(0,R.useRef)(0),A=(0,R.useRef)(null),I=(0,R.useRef)(""),b=(0,R.useCallback)(async(d,a)=>{A.current?.abort();let l=new AbortController;A.current=l;let K=++w.current,k=e.current.length;n.current.some(E=>E.type!=="placeholder")||g(!0),_(null);try{let E=await ze(d,a,{maskCompletedText:r.current,signal:l.signal,apiConfig:i.current});if(K!==w.current)return;let j=Fe(E.data.suggestions??[],s.current);v(E.data.is_ready??!1),I.current=d;let L=E.data.input??[],M=L[L.length-1],U=e.current;if(M?.state==="in_progress"){o.current=!0;let N=U.toLowerCase().lastIndexOf(M.text.toLowerCase());N!==-1?t.current=N:t.current=k}else o.current=!1,t.current=k;let q=j.filter(N=>N.type!=="placeholder")[0];if(q){let N=Y(U,t.current,o.current),B=re(q.options,N);B&&(m(V=>[...V,{id:crypto.randomUUID(),placeholder:"",type:q.type,text:B.text,kind:B.kind,suggestionType:q.type,suggestionPlaceholder:q.text,options:q.options??[],metadata:B.metadata}]),j=j.filter(V=>V!==q))}c(j),g(!1),u(-1)}catch(E){if(K===w.current){let j=E instanceof Error?E:new Error(String(E));_(j),g(!1),h.current?.(j)}}},[e,n,t,o,r,i,s,h,m,c,u]);return(0,R.useEffect)(()=>(b("",[]),()=>{A.current?.abort()}),[b]),{doFetch:b,isLoading:y,error:f,isReady:x,lastRawQueryRef:I}}function Ne({text:e,completedParams:n,doFetch:t,filterBaseRef:o,filterInProgressRef:r,skipNextFetchRef:i,suggestionsRef:s,lastRawQueryRef:h}){let m=(0,R.useRef)(null),c=(0,R.useRef)(null),u=(0,R.useRef)(!0);(0,R.useEffect)(()=>{m.current&&clearTimeout(m.current),c.current&&clearTimeout(c.current);let y=g=>{if(i.current)return i.current=!1,!1;if(!e&&n.length===0)return u.current?(t("",[]),!0):(u.current=!0,!1);let f=Y(e,o.current,r.current),v=s.current.filter(k=>k.type!=="placeholder")[0],A=(v?ce(v.options,f):[]).filter(k=>k.is_tappable),I=v?re(v.options,f)!==null:!1,b=f.trim().length>0;if(A.length>0&&!I&&b)return!1;let{rawQuery:d,completedParams:a}=ee(e,n),l=d.length<h.current.length,K=Math.abs(d.length-h.current.length);return l||K>=g?(t(d,a),!0):!1};return m.current=setTimeout(()=>{y(mt)&&c.current&&clearTimeout(c.current)},pt),c.current=setTimeout(()=>y(1),dt),()=>{m.current&&clearTimeout(m.current),c.current&&clearTimeout(c.current)}},[e,n,t,o,r,i,s,h])}var Ce=require("react");function Qe({activeDropdownIndex:e,setActiveDropdownIndex:n,filteredOptions:t,selectOption:o,onSubmitRef:r,text:i,completedParams:s,isDropdownOpen:h,hasPlaceholder:m,placeholderText:c,suggestions:u,actionableSuggestions:y,setActivePill:g,filterBaseRef:f,columns:_,setText:x,setCompletedParams:v,setSuggestions:w}){let A=(0,Ce.useCallback)(()=>{let b=t.map((a,l)=>a.is_tappable?l:-1).filter(a=>a!==-1),d=Array.from({length:_},()=>[]);for(let a of b)d[a%_].push(a);return d.flat()},[t,_]);return{handleKeyDown:(0,Ce.useCallback)(b=>{let d=A();switch(b.key){case"ArrowDown":{if(b.preventDefault(),d.length===0)return;let a=d.indexOf(e),l=a<d.length-1?a+1:0;n(d[l]);break}case"ArrowUp":{if(b.preventDefault(),d.length===0)return;let a=d.indexOf(e),l=a>0?a-1:d.length-1;n(d[l]);break}case"ArrowRight":{if(e<0){y.length>1&&(b.preventDefault(),g(1));break}if(e%_<_-1){let l=e+1;l<t.length&&t[l]?.is_tappable&&(b.preventDefault(),n(l))}break}case"ArrowLeft":{if(e<0)break;if(e%_>0){let a=e-1;a>=0&&t[a]?.is_tappable&&(b.preventDefault(),n(a))}break}case"Enter":{if(b.preventDefault(),e>=0&&t[e]?.is_tappable)o(t[e]);else if(r.current){let{rawQuery:a,completedParams:l}=ee(i,s),K={query:i.trim(),raw_query:a,completed_params:l};r.current(K)}break}case"Tab":{if(e>=0&&t[e]?.is_tappable)b.preventDefault(),o(t[e]);else if(h){let a=t.find(l=>l.is_tappable);a&&(b.preventDefault(),o(a))}else if(!i&&m){b.preventDefault();let a=u.find(l=>l.type==="placeholder");a?(x(c),f.current=c.length,v(l=>[...l,{id:crypto.randomUUID(),placeholder:"",type:a.type,text:c,kind:null,suggestionType:a.type,suggestionPlaceholder:a.text,options:a.options??[]}]),w(l=>l.filter(K=>K!==a))):(x(c),f.current=c.length)}break}case"Escape":n(-1);break}},[y,e,_,s,t,f,A,m,h,r,c,o,n,g,v,w,x,u,i]),getTappableIndices:A}}var ue=require("react");function $e({completedParams:e,suggestions:n,setCompletedParams:t,setSuggestions:o,setActiveDropdownIndex:r,filterBaseRef:i,pillTappedRef:s}){let h=(0,ue.useCallback)(u=>{let y=n.filter(x=>x.type!=="placeholder");if(u<0||u>=y.length)return;let g=y[u],f=y.filter((x,v)=>v!==u),_=n.filter(x=>x.type==="placeholder");o([..._,g,...f]),s.current=!0,r(-1)},[n,o,r,s]),m=(0,ue.useCallback)(()=>{if(e.length===0)return;let u=e[e.length-1],y={type:u.suggestionType,text:u.suggestionPlaceholder,required:!0,options:u.options};t(g=>g.slice(0,-1)),o(g=>[y,...g]),r(-1)},[e,t,o,r]),c=(0,ue.useCallback)(u=>{let y={type:u.suggestionType,text:u.suggestionPlaceholder,required:!0,options:u.options};return{apply:g=>{g(f=>{let _=0;for(let x of e){let v=f.indexOf(x.text,_);if(v!==-1){if(x.id===u.id){let w=f.slice(0,v),A=f.slice(v+u.text.length),I=(w+A).replace(/ {2,}/g," ");return i.current=Math.min(i.current,I.length),I}_=v+x.text.length}}return f}),t(f=>f.filter(_=>_.id!==u.id)),o(f=>[y,...f]),r(-1),s.current=!0}}},[e,t,o,r,i,s]);return{setActivePill:h,removeLastParam:m,reEditParam:c}}var gt=0;function ft(){let e=(0,p.useRef)(null);return e.current===null&&(e.current=`:ac-${++gt}:`),e.current}function pe({onSubmit:e,onError:n,optionOverrides:t,maskCompletedText:o,placeholder:r,apiConfig:i,columns:s=2,eagerSuggestions:h=!0,value:m,completedParams:c,onChange:u,onParamsChange:y}){let g=m!==void 0,f=c!==void 0,[_,x]=(0,p.useState)(""),[v,w]=(0,p.useState)([]),[A,I]=(0,p.useState)([]),[b,d]=(0,p.useState)(-1),a=g?m:_,l=f?c:v,K=(0,p.useRef)(e);K.current=e;let k=(0,p.useRef)(u);k.current=u;let $=(0,p.useRef)(y);$.current=y;let E=(0,p.useRef)(m);E.current=m;let j=(0,p.useRef)(c);j.current=c;let L=(0,p.useCallback)(S=>{if(typeof S=="function")if(g){let C=S(E.current??"");k.current?.(C)}else x(C=>{let H=S(C);return k.current?.(H),H});else g||x(S),k.current?.(S)},[g]),M=(0,p.useCallback)(S=>{if(typeof S=="function")if(f){let C=S(j.current??[]);$.current?.(C)}else w(C=>{let H=S(C);return $.current?.(H),H});else f||w(S),$.current?.(S)},[f]),U=(0,p.useRef)(n);U.current=n;let W=(0,p.useRef)(t);W.current=t;let q=(0,p.useRef)(o);q.current=o;let N=(0,p.useRef)(i);N.current=i;let B=(0,p.useRef)(a);B.current=a;let V=(0,p.useRef)(A);V.current=A;let z=(0,p.useRef)(0),te=(0,p.useRef)(!1),ie=(0,p.useRef)(!1),Ie=(0,p.useRef)(!1),de=ft(),{doFetch:me,isLoading:we,error:He,isReady:We,lastRawQueryRef:ge}=qe({textRef:B,suggestionsRef:V,filterBaseRef:z,filterInProgressRef:te,maskCompletedTextRef:q,apiConfigRef:N,optionOverridesRef:W,onErrorRef:U,setCompletedParams:M,setSuggestions:I,setActiveDropdownIndex:d});Ne({text:a,completedParams:l,doFetch:me,filterBaseRef:z,filterInProgressRef:te,skipNextFetchRef:Ie,suggestionsRef:V,lastRawQueryRef:ge});let Ve=(0,p.useMemo)(()=>De(a,l),[a,l]);z.current=Math.min(z.current,a.length);let fe=Y(a,z.current,te.current),be=(0,p.useMemo)(()=>A.filter(C=>C.type==="placeholder").map(C=>C.text).join(" ")||r||"",[A,r]),oe=(0,p.useMemo)(()=>A.filter(S=>S.type!=="placeholder"),[A]),P=oe[0],Oe=P?t?.[P.type]:void 0,Re=P?Oe?Oe(fe.trim()):P.options??[]:[],he=(0,p.useMemo)(()=>ce(Re,fe),[Re,fe]),ke=be.length>0,ye=!we&&he.length>0&&(!!a||ie.current||!ke),Me=(0,p.useCallback)(S=>{if(!P)return;let C={id:crypto.randomUUID(),placeholder:"",type:P.type,text:S.text,kind:S.kind,suggestionType:P.type,suggestionPlaceholder:P.text,options:P.options??[],metadata:S.metadata},H=z.current,D=B.current.slice(0,H);if(D.length>0&&!D.endsWith(" ")){let O=D.split(/\s+/).pop()??"";O&&S.text.toLowerCase().startsWith(O.toLowerCase())&&(D=D.slice(0,D.length-O.length))}let Se=D.length>0&&D[D.length-1]!==" ",Z=D+(Se?" ":"")+S.text+" ";L(Z),z.current=Z.length,M(O=>[...O,C]),ie.current=!1,d(-1);let G=oe.length-1;h&&G>0?(I(O=>O.filter(X=>X!==P)),Ie.current=!0):I(O=>O.filter(X=>X.type==="placeholder"))},[P,oe,h,L,M]),Ge=(0,p.useCallback)(S=>{let C=S.target.value,D=C.length>0&&!S.nativeEvent?.isComposing&&C[0]!==C[0].toUpperCase()?C[0].toUpperCase()+C.slice(1):C;L(D),ie.current=!1,d(-1);let{valid:Se,invalid:Z}=Ke(D,l);if(Z.length>0){M(()=>Se);for(let G of Z)I(O=>[{type:G.suggestionType,text:G.suggestionPlaceholder,required:!0,options:G.options},...O])}if(P&&Z.length===0){let G=Y(D,z.current,te.current),O=re(P.options,G);O&&(M(X=>[...X,{id:crypto.randomUUID(),placeholder:"",type:P.type,text:O.text,kind:O.kind,suggestionType:P.type,suggestionPlaceholder:P.text,options:P.options??[],metadata:O.metadata}]),I(X=>X.filter(et=>et!==P)))}},[l,P,L,M]),ne=$e({completedParams:l,suggestions:A,setCompletedParams:M,setSuggestions:I,setActiveDropdownIndex:d,filterBaseRef:z,pillTappedRef:ie}),Xe=(0,p.useCallback)(S=>{ne.reEditParam(S).apply(L)},[ne,L]),{handleKeyDown:Ze}=Qe({activeDropdownIndex:b,setActiveDropdownIndex:d,filteredOptions:he,selectOption:Me,onSubmitRef:K,text:a,completedParams:l,isDropdownOpen:ye,hasPlaceholder:ke,placeholderText:be,suggestions:A,actionableSuggestions:oe,setActivePill:ne.setActivePill,filterBaseRef:z,columns:s,setText:L,setCompletedParams:M,setSuggestions:I}),Je=(0,p.useCallback)(()=>{L(""),M(()=>[]),I([]),d(-1),z.current=0,te.current=!1,ge.current="",me("",[])},[me,L,M,ge]),Ye=b>=0?`${de}-option-${b}`:void 0;return{completedParams:l,suggestionPills:oe,setActivePill:ne.setActivePill,removeLastParam:ne.removeLastParam,reEditParam:Xe,segments:Ve,suggestions:A,activeIndex:b,isReady:We,isLoading:we,error:He,inputProps:{value:a,placeholder:be||void 0,onChange:Ge,onKeyDown:Ze,role:"combobox","aria-expanded":ye,"aria-activedescendant":Ye,"aria-autocomplete":"list","aria-controls":de},reset:Je,dropdownProps:{suggestions:P?[{...P,options:he}]:[],activeIndex:b,onSelect:Me,onHighlight:d,isOpen:ye,id:de}}}var T=require("react/jsx-runtime"),Be=(0,F.forwardRef)(function({onSubmit:n,onError:t,optionOverrides:o,maskCompletedText:r,placeholder:i,className:s,apiConfig:h,columns:m,eagerSuggestions:c,value:u,completedParams:y,onChange:g,onParamsChange:f},_){let x=(0,F.useRef)(null),v=(0,F.useRef)(()=>{});(0,F.useEffect)(()=>{x.current?.focus()},[]);let{completedParams:w,suggestionPills:A,setActivePill:I,segments:b,inputProps:d,dropdownProps:a,reset:l}=pe({onSubmit:U=>v.current(U),onError:t,optionOverrides:o,maskCompletedText:r,placeholder:i,apiConfig:h,columns:m,eagerSuggestions:c,value:u,completedParams:y,onChange:g,onParamsChange:f});(0,F.useImperativeHandle)(_,()=>({focus:()=>x.current?.focus(),reset:l}),[l]);let K=()=>{x.current?.focus()},k=!!d.value||w.length>0,$=(0,F.useCallback)(()=>{if(!k)return;let{rawQuery:U,completedParams:W}=ee(d.value,w);n({query:d.value.trim(),raw_query:U,completed_params:W}),l()},[k,d.value,w,n,l]);v.current=$;let{onChange:E,placeholder:j,...L}=d,M=!d.value;return(0,T.jsxs)("div",{className:`${Q.container} ${s??""}`,children:[(0,T.jsx)(se,{...a}),(0,T.jsxs)("div",{className:Q.inputWrapper,onClick:K,children:[(0,T.jsxs)("div",{className:Q.editorArea,children:[(0,T.jsxs)("div",{className:Q.sizerContent,"aria-hidden":"true",children:[M&&j?(0,T.jsxs)("span",{className:Q.placeholderText,children:[j," "]}):(0,T.jsxs)("span",{className:Q.sizerText,children:[b.map((U,W)=>(0,T.jsx)("span",{children:U.value},`${W}-${U.type}`)),b.length===0&&"\xA0"]})," ",(0,T.jsx)(Ue,{pills:A,activePillIndex:0,onSelectPill:I})]}),(0,T.jsx)("textarea",{ref:x,className:Q.textarea,rows:1,onChange:E,...L})]}),(0,T.jsx)("button",{type:"button",className:Q.submitButton,disabled:!k,onClick:U=>{U.stopPropagation(),$()},"aria-label":"Submit",children:(0,T.jsx)("svg",{width:"18",height:"18",viewBox:"0 0 18 18",fill:"none",role:"img","aria-label":"Submit",children:(0,T.jsx)("path",{d:"M9 14V4M9 4L4 9M9 4L14 9",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})})]})]})});0&&(module.exports={AIAutocomplete,AIAutocompleteDropdown,useAIAutocomplete});
|
|
215
215
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/AIAutocomplete.tsx","css-module:/Users/saharshv/MagicX/ai-autocomplete-react/src/AIAutocomplete.module.css.js","css-module:/Users/saharshv/MagicX/ai-autocomplete-react/src/AIAutocompleteDropdown.module.css.js","css-module:/Users/saharshv/MagicX/ai-autocomplete-react/src/components/SuggestionGrid.module.css.js","css-module:/Users/saharshv/MagicX/ai-autocomplete-react/src/components/SuggestionItem.module.css.js","../src/components/SuggestionItem.tsx","../src/components/SuggestionGrid.tsx","../src/AIAutocompleteDropdown.tsx","css-module:/Users/saharshv/MagicX/ai-autocomplete-react/src/components/PillList.module.css.js","../src/components/PillList.tsx","../src/hooks/useAIAutocomplete.ts","../src/utils/filtering.ts","../src/utils/segments.ts","../src/hooks/useAutocompleteFetch.ts","../src/utils/api.ts","../src/utils/buildQuery.ts","../src/utils/overrides.ts","../src/hooks/useAutocompleteKeyboard.ts","../src/hooks/useAutocompletePills.ts"],"sourcesContent":["export { AIAutocomplete } from \"./AIAutocomplete\";\nexport { AIAutocompleteDropdown } from \"./AIAutocompleteDropdown\";\nexport { useAIAutocomplete } from \"./hooks/useAIAutocomplete\";\nexport type {\n AIAutocompleteDropdownProps,\n AIAutocompleteHandle,\n AIAutocompleteProps,\n APIConfig,\n AutocompleteResult,\n CompletedParam,\n CompletedParamState,\n OptionOverrides,\n Segment,\n Suggestion,\n SuggestionOption,\n TaskKind,\n UseAIAutocompleteOptions,\n UseAIAutocompleteReturn,\n} from \"./types\";\n","import { forwardRef, useCallback, useEffect, useImperativeHandle, useRef } from \"react\";\nimport styles from \"./AIAutocomplete.module.css\";\nimport { AIAutocompleteDropdown } from \"./AIAutocompleteDropdown\";\nimport { PillList } from \"./components/PillList\";\nimport { useAIAutocomplete } from \"./hooks/useAIAutocomplete\";\nimport type { AIAutocompleteHandle, AIAutocompleteProps, AutocompleteResult } from \"./types\";\nimport { buildQuery } from \"./utils/buildQuery\";\n\nexport const AIAutocomplete = forwardRef<AIAutocompleteHandle, AIAutocompleteProps>(\n function AIAutocomplete(\n {\n onSubmit,\n onError,\n optionOverrides,\n maskCompletedText,\n placeholder,\n className,\n apiConfig,\n columns,\n eagerSuggestions,\n value,\n completedParams: controlledParams,\n onChange: onChangeProp,\n onParamsChange,\n },\n ref,\n ) {\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n // Render-phase ref assignment — matches the pattern in useAIAutocomplete.ts\n const handleSubmitRef = useRef<(result: AutocompleteResult) => void>(() => {});\n\n useEffect(() => {\n textareaRef.current?.focus();\n }, []);\n\n const {\n completedParams,\n suggestionPills,\n setActivePill,\n segments,\n inputProps,\n dropdownProps,\n reset,\n } = useAIAutocomplete({\n onSubmit: (result) => handleSubmitRef.current(result),\n onError,\n optionOverrides,\n maskCompletedText,\n placeholder,\n apiConfig,\n columns,\n eagerSuggestions,\n value,\n completedParams: controlledParams,\n onChange: onChangeProp,\n onParamsChange,\n });\n\n useImperativeHandle(\n ref,\n () => ({\n focus: () => textareaRef.current?.focus(),\n reset,\n }),\n [reset],\n );\n\n const handleContainerClick = () => {\n textareaRef.current?.focus();\n };\n\n const canSubmit = !!inputProps.value || completedParams.length > 0;\n\n const handleSubmit = useCallback(() => {\n if (!canSubmit) return;\n const { rawQuery, completedParams: finalParams } = buildQuery(\n inputProps.value,\n completedParams,\n );\n onSubmit({\n query: inputProps.value.trim(),\n raw_query: rawQuery,\n completed_params: finalParams,\n });\n reset();\n }, [canSubmit, inputProps.value, completedParams, onSubmit, reset]);\n\n handleSubmitRef.current = handleSubmit;\n\n const { onChange, placeholder: inputPlaceholder, ...restProps } = inputProps;\n const isEmpty = !inputProps.value;\n\n return (\n <div className={`${styles.container} ${className ?? \"\"}`}>\n <AIAutocompleteDropdown {...dropdownProps} />\n {/* biome-ignore lint/a11y/useKeyWithClickEvents: container click delegates to textarea focus */}\n {/* biome-ignore lint/a11y/noStaticElementInteractions: wrapper delegates focus to textarea */}\n <div className={styles.inputWrapper} onClick={handleContainerClick}>\n <div className={styles.editorArea}>\n <div className={styles.sizerContent} aria-hidden=\"true\">\n {isEmpty && inputPlaceholder ? (\n <span className={styles.placeholderText}>{inputPlaceholder} </span>\n ) : (\n <span className={styles.sizerText}>\n {segments.map((seg, i) => (\n // biome-ignore lint/suspicious/noArrayIndexKey: segments are positional and don't reorder\n <span key={`${i}-${seg.type}`}>{seg.value}</span>\n ))}\n {segments.length === 0 && \"\\u00A0\"}\n </span>\n )}\n {\" \"}\n <PillList pills={suggestionPills} activePillIndex={0} onSelectPill={setActivePill} />\n </div>\n <textarea\n ref={textareaRef}\n className={styles.textarea}\n rows={1}\n onChange={onChange}\n {...restProps}\n />\n </div>\n <button\n type=\"button\"\n className={styles.submitButton}\n disabled={!canSubmit}\n onClick={(e) => {\n e.stopPropagation();\n handleSubmit();\n }}\n aria-label=\"Submit\"\n >\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 18 18\"\n fill=\"none\"\n role=\"img\"\n aria-label=\"Submit\"\n >\n <path\n d=\"M9 14V4M9 4L4 9M9 4L14 9\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n </button>\n </div>\n </div>\n );\n },\n);\n","if (typeof document !== \"undefined\" && !document.getElementById(\"ac-style-cc65f4cc\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-cc65f4cc\";\n s.textContent = `.AIAutocomplete-module_container_KKjFU {\n position: relative;\n font-family: \"IBM Plex Sans\", sans-serif;\n}\n\n.AIAutocomplete-module_inputWrapper_FLq1b {\n min-height: 60px;\n padding: 24px;\n border: 1px solid var(--ac-color-border-default, #9ea5b2);\n border-radius: 23px;\n background: transparent;\n overflow: hidden;\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.AIAutocomplete-module_editorArea_7rBWq {\n position: relative;\n flex: 1;\n min-width: 0;\n}\n\n.AIAutocomplete-module_sizerContent_DQgmV {\n position: relative;\n z-index: 1;\n pointer-events: none;\n min-height: 60px;\n white-space: pre-wrap;\n word-break: break-word;\n font-family: inherit;\n font-size: 21px;\n line-height: 38px;\n}\n\n.AIAutocomplete-module_sizerText_iZIMK {\n color: transparent;\n}\n\n.AIAutocomplete-module_placeholderText_K3ayy {\n color: var(--ac-color-text-muted, #c1c4cb);\n opacity: 0.7;\n}\n\n.AIAutocomplete-module_textarea_eyn6A {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n padding: 0;\n border: none;\n background: transparent;\n color: var(--ac-color-text-default, #fff);\n caret-color: var(--ac-color-text-default, #fff);\n font-family: inherit;\n font-size: 21px;\n line-height: 38px;\n white-space: pre-wrap;\n word-break: break-word;\n outline: none;\n resize: none;\n overflow: hidden;\n}\n\n.AIAutocomplete-module_textarea_eyn6A::placeholder {\n color: var(--ac-color-text-muted, #c1c4cb);\n}\n\n.AIAutocomplete-module_submitButton_sl1Mi {\n flex-shrink: 0;\n width: 36px;\n height: 36px;\n border-radius: 50%;\n border: none;\n background: var(--ac-color-text-default, #fff);\n color: var(--ac-color-bg-default, #000);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n transition: opacity 0.2s ease;\n}\n\n.AIAutocomplete-module_submitButton_sl1Mi:hover {\n opacity: 0.85;\n}\n`;\n document.head.appendChild(s);\n}\nexport default {\"container\":\"AIAutocomplete-module_container_KKjFU\",\"inputWrapper\":\"AIAutocomplete-module_inputWrapper_FLq1b\",\"editorArea\":\"AIAutocomplete-module_editorArea_7rBWq\",\"sizerContent\":\"AIAutocomplete-module_sizerContent_DQgmV\",\"sizerText\":\"AIAutocomplete-module_sizerText_iZIMK\",\"placeholderText\":\"AIAutocomplete-module_placeholderText_K3ayy\",\"textarea\":\"AIAutocomplete-module_textarea_eyn6A\",\"submitButton\":\"AIAutocomplete-module_submitButton_sl1Mi\"};","if (typeof document !== \"undefined\" && !document.getElementById(\"ac-style-2eef895d\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-2eef895d\";\n s.textContent = `.AIAutocompleteDropdown-module_dropdown_yz2KC {\n position: absolute;\n left: 0;\n right: 0;\n top: 100%;\n margin-top: 6px;\n background: var(--ac-color-background-default, #00002d);\n border-radius: 23px;\n overflow: hidden;\n z-index: 10;\n opacity: 0;\n pointer-events: none;\n transition: opacity 400ms cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.AIAutocompleteDropdown-module_visible_QCoXj {\n opacity: 1;\n pointer-events: auto;\n}\n`;\n document.head.appendChild(s);\n}\nexport default {\"dropdown\":\"AIAutocompleteDropdown-module_dropdown_yz2KC\",\"visible\":\"AIAutocompleteDropdown-module_visible_QCoXj\"};","if (typeof document !== \"undefined\" && !document.getElementById(\"ac-style-d91f2b06\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-d91f2b06\";\n s.textContent = `.SuggestionGrid-module_grid_jvaPb {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 12px 18px;\n padding: 18px 24px;\n max-height: 192px;\n overflow-y: auto;\n scrollbar-width: thin;\n scrollbar-color: rgba(255, 255, 255, 0.3) transparent;\n}\n\n.SuggestionGrid-module_grid_jvaPb::-webkit-scrollbar {\n width: 6px;\n}\n\n.SuggestionGrid-module_grid_jvaPb::-webkit-scrollbar-track {\n background: transparent;\n}\n\n.SuggestionGrid-module_grid_jvaPb::-webkit-scrollbar-thumb {\n background: rgba(255, 255, 255, 0.3);\n border-radius: 3px;\n}\n`;\n document.head.appendChild(s);\n}\nexport default {\"grid\":\"SuggestionGrid-module_grid_jvaPb\"};","if (typeof document !== \"undefined\" && !document.getElementById(\"ac-style-f6bdc634\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-f6bdc634\";\n s.textContent = `.SuggestionItem-module_item_d4vpD {\n display: flex;\n align-items: center;\n font-family: \"IBM Plex Sans\", sans-serif;\n font-size: 21px;\n line-height: 30px;\n color: var(--ac-color-text-muted, #c1c4cb);\n white-space: nowrap;\n opacity: 0.35;\n animation: SuggestionItem-module_fadeIn_I8u35 400ms cubic-bezier(0.4, 0, 0.2, 1) forwards;\n}\n\n@keyframes SuggestionItem-module_fadeIn_I8u35 {\n from {\n opacity: 0;\n }\n}\n\n.SuggestionItem-module_tappable_70KcX {\n cursor: pointer;\n}\n\n.SuggestionItem-module_tappable_70KcX:hover {\n color: var(--ac-color-text-default, #fff);\n}\n\n.SuggestionItem-module_nonTappable_xSZM- {\n cursor: default;\n opacity: 0.3;\n}\n\n.SuggestionItem-module_highlighted_Hb0SU {\n color: var(--ac-color-text-default, #fff);\n opacity: 0.5;\n}\n\n.SuggestionItem-module_tag_e3Fwe {\n font-size: 13px;\n margin-left: 6px;\n opacity: 0.5;\n}\n`;\n document.head.appendChild(s);\n}\nexport default {\"item\":\"SuggestionItem-module_item_d4vpD\",\"fadeIn\":\"SuggestionItem-module_fadeIn_I8u35\",\"tappable\":\"SuggestionItem-module_tappable_70KcX\",\"nonTappable\":\"SuggestionItem-module_nonTappable_xSZM-\",\"highlighted\":\"SuggestionItem-module_highlighted_Hb0SU\",\"tag\":\"SuggestionItem-module_tag_e3Fwe\"};","import type { SuggestionOption } from \"../types\";\nimport styles from \"./SuggestionItem.module.css\";\n\ninterface SuggestionItemProps {\n option: SuggestionOption;\n isHighlighted: boolean;\n onSelect: (option: SuggestionOption) => void;\n onHighlight: () => void;\n id: string;\n}\n\nexport function SuggestionItem({\n option,\n isHighlighted,\n onSelect,\n onHighlight,\n id,\n}: SuggestionItemProps) {\n const className = [\n styles.item,\n isHighlighted ? styles.highlighted : \"\",\n option.is_tappable ? styles.tappable : styles.nonTappable,\n ]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <div\n id={id}\n role=\"option\"\n aria-selected={isHighlighted}\n className={className}\n tabIndex={option.is_tappable ? 0 : -1}\n onClick={() => option.is_tappable && onSelect(option)}\n onKeyDown={(e) => {\n if (option.is_tappable && (e.key === \"Enter\" || e.key === \" \")) {\n e.preventDefault();\n onSelect(option);\n }\n }}\n onMouseEnter={onHighlight}\n >\n {option.icon ? `${option.icon} ${option.text}` : option.text}\n {option.tag && <span className={styles.tag}>{option.tag}</span>}\n </div>\n );\n}\n","import type { SuggestionOption } from \"../types\";\nimport styles from \"./SuggestionGrid.module.css\";\nimport { SuggestionItem } from \"./SuggestionItem\";\n\ninterface SuggestionGridProps {\n options: SuggestionOption[];\n activeIndex: number;\n onSelect: (option: SuggestionOption) => void;\n onHighlight: (index: number) => void;\n listboxId: string;\n}\n\nexport function SuggestionGrid({\n options,\n activeIndex,\n onSelect,\n onHighlight,\n listboxId,\n}: SuggestionGridProps) {\n return (\n <div className={styles.grid}>\n {options.map((option, i) => (\n <SuggestionItem\n key={option.text}\n option={option}\n isHighlighted={i === activeIndex}\n onSelect={onSelect}\n onHighlight={() => onHighlight(i)}\n id={`${listboxId}-option-${i}`}\n />\n ))}\n </div>\n );\n}\n","import styles from \"./AIAutocompleteDropdown.module.css\";\nimport { SuggestionGrid } from \"./components/SuggestionGrid\";\nimport type { AIAutocompleteDropdownProps } from \"./types\";\n\nexport function AIAutocompleteDropdown({\n suggestions,\n activeIndex,\n onSelect,\n onHighlight,\n isOpen,\n id,\n className,\n}: AIAutocompleteDropdownProps) {\n const activeSuggestion = suggestions[0];\n const options = activeSuggestion?.options ?? [];\n const hasOptions = isOpen && options.length > 0;\n\n return (\n <div\n id={id}\n role=\"listbox\"\n className={`${styles.dropdown} ${hasOptions ? styles.visible : \"\"} ${className ?? \"\"}`}\n onMouseDown={(e) => e.preventDefault()}\n >\n {options.length > 0 && (\n <SuggestionGrid\n options={options}\n activeIndex={activeIndex}\n onSelect={onSelect}\n onHighlight={onHighlight}\n listboxId={id}\n />\n )}\n </div>\n );\n}\n","if (typeof document !== \"undefined\" && !document.getElementById(\"ac-style-b745b4fb\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-b745b4fb\";\n s.textContent = `.PillList-module_list_qvLqO {\n position: relative;\n z-index: 1;\n pointer-events: auto;\n display: inline-flex;\n gap: 5px;\n align-items: center;\n vertical-align: middle;\n transform: translateY(-3px);\n}\n\n.PillList-module_pill_osSyz {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n height: 36px;\n padding: 7px 9px;\n border: none;\n border-radius: 6px;\n background: var(--ac-color-background-supportive, #313255);\n color: var(--ac-color-text-muted, #c1c4cb);\n font-family: \"IBM Plex Sans\", sans-serif;\n font-size: 21px;\n line-height: 30px;\n cursor: pointer;\n white-space: nowrap;\n animation: PillList-module_fadeIn_Aezob 400ms cubic-bezier(0.4, 0, 0.2, 1) forwards;\n}\n\n.PillList-module_pill_osSyz:hover {\n filter: brightness(1.2);\n}\n\n.PillList-module_active_Oll-- {\n outline: 1px solid #5a5b8a;\n}\n\n@keyframes PillList-module_fadeIn_Aezob {\n from {\n opacity: 0;\n }\n}\n`;\n document.head.appendChild(s);\n}\nexport default {\"list\":\"PillList-module_list_qvLqO\",\"pill\":\"PillList-module_pill_osSyz\",\"fadeIn\":\"PillList-module_fadeIn_Aezob\",\"active\":\"PillList-module_active_Oll--\"};","import type { Suggestion } from \"../types\";\nimport styles from \"./PillList.module.css\";\n\ninterface PillListProps {\n pills: Suggestion[];\n activePillIndex: number;\n onSelectPill: (index: number) => void;\n}\n\nfunction getPillOpacity(index: number): number {\n if (index === 0) return 0.4;\n if (index === 1) return 0.3;\n return 0.15;\n}\n\nexport function PillList({ pills, activePillIndex, onSelectPill }: PillListProps) {\n return (\n <span className={styles.list}>\n {pills.map((pill, i) => (\n <button\n key={`${pill.type}-${pill.text}`}\n type=\"button\"\n className={`${styles.pill} ${i === activePillIndex ? styles.active : \"\"}`}\n style={{ opacity: getPillOpacity(i) }}\n onClick={() => onSelectPill(i)}\n >\n {pill.text}\n </button>\n ))}\n </span>\n );\n}\n","import { type ChangeEvent, useCallback, useMemo, useRef, useState } from \"react\";\nimport type {\n CompletedParamState,\n Suggestion,\n SuggestionOption,\n UseAIAutocompleteOptions,\n UseAIAutocompleteReturn,\n} from \"../types\";\nimport { filterOptions, findExactMatch } from \"../utils/filtering\";\nimport { deriveSegments, reconcileParams } from \"../utils/segments\";\nimport { useAutocompleteFetch, useDebouncedFetch } from \"./useAutocompleteFetch\";\nimport { useAutocompleteKeyboard } from \"./useAutocompleteKeyboard\";\nimport { useAutocompletePills } from \"./useAutocompletePills\";\n\nlet idCounter = 0;\nfunction useStableId(): string {\n const id = useRef<string | null>(null);\n if (id.current === null) {\n id.current = `:ac-${++idCounter}:`;\n }\n return id.current;\n}\n\nexport function useAIAutocomplete({\n onSubmit,\n onError,\n optionOverrides,\n maskCompletedText,\n placeholder: customPlaceholder,\n apiConfig,\n columns = 2,\n eagerSuggestions = true,\n value: controlledValue,\n completedParams: controlledParams,\n onChange: onChangeProp,\n onParamsChange,\n}: UseAIAutocompleteOptions): UseAIAutocompleteReturn {\n // === Controlled / uncontrolled state ===\n const isTextControlled = controlledValue !== undefined;\n const isParamsControlled = controlledParams !== undefined;\n\n const [internalText, setInternalText] = useState(\"\");\n const [internalCompletedParams, setInternalCompletedParams] = useState<CompletedParamState[]>([]);\n const [suggestions, setSuggestions] = useState<Suggestion[]>([]);\n const [activeDropdownIndex, setActiveDropdownIndex] = useState(-1);\n\n const text = isTextControlled ? controlledValue : internalText;\n const completedParams = isParamsControlled ? controlledParams : internalCompletedParams;\n\n // === Refs — must be before setText/setCompletedParams which read them ===\n const onSubmitRef = useRef(onSubmit);\n onSubmitRef.current = onSubmit;\n const onChangeRef = useRef(onChangeProp);\n onChangeRef.current = onChangeProp;\n const onParamsChangeRef = useRef(onParamsChange);\n onParamsChangeRef.current = onParamsChange;\n const controlledValueRef = useRef(controlledValue);\n controlledValueRef.current = controlledValue;\n const controlledParamsRef = useRef(controlledParams);\n controlledParamsRef.current = controlledParams;\n\n // Stable setText that reads controlled value + callback via refs (no stale closures)\n const setText = useCallback(\n (value: string | ((prev: string) => string)) => {\n if (typeof value === \"function\") {\n if (isTextControlled) {\n const newVal = value(controlledValueRef.current ?? \"\");\n onChangeRef.current?.(newVal);\n } else {\n setInternalText((prev) => {\n const newVal = value(prev);\n onChangeRef.current?.(newVal);\n return newVal;\n });\n }\n } else {\n if (!isTextControlled) setInternalText(value);\n onChangeRef.current?.(value);\n }\n },\n [isTextControlled],\n );\n\n // Stable setCompletedParams — same ref pattern\n const setCompletedParams = useCallback(\n (value: CompletedParamState[] | ((prev: CompletedParamState[]) => CompletedParamState[])) => {\n if (typeof value === \"function\") {\n if (isParamsControlled) {\n const newVal = value(controlledParamsRef.current ?? []);\n onParamsChangeRef.current?.(newVal);\n } else {\n setInternalCompletedParams((prev) => {\n const newVal = value(prev);\n onParamsChangeRef.current?.(newVal);\n return newVal;\n });\n }\n } else {\n if (!isParamsControlled) setInternalCompletedParams(value);\n onParamsChangeRef.current?.(value);\n }\n },\n [isParamsControlled],\n );\n const onErrorRef = useRef(onError);\n onErrorRef.current = onError;\n const optionOverridesRef = useRef(optionOverrides);\n optionOverridesRef.current = optionOverrides;\n const maskCompletedTextRef = useRef(maskCompletedText);\n maskCompletedTextRef.current = maskCompletedText;\n const apiConfigRef = useRef(apiConfig);\n apiConfigRef.current = apiConfig;\n const textRef = useRef(text);\n textRef.current = text;\n const suggestionsRef = useRef(suggestions);\n suggestionsRef.current = suggestions;\n const filterBaseRef = useRef(0);\n const pillTappedRef = useRef(false);\n const skipNextFetchRef = useRef(false);\n const listboxId = useStableId();\n\n // === Fetch ===\n const { doFetch, isLoading, error, isReady, lastRawQueryRef } = useAutocompleteFetch({\n textRef,\n suggestionsRef,\n filterBaseRef,\n maskCompletedTextRef,\n apiConfigRef,\n optionOverridesRef,\n onErrorRef,\n setCompletedParams,\n setSuggestions,\n setActiveDropdownIndex,\n });\n\n useDebouncedFetch({\n text,\n completedParams,\n doFetch,\n filterBaseRef,\n skipNextFetchRef,\n suggestionsRef,\n lastRawQueryRef,\n });\n\n // === Derived ===\n const segments = useMemo(() => deriveSegments(text, completedParams), [text, completedParams]);\n\n filterBaseRef.current = Math.min(filterBaseRef.current, text.length);\n const filterQuery = text.slice(filterBaseRef.current);\n\n const placeholderText = useMemo(() => {\n const serverPlaceholder = suggestions\n .filter((s) => s.type === \"placeholder\")\n .map((s) => s.text)\n .join(\" \");\n return serverPlaceholder || customPlaceholder || \"\";\n }, [suggestions, customPlaceholder]);\n const actionableSuggestions = useMemo(\n () => suggestions.filter((s) => s.type !== \"placeholder\"),\n [suggestions],\n );\n const activeSuggestion: Suggestion | undefined = actionableSuggestions[0];\n const overrideFn = activeSuggestion ? optionOverrides?.[activeSuggestion.type] : undefined;\n const baseOptions = activeSuggestion\n ? overrideFn\n ? overrideFn(filterQuery.trim())\n : (activeSuggestion.options ?? [])\n : [];\n const filteredOptions = useMemo(\n () => filterOptions(baseOptions, filterQuery),\n [baseOptions, filterQuery],\n );\n const hasPlaceholder = placeholderText.length > 0;\n const isDropdownOpen =\n !isLoading &&\n filteredOptions.length > 0 &&\n (!!text || pillTappedRef.current || !hasPlaceholder);\n\n // === Option selection ===\n const selectOption = useCallback(\n (option: SuggestionOption) => {\n if (!activeSuggestion) return;\n\n const completed: CompletedParamState = {\n id: crypto.randomUUID(),\n placeholder: \"\",\n type: activeSuggestion.type,\n text: option.text,\n kind: option.kind,\n suggestionType: activeSuggestion.type,\n suggestionPlaceholder: activeSuggestion.text,\n options: activeSuggestion.options ?? [],\n metadata: option.metadata,\n };\n\n const base = filterBaseRef.current;\n let prefix = textRef.current.slice(0, base);\n if (prefix.length > 0 && !prefix.endsWith(\" \")) {\n const lastWord = prefix.split(/\\s+/).pop() ?? \"\";\n if (lastWord && option.text.toLowerCase().startsWith(lastWord.toLowerCase())) {\n prefix = prefix.slice(0, prefix.length - lastWord.length);\n }\n }\n\n const needsSpace = prefix.length > 0 && prefix[prefix.length - 1] !== \" \";\n const newText = prefix + (needsSpace ? \" \" : \"\") + option.text + \" \";\n setText(newText);\n filterBaseRef.current = newText.length;\n setCompletedParams((prev) => [...prev, completed]);\n pillTappedRef.current = false;\n setActiveDropdownIndex(-1);\n const remainingActionable = actionableSuggestions.length - 1;\n if (eagerSuggestions && remainingActionable > 0) {\n // Keep cached suggestions visible and skip the fetch\n setSuggestions((prev) => prev.filter((s) => s !== activeSuggestion));\n skipNextFetchRef.current = true;\n } else {\n // Clear all suggestions and let the debounced fetch bring fresh ones\n setSuggestions((prev) => prev.filter((s) => s.type === \"placeholder\"));\n }\n },\n [activeSuggestion, actionableSuggestions, eagerSuggestions, setText, setCompletedParams],\n );\n\n // === Text change handler ===\n const handleChange = useCallback(\n (e: ChangeEvent<HTMLTextAreaElement>) => {\n const raw = e.target.value;\n const shouldCapitalize =\n raw.length > 0 &&\n !(e.nativeEvent as InputEvent)?.isComposing &&\n raw[0] !== raw[0].toUpperCase();\n const newValue = shouldCapitalize ? raw[0].toUpperCase() + raw.slice(1) : raw;\n setText(newValue);\n pillTappedRef.current = false;\n setActiveDropdownIndex(-1);\n\n const { valid, invalid } = reconcileParams(newValue, completedParams);\n if (invalid.length > 0) {\n setCompletedParams(() => valid);\n for (const param of invalid) {\n setSuggestions((prev) => [\n {\n type: param.suggestionType,\n text: param.suggestionPlaceholder,\n required: true,\n options: param.options,\n },\n ...prev,\n ]);\n }\n }\n\n if (activeSuggestion && invalid.length === 0) {\n const newFilterQuery = newValue.slice(filterBaseRef.current);\n const match = findExactMatch(activeSuggestion.options, newFilterQuery);\n if (match) {\n setCompletedParams((prev) => [\n ...prev,\n {\n id: crypto.randomUUID(),\n placeholder: \"\",\n type: activeSuggestion.type,\n text: match.text,\n kind: match.kind,\n suggestionType: activeSuggestion.type,\n suggestionPlaceholder: activeSuggestion.text,\n options: activeSuggestion.options ?? [],\n metadata: match.metadata,\n },\n ]);\n setSuggestions((prev) => prev.filter((s) => s !== activeSuggestion));\n }\n }\n },\n [completedParams, activeSuggestion, setText, setCompletedParams],\n );\n\n // === Keyboard ===\n const { handleKeyDown } = useAutocompleteKeyboard({\n activeDropdownIndex,\n setActiveDropdownIndex,\n filteredOptions,\n selectOption,\n onSubmitRef,\n text,\n completedParams,\n isDropdownOpen,\n hasPlaceholder,\n placeholderText,\n suggestions,\n filterBaseRef,\n columns,\n setText,\n setCompletedParams,\n setSuggestions,\n });\n\n // === Pills ===\n const pills = useAutocompletePills({\n completedParams,\n suggestions,\n setCompletedParams,\n setSuggestions,\n setActiveDropdownIndex,\n filterBaseRef,\n pillTappedRef,\n });\n\n const reEditParam = useCallback(\n (param: CompletedParamState) => {\n pills.reEditParam(param).apply(setText);\n },\n [pills, setText],\n );\n\n // === Reset ===\n const reset = useCallback(() => {\n setText(\"\");\n setCompletedParams(() => []);\n setSuggestions([]);\n setActiveDropdownIndex(-1);\n filterBaseRef.current = 0;\n lastRawQueryRef.current = \"\";\n doFetch(\"\", []);\n }, [doFetch, setText, setCompletedParams, lastRawQueryRef]);\n\n const activeDescendantId =\n activeDropdownIndex >= 0 ? `${listboxId}-option-${activeDropdownIndex}` : undefined;\n\n return {\n completedParams,\n suggestionPills: actionableSuggestions,\n setActivePill: pills.setActivePill,\n removeLastParam: pills.removeLastParam,\n reEditParam,\n segments,\n suggestions,\n activeIndex: activeDropdownIndex,\n isReady,\n isLoading,\n error,\n inputProps: {\n value: text,\n placeholder: placeholderText || undefined,\n onChange: handleChange,\n onKeyDown: handleKeyDown,\n role: \"combobox\" as const,\n \"aria-expanded\": isDropdownOpen,\n \"aria-activedescendant\": activeDescendantId,\n \"aria-autocomplete\": \"list\" as const,\n \"aria-controls\": listboxId,\n },\n reset,\n dropdownProps: {\n suggestions: activeSuggestion ? [{ ...activeSuggestion, options: filteredOptions }] : [],\n activeIndex: activeDropdownIndex,\n onSelect: selectOption,\n onHighlight: setActiveDropdownIndex,\n isOpen: isDropdownOpen,\n id: listboxId,\n },\n };\n}\n","import type { SuggestionOption } from \"../types\";\n\n/**\n * Filters options using partial substring match on the text after the last completed param.\n */\nexport function filterOptions(\n options: SuggestionOption[] | undefined,\n query: string,\n): SuggestionOption[] {\n if (!options) return [];\n const trimmed = query.trimStart();\n if (!trimmed) return options;\n const lower = trimmed.toLowerCase();\n return options.filter((o) => !o.is_tappable || o.text.toLowerCase().includes(lower));\n}\n\n/**\n * Finds an exact match for the trimmed filter query against options.\n */\nexport function findExactMatch(\n options: SuggestionOption[] | undefined,\n query: string,\n): SuggestionOption | null {\n if (!options) return null;\n const trimmed = query.trim();\n if (!trimmed) return null;\n const lower = trimmed.toLowerCase();\n return options.find((o) => o.is_tappable && o.text.toLowerCase() === lower) ?? null;\n}\n","import type { CompletedParamState, Segment } from \"../types\";\n\n/**\n * Derives segments for overlay rendering by matching completed params in text.\n */\nexport function deriveSegments(text: string, completedParams: CompletedParamState[]): Segment[] {\n const result: Segment[] = [];\n let pos = 0;\n\n for (const param of completedParams) {\n const idx = text.indexOf(param.text, pos);\n if (idx === -1) continue;\n if (idx > pos) {\n result.push({ type: \"text\", value: text.slice(pos, idx) });\n }\n result.push({ type: \"completed\", value: param.text, param });\n pos = idx + param.text.length;\n }\n\n const remaining = text.slice(pos);\n if (remaining) {\n result.push({ type: \"text\", value: remaining });\n }\n\n return result;\n}\n\n/**\n * Checks which completed params still exist in the new text.\n */\nexport function reconcileParams(\n text: string,\n completedParams: CompletedParamState[],\n): { valid: CompletedParamState[]; invalid: CompletedParamState[] } {\n const valid: CompletedParamState[] = [];\n const invalid: CompletedParamState[] = [];\n let pos = 0;\n\n for (const param of completedParams) {\n const idx = text.indexOf(param.text, pos);\n if (idx === -1) {\n invalid.push(param);\n } else {\n valid.push(param);\n pos = idx + param.text.length;\n }\n }\n\n return { valid, invalid };\n}\n","import { type MutableRefObject, useCallback, useEffect, useRef, useState } from \"react\";\nimport type {\n APIConfig,\n CompletedParamState,\n OptionOverrides,\n Suggestion,\n SuggestionOption,\n} from \"../types\";\nimport { fetchSuggestions } from \"../utils/api\";\nimport { buildQuery } from \"../utils/buildQuery\";\nimport { filterOptions, findExactMatch } from \"../utils/filtering\";\nimport { applyOptionOverrides } from \"../utils/overrides\";\n\nconst DEBOUNCE_MS = 100;\nconst SLOW_DEBOUNCE_MS = 300;\nconst MIN_CHARS_DIFF = 2;\n\ninterface UseAutocompleteFetchOptions {\n textRef: MutableRefObject<string>;\n suggestionsRef: MutableRefObject<Suggestion[]>;\n filterBaseRef: MutableRefObject<number>;\n maskCompletedTextRef: MutableRefObject<boolean | undefined>;\n apiConfigRef: MutableRefObject<APIConfig | undefined>;\n optionOverridesRef: MutableRefObject<OptionOverrides | undefined>;\n onErrorRef: MutableRefObject<((error: Error) => void) | undefined>;\n setCompletedParams: (fn: (prev: CompletedParamState[]) => CompletedParamState[]) => void;\n setSuggestions: (fn: Suggestion[] | ((prev: Suggestion[]) => Suggestion[])) => void;\n setActiveDropdownIndex: (index: number) => void;\n}\n\ninterface UseAutocompleteFetchReturn {\n doFetch: (rawQuery: string, completed: CompletedParamState[]) => Promise<void>;\n isLoading: boolean;\n error: Error | null;\n isReady: boolean;\n lastRawQueryRef: MutableRefObject<string>;\n}\n\nexport function useAutocompleteFetch({\n textRef,\n suggestionsRef,\n filterBaseRef,\n maskCompletedTextRef,\n apiConfigRef,\n optionOverridesRef,\n onErrorRef,\n setCompletedParams,\n setSuggestions,\n setActiveDropdownIndex,\n}: UseAutocompleteFetchOptions): UseAutocompleteFetchReturn {\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [isReady, setIsReady] = useState(false);\n const fetchVersionRef = useRef(0);\n const abortRef = useRef<AbortController | null>(null);\n const lastRawQueryRef = useRef(\"\");\n\n const doFetch = useCallback(\n async (rawQuery: string, completed: CompletedParamState[]) => {\n abortRef.current?.abort();\n const controller = new AbortController();\n abortRef.current = controller;\n const version = ++fetchVersionRef.current;\n const textAtRequest = textRef.current.length;\n\n const hasSuggestions = suggestionsRef.current.some((s) => s.type !== \"placeholder\");\n if (!hasSuggestions) setIsLoading(true);\n setError(null);\n try {\n const res = await fetchSuggestions(rawQuery, completed, {\n maskCompletedText: maskCompletedTextRef.current,\n signal: controller.signal,\n apiConfig: apiConfigRef.current,\n });\n\n if (version !== fetchVersionRef.current) return;\n\n let newSuggestions = applyOptionOverrides(\n res.data.suggestions ?? [],\n optionOverridesRef.current,\n );\n setIsReady(res.data.is_ready ?? false);\n lastRawQueryRef.current = rawQuery;\n\n const input = res.data.input ?? [];\n const lastInput = input[input.length - 1];\n const currentText = textRef.current;\n if (lastInput?.state === \"in_progress\") {\n const inProgressIdx = currentText.toLowerCase().lastIndexOf(lastInput.text.toLowerCase());\n if (inProgressIdx !== -1) {\n filterBaseRef.current = inProgressIdx;\n } else {\n filterBaseRef.current = textAtRequest;\n }\n } else {\n filterBaseRef.current = textAtRequest;\n }\n\n // Check if the user already typed an exact match while waiting\n const actionable = newSuggestions.filter((s) => s.type !== \"placeholder\");\n const active = actionable[0];\n if (active) {\n const query = currentText.slice(filterBaseRef.current);\n const match = findExactMatch(active.options, query);\n if (match) {\n setCompletedParams((prev) => [\n ...prev,\n {\n id: crypto.randomUUID(),\n placeholder: \"\",\n type: active.type,\n text: match.text,\n kind: match.kind,\n suggestionType: active.type,\n suggestionPlaceholder: active.text,\n options: active.options ?? [],\n metadata: match.metadata,\n },\n ]);\n newSuggestions = newSuggestions.filter((s) => s !== active);\n }\n }\n\n setSuggestions(newSuggestions);\n setIsLoading(false);\n setActiveDropdownIndex(-1);\n } catch (err) {\n if (version === fetchVersionRef.current) {\n const caughtError = err instanceof Error ? err : new Error(String(err));\n setError(caughtError);\n setIsLoading(false);\n onErrorRef.current?.(caughtError);\n }\n }\n },\n [\n textRef,\n suggestionsRef,\n filterBaseRef,\n maskCompletedTextRef,\n apiConfigRef,\n optionOverridesRef,\n onErrorRef,\n setCompletedParams,\n setSuggestions,\n setActiveDropdownIndex,\n ],\n );\n\n // Mount fetch\n useEffect(() => {\n doFetch(\"\", []);\n return () => {\n abortRef.current?.abort();\n };\n }, [doFetch]);\n\n return { doFetch, isLoading, error, isReady, lastRawQueryRef };\n}\n\ninterface UseDebouncedFetchOptions {\n text: string;\n completedParams: CompletedParamState[];\n doFetch: (rawQuery: string, completed: CompletedParamState[]) => Promise<void>;\n filterBaseRef: MutableRefObject<number>;\n skipNextFetchRef: MutableRefObject<boolean>;\n suggestionsRef: MutableRefObject<Suggestion[]>;\n lastRawQueryRef: MutableRefObject<string>;\n}\n\nexport function useDebouncedFetch({\n text,\n completedParams,\n doFetch,\n filterBaseRef,\n skipNextFetchRef,\n suggestionsRef,\n lastRawQueryRef,\n}: UseDebouncedFetchOptions): void {\n const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const slowDebounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const hasFetchedRef = useRef(true);\n\n useEffect(() => {\n if (debounceRef.current) clearTimeout(debounceRef.current);\n if (slowDebounceRef.current) clearTimeout(slowDebounceRef.current);\n\n const attemptFetch = (minDiff: number): boolean => {\n if (skipNextFetchRef.current) {\n skipNextFetchRef.current = false;\n return false;\n }\n\n if (!text && completedParams.length === 0) {\n if (!hasFetchedRef.current) {\n hasFetchedRef.current = true;\n return false;\n }\n doFetch(\"\", []);\n return true;\n }\n\n const currentQuery = text.slice(filterBaseRef.current);\n const currentSuggestions = suggestionsRef.current;\n const actionable = currentSuggestions.filter((s: Suggestion) => s.type !== \"placeholder\");\n const active = actionable[0];\n const currentFiltered = active ? filterOptions(active.options, currentQuery) : [];\n const tappableFiltered = currentFiltered.filter((o: SuggestionOption) => o.is_tappable);\n const hasExactMatch = active ? findExactMatch(active.options, currentQuery) !== null : false;\n\n const isInFilterZone = currentQuery.trim().length > 0;\n if (tappableFiltered.length > 0 && !hasExactMatch && isInFilterZone) return false;\n\n const { rawQuery, completedParams: updatedParams } = buildQuery(text, completedParams);\n const isDeleting = rawQuery.length < lastRawQueryRef.current.length;\n const charDiff = Math.abs(rawQuery.length - lastRawQueryRef.current.length);\n if (isDeleting || charDiff >= minDiff) {\n doFetch(rawQuery, updatedParams);\n return true;\n }\n return false;\n };\n\n debounceRef.current = setTimeout(() => {\n if (attemptFetch(MIN_CHARS_DIFF)) {\n if (slowDebounceRef.current) clearTimeout(slowDebounceRef.current);\n }\n }, DEBOUNCE_MS);\n\n slowDebounceRef.current = setTimeout(() => attemptFetch(1), SLOW_DEBOUNCE_MS);\n\n return () => {\n if (debounceRef.current) clearTimeout(debounceRef.current);\n if (slowDebounceRef.current) clearTimeout(slowDebounceRef.current);\n };\n }, [\n text,\n completedParams,\n doFetch,\n filterBaseRef,\n skipNextFetchRef,\n suggestionsRef,\n lastRawQueryRef,\n ]);\n}\n","import type {\n APIConfig,\n AutocompleteRequest,\n AutocompleteResponse,\n CompletedParam,\n CompletedParamState,\n} from \"../types\";\n\n// Replaced at build time by tsup/vitest `define` config with the package.json version.\ndeclare const __SDK_VERSION__: string;\nconst SDK_VERSION = __SDK_VERSION__;\n\nlet hasWarnedMissingKey = false;\n\nfunction generateRequestId(): string {\n return crypto.randomUUID();\n}\n\nfunction toWireParam(param: CompletedParamState, includeText: boolean): CompletedParam {\n return {\n placeholder: param.placeholder,\n type: param.type,\n ...(includeText && { text: param.text }),\n kind: param.kind,\n };\n}\n\nexport async function fetchSuggestions(\n rawQuery: string,\n completedParams: CompletedParamState[],\n options?: {\n maskCompletedText?: boolean;\n signal?: AbortSignal;\n apiConfig?: APIConfig;\n },\n): Promise<AutocompleteResponse> {\n const apiConfig = options?.apiConfig;\n const apiKey = apiConfig?.apiKey ?? \"\";\n if (!apiKey && !hasWarnedMissingKey) {\n hasWarnedMissingKey = true;\n // biome-ignore lint/suspicious/noConsole: intentional dev warning\n console.warn(\n \"[AIAutocomplete] No apiKey in apiConfig. Requests will be sent without an Authorization header.\",\n );\n }\n const authScheme = apiConfig?.authScheme ?? \"Bearer\";\n const includeText = !options?.maskCompletedText;\n\n const rawCount = completedParams.find(\n (p) => p.type === \"contact\" && p.metadata?.contact_account_count,\n )?.metadata?.contact_account_count;\n const contactAccountCount = typeof rawCount === \"number\" ? rawCount : undefined;\n\n const body: AutocompleteRequest = {\n data: {\n raw_query: rawQuery,\n completed_params: completedParams.map((p) => toWireParam(p, includeText)),\n ...(contactAccountCount != null && { contact_account_count: contactAccountCount }),\n },\n meta: {\n request_id: generateRequestId(),\n request_at: new Date().toISOString(),\n language: typeof navigator !== \"undefined\" ? navigator.language : \"en-US\",\n client_version: SDK_VERSION,\n },\n };\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n ...(apiConfig?.appIdentifier && { \"X-App-Identifier\": apiConfig.appIdentifier }),\n ...apiConfig?.headers,\n };\n if (apiKey) {\n headers.Authorization = authScheme === \"Basic\" ? `Basic ${btoa(apiKey)}` : `Bearer ${apiKey}`;\n }\n\n const response = await fetch(apiConfig?.endpoint ?? \"/ac/suggest\", {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n signal: options?.signal,\n });\n\n if (!response.ok) {\n throw new Error(`API error: ${response.status} ${response.statusText}`);\n }\n\n return response.json() as Promise<AutocompleteResponse>;\n}\n","import type { CompletedParamState } from \"../types\";\n\ninterface BuildQueryResult {\n rawQuery: string;\n completedParams: CompletedParamState[];\n}\n\n/**\n * Takes the raw input text and completed params (without placeholders),\n * replaces each completed param's text in the string with a {{TYPE_N}} token,\n * and returns the transformed query + params with placeholders filled in.\n *\n * Replacements happen left-to-right, first occurrence only per param.\n * Counter is per-type (e.g. {{TASK_1}}, {{GOAL_1}}, {{GOAL_2}}).\n */\nexport function buildQuery(text: string, completedParams: CompletedParamState[]): BuildQueryResult {\n let result = text;\n const typeCounts: Record<string, number> = {};\n const updatedParams: CompletedParamState[] = [];\n\n for (const param of completedParams) {\n const count = (typeCounts[param.type] ?? 0) + 1;\n typeCounts[param.type] = count;\n\n const typeKey = param.type.toUpperCase().replace(/\\s+/g, \"_\");\n const placeholder = `{{${typeKey}_${count}}}`;\n\n // Replace first occurrence of the param text in the string\n const index = result.indexOf(param.text);\n if (index !== -1) {\n result = result.slice(0, index) + placeholder + result.slice(index + param.text.length);\n }\n\n updatedParams.push({ ...param, placeholder });\n }\n\n return { rawQuery: result, completedParams: updatedParams };\n}\n","import type { Suggestion, SuggestionOption } from \"../types\";\n\n/**\n * Applies option overrides by calling the override function with an empty query,\n * then prepending results to suggestions that match by type, deduplicating by text.\n */\nexport function applyOptionOverrides(\n suggestions: Suggestion[],\n overrides?: Record<string, (query: string) => SuggestionOption[]>,\n): Suggestion[] {\n if (!overrides) return suggestions;\n return suggestions.map((s) => {\n const fn = overrides[s.type];\n if (!fn) return s;\n const extra = fn(\"\");\n if (extra.length === 0) return s;\n const existingTexts = new Set(extra.map((o) => o.text));\n const deduped = (s.options ?? []).filter((o) => !existingTexts.has(o.text));\n return { ...s, options: [...extra, ...deduped] };\n });\n}\n","import { type KeyboardEvent, type MutableRefObject, useCallback } from \"react\";\nimport type {\n AutocompleteResult,\n CompletedParamState,\n Suggestion,\n SuggestionOption,\n} from \"../types\";\nimport { buildQuery } from \"../utils/buildQuery\";\n\ninterface UseAutocompleteKeyboardOptions {\n activeDropdownIndex: number;\n setActiveDropdownIndex: (index: number) => void;\n filteredOptions: SuggestionOption[];\n selectOption: (option: SuggestionOption) => void;\n onSubmitRef: MutableRefObject<((result: AutocompleteResult) => void) | undefined>;\n text: string;\n completedParams: CompletedParamState[];\n isDropdownOpen: boolean;\n hasPlaceholder: boolean;\n placeholderText: string;\n suggestions: Suggestion[];\n filterBaseRef: MutableRefObject<number>;\n columns: number;\n setText: (value: string) => void;\n setCompletedParams: (fn: (prev: CompletedParamState[]) => CompletedParamState[]) => void;\n setSuggestions: (fn: (prev: Suggestion[]) => Suggestion[]) => void;\n}\n\nexport function useAutocompleteKeyboard({\n activeDropdownIndex,\n setActiveDropdownIndex,\n filteredOptions,\n selectOption,\n onSubmitRef,\n text,\n completedParams,\n isDropdownOpen,\n hasPlaceholder,\n placeholderText,\n suggestions,\n filterBaseRef,\n columns,\n setText,\n setCompletedParams,\n setSuggestions,\n}: UseAutocompleteKeyboardOptions) {\n const getTappableIndices = useCallback(() => {\n const tappable = filteredOptions\n .map((o, i) => (o.is_tappable ? i : -1))\n .filter((i) => i !== -1);\n // Column-first ordering: all column-0 items, then column-1, etc.\n const buckets: number[][] = Array.from({ length: columns }, () => []);\n for (const i of tappable) buckets[i % columns].push(i);\n return buckets.flat();\n }, [filteredOptions, columns]);\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLTextAreaElement>) => {\n const tappableIndices = getTappableIndices();\n\n switch (e.key) {\n case \"ArrowDown\": {\n e.preventDefault();\n if (tappableIndices.length === 0) return;\n const currentPos = tappableIndices.indexOf(activeDropdownIndex);\n const nextPos = currentPos < tappableIndices.length - 1 ? currentPos + 1 : 0;\n setActiveDropdownIndex(tappableIndices[nextPos]);\n break;\n }\n case \"ArrowUp\": {\n e.preventDefault();\n if (tappableIndices.length === 0) return;\n const currentPos = tappableIndices.indexOf(activeDropdownIndex);\n const prevPos = currentPos > 0 ? currentPos - 1 : tappableIndices.length - 1;\n setActiveDropdownIndex(tappableIndices[prevPos]);\n break;\n }\n case \"ArrowRight\": {\n if (activeDropdownIndex < 0) break;\n const col = activeDropdownIndex % columns;\n if (col < columns - 1) {\n const rightNeighbor = activeDropdownIndex + 1;\n if (\n rightNeighbor < filteredOptions.length &&\n filteredOptions[rightNeighbor]?.is_tappable\n ) {\n e.preventDefault();\n setActiveDropdownIndex(rightNeighbor);\n }\n }\n break;\n }\n case \"ArrowLeft\": {\n if (activeDropdownIndex < 0) break;\n if (activeDropdownIndex % columns > 0) {\n const leftNeighbor = activeDropdownIndex - 1;\n if (leftNeighbor >= 0 && filteredOptions[leftNeighbor]?.is_tappable) {\n e.preventDefault();\n setActiveDropdownIndex(leftNeighbor);\n }\n }\n break;\n }\n case \"Enter\": {\n e.preventDefault();\n if (activeDropdownIndex >= 0 && filteredOptions[activeDropdownIndex]?.is_tappable) {\n selectOption(filteredOptions[activeDropdownIndex]);\n } else if (onSubmitRef.current) {\n const { rawQuery, completedParams: finalParams } = buildQuery(text, completedParams);\n const result: AutocompleteResult = {\n query: text.trim(),\n raw_query: rawQuery,\n completed_params: finalParams,\n };\n onSubmitRef.current(result);\n }\n break;\n }\n case \"Tab\": {\n if (activeDropdownIndex >= 0 && filteredOptions[activeDropdownIndex]?.is_tappable) {\n e.preventDefault();\n selectOption(filteredOptions[activeDropdownIndex]);\n } else if (isDropdownOpen) {\n const firstTappable = filteredOptions.find((o) => o.is_tappable);\n if (firstTappable) {\n e.preventDefault();\n selectOption(firstTappable);\n }\n } else if (!text && hasPlaceholder) {\n e.preventDefault();\n const placeholderSuggestion = suggestions.find((s) => s.type === \"placeholder\");\n if (placeholderSuggestion) {\n setText(placeholderText);\n filterBaseRef.current = placeholderText.length;\n setCompletedParams((prev) => [\n ...prev,\n {\n id: crypto.randomUUID(),\n placeholder: \"\",\n type: placeholderSuggestion.type,\n text: placeholderText,\n kind: null,\n suggestionType: placeholderSuggestion.type,\n suggestionPlaceholder: placeholderSuggestion.text,\n options: placeholderSuggestion.options ?? [],\n },\n ]);\n setSuggestions((prev) => prev.filter((s) => s !== placeholderSuggestion));\n } else {\n setText(placeholderText);\n filterBaseRef.current = placeholderText.length;\n }\n }\n break;\n }\n case \"Escape\":\n setActiveDropdownIndex(-1);\n break;\n }\n },\n [\n activeDropdownIndex,\n columns,\n completedParams,\n filteredOptions,\n filterBaseRef,\n getTappableIndices,\n hasPlaceholder,\n isDropdownOpen,\n onSubmitRef,\n placeholderText,\n selectOption,\n setActiveDropdownIndex,\n setCompletedParams,\n setSuggestions,\n setText,\n suggestions,\n text,\n ],\n );\n\n return { handleKeyDown, getTappableIndices };\n}\n","import { type MutableRefObject, useCallback } from \"react\";\nimport type { CompletedParamState, Suggestion } from \"../types\";\n\ninterface UseAutocompletePillsOptions {\n completedParams: CompletedParamState[];\n suggestions: Suggestion[];\n setCompletedParams: (fn: (prev: CompletedParamState[]) => CompletedParamState[]) => void;\n setSuggestions: (fn: Suggestion[] | ((prev: Suggestion[]) => Suggestion[])) => void;\n setActiveDropdownIndex: (index: number) => void;\n filterBaseRef: MutableRefObject<number>;\n pillTappedRef: MutableRefObject<boolean>;\n}\n\nexport function useAutocompletePills({\n completedParams,\n suggestions,\n setCompletedParams,\n setSuggestions,\n setActiveDropdownIndex,\n filterBaseRef,\n pillTappedRef,\n}: UseAutocompletePillsOptions) {\n const setActivePill = useCallback(\n (index: number) => {\n const actionable = suggestions.filter((s) => s.type !== \"placeholder\");\n if (index < 0 || index >= actionable.length) return;\n const moved = actionable[index];\n const rest = actionable.filter((_, i) => i !== index);\n const placeholders = suggestions.filter((s) => s.type === \"placeholder\");\n setSuggestions([...placeholders, moved, ...rest]);\n pillTappedRef.current = true;\n setActiveDropdownIndex(-1);\n },\n [suggestions, setSuggestions, setActiveDropdownIndex, pillTappedRef],\n );\n\n const removeLastParam = useCallback(() => {\n if (completedParams.length === 0) return;\n const lastParam = completedParams[completedParams.length - 1];\n const restoredSuggestion: Suggestion = {\n type: lastParam.suggestionType,\n text: lastParam.suggestionPlaceholder,\n required: true,\n options: lastParam.options,\n };\n setCompletedParams((prev) => prev.slice(0, -1));\n setSuggestions((prev: Suggestion[]) => [restoredSuggestion, ...prev]);\n setActiveDropdownIndex(-1);\n }, [completedParams, setCompletedParams, setSuggestions, setActiveDropdownIndex]);\n\n const reEditParam = useCallback(\n (param: CompletedParamState) => {\n const restoredSuggestion: Suggestion = {\n type: param.suggestionType,\n text: param.suggestionPlaceholder,\n required: true,\n options: param.options,\n };\n return {\n apply: (setText: (fn: (prev: string) => string) => void) => {\n setText((prev) => {\n let pos = 0;\n for (const p of completedParams) {\n const idx = prev.indexOf(p.text, pos);\n if (idx === -1) continue;\n if (p.id === param.id) {\n const before = prev.slice(0, idx);\n const after = prev.slice(idx + param.text.length);\n const cleaned = (before + after).replace(/ {2,}/g, \" \");\n filterBaseRef.current = Math.min(filterBaseRef.current, cleaned.length);\n return cleaned;\n }\n pos = idx + p.text.length;\n }\n return prev;\n });\n setCompletedParams((prev) => prev.filter((p) => p.id !== param.id));\n setSuggestions((prev: Suggestion[]) => [restoredSuggestion, ...prev]);\n setActiveDropdownIndex(-1);\n pillTappedRef.current = true;\n },\n };\n },\n [\n completedParams,\n setCompletedParams,\n setSuggestions,\n setActiveDropdownIndex,\n filterBaseRef,\n pillTappedRef,\n ],\n );\n\n return { setActivePill, removeLastParam, reEditParam };\n}\n"],"mappings":"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","names":["index_exports","__export","AIAutocomplete","AIAutocompleteDropdown","useAIAutocomplete","__toCommonJS","import_react","s","AIAutocomplete_module_css_default","s","AIAutocompleteDropdown_module_css_default","s","SuggestionGrid_module_css_default","s","SuggestionItem_module_css_default","import_jsx_runtime","SuggestionItem","option","isHighlighted","onSelect","onHighlight","id","className","SuggestionItem_module_css_default","e","import_jsx_runtime","SuggestionGrid","options","activeIndex","onSelect","onHighlight","listboxId","SuggestionGrid_module_css_default","option","i","SuggestionItem","import_jsx_runtime","AIAutocompleteDropdown","suggestions","activeIndex","onSelect","onHighlight","isOpen","id","className","options","hasOptions","AIAutocompleteDropdown_module_css_default","e","SuggestionGrid","s","PillList_module_css_default","import_jsx_runtime","getPillOpacity","index","PillList","pills","activePillIndex","onSelectPill","PillList_module_css_default","pill","i","import_react","filterOptions","options","query","trimmed","lower","findExactMatch","deriveSegments","text","completedParams","result","pos","param","idx","remaining","reconcileParams","valid","invalid","import_react","SDK_VERSION","hasWarnedMissingKey","generateRequestId","toWireParam","param","includeText","fetchSuggestions","rawQuery","completedParams","options","apiConfig","apiKey","authScheme","rawCount","p","contactAccountCount","body","headers","response","buildQuery","text","completedParams","result","typeCounts","updatedParams","param","count","placeholder","index","applyOptionOverrides","suggestions","overrides","s","fn","extra","existingTexts","o","deduped","DEBOUNCE_MS","SLOW_DEBOUNCE_MS","MIN_CHARS_DIFF","useAutocompleteFetch","textRef","suggestionsRef","filterBaseRef","maskCompletedTextRef","apiConfigRef","optionOverridesRef","onErrorRef","setCompletedParams","setSuggestions","setActiveDropdownIndex","isLoading","setIsLoading","error","setError","isReady","setIsReady","fetchVersionRef","abortRef","lastRawQueryRef","doFetch","rawQuery","completed","controller","version","textAtRequest","s","res","fetchSuggestions","newSuggestions","applyOptionOverrides","input","lastInput","currentText","inProgressIdx","active","query","match","findExactMatch","prev","err","caughtError","useDebouncedFetch","text","completedParams","skipNextFetchRef","debounceRef","slowDebounceRef","hasFetchedRef","attemptFetch","minDiff","currentQuery","tappableFiltered","filterOptions","o","hasExactMatch","isInFilterZone","updatedParams","buildQuery","isDeleting","charDiff","import_react","useAutocompleteKeyboard","activeDropdownIndex","setActiveDropdownIndex","filteredOptions","selectOption","onSubmitRef","text","completedParams","isDropdownOpen","hasPlaceholder","placeholderText","suggestions","filterBaseRef","columns","setText","setCompletedParams","setSuggestions","getTappableIndices","tappable","o","i","buckets","e","tappableIndices","currentPos","nextPos","prevPos","rightNeighbor","leftNeighbor","rawQuery","finalParams","buildQuery","result","firstTappable","placeholderSuggestion","s","prev","import_react","useAutocompletePills","completedParams","suggestions","setCompletedParams","setSuggestions","setActiveDropdownIndex","filterBaseRef","pillTappedRef","setActivePill","index","actionable","s","moved","rest","_","i","placeholders","removeLastParam","lastParam","restoredSuggestion","prev","reEditParam","param","setText","pos","p","idx","before","after","cleaned","idCounter","useStableId","id","useAIAutocomplete","onSubmit","onError","optionOverrides","maskCompletedText","customPlaceholder","apiConfig","columns","eagerSuggestions","controlledValue","controlledParams","onChangeProp","onParamsChange","isTextControlled","isParamsControlled","internalText","setInternalText","internalCompletedParams","setInternalCompletedParams","suggestions","setSuggestions","activeDropdownIndex","setActiveDropdownIndex","text","completedParams","onSubmitRef","onChangeRef","onParamsChangeRef","controlledValueRef","controlledParamsRef","setText","value","newVal","prev","setCompletedParams","onErrorRef","optionOverridesRef","maskCompletedTextRef","apiConfigRef","textRef","suggestionsRef","filterBaseRef","pillTappedRef","skipNextFetchRef","listboxId","doFetch","isLoading","error","isReady","lastRawQueryRef","useAutocompleteFetch","useDebouncedFetch","segments","deriveSegments","filterQuery","placeholderText","s","actionableSuggestions","activeSuggestion","overrideFn","baseOptions","filteredOptions","filterOptions","hasPlaceholder","isDropdownOpen","selectOption","option","completed","base","prefix","lastWord","needsSpace","newText","remainingActionable","handleChange","e","raw","newValue","valid","invalid","reconcileParams","param","newFilterQuery","match","findExactMatch","handleKeyDown","useAutocompleteKeyboard","pills","useAutocompletePills","reEditParam","reset","activeDescendantId","import_jsx_runtime","AIAutocomplete","onSubmit","onError","optionOverrides","maskCompletedText","placeholder","className","apiConfig","columns","eagerSuggestions","value","controlledParams","onChangeProp","onParamsChange","ref","textareaRef","handleSubmitRef","completedParams","suggestionPills","setActivePill","segments","inputProps","dropdownProps","reset","useAIAutocomplete","result","handleContainerClick","canSubmit","handleSubmit","rawQuery","finalParams","buildQuery","onChange","inputPlaceholder","restProps","isEmpty","AIAutocomplete_module_css_default","AIAutocompleteDropdown","seg","i","PillList","e"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/AIAutocomplete.tsx","css-module:/Users/saharshv/MagicX/ai-autocomplete-react/src/AIAutocomplete.module.css.js","css-module:/Users/saharshv/MagicX/ai-autocomplete-react/src/AIAutocompleteDropdown.module.css.js","css-module:/Users/saharshv/MagicX/ai-autocomplete-react/src/components/SuggestionGrid.module.css.js","css-module:/Users/saharshv/MagicX/ai-autocomplete-react/src/components/SuggestionItem.module.css.js","../src/components/SuggestionItem.tsx","../src/components/SuggestionGrid.tsx","../src/AIAutocompleteDropdown.tsx","css-module:/Users/saharshv/MagicX/ai-autocomplete-react/src/components/PillList.module.css.js","../src/components/PillList.tsx","../src/hooks/useAIAutocomplete.ts","../src/utils/filtering.ts","../src/utils/segments.ts","../src/hooks/useAutocompleteFetch.ts","../src/utils/api.ts","../src/utils/buildQuery.ts","../src/utils/overrides.ts","../src/hooks/useAutocompleteKeyboard.ts","../src/hooks/useAutocompletePills.ts"],"sourcesContent":["export { AIAutocomplete } from \"./AIAutocomplete\";\nexport { AIAutocompleteDropdown } from \"./AIAutocompleteDropdown\";\nexport { useAIAutocomplete } from \"./hooks/useAIAutocomplete\";\nexport type {\n AIAutocompleteDropdownProps,\n AIAutocompleteHandle,\n AIAutocompleteProps,\n APIConfig,\n AutocompleteResult,\n CompletedParam,\n CompletedParamState,\n OptionOverrides,\n Segment,\n Suggestion,\n SuggestionOption,\n TaskKind,\n UseAIAutocompleteOptions,\n UseAIAutocompleteReturn,\n} from \"./types\";\n","import { forwardRef, useCallback, useEffect, useImperativeHandle, useRef } from \"react\";\nimport styles from \"./AIAutocomplete.module.css\";\nimport { AIAutocompleteDropdown } from \"./AIAutocompleteDropdown\";\nimport { PillList } from \"./components/PillList\";\nimport { useAIAutocomplete } from \"./hooks/useAIAutocomplete\";\nimport type { AIAutocompleteHandle, AIAutocompleteProps, AutocompleteResult } from \"./types\";\nimport { buildQuery } from \"./utils/buildQuery\";\n\nexport const AIAutocomplete = forwardRef<AIAutocompleteHandle, AIAutocompleteProps>(\n function AIAutocomplete(\n {\n onSubmit,\n onError,\n optionOverrides,\n maskCompletedText,\n placeholder,\n className,\n apiConfig,\n columns,\n eagerSuggestions,\n value,\n completedParams: controlledParams,\n onChange: onChangeProp,\n onParamsChange,\n },\n ref,\n ) {\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n // Render-phase ref assignment — matches the pattern in useAIAutocomplete.ts\n const handleSubmitRef = useRef<(result: AutocompleteResult) => void>(() => {});\n\n useEffect(() => {\n textareaRef.current?.focus();\n }, []);\n\n const {\n completedParams,\n suggestionPills,\n setActivePill,\n segments,\n inputProps,\n dropdownProps,\n reset,\n } = useAIAutocomplete({\n onSubmit: (result) => handleSubmitRef.current(result),\n onError,\n optionOverrides,\n maskCompletedText,\n placeholder,\n apiConfig,\n columns,\n eagerSuggestions,\n value,\n completedParams: controlledParams,\n onChange: onChangeProp,\n onParamsChange,\n });\n\n useImperativeHandle(\n ref,\n () => ({\n focus: () => textareaRef.current?.focus(),\n reset,\n }),\n [reset],\n );\n\n const handleContainerClick = () => {\n textareaRef.current?.focus();\n };\n\n const canSubmit = !!inputProps.value || completedParams.length > 0;\n\n const handleSubmit = useCallback(() => {\n if (!canSubmit) return;\n const { rawQuery, completedParams: finalParams } = buildQuery(\n inputProps.value,\n completedParams,\n );\n onSubmit({\n query: inputProps.value.trim(),\n raw_query: rawQuery,\n completed_params: finalParams,\n });\n reset();\n }, [canSubmit, inputProps.value, completedParams, onSubmit, reset]);\n\n handleSubmitRef.current = handleSubmit;\n\n const { onChange, placeholder: inputPlaceholder, ...restProps } = inputProps;\n const isEmpty = !inputProps.value;\n\n return (\n <div className={`${styles.container} ${className ?? \"\"}`}>\n <AIAutocompleteDropdown {...dropdownProps} />\n {/* biome-ignore lint/a11y/useKeyWithClickEvents: container click delegates to textarea focus */}\n {/* biome-ignore lint/a11y/noStaticElementInteractions: wrapper delegates focus to textarea */}\n <div className={styles.inputWrapper} onClick={handleContainerClick}>\n <div className={styles.editorArea}>\n <div className={styles.sizerContent} aria-hidden=\"true\">\n {isEmpty && inputPlaceholder ? (\n <span className={styles.placeholderText}>{inputPlaceholder} </span>\n ) : (\n <span className={styles.sizerText}>\n {segments.map((seg, i) => (\n // biome-ignore lint/suspicious/noArrayIndexKey: segments are positional and don't reorder\n <span key={`${i}-${seg.type}`}>{seg.value}</span>\n ))}\n {segments.length === 0 && \"\\u00A0\"}\n </span>\n )}\n {\" \"}\n <PillList pills={suggestionPills} activePillIndex={0} onSelectPill={setActivePill} />\n </div>\n <textarea\n ref={textareaRef}\n className={styles.textarea}\n rows={1}\n onChange={onChange}\n {...restProps}\n />\n </div>\n <button\n type=\"button\"\n className={styles.submitButton}\n disabled={!canSubmit}\n onClick={(e) => {\n e.stopPropagation();\n handleSubmit();\n }}\n aria-label=\"Submit\"\n >\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 18 18\"\n fill=\"none\"\n role=\"img\"\n aria-label=\"Submit\"\n >\n <path\n d=\"M9 14V4M9 4L4 9M9 4L14 9\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n </button>\n </div>\n </div>\n );\n },\n);\n","if (typeof document !== \"undefined\" && !document.getElementById(\"ac-style-cc65f4cc\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-cc65f4cc\";\n s.textContent = `.AIAutocomplete-module_container_KKjFU {\n position: relative;\n font-family: \"IBM Plex Sans\", sans-serif;\n}\n\n.AIAutocomplete-module_inputWrapper_FLq1b {\n min-height: 60px;\n padding: 24px;\n border: 1px solid var(--ac-color-border-default, #9ea5b2);\n border-radius: 23px;\n background: transparent;\n overflow: hidden;\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.AIAutocomplete-module_editorArea_7rBWq {\n position: relative;\n flex: 1;\n min-width: 0;\n}\n\n.AIAutocomplete-module_sizerContent_DQgmV {\n position: relative;\n z-index: 1;\n pointer-events: none;\n min-height: 60px;\n white-space: pre-wrap;\n word-break: break-word;\n font-family: inherit;\n font-size: 21px;\n line-height: 38px;\n}\n\n.AIAutocomplete-module_sizerText_iZIMK {\n color: transparent;\n}\n\n.AIAutocomplete-module_placeholderText_K3ayy {\n color: var(--ac-color-text-muted, #c1c4cb);\n opacity: 0.7;\n}\n\n.AIAutocomplete-module_textarea_eyn6A {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n padding: 0;\n border: none;\n background: transparent;\n color: var(--ac-color-text-default, #fff);\n caret-color: var(--ac-color-text-default, #fff);\n font-family: inherit;\n font-size: 21px;\n line-height: 38px;\n white-space: pre-wrap;\n word-break: break-word;\n outline: none;\n resize: none;\n overflow: hidden;\n}\n\n.AIAutocomplete-module_textarea_eyn6A::placeholder {\n color: var(--ac-color-text-muted, #c1c4cb);\n}\n\n.AIAutocomplete-module_submitButton_sl1Mi {\n flex-shrink: 0;\n width: 36px;\n height: 36px;\n border-radius: 50%;\n border: none;\n background: var(--ac-color-text-default, #fff);\n color: var(--ac-color-bg-default, #000);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n transition: opacity 0.2s ease;\n}\n\n.AIAutocomplete-module_submitButton_sl1Mi:hover {\n opacity: 0.85;\n}\n`;\n document.head.appendChild(s);\n}\nexport default {\"container\":\"AIAutocomplete-module_container_KKjFU\",\"inputWrapper\":\"AIAutocomplete-module_inputWrapper_FLq1b\",\"editorArea\":\"AIAutocomplete-module_editorArea_7rBWq\",\"sizerContent\":\"AIAutocomplete-module_sizerContent_DQgmV\",\"sizerText\":\"AIAutocomplete-module_sizerText_iZIMK\",\"placeholderText\":\"AIAutocomplete-module_placeholderText_K3ayy\",\"textarea\":\"AIAutocomplete-module_textarea_eyn6A\",\"submitButton\":\"AIAutocomplete-module_submitButton_sl1Mi\"};","if (typeof document !== \"undefined\" && !document.getElementById(\"ac-style-2eef895d\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-2eef895d\";\n s.textContent = `.AIAutocompleteDropdown-module_dropdown_yz2KC {\n position: absolute;\n left: 0;\n right: 0;\n top: 100%;\n margin-top: 6px;\n background: var(--ac-color-background-default, #00002d);\n border-radius: 23px;\n overflow: hidden;\n z-index: 10;\n opacity: 0;\n pointer-events: none;\n transition: opacity 400ms cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.AIAutocompleteDropdown-module_visible_QCoXj {\n opacity: 1;\n pointer-events: auto;\n}\n`;\n document.head.appendChild(s);\n}\nexport default {\"dropdown\":\"AIAutocompleteDropdown-module_dropdown_yz2KC\",\"visible\":\"AIAutocompleteDropdown-module_visible_QCoXj\"};","if (typeof document !== \"undefined\" && !document.getElementById(\"ac-style-d91f2b06\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-d91f2b06\";\n s.textContent = `.SuggestionGrid-module_grid_jvaPb {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 12px 18px;\n padding: 18px 24px;\n max-height: 192px;\n overflow-y: auto;\n scrollbar-width: thin;\n scrollbar-color: rgba(255, 255, 255, 0.3) transparent;\n}\n\n.SuggestionGrid-module_grid_jvaPb::-webkit-scrollbar {\n width: 6px;\n}\n\n.SuggestionGrid-module_grid_jvaPb::-webkit-scrollbar-track {\n background: transparent;\n}\n\n.SuggestionGrid-module_grid_jvaPb::-webkit-scrollbar-thumb {\n background: rgba(255, 255, 255, 0.3);\n border-radius: 3px;\n}\n`;\n document.head.appendChild(s);\n}\nexport default {\"grid\":\"SuggestionGrid-module_grid_jvaPb\"};","if (typeof document !== \"undefined\" && !document.getElementById(\"ac-style-f6bdc634\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-f6bdc634\";\n s.textContent = `.SuggestionItem-module_item_d4vpD {\n display: flex;\n align-items: center;\n font-family: \"IBM Plex Sans\", sans-serif;\n font-size: 21px;\n line-height: 30px;\n color: var(--ac-color-text-muted, #c1c4cb);\n white-space: nowrap;\n opacity: 0.35;\n animation: SuggestionItem-module_fadeIn_I8u35 400ms cubic-bezier(0.4, 0, 0.2, 1) forwards;\n}\n\n@keyframes SuggestionItem-module_fadeIn_I8u35 {\n from {\n opacity: 0;\n }\n}\n\n.SuggestionItem-module_tappable_70KcX {\n cursor: pointer;\n}\n\n.SuggestionItem-module_tappable_70KcX:hover {\n color: var(--ac-color-text-default, #fff);\n}\n\n.SuggestionItem-module_nonTappable_xSZM- {\n cursor: default;\n opacity: 0.3;\n}\n\n.SuggestionItem-module_highlighted_Hb0SU {\n color: var(--ac-color-text-default, #fff);\n opacity: 0.5;\n}\n\n.SuggestionItem-module_tag_e3Fwe {\n font-size: 13px;\n margin-left: 6px;\n opacity: 0.5;\n}\n`;\n document.head.appendChild(s);\n}\nexport default {\"item\":\"SuggestionItem-module_item_d4vpD\",\"fadeIn\":\"SuggestionItem-module_fadeIn_I8u35\",\"tappable\":\"SuggestionItem-module_tappable_70KcX\",\"nonTappable\":\"SuggestionItem-module_nonTappable_xSZM-\",\"highlighted\":\"SuggestionItem-module_highlighted_Hb0SU\",\"tag\":\"SuggestionItem-module_tag_e3Fwe\"};","import type { SuggestionOption } from \"../types\";\nimport styles from \"./SuggestionItem.module.css\";\n\ninterface SuggestionItemProps {\n option: SuggestionOption;\n isHighlighted: boolean;\n onSelect: (option: SuggestionOption) => void;\n onHighlight: () => void;\n id: string;\n}\n\nexport function SuggestionItem({\n option,\n isHighlighted,\n onSelect,\n onHighlight,\n id,\n}: SuggestionItemProps) {\n const className = [\n styles.item,\n isHighlighted ? styles.highlighted : \"\",\n option.is_tappable ? styles.tappable : styles.nonTappable,\n ]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <div\n id={id}\n role=\"option\"\n aria-selected={isHighlighted}\n className={className}\n tabIndex={option.is_tappable ? 0 : -1}\n onClick={() => option.is_tappable && onSelect(option)}\n onKeyDown={(e) => {\n if (option.is_tappable && (e.key === \"Enter\" || e.key === \" \")) {\n e.preventDefault();\n onSelect(option);\n }\n }}\n onMouseEnter={onHighlight}\n >\n {option.icon ? `${option.icon} ${option.text}` : option.text}\n {option.tag && <span className={styles.tag}>{option.tag}</span>}\n </div>\n );\n}\n","import type { SuggestionOption } from \"../types\";\nimport styles from \"./SuggestionGrid.module.css\";\nimport { SuggestionItem } from \"./SuggestionItem\";\n\ninterface SuggestionGridProps {\n options: SuggestionOption[];\n activeIndex: number;\n onSelect: (option: SuggestionOption) => void;\n onHighlight: (index: number) => void;\n listboxId: string;\n}\n\nexport function SuggestionGrid({\n options,\n activeIndex,\n onSelect,\n onHighlight,\n listboxId,\n}: SuggestionGridProps) {\n return (\n <div className={styles.grid}>\n {options.map((option, i) => (\n <SuggestionItem\n key={option.text}\n option={option}\n isHighlighted={i === activeIndex}\n onSelect={onSelect}\n onHighlight={() => onHighlight(i)}\n id={`${listboxId}-option-${i}`}\n />\n ))}\n </div>\n );\n}\n","import styles from \"./AIAutocompleteDropdown.module.css\";\nimport { SuggestionGrid } from \"./components/SuggestionGrid\";\nimport type { AIAutocompleteDropdownProps } from \"./types\";\n\nexport function AIAutocompleteDropdown({\n suggestions,\n activeIndex,\n onSelect,\n onHighlight,\n isOpen,\n id,\n className,\n}: AIAutocompleteDropdownProps) {\n const activeSuggestion = suggestions[0];\n const options = activeSuggestion?.options ?? [];\n const hasOptions = isOpen && options.length > 0;\n\n return (\n <div\n id={id}\n role=\"listbox\"\n className={`${styles.dropdown} ${hasOptions ? styles.visible : \"\"} ${className ?? \"\"}`}\n onMouseDown={(e) => e.preventDefault()}\n >\n {options.length > 0 && (\n <SuggestionGrid\n options={options}\n activeIndex={activeIndex}\n onSelect={onSelect}\n onHighlight={onHighlight}\n listboxId={id}\n />\n )}\n </div>\n );\n}\n","if (typeof document !== \"undefined\" && !document.getElementById(\"ac-style-b745b4fb\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-b745b4fb\";\n s.textContent = `.PillList-module_list_qvLqO {\n position: relative;\n z-index: 1;\n pointer-events: auto;\n display: inline-flex;\n gap: 5px;\n align-items: center;\n vertical-align: middle;\n transform: translateY(-3px);\n}\n\n.PillList-module_pill_osSyz {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n height: 36px;\n padding: 7px 9px;\n border: none;\n border-radius: 6px;\n background: var(--ac-color-background-supportive, #313255);\n color: var(--ac-color-text-muted, #c1c4cb);\n font-family: \"IBM Plex Sans\", sans-serif;\n font-size: 21px;\n line-height: 30px;\n cursor: pointer;\n white-space: nowrap;\n animation: PillList-module_fadeIn_Aezob 400ms cubic-bezier(0.4, 0, 0.2, 1) forwards;\n}\n\n.PillList-module_pill_osSyz:hover {\n filter: brightness(1.2);\n}\n\n.PillList-module_active_Oll-- {\n outline: 1px solid #5a5b8a;\n}\n\n@keyframes PillList-module_fadeIn_Aezob {\n from {\n opacity: 0;\n }\n}\n`;\n document.head.appendChild(s);\n}\nexport default {\"list\":\"PillList-module_list_qvLqO\",\"pill\":\"PillList-module_pill_osSyz\",\"fadeIn\":\"PillList-module_fadeIn_Aezob\",\"active\":\"PillList-module_active_Oll--\"};","import type { Suggestion } from \"../types\";\nimport styles from \"./PillList.module.css\";\n\ninterface PillListProps {\n pills: Suggestion[];\n activePillIndex: number;\n onSelectPill: (index: number) => void;\n}\n\nfunction getPillOpacity(index: number): number {\n if (index === 0) return 0.4;\n if (index === 1) return 0.3;\n return 0.15;\n}\n\nexport function PillList({ pills, activePillIndex, onSelectPill }: PillListProps) {\n return (\n <span className={styles.list}>\n {pills.map((pill, i) => (\n <button\n key={`${pill.type}-${pill.text}`}\n type=\"button\"\n className={`${styles.pill} ${i === activePillIndex ? styles.active : \"\"}`}\n style={{ opacity: getPillOpacity(i) }}\n onClick={() => onSelectPill(i)}\n >\n {pill.text}\n </button>\n ))}\n </span>\n );\n}\n","import { type ChangeEvent, useCallback, useMemo, useRef, useState } from \"react\";\nimport type {\n CompletedParamState,\n Suggestion,\n SuggestionOption,\n UseAIAutocompleteOptions,\n UseAIAutocompleteReturn,\n} from \"../types\";\nimport { extractFilterQuery, filterOptions, findExactMatch } from \"../utils/filtering\";\nimport { deriveSegments, reconcileParams } from \"../utils/segments\";\nimport { useAutocompleteFetch, useDebouncedFetch } from \"./useAutocompleteFetch\";\nimport { useAutocompleteKeyboard } from \"./useAutocompleteKeyboard\";\nimport { useAutocompletePills } from \"./useAutocompletePills\";\n\nlet idCounter = 0;\nfunction useStableId(): string {\n const id = useRef<string | null>(null);\n if (id.current === null) {\n id.current = `:ac-${++idCounter}:`;\n }\n return id.current;\n}\n\nexport function useAIAutocomplete({\n onSubmit,\n onError,\n optionOverrides,\n maskCompletedText,\n placeholder: customPlaceholder,\n apiConfig,\n columns = 2,\n eagerSuggestions = true,\n value: controlledValue,\n completedParams: controlledParams,\n onChange: onChangeProp,\n onParamsChange,\n}: UseAIAutocompleteOptions): UseAIAutocompleteReturn {\n // === Controlled / uncontrolled state ===\n const isTextControlled = controlledValue !== undefined;\n const isParamsControlled = controlledParams !== undefined;\n\n const [internalText, setInternalText] = useState(\"\");\n const [internalCompletedParams, setInternalCompletedParams] = useState<CompletedParamState[]>([]);\n const [suggestions, setSuggestions] = useState<Suggestion[]>([]);\n const [activeDropdownIndex, setActiveDropdownIndex] = useState(-1);\n\n const text = isTextControlled ? controlledValue : internalText;\n const completedParams = isParamsControlled ? controlledParams : internalCompletedParams;\n\n // === Refs — must be before setText/setCompletedParams which read them ===\n const onSubmitRef = useRef(onSubmit);\n onSubmitRef.current = onSubmit;\n const onChangeRef = useRef(onChangeProp);\n onChangeRef.current = onChangeProp;\n const onParamsChangeRef = useRef(onParamsChange);\n onParamsChangeRef.current = onParamsChange;\n const controlledValueRef = useRef(controlledValue);\n controlledValueRef.current = controlledValue;\n const controlledParamsRef = useRef(controlledParams);\n controlledParamsRef.current = controlledParams;\n\n // Stable setText that reads controlled value + callback via refs (no stale closures)\n const setText = useCallback(\n (value: string | ((prev: string) => string)) => {\n if (typeof value === \"function\") {\n if (isTextControlled) {\n const newVal = value(controlledValueRef.current ?? \"\");\n onChangeRef.current?.(newVal);\n } else {\n setInternalText((prev) => {\n const newVal = value(prev);\n onChangeRef.current?.(newVal);\n return newVal;\n });\n }\n } else {\n if (!isTextControlled) setInternalText(value);\n onChangeRef.current?.(value);\n }\n },\n [isTextControlled],\n );\n\n // Stable setCompletedParams — same ref pattern\n const setCompletedParams = useCallback(\n (value: CompletedParamState[] | ((prev: CompletedParamState[]) => CompletedParamState[])) => {\n if (typeof value === \"function\") {\n if (isParamsControlled) {\n const newVal = value(controlledParamsRef.current ?? []);\n onParamsChangeRef.current?.(newVal);\n } else {\n setInternalCompletedParams((prev) => {\n const newVal = value(prev);\n onParamsChangeRef.current?.(newVal);\n return newVal;\n });\n }\n } else {\n if (!isParamsControlled) setInternalCompletedParams(value);\n onParamsChangeRef.current?.(value);\n }\n },\n [isParamsControlled],\n );\n const onErrorRef = useRef(onError);\n onErrorRef.current = onError;\n const optionOverridesRef = useRef(optionOverrides);\n optionOverridesRef.current = optionOverrides;\n const maskCompletedTextRef = useRef(maskCompletedText);\n maskCompletedTextRef.current = maskCompletedText;\n const apiConfigRef = useRef(apiConfig);\n apiConfigRef.current = apiConfig;\n const textRef = useRef(text);\n textRef.current = text;\n const suggestionsRef = useRef(suggestions);\n suggestionsRef.current = suggestions;\n const filterBaseRef = useRef(0);\n const filterInProgressRef = useRef(false);\n const pillTappedRef = useRef(false);\n const skipNextFetchRef = useRef(false);\n const listboxId = useStableId();\n\n // === Fetch ===\n const { doFetch, isLoading, error, isReady, lastRawQueryRef } = useAutocompleteFetch({\n textRef,\n suggestionsRef,\n filterBaseRef,\n filterInProgressRef,\n maskCompletedTextRef,\n apiConfigRef,\n optionOverridesRef,\n onErrorRef,\n setCompletedParams,\n setSuggestions,\n setActiveDropdownIndex,\n });\n\n useDebouncedFetch({\n text,\n completedParams,\n doFetch,\n filterBaseRef,\n filterInProgressRef,\n skipNextFetchRef,\n suggestionsRef,\n lastRawQueryRef,\n });\n\n // === Derived ===\n const segments = useMemo(() => deriveSegments(text, completedParams), [text, completedParams]);\n\n filterBaseRef.current = Math.min(filterBaseRef.current, text.length);\n const filterQuery = extractFilterQuery(text, filterBaseRef.current, filterInProgressRef.current);\n\n const placeholderText = useMemo(() => {\n const serverPlaceholder = suggestions\n .filter((s) => s.type === \"placeholder\")\n .map((s) => s.text)\n .join(\" \");\n return serverPlaceholder || customPlaceholder || \"\";\n }, [suggestions, customPlaceholder]);\n const actionableSuggestions = useMemo(\n () => suggestions.filter((s) => s.type !== \"placeholder\"),\n [suggestions],\n );\n const activeSuggestion: Suggestion | undefined = actionableSuggestions[0];\n const overrideFn = activeSuggestion ? optionOverrides?.[activeSuggestion.type] : undefined;\n const baseOptions = activeSuggestion\n ? overrideFn\n ? overrideFn(filterQuery.trim())\n : (activeSuggestion.options ?? [])\n : [];\n const filteredOptions = useMemo(\n () => filterOptions(baseOptions, filterQuery),\n [baseOptions, filterQuery],\n );\n const hasPlaceholder = placeholderText.length > 0;\n const isDropdownOpen =\n !isLoading &&\n filteredOptions.length > 0 &&\n (!!text || pillTappedRef.current || !hasPlaceholder);\n\n // === Option selection ===\n const selectOption = useCallback(\n (option: SuggestionOption) => {\n if (!activeSuggestion) return;\n\n const completed: CompletedParamState = {\n id: crypto.randomUUID(),\n placeholder: \"\",\n type: activeSuggestion.type,\n text: option.text,\n kind: option.kind,\n suggestionType: activeSuggestion.type,\n suggestionPlaceholder: activeSuggestion.text,\n options: activeSuggestion.options ?? [],\n metadata: option.metadata,\n };\n\n const base = filterBaseRef.current;\n let prefix = textRef.current.slice(0, base);\n if (prefix.length > 0 && !prefix.endsWith(\" \")) {\n const lastWord = prefix.split(/\\s+/).pop() ?? \"\";\n if (lastWord && option.text.toLowerCase().startsWith(lastWord.toLowerCase())) {\n prefix = prefix.slice(0, prefix.length - lastWord.length);\n }\n }\n\n const needsSpace = prefix.length > 0 && prefix[prefix.length - 1] !== \" \";\n const newText = prefix + (needsSpace ? \" \" : \"\") + option.text + \" \";\n setText(newText);\n filterBaseRef.current = newText.length;\n setCompletedParams((prev) => [...prev, completed]);\n pillTappedRef.current = false;\n setActiveDropdownIndex(-1);\n const remainingActionable = actionableSuggestions.length - 1;\n if (eagerSuggestions && remainingActionable > 0) {\n // Keep cached suggestions visible and skip the fetch\n setSuggestions((prev) => prev.filter((s) => s !== activeSuggestion));\n skipNextFetchRef.current = true;\n } else {\n // Clear all suggestions and let the debounced fetch bring fresh ones\n setSuggestions((prev) => prev.filter((s) => s.type === \"placeholder\"));\n }\n },\n [activeSuggestion, actionableSuggestions, eagerSuggestions, setText, setCompletedParams],\n );\n\n // === Text change handler ===\n const handleChange = useCallback(\n (e: ChangeEvent<HTMLTextAreaElement>) => {\n const raw = e.target.value;\n const shouldCapitalize =\n raw.length > 0 &&\n !(e.nativeEvent as InputEvent)?.isComposing &&\n raw[0] !== raw[0].toUpperCase();\n const newValue = shouldCapitalize ? raw[0].toUpperCase() + raw.slice(1) : raw;\n setText(newValue);\n pillTappedRef.current = false;\n setActiveDropdownIndex(-1);\n\n const { valid, invalid } = reconcileParams(newValue, completedParams);\n if (invalid.length > 0) {\n setCompletedParams(() => valid);\n for (const param of invalid) {\n setSuggestions((prev) => [\n {\n type: param.suggestionType,\n text: param.suggestionPlaceholder,\n required: true,\n options: param.options,\n },\n ...prev,\n ]);\n }\n }\n\n if (activeSuggestion && invalid.length === 0) {\n const newFilterQuery = extractFilterQuery(\n newValue,\n filterBaseRef.current,\n filterInProgressRef.current,\n );\n const match = findExactMatch(activeSuggestion.options, newFilterQuery);\n if (match) {\n setCompletedParams((prev) => [\n ...prev,\n {\n id: crypto.randomUUID(),\n placeholder: \"\",\n type: activeSuggestion.type,\n text: match.text,\n kind: match.kind,\n suggestionType: activeSuggestion.type,\n suggestionPlaceholder: activeSuggestion.text,\n options: activeSuggestion.options ?? [],\n metadata: match.metadata,\n },\n ]);\n setSuggestions((prev) => prev.filter((s) => s !== activeSuggestion));\n }\n }\n },\n [completedParams, activeSuggestion, setText, setCompletedParams],\n );\n\n // === Pills ===\n const pills = useAutocompletePills({\n completedParams,\n suggestions,\n setCompletedParams,\n setSuggestions,\n setActiveDropdownIndex,\n filterBaseRef,\n pillTappedRef,\n });\n\n const reEditParam = useCallback(\n (param: CompletedParamState) => {\n pills.reEditParam(param).apply(setText);\n },\n [pills, setText],\n );\n\n // === Keyboard ===\n const { handleKeyDown } = useAutocompleteKeyboard({\n activeDropdownIndex,\n setActiveDropdownIndex,\n filteredOptions,\n selectOption,\n onSubmitRef,\n text,\n completedParams,\n isDropdownOpen,\n hasPlaceholder,\n placeholderText,\n suggestions,\n actionableSuggestions,\n setActivePill: pills.setActivePill,\n filterBaseRef,\n columns,\n setText,\n setCompletedParams,\n setSuggestions,\n });\n\n // === Reset ===\n const reset = useCallback(() => {\n setText(\"\");\n setCompletedParams(() => []);\n setSuggestions([]);\n setActiveDropdownIndex(-1);\n filterBaseRef.current = 0;\n filterInProgressRef.current = false;\n lastRawQueryRef.current = \"\";\n doFetch(\"\", []);\n }, [doFetch, setText, setCompletedParams, lastRawQueryRef]);\n\n const activeDescendantId =\n activeDropdownIndex >= 0 ? `${listboxId}-option-${activeDropdownIndex}` : undefined;\n\n return {\n completedParams,\n suggestionPills: actionableSuggestions,\n setActivePill: pills.setActivePill,\n removeLastParam: pills.removeLastParam,\n reEditParam,\n segments,\n suggestions,\n activeIndex: activeDropdownIndex,\n isReady,\n isLoading,\n error,\n inputProps: {\n value: text,\n placeholder: placeholderText || undefined,\n onChange: handleChange,\n onKeyDown: handleKeyDown,\n role: \"combobox\" as const,\n \"aria-expanded\": isDropdownOpen,\n \"aria-activedescendant\": activeDescendantId,\n \"aria-autocomplete\": \"list\" as const,\n \"aria-controls\": listboxId,\n },\n reset,\n dropdownProps: {\n suggestions: activeSuggestion ? [{ ...activeSuggestion, options: filteredOptions }] : [],\n activeIndex: activeDropdownIndex,\n onSelect: selectOption,\n onHighlight: setActiveDropdownIndex,\n isOpen: isDropdownOpen,\n id: listboxId,\n },\n };\n}\n","import type { SuggestionOption } from \"../types\";\n\n/**\n * Extracts the effective filter query from the region after filterBase.\n * If the server marked the region as in_progress, the full region is used.\n * Otherwise, filtering only starts after the first space (to avoid filtering\n * mid-word when the user continues typing a word that was already in the input).\n */\nexport function extractFilterQuery(\n text: string,\n filterBase: number,\n isInProgress: boolean,\n): string {\n const rawRegion = text.slice(filterBase);\n if (isInProgress || filterBase === 0 || text[filterBase - 1] === \" \") {\n return rawRegion;\n }\n const spaceIdx = rawRegion.indexOf(\" \");\n return spaceIdx === -1 ? \"\" : rawRegion.slice(spaceIdx + 1);\n}\n\n/**\n * Filters options using partial substring match on the text after the last completed param.\n */\nexport function filterOptions(\n options: SuggestionOption[] | undefined,\n query: string,\n): SuggestionOption[] {\n if (!options) return [];\n const trimmed = query.trimStart();\n if (!trimmed) return options;\n const lower = trimmed.toLowerCase();\n return options.filter((o) => !o.is_tappable || o.text.toLowerCase().includes(lower));\n}\n\n/**\n * Finds an exact match for the trimmed filter query against options.\n */\nexport function findExactMatch(\n options: SuggestionOption[] | undefined,\n query: string,\n): SuggestionOption | null {\n if (!options) return null;\n const trimmed = query.trim();\n if (!trimmed) return null;\n const lower = trimmed.toLowerCase();\n return options.find((o) => o.is_tappable && o.text.toLowerCase() === lower) ?? null;\n}\n","import type { CompletedParamState, Segment } from \"../types\";\n\n/**\n * Derives segments for overlay rendering by matching completed params in text.\n */\nexport function deriveSegments(text: string, completedParams: CompletedParamState[]): Segment[] {\n const result: Segment[] = [];\n let pos = 0;\n\n for (const param of completedParams) {\n const idx = text.indexOf(param.text, pos);\n if (idx === -1) continue;\n if (idx > pos) {\n result.push({ type: \"text\", value: text.slice(pos, idx) });\n }\n result.push({ type: \"completed\", value: param.text, param });\n pos = idx + param.text.length;\n }\n\n const remaining = text.slice(pos);\n if (remaining) {\n result.push({ type: \"text\", value: remaining });\n }\n\n return result;\n}\n\n/**\n * Checks which completed params still exist in the new text.\n */\nexport function reconcileParams(\n text: string,\n completedParams: CompletedParamState[],\n): { valid: CompletedParamState[]; invalid: CompletedParamState[] } {\n const valid: CompletedParamState[] = [];\n const invalid: CompletedParamState[] = [];\n let pos = 0;\n\n for (const param of completedParams) {\n const idx = text.indexOf(param.text, pos);\n if (idx === -1) {\n invalid.push(param);\n } else {\n valid.push(param);\n pos = idx + param.text.length;\n }\n }\n\n return { valid, invalid };\n}\n","import { type MutableRefObject, useCallback, useEffect, useRef, useState } from \"react\";\nimport type {\n APIConfig,\n CompletedParamState,\n OptionOverrides,\n Suggestion,\n SuggestionOption,\n} from \"../types\";\nimport { fetchSuggestions } from \"../utils/api\";\nimport { buildQuery } from \"../utils/buildQuery\";\nimport { extractFilterQuery, filterOptions, findExactMatch } from \"../utils/filtering\";\nimport { applyOptionOverrides } from \"../utils/overrides\";\n\nconst DEBOUNCE_MS = 100;\nconst SLOW_DEBOUNCE_MS = 300;\nconst MIN_CHARS_DIFF = 2;\n\ninterface UseAutocompleteFetchOptions {\n textRef: MutableRefObject<string>;\n suggestionsRef: MutableRefObject<Suggestion[]>;\n filterBaseRef: MutableRefObject<number>;\n filterInProgressRef: MutableRefObject<boolean>;\n maskCompletedTextRef: MutableRefObject<boolean | undefined>;\n apiConfigRef: MutableRefObject<APIConfig | undefined>;\n optionOverridesRef: MutableRefObject<OptionOverrides | undefined>;\n onErrorRef: MutableRefObject<((error: Error) => void) | undefined>;\n setCompletedParams: (fn: (prev: CompletedParamState[]) => CompletedParamState[]) => void;\n setSuggestions: (fn: Suggestion[] | ((prev: Suggestion[]) => Suggestion[])) => void;\n setActiveDropdownIndex: (index: number) => void;\n}\n\ninterface UseAutocompleteFetchReturn {\n doFetch: (rawQuery: string, completed: CompletedParamState[]) => Promise<void>;\n isLoading: boolean;\n error: Error | null;\n isReady: boolean;\n lastRawQueryRef: MutableRefObject<string>;\n}\n\nexport function useAutocompleteFetch({\n textRef,\n suggestionsRef,\n filterBaseRef,\n filterInProgressRef,\n maskCompletedTextRef,\n apiConfigRef,\n optionOverridesRef,\n onErrorRef,\n setCompletedParams,\n setSuggestions,\n setActiveDropdownIndex,\n}: UseAutocompleteFetchOptions): UseAutocompleteFetchReturn {\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [isReady, setIsReady] = useState(false);\n const fetchVersionRef = useRef(0);\n const abortRef = useRef<AbortController | null>(null);\n const lastRawQueryRef = useRef(\"\");\n\n const doFetch = useCallback(\n async (rawQuery: string, completed: CompletedParamState[]) => {\n abortRef.current?.abort();\n const controller = new AbortController();\n abortRef.current = controller;\n const version = ++fetchVersionRef.current;\n const textAtRequest = textRef.current.length;\n\n const hasSuggestions = suggestionsRef.current.some((s) => s.type !== \"placeholder\");\n if (!hasSuggestions) setIsLoading(true);\n setError(null);\n try {\n const res = await fetchSuggestions(rawQuery, completed, {\n maskCompletedText: maskCompletedTextRef.current,\n signal: controller.signal,\n apiConfig: apiConfigRef.current,\n });\n\n if (version !== fetchVersionRef.current) return;\n\n let newSuggestions = applyOptionOverrides(\n res.data.suggestions ?? [],\n optionOverridesRef.current,\n );\n setIsReady(res.data.is_ready ?? false);\n lastRawQueryRef.current = rawQuery;\n\n const input = res.data.input ?? [];\n const lastInput = input[input.length - 1];\n const currentText = textRef.current;\n if (lastInput?.state === \"in_progress\") {\n filterInProgressRef.current = true;\n const inProgressIdx = currentText.toLowerCase().lastIndexOf(lastInput.text.toLowerCase());\n if (inProgressIdx !== -1) {\n filterBaseRef.current = inProgressIdx;\n } else {\n filterBaseRef.current = textAtRequest;\n }\n } else {\n filterInProgressRef.current = false;\n filterBaseRef.current = textAtRequest;\n }\n\n // Check if the user already typed an exact match while waiting\n const actionable = newSuggestions.filter((s) => s.type !== \"placeholder\");\n const active = actionable[0];\n if (active) {\n const query = extractFilterQuery(\n currentText,\n filterBaseRef.current,\n filterInProgressRef.current,\n );\n const match = findExactMatch(active.options, query);\n if (match) {\n setCompletedParams((prev) => [\n ...prev,\n {\n id: crypto.randomUUID(),\n placeholder: \"\",\n type: active.type,\n text: match.text,\n kind: match.kind,\n suggestionType: active.type,\n suggestionPlaceholder: active.text,\n options: active.options ?? [],\n metadata: match.metadata,\n },\n ]);\n newSuggestions = newSuggestions.filter((s) => s !== active);\n }\n }\n\n setSuggestions(newSuggestions);\n setIsLoading(false);\n setActiveDropdownIndex(-1);\n } catch (err) {\n if (version === fetchVersionRef.current) {\n const caughtError = err instanceof Error ? err : new Error(String(err));\n setError(caughtError);\n setIsLoading(false);\n onErrorRef.current?.(caughtError);\n }\n }\n },\n [\n textRef,\n suggestionsRef,\n filterBaseRef,\n filterInProgressRef,\n maskCompletedTextRef,\n apiConfigRef,\n optionOverridesRef,\n onErrorRef,\n setCompletedParams,\n setSuggestions,\n setActiveDropdownIndex,\n ],\n );\n\n // Mount fetch\n useEffect(() => {\n doFetch(\"\", []);\n return () => {\n abortRef.current?.abort();\n };\n }, [doFetch]);\n\n return { doFetch, isLoading, error, isReady, lastRawQueryRef };\n}\n\ninterface UseDebouncedFetchOptions {\n text: string;\n completedParams: CompletedParamState[];\n doFetch: (rawQuery: string, completed: CompletedParamState[]) => Promise<void>;\n filterBaseRef: MutableRefObject<number>;\n filterInProgressRef: MutableRefObject<boolean>;\n skipNextFetchRef: MutableRefObject<boolean>;\n suggestionsRef: MutableRefObject<Suggestion[]>;\n lastRawQueryRef: MutableRefObject<string>;\n}\n\nexport function useDebouncedFetch({\n text,\n completedParams,\n doFetch,\n filterBaseRef,\n filterInProgressRef,\n skipNextFetchRef,\n suggestionsRef,\n lastRawQueryRef,\n}: UseDebouncedFetchOptions): void {\n const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const slowDebounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const hasFetchedRef = useRef(true);\n\n useEffect(() => {\n if (debounceRef.current) clearTimeout(debounceRef.current);\n if (slowDebounceRef.current) clearTimeout(slowDebounceRef.current);\n\n const attemptFetch = (minDiff: number): boolean => {\n if (skipNextFetchRef.current) {\n skipNextFetchRef.current = false;\n return false;\n }\n\n if (!text && completedParams.length === 0) {\n if (!hasFetchedRef.current) {\n hasFetchedRef.current = true;\n return false;\n }\n doFetch(\"\", []);\n return true;\n }\n\n const currentQuery = extractFilterQuery(\n text,\n filterBaseRef.current,\n filterInProgressRef.current,\n );\n const currentSuggestions = suggestionsRef.current;\n const actionable = currentSuggestions.filter((s: Suggestion) => s.type !== \"placeholder\");\n const active = actionable[0];\n const currentFiltered = active ? filterOptions(active.options, currentQuery) : [];\n const tappableFiltered = currentFiltered.filter((o: SuggestionOption) => o.is_tappable);\n const hasExactMatch = active ? findExactMatch(active.options, currentQuery) !== null : false;\n\n const isInFilterZone = currentQuery.trim().length > 0;\n if (tappableFiltered.length > 0 && !hasExactMatch && isInFilterZone) return false;\n\n const { rawQuery, completedParams: updatedParams } = buildQuery(text, completedParams);\n const isDeleting = rawQuery.length < lastRawQueryRef.current.length;\n const charDiff = Math.abs(rawQuery.length - lastRawQueryRef.current.length);\n if (isDeleting || charDiff >= minDiff) {\n doFetch(rawQuery, updatedParams);\n return true;\n }\n return false;\n };\n\n debounceRef.current = setTimeout(() => {\n if (attemptFetch(MIN_CHARS_DIFF)) {\n if (slowDebounceRef.current) clearTimeout(slowDebounceRef.current);\n }\n }, DEBOUNCE_MS);\n\n slowDebounceRef.current = setTimeout(() => attemptFetch(1), SLOW_DEBOUNCE_MS);\n\n return () => {\n if (debounceRef.current) clearTimeout(debounceRef.current);\n if (slowDebounceRef.current) clearTimeout(slowDebounceRef.current);\n };\n }, [\n text,\n completedParams,\n doFetch,\n filterBaseRef,\n filterInProgressRef,\n skipNextFetchRef,\n suggestionsRef,\n lastRawQueryRef,\n ]);\n}\n","import type {\n APIConfig,\n AutocompleteRequest,\n AutocompleteResponse,\n CompletedParam,\n CompletedParamState,\n} from \"../types\";\n\n// Replaced at build time by tsup/vitest `define` config with the package.json version.\ndeclare const __SDK_VERSION__: string;\nconst SDK_VERSION = __SDK_VERSION__;\n\nlet hasWarnedMissingKey = false;\n\nfunction generateRequestId(): string {\n return crypto.randomUUID();\n}\n\nfunction toWireParam(param: CompletedParamState, includeText: boolean): CompletedParam {\n return {\n placeholder: param.placeholder,\n type: param.type,\n ...(includeText && { text: param.text }),\n kind: param.kind,\n };\n}\n\nexport async function fetchSuggestions(\n rawQuery: string,\n completedParams: CompletedParamState[],\n options?: {\n maskCompletedText?: boolean;\n signal?: AbortSignal;\n apiConfig?: APIConfig;\n },\n): Promise<AutocompleteResponse> {\n const apiConfig = options?.apiConfig;\n const apiKey = apiConfig?.apiKey ?? \"\";\n if (!apiKey && !hasWarnedMissingKey) {\n hasWarnedMissingKey = true;\n // biome-ignore lint/suspicious/noConsole: intentional dev warning\n console.warn(\n \"[AIAutocomplete] No apiKey in apiConfig. Requests will be sent without an Authorization header.\",\n );\n }\n const authScheme = apiConfig?.authScheme ?? \"Bearer\";\n const includeText = !options?.maskCompletedText;\n\n const rawCount = completedParams.find(\n (p) => p.type === \"contact\" && p.metadata?.contact_account_count,\n )?.metadata?.contact_account_count;\n const contactAccountCount = typeof rawCount === \"number\" ? rawCount : undefined;\n\n const body: AutocompleteRequest = {\n data: {\n raw_query: rawQuery,\n completed_params: completedParams.map((p) => toWireParam(p, includeText)),\n ...(contactAccountCount != null && { contact_account_count: contactAccountCount }),\n },\n meta: {\n request_id: generateRequestId(),\n request_at: new Date().toISOString(),\n language: typeof navigator !== \"undefined\" ? navigator.language : \"en-US\",\n client_version: SDK_VERSION,\n },\n };\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n ...(apiConfig?.appIdentifier && { \"X-App-Identifier\": apiConfig.appIdentifier }),\n ...apiConfig?.headers,\n };\n if (apiKey) {\n headers.Authorization = authScheme === \"Basic\" ? `Basic ${btoa(apiKey)}` : `Bearer ${apiKey}`;\n }\n\n const response = await fetch(apiConfig?.endpoint ?? \"/ac/suggest\", {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n signal: options?.signal,\n });\n\n if (!response.ok) {\n throw new Error(`API error: ${response.status} ${response.statusText}`);\n }\n\n return response.json() as Promise<AutocompleteResponse>;\n}\n","import type { CompletedParamState } from \"../types\";\n\ninterface BuildQueryResult {\n rawQuery: string;\n completedParams: CompletedParamState[];\n}\n\n/**\n * Takes the raw input text and completed params (without placeholders),\n * replaces each completed param's text in the string with a {{TYPE_N}} token,\n * and returns the transformed query + params with placeholders filled in.\n *\n * Replacements happen left-to-right, first occurrence only per param.\n * Counter is per-type (e.g. {{TASK_1}}, {{GOAL_1}}, {{GOAL_2}}).\n */\nexport function buildQuery(text: string, completedParams: CompletedParamState[]): BuildQueryResult {\n let result = text;\n const typeCounts: Record<string, number> = {};\n const updatedParams: CompletedParamState[] = [];\n\n for (const param of completedParams) {\n const count = (typeCounts[param.type] ?? 0) + 1;\n typeCounts[param.type] = count;\n\n const typeKey = param.type.toUpperCase().replace(/\\s+/g, \"_\");\n const placeholder = `{{${typeKey}_${count}}}`;\n\n // Replace first occurrence of the param text in the string\n const index = result.indexOf(param.text);\n if (index !== -1) {\n result = result.slice(0, index) + placeholder + result.slice(index + param.text.length);\n }\n\n updatedParams.push({ ...param, placeholder });\n }\n\n return { rawQuery: result, completedParams: updatedParams };\n}\n","import type { Suggestion, SuggestionOption } from \"../types\";\n\n/**\n * Applies option overrides by calling the override function with an empty query,\n * then prepending results to suggestions that match by type, deduplicating by text.\n */\nexport function applyOptionOverrides(\n suggestions: Suggestion[],\n overrides?: Record<string, (query: string) => SuggestionOption[]>,\n): Suggestion[] {\n if (!overrides) return suggestions;\n return suggestions.map((s) => {\n const fn = overrides[s.type];\n if (!fn) return s;\n const extra = fn(\"\");\n if (extra.length === 0) return s;\n const existingTexts = new Set(extra.map((o) => o.text));\n const deduped = (s.options ?? []).filter((o) => !existingTexts.has(o.text));\n return { ...s, options: [...extra, ...deduped] };\n });\n}\n","import { type KeyboardEvent, type MutableRefObject, useCallback } from \"react\";\nimport type {\n AutocompleteResult,\n CompletedParamState,\n Suggestion,\n SuggestionOption,\n} from \"../types\";\nimport { buildQuery } from \"../utils/buildQuery\";\n\ninterface UseAutocompleteKeyboardOptions {\n activeDropdownIndex: number;\n setActiveDropdownIndex: (index: number) => void;\n filteredOptions: SuggestionOption[];\n selectOption: (option: SuggestionOption) => void;\n onSubmitRef: MutableRefObject<((result: AutocompleteResult) => void) | undefined>;\n text: string;\n completedParams: CompletedParamState[];\n isDropdownOpen: boolean;\n hasPlaceholder: boolean;\n placeholderText: string;\n suggestions: Suggestion[];\n actionableSuggestions: Suggestion[];\n setActivePill: (index: number) => void;\n filterBaseRef: MutableRefObject<number>;\n columns: number;\n setText: (value: string) => void;\n setCompletedParams: (fn: (prev: CompletedParamState[]) => CompletedParamState[]) => void;\n setSuggestions: (fn: (prev: Suggestion[]) => Suggestion[]) => void;\n}\n\nexport function useAutocompleteKeyboard({\n activeDropdownIndex,\n setActiveDropdownIndex,\n filteredOptions,\n selectOption,\n onSubmitRef,\n text,\n completedParams,\n isDropdownOpen,\n hasPlaceholder,\n placeholderText,\n suggestions,\n actionableSuggestions,\n setActivePill,\n filterBaseRef,\n columns,\n setText,\n setCompletedParams,\n setSuggestions,\n}: UseAutocompleteKeyboardOptions) {\n const getTappableIndices = useCallback(() => {\n const tappable = filteredOptions\n .map((o, i) => (o.is_tappable ? i : -1))\n .filter((i) => i !== -1);\n // Column-first ordering: all column-0 items, then column-1, etc.\n const buckets: number[][] = Array.from({ length: columns }, () => []);\n for (const i of tappable) buckets[i % columns].push(i);\n return buckets.flat();\n }, [filteredOptions, columns]);\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLTextAreaElement>) => {\n const tappableIndices = getTappableIndices();\n\n switch (e.key) {\n case \"ArrowDown\": {\n e.preventDefault();\n if (tappableIndices.length === 0) return;\n const currentPos = tappableIndices.indexOf(activeDropdownIndex);\n const nextPos = currentPos < tappableIndices.length - 1 ? currentPos + 1 : 0;\n setActiveDropdownIndex(tappableIndices[nextPos]);\n break;\n }\n case \"ArrowUp\": {\n e.preventDefault();\n if (tappableIndices.length === 0) return;\n const currentPos = tappableIndices.indexOf(activeDropdownIndex);\n const prevPos = currentPos > 0 ? currentPos - 1 : tappableIndices.length - 1;\n setActiveDropdownIndex(tappableIndices[prevPos]);\n break;\n }\n case \"ArrowRight\": {\n if (activeDropdownIndex < 0) {\n // No dropdown option selected — cycle to the next suggestion pill\n if (actionableSuggestions.length > 1) {\n e.preventDefault();\n setActivePill(1);\n }\n break;\n }\n const col = activeDropdownIndex % columns;\n if (col < columns - 1) {\n const rightNeighbor = activeDropdownIndex + 1;\n if (\n rightNeighbor < filteredOptions.length &&\n filteredOptions[rightNeighbor]?.is_tappable\n ) {\n e.preventDefault();\n setActiveDropdownIndex(rightNeighbor);\n }\n }\n break;\n }\n case \"ArrowLeft\": {\n if (activeDropdownIndex < 0) break;\n if (activeDropdownIndex % columns > 0) {\n const leftNeighbor = activeDropdownIndex - 1;\n if (leftNeighbor >= 0 && filteredOptions[leftNeighbor]?.is_tappable) {\n e.preventDefault();\n setActiveDropdownIndex(leftNeighbor);\n }\n }\n break;\n }\n case \"Enter\": {\n e.preventDefault();\n if (activeDropdownIndex >= 0 && filteredOptions[activeDropdownIndex]?.is_tappable) {\n selectOption(filteredOptions[activeDropdownIndex]);\n } else if (onSubmitRef.current) {\n const { rawQuery, completedParams: finalParams } = buildQuery(text, completedParams);\n const result: AutocompleteResult = {\n query: text.trim(),\n raw_query: rawQuery,\n completed_params: finalParams,\n };\n onSubmitRef.current(result);\n }\n break;\n }\n case \"Tab\": {\n if (activeDropdownIndex >= 0 && filteredOptions[activeDropdownIndex]?.is_tappable) {\n e.preventDefault();\n selectOption(filteredOptions[activeDropdownIndex]);\n } else if (isDropdownOpen) {\n const firstTappable = filteredOptions.find((o) => o.is_tappable);\n if (firstTappable) {\n e.preventDefault();\n selectOption(firstTappable);\n }\n } else if (!text && hasPlaceholder) {\n e.preventDefault();\n const placeholderSuggestion = suggestions.find((s) => s.type === \"placeholder\");\n if (placeholderSuggestion) {\n setText(placeholderText);\n filterBaseRef.current = placeholderText.length;\n setCompletedParams((prev) => [\n ...prev,\n {\n id: crypto.randomUUID(),\n placeholder: \"\",\n type: placeholderSuggestion.type,\n text: placeholderText,\n kind: null,\n suggestionType: placeholderSuggestion.type,\n suggestionPlaceholder: placeholderSuggestion.text,\n options: placeholderSuggestion.options ?? [],\n },\n ]);\n setSuggestions((prev) => prev.filter((s) => s !== placeholderSuggestion));\n } else {\n setText(placeholderText);\n filterBaseRef.current = placeholderText.length;\n }\n }\n break;\n }\n case \"Escape\":\n setActiveDropdownIndex(-1);\n break;\n }\n },\n [\n actionableSuggestions,\n activeDropdownIndex,\n columns,\n completedParams,\n filteredOptions,\n filterBaseRef,\n getTappableIndices,\n hasPlaceholder,\n isDropdownOpen,\n onSubmitRef,\n placeholderText,\n selectOption,\n setActiveDropdownIndex,\n setActivePill,\n setCompletedParams,\n setSuggestions,\n setText,\n suggestions,\n text,\n ],\n );\n\n return { handleKeyDown, getTappableIndices };\n}\n","import { type MutableRefObject, useCallback } from \"react\";\nimport type { CompletedParamState, Suggestion } from \"../types\";\n\ninterface UseAutocompletePillsOptions {\n completedParams: CompletedParamState[];\n suggestions: Suggestion[];\n setCompletedParams: (fn: (prev: CompletedParamState[]) => CompletedParamState[]) => void;\n setSuggestions: (fn: Suggestion[] | ((prev: Suggestion[]) => Suggestion[])) => void;\n setActiveDropdownIndex: (index: number) => void;\n filterBaseRef: MutableRefObject<number>;\n pillTappedRef: MutableRefObject<boolean>;\n}\n\nexport function useAutocompletePills({\n completedParams,\n suggestions,\n setCompletedParams,\n setSuggestions,\n setActiveDropdownIndex,\n filterBaseRef,\n pillTappedRef,\n}: UseAutocompletePillsOptions) {\n const setActivePill = useCallback(\n (index: number) => {\n const actionable = suggestions.filter((s) => s.type !== \"placeholder\");\n if (index < 0 || index >= actionable.length) return;\n const moved = actionable[index];\n const rest = actionable.filter((_, i) => i !== index);\n const placeholders = suggestions.filter((s) => s.type === \"placeholder\");\n setSuggestions([...placeholders, moved, ...rest]);\n pillTappedRef.current = true;\n setActiveDropdownIndex(-1);\n },\n [suggestions, setSuggestions, setActiveDropdownIndex, pillTappedRef],\n );\n\n const removeLastParam = useCallback(() => {\n if (completedParams.length === 0) return;\n const lastParam = completedParams[completedParams.length - 1];\n const restoredSuggestion: Suggestion = {\n type: lastParam.suggestionType,\n text: lastParam.suggestionPlaceholder,\n required: true,\n options: lastParam.options,\n };\n setCompletedParams((prev) => prev.slice(0, -1));\n setSuggestions((prev: Suggestion[]) => [restoredSuggestion, ...prev]);\n setActiveDropdownIndex(-1);\n }, [completedParams, setCompletedParams, setSuggestions, setActiveDropdownIndex]);\n\n const reEditParam = useCallback(\n (param: CompletedParamState) => {\n const restoredSuggestion: Suggestion = {\n type: param.suggestionType,\n text: param.suggestionPlaceholder,\n required: true,\n options: param.options,\n };\n return {\n apply: (setText: (fn: (prev: string) => string) => void) => {\n setText((prev) => {\n let pos = 0;\n for (const p of completedParams) {\n const idx = prev.indexOf(p.text, pos);\n if (idx === -1) continue;\n if (p.id === param.id) {\n const before = prev.slice(0, idx);\n const after = prev.slice(idx + param.text.length);\n const cleaned = (before + after).replace(/ {2,}/g, \" \");\n filterBaseRef.current = Math.min(filterBaseRef.current, cleaned.length);\n return cleaned;\n }\n pos = idx + p.text.length;\n }\n return prev;\n });\n setCompletedParams((prev) => prev.filter((p) => p.id !== param.id));\n setSuggestions((prev: Suggestion[]) => [restoredSuggestion, ...prev]);\n setActiveDropdownIndex(-1);\n pillTappedRef.current = true;\n },\n };\n },\n [\n completedParams,\n setCompletedParams,\n setSuggestions,\n setActiveDropdownIndex,\n filterBaseRef,\n pillTappedRef,\n ],\n );\n\n return { setActivePill, removeLastParam, reEditParam };\n}\n"],"mappings":"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","names":["index_exports","__export","AIAutocomplete","AIAutocompleteDropdown","useAIAutocomplete","__toCommonJS","import_react","s","AIAutocomplete_module_css_default","s","AIAutocompleteDropdown_module_css_default","s","SuggestionGrid_module_css_default","s","SuggestionItem_module_css_default","import_jsx_runtime","SuggestionItem","option","isHighlighted","onSelect","onHighlight","id","className","SuggestionItem_module_css_default","e","import_jsx_runtime","SuggestionGrid","options","activeIndex","onSelect","onHighlight","listboxId","SuggestionGrid_module_css_default","option","i","SuggestionItem","import_jsx_runtime","AIAutocompleteDropdown","suggestions","activeIndex","onSelect","onHighlight","isOpen","id","className","options","hasOptions","AIAutocompleteDropdown_module_css_default","e","SuggestionGrid","s","PillList_module_css_default","import_jsx_runtime","getPillOpacity","index","PillList","pills","activePillIndex","onSelectPill","PillList_module_css_default","pill","i","import_react","extractFilterQuery","text","filterBase","isInProgress","rawRegion","spaceIdx","filterOptions","options","query","trimmed","lower","o","findExactMatch","deriveSegments","text","completedParams","result","pos","param","idx","remaining","reconcileParams","valid","invalid","import_react","SDK_VERSION","hasWarnedMissingKey","generateRequestId","toWireParam","param","includeText","fetchSuggestions","rawQuery","completedParams","options","apiConfig","apiKey","authScheme","rawCount","p","contactAccountCount","body","headers","response","buildQuery","text","completedParams","result","typeCounts","updatedParams","param","count","placeholder","index","applyOptionOverrides","suggestions","overrides","s","fn","extra","existingTexts","o","deduped","DEBOUNCE_MS","SLOW_DEBOUNCE_MS","MIN_CHARS_DIFF","useAutocompleteFetch","textRef","suggestionsRef","filterBaseRef","filterInProgressRef","maskCompletedTextRef","apiConfigRef","optionOverridesRef","onErrorRef","setCompletedParams","setSuggestions","setActiveDropdownIndex","isLoading","setIsLoading","error","setError","isReady","setIsReady","fetchVersionRef","abortRef","lastRawQueryRef","doFetch","rawQuery","completed","controller","version","textAtRequest","s","res","fetchSuggestions","newSuggestions","applyOptionOverrides","input","lastInput","currentText","inProgressIdx","active","query","extractFilterQuery","match","findExactMatch","prev","err","caughtError","useDebouncedFetch","text","completedParams","skipNextFetchRef","debounceRef","slowDebounceRef","hasFetchedRef","attemptFetch","minDiff","currentQuery","tappableFiltered","filterOptions","o","hasExactMatch","isInFilterZone","updatedParams","buildQuery","isDeleting","charDiff","import_react","useAutocompleteKeyboard","activeDropdownIndex","setActiveDropdownIndex","filteredOptions","selectOption","onSubmitRef","text","completedParams","isDropdownOpen","hasPlaceholder","placeholderText","suggestions","actionableSuggestions","setActivePill","filterBaseRef","columns","setText","setCompletedParams","setSuggestions","getTappableIndices","tappable","o","i","buckets","e","tappableIndices","currentPos","nextPos","prevPos","rightNeighbor","leftNeighbor","rawQuery","finalParams","buildQuery","result","firstTappable","placeholderSuggestion","s","prev","import_react","useAutocompletePills","completedParams","suggestions","setCompletedParams","setSuggestions","setActiveDropdownIndex","filterBaseRef","pillTappedRef","setActivePill","index","actionable","s","moved","rest","_","i","placeholders","removeLastParam","lastParam","restoredSuggestion","prev","reEditParam","param","setText","pos","p","idx","before","after","cleaned","idCounter","useStableId","id","useAIAutocomplete","onSubmit","onError","optionOverrides","maskCompletedText","customPlaceholder","apiConfig","columns","eagerSuggestions","controlledValue","controlledParams","onChangeProp","onParamsChange","isTextControlled","isParamsControlled","internalText","setInternalText","internalCompletedParams","setInternalCompletedParams","suggestions","setSuggestions","activeDropdownIndex","setActiveDropdownIndex","text","completedParams","onSubmitRef","onChangeRef","onParamsChangeRef","controlledValueRef","controlledParamsRef","setText","value","newVal","prev","setCompletedParams","onErrorRef","optionOverridesRef","maskCompletedTextRef","apiConfigRef","textRef","suggestionsRef","filterBaseRef","filterInProgressRef","pillTappedRef","skipNextFetchRef","listboxId","doFetch","isLoading","error","isReady","lastRawQueryRef","useAutocompleteFetch","useDebouncedFetch","segments","deriveSegments","filterQuery","extractFilterQuery","placeholderText","s","actionableSuggestions","activeSuggestion","overrideFn","baseOptions","filteredOptions","filterOptions","hasPlaceholder","isDropdownOpen","selectOption","option","completed","base","prefix","lastWord","needsSpace","newText","remainingActionable","handleChange","e","raw","newValue","valid","invalid","reconcileParams","param","newFilterQuery","match","findExactMatch","pills","useAutocompletePills","reEditParam","handleKeyDown","useAutocompleteKeyboard","reset","activeDescendantId","import_jsx_runtime","AIAutocomplete","onSubmit","onError","optionOverrides","maskCompletedText","placeholder","className","apiConfig","columns","eagerSuggestions","value","controlledParams","onChangeProp","onParamsChange","ref","textareaRef","handleSubmitRef","completedParams","suggestionPills","setActivePill","segments","inputProps","dropdownProps","reset","useAIAutocomplete","result","handleContainerClick","canSubmit","handleSubmit","rawQuery","finalParams","buildQuery","onChange","inputPlaceholder","restProps","isEmpty","AIAutocomplete_module_css_default","AIAutocompleteDropdown","seg","i","PillList","e"]}
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{forwardRef as
|
|
1
|
+
import{forwardRef as bt,useCallback as ht,useEffect as yt,useImperativeHandle as St,useRef as Ve}from"react";if(typeof document<"u"&&!document.getElementById("ac-style-cc65f4cc")){let e=document.createElement("style");e.id="ac-style-cc65f4cc",e.textContent=`.AIAutocomplete-module_container_KKjFU {
|
|
2
2
|
position: relative;
|
|
3
3
|
font-family: "IBM Plex Sans", sans-serif;
|
|
4
4
|
}
|
|
@@ -105,7 +105,7 @@ import{forwardRef as gt,useCallback as ft,useEffect as bt,useImperativeHandle as
|
|
|
105
105
|
opacity: 1;
|
|
106
106
|
pointer-events: auto;
|
|
107
107
|
}
|
|
108
|
-
`,document.head.appendChild(e)}var
|
|
108
|
+
`,document.head.appendChild(e)}var Se={dropdown:"AIAutocompleteDropdown-module_dropdown_yz2KC",visible:"AIAutocompleteDropdown-module_visible_QCoXj"};if(typeof document<"u"&&!document.getElementById("ac-style-d91f2b06")){let e=document.createElement("style");e.id="ac-style-d91f2b06",e.textContent=`.SuggestionGrid-module_grid_jvaPb {
|
|
109
109
|
display: grid;
|
|
110
110
|
grid-template-columns: 1fr 1fr;
|
|
111
111
|
gap: 12px 18px;
|
|
@@ -128,7 +128,7 @@ import{forwardRef as gt,useCallback as ft,useEffect as bt,useImperativeHandle as
|
|
|
128
128
|
background: rgba(255, 255, 255, 0.3);
|
|
129
129
|
border-radius: 3px;
|
|
130
130
|
}
|
|
131
|
-
`,document.head.appendChild(e)}var
|
|
131
|
+
`,document.head.appendChild(e)}var ke={grid:"SuggestionGrid-module_grid_jvaPb"};if(typeof document<"u"&&!document.getElementById("ac-style-f6bdc634")){let e=document.createElement("style");e.id="ac-style-f6bdc634",e.textContent=`.SuggestionItem-module_item_d4vpD {
|
|
132
132
|
display: flex;
|
|
133
133
|
align-items: center;
|
|
134
134
|
font-family: "IBM Plex Sans", sans-serif;
|
|
@@ -169,7 +169,7 @@ import{forwardRef as gt,useCallback as ft,useEffect as bt,useImperativeHandle as
|
|
|
169
169
|
margin-left: 6px;
|
|
170
170
|
opacity: 0.5;
|
|
171
171
|
}
|
|
172
|
-
`,document.head.appendChild(e)}var
|
|
172
|
+
`,document.head.appendChild(e)}var X={item:"SuggestionItem-module_item_d4vpD",fadeIn:"SuggestionItem-module_fadeIn_I8u35",tappable:"SuggestionItem-module_tappable_70KcX",nonTappable:"SuggestionItem-module_nonTappable_xSZM-",highlighted:"SuggestionItem-module_highlighted_Hb0SU",tag:"SuggestionItem-module_tag_e3Fwe"};import{jsx as rt,jsxs as it}from"react/jsx-runtime";function Me({option:e,isHighlighted:r,onSelect:t,onHighlight:o,id:n}){let i=[X.item,r?X.highlighted:"",e.is_tappable?X.tappable:X.nonTappable].filter(Boolean).join(" ");return it("div",{id:n,role:"option","aria-selected":r,className:i,tabIndex:e.is_tappable?0:-1,onClick:()=>e.is_tappable&&t(e),onKeyDown:s=>{e.is_tappable&&(s.key==="Enter"||s.key===" ")&&(s.preventDefault(),t(e))},onMouseEnter:o,children:[e.icon?`${e.icon} ${e.text}`:e.text,e.tag&&rt("span",{className:X.tag,children:e.tag})]})}import{jsx as Te}from"react/jsx-runtime";function Ee({options:e,activeIndex:r,onSelect:t,onHighlight:o,listboxId:n}){return Te("div",{className:ke.grid,children:e.map((i,s)=>Te(Me,{option:i,isHighlighted:s===r,onSelect:t,onHighlight:()=>o(s),id:`${n}-option-${s}`},i.text))})}import{jsx as Le}from"react/jsx-runtime";function xe({suggestions:e,activeIndex:r,onSelect:t,onHighlight:o,isOpen:n,id:i,className:s}){let d=e[0]?.options??[],c=n&&d.length>0;return Le("div",{id:i,role:"listbox",className:`${Se.dropdown} ${c?Se.visible:""} ${s??""}`,onMouseDown:u=>u.preventDefault(),children:d.length>0&&Le(Ee,{options:d,activeIndex:r,onSelect:t,onHighlight:o,listboxId:i})})}if(typeof document<"u"&&!document.getElementById("ac-style-b745b4fb")){let e=document.createElement("style");e.id="ac-style-b745b4fb",e.textContent=`.PillList-module_list_qvLqO {
|
|
173
173
|
position: relative;
|
|
174
174
|
z-index: 1;
|
|
175
175
|
pointer-events: auto;
|
|
@@ -211,5 +211,5 @@ import{forwardRef as gt,useCallback as ft,useEffect as bt,useImperativeHandle as
|
|
|
211
211
|
opacity: 0;
|
|
212
212
|
}
|
|
213
213
|
}
|
|
214
|
-
`,document.head.appendChild(e)}var re={list:"PillList-module_list_qvLqO",pill:"PillList-module_pill_osSyz",fadeIn:"PillList-module_fadeIn_Aezob",active:"PillList-module_active_Oll--"};import{jsx as Ee}from"react/jsx-runtime";function rt(e){return e===0?.4:e===1?.3:.15}function Le({pills:e,activePillIndex:r,onSelectPill:t}){return Ee("span",{className:re.list,children:e.map((o,n)=>Ee("button",{type:"button",className:`${re.pill} ${n===r?re.active:""}`,style:{opacity:rt(n)},onClick:()=>t(n),children:o.text},`${o.type}-${o.text}`))})}import{useCallback as J,useMemo as ae,useRef as k,useState as se}from"react";function ie(e,r){if(!e)return[];let t=r.trimStart();if(!t)return e;let o=t.toLowerCase();return e.filter(n=>!n.is_tappable||n.text.toLowerCase().includes(o))}function ee(e,r){if(!e)return null;let t=r.trim();if(!t)return null;let o=t.toLowerCase();return e.find(n=>n.is_tappable&&n.text.toLowerCase()===o)??null}function Ue(e,r){let t=[],o=0;for(let i of r){let s=e.indexOf(i.text,o);s!==-1&&(s>o&&t.push({type:"text",value:e.slice(o,s)}),t.push({type:"completed",value:i.text,param:i}),o=s+i.text.length)}let n=e.slice(o);return n&&t.push({type:"text",value:n}),t}function Ke(e,r){let t=[],o=[],n=0;for(let i of r){let s=e.indexOf(i.text,n);s===-1?o.push(i):(t.push(i),n=s+i.text.length)}return{valid:t,invalid:o}}import{useCallback as lt,useEffect as Fe,useRef as Z,useState as Se}from"react";var it="0.1.12",De=!1;function at(){return crypto.randomUUID()}function st(e,r){return{placeholder:e.placeholder,type:e.type,...r&&{text:e.text},kind:e.kind}}async function ze(e,r,t){let o=t?.apiConfig,n=o?.apiKey??"";!n&&!De&&(De=!0,console.warn("[AIAutocomplete] No apiKey in apiConfig. Requests will be sent without an Authorization header."));let i=o?.authScheme??"Bearer",s=!t?.maskCompletedText,f=r.find(u=>u.type==="contact"&&u.metadata?.contact_account_count)?.metadata?.contact_account_count,p=typeof f=="number"?f:void 0,g={data:{raw_query:e,completed_params:r.map(u=>st(u,s)),...p!=null&&{contact_account_count:p}},meta:{request_id:at(),request_at:new Date().toISOString(),language:typeof navigator<"u"?navigator.language:"en-US",client_version:it}},c={"Content-Type":"application/json",...o?.appIdentifier&&{"X-App-Identifier":o.appIdentifier},...o?.headers};n&&(c.Authorization=i==="Basic"?`Basic ${btoa(n)}`:`Bearer ${n}`);let b=await fetch(o?.endpoint??"/ac/suggest",{method:"POST",headers:c,body:JSON.stringify(g),signal:t?.signal});if(!b.ok)throw new Error(`API error: ${b.status} ${b.statusText}`);return b.json()}function X(e,r){let t=e,o={},n=[];for(let i of r){let s=(o[i.type]??0)+1;o[i.type]=s;let p=`{{${i.type.toUpperCase().replace(/\s+/g,"_")}_${s}}}`,g=t.indexOf(i.text);g!==-1&&(t=t.slice(0,g)+p+t.slice(g+i.text.length)),n.push({...i,placeholder:p})}return{rawQuery:t,completedParams:n}}function je(e,r){return r?e.map(t=>{let o=r[t.type];if(!o)return t;let n=o("");if(n.length===0)return t;let i=new Set(n.map(f=>f.text)),s=(t.options??[]).filter(f=>!i.has(f.text));return{...t,options:[...n,...s]}}):e}var ct=100,ut=300,pt=2;function qe({textRef:e,suggestionsRef:r,filterBaseRef:t,maskCompletedTextRef:o,apiConfigRef:n,optionOverridesRef:i,onErrorRef:s,setCompletedParams:f,setSuggestions:p,setActiveDropdownIndex:g}){let[c,b]=Se(!1),[u,y]=Se(null),[I,h]=Se(!1),_=Z(0),O=Z(null),m=Z(""),d=lt(async(a,l)=>{O.current?.abort();let x=new AbortController;O.current=x;let v=++_.current,K=e.current.length;r.current.some(C=>C.type!=="placeholder")||b(!0),y(null);try{let C=await ze(a,l,{maskCompletedText:o.current,signal:x.signal,apiConfig:n.current});if(v!==_.current)return;let L=je(C.data.suggestions??[],i.current);h(C.data.is_ready??!1),m.current=a;let q=C.data.input??[],M=q[q.length-1],R=e.current;if(M?.state==="in_progress"){let j=R.toLowerCase().lastIndexOf(M.text.toLowerCase());j!==-1?t.current=j:t.current=K}else t.current=K;let T=L.filter(j=>j.type!=="placeholder")[0];if(T){let j=R.slice(t.current),$=ee(T.options,j);$&&(f(B=>[...B,{id:crypto.randomUUID(),placeholder:"",type:T.type,text:$.text,kind:$.kind,suggestionType:T.type,suggestionPlaceholder:T.text,options:T.options??[],metadata:$.metadata}]),L=L.filter(B=>B!==T))}p(L),b(!1),g(-1)}catch(C){if(v===_.current){let L=C instanceof Error?C:new Error(String(C));y(L),b(!1),s.current?.(L)}}},[e,r,t,o,n,i,s,f,p,g]);return Fe(()=>(d("",[]),()=>{O.current?.abort()}),[d]),{doFetch:d,isLoading:c,error:u,isReady:I,lastRawQueryRef:m}}function Ne({text:e,completedParams:r,doFetch:t,filterBaseRef:o,skipNextFetchRef:n,suggestionsRef:i,lastRawQueryRef:s}){let f=Z(null),p=Z(null),g=Z(!0);Fe(()=>{f.current&&clearTimeout(f.current),p.current&&clearTimeout(p.current);let c=b=>{if(n.current)return n.current=!1,!1;if(!e&&r.length===0)return g.current?(t("",[]),!0):(g.current=!0,!1);let u=e.slice(o.current),h=i.current.filter(K=>K.type!=="placeholder")[0],O=(h?ie(h.options,u):[]).filter(K=>K.is_tappable),m=h?ee(h.options,u)!==null:!1,d=u.trim().length>0;if(O.length>0&&!m&&d)return!1;let{rawQuery:a,completedParams:l}=X(e,r),x=a.length<s.current.length,v=Math.abs(a.length-s.current.length);return x||v>=b?(t(a,l),!0):!1};return f.current=setTimeout(()=>{c(pt)&&p.current&&clearTimeout(p.current)},ct),p.current=setTimeout(()=>c(1),ut),()=>{f.current&&clearTimeout(f.current),p.current&&clearTimeout(p.current)}},[e,r,t,o,n,i,s])}import{useCallback as $e}from"react";function Be({activeDropdownIndex:e,setActiveDropdownIndex:r,filteredOptions:t,selectOption:o,onSubmitRef:n,text:i,completedParams:s,isDropdownOpen:f,hasPlaceholder:p,placeholderText:g,suggestions:c,filterBaseRef:b,columns:u,setText:y,setCompletedParams:I,setSuggestions:h}){let _=$e(()=>{let m=t.map((a,l)=>a.is_tappable?l:-1).filter(a=>a!==-1),d=Array.from({length:u},()=>[]);for(let a of m)d[a%u].push(a);return d.flat()},[t,u]);return{handleKeyDown:$e(m=>{let d=_();switch(m.key){case"ArrowDown":{if(m.preventDefault(),d.length===0)return;let a=d.indexOf(e),l=a<d.length-1?a+1:0;r(d[l]);break}case"ArrowUp":{if(m.preventDefault(),d.length===0)return;let a=d.indexOf(e),l=a>0?a-1:d.length-1;r(d[l]);break}case"ArrowRight":{if(e<0)break;if(e%u<u-1){let l=e+1;l<t.length&&t[l]?.is_tappable&&(m.preventDefault(),r(l))}break}case"ArrowLeft":{if(e<0)break;if(e%u>0){let a=e-1;a>=0&&t[a]?.is_tappable&&(m.preventDefault(),r(a))}break}case"Enter":{if(m.preventDefault(),e>=0&&t[e]?.is_tappable)o(t[e]);else if(n.current){let{rawQuery:a,completedParams:l}=X(i,s),x={query:i.trim(),raw_query:a,completed_params:l};n.current(x)}break}case"Tab":{if(e>=0&&t[e]?.is_tappable)m.preventDefault(),o(t[e]);else if(f){let a=t.find(l=>l.is_tappable);a&&(m.preventDefault(),o(a))}else if(!i&&p){m.preventDefault();let a=c.find(l=>l.type==="placeholder");a?(y(g),b.current=g.length,I(l=>[...l,{id:crypto.randomUUID(),placeholder:"",type:a.type,text:g,kind:null,suggestionType:a.type,suggestionPlaceholder:a.text,options:a.options??[]}]),h(l=>l.filter(x=>x!==a))):(y(g),b.current=g.length)}break}case"Escape":r(-1);break}},[e,u,s,t,b,_,p,f,n,g,o,r,I,h,y,c,i]),getTappableIndices:_}}import{useCallback as xe}from"react";function Qe({completedParams:e,suggestions:r,setCompletedParams:t,setSuggestions:o,setActiveDropdownIndex:n,filterBaseRef:i,pillTappedRef:s}){let f=xe(c=>{let b=r.filter(h=>h.type!=="placeholder");if(c<0||c>=b.length)return;let u=b[c],y=b.filter((h,_)=>_!==c),I=r.filter(h=>h.type==="placeholder");o([...I,u,...y]),s.current=!0,n(-1)},[r,o,n,s]),p=xe(()=>{if(e.length===0)return;let c=e[e.length-1],b={type:c.suggestionType,text:c.suggestionPlaceholder,required:!0,options:c.options};t(u=>u.slice(0,-1)),o(u=>[b,...u]),n(-1)},[e,t,o,n]),g=xe(c=>{let b={type:c.suggestionType,text:c.suggestionPlaceholder,required:!0,options:c.options};return{apply:u=>{u(y=>{let I=0;for(let h of e){let _=y.indexOf(h.text,I);if(_!==-1){if(h.id===c.id){let O=y.slice(0,_),m=y.slice(_+c.text.length),d=(O+m).replace(/ {2,}/g," ");return i.current=Math.min(i.current,d.length),d}I=_+h.text.length}}return y}),t(y=>y.filter(I=>I.id!==c.id)),o(y=>[b,...y]),n(-1),s.current=!0}}},[e,t,o,n,i,s]);return{setActivePill:f,removeLastParam:p,reEditParam:g}}var dt=0;function mt(){let e=k(null);return e.current===null&&(e.current=`:ac-${++dt}:`),e.current}function Ae({onSubmit:e,onError:r,optionOverrides:t,maskCompletedText:o,placeholder:n,apiConfig:i,columns:s=2,eagerSuggestions:f=!0,value:p,completedParams:g,onChange:c,onParamsChange:b}){let u=p!==void 0,y=g!==void 0,[I,h]=se(""),[_,O]=se([]),[m,d]=se([]),[a,l]=se(-1),x=u?p:I,v=y?g:_,K=k(e);K.current=e;let z=k(c);z.current=c;let C=k(b);C.current=b;let L=k(p);L.current=p;let q=k(g);q.current=g;let M=J(S=>{if(typeof S=="function")if(u){let P=S(L.current??"");z.current?.(P)}else h(P=>{let N=S(P);return z.current?.(N),N});else u||h(S),z.current?.(S)},[u]),R=J(S=>{if(typeof S=="function")if(y){let P=S(q.current??[]);C.current?.(P)}else O(P=>{let N=S(P);return C.current?.(N),N});else y||O(S),C.current?.(S)},[y]),U=k(r);U.current=r;let T=k(t);T.current=t;let j=k(o);j.current=o;let $=k(i);$.current=i;let B=k(x);B.current=x;let le=k(m);le.current=m;let D=k(0),te=k(!1),_e=k(!1),ce=mt(),{doFetch:ue,isLoading:Pe,error:We,isReady:Ve,lastRawQueryRef:pe}=qe({textRef:B,suggestionsRef:le,filterBaseRef:D,maskCompletedTextRef:j,apiConfigRef:$,optionOverridesRef:T,onErrorRef:U,setCompletedParams:R,setSuggestions:d,setActiveDropdownIndex:l});Ne({text:x,completedParams:v,doFetch:ue,filterBaseRef:D,skipNextFetchRef:_e,suggestionsRef:le,lastRawQueryRef:pe});let Ge=ae(()=>Ue(x,v),[x,v]);D.current=Math.min(D.current,x.length);let de=x.slice(D.current),me=ae(()=>m.filter(P=>P.type==="placeholder").map(P=>P.text).join(" ")||n||"",[m,n]),oe=ae(()=>m.filter(S=>S.type!=="placeholder"),[m]),A=oe[0],ve=A?t?.[A.type]:void 0,Ce=A?ve?ve(de.trim()):A.options??[]:[],ge=ae(()=>ie(Ce,de),[Ce,de]),Ie=me.length>0,fe=!Pe&&ge.length>0&&(!!x||te.current||!Ie),we=J(S=>{if(!A)return;let P={id:crypto.randomUUID(),placeholder:"",type:A.type,text:S.text,kind:S.kind,suggestionType:A.type,suggestionPlaceholder:A.text,options:A.options??[],metadata:S.metadata},N=D.current,E=B.current.slice(0,N);if(E.length>0&&!E.endsWith(" ")){let w=E.split(/\s+/).pop()??"";w&&S.text.toLowerCase().startsWith(w.toLowerCase())&&(E=E.slice(0,E.length-w.length))}let be=E.length>0&&E[E.length-1]!==" ",V=E+(be?" ":"")+S.text+" ";M(V),D.current=V.length,R(w=>[...w,P]),te.current=!1,l(-1);let Q=oe.length-1;f&&Q>0?(d(w=>w.filter(H=>H!==A)),_e.current=!0):d(w=>w.filter(H=>H.type==="placeholder"))},[A,oe,f,M,R]),Xe=J(S=>{let P=S.target.value,E=P.length>0&&!S.nativeEvent?.isComposing&&P[0]!==P[0].toUpperCase()?P[0].toUpperCase()+P.slice(1):P;M(E),te.current=!1,l(-1);let{valid:be,invalid:V}=Ke(E,v);if(V.length>0){R(()=>be);for(let Q of V)d(w=>[{type:Q.suggestionType,text:Q.suggestionPlaceholder,required:!0,options:Q.options},...w])}if(A&&V.length===0){let Q=E.slice(D.current),w=ee(A.options,Q);w&&(R(H=>[...H,{id:crypto.randomUUID(),placeholder:"",type:A.type,text:w.text,kind:w.kind,suggestionType:A.type,suggestionPlaceholder:A.text,options:A.options??[],metadata:w.metadata}]),d(H=>H.filter(tt=>tt!==A)))}},[v,A,M,R]),{handleKeyDown:Ze}=Be({activeDropdownIndex:a,setActiveDropdownIndex:l,filteredOptions:ge,selectOption:we,onSubmitRef:K,text:x,completedParams:v,isDropdownOpen:fe,hasPlaceholder:Ie,placeholderText:me,suggestions:m,filterBaseRef:D,columns:s,setText:M,setCompletedParams:R,setSuggestions:d}),ne=Qe({completedParams:v,suggestions:m,setCompletedParams:R,setSuggestions:d,setActiveDropdownIndex:l,filterBaseRef:D,pillTappedRef:te}),Je=J(S=>{ne.reEditParam(S).apply(M)},[ne,M]),Ye=J(()=>{M(""),R(()=>[]),d([]),l(-1),D.current=0,pe.current="",ue("",[])},[ue,M,R,pe]),et=a>=0?`${ce}-option-${a}`:void 0;return{completedParams:v,suggestionPills:oe,setActivePill:ne.setActivePill,removeLastParam:ne.removeLastParam,reEditParam:Je,segments:Ge,suggestions:m,activeIndex:a,isReady:Ve,isLoading:Pe,error:We,inputProps:{value:x,placeholder:me||void 0,onChange:Xe,onKeyDown:Ze,role:"combobox","aria-expanded":fe,"aria-activedescendant":et,"aria-autocomplete":"list","aria-controls":ce},reset:Ye,dropdownProps:{suggestions:A?[{...A,options:ge}]:[],activeIndex:a,onSelect:we,onHighlight:l,isOpen:fe,id:ce}}}import{jsx as W,jsxs as Y}from"react/jsx-runtime";var yt=gt(function({onSubmit:r,onError:t,optionOverrides:o,maskCompletedText:n,placeholder:i,className:s,apiConfig:f,columns:p,eagerSuggestions:g,value:c,completedParams:b,onChange:u,onParamsChange:y},I){let h=He(null),_=He(()=>{});bt(()=>{h.current?.focus()},[]);let{completedParams:O,suggestionPills:m,setActivePill:d,segments:a,inputProps:l,dropdownProps:x,reset:v}=Ae({onSubmit:U=>_.current(U),onError:t,optionOverrides:o,maskCompletedText:n,placeholder:i,apiConfig:f,columns:p,eagerSuggestions:g,value:c,completedParams:b,onChange:u,onParamsChange:y});ht(I,()=>({focus:()=>h.current?.focus(),reset:v}),[v]);let K=()=>{h.current?.focus()},z=!!l.value||O.length>0,C=ft(()=>{if(!z)return;let{rawQuery:U,completedParams:T}=X(l.value,O);r({query:l.value.trim(),raw_query:U,completed_params:T}),v()},[z,l.value,O,r,v]);_.current=C;let{onChange:L,placeholder:q,...M}=l,R=!l.value;return Y("div",{className:`${F.container} ${s??""}`,children:[W(ye,{...x}),Y("div",{className:F.inputWrapper,onClick:K,children:[Y("div",{className:F.editorArea,children:[Y("div",{className:F.sizerContent,"aria-hidden":"true",children:[R&&q?Y("span",{className:F.placeholderText,children:[q," "]}):Y("span",{className:F.sizerText,children:[a.map((U,T)=>W("span",{children:U.value},`${T}-${U.type}`)),a.length===0&&"\xA0"]})," ",W(Le,{pills:m,activePillIndex:0,onSelectPill:d})]}),W("textarea",{ref:h,className:F.textarea,rows:1,onChange:L,...M})]}),W("button",{type:"button",className:F.submitButton,disabled:!z,onClick:U=>{U.stopPropagation(),C()},"aria-label":"Submit",children:W("svg",{width:"18",height:"18",viewBox:"0 0 18 18",fill:"none",role:"img","aria-label":"Submit",children:W("path",{d:"M9 14V4M9 4L4 9M9 4L14 9",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})})]})]})});export{yt as AIAutocomplete,ye as AIAutocompleteDropdown,Ae as useAIAutocomplete};
|
|
214
|
+
`,document.head.appendChild(e)}var se={list:"PillList-module_list_qvLqO",pill:"PillList-module_pill_osSyz",fadeIn:"PillList-module_fadeIn_Aezob",active:"PillList-module_active_Oll--"};import{jsx as Ue}from"react/jsx-runtime";function at(e){return e===0?.4:e===1?.3:.15}function De({pills:e,activePillIndex:r,onSelectPill:t}){return Ue("span",{className:se.list,children:e.map((o,n)=>Ue("button",{type:"button",className:`${se.pill} ${n===r?se.active:""}`,style:{opacity:at(n)},onClick:()=>t(n),children:o.text},`${o.type}-${o.text}`))})}import{useCallback as ee,useMemo as ce,useRef as O,useState as ue}from"react";function Z(e,r,t){let o=e.slice(r);if(t||r===0||e[r-1]===" ")return o;let n=o.indexOf(" ");return n===-1?"":o.slice(n+1)}function le(e,r){if(!e)return[];let t=r.trimStart();if(!t)return e;let o=t.toLowerCase();return e.filter(n=>!n.is_tappable||n.text.toLowerCase().includes(o))}function ie(e,r){if(!e)return null;let t=r.trim();if(!t)return null;let o=t.toLowerCase();return e.find(n=>n.is_tappable&&n.text.toLowerCase()===o)??null}function Ke(e,r){let t=[],o=0;for(let i of r){let s=e.indexOf(i.text,o);s!==-1&&(s>o&&t.push({type:"text",value:e.slice(o,s)}),t.push({type:"completed",value:i.text,param:i}),o=s+i.text.length)}let n=e.slice(o);return n&&t.push({type:"text",value:n}),t}function je(e,r){let t=[],o=[],n=0;for(let i of r){let s=e.indexOf(i.text,n);s===-1?o.push(i):(t.push(i),n=s+i.text.length)}return{valid:t,invalid:o}}import{useCallback as ut,useEffect as Ne,useRef as Y,useState as Ae}from"react";var st="0.1.13",ze=!1;function lt(){return crypto.randomUUID()}function ct(e,r){return{placeholder:e.placeholder,type:e.type,...r&&{text:e.text},kind:e.kind}}async function Fe(e,r,t){let o=t?.apiConfig,n=o?.apiKey??"";!n&&!ze&&(ze=!0,console.warn("[AIAutocomplete] No apiKey in apiConfig. Requests will be sent without an Authorization header."));let i=o?.authScheme??"Bearer",s=!t?.maskCompletedText,b=r.find(m=>m.type==="contact"&&m.metadata?.contact_account_count)?.metadata?.contact_account_count,d=typeof b=="number"?b:void 0,c={data:{raw_query:e,completed_params:r.map(m=>ct(m,s)),...d!=null&&{contact_account_count:d}},meta:{request_id:lt(),request_at:new Date().toISOString(),language:typeof navigator<"u"?navigator.language:"en-US",client_version:st}},u={"Content-Type":"application/json",...o?.appIdentifier&&{"X-App-Identifier":o.appIdentifier},...o?.headers};n&&(u.Authorization=i==="Basic"?`Basic ${btoa(n)}`:`Bearer ${n}`);let h=await fetch(o?.endpoint??"/ac/suggest",{method:"POST",headers:u,body:JSON.stringify(c),signal:t?.signal});if(!h.ok)throw new Error(`API error: ${h.status} ${h.statusText}`);return h.json()}function J(e,r){let t=e,o={},n=[];for(let i of r){let s=(o[i.type]??0)+1;o[i.type]=s;let d=`{{${i.type.toUpperCase().replace(/\s+/g,"_")}_${s}}}`,c=t.indexOf(i.text);c!==-1&&(t=t.slice(0,c)+d+t.slice(c+i.text.length)),n.push({...i,placeholder:d})}return{rawQuery:t,completedParams:n}}function qe(e,r){return r?e.map(t=>{let o=r[t.type];if(!o)return t;let n=o("");if(n.length===0)return t;let i=new Set(n.map(b=>b.text)),s=(t.options??[]).filter(b=>!i.has(b.text));return{...t,options:[...n,...s]}}):e}var pt=100,dt=300,mt=2;function Qe({textRef:e,suggestionsRef:r,filterBaseRef:t,filterInProgressRef:o,maskCompletedTextRef:n,apiConfigRef:i,optionOverridesRef:s,onErrorRef:b,setCompletedParams:d,setSuggestions:c,setActiveDropdownIndex:u}){let[h,m]=Ae(!1),[g,A]=Ae(null),[S,_]=Ae(!1),I=Y(0),x=Y(null),C=Y(""),f=ut(async(p,a)=>{x.current?.abort();let l=new AbortController;x.current=l;let U=++I.current,R=e.current.length;r.current.some(M=>M.type!=="placeholder")||m(!0),A(null);try{let M=await Fe(p,a,{maskCompletedText:n.current,signal:l.signal,apiConfig:i.current});if(U!==I.current)return;let D=qe(M.data.suggestions??[],s.current);_(M.data.is_ready??!1),C.current=p;let T=M.data.input??[],k=T[T.length-1],E=e.current;if(k?.state==="in_progress"){o.current=!0;let z=E.toLowerCase().lastIndexOf(k.text.toLowerCase());z!==-1?t.current=z:t.current=R}else o.current=!1,t.current=R;let j=D.filter(z=>z.type!=="placeholder")[0];if(j){let z=Z(E,t.current,o.current),N=ie(j.options,z);N&&(d(B=>[...B,{id:crypto.randomUUID(),placeholder:"",type:j.type,text:N.text,kind:N.kind,suggestionType:j.type,suggestionPlaceholder:j.text,options:j.options??[],metadata:N.metadata}]),D=D.filter(B=>B!==j))}c(D),m(!1),u(-1)}catch(M){if(U===I.current){let D=M instanceof Error?M:new Error(String(M));A(D),m(!1),b.current?.(D)}}},[e,r,t,o,n,i,s,b,d,c,u]);return Ne(()=>(f("",[]),()=>{x.current?.abort()}),[f]),{doFetch:f,isLoading:h,error:g,isReady:S,lastRawQueryRef:C}}function $e({text:e,completedParams:r,doFetch:t,filterBaseRef:o,filterInProgressRef:n,skipNextFetchRef:i,suggestionsRef:s,lastRawQueryRef:b}){let d=Y(null),c=Y(null),u=Y(!0);Ne(()=>{d.current&&clearTimeout(d.current),c.current&&clearTimeout(c.current);let h=m=>{if(i.current)return i.current=!1,!1;if(!e&&r.length===0)return u.current?(t("",[]),!0):(u.current=!0,!1);let g=Z(e,o.current,n.current),_=s.current.filter(R=>R.type!=="placeholder")[0],x=(_?le(_.options,g):[]).filter(R=>R.is_tappable),C=_?ie(_.options,g)!==null:!1,f=g.trim().length>0;if(x.length>0&&!C&&f)return!1;let{rawQuery:p,completedParams:a}=J(e,r),l=p.length<b.current.length,U=Math.abs(p.length-b.current.length);return l||U>=m?(t(p,a),!0):!1};return d.current=setTimeout(()=>{h(mt)&&c.current&&clearTimeout(c.current)},pt),c.current=setTimeout(()=>h(1),dt),()=>{d.current&&clearTimeout(d.current),c.current&&clearTimeout(c.current)}},[e,r,t,o,n,i,s,b])}import{useCallback as Be}from"react";function He({activeDropdownIndex:e,setActiveDropdownIndex:r,filteredOptions:t,selectOption:o,onSubmitRef:n,text:i,completedParams:s,isDropdownOpen:b,hasPlaceholder:d,placeholderText:c,suggestions:u,actionableSuggestions:h,setActivePill:m,filterBaseRef:g,columns:A,setText:S,setCompletedParams:_,setSuggestions:I}){let x=Be(()=>{let f=t.map((a,l)=>a.is_tappable?l:-1).filter(a=>a!==-1),p=Array.from({length:A},()=>[]);for(let a of f)p[a%A].push(a);return p.flat()},[t,A]);return{handleKeyDown:Be(f=>{let p=x();switch(f.key){case"ArrowDown":{if(f.preventDefault(),p.length===0)return;let a=p.indexOf(e),l=a<p.length-1?a+1:0;r(p[l]);break}case"ArrowUp":{if(f.preventDefault(),p.length===0)return;let a=p.indexOf(e),l=a>0?a-1:p.length-1;r(p[l]);break}case"ArrowRight":{if(e<0){h.length>1&&(f.preventDefault(),m(1));break}if(e%A<A-1){let l=e+1;l<t.length&&t[l]?.is_tappable&&(f.preventDefault(),r(l))}break}case"ArrowLeft":{if(e<0)break;if(e%A>0){let a=e-1;a>=0&&t[a]?.is_tappable&&(f.preventDefault(),r(a))}break}case"Enter":{if(f.preventDefault(),e>=0&&t[e]?.is_tappable)o(t[e]);else if(n.current){let{rawQuery:a,completedParams:l}=J(i,s),U={query:i.trim(),raw_query:a,completed_params:l};n.current(U)}break}case"Tab":{if(e>=0&&t[e]?.is_tappable)f.preventDefault(),o(t[e]);else if(b){let a=t.find(l=>l.is_tappable);a&&(f.preventDefault(),o(a))}else if(!i&&d){f.preventDefault();let a=u.find(l=>l.type==="placeholder");a?(S(c),g.current=c.length,_(l=>[...l,{id:crypto.randomUUID(),placeholder:"",type:a.type,text:c,kind:null,suggestionType:a.type,suggestionPlaceholder:a.text,options:a.options??[]}]),I(l=>l.filter(U=>U!==a))):(S(c),g.current=c.length)}break}case"Escape":r(-1);break}},[h,e,A,s,t,g,x,d,b,n,c,o,r,m,_,I,S,u,i]),getTappableIndices:x}}import{useCallback as _e}from"react";function We({completedParams:e,suggestions:r,setCompletedParams:t,setSuggestions:o,setActiveDropdownIndex:n,filterBaseRef:i,pillTappedRef:s}){let b=_e(u=>{let h=r.filter(S=>S.type!=="placeholder");if(u<0||u>=h.length)return;let m=h[u],g=h.filter((S,_)=>_!==u),A=r.filter(S=>S.type==="placeholder");o([...A,m,...g]),s.current=!0,n(-1)},[r,o,n,s]),d=_e(()=>{if(e.length===0)return;let u=e[e.length-1],h={type:u.suggestionType,text:u.suggestionPlaceholder,required:!0,options:u.options};t(m=>m.slice(0,-1)),o(m=>[h,...m]),n(-1)},[e,t,o,n]),c=_e(u=>{let h={type:u.suggestionType,text:u.suggestionPlaceholder,required:!0,options:u.options};return{apply:m=>{m(g=>{let A=0;for(let S of e){let _=g.indexOf(S.text,A);if(_!==-1){if(S.id===u.id){let I=g.slice(0,_),x=g.slice(_+u.text.length),C=(I+x).replace(/ {2,}/g," ");return i.current=Math.min(i.current,C.length),C}A=_+S.text.length}}return g}),t(g=>g.filter(A=>A.id!==u.id)),o(g=>[h,...g]),n(-1),s.current=!0}}},[e,t,o,n,i,s]);return{setActivePill:b,removeLastParam:d,reEditParam:c}}var gt=0;function ft(){let e=O(null);return e.current===null&&(e.current=`:ac-${++gt}:`),e.current}function ve({onSubmit:e,onError:r,optionOverrides:t,maskCompletedText:o,placeholder:n,apiConfig:i,columns:s=2,eagerSuggestions:b=!0,value:d,completedParams:c,onChange:u,onParamsChange:h}){let m=d!==void 0,g=c!==void 0,[A,S]=ue(""),[_,I]=ue([]),[x,C]=ue([]),[f,p]=ue(-1),a=m?d:A,l=g?c:_,U=O(e);U.current=e;let R=O(u);R.current=u;let q=O(h);q.current=h;let M=O(d);M.current=d;let D=O(c);D.current=c;let T=ee(y=>{if(typeof y=="function")if(m){let P=y(M.current??"");R.current?.(P)}else S(P=>{let Q=y(P);return R.current?.(Q),Q});else m||S(y),R.current?.(y)},[m]),k=ee(y=>{if(typeof y=="function")if(g){let P=y(D.current??[]);q.current?.(P)}else I(P=>{let Q=y(P);return q.current?.(Q),Q});else g||I(y),q.current?.(y)},[g]),E=O(r);E.current=r;let $=O(t);$.current=t;let j=O(o);j.current=o;let z=O(i);z.current=i;let N=O(a);N.current=a;let B=O(x);B.current=x;let K=O(0),oe=O(!1),ae=O(!1),Pe=O(!1),pe=ft(),{doFetch:de,isLoading:Ce,error:Ge,isReady:Xe,lastRawQueryRef:me}=Qe({textRef:N,suggestionsRef:B,filterBaseRef:K,filterInProgressRef:oe,maskCompletedTextRef:j,apiConfigRef:z,optionOverridesRef:$,onErrorRef:E,setCompletedParams:k,setSuggestions:C,setActiveDropdownIndex:p});$e({text:a,completedParams:l,doFetch:de,filterBaseRef:K,filterInProgressRef:oe,skipNextFetchRef:Pe,suggestionsRef:B,lastRawQueryRef:me});let Ze=ce(()=>Ke(a,l),[a,l]);K.current=Math.min(K.current,a.length);let ge=Z(a,K.current,oe.current),fe=ce(()=>x.filter(P=>P.type==="placeholder").map(P=>P.text).join(" ")||n||"",[x,n]),ne=ce(()=>x.filter(y=>y.type!=="placeholder"),[x]),v=ne[0],Ie=v?t?.[v.type]:void 0,we=v?Ie?Ie(ge.trim()):v.options??[]:[],be=ce(()=>le(we,ge),[we,ge]),Oe=fe.length>0,he=!Ce&&be.length>0&&(!!a||ae.current||!Oe),Re=ee(y=>{if(!v)return;let P={id:crypto.randomUUID(),placeholder:"",type:v.type,text:y.text,kind:y.kind,suggestionType:v.type,suggestionPlaceholder:v.text,options:v.options??[],metadata:y.metadata},Q=K.current,L=N.current.slice(0,Q);if(L.length>0&&!L.endsWith(" ")){let w=L.split(/\s+/).pop()??"";w&&y.text.toLowerCase().startsWith(w.toLowerCase())&&(L=L.slice(0,L.length-w.length))}let ye=L.length>0&&L[L.length-1]!==" ",G=L+(ye?" ":"")+y.text+" ";T(G),K.current=G.length,k(w=>[...w,P]),ae.current=!1,p(-1);let H=ne.length-1;b&&H>0?(C(w=>w.filter(W=>W!==v)),Pe.current=!0):C(w=>w.filter(W=>W.type==="placeholder"))},[v,ne,b,T,k]),Je=ee(y=>{let P=y.target.value,L=P.length>0&&!y.nativeEvent?.isComposing&&P[0]!==P[0].toUpperCase()?P[0].toUpperCase()+P.slice(1):P;T(L),ae.current=!1,p(-1);let{valid:ye,invalid:G}=je(L,l);if(G.length>0){k(()=>ye);for(let H of G)C(w=>[{type:H.suggestionType,text:H.suggestionPlaceholder,required:!0,options:H.options},...w])}if(v&&G.length===0){let H=Z(L,K.current,oe.current),w=ie(v.options,H);w&&(k(W=>[...W,{id:crypto.randomUUID(),placeholder:"",type:v.type,text:w.text,kind:w.kind,suggestionType:v.type,suggestionPlaceholder:v.text,options:v.options??[],metadata:w.metadata}]),C(W=>W.filter(nt=>nt!==v)))}},[l,v,T,k]),re=We({completedParams:l,suggestions:x,setCompletedParams:k,setSuggestions:C,setActiveDropdownIndex:p,filterBaseRef:K,pillTappedRef:ae}),Ye=ee(y=>{re.reEditParam(y).apply(T)},[re,T]),{handleKeyDown:et}=He({activeDropdownIndex:f,setActiveDropdownIndex:p,filteredOptions:be,selectOption:Re,onSubmitRef:U,text:a,completedParams:l,isDropdownOpen:he,hasPlaceholder:Oe,placeholderText:fe,suggestions:x,actionableSuggestions:ne,setActivePill:re.setActivePill,filterBaseRef:K,columns:s,setText:T,setCompletedParams:k,setSuggestions:C}),tt=ee(()=>{T(""),k(()=>[]),C([]),p(-1),K.current=0,oe.current=!1,me.current="",de("",[])},[de,T,k,me]),ot=f>=0?`${pe}-option-${f}`:void 0;return{completedParams:l,suggestionPills:ne,setActivePill:re.setActivePill,removeLastParam:re.removeLastParam,reEditParam:Ye,segments:Ze,suggestions:x,activeIndex:f,isReady:Xe,isLoading:Ce,error:Ge,inputProps:{value:a,placeholder:fe||void 0,onChange:Je,onKeyDown:et,role:"combobox","aria-expanded":he,"aria-activedescendant":ot,"aria-autocomplete":"list","aria-controls":pe},reset:tt,dropdownProps:{suggestions:v?[{...v,options:be}]:[],activeIndex:f,onSelect:Re,onHighlight:p,isOpen:he,id:pe}}}import{jsx as V,jsxs as te}from"react/jsx-runtime";var xt=bt(function({onSubmit:r,onError:t,optionOverrides:o,maskCompletedText:n,placeholder:i,className:s,apiConfig:b,columns:d,eagerSuggestions:c,value:u,completedParams:h,onChange:m,onParamsChange:g},A){let S=Ve(null),_=Ve(()=>{});yt(()=>{S.current?.focus()},[]);let{completedParams:I,suggestionPills:x,setActivePill:C,segments:f,inputProps:p,dropdownProps:a,reset:l}=ve({onSubmit:E=>_.current(E),onError:t,optionOverrides:o,maskCompletedText:n,placeholder:i,apiConfig:b,columns:d,eagerSuggestions:c,value:u,completedParams:h,onChange:m,onParamsChange:g});St(A,()=>({focus:()=>S.current?.focus(),reset:l}),[l]);let U=()=>{S.current?.focus()},R=!!p.value||I.length>0,q=ht(()=>{if(!R)return;let{rawQuery:E,completedParams:$}=J(p.value,I);r({query:p.value.trim(),raw_query:E,completed_params:$}),l()},[R,p.value,I,r,l]);_.current=q;let{onChange:M,placeholder:D,...T}=p,k=!p.value;return te("div",{className:`${F.container} ${s??""}`,children:[V(xe,{...a}),te("div",{className:F.inputWrapper,onClick:U,children:[te("div",{className:F.editorArea,children:[te("div",{className:F.sizerContent,"aria-hidden":"true",children:[k&&D?te("span",{className:F.placeholderText,children:[D," "]}):te("span",{className:F.sizerText,children:[f.map((E,$)=>V("span",{children:E.value},`${$}-${E.type}`)),f.length===0&&"\xA0"]})," ",V(De,{pills:x,activePillIndex:0,onSelectPill:C})]}),V("textarea",{ref:S,className:F.textarea,rows:1,onChange:M,...T})]}),V("button",{type:"button",className:F.submitButton,disabled:!R,onClick:E=>{E.stopPropagation(),q()},"aria-label":"Submit",children:V("svg",{width:"18",height:"18",viewBox:"0 0 18 18",fill:"none",role:"img","aria-label":"Submit",children:V("path",{d:"M9 14V4M9 4L4 9M9 4L14 9",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})})]})]})});export{xt as AIAutocomplete,xe as AIAutocompleteDropdown,ve as useAIAutocomplete};
|
|
215
215
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/AIAutocomplete.tsx","css-module:/Users/saharshv/MagicX/ai-autocomplete-react/src/AIAutocomplete.module.css.js","css-module:/Users/saharshv/MagicX/ai-autocomplete-react/src/AIAutocompleteDropdown.module.css.js","css-module:/Users/saharshv/MagicX/ai-autocomplete-react/src/components/SuggestionGrid.module.css.js","css-module:/Users/saharshv/MagicX/ai-autocomplete-react/src/components/SuggestionItem.module.css.js","../src/components/SuggestionItem.tsx","../src/components/SuggestionGrid.tsx","../src/AIAutocompleteDropdown.tsx","css-module:/Users/saharshv/MagicX/ai-autocomplete-react/src/components/PillList.module.css.js","../src/components/PillList.tsx","../src/hooks/useAIAutocomplete.ts","../src/utils/filtering.ts","../src/utils/segments.ts","../src/hooks/useAutocompleteFetch.ts","../src/utils/api.ts","../src/utils/buildQuery.ts","../src/utils/overrides.ts","../src/hooks/useAutocompleteKeyboard.ts","../src/hooks/useAutocompletePills.ts"],"sourcesContent":["import { forwardRef, useCallback, useEffect, useImperativeHandle, useRef } from \"react\";\nimport styles from \"./AIAutocomplete.module.css\";\nimport { AIAutocompleteDropdown } from \"./AIAutocompleteDropdown\";\nimport { PillList } from \"./components/PillList\";\nimport { useAIAutocomplete } from \"./hooks/useAIAutocomplete\";\nimport type { AIAutocompleteHandle, AIAutocompleteProps, AutocompleteResult } from \"./types\";\nimport { buildQuery } from \"./utils/buildQuery\";\n\nexport const AIAutocomplete = forwardRef<AIAutocompleteHandle, AIAutocompleteProps>(\n function AIAutocomplete(\n {\n onSubmit,\n onError,\n optionOverrides,\n maskCompletedText,\n placeholder,\n className,\n apiConfig,\n columns,\n eagerSuggestions,\n value,\n completedParams: controlledParams,\n onChange: onChangeProp,\n onParamsChange,\n },\n ref,\n ) {\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n // Render-phase ref assignment — matches the pattern in useAIAutocomplete.ts\n const handleSubmitRef = useRef<(result: AutocompleteResult) => void>(() => {});\n\n useEffect(() => {\n textareaRef.current?.focus();\n }, []);\n\n const {\n completedParams,\n suggestionPills,\n setActivePill,\n segments,\n inputProps,\n dropdownProps,\n reset,\n } = useAIAutocomplete({\n onSubmit: (result) => handleSubmitRef.current(result),\n onError,\n optionOverrides,\n maskCompletedText,\n placeholder,\n apiConfig,\n columns,\n eagerSuggestions,\n value,\n completedParams: controlledParams,\n onChange: onChangeProp,\n onParamsChange,\n });\n\n useImperativeHandle(\n ref,\n () => ({\n focus: () => textareaRef.current?.focus(),\n reset,\n }),\n [reset],\n );\n\n const handleContainerClick = () => {\n textareaRef.current?.focus();\n };\n\n const canSubmit = !!inputProps.value || completedParams.length > 0;\n\n const handleSubmit = useCallback(() => {\n if (!canSubmit) return;\n const { rawQuery, completedParams: finalParams } = buildQuery(\n inputProps.value,\n completedParams,\n );\n onSubmit({\n query: inputProps.value.trim(),\n raw_query: rawQuery,\n completed_params: finalParams,\n });\n reset();\n }, [canSubmit, inputProps.value, completedParams, onSubmit, reset]);\n\n handleSubmitRef.current = handleSubmit;\n\n const { onChange, placeholder: inputPlaceholder, ...restProps } = inputProps;\n const isEmpty = !inputProps.value;\n\n return (\n <div className={`${styles.container} ${className ?? \"\"}`}>\n <AIAutocompleteDropdown {...dropdownProps} />\n {/* biome-ignore lint/a11y/useKeyWithClickEvents: container click delegates to textarea focus */}\n {/* biome-ignore lint/a11y/noStaticElementInteractions: wrapper delegates focus to textarea */}\n <div className={styles.inputWrapper} onClick={handleContainerClick}>\n <div className={styles.editorArea}>\n <div className={styles.sizerContent} aria-hidden=\"true\">\n {isEmpty && inputPlaceholder ? (\n <span className={styles.placeholderText}>{inputPlaceholder} </span>\n ) : (\n <span className={styles.sizerText}>\n {segments.map((seg, i) => (\n // biome-ignore lint/suspicious/noArrayIndexKey: segments are positional and don't reorder\n <span key={`${i}-${seg.type}`}>{seg.value}</span>\n ))}\n {segments.length === 0 && \"\\u00A0\"}\n </span>\n )}\n {\" \"}\n <PillList pills={suggestionPills} activePillIndex={0} onSelectPill={setActivePill} />\n </div>\n <textarea\n ref={textareaRef}\n className={styles.textarea}\n rows={1}\n onChange={onChange}\n {...restProps}\n />\n </div>\n <button\n type=\"button\"\n className={styles.submitButton}\n disabled={!canSubmit}\n onClick={(e) => {\n e.stopPropagation();\n handleSubmit();\n }}\n aria-label=\"Submit\"\n >\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 18 18\"\n fill=\"none\"\n role=\"img\"\n aria-label=\"Submit\"\n >\n <path\n d=\"M9 14V4M9 4L4 9M9 4L14 9\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n </button>\n </div>\n </div>\n );\n },\n);\n","if (typeof document !== \"undefined\" && !document.getElementById(\"ac-style-cc65f4cc\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-cc65f4cc\";\n s.textContent = `.AIAutocomplete-module_container_KKjFU {\n position: relative;\n font-family: \"IBM Plex Sans\", sans-serif;\n}\n\n.AIAutocomplete-module_inputWrapper_FLq1b {\n min-height: 60px;\n padding: 24px;\n border: 1px solid var(--ac-color-border-default, #9ea5b2);\n border-radius: 23px;\n background: transparent;\n overflow: hidden;\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.AIAutocomplete-module_editorArea_7rBWq {\n position: relative;\n flex: 1;\n min-width: 0;\n}\n\n.AIAutocomplete-module_sizerContent_DQgmV {\n position: relative;\n z-index: 1;\n pointer-events: none;\n min-height: 60px;\n white-space: pre-wrap;\n word-break: break-word;\n font-family: inherit;\n font-size: 21px;\n line-height: 38px;\n}\n\n.AIAutocomplete-module_sizerText_iZIMK {\n color: transparent;\n}\n\n.AIAutocomplete-module_placeholderText_K3ayy {\n color: var(--ac-color-text-muted, #c1c4cb);\n opacity: 0.7;\n}\n\n.AIAutocomplete-module_textarea_eyn6A {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n padding: 0;\n border: none;\n background: transparent;\n color: var(--ac-color-text-default, #fff);\n caret-color: var(--ac-color-text-default, #fff);\n font-family: inherit;\n font-size: 21px;\n line-height: 38px;\n white-space: pre-wrap;\n word-break: break-word;\n outline: none;\n resize: none;\n overflow: hidden;\n}\n\n.AIAutocomplete-module_textarea_eyn6A::placeholder {\n color: var(--ac-color-text-muted, #c1c4cb);\n}\n\n.AIAutocomplete-module_submitButton_sl1Mi {\n flex-shrink: 0;\n width: 36px;\n height: 36px;\n border-radius: 50%;\n border: none;\n background: var(--ac-color-text-default, #fff);\n color: var(--ac-color-bg-default, #000);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n transition: opacity 0.2s ease;\n}\n\n.AIAutocomplete-module_submitButton_sl1Mi:hover {\n opacity: 0.85;\n}\n`;\n document.head.appendChild(s);\n}\nexport default {\"container\":\"AIAutocomplete-module_container_KKjFU\",\"inputWrapper\":\"AIAutocomplete-module_inputWrapper_FLq1b\",\"editorArea\":\"AIAutocomplete-module_editorArea_7rBWq\",\"sizerContent\":\"AIAutocomplete-module_sizerContent_DQgmV\",\"sizerText\":\"AIAutocomplete-module_sizerText_iZIMK\",\"placeholderText\":\"AIAutocomplete-module_placeholderText_K3ayy\",\"textarea\":\"AIAutocomplete-module_textarea_eyn6A\",\"submitButton\":\"AIAutocomplete-module_submitButton_sl1Mi\"};","if (typeof document !== \"undefined\" && !document.getElementById(\"ac-style-2eef895d\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-2eef895d\";\n s.textContent = `.AIAutocompleteDropdown-module_dropdown_yz2KC {\n position: absolute;\n left: 0;\n right: 0;\n top: 100%;\n margin-top: 6px;\n background: var(--ac-color-background-default, #00002d);\n border-radius: 23px;\n overflow: hidden;\n z-index: 10;\n opacity: 0;\n pointer-events: none;\n transition: opacity 400ms cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.AIAutocompleteDropdown-module_visible_QCoXj {\n opacity: 1;\n pointer-events: auto;\n}\n`;\n document.head.appendChild(s);\n}\nexport default {\"dropdown\":\"AIAutocompleteDropdown-module_dropdown_yz2KC\",\"visible\":\"AIAutocompleteDropdown-module_visible_QCoXj\"};","if (typeof document !== \"undefined\" && !document.getElementById(\"ac-style-d91f2b06\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-d91f2b06\";\n s.textContent = `.SuggestionGrid-module_grid_jvaPb {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 12px 18px;\n padding: 18px 24px;\n max-height: 192px;\n overflow-y: auto;\n scrollbar-width: thin;\n scrollbar-color: rgba(255, 255, 255, 0.3) transparent;\n}\n\n.SuggestionGrid-module_grid_jvaPb::-webkit-scrollbar {\n width: 6px;\n}\n\n.SuggestionGrid-module_grid_jvaPb::-webkit-scrollbar-track {\n background: transparent;\n}\n\n.SuggestionGrid-module_grid_jvaPb::-webkit-scrollbar-thumb {\n background: rgba(255, 255, 255, 0.3);\n border-radius: 3px;\n}\n`;\n document.head.appendChild(s);\n}\nexport default {\"grid\":\"SuggestionGrid-module_grid_jvaPb\"};","if (typeof document !== \"undefined\" && !document.getElementById(\"ac-style-f6bdc634\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-f6bdc634\";\n s.textContent = `.SuggestionItem-module_item_d4vpD {\n display: flex;\n align-items: center;\n font-family: \"IBM Plex Sans\", sans-serif;\n font-size: 21px;\n line-height: 30px;\n color: var(--ac-color-text-muted, #c1c4cb);\n white-space: nowrap;\n opacity: 0.35;\n animation: SuggestionItem-module_fadeIn_I8u35 400ms cubic-bezier(0.4, 0, 0.2, 1) forwards;\n}\n\n@keyframes SuggestionItem-module_fadeIn_I8u35 {\n from {\n opacity: 0;\n }\n}\n\n.SuggestionItem-module_tappable_70KcX {\n cursor: pointer;\n}\n\n.SuggestionItem-module_tappable_70KcX:hover {\n color: var(--ac-color-text-default, #fff);\n}\n\n.SuggestionItem-module_nonTappable_xSZM- {\n cursor: default;\n opacity: 0.3;\n}\n\n.SuggestionItem-module_highlighted_Hb0SU {\n color: var(--ac-color-text-default, #fff);\n opacity: 0.5;\n}\n\n.SuggestionItem-module_tag_e3Fwe {\n font-size: 13px;\n margin-left: 6px;\n opacity: 0.5;\n}\n`;\n document.head.appendChild(s);\n}\nexport default {\"item\":\"SuggestionItem-module_item_d4vpD\",\"fadeIn\":\"SuggestionItem-module_fadeIn_I8u35\",\"tappable\":\"SuggestionItem-module_tappable_70KcX\",\"nonTappable\":\"SuggestionItem-module_nonTappable_xSZM-\",\"highlighted\":\"SuggestionItem-module_highlighted_Hb0SU\",\"tag\":\"SuggestionItem-module_tag_e3Fwe\"};","import type { SuggestionOption } from \"../types\";\nimport styles from \"./SuggestionItem.module.css\";\n\ninterface SuggestionItemProps {\n option: SuggestionOption;\n isHighlighted: boolean;\n onSelect: (option: SuggestionOption) => void;\n onHighlight: () => void;\n id: string;\n}\n\nexport function SuggestionItem({\n option,\n isHighlighted,\n onSelect,\n onHighlight,\n id,\n}: SuggestionItemProps) {\n const className = [\n styles.item,\n isHighlighted ? styles.highlighted : \"\",\n option.is_tappable ? styles.tappable : styles.nonTappable,\n ]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <div\n id={id}\n role=\"option\"\n aria-selected={isHighlighted}\n className={className}\n tabIndex={option.is_tappable ? 0 : -1}\n onClick={() => option.is_tappable && onSelect(option)}\n onKeyDown={(e) => {\n if (option.is_tappable && (e.key === \"Enter\" || e.key === \" \")) {\n e.preventDefault();\n onSelect(option);\n }\n }}\n onMouseEnter={onHighlight}\n >\n {option.icon ? `${option.icon} ${option.text}` : option.text}\n {option.tag && <span className={styles.tag}>{option.tag}</span>}\n </div>\n );\n}\n","import type { SuggestionOption } from \"../types\";\nimport styles from \"./SuggestionGrid.module.css\";\nimport { SuggestionItem } from \"./SuggestionItem\";\n\ninterface SuggestionGridProps {\n options: SuggestionOption[];\n activeIndex: number;\n onSelect: (option: SuggestionOption) => void;\n onHighlight: (index: number) => void;\n listboxId: string;\n}\n\nexport function SuggestionGrid({\n options,\n activeIndex,\n onSelect,\n onHighlight,\n listboxId,\n}: SuggestionGridProps) {\n return (\n <div className={styles.grid}>\n {options.map((option, i) => (\n <SuggestionItem\n key={option.text}\n option={option}\n isHighlighted={i === activeIndex}\n onSelect={onSelect}\n onHighlight={() => onHighlight(i)}\n id={`${listboxId}-option-${i}`}\n />\n ))}\n </div>\n );\n}\n","import styles from \"./AIAutocompleteDropdown.module.css\";\nimport { SuggestionGrid } from \"./components/SuggestionGrid\";\nimport type { AIAutocompleteDropdownProps } from \"./types\";\n\nexport function AIAutocompleteDropdown({\n suggestions,\n activeIndex,\n onSelect,\n onHighlight,\n isOpen,\n id,\n className,\n}: AIAutocompleteDropdownProps) {\n const activeSuggestion = suggestions[0];\n const options = activeSuggestion?.options ?? [];\n const hasOptions = isOpen && options.length > 0;\n\n return (\n <div\n id={id}\n role=\"listbox\"\n className={`${styles.dropdown} ${hasOptions ? styles.visible : \"\"} ${className ?? \"\"}`}\n onMouseDown={(e) => e.preventDefault()}\n >\n {options.length > 0 && (\n <SuggestionGrid\n options={options}\n activeIndex={activeIndex}\n onSelect={onSelect}\n onHighlight={onHighlight}\n listboxId={id}\n />\n )}\n </div>\n );\n}\n","if (typeof document !== \"undefined\" && !document.getElementById(\"ac-style-b745b4fb\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-b745b4fb\";\n s.textContent = `.PillList-module_list_qvLqO {\n position: relative;\n z-index: 1;\n pointer-events: auto;\n display: inline-flex;\n gap: 5px;\n align-items: center;\n vertical-align: middle;\n transform: translateY(-3px);\n}\n\n.PillList-module_pill_osSyz {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n height: 36px;\n padding: 7px 9px;\n border: none;\n border-radius: 6px;\n background: var(--ac-color-background-supportive, #313255);\n color: var(--ac-color-text-muted, #c1c4cb);\n font-family: \"IBM Plex Sans\", sans-serif;\n font-size: 21px;\n line-height: 30px;\n cursor: pointer;\n white-space: nowrap;\n animation: PillList-module_fadeIn_Aezob 400ms cubic-bezier(0.4, 0, 0.2, 1) forwards;\n}\n\n.PillList-module_pill_osSyz:hover {\n filter: brightness(1.2);\n}\n\n.PillList-module_active_Oll-- {\n outline: 1px solid #5a5b8a;\n}\n\n@keyframes PillList-module_fadeIn_Aezob {\n from {\n opacity: 0;\n }\n}\n`;\n document.head.appendChild(s);\n}\nexport default {\"list\":\"PillList-module_list_qvLqO\",\"pill\":\"PillList-module_pill_osSyz\",\"fadeIn\":\"PillList-module_fadeIn_Aezob\",\"active\":\"PillList-module_active_Oll--\"};","import type { Suggestion } from \"../types\";\nimport styles from \"./PillList.module.css\";\n\ninterface PillListProps {\n pills: Suggestion[];\n activePillIndex: number;\n onSelectPill: (index: number) => void;\n}\n\nfunction getPillOpacity(index: number): number {\n if (index === 0) return 0.4;\n if (index === 1) return 0.3;\n return 0.15;\n}\n\nexport function PillList({ pills, activePillIndex, onSelectPill }: PillListProps) {\n return (\n <span className={styles.list}>\n {pills.map((pill, i) => (\n <button\n key={`${pill.type}-${pill.text}`}\n type=\"button\"\n className={`${styles.pill} ${i === activePillIndex ? styles.active : \"\"}`}\n style={{ opacity: getPillOpacity(i) }}\n onClick={() => onSelectPill(i)}\n >\n {pill.text}\n </button>\n ))}\n </span>\n );\n}\n","import { type ChangeEvent, useCallback, useMemo, useRef, useState } from \"react\";\nimport type {\n CompletedParamState,\n Suggestion,\n SuggestionOption,\n UseAIAutocompleteOptions,\n UseAIAutocompleteReturn,\n} from \"../types\";\nimport { filterOptions, findExactMatch } from \"../utils/filtering\";\nimport { deriveSegments, reconcileParams } from \"../utils/segments\";\nimport { useAutocompleteFetch, useDebouncedFetch } from \"./useAutocompleteFetch\";\nimport { useAutocompleteKeyboard } from \"./useAutocompleteKeyboard\";\nimport { useAutocompletePills } from \"./useAutocompletePills\";\n\nlet idCounter = 0;\nfunction useStableId(): string {\n const id = useRef<string | null>(null);\n if (id.current === null) {\n id.current = `:ac-${++idCounter}:`;\n }\n return id.current;\n}\n\nexport function useAIAutocomplete({\n onSubmit,\n onError,\n optionOverrides,\n maskCompletedText,\n placeholder: customPlaceholder,\n apiConfig,\n columns = 2,\n eagerSuggestions = true,\n value: controlledValue,\n completedParams: controlledParams,\n onChange: onChangeProp,\n onParamsChange,\n}: UseAIAutocompleteOptions): UseAIAutocompleteReturn {\n // === Controlled / uncontrolled state ===\n const isTextControlled = controlledValue !== undefined;\n const isParamsControlled = controlledParams !== undefined;\n\n const [internalText, setInternalText] = useState(\"\");\n const [internalCompletedParams, setInternalCompletedParams] = useState<CompletedParamState[]>([]);\n const [suggestions, setSuggestions] = useState<Suggestion[]>([]);\n const [activeDropdownIndex, setActiveDropdownIndex] = useState(-1);\n\n const text = isTextControlled ? controlledValue : internalText;\n const completedParams = isParamsControlled ? controlledParams : internalCompletedParams;\n\n // === Refs — must be before setText/setCompletedParams which read them ===\n const onSubmitRef = useRef(onSubmit);\n onSubmitRef.current = onSubmit;\n const onChangeRef = useRef(onChangeProp);\n onChangeRef.current = onChangeProp;\n const onParamsChangeRef = useRef(onParamsChange);\n onParamsChangeRef.current = onParamsChange;\n const controlledValueRef = useRef(controlledValue);\n controlledValueRef.current = controlledValue;\n const controlledParamsRef = useRef(controlledParams);\n controlledParamsRef.current = controlledParams;\n\n // Stable setText that reads controlled value + callback via refs (no stale closures)\n const setText = useCallback(\n (value: string | ((prev: string) => string)) => {\n if (typeof value === \"function\") {\n if (isTextControlled) {\n const newVal = value(controlledValueRef.current ?? \"\");\n onChangeRef.current?.(newVal);\n } else {\n setInternalText((prev) => {\n const newVal = value(prev);\n onChangeRef.current?.(newVal);\n return newVal;\n });\n }\n } else {\n if (!isTextControlled) setInternalText(value);\n onChangeRef.current?.(value);\n }\n },\n [isTextControlled],\n );\n\n // Stable setCompletedParams — same ref pattern\n const setCompletedParams = useCallback(\n (value: CompletedParamState[] | ((prev: CompletedParamState[]) => CompletedParamState[])) => {\n if (typeof value === \"function\") {\n if (isParamsControlled) {\n const newVal = value(controlledParamsRef.current ?? []);\n onParamsChangeRef.current?.(newVal);\n } else {\n setInternalCompletedParams((prev) => {\n const newVal = value(prev);\n onParamsChangeRef.current?.(newVal);\n return newVal;\n });\n }\n } else {\n if (!isParamsControlled) setInternalCompletedParams(value);\n onParamsChangeRef.current?.(value);\n }\n },\n [isParamsControlled],\n );\n const onErrorRef = useRef(onError);\n onErrorRef.current = onError;\n const optionOverridesRef = useRef(optionOverrides);\n optionOverridesRef.current = optionOverrides;\n const maskCompletedTextRef = useRef(maskCompletedText);\n maskCompletedTextRef.current = maskCompletedText;\n const apiConfigRef = useRef(apiConfig);\n apiConfigRef.current = apiConfig;\n const textRef = useRef(text);\n textRef.current = text;\n const suggestionsRef = useRef(suggestions);\n suggestionsRef.current = suggestions;\n const filterBaseRef = useRef(0);\n const pillTappedRef = useRef(false);\n const skipNextFetchRef = useRef(false);\n const listboxId = useStableId();\n\n // === Fetch ===\n const { doFetch, isLoading, error, isReady, lastRawQueryRef } = useAutocompleteFetch({\n textRef,\n suggestionsRef,\n filterBaseRef,\n maskCompletedTextRef,\n apiConfigRef,\n optionOverridesRef,\n onErrorRef,\n setCompletedParams,\n setSuggestions,\n setActiveDropdownIndex,\n });\n\n useDebouncedFetch({\n text,\n completedParams,\n doFetch,\n filterBaseRef,\n skipNextFetchRef,\n suggestionsRef,\n lastRawQueryRef,\n });\n\n // === Derived ===\n const segments = useMemo(() => deriveSegments(text, completedParams), [text, completedParams]);\n\n filterBaseRef.current = Math.min(filterBaseRef.current, text.length);\n const filterQuery = text.slice(filterBaseRef.current);\n\n const placeholderText = useMemo(() => {\n const serverPlaceholder = suggestions\n .filter((s) => s.type === \"placeholder\")\n .map((s) => s.text)\n .join(\" \");\n return serverPlaceholder || customPlaceholder || \"\";\n }, [suggestions, customPlaceholder]);\n const actionableSuggestions = useMemo(\n () => suggestions.filter((s) => s.type !== \"placeholder\"),\n [suggestions],\n );\n const activeSuggestion: Suggestion | undefined = actionableSuggestions[0];\n const overrideFn = activeSuggestion ? optionOverrides?.[activeSuggestion.type] : undefined;\n const baseOptions = activeSuggestion\n ? overrideFn\n ? overrideFn(filterQuery.trim())\n : (activeSuggestion.options ?? [])\n : [];\n const filteredOptions = useMemo(\n () => filterOptions(baseOptions, filterQuery),\n [baseOptions, filterQuery],\n );\n const hasPlaceholder = placeholderText.length > 0;\n const isDropdownOpen =\n !isLoading &&\n filteredOptions.length > 0 &&\n (!!text || pillTappedRef.current || !hasPlaceholder);\n\n // === Option selection ===\n const selectOption = useCallback(\n (option: SuggestionOption) => {\n if (!activeSuggestion) return;\n\n const completed: CompletedParamState = {\n id: crypto.randomUUID(),\n placeholder: \"\",\n type: activeSuggestion.type,\n text: option.text,\n kind: option.kind,\n suggestionType: activeSuggestion.type,\n suggestionPlaceholder: activeSuggestion.text,\n options: activeSuggestion.options ?? [],\n metadata: option.metadata,\n };\n\n const base = filterBaseRef.current;\n let prefix = textRef.current.slice(0, base);\n if (prefix.length > 0 && !prefix.endsWith(\" \")) {\n const lastWord = prefix.split(/\\s+/).pop() ?? \"\";\n if (lastWord && option.text.toLowerCase().startsWith(lastWord.toLowerCase())) {\n prefix = prefix.slice(0, prefix.length - lastWord.length);\n }\n }\n\n const needsSpace = prefix.length > 0 && prefix[prefix.length - 1] !== \" \";\n const newText = prefix + (needsSpace ? \" \" : \"\") + option.text + \" \";\n setText(newText);\n filterBaseRef.current = newText.length;\n setCompletedParams((prev) => [...prev, completed]);\n pillTappedRef.current = false;\n setActiveDropdownIndex(-1);\n const remainingActionable = actionableSuggestions.length - 1;\n if (eagerSuggestions && remainingActionable > 0) {\n // Keep cached suggestions visible and skip the fetch\n setSuggestions((prev) => prev.filter((s) => s !== activeSuggestion));\n skipNextFetchRef.current = true;\n } else {\n // Clear all suggestions and let the debounced fetch bring fresh ones\n setSuggestions((prev) => prev.filter((s) => s.type === \"placeholder\"));\n }\n },\n [activeSuggestion, actionableSuggestions, eagerSuggestions, setText, setCompletedParams],\n );\n\n // === Text change handler ===\n const handleChange = useCallback(\n (e: ChangeEvent<HTMLTextAreaElement>) => {\n const raw = e.target.value;\n const shouldCapitalize =\n raw.length > 0 &&\n !(e.nativeEvent as InputEvent)?.isComposing &&\n raw[0] !== raw[0].toUpperCase();\n const newValue = shouldCapitalize ? raw[0].toUpperCase() + raw.slice(1) : raw;\n setText(newValue);\n pillTappedRef.current = false;\n setActiveDropdownIndex(-1);\n\n const { valid, invalid } = reconcileParams(newValue, completedParams);\n if (invalid.length > 0) {\n setCompletedParams(() => valid);\n for (const param of invalid) {\n setSuggestions((prev) => [\n {\n type: param.suggestionType,\n text: param.suggestionPlaceholder,\n required: true,\n options: param.options,\n },\n ...prev,\n ]);\n }\n }\n\n if (activeSuggestion && invalid.length === 0) {\n const newFilterQuery = newValue.slice(filterBaseRef.current);\n const match = findExactMatch(activeSuggestion.options, newFilterQuery);\n if (match) {\n setCompletedParams((prev) => [\n ...prev,\n {\n id: crypto.randomUUID(),\n placeholder: \"\",\n type: activeSuggestion.type,\n text: match.text,\n kind: match.kind,\n suggestionType: activeSuggestion.type,\n suggestionPlaceholder: activeSuggestion.text,\n options: activeSuggestion.options ?? [],\n metadata: match.metadata,\n },\n ]);\n setSuggestions((prev) => prev.filter((s) => s !== activeSuggestion));\n }\n }\n },\n [completedParams, activeSuggestion, setText, setCompletedParams],\n );\n\n // === Keyboard ===\n const { handleKeyDown } = useAutocompleteKeyboard({\n activeDropdownIndex,\n setActiveDropdownIndex,\n filteredOptions,\n selectOption,\n onSubmitRef,\n text,\n completedParams,\n isDropdownOpen,\n hasPlaceholder,\n placeholderText,\n suggestions,\n filterBaseRef,\n columns,\n setText,\n setCompletedParams,\n setSuggestions,\n });\n\n // === Pills ===\n const pills = useAutocompletePills({\n completedParams,\n suggestions,\n setCompletedParams,\n setSuggestions,\n setActiveDropdownIndex,\n filterBaseRef,\n pillTappedRef,\n });\n\n const reEditParam = useCallback(\n (param: CompletedParamState) => {\n pills.reEditParam(param).apply(setText);\n },\n [pills, setText],\n );\n\n // === Reset ===\n const reset = useCallback(() => {\n setText(\"\");\n setCompletedParams(() => []);\n setSuggestions([]);\n setActiveDropdownIndex(-1);\n filterBaseRef.current = 0;\n lastRawQueryRef.current = \"\";\n doFetch(\"\", []);\n }, [doFetch, setText, setCompletedParams, lastRawQueryRef]);\n\n const activeDescendantId =\n activeDropdownIndex >= 0 ? `${listboxId}-option-${activeDropdownIndex}` : undefined;\n\n return {\n completedParams,\n suggestionPills: actionableSuggestions,\n setActivePill: pills.setActivePill,\n removeLastParam: pills.removeLastParam,\n reEditParam,\n segments,\n suggestions,\n activeIndex: activeDropdownIndex,\n isReady,\n isLoading,\n error,\n inputProps: {\n value: text,\n placeholder: placeholderText || undefined,\n onChange: handleChange,\n onKeyDown: handleKeyDown,\n role: \"combobox\" as const,\n \"aria-expanded\": isDropdownOpen,\n \"aria-activedescendant\": activeDescendantId,\n \"aria-autocomplete\": \"list\" as const,\n \"aria-controls\": listboxId,\n },\n reset,\n dropdownProps: {\n suggestions: activeSuggestion ? [{ ...activeSuggestion, options: filteredOptions }] : [],\n activeIndex: activeDropdownIndex,\n onSelect: selectOption,\n onHighlight: setActiveDropdownIndex,\n isOpen: isDropdownOpen,\n id: listboxId,\n },\n };\n}\n","import type { SuggestionOption } from \"../types\";\n\n/**\n * Filters options using partial substring match on the text after the last completed param.\n */\nexport function filterOptions(\n options: SuggestionOption[] | undefined,\n query: string,\n): SuggestionOption[] {\n if (!options) return [];\n const trimmed = query.trimStart();\n if (!trimmed) return options;\n const lower = trimmed.toLowerCase();\n return options.filter((o) => !o.is_tappable || o.text.toLowerCase().includes(lower));\n}\n\n/**\n * Finds an exact match for the trimmed filter query against options.\n */\nexport function findExactMatch(\n options: SuggestionOption[] | undefined,\n query: string,\n): SuggestionOption | null {\n if (!options) return null;\n const trimmed = query.trim();\n if (!trimmed) return null;\n const lower = trimmed.toLowerCase();\n return options.find((o) => o.is_tappable && o.text.toLowerCase() === lower) ?? null;\n}\n","import type { CompletedParamState, Segment } from \"../types\";\n\n/**\n * Derives segments for overlay rendering by matching completed params in text.\n */\nexport function deriveSegments(text: string, completedParams: CompletedParamState[]): Segment[] {\n const result: Segment[] = [];\n let pos = 0;\n\n for (const param of completedParams) {\n const idx = text.indexOf(param.text, pos);\n if (idx === -1) continue;\n if (idx > pos) {\n result.push({ type: \"text\", value: text.slice(pos, idx) });\n }\n result.push({ type: \"completed\", value: param.text, param });\n pos = idx + param.text.length;\n }\n\n const remaining = text.slice(pos);\n if (remaining) {\n result.push({ type: \"text\", value: remaining });\n }\n\n return result;\n}\n\n/**\n * Checks which completed params still exist in the new text.\n */\nexport function reconcileParams(\n text: string,\n completedParams: CompletedParamState[],\n): { valid: CompletedParamState[]; invalid: CompletedParamState[] } {\n const valid: CompletedParamState[] = [];\n const invalid: CompletedParamState[] = [];\n let pos = 0;\n\n for (const param of completedParams) {\n const idx = text.indexOf(param.text, pos);\n if (idx === -1) {\n invalid.push(param);\n } else {\n valid.push(param);\n pos = idx + param.text.length;\n }\n }\n\n return { valid, invalid };\n}\n","import { type MutableRefObject, useCallback, useEffect, useRef, useState } from \"react\";\nimport type {\n APIConfig,\n CompletedParamState,\n OptionOverrides,\n Suggestion,\n SuggestionOption,\n} from \"../types\";\nimport { fetchSuggestions } from \"../utils/api\";\nimport { buildQuery } from \"../utils/buildQuery\";\nimport { filterOptions, findExactMatch } from \"../utils/filtering\";\nimport { applyOptionOverrides } from \"../utils/overrides\";\n\nconst DEBOUNCE_MS = 100;\nconst SLOW_DEBOUNCE_MS = 300;\nconst MIN_CHARS_DIFF = 2;\n\ninterface UseAutocompleteFetchOptions {\n textRef: MutableRefObject<string>;\n suggestionsRef: MutableRefObject<Suggestion[]>;\n filterBaseRef: MutableRefObject<number>;\n maskCompletedTextRef: MutableRefObject<boolean | undefined>;\n apiConfigRef: MutableRefObject<APIConfig | undefined>;\n optionOverridesRef: MutableRefObject<OptionOverrides | undefined>;\n onErrorRef: MutableRefObject<((error: Error) => void) | undefined>;\n setCompletedParams: (fn: (prev: CompletedParamState[]) => CompletedParamState[]) => void;\n setSuggestions: (fn: Suggestion[] | ((prev: Suggestion[]) => Suggestion[])) => void;\n setActiveDropdownIndex: (index: number) => void;\n}\n\ninterface UseAutocompleteFetchReturn {\n doFetch: (rawQuery: string, completed: CompletedParamState[]) => Promise<void>;\n isLoading: boolean;\n error: Error | null;\n isReady: boolean;\n lastRawQueryRef: MutableRefObject<string>;\n}\n\nexport function useAutocompleteFetch({\n textRef,\n suggestionsRef,\n filterBaseRef,\n maskCompletedTextRef,\n apiConfigRef,\n optionOverridesRef,\n onErrorRef,\n setCompletedParams,\n setSuggestions,\n setActiveDropdownIndex,\n}: UseAutocompleteFetchOptions): UseAutocompleteFetchReturn {\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [isReady, setIsReady] = useState(false);\n const fetchVersionRef = useRef(0);\n const abortRef = useRef<AbortController | null>(null);\n const lastRawQueryRef = useRef(\"\");\n\n const doFetch = useCallback(\n async (rawQuery: string, completed: CompletedParamState[]) => {\n abortRef.current?.abort();\n const controller = new AbortController();\n abortRef.current = controller;\n const version = ++fetchVersionRef.current;\n const textAtRequest = textRef.current.length;\n\n const hasSuggestions = suggestionsRef.current.some((s) => s.type !== \"placeholder\");\n if (!hasSuggestions) setIsLoading(true);\n setError(null);\n try {\n const res = await fetchSuggestions(rawQuery, completed, {\n maskCompletedText: maskCompletedTextRef.current,\n signal: controller.signal,\n apiConfig: apiConfigRef.current,\n });\n\n if (version !== fetchVersionRef.current) return;\n\n let newSuggestions = applyOptionOverrides(\n res.data.suggestions ?? [],\n optionOverridesRef.current,\n );\n setIsReady(res.data.is_ready ?? false);\n lastRawQueryRef.current = rawQuery;\n\n const input = res.data.input ?? [];\n const lastInput = input[input.length - 1];\n const currentText = textRef.current;\n if (lastInput?.state === \"in_progress\") {\n const inProgressIdx = currentText.toLowerCase().lastIndexOf(lastInput.text.toLowerCase());\n if (inProgressIdx !== -1) {\n filterBaseRef.current = inProgressIdx;\n } else {\n filterBaseRef.current = textAtRequest;\n }\n } else {\n filterBaseRef.current = textAtRequest;\n }\n\n // Check if the user already typed an exact match while waiting\n const actionable = newSuggestions.filter((s) => s.type !== \"placeholder\");\n const active = actionable[0];\n if (active) {\n const query = currentText.slice(filterBaseRef.current);\n const match = findExactMatch(active.options, query);\n if (match) {\n setCompletedParams((prev) => [\n ...prev,\n {\n id: crypto.randomUUID(),\n placeholder: \"\",\n type: active.type,\n text: match.text,\n kind: match.kind,\n suggestionType: active.type,\n suggestionPlaceholder: active.text,\n options: active.options ?? [],\n metadata: match.metadata,\n },\n ]);\n newSuggestions = newSuggestions.filter((s) => s !== active);\n }\n }\n\n setSuggestions(newSuggestions);\n setIsLoading(false);\n setActiveDropdownIndex(-1);\n } catch (err) {\n if (version === fetchVersionRef.current) {\n const caughtError = err instanceof Error ? err : new Error(String(err));\n setError(caughtError);\n setIsLoading(false);\n onErrorRef.current?.(caughtError);\n }\n }\n },\n [\n textRef,\n suggestionsRef,\n filterBaseRef,\n maskCompletedTextRef,\n apiConfigRef,\n optionOverridesRef,\n onErrorRef,\n setCompletedParams,\n setSuggestions,\n setActiveDropdownIndex,\n ],\n );\n\n // Mount fetch\n useEffect(() => {\n doFetch(\"\", []);\n return () => {\n abortRef.current?.abort();\n };\n }, [doFetch]);\n\n return { doFetch, isLoading, error, isReady, lastRawQueryRef };\n}\n\ninterface UseDebouncedFetchOptions {\n text: string;\n completedParams: CompletedParamState[];\n doFetch: (rawQuery: string, completed: CompletedParamState[]) => Promise<void>;\n filterBaseRef: MutableRefObject<number>;\n skipNextFetchRef: MutableRefObject<boolean>;\n suggestionsRef: MutableRefObject<Suggestion[]>;\n lastRawQueryRef: MutableRefObject<string>;\n}\n\nexport function useDebouncedFetch({\n text,\n completedParams,\n doFetch,\n filterBaseRef,\n skipNextFetchRef,\n suggestionsRef,\n lastRawQueryRef,\n}: UseDebouncedFetchOptions): void {\n const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const slowDebounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const hasFetchedRef = useRef(true);\n\n useEffect(() => {\n if (debounceRef.current) clearTimeout(debounceRef.current);\n if (slowDebounceRef.current) clearTimeout(slowDebounceRef.current);\n\n const attemptFetch = (minDiff: number): boolean => {\n if (skipNextFetchRef.current) {\n skipNextFetchRef.current = false;\n return false;\n }\n\n if (!text && completedParams.length === 0) {\n if (!hasFetchedRef.current) {\n hasFetchedRef.current = true;\n return false;\n }\n doFetch(\"\", []);\n return true;\n }\n\n const currentQuery = text.slice(filterBaseRef.current);\n const currentSuggestions = suggestionsRef.current;\n const actionable = currentSuggestions.filter((s: Suggestion) => s.type !== \"placeholder\");\n const active = actionable[0];\n const currentFiltered = active ? filterOptions(active.options, currentQuery) : [];\n const tappableFiltered = currentFiltered.filter((o: SuggestionOption) => o.is_tappable);\n const hasExactMatch = active ? findExactMatch(active.options, currentQuery) !== null : false;\n\n const isInFilterZone = currentQuery.trim().length > 0;\n if (tappableFiltered.length > 0 && !hasExactMatch && isInFilterZone) return false;\n\n const { rawQuery, completedParams: updatedParams } = buildQuery(text, completedParams);\n const isDeleting = rawQuery.length < lastRawQueryRef.current.length;\n const charDiff = Math.abs(rawQuery.length - lastRawQueryRef.current.length);\n if (isDeleting || charDiff >= minDiff) {\n doFetch(rawQuery, updatedParams);\n return true;\n }\n return false;\n };\n\n debounceRef.current = setTimeout(() => {\n if (attemptFetch(MIN_CHARS_DIFF)) {\n if (slowDebounceRef.current) clearTimeout(slowDebounceRef.current);\n }\n }, DEBOUNCE_MS);\n\n slowDebounceRef.current = setTimeout(() => attemptFetch(1), SLOW_DEBOUNCE_MS);\n\n return () => {\n if (debounceRef.current) clearTimeout(debounceRef.current);\n if (slowDebounceRef.current) clearTimeout(slowDebounceRef.current);\n };\n }, [\n text,\n completedParams,\n doFetch,\n filterBaseRef,\n skipNextFetchRef,\n suggestionsRef,\n lastRawQueryRef,\n ]);\n}\n","import type {\n APIConfig,\n AutocompleteRequest,\n AutocompleteResponse,\n CompletedParam,\n CompletedParamState,\n} from \"../types\";\n\n// Replaced at build time by tsup/vitest `define` config with the package.json version.\ndeclare const __SDK_VERSION__: string;\nconst SDK_VERSION = __SDK_VERSION__;\n\nlet hasWarnedMissingKey = false;\n\nfunction generateRequestId(): string {\n return crypto.randomUUID();\n}\n\nfunction toWireParam(param: CompletedParamState, includeText: boolean): CompletedParam {\n return {\n placeholder: param.placeholder,\n type: param.type,\n ...(includeText && { text: param.text }),\n kind: param.kind,\n };\n}\n\nexport async function fetchSuggestions(\n rawQuery: string,\n completedParams: CompletedParamState[],\n options?: {\n maskCompletedText?: boolean;\n signal?: AbortSignal;\n apiConfig?: APIConfig;\n },\n): Promise<AutocompleteResponse> {\n const apiConfig = options?.apiConfig;\n const apiKey = apiConfig?.apiKey ?? \"\";\n if (!apiKey && !hasWarnedMissingKey) {\n hasWarnedMissingKey = true;\n // biome-ignore lint/suspicious/noConsole: intentional dev warning\n console.warn(\n \"[AIAutocomplete] No apiKey in apiConfig. Requests will be sent without an Authorization header.\",\n );\n }\n const authScheme = apiConfig?.authScheme ?? \"Bearer\";\n const includeText = !options?.maskCompletedText;\n\n const rawCount = completedParams.find(\n (p) => p.type === \"contact\" && p.metadata?.contact_account_count,\n )?.metadata?.contact_account_count;\n const contactAccountCount = typeof rawCount === \"number\" ? rawCount : undefined;\n\n const body: AutocompleteRequest = {\n data: {\n raw_query: rawQuery,\n completed_params: completedParams.map((p) => toWireParam(p, includeText)),\n ...(contactAccountCount != null && { contact_account_count: contactAccountCount }),\n },\n meta: {\n request_id: generateRequestId(),\n request_at: new Date().toISOString(),\n language: typeof navigator !== \"undefined\" ? navigator.language : \"en-US\",\n client_version: SDK_VERSION,\n },\n };\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n ...(apiConfig?.appIdentifier && { \"X-App-Identifier\": apiConfig.appIdentifier }),\n ...apiConfig?.headers,\n };\n if (apiKey) {\n headers.Authorization = authScheme === \"Basic\" ? `Basic ${btoa(apiKey)}` : `Bearer ${apiKey}`;\n }\n\n const response = await fetch(apiConfig?.endpoint ?? \"/ac/suggest\", {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n signal: options?.signal,\n });\n\n if (!response.ok) {\n throw new Error(`API error: ${response.status} ${response.statusText}`);\n }\n\n return response.json() as Promise<AutocompleteResponse>;\n}\n","import type { CompletedParamState } from \"../types\";\n\ninterface BuildQueryResult {\n rawQuery: string;\n completedParams: CompletedParamState[];\n}\n\n/**\n * Takes the raw input text and completed params (without placeholders),\n * replaces each completed param's text in the string with a {{TYPE_N}} token,\n * and returns the transformed query + params with placeholders filled in.\n *\n * Replacements happen left-to-right, first occurrence only per param.\n * Counter is per-type (e.g. {{TASK_1}}, {{GOAL_1}}, {{GOAL_2}}).\n */\nexport function buildQuery(text: string, completedParams: CompletedParamState[]): BuildQueryResult {\n let result = text;\n const typeCounts: Record<string, number> = {};\n const updatedParams: CompletedParamState[] = [];\n\n for (const param of completedParams) {\n const count = (typeCounts[param.type] ?? 0) + 1;\n typeCounts[param.type] = count;\n\n const typeKey = param.type.toUpperCase().replace(/\\s+/g, \"_\");\n const placeholder = `{{${typeKey}_${count}}}`;\n\n // Replace first occurrence of the param text in the string\n const index = result.indexOf(param.text);\n if (index !== -1) {\n result = result.slice(0, index) + placeholder + result.slice(index + param.text.length);\n }\n\n updatedParams.push({ ...param, placeholder });\n }\n\n return { rawQuery: result, completedParams: updatedParams };\n}\n","import type { Suggestion, SuggestionOption } from \"../types\";\n\n/**\n * Applies option overrides by calling the override function with an empty query,\n * then prepending results to suggestions that match by type, deduplicating by text.\n */\nexport function applyOptionOverrides(\n suggestions: Suggestion[],\n overrides?: Record<string, (query: string) => SuggestionOption[]>,\n): Suggestion[] {\n if (!overrides) return suggestions;\n return suggestions.map((s) => {\n const fn = overrides[s.type];\n if (!fn) return s;\n const extra = fn(\"\");\n if (extra.length === 0) return s;\n const existingTexts = new Set(extra.map((o) => o.text));\n const deduped = (s.options ?? []).filter((o) => !existingTexts.has(o.text));\n return { ...s, options: [...extra, ...deduped] };\n });\n}\n","import { type KeyboardEvent, type MutableRefObject, useCallback } from \"react\";\nimport type {\n AutocompleteResult,\n CompletedParamState,\n Suggestion,\n SuggestionOption,\n} from \"../types\";\nimport { buildQuery } from \"../utils/buildQuery\";\n\ninterface UseAutocompleteKeyboardOptions {\n activeDropdownIndex: number;\n setActiveDropdownIndex: (index: number) => void;\n filteredOptions: SuggestionOption[];\n selectOption: (option: SuggestionOption) => void;\n onSubmitRef: MutableRefObject<((result: AutocompleteResult) => void) | undefined>;\n text: string;\n completedParams: CompletedParamState[];\n isDropdownOpen: boolean;\n hasPlaceholder: boolean;\n placeholderText: string;\n suggestions: Suggestion[];\n filterBaseRef: MutableRefObject<number>;\n columns: number;\n setText: (value: string) => void;\n setCompletedParams: (fn: (prev: CompletedParamState[]) => CompletedParamState[]) => void;\n setSuggestions: (fn: (prev: Suggestion[]) => Suggestion[]) => void;\n}\n\nexport function useAutocompleteKeyboard({\n activeDropdownIndex,\n setActiveDropdownIndex,\n filteredOptions,\n selectOption,\n onSubmitRef,\n text,\n completedParams,\n isDropdownOpen,\n hasPlaceholder,\n placeholderText,\n suggestions,\n filterBaseRef,\n columns,\n setText,\n setCompletedParams,\n setSuggestions,\n}: UseAutocompleteKeyboardOptions) {\n const getTappableIndices = useCallback(() => {\n const tappable = filteredOptions\n .map((o, i) => (o.is_tappable ? i : -1))\n .filter((i) => i !== -1);\n // Column-first ordering: all column-0 items, then column-1, etc.\n const buckets: number[][] = Array.from({ length: columns }, () => []);\n for (const i of tappable) buckets[i % columns].push(i);\n return buckets.flat();\n }, [filteredOptions, columns]);\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLTextAreaElement>) => {\n const tappableIndices = getTappableIndices();\n\n switch (e.key) {\n case \"ArrowDown\": {\n e.preventDefault();\n if (tappableIndices.length === 0) return;\n const currentPos = tappableIndices.indexOf(activeDropdownIndex);\n const nextPos = currentPos < tappableIndices.length - 1 ? currentPos + 1 : 0;\n setActiveDropdownIndex(tappableIndices[nextPos]);\n break;\n }\n case \"ArrowUp\": {\n e.preventDefault();\n if (tappableIndices.length === 0) return;\n const currentPos = tappableIndices.indexOf(activeDropdownIndex);\n const prevPos = currentPos > 0 ? currentPos - 1 : tappableIndices.length - 1;\n setActiveDropdownIndex(tappableIndices[prevPos]);\n break;\n }\n case \"ArrowRight\": {\n if (activeDropdownIndex < 0) break;\n const col = activeDropdownIndex % columns;\n if (col < columns - 1) {\n const rightNeighbor = activeDropdownIndex + 1;\n if (\n rightNeighbor < filteredOptions.length &&\n filteredOptions[rightNeighbor]?.is_tappable\n ) {\n e.preventDefault();\n setActiveDropdownIndex(rightNeighbor);\n }\n }\n break;\n }\n case \"ArrowLeft\": {\n if (activeDropdownIndex < 0) break;\n if (activeDropdownIndex % columns > 0) {\n const leftNeighbor = activeDropdownIndex - 1;\n if (leftNeighbor >= 0 && filteredOptions[leftNeighbor]?.is_tappable) {\n e.preventDefault();\n setActiveDropdownIndex(leftNeighbor);\n }\n }\n break;\n }\n case \"Enter\": {\n e.preventDefault();\n if (activeDropdownIndex >= 0 && filteredOptions[activeDropdownIndex]?.is_tappable) {\n selectOption(filteredOptions[activeDropdownIndex]);\n } else if (onSubmitRef.current) {\n const { rawQuery, completedParams: finalParams } = buildQuery(text, completedParams);\n const result: AutocompleteResult = {\n query: text.trim(),\n raw_query: rawQuery,\n completed_params: finalParams,\n };\n onSubmitRef.current(result);\n }\n break;\n }\n case \"Tab\": {\n if (activeDropdownIndex >= 0 && filteredOptions[activeDropdownIndex]?.is_tappable) {\n e.preventDefault();\n selectOption(filteredOptions[activeDropdownIndex]);\n } else if (isDropdownOpen) {\n const firstTappable = filteredOptions.find((o) => o.is_tappable);\n if (firstTappable) {\n e.preventDefault();\n selectOption(firstTappable);\n }\n } else if (!text && hasPlaceholder) {\n e.preventDefault();\n const placeholderSuggestion = suggestions.find((s) => s.type === \"placeholder\");\n if (placeholderSuggestion) {\n setText(placeholderText);\n filterBaseRef.current = placeholderText.length;\n setCompletedParams((prev) => [\n ...prev,\n {\n id: crypto.randomUUID(),\n placeholder: \"\",\n type: placeholderSuggestion.type,\n text: placeholderText,\n kind: null,\n suggestionType: placeholderSuggestion.type,\n suggestionPlaceholder: placeholderSuggestion.text,\n options: placeholderSuggestion.options ?? [],\n },\n ]);\n setSuggestions((prev) => prev.filter((s) => s !== placeholderSuggestion));\n } else {\n setText(placeholderText);\n filterBaseRef.current = placeholderText.length;\n }\n }\n break;\n }\n case \"Escape\":\n setActiveDropdownIndex(-1);\n break;\n }\n },\n [\n activeDropdownIndex,\n columns,\n completedParams,\n filteredOptions,\n filterBaseRef,\n getTappableIndices,\n hasPlaceholder,\n isDropdownOpen,\n onSubmitRef,\n placeholderText,\n selectOption,\n setActiveDropdownIndex,\n setCompletedParams,\n setSuggestions,\n setText,\n suggestions,\n text,\n ],\n );\n\n return { handleKeyDown, getTappableIndices };\n}\n","import { type MutableRefObject, useCallback } from \"react\";\nimport type { CompletedParamState, Suggestion } from \"../types\";\n\ninterface UseAutocompletePillsOptions {\n completedParams: CompletedParamState[];\n suggestions: Suggestion[];\n setCompletedParams: (fn: (prev: CompletedParamState[]) => CompletedParamState[]) => void;\n setSuggestions: (fn: Suggestion[] | ((prev: Suggestion[]) => Suggestion[])) => void;\n setActiveDropdownIndex: (index: number) => void;\n filterBaseRef: MutableRefObject<number>;\n pillTappedRef: MutableRefObject<boolean>;\n}\n\nexport function useAutocompletePills({\n completedParams,\n suggestions,\n setCompletedParams,\n setSuggestions,\n setActiveDropdownIndex,\n filterBaseRef,\n pillTappedRef,\n}: UseAutocompletePillsOptions) {\n const setActivePill = useCallback(\n (index: number) => {\n const actionable = suggestions.filter((s) => s.type !== \"placeholder\");\n if (index < 0 || index >= actionable.length) return;\n const moved = actionable[index];\n const rest = actionable.filter((_, i) => i !== index);\n const placeholders = suggestions.filter((s) => s.type === \"placeholder\");\n setSuggestions([...placeholders, moved, ...rest]);\n pillTappedRef.current = true;\n setActiveDropdownIndex(-1);\n },\n [suggestions, setSuggestions, setActiveDropdownIndex, pillTappedRef],\n );\n\n const removeLastParam = useCallback(() => {\n if (completedParams.length === 0) return;\n const lastParam = completedParams[completedParams.length - 1];\n const restoredSuggestion: Suggestion = {\n type: lastParam.suggestionType,\n text: lastParam.suggestionPlaceholder,\n required: true,\n options: lastParam.options,\n };\n setCompletedParams((prev) => prev.slice(0, -1));\n setSuggestions((prev: Suggestion[]) => [restoredSuggestion, ...prev]);\n setActiveDropdownIndex(-1);\n }, [completedParams, setCompletedParams, setSuggestions, setActiveDropdownIndex]);\n\n const reEditParam = useCallback(\n (param: CompletedParamState) => {\n const restoredSuggestion: Suggestion = {\n type: param.suggestionType,\n text: param.suggestionPlaceholder,\n required: true,\n options: param.options,\n };\n return {\n apply: (setText: (fn: (prev: string) => string) => void) => {\n setText((prev) => {\n let pos = 0;\n for (const p of completedParams) {\n const idx = prev.indexOf(p.text, pos);\n if (idx === -1) continue;\n if (p.id === param.id) {\n const before = prev.slice(0, idx);\n const after = prev.slice(idx + param.text.length);\n const cleaned = (before + after).replace(/ {2,}/g, \" \");\n filterBaseRef.current = Math.min(filterBaseRef.current, cleaned.length);\n return cleaned;\n }\n pos = idx + p.text.length;\n }\n return prev;\n });\n setCompletedParams((prev) => prev.filter((p) => p.id !== param.id));\n setSuggestions((prev: Suggestion[]) => [restoredSuggestion, ...prev]);\n setActiveDropdownIndex(-1);\n pillTappedRef.current = true;\n },\n };\n },\n [\n completedParams,\n setCompletedParams,\n setSuggestions,\n setActiveDropdownIndex,\n filterBaseRef,\n pillTappedRef,\n ],\n );\n\n return { setActivePill, removeLastParam, reEditParam };\n}\n"],"mappings":"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","names":["forwardRef","useCallback","useEffect","useImperativeHandle","useRef","s","AIAutocomplete_module_css_default","s","AIAutocompleteDropdown_module_css_default","s","SuggestionGrid_module_css_default","s","SuggestionItem_module_css_default","jsx","jsxs","SuggestionItem","option","isHighlighted","onSelect","onHighlight","id","className","SuggestionItem_module_css_default","e","jsx","SuggestionGrid","options","activeIndex","onSelect","onHighlight","listboxId","SuggestionGrid_module_css_default","option","i","SuggestionItem","jsx","AIAutocompleteDropdown","suggestions","activeIndex","onSelect","onHighlight","isOpen","id","className","options","hasOptions","AIAutocompleteDropdown_module_css_default","e","SuggestionGrid","s","PillList_module_css_default","jsx","getPillOpacity","index","PillList","pills","activePillIndex","onSelectPill","PillList_module_css_default","pill","i","useCallback","useMemo","useRef","useState","filterOptions","options","query","trimmed","lower","o","findExactMatch","deriveSegments","text","completedParams","result","pos","param","idx","remaining","reconcileParams","valid","invalid","useCallback","useEffect","useRef","useState","SDK_VERSION","hasWarnedMissingKey","generateRequestId","toWireParam","param","includeText","fetchSuggestions","rawQuery","completedParams","options","apiConfig","apiKey","authScheme","rawCount","p","contactAccountCount","body","headers","response","buildQuery","text","completedParams","result","typeCounts","updatedParams","param","count","placeholder","index","applyOptionOverrides","suggestions","overrides","s","fn","extra","existingTexts","o","deduped","DEBOUNCE_MS","SLOW_DEBOUNCE_MS","MIN_CHARS_DIFF","useAutocompleteFetch","textRef","suggestionsRef","filterBaseRef","maskCompletedTextRef","apiConfigRef","optionOverridesRef","onErrorRef","setCompletedParams","setSuggestions","setActiveDropdownIndex","isLoading","setIsLoading","useState","error","setError","isReady","setIsReady","fetchVersionRef","useRef","abortRef","lastRawQueryRef","doFetch","useCallback","rawQuery","completed","controller","version","textAtRequest","s","res","fetchSuggestions","newSuggestions","applyOptionOverrides","input","lastInput","currentText","inProgressIdx","active","query","match","findExactMatch","prev","err","caughtError","useEffect","useDebouncedFetch","text","completedParams","skipNextFetchRef","debounceRef","slowDebounceRef","hasFetchedRef","attemptFetch","minDiff","currentQuery","tappableFiltered","filterOptions","o","hasExactMatch","isInFilterZone","updatedParams","buildQuery","isDeleting","charDiff","useCallback","useAutocompleteKeyboard","activeDropdownIndex","setActiveDropdownIndex","filteredOptions","selectOption","onSubmitRef","text","completedParams","isDropdownOpen","hasPlaceholder","placeholderText","suggestions","filterBaseRef","columns","setText","setCompletedParams","setSuggestions","getTappableIndices","useCallback","tappable","o","i","buckets","e","tappableIndices","currentPos","nextPos","prevPos","rightNeighbor","leftNeighbor","rawQuery","finalParams","buildQuery","result","firstTappable","placeholderSuggestion","s","prev","useCallback","useAutocompletePills","completedParams","suggestions","setCompletedParams","setSuggestions","setActiveDropdownIndex","filterBaseRef","pillTappedRef","setActivePill","index","actionable","s","moved","rest","_","i","placeholders","removeLastParam","lastParam","restoredSuggestion","prev","reEditParam","param","setText","pos","p","idx","before","after","cleaned","idCounter","useStableId","id","useRef","useAIAutocomplete","onSubmit","onError","optionOverrides","maskCompletedText","customPlaceholder","apiConfig","columns","eagerSuggestions","controlledValue","controlledParams","onChangeProp","onParamsChange","isTextControlled","isParamsControlled","internalText","setInternalText","useState","internalCompletedParams","setInternalCompletedParams","suggestions","setSuggestions","activeDropdownIndex","setActiveDropdownIndex","text","completedParams","onSubmitRef","onChangeRef","onParamsChangeRef","controlledValueRef","controlledParamsRef","setText","useCallback","value","newVal","prev","setCompletedParams","onErrorRef","optionOverridesRef","maskCompletedTextRef","apiConfigRef","textRef","suggestionsRef","filterBaseRef","pillTappedRef","skipNextFetchRef","listboxId","doFetch","isLoading","error","isReady","lastRawQueryRef","useAutocompleteFetch","useDebouncedFetch","segments","useMemo","deriveSegments","filterQuery","placeholderText","s","actionableSuggestions","activeSuggestion","overrideFn","baseOptions","filteredOptions","filterOptions","hasPlaceholder","isDropdownOpen","selectOption","option","completed","base","prefix","lastWord","needsSpace","newText","remainingActionable","handleChange","e","raw","newValue","valid","invalid","reconcileParams","param","newFilterQuery","match","findExactMatch","handleKeyDown","useAutocompleteKeyboard","pills","useAutocompletePills","reEditParam","reset","activeDescendantId","jsx","jsxs","AIAutocomplete","forwardRef","onSubmit","onError","optionOverrides","maskCompletedText","placeholder","className","apiConfig","columns","eagerSuggestions","value","controlledParams","onChangeProp","onParamsChange","ref","textareaRef","useRef","handleSubmitRef","useEffect","completedParams","suggestionPills","setActivePill","segments","inputProps","dropdownProps","reset","useAIAutocomplete","result","useImperativeHandle","handleContainerClick","canSubmit","handleSubmit","useCallback","rawQuery","finalParams","buildQuery","onChange","inputPlaceholder","restProps","isEmpty","AIAutocomplete_module_css_default","AIAutocompleteDropdown","seg","i","PillList","e"]}
|
|
1
|
+
{"version":3,"sources":["../src/AIAutocomplete.tsx","css-module:/Users/saharshv/MagicX/ai-autocomplete-react/src/AIAutocomplete.module.css.js","css-module:/Users/saharshv/MagicX/ai-autocomplete-react/src/AIAutocompleteDropdown.module.css.js","css-module:/Users/saharshv/MagicX/ai-autocomplete-react/src/components/SuggestionGrid.module.css.js","css-module:/Users/saharshv/MagicX/ai-autocomplete-react/src/components/SuggestionItem.module.css.js","../src/components/SuggestionItem.tsx","../src/components/SuggestionGrid.tsx","../src/AIAutocompleteDropdown.tsx","css-module:/Users/saharshv/MagicX/ai-autocomplete-react/src/components/PillList.module.css.js","../src/components/PillList.tsx","../src/hooks/useAIAutocomplete.ts","../src/utils/filtering.ts","../src/utils/segments.ts","../src/hooks/useAutocompleteFetch.ts","../src/utils/api.ts","../src/utils/buildQuery.ts","../src/utils/overrides.ts","../src/hooks/useAutocompleteKeyboard.ts","../src/hooks/useAutocompletePills.ts"],"sourcesContent":["import { forwardRef, useCallback, useEffect, useImperativeHandle, useRef } from \"react\";\nimport styles from \"./AIAutocomplete.module.css\";\nimport { AIAutocompleteDropdown } from \"./AIAutocompleteDropdown\";\nimport { PillList } from \"./components/PillList\";\nimport { useAIAutocomplete } from \"./hooks/useAIAutocomplete\";\nimport type { AIAutocompleteHandle, AIAutocompleteProps, AutocompleteResult } from \"./types\";\nimport { buildQuery } from \"./utils/buildQuery\";\n\nexport const AIAutocomplete = forwardRef<AIAutocompleteHandle, AIAutocompleteProps>(\n function AIAutocomplete(\n {\n onSubmit,\n onError,\n optionOverrides,\n maskCompletedText,\n placeholder,\n className,\n apiConfig,\n columns,\n eagerSuggestions,\n value,\n completedParams: controlledParams,\n onChange: onChangeProp,\n onParamsChange,\n },\n ref,\n ) {\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n // Render-phase ref assignment — matches the pattern in useAIAutocomplete.ts\n const handleSubmitRef = useRef<(result: AutocompleteResult) => void>(() => {});\n\n useEffect(() => {\n textareaRef.current?.focus();\n }, []);\n\n const {\n completedParams,\n suggestionPills,\n setActivePill,\n segments,\n inputProps,\n dropdownProps,\n reset,\n } = useAIAutocomplete({\n onSubmit: (result) => handleSubmitRef.current(result),\n onError,\n optionOverrides,\n maskCompletedText,\n placeholder,\n apiConfig,\n columns,\n eagerSuggestions,\n value,\n completedParams: controlledParams,\n onChange: onChangeProp,\n onParamsChange,\n });\n\n useImperativeHandle(\n ref,\n () => ({\n focus: () => textareaRef.current?.focus(),\n reset,\n }),\n [reset],\n );\n\n const handleContainerClick = () => {\n textareaRef.current?.focus();\n };\n\n const canSubmit = !!inputProps.value || completedParams.length > 0;\n\n const handleSubmit = useCallback(() => {\n if (!canSubmit) return;\n const { rawQuery, completedParams: finalParams } = buildQuery(\n inputProps.value,\n completedParams,\n );\n onSubmit({\n query: inputProps.value.trim(),\n raw_query: rawQuery,\n completed_params: finalParams,\n });\n reset();\n }, [canSubmit, inputProps.value, completedParams, onSubmit, reset]);\n\n handleSubmitRef.current = handleSubmit;\n\n const { onChange, placeholder: inputPlaceholder, ...restProps } = inputProps;\n const isEmpty = !inputProps.value;\n\n return (\n <div className={`${styles.container} ${className ?? \"\"}`}>\n <AIAutocompleteDropdown {...dropdownProps} />\n {/* biome-ignore lint/a11y/useKeyWithClickEvents: container click delegates to textarea focus */}\n {/* biome-ignore lint/a11y/noStaticElementInteractions: wrapper delegates focus to textarea */}\n <div className={styles.inputWrapper} onClick={handleContainerClick}>\n <div className={styles.editorArea}>\n <div className={styles.sizerContent} aria-hidden=\"true\">\n {isEmpty && inputPlaceholder ? (\n <span className={styles.placeholderText}>{inputPlaceholder} </span>\n ) : (\n <span className={styles.sizerText}>\n {segments.map((seg, i) => (\n // biome-ignore lint/suspicious/noArrayIndexKey: segments are positional and don't reorder\n <span key={`${i}-${seg.type}`}>{seg.value}</span>\n ))}\n {segments.length === 0 && \"\\u00A0\"}\n </span>\n )}\n {\" \"}\n <PillList pills={suggestionPills} activePillIndex={0} onSelectPill={setActivePill} />\n </div>\n <textarea\n ref={textareaRef}\n className={styles.textarea}\n rows={1}\n onChange={onChange}\n {...restProps}\n />\n </div>\n <button\n type=\"button\"\n className={styles.submitButton}\n disabled={!canSubmit}\n onClick={(e) => {\n e.stopPropagation();\n handleSubmit();\n }}\n aria-label=\"Submit\"\n >\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 18 18\"\n fill=\"none\"\n role=\"img\"\n aria-label=\"Submit\"\n >\n <path\n d=\"M9 14V4M9 4L4 9M9 4L14 9\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n </button>\n </div>\n </div>\n );\n },\n);\n","if (typeof document !== \"undefined\" && !document.getElementById(\"ac-style-cc65f4cc\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-cc65f4cc\";\n s.textContent = `.AIAutocomplete-module_container_KKjFU {\n position: relative;\n font-family: \"IBM Plex Sans\", sans-serif;\n}\n\n.AIAutocomplete-module_inputWrapper_FLq1b {\n min-height: 60px;\n padding: 24px;\n border: 1px solid var(--ac-color-border-default, #9ea5b2);\n border-radius: 23px;\n background: transparent;\n overflow: hidden;\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.AIAutocomplete-module_editorArea_7rBWq {\n position: relative;\n flex: 1;\n min-width: 0;\n}\n\n.AIAutocomplete-module_sizerContent_DQgmV {\n position: relative;\n z-index: 1;\n pointer-events: none;\n min-height: 60px;\n white-space: pre-wrap;\n word-break: break-word;\n font-family: inherit;\n font-size: 21px;\n line-height: 38px;\n}\n\n.AIAutocomplete-module_sizerText_iZIMK {\n color: transparent;\n}\n\n.AIAutocomplete-module_placeholderText_K3ayy {\n color: var(--ac-color-text-muted, #c1c4cb);\n opacity: 0.7;\n}\n\n.AIAutocomplete-module_textarea_eyn6A {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n padding: 0;\n border: none;\n background: transparent;\n color: var(--ac-color-text-default, #fff);\n caret-color: var(--ac-color-text-default, #fff);\n font-family: inherit;\n font-size: 21px;\n line-height: 38px;\n white-space: pre-wrap;\n word-break: break-word;\n outline: none;\n resize: none;\n overflow: hidden;\n}\n\n.AIAutocomplete-module_textarea_eyn6A::placeholder {\n color: var(--ac-color-text-muted, #c1c4cb);\n}\n\n.AIAutocomplete-module_submitButton_sl1Mi {\n flex-shrink: 0;\n width: 36px;\n height: 36px;\n border-radius: 50%;\n border: none;\n background: var(--ac-color-text-default, #fff);\n color: var(--ac-color-bg-default, #000);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n transition: opacity 0.2s ease;\n}\n\n.AIAutocomplete-module_submitButton_sl1Mi:hover {\n opacity: 0.85;\n}\n`;\n document.head.appendChild(s);\n}\nexport default {\"container\":\"AIAutocomplete-module_container_KKjFU\",\"inputWrapper\":\"AIAutocomplete-module_inputWrapper_FLq1b\",\"editorArea\":\"AIAutocomplete-module_editorArea_7rBWq\",\"sizerContent\":\"AIAutocomplete-module_sizerContent_DQgmV\",\"sizerText\":\"AIAutocomplete-module_sizerText_iZIMK\",\"placeholderText\":\"AIAutocomplete-module_placeholderText_K3ayy\",\"textarea\":\"AIAutocomplete-module_textarea_eyn6A\",\"submitButton\":\"AIAutocomplete-module_submitButton_sl1Mi\"};","if (typeof document !== \"undefined\" && !document.getElementById(\"ac-style-2eef895d\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-2eef895d\";\n s.textContent = `.AIAutocompleteDropdown-module_dropdown_yz2KC {\n position: absolute;\n left: 0;\n right: 0;\n top: 100%;\n margin-top: 6px;\n background: var(--ac-color-background-default, #00002d);\n border-radius: 23px;\n overflow: hidden;\n z-index: 10;\n opacity: 0;\n pointer-events: none;\n transition: opacity 400ms cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.AIAutocompleteDropdown-module_visible_QCoXj {\n opacity: 1;\n pointer-events: auto;\n}\n`;\n document.head.appendChild(s);\n}\nexport default {\"dropdown\":\"AIAutocompleteDropdown-module_dropdown_yz2KC\",\"visible\":\"AIAutocompleteDropdown-module_visible_QCoXj\"};","if (typeof document !== \"undefined\" && !document.getElementById(\"ac-style-d91f2b06\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-d91f2b06\";\n s.textContent = `.SuggestionGrid-module_grid_jvaPb {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 12px 18px;\n padding: 18px 24px;\n max-height: 192px;\n overflow-y: auto;\n scrollbar-width: thin;\n scrollbar-color: rgba(255, 255, 255, 0.3) transparent;\n}\n\n.SuggestionGrid-module_grid_jvaPb::-webkit-scrollbar {\n width: 6px;\n}\n\n.SuggestionGrid-module_grid_jvaPb::-webkit-scrollbar-track {\n background: transparent;\n}\n\n.SuggestionGrid-module_grid_jvaPb::-webkit-scrollbar-thumb {\n background: rgba(255, 255, 255, 0.3);\n border-radius: 3px;\n}\n`;\n document.head.appendChild(s);\n}\nexport default {\"grid\":\"SuggestionGrid-module_grid_jvaPb\"};","if (typeof document !== \"undefined\" && !document.getElementById(\"ac-style-f6bdc634\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-f6bdc634\";\n s.textContent = `.SuggestionItem-module_item_d4vpD {\n display: flex;\n align-items: center;\n font-family: \"IBM Plex Sans\", sans-serif;\n font-size: 21px;\n line-height: 30px;\n color: var(--ac-color-text-muted, #c1c4cb);\n white-space: nowrap;\n opacity: 0.35;\n animation: SuggestionItem-module_fadeIn_I8u35 400ms cubic-bezier(0.4, 0, 0.2, 1) forwards;\n}\n\n@keyframes SuggestionItem-module_fadeIn_I8u35 {\n from {\n opacity: 0;\n }\n}\n\n.SuggestionItem-module_tappable_70KcX {\n cursor: pointer;\n}\n\n.SuggestionItem-module_tappable_70KcX:hover {\n color: var(--ac-color-text-default, #fff);\n}\n\n.SuggestionItem-module_nonTappable_xSZM- {\n cursor: default;\n opacity: 0.3;\n}\n\n.SuggestionItem-module_highlighted_Hb0SU {\n color: var(--ac-color-text-default, #fff);\n opacity: 0.5;\n}\n\n.SuggestionItem-module_tag_e3Fwe {\n font-size: 13px;\n margin-left: 6px;\n opacity: 0.5;\n}\n`;\n document.head.appendChild(s);\n}\nexport default {\"item\":\"SuggestionItem-module_item_d4vpD\",\"fadeIn\":\"SuggestionItem-module_fadeIn_I8u35\",\"tappable\":\"SuggestionItem-module_tappable_70KcX\",\"nonTappable\":\"SuggestionItem-module_nonTappable_xSZM-\",\"highlighted\":\"SuggestionItem-module_highlighted_Hb0SU\",\"tag\":\"SuggestionItem-module_tag_e3Fwe\"};","import type { SuggestionOption } from \"../types\";\nimport styles from \"./SuggestionItem.module.css\";\n\ninterface SuggestionItemProps {\n option: SuggestionOption;\n isHighlighted: boolean;\n onSelect: (option: SuggestionOption) => void;\n onHighlight: () => void;\n id: string;\n}\n\nexport function SuggestionItem({\n option,\n isHighlighted,\n onSelect,\n onHighlight,\n id,\n}: SuggestionItemProps) {\n const className = [\n styles.item,\n isHighlighted ? styles.highlighted : \"\",\n option.is_tappable ? styles.tappable : styles.nonTappable,\n ]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <div\n id={id}\n role=\"option\"\n aria-selected={isHighlighted}\n className={className}\n tabIndex={option.is_tappable ? 0 : -1}\n onClick={() => option.is_tappable && onSelect(option)}\n onKeyDown={(e) => {\n if (option.is_tappable && (e.key === \"Enter\" || e.key === \" \")) {\n e.preventDefault();\n onSelect(option);\n }\n }}\n onMouseEnter={onHighlight}\n >\n {option.icon ? `${option.icon} ${option.text}` : option.text}\n {option.tag && <span className={styles.tag}>{option.tag}</span>}\n </div>\n );\n}\n","import type { SuggestionOption } from \"../types\";\nimport styles from \"./SuggestionGrid.module.css\";\nimport { SuggestionItem } from \"./SuggestionItem\";\n\ninterface SuggestionGridProps {\n options: SuggestionOption[];\n activeIndex: number;\n onSelect: (option: SuggestionOption) => void;\n onHighlight: (index: number) => void;\n listboxId: string;\n}\n\nexport function SuggestionGrid({\n options,\n activeIndex,\n onSelect,\n onHighlight,\n listboxId,\n}: SuggestionGridProps) {\n return (\n <div className={styles.grid}>\n {options.map((option, i) => (\n <SuggestionItem\n key={option.text}\n option={option}\n isHighlighted={i === activeIndex}\n onSelect={onSelect}\n onHighlight={() => onHighlight(i)}\n id={`${listboxId}-option-${i}`}\n />\n ))}\n </div>\n );\n}\n","import styles from \"./AIAutocompleteDropdown.module.css\";\nimport { SuggestionGrid } from \"./components/SuggestionGrid\";\nimport type { AIAutocompleteDropdownProps } from \"./types\";\n\nexport function AIAutocompleteDropdown({\n suggestions,\n activeIndex,\n onSelect,\n onHighlight,\n isOpen,\n id,\n className,\n}: AIAutocompleteDropdownProps) {\n const activeSuggestion = suggestions[0];\n const options = activeSuggestion?.options ?? [];\n const hasOptions = isOpen && options.length > 0;\n\n return (\n <div\n id={id}\n role=\"listbox\"\n className={`${styles.dropdown} ${hasOptions ? styles.visible : \"\"} ${className ?? \"\"}`}\n onMouseDown={(e) => e.preventDefault()}\n >\n {options.length > 0 && (\n <SuggestionGrid\n options={options}\n activeIndex={activeIndex}\n onSelect={onSelect}\n onHighlight={onHighlight}\n listboxId={id}\n />\n )}\n </div>\n );\n}\n","if (typeof document !== \"undefined\" && !document.getElementById(\"ac-style-b745b4fb\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-b745b4fb\";\n s.textContent = `.PillList-module_list_qvLqO {\n position: relative;\n z-index: 1;\n pointer-events: auto;\n display: inline-flex;\n gap: 5px;\n align-items: center;\n vertical-align: middle;\n transform: translateY(-3px);\n}\n\n.PillList-module_pill_osSyz {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n height: 36px;\n padding: 7px 9px;\n border: none;\n border-radius: 6px;\n background: var(--ac-color-background-supportive, #313255);\n color: var(--ac-color-text-muted, #c1c4cb);\n font-family: \"IBM Plex Sans\", sans-serif;\n font-size: 21px;\n line-height: 30px;\n cursor: pointer;\n white-space: nowrap;\n animation: PillList-module_fadeIn_Aezob 400ms cubic-bezier(0.4, 0, 0.2, 1) forwards;\n}\n\n.PillList-module_pill_osSyz:hover {\n filter: brightness(1.2);\n}\n\n.PillList-module_active_Oll-- {\n outline: 1px solid #5a5b8a;\n}\n\n@keyframes PillList-module_fadeIn_Aezob {\n from {\n opacity: 0;\n }\n}\n`;\n document.head.appendChild(s);\n}\nexport default {\"list\":\"PillList-module_list_qvLqO\",\"pill\":\"PillList-module_pill_osSyz\",\"fadeIn\":\"PillList-module_fadeIn_Aezob\",\"active\":\"PillList-module_active_Oll--\"};","import type { Suggestion } from \"../types\";\nimport styles from \"./PillList.module.css\";\n\ninterface PillListProps {\n pills: Suggestion[];\n activePillIndex: number;\n onSelectPill: (index: number) => void;\n}\n\nfunction getPillOpacity(index: number): number {\n if (index === 0) return 0.4;\n if (index === 1) return 0.3;\n return 0.15;\n}\n\nexport function PillList({ pills, activePillIndex, onSelectPill }: PillListProps) {\n return (\n <span className={styles.list}>\n {pills.map((pill, i) => (\n <button\n key={`${pill.type}-${pill.text}`}\n type=\"button\"\n className={`${styles.pill} ${i === activePillIndex ? styles.active : \"\"}`}\n style={{ opacity: getPillOpacity(i) }}\n onClick={() => onSelectPill(i)}\n >\n {pill.text}\n </button>\n ))}\n </span>\n );\n}\n","import { type ChangeEvent, useCallback, useMemo, useRef, useState } from \"react\";\nimport type {\n CompletedParamState,\n Suggestion,\n SuggestionOption,\n UseAIAutocompleteOptions,\n UseAIAutocompleteReturn,\n} from \"../types\";\nimport { extractFilterQuery, filterOptions, findExactMatch } from \"../utils/filtering\";\nimport { deriveSegments, reconcileParams } from \"../utils/segments\";\nimport { useAutocompleteFetch, useDebouncedFetch } from \"./useAutocompleteFetch\";\nimport { useAutocompleteKeyboard } from \"./useAutocompleteKeyboard\";\nimport { useAutocompletePills } from \"./useAutocompletePills\";\n\nlet idCounter = 0;\nfunction useStableId(): string {\n const id = useRef<string | null>(null);\n if (id.current === null) {\n id.current = `:ac-${++idCounter}:`;\n }\n return id.current;\n}\n\nexport function useAIAutocomplete({\n onSubmit,\n onError,\n optionOverrides,\n maskCompletedText,\n placeholder: customPlaceholder,\n apiConfig,\n columns = 2,\n eagerSuggestions = true,\n value: controlledValue,\n completedParams: controlledParams,\n onChange: onChangeProp,\n onParamsChange,\n}: UseAIAutocompleteOptions): UseAIAutocompleteReturn {\n // === Controlled / uncontrolled state ===\n const isTextControlled = controlledValue !== undefined;\n const isParamsControlled = controlledParams !== undefined;\n\n const [internalText, setInternalText] = useState(\"\");\n const [internalCompletedParams, setInternalCompletedParams] = useState<CompletedParamState[]>([]);\n const [suggestions, setSuggestions] = useState<Suggestion[]>([]);\n const [activeDropdownIndex, setActiveDropdownIndex] = useState(-1);\n\n const text = isTextControlled ? controlledValue : internalText;\n const completedParams = isParamsControlled ? controlledParams : internalCompletedParams;\n\n // === Refs — must be before setText/setCompletedParams which read them ===\n const onSubmitRef = useRef(onSubmit);\n onSubmitRef.current = onSubmit;\n const onChangeRef = useRef(onChangeProp);\n onChangeRef.current = onChangeProp;\n const onParamsChangeRef = useRef(onParamsChange);\n onParamsChangeRef.current = onParamsChange;\n const controlledValueRef = useRef(controlledValue);\n controlledValueRef.current = controlledValue;\n const controlledParamsRef = useRef(controlledParams);\n controlledParamsRef.current = controlledParams;\n\n // Stable setText that reads controlled value + callback via refs (no stale closures)\n const setText = useCallback(\n (value: string | ((prev: string) => string)) => {\n if (typeof value === \"function\") {\n if (isTextControlled) {\n const newVal = value(controlledValueRef.current ?? \"\");\n onChangeRef.current?.(newVal);\n } else {\n setInternalText((prev) => {\n const newVal = value(prev);\n onChangeRef.current?.(newVal);\n return newVal;\n });\n }\n } else {\n if (!isTextControlled) setInternalText(value);\n onChangeRef.current?.(value);\n }\n },\n [isTextControlled],\n );\n\n // Stable setCompletedParams — same ref pattern\n const setCompletedParams = useCallback(\n (value: CompletedParamState[] | ((prev: CompletedParamState[]) => CompletedParamState[])) => {\n if (typeof value === \"function\") {\n if (isParamsControlled) {\n const newVal = value(controlledParamsRef.current ?? []);\n onParamsChangeRef.current?.(newVal);\n } else {\n setInternalCompletedParams((prev) => {\n const newVal = value(prev);\n onParamsChangeRef.current?.(newVal);\n return newVal;\n });\n }\n } else {\n if (!isParamsControlled) setInternalCompletedParams(value);\n onParamsChangeRef.current?.(value);\n }\n },\n [isParamsControlled],\n );\n const onErrorRef = useRef(onError);\n onErrorRef.current = onError;\n const optionOverridesRef = useRef(optionOverrides);\n optionOverridesRef.current = optionOverrides;\n const maskCompletedTextRef = useRef(maskCompletedText);\n maskCompletedTextRef.current = maskCompletedText;\n const apiConfigRef = useRef(apiConfig);\n apiConfigRef.current = apiConfig;\n const textRef = useRef(text);\n textRef.current = text;\n const suggestionsRef = useRef(suggestions);\n suggestionsRef.current = suggestions;\n const filterBaseRef = useRef(0);\n const filterInProgressRef = useRef(false);\n const pillTappedRef = useRef(false);\n const skipNextFetchRef = useRef(false);\n const listboxId = useStableId();\n\n // === Fetch ===\n const { doFetch, isLoading, error, isReady, lastRawQueryRef } = useAutocompleteFetch({\n textRef,\n suggestionsRef,\n filterBaseRef,\n filterInProgressRef,\n maskCompletedTextRef,\n apiConfigRef,\n optionOverridesRef,\n onErrorRef,\n setCompletedParams,\n setSuggestions,\n setActiveDropdownIndex,\n });\n\n useDebouncedFetch({\n text,\n completedParams,\n doFetch,\n filterBaseRef,\n filterInProgressRef,\n skipNextFetchRef,\n suggestionsRef,\n lastRawQueryRef,\n });\n\n // === Derived ===\n const segments = useMemo(() => deriveSegments(text, completedParams), [text, completedParams]);\n\n filterBaseRef.current = Math.min(filterBaseRef.current, text.length);\n const filterQuery = extractFilterQuery(text, filterBaseRef.current, filterInProgressRef.current);\n\n const placeholderText = useMemo(() => {\n const serverPlaceholder = suggestions\n .filter((s) => s.type === \"placeholder\")\n .map((s) => s.text)\n .join(\" \");\n return serverPlaceholder || customPlaceholder || \"\";\n }, [suggestions, customPlaceholder]);\n const actionableSuggestions = useMemo(\n () => suggestions.filter((s) => s.type !== \"placeholder\"),\n [suggestions],\n );\n const activeSuggestion: Suggestion | undefined = actionableSuggestions[0];\n const overrideFn = activeSuggestion ? optionOverrides?.[activeSuggestion.type] : undefined;\n const baseOptions = activeSuggestion\n ? overrideFn\n ? overrideFn(filterQuery.trim())\n : (activeSuggestion.options ?? [])\n : [];\n const filteredOptions = useMemo(\n () => filterOptions(baseOptions, filterQuery),\n [baseOptions, filterQuery],\n );\n const hasPlaceholder = placeholderText.length > 0;\n const isDropdownOpen =\n !isLoading &&\n filteredOptions.length > 0 &&\n (!!text || pillTappedRef.current || !hasPlaceholder);\n\n // === Option selection ===\n const selectOption = useCallback(\n (option: SuggestionOption) => {\n if (!activeSuggestion) return;\n\n const completed: CompletedParamState = {\n id: crypto.randomUUID(),\n placeholder: \"\",\n type: activeSuggestion.type,\n text: option.text,\n kind: option.kind,\n suggestionType: activeSuggestion.type,\n suggestionPlaceholder: activeSuggestion.text,\n options: activeSuggestion.options ?? [],\n metadata: option.metadata,\n };\n\n const base = filterBaseRef.current;\n let prefix = textRef.current.slice(0, base);\n if (prefix.length > 0 && !prefix.endsWith(\" \")) {\n const lastWord = prefix.split(/\\s+/).pop() ?? \"\";\n if (lastWord && option.text.toLowerCase().startsWith(lastWord.toLowerCase())) {\n prefix = prefix.slice(0, prefix.length - lastWord.length);\n }\n }\n\n const needsSpace = prefix.length > 0 && prefix[prefix.length - 1] !== \" \";\n const newText = prefix + (needsSpace ? \" \" : \"\") + option.text + \" \";\n setText(newText);\n filterBaseRef.current = newText.length;\n setCompletedParams((prev) => [...prev, completed]);\n pillTappedRef.current = false;\n setActiveDropdownIndex(-1);\n const remainingActionable = actionableSuggestions.length - 1;\n if (eagerSuggestions && remainingActionable > 0) {\n // Keep cached suggestions visible and skip the fetch\n setSuggestions((prev) => prev.filter((s) => s !== activeSuggestion));\n skipNextFetchRef.current = true;\n } else {\n // Clear all suggestions and let the debounced fetch bring fresh ones\n setSuggestions((prev) => prev.filter((s) => s.type === \"placeholder\"));\n }\n },\n [activeSuggestion, actionableSuggestions, eagerSuggestions, setText, setCompletedParams],\n );\n\n // === Text change handler ===\n const handleChange = useCallback(\n (e: ChangeEvent<HTMLTextAreaElement>) => {\n const raw = e.target.value;\n const shouldCapitalize =\n raw.length > 0 &&\n !(e.nativeEvent as InputEvent)?.isComposing &&\n raw[0] !== raw[0].toUpperCase();\n const newValue = shouldCapitalize ? raw[0].toUpperCase() + raw.slice(1) : raw;\n setText(newValue);\n pillTappedRef.current = false;\n setActiveDropdownIndex(-1);\n\n const { valid, invalid } = reconcileParams(newValue, completedParams);\n if (invalid.length > 0) {\n setCompletedParams(() => valid);\n for (const param of invalid) {\n setSuggestions((prev) => [\n {\n type: param.suggestionType,\n text: param.suggestionPlaceholder,\n required: true,\n options: param.options,\n },\n ...prev,\n ]);\n }\n }\n\n if (activeSuggestion && invalid.length === 0) {\n const newFilterQuery = extractFilterQuery(\n newValue,\n filterBaseRef.current,\n filterInProgressRef.current,\n );\n const match = findExactMatch(activeSuggestion.options, newFilterQuery);\n if (match) {\n setCompletedParams((prev) => [\n ...prev,\n {\n id: crypto.randomUUID(),\n placeholder: \"\",\n type: activeSuggestion.type,\n text: match.text,\n kind: match.kind,\n suggestionType: activeSuggestion.type,\n suggestionPlaceholder: activeSuggestion.text,\n options: activeSuggestion.options ?? [],\n metadata: match.metadata,\n },\n ]);\n setSuggestions((prev) => prev.filter((s) => s !== activeSuggestion));\n }\n }\n },\n [completedParams, activeSuggestion, setText, setCompletedParams],\n );\n\n // === Pills ===\n const pills = useAutocompletePills({\n completedParams,\n suggestions,\n setCompletedParams,\n setSuggestions,\n setActiveDropdownIndex,\n filterBaseRef,\n pillTappedRef,\n });\n\n const reEditParam = useCallback(\n (param: CompletedParamState) => {\n pills.reEditParam(param).apply(setText);\n },\n [pills, setText],\n );\n\n // === Keyboard ===\n const { handleKeyDown } = useAutocompleteKeyboard({\n activeDropdownIndex,\n setActiveDropdownIndex,\n filteredOptions,\n selectOption,\n onSubmitRef,\n text,\n completedParams,\n isDropdownOpen,\n hasPlaceholder,\n placeholderText,\n suggestions,\n actionableSuggestions,\n setActivePill: pills.setActivePill,\n filterBaseRef,\n columns,\n setText,\n setCompletedParams,\n setSuggestions,\n });\n\n // === Reset ===\n const reset = useCallback(() => {\n setText(\"\");\n setCompletedParams(() => []);\n setSuggestions([]);\n setActiveDropdownIndex(-1);\n filterBaseRef.current = 0;\n filterInProgressRef.current = false;\n lastRawQueryRef.current = \"\";\n doFetch(\"\", []);\n }, [doFetch, setText, setCompletedParams, lastRawQueryRef]);\n\n const activeDescendantId =\n activeDropdownIndex >= 0 ? `${listboxId}-option-${activeDropdownIndex}` : undefined;\n\n return {\n completedParams,\n suggestionPills: actionableSuggestions,\n setActivePill: pills.setActivePill,\n removeLastParam: pills.removeLastParam,\n reEditParam,\n segments,\n suggestions,\n activeIndex: activeDropdownIndex,\n isReady,\n isLoading,\n error,\n inputProps: {\n value: text,\n placeholder: placeholderText || undefined,\n onChange: handleChange,\n onKeyDown: handleKeyDown,\n role: \"combobox\" as const,\n \"aria-expanded\": isDropdownOpen,\n \"aria-activedescendant\": activeDescendantId,\n \"aria-autocomplete\": \"list\" as const,\n \"aria-controls\": listboxId,\n },\n reset,\n dropdownProps: {\n suggestions: activeSuggestion ? [{ ...activeSuggestion, options: filteredOptions }] : [],\n activeIndex: activeDropdownIndex,\n onSelect: selectOption,\n onHighlight: setActiveDropdownIndex,\n isOpen: isDropdownOpen,\n id: listboxId,\n },\n };\n}\n","import type { SuggestionOption } from \"../types\";\n\n/**\n * Extracts the effective filter query from the region after filterBase.\n * If the server marked the region as in_progress, the full region is used.\n * Otherwise, filtering only starts after the first space (to avoid filtering\n * mid-word when the user continues typing a word that was already in the input).\n */\nexport function extractFilterQuery(\n text: string,\n filterBase: number,\n isInProgress: boolean,\n): string {\n const rawRegion = text.slice(filterBase);\n if (isInProgress || filterBase === 0 || text[filterBase - 1] === \" \") {\n return rawRegion;\n }\n const spaceIdx = rawRegion.indexOf(\" \");\n return spaceIdx === -1 ? \"\" : rawRegion.slice(spaceIdx + 1);\n}\n\n/**\n * Filters options using partial substring match on the text after the last completed param.\n */\nexport function filterOptions(\n options: SuggestionOption[] | undefined,\n query: string,\n): SuggestionOption[] {\n if (!options) return [];\n const trimmed = query.trimStart();\n if (!trimmed) return options;\n const lower = trimmed.toLowerCase();\n return options.filter((o) => !o.is_tappable || o.text.toLowerCase().includes(lower));\n}\n\n/**\n * Finds an exact match for the trimmed filter query against options.\n */\nexport function findExactMatch(\n options: SuggestionOption[] | undefined,\n query: string,\n): SuggestionOption | null {\n if (!options) return null;\n const trimmed = query.trim();\n if (!trimmed) return null;\n const lower = trimmed.toLowerCase();\n return options.find((o) => o.is_tappable && o.text.toLowerCase() === lower) ?? null;\n}\n","import type { CompletedParamState, Segment } from \"../types\";\n\n/**\n * Derives segments for overlay rendering by matching completed params in text.\n */\nexport function deriveSegments(text: string, completedParams: CompletedParamState[]): Segment[] {\n const result: Segment[] = [];\n let pos = 0;\n\n for (const param of completedParams) {\n const idx = text.indexOf(param.text, pos);\n if (idx === -1) continue;\n if (idx > pos) {\n result.push({ type: \"text\", value: text.slice(pos, idx) });\n }\n result.push({ type: \"completed\", value: param.text, param });\n pos = idx + param.text.length;\n }\n\n const remaining = text.slice(pos);\n if (remaining) {\n result.push({ type: \"text\", value: remaining });\n }\n\n return result;\n}\n\n/**\n * Checks which completed params still exist in the new text.\n */\nexport function reconcileParams(\n text: string,\n completedParams: CompletedParamState[],\n): { valid: CompletedParamState[]; invalid: CompletedParamState[] } {\n const valid: CompletedParamState[] = [];\n const invalid: CompletedParamState[] = [];\n let pos = 0;\n\n for (const param of completedParams) {\n const idx = text.indexOf(param.text, pos);\n if (idx === -1) {\n invalid.push(param);\n } else {\n valid.push(param);\n pos = idx + param.text.length;\n }\n }\n\n return { valid, invalid };\n}\n","import { type MutableRefObject, useCallback, useEffect, useRef, useState } from \"react\";\nimport type {\n APIConfig,\n CompletedParamState,\n OptionOverrides,\n Suggestion,\n SuggestionOption,\n} from \"../types\";\nimport { fetchSuggestions } from \"../utils/api\";\nimport { buildQuery } from \"../utils/buildQuery\";\nimport { extractFilterQuery, filterOptions, findExactMatch } from \"../utils/filtering\";\nimport { applyOptionOverrides } from \"../utils/overrides\";\n\nconst DEBOUNCE_MS = 100;\nconst SLOW_DEBOUNCE_MS = 300;\nconst MIN_CHARS_DIFF = 2;\n\ninterface UseAutocompleteFetchOptions {\n textRef: MutableRefObject<string>;\n suggestionsRef: MutableRefObject<Suggestion[]>;\n filterBaseRef: MutableRefObject<number>;\n filterInProgressRef: MutableRefObject<boolean>;\n maskCompletedTextRef: MutableRefObject<boolean | undefined>;\n apiConfigRef: MutableRefObject<APIConfig | undefined>;\n optionOverridesRef: MutableRefObject<OptionOverrides | undefined>;\n onErrorRef: MutableRefObject<((error: Error) => void) | undefined>;\n setCompletedParams: (fn: (prev: CompletedParamState[]) => CompletedParamState[]) => void;\n setSuggestions: (fn: Suggestion[] | ((prev: Suggestion[]) => Suggestion[])) => void;\n setActiveDropdownIndex: (index: number) => void;\n}\n\ninterface UseAutocompleteFetchReturn {\n doFetch: (rawQuery: string, completed: CompletedParamState[]) => Promise<void>;\n isLoading: boolean;\n error: Error | null;\n isReady: boolean;\n lastRawQueryRef: MutableRefObject<string>;\n}\n\nexport function useAutocompleteFetch({\n textRef,\n suggestionsRef,\n filterBaseRef,\n filterInProgressRef,\n maskCompletedTextRef,\n apiConfigRef,\n optionOverridesRef,\n onErrorRef,\n setCompletedParams,\n setSuggestions,\n setActiveDropdownIndex,\n}: UseAutocompleteFetchOptions): UseAutocompleteFetchReturn {\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [isReady, setIsReady] = useState(false);\n const fetchVersionRef = useRef(0);\n const abortRef = useRef<AbortController | null>(null);\n const lastRawQueryRef = useRef(\"\");\n\n const doFetch = useCallback(\n async (rawQuery: string, completed: CompletedParamState[]) => {\n abortRef.current?.abort();\n const controller = new AbortController();\n abortRef.current = controller;\n const version = ++fetchVersionRef.current;\n const textAtRequest = textRef.current.length;\n\n const hasSuggestions = suggestionsRef.current.some((s) => s.type !== \"placeholder\");\n if (!hasSuggestions) setIsLoading(true);\n setError(null);\n try {\n const res = await fetchSuggestions(rawQuery, completed, {\n maskCompletedText: maskCompletedTextRef.current,\n signal: controller.signal,\n apiConfig: apiConfigRef.current,\n });\n\n if (version !== fetchVersionRef.current) return;\n\n let newSuggestions = applyOptionOverrides(\n res.data.suggestions ?? [],\n optionOverridesRef.current,\n );\n setIsReady(res.data.is_ready ?? false);\n lastRawQueryRef.current = rawQuery;\n\n const input = res.data.input ?? [];\n const lastInput = input[input.length - 1];\n const currentText = textRef.current;\n if (lastInput?.state === \"in_progress\") {\n filterInProgressRef.current = true;\n const inProgressIdx = currentText.toLowerCase().lastIndexOf(lastInput.text.toLowerCase());\n if (inProgressIdx !== -1) {\n filterBaseRef.current = inProgressIdx;\n } else {\n filterBaseRef.current = textAtRequest;\n }\n } else {\n filterInProgressRef.current = false;\n filterBaseRef.current = textAtRequest;\n }\n\n // Check if the user already typed an exact match while waiting\n const actionable = newSuggestions.filter((s) => s.type !== \"placeholder\");\n const active = actionable[0];\n if (active) {\n const query = extractFilterQuery(\n currentText,\n filterBaseRef.current,\n filterInProgressRef.current,\n );\n const match = findExactMatch(active.options, query);\n if (match) {\n setCompletedParams((prev) => [\n ...prev,\n {\n id: crypto.randomUUID(),\n placeholder: \"\",\n type: active.type,\n text: match.text,\n kind: match.kind,\n suggestionType: active.type,\n suggestionPlaceholder: active.text,\n options: active.options ?? [],\n metadata: match.metadata,\n },\n ]);\n newSuggestions = newSuggestions.filter((s) => s !== active);\n }\n }\n\n setSuggestions(newSuggestions);\n setIsLoading(false);\n setActiveDropdownIndex(-1);\n } catch (err) {\n if (version === fetchVersionRef.current) {\n const caughtError = err instanceof Error ? err : new Error(String(err));\n setError(caughtError);\n setIsLoading(false);\n onErrorRef.current?.(caughtError);\n }\n }\n },\n [\n textRef,\n suggestionsRef,\n filterBaseRef,\n filterInProgressRef,\n maskCompletedTextRef,\n apiConfigRef,\n optionOverridesRef,\n onErrorRef,\n setCompletedParams,\n setSuggestions,\n setActiveDropdownIndex,\n ],\n );\n\n // Mount fetch\n useEffect(() => {\n doFetch(\"\", []);\n return () => {\n abortRef.current?.abort();\n };\n }, [doFetch]);\n\n return { doFetch, isLoading, error, isReady, lastRawQueryRef };\n}\n\ninterface UseDebouncedFetchOptions {\n text: string;\n completedParams: CompletedParamState[];\n doFetch: (rawQuery: string, completed: CompletedParamState[]) => Promise<void>;\n filterBaseRef: MutableRefObject<number>;\n filterInProgressRef: MutableRefObject<boolean>;\n skipNextFetchRef: MutableRefObject<boolean>;\n suggestionsRef: MutableRefObject<Suggestion[]>;\n lastRawQueryRef: MutableRefObject<string>;\n}\n\nexport function useDebouncedFetch({\n text,\n completedParams,\n doFetch,\n filterBaseRef,\n filterInProgressRef,\n skipNextFetchRef,\n suggestionsRef,\n lastRawQueryRef,\n}: UseDebouncedFetchOptions): void {\n const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const slowDebounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const hasFetchedRef = useRef(true);\n\n useEffect(() => {\n if (debounceRef.current) clearTimeout(debounceRef.current);\n if (slowDebounceRef.current) clearTimeout(slowDebounceRef.current);\n\n const attemptFetch = (minDiff: number): boolean => {\n if (skipNextFetchRef.current) {\n skipNextFetchRef.current = false;\n return false;\n }\n\n if (!text && completedParams.length === 0) {\n if (!hasFetchedRef.current) {\n hasFetchedRef.current = true;\n return false;\n }\n doFetch(\"\", []);\n return true;\n }\n\n const currentQuery = extractFilterQuery(\n text,\n filterBaseRef.current,\n filterInProgressRef.current,\n );\n const currentSuggestions = suggestionsRef.current;\n const actionable = currentSuggestions.filter((s: Suggestion) => s.type !== \"placeholder\");\n const active = actionable[0];\n const currentFiltered = active ? filterOptions(active.options, currentQuery) : [];\n const tappableFiltered = currentFiltered.filter((o: SuggestionOption) => o.is_tappable);\n const hasExactMatch = active ? findExactMatch(active.options, currentQuery) !== null : false;\n\n const isInFilterZone = currentQuery.trim().length > 0;\n if (tappableFiltered.length > 0 && !hasExactMatch && isInFilterZone) return false;\n\n const { rawQuery, completedParams: updatedParams } = buildQuery(text, completedParams);\n const isDeleting = rawQuery.length < lastRawQueryRef.current.length;\n const charDiff = Math.abs(rawQuery.length - lastRawQueryRef.current.length);\n if (isDeleting || charDiff >= minDiff) {\n doFetch(rawQuery, updatedParams);\n return true;\n }\n return false;\n };\n\n debounceRef.current = setTimeout(() => {\n if (attemptFetch(MIN_CHARS_DIFF)) {\n if (slowDebounceRef.current) clearTimeout(slowDebounceRef.current);\n }\n }, DEBOUNCE_MS);\n\n slowDebounceRef.current = setTimeout(() => attemptFetch(1), SLOW_DEBOUNCE_MS);\n\n return () => {\n if (debounceRef.current) clearTimeout(debounceRef.current);\n if (slowDebounceRef.current) clearTimeout(slowDebounceRef.current);\n };\n }, [\n text,\n completedParams,\n doFetch,\n filterBaseRef,\n filterInProgressRef,\n skipNextFetchRef,\n suggestionsRef,\n lastRawQueryRef,\n ]);\n}\n","import type {\n APIConfig,\n AutocompleteRequest,\n AutocompleteResponse,\n CompletedParam,\n CompletedParamState,\n} from \"../types\";\n\n// Replaced at build time by tsup/vitest `define` config with the package.json version.\ndeclare const __SDK_VERSION__: string;\nconst SDK_VERSION = __SDK_VERSION__;\n\nlet hasWarnedMissingKey = false;\n\nfunction generateRequestId(): string {\n return crypto.randomUUID();\n}\n\nfunction toWireParam(param: CompletedParamState, includeText: boolean): CompletedParam {\n return {\n placeholder: param.placeholder,\n type: param.type,\n ...(includeText && { text: param.text }),\n kind: param.kind,\n };\n}\n\nexport async function fetchSuggestions(\n rawQuery: string,\n completedParams: CompletedParamState[],\n options?: {\n maskCompletedText?: boolean;\n signal?: AbortSignal;\n apiConfig?: APIConfig;\n },\n): Promise<AutocompleteResponse> {\n const apiConfig = options?.apiConfig;\n const apiKey = apiConfig?.apiKey ?? \"\";\n if (!apiKey && !hasWarnedMissingKey) {\n hasWarnedMissingKey = true;\n // biome-ignore lint/suspicious/noConsole: intentional dev warning\n console.warn(\n \"[AIAutocomplete] No apiKey in apiConfig. Requests will be sent without an Authorization header.\",\n );\n }\n const authScheme = apiConfig?.authScheme ?? \"Bearer\";\n const includeText = !options?.maskCompletedText;\n\n const rawCount = completedParams.find(\n (p) => p.type === \"contact\" && p.metadata?.contact_account_count,\n )?.metadata?.contact_account_count;\n const contactAccountCount = typeof rawCount === \"number\" ? rawCount : undefined;\n\n const body: AutocompleteRequest = {\n data: {\n raw_query: rawQuery,\n completed_params: completedParams.map((p) => toWireParam(p, includeText)),\n ...(contactAccountCount != null && { contact_account_count: contactAccountCount }),\n },\n meta: {\n request_id: generateRequestId(),\n request_at: new Date().toISOString(),\n language: typeof navigator !== \"undefined\" ? navigator.language : \"en-US\",\n client_version: SDK_VERSION,\n },\n };\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n ...(apiConfig?.appIdentifier && { \"X-App-Identifier\": apiConfig.appIdentifier }),\n ...apiConfig?.headers,\n };\n if (apiKey) {\n headers.Authorization = authScheme === \"Basic\" ? `Basic ${btoa(apiKey)}` : `Bearer ${apiKey}`;\n }\n\n const response = await fetch(apiConfig?.endpoint ?? \"/ac/suggest\", {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n signal: options?.signal,\n });\n\n if (!response.ok) {\n throw new Error(`API error: ${response.status} ${response.statusText}`);\n }\n\n return response.json() as Promise<AutocompleteResponse>;\n}\n","import type { CompletedParamState } from \"../types\";\n\ninterface BuildQueryResult {\n rawQuery: string;\n completedParams: CompletedParamState[];\n}\n\n/**\n * Takes the raw input text and completed params (without placeholders),\n * replaces each completed param's text in the string with a {{TYPE_N}} token,\n * and returns the transformed query + params with placeholders filled in.\n *\n * Replacements happen left-to-right, first occurrence only per param.\n * Counter is per-type (e.g. {{TASK_1}}, {{GOAL_1}}, {{GOAL_2}}).\n */\nexport function buildQuery(text: string, completedParams: CompletedParamState[]): BuildQueryResult {\n let result = text;\n const typeCounts: Record<string, number> = {};\n const updatedParams: CompletedParamState[] = [];\n\n for (const param of completedParams) {\n const count = (typeCounts[param.type] ?? 0) + 1;\n typeCounts[param.type] = count;\n\n const typeKey = param.type.toUpperCase().replace(/\\s+/g, \"_\");\n const placeholder = `{{${typeKey}_${count}}}`;\n\n // Replace first occurrence of the param text in the string\n const index = result.indexOf(param.text);\n if (index !== -1) {\n result = result.slice(0, index) + placeholder + result.slice(index + param.text.length);\n }\n\n updatedParams.push({ ...param, placeholder });\n }\n\n return { rawQuery: result, completedParams: updatedParams };\n}\n","import type { Suggestion, SuggestionOption } from \"../types\";\n\n/**\n * Applies option overrides by calling the override function with an empty query,\n * then prepending results to suggestions that match by type, deduplicating by text.\n */\nexport function applyOptionOverrides(\n suggestions: Suggestion[],\n overrides?: Record<string, (query: string) => SuggestionOption[]>,\n): Suggestion[] {\n if (!overrides) return suggestions;\n return suggestions.map((s) => {\n const fn = overrides[s.type];\n if (!fn) return s;\n const extra = fn(\"\");\n if (extra.length === 0) return s;\n const existingTexts = new Set(extra.map((o) => o.text));\n const deduped = (s.options ?? []).filter((o) => !existingTexts.has(o.text));\n return { ...s, options: [...extra, ...deduped] };\n });\n}\n","import { type KeyboardEvent, type MutableRefObject, useCallback } from \"react\";\nimport type {\n AutocompleteResult,\n CompletedParamState,\n Suggestion,\n SuggestionOption,\n} from \"../types\";\nimport { buildQuery } from \"../utils/buildQuery\";\n\ninterface UseAutocompleteKeyboardOptions {\n activeDropdownIndex: number;\n setActiveDropdownIndex: (index: number) => void;\n filteredOptions: SuggestionOption[];\n selectOption: (option: SuggestionOption) => void;\n onSubmitRef: MutableRefObject<((result: AutocompleteResult) => void) | undefined>;\n text: string;\n completedParams: CompletedParamState[];\n isDropdownOpen: boolean;\n hasPlaceholder: boolean;\n placeholderText: string;\n suggestions: Suggestion[];\n actionableSuggestions: Suggestion[];\n setActivePill: (index: number) => void;\n filterBaseRef: MutableRefObject<number>;\n columns: number;\n setText: (value: string) => void;\n setCompletedParams: (fn: (prev: CompletedParamState[]) => CompletedParamState[]) => void;\n setSuggestions: (fn: (prev: Suggestion[]) => Suggestion[]) => void;\n}\n\nexport function useAutocompleteKeyboard({\n activeDropdownIndex,\n setActiveDropdownIndex,\n filteredOptions,\n selectOption,\n onSubmitRef,\n text,\n completedParams,\n isDropdownOpen,\n hasPlaceholder,\n placeholderText,\n suggestions,\n actionableSuggestions,\n setActivePill,\n filterBaseRef,\n columns,\n setText,\n setCompletedParams,\n setSuggestions,\n}: UseAutocompleteKeyboardOptions) {\n const getTappableIndices = useCallback(() => {\n const tappable = filteredOptions\n .map((o, i) => (o.is_tappable ? i : -1))\n .filter((i) => i !== -1);\n // Column-first ordering: all column-0 items, then column-1, etc.\n const buckets: number[][] = Array.from({ length: columns }, () => []);\n for (const i of tappable) buckets[i % columns].push(i);\n return buckets.flat();\n }, [filteredOptions, columns]);\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLTextAreaElement>) => {\n const tappableIndices = getTappableIndices();\n\n switch (e.key) {\n case \"ArrowDown\": {\n e.preventDefault();\n if (tappableIndices.length === 0) return;\n const currentPos = tappableIndices.indexOf(activeDropdownIndex);\n const nextPos = currentPos < tappableIndices.length - 1 ? currentPos + 1 : 0;\n setActiveDropdownIndex(tappableIndices[nextPos]);\n break;\n }\n case \"ArrowUp\": {\n e.preventDefault();\n if (tappableIndices.length === 0) return;\n const currentPos = tappableIndices.indexOf(activeDropdownIndex);\n const prevPos = currentPos > 0 ? currentPos - 1 : tappableIndices.length - 1;\n setActiveDropdownIndex(tappableIndices[prevPos]);\n break;\n }\n case \"ArrowRight\": {\n if (activeDropdownIndex < 0) {\n // No dropdown option selected — cycle to the next suggestion pill\n if (actionableSuggestions.length > 1) {\n e.preventDefault();\n setActivePill(1);\n }\n break;\n }\n const col = activeDropdownIndex % columns;\n if (col < columns - 1) {\n const rightNeighbor = activeDropdownIndex + 1;\n if (\n rightNeighbor < filteredOptions.length &&\n filteredOptions[rightNeighbor]?.is_tappable\n ) {\n e.preventDefault();\n setActiveDropdownIndex(rightNeighbor);\n }\n }\n break;\n }\n case \"ArrowLeft\": {\n if (activeDropdownIndex < 0) break;\n if (activeDropdownIndex % columns > 0) {\n const leftNeighbor = activeDropdownIndex - 1;\n if (leftNeighbor >= 0 && filteredOptions[leftNeighbor]?.is_tappable) {\n e.preventDefault();\n setActiveDropdownIndex(leftNeighbor);\n }\n }\n break;\n }\n case \"Enter\": {\n e.preventDefault();\n if (activeDropdownIndex >= 0 && filteredOptions[activeDropdownIndex]?.is_tappable) {\n selectOption(filteredOptions[activeDropdownIndex]);\n } else if (onSubmitRef.current) {\n const { rawQuery, completedParams: finalParams } = buildQuery(text, completedParams);\n const result: AutocompleteResult = {\n query: text.trim(),\n raw_query: rawQuery,\n completed_params: finalParams,\n };\n onSubmitRef.current(result);\n }\n break;\n }\n case \"Tab\": {\n if (activeDropdownIndex >= 0 && filteredOptions[activeDropdownIndex]?.is_tappable) {\n e.preventDefault();\n selectOption(filteredOptions[activeDropdownIndex]);\n } else if (isDropdownOpen) {\n const firstTappable = filteredOptions.find((o) => o.is_tappable);\n if (firstTappable) {\n e.preventDefault();\n selectOption(firstTappable);\n }\n } else if (!text && hasPlaceholder) {\n e.preventDefault();\n const placeholderSuggestion = suggestions.find((s) => s.type === \"placeholder\");\n if (placeholderSuggestion) {\n setText(placeholderText);\n filterBaseRef.current = placeholderText.length;\n setCompletedParams((prev) => [\n ...prev,\n {\n id: crypto.randomUUID(),\n placeholder: \"\",\n type: placeholderSuggestion.type,\n text: placeholderText,\n kind: null,\n suggestionType: placeholderSuggestion.type,\n suggestionPlaceholder: placeholderSuggestion.text,\n options: placeholderSuggestion.options ?? [],\n },\n ]);\n setSuggestions((prev) => prev.filter((s) => s !== placeholderSuggestion));\n } else {\n setText(placeholderText);\n filterBaseRef.current = placeholderText.length;\n }\n }\n break;\n }\n case \"Escape\":\n setActiveDropdownIndex(-1);\n break;\n }\n },\n [\n actionableSuggestions,\n activeDropdownIndex,\n columns,\n completedParams,\n filteredOptions,\n filterBaseRef,\n getTappableIndices,\n hasPlaceholder,\n isDropdownOpen,\n onSubmitRef,\n placeholderText,\n selectOption,\n setActiveDropdownIndex,\n setActivePill,\n setCompletedParams,\n setSuggestions,\n setText,\n suggestions,\n text,\n ],\n );\n\n return { handleKeyDown, getTappableIndices };\n}\n","import { type MutableRefObject, useCallback } from \"react\";\nimport type { CompletedParamState, Suggestion } from \"../types\";\n\ninterface UseAutocompletePillsOptions {\n completedParams: CompletedParamState[];\n suggestions: Suggestion[];\n setCompletedParams: (fn: (prev: CompletedParamState[]) => CompletedParamState[]) => void;\n setSuggestions: (fn: Suggestion[] | ((prev: Suggestion[]) => Suggestion[])) => void;\n setActiveDropdownIndex: (index: number) => void;\n filterBaseRef: MutableRefObject<number>;\n pillTappedRef: MutableRefObject<boolean>;\n}\n\nexport function useAutocompletePills({\n completedParams,\n suggestions,\n setCompletedParams,\n setSuggestions,\n setActiveDropdownIndex,\n filterBaseRef,\n pillTappedRef,\n}: UseAutocompletePillsOptions) {\n const setActivePill = useCallback(\n (index: number) => {\n const actionable = suggestions.filter((s) => s.type !== \"placeholder\");\n if (index < 0 || index >= actionable.length) return;\n const moved = actionable[index];\n const rest = actionable.filter((_, i) => i !== index);\n const placeholders = suggestions.filter((s) => s.type === \"placeholder\");\n setSuggestions([...placeholders, moved, ...rest]);\n pillTappedRef.current = true;\n setActiveDropdownIndex(-1);\n },\n [suggestions, setSuggestions, setActiveDropdownIndex, pillTappedRef],\n );\n\n const removeLastParam = useCallback(() => {\n if (completedParams.length === 0) return;\n const lastParam = completedParams[completedParams.length - 1];\n const restoredSuggestion: Suggestion = {\n type: lastParam.suggestionType,\n text: lastParam.suggestionPlaceholder,\n required: true,\n options: lastParam.options,\n };\n setCompletedParams((prev) => prev.slice(0, -1));\n setSuggestions((prev: Suggestion[]) => [restoredSuggestion, ...prev]);\n setActiveDropdownIndex(-1);\n }, [completedParams, setCompletedParams, setSuggestions, setActiveDropdownIndex]);\n\n const reEditParam = useCallback(\n (param: CompletedParamState) => {\n const restoredSuggestion: Suggestion = {\n type: param.suggestionType,\n text: param.suggestionPlaceholder,\n required: true,\n options: param.options,\n };\n return {\n apply: (setText: (fn: (prev: string) => string) => void) => {\n setText((prev) => {\n let pos = 0;\n for (const p of completedParams) {\n const idx = prev.indexOf(p.text, pos);\n if (idx === -1) continue;\n if (p.id === param.id) {\n const before = prev.slice(0, idx);\n const after = prev.slice(idx + param.text.length);\n const cleaned = (before + after).replace(/ {2,}/g, \" \");\n filterBaseRef.current = Math.min(filterBaseRef.current, cleaned.length);\n return cleaned;\n }\n pos = idx + p.text.length;\n }\n return prev;\n });\n setCompletedParams((prev) => prev.filter((p) => p.id !== param.id));\n setSuggestions((prev: Suggestion[]) => [restoredSuggestion, ...prev]);\n setActiveDropdownIndex(-1);\n pillTappedRef.current = true;\n },\n };\n },\n [\n completedParams,\n setCompletedParams,\n setSuggestions,\n setActiveDropdownIndex,\n filterBaseRef,\n pillTappedRef,\n ],\n );\n\n return { setActivePill, removeLastParam, reEditParam };\n}\n"],"mappings":"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","names":["forwardRef","useCallback","useEffect","useImperativeHandle","useRef","s","AIAutocomplete_module_css_default","s","AIAutocompleteDropdown_module_css_default","s","SuggestionGrid_module_css_default","s","SuggestionItem_module_css_default","jsx","jsxs","SuggestionItem","option","isHighlighted","onSelect","onHighlight","id","className","SuggestionItem_module_css_default","e","jsx","SuggestionGrid","options","activeIndex","onSelect","onHighlight","listboxId","SuggestionGrid_module_css_default","option","i","SuggestionItem","jsx","AIAutocompleteDropdown","suggestions","activeIndex","onSelect","onHighlight","isOpen","id","className","options","hasOptions","AIAutocompleteDropdown_module_css_default","e","SuggestionGrid","s","PillList_module_css_default","jsx","getPillOpacity","index","PillList","pills","activePillIndex","onSelectPill","PillList_module_css_default","pill","i","useCallback","useMemo","useRef","useState","extractFilterQuery","text","filterBase","isInProgress","rawRegion","spaceIdx","filterOptions","options","query","trimmed","lower","o","findExactMatch","deriveSegments","text","completedParams","result","pos","param","idx","remaining","reconcileParams","valid","invalid","useCallback","useEffect","useRef","useState","SDK_VERSION","hasWarnedMissingKey","generateRequestId","toWireParam","param","includeText","fetchSuggestions","rawQuery","completedParams","options","apiConfig","apiKey","authScheme","rawCount","p","contactAccountCount","body","headers","response","buildQuery","text","completedParams","result","typeCounts","updatedParams","param","count","placeholder","index","applyOptionOverrides","suggestions","overrides","s","fn","extra","existingTexts","o","deduped","DEBOUNCE_MS","SLOW_DEBOUNCE_MS","MIN_CHARS_DIFF","useAutocompleteFetch","textRef","suggestionsRef","filterBaseRef","filterInProgressRef","maskCompletedTextRef","apiConfigRef","optionOverridesRef","onErrorRef","setCompletedParams","setSuggestions","setActiveDropdownIndex","isLoading","setIsLoading","useState","error","setError","isReady","setIsReady","fetchVersionRef","useRef","abortRef","lastRawQueryRef","doFetch","useCallback","rawQuery","completed","controller","version","textAtRequest","s","res","fetchSuggestions","newSuggestions","applyOptionOverrides","input","lastInput","currentText","inProgressIdx","active","query","extractFilterQuery","match","findExactMatch","prev","err","caughtError","useEffect","useDebouncedFetch","text","completedParams","skipNextFetchRef","debounceRef","slowDebounceRef","hasFetchedRef","attemptFetch","minDiff","currentQuery","tappableFiltered","filterOptions","o","hasExactMatch","isInFilterZone","updatedParams","buildQuery","isDeleting","charDiff","useCallback","useAutocompleteKeyboard","activeDropdownIndex","setActiveDropdownIndex","filteredOptions","selectOption","onSubmitRef","text","completedParams","isDropdownOpen","hasPlaceholder","placeholderText","suggestions","actionableSuggestions","setActivePill","filterBaseRef","columns","setText","setCompletedParams","setSuggestions","getTappableIndices","useCallback","tappable","o","i","buckets","e","tappableIndices","currentPos","nextPos","prevPos","rightNeighbor","leftNeighbor","rawQuery","finalParams","buildQuery","result","firstTappable","placeholderSuggestion","s","prev","useCallback","useAutocompletePills","completedParams","suggestions","setCompletedParams","setSuggestions","setActiveDropdownIndex","filterBaseRef","pillTappedRef","setActivePill","index","actionable","s","moved","rest","_","i","placeholders","removeLastParam","lastParam","restoredSuggestion","prev","reEditParam","param","setText","pos","p","idx","before","after","cleaned","idCounter","useStableId","id","useRef","useAIAutocomplete","onSubmit","onError","optionOverrides","maskCompletedText","customPlaceholder","apiConfig","columns","eagerSuggestions","controlledValue","controlledParams","onChangeProp","onParamsChange","isTextControlled","isParamsControlled","internalText","setInternalText","useState","internalCompletedParams","setInternalCompletedParams","suggestions","setSuggestions","activeDropdownIndex","setActiveDropdownIndex","text","completedParams","onSubmitRef","onChangeRef","onParamsChangeRef","controlledValueRef","controlledParamsRef","setText","useCallback","value","newVal","prev","setCompletedParams","onErrorRef","optionOverridesRef","maskCompletedTextRef","apiConfigRef","textRef","suggestionsRef","filterBaseRef","filterInProgressRef","pillTappedRef","skipNextFetchRef","listboxId","doFetch","isLoading","error","isReady","lastRawQueryRef","useAutocompleteFetch","useDebouncedFetch","segments","useMemo","deriveSegments","filterQuery","extractFilterQuery","placeholderText","s","actionableSuggestions","activeSuggestion","overrideFn","baseOptions","filteredOptions","filterOptions","hasPlaceholder","isDropdownOpen","selectOption","option","completed","base","prefix","lastWord","needsSpace","newText","remainingActionable","handleChange","e","raw","newValue","valid","invalid","reconcileParams","param","newFilterQuery","match","findExactMatch","pills","useAutocompletePills","reEditParam","handleKeyDown","useAutocompleteKeyboard","reset","activeDescendantId","jsx","jsxs","AIAutocomplete","forwardRef","onSubmit","onError","optionOverrides","maskCompletedText","placeholder","className","apiConfig","columns","eagerSuggestions","value","controlledParams","onChangeProp","onParamsChange","ref","textareaRef","useRef","handleSubmitRef","useEffect","completedParams","suggestionPills","setActivePill","segments","inputProps","dropdownProps","reset","useAIAutocomplete","result","useImperativeHandle","handleContainerClick","canSubmit","handleSubmit","useCallback","rawQuery","finalParams","buildQuery","onChange","inputPlaceholder","restProps","isEmpty","AIAutocomplete_module_css_default","AIAutocompleteDropdown","seg","i","PillList","e"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@magicx-eng/ai-autocomplete-react",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.13",
|
|
4
4
|
"description": "AI Autocomplete React SDK — guided autocomplete with pill-based input and dropdown suggestions",
|
|
5
5
|
"main": "./dist/index.cjs",
|
|
6
6
|
"module": "./dist/index.js",
|