@magicx-eng/ai-autocomplete-react 0.1.5 → 0.1.7
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 +71 -23
- package/dist/index.d.mts +8 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -8
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
|
|
26
|
+
React 17 or later:
|
|
27
27
|
|
|
28
28
|
```bash
|
|
29
29
|
pnpm add react react-dom
|
|
@@ -41,7 +41,7 @@ import { AIAutocomplete } from "@magicx-eng/ai-autocomplete-react";
|
|
|
41
41
|
function App() {
|
|
42
42
|
return (
|
|
43
43
|
<AIAutocomplete
|
|
44
|
-
apiConfig={{ apiKey: "your_api_key" }}
|
|
44
|
+
apiConfig={{ endpoint: "https://api.example.com/ac/suggest", apiKey: "your_api_key" }}
|
|
45
45
|
onSubmit={(result) => {
|
|
46
46
|
console.log(result.query); // "Create a email"
|
|
47
47
|
console.log(result.raw_query); // "Create a {{TASK_1}}"
|
|
@@ -73,7 +73,7 @@ function App() {
|
|
|
73
73
|
reset,
|
|
74
74
|
} = useAIAutocomplete({
|
|
75
75
|
onSubmit: (result) => handleMySubmit(result),
|
|
76
|
-
apiConfig: { apiKey: "your_api_key" },
|
|
76
|
+
apiConfig: { endpoint: "https://api.example.com/ac/suggest", apiKey: "your_api_key" },
|
|
77
77
|
});
|
|
78
78
|
|
|
79
79
|
return (
|
|
@@ -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). |
|
|
@@ -142,6 +143,7 @@ The full component. Owns the input, pills, dropdown, and keyboard navigation.
|
|
|
142
143
|
|
|
143
144
|
| Field | Type | Description |
|
|
144
145
|
|---|---|---|
|
|
146
|
+
| `endpoint?` | `string` | Full URL for the suggest endpoint (e.g. `"https://api.example.com/ac/suggest"`). Falls back to `MAGICX_API_ENDPOINT` env var, then `"/ac/suggest"`. |
|
|
145
147
|
| `apiKey?` | `string` | API key for Authorization header. Falls back to `MAGICX_AI_AUTOCOMPLETE_API_KEY` env var. |
|
|
146
148
|
| `authScheme?` | `"Bearer" \| "Basic"` | Auth header scheme. Default: `"Bearer"`. |
|
|
147
149
|
| `headers?` | `Record<string, string>` | Additional headers merged into every request. |
|
|
@@ -164,39 +166,85 @@ Accepts the same props as `<AIAutocomplete />` (except `className` and `ref`), w
|
|
|
164
166
|
|
|
165
167
|
#### Return Value
|
|
166
168
|
|
|
169
|
+
**State**
|
|
170
|
+
|
|
171
|
+
| Field | Type | Description |
|
|
172
|
+
|---|---|---|
|
|
173
|
+
| `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. |
|
|
174
|
+
| `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`. |
|
|
175
|
+
| `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. |
|
|
176
|
+
| `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. |
|
|
177
|
+
| `activeIndex` | `number` | Index of the currently keyboard-highlighted option in the dropdown. `-1` when no option is highlighted. Automatically managed by arrow keys. |
|
|
178
|
+
| `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. |
|
|
179
|
+
| `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. |
|
|
180
|
+
| `error` | `Error \| null` | The most recent fetch error, or `null` if the last fetch succeeded. Cleared on every new fetch attempt. |
|
|
181
|
+
|
|
182
|
+
**Actions**
|
|
183
|
+
|
|
167
184
|
| Field | Type | Description |
|
|
168
185
|
|---|---|---|
|
|
169
|
-
| `
|
|
170
|
-
| `
|
|
171
|
-
| `
|
|
172
|
-
| `
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
|
177
|
-
|
|
178
|
-
| `
|
|
179
|
-
| `
|
|
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 />`. |
|
|
186
|
+
| `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. |
|
|
187
|
+
| `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. |
|
|
188
|
+
| `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. |
|
|
189
|
+
| `reset` | `() => void` | Clear all text, completed params, and suggestions, then re-fetch initial suggestions from the server. Returns the component to its mount state. |
|
|
190
|
+
|
|
191
|
+
**Spread Props**
|
|
192
|
+
|
|
193
|
+
| Field | Type | Description |
|
|
194
|
+
|---|---|---|
|
|
195
|
+
| `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. |
|
|
196
|
+
| `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
197
|
|
|
184
198
|
### `<AIAutocompleteDropdown />`
|
|
185
199
|
|
|
186
200
|
The dropdown component for Tier 2 headless integration. Spread `dropdownProps` from the hook.
|
|
187
201
|
|
|
202
|
+
| Prop | Type | Description |
|
|
203
|
+
|---|---|---|
|
|
204
|
+
| `suggestions` | `Suggestion[]` | Suggestions to display (from `dropdownProps`). |
|
|
205
|
+
| `activeIndex` | `number` | Currently highlighted option index. |
|
|
206
|
+
| `onSelect` | `(option: SuggestionOption) => void` | Called when an option is selected. |
|
|
207
|
+
| `onHighlight` | `(index: number) => void` | Called when an option is highlighted (mouse hover). |
|
|
208
|
+
| `isOpen` | `boolean` | Whether the dropdown is visible. |
|
|
209
|
+
| `id` | `string` | Listbox ID for ARIA. |
|
|
210
|
+
| `className?` | `string` | CSS class applied to the dropdown. |
|
|
211
|
+
|
|
212
|
+
### `Suggestion`
|
|
213
|
+
|
|
214
|
+
Represents an unfilled parameter slot. Rendered as a pill in Tier 1, or available via `suggestionPills` in Tier 2.
|
|
215
|
+
|
|
216
|
+
| Field | Type | Description |
|
|
217
|
+
|---|---|---|
|
|
218
|
+
| `type` | `string` | Suggestion type identifier (e.g. `"task"`, `"goal"`, `"contact"`). Used as the key for `optionOverrides`. |
|
|
219
|
+
| `text` | `string` | Display text for the pill (e.g. `"type"`, `"goal"`). |
|
|
220
|
+
| `required` | `boolean` | Whether this suggestion must be filled before submission. |
|
|
221
|
+
| `options` | `SuggestionOption[]` | Available options the user can select from. |
|
|
222
|
+
|
|
223
|
+
### `SuggestionOption`
|
|
224
|
+
|
|
225
|
+
An individual option within a suggestion's dropdown.
|
|
226
|
+
|
|
227
|
+
| Field | Type | Description |
|
|
228
|
+
|---|---|---|
|
|
229
|
+
| `text` | `string` | Display text for the option. |
|
|
230
|
+
| `icon?` | `string` | Icon shown before the text (e.g. emoji). |
|
|
231
|
+
| `tag?` | `string` | Label shown after the text in smaller, muted style. |
|
|
232
|
+
| `is_tappable` | `boolean` | Whether the option can be selected. Non-tappable options are always-visible hints that cannot be chosen. |
|
|
233
|
+
| `kind` | `string \| null` | Category of the option (e.g. `"automation"`, `"email"`), or `null`. Passed through to `CompletedParam` on selection. |
|
|
234
|
+
| `metadata?` | `Record<string, unknown>` | Arbitrary metadata passed through with the selection. Available on the completed param after the user selects this option. |
|
|
235
|
+
|
|
188
236
|
## CSS Customization
|
|
189
237
|
|
|
190
238
|
The component uses CSS Modules with customizable CSS variables. Override them on a parent element:
|
|
191
239
|
|
|
192
240
|
```css
|
|
193
241
|
.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: #
|
|
198
|
-
--ac-color-background-default: #fff;
|
|
199
|
-
--ac-color-background-supportive: #
|
|
242
|
+
--ac-color-border-default: #ccc; /* Input border */
|
|
243
|
+
--ac-color-text-default: #333; /* Input text, caret, submit button bg, highlighted option */
|
|
244
|
+
--ac-color-text-muted: #999; /* Placeholder, pill text, option text */
|
|
245
|
+
--ac-color-bg-default: #000; /* Submit button icon color (foreground on button) */
|
|
246
|
+
--ac-color-background-default: #fff; /* Dropdown background */
|
|
247
|
+
--ac-color-background-supportive: #eee; /* Pill background */
|
|
200
248
|
}
|
|
201
249
|
```
|
|
202
250
|
|
package/dist/index.d.mts
CHANGED
|
@@ -44,6 +44,7 @@ interface AIAutocompleteHandle {
|
|
|
44
44
|
reset: () => void;
|
|
45
45
|
}
|
|
46
46
|
interface APIConfig {
|
|
47
|
+
endpoint?: string;
|
|
47
48
|
apiKey?: string;
|
|
48
49
|
authScheme?: "Bearer" | "Basic";
|
|
49
50
|
headers?: Record<string, string>;
|
|
@@ -58,6 +59,9 @@ interface AIAutocompleteProps {
|
|
|
58
59
|
className?: string;
|
|
59
60
|
apiConfig?: APIConfig;
|
|
60
61
|
columns?: number;
|
|
62
|
+
/** When true (default), show cached next suggestions immediately after option select.
|
|
63
|
+
* When false, clear suggestions and wait for the server response. */
|
|
64
|
+
eagerSuggestions?: boolean;
|
|
61
65
|
value?: string;
|
|
62
66
|
completedParams?: CompletedParamState[];
|
|
63
67
|
onChange?: (value: string) => void;
|
|
@@ -76,6 +80,9 @@ interface UseAIAutocompleteOptions {
|
|
|
76
80
|
placeholder?: string;
|
|
77
81
|
apiConfig?: APIConfig;
|
|
78
82
|
columns?: number;
|
|
83
|
+
/** When true (default), show cached next suggestions immediately after option select.
|
|
84
|
+
* When false, clear suggestions and wait for the server response. */
|
|
85
|
+
eagerSuggestions?: boolean;
|
|
79
86
|
value?: string;
|
|
80
87
|
completedParams?: CompletedParamState[];
|
|
81
88
|
onChange?: (value: string) => void;
|
|
@@ -121,6 +128,6 @@ declare const AIAutocomplete: react.ForwardRefExoticComponent<AIAutocompleteProp
|
|
|
121
128
|
|
|
122
129
|
declare function AIAutocompleteDropdown({ suggestions, activeIndex, onSelect, onHighlight, isOpen, id, className, }: AIAutocompleteDropdownProps): react_jsx_runtime.JSX.Element;
|
|
123
130
|
|
|
124
|
-
declare function useAIAutocomplete({ onSubmit, onError, optionOverrides, maskCompletedText, placeholder: customPlaceholder, apiConfig, columns, value: controlledValue, completedParams: controlledParams, onChange: onChangeProp, onParamsChange, }: UseAIAutocompleteOptions): UseAIAutocompleteReturn;
|
|
131
|
+
declare function useAIAutocomplete({ onSubmit, onError, optionOverrides, maskCompletedText, placeholder: customPlaceholder, apiConfig, columns, eagerSuggestions, value: controlledValue, completedParams: controlledParams, onChange: onChangeProp, onParamsChange, }: UseAIAutocompleteOptions): UseAIAutocompleteReturn;
|
|
125
132
|
|
|
126
133
|
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
|
@@ -44,6 +44,7 @@ interface AIAutocompleteHandle {
|
|
|
44
44
|
reset: () => void;
|
|
45
45
|
}
|
|
46
46
|
interface APIConfig {
|
|
47
|
+
endpoint?: string;
|
|
47
48
|
apiKey?: string;
|
|
48
49
|
authScheme?: "Bearer" | "Basic";
|
|
49
50
|
headers?: Record<string, string>;
|
|
@@ -58,6 +59,9 @@ interface AIAutocompleteProps {
|
|
|
58
59
|
className?: string;
|
|
59
60
|
apiConfig?: APIConfig;
|
|
60
61
|
columns?: number;
|
|
62
|
+
/** When true (default), show cached next suggestions immediately after option select.
|
|
63
|
+
* When false, clear suggestions and wait for the server response. */
|
|
64
|
+
eagerSuggestions?: boolean;
|
|
61
65
|
value?: string;
|
|
62
66
|
completedParams?: CompletedParamState[];
|
|
63
67
|
onChange?: (value: string) => void;
|
|
@@ -76,6 +80,9 @@ interface UseAIAutocompleteOptions {
|
|
|
76
80
|
placeholder?: string;
|
|
77
81
|
apiConfig?: APIConfig;
|
|
78
82
|
columns?: number;
|
|
83
|
+
/** When true (default), show cached next suggestions immediately after option select.
|
|
84
|
+
* When false, clear suggestions and wait for the server response. */
|
|
85
|
+
eagerSuggestions?: boolean;
|
|
79
86
|
value?: string;
|
|
80
87
|
completedParams?: CompletedParamState[];
|
|
81
88
|
onChange?: (value: string) => void;
|
|
@@ -121,6 +128,6 @@ declare const AIAutocomplete: react.ForwardRefExoticComponent<AIAutocompleteProp
|
|
|
121
128
|
|
|
122
129
|
declare function AIAutocompleteDropdown({ suggestions, activeIndex, onSelect, onHighlight, isOpen, id, className, }: AIAutocompleteDropdownProps): react_jsx_runtime.JSX.Element;
|
|
123
130
|
|
|
124
|
-
declare function useAIAutocomplete({ onSubmit, onError, optionOverrides, maskCompletedText, placeholder: customPlaceholder, apiConfig, columns, value: controlledValue, completedParams: controlledParams, onChange: onChangeProp, onParamsChange, }: UseAIAutocompleteOptions): UseAIAutocompleteReturn;
|
|
131
|
+
declare function useAIAutocomplete({ onSubmit, onError, optionOverrides, maskCompletedText, placeholder: customPlaceholder, apiConfig, columns, eagerSuggestions, value: controlledValue, completedParams: controlledParams, onChange: onChangeProp, onParamsChange, }: UseAIAutocompleteOptions): UseAIAutocompleteReturn;
|
|
125
132
|
|
|
126
133
|
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 Ee({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)(Ee,{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 Me({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 E=require("react");var pt="0.1.7",mt="/ac/suggest",Ne=!1;function dt(e){let o=e?.apiKey||""||"";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:""==="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":"active-campaign-demo",...n?.headers};r&&(d.Authorization=a==="Basic"?`Basic ${btoa(r)}`:`Bearer ${r}`);let b=await fetch(n?.endpoint||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 Fe(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 $e({textRef:e,suggestionsRef:o,filterBaseRef:t,maskCompletedTextRef:n,apiConfigRef:r,optionOverridesRef:a,onErrorRef:i,setCompletedParams:m,setSuggestions:g,setActiveDropdownIndex:h}){let[d,b]=(0,E.useState)(!1),[c,S]=(0,E.useState)(null),[O,y]=(0,E.useState)(!1),C=(0,E.useRef)(0),L=(0,E.useRef)(null),f=(0,E.useRef)(""),l=(0,E.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 F=Fe(k.data.suggestions??[],a.current);y(k.data.is_ready??!1),f.current=s;let B=k.data.input??[],M=B[B.length-1],U=e.current;if(M?.state==="in_progress"){let j=U.toLowerCase().lastIndexOf(M.text.toLowerCase());j!==-1?t.current=j:t.current=R}else t.current=R;let $=F.filter(j=>j.type!=="placeholder")[0];if($){let j=U.slice(t.current),_=Z($.options,j);_&&(m(z=>[...z,{id:crypto.randomUUID(),placeholder:"",type:$.type,text:_.text,kind:_.kind,suggestionType:$.type,suggestionPlaceholder:$.text,options:$.options,metadata:_.metadata}]),F=F.filter(z=>z!==$))}g(F),b(!1),h(-1)}catch(k){if(I===C.current){let F=k instanceof Error?k:new Error(String(k));S(F),b(!1),i.current?.(F)}}},[e,o,t,n,r,a,i,m,g,h]);return(0,E.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,E.useRef)(null),g=(0,E.useRef)(null),h=(0,E.useRef)(!0);(0,E.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 F=(0,p.useRef)(g);F.current=g;let B=(0,p.useRef)(h);B.current=h;let M=(0,p.useCallback)(x=>{if(typeof x=="function")if(c){let A=x(F.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 $=(0,p.useRef)(t);$.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}=$e({textRef:z,suggestionsRef:le,filterBaseRef:q,maskCompletedTextRef:j,apiConfigRef:_,optionOverridesRef:$,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+" ";M(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,M,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;M(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,M,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:M,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(M)},[oe,M]),Ge=(0,p.useCallback)(()=>{M(""),U(()=>[]),l([]),u(-1),q.current=0,me.current="",pe("",[])},[pe,M,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 F=()=>{y.current?.focus()},B=!!R.value||s.length>0,M=(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=M;let{onChange:U,placeholder:W,...$}=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:F,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)(Me,{pills:u,activePillIndex:0,onSelectPill:P})]}),(0,w.jsx)("textarea",{ref:y,className:K.textarea,rows:1,onChange:U,...$})]}),(0,w.jsx)("button",{type:"button",className:K.submitButton,disabled:!B,onClick:_=>{_.stopPropagation(),M()},"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
|