@magicx-eng/ai-autocomplete-react 0.1.5 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -23,7 +23,7 @@ pnpm add @magicx-eng/ai-autocomplete-react
23
23
 
24
24
  ### Peer Dependencies
25
25
 
26
- React 18 or later:
26
+ React 17 or later:
27
27
 
28
28
  ```bash
29
29
  pnpm add react react-dom
@@ -132,6 +132,7 @@ The full component. Owns the input, pills, dropdown, and keyboard navigation.
132
132
  | `placeholder?` | `string` | — | Fallback placeholder when the server doesn't return one. |
133
133
  | `className?` | `string` | — | CSS class applied to the container. |
134
134
  | `columns?` | `number` | `2` | Number of columns in the dropdown grid. |
135
+ | `eagerSuggestions?` | `boolean` | `true` | When `true`, show cached next suggestions immediately after selecting an option. When `false`, clear the dropdown and wait for the server response before showing the next suggestions. |
135
136
  | `value?` | `string` | — | Controlled text value. |
136
137
  | `completedParams?` | `CompletedParamState[]` | — | Controlled completed params. |
137
138
  | `onChange?` | `(value: string) => void` | — | Called when text changes (controlled mode). |
@@ -164,39 +165,85 @@ Accepts the same props as `<AIAutocomplete />` (except `className` and `ref`), w
164
165
 
165
166
  #### Return Value
166
167
 
168
+ **State**
169
+
170
+ | Field | Type | Description |
171
+ |---|---|---|
172
+ | `completedParams` | `CompletedParamState[]` | All parameters the user has filled so far. Each entry contains the selected option's `text`, `kind`, `type`, and `metadata`, plus client-side fields like `id` (stable UUID), `options` (cached for re-editing), `suggestionType`, and `suggestionPlaceholder`. Use these to render completed values (e.g. bold text) and to build the final query on submit. |
173
+ | `suggestionPills` | `Suggestion[]` | Unfilled suggestions that should be rendered as pills (inline chips). Excludes placeholder-type suggestions. The first item is the "active" pill whose options appear in the dropdown. Tapping a pill reorders it to the front via `setActivePill`. |
174
+ | `segments` | `Segment[]` | The input text split into typed segments for overlay rendering. Each segment is either `{ type: "text", value: string }` for plain text, or `{ type: "completed", value: string, param: CompletedParamState }` for a completed parameter. Use these to render a styled overlay on top of the textarea — e.g. showing completed params in bold while keeping the textarea's actual text transparent. |
175
+ | `suggestions` | `Suggestion[]` | All suggestions from the server, including placeholder-type suggestions. Most consumers should use `suggestionPills` and `dropdownProps` instead — this is exposed for advanced use cases like custom pill or dropdown rendering. |
176
+ | `activeIndex` | `number` | Index of the currently keyboard-highlighted option in the dropdown. `-1` when no option is highlighted. Automatically managed by arrow keys. |
177
+ | `isLoading` | `boolean` | `true` while a fetch is in flight and no cached suggestions are visible. With `eagerSuggestions={true}` (default), this only triggers on initial mount or after `reset()` — the dropdown stays open during background re-fetches. With `eagerSuggestions={false}`, it also becomes `true` after each option selection, closing the dropdown until fresh data arrives. |
178
+ | `isReady` | `boolean` | `true` when the server's `is_ready` flag indicates the query is complete and ready for execution. Use this to show a visual indicator or enable a submit button. |
179
+ | `error` | `Error \| null` | The most recent fetch error, or `null` if the last fetch succeeded. Cleared on every new fetch attempt. |
180
+
181
+ **Actions**
182
+
167
183
  | Field | Type | Description |
168
184
  |---|---|---|
169
- | `completedParams` | `CompletedParamState[]` | All filled parameters with client-side state. |
170
- | `suggestionPills` | `Suggestion[]` | Unfilled suggestion pills (excludes placeholders). |
171
- | `setActivePill` | `(index: number) => void` | Reorder pills by moving one to the front. |
172
- | `removeLastParam` | `() => void` | Remove the last completed parameter and restore its pill. |
173
- | `reEditParam` | `(param: CompletedParamState) => void` | Remove a completed parameter and restore its pill. |
174
- | `reset` | `() => void` | Clear all state and re-fetch initial suggestions. |
175
- | `segments` | `Segment[]` | Text segments for overlay rendering. |
176
- | `suggestions` | `Suggestion[]` | All suggestions including placeholders. |
177
- | `activeIndex` | `number` | Currently highlighted option index (`-1` when none). |
178
- | `isLoading` | `boolean` | Whether a fetch is in progress. |
179
- | `isReady` | `boolean` | Whether the server considers the query complete. |
180
- | `error` | `Error \| null` | Last fetch error, or `null`. |
181
- | `inputProps` | `object` | Spread onto a `<textarea>` — value, placeholder, onChange, onKeyDown, ARIA. |
182
- | `dropdownProps` | `AIAutocompleteDropdownProps` | Spread onto `<AIAutocompleteDropdown />`. |
185
+ | `setActivePill` | `(index: number) => void` | Reorder pills by moving the pill at `index` to the front, making it the active pill whose options show in the dropdown. |
186
+ | `removeLastParam` | `() => void` | Remove the most recently completed parameter, restore it as a pill, and re-show its options in the dropdown. Useful for handling backspace on an empty input. |
187
+ | `reEditParam` | `(param: CompletedParamState) => void` | Remove a specific completed parameter from the input text, restore it as a pill with its cached options, and open the dropdown. Use this when the user taps on a bold (completed) param to change their selection. |
188
+ | `reset` | `() => void` | Clear all text, completed params, and suggestions, then re-fetch initial suggestions from the server. Returns the component to its mount state. |
189
+
190
+ **Spread Props**
191
+
192
+ | Field | Type | Description |
193
+ |---|---|---|
194
+ | `inputProps` | `object` | Spread onto a `<textarea>` element. Includes `value`, `placeholder`, `onChange`, `onKeyDown`, and ARIA attributes (`role="combobox"`, `aria-expanded`, `aria-activedescendant`, `aria-autocomplete`, `aria-controls`). Handles keyboard navigation, text capitalization, param reconciliation, and exact-match auto-completion internally. |
195
+ | `dropdownProps` | `AIAutocompleteDropdownProps` | Spread onto `<AIAutocompleteDropdown />`. Includes the filtered options for the active suggestion, highlight index, selection handler, highlight handler, open state, and listbox ID. The dropdown handles mouse selection and hover highlighting. |
183
196
 
184
197
  ### `<AIAutocompleteDropdown />`
185
198
 
186
199
  The dropdown component for Tier 2 headless integration. Spread `dropdownProps` from the hook.
187
200
 
201
+ | Prop | Type | Description |
202
+ |---|---|---|
203
+ | `suggestions` | `Suggestion[]` | Suggestions to display (from `dropdownProps`). |
204
+ | `activeIndex` | `number` | Currently highlighted option index. |
205
+ | `onSelect` | `(option: SuggestionOption) => void` | Called when an option is selected. |
206
+ | `onHighlight` | `(index: number) => void` | Called when an option is highlighted (mouse hover). |
207
+ | `isOpen` | `boolean` | Whether the dropdown is visible. |
208
+ | `id` | `string` | Listbox ID for ARIA. |
209
+ | `className?` | `string` | CSS class applied to the dropdown. |
210
+
211
+ ### `Suggestion`
212
+
213
+ Represents an unfilled parameter slot. Rendered as a pill in Tier 1, or available via `suggestionPills` in Tier 2.
214
+
215
+ | Field | Type | Description |
216
+ |---|---|---|
217
+ | `type` | `string` | Suggestion type identifier (e.g. `"task"`, `"goal"`, `"contact"`). Used as the key for `optionOverrides`. |
218
+ | `text` | `string` | Display text for the pill (e.g. `"type"`, `"goal"`). |
219
+ | `required` | `boolean` | Whether this suggestion must be filled before submission. |
220
+ | `options` | `SuggestionOption[]` | Available options the user can select from. |
221
+
222
+ ### `SuggestionOption`
223
+
224
+ An individual option within a suggestion's dropdown.
225
+
226
+ | Field | Type | Description |
227
+ |---|---|---|
228
+ | `text` | `string` | Display text for the option. |
229
+ | `icon?` | `string` | Icon shown before the text (e.g. emoji). |
230
+ | `tag?` | `string` | Label shown after the text in smaller, muted style. |
231
+ | `is_tappable` | `boolean` | Whether the option can be selected. Non-tappable options are always-visible hints that cannot be chosen. |
232
+ | `kind` | `string \| null` | Category of the option (e.g. `"automation"`, `"email"`), or `null`. Passed through to `CompletedParam` on selection. |
233
+ | `metadata?` | `Record<string, unknown>` | Arbitrary metadata passed through with the selection. Available on the completed param after the user selects this option. |
234
+
188
235
  ## CSS Customization
189
236
 
190
237
  The component uses CSS Modules with customizable CSS variables. Override them on a parent element:
191
238
 
192
239
  ```css
193
240
  .my-autocomplete {
194
- --ac-color-border-default: #ccc;
195
- --ac-color-text-default: #333;
196
- --ac-color-text-muted: #999;
197
- --ac-color-bg-default: #fff;
198
- --ac-color-background-default: #fff;
199
- --ac-color-background-supportive: #f0f0f0;
241
+ --ac-color-border-default: #ccc; /* Input border */
242
+ --ac-color-text-default: #333; /* Input text, caret, submit button bg, highlighted option */
243
+ --ac-color-text-muted: #999; /* Placeholder, pill text, option text */
244
+ --ac-color-bg-default: #000; /* Submit button icon color (foreground on button) */
245
+ --ac-color-background-default: #fff; /* Dropdown background */
246
+ --ac-color-background-supportive: #eee; /* Pill background */
200
247
  }
201
248
  ```
202
249
 
package/dist/index.d.mts CHANGED
@@ -58,6 +58,9 @@ interface AIAutocompleteProps {
58
58
  className?: string;
59
59
  apiConfig?: APIConfig;
60
60
  columns?: number;
61
+ /** When true (default), show cached next suggestions immediately after option select.
62
+ * When false, clear suggestions and wait for the server response. */
63
+ eagerSuggestions?: boolean;
61
64
  value?: string;
62
65
  completedParams?: CompletedParamState[];
63
66
  onChange?: (value: string) => void;
@@ -76,6 +79,9 @@ interface UseAIAutocompleteOptions {
76
79
  placeholder?: string;
77
80
  apiConfig?: APIConfig;
78
81
  columns?: number;
82
+ /** When true (default), show cached next suggestions immediately after option select.
83
+ * When false, clear suggestions and wait for the server response. */
84
+ eagerSuggestions?: boolean;
79
85
  value?: string;
80
86
  completedParams?: CompletedParamState[];
81
87
  onChange?: (value: string) => void;
@@ -121,6 +127,6 @@ declare const AIAutocomplete: react.ForwardRefExoticComponent<AIAutocompleteProp
121
127
 
122
128
  declare function AIAutocompleteDropdown({ suggestions, activeIndex, onSelect, onHighlight, isOpen, id, className, }: AIAutocompleteDropdownProps): react_jsx_runtime.JSX.Element;
123
129
 
124
- declare function useAIAutocomplete({ onSubmit, onError, optionOverrides, maskCompletedText, placeholder: customPlaceholder, apiConfig, columns, value: controlledValue, completedParams: controlledParams, onChange: onChangeProp, onParamsChange, }: UseAIAutocompleteOptions): UseAIAutocompleteReturn;
130
+ declare function useAIAutocomplete({ onSubmit, onError, optionOverrides, maskCompletedText, placeholder: customPlaceholder, apiConfig, columns, eagerSuggestions, value: controlledValue, completedParams: controlledParams, onChange: onChangeProp, onParamsChange, }: UseAIAutocompleteOptions): UseAIAutocompleteReturn;
125
131
 
126
132
  export { AIAutocomplete, AIAutocompleteDropdown, type AIAutocompleteDropdownProps, type AIAutocompleteHandle, type AIAutocompleteProps, type APIConfig, type AutocompleteResult, type CompletedParam, type CompletedParamState, type OptionOverrides, type Segment, type Suggestion, type SuggestionOption, type TaskKind, type UseAIAutocompleteOptions, type UseAIAutocompleteReturn, useAIAutocomplete };
package/dist/index.d.ts CHANGED
@@ -58,6 +58,9 @@ interface AIAutocompleteProps {
58
58
  className?: string;
59
59
  apiConfig?: APIConfig;
60
60
  columns?: number;
61
+ /** When true (default), show cached next suggestions immediately after option select.
62
+ * When false, clear suggestions and wait for the server response. */
63
+ eagerSuggestions?: boolean;
61
64
  value?: string;
62
65
  completedParams?: CompletedParamState[];
63
66
  onChange?: (value: string) => void;
@@ -76,6 +79,9 @@ interface UseAIAutocompleteOptions {
76
79
  placeholder?: string;
77
80
  apiConfig?: APIConfig;
78
81
  columns?: number;
82
+ /** When true (default), show cached next suggestions immediately after option select.
83
+ * When false, clear suggestions and wait for the server response. */
84
+ eagerSuggestions?: boolean;
79
85
  value?: string;
80
86
  completedParams?: CompletedParamState[];
81
87
  onChange?: (value: string) => void;
@@ -121,6 +127,6 @@ declare const AIAutocomplete: react.ForwardRefExoticComponent<AIAutocompleteProp
121
127
 
122
128
  declare function AIAutocompleteDropdown({ suggestions, activeIndex, onSelect, onHighlight, isOpen, id, className, }: AIAutocompleteDropdownProps): react_jsx_runtime.JSX.Element;
123
129
 
124
- declare function useAIAutocomplete({ onSubmit, onError, optionOverrides, maskCompletedText, placeholder: customPlaceholder, apiConfig, columns, value: controlledValue, completedParams: controlledParams, onChange: onChangeProp, onParamsChange, }: UseAIAutocompleteOptions): UseAIAutocompleteReturn;
130
+ declare function useAIAutocomplete({ onSubmit, onError, optionOverrides, maskCompletedText, placeholder: customPlaceholder, apiConfig, columns, eagerSuggestions, value: controlledValue, completedParams: controlledParams, onChange: onChangeProp, onParamsChange, }: UseAIAutocompleteOptions): UseAIAutocompleteReturn;
125
131
 
126
132
  export { AIAutocomplete, AIAutocompleteDropdown, type AIAutocompleteDropdownProps, type AIAutocompleteHandle, type AIAutocompleteProps, type APIConfig, type AutocompleteResult, type CompletedParam, type CompletedParamState, type OptionOverrides, type Segment, type Suggestion, type SuggestionOption, type TaskKind, type UseAIAutocompleteOptions, type UseAIAutocompleteReturn, useAIAutocomplete };
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";var be=Object.defineProperty;var Je=Object.getOwnPropertyDescriptor;var Ze=Object.getOwnPropertyNames;var et=Object.prototype.hasOwnProperty;var tt=(e,o)=>{for(var t in o)be(e,t,{get:o[t],enumerable:!0})},ot=(e,o,t,r)=>{if(o&&typeof o=="object"||typeof o=="function")for(let n of Ze(o))!et.call(e,n)&&n!==t&&be(e,n,{get:()=>o[n],enumerable:!(r=Je(o,n))||r.enumerable});return e};var nt=e=>ot(be({},"__esModule",{value:!0}),e);var St={};tt(St,{AIAutocomplete:()=>ze,AIAutocompleteDropdown:()=>re,useAIAutocomplete:()=>ce});module.exports=nt(St);var D=require("react");var j={};var ye={};var Re={};var W={};var ne=require("react/jsx-runtime");function _e({option:e,isHighlighted:o,onSelect:t,onHighlight:r,id:n}){let a=[W.item,o?W.highlighted:"",e.is_tappable?W.tappable:W.nonTappable].filter(Boolean).join(" ");return(0,ne.jsxs)("div",{id:n,role:"option","aria-selected":o,className:a,tabIndex:e.is_tappable?0:-1,onClick:()=>e.is_tappable&&t(e),onKeyDown:i=>{e.is_tappable&&(i.key==="Enter"||i.key===" ")&&(i.preventDefault(),t(e))},onMouseEnter:r,children:[e.icon?`${e.icon} ${e.text}`:e.text,e.tag&&(0,ne.jsx)("span",{className:W.tag,children:e.tag})]})}var Se=require("react/jsx-runtime");function Te({options:e,activeIndex:o,onSelect:t,onHighlight:r,listboxId:n}){return(0,Se.jsx)("div",{className:Re.grid,children:e.map((a,i)=>(0,Se.jsx)(_e,{option:a,isHighlighted:i===o,onSelect:t,onHighlight:()=>r(i),id:`${n}-option-${i}`},a.text))})}var xe=require("react/jsx-runtime");function re({suggestions:e,activeIndex:o,onSelect:t,onHighlight:r,isOpen:n,id:a,className:i}){let l=e[0],d=n&&l&&l.options.length>0;return(0,xe.jsx)("div",{id:a,role:"listbox",className:`${ye.dropdown} ${d?ye.visible:""} ${i??""}`,onMouseDown:g=>g.preventDefault(),children:l&&l.options.length>0&&(0,xe.jsx)(Te,{options:l.options,activeIndex:o,onSelect:t,onHighlight:r,listboxId:a})})}var ae={};var Pe=require("react/jsx-runtime");function lt(e){return e===0?.4:e===1?.3:.15}function Ee({pills:e,activePillIndex:o,onSelectPill:t}){return(0,Pe.jsx)("span",{className:ae.list,children:e.map((r,n)=>(0,Pe.jsx)("button",{type:"button",className:`${ae.pill} ${n===o?ae.active:""}`,style:{opacity:lt(n)},onClick:()=>t(n),children:r.text},`${r.type}-${r.text}`))})}var u=require("react");function se(e,o){let t=o.trimStart();if(!t)return e;let r=t.toLowerCase();return e.filter(n=>!n.is_tappable||n.text.toLowerCase().includes(r))}function Z(e,o){let t=o.trim();if(!t)return null;let r=t.toLowerCase();return e.find(n=>n.is_tappable&&n.text.toLowerCase()===r)??null}function Me(e,o){let t=[],r=0;for(let a of o){let i=e.indexOf(a.text,r);i!==-1&&(i>r&&t.push({type:"text",value:e.slice(r,i)}),t.push({type:"completed",value:a.text,param:a}),r=i+a.text.length)}let n=e.slice(r);return n&&t.push({type:"text",value:n}),t}function Ue(e,o){let t=[],r=[],n=0;for(let a of o){let i=e.indexOf(a.text,n);i===-1?r.push(a):(t.push(a),n=i+a.text.length)}return{valid:t,invalid:r}}var T=require("react");var ut="0.1.5",pt=process?.env.MAGICX_API_ENDPOINT||"/api/suggest",Le=!1;function mt(e){let o=e?.apiKey||process?.env.MAGICX_AI_AUTOCOMPLETE_API_KEY||"";return!o&&!Le&&(Le=!0,console.warn("[AIAutocomplete] No API key set (MAGICX_AI_AUTOCOMPLETE_API_KEY). Requests will be sent without an Authorization header.")),o}function dt(e){return e?.authScheme?e.authScheme:process?.env.MAGICX_AUTH_SCHEME==="Basic"?"Basic":"Bearer"}function ft(){return crypto.randomUUID()}function gt(e,o){return{placeholder:e.placeholder,type:e.type,...o&&{text:e.text},kind:e.kind}}async function Ne(e,o,t){let r=t?.apiConfig,n=mt(r),a=dt(r),i=!t?.maskCompletedText,l=t?.contactAccountCount,d={data:{raw_query:e,completed_params:o.map(b=>gt(b,i)),...l!=null&&{contact_account_count:l}},meta:{request_id:ft(),request_at:new Date().toISOString(),language:typeof navigator<"u"?navigator.language:"en-US",client_version:ut}},g={"Content-Type":"application/json","X-App-Identifier":process?.env.MAGICX_APP_IDENTIFIER||"active-campaign-demo",...r?.headers};n&&(g.Authorization=a==="Basic"?`Basic ${btoa(n)}`:`Bearer ${n}`);let p=await fetch(pt,{method:"POST",headers:g,body:JSON.stringify(d),signal:t?.signal});if(!p.ok)throw new Error(`API error: ${p.status} ${p.statusText}`);return p.json()}function G(e,o){let t=e,r={},n=[];for(let a of o){let i=(r[a.type]??0)+1;r[a.type]=i;let d=`{{${a.type.toUpperCase().replace(/\s+/g,"_")}_${i}}}`,g=t.indexOf(a.text);g!==-1&&(t=t.slice(0,g)+d+t.slice(g+a.text.length)),n.push({...a,placeholder:d})}return{rawQuery:t,completedParams:n}}function De(e,o){return o?e.map(t=>{let r=o[t.type];if(!r)return t;let n=r("");if(n.length===0)return t;let a=new Set(n.map(l=>l.text)),i=(t.options??[]).filter(l=>!a.has(l.text));return{...t,options:[...n,...i]}}):e}var ht=100,bt=300,yt=2;function Fe({textRef:e,suggestionsRef:o,filterBaseRef:t,maskCompletedTextRef:r,apiConfigRef:n,optionOverridesRef:a,onErrorRef:i,setCompletedParams:l,setSuggestions:d,setActiveDropdownIndex:g}){let[p,b]=(0,T.useState)(!1),[h,S]=(0,T.useState)(null),[k,x]=(0,T.useState)(!1),v=(0,T.useRef)(0),A=(0,T.useRef)(null),m=(0,T.useRef)(""),f=(0,T.useCallback)(async(s,c)=>{A.current?.abort();let P=new AbortController;A.current=P;let U=++v.current,F=e.current.length;o.current.some($=>$.type!=="placeholder")||b(!0),S(null);try{let $=c.find(_=>_.type==="contact"&&_.metadata?.contact_account_count)?.metadata?.contact_account_count,K=await Ne(s,c,{maskCompletedText:r.current,signal:P.signal,contactAccountCount:typeof $=="number"?$:void 0,apiConfig:n.current});if(U!==v.current)return;let R=De(K.data.suggestions??[],a.current);x(K.data.is_ready??!1),m.current=s;let E=K.data.input??[],q=E[E.length-1],H=e.current;if(q?.state==="in_progress"){let _=H.toLowerCase().lastIndexOf(q.text.toLowerCase());_!==-1?t.current=_:t.current=F}else t.current=F;let O=R.filter(_=>_.type!=="placeholder")[0];if(O){let _=H.slice(t.current),B=Z(O.options,_);B&&(l(M=>[...M,{id:crypto.randomUUID(),placeholder:"",type:O.type,text:B.text,kind:B.kind,suggestionType:O.type,suggestionPlaceholder:O.text,options:O.options,metadata:B.metadata}]),R=R.filter(M=>M!==O))}d(R),b(!1),g(-1)}catch($){if(U===v.current){let K=$ instanceof Error?$:new Error(String($));S(K),b(!1),i.current?.(K)}}},[e,o,t,r,n,a,i,l,d,g]);return(0,T.useEffect)(()=>(f("",[]),()=>{A.current?.abort()}),[f]),{doFetch:f,isLoading:p,error:h,isReady:k,lastRawQueryRef:m}}function $e({text:e,completedParams:o,doFetch:t,filterBaseRef:r,skipNextFetchRef:n,suggestionsRef:a,lastRawQueryRef:i}){let l=(0,T.useRef)(null),d=(0,T.useRef)(null),g=(0,T.useRef)(!0);(0,T.useEffect)(()=>{l.current&&clearTimeout(l.current),d.current&&clearTimeout(d.current);let p=b=>{if(n.current)return n.current=!1,!1;if(!e&&o.length===0)return g.current?(t("",[]),!0):(g.current=!0,!1);let h=e.slice(r.current),x=a.current.filter(F=>F.type!=="placeholder")[0],A=(x?se(x.options,h):[]).filter(F=>F.is_tappable),m=x?Z(x.options,h)!==null:!1,f=h.trim().length>0;if(A.length>0&&!m&&f)return!1;let{rawQuery:s,completedParams:c}=G(e,o),P=s.length<i.current.length,U=Math.abs(s.length-i.current.length);return P||U>=b?(t(s,c),!0):!1};return l.current=setTimeout(()=>{p(yt)&&d.current&&clearTimeout(d.current)},ht),d.current=setTimeout(()=>p(1),bt),()=>{l.current&&clearTimeout(l.current),d.current&&clearTimeout(d.current)}},[e,o,t,r,n,a,i])}var ve=require("react");function Ke({activeDropdownIndex:e,setActiveDropdownIndex:o,filteredOptions:t,selectOption:r,onSubmitRef:n,text:a,completedParams:i,isDropdownOpen:l,hasPlaceholder:d,placeholderText:g,suggestions:p,filterBaseRef:b,columns:h,setText:S,setCompletedParams:k,setSuggestions:x}){let v=(0,ve.useCallback)(()=>{let m=t.map((c,P)=>c.is_tappable?P:-1).filter(c=>c!==-1),f=m.filter(c=>c%h===0),s=m.filter(c=>c%h===1);return[...f,...s]},[t,h]);return{handleKeyDown:(0,ve.useCallback)(m=>{let f=v();switch(m.key){case"ArrowDown":{if(m.preventDefault(),f.length===0)return;let s=f.indexOf(e),c=s<f.length-1?s+1:0;o(f[c]);break}case"ArrowUp":{if(m.preventDefault(),f.length===0)return;let s=f.indexOf(e),c=s>0?s-1:f.length-1;o(f[c]);break}case"ArrowRight":{if(e<0)break;if(e%h===0){let s=e+1;s<t.length&&t[s]?.is_tappable&&(m.preventDefault(),o(s))}break}case"ArrowLeft":{if(e<0)break;if(e%h===1){let s=e-1;s>=0&&t[s]?.is_tappable&&(m.preventDefault(),o(s))}break}case"Enter":{if(m.preventDefault(),e>=0&&t[e]?.is_tappable)r(t[e]);else if(n.current){let{rawQuery:s,completedParams:c}=G(a,i),P={query:a.trim(),raw_query:s,completed_params:c};n.current(P)}break}case"Tab":{if(e>=0&&t[e]?.is_tappable)m.preventDefault(),r(t[e]);else if(l){let s=t.find(c=>c.is_tappable);s&&(m.preventDefault(),r(s))}else if(!a&&d){m.preventDefault();let s=p.find(c=>c.type==="placeholder");s?(S(g),b.current=g.length,k(c=>[...c,{id:crypto.randomUUID(),placeholder:"",type:s.type,text:g,kind:null,suggestionType:s.type,suggestionPlaceholder:s.text,options:s.options}]),x(c=>c.filter(P=>P!==s))):(S(g),b.current=g.length)}break}case"Escape":o(-1);break}},[e,h,i,t,b,v,d,l,n,g,r,o,k,x,S,p,a]),getTappableIndices:v}}var ie=require("react");function je({completedParams:e,suggestions:o,setCompletedParams:t,setSuggestions:r,setActiveDropdownIndex:n,filterBaseRef:a,pillTappedRef:i}){let l=(0,ie.useCallback)(p=>{let b=o.filter(x=>x.type!=="placeholder");if(p<0||p>=b.length)return;let h=b[p],S=b.filter((x,v)=>v!==p),k=o.filter(x=>x.type==="placeholder");r([...k,h,...S]),i.current=!0,n(-1)},[o,r,n,i]),d=(0,ie.useCallback)(()=>{if(e.length===0)return;let p=e[e.length-1],b={type:p.suggestionType,text:p.suggestionPlaceholder,required:!0,options:p.options};t(h=>h.slice(0,-1)),r(h=>[b,...h]),n(-1)},[e,t,r,n]),g=(0,ie.useCallback)(p=>{let b={type:p.suggestionType,text:p.suggestionPlaceholder,required:!0,options:p.options};return{apply:h=>{h(S=>{let k=0;for(let x of e){let v=S.indexOf(x.text,k);if(v!==-1){if(x.id===p.id){let A=S.slice(0,v),m=S.slice(v+p.text.length),f=(A+m).replace(/ {2,}/g," ");return a.current=Math.min(a.current,f.length),f}k=v+x.text.length}}return S}),t(S=>S.filter(k=>k.id!==p.id)),r(S=>[b,...S]),n(-1),i.current=!0}}},[e,t,r,n,a,i]);return{setActivePill:l,removeLastParam:d,reEditParam:g}}function ce({onSubmit:e,onError:o,optionOverrides:t,maskCompletedText:r,placeholder:n,apiConfig:a,columns:i=2,value:l,completedParams:d,onChange:g,onParamsChange:p}){let b=l!==void 0,h=d!==void 0,[S,k]=(0,u.useState)(""),[x,v]=(0,u.useState)([]),[A,m]=(0,u.useState)([]),[f,s]=(0,u.useState)(-1),c=b?l:S,P=h?d:x,U=(0,u.useRef)(e);U.current=e;let F=(0,u.useRef)(g);F.current=g;let z=(0,u.useRef)(p);z.current=p;let $=(0,u.useRef)(l);$.current=l;let K=(0,u.useRef)(d);K.current=d;let R=(0,u.useCallback)(y=>{if(typeof y=="function")if(b){let w=y($.current??"");F.current?.(w)}else k(w=>{let Q=y(w);return F.current?.(Q),Q});else b||k(y),F.current?.(y)},[b]),E=(0,u.useCallback)(y=>{if(typeof y=="function")if(h){let w=y(K.current??[]);z.current?.(w)}else v(w=>{let Q=y(w);return z.current?.(Q),Q});else h||v(y),z.current?.(y)},[h]),q=(0,u.useRef)(o);q.current=o;let H=(0,u.useRef)(t);H.current=t;let Y=(0,u.useRef)(r);Y.current=r;let O=(0,u.useRef)(a);O.current=a;let _=(0,u.useRef)(c);_.current=c;let B=(0,u.useRef)(A);B.current=A;let M=(0,u.useRef)(0),ee=(0,u.useRef)(!1),Ae=(0,u.useRef)(!1),le=(0,u.useId)(),{doFetch:ue,isLoading:Ce,error:qe,isReady:Be,lastRawQueryRef:pe}=Fe({textRef:_,suggestionsRef:B,filterBaseRef:M,maskCompletedTextRef:Y,apiConfigRef:O,optionOverridesRef:H,onErrorRef:q,setCompletedParams:E,setSuggestions:m,setActiveDropdownIndex:s});$e({text:c,completedParams:P,doFetch:ue,filterBaseRef:M,skipNextFetchRef:Ae,suggestionsRef:B,lastRawQueryRef:pe});let Qe=(0,u.useMemo)(()=>Me(c,P),[c,P]);M.current=Math.min(M.current,c.length);let me=c.slice(M.current),de=(0,u.useMemo)(()=>A.filter(w=>w.type==="placeholder").map(w=>w.text).join(" ")||n||"",[A,n]),te=(0,u.useMemo)(()=>A.filter(y=>y.type!=="placeholder"),[A]),C=te[0],ke=C?t?.[C.type]:void 0,we=C?ke?ke(me.trim()):C.options??[]:[],fe=(0,u.useMemo)(()=>se(we,me),[we,me]),Oe=de.length>0,ge=!Ce&&fe.length>0&&(!!c||ee.current||!Oe),Ie=(0,u.useCallback)(y=>{if(!C)return;let w={id:crypto.randomUUID(),placeholder:"",type:C.type,text:y.text,kind:y.kind,suggestionType:C.type,suggestionPlaceholder:C.text,options:C.options,metadata:y.metadata},Q=M.current,L=_.current.slice(0,Q);if(L.length>0&&!L.endsWith(" ")){let N=L.split(/\s+/).pop()??"";N&&y.text.toLowerCase().startsWith(N.toLowerCase())&&(L=L.slice(0,L.length-N.length))}let he=L.length>0&&L[L.length-1]!==" ",V=L+(he?" ":"")+y.text+" ";R(V),M.current=V.length,E(N=>[...N,w]),m(N=>N.filter(J=>J!==C)),ee.current=!1,s(-1),te.length-1>0&&(Ae.current=!0)},[C,te,R,E]),He=(0,u.useCallback)(y=>{let w=y.target.value,L=w.length>0&&!y.nativeEvent?.isComposing&&w[0]!==w[0].toUpperCase()?w[0].toUpperCase()+w.slice(1):w;R(L),ee.current=!1,s(-1);let{valid:he,invalid:V}=Ue(L,P);if(V.length>0){E(()=>he);for(let X of V)m(N=>[{type:X.suggestionType,text:X.suggestionPlaceholder,required:!0,options:X.options},...N])}if(C&&V.length===0){let X=L.slice(M.current),N=Z(C.options,X);N&&(E(J=>[...J,{id:crypto.randomUUID(),placeholder:"",type:C.type,text:N.text,kind:N.kind,suggestionType:C.type,suggestionPlaceholder:C.text,options:C.options,metadata:N.metadata}]),m(J=>J.filter(Ye=>Ye!==C)))}},[P,C,R,E]),{handleKeyDown:Ve}=Ke({activeDropdownIndex:f,setActiveDropdownIndex:s,filteredOptions:fe,selectOption:Ie,onSubmitRef:U,text:c,completedParams:P,isDropdownOpen:ge,hasPlaceholder:Oe,placeholderText:de,suggestions:A,filterBaseRef:M,columns:i,setText:R,setCompletedParams:E,setSuggestions:m}),oe=je({completedParams:P,suggestions:A,setCompletedParams:E,setSuggestions:m,setActiveDropdownIndex:s,filterBaseRef:M,pillTappedRef:ee}),Xe=(0,u.useCallback)(y=>{oe.reEditParam(y).apply(R)},[oe,R]),We=(0,u.useCallback)(()=>{R(""),E(()=>[]),m([]),s(-1),M.current=0,pe.current="",ue("",[])},[ue,R,E,pe]),Ge=f>=0?`${le}-option-${f}`:void 0;return{completedParams:P,suggestionPills:te,setActivePill:oe.setActivePill,removeLastParam:oe.removeLastParam,reEditParam:Xe,segments:Qe,suggestions:A,activeIndex:f,isReady:Be,isLoading:Ce,error:qe,inputProps:{value:c,placeholder:de||void 0,onChange:He,onKeyDown:Ve,role:"combobox","aria-expanded":ge,"aria-activedescendant":Ge,"aria-autocomplete":"list","aria-controls":le},reset:We,dropdownProps:{suggestions:C?[{...C,options:fe}]:[],activeIndex:f,onSelect:Ie,onHighlight:s,isOpen:ge,id:le}}}var I=require("react/jsx-runtime"),ze=(0,D.forwardRef)(function({onSubmit:o,onError:t,optionOverrides:r,maskCompletedText:n,placeholder:a,className:i,apiConfig:l,columns:d,value:g,completedParams:p,onChange:b,onParamsChange:h},S){let k=(0,D.useRef)(null),[x,v]=(0,D.useState)(!1),A=(0,D.useRef)(()=>{}),m=(0,D.useRef)(void 0);(0,D.useEffect)(()=>(k.current?.focus(),()=>clearTimeout(m.current)),[]);let{completedParams:f,suggestionPills:s,setActivePill:c,segments:P,inputProps:U,dropdownProps:F,reset:z}=ce({onSubmit:O=>A.current(O),onError:t,optionOverrides:r,maskCompletedText:n,placeholder:a,apiConfig:l,columns:d,value:g,completedParams:p,onChange:b,onParamsChange:h});(0,D.useImperativeHandle)(S,()=>({focus:()=>k.current?.focus(),reset:z}),[z]);let $=()=>{k.current?.focus()},K=!!U.value||f.length>0,R=(0,D.useCallback)(()=>{if(!K)return;let{rawQuery:O,completedParams:_}=G(U.value,f);o({query:U.value.trim(),raw_query:O,completed_params:_}),z(),v(!0),clearTimeout(m.current),m.current=setTimeout(()=>v(!1),3e3)},[K,U.value,f,o,z]);A.current=R;let{onChange:E,placeholder:q,...H}=U,Y=!U.value;return(0,I.jsxs)("div",{className:`${j.container} ${i??""}`,children:[(0,I.jsx)("div",{className:`${j.checkmark} ${x?j.checkmarkVisible:""}`,children:(0,I.jsxs)("svg",{width:"72",height:"72",viewBox:"0 0 24 24",fill:"none",role:"img","aria-label":"Success",children:[(0,I.jsx)("circle",{cx:"12",cy:"12",r:"12",fill:"#34C759"}),(0,I.jsx)("path",{d:"M7 12.5l3.5 3.5L17 9",stroke:"#000",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round",className:j.checkmarkPath})]})}),(0,I.jsx)(re,{...F}),(0,I.jsxs)("div",{className:j.inputWrapper,onClick:$,children:[(0,I.jsxs)("div",{className:j.editorArea,children:[(0,I.jsxs)("div",{className:j.sizerContent,"aria-hidden":"true",children:[Y&&q?(0,I.jsxs)("span",{className:j.placeholderText,children:[q," "]}):(0,I.jsxs)("span",{className:j.sizerText,children:[P.map((O,_)=>(0,I.jsx)("span",{children:O.value},`${_}-${O.type}`)),P.length===0&&"\xA0"]})," ",(0,I.jsx)(Ee,{pills:s,activePillIndex:0,onSelectPill:c})]}),(0,I.jsx)("textarea",{ref:k,className:j.textarea,rows:1,onChange:E,...H})]}),(0,I.jsx)("button",{type:"button",className:j.submitButton,disabled:!K,onClick:O=>{O.stopPropagation(),R()},"aria-label":"Submit",children:(0,I.jsx)("svg",{width:"18",height:"18",viewBox:"0 0 18 18",fill:"none",role:"img","aria-label":"Submit",children:(0,I.jsx)("path",{d:"M9 14V4M9 4L4 9M9 4L14 9",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})})]})]})});0&&(module.exports={AIAutocomplete,AIAutocompleteDropdown,useAIAutocomplete});
1
+ "use strict";var ye=Object.defineProperty;var Ze=Object.getOwnPropertyDescriptor;var et=Object.getOwnPropertyNames;var tt=Object.prototype.hasOwnProperty;var ot=(e,o)=>{for(var t in o)ye(e,t,{get:o[t],enumerable:!0})},rt=(e,o,t,n)=>{if(o&&typeof o=="object"||typeof o=="function")for(let r of et(o))!tt.call(e,r)&&r!==t&&ye(e,r,{get:()=>o[r],enumerable:!(n=Ze(o,r))||n.enumerable});return e};var nt=e=>rt(ye({},"__esModule",{value:!0}),e);var vt={};ot(vt,{AIAutocomplete:()=>qe,AIAutocompleteDropdown:()=>ne,useAIAutocomplete:()=>ce});module.exports=nt(vt);var D=require("react");var K={};var Se={};var _e={};var Y={};var re=require("react/jsx-runtime");function Te({option:e,isHighlighted:o,onSelect:t,onHighlight:n,id:r}){let a=[Y.item,o?Y.highlighted:"",e.is_tappable?Y.tappable:Y.nonTappable].filter(Boolean).join(" ");return(0,re.jsxs)("div",{id:r,role:"option","aria-selected":o,className:a,tabIndex:e.is_tappable?0:-1,onClick:()=>e.is_tappable&&t(e),onKeyDown:i=>{e.is_tappable&&(i.key==="Enter"||i.key===" ")&&(i.preventDefault(),t(e))},onMouseEnter:n,children:[e.icon?`${e.icon} ${e.text}`:e.text,e.tag&&(0,re.jsx)("span",{className:Y.tag,children:e.tag})]})}var xe=require("react/jsx-runtime");function Me({options:e,activeIndex:o,onSelect:t,onHighlight:n,listboxId:r}){return(0,xe.jsx)("div",{className:_e.grid,children:e.map((a,i)=>(0,xe.jsx)(Te,{option:a,isHighlighted:i===o,onSelect:t,onHighlight:()=>n(i),id:`${r}-option-${i}`},a.text))})}var Pe=require("react/jsx-runtime");function ne({suggestions:e,activeIndex:o,onSelect:t,onHighlight:n,isOpen:r,id:a,className:i}){let m=e[0],g=r&&m&&m.options.length>0;return(0,Pe.jsx)("div",{id:a,role:"listbox",className:`${Se.dropdown} ${g?Se.visible:""} ${i??""}`,onMouseDown:h=>h.preventDefault(),children:m&&m.options.length>0&&(0,Pe.jsx)(Me,{options:m.options,activeIndex:o,onSelect:t,onHighlight:n,listboxId:a})})}var ae={};var ve=require("react/jsx-runtime");function ut(e){return e===0?.4:e===1?.3:.15}function Ee({pills:e,activePillIndex:o,onSelectPill:t}){return(0,ve.jsx)("span",{className:ae.list,children:e.map((n,r)=>(0,ve.jsx)("button",{type:"button",className:`${ae.pill} ${r===o?ae.active:""}`,style:{opacity:ut(r)},onClick:()=>t(r),children:n.text},`${n.type}-${n.text}`))})}var p=require("react");function se(e,o){let t=o.trimStart();if(!t)return e;let n=t.toLowerCase();return e.filter(r=>!r.is_tappable||r.text.toLowerCase().includes(n))}function Z(e,o){let t=o.trim();if(!t)return null;let n=t.toLowerCase();return e.find(r=>r.is_tappable&&r.text.toLowerCase()===n)??null}function Ue(e,o){let t=[],n=0;for(let a of o){let i=e.indexOf(a.text,n);i!==-1&&(i>n&&t.push({type:"text",value:e.slice(n,i)}),t.push({type:"completed",value:a.text,param:a}),n=i+a.text.length)}let r=e.slice(n);return r&&t.push({type:"text",value:r}),t}function Le(e,o){let t=[],n=[],r=0;for(let a of o){let i=e.indexOf(a.text,r);i===-1?n.push(a):(t.push(a),r=i+a.text.length)}return{valid:t,invalid:n}}var M=require("react");var pt="0.1.6",mt=process?.env.MAGICX_API_ENDPOINT||"/api/suggest",Ne=!1;function dt(e){let o=e?.apiKey||process?.env.MAGICX_AI_AUTOCOMPLETE_API_KEY||"";return!o&&!Ne&&(Ne=!0,console.warn("[AIAutocomplete] No API key set (MAGICX_AI_AUTOCOMPLETE_API_KEY). Requests will be sent without an Authorization header.")),o}function ft(e){return e?.authScheme?e.authScheme:process?.env.MAGICX_AUTH_SCHEME==="Basic"?"Basic":"Bearer"}function gt(){return crypto.randomUUID()}function ht(e,o){return{placeholder:e.placeholder,type:e.type,...o&&{text:e.text},kind:e.kind}}async function De(e,o,t){let n=t?.apiConfig,r=dt(n),a=ft(n),i=!t?.maskCompletedText,m=o.find(c=>c.type==="contact"&&c.metadata?.contact_account_count)?.metadata?.contact_account_count,g=typeof m=="number"?m:void 0,h={data:{raw_query:e,completed_params:o.map(c=>ht(c,i)),...g!=null&&{contact_account_count:g}},meta:{request_id:gt(),request_at:new Date().toISOString(),language:typeof navigator<"u"?navigator.language:"en-US",client_version:pt}},d={"Content-Type":"application/json","X-App-Identifier":process?.env.MAGICX_APP_IDENTIFIER||"active-campaign-demo",...n?.headers};r&&(d.Authorization=a==="Basic"?`Basic ${btoa(r)}`:`Bearer ${r}`);let b=await fetch(mt,{method:"POST",headers:d,body:JSON.stringify(h),signal:t?.signal});if(!b.ok)throw new Error(`API error: ${b.status} ${b.statusText}`);return b.json()}function J(e,o){let t=e,n={},r=[];for(let a of o){let i=(n[a.type]??0)+1;n[a.type]=i;let g=`{{${a.type.toUpperCase().replace(/\s+/g,"_")}_${i}}}`,h=t.indexOf(a.text);h!==-1&&(t=t.slice(0,h)+g+t.slice(h+a.text.length)),r.push({...a,placeholder:g})}return{rawQuery:t,completedParams:r}}function $e(e,o){return o?e.map(t=>{let n=o[t.type];if(!n)return t;let r=n("");if(r.length===0)return t;let a=new Set(r.map(m=>m.text)),i=(t.options??[]).filter(m=>!a.has(m.text));return{...t,options:[...r,...i]}}):e}var bt=100,yt=300,St=2;function Fe({textRef:e,suggestionsRef:o,filterBaseRef:t,maskCompletedTextRef:n,apiConfigRef:r,optionOverridesRef:a,onErrorRef:i,setCompletedParams:m,setSuggestions:g,setActiveDropdownIndex:h}){let[d,b]=(0,M.useState)(!1),[c,S]=(0,M.useState)(null),[O,y]=(0,M.useState)(!1),C=(0,M.useRef)(0),L=(0,M.useRef)(null),f=(0,M.useRef)(""),l=(0,M.useCallback)(async(s,u)=>{L.current?.abort();let P=new AbortController;L.current=P;let I=++C.current,R=e.current.length;o.current.some(k=>k.type!=="placeholder")||b(!0),S(null);try{let k=await De(s,u,{maskCompletedText:n.current,signal:P.signal,apiConfig:r.current});if(I!==C.current)return;let $=$e(k.data.suggestions??[],a.current);y(k.data.is_ready??!1),f.current=s;let B=k.data.input??[],E=B[B.length-1],U=e.current;if(E?.state==="in_progress"){let j=U.toLowerCase().lastIndexOf(E.text.toLowerCase());j!==-1?t.current=j:t.current=R}else t.current=R;let F=$.filter(j=>j.type!=="placeholder")[0];if(F){let j=U.slice(t.current),_=Z(F.options,j);_&&(m(z=>[...z,{id:crypto.randomUUID(),placeholder:"",type:F.type,text:_.text,kind:_.kind,suggestionType:F.type,suggestionPlaceholder:F.text,options:F.options,metadata:_.metadata}]),$=$.filter(z=>z!==F))}g($),b(!1),h(-1)}catch(k){if(I===C.current){let $=k instanceof Error?k:new Error(String(k));S($),b(!1),i.current?.($)}}},[e,o,t,n,r,a,i,m,g,h]);return(0,M.useEffect)(()=>(l("",[]),()=>{L.current?.abort()}),[l]),{doFetch:l,isLoading:d,error:c,isReady:O,lastRawQueryRef:f}}function Ke({text:e,completedParams:o,doFetch:t,filterBaseRef:n,skipNextFetchRef:r,suggestionsRef:a,lastRawQueryRef:i}){let m=(0,M.useRef)(null),g=(0,M.useRef)(null),h=(0,M.useRef)(!0);(0,M.useEffect)(()=>{m.current&&clearTimeout(m.current),g.current&&clearTimeout(g.current);let d=b=>{if(r.current)return r.current=!1,!1;if(!e&&o.length===0)return h.current?(t("",[]),!0):(h.current=!0,!1);let c=e.slice(n.current),y=a.current.filter(R=>R.type!=="placeholder")[0],L=(y?se(y.options,c):[]).filter(R=>R.is_tappable),f=y?Z(y.options,c)!==null:!1,l=c.trim().length>0;if(L.length>0&&!f&&l)return!1;let{rawQuery:s,completedParams:u}=J(e,o),P=s.length<i.current.length,I=Math.abs(s.length-i.current.length);return P||I>=b?(t(s,u),!0):!1};return m.current=setTimeout(()=>{d(St)&&g.current&&clearTimeout(g.current)},bt),g.current=setTimeout(()=>d(1),yt),()=>{m.current&&clearTimeout(m.current),g.current&&clearTimeout(g.current)}},[e,o,t,n,r,a,i])}var Ae=require("react");function je({activeDropdownIndex:e,setActiveDropdownIndex:o,filteredOptions:t,selectOption:n,onSubmitRef:r,text:a,completedParams:i,isDropdownOpen:m,hasPlaceholder:g,placeholderText:h,suggestions:d,filterBaseRef:b,columns:c,setText:S,setCompletedParams:O,setSuggestions:y}){let C=(0,Ae.useCallback)(()=>{let f=t.map((s,u)=>s.is_tappable?u:-1).filter(s=>s!==-1),l=Array.from({length:c},()=>[]);for(let s of f)l[s%c].push(s);return l.flat()},[t,c]);return{handleKeyDown:(0,Ae.useCallback)(f=>{let l=C();switch(f.key){case"ArrowDown":{if(f.preventDefault(),l.length===0)return;let s=l.indexOf(e),u=s<l.length-1?s+1:0;o(l[u]);break}case"ArrowUp":{if(f.preventDefault(),l.length===0)return;let s=l.indexOf(e),u=s>0?s-1:l.length-1;o(l[u]);break}case"ArrowRight":{if(e<0)break;if(e%c<c-1){let u=e+1;u<t.length&&t[u]?.is_tappable&&(f.preventDefault(),o(u))}break}case"ArrowLeft":{if(e<0)break;if(e%c>0){let s=e-1;s>=0&&t[s]?.is_tappable&&(f.preventDefault(),o(s))}break}case"Enter":{if(f.preventDefault(),e>=0&&t[e]?.is_tappable)n(t[e]);else if(r.current){let{rawQuery:s,completedParams:u}=J(a,i),P={query:a.trim(),raw_query:s,completed_params:u};r.current(P)}break}case"Tab":{if(e>=0&&t[e]?.is_tappable)f.preventDefault(),n(t[e]);else if(m){let s=t.find(u=>u.is_tappable);s&&(f.preventDefault(),n(s))}else if(!a&&g){f.preventDefault();let s=d.find(u=>u.type==="placeholder");s?(S(h),b.current=h.length,O(u=>[...u,{id:crypto.randomUUID(),placeholder:"",type:s.type,text:h,kind:null,suggestionType:s.type,suggestionPlaceholder:s.text,options:s.options}]),y(u=>u.filter(P=>P!==s))):(S(h),b.current=h.length)}break}case"Escape":o(-1);break}},[e,c,i,t,b,C,g,m,r,h,n,o,O,y,S,d,a]),getTappableIndices:C}}var ie=require("react");function ze({completedParams:e,suggestions:o,setCompletedParams:t,setSuggestions:n,setActiveDropdownIndex:r,filterBaseRef:a,pillTappedRef:i}){let m=(0,ie.useCallback)(d=>{let b=o.filter(y=>y.type!=="placeholder");if(d<0||d>=b.length)return;let c=b[d],S=b.filter((y,C)=>C!==d),O=o.filter(y=>y.type==="placeholder");n([...O,c,...S]),i.current=!0,r(-1)},[o,n,r,i]),g=(0,ie.useCallback)(()=>{if(e.length===0)return;let d=e[e.length-1],b={type:d.suggestionType,text:d.suggestionPlaceholder,required:!0,options:d.options};t(c=>c.slice(0,-1)),n(c=>[b,...c]),r(-1)},[e,t,n,r]),h=(0,ie.useCallback)(d=>{let b={type:d.suggestionType,text:d.suggestionPlaceholder,required:!0,options:d.options};return{apply:c=>{c(S=>{let O=0;for(let y of e){let C=S.indexOf(y.text,O);if(C!==-1){if(y.id===d.id){let L=S.slice(0,C),f=S.slice(C+d.text.length),l=(L+f).replace(/ {2,}/g," ");return a.current=Math.min(a.current,l.length),l}O=C+y.text.length}}return S}),t(S=>S.filter(O=>O.id!==d.id)),n(S=>[b,...S]),r(-1),i.current=!0}}},[e,t,n,r,a,i]);return{setActivePill:m,removeLastParam:g,reEditParam:h}}var xt=0;function Pt(){let e=(0,p.useRef)(null);return e.current===null&&(e.current=`:ac-${++xt}:`),e.current}function ce({onSubmit:e,onError:o,optionOverrides:t,maskCompletedText:n,placeholder:r,apiConfig:a,columns:i=2,eagerSuggestions:m=!0,value:g,completedParams:h,onChange:d,onParamsChange:b}){let c=g!==void 0,S=h!==void 0,[O,y]=(0,p.useState)(""),[C,L]=(0,p.useState)([]),[f,l]=(0,p.useState)([]),[s,u]=(0,p.useState)(-1),P=c?g:O,I=S?h:C,R=(0,p.useRef)(e);R.current=e;let H=(0,p.useRef)(d);H.current=d;let k=(0,p.useRef)(b);k.current=b;let $=(0,p.useRef)(g);$.current=g;let B=(0,p.useRef)(h);B.current=h;let E=(0,p.useCallback)(x=>{if(typeof x=="function")if(c){let A=x($.current??"");H.current?.(A)}else y(A=>{let Q=x(A);return H.current?.(Q),Q});else c||y(x),H.current?.(x)},[c]),U=(0,p.useCallback)(x=>{if(typeof x=="function")if(S){let A=x(B.current??[]);k.current?.(A)}else L(A=>{let Q=x(A);return k.current?.(Q),Q});else S||L(x),k.current?.(x)},[S]),W=(0,p.useRef)(o);W.current=o;let F=(0,p.useRef)(t);F.current=t;let j=(0,p.useRef)(n);j.current=n;let _=(0,p.useRef)(a);_.current=a;let z=(0,p.useRef)(P);z.current=P;let le=(0,p.useRef)(f);le.current=f;let q=(0,p.useRef)(0),ee=(0,p.useRef)(!1),Ce=(0,p.useRef)(!1),ue=Pt(),{doFetch:pe,isLoading:ke,error:Be,isReady:Qe,lastRawQueryRef:me}=Fe({textRef:z,suggestionsRef:le,filterBaseRef:q,maskCompletedTextRef:j,apiConfigRef:_,optionOverridesRef:F,onErrorRef:W,setCompletedParams:U,setSuggestions:l,setActiveDropdownIndex:u});Ke({text:P,completedParams:I,doFetch:pe,filterBaseRef:q,skipNextFetchRef:Ce,suggestionsRef:le,lastRawQueryRef:me});let He=(0,p.useMemo)(()=>Ue(P,I),[P,I]);q.current=Math.min(q.current,P.length);let de=P.slice(q.current),fe=(0,p.useMemo)(()=>f.filter(A=>A.type==="placeholder").map(A=>A.text).join(" ")||r||"",[f,r]),te=(0,p.useMemo)(()=>f.filter(x=>x.type!=="placeholder"),[f]),v=te[0],we=v?t?.[v.type]:void 0,Oe=v?we?we(de.trim()):v.options??[]:[],ge=(0,p.useMemo)(()=>se(Oe,de),[Oe,de]),Ie=fe.length>0,he=!ke&&ge.length>0&&(!!P||ee.current||!Ie),Re=(0,p.useCallback)(x=>{if(!v)return;let A={id:crypto.randomUUID(),placeholder:"",type:v.type,text:x.text,kind:x.kind,suggestionType:v.type,suggestionPlaceholder:v.text,options:v.options,metadata:x.metadata},Q=q.current,N=z.current.slice(0,Q);if(N.length>0&&!N.endsWith(" ")){let T=N.split(/\s+/).pop()??"";T&&x.text.toLowerCase().startsWith(T.toLowerCase())&&(N=N.slice(0,N.length-T.length))}let be=N.length>0&&N[N.length-1]!==" ",G=N+(be?" ":"")+x.text+" ";E(G),q.current=G.length,U(T=>[...T,A]),ee.current=!1,u(-1);let V=te.length-1;m&&V>0?(l(T=>T.filter(X=>X!==v)),Ce.current=!0):l(T=>T.filter(X=>X.type==="placeholder"))},[v,te,m,E,U]),Ve=(0,p.useCallback)(x=>{let A=x.target.value,N=A.length>0&&!x.nativeEvent?.isComposing&&A[0]!==A[0].toUpperCase()?A[0].toUpperCase()+A.slice(1):A;E(N),ee.current=!1,u(-1);let{valid:be,invalid:G}=Le(N,I);if(G.length>0){U(()=>be);for(let V of G)l(T=>[{type:V.suggestionType,text:V.suggestionPlaceholder,required:!0,options:V.options},...T])}if(v&&G.length===0){let V=N.slice(q.current),T=Z(v.options,V);T&&(U(X=>[...X,{id:crypto.randomUUID(),placeholder:"",type:v.type,text:T.text,kind:T.kind,suggestionType:v.type,suggestionPlaceholder:v.text,options:v.options,metadata:T.metadata}]),l(X=>X.filter(Je=>Je!==v)))}},[I,v,E,U]),{handleKeyDown:Xe}=je({activeDropdownIndex:s,setActiveDropdownIndex:u,filteredOptions:ge,selectOption:Re,onSubmitRef:R,text:P,completedParams:I,isDropdownOpen:he,hasPlaceholder:Ie,placeholderText:fe,suggestions:f,filterBaseRef:q,columns:i,setText:E,setCompletedParams:U,setSuggestions:l}),oe=ze({completedParams:I,suggestions:f,setCompletedParams:U,setSuggestions:l,setActiveDropdownIndex:u,filterBaseRef:q,pillTappedRef:ee}),We=(0,p.useCallback)(x=>{oe.reEditParam(x).apply(E)},[oe,E]),Ge=(0,p.useCallback)(()=>{E(""),U(()=>[]),l([]),u(-1),q.current=0,me.current="",pe("",[])},[pe,E,U,me]),Ye=s>=0?`${ue}-option-${s}`:void 0;return{completedParams:I,suggestionPills:te,setActivePill:oe.setActivePill,removeLastParam:oe.removeLastParam,reEditParam:We,segments:He,suggestions:f,activeIndex:s,isReady:Qe,isLoading:ke,error:Be,inputProps:{value:P,placeholder:fe||void 0,onChange:Ve,onKeyDown:Xe,role:"combobox","aria-expanded":he,"aria-activedescendant":Ye,"aria-autocomplete":"list","aria-controls":ue},reset:Ge,dropdownProps:{suggestions:v?[{...v,options:ge}]:[],activeIndex:s,onSelect:Re,onHighlight:u,isOpen:he,id:ue}}}var w=require("react/jsx-runtime"),qe=(0,D.forwardRef)(function({onSubmit:o,onError:t,optionOverrides:n,maskCompletedText:r,placeholder:a,className:i,apiConfig:m,columns:g,eagerSuggestions:h,value:d,completedParams:b,onChange:c,onParamsChange:S},O){let y=(0,D.useRef)(null),[C,L]=(0,D.useState)(!1),f=(0,D.useRef)(()=>{}),l=(0,D.useRef)(void 0);(0,D.useEffect)(()=>(y.current?.focus(),()=>clearTimeout(l.current)),[]);let{completedParams:s,suggestionPills:u,setActivePill:P,segments:I,inputProps:R,dropdownProps:H,reset:k}=ce({onSubmit:_=>f.current(_),onError:t,optionOverrides:n,maskCompletedText:r,placeholder:a,apiConfig:m,columns:g,eagerSuggestions:h,value:d,completedParams:b,onChange:c,onParamsChange:S});(0,D.useImperativeHandle)(O,()=>({focus:()=>y.current?.focus(),reset:k}),[k]);let $=()=>{y.current?.focus()},B=!!R.value||s.length>0,E=(0,D.useCallback)(()=>{if(!B)return;let{rawQuery:_,completedParams:z}=J(R.value,s);o({query:R.value.trim(),raw_query:_,completed_params:z}),k(),L(!0),clearTimeout(l.current),l.current=setTimeout(()=>L(!1),3e3)},[B,R.value,s,o,k]);f.current=E;let{onChange:U,placeholder:W,...F}=R,j=!R.value;return(0,w.jsxs)("div",{className:`${K.container} ${i??""}`,children:[(0,w.jsx)("div",{className:`${K.checkmark} ${C?K.checkmarkVisible:""}`,children:(0,w.jsxs)("svg",{width:"72",height:"72",viewBox:"0 0 24 24",fill:"none",role:"img","aria-label":"Success",children:[(0,w.jsx)("circle",{cx:"12",cy:"12",r:"12",fill:"#34C759"}),(0,w.jsx)("path",{d:"M7 12.5l3.5 3.5L17 9",stroke:"#000",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round",className:K.checkmarkPath})]})}),(0,w.jsx)(ne,{...H}),(0,w.jsxs)("div",{className:K.inputWrapper,onClick:$,children:[(0,w.jsxs)("div",{className:K.editorArea,children:[(0,w.jsxs)("div",{className:K.sizerContent,"aria-hidden":"true",children:[j&&W?(0,w.jsxs)("span",{className:K.placeholderText,children:[W," "]}):(0,w.jsxs)("span",{className:K.sizerText,children:[I.map((_,z)=>(0,w.jsx)("span",{children:_.value},`${z}-${_.type}`)),I.length===0&&"\xA0"]})," ",(0,w.jsx)(Ee,{pills:u,activePillIndex:0,onSelectPill:P})]}),(0,w.jsx)("textarea",{ref:y,className:K.textarea,rows:1,onChange:U,...F})]}),(0,w.jsx)("button",{type:"button",className:K.submitButton,disabled:!B,onClick:_=>{_.stopPropagation(),E()},"aria-label":"Submit",children:(0,w.jsx)("svg",{width:"18",height:"18",viewBox:"0 0 18 18",fill:"none",role:"img","aria-label":"Submit",children:(0,w.jsx)("path",{d:"M9 14V4M9 4L4 9M9 4L14 9",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})})]})]})});0&&(module.exports={AIAutocomplete,AIAutocompleteDropdown,useAIAutocomplete});
2
2
  //# sourceMappingURL=index.js.map