@magicx-eng/ai-autocomplete-react 0.1.37 → 0.1.38

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/AIAutocomplete.tsx","css-module:/Users/saharshv/MagicX/ai-autocomplete-react/src/AIAutocomplete.module.css.js","css-module:/Users/saharshv/MagicX/ai-autocomplete-react/src/AIAutocompleteDropdown.module.css.js","css-module:/Users/saharshv/MagicX/ai-autocomplete-react/src/components/PillList.module.css.js","../src/components/PillList.tsx","../src/components/SuggestionGrid.tsx","css-module:/Users/saharshv/MagicX/ai-autocomplete-react/src/components/SuggestionGrid.module.css.js","../src/components/SuggestionItem.tsx","css-module:/Users/saharshv/MagicX/ai-autocomplete-react/src/components/SuggestionItem.module.css.js","../src/AIAutocompleteDropdown.tsx","plain-css:/Users/saharshv/MagicX/ai-autocomplete-react/src/appearance.css.js","../src/hooks/useAIAutocomplete.ts","../src/utils/buildQuery.ts","../src/utils/filtering.ts","../src/utils/modeController.ts","../src/utils/segments.ts","../src/utils/tokenManager.ts","../src/utils/auth.ts","../src/utils/telemetry.ts","../src/utils/api.ts","../src/utils/overrides.ts","../src/core/controllers/fetchController.ts","../src/core/controllers/keyboardController.ts","../src/core/controllers/pillsController.ts","../src/core/render/renderPills.ts","../src/core/render/renderDropdown.ts","../src/core/render/renderDropdownOnly.ts","../src/core/render/renderSegments.ts","../src/core/render/renderInput.ts","../src/core/state.ts","../src/core/styleInjector.ts","../src/core/AIAutocomplete.ts"],"sourcesContent":["import { forwardRef, useCallback, useEffect, useImperativeHandle, useRef } from \"react\";\nimport styles from \"./AIAutocomplete.module.css\";\nimport { AIAutocompleteDropdown } from \"./AIAutocompleteDropdown\";\nimport \"./appearance.css\";\nimport { PillList } from \"./components/PillList\";\nimport { useAIAutocomplete } from \"./hooks/useAIAutocomplete\";\nimport type {\n AIAutocompleteHandle,\n AIAutocompleteProps,\n AppearanceMode,\n AutocompleteResult,\n} from \"./types\";\nimport { buildQuery } from \"./utils/buildQuery\";\nimport { ModeController } from \"./utils/modeController\";\n\nfunction resolveInitialMode(mode: AppearanceMode): \"light\" | \"dark\" {\n if (mode !== \"auto\") return mode;\n if (typeof window === \"undefined\") return \"dark\";\n return window.matchMedia(\"(prefers-color-scheme: dark)\").matches ? \"dark\" : \"light\";\n}\n\nexport const AIAutocomplete = forwardRef<AIAutocompleteHandle, AIAutocompleteProps>(\n function AIAutocomplete(\n {\n onSubmit,\n onError,\n optionOverrides,\n maskCompletedText,\n className,\n apiConfig,\n columns,\n pillPlacement = \"inline\",\n mode = \"auto\",\n optionsPosition = \"below\",\n animations = true,\n dropdownTrigger,\n closeDropdownOnBlur,\n autoFocus = true,\n onFocus,\n onBlur,\n value,\n completedParams: controlledParams,\n onChange: onChangeProp,\n onParamsChange,\n submitButton,\n },\n ref,\n ) {\n const containerRef = useRef<HTMLDivElement>(null);\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n // Render-phase ref assignment — matches the pattern in useAIAutocomplete.ts\n const handleSubmitRef = useRef<(result: AutocompleteResult) => void>(() => {});\n const modeControllerRef = useRef<ModeController | null>(null);\n\n // ModeController — keeps data-mode updated for live prefers-color-scheme changes\n // Initial data-mode is set synchronously in JSX via resolveInitialMode()\n useEffect(() => {\n const el = containerRef.current;\n if (!el) return;\n if (modeControllerRef.current) {\n modeControllerRef.current.setMode(mode);\n } else {\n modeControllerRef.current = new ModeController(el, mode);\n }\n return () => {\n modeControllerRef.current?.destroy();\n modeControllerRef.current = null;\n };\n }, [mode]);\n\n const {\n completedParams,\n suggestionPills,\n setActivePill,\n segments,\n newParamId,\n clearNewParamId,\n inputProps,\n dropdownProps,\n reset,\n } = useAIAutocomplete({\n onSubmit: (result) => handleSubmitRef.current(result),\n onError,\n optionOverrides,\n maskCompletedText,\n apiConfig,\n columns,\n dropdownTrigger,\n closeDropdownOnBlur,\n onFocus,\n onBlur,\n value,\n completedParams: controlledParams,\n onChange: onChangeProp,\n onParamsChange,\n source: \"full-sdk\",\n });\n\n // Auto-focus on mount. Depends on inputProps.onFocus so we re-run once the\n // hook's instance is ready — otherwise the focus event fires before the\n // real handler is wired and the auto-trigger dropdown stays closed.\n const focusHandler = inputProps.onFocus;\n useEffect(() => {\n if (!autoFocus) return;\n const ta = textareaRef.current;\n if (!ta) return;\n if (document.activeElement === ta) {\n focusHandler();\n } else {\n ta.focus();\n }\n }, [focusHandler, autoFocus]);\n\n // Clear shimmer after animation completes\n useEffect(() => {\n if (!newParamId) return;\n const timeoutId = window.setTimeout(() => clearNewParamId(), 650);\n return () => window.clearTimeout(timeoutId);\n }, [newParamId, clearNewParamId]);\n\n useImperativeHandle(\n ref,\n () => ({\n focus: () => textareaRef.current?.focus(),\n blur: () => textareaRef.current?.blur(),\n reset,\n setMode: (m) => modeControllerRef.current?.setMode(m),\n }),\n [reset],\n );\n\n const handleContainerClick = () => {\n textareaRef.current?.focus();\n };\n\n const canSubmit = !!inputProps.value || completedParams.length > 0;\n\n const handleSubmit = useCallback(() => {\n if (!canSubmit) return;\n const { rawQuery, completedParams: finalParams } = buildQuery(\n inputProps.value,\n completedParams,\n );\n onSubmit({\n query: inputProps.value.trim(),\n raw_query: rawQuery,\n completed_params: finalParams,\n });\n reset();\n }, [canSubmit, inputProps.value, completedParams, onSubmit, reset]);\n\n handleSubmitRef.current = handleSubmit;\n\n const { onChange, placeholder: inputPlaceholder, ...restProps } = inputProps;\n const isEmpty = !inputProps.value;\n\n const showInlinePills = pillPlacement === \"inline\";\n const showDropdownPills = pillPlacement === \"dropdown\";\n\n return (\n <div\n ref={containerRef}\n className={`magicx-aia ${styles.container} ${className ?? \"\"}`}\n data-pill-placement={pillPlacement}\n data-options-position={optionsPosition}\n data-animations={animations ? \"on\" : \"off\"}\n data-mode={resolveInitialMode(mode)}\n >\n <AIAutocompleteDropdown {...dropdownProps} showPills={showDropdownPills} />\n {/* biome-ignore lint/a11y/useKeyWithClickEvents: container click delegates to textarea focus */}\n {/* biome-ignore lint/a11y/noStaticElementInteractions: wrapper delegates focus to textarea */}\n <div className={styles.inputWrapper} onClick={handleContainerClick}>\n <div className={styles.editorArea} data-aia-editor=\"\">\n <div className={styles.sizerContent} aria-hidden=\"true\">\n {isEmpty && inputPlaceholder ? (\n <span className={styles.placeholderText}>{inputPlaceholder} </span>\n ) : (\n <span\n className={`${styles.sizerText} ${newParamId ? styles.sizerTextVisible : \"\"}`}\n >\n {segments.map((seg, i) => {\n const isNew = seg.type === \"completed\" && seg.param.id === newParamId;\n if (isNew) {\n const cls = `${styles.shimmerRevealed} ${styles.shimmerSweep}`;\n return (\n // biome-ignore lint/suspicious/noArrayIndexKey: segments are positional and don't reorder\n <span key={`${i}-${seg.type}`} className={cls}>\n {seg.value}\n </span>\n );\n }\n return (\n // biome-ignore lint/suspicious/noArrayIndexKey: segments are positional and don't reorder\n <span key={`${i}-${seg.type}`}>{seg.value}</span>\n );\n })}\n {segments.length === 0 && \"\\u00A0\"}\n </span>\n )}{\" \"}\n {showInlinePills && (\n <PillList\n pills={suggestionPills}\n activePillIndex={0}\n onSelectPill={setActivePill}\n />\n )}\n </div>\n <textarea\n ref={textareaRef}\n data-aia-textarea=\"\"\n className={`${styles.textarea} ${newParamId ? styles.textareaHidden : \"\"}`}\n rows={1}\n onChange={onChange}\n {...restProps}\n />\n </div>\n {submitButton === null ? null : submitButton === undefined ? (\n <button\n type=\"button\"\n data-aia-submit=\"\"\n className={styles.submitButton}\n disabled={!canSubmit}\n onClick={(e) => {\n e.stopPropagation();\n handleSubmit();\n }}\n aria-label=\"Submit\"\n >\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 18 18\"\n fill=\"none\"\n role=\"img\"\n aria-label=\"Submit\"\n >\n <path\n d=\"M9 14V4M9 4L4 9M9 4L14 9\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n </button>\n ) : (\n // biome-ignore lint/a11y/useKeyWithClickEvents: consumer-provided element handles its own keyboard interaction\n // biome-ignore lint/a11y/noStaticElementInteractions: transparent slot — click bubbles from consumer's element\n <span\n data-aia-submit=\"\"\n className={styles.submitSlot}\n onClick={(e) => {\n if (!canSubmit) return;\n e.stopPropagation();\n handleSubmit();\n }}\n >\n {submitButton}\n </span>\n )}\n </div>\n </div>\n );\n },\n);\n","if (typeof document !== \"undefined\" && !document.getElementById(\"ac-style-cc65f4cc\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-cc65f4cc\";\n s.textContent = `.AIAutocomplete-module_container_KKjFU {\n position: relative;\n font-family: \"IBM Plex Sans\", sans-serif;\n container-type: inline-size;\n}\n\n.AIAutocomplete-module_inputWrapper_FLq1b {\n padding: 20px;\n border: 1px solid var(--aia-color-border-default, #9ea5b2);\n border-radius: 23px;\n background: transparent;\n overflow: hidden;\n display: flex;\n align-items: center;\n gap: 0px;\n}\n\n.AIAutocomplete-module_editorArea_7rBWq {\n position: relative;\n flex: 1;\n min-width: 0;\n}\n\n.AIAutocomplete-module_sizerContent_DQgmV {\n position: relative;\n z-index: 1;\n pointer-events: none;\n white-space: pre-wrap;\n word-break: break-word;\n font-family: inherit;\n font-size: var(--aia-written-text-font-size, 19px);\n line-height: 38px;\n}\n\n.AIAutocomplete-module_sizerText_iZIMK {\n color: transparent;\n}\n\n.AIAutocomplete-module_sizerTextVisible_HR-5h {\n color: var(--aia-written-text-color, var(--aia-color-text-default, #fff));\n font-size: var(--aia-written-text-font-size, inherit);\n}\n\n.AIAutocomplete-module_textareaHidden_UayJt {\n color: transparent !important;\n}\n\n.AIAutocomplete-module_placeholderText_K3ayy {\n color: var(--aia-color-text-muted, #c1c4cb);\n opacity: 0.4;\n}\n\n.AIAutocomplete-module_textarea_eyn6A {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n padding: 0;\n border: none;\n background: transparent;\n color: var(--aia-written-text-color, var(--aia-color-text-default, #fff));\n caret-color: var(\n --aia-caret-color,\n var(--aia-written-text-color, var(--aia-color-text-default, #fff))\n );\n font-family: inherit;\n font-size: var(--aia-written-text-font-size, 19px);\n line-height: 38px;\n white-space: pre-wrap;\n word-break: break-word;\n outline: none;\n resize: none;\n overflow: hidden;\n}\n\n.AIAutocomplete-module_textarea_eyn6A::placeholder {\n color: var(--aia-color-text-muted, #c1c4cb);\n}\n\n.AIAutocomplete-module_submitButton_sl1Mi {\n flex-shrink: 0;\n width: 36px;\n height: 36px;\n border-radius: 50%;\n border: none;\n background: var(--aia-submit-bg, var(--aia-color-text-default, #fff));\n color: var(--aia-submit-color, var(--aia-color-bg-default, #000));\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n transition: opacity 0.2s ease;\n}\n\n.AIAutocomplete-module_submitButton_sl1Mi:hover {\n opacity: 0.85;\n}\n\n.AIAutocomplete-module_submitSlot_GhuCM {\n display: contents;\n}\n\n/* Text shimmer on newly added completed param.\n The sizer sits above the textarea (z-index: 1). Normally sizer text is\n transparent and the textarea shows the real text. During the shimmer, we\n make this span visible with a moving gradient clipped to the text shape,\n so the shimmer renders on top of the textarea's static white text. */\n\n.AIAutocomplete-module_shimmer_13AnY {\n position: relative;\n z-index: 2;\n display: inline;\n}\n\n.AIAutocomplete-module_shimmerRevealed_RR8dp {\n color: transparent;\n background: linear-gradient(\n 120deg,\n var(--aia-written-text-color, var(--aia-color-text-default, #fff)) 0%,\n var(--aia-written-text-color, var(--aia-color-text-default, #fff)) 44%,\n #b0b0b0 48%,\n #b0b0b0 52%,\n var(--aia-written-text-color, var(--aia-color-text-default, #fff)) 56%,\n var(--aia-written-text-color, var(--aia-color-text-default, #fff)) 100%\n );\n background-size: 200% 100%;\n -webkit-background-clip: text;\n background-clip: text;\n}\n\n.AIAutocomplete-module_shimmerSweep_ARCon {\n animation: AIAutocomplete-module_textShimmer_eCLdq 650ms ease-out forwards;\n}\n\n@keyframes AIAutocomplete-module_textShimmer_eCLdq {\n 0% {\n background-position: 100% 0;\n }\n 100% {\n background-position: -50% 0;\n }\n}\n\n.AIAutocomplete-module_shimmerHidden_45-Pf {\n color: transparent !important;\n}\n`;\n document.head.appendChild(s);\n}\nexport default {\"container\":\"AIAutocomplete-module_container_KKjFU\",\"inputWrapper\":\"AIAutocomplete-module_inputWrapper_FLq1b\",\"editorArea\":\"AIAutocomplete-module_editorArea_7rBWq\",\"sizerContent\":\"AIAutocomplete-module_sizerContent_DQgmV\",\"sizerText\":\"AIAutocomplete-module_sizerText_iZIMK\",\"sizerTextVisible\":\"AIAutocomplete-module_sizerTextVisible_HR-5h\",\"textareaHidden\":\"AIAutocomplete-module_textareaHidden_UayJt\",\"placeholderText\":\"AIAutocomplete-module_placeholderText_K3ayy\",\"textarea\":\"AIAutocomplete-module_textarea_eyn6A\",\"submitButton\":\"AIAutocomplete-module_submitButton_sl1Mi\",\"submitSlot\":\"AIAutocomplete-module_submitSlot_GhuCM\",\"shimmer\":\"AIAutocomplete-module_shimmer_13AnY\",\"shimmerRevealed\":\"AIAutocomplete-module_shimmerRevealed_RR8dp\",\"shimmerSweep\":\"AIAutocomplete-module_shimmerSweep_ARCon\",\"textShimmer\":\"AIAutocomplete-module_textShimmer_eCLdq\",\"shimmerHidden\":\"AIAutocomplete-module_shimmerHidden_45-Pf\"};","if (typeof document !== \"undefined\" && !document.getElementById(\"ac-style-2eef895d\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-2eef895d\";\n s.textContent = `.AIAutocompleteDropdown-module_dropdown_yz2KC {\n position: absolute;\n left: 0;\n right: 0;\n top: 100%;\n max-width: 516px;\n margin-top: 6px;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n container-type: inline-size;\n z-index: 10;\n opacity: 0;\n pointer-events: none;\n transition: opacity 400ms cubic-bezier(0.4, 0, 0.2, 1);\n box-shadow:\n hsla(0, 0%, 100%, 1) -3.2px -3.2px 3.2px -3.2px inset,\n hsla(0, 0%, 100%, 1) 6.4px 6.4px 1.6px -8px inset,\n var(--aia-dropdown-bg, transparent) -6.4px 6.4px 1.6px -8px inset, /* same color as bg */\n var(--aia-dropdown-bg, transparent) 6.4px -6.4px 1.6px -8px inset, /* same color as bg */\n hsla(0, 0%, 100%, 0.15) -1.6px 0px 0px -1.6px inset,\n hsla(0, 0%, 100%, 0.15) 0px -1.6px 0px -1.6px inset,\n hsla(0, 0%, 100%, 0.3) 0px 1.6px 0px 0px inset,\n hsla(0, 0%, 100%, 0.3) 1.6px 0px 0px 0px inset,\n inset 0 0 30px 5px hsla(0, 0%, 0%, 0.05),\n hsla(0, 0%, 0%, 0.08) 0px 0px 30px 2px;\n backdrop-filter: blur(30px);\n border-radius: 28px;\n}\n\n.AIAutocompleteDropdown-module_visible_QCoXj {\n opacity: 1;\n pointer-events: auto;\n}\n\n.AIAutocompleteDropdown-module_pillBar_pwTXe {\n padding: 27px 27px 0px 27px;\n}\n`;\n document.head.appendChild(s);\n}\nexport default {\"dropdown\":\"AIAutocompleteDropdown-module_dropdown_yz2KC\",\"visible\":\"AIAutocompleteDropdown-module_visible_QCoXj\",\"pillBar\":\"AIAutocompleteDropdown-module_pillBar_pwTXe\"};","if (typeof document !== \"undefined\" && !document.getElementById(\"ac-style-b745b4fb\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-b745b4fb\";\n s.textContent = `.PillList-module_list_qvLqO {\n position: relative;\n z-index: 1;\n pointer-events: auto;\n display: inline-flex;\n gap: 5px;\n align-items: center;\n vertical-align: middle;\n transform: translateY(-3px);\n}\n\n.PillList-module_pill_osSyz {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n height: 36px;\n padding: 13px 13px;\n border: none;\n border-radius: 999px;\n background: rgba(49, 50, 85, 0.25);\n background: color-mix(\n in srgb,\n var(--aia-pill-bg, var(--aia-color-background-supportive, #313255)) 25%,\n transparent\n );\n color: var(--aia-pill-color, var(--aia-color-text-muted, #c1c4cb));\n font-family: \"IBM Plex Sans\", sans-serif;\n font-size: var(--aia-pill-font-size, 19px);\n line-height: 30px;\n cursor: pointer;\n white-space: nowrap;\n animation: PillList-module_fadeIn_Aezob 400ms cubic-bezier(0.4, 0, 0.2, 1) forwards;\n box-shadow:\n hsla(0, 0%, 100%, 1) -3.2px -3.2px 3.2px -3.2px inset,\n hsla(0, 0%, 100%, 1) 6.4px 6.4px 1.6px -8px inset,\n var(--aia-dropdown-bg, transparent) -6.4px 6.4px 1.6px -8px inset,\n var(--aia-dropdown-bg, transparent) 6.4px -6.4px 1.6px -8px inset,\n hsla(0, 0%, 100%, 0.15) -1.6px 0px 0px -1.6px inset,\n hsla(0, 0%, 100%, 0.15) 0px -1.6px 0px -1.6px inset,\n hsla(0, 0%, 100%, 0.3) 0px 1.6px 0px 0px inset,\n hsla(0, 0%, 100%, 0.3) 1.6px 0px 0px 0px inset,\n inset 0 0 30px 5px hsla(0, 0%, 0%, 0.05),\n hsla(0, 0%, 0%, 0.08) 0px 0px 30px 2px;\n backdrop-filter: blur(30px);\n}\n\n.PillList-module_rounded_WvXy4 {\n border-radius: 999px;\n}\n\n.PillList-module_pill_osSyz:hover {\n filter: brightness(1.2);\n}\n\n.PillList-module_active_Oll-- {\n outline: 1px solid #5a5b8a;\n}\n\n@keyframes PillList-module_fadeIn_Aezob {\n from {\n opacity: 0;\n }\n}\n`;\n document.head.appendChild(s);\n}\nexport default {\"list\":\"PillList-module_list_qvLqO\",\"pill\":\"PillList-module_pill_osSyz\",\"fadeIn\":\"PillList-module_fadeIn_Aezob\",\"rounded\":\"PillList-module_rounded_WvXy4\",\"active\":\"PillList-module_active_Oll--\"};","import type { Suggestion } from \"../types\";\nimport styles from \"./PillList.module.css\";\n\ninterface PillListProps {\n pills: Suggestion[];\n activePillIndex: number;\n onSelectPill: (index: number) => void;\n /** Use capsule-shaped pills (fully rounded). Default: false. */\n rounded?: boolean;\n}\n\nfunction getPillOpacity(index: number): number {\n if (index === 0) return 0.4;\n if (index === 1) return 0.3;\n return 0.15;\n}\n\nexport function PillList({ pills, activePillIndex, onSelectPill, rounded }: PillListProps) {\n return (\n <span className={styles.list}>\n {pills.map((pill, i) => (\n <button\n key={`${pill.type}-${pill.text}`}\n type=\"button\"\n data-aia-pill=\"\"\n className={`${styles.pill} ${rounded ? styles.rounded : \"\"} ${i === activePillIndex ? styles.active : \"\"}`}\n style={{ opacity: getPillOpacity(i) }}\n onClick={() => onSelectPill(i)}\n >\n {pill.text}\n </button>\n ))}\n </span>\n );\n}\n","import { useEffect, useLayoutEffect, useRef, useState } from \"react\";\nimport type { SuggestionOption } from \"../types\";\nimport styles from \"./SuggestionGrid.module.css\";\nimport { SuggestionItem } from \"./SuggestionItem\";\n\ninterface SuggestionGridProps {\n options: SuggestionOption[];\n activeIndex: number;\n onSelect: (option: SuggestionOption) => void;\n onHighlight: (index: number) => void;\n listboxId: string;\n}\n\nexport function SuggestionGrid({\n options,\n activeIndex,\n onSelect,\n onHighlight,\n listboxId,\n}: SuggestionGridProps) {\n const gridRef = useRef<HTMLDivElement>(null);\n const [hasBottomOverflow, setHasBottomOverflow] = useState(false);\n\n useEffect(() => {\n const el = gridRef.current;\n if (!el) return;\n\n const update = () => {\n setHasBottomOverflow(el.scrollHeight - el.scrollTop - el.clientHeight > 1);\n };\n\n el.addEventListener(\"scroll\", update, { passive: true });\n const resizeObserver = new ResizeObserver(update);\n resizeObserver.observe(el);\n\n return () => {\n el.removeEventListener(\"scroll\", update);\n resizeObserver.disconnect();\n };\n }, []);\n\n // Re-measure synchronously when the option list changes. ResizeObserver\n // misses this case (the grid hits max-height, so scrollHeight grows but the\n // observed box doesn't) and useEffect would leave a frame of stale fade.\n // biome-ignore lint/correctness/useExhaustiveDependencies: options is a trigger-only dep\n useLayoutEffect(() => {\n const el = gridRef.current;\n if (!el) return;\n setHasBottomOverflow(el.scrollHeight - el.scrollTop - el.clientHeight > 1);\n }, [options]);\n\n return (\n <div className={styles.scrollWrapper} data-fade={hasBottomOverflow ? \"\" : undefined}>\n <div ref={gridRef} className={styles.grid}>\n {options.map((option, i) => (\n <SuggestionItem\n key={option.text}\n option={option}\n isHighlighted={i === activeIndex}\n onSelect={onSelect}\n onHighlight={() => onHighlight(i)}\n id={`${listboxId}-option-${i}`}\n />\n ))}\n </div>\n </div>\n );\n}\n","if (typeof document !== \"undefined\" && !document.getElementById(\"ac-style-d91f2b06\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-d91f2b06\";\n s.textContent = `.SuggestionGrid-module_scrollWrapper_MOqfw {\n position: relative;\n}\n\n.SuggestionGrid-module_scrollWrapper_MOqfw::after {\n content: \"\";\n position: absolute;\n left: 0;\n right: 0;\n bottom: 0;\n height: 50%;\n pointer-events: none;\n opacity: 0;\n transition: opacity 150ms ease-out;\n backdrop-filter: blur(12px);\n mask-image: linear-gradient(to bottom, transparent, white);\n}\n\n.SuggestionGrid-module_scrollWrapper_MOqfw[data-fade]::after {\n opacity: 1;\n}\n\n.SuggestionGrid-module_grid_jvaPb {\n display: grid;\n grid-template-columns: minmax(0, 250px);\n max-width: 100cqi;\n padding: 8px 8px;\n max-height: 200px;\n overflow-y: auto;\n scrollbar-width: thin;\n scrollbar-color: var(--aia-scrollbar-thumb, rgba(0, 0, 0, 0.3)) transparent;\n}\n\n@container (min-width: 516px) {\n .SuggestionGrid-module_grid_jvaPb {\n grid-template-columns: repeat(2, minmax(0, 250px));\n justify-content: start;\n }\n}\n\n.SuggestionGrid-module_grid_jvaPb::-webkit-scrollbar {\n width: 6px;\n}\n\n.SuggestionGrid-module_grid_jvaPb::-webkit-scrollbar-track {\n background: transparent;\n}\n\n.SuggestionGrid-module_grid_jvaPb::-webkit-scrollbar-thumb {\n background: var(--aia-scrollbar-thumb, rgba(0, 0, 0, 0.3));\n border-radius: 3px;\n}\n`;\n document.head.appendChild(s);\n}\nexport default {\"scrollWrapper\":\"SuggestionGrid-module_scrollWrapper_MOqfw\",\"grid\":\"SuggestionGrid-module_grid_jvaPb\"};","import { useEffect, useRef, useState } from \"react\";\nimport type { SuggestionOption } from \"../types\";\nimport styles from \"./SuggestionItem.module.css\";\n\ninterface SuggestionItemProps {\n option: SuggestionOption;\n isHighlighted: boolean;\n onSelect: (option: SuggestionOption) => void;\n onHighlight: () => void;\n id: string;\n}\n\nexport function SuggestionItem({\n option,\n isHighlighted,\n onSelect,\n onHighlight,\n id,\n}: SuggestionItemProps) {\n const [pressed, setPressed] = useState(false);\n const timerRef = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n\n useEffect(() => {\n return () => clearTimeout(timerRef.current);\n }, []);\n\n const handleSelect = () => {\n if (!option.is_tappable || pressed) return;\n setPressed(true);\n onSelect(option);\n clearTimeout(timerRef.current);\n timerRef.current = setTimeout(() => setPressed(false), 400);\n };\n\n const className = [\n styles.item,\n isHighlighted ? styles.highlighted : \"\",\n option.is_tappable ? styles.tappable : styles.nonTappable,\n pressed ? styles.pressed : \"\",\n ]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <div\n id={id}\n role=\"option\"\n data-aia-option=\"\"\n aria-selected={isHighlighted}\n className={className}\n tabIndex={option.is_tappable ? 0 : -1}\n onClick={handleSelect}\n onKeyDown={(e) => {\n if (option.is_tappable && (e.key === \"Enter\" || e.key === \" \")) {\n e.preventDefault();\n handleSelect();\n }\n }}\n onMouseEnter={option.is_tappable ? onHighlight : undefined}\n >\n <div className={styles.streaks} />\n <div className={styles.streaksVert} />\n <span className={styles.content}>\n {option.icon ? `${option.icon} ${option.text}` : option.text}\n {option.tag && <span className={styles.tag}>{option.tag}</span>}\n </span>\n </div>\n );\n}\n","if (typeof document !== \"undefined\" && !document.getElementById(\"ac-style-f6bdc634\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-f6bdc634\";\n s.textContent = `.SuggestionItem-module_item_d4vpD {\n position: relative;\n overflow: visible;\n display: flex;\n align-items: center;\n font-family: \"IBM Plex Sans\", sans-serif;\n font-size: var(--aia-option-font-size, 19px);\n line-height: 24px;\n color: var(--aia-option-color, var(--aia-color-text-muted, #c1c4cb));\n white-space: normal;\n word-break: break-word;\n opacity: 0.4;\n border-radius: 12px;\n padding: 13px 13px;\n animation: SuggestionItem-module_fadeIn_I8u35 500ms cubic-bezier(0.4, 0, 0.2, 1) forwards;\n}\n\n@keyframes SuggestionItem-module_fadeIn_I8u35 {\n from {\n opacity: 0;\n }\n}\n\n.SuggestionItem-module_content_T-Qba {\n position: relative;\n z-index: 2;\n}\n\n.SuggestionItem-module_tappable_70KcX {\n cursor: pointer;\n}\n\n.SuggestionItem-module_tappable_70KcX:hover {\n color: var(--aia-option-color-selected, var(--aia-color-text-default, #fff));\n}\n\n.SuggestionItem-module_nonTappable_xSZM- {\n cursor: default;\n opacity: 0.3;\n}\n\n.SuggestionItem-module_highlighted_Hb0SU {\n color: var(--aia-option-color-selected, var(--aia-color-text-default, #fff));\n background: var(--aia-option-bg, transparent);\n opacity: 0.5;\n}\n\n.SuggestionItem-module_tag_e3Fwe {\n font-size: 11px;\n margin-left: 6px;\n opacity: 0.5;\n}\n\n.SuggestionItem-module_pressed_98o-r {\n opacity: 0.8;\n color: var(--aia-color-text-default, #fff);\n background: rgba(var(--aia-streak-rgb, 255, 255, 255), 0.06);\n animation:\n SuggestionItem-module_glassFade_oyiSj 500ms ease forwards,\n SuggestionItem-module_tapDown_G3WGz 500ms ease forwards;\n}\n\n@keyframes SuggestionItem-module_tapDown_G3WGz {\n 0% {\n transform: scale(1);\n }\n 30% {\n transform: scale(0.97);\n }\n 100% {\n transform: scale(1);\n }\n}\n\n@keyframes SuggestionItem-module_glassFade_oyiSj {\n 0% {\n background: var(--aia-streak-glass-bg, rgba(255, 255, 255, 0.1));\n }\n 100% {\n background: transparent;\n }\n}\n\n/* Border streaks — horizontal segments */\n\n.SuggestionItem-module_streaks_d9PEB {\n position: absolute;\n inset: 0;\n z-index: 1;\n pointer-events: none;\n border-radius: inherit;\n overflow: hidden;\n}\n\n/* Bottom horizontal: 40% from right → right corner */\n.SuggestionItem-module_streaks_d9PEB::before {\n content: \"\";\n position: absolute;\n bottom: -3px;\n left: 60%;\n width: 0;\n height: 6px;\n opacity: 0;\n background: radial-gradient(\n ellipse at center,\n rgba(var(--aia-streak-rgb, 255, 255, 255), 0.5) 0%,\n rgba(var(--aia-streak-rgb, 255, 255, 255), 0.2) 40%,\n transparent 70%\n );\n box-shadow: 0 0 12px 4px rgba(var(--aia-streak-rgb, 255, 255, 255), 0.2);\n filter: blur(1px);\n border-radius: 50%;\n}\n\n/* Top horizontal: 40% from left → left corner */\n.SuggestionItem-module_streaks_d9PEB::after {\n content: \"\";\n position: absolute;\n top: -3px;\n right: 60%;\n width: 0;\n height: 6px;\n opacity: 0;\n background: radial-gradient(\n ellipse at center,\n rgba(var(--aia-streak-rgb, 255, 255, 255), 0.5) 0%,\n rgba(var(--aia-streak-rgb, 255, 255, 255), 0.2) 40%,\n transparent 70%\n );\n box-shadow: 0 0 12px 4px rgba(var(--aia-streak-rgb, 255, 255, 255), 0.2);\n filter: blur(1px);\n border-radius: 50%;\n}\n\n/* Border streaks — vertical segments */\n\n.SuggestionItem-module_streaksVert_ERlV1 {\n position: absolute;\n inset: 0;\n z-index: 1;\n pointer-events: none;\n border-radius: inherit;\n overflow: hidden;\n}\n\n/* Right vertical: bottom-right corner → up */\n.SuggestionItem-module_streaksVert_ERlV1::before {\n content: \"\";\n position: absolute;\n bottom: 0;\n right: -3px;\n width: 6px;\n height: 0;\n opacity: 0;\n background: radial-gradient(\n ellipse at center,\n rgba(var(--aia-streak-rgb, 255, 255, 255), 0.4) 0%,\n rgba(var(--aia-streak-rgb, 255, 255, 255), 0.15) 40%,\n transparent 70%\n );\n box-shadow: 0 0 12px 4px rgba(var(--aia-streak-rgb, 255, 255, 255), 0.15);\n filter: blur(1px);\n border-radius: 50%;\n}\n\n/* Left vertical: top-left corner → down */\n.SuggestionItem-module_streaksVert_ERlV1::after {\n content: \"\";\n position: absolute;\n top: 0;\n left: -3px;\n width: 6px;\n height: 0;\n opacity: 0;\n background: radial-gradient(\n ellipse at center,\n rgba(var(--aia-streak-rgb, 255, 255, 255), 0.4) 0%,\n rgba(var(--aia-streak-rgb, 255, 255, 255), 0.15) 40%,\n transparent 70%\n );\n box-shadow: 0 0 12px 4px rgba(var(--aia-streak-rgb, 255, 255, 255), 0.15);\n filter: blur(1px);\n border-radius: 50%;\n}\n\n.SuggestionItem-module_pressed_98o-r .SuggestionItem-module_streaks_d9PEB::before {\n animation: SuggestionItem-module_streakHorizRight_aboGz 500ms cubic-bezier(0.4, 0, 0.2, 1) forwards;\n}\n\n.SuggestionItem-module_pressed_98o-r .SuggestionItem-module_streaks_d9PEB::after {\n animation: SuggestionItem-module_streakHorizLeft_BreWJ 500ms cubic-bezier(0.4, 0, 0.2, 1) forwards;\n}\n\n.SuggestionItem-module_pressed_98o-r .SuggestionItem-module_streaksVert_ERlV1::before {\n animation: SuggestionItem-module_streakVertUp_to1GD 300ms cubic-bezier(0.3, 0, 0.2, 1) 200ms forwards;\n}\n\n.SuggestionItem-module_pressed_98o-r .SuggestionItem-module_streaksVert_ERlV1::after {\n animation: SuggestionItem-module_streakVertDown_OrcLh 300ms cubic-bezier(0.3, 0, 0.2, 1) 200ms forwards;\n}\n\n/* Horizontal: bottom center-ish → right edge */\n@keyframes SuggestionItem-module_streakHorizRight_aboGz {\n 0% {\n width: 0;\n height: 4px;\n opacity: 0;\n filter: blur(1px);\n box-shadow: 0 0 8px 3px rgba(var(--aia-streak-rgb, 255, 255, 255), 0.3);\n }\n 15% {\n height: 4px;\n opacity: 1;\n filter: blur(1px);\n box-shadow: 0 0 10px 4px rgba(var(--aia-streak-rgb, 255, 255, 255), 0.3);\n }\n 80% {\n width: 50%;\n height: 10px;\n opacity: 0.8;\n filter: blur(3px);\n box-shadow: 0 0 16px 6px rgba(var(--aia-streak-rgb, 255, 255, 255), 0.1);\n }\n 100% {\n width: 50%;\n height: 12px;\n opacity: 0;\n filter: blur(5px);\n box-shadow: 0 0 20px 8px rgba(var(--aia-streak-rgb, 255, 255, 255), 0.03);\n }\n}\n\n/* Horizontal: top center-ish → left edge */\n@keyframes SuggestionItem-module_streakHorizLeft_BreWJ {\n 0% {\n width: 0;\n height: 4px;\n opacity: 0;\n filter: blur(1px);\n box-shadow: 0 0 8px 3px rgba(var(--aia-streak-rgb, 255, 255, 255), 0.3);\n }\n 15% {\n height: 4px;\n opacity: 1;\n filter: blur(1px);\n box-shadow: 0 0 10px 4px rgba(var(--aia-streak-rgb, 255, 255, 255), 0.3);\n }\n 80% {\n width: 50%;\n height: 10px;\n opacity: 0.8;\n filter: blur(3px);\n box-shadow: 0 0 16px 6px rgba(var(--aia-streak-rgb, 255, 255, 255), 0.1);\n }\n 100% {\n width: 50%;\n height: 12px;\n opacity: 0;\n filter: blur(5px);\n box-shadow: 0 0 20px 8px rgba(var(--aia-streak-rgb, 255, 255, 255), 0.03);\n }\n}\n\n/* Vertical segments start matching horizontal state at 200ms handoff */\n@keyframes SuggestionItem-module_streakVertUp_to1GD {\n 0% {\n height: 0;\n width: 6px;\n opacity: 0.9;\n filter: blur(1.8px);\n box-shadow: 0 0 12px 5px rgba(var(--aia-streak-rgb, 255, 255, 255), 0.25);\n }\n 75% {\n height: 100%;\n width: 10px;\n opacity: 0.4;\n filter: blur(3px);\n box-shadow: 0 0 18px 8px rgba(var(--aia-streak-rgb, 255, 255, 255), 0.06);\n }\n 100% {\n height: 100%;\n width: 14px;\n opacity: 0;\n filter: blur(5px);\n box-shadow: 0 0 24px 10px rgba(var(--aia-streak-rgb, 255, 255, 255), 0.02);\n }\n}\n\n@keyframes SuggestionItem-module_streakVertDown_OrcLh {\n 0% {\n height: 0;\n width: 6px;\n opacity: 0.9;\n filter: blur(1.8px);\n box-shadow: 0 0 12px 5px rgba(var(--aia-streak-rgb, 255, 255, 255), 0.25);\n }\n 75% {\n height: 100%;\n width: 10px;\n opacity: 0.4;\n filter: blur(3px);\n box-shadow: 0 0 18px 8px rgba(var(--aia-streak-rgb, 255, 255, 255), 0.06);\n }\n 100% {\n height: 100%;\n width: 14px;\n opacity: 0;\n filter: blur(5px);\n box-shadow: 0 0 24px 10px rgba(var(--aia-streak-rgb, 255, 255, 255), 0.02);\n }\n}\n`;\n document.head.appendChild(s);\n}\nexport default {\"item\":\"SuggestionItem-module_item_d4vpD\",\"fadeIn\":\"SuggestionItem-module_fadeIn_I8u35\",\"content\":\"SuggestionItem-module_content_T-Qba\",\"tappable\":\"SuggestionItem-module_tappable_70KcX\",\"nonTappable\":\"SuggestionItem-module_nonTappable_xSZM-\",\"highlighted\":\"SuggestionItem-module_highlighted_Hb0SU\",\"tag\":\"SuggestionItem-module_tag_e3Fwe\",\"pressed\":\"SuggestionItem-module_pressed_98o-r\",\"glassFade\":\"SuggestionItem-module_glassFade_oyiSj\",\"tapDown\":\"SuggestionItem-module_tapDown_G3WGz\",\"streaks\":\"SuggestionItem-module_streaks_d9PEB\",\"streaksVert\":\"SuggestionItem-module_streaksVert_ERlV1\",\"streakHorizRight\":\"SuggestionItem-module_streakHorizRight_aboGz\",\"streakHorizLeft\":\"SuggestionItem-module_streakHorizLeft_BreWJ\",\"streakVertUp\":\"SuggestionItem-module_streakVertUp_to1GD\",\"streakVertDown\":\"SuggestionItem-module_streakVertDown_OrcLh\"};","import styles from \"./AIAutocompleteDropdown.module.css\";\nimport { PillList } from \"./components/PillList\";\nimport { SuggestionGrid } from \"./components/SuggestionGrid\";\nimport type { AIAutocompleteDropdownProps } from \"./types\";\n\nexport function AIAutocompleteDropdown({\n suggestions,\n activeIndex,\n onSelect,\n onHighlight,\n isOpen,\n id,\n className,\n pills,\n onPillClick,\n showPills = true,\n}: AIAutocompleteDropdownProps) {\n const activeSuggestion = suggestions[0];\n const options = activeSuggestion?.options ?? [];\n const hasPills = showPills && pills && pills.length > 0 && onPillClick;\n const hasOptions = isOpen && options.length > 0;\n const isVisible = hasOptions || (isOpen && hasPills);\n\n return (\n <div\n id={id}\n role=\"listbox\"\n data-aia-dropdown=\"\"\n className={`${styles.dropdown} ${isVisible ? styles.visible : \"\"} ${className ?? \"\"}`}\n onMouseDown={(e) => e.preventDefault()}\n >\n {hasPills && (\n <div className={styles.pillBar} data-aia-pillbar=\"\">\n <PillList pills={pills} activePillIndex={0} onSelectPill={onPillClick} rounded />\n </div>\n )}\n {options.length > 0 && (\n <SuggestionGrid\n options={options}\n activeIndex={activeIndex}\n onSelect={onSelect}\n onHighlight={onHighlight}\n listboxId={id}\n />\n )}\n </div>\n );\n}\n","if (typeof document !== \"undefined\" && !document.getElementById(\"ac-style-dc8da745\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-dc8da745\";\n s.textContent = `/*\n * Built-in appearance defaults — zero specificity via :where().\n * Consumer CSS always wins without !important.\n *\n * Resolution priority (highest wins):\n * 1. Consumer CSS targeting new vars (--aia-pill-bg, etc.)\n * 2. Consumer CSS targeting legacy vars (--aia-color-*, via fallback chain)\n * 3. These built-in defaults\n */\n\n/* Light mode defaults (base) */\n:where(.magicx-aia),\n:where(.magicx-aia[data-mode=\"light\"]) {\n --aia-pill-bg: #bdbdbd;\n --aia-pill-color: #000000;\n --aia-pill-font-size: 19px;\n\n --aia-option-bg: transparent;\n --aia-option-color: #000000;\n --aia-option-color-selected: #000000;\n --aia-option-font-size: 19px;\n\n --aia-written-text-color: #000000;\n --aia-written-text-font-size: 19px;\n --aia-caret-color: var(--aia-written-text-color, #000000);\n\n --aia-submit-bg: #000000;\n --aia-submit-color: #ffffff;\n\n --aia-color-text-muted: #6b7280;\n\n --aia-streak-rgb: 99, 102, 241;\n --aia-streak-glass-bg: rgba(99, 102, 241, 0.1);\n}\n\n/* Dark mode defaults */\n:where(.magicx-aia[data-mode=\"dark\"]) {\n --aia-pill-bg: #bdbdbd;\n --aia-pill-color: #ffffff;\n --aia-pill-font-size: 19px;\n\n --aia-option-bg: transparent;\n --aia-option-color: #ffffff;\n --aia-option-color-selected: #ffffff;\n --aia-option-font-size: 19px;\n\n --aia-written-text-color: #ffffff;\n --aia-written-text-font-size: 19px;\n --aia-caret-color: var(--aia-written-text-color, #ffffff);\n\n --aia-submit-bg: #ffffff;\n --aia-submit-color: #000000;\n\n --aia-color-text-muted: #c1c4cb;\n\n --aia-streak-rgb: 255, 255, 255;\n --aia-streak-glass-bg: rgba(255, 255, 255, 0.1);\n}\n\n/* optionsPosition: dropdown above the input */\n:where(.magicx-aia[data-options-position=\"above\"]) [data-aia-dropdown] {\n top: auto;\n bottom: 100%;\n margin-top: 0;\n margin-bottom: 6px;\n flex-direction: column-reverse;\n}\n\n:where(.magicx-aia[data-options-position=\"above\"]) [data-aia-pillbar] {\n padding: 0 27px 27px 27px;\n}\n\n/* Disable all animations when data-animations=\"off\" */\n:where(.magicx-aia[data-animations=\"off\"]) *,\n:where(.magicx-aia[data-animations=\"off\"]) *::before,\n:where(.magicx-aia[data-animations=\"off\"]) *::after {\n animation-duration: 0s !important;\n transition-duration: 0s !important;\n}\n`;\n document.head.appendChild(s);\n}\nexport {};","import {\n type ChangeEvent,\n type KeyboardEvent,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport { AIAutocomplete as CoreAIAutocomplete } from \"../core/AIAutocomplete\";\nimport type { CoreState } from \"../core/types\";\nimport type {\n Suggestion,\n SuggestionOption,\n UseAIAutocompleteOptions,\n UseAIAutocompleteReturn,\n} from \"../types\";\n\nexport function useAIAutocomplete({\n onSubmit,\n onError,\n optionOverrides,\n maskCompletedText,\n apiConfig,\n columns = 2,\n dropdownTrigger,\n closeDropdownOnBlur,\n onFocus,\n onBlur,\n value: controlledValue,\n completedParams: controlledParams,\n onChange: onChangeProp,\n onParamsChange,\n source,\n}: UseAIAutocompleteOptions): UseAIAutocompleteReturn {\n const instanceRef = useRef<CoreAIAutocomplete | null>(null);\n const [coreState, setCoreState] = useState<CoreState | null>(null);\n\n // Refs for callbacks to avoid stale closures\n const onSubmitRef = useRef(onSubmit);\n onSubmitRef.current = onSubmit;\n const onErrorRef = useRef(onError);\n onErrorRef.current = onError;\n const onChangeRef = useRef(onChangeProp);\n onChangeRef.current = onChangeProp;\n const onParamsChangeRef = useRef(onParamsChange);\n onParamsChangeRef.current = onParamsChange;\n const onFocusRef = useRef(onFocus);\n onFocusRef.current = onFocus;\n const onBlurRef = useRef(onBlur);\n onBlurRef.current = onBlur;\n\n // Create, subscribe, and destroy the core instance in one mount-only effect.\n // Keeping creation out of render (and pairing it with the cleanup) is what\n // makes this StrictMode-safe — otherwise cleanup nulls the ref, render\n // re-creates, and the store subscription drives an infinite setState loop.\n // biome-ignore lint/correctness/useExhaustiveDependencies: initial-opts snapshot; later changes are synced by the update-effect below\n useEffect(() => {\n if (typeof document === \"undefined\") return;\n const instance = new CoreAIAutocomplete(document.createElement(\"div\"), {\n renderMode: \"headless\",\n apiConfig,\n optionOverrides,\n maskCompletedText,\n columns,\n dropdownTrigger,\n closeDropdownOnBlur,\n source,\n value: controlledValue,\n completedParams: controlledParams,\n onSubmit: (...args) => onSubmitRef.current?.(...args),\n onError: (...args) => onErrorRef.current?.(...args),\n onChange: (...args) => onChangeRef.current?.(...args),\n onParamsChange: (...args) => onParamsChangeRef.current?.(...args),\n onFocus: () => onFocusRef.current?.(),\n onBlur: () => onBlurRef.current?.(),\n });\n instanceRef.current = instance;\n setCoreState(instance.getState());\n const unsub = instance.subscribe((state) => setCoreState(state));\n return () => {\n unsub();\n instance.destroy();\n if (instanceRef.current === instance) instanceRef.current = null;\n };\n }, []);\n\n const instance = instanceRef.current;\n\n // SSR bail-out — no instance, return safe empty defaults\n // Hooks below are unconditional (React rules of hooks) but guarded internally\n const noop = useCallback(() => {}, []);\n\n // Sync controlled value\n useEffect(() => {\n if (controlledValue !== undefined) instance?.setValue(controlledValue);\n }, [controlledValue, instance]);\n\n // Sync controlled params\n useEffect(() => {\n if (controlledParams !== undefined) instance?.setCompletedParams(controlledParams);\n }, [controlledParams, instance]);\n\n // Sync apiConfig/optionOverrides/dropdownTrigger when values change\n const apiConfigJson = JSON.stringify(apiConfig ?? null);\n const prevOverridesRef = useRef(optionOverrides);\n const overridesVersion = useRef(0);\n if (optionOverrides !== prevOverridesRef.current) {\n const prev = prevOverridesRef.current;\n const next = optionOverrides;\n const prevKeys = Object.keys(prev ?? {});\n const nextKeys = Object.keys(next ?? {});\n if (\n prevKeys.length !== nextKeys.length ||\n nextKeys.some(\n (k) =>\n !(prev as Record<string, unknown>)?.[k] ||\n (next as Record<string, unknown>)[k] !== (prev as Record<string, unknown>)[k],\n )\n ) {\n overridesVersion.current++;\n }\n prevOverridesRef.current = optionOverrides;\n }\n // biome-ignore lint/correctness/useExhaustiveDependencies: overridesVersion tracks shallow changes to fn-valued optionOverrides\n useEffect(() => {\n instance?.update({ apiConfig, optionOverrides, dropdownTrigger, closeDropdownOnBlur });\n }, [apiConfigJson, overridesVersion.current, dropdownTrigger, closeDropdownOnBlur, instance]);\n\n // Handle text change from textarea\n const handleChange = useCallback(\n (e: ChangeEvent<HTMLTextAreaElement>) => {\n if (!instance) return;\n const raw = e.target.value;\n const shouldCapitalize =\n raw.length > 0 &&\n !(e.nativeEvent as InputEvent)?.isComposing &&\n raw[0] !== raw[0].toUpperCase();\n const newValue = shouldCapitalize ? raw[0].toUpperCase() + raw.slice(1) : raw;\n instance.handleTextChange(newValue);\n },\n [instance],\n );\n\n // Handle keyboard\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLTextAreaElement>) => {\n instance?.handleKeyDown(e.nativeEvent);\n },\n [instance],\n );\n\n const handleFocus = useCallback(() => instance?.setFocused(true), [instance]);\n const handleBlur = useCallback(() => instance?.setFocused(false), [instance]);\n\n // Actions\n const setActivePill = useCallback((index: number) => instance?.setActivePill(index), [instance]);\n const removeLastParam = useCallback(() => instance?.removeLastParam(), [instance]);\n const clearNewParamId = useCallback(() => instance?.clearNewParamId(), [instance]);\n const reset = useCallback(() => instance?.reset(), [instance]);\n const selectOption = useCallback(\n (option: SuggestionOption) => instance?.selectOption(option),\n [instance],\n );\n const setActiveDropdownIndex = useCallback(\n (index: number) => instance?.setActiveDropdownIndex(index),\n [instance],\n );\n\n // No instance (SSR) — return safe defaults\n if (!instance) {\n return {\n completedParams: controlledParams ?? [],\n suggestionPills: [],\n setActivePill: noop,\n removeLastParam: noop,\n segments: [],\n newParamId: null,\n clearNewParamId: noop,\n suggestions: [],\n activeIndex: -1,\n isReady: false,\n isLoading: true,\n error: null,\n inputProps: {\n value: controlledValue ?? \"\",\n placeholder: undefined,\n onChange: noop as unknown as UseAIAutocompleteReturn[\"inputProps\"][\"onChange\"],\n onKeyDown: noop as unknown as UseAIAutocompleteReturn[\"inputProps\"][\"onKeyDown\"],\n onFocus: noop,\n onBlur: noop,\n role: \"combobox\" as const,\n \"aria-expanded\": false,\n \"aria-activedescendant\": undefined,\n \"aria-autocomplete\": \"list\" as const,\n \"aria-controls\": \"\",\n },\n reset: noop,\n dropdownProps: {\n suggestions: [],\n activeIndex: -1,\n onSelect: noop as unknown as (option: SuggestionOption) => void,\n onHighlight: noop as unknown as (index: number) => void,\n isOpen: false,\n id: \"\",\n pills: [],\n onPillClick: noop as unknown as (index: number) => void,\n },\n };\n }\n\n // Derive current state\n const state = coreState ?? instance.getState();\n const text = controlledValue !== undefined ? controlledValue : state.text;\n const completedParams = controlledParams !== undefined ? controlledParams : state.completedParams;\n\n const actionableSuggestions = state.actionableSuggestions;\n const activeSuggestion: Suggestion | undefined = actionableSuggestions[0];\n const filteredOptions = state.filteredOptions;\n\n const activeDescendantId =\n state.activeDropdownIndex >= 0\n ? `${instance.listboxId}-option-${state.activeDropdownIndex}`\n : undefined;\n\n return {\n completedParams,\n suggestionPills: actionableSuggestions,\n setActivePill,\n removeLastParam,\n segments: state.segments,\n newParamId: state.newParamId,\n clearNewParamId,\n suggestions: state.suggestions,\n activeIndex: state.activeDropdownIndex,\n isReady: state.isReady,\n isLoading: state.isLoading,\n error: state.error,\n inputProps: {\n value: text,\n placeholder: state.placeholderText || undefined,\n onChange: handleChange,\n onKeyDown: handleKeyDown,\n onFocus: handleFocus,\n onBlur: handleBlur,\n role: \"combobox\" as const,\n \"aria-expanded\": state.isDropdownOpen,\n \"aria-activedescendant\": activeDescendantId,\n \"aria-autocomplete\": \"list\" as const,\n \"aria-controls\": instance.listboxId,\n },\n reset,\n dropdownProps: {\n suggestions: activeSuggestion ? [{ ...activeSuggestion, options: filteredOptions }] : [],\n activeIndex: state.activeDropdownIndex,\n onSelect: selectOption,\n onHighlight: setActiveDropdownIndex,\n isOpen: state.isDropdownOpen,\n id: instance.listboxId,\n pills: actionableSuggestions,\n onPillClick: setActivePill,\n },\n };\n}\n","import type { CompletedParamState } from \"../types\";\n\ninterface BuildQueryResult {\n rawQuery: string;\n completedParams: CompletedParamState[];\n}\n\n/**\n * Takes the raw input text and completed params (without placeholders),\n * replaces each completed param's text in the string with a {{TYPE_N}} token,\n * and returns the transformed query + params with placeholders filled in.\n *\n * Replacements happen left-to-right, first occurrence only per param.\n * Counter is per-type (e.g. {{TASK_1}}, {{GOAL_1}}, {{GOAL_2}}).\n */\nexport function buildQuery(text: string, completedParams: CompletedParamState[]): BuildQueryResult {\n let result = text;\n const typeCounts: Record<string, number> = {};\n const updatedParams: CompletedParamState[] = [];\n\n for (const param of completedParams) {\n const count = (typeCounts[param.type] ?? 0) + 1;\n typeCounts[param.type] = count;\n\n const typeKey = param.type.toUpperCase().replace(/\\s+/g, \"_\");\n const placeholder = `{{${typeKey}_${count}}}`;\n\n // Replace first occurrence of the param text in the string\n const index = result.indexOf(param.text);\n if (index !== -1) {\n result = result.slice(0, index) + placeholder + result.slice(index + param.text.length);\n }\n\n updatedParams.push({ ...param, placeholder });\n }\n\n return { rawQuery: result, completedParams: updatedParams };\n}\n","import type { SuggestionOption } from \"../types\";\n\n/**\n * Extracts the effective filter query from the region after filterBase.\n * If the server marked the region as in_progress, the full region is used.\n * Otherwise, filtering only starts after the first space (to avoid filtering\n * mid-word when the user continues typing a word that was already in the input).\n */\nexport function extractFilterQuery(\n text: string,\n filterBase: number,\n isInProgress: boolean,\n): string {\n const rawRegion = text.slice(filterBase);\n if (isInProgress || filterBase === 0 || text[filterBase - 1] === \" \") {\n return rawRegion;\n }\n const spaceIdx = rawRegion.indexOf(\" \");\n return spaceIdx === -1 ? \"\" : rawRegion.slice(spaceIdx + 1);\n}\n\n/**\n * Finds the longest word-boundary-aligned suffix of `prefix` that matches a\n * prefix of `optionText` (case-insensitive). Returns the number of characters\n * to remove from the end of `prefix` to avoid duplication.\n */\nexport function findPrefixOverlap(prefix: string, optionText: string): number {\n // Normalize internal whitespace so words.join(\" \") roundtrips losslessly\n const trimmed = prefix.trimEnd().replace(/\\s+/g, \" \");\n if (trimmed.length === 0 || optionText.length === 0) return 0;\n\n const words = trimmed.split(\" \");\n const optionLower = optionText.toLowerCase();\n\n // Try from longest suffix (all words) to shortest (last word only)\n for (let i = 0; i < words.length; i++) {\n const candidate = words.slice(i).join(\" \");\n if (optionLower.startsWith(candidate.toLowerCase())) {\n const suffixStart = trimmed.length - candidate.length;\n return prefix.length - suffixStart;\n }\n }\n\n return 0;\n}\n\n/**\n * Filters options using partial substring match on the text after the last completed param.\n */\nexport function filterOptions(\n options: SuggestionOption[] | undefined,\n query: string,\n): SuggestionOption[] {\n if (!options) return [];\n const trimmed = query.trimStart();\n if (!trimmed) return options;\n const lower = trimmed.toLowerCase();\n return options.filter((o) => !o.is_tappable || o.text.toLowerCase().includes(lower));\n}\n\n/**\n * Finds an exact match for the trimmed filter query against options.\n */\nexport function findExactMatch(\n options: SuggestionOption[] | undefined,\n query: string,\n): SuggestionOption | null {\n if (!options) return null;\n const trimmed = query.trim();\n if (!trimmed) return null;\n const lower = trimmed.toLowerCase();\n return options.find((o) => o.is_tappable && o.text.toLowerCase() === lower) ?? null;\n}\n","import type { AppearanceMode } from \"../types\";\n\nexport class ModeController {\n private mediaQuery: MediaQueryList | null = null;\n\n constructor(\n private container: HTMLElement,\n private mode: AppearanceMode = \"auto\",\n ) {\n this.apply();\n }\n\n setMode(mode: AppearanceMode) {\n this.detachListener();\n this.mode = mode;\n this.apply();\n }\n\n destroy() {\n this.detachListener();\n }\n\n private apply() {\n if (this.mode === \"auto\") {\n this.mediaQuery ??= window.matchMedia(\"(prefers-color-scheme: dark)\");\n this.mediaQuery.addEventListener(\"change\", this.onSystemChange);\n this.container.dataset.mode = this.mediaQuery.matches ? \"dark\" : \"light\";\n } else {\n this.container.dataset.mode = this.mode;\n }\n }\n\n private onSystemChange = (e: MediaQueryListEvent) => {\n this.container.dataset.mode = e.matches ? \"dark\" : \"light\";\n };\n\n private detachListener() {\n this.mediaQuery?.removeEventListener(\"change\", this.onSystemChange);\n }\n}\n","import type { CompletedParamState, Segment } from \"../types\";\n\n/**\n * Derives segments for overlay rendering by matching completed params in text.\n */\nexport function deriveSegments(text: string, completedParams: CompletedParamState[]): Segment[] {\n const result: Segment[] = [];\n let pos = 0;\n\n for (const param of completedParams) {\n const idx = text.indexOf(param.text, pos);\n if (idx === -1) continue;\n if (idx > pos) {\n result.push({ type: \"text\", value: text.slice(pos, idx) });\n }\n result.push({ type: \"completed\", value: param.text, param });\n pos = idx + param.text.length;\n }\n\n const remaining = text.slice(pos);\n if (remaining) {\n result.push({ type: \"text\", value: remaining });\n }\n\n return result;\n}\n\n/**\n * Checks which completed params still exist in the new text.\n */\nexport function reconcileParams(\n text: string,\n completedParams: CompletedParamState[],\n): { valid: CompletedParamState[]; invalid: CompletedParamState[] } {\n const valid: CompletedParamState[] = [];\n const invalid: CompletedParamState[] = [];\n let pos = 0;\n\n for (const param of completedParams) {\n const idx = text.indexOf(param.text, pos);\n if (idx === -1) {\n invalid.push(param);\n } else {\n valid.push(param);\n pos = idx + param.text.length;\n }\n }\n\n return { valid, invalid };\n}\n","import type { AccessTokenConfig } from \"../types\";\n\n/** Refresh 30 seconds before stated expiry to absorb clock drift and request latency. */\nconst REFRESH_SKEW_MS = 30_000;\n\nexport class TokenManager {\n private current: string | null = null;\n private expiresAt: number | null = null;\n private inFlightRefresh: Promise<string> | null = null;\n\n constructor(private config: AccessTokenConfig) {\n if (config.accessToken) {\n this.current = config.accessToken;\n }\n }\n\n /** Returns a valid token, refreshing if needed. Single-flight: concurrent callers share one refresh. */\n async getToken(forceRefresh = false): Promise<string> {\n if (!forceRefresh && this.current && !this.isExpired()) {\n return this.current;\n }\n if (!forceRefresh && this.inFlightRefresh) {\n return this.inFlightRefresh;\n }\n this.inFlightRefresh = this.refresh();\n try {\n return await this.inFlightRefresh;\n } finally {\n this.inFlightRefresh = null;\n }\n }\n\n private async refresh(): Promise<string> {\n const result = await this.config.getAccessToken();\n this.current = result.accessToken;\n this.expiresAt = result.expiresAt ?? null;\n return this.current;\n }\n\n private isExpired(): boolean {\n if (this.expiresAt == null) return false;\n return Date.now() >= this.expiresAt - REFRESH_SKEW_MS;\n }\n}\n","import type { AccessTokenConfig, APIConfig, APIKeyConfig } from \"../types\";\nimport { TokenManager } from \"./tokenManager\";\n\n// Keyed by getAccessToken function reference (stable across React re-renders)\nconst tokenManagers = new WeakMap<AccessTokenConfig[\"getAccessToken\"], TokenManager>();\n\nexport function isAccessTokenConfig(config?: APIConfig): config is AccessTokenConfig {\n return config?.type === \"accessToken\";\n}\n\nexport function getApiKeyConfig(config?: APIConfig): APIKeyConfig | undefined {\n if (!config || isAccessTokenConfig(config)) return undefined;\n return config;\n}\n\nexport function getTokenManager(config: AccessTokenConfig): TokenManager {\n let manager = tokenManagers.get(config.getAccessToken);\n if (!manager) {\n manager = new TokenManager(config);\n tokenManagers.set(config.getAccessToken, manager);\n }\n return manager;\n}\n\n/**\n * Builds shared (non-auth) request headers used by every backend call.\n * Mirrors what /suggest sends so /api/telemetry/events sees the same envelope.\n */\nexport function buildHeaders(apiConfig?: APIConfig): Record<string, string> {\n return {\n \"Content-Type\": \"application/json\",\n ...(apiConfig?.appIdentifier && { \"X-App-Identifier\": apiConfig.appIdentifier }),\n ...apiConfig?.headers,\n };\n}\n\n/**\n * Returns the Authorization header value for an API-key config, or `null` if no\n * apiKey is set (matches /suggest's behavior of sending the request without an\n * Authorization header in that case — the warn lives in api.ts so it fires only\n * for the user-visible suggest call).\n */\nexport function buildApiKeyAuthHeader(apiConfig?: APIConfig): string | null {\n const apiKeyConfig = getApiKeyConfig(apiConfig);\n const apiKey = apiKeyConfig?.apiKey;\n if (!apiKey) return null;\n const scheme = apiKeyConfig?.authScheme ?? \"Bearer\";\n return scheme === \"Basic\" ? `Basic ${btoa(apiKey)}` : `Bearer ${apiKey}`;\n}\n","import type { APIConfig } from \"../types\";\nimport { buildApiKeyAuthHeader, buildHeaders, getTokenManager, isAccessTokenConfig } from \"./auth\";\n\nexport type TelemetrySource = \"full-sdk\" | \"headless-sdk\" | \"endpoint-direct\";\nexport type TelemetryType = \"pill\" | \"option\";\n\nexport interface TelemetryEvent {\n source: TelemetrySource;\n sessionId: string;\n type: TelemetryType;\n queryData: Record<string, unknown>;\n apiConfig?: APIConfig;\n}\n\nconst DEFAULT_SUGGEST_ENDPOINT = \"https://api.ai-autocomplete.com/api/suggest\";\nconst TELEMETRY_PATH = \"/api/telemetry/events\";\n\nfunction deriveTelemetryEndpoint(suggestEndpoint?: string): string {\n const base = suggestEndpoint ?? DEFAULT_SUGGEST_ENDPOINT;\n try {\n const url = new URL(base);\n return `${url.origin}${TELEMETRY_PATH}`;\n } catch {\n return `https://api.ai-autocomplete.com${TELEMETRY_PATH}`;\n }\n}\n\n/**\n * Resolves Authorization header using the same logic as /suggest:\n * - accessToken mode → Bearer from TokenManager\n * - apiKey mode → Bearer/Basic from configured key\n * - neither → null (request is sent without an Authorization header, matching\n * /suggest's behavior)\n */\nasync function resolveAuthHeader(apiConfig?: APIConfig): Promise<string | null> {\n if (isAccessTokenConfig(apiConfig)) {\n const token = await getTokenManager(apiConfig).getToken();\n return `Bearer ${token}`;\n }\n return buildApiKeyAuthHeader(apiConfig);\n}\n\n/**\n * Fire-and-forget telemetry POST. Never throws; failures are swallowed so the\n * UI is never disrupted by analytics. Auth headers are constructed via the\n * same helpers used by /suggest, so credential resolution stays consistent\n * across endpoints.\n */\nexport async function sendTelemetry(event: TelemetryEvent): Promise<void> {\n try {\n const endpoint = deriveTelemetryEndpoint(event.apiConfig?.endpoint);\n const headers = buildHeaders(event.apiConfig);\n const authHeader = await resolveAuthHeader(event.apiConfig);\n if (authHeader) headers.Authorization = authHeader;\n\n const body = JSON.stringify({\n source: event.source,\n session_id: event.sessionId,\n type: event.type,\n at: new Date().toISOString(),\n query_data: event.queryData,\n });\n\n await fetch(endpoint, { method: \"POST\", headers, body });\n } catch {\n // best-effort\n }\n}\n","import type {\n APIConfig,\n AutocompleteRequest,\n AutocompleteResponse,\n CompletedParam,\n CompletedParamState,\n} from \"../types\";\nimport { buildApiKeyAuthHeader, buildHeaders, getTokenManager, isAccessTokenConfig } from \"./auth\";\n\n// Replaced at build time by tsup/vitest `define` config with the package.json version.\ndeclare const __SDK_VERSION__: string;\nconst SDK_VERSION = __SDK_VERSION__;\n\nlet hasWarnedMissingKey = false;\n\nfunction generateRequestId(): string {\n return crypto.randomUUID();\n}\n\nfunction toWireParam(param: CompletedParamState, includeText: boolean): CompletedParam {\n return {\n placeholder: param.placeholder,\n type: param.type,\n ...(includeText && { text: param.text }),\n kind: param.kind,\n };\n}\n\nfunction buildRequestBody(\n rawQuery: string,\n completedParams: CompletedParamState[],\n includeText: boolean,\n sessionId: string,\n): AutocompleteRequest {\n const rawCount = completedParams.find(\n (p) => p.type === \"contact\" && p.metadata?.contact_account_count,\n )?.metadata?.contact_account_count;\n const contactAccountCount = typeof rawCount === \"number\" ? rawCount : undefined;\n\n return {\n data: {\n raw_query: rawQuery,\n completed_params: completedParams.map((p) => toWireParam(p, includeText)),\n ...(contactAccountCount != null && { contact_account_count: contactAccountCount }),\n },\n meta: {\n request_id: generateRequestId(),\n request_at: new Date().toISOString(),\n language: typeof navigator !== \"undefined\" ? navigator.language : \"en-US\",\n client_version: SDK_VERSION,\n session_id: sessionId,\n },\n };\n}\n\nasync function doFetch(\n endpoint: string,\n headers: Record<string, string>,\n token: string,\n body: string,\n signal?: AbortSignal,\n): Promise<Response> {\n return fetch(endpoint, {\n method: \"POST\",\n headers: { ...headers, Authorization: `Bearer ${token}` },\n body,\n signal,\n });\n}\n\nexport async function fetchSuggestions(\n rawQuery: string,\n completedParams: CompletedParamState[],\n options: {\n sessionId: string;\n maskCompletedText?: boolean;\n signal?: AbortSignal;\n apiConfig?: APIConfig;\n },\n): Promise<AutocompleteResponse> {\n const apiConfig = options.apiConfig;\n const includeText = !options.maskCompletedText;\n const body = buildRequestBody(rawQuery, completedParams, includeText, options.sessionId);\n const headers = buildHeaders(apiConfig);\n const endpoint = apiConfig?.endpoint ?? \"https://api.ai-autocomplete.com/api/suggest\";\n const jsonBody = JSON.stringify(body);\n\n // === Access token mode ===\n if (isAccessTokenConfig(apiConfig)) {\n const manager = getTokenManager(apiConfig);\n const token = await manager.getToken();\n\n let response = await doFetch(endpoint, headers, token, jsonBody, options.signal);\n\n // 401 retry: force-refresh token and retry exactly once\n if (response.status === 401) {\n const newToken = await manager.getToken(true);\n response = await doFetch(endpoint, headers, newToken, jsonBody, options.signal);\n }\n\n if (!response.ok) {\n throw new Error(`API error: ${response.status} ${response.statusText}`);\n }\n\n return response.json() as Promise<AutocompleteResponse>;\n }\n\n // === API key mode (default) ===\n const authHeader = buildApiKeyAuthHeader(apiConfig);\n if (!authHeader && !hasWarnedMissingKey) {\n hasWarnedMissingKey = true;\n // biome-ignore lint/suspicious/noConsole: intentional dev warning\n console.warn(\n \"[AIAutocomplete] No apiKey in apiConfig. Requests will be sent without an Authorization header.\",\n );\n }\n if (authHeader) headers.Authorization = authHeader;\n\n const response = await fetch(endpoint, {\n method: \"POST\",\n headers,\n body: jsonBody,\n signal: options.signal,\n });\n\n if (!response.ok) {\n throw new Error(`API error: ${response.status} ${response.statusText}`);\n }\n\n return response.json() as Promise<AutocompleteResponse>;\n}\n","import type { Suggestion, SuggestionOption } from \"../types\";\n\n/**\n * Applies option overrides by calling the override function with an empty query,\n * then prepending results to suggestions that match by type, deduplicating by text.\n */\nexport function applyOptionOverrides(\n suggestions: Suggestion[],\n overrides?: Record<string, (query: string) => SuggestionOption[]>,\n): Suggestion[] {\n if (!overrides) return suggestions;\n return suggestions.map((s) => {\n const fn = overrides[s.type];\n if (!fn) return s;\n const extra = fn(\"\");\n if (extra.length === 0) return s;\n const existingTexts = new Set(extra.map((o) => o.text));\n const deduped = (s.options ?? []).filter((o) => !existingTexts.has(o.text));\n return { ...s, options: [...extra, ...deduped] };\n });\n}\n","import type {\n APIConfig,\n CompletedParamState,\n OptionOverrides,\n Suggestion,\n SuggestionOption,\n} from \"../../types\";\nimport { fetchSuggestions } from \"../../utils/api\";\nimport { buildQuery } from \"../../utils/buildQuery\";\nimport { extractFilterQuery, filterOptions, findExactMatch } from \"../../utils/filtering\";\nimport { applyOptionOverrides } from \"../../utils/overrides\";\nimport type { Store } from \"../state\";\nimport type { CoreState } from \"../types\";\n\nconst DEBOUNCE_MS = 100;\nconst SLOW_DEBOUNCE_MS = 300;\nconst MIN_CHARS_DIFF = 2;\n\nexport interface FetchAutoMatchEvent {\n active: Suggestion;\n matched: SuggestionOption;\n rawQuery: string;\n}\n\nexport interface FetchControllerCallbacks {\n onAutoMatch?: (event: FetchAutoMatchEvent) => void;\n}\n\nexport class FetchController {\n private fetchVersion = 0;\n private abortController: AbortController | null = null;\n private debounceTimer: ReturnType<typeof setTimeout> | null = null;\n private slowDebounceTimer: ReturnType<typeof setTimeout> | null = null;\n private unsubscribe: (() => void) | null = null;\n\n constructor(\n private store: Store<CoreState>,\n private getApiConfig: () => APIConfig | undefined,\n private getOptionOverrides: () => OptionOverrides | undefined,\n private getMaskCompletedText: () => boolean | undefined,\n private getOnError: () => ((error: Error) => void) | undefined,\n private getSessionId: () => string,\n private callbacks: FetchControllerCallbacks = {},\n ) {}\n\n start() {\n // Initial fetch\n this.doFetch(\"\", []);\n\n // Subscribe to state changes for debounced fetching\n let prevText = this.store.get().text;\n let prevParams = this.store.get().completedParams;\n this.unsubscribe = this.store.subscribe((next) => {\n if (next.text !== prevText || next.completedParams !== prevParams) {\n prevText = next.text;\n prevParams = next.completedParams;\n this.scheduleFetch();\n }\n });\n }\n\n dispose() {\n this.abortController?.abort();\n this.clearTimers();\n this.unsubscribe?.();\n }\n\n async doFetch(rawQuery: string, completed: CompletedParamState[]) {\n this.abortController?.abort();\n const controller = new AbortController();\n this.abortController = controller;\n const version = ++this.fetchVersion;\n const state = this.store.get();\n const textAtRequest = state.text.length;\n\n const hasSuggestions = state.suggestions.some((s) => s.type !== \"placeholder\");\n if (!hasSuggestions) this.store.set({ isLoading: true });\n this.store.set({ error: null });\n\n try {\n const res = await fetchSuggestions(rawQuery, completed, {\n sessionId: this.getSessionId(),\n maskCompletedText: this.getMaskCompletedText(),\n signal: controller.signal,\n apiConfig: this.getApiConfig(),\n });\n\n if (version !== this.fetchVersion) return;\n\n let newSuggestions = applyOptionOverrides(\n res.data.suggestions ?? [],\n this.getOptionOverrides(),\n );\n\n const input = res.data.input ?? [];\n const lastInput = input[input.length - 1];\n const currentText = this.store.get().text;\n let filterBase: number;\n let filterInProgress: boolean;\n\n if (lastInput?.state === \"in_progress\") {\n filterInProgress = true;\n const inProgressIdx = currentText.toLowerCase().lastIndexOf(lastInput.text.toLowerCase());\n filterBase = inProgressIdx !== -1 ? inProgressIdx : textAtRequest;\n } else {\n filterInProgress = false;\n filterBase = textAtRequest;\n }\n\n // Check if user already typed an exact match while waiting\n const actionable = newSuggestions.filter((s) => s.type !== \"placeholder\");\n const active = actionable[0];\n let extraParam: CompletedParamState | null = null;\n if (active) {\n const query = extractFilterQuery(currentText, filterBase, filterInProgress);\n const match = findExactMatch(active.options, query);\n if (match) {\n extraParam = {\n id: crypto.randomUUID(),\n placeholder: \"\",\n type: active.type,\n text: match.text,\n kind: match.kind,\n suggestionType: active.type,\n suggestionPlaceholder: active.text,\n options: active.options ?? [],\n metadata: match.metadata,\n };\n newSuggestions = newSuggestions.filter((s) => s !== active);\n this.callbacks.onAutoMatch?.({ active, matched: match, rawQuery });\n }\n }\n\n this.store.set((s) => ({\n suggestions: newSuggestions,\n isLoading: false,\n isReady: res.data.is_ready ?? false,\n lastRawQuery: rawQuery,\n activeDropdownIndex: -1,\n filterBase,\n filterInProgress,\n ...(extraParam ? { completedParams: [...s.completedParams, extraParam] } : {}),\n }));\n } catch (err) {\n if (version === this.fetchVersion) {\n const caughtError = err instanceof Error ? err : new Error(String(err));\n this.store.set({ error: caughtError, isLoading: false });\n this.getOnError()?.(caughtError);\n }\n }\n }\n\n private scheduleFetch() {\n this.clearTimers();\n const state = this.store.get();\n\n if (state.skipNextFetch) {\n this.store.set({ skipNextFetch: false });\n return;\n }\n\n const attemptFetch = (minDiff: number): boolean => {\n const s = this.store.get();\n if (!s.text && s.completedParams.length === 0) {\n this.doFetch(\"\", []);\n return true;\n }\n\n const currentQuery = extractFilterQuery(s.text, s.filterBase, s.filterInProgress);\n const actionable = s.suggestions.filter((sg: Suggestion) => sg.type !== \"placeholder\");\n const active = actionable[0];\n const currentFiltered = active ? filterOptions(active.options, currentQuery) : [];\n const tappableFiltered = currentFiltered.filter((o: SuggestionOption) => o.is_tappable);\n const hasExactMatch = active ? findExactMatch(active.options, currentQuery) !== null : false;\n\n const isInFilterZone = currentQuery.trim().length > 0;\n if (tappableFiltered.length > 0 && !hasExactMatch && isInFilterZone) return false;\n\n // Mirror the filter-zone behavior for placeholder suggestions: if the user is\n // still typing a prefix of the server-provided placeholder, don't fetch yet.\n if (s.completedParams.length === 0 && s.text.length > 0) {\n const placeholderText = s.suggestions\n .filter((sg: Suggestion) => sg.type === \"placeholder\")\n .map((sg: Suggestion) => sg.text)\n .join(\" \");\n if (\n placeholderText.length > 0 &&\n placeholderText.toLowerCase().startsWith(s.text.toLowerCase())\n ) {\n return false;\n }\n }\n\n const { rawQuery, completedParams: updatedParams } = buildQuery(s.text, s.completedParams);\n const isDeleting = rawQuery.length < s.lastRawQuery.length;\n const charDiff = Math.abs(rawQuery.length - s.lastRawQuery.length);\n if (isDeleting || charDiff >= minDiff) {\n this.doFetch(rawQuery, updatedParams);\n return true;\n }\n return false;\n };\n\n this.debounceTimer = setTimeout(() => {\n if (attemptFetch(MIN_CHARS_DIFF)) {\n if (this.slowDebounceTimer) clearTimeout(this.slowDebounceTimer);\n }\n }, DEBOUNCE_MS);\n\n this.slowDebounceTimer = setTimeout(() => attemptFetch(1), SLOW_DEBOUNCE_MS);\n }\n\n private clearTimers() {\n if (this.debounceTimer) clearTimeout(this.debounceTimer);\n if (this.slowDebounceTimer) clearTimeout(this.slowDebounceTimer);\n this.debounceTimer = null;\n this.slowDebounceTimer = null;\n }\n}\n","import type { AutocompleteResult, SuggestionOption } from \"../../types\";\nimport { buildQuery } from \"../../utils/buildQuery\";\nimport type { Store } from \"../state\";\nimport type { CoreState } from \"../types\";\n\nexport interface KeyboardContext {\n columns: number;\n listboxId: string;\n getOnSubmit: () => ((result: AutocompleteResult) => void) | undefined;\n /** Optional hook invoked after onSubmit fires (used by Tier 1 to auto-reset). */\n afterSubmit?: () => void;\n selectOption: (option: SuggestionOption) => void;\n}\n\nexport class KeyboardController {\n constructor(\n private store: Store<CoreState>,\n private ctx: KeyboardContext,\n ) {}\n\n handleKeyDown(e: KeyboardEvent) {\n const state = this.store.get();\n const { listboxId, getOnSubmit } = this.ctx;\n const columns = this.getEffectiveColumns();\n const onSubmit = getOnSubmit();\n const tappableIndices = this.getTappableIndices(columns);\n\n switch (e.key) {\n case \"ArrowDown\": {\n const target = e.target as HTMLTextAreaElement;\n const cursorAtEnd =\n target.selectionStart != null && target.selectionStart === target.value.length;\n if (!cursorAtEnd && state.activeDropdownIndex < 0) break;\n\n e.preventDefault();\n if (!state.isDropdownOpen && state.actionableSuggestions.length > 0) {\n this.store.set({ pillTapped: true, activeDropdownIndex: tappableIndices[0] ?? 0 });\n break;\n }\n if (tappableIndices.length === 0) return;\n const currentPos = tappableIndices.indexOf(state.activeDropdownIndex);\n const nextPos = currentPos < tappableIndices.length - 1 ? currentPos + 1 : 0;\n this.store.set({ activeDropdownIndex: tappableIndices[nextPos] });\n break;\n }\n case \"ArrowUp\": {\n if (tappableIndices.length === 0 || state.activeDropdownIndex < 0) break;\n e.preventDefault();\n if (state.activeDropdownIndex < columns) {\n this.store.set({ activeDropdownIndex: -1 });\n break;\n }\n const currentPos = tappableIndices.indexOf(state.activeDropdownIndex);\n const prevPos = currentPos > 0 ? currentPos - 1 : tappableIndices.length - 1;\n this.store.set({ activeDropdownIndex: tappableIndices[prevPos] });\n break;\n }\n case \"ArrowRight\": {\n if (state.activeDropdownIndex < 0) {\n const target = e.target as HTMLTextAreaElement;\n const atEnd =\n target.selectionStart != null && target.selectionStart === target.value.length;\n if (atEnd && state.actionableSuggestions.length > 1) {\n e.preventDefault();\n this.pillsSetActivePill(1);\n }\n break;\n }\n const col = state.activeDropdownIndex % columns;\n if (col < columns - 1) {\n const rightNeighbor = state.activeDropdownIndex + 1;\n if (\n rightNeighbor < state.filteredOptions.length &&\n state.filteredOptions[rightNeighbor]?.is_tappable\n ) {\n e.preventDefault();\n this.store.set({ activeDropdownIndex: rightNeighbor });\n }\n }\n break;\n }\n case \"ArrowLeft\": {\n if (state.activeDropdownIndex < 0) break;\n if (state.activeDropdownIndex % columns > 0) {\n const leftNeighbor = state.activeDropdownIndex - 1;\n if (leftNeighbor >= 0 && state.filteredOptions[leftNeighbor]?.is_tappable) {\n e.preventDefault();\n this.store.set({ activeDropdownIndex: leftNeighbor });\n }\n }\n break;\n }\n case \"Enter\": {\n e.preventDefault();\n if (\n state.activeDropdownIndex >= 0 &&\n state.filteredOptions[state.activeDropdownIndex]?.is_tappable\n ) {\n this.clickOrSelect(state.activeDropdownIndex, state.filteredOptions, listboxId);\n } else if (onSubmit) {\n const { rawQuery, completedParams: finalParams } = buildQuery(\n state.text,\n state.completedParams,\n );\n onSubmit({\n query: state.text.trim(),\n raw_query: rawQuery,\n completed_params: finalParams,\n });\n this.ctx.afterSubmit?.();\n }\n break;\n }\n case \"Tab\": {\n const placeholderVisible = !state.text && !!state.placeholderText;\n const hasHighlightedOption =\n state.activeDropdownIndex >= 0 &&\n state.filteredOptions[state.activeDropdownIndex]?.is_tappable;\n\n // Placeholder visible + option highlighted → defer to selectOption,\n // which prepends the placeholder text to the option (see AIAutocomplete.selectOption).\n if (placeholderVisible && !hasHighlightedOption) {\n e.preventDefault();\n const placeholderSuggestion = state.suggestions.find((s) => s.type === \"placeholder\");\n if (placeholderSuggestion) {\n this.store.set((s) => ({\n text: state.placeholderText,\n filterBase: state.placeholderText.length,\n completedParams: [\n ...s.completedParams,\n {\n id: crypto.randomUUID(),\n placeholder: \"\",\n type: placeholderSuggestion.type,\n text: state.placeholderText,\n kind: null,\n suggestionType: placeholderSuggestion.type,\n suggestionPlaceholder: placeholderSuggestion.text,\n options: placeholderSuggestion.options ?? [],\n },\n ],\n suggestions: s.suggestions.filter((sg) => sg !== placeholderSuggestion),\n }));\n } else {\n this.store.set({\n text: state.placeholderText,\n filterBase: state.placeholderText.length,\n });\n }\n } else if (hasHighlightedOption) {\n e.preventDefault();\n this.clickOrSelect(state.activeDropdownIndex, state.filteredOptions, listboxId);\n } else if (state.isDropdownOpen) {\n const firstTappableIdx = state.filteredOptions.findIndex((o) => o.is_tappable);\n if (firstTappableIdx >= 0) {\n e.preventDefault();\n this.clickOrSelect(firstTappableIdx, state.filteredOptions, listboxId);\n }\n }\n break;\n }\n case \"Escape\":\n this.store.set({ activeDropdownIndex: -1 });\n break;\n }\n }\n\n private getTappableIndices(columns: number): number[] {\n const state = this.store.get();\n const tappable = state.filteredOptions\n .map((o, i) => (o.is_tappable ? i : -1))\n .filter((i) => i !== -1);\n const buckets: number[][] = Array.from({ length: columns }, () => []);\n for (const i of tappable) buckets[i % columns].push(i);\n return buckets.flat();\n }\n\n /**\n * The grid uses a container query to switch between 1 and 2 columns based on\n * width, so the prop value can disagree with what's actually rendered. Read\n * the live column count from the grid; fall back to the prop if unavailable.\n */\n private getEffectiveColumns(): number {\n const firstOption = document.getElementById(`${this.ctx.listboxId}-option-0`);\n const grid = firstOption?.parentElement;\n if (!grid) return this.ctx.columns;\n const tracks = getComputedStyle(grid).gridTemplateColumns.split(\" \").filter(Boolean).length;\n return tracks > 0 ? tracks : this.ctx.columns;\n }\n\n private clickOrSelect(index: number, options: SuggestionOption[], listboxId: string) {\n const optionEl = document.getElementById(`${listboxId}-option-${index}`);\n if (optionEl) {\n optionEl.click();\n } else {\n this.ctx.selectOption(options[index]);\n }\n }\n\n /** Delegate to pills controller logic inline (avoids circular dep) */\n private pillsSetActivePill(index: number) {\n const state = this.store.get();\n const actionable = state.suggestions.filter((s) => s.type !== \"placeholder\");\n if (index < 0 || index >= actionable.length) return;\n const moved = actionable[index];\n const rest = actionable.filter((_, i) => i !== index);\n const placeholders = state.suggestions.filter((s) => s.type === \"placeholder\");\n this.store.set({\n suggestions: [...placeholders, moved, ...rest],\n pillTapped: true,\n activeDropdownIndex: -1,\n });\n }\n}\n","import type { Suggestion } from \"../../types\";\nimport { buildQuery } from \"../../utils/buildQuery\";\nimport type { Store } from \"../state\";\nimport type { CoreState } from \"../types\";\n\nexport interface PillSelectedEvent {\n rawQuery: string;\n selectedPill: string;\n otherPills: string[];\n}\n\nexport interface PillsControllerCallbacks {\n onPillSelected?: (event: PillSelectedEvent) => void;\n}\n\nexport class PillsController {\n constructor(\n private store: Store<CoreState>,\n private callbacks: PillsControllerCallbacks = {},\n ) {}\n\n setActivePill(index: number) {\n const state = this.store.get();\n const actionable = state.suggestions.filter((s) => s.type !== \"placeholder\");\n if (index < 0 || index >= actionable.length) return;\n const moved = actionable[index];\n const rest = actionable.filter((_, i) => i !== index);\n const placeholders = state.suggestions.filter((s) => s.type === \"placeholder\");\n\n if (this.callbacks.onPillSelected) {\n const { rawQuery } = buildQuery(state.text, state.completedParams);\n this.callbacks.onPillSelected({\n rawQuery,\n selectedPill: moved.text,\n otherPills: rest.map((s) => s.text),\n });\n }\n\n this.store.set({\n suggestions: [...placeholders, moved, ...rest],\n pillTapped: true,\n activeDropdownIndex: -1,\n });\n }\n\n removeLastParam() {\n const state = this.store.get();\n if (state.completedParams.length === 0) return;\n const lastParam = state.completedParams[state.completedParams.length - 1];\n const restoredSuggestion: Suggestion = {\n type: lastParam.suggestionType,\n text: lastParam.suggestionPlaceholder,\n required: true,\n options: lastParam.options,\n };\n this.store.set((s) => ({\n completedParams: s.completedParams.slice(0, -1),\n suggestions: [restoredSuggestion, ...s.suggestions],\n activeDropdownIndex: -1,\n }));\n }\n}\n","import type { Suggestion } from \"../../types\";\n\nfunction getPillOpacity(index: number): number {\n if (index === 0) return 0.4;\n if (index === 1) return 0.3;\n return 0.15;\n}\n\nexport function renderPills(\n container: HTMLElement,\n pills: Suggestion[],\n activePillIndex: number,\n onSelectPill: (index: number) => void,\n rounded = false,\n) {\n // Reuse or create the list wrapper\n let list = container.querySelector<HTMLElement>(\".magicx-aia-pill-list\");\n if (!list) {\n list = document.createElement(\"span\");\n list.className = \"magicx-aia-pill-list\";\n container.appendChild(list);\n }\n\n // Diff by key (type-text)\n const existing = new Map<string, HTMLButtonElement>();\n for (const btn of list.querySelectorAll<HTMLButtonElement>(\".magicx-aia-pill\")) {\n existing.set(btn.dataset.pillKey ?? \"\", btn);\n }\n\n const used = new Set<string>();\n for (let i = 0; i < pills.length; i++) {\n const pill = pills[i];\n const key = `${pill.type}-${pill.text}`;\n used.add(key);\n\n let btn = existing.get(key);\n if (!btn) {\n btn = document.createElement(\"button\");\n btn.type = \"button\";\n btn.dataset.pillKey = key;\n btn.setAttribute(\"data-aia-pill\", \"\");\n btn.textContent = pill.text;\n }\n\n btn.className = `magicx-aia-pill${rounded ? \" magicx-aia-pill--rounded\" : \"\"}${i === activePillIndex ? \" magicx-aia-pill--active\" : \"\"}`;\n btn.style.opacity = String(getPillOpacity(i));\n btn.onclick = () => onSelectPill(i);\n\n // Ensure correct order\n if (list.children[i] !== btn) {\n list.insertBefore(btn, list.children[i] ?? null);\n }\n }\n\n // Remove stale pills\n for (const [key, btn] of existing) {\n if (!used.has(key)) btn.remove();\n }\n}\n\nexport function clearPills(container: HTMLElement) {\n container.querySelector(\".magicx-aia-pill-list\")?.remove();\n}\n","import type { Suggestion, SuggestionOption } from \"../../types\";\nimport { renderPills } from \"./renderPills\";\n\ninterface DropdownState {\n suggestions: Suggestion[];\n filteredOptions: SuggestionOption[];\n activeIndex: number;\n isOpen: boolean;\n listboxId: string;\n pills: Suggestion[];\n showPills: boolean;\n onSelect: (option: SuggestionOption) => void;\n onHighlight: (index: number) => void;\n onPillClick: (index: number) => void;\n}\n\nexport function createDropdown(listboxId: string): HTMLElement {\n const dropdown = document.createElement(\"div\");\n dropdown.id = listboxId;\n dropdown.setAttribute(\"role\", \"listbox\");\n dropdown.setAttribute(\"data-aia-dropdown\", \"\");\n dropdown.className = \"magicx-aia-dropdown\";\n dropdown.addEventListener(\"mousedown\", (e) => e.preventDefault());\n return dropdown;\n}\n\nexport function renderDropdown(dropdown: HTMLElement, state: DropdownState) {\n const {\n filteredOptions,\n activeIndex,\n isOpen,\n pills,\n showPills,\n onSelect,\n onHighlight,\n onPillClick,\n } = state;\n\n const hasPills = showPills && pills.length > 0;\n const hasOptions = isOpen && filteredOptions.length > 0;\n const isVisible = hasOptions || (isOpen && hasPills);\n\n // Toggle visibility\n if (isVisible) {\n dropdown.classList.add(\"magicx-aia-dropdown--visible\");\n } else {\n dropdown.classList.remove(\"magicx-aia-dropdown--visible\");\n }\n\n // --- Pill bar ---\n let pillBar = dropdown.querySelector<HTMLElement>(\".magicx-aia-pill-bar\");\n if (hasPills) {\n if (!pillBar) {\n pillBar = document.createElement(\"div\");\n pillBar.className = \"magicx-aia-pill-bar\";\n pillBar.setAttribute(\"data-aia-pillbar\", \"\");\n dropdown.insertBefore(pillBar, dropdown.firstChild);\n }\n renderPills(pillBar, pills, 0, onPillClick, true);\n } else if (pillBar) {\n pillBar.remove();\n }\n\n // --- Options grid ---\n let grid = dropdown.querySelector<HTMLElement>(\".magicx-aia-grid\");\n if (filteredOptions.length > 0) {\n if (!grid) {\n grid = document.createElement(\"div\");\n grid.className = \"magicx-aia-grid\";\n dropdown.appendChild(grid);\n }\n renderOptions(grid, filteredOptions, activeIndex, onSelect, onHighlight, state.listboxId);\n } else if (grid) {\n grid.innerHTML = \"\";\n }\n}\n\nfunction renderOptions(\n grid: HTMLElement,\n options: SuggestionOption[],\n activeIndex: number,\n onSelect: (option: SuggestionOption) => void,\n onHighlight: (index: number) => void,\n listboxId: string,\n) {\n const optionsKey = options.map((o) => o.text).join(\"\\0\");\n const lastKey = grid.dataset.optionsKey ?? \"\";\n const listChanged = optionsKey !== lastKey;\n grid.dataset.optionsKey = optionsKey;\n\n if (listChanged) {\n // Full rebuild — options changed (filter, new suggestion, etc.)\n const fragment = document.createDocumentFragment();\n\n for (let i = 0; i < options.length; i++) {\n const option = options[i];\n const item = createOptionElement(option, i, activeIndex, onSelect, onHighlight, listboxId);\n fragment.appendChild(item);\n }\n\n grid.innerHTML = \"\";\n grid.appendChild(fragment);\n } else {\n // Just update highlight classes — no DOM rebuild\n const items = grid.querySelectorAll<HTMLElement>(\".magicx-aia-option\");\n for (let i = 0; i < items.length; i++) {\n const item = items[i];\n const isHighlighted = i === activeIndex;\n item.setAttribute(\"aria-selected\", String(isHighlighted));\n if (isHighlighted) {\n item.classList.add(\"magicx-aia-option--highlighted\");\n } else {\n item.classList.remove(\"magicx-aia-option--highlighted\");\n }\n }\n }\n}\n\nfunction createOptionElement(\n option: SuggestionOption,\n index: number,\n activeIndex: number,\n onSelect: (option: SuggestionOption) => void,\n onHighlight: (index: number) => void,\n listboxId: string,\n): HTMLElement {\n const item = document.createElement(\"div\");\n item.id = `${listboxId}-option-${index}`;\n item.setAttribute(\"role\", \"option\");\n item.setAttribute(\"data-aia-option\", \"\");\n item.setAttribute(\"aria-selected\", String(index === activeIndex));\n item.tabIndex = option.is_tappable ? 0 : -1;\n\n const classes = [\"magicx-aia-option\"];\n if (index === activeIndex) classes.push(\"magicx-aia-option--highlighted\");\n if (option.is_tappable) {\n classes.push(\"magicx-aia-option--tappable\");\n } else {\n classes.push(\"magicx-aia-option--non-tappable\");\n }\n item.className = classes.join(\" \");\n\n // Streaks\n const streaks = document.createElement(\"div\");\n streaks.className = \"magicx-aia-streaks\";\n item.appendChild(streaks);\n\n const streaksVert = document.createElement(\"div\");\n streaksVert.className = \"magicx-aia-streaks-vert\";\n item.appendChild(streaksVert);\n\n // Content\n const content = document.createElement(\"span\");\n content.className = \"magicx-aia-option-content\";\n content.textContent = option.icon ? `${option.icon} ${option.text}` : option.text;\n\n if (option.tag) {\n const tag = document.createElement(\"span\");\n tag.className = \"magicx-aia-option-tag\";\n tag.textContent = option.tag;\n content.appendChild(tag);\n }\n\n item.appendChild(content);\n\n // Events\n if (option.is_tappable) {\n item.addEventListener(\"click\", () => {\n item.classList.add(\"magicx-aia-option--pressed\");\n onSelect(option);\n setTimeout(() => item.classList.remove(\"magicx-aia-option--pressed\"), 400);\n });\n item.addEventListener(\"mouseenter\", () => onHighlight(index));\n }\n\n return item;\n}\n","import type { SuggestionOption } from \"../../types\";\nimport type { Store } from \"../state\";\nimport type { CoreState } from \"../types\";\nimport { createDropdown, renderDropdown } from \"./renderDropdown\";\n\ninterface DropdownOnlyRefs {\n dropdown: HTMLElement;\n}\n\ninterface DropdownOnlyOptions {\n store: Store<CoreState>;\n listboxId: string;\n selectOption: (option: SuggestionOption) => void;\n setActivePill: (index: number) => void;\n}\n\nexport function buildDropdownOnly(\n container: HTMLElement,\n opts: DropdownOnlyOptions,\n): DropdownOnlyRefs {\n const dropdown = createDropdown(opts.listboxId);\n container.appendChild(dropdown);\n return { dropdown };\n}\n\nexport function updateDropdownOnly(\n refs: DropdownOnlyRefs,\n state: CoreState,\n opts: DropdownOnlyOptions,\n) {\n renderDropdown(refs.dropdown, {\n suggestions:\n state.actionableSuggestions.length > 0\n ? [{ ...state.actionableSuggestions[0], options: state.filteredOptions }]\n : [],\n filteredOptions: state.filteredOptions,\n activeIndex: state.activeDropdownIndex,\n isOpen: state.isDropdownOpen,\n listboxId: opts.listboxId,\n pills: state.actionableSuggestions,\n showPills: true, // always show pills in dropdown-only mode\n onSelect: opts.selectOption,\n onHighlight: (i) => opts.store.set({ activeDropdownIndex: i }),\n onPillClick: opts.setActivePill,\n });\n}\n","import type { Segment } from \"../../types\";\n\n/**\n * Renders text segments into the sizer overlay.\n * Only rebuilds the DOM when segment content or newParamId changes,\n * preserving in-flight CSS animations (shimmer).\n * Cache keys stored on the DOM element to support multi-instance use.\n */\nexport function renderSegments(\n sizer: HTMLElement,\n segments: Segment[],\n newParamId: string | null,\n isEmpty: boolean,\n placeholderText: string,\n) {\n let sizerText = sizer.querySelector<HTMLElement>(\".magicx-aia-sizer-text\");\n let placeholder = sizer.querySelector<HTMLElement>(\".magicx-aia-placeholder\");\n\n if (isEmpty && placeholderText) {\n if (sizerText) sizerText.style.display = \"none\";\n if (!placeholder) {\n placeholder = document.createElement(\"span\");\n placeholder.className = \"magicx-aia-placeholder\";\n sizer.insertBefore(placeholder, sizer.firstChild);\n }\n placeholder.style.display = \"\";\n placeholder.textContent = `${placeholderText} `;\n sizer.dataset.segmentKey = \"\";\n return;\n }\n\n if (placeholder) placeholder.style.display = \"none\";\n if (!sizerText) {\n sizerText = document.createElement(\"span\");\n sizerText.className = \"magicx-aia-sizer-text\";\n sizer.insertBefore(sizerText, sizer.firstChild);\n }\n sizerText.style.display = \"\";\n sizerText.className = `magicx-aia-sizer-text${newParamId ? \" magicx-aia-sizer-text--visible\" : \"\"}`;\n\n const segmentKey = segments.map((s) => `${s.type}:${s.value}`).join(\"\\0\");\n const lastKey = sizer.dataset.segmentKey ?? \"\";\n const lastParamId = sizer.dataset.newParamId ?? \"\";\n if (segmentKey === lastKey && (newParamId ?? \"\") === lastParamId) {\n return; // Nothing changed — preserve existing DOM and animations\n }\n sizer.dataset.segmentKey = segmentKey;\n sizer.dataset.newParamId = newParamId ?? \"\";\n\n sizerText.innerHTML = \"\";\n for (const seg of segments) {\n const span = document.createElement(\"span\");\n if (seg.type === \"completed\") {\n const isNew = seg.param.id === newParamId;\n if (isNew) {\n span.className = \"magicx-aia-shimmer-revealed magicx-aia-shimmer-sweep\";\n } else {\n span.className = \"magicx-aia-segment magicx-aia-segment--completed\";\n }\n }\n span.textContent = seg.value;\n sizerText.appendChild(span);\n }\n\n if (segments.length === 0) {\n sizerText.textContent = \"\\u00A0\";\n }\n}\n","import type { AutocompleteResult } from \"../../types\";\nimport { buildQuery } from \"../../utils/buildQuery\";\nimport type { Store } from \"../state\";\nimport type { CoreState } from \"../types\";\nimport { createDropdown, renderDropdown } from \"./renderDropdown\";\nimport { renderPills } from \"./renderPills\";\nimport { renderSegments } from \"./renderSegments\";\n\ninterface RenderInputOptions {\n store: Store<CoreState>;\n listboxId: string;\n pillPlacement: \"inline\" | \"dropdown\" | \"hidden\";\n autoFocus?: boolean;\n onSubmit?: (result: AutocompleteResult) => void;\n /** Invoked after onSubmit fires — Tier 1 uses this to auto-reset. */\n afterSubmit?: () => void;\n submitButton?: HTMLElement | null;\n selectOption: (option: import(\"../../types\").SuggestionOption) => void;\n setActivePill: (index: number) => void;\n handleKeyDown: (e: KeyboardEvent) => void;\n handleChange: (value: string) => void;\n}\n\nexport interface DOMRefs {\n textarea: HTMLTextAreaElement;\n dropdown: HTMLElement;\n sizer: HTMLElement;\n /** The default built-in button when no `submitButton` was provided. Null when consumer passed `null` or a custom element. */\n submitButton: HTMLButtonElement | null;\n inlinePillContainer: HTMLElement;\n}\n\nconst SUBMIT_SVG = `<svg width=\"18\" height=\"18\" viewBox=\"0 0 18 18\" fill=\"none\" role=\"img\" aria-label=\"Submit\"><path d=\"M9 14V4M9 4L4 9M9 4L14 9\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>`;\n\nexport function buildDOM(container: HTMLElement, opts: RenderInputOptions): DOMRefs {\n const { listboxId } = opts;\n\n // Dropdown\n const dropdown = createDropdown(listboxId);\n container.appendChild(dropdown);\n\n // Input wrapper\n const inputWrapper = document.createElement(\"div\");\n inputWrapper.className = \"magicx-aia-input-wrapper\";\n container.appendChild(inputWrapper);\n\n // Editor area\n const editor = document.createElement(\"div\");\n editor.className = \"magicx-aia-editor\";\n editor.setAttribute(\"data-aia-editor\", \"\");\n inputWrapper.appendChild(editor);\n\n // Sizer (overlay)\n const sizer = document.createElement(\"div\");\n sizer.className = \"magicx-aia-sizer\";\n sizer.setAttribute(\"aria-hidden\", \"true\");\n editor.appendChild(sizer);\n\n // Inline pill container (inside sizer, after segments)\n const inlinePillContainer = document.createElement(\"span\");\n sizer.appendChild(document.createTextNode(\" \"));\n sizer.appendChild(inlinePillContainer);\n\n // Textarea\n const textarea = document.createElement(\"textarea\");\n textarea.className = \"magicx-aia-textarea\";\n textarea.rows = 1;\n textarea.setAttribute(\"role\", \"combobox\");\n textarea.setAttribute(\"aria-autocomplete\", \"list\");\n textarea.setAttribute(\"aria-controls\", listboxId);\n textarea.setAttribute(\"data-aia-textarea\", \"\");\n editor.appendChild(textarea);\n\n // Submit button — null means render nothing; undefined means default; HTMLElement means custom\n let submitButton: HTMLButtonElement | null = null;\n let submitTarget: HTMLElement | null = null;\n if (opts.submitButton === undefined) {\n submitButton = document.createElement(\"button\");\n submitButton.type = \"button\";\n submitButton.className = \"magicx-aia-submit\";\n submitButton.setAttribute(\"aria-label\", \"Submit\");\n submitButton.setAttribute(\"data-aia-submit\", \"\");\n submitButton.innerHTML = SUBMIT_SVG;\n inputWrapper.appendChild(submitButton);\n submitTarget = submitButton;\n } else if (opts.submitButton !== null) {\n submitTarget = opts.submitButton;\n if (!submitTarget.hasAttribute(\"data-aia-submit\")) {\n submitTarget.setAttribute(\"data-aia-submit\", \"\");\n }\n inputWrapper.appendChild(submitTarget);\n }\n\n // --- Event wiring ---\n\n // Click wrapper → focus textarea\n inputWrapper.addEventListener(\"click\", () => textarea.focus());\n\n // Textarea change\n textarea.addEventListener(\"input\", () => {\n const raw = textarea.value;\n const shouldCapitalize = raw.length > 0 && raw[0] !== raw[0].toUpperCase();\n const newValue = shouldCapitalize ? raw[0].toUpperCase() + raw.slice(1) : raw;\n opts.handleChange(newValue);\n });\n\n // Keyboard\n textarea.addEventListener(\"keydown\", (e) => opts.handleKeyDown(e));\n\n // Focus tracking — auto-trigger uses this to open dropdown when focused\n textarea.addEventListener(\"focus\", () => opts.store.set({ isFocused: true }));\n textarea.addEventListener(\"blur\", () => opts.store.set({ isFocused: false }));\n\n // Submit click — wired on whatever element fills the slot (default or custom)\n if (submitTarget) {\n submitTarget.addEventListener(\"click\", (e) => {\n const state = opts.store.get();\n const canSubmit = !!state.text || state.completedParams.length > 0;\n if (!canSubmit || !opts.onSubmit) return;\n e.stopPropagation();\n const { rawQuery, completedParams: finalParams } = buildQuery(\n state.text,\n state.completedParams,\n );\n opts.onSubmit({\n query: state.text.trim(),\n raw_query: rawQuery,\n completed_params: finalParams,\n });\n opts.afterSubmit?.();\n });\n }\n\n // Focus textarea on mount\n if (opts.autoFocus !== false) {\n textarea.focus();\n }\n\n return { textarea, dropdown, sizer, submitButton, inlinePillContainer };\n}\n\nexport function updateDOM(refs: DOMRefs, state: CoreState, opts: RenderInputOptions) {\n const { textarea, dropdown, sizer, submitButton, inlinePillContainer } = refs;\n const { pillPlacement, setActivePill, selectOption, store } = opts;\n\n // Textarea value\n if (textarea.value !== state.text) {\n textarea.value = state.text;\n }\n\n // Placeholder\n if (state.placeholderText) {\n textarea.placeholder = state.placeholderText;\n } else {\n textarea.removeAttribute(\"placeholder\");\n }\n\n // ARIA\n textarea.setAttribute(\"aria-expanded\", String(state.isDropdownOpen));\n const activeDescendant =\n state.activeDropdownIndex >= 0 ? `${opts.listboxId}-option-${state.activeDropdownIndex}` : \"\";\n if (activeDescendant) {\n textarea.setAttribute(\"aria-activedescendant\", activeDescendant);\n } else {\n textarea.removeAttribute(\"aria-activedescendant\");\n }\n\n // Shimmer: hide textarea text during animation\n if (state.newParamId) {\n textarea.classList.add(\"magicx-aia-textarea--hidden\");\n } else {\n textarea.classList.remove(\"magicx-aia-textarea--hidden\");\n }\n\n // Submit button disabled state — only applies to the default built-in button.\n // Consumer-provided buttons own their own disabled visuals.\n if (submitButton) {\n const canSubmit = !!state.text || state.completedParams.length > 0;\n submitButton.disabled = !canSubmit;\n }\n\n // Segments overlay\n renderSegments(sizer, state.segments, state.newParamId, !state.text, state.placeholderText);\n\n // Inline pills\n if (pillPlacement === \"inline\") {\n renderPills(inlinePillContainer, state.actionableSuggestions, 0, setActivePill);\n } else {\n // Clear inline pills in dropdown mode\n inlinePillContainer.innerHTML = \"\";\n }\n\n // Dropdown\n renderDropdown(dropdown, {\n suggestions:\n state.actionableSuggestions.length > 0\n ? [{ ...state.actionableSuggestions[0], options: state.filteredOptions }]\n : [],\n filteredOptions: state.filteredOptions,\n activeIndex: state.activeDropdownIndex,\n isOpen: state.isDropdownOpen,\n listboxId: opts.listboxId,\n pills: state.actionableSuggestions,\n showPills: pillPlacement === \"dropdown\",\n onSelect: selectOption,\n onHighlight: (i) => store.set({ activeDropdownIndex: i }),\n onPillClick: setActivePill,\n });\n}\n","export type Listener<S> = (next: S, prev: S) => void;\n\nexport interface Store<S> {\n get: () => S;\n set: (patch: Partial<S> | ((s: S) => Partial<S>)) => void;\n subscribe: (listener: Listener<S>) => () => void;\n}\n\nexport function createStore<S>(initial: S): Store<S> {\n let state = initial;\n const listeners = new Set<Listener<S>>();\n return {\n get: () => state,\n set: (patch) => {\n const resolved = typeof patch === \"function\" ? patch(state) : patch;\n const next = { ...state, ...resolved };\n const prev = state;\n state = next;\n for (const l of listeners) l(next, prev);\n },\n subscribe: (listener) => {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n };\n}\n","let injected = false;\n\n/** Inject core + appearance CSS into document.head once. Idempotent. */\nexport function injectStyles() {\n if (injected || typeof document === \"undefined\") return;\n if (document.querySelector(\"style[data-magicx-aia]\")) {\n injected = true;\n return;\n }\n injected = true;\n\n const style = document.createElement(\"style\");\n style.setAttribute(\"data-magicx-aia\", \"\");\n style.textContent = STYLES;\n document.head.appendChild(style);\n}\n\n// Replaced at build time by tsup.config.core.ts / vitest.config.ts\ndeclare const __MAGICX_AC_STYLES__: string;\nconst STYLES = __MAGICX_AC_STYLES__;\n","import type { AppearanceMode, CompletedParamState, Suggestion, SuggestionOption } from \"../types\";\nimport { buildQuery } from \"../utils/buildQuery\";\nimport { extractFilterQuery, filterOptions, findPrefixOverlap } from \"../utils/filtering\";\nimport { ModeController } from \"../utils/modeController\";\nimport { deriveSegments, reconcileParams } from \"../utils/segments\";\nimport { sendTelemetry, type TelemetrySource } from \"../utils/telemetry\";\nimport { FetchController } from \"./controllers/fetchController\";\nimport { KeyboardController } from \"./controllers/keyboardController\";\nimport { PillsController } from \"./controllers/pillsController\";\nimport { buildDropdownOnly, updateDropdownOnly } from \"./render/renderDropdownOnly\";\nimport { buildDOM, type DOMRefs, updateDOM } from \"./render/renderInput\";\nimport { createStore } from \"./state\";\nimport { injectStyles } from \"./styleInjector\";\nimport type { CoreOptions, CoreState, RenderMode } from \"./types\";\n\nlet idCounter = 0;\nfunction stableId(): string {\n return `:ac-${++idCounter}:`;\n}\n\nfunction initialState(): CoreState {\n return {\n text: \"\",\n completedParams: [],\n suggestions: [],\n activeDropdownIndex: -1,\n newParamId: null,\n isLoading: false,\n isReady: false,\n error: null,\n segments: [],\n actionableSuggestions: [],\n filteredOptions: [],\n placeholderText: \"\",\n isDropdownOpen: false,\n filterBase: 0,\n filterInProgress: false,\n pillTapped: false,\n skipNextFetch: false,\n lastRawQuery: \"\",\n isFocused: false,\n };\n}\n\nexport class AIAutocomplete {\n private store = createStore<CoreState>(initialState());\n private _listboxId = stableId();\n private opts: CoreOptions;\n private fetchController: FetchController;\n private keyboardController: KeyboardController;\n private pillsController: PillsController;\n private modeController: ModeController | null = null;\n private container: HTMLElement;\n private unsubscribers: (() => void)[] = [];\n private derivedInProgress = false;\n private renderMode: RenderMode;\n private domRefs: DOMRefs | null = null;\n private dropdownRefs: { dropdown: HTMLElement } | null = null;\n private newParamTimer: number | undefined;\n private suggestionRemovalTimer: number | undefined;\n private externalListeners = new Set<(state: CoreState) => void>();\n private sessionId: string = crypto.randomUUID();\n\n constructor(container: HTMLElement, opts: CoreOptions = {}) {\n this.container = container;\n this.opts = opts;\n this.renderMode = opts.renderMode ?? \"full\";\n\n // Apply controlled initial values\n if (opts.value !== undefined) {\n this.store.set({ text: opts.value });\n }\n if (opts.completedParams !== undefined) {\n this.store.set({ completedParams: opts.completedParams });\n }\n\n // Controllers\n this.pillsController = new PillsController(this.store, {\n onPillSelected: ({ rawQuery, selectedPill, otherPills }) => {\n this.fireTelemetry(\"pill\", {\n raw_query: rawQuery,\n selected_pill: selectedPill,\n other_pills: otherPills,\n });\n },\n });\n\n this.fetchController = new FetchController(\n this.store,\n () => this.opts.apiConfig,\n () => this.opts.optionOverrides,\n () => this.opts.maskCompletedText,\n () => this.opts.onError,\n () => this.sessionId,\n {\n onAutoMatch: ({ active, matched, rawQuery }) => {\n this.fireTelemetry(\"option\", {\n raw_query: rawQuery,\n selected_option: matched.text,\n other_options: (active.options ?? [])\n .filter((o) => o.text !== matched.text)\n .map((o) => o.text),\n });\n },\n },\n );\n\n this.keyboardController = new KeyboardController(this.store, {\n columns: opts.columns ?? 2,\n listboxId: this.listboxId,\n getOnSubmit: () => this.opts.onSubmit,\n // Tier 1 (full) auto-resets after submit; Tier 2/3 leave it to the consumer.\n afterSubmit: this.renderMode === \"full\" ? () => this.reset() : undefined,\n selectOption: (option) => this.selectOption(option),\n });\n\n // Derived state recomputation\n this.unsubscribers.push(\n this.store.subscribe((next, prev) => {\n this.recomputeDerived(next, prev);\n }),\n );\n\n // Event callbacks\n this.unsubscribers.push(\n this.store.subscribe((next, prev) => {\n if (next.text !== prev.text) this.opts.onChange?.(next.text);\n if (next.completedParams !== prev.completedParams)\n this.opts.onParamsChange?.(next.completedParams);\n if (next.isFocused !== prev.isFocused) {\n if (next.isFocused) this.opts.onFocus?.();\n else this.opts.onBlur?.();\n }\n this.opts.onStateChange?.(next);\n }),\n );\n\n // Setup DOM based on render mode\n if (this.renderMode !== \"headless\") {\n injectStyles();\n this.setupContainer();\n }\n if (this.renderMode === \"full\") {\n this.buildAndRenderFull();\n } else if (this.renderMode === \"dropdown\") {\n this.buildAndRenderDropdown();\n }\n this.fetchController.start();\n }\n\n // === Public API ===\n\n focus() {\n this.domRefs?.textarea.focus();\n }\n\n blur() {\n this.domRefs?.textarea.blur();\n }\n\n reset() {\n // skipNextFetch suppresses the debounced fetch the FetchController would\n // otherwise schedule in response to text/params changing here — we issue\n // the empty fetch ourselves below so the new session starts immediately.\n this.store.set({\n ...initialState(),\n skipNextFetch: true,\n });\n this.sessionId = crypto.randomUUID();\n this.fetchController.doFetch(\"\", []);\n }\n\n destroy() {\n this.fetchController.dispose();\n this.modeController?.destroy();\n if (this.newParamTimer) clearTimeout(this.newParamTimer);\n if (this.suggestionRemovalTimer) clearTimeout(this.suggestionRemovalTimer);\n this.externalListeners.clear();\n for (const unsub of this.unsubscribers) unsub();\n this.unsubscribers = [];\n this.domRefs = null;\n this.dropdownRefs = null;\n if (this.renderMode !== \"headless\") {\n this.container.innerHTML = \"\";\n }\n }\n\n setMode(mode: AppearanceMode) {\n this.modeController?.setMode(mode);\n }\n\n setValue(text: string) {\n this.store.set({ text });\n }\n\n setCompletedParams(params: CompletedParamState[]) {\n this.store.set({ completedParams: params });\n }\n\n setActivePill(index: number) {\n this.pillsController.setActivePill(index);\n }\n\n removeLastParam() {\n this.pillsController.removeLastParam();\n }\n\n clearNewParamId() {\n this.store.set({ newParamId: null });\n }\n\n setActiveDropdownIndex(index: number) {\n this.store.set({ activeDropdownIndex: index });\n }\n\n handleTextChange(value: string) {\n this.handleChange(value);\n }\n\n handleKeyDown(e: KeyboardEvent) {\n this.keyboardController.handleKeyDown(e);\n }\n\n setFocused(focused: boolean) {\n if (this.store.get().isFocused === focused) return;\n this.store.set({ isFocused: focused });\n }\n\n /** Subscribe to state changes (fires after derived state is settled). Returns unsubscribe function. */\n subscribe(listener: (state: CoreState) => void): () => void {\n this.externalListeners.add(listener);\n return () => {\n this.externalListeners.delete(listener);\n };\n }\n\n getState(): CoreState {\n return this.store.get();\n }\n\n get listboxId(): string {\n return this._listboxId;\n }\n\n get isReady(): boolean {\n return this.store.get().isReady;\n }\n\n on(event: string, callback: (...args: unknown[]) => void): () => void {\n switch (event) {\n case \"submit\":\n this.opts.onSubmit = callback as CoreOptions[\"onSubmit\"];\n return () => {\n this.opts.onSubmit = undefined;\n };\n case \"error\":\n this.opts.onError = callback as CoreOptions[\"onError\"];\n return () => {\n this.opts.onError = undefined;\n };\n case \"change\":\n this.opts.onChange = callback as CoreOptions[\"onChange\"];\n return () => {\n this.opts.onChange = undefined;\n };\n case \"paramsChange\":\n this.opts.onParamsChange = callback as CoreOptions[\"onParamsChange\"];\n return () => {\n this.opts.onParamsChange = undefined;\n };\n case \"stateChange\":\n this.opts.onStateChange = callback as CoreOptions[\"onStateChange\"];\n return () => {\n this.opts.onStateChange = undefined;\n };\n case \"focus\":\n this.opts.onFocus = callback as CoreOptions[\"onFocus\"];\n return () => {\n this.opts.onFocus = undefined;\n };\n case \"blur\":\n this.opts.onBlur = callback as CoreOptions[\"onBlur\"];\n return () => {\n this.opts.onBlur = undefined;\n };\n default:\n return () => {};\n }\n }\n\n update(opts: Partial<CoreOptions>) {\n Object.assign(this.opts, opts);\n if (opts.mode !== undefined) {\n this.modeController?.setMode(opts.mode);\n }\n if (opts.optionsPosition !== undefined) {\n this.container.dataset.optionsPosition = opts.optionsPosition;\n }\n if (opts.animations !== undefined) {\n this.container.dataset.animations = opts.animations ? \"on\" : \"off\";\n }\n if (opts.pillPlacement !== undefined) {\n this.container.dataset.pillPlacement = opts.pillPlacement;\n this.store.set({});\n }\n if (opts.dropdownTrigger !== undefined || opts.closeDropdownOnBlur !== undefined) {\n // Trigger recompute so isDropdownOpen updates\n this.store.set({});\n }\n if (opts.value !== undefined) {\n this.store.set({ text: opts.value });\n }\n if (opts.completedParams !== undefined) {\n this.store.set({ completedParams: opts.completedParams });\n }\n }\n\n // === Public (for framework wrappers) ===\n\n selectOption(option: SuggestionOption) {\n const state = this.store.get();\n const activeSuggestion = state.actionableSuggestions[0];\n if (!activeSuggestion) return;\n\n const { rawQuery: telemetryRawQuery } = buildQuery(state.text, state.completedParams);\n this.fireTelemetry(\"option\", {\n raw_query: telemetryRawQuery,\n selected_option: option.text,\n other_options: state.filteredOptions.filter((o) => o.text !== option.text).map((o) => o.text),\n });\n\n const base = state.filterBase;\n let prefix = state.text.slice(0, base);\n\n const inputWasEmpty = prefix.length === 0 && state.text.length === 0;\n // The user is still typing within the server-provided placeholder (e.g. typed\n // \"Cre\" for placeholder \"Create a\"). Selecting an option here should keep the\n // placeholder rather than discard it — otherwise tapping \"email\" replaces\n // \"Cre\" with just \"email\" instead of \"Create a email\".\n const inputIsPlaceholderPrefix =\n prefix.length === 0 &&\n state.text.length > 0 &&\n state.placeholderText.length > 0 &&\n state.placeholderText.toLowerCase().startsWith(state.text.toLowerCase());\n if ((inputWasEmpty || inputIsPlaceholderPrefix) && state.placeholderText) {\n prefix = `${state.placeholderText} `;\n }\n\n const overlapChars = findPrefixOverlap(prefix, option.text);\n if (overlapChars > 0) {\n prefix = prefix.slice(0, prefix.length - overlapChars);\n }\n\n const needsSpace = prefix.length > 0 && prefix[prefix.length - 1] !== \" \";\n const newText = `${prefix}${needsSpace ? \" \" : \"\"}${option.text} `;\n const finalText =\n (inputWasEmpty || inputIsPlaceholderPrefix) && newText.length > 0\n ? newText[0].toUpperCase() + newText.slice(1)\n : newText;\n\n const optionStart = finalText.toLowerCase().lastIndexOf(option.text.toLowerCase());\n const optionInFinal =\n optionStart >= 0\n ? finalText.slice(optionStart, optionStart + option.text.length)\n : option.text;\n\n const completed: CompletedParamState = {\n id: crypto.randomUUID(),\n placeholder: \"\",\n type: activeSuggestion.type,\n text: optionInFinal,\n kind: option.kind,\n suggestionType: activeSuggestion.type,\n suggestionPlaceholder: activeSuggestion.text,\n options: activeSuggestion.options ?? [],\n metadata: option.metadata,\n };\n\n const remainingActionable = state.actionableSuggestions.length - 1;\n\n this.store.set((s) => ({\n text: finalText,\n filterBase: finalText.length,\n completedParams: [...s.completedParams, completed],\n newParamId: completed.id,\n pillTapped: false,\n activeDropdownIndex: -1,\n skipNextFetch: remainingActionable > 0,\n }));\n\n // Delay suggestion removal for animation\n this.suggestionRemovalTimer = window.setTimeout(() => {\n this.store.set((s) => ({\n suggestions: s.suggestions.filter((sg) => sg !== activeSuggestion),\n }));\n }, 400);\n }\n\n private fireTelemetry(type: \"pill\" | \"option\", queryData: Record<string, unknown>) {\n // Vanilla consumers don't pass `source` — derive from renderMode.\n // The React hook always uses renderMode \"headless\" but Tier 1 explicitly\n // passes source: \"full-sdk\" via opts to override.\n const source: TelemetrySource =\n this.opts.source ?? (this.renderMode === \"full\" ? \"full-sdk\" : \"headless-sdk\");\n void sendTelemetry({\n source,\n sessionId: this.sessionId,\n type,\n queryData,\n apiConfig: this.opts.apiConfig,\n });\n }\n\n private recomputeDerived(next: CoreState, _prev: CoreState) {\n if (this.derivedInProgress) return;\n this.derivedInProgress = true;\n const segments = deriveSegments(next.text, next.completedParams);\n const actionableSuggestions = next.suggestions.filter((s) => s.type !== \"placeholder\");\n const activeSuggestion = actionableSuggestions[0] as Suggestion | undefined;\n const overrideFn = activeSuggestion\n ? this.opts.optionOverrides?.[activeSuggestion.type]\n : undefined;\n\n // Clamp filterBase so it never exceeds text length (matches old React behavior)\n const clampedFilterBase = Math.min(next.filterBase, next.text.length);\n // When filterBase is 0 and no fetch has set it yet, don't filter by typed text —\n // the user is still typing the initial query and no server context exists\n const hasServerContext = next.lastRawQuery !== \"\" || clampedFilterBase > 0;\n const filterQuery = hasServerContext\n ? extractFilterQuery(next.text, clampedFilterBase, next.filterInProgress)\n : \"\";\n const baseOptions = activeSuggestion\n ? overrideFn\n ? overrideFn(filterQuery.trim())\n : (activeSuggestion.options ?? [])\n : [];\n const filteredOptions = filterOptions(baseOptions, filterQuery);\n\n const placeholderText = next.suggestions\n .filter((s) => s.type === \"placeholder\")\n .map((s) => s.text)\n .join(\" \");\n\n const trigger = this.opts.dropdownTrigger ?? \"auto\";\n const closeOnBlur = this.opts.closeDropdownOnBlur ?? true;\n let isDropdownOpen = false;\n if (trigger === \"auto\") {\n const focusGate = closeOnBlur ? next.isFocused : true;\n isDropdownOpen = !next.isLoading && filteredOptions.length > 0 && focusGate;\n } else if (trigger === \"manual\") {\n isDropdownOpen = !next.isLoading && filteredOptions.length > 0 && next.pillTapped;\n }\n\n this.store.set({\n segments,\n actionableSuggestions,\n filteredOptions,\n placeholderText,\n isDropdownOpen,\n });\n this.derivedInProgress = false;\n\n // Notify external listeners after derived state is settled\n const settled = this.store.get();\n for (const listener of this.externalListeners) {\n listener(settled);\n }\n }\n\n private setupContainer() {\n this.container.classList.add(\"magicx-aia\");\n // In dropdown mode, pills are always in the dropdown\n this.container.dataset.pillPlacement =\n this.renderMode === \"dropdown\" ? \"dropdown\" : (this.opts.pillPlacement ?? \"inline\");\n this.container.dataset.optionsPosition = this.opts.optionsPosition ?? \"below\";\n this.container.dataset.animations = (this.opts.animations ?? true) ? \"on\" : \"off\";\n\n // ModeController\n this.modeController = new ModeController(this.container, this.opts.mode ?? \"auto\");\n }\n\n private buildAndRenderFull() {\n const self = this;\n const renderOpts = {\n store: this.store,\n listboxId: this.listboxId,\n get pillPlacement() {\n return (self.opts.pillPlacement ?? \"inline\") as \"inline\" | \"dropdown\";\n },\n get onSubmit() {\n return self.opts.onSubmit;\n },\n // Tier 1 only (this code path runs only for renderMode === \"full\").\n afterSubmit: () => self.reset(),\n submitButton: this.opts.submitButton,\n autoFocus: this.opts.autoFocus ?? true,\n selectOption: (option: SuggestionOption) => this.selectOption(option),\n setActivePill: (index: number) => this.pillsController.setActivePill(index),\n handleKeyDown: (e: KeyboardEvent) => this.keyboardController.handleKeyDown(e),\n handleChange: (value: string) => this.handleChange(value),\n };\n\n this.domRefs = buildDOM(this.container, renderOpts);\n\n this.subscribeBatchedRender(() => {\n if (this.domRefs) {\n updateDOM(this.domRefs, this.store.get(), renderOpts);\n }\n });\n\n // Initial render\n updateDOM(this.domRefs, this.store.get(), renderOpts);\n this.subscribeNewParamTimer();\n }\n\n private buildAndRenderDropdown() {\n const dropdownOpts = {\n store: this.store,\n listboxId: this.listboxId,\n selectOption: (option: SuggestionOption) => this.selectOption(option),\n setActivePill: (index: number) => this.pillsController.setActivePill(index),\n };\n\n this.dropdownRefs = buildDropdownOnly(this.container, dropdownOpts);\n\n this.subscribeBatchedRender(() => {\n if (this.dropdownRefs) {\n updateDropdownOnly(this.dropdownRefs, this.store.get(), dropdownOpts);\n }\n });\n\n // Initial render\n updateDropdownOnly(this.dropdownRefs, this.store.get(), dropdownOpts);\n this.subscribeNewParamTimer();\n }\n\n /** Batched render subscriber — coalesces multiple store.set calls into one DOM update. */\n private subscribeBatchedRender(render: () => void) {\n let scheduled = false;\n this.unsubscribers.push(\n this.store.subscribe(() => {\n if (scheduled) return;\n scheduled = true;\n queueMicrotask(() => {\n scheduled = false;\n render();\n });\n }),\n );\n }\n\n /** Auto-clear newParamId after shimmer animation. */\n private subscribeNewParamTimer() {\n this.unsubscribers.push(\n this.store.subscribe((next, prev) => {\n if (next.newParamId && next.newParamId !== prev.newParamId) {\n if (this.newParamTimer) clearTimeout(this.newParamTimer);\n this.newParamTimer = window.setTimeout(() => {\n this.store.set({ newParamId: null });\n }, 650);\n }\n }),\n );\n }\n\n private handleChange(newValue: string) {\n const state = this.store.get();\n this.store.set({\n text: newValue,\n pillTapped: false,\n activeDropdownIndex: -1,\n });\n\n const { valid, invalid } = reconcileParams(newValue, state.completedParams);\n if (invalid.length > 0) {\n this.store.set((s) => ({\n completedParams: valid,\n suggestions: [\n ...invalid.map((param) => ({\n type: param.suggestionType,\n text: param.suggestionPlaceholder,\n required: true,\n options: param.options,\n })),\n ...s.suggestions,\n ],\n }));\n }\n }\n}\n"],"mappings":"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AA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA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","names":["forwardRef","useCallback","useEffect","useImperativeHandle","useRef","s","AIAutocomplete_module_css_default","s","AIAutocompleteDropdown_module_css_default","s","PillList_module_css_default","jsx","getPillOpacity","index","PillList","pills","activePillIndex","onSelectPill","rounded","PillList_module_css_default","pill","i","useEffect","useLayoutEffect","useRef","useState","s","SuggestionGrid_module_css_default","useEffect","useRef","useState","s","SuggestionItem_module_css_default","jsx","jsxs","SuggestionItem","option","isHighlighted","onSelect","onHighlight","id","pressed","setPressed","useState","timerRef","useRef","useEffect","handleSelect","className","SuggestionItem_module_css_default","e","jsx","SuggestionGrid","options","activeIndex","onSelect","onHighlight","listboxId","gridRef","useRef","hasBottomOverflow","setHasBottomOverflow","useState","useEffect","el","update","resizeObserver","useLayoutEffect","SuggestionGrid_module_css_default","option","i","SuggestionItem","jsx","jsxs","AIAutocompleteDropdown","suggestions","activeIndex","onSelect","onHighlight","isOpen","id","className","pills","onPillClick","showPills","options","hasPills","isVisible","AIAutocompleteDropdown_module_css_default","e","PillList","SuggestionGrid","s","useCallback","useEffect","useRef","useState","buildQuery","text","completedParams","result","typeCounts","updatedParams","param","count","placeholder","index","extractFilterQuery","text","filterBase","isInProgress","rawRegion","spaceIdx","findPrefixOverlap","prefix","optionText","trimmed","words","optionLower","i","candidate","suffixStart","filterOptions","options","query","lower","o","findExactMatch","ModeController","container","mode","deriveSegments","text","completedParams","result","pos","param","idx","remaining","reconcileParams","valid","invalid","TokenManager","config","forceRefresh","result","tokenManagers","isAccessTokenConfig","config","getApiKeyConfig","getTokenManager","manager","TokenManager","buildHeaders","apiConfig","buildApiKeyAuthHeader","apiKeyConfig","apiKey","DEFAULT_SUGGEST_ENDPOINT","TELEMETRY_PATH","deriveTelemetryEndpoint","suggestEndpoint","base","resolveAuthHeader","apiConfig","isAccessTokenConfig","getTokenManager","buildApiKeyAuthHeader","sendTelemetry","event","endpoint","headers","buildHeaders","authHeader","body","SDK_VERSION","hasWarnedMissingKey","generateRequestId","toWireParam","param","includeText","buildRequestBody","rawQuery","completedParams","sessionId","rawCount","p","contactAccountCount","doFetch","endpoint","headers","token","body","signal","fetchSuggestions","options","apiConfig","buildHeaders","jsonBody","isAccessTokenConfig","manager","getTokenManager","response","newToken","authHeader","buildApiKeyAuthHeader","applyOptionOverrides","suggestions","overrides","s","fn","extra","existingTexts","o","deduped","DEBOUNCE_MS","SLOW_DEBOUNCE_MS","MIN_CHARS_DIFF","FetchController","store","getApiConfig","getOptionOverrides","getMaskCompletedText","getOnError","getSessionId","callbacks","prevText","prevParams","next","rawQuery","completed","controller","version","state","textAtRequest","s","res","fetchSuggestions","newSuggestions","applyOptionOverrides","input","lastInput","currentText","filterBase","filterInProgress","inProgressIdx","active","extraParam","query","extractFilterQuery","match","findExactMatch","err","caughtError","attemptFetch","minDiff","currentQuery","sg","tappableFiltered","filterOptions","o","hasExactMatch","isInFilterZone","placeholderText","updatedParams","buildQuery","isDeleting","charDiff","KeyboardController","store","ctx","state","listboxId","getOnSubmit","columns","onSubmit","tappableIndices","target","currentPos","nextPos","prevPos","rightNeighbor","leftNeighbor","rawQuery","finalParams","buildQuery","placeholderVisible","hasHighlightedOption","placeholderSuggestion","s","sg","firstTappableIdx","o","tappable","i","buckets","grid","tracks","index","options","optionEl","actionable","moved","rest","_","placeholders","PillsController","store","callbacks","index","state","actionable","s","moved","rest","_","i","placeholders","rawQuery","buildQuery","lastParam","restoredSuggestion","getPillOpacity","index","renderPills","container","pills","activePillIndex","onSelectPill","rounded","list","existing","btn","used","i","pill","key","createDropdown","listboxId","dropdown","e","renderDropdown","state","filteredOptions","activeIndex","isOpen","pills","showPills","onSelect","onHighlight","onPillClick","hasPills","pillBar","renderPills","grid","renderOptions","options","optionsKey","o","lastKey","listChanged","fragment","i","option","item","createOptionElement","items","isHighlighted","index","classes","streaks","streaksVert","content","tag","buildDropdownOnly","container","opts","dropdown","createDropdown","updateDropdownOnly","refs","state","renderDropdown","renderSegments","sizer","segments","newParamId","isEmpty","placeholderText","sizerText","placeholder","segmentKey","s","lastKey","lastParamId","seg","span","SUBMIT_SVG","buildDOM","container","opts","listboxId","dropdown","createDropdown","inputWrapper","editor","sizer","inlinePillContainer","textarea","submitButton","submitTarget","raw","newValue","e","state","rawQuery","finalParams","buildQuery","updateDOM","refs","pillPlacement","setActivePill","selectOption","store","activeDescendant","canSubmit","renderSegments","renderPills","renderDropdown","i","createStore","initial","state","listeners","patch","resolved","next","prev","l","listener","injected","injectStyles","style","STYLES","idCounter","stableId","initialState","AIAutocomplete","container","opts","createStore","PillsController","rawQuery","selectedPill","otherPills","FetchController","active","matched","o","KeyboardController","option","next","prev","injectStyles","unsub","mode","text","params","index","value","focused","listener","event","callback","state","activeSuggestion","telemetryRawQuery","buildQuery","base","prefix","inputWasEmpty","inputIsPlaceholderPrefix","overlapChars","findPrefixOverlap","needsSpace","newText","finalText","optionStart","optionInFinal","completed","remainingActionable","s","sg","type","queryData","source","sendTelemetry","_prev","segments","deriveSegments","actionableSuggestions","overrideFn","clampedFilterBase","filterQuery","extractFilterQuery","baseOptions","filteredOptions","filterOptions","placeholderText","trigger","closeOnBlur","isDropdownOpen","focusGate","settled","ModeController","self","renderOpts","e","buildDOM","updateDOM","dropdownOpts","buildDropdownOnly","updateDropdownOnly","render","scheduled","newValue","valid","invalid","reconcileParams","param","useAIAutocomplete","onSubmit","onError","optionOverrides","maskCompletedText","apiConfig","columns","dropdownTrigger","closeDropdownOnBlur","onFocus","onBlur","controlledValue","controlledParams","onChangeProp","onParamsChange","source","instanceRef","useRef","coreState","setCoreState","useState","onSubmitRef","onErrorRef","onChangeRef","onParamsChangeRef","onFocusRef","onBlurRef","useEffect","instance","AIAutocomplete","args","unsub","state","noop","useCallback","apiConfigJson","prevOverridesRef","overridesVersion","prev","next","prevKeys","nextKeys","k","handleChange","e","raw","newValue","handleKeyDown","handleFocus","handleBlur","setActivePill","index","removeLastParam","clearNewParamId","reset","selectOption","option","setActiveDropdownIndex","text","completedParams","actionableSuggestions","activeSuggestion","filteredOptions","activeDescendantId","jsx","jsxs","resolveInitialMode","mode","AIAutocomplete","forwardRef","onSubmit","onError","optionOverrides","maskCompletedText","className","apiConfig","columns","pillPlacement","optionsPosition","animations","dropdownTrigger","closeDropdownOnBlur","autoFocus","onFocus","onBlur","value","controlledParams","onChangeProp","onParamsChange","submitButton","ref","containerRef","useRef","textareaRef","handleSubmitRef","modeControllerRef","useEffect","el","ModeController","completedParams","suggestionPills","setActivePill","segments","newParamId","clearNewParamId","inputProps","dropdownProps","reset","useAIAutocomplete","result","focusHandler","ta","timeoutId","useImperativeHandle","m","handleContainerClick","canSubmit","handleSubmit","useCallback","rawQuery","finalParams","buildQuery","onChange","inputPlaceholder","restProps","isEmpty","showInlinePills","showDropdownPills","AIAutocomplete_module_css_default","AIAutocompleteDropdown","seg","i","cls","PillList","e"]}
1
+ {"version":3,"sources":["../src/AIAutocomplete.tsx","css-module:/Users/saharshv/MagicX/ai-autocomplete-react/src/AIAutocomplete.module.css.js","css-module:/Users/saharshv/MagicX/ai-autocomplete-react/src/AIAutocompleteDropdown.module.css.js","css-module:/Users/saharshv/MagicX/ai-autocomplete-react/src/components/PillList.module.css.js","../src/components/PillList.tsx","../src/components/SuggestionGrid.tsx","css-module:/Users/saharshv/MagicX/ai-autocomplete-react/src/components/SuggestionGrid.module.css.js","../src/components/SuggestionItem.tsx","css-module:/Users/saharshv/MagicX/ai-autocomplete-react/src/components/SuggestionItem.module.css.js","../src/AIAutocompleteDropdown.tsx","plain-css:/Users/saharshv/MagicX/ai-autocomplete-react/src/appearance.css.js","../src/hooks/useAIAutocomplete.ts","../src/utils/buildQuery.ts","../src/utils/filtering.ts","../src/utils/modeController.ts","../src/utils/segments.ts","../src/utils/tokenManager.ts","../src/utils/auth.ts","../src/utils/telemetry.ts","../src/utils/api.ts","../src/utils/overrides.ts","../src/core/controllers/fetchController.ts","../src/core/controllers/keyboardController.ts","../src/core/controllers/pillsController.ts","../src/core/render/renderPills.ts","../src/core/render/renderDropdown.ts","../src/core/render/renderDropdownOnly.ts","../src/core/render/renderSegments.ts","../src/core/render/renderInput.ts","../src/core/state.ts","../src/core/styleInjector.ts","../src/core/AIAutocomplete.ts"],"sourcesContent":["import { forwardRef, useCallback, useEffect, useImperativeHandle, useRef } from \"react\";\nimport styles from \"./AIAutocomplete.module.css\";\nimport { AIAutocompleteDropdown } from \"./AIAutocompleteDropdown\";\nimport \"./appearance.css\";\nimport { PillList } from \"./components/PillList\";\nimport { useAIAutocomplete } from \"./hooks/useAIAutocomplete\";\nimport type {\n AIAutocompleteHandle,\n AIAutocompleteProps,\n AppearanceMode,\n AutocompleteResult,\n} from \"./types\";\nimport { buildQuery } from \"./utils/buildQuery\";\nimport { ModeController } from \"./utils/modeController\";\n\nfunction resolveInitialMode(mode: AppearanceMode): \"light\" | \"dark\" {\n if (mode !== \"auto\") return mode;\n if (typeof window === \"undefined\") return \"dark\";\n return window.matchMedia(\"(prefers-color-scheme: dark)\").matches ? \"dark\" : \"light\";\n}\n\nexport const AIAutocomplete = forwardRef<AIAutocompleteHandle, AIAutocompleteProps>(\n function AIAutocomplete(\n {\n onSubmit,\n onError,\n optionOverrides,\n maskCompletedText,\n className,\n apiConfig,\n columns,\n pillPlacement = \"inline\",\n mode = \"auto\",\n optionsPosition = \"below\",\n animations = true,\n dropdownTrigger,\n closeDropdownOnBlur,\n autoFocus = true,\n onFocus,\n onBlur,\n value,\n completedParams: controlledParams,\n onChange: onChangeProp,\n onParamsChange,\n submitButton,\n },\n ref,\n ) {\n const containerRef = useRef<HTMLDivElement>(null);\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n // Render-phase ref assignment — matches the pattern in useAIAutocomplete.ts\n const handleSubmitRef = useRef<(result: AutocompleteResult) => void>(() => {});\n const modeControllerRef = useRef<ModeController | null>(null);\n\n // ModeController — keeps data-mode updated for live prefers-color-scheme changes\n // Initial data-mode is set synchronously in JSX via resolveInitialMode()\n useEffect(() => {\n const el = containerRef.current;\n if (!el) return;\n if (modeControllerRef.current) {\n modeControllerRef.current.setMode(mode);\n } else {\n modeControllerRef.current = new ModeController(el, mode);\n }\n return () => {\n modeControllerRef.current?.destroy();\n modeControllerRef.current = null;\n };\n }, [mode]);\n\n const {\n completedParams,\n suggestionPills,\n setActivePill,\n segments,\n newParamId,\n clearNewParamId,\n inputProps,\n dropdownProps,\n reset,\n } = useAIAutocomplete({\n onSubmit: (result) => handleSubmitRef.current(result),\n onError,\n optionOverrides,\n maskCompletedText,\n apiConfig,\n columns,\n dropdownTrigger,\n closeDropdownOnBlur,\n onFocus,\n onBlur,\n value,\n completedParams: controlledParams,\n onChange: onChangeProp,\n onParamsChange,\n source: \"full-sdk\",\n });\n\n // Auto-focus on mount. Depends on inputProps.onFocus so we re-run once the\n // hook's instance is ready — otherwise the focus event fires before the\n // real handler is wired and the auto-trigger dropdown stays closed.\n const focusHandler = inputProps.onFocus;\n useEffect(() => {\n if (!autoFocus) return;\n const ta = textareaRef.current;\n if (!ta) return;\n if (document.activeElement === ta) {\n focusHandler();\n } else {\n ta.focus();\n }\n }, [focusHandler, autoFocus]);\n\n // Clear shimmer after animation completes\n useEffect(() => {\n if (!newParamId) return;\n const timeoutId = window.setTimeout(() => clearNewParamId(), 650);\n return () => window.clearTimeout(timeoutId);\n }, [newParamId, clearNewParamId]);\n\n useImperativeHandle(\n ref,\n () => ({\n focus: () => textareaRef.current?.focus(),\n blur: () => textareaRef.current?.blur(),\n reset,\n setMode: (m) => modeControllerRef.current?.setMode(m),\n }),\n [reset],\n );\n\n const handleContainerClick = () => {\n textareaRef.current?.focus();\n };\n\n const canSubmit = !!inputProps.value || completedParams.length > 0;\n\n const handleSubmit = useCallback(() => {\n if (!canSubmit) return;\n const { rawQuery, completedParams: finalParams } = buildQuery(\n inputProps.value,\n completedParams,\n );\n onSubmit({\n query: inputProps.value.trim(),\n raw_query: rawQuery,\n completed_params: finalParams,\n });\n reset();\n }, [canSubmit, inputProps.value, completedParams, onSubmit, reset]);\n\n handleSubmitRef.current = handleSubmit;\n\n const { onChange, placeholder: inputPlaceholder, ...restProps } = inputProps;\n const isEmpty = !inputProps.value;\n\n const showInlinePills = pillPlacement === \"inline\";\n const showDropdownPills = pillPlacement === \"dropdown\";\n\n return (\n <div\n ref={containerRef}\n className={`magicx-aia ${styles.container} ${className ?? \"\"}`}\n data-pill-placement={pillPlacement}\n data-options-position={optionsPosition}\n data-animations={animations ? \"on\" : \"off\"}\n data-mode={resolveInitialMode(mode)}\n >\n <AIAutocompleteDropdown {...dropdownProps} showPills={showDropdownPills} />\n {/* biome-ignore lint/a11y/useKeyWithClickEvents: container click delegates to textarea focus */}\n {/* biome-ignore lint/a11y/noStaticElementInteractions: wrapper delegates focus to textarea */}\n <div className={styles.inputWrapper} onClick={handleContainerClick}>\n <div className={styles.editorArea} data-aia-editor=\"\">\n <div className={styles.sizerContent} aria-hidden=\"true\">\n {isEmpty && inputPlaceholder ? (\n <span className={styles.placeholderText}>{inputPlaceholder} </span>\n ) : (\n <span\n className={`${styles.sizerText} ${newParamId ? styles.sizerTextVisible : \"\"}`}\n >\n {segments.map((seg, i) => {\n const isNew = seg.type === \"completed\" && seg.param.id === newParamId;\n if (isNew) {\n const cls = `${styles.shimmerRevealed} ${styles.shimmerSweep}`;\n return (\n // biome-ignore lint/suspicious/noArrayIndexKey: segments are positional and don't reorder\n <span key={`${i}-${seg.type}`} className={cls}>\n {seg.value}\n </span>\n );\n }\n return (\n // biome-ignore lint/suspicious/noArrayIndexKey: segments are positional and don't reorder\n <span key={`${i}-${seg.type}`}>{seg.value}</span>\n );\n })}\n {segments.length === 0 && \"\\u00A0\"}\n </span>\n )}{\" \"}\n {showInlinePills && (\n <PillList\n pills={suggestionPills}\n activePillIndex={0}\n onSelectPill={setActivePill}\n />\n )}\n </div>\n <textarea\n ref={textareaRef}\n data-aia-textarea=\"\"\n className={`${styles.textarea} ${newParamId ? styles.textareaHidden : \"\"}`}\n rows={1}\n onChange={onChange}\n {...restProps}\n />\n </div>\n {submitButton === null ? null : submitButton === undefined ? (\n <button\n type=\"button\"\n data-aia-submit=\"\"\n className={styles.submitButton}\n disabled={!canSubmit}\n onClick={(e) => {\n e.stopPropagation();\n handleSubmit();\n }}\n aria-label=\"Submit\"\n >\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 18 18\"\n fill=\"none\"\n role=\"img\"\n aria-label=\"Submit\"\n >\n <path\n d=\"M9 14V4M9 4L4 9M9 4L14 9\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n </button>\n ) : (\n // biome-ignore lint/a11y/useKeyWithClickEvents: consumer-provided element handles its own keyboard interaction\n // biome-ignore lint/a11y/noStaticElementInteractions: transparent slot — click bubbles from consumer's element\n <span\n data-aia-submit=\"\"\n className={styles.submitSlot}\n onClick={(e) => {\n if (!canSubmit) return;\n e.stopPropagation();\n handleSubmit();\n }}\n >\n {submitButton}\n </span>\n )}\n </div>\n </div>\n );\n },\n);\n","if (typeof document !== \"undefined\" && !document.getElementById(\"ac-style-cc65f4cc\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-cc65f4cc\";\n s.textContent = `.AIAutocomplete-module_container_KKjFU {\n position: relative;\n font-family: \"IBM Plex Sans\", sans-serif;\n container-type: inline-size;\n}\n\n.AIAutocomplete-module_inputWrapper_FLq1b {\n padding: 20px;\n border: 1px solid var(--aia-color-border-default, #9ea5b2);\n border-radius: 23px;\n background: transparent;\n overflow: hidden;\n display: flex;\n align-items: center;\n gap: 0px;\n}\n\n.AIAutocomplete-module_editorArea_7rBWq {\n position: relative;\n flex: 1;\n min-width: 0;\n}\n\n.AIAutocomplete-module_sizerContent_DQgmV {\n position: relative;\n z-index: 1;\n pointer-events: none;\n white-space: pre-wrap;\n word-break: break-word;\n font-family: inherit;\n font-size: var(--aia-written-text-font-size, 19px);\n line-height: 38px;\n}\n\n.AIAutocomplete-module_sizerText_iZIMK {\n color: transparent;\n}\n\n.AIAutocomplete-module_sizerTextVisible_HR-5h {\n color: var(--aia-written-text-color, var(--aia-color-text-default, #fff));\n font-size: var(--aia-written-text-font-size, inherit);\n}\n\n.AIAutocomplete-module_textareaHidden_UayJt {\n color: transparent !important;\n}\n\n.AIAutocomplete-module_placeholderText_K3ayy {\n color: var(--aia-color-text-muted, #c1c4cb);\n opacity: 0.4;\n}\n\n.AIAutocomplete-module_textarea_eyn6A {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n padding: 0;\n border: none;\n background: transparent;\n color: var(--aia-written-text-color, var(--aia-color-text-default, #fff));\n caret-color: var(\n --aia-caret-color,\n var(--aia-written-text-color, var(--aia-color-text-default, #fff))\n );\n font-family: inherit;\n font-size: var(--aia-written-text-font-size, 19px);\n line-height: 38px;\n white-space: pre-wrap;\n word-break: break-word;\n outline: none;\n resize: none;\n overflow: hidden;\n}\n\n.AIAutocomplete-module_textarea_eyn6A::placeholder {\n color: var(--aia-color-text-muted, #c1c4cb);\n}\n\n.AIAutocomplete-module_submitButton_sl1Mi {\n flex-shrink: 0;\n width: 36px;\n height: 36px;\n border-radius: 50%;\n border: none;\n background: var(--aia-submit-bg, var(--aia-color-text-default, #fff));\n color: var(--aia-submit-color, var(--aia-color-bg-default, #000));\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n transition: opacity 0.2s ease;\n}\n\n.AIAutocomplete-module_submitButton_sl1Mi:hover {\n opacity: 0.85;\n}\n\n.AIAutocomplete-module_submitSlot_GhuCM {\n display: contents;\n}\n\n/* Text shimmer on newly added completed param.\n The sizer sits above the textarea (z-index: 1). Normally sizer text is\n transparent and the textarea shows the real text. During the shimmer, we\n make this span visible with a moving gradient clipped to the text shape,\n so the shimmer renders on top of the textarea's static white text. */\n\n.AIAutocomplete-module_shimmer_13AnY {\n position: relative;\n z-index: 2;\n display: inline;\n}\n\n.AIAutocomplete-module_shimmerRevealed_RR8dp {\n color: transparent;\n background: linear-gradient(\n 120deg,\n var(--aia-written-text-color, var(--aia-color-text-default, #fff)) 0%,\n var(--aia-written-text-color, var(--aia-color-text-default, #fff)) 44%,\n #b0b0b0 48%,\n #b0b0b0 52%,\n var(--aia-written-text-color, var(--aia-color-text-default, #fff)) 56%,\n var(--aia-written-text-color, var(--aia-color-text-default, #fff)) 100%\n );\n background-size: 200% 100%;\n -webkit-background-clip: text;\n background-clip: text;\n}\n\n.AIAutocomplete-module_shimmerSweep_ARCon {\n animation: AIAutocomplete-module_textShimmer_eCLdq 650ms ease-out forwards;\n}\n\n@keyframes AIAutocomplete-module_textShimmer_eCLdq {\n 0% {\n background-position: 100% 0;\n }\n 100% {\n background-position: -50% 0;\n }\n}\n\n.AIAutocomplete-module_shimmerHidden_45-Pf {\n color: transparent !important;\n}\n`;\n document.head.appendChild(s);\n}\nexport default {\"container\":\"AIAutocomplete-module_container_KKjFU\",\"inputWrapper\":\"AIAutocomplete-module_inputWrapper_FLq1b\",\"editorArea\":\"AIAutocomplete-module_editorArea_7rBWq\",\"sizerContent\":\"AIAutocomplete-module_sizerContent_DQgmV\",\"sizerText\":\"AIAutocomplete-module_sizerText_iZIMK\",\"sizerTextVisible\":\"AIAutocomplete-module_sizerTextVisible_HR-5h\",\"textareaHidden\":\"AIAutocomplete-module_textareaHidden_UayJt\",\"placeholderText\":\"AIAutocomplete-module_placeholderText_K3ayy\",\"textarea\":\"AIAutocomplete-module_textarea_eyn6A\",\"submitButton\":\"AIAutocomplete-module_submitButton_sl1Mi\",\"submitSlot\":\"AIAutocomplete-module_submitSlot_GhuCM\",\"shimmer\":\"AIAutocomplete-module_shimmer_13AnY\",\"shimmerRevealed\":\"AIAutocomplete-module_shimmerRevealed_RR8dp\",\"shimmerSweep\":\"AIAutocomplete-module_shimmerSweep_ARCon\",\"textShimmer\":\"AIAutocomplete-module_textShimmer_eCLdq\",\"shimmerHidden\":\"AIAutocomplete-module_shimmerHidden_45-Pf\"};","if (typeof document !== \"undefined\" && !document.getElementById(\"ac-style-2eef895d\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-2eef895d\";\n s.textContent = `.AIAutocompleteDropdown-module_dropdown_yz2KC {\n position: absolute;\n left: 0;\n right: 0;\n top: 100%;\n max-width: 516px;\n margin-top: 6px;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n container-type: inline-size;\n z-index: 10;\n opacity: 0;\n pointer-events: none;\n transition: opacity 400ms cubic-bezier(0.4, 0, 0.2, 1);\n box-shadow:\n hsla(0, 0%, 100%, 1) -3.2px -3.2px 3.2px -3.2px inset,\n hsla(0, 0%, 100%, 1) 6.4px 6.4px 1.6px -8px inset,\n var(--aia-dropdown-bg, transparent) -6.4px 6.4px 1.6px -8px inset, /* same color as bg */\n var(--aia-dropdown-bg, transparent) 6.4px -6.4px 1.6px -8px inset, /* same color as bg */\n hsla(0, 0%, 100%, 0.15) -1.6px 0px 0px -1.6px inset,\n hsla(0, 0%, 100%, 0.15) 0px -1.6px 0px -1.6px inset,\n hsla(0, 0%, 100%, 0.3) 0px 1.6px 0px 0px inset,\n hsla(0, 0%, 100%, 0.3) 1.6px 0px 0px 0px inset,\n inset 0 0 30px 5px hsla(0, 0%, 0%, 0.05),\n hsla(0, 0%, 0%, 0.08) 0px 0px 30px 2px;\n backdrop-filter: blur(30px);\n border-radius: 28px;\n}\n\n.AIAutocompleteDropdown-module_visible_QCoXj {\n opacity: 1;\n pointer-events: auto;\n}\n\n.AIAutocompleteDropdown-module_pillBar_pwTXe {\n padding: 27px 27px 0px 27px;\n}\n`;\n document.head.appendChild(s);\n}\nexport default {\"dropdown\":\"AIAutocompleteDropdown-module_dropdown_yz2KC\",\"visible\":\"AIAutocompleteDropdown-module_visible_QCoXj\",\"pillBar\":\"AIAutocompleteDropdown-module_pillBar_pwTXe\"};","if (typeof document !== \"undefined\" && !document.getElementById(\"ac-style-b745b4fb\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-b745b4fb\";\n s.textContent = `.PillList-module_list_qvLqO {\n position: relative;\n z-index: 1;\n pointer-events: auto;\n display: inline-flex;\n gap: 5px;\n align-items: center;\n vertical-align: middle;\n transform: translateY(-3px);\n}\n\n.PillList-module_pill_osSyz {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n height: 36px;\n padding: 13px 13px;\n border: none;\n border-radius: 999px;\n background: rgba(49, 50, 85, 0.25);\n background: color-mix(\n in srgb,\n var(--aia-pill-bg, var(--aia-color-background-supportive, #313255)) 25%,\n transparent\n );\n color: var(--aia-pill-color, var(--aia-color-text-muted, #c1c4cb));\n font-family: \"IBM Plex Sans\", sans-serif;\n font-size: var(--aia-pill-font-size, 19px);\n line-height: 30px;\n cursor: pointer;\n white-space: nowrap;\n animation: PillList-module_fadeIn_Aezob 400ms cubic-bezier(0.4, 0, 0.2, 1) forwards;\n box-shadow:\n hsla(0, 0%, 100%, 1) -3.2px -3.2px 3.2px -3.2px inset,\n hsla(0, 0%, 100%, 1) 6.4px 6.4px 1.6px -8px inset,\n var(--aia-dropdown-bg, transparent) -6.4px 6.4px 1.6px -8px inset,\n var(--aia-dropdown-bg, transparent) 6.4px -6.4px 1.6px -8px inset,\n hsla(0, 0%, 100%, 0.15) -1.6px 0px 0px -1.6px inset,\n hsla(0, 0%, 100%, 0.15) 0px -1.6px 0px -1.6px inset,\n hsla(0, 0%, 100%, 0.3) 0px 1.6px 0px 0px inset,\n hsla(0, 0%, 100%, 0.3) 1.6px 0px 0px 0px inset,\n inset 0 0 30px 5px hsla(0, 0%, 0%, 0.05),\n hsla(0, 0%, 0%, 0.08) 0px 0px 30px 2px;\n backdrop-filter: blur(30px);\n}\n\n.PillList-module_rounded_WvXy4 {\n border-radius: 999px;\n}\n\n.PillList-module_pill_osSyz:hover {\n filter: brightness(1.2);\n}\n\n.PillList-module_active_Oll-- {\n outline: 1px solid #5a5b8a;\n}\n\n@keyframes PillList-module_fadeIn_Aezob {\n from {\n opacity: 0;\n }\n}\n`;\n document.head.appendChild(s);\n}\nexport default {\"list\":\"PillList-module_list_qvLqO\",\"pill\":\"PillList-module_pill_osSyz\",\"fadeIn\":\"PillList-module_fadeIn_Aezob\",\"rounded\":\"PillList-module_rounded_WvXy4\",\"active\":\"PillList-module_active_Oll--\"};","import type { Suggestion } from \"../types\";\nimport styles from \"./PillList.module.css\";\n\ninterface PillListProps {\n pills: Suggestion[];\n activePillIndex: number;\n onSelectPill: (index: number) => void;\n /** Use capsule-shaped pills (fully rounded). Default: false. */\n rounded?: boolean;\n}\n\nfunction getPillOpacity(index: number): number {\n if (index === 0) return 0.4;\n if (index === 1) return 0.3;\n return 0.15;\n}\n\nexport function PillList({ pills, activePillIndex, onSelectPill, rounded }: PillListProps) {\n return (\n <span className={styles.list}>\n {pills.map((pill, i) => (\n <button\n key={`${pill.type}-${pill.text}`}\n type=\"button\"\n data-aia-pill=\"\"\n className={`${styles.pill} ${rounded ? styles.rounded : \"\"} ${i === activePillIndex ? styles.active : \"\"}`}\n style={{ opacity: getPillOpacity(i) }}\n onClick={() => onSelectPill(i)}\n >\n {pill.text}\n </button>\n ))}\n </span>\n );\n}\n","import { useEffect, useLayoutEffect, useRef, useState } from \"react\";\nimport type { SuggestionOption } from \"../types\";\nimport styles from \"./SuggestionGrid.module.css\";\nimport { SuggestionItem } from \"./SuggestionItem\";\n\ninterface SuggestionGridProps {\n options: SuggestionOption[];\n activeIndex: number;\n onSelect: (option: SuggestionOption) => void;\n onHighlight: (index: number) => void;\n listboxId: string;\n}\n\nexport function SuggestionGrid({\n options,\n activeIndex,\n onSelect,\n onHighlight,\n listboxId,\n}: SuggestionGridProps) {\n const gridRef = useRef<HTMLDivElement>(null);\n const [hasBottomOverflow, setHasBottomOverflow] = useState(false);\n\n useEffect(() => {\n const el = gridRef.current;\n if (!el) return;\n\n const update = () => {\n setHasBottomOverflow(el.scrollHeight - el.scrollTop - el.clientHeight > 1);\n };\n\n el.addEventListener(\"scroll\", update, { passive: true });\n const resizeObserver = new ResizeObserver(update);\n resizeObserver.observe(el);\n\n return () => {\n el.removeEventListener(\"scroll\", update);\n resizeObserver.disconnect();\n };\n }, []);\n\n // Re-measure synchronously when the option list changes. ResizeObserver\n // misses this case (the grid hits max-height, so scrollHeight grows but the\n // observed box doesn't) and useEffect would leave a frame of stale fade.\n // biome-ignore lint/correctness/useExhaustiveDependencies: options is a trigger-only dep\n useLayoutEffect(() => {\n const el = gridRef.current;\n if (!el) return;\n setHasBottomOverflow(el.scrollHeight - el.scrollTop - el.clientHeight > 1);\n }, [options]);\n\n return (\n <div className={styles.scrollWrapper} data-fade={hasBottomOverflow ? \"\" : undefined}>\n <div ref={gridRef} className={styles.grid}>\n {options.map((option, i) => (\n <SuggestionItem\n key={option.text}\n option={option}\n isHighlighted={i === activeIndex}\n onSelect={onSelect}\n onHighlight={() => onHighlight(i)}\n id={`${listboxId}-option-${i}`}\n />\n ))}\n </div>\n </div>\n );\n}\n","if (typeof document !== \"undefined\" && !document.getElementById(\"ac-style-d91f2b06\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-d91f2b06\";\n s.textContent = `.SuggestionGrid-module_scrollWrapper_MOqfw {\n position: relative;\n}\n\n.SuggestionGrid-module_scrollWrapper_MOqfw::after {\n content: \"\";\n position: absolute;\n left: 0;\n right: 0;\n bottom: 0;\n height: 50%;\n pointer-events: none;\n opacity: 0;\n transition: opacity 150ms ease-out;\n backdrop-filter: blur(12px);\n mask-image: linear-gradient(to bottom, transparent, white);\n}\n\n.SuggestionGrid-module_scrollWrapper_MOqfw[data-fade]::after {\n opacity: 1;\n}\n\n.SuggestionGrid-module_grid_jvaPb {\n display: grid;\n grid-template-columns: minmax(0, 250px);\n max-width: 100cqi;\n padding: 8px 8px;\n max-height: 200px;\n overflow-y: auto;\n scrollbar-width: thin;\n scrollbar-color: var(--aia-scrollbar-thumb, rgba(0, 0, 0, 0.3)) transparent;\n}\n\n@container (min-width: 516px) {\n .SuggestionGrid-module_grid_jvaPb {\n grid-template-columns: repeat(2, minmax(0, 250px));\n justify-content: start;\n }\n}\n\n.SuggestionGrid-module_grid_jvaPb::-webkit-scrollbar {\n width: 6px;\n}\n\n.SuggestionGrid-module_grid_jvaPb::-webkit-scrollbar-track {\n background: transparent;\n}\n\n.SuggestionGrid-module_grid_jvaPb::-webkit-scrollbar-thumb {\n background: var(--aia-scrollbar-thumb, rgba(0, 0, 0, 0.3));\n border-radius: 3px;\n}\n`;\n document.head.appendChild(s);\n}\nexport default {\"scrollWrapper\":\"SuggestionGrid-module_scrollWrapper_MOqfw\",\"grid\":\"SuggestionGrid-module_grid_jvaPb\"};","import { useEffect, useRef, useState } from \"react\";\nimport type { SuggestionOption } from \"../types\";\nimport styles from \"./SuggestionItem.module.css\";\n\ninterface SuggestionItemProps {\n option: SuggestionOption;\n isHighlighted: boolean;\n onSelect: (option: SuggestionOption) => void;\n onHighlight: () => void;\n id: string;\n}\n\nexport function SuggestionItem({\n option,\n isHighlighted,\n onSelect,\n onHighlight,\n id,\n}: SuggestionItemProps) {\n const [pressed, setPressed] = useState(false);\n const timerRef = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n\n useEffect(() => {\n return () => clearTimeout(timerRef.current);\n }, []);\n\n const handleSelect = () => {\n if (!option.is_tappable || pressed) return;\n setPressed(true);\n onSelect(option);\n clearTimeout(timerRef.current);\n timerRef.current = setTimeout(() => setPressed(false), 400);\n };\n\n const className = [\n styles.item,\n isHighlighted ? styles.highlighted : \"\",\n option.is_tappable ? styles.tappable : styles.nonTappable,\n pressed ? styles.pressed : \"\",\n ]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <div\n id={id}\n role=\"option\"\n data-aia-option=\"\"\n aria-selected={isHighlighted}\n className={className}\n tabIndex={option.is_tappable ? 0 : -1}\n onClick={handleSelect}\n onKeyDown={(e) => {\n if (option.is_tappable && (e.key === \"Enter\" || e.key === \" \")) {\n e.preventDefault();\n handleSelect();\n }\n }}\n onMouseEnter={option.is_tappable ? onHighlight : undefined}\n >\n <div className={styles.streaks} />\n <div className={styles.streaksVert} />\n <span className={styles.content}>\n {option.icon ? `${option.icon} ${option.text}` : option.text}\n {option.tag && <span className={styles.tag}>{option.tag}</span>}\n </span>\n </div>\n );\n}\n","if (typeof document !== \"undefined\" && !document.getElementById(\"ac-style-f6bdc634\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-f6bdc634\";\n s.textContent = `.SuggestionItem-module_item_d4vpD {\n position: relative;\n overflow: visible;\n display: flex;\n align-items: center;\n font-family: \"IBM Plex Sans\", sans-serif;\n font-size: var(--aia-option-font-size, 19px);\n line-height: 24px;\n color: var(--aia-option-color, var(--aia-color-text-muted, #c1c4cb));\n white-space: normal;\n word-break: break-word;\n opacity: 0.4;\n border-radius: 12px;\n padding: 13px 13px;\n animation: SuggestionItem-module_fadeIn_I8u35 500ms cubic-bezier(0.4, 0, 0.2, 1) forwards;\n}\n\n@keyframes SuggestionItem-module_fadeIn_I8u35 {\n from {\n opacity: 0;\n }\n}\n\n.SuggestionItem-module_content_T-Qba {\n position: relative;\n z-index: 2;\n}\n\n.SuggestionItem-module_tappable_70KcX {\n cursor: pointer;\n}\n\n.SuggestionItem-module_tappable_70KcX:hover {\n color: var(--aia-option-color-selected, var(--aia-color-text-default, #fff));\n}\n\n.SuggestionItem-module_nonTappable_xSZM- {\n cursor: default;\n opacity: 0.3;\n}\n\n.SuggestionItem-module_highlighted_Hb0SU {\n color: var(--aia-option-color-selected, var(--aia-color-text-default, #fff));\n background: var(--aia-option-bg, transparent);\n opacity: 0.5;\n}\n\n.SuggestionItem-module_tag_e3Fwe {\n font-size: 11px;\n margin-left: 6px;\n opacity: 0.5;\n}\n\n.SuggestionItem-module_pressed_98o-r {\n opacity: 0.8;\n color: var(--aia-color-text-default, #fff);\n background: rgba(var(--aia-streak-rgb, 255, 255, 255), 0.06);\n animation:\n SuggestionItem-module_glassFade_oyiSj 500ms ease forwards,\n SuggestionItem-module_tapDown_G3WGz 500ms ease forwards;\n}\n\n@keyframes SuggestionItem-module_tapDown_G3WGz {\n 0% {\n transform: scale(1);\n }\n 30% {\n transform: scale(0.97);\n }\n 100% {\n transform: scale(1);\n }\n}\n\n@keyframes SuggestionItem-module_glassFade_oyiSj {\n 0% {\n background: var(--aia-streak-glass-bg, rgba(255, 255, 255, 0.1));\n }\n 100% {\n background: transparent;\n }\n}\n\n/* Border streaks — horizontal segments */\n\n.SuggestionItem-module_streaks_d9PEB {\n position: absolute;\n inset: 0;\n z-index: 1;\n pointer-events: none;\n border-radius: inherit;\n overflow: hidden;\n}\n\n/* Bottom horizontal: 40% from right → right corner */\n.SuggestionItem-module_streaks_d9PEB::before {\n content: \"\";\n position: absolute;\n bottom: -3px;\n left: 60%;\n width: 0;\n height: 6px;\n opacity: 0;\n background: radial-gradient(\n ellipse at center,\n rgba(var(--aia-streak-rgb, 255, 255, 255), 0.5) 0%,\n rgba(var(--aia-streak-rgb, 255, 255, 255), 0.2) 40%,\n transparent 70%\n );\n box-shadow: 0 0 12px 4px rgba(var(--aia-streak-rgb, 255, 255, 255), 0.2);\n filter: blur(1px);\n border-radius: 50%;\n}\n\n/* Top horizontal: 40% from left → left corner */\n.SuggestionItem-module_streaks_d9PEB::after {\n content: \"\";\n position: absolute;\n top: -3px;\n right: 60%;\n width: 0;\n height: 6px;\n opacity: 0;\n background: radial-gradient(\n ellipse at center,\n rgba(var(--aia-streak-rgb, 255, 255, 255), 0.5) 0%,\n rgba(var(--aia-streak-rgb, 255, 255, 255), 0.2) 40%,\n transparent 70%\n );\n box-shadow: 0 0 12px 4px rgba(var(--aia-streak-rgb, 255, 255, 255), 0.2);\n filter: blur(1px);\n border-radius: 50%;\n}\n\n/* Border streaks — vertical segments */\n\n.SuggestionItem-module_streaksVert_ERlV1 {\n position: absolute;\n inset: 0;\n z-index: 1;\n pointer-events: none;\n border-radius: inherit;\n overflow: hidden;\n}\n\n/* Right vertical: bottom-right corner → up */\n.SuggestionItem-module_streaksVert_ERlV1::before {\n content: \"\";\n position: absolute;\n bottom: 0;\n right: -3px;\n width: 6px;\n height: 0;\n opacity: 0;\n background: radial-gradient(\n ellipse at center,\n rgba(var(--aia-streak-rgb, 255, 255, 255), 0.4) 0%,\n rgba(var(--aia-streak-rgb, 255, 255, 255), 0.15) 40%,\n transparent 70%\n );\n box-shadow: 0 0 12px 4px rgba(var(--aia-streak-rgb, 255, 255, 255), 0.15);\n filter: blur(1px);\n border-radius: 50%;\n}\n\n/* Left vertical: top-left corner → down */\n.SuggestionItem-module_streaksVert_ERlV1::after {\n content: \"\";\n position: absolute;\n top: 0;\n left: -3px;\n width: 6px;\n height: 0;\n opacity: 0;\n background: radial-gradient(\n ellipse at center,\n rgba(var(--aia-streak-rgb, 255, 255, 255), 0.4) 0%,\n rgba(var(--aia-streak-rgb, 255, 255, 255), 0.15) 40%,\n transparent 70%\n );\n box-shadow: 0 0 12px 4px rgba(var(--aia-streak-rgb, 255, 255, 255), 0.15);\n filter: blur(1px);\n border-radius: 50%;\n}\n\n.SuggestionItem-module_pressed_98o-r .SuggestionItem-module_streaks_d9PEB::before {\n animation: SuggestionItem-module_streakHorizRight_aboGz 500ms cubic-bezier(0.4, 0, 0.2, 1) forwards;\n}\n\n.SuggestionItem-module_pressed_98o-r .SuggestionItem-module_streaks_d9PEB::after {\n animation: SuggestionItem-module_streakHorizLeft_BreWJ 500ms cubic-bezier(0.4, 0, 0.2, 1) forwards;\n}\n\n.SuggestionItem-module_pressed_98o-r .SuggestionItem-module_streaksVert_ERlV1::before {\n animation: SuggestionItem-module_streakVertUp_to1GD 300ms cubic-bezier(0.3, 0, 0.2, 1) 200ms forwards;\n}\n\n.SuggestionItem-module_pressed_98o-r .SuggestionItem-module_streaksVert_ERlV1::after {\n animation: SuggestionItem-module_streakVertDown_OrcLh 300ms cubic-bezier(0.3, 0, 0.2, 1) 200ms forwards;\n}\n\n/* Horizontal: bottom center-ish → right edge */\n@keyframes SuggestionItem-module_streakHorizRight_aboGz {\n 0% {\n width: 0;\n height: 4px;\n opacity: 0;\n filter: blur(1px);\n box-shadow: 0 0 8px 3px rgba(var(--aia-streak-rgb, 255, 255, 255), 0.3);\n }\n 15% {\n height: 4px;\n opacity: 1;\n filter: blur(1px);\n box-shadow: 0 0 10px 4px rgba(var(--aia-streak-rgb, 255, 255, 255), 0.3);\n }\n 80% {\n width: 50%;\n height: 10px;\n opacity: 0.8;\n filter: blur(3px);\n box-shadow: 0 0 16px 6px rgba(var(--aia-streak-rgb, 255, 255, 255), 0.1);\n }\n 100% {\n width: 50%;\n height: 12px;\n opacity: 0;\n filter: blur(5px);\n box-shadow: 0 0 20px 8px rgba(var(--aia-streak-rgb, 255, 255, 255), 0.03);\n }\n}\n\n/* Horizontal: top center-ish → left edge */\n@keyframes SuggestionItem-module_streakHorizLeft_BreWJ {\n 0% {\n width: 0;\n height: 4px;\n opacity: 0;\n filter: blur(1px);\n box-shadow: 0 0 8px 3px rgba(var(--aia-streak-rgb, 255, 255, 255), 0.3);\n }\n 15% {\n height: 4px;\n opacity: 1;\n filter: blur(1px);\n box-shadow: 0 0 10px 4px rgba(var(--aia-streak-rgb, 255, 255, 255), 0.3);\n }\n 80% {\n width: 50%;\n height: 10px;\n opacity: 0.8;\n filter: blur(3px);\n box-shadow: 0 0 16px 6px rgba(var(--aia-streak-rgb, 255, 255, 255), 0.1);\n }\n 100% {\n width: 50%;\n height: 12px;\n opacity: 0;\n filter: blur(5px);\n box-shadow: 0 0 20px 8px rgba(var(--aia-streak-rgb, 255, 255, 255), 0.03);\n }\n}\n\n/* Vertical segments start matching horizontal state at 200ms handoff */\n@keyframes SuggestionItem-module_streakVertUp_to1GD {\n 0% {\n height: 0;\n width: 6px;\n opacity: 0.9;\n filter: blur(1.8px);\n box-shadow: 0 0 12px 5px rgba(var(--aia-streak-rgb, 255, 255, 255), 0.25);\n }\n 75% {\n height: 100%;\n width: 10px;\n opacity: 0.4;\n filter: blur(3px);\n box-shadow: 0 0 18px 8px rgba(var(--aia-streak-rgb, 255, 255, 255), 0.06);\n }\n 100% {\n height: 100%;\n width: 14px;\n opacity: 0;\n filter: blur(5px);\n box-shadow: 0 0 24px 10px rgba(var(--aia-streak-rgb, 255, 255, 255), 0.02);\n }\n}\n\n@keyframes SuggestionItem-module_streakVertDown_OrcLh {\n 0% {\n height: 0;\n width: 6px;\n opacity: 0.9;\n filter: blur(1.8px);\n box-shadow: 0 0 12px 5px rgba(var(--aia-streak-rgb, 255, 255, 255), 0.25);\n }\n 75% {\n height: 100%;\n width: 10px;\n opacity: 0.4;\n filter: blur(3px);\n box-shadow: 0 0 18px 8px rgba(var(--aia-streak-rgb, 255, 255, 255), 0.06);\n }\n 100% {\n height: 100%;\n width: 14px;\n opacity: 0;\n filter: blur(5px);\n box-shadow: 0 0 24px 10px rgba(var(--aia-streak-rgb, 255, 255, 255), 0.02);\n }\n}\n`;\n document.head.appendChild(s);\n}\nexport default {\"item\":\"SuggestionItem-module_item_d4vpD\",\"fadeIn\":\"SuggestionItem-module_fadeIn_I8u35\",\"content\":\"SuggestionItem-module_content_T-Qba\",\"tappable\":\"SuggestionItem-module_tappable_70KcX\",\"nonTappable\":\"SuggestionItem-module_nonTappable_xSZM-\",\"highlighted\":\"SuggestionItem-module_highlighted_Hb0SU\",\"tag\":\"SuggestionItem-module_tag_e3Fwe\",\"pressed\":\"SuggestionItem-module_pressed_98o-r\",\"glassFade\":\"SuggestionItem-module_glassFade_oyiSj\",\"tapDown\":\"SuggestionItem-module_tapDown_G3WGz\",\"streaks\":\"SuggestionItem-module_streaks_d9PEB\",\"streaksVert\":\"SuggestionItem-module_streaksVert_ERlV1\",\"streakHorizRight\":\"SuggestionItem-module_streakHorizRight_aboGz\",\"streakHorizLeft\":\"SuggestionItem-module_streakHorizLeft_BreWJ\",\"streakVertUp\":\"SuggestionItem-module_streakVertUp_to1GD\",\"streakVertDown\":\"SuggestionItem-module_streakVertDown_OrcLh\"};","import styles from \"./AIAutocompleteDropdown.module.css\";\nimport { PillList } from \"./components/PillList\";\nimport { SuggestionGrid } from \"./components/SuggestionGrid\";\nimport type { AIAutocompleteDropdownProps } from \"./types\";\n\nexport function AIAutocompleteDropdown({\n suggestions,\n activeIndex,\n onSelect,\n onHighlight,\n isOpen,\n id,\n className,\n pills,\n onPillClick,\n showPills = true,\n}: AIAutocompleteDropdownProps) {\n const activeSuggestion = suggestions[0];\n const options = activeSuggestion?.options ?? [];\n const hasPills = showPills && pills && pills.length > 0 && onPillClick;\n const hasOptions = isOpen && options.length > 0;\n const isVisible = hasOptions || (isOpen && hasPills);\n\n return (\n <div\n id={id}\n role=\"listbox\"\n data-aia-dropdown=\"\"\n className={`${styles.dropdown} ${isVisible ? styles.visible : \"\"} ${className ?? \"\"}`}\n onMouseDown={(e) => e.preventDefault()}\n >\n {hasPills && (\n <div className={styles.pillBar} data-aia-pillbar=\"\">\n <PillList pills={pills} activePillIndex={0} onSelectPill={onPillClick} rounded />\n </div>\n )}\n {options.length > 0 && (\n <SuggestionGrid\n options={options}\n activeIndex={activeIndex}\n onSelect={onSelect}\n onHighlight={onHighlight}\n listboxId={id}\n />\n )}\n </div>\n );\n}\n","if (typeof document !== \"undefined\" && !document.getElementById(\"ac-style-dc8da745\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-dc8da745\";\n s.textContent = `/*\n * Built-in appearance defaults — zero specificity via :where().\n * Consumer CSS always wins without !important.\n *\n * Resolution priority (highest wins):\n * 1. Consumer CSS targeting new vars (--aia-pill-bg, etc.)\n * 2. Consumer CSS targeting legacy vars (--aia-color-*, via fallback chain)\n * 3. These built-in defaults\n */\n\n/* Light mode defaults (base) */\n:where(.magicx-aia),\n:where(.magicx-aia[data-mode=\"light\"]) {\n --aia-pill-bg: #bdbdbd;\n --aia-pill-color: #000000;\n --aia-pill-font-size: 19px;\n\n --aia-option-bg: transparent;\n --aia-option-color: #000000;\n --aia-option-color-selected: #000000;\n --aia-option-font-size: 19px;\n\n --aia-written-text-color: #000000;\n --aia-written-text-font-size: 19px;\n --aia-caret-color: var(--aia-written-text-color, #000000);\n\n --aia-submit-bg: #000000;\n --aia-submit-color: #ffffff;\n\n --aia-color-text-muted: #6b7280;\n\n --aia-streak-rgb: 99, 102, 241;\n --aia-streak-glass-bg: rgba(99, 102, 241, 0.1);\n}\n\n/* Dark mode defaults */\n:where(.magicx-aia[data-mode=\"dark\"]) {\n --aia-pill-bg: #bdbdbd;\n --aia-pill-color: #ffffff;\n --aia-pill-font-size: 19px;\n\n --aia-option-bg: transparent;\n --aia-option-color: #ffffff;\n --aia-option-color-selected: #ffffff;\n --aia-option-font-size: 19px;\n\n --aia-written-text-color: #ffffff;\n --aia-written-text-font-size: 19px;\n --aia-caret-color: var(--aia-written-text-color, #ffffff);\n\n --aia-submit-bg: #ffffff;\n --aia-submit-color: #000000;\n\n --aia-color-text-muted: #c1c4cb;\n\n --aia-streak-rgb: 255, 255, 255;\n --aia-streak-glass-bg: rgba(255, 255, 255, 0.1);\n}\n\n/* optionsPosition: dropdown above the input */\n:where(.magicx-aia[data-options-position=\"above\"]) [data-aia-dropdown] {\n top: auto;\n bottom: 100%;\n margin-top: 0;\n margin-bottom: 6px;\n flex-direction: column-reverse;\n}\n\n:where(.magicx-aia[data-options-position=\"above\"]) [data-aia-pillbar] {\n padding: 0 27px 27px 27px;\n}\n\n/* Disable all animations when data-animations=\"off\" */\n:where(.magicx-aia[data-animations=\"off\"]) *,\n:where(.magicx-aia[data-animations=\"off\"]) *::before,\n:where(.magicx-aia[data-animations=\"off\"]) *::after {\n animation-duration: 0s !important;\n transition-duration: 0s !important;\n}\n`;\n document.head.appendChild(s);\n}\nexport {};","import {\n type ChangeEvent,\n type KeyboardEvent,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport { AIAutocomplete as CoreAIAutocomplete } from \"../core/AIAutocomplete\";\nimport type { CoreState } from \"../core/types\";\nimport type {\n Suggestion,\n SuggestionOption,\n UseAIAutocompleteOptions,\n UseAIAutocompleteReturn,\n} from \"../types\";\n\nexport function useAIAutocomplete({\n onSubmit,\n onError,\n optionOverrides,\n maskCompletedText,\n apiConfig,\n columns = 2,\n dropdownTrigger,\n closeDropdownOnBlur,\n onFocus,\n onBlur,\n value: controlledValue,\n completedParams: controlledParams,\n onChange: onChangeProp,\n onParamsChange,\n source,\n}: UseAIAutocompleteOptions): UseAIAutocompleteReturn {\n const instanceRef = useRef<CoreAIAutocomplete | null>(null);\n const [coreState, setCoreState] = useState<CoreState | null>(null);\n\n // Refs for callbacks to avoid stale closures\n const onSubmitRef = useRef(onSubmit);\n onSubmitRef.current = onSubmit;\n const onErrorRef = useRef(onError);\n onErrorRef.current = onError;\n const onChangeRef = useRef(onChangeProp);\n onChangeRef.current = onChangeProp;\n const onParamsChangeRef = useRef(onParamsChange);\n onParamsChangeRef.current = onParamsChange;\n const onFocusRef = useRef(onFocus);\n onFocusRef.current = onFocus;\n const onBlurRef = useRef(onBlur);\n onBlurRef.current = onBlur;\n\n // Create, subscribe, and destroy the core instance in one mount-only effect.\n // Keeping creation out of render (and pairing it with the cleanup) is what\n // makes this StrictMode-safe — otherwise cleanup nulls the ref, render\n // re-creates, and the store subscription drives an infinite setState loop.\n // biome-ignore lint/correctness/useExhaustiveDependencies: initial-opts snapshot; later changes are synced by the update-effect below\n useEffect(() => {\n if (typeof document === \"undefined\") return;\n const instance = new CoreAIAutocomplete(document.createElement(\"div\"), {\n renderMode: \"headless\",\n apiConfig,\n optionOverrides,\n maskCompletedText,\n columns,\n dropdownTrigger,\n closeDropdownOnBlur,\n source,\n value: controlledValue,\n completedParams: controlledParams,\n onSubmit: (...args) => onSubmitRef.current?.(...args),\n onError: (...args) => onErrorRef.current?.(...args),\n onChange: (...args) => onChangeRef.current?.(...args),\n onParamsChange: (...args) => onParamsChangeRef.current?.(...args),\n onFocus: () => onFocusRef.current?.(),\n onBlur: () => onBlurRef.current?.(),\n });\n instanceRef.current = instance;\n setCoreState(instance.getState());\n const unsub = instance.subscribe((state) => setCoreState(state));\n return () => {\n unsub();\n instance.destroy();\n if (instanceRef.current === instance) instanceRef.current = null;\n };\n }, []);\n\n const instance = instanceRef.current;\n\n // SSR bail-out — no instance, return safe empty defaults\n // Hooks below are unconditional (React rules of hooks) but guarded internally\n const noop = useCallback(() => {}, []);\n\n // Sync controlled value\n useEffect(() => {\n if (controlledValue !== undefined) instance?.setValue(controlledValue);\n }, [controlledValue, instance]);\n\n // Sync controlled params\n useEffect(() => {\n if (controlledParams !== undefined) instance?.setCompletedParams(controlledParams);\n }, [controlledParams, instance]);\n\n // Sync apiConfig/optionOverrides/dropdownTrigger when values change\n const apiConfigJson = JSON.stringify(apiConfig ?? null);\n const prevOverridesRef = useRef(optionOverrides);\n const overridesVersion = useRef(0);\n if (optionOverrides !== prevOverridesRef.current) {\n const prev = prevOverridesRef.current;\n const next = optionOverrides;\n const prevKeys = Object.keys(prev ?? {});\n const nextKeys = Object.keys(next ?? {});\n if (\n prevKeys.length !== nextKeys.length ||\n nextKeys.some(\n (k) =>\n !(prev as Record<string, unknown>)?.[k] ||\n (next as Record<string, unknown>)[k] !== (prev as Record<string, unknown>)[k],\n )\n ) {\n overridesVersion.current++;\n }\n prevOverridesRef.current = optionOverrides;\n }\n // biome-ignore lint/correctness/useExhaustiveDependencies: overridesVersion tracks shallow changes to fn-valued optionOverrides\n useEffect(() => {\n instance?.update({ apiConfig, optionOverrides, dropdownTrigger, closeDropdownOnBlur });\n }, [apiConfigJson, overridesVersion.current, dropdownTrigger, closeDropdownOnBlur, instance]);\n\n // Handle text change from textarea\n const handleChange = useCallback(\n (e: ChangeEvent<HTMLTextAreaElement>) => {\n if (!instance) return;\n const raw = e.target.value;\n const shouldCapitalize =\n raw.length > 0 &&\n !(e.nativeEvent as InputEvent)?.isComposing &&\n raw[0] !== raw[0].toUpperCase();\n const newValue = shouldCapitalize ? raw[0].toUpperCase() + raw.slice(1) : raw;\n instance.handleTextChange(newValue);\n },\n [instance],\n );\n\n // Handle keyboard\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLTextAreaElement>) => {\n instance?.handleKeyDown(e.nativeEvent);\n },\n [instance],\n );\n\n const handleFocus = useCallback(() => instance?.setFocused(true), [instance]);\n const handleBlur = useCallback(() => instance?.setFocused(false), [instance]);\n\n // Actions\n const setActivePill = useCallback((index: number) => instance?.setActivePill(index), [instance]);\n const removeLastParam = useCallback(() => instance?.removeLastParam(), [instance]);\n const clearNewParamId = useCallback(() => instance?.clearNewParamId(), [instance]);\n const reset = useCallback(() => instance?.reset(), [instance]);\n const selectOption = useCallback(\n (option: SuggestionOption) => instance?.selectOption(option),\n [instance],\n );\n const setActiveDropdownIndex = useCallback(\n (index: number) => instance?.setActiveDropdownIndex(index),\n [instance],\n );\n\n // No instance (SSR) — return safe defaults\n if (!instance) {\n return {\n completedParams: controlledParams ?? [],\n suggestionPills: [],\n setActivePill: noop,\n removeLastParam: noop,\n segments: [],\n newParamId: null,\n clearNewParamId: noop,\n suggestions: [],\n activeIndex: -1,\n isReady: false,\n isLoading: true,\n error: null,\n inputProps: {\n value: controlledValue ?? \"\",\n placeholder: undefined,\n onChange: noop as unknown as UseAIAutocompleteReturn[\"inputProps\"][\"onChange\"],\n onKeyDown: noop as unknown as UseAIAutocompleteReturn[\"inputProps\"][\"onKeyDown\"],\n onFocus: noop,\n onBlur: noop,\n role: \"combobox\" as const,\n \"aria-expanded\": false,\n \"aria-activedescendant\": undefined,\n \"aria-autocomplete\": \"list\" as const,\n \"aria-controls\": \"\",\n },\n reset: noop,\n dropdownProps: {\n suggestions: [],\n activeIndex: -1,\n onSelect: noop as unknown as (option: SuggestionOption) => void,\n onHighlight: noop as unknown as (index: number) => void,\n isOpen: false,\n id: \"\",\n pills: [],\n onPillClick: noop as unknown as (index: number) => void,\n },\n };\n }\n\n // Derive current state\n const state = coreState ?? instance.getState();\n const text = controlledValue !== undefined ? controlledValue : state.text;\n const completedParams = controlledParams !== undefined ? controlledParams : state.completedParams;\n\n const actionableSuggestions = state.actionableSuggestions;\n const activeSuggestion: Suggestion | undefined = actionableSuggestions[0];\n const filteredOptions = state.filteredOptions;\n\n const activeDescendantId =\n state.activeDropdownIndex >= 0\n ? `${instance.listboxId}-option-${state.activeDropdownIndex}`\n : undefined;\n\n return {\n completedParams,\n suggestionPills: actionableSuggestions,\n setActivePill,\n removeLastParam,\n segments: state.segments,\n newParamId: state.newParamId,\n clearNewParamId,\n suggestions: state.suggestions,\n activeIndex: state.activeDropdownIndex,\n isReady: state.isReady,\n isLoading: state.isLoading,\n error: state.error,\n inputProps: {\n value: text,\n placeholder: state.placeholderText || undefined,\n onChange: handleChange,\n onKeyDown: handleKeyDown,\n onFocus: handleFocus,\n onBlur: handleBlur,\n role: \"combobox\" as const,\n \"aria-expanded\": state.isDropdownOpen,\n \"aria-activedescendant\": activeDescendantId,\n \"aria-autocomplete\": \"list\" as const,\n \"aria-controls\": instance.listboxId,\n },\n reset,\n dropdownProps: {\n suggestions: activeSuggestion ? [{ ...activeSuggestion, options: filteredOptions }] : [],\n activeIndex: state.activeDropdownIndex,\n onSelect: selectOption,\n onHighlight: setActiveDropdownIndex,\n isOpen: state.isDropdownOpen,\n id: instance.listboxId,\n pills: actionableSuggestions,\n onPillClick: setActivePill,\n },\n };\n}\n","import type { CompletedParamState } from \"../types\";\n\ninterface BuildQueryResult {\n rawQuery: string;\n completedParams: CompletedParamState[];\n}\n\n/**\n * Takes the raw input text and completed params (without placeholders),\n * replaces each completed param's text in the string with a {{TYPE_N}} token,\n * and returns the transformed query + params with placeholders filled in.\n *\n * Replacements happen left-to-right, first occurrence only per param.\n * Counter is per-type (e.g. {{TASK_1}}, {{GOAL_1}}, {{GOAL_2}}).\n */\nexport function buildQuery(text: string, completedParams: CompletedParamState[]): BuildQueryResult {\n let result = text;\n const typeCounts: Record<string, number> = {};\n const updatedParams: CompletedParamState[] = [];\n\n for (const param of completedParams) {\n const count = (typeCounts[param.type] ?? 0) + 1;\n typeCounts[param.type] = count;\n\n const typeKey = param.type.toUpperCase().replace(/\\s+/g, \"_\");\n const placeholder = `{{${typeKey}_${count}}}`;\n\n // Replace first occurrence of the param text in the string\n const index = result.indexOf(param.text);\n if (index !== -1) {\n result = result.slice(0, index) + placeholder + result.slice(index + param.text.length);\n }\n\n updatedParams.push({ ...param, placeholder });\n }\n\n return { rawQuery: result, completedParams: updatedParams };\n}\n","import type { SuggestionOption } from \"../types\";\n\n/**\n * Extracts the effective filter query from the region after filterBase.\n * If the server marked the region as in_progress, the full region is used.\n * Otherwise, filtering only starts after the first space (to avoid filtering\n * mid-word when the user continues typing a word that was already in the input).\n */\nexport function extractFilterQuery(\n text: string,\n filterBase: number,\n isInProgress: boolean,\n): string {\n const rawRegion = text.slice(filterBase);\n if (isInProgress || filterBase === 0 || text[filterBase - 1] === \" \") {\n return rawRegion;\n }\n const spaceIdx = rawRegion.indexOf(\" \");\n return spaceIdx === -1 ? \"\" : rawRegion.slice(spaceIdx + 1);\n}\n\n/**\n * Finds the longest word-boundary-aligned suffix of `prefix` that matches a\n * prefix of `optionText` (case-insensitive). Returns the number of characters\n * to remove from the end of `prefix` to avoid duplication.\n */\nexport function findPrefixOverlap(prefix: string, optionText: string): number {\n // Normalize internal whitespace so words.join(\" \") roundtrips losslessly\n const trimmed = prefix.trimEnd().replace(/\\s+/g, \" \");\n if (trimmed.length === 0 || optionText.length === 0) return 0;\n\n const words = trimmed.split(\" \");\n const optionLower = optionText.toLowerCase();\n\n // Try from longest suffix (all words) to shortest (last word only)\n for (let i = 0; i < words.length; i++) {\n const candidate = words.slice(i).join(\" \");\n if (optionLower.startsWith(candidate.toLowerCase())) {\n const suffixStart = trimmed.length - candidate.length;\n return prefix.length - suffixStart;\n }\n }\n\n return 0;\n}\n\n/**\n * Filters options using partial substring match on the text after the last completed param.\n */\nexport function filterOptions(\n options: SuggestionOption[] | undefined,\n query: string,\n): SuggestionOption[] {\n if (!options) return [];\n const trimmed = query.trimStart();\n if (!trimmed) return options;\n const lower = trimmed.toLowerCase();\n return options.filter((o) => !o.is_tappable || o.text.toLowerCase().includes(lower));\n}\n\n/**\n * Finds an exact match for the trimmed filter query against options.\n */\nexport function findExactMatch(\n options: SuggestionOption[] | undefined,\n query: string,\n): SuggestionOption | null {\n if (!options) return null;\n const trimmed = query.trim();\n if (!trimmed) return null;\n const lower = trimmed.toLowerCase();\n return options.find((o) => o.is_tappable && o.text.toLowerCase() === lower) ?? null;\n}\n","import type { AppearanceMode } from \"../types\";\n\nexport class ModeController {\n private mediaQuery: MediaQueryList | null = null;\n\n constructor(\n private container: HTMLElement,\n private mode: AppearanceMode = \"auto\",\n ) {\n this.apply();\n }\n\n setMode(mode: AppearanceMode) {\n this.detachListener();\n this.mode = mode;\n this.apply();\n }\n\n destroy() {\n this.detachListener();\n }\n\n private apply() {\n if (this.mode === \"auto\") {\n this.mediaQuery ??= window.matchMedia(\"(prefers-color-scheme: dark)\");\n this.mediaQuery.addEventListener(\"change\", this.onSystemChange);\n this.container.dataset.mode = this.mediaQuery.matches ? \"dark\" : \"light\";\n } else {\n this.container.dataset.mode = this.mode;\n }\n }\n\n private onSystemChange = (e: MediaQueryListEvent) => {\n this.container.dataset.mode = e.matches ? \"dark\" : \"light\";\n };\n\n private detachListener() {\n this.mediaQuery?.removeEventListener(\"change\", this.onSystemChange);\n }\n}\n","import type { CompletedParamState, Segment } from \"../types\";\n\n/**\n * Derives segments for overlay rendering by matching completed params in text.\n */\nexport function deriveSegments(text: string, completedParams: CompletedParamState[]): Segment[] {\n const result: Segment[] = [];\n let pos = 0;\n\n for (const param of completedParams) {\n const idx = text.indexOf(param.text, pos);\n if (idx === -1) continue;\n if (idx > pos) {\n result.push({ type: \"text\", value: text.slice(pos, idx) });\n }\n result.push({ type: \"completed\", value: param.text, param });\n pos = idx + param.text.length;\n }\n\n const remaining = text.slice(pos);\n if (remaining) {\n result.push({ type: \"text\", value: remaining });\n }\n\n return result;\n}\n\n/**\n * Checks which completed params still exist in the new text.\n */\nexport function reconcileParams(\n text: string,\n completedParams: CompletedParamState[],\n): { valid: CompletedParamState[]; invalid: CompletedParamState[] } {\n const valid: CompletedParamState[] = [];\n const invalid: CompletedParamState[] = [];\n let pos = 0;\n\n for (const param of completedParams) {\n const idx = text.indexOf(param.text, pos);\n if (idx === -1) {\n invalid.push(param);\n } else {\n valid.push(param);\n pos = idx + param.text.length;\n }\n }\n\n return { valid, invalid };\n}\n","import type { AccessTokenConfig } from \"../types\";\n\n/** Refresh 30 seconds before stated expiry to absorb clock drift and request latency. */\nconst REFRESH_SKEW_MS = 30_000;\n\nexport class TokenManager {\n private current: string | null = null;\n private expiresAt: number | null = null;\n private inFlightRefresh: Promise<string> | null = null;\n\n constructor(private config: AccessTokenConfig) {\n if (config.accessToken) {\n this.current = config.accessToken;\n }\n }\n\n /** Returns a valid token, refreshing if needed. Single-flight: concurrent callers share one refresh. */\n async getToken(forceRefresh = false): Promise<string> {\n if (!forceRefresh && this.current && !this.isExpired()) {\n return this.current;\n }\n if (!forceRefresh && this.inFlightRefresh) {\n return this.inFlightRefresh;\n }\n this.inFlightRefresh = this.refresh();\n try {\n return await this.inFlightRefresh;\n } finally {\n this.inFlightRefresh = null;\n }\n }\n\n private async refresh(): Promise<string> {\n const result = await this.config.getAccessToken();\n this.current = result.accessToken;\n this.expiresAt = result.expiresAt ?? null;\n return this.current;\n }\n\n private isExpired(): boolean {\n if (this.expiresAt == null) return false;\n return Date.now() >= this.expiresAt - REFRESH_SKEW_MS;\n }\n}\n","import type { AccessTokenConfig, APIConfig, APIKeyConfig } from \"../types\";\nimport { TokenManager } from \"./tokenManager\";\n\n/** Default backend origin used when apiConfig.endpoint is not set. */\nexport const DEFAULT_API_ORIGIN = \"https://api.ai-autocomplete.com\";\nexport const DEFAULT_SUGGEST_ENDPOINT = `${DEFAULT_API_ORIGIN}/api/suggest`;\n\n// Keyed by getAccessToken function reference (stable across React re-renders)\nconst tokenManagers = new WeakMap<AccessTokenConfig[\"getAccessToken\"], TokenManager>();\n\nexport function isAccessTokenConfig(config?: APIConfig): config is AccessTokenConfig {\n return config?.type === \"accessToken\";\n}\n\nexport function getApiKeyConfig(config?: APIConfig): APIKeyConfig | undefined {\n if (!config || isAccessTokenConfig(config)) return undefined;\n return config;\n}\n\nexport function getTokenManager(config: AccessTokenConfig): TokenManager {\n let manager = tokenManagers.get(config.getAccessToken);\n if (!manager) {\n manager = new TokenManager(config);\n tokenManagers.set(config.getAccessToken, manager);\n }\n return manager;\n}\n\n/**\n * Builds shared (non-auth) request headers used by every backend call.\n * Mirrors what /suggest sends so /api/telemetry/events sees the same envelope.\n */\nexport function buildHeaders(apiConfig?: APIConfig): Record<string, string> {\n return {\n \"Content-Type\": \"application/json\",\n ...(apiConfig?.appIdentifier && { \"X-App-Identifier\": apiConfig.appIdentifier }),\n ...apiConfig?.headers,\n };\n}\n\n/**\n * Returns the Authorization header value for an API-key config, or `null` if no\n * apiKey is set (matches /suggest's behavior of sending the request without an\n * Authorization header in that case — the warn lives in api.ts so it fires only\n * for the user-visible suggest call).\n */\nexport function buildApiKeyAuthHeader(apiConfig?: APIConfig): string | null {\n const apiKeyConfig = getApiKeyConfig(apiConfig);\n const apiKey = apiKeyConfig?.apiKey;\n if (!apiKey) return null;\n const scheme = apiKeyConfig?.authScheme ?? \"Bearer\";\n return scheme === \"Basic\" ? `Basic ${btoa(apiKey)}` : `Bearer ${apiKey}`;\n}\n","import type { APIConfig } from \"../types\";\nimport {\n buildApiKeyAuthHeader,\n buildHeaders,\n DEFAULT_SUGGEST_ENDPOINT,\n getTokenManager,\n isAccessTokenConfig,\n} from \"./auth\";\n\nexport type TelemetrySource = \"full-sdk\" | \"headless-sdk\" | \"endpoint-direct\";\nexport type TelemetryType = \"pill\" | \"option\";\n\nexport interface TelemetryEvent {\n source: TelemetrySource;\n sessionId: string;\n type: TelemetryType;\n queryData: Record<string, unknown>;\n apiConfig?: APIConfig;\n}\n\n/**\n * Telemetry sits next to /suggest on the server, so we derive the URL by\n * rewriting the trailing `/suggest` segment. This preserves whatever origin\n * and path-prefix the consumer configured — including relative dev-proxy\n * paths like \"/api/suggest\" → \"/api/telemetry/events\" or \"/ac/api/suggest\" →\n * \"/ac/api/telemetry/events\".\n */\nfunction deriveTelemetryEndpoint(suggestEndpoint?: string): string {\n const base = suggestEndpoint ?? DEFAULT_SUGGEST_ENDPOINT;\n return base.replace(/\\/suggest(\\?|#|$)/, \"/telemetry/events$1\");\n}\n\n/**\n * Resolves Authorization header using the same logic as /suggest:\n * - accessToken mode → Bearer from TokenManager\n * - apiKey mode → Bearer/Basic from configured key\n * - neither → null (request is sent without an Authorization header, matching\n * /suggest's behavior)\n */\nasync function resolveAuthHeader(apiConfig?: APIConfig): Promise<string | null> {\n if (isAccessTokenConfig(apiConfig)) {\n const token = await getTokenManager(apiConfig).getToken();\n return `Bearer ${token}`;\n }\n return buildApiKeyAuthHeader(apiConfig);\n}\n\n/**\n * Fire-and-forget telemetry POST. Never throws; failures are swallowed so the\n * UI is never disrupted by analytics. Auth headers are constructed via the\n * same helpers used by /suggest, so credential resolution stays consistent\n * across endpoints.\n */\nexport async function sendTelemetry(event: TelemetryEvent): Promise<void> {\n try {\n const endpoint = deriveTelemetryEndpoint(event.apiConfig?.endpoint);\n const headers = buildHeaders(event.apiConfig);\n const authHeader = await resolveAuthHeader(event.apiConfig);\n if (authHeader) headers.Authorization = authHeader;\n\n const body = JSON.stringify({\n source: event.source,\n session_id: event.sessionId,\n type: event.type,\n at: new Date().toISOString(),\n query_data: event.queryData,\n });\n\n await fetch(endpoint, { method: \"POST\", headers, body });\n } catch {\n // best-effort\n }\n}\n","import type {\n APIConfig,\n AutocompleteRequest,\n AutocompleteResponse,\n CompletedParam,\n CompletedParamState,\n} from \"../types\";\nimport {\n buildApiKeyAuthHeader,\n buildHeaders,\n DEFAULT_SUGGEST_ENDPOINT,\n getTokenManager,\n isAccessTokenConfig,\n} from \"./auth\";\n\n// Replaced at build time by tsup/vitest `define` config with the package.json version.\ndeclare const __SDK_VERSION__: string;\nconst SDK_VERSION = __SDK_VERSION__;\n\nlet hasWarnedMissingKey = false;\n\nfunction generateRequestId(): string {\n return crypto.randomUUID();\n}\n\nfunction toWireParam(param: CompletedParamState, includeText: boolean): CompletedParam {\n return {\n placeholder: param.placeholder,\n type: param.type,\n ...(includeText && { text: param.text }),\n kind: param.kind,\n };\n}\n\nfunction buildRequestBody(\n rawQuery: string,\n completedParams: CompletedParamState[],\n includeText: boolean,\n sessionId: string,\n): AutocompleteRequest {\n const rawCount = completedParams.find(\n (p) => p.type === \"contact\" && p.metadata?.contact_account_count,\n )?.metadata?.contact_account_count;\n const contactAccountCount = typeof rawCount === \"number\" ? rawCount : undefined;\n\n return {\n data: {\n raw_query: rawQuery,\n completed_params: completedParams.map((p) => toWireParam(p, includeText)),\n ...(contactAccountCount != null && { contact_account_count: contactAccountCount }),\n },\n meta: {\n request_id: generateRequestId(),\n request_at: new Date().toISOString(),\n language: typeof navigator !== \"undefined\" ? navigator.language : \"en-US\",\n client_version: SDK_VERSION,\n session_id: sessionId,\n },\n };\n}\n\nasync function doFetch(\n endpoint: string,\n headers: Record<string, string>,\n token: string,\n body: string,\n signal?: AbortSignal,\n): Promise<Response> {\n return fetch(endpoint, {\n method: \"POST\",\n headers: { ...headers, Authorization: `Bearer ${token}` },\n body,\n signal,\n });\n}\n\nexport async function fetchSuggestions(\n rawQuery: string,\n completedParams: CompletedParamState[],\n options: {\n sessionId: string;\n maskCompletedText?: boolean;\n signal?: AbortSignal;\n apiConfig?: APIConfig;\n },\n): Promise<AutocompleteResponse> {\n const apiConfig = options.apiConfig;\n const includeText = !options.maskCompletedText;\n const body = buildRequestBody(rawQuery, completedParams, includeText, options.sessionId);\n const headers = buildHeaders(apiConfig);\n const endpoint = apiConfig?.endpoint ?? DEFAULT_SUGGEST_ENDPOINT;\n const jsonBody = JSON.stringify(body);\n\n // === Access token mode ===\n if (isAccessTokenConfig(apiConfig)) {\n const manager = getTokenManager(apiConfig);\n const token = await manager.getToken();\n\n let response = await doFetch(endpoint, headers, token, jsonBody, options.signal);\n\n // 401 retry: force-refresh token and retry exactly once\n if (response.status === 401) {\n const newToken = await manager.getToken(true);\n response = await doFetch(endpoint, headers, newToken, jsonBody, options.signal);\n }\n\n if (!response.ok) {\n throw new Error(`API error: ${response.status} ${response.statusText}`);\n }\n\n return response.json() as Promise<AutocompleteResponse>;\n }\n\n // === API key mode (default) ===\n const authHeader = buildApiKeyAuthHeader(apiConfig);\n if (!authHeader && !hasWarnedMissingKey) {\n hasWarnedMissingKey = true;\n // biome-ignore lint/suspicious/noConsole: intentional dev warning\n console.warn(\n \"[AIAutocomplete] No apiKey in apiConfig. Requests will be sent without an Authorization header.\",\n );\n }\n if (authHeader) headers.Authorization = authHeader;\n\n const response = await fetch(endpoint, {\n method: \"POST\",\n headers,\n body: jsonBody,\n signal: options.signal,\n });\n\n if (!response.ok) {\n throw new Error(`API error: ${response.status} ${response.statusText}`);\n }\n\n return response.json() as Promise<AutocompleteResponse>;\n}\n","import type { Suggestion, SuggestionOption } from \"../types\";\n\n/**\n * Applies option overrides by calling the override function with an empty query,\n * then prepending results to suggestions that match by type, deduplicating by text.\n */\nexport function applyOptionOverrides(\n suggestions: Suggestion[],\n overrides?: Record<string, (query: string) => SuggestionOption[]>,\n): Suggestion[] {\n if (!overrides) return suggestions;\n return suggestions.map((s) => {\n const fn = overrides[s.type];\n if (!fn) return s;\n const extra = fn(\"\");\n if (extra.length === 0) return s;\n const existingTexts = new Set(extra.map((o) => o.text));\n const deduped = (s.options ?? []).filter((o) => !existingTexts.has(o.text));\n return { ...s, options: [...extra, ...deduped] };\n });\n}\n","import type {\n APIConfig,\n CompletedParamState,\n OptionOverrides,\n Suggestion,\n SuggestionOption,\n} from \"../../types\";\nimport { fetchSuggestions } from \"../../utils/api\";\nimport { buildQuery } from \"../../utils/buildQuery\";\nimport { extractFilterQuery, filterOptions, findExactMatch } from \"../../utils/filtering\";\nimport { applyOptionOverrides } from \"../../utils/overrides\";\nimport type { Store } from \"../state\";\nimport type { CoreState } from \"../types\";\n\nconst DEBOUNCE_MS = 100;\nconst SLOW_DEBOUNCE_MS = 300;\nconst MIN_CHARS_DIFF = 2;\n\nexport interface FetchAutoMatchEvent {\n active: Suggestion;\n matched: SuggestionOption;\n rawQuery: string;\n}\n\nexport interface FetchControllerCallbacks {\n onAutoMatch?: (event: FetchAutoMatchEvent) => void;\n}\n\nexport class FetchController {\n private fetchVersion = 0;\n private abortController: AbortController | null = null;\n private debounceTimer: ReturnType<typeof setTimeout> | null = null;\n private slowDebounceTimer: ReturnType<typeof setTimeout> | null = null;\n private unsubscribe: (() => void) | null = null;\n\n constructor(\n private store: Store<CoreState>,\n private getApiConfig: () => APIConfig | undefined,\n private getOptionOverrides: () => OptionOverrides | undefined,\n private getMaskCompletedText: () => boolean | undefined,\n private getOnError: () => ((error: Error) => void) | undefined,\n private getSessionId: () => string,\n private callbacks: FetchControllerCallbacks = {},\n ) {}\n\n start() {\n // Initial fetch\n this.doFetch(\"\", []);\n\n // Subscribe to state changes for debounced fetching\n let prevText = this.store.get().text;\n let prevParams = this.store.get().completedParams;\n this.unsubscribe = this.store.subscribe((next) => {\n if (next.text !== prevText || next.completedParams !== prevParams) {\n prevText = next.text;\n prevParams = next.completedParams;\n this.scheduleFetch();\n }\n });\n }\n\n dispose() {\n this.abortController?.abort();\n this.clearTimers();\n this.unsubscribe?.();\n }\n\n async doFetch(rawQuery: string, completed: CompletedParamState[]) {\n this.abortController?.abort();\n const controller = new AbortController();\n this.abortController = controller;\n const version = ++this.fetchVersion;\n const state = this.store.get();\n const textAtRequest = state.text.length;\n\n const hasSuggestions = state.suggestions.some((s) => s.type !== \"placeholder\");\n if (!hasSuggestions) this.store.set({ isLoading: true });\n this.store.set({ error: null });\n\n try {\n const res = await fetchSuggestions(rawQuery, completed, {\n sessionId: this.getSessionId(),\n maskCompletedText: this.getMaskCompletedText(),\n signal: controller.signal,\n apiConfig: this.getApiConfig(),\n });\n\n if (version !== this.fetchVersion) return;\n\n let newSuggestions = applyOptionOverrides(\n res.data.suggestions ?? [],\n this.getOptionOverrides(),\n );\n\n const input = res.data.input ?? [];\n const lastInput = input[input.length - 1];\n const currentText = this.store.get().text;\n let filterBase: number;\n let filterInProgress: boolean;\n\n if (lastInput?.state === \"in_progress\") {\n filterInProgress = true;\n const inProgressIdx = currentText.toLowerCase().lastIndexOf(lastInput.text.toLowerCase());\n filterBase = inProgressIdx !== -1 ? inProgressIdx : textAtRequest;\n } else {\n filterInProgress = false;\n filterBase = textAtRequest;\n }\n\n // Check if user already typed an exact match while waiting\n const actionable = newSuggestions.filter((s) => s.type !== \"placeholder\");\n const active = actionable[0];\n let extraParam: CompletedParamState | null = null;\n if (active) {\n const query = extractFilterQuery(currentText, filterBase, filterInProgress);\n const match = findExactMatch(active.options, query);\n if (match) {\n extraParam = {\n id: crypto.randomUUID(),\n placeholder: \"\",\n type: active.type,\n text: match.text,\n kind: match.kind,\n suggestionType: active.type,\n suggestionPlaceholder: active.text,\n options: active.options ?? [],\n metadata: match.metadata,\n };\n newSuggestions = newSuggestions.filter((s) => s !== active);\n this.callbacks.onAutoMatch?.({ active, matched: match, rawQuery });\n }\n }\n\n this.store.set((s) => ({\n suggestions: newSuggestions,\n isLoading: false,\n isReady: res.data.is_ready ?? false,\n lastRawQuery: rawQuery,\n activeDropdownIndex: -1,\n filterBase,\n filterInProgress,\n ...(extraParam ? { completedParams: [...s.completedParams, extraParam] } : {}),\n }));\n } catch (err) {\n if (version === this.fetchVersion) {\n const caughtError = err instanceof Error ? err : new Error(String(err));\n this.store.set({ error: caughtError, isLoading: false });\n this.getOnError()?.(caughtError);\n }\n }\n }\n\n private scheduleFetch() {\n this.clearTimers();\n const state = this.store.get();\n\n if (state.skipNextFetch) {\n this.store.set({ skipNextFetch: false });\n return;\n }\n\n const attemptFetch = (minDiff: number): boolean => {\n const s = this.store.get();\n if (!s.text && s.completedParams.length === 0) {\n this.doFetch(\"\", []);\n return true;\n }\n\n const currentQuery = extractFilterQuery(s.text, s.filterBase, s.filterInProgress);\n const actionable = s.suggestions.filter((sg: Suggestion) => sg.type !== \"placeholder\");\n const active = actionable[0];\n const currentFiltered = active ? filterOptions(active.options, currentQuery) : [];\n const tappableFiltered = currentFiltered.filter((o: SuggestionOption) => o.is_tappable);\n const hasExactMatch = active ? findExactMatch(active.options, currentQuery) !== null : false;\n\n const isInFilterZone = currentQuery.trim().length > 0;\n if (tappableFiltered.length > 0 && !hasExactMatch && isInFilterZone) return false;\n\n // Mirror the filter-zone behavior for placeholder suggestions: if the user is\n // still typing a prefix of the server-provided placeholder, don't fetch yet.\n if (s.completedParams.length === 0 && s.text.length > 0) {\n const placeholderText = s.suggestions\n .filter((sg: Suggestion) => sg.type === \"placeholder\")\n .map((sg: Suggestion) => sg.text)\n .join(\" \");\n if (\n placeholderText.length > 0 &&\n placeholderText.toLowerCase().startsWith(s.text.toLowerCase())\n ) {\n return false;\n }\n }\n\n const { rawQuery, completedParams: updatedParams } = buildQuery(s.text, s.completedParams);\n const isDeleting = rawQuery.length < s.lastRawQuery.length;\n const charDiff = Math.abs(rawQuery.length - s.lastRawQuery.length);\n if (isDeleting || charDiff >= minDiff) {\n this.doFetch(rawQuery, updatedParams);\n return true;\n }\n return false;\n };\n\n this.debounceTimer = setTimeout(() => {\n if (attemptFetch(MIN_CHARS_DIFF)) {\n if (this.slowDebounceTimer) clearTimeout(this.slowDebounceTimer);\n }\n }, DEBOUNCE_MS);\n\n this.slowDebounceTimer = setTimeout(() => attemptFetch(1), SLOW_DEBOUNCE_MS);\n }\n\n private clearTimers() {\n if (this.debounceTimer) clearTimeout(this.debounceTimer);\n if (this.slowDebounceTimer) clearTimeout(this.slowDebounceTimer);\n this.debounceTimer = null;\n this.slowDebounceTimer = null;\n }\n}\n","import type { AutocompleteResult, SuggestionOption } from \"../../types\";\nimport { buildQuery } from \"../../utils/buildQuery\";\nimport type { Store } from \"../state\";\nimport type { CoreState } from \"../types\";\n\nexport interface KeyboardContext {\n columns: number;\n listboxId: string;\n getOnSubmit: () => ((result: AutocompleteResult) => void) | undefined;\n /** Optional hook invoked after onSubmit fires (used by Tier 1 to auto-reset). */\n afterSubmit?: () => void;\n selectOption: (option: SuggestionOption) => void;\n}\n\nexport class KeyboardController {\n constructor(\n private store: Store<CoreState>,\n private ctx: KeyboardContext,\n ) {}\n\n handleKeyDown(e: KeyboardEvent) {\n const state = this.store.get();\n const { listboxId, getOnSubmit } = this.ctx;\n const columns = this.getEffectiveColumns();\n const onSubmit = getOnSubmit();\n const tappableIndices = this.getTappableIndices(columns);\n\n switch (e.key) {\n case \"ArrowDown\": {\n const target = e.target as HTMLTextAreaElement;\n const cursorAtEnd =\n target.selectionStart != null && target.selectionStart === target.value.length;\n if (!cursorAtEnd && state.activeDropdownIndex < 0) break;\n\n e.preventDefault();\n if (!state.isDropdownOpen && state.actionableSuggestions.length > 0) {\n this.store.set({ pillTapped: true, activeDropdownIndex: tappableIndices[0] ?? 0 });\n break;\n }\n if (tappableIndices.length === 0) return;\n const currentPos = tappableIndices.indexOf(state.activeDropdownIndex);\n const nextPos = currentPos < tappableIndices.length - 1 ? currentPos + 1 : 0;\n this.store.set({ activeDropdownIndex: tappableIndices[nextPos] });\n break;\n }\n case \"ArrowUp\": {\n if (tappableIndices.length === 0 || state.activeDropdownIndex < 0) break;\n e.preventDefault();\n if (state.activeDropdownIndex < columns) {\n this.store.set({ activeDropdownIndex: -1 });\n break;\n }\n const currentPos = tappableIndices.indexOf(state.activeDropdownIndex);\n const prevPos = currentPos > 0 ? currentPos - 1 : tappableIndices.length - 1;\n this.store.set({ activeDropdownIndex: tappableIndices[prevPos] });\n break;\n }\n case \"ArrowRight\": {\n if (state.activeDropdownIndex < 0) {\n const target = e.target as HTMLTextAreaElement;\n const atEnd =\n target.selectionStart != null && target.selectionStart === target.value.length;\n if (atEnd && state.actionableSuggestions.length > 1) {\n e.preventDefault();\n this.pillsSetActivePill(1);\n }\n break;\n }\n const col = state.activeDropdownIndex % columns;\n if (col < columns - 1) {\n const rightNeighbor = state.activeDropdownIndex + 1;\n if (\n rightNeighbor < state.filteredOptions.length &&\n state.filteredOptions[rightNeighbor]?.is_tappable\n ) {\n e.preventDefault();\n this.store.set({ activeDropdownIndex: rightNeighbor });\n }\n }\n break;\n }\n case \"ArrowLeft\": {\n if (state.activeDropdownIndex < 0) break;\n if (state.activeDropdownIndex % columns > 0) {\n const leftNeighbor = state.activeDropdownIndex - 1;\n if (leftNeighbor >= 0 && state.filteredOptions[leftNeighbor]?.is_tappable) {\n e.preventDefault();\n this.store.set({ activeDropdownIndex: leftNeighbor });\n }\n }\n break;\n }\n case \"Enter\": {\n e.preventDefault();\n if (\n state.activeDropdownIndex >= 0 &&\n state.filteredOptions[state.activeDropdownIndex]?.is_tappable\n ) {\n this.clickOrSelect(state.activeDropdownIndex, state.filteredOptions, listboxId);\n } else if (onSubmit) {\n const { rawQuery, completedParams: finalParams } = buildQuery(\n state.text,\n state.completedParams,\n );\n onSubmit({\n query: state.text.trim(),\n raw_query: rawQuery,\n completed_params: finalParams,\n });\n this.ctx.afterSubmit?.();\n }\n break;\n }\n case \"Tab\": {\n const placeholderVisible = !state.text && !!state.placeholderText;\n const hasHighlightedOption =\n state.activeDropdownIndex >= 0 &&\n state.filteredOptions[state.activeDropdownIndex]?.is_tappable;\n\n // Placeholder visible + option highlighted → defer to selectOption,\n // which prepends the placeholder text to the option (see AIAutocomplete.selectOption).\n if (placeholderVisible && !hasHighlightedOption) {\n e.preventDefault();\n const placeholderSuggestion = state.suggestions.find((s) => s.type === \"placeholder\");\n if (placeholderSuggestion) {\n this.store.set((s) => ({\n text: state.placeholderText,\n filterBase: state.placeholderText.length,\n completedParams: [\n ...s.completedParams,\n {\n id: crypto.randomUUID(),\n placeholder: \"\",\n type: placeholderSuggestion.type,\n text: state.placeholderText,\n kind: null,\n suggestionType: placeholderSuggestion.type,\n suggestionPlaceholder: placeholderSuggestion.text,\n options: placeholderSuggestion.options ?? [],\n },\n ],\n suggestions: s.suggestions.filter((sg) => sg !== placeholderSuggestion),\n }));\n } else {\n this.store.set({\n text: state.placeholderText,\n filterBase: state.placeholderText.length,\n });\n }\n } else if (hasHighlightedOption) {\n e.preventDefault();\n this.clickOrSelect(state.activeDropdownIndex, state.filteredOptions, listboxId);\n } else if (state.isDropdownOpen) {\n const firstTappableIdx = state.filteredOptions.findIndex((o) => o.is_tappable);\n if (firstTappableIdx >= 0) {\n e.preventDefault();\n this.clickOrSelect(firstTappableIdx, state.filteredOptions, listboxId);\n }\n }\n break;\n }\n case \"Escape\":\n this.store.set({ activeDropdownIndex: -1 });\n break;\n }\n }\n\n private getTappableIndices(columns: number): number[] {\n const state = this.store.get();\n const tappable = state.filteredOptions\n .map((o, i) => (o.is_tappable ? i : -1))\n .filter((i) => i !== -1);\n const buckets: number[][] = Array.from({ length: columns }, () => []);\n for (const i of tappable) buckets[i % columns].push(i);\n return buckets.flat();\n }\n\n /**\n * The grid uses a container query to switch between 1 and 2 columns based on\n * width, so the prop value can disagree with what's actually rendered. Read\n * the live column count from the grid; fall back to the prop if unavailable.\n */\n private getEffectiveColumns(): number {\n const firstOption = document.getElementById(`${this.ctx.listboxId}-option-0`);\n const grid = firstOption?.parentElement;\n if (!grid) return this.ctx.columns;\n const tracks = getComputedStyle(grid).gridTemplateColumns.split(\" \").filter(Boolean).length;\n return tracks > 0 ? tracks : this.ctx.columns;\n }\n\n private clickOrSelect(index: number, options: SuggestionOption[], listboxId: string) {\n const optionEl = document.getElementById(`${listboxId}-option-${index}`);\n if (optionEl) {\n optionEl.click();\n } else {\n this.ctx.selectOption(options[index]);\n }\n }\n\n /** Delegate to pills controller logic inline (avoids circular dep) */\n private pillsSetActivePill(index: number) {\n const state = this.store.get();\n const actionable = state.suggestions.filter((s) => s.type !== \"placeholder\");\n if (index < 0 || index >= actionable.length) return;\n const moved = actionable[index];\n const rest = actionable.filter((_, i) => i !== index);\n const placeholders = state.suggestions.filter((s) => s.type === \"placeholder\");\n this.store.set({\n suggestions: [...placeholders, moved, ...rest],\n pillTapped: true,\n activeDropdownIndex: -1,\n });\n }\n}\n","import type { Suggestion } from \"../../types\";\nimport { buildQuery } from \"../../utils/buildQuery\";\nimport type { Store } from \"../state\";\nimport type { CoreState } from \"../types\";\n\nexport interface PillSelectedEvent {\n rawQuery: string;\n selectedPill: string;\n otherPills: string[];\n}\n\nexport interface PillsControllerCallbacks {\n onPillSelected?: (event: PillSelectedEvent) => void;\n}\n\nexport class PillsController {\n constructor(\n private store: Store<CoreState>,\n private callbacks: PillsControllerCallbacks = {},\n ) {}\n\n setActivePill(index: number) {\n const state = this.store.get();\n const actionable = state.suggestions.filter((s) => s.type !== \"placeholder\");\n if (index < 0 || index >= actionable.length) return;\n const moved = actionable[index];\n const rest = actionable.filter((_, i) => i !== index);\n const placeholders = state.suggestions.filter((s) => s.type === \"placeholder\");\n\n if (this.callbacks.onPillSelected) {\n const { rawQuery } = buildQuery(state.text, state.completedParams);\n this.callbacks.onPillSelected({\n rawQuery,\n selectedPill: moved.text,\n otherPills: rest.map((s) => s.text),\n });\n }\n\n this.store.set({\n suggestions: [...placeholders, moved, ...rest],\n pillTapped: true,\n activeDropdownIndex: -1,\n });\n }\n\n removeLastParam() {\n const state = this.store.get();\n if (state.completedParams.length === 0) return;\n const lastParam = state.completedParams[state.completedParams.length - 1];\n const restoredSuggestion: Suggestion = {\n type: lastParam.suggestionType,\n text: lastParam.suggestionPlaceholder,\n required: true,\n options: lastParam.options,\n };\n this.store.set((s) => ({\n completedParams: s.completedParams.slice(0, -1),\n suggestions: [restoredSuggestion, ...s.suggestions],\n activeDropdownIndex: -1,\n }));\n }\n}\n","import type { Suggestion } from \"../../types\";\n\nfunction getPillOpacity(index: number): number {\n if (index === 0) return 0.4;\n if (index === 1) return 0.3;\n return 0.15;\n}\n\nexport function renderPills(\n container: HTMLElement,\n pills: Suggestion[],\n activePillIndex: number,\n onSelectPill: (index: number) => void,\n rounded = false,\n) {\n // Reuse or create the list wrapper\n let list = container.querySelector<HTMLElement>(\".magicx-aia-pill-list\");\n if (!list) {\n list = document.createElement(\"span\");\n list.className = \"magicx-aia-pill-list\";\n container.appendChild(list);\n }\n\n // Diff by key (type-text)\n const existing = new Map<string, HTMLButtonElement>();\n for (const btn of list.querySelectorAll<HTMLButtonElement>(\".magicx-aia-pill\")) {\n existing.set(btn.dataset.pillKey ?? \"\", btn);\n }\n\n const used = new Set<string>();\n for (let i = 0; i < pills.length; i++) {\n const pill = pills[i];\n const key = `${pill.type}-${pill.text}`;\n used.add(key);\n\n let btn = existing.get(key);\n if (!btn) {\n btn = document.createElement(\"button\");\n btn.type = \"button\";\n btn.dataset.pillKey = key;\n btn.setAttribute(\"data-aia-pill\", \"\");\n btn.textContent = pill.text;\n }\n\n btn.className = `magicx-aia-pill${rounded ? \" magicx-aia-pill--rounded\" : \"\"}${i === activePillIndex ? \" magicx-aia-pill--active\" : \"\"}`;\n btn.style.opacity = String(getPillOpacity(i));\n btn.onclick = () => onSelectPill(i);\n\n // Ensure correct order\n if (list.children[i] !== btn) {\n list.insertBefore(btn, list.children[i] ?? null);\n }\n }\n\n // Remove stale pills\n for (const [key, btn] of existing) {\n if (!used.has(key)) btn.remove();\n }\n}\n\nexport function clearPills(container: HTMLElement) {\n container.querySelector(\".magicx-aia-pill-list\")?.remove();\n}\n","import type { Suggestion, SuggestionOption } from \"../../types\";\nimport { renderPills } from \"./renderPills\";\n\ninterface DropdownState {\n suggestions: Suggestion[];\n filteredOptions: SuggestionOption[];\n activeIndex: number;\n isOpen: boolean;\n listboxId: string;\n pills: Suggestion[];\n showPills: boolean;\n onSelect: (option: SuggestionOption) => void;\n onHighlight: (index: number) => void;\n onPillClick: (index: number) => void;\n}\n\nexport function createDropdown(listboxId: string): HTMLElement {\n const dropdown = document.createElement(\"div\");\n dropdown.id = listboxId;\n dropdown.setAttribute(\"role\", \"listbox\");\n dropdown.setAttribute(\"data-aia-dropdown\", \"\");\n dropdown.className = \"magicx-aia-dropdown\";\n dropdown.addEventListener(\"mousedown\", (e) => e.preventDefault());\n return dropdown;\n}\n\nexport function renderDropdown(dropdown: HTMLElement, state: DropdownState) {\n const {\n filteredOptions,\n activeIndex,\n isOpen,\n pills,\n showPills,\n onSelect,\n onHighlight,\n onPillClick,\n } = state;\n\n const hasPills = showPills && pills.length > 0;\n const hasOptions = isOpen && filteredOptions.length > 0;\n const isVisible = hasOptions || (isOpen && hasPills);\n\n // Toggle visibility\n if (isVisible) {\n dropdown.classList.add(\"magicx-aia-dropdown--visible\");\n } else {\n dropdown.classList.remove(\"magicx-aia-dropdown--visible\");\n }\n\n // --- Pill bar ---\n let pillBar = dropdown.querySelector<HTMLElement>(\".magicx-aia-pill-bar\");\n if (hasPills) {\n if (!pillBar) {\n pillBar = document.createElement(\"div\");\n pillBar.className = \"magicx-aia-pill-bar\";\n pillBar.setAttribute(\"data-aia-pillbar\", \"\");\n dropdown.insertBefore(pillBar, dropdown.firstChild);\n }\n renderPills(pillBar, pills, 0, onPillClick, true);\n } else if (pillBar) {\n pillBar.remove();\n }\n\n // --- Options grid ---\n let grid = dropdown.querySelector<HTMLElement>(\".magicx-aia-grid\");\n if (filteredOptions.length > 0) {\n if (!grid) {\n grid = document.createElement(\"div\");\n grid.className = \"magicx-aia-grid\";\n dropdown.appendChild(grid);\n }\n renderOptions(grid, filteredOptions, activeIndex, onSelect, onHighlight, state.listboxId);\n } else if (grid) {\n grid.innerHTML = \"\";\n }\n}\n\nfunction renderOptions(\n grid: HTMLElement,\n options: SuggestionOption[],\n activeIndex: number,\n onSelect: (option: SuggestionOption) => void,\n onHighlight: (index: number) => void,\n listboxId: string,\n) {\n const optionsKey = options.map((o) => o.text).join(\"\\0\");\n const lastKey = grid.dataset.optionsKey ?? \"\";\n const listChanged = optionsKey !== lastKey;\n grid.dataset.optionsKey = optionsKey;\n\n if (listChanged) {\n // Full rebuild — options changed (filter, new suggestion, etc.)\n const fragment = document.createDocumentFragment();\n\n for (let i = 0; i < options.length; i++) {\n const option = options[i];\n const item = createOptionElement(option, i, activeIndex, onSelect, onHighlight, listboxId);\n fragment.appendChild(item);\n }\n\n grid.innerHTML = \"\";\n grid.appendChild(fragment);\n } else {\n // Just update highlight classes — no DOM rebuild\n const items = grid.querySelectorAll<HTMLElement>(\".magicx-aia-option\");\n for (let i = 0; i < items.length; i++) {\n const item = items[i];\n const isHighlighted = i === activeIndex;\n item.setAttribute(\"aria-selected\", String(isHighlighted));\n if (isHighlighted) {\n item.classList.add(\"magicx-aia-option--highlighted\");\n } else {\n item.classList.remove(\"magicx-aia-option--highlighted\");\n }\n }\n }\n}\n\nfunction createOptionElement(\n option: SuggestionOption,\n index: number,\n activeIndex: number,\n onSelect: (option: SuggestionOption) => void,\n onHighlight: (index: number) => void,\n listboxId: string,\n): HTMLElement {\n const item = document.createElement(\"div\");\n item.id = `${listboxId}-option-${index}`;\n item.setAttribute(\"role\", \"option\");\n item.setAttribute(\"data-aia-option\", \"\");\n item.setAttribute(\"aria-selected\", String(index === activeIndex));\n item.tabIndex = option.is_tappable ? 0 : -1;\n\n const classes = [\"magicx-aia-option\"];\n if (index === activeIndex) classes.push(\"magicx-aia-option--highlighted\");\n if (option.is_tappable) {\n classes.push(\"magicx-aia-option--tappable\");\n } else {\n classes.push(\"magicx-aia-option--non-tappable\");\n }\n item.className = classes.join(\" \");\n\n // Streaks\n const streaks = document.createElement(\"div\");\n streaks.className = \"magicx-aia-streaks\";\n item.appendChild(streaks);\n\n const streaksVert = document.createElement(\"div\");\n streaksVert.className = \"magicx-aia-streaks-vert\";\n item.appendChild(streaksVert);\n\n // Content\n const content = document.createElement(\"span\");\n content.className = \"magicx-aia-option-content\";\n content.textContent = option.icon ? `${option.icon} ${option.text}` : option.text;\n\n if (option.tag) {\n const tag = document.createElement(\"span\");\n tag.className = \"magicx-aia-option-tag\";\n tag.textContent = option.tag;\n content.appendChild(tag);\n }\n\n item.appendChild(content);\n\n // Events\n if (option.is_tappable) {\n item.addEventListener(\"click\", () => {\n item.classList.add(\"magicx-aia-option--pressed\");\n onSelect(option);\n setTimeout(() => item.classList.remove(\"magicx-aia-option--pressed\"), 400);\n });\n item.addEventListener(\"mouseenter\", () => onHighlight(index));\n }\n\n return item;\n}\n","import type { SuggestionOption } from \"../../types\";\nimport type { Store } from \"../state\";\nimport type { CoreState } from \"../types\";\nimport { createDropdown, renderDropdown } from \"./renderDropdown\";\n\ninterface DropdownOnlyRefs {\n dropdown: HTMLElement;\n}\n\ninterface DropdownOnlyOptions {\n store: Store<CoreState>;\n listboxId: string;\n selectOption: (option: SuggestionOption) => void;\n setActivePill: (index: number) => void;\n}\n\nexport function buildDropdownOnly(\n container: HTMLElement,\n opts: DropdownOnlyOptions,\n): DropdownOnlyRefs {\n const dropdown = createDropdown(opts.listboxId);\n container.appendChild(dropdown);\n return { dropdown };\n}\n\nexport function updateDropdownOnly(\n refs: DropdownOnlyRefs,\n state: CoreState,\n opts: DropdownOnlyOptions,\n) {\n renderDropdown(refs.dropdown, {\n suggestions:\n state.actionableSuggestions.length > 0\n ? [{ ...state.actionableSuggestions[0], options: state.filteredOptions }]\n : [],\n filteredOptions: state.filteredOptions,\n activeIndex: state.activeDropdownIndex,\n isOpen: state.isDropdownOpen,\n listboxId: opts.listboxId,\n pills: state.actionableSuggestions,\n showPills: true, // always show pills in dropdown-only mode\n onSelect: opts.selectOption,\n onHighlight: (i) => opts.store.set({ activeDropdownIndex: i }),\n onPillClick: opts.setActivePill,\n });\n}\n","import type { Segment } from \"../../types\";\n\n/**\n * Renders text segments into the sizer overlay.\n * Only rebuilds the DOM when segment content or newParamId changes,\n * preserving in-flight CSS animations (shimmer).\n * Cache keys stored on the DOM element to support multi-instance use.\n */\nexport function renderSegments(\n sizer: HTMLElement,\n segments: Segment[],\n newParamId: string | null,\n isEmpty: boolean,\n placeholderText: string,\n) {\n let sizerText = sizer.querySelector<HTMLElement>(\".magicx-aia-sizer-text\");\n let placeholder = sizer.querySelector<HTMLElement>(\".magicx-aia-placeholder\");\n\n if (isEmpty && placeholderText) {\n if (sizerText) sizerText.style.display = \"none\";\n if (!placeholder) {\n placeholder = document.createElement(\"span\");\n placeholder.className = \"magicx-aia-placeholder\";\n sizer.insertBefore(placeholder, sizer.firstChild);\n }\n placeholder.style.display = \"\";\n placeholder.textContent = `${placeholderText} `;\n sizer.dataset.segmentKey = \"\";\n return;\n }\n\n if (placeholder) placeholder.style.display = \"none\";\n if (!sizerText) {\n sizerText = document.createElement(\"span\");\n sizerText.className = \"magicx-aia-sizer-text\";\n sizer.insertBefore(sizerText, sizer.firstChild);\n }\n sizerText.style.display = \"\";\n sizerText.className = `magicx-aia-sizer-text${newParamId ? \" magicx-aia-sizer-text--visible\" : \"\"}`;\n\n const segmentKey = segments.map((s) => `${s.type}:${s.value}`).join(\"\\0\");\n const lastKey = sizer.dataset.segmentKey ?? \"\";\n const lastParamId = sizer.dataset.newParamId ?? \"\";\n if (segmentKey === lastKey && (newParamId ?? \"\") === lastParamId) {\n return; // Nothing changed — preserve existing DOM and animations\n }\n sizer.dataset.segmentKey = segmentKey;\n sizer.dataset.newParamId = newParamId ?? \"\";\n\n sizerText.innerHTML = \"\";\n for (const seg of segments) {\n const span = document.createElement(\"span\");\n if (seg.type === \"completed\") {\n const isNew = seg.param.id === newParamId;\n if (isNew) {\n span.className = \"magicx-aia-shimmer-revealed magicx-aia-shimmer-sweep\";\n } else {\n span.className = \"magicx-aia-segment magicx-aia-segment--completed\";\n }\n }\n span.textContent = seg.value;\n sizerText.appendChild(span);\n }\n\n if (segments.length === 0) {\n sizerText.textContent = \"\\u00A0\";\n }\n}\n","import type { AutocompleteResult } from \"../../types\";\nimport { buildQuery } from \"../../utils/buildQuery\";\nimport type { Store } from \"../state\";\nimport type { CoreState } from \"../types\";\nimport { createDropdown, renderDropdown } from \"./renderDropdown\";\nimport { renderPills } from \"./renderPills\";\nimport { renderSegments } from \"./renderSegments\";\n\ninterface RenderInputOptions {\n store: Store<CoreState>;\n listboxId: string;\n pillPlacement: \"inline\" | \"dropdown\" | \"hidden\";\n autoFocus?: boolean;\n onSubmit?: (result: AutocompleteResult) => void;\n /** Invoked after onSubmit fires — Tier 1 uses this to auto-reset. */\n afterSubmit?: () => void;\n submitButton?: HTMLElement | null;\n selectOption: (option: import(\"../../types\").SuggestionOption) => void;\n setActivePill: (index: number) => void;\n handleKeyDown: (e: KeyboardEvent) => void;\n handleChange: (value: string) => void;\n}\n\nexport interface DOMRefs {\n textarea: HTMLTextAreaElement;\n dropdown: HTMLElement;\n sizer: HTMLElement;\n /** The default built-in button when no `submitButton` was provided. Null when consumer passed `null` or a custom element. */\n submitButton: HTMLButtonElement | null;\n inlinePillContainer: HTMLElement;\n}\n\nconst SUBMIT_SVG = `<svg width=\"18\" height=\"18\" viewBox=\"0 0 18 18\" fill=\"none\" role=\"img\" aria-label=\"Submit\"><path d=\"M9 14V4M9 4L4 9M9 4L14 9\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>`;\n\nexport function buildDOM(container: HTMLElement, opts: RenderInputOptions): DOMRefs {\n const { listboxId } = opts;\n\n // Dropdown\n const dropdown = createDropdown(listboxId);\n container.appendChild(dropdown);\n\n // Input wrapper\n const inputWrapper = document.createElement(\"div\");\n inputWrapper.className = \"magicx-aia-input-wrapper\";\n container.appendChild(inputWrapper);\n\n // Editor area\n const editor = document.createElement(\"div\");\n editor.className = \"magicx-aia-editor\";\n editor.setAttribute(\"data-aia-editor\", \"\");\n inputWrapper.appendChild(editor);\n\n // Sizer (overlay)\n const sizer = document.createElement(\"div\");\n sizer.className = \"magicx-aia-sizer\";\n sizer.setAttribute(\"aria-hidden\", \"true\");\n editor.appendChild(sizer);\n\n // Inline pill container (inside sizer, after segments)\n const inlinePillContainer = document.createElement(\"span\");\n sizer.appendChild(document.createTextNode(\" \"));\n sizer.appendChild(inlinePillContainer);\n\n // Textarea\n const textarea = document.createElement(\"textarea\");\n textarea.className = \"magicx-aia-textarea\";\n textarea.rows = 1;\n textarea.setAttribute(\"role\", \"combobox\");\n textarea.setAttribute(\"aria-autocomplete\", \"list\");\n textarea.setAttribute(\"aria-controls\", listboxId);\n textarea.setAttribute(\"data-aia-textarea\", \"\");\n editor.appendChild(textarea);\n\n // Submit button — null means render nothing; undefined means default; HTMLElement means custom\n let submitButton: HTMLButtonElement | null = null;\n let submitTarget: HTMLElement | null = null;\n if (opts.submitButton === undefined) {\n submitButton = document.createElement(\"button\");\n submitButton.type = \"button\";\n submitButton.className = \"magicx-aia-submit\";\n submitButton.setAttribute(\"aria-label\", \"Submit\");\n submitButton.setAttribute(\"data-aia-submit\", \"\");\n submitButton.innerHTML = SUBMIT_SVG;\n inputWrapper.appendChild(submitButton);\n submitTarget = submitButton;\n } else if (opts.submitButton !== null) {\n submitTarget = opts.submitButton;\n if (!submitTarget.hasAttribute(\"data-aia-submit\")) {\n submitTarget.setAttribute(\"data-aia-submit\", \"\");\n }\n inputWrapper.appendChild(submitTarget);\n }\n\n // --- Event wiring ---\n\n // Click wrapper → focus textarea\n inputWrapper.addEventListener(\"click\", () => textarea.focus());\n\n // Textarea change\n textarea.addEventListener(\"input\", () => {\n const raw = textarea.value;\n const shouldCapitalize = raw.length > 0 && raw[0] !== raw[0].toUpperCase();\n const newValue = shouldCapitalize ? raw[0].toUpperCase() + raw.slice(1) : raw;\n opts.handleChange(newValue);\n });\n\n // Keyboard\n textarea.addEventListener(\"keydown\", (e) => opts.handleKeyDown(e));\n\n // Focus tracking — auto-trigger uses this to open dropdown when focused\n textarea.addEventListener(\"focus\", () => opts.store.set({ isFocused: true }));\n textarea.addEventListener(\"blur\", () => opts.store.set({ isFocused: false }));\n\n // Submit click — wired on whatever element fills the slot (default or custom)\n if (submitTarget) {\n submitTarget.addEventListener(\"click\", (e) => {\n const state = opts.store.get();\n const canSubmit = !!state.text || state.completedParams.length > 0;\n if (!canSubmit || !opts.onSubmit) return;\n e.stopPropagation();\n const { rawQuery, completedParams: finalParams } = buildQuery(\n state.text,\n state.completedParams,\n );\n opts.onSubmit({\n query: state.text.trim(),\n raw_query: rawQuery,\n completed_params: finalParams,\n });\n opts.afterSubmit?.();\n });\n }\n\n // Focus textarea on mount\n if (opts.autoFocus !== false) {\n textarea.focus();\n }\n\n return { textarea, dropdown, sizer, submitButton, inlinePillContainer };\n}\n\nexport function updateDOM(refs: DOMRefs, state: CoreState, opts: RenderInputOptions) {\n const { textarea, dropdown, sizer, submitButton, inlinePillContainer } = refs;\n const { pillPlacement, setActivePill, selectOption, store } = opts;\n\n // Textarea value\n if (textarea.value !== state.text) {\n textarea.value = state.text;\n }\n\n // Placeholder\n if (state.placeholderText) {\n textarea.placeholder = state.placeholderText;\n } else {\n textarea.removeAttribute(\"placeholder\");\n }\n\n // ARIA\n textarea.setAttribute(\"aria-expanded\", String(state.isDropdownOpen));\n const activeDescendant =\n state.activeDropdownIndex >= 0 ? `${opts.listboxId}-option-${state.activeDropdownIndex}` : \"\";\n if (activeDescendant) {\n textarea.setAttribute(\"aria-activedescendant\", activeDescendant);\n } else {\n textarea.removeAttribute(\"aria-activedescendant\");\n }\n\n // Shimmer: hide textarea text during animation\n if (state.newParamId) {\n textarea.classList.add(\"magicx-aia-textarea--hidden\");\n } else {\n textarea.classList.remove(\"magicx-aia-textarea--hidden\");\n }\n\n // Submit button disabled state — only applies to the default built-in button.\n // Consumer-provided buttons own their own disabled visuals.\n if (submitButton) {\n const canSubmit = !!state.text || state.completedParams.length > 0;\n submitButton.disabled = !canSubmit;\n }\n\n // Segments overlay\n renderSegments(sizer, state.segments, state.newParamId, !state.text, state.placeholderText);\n\n // Inline pills\n if (pillPlacement === \"inline\") {\n renderPills(inlinePillContainer, state.actionableSuggestions, 0, setActivePill);\n } else {\n // Clear inline pills in dropdown mode\n inlinePillContainer.innerHTML = \"\";\n }\n\n // Dropdown\n renderDropdown(dropdown, {\n suggestions:\n state.actionableSuggestions.length > 0\n ? [{ ...state.actionableSuggestions[0], options: state.filteredOptions }]\n : [],\n filteredOptions: state.filteredOptions,\n activeIndex: state.activeDropdownIndex,\n isOpen: state.isDropdownOpen,\n listboxId: opts.listboxId,\n pills: state.actionableSuggestions,\n showPills: pillPlacement === \"dropdown\",\n onSelect: selectOption,\n onHighlight: (i) => store.set({ activeDropdownIndex: i }),\n onPillClick: setActivePill,\n });\n}\n","export type Listener<S> = (next: S, prev: S) => void;\n\nexport interface Store<S> {\n get: () => S;\n set: (patch: Partial<S> | ((s: S) => Partial<S>)) => void;\n subscribe: (listener: Listener<S>) => () => void;\n}\n\nexport function createStore<S>(initial: S): Store<S> {\n let state = initial;\n const listeners = new Set<Listener<S>>();\n return {\n get: () => state,\n set: (patch) => {\n const resolved = typeof patch === \"function\" ? patch(state) : patch;\n const next = { ...state, ...resolved };\n const prev = state;\n state = next;\n for (const l of listeners) l(next, prev);\n },\n subscribe: (listener) => {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n };\n}\n","let injected = false;\n\n/** Inject core + appearance CSS into document.head once. Idempotent. */\nexport function injectStyles() {\n if (injected || typeof document === \"undefined\") return;\n if (document.querySelector(\"style[data-magicx-aia]\")) {\n injected = true;\n return;\n }\n injected = true;\n\n const style = document.createElement(\"style\");\n style.setAttribute(\"data-magicx-aia\", \"\");\n style.textContent = STYLES;\n document.head.appendChild(style);\n}\n\n// Replaced at build time by tsup.config.core.ts / vitest.config.ts\ndeclare const __MAGICX_AC_STYLES__: string;\nconst STYLES = __MAGICX_AC_STYLES__;\n","import type { AppearanceMode, CompletedParamState, Suggestion, SuggestionOption } from \"../types\";\nimport { buildQuery } from \"../utils/buildQuery\";\nimport { extractFilterQuery, filterOptions, findPrefixOverlap } from \"../utils/filtering\";\nimport { ModeController } from \"../utils/modeController\";\nimport { deriveSegments, reconcileParams } from \"../utils/segments\";\nimport { sendTelemetry, type TelemetrySource } from \"../utils/telemetry\";\nimport { FetchController } from \"./controllers/fetchController\";\nimport { KeyboardController } from \"./controllers/keyboardController\";\nimport { PillsController } from \"./controllers/pillsController\";\nimport { buildDropdownOnly, updateDropdownOnly } from \"./render/renderDropdownOnly\";\nimport { buildDOM, type DOMRefs, updateDOM } from \"./render/renderInput\";\nimport { createStore } from \"./state\";\nimport { injectStyles } from \"./styleInjector\";\nimport type { CoreOptions, CoreState, RenderMode } from \"./types\";\n\nlet idCounter = 0;\nfunction stableId(): string {\n return `:ac-${++idCounter}:`;\n}\n\nfunction initialState(): CoreState {\n return {\n text: \"\",\n completedParams: [],\n suggestions: [],\n activeDropdownIndex: -1,\n newParamId: null,\n isLoading: false,\n isReady: false,\n error: null,\n segments: [],\n actionableSuggestions: [],\n filteredOptions: [],\n placeholderText: \"\",\n isDropdownOpen: false,\n filterBase: 0,\n filterInProgress: false,\n pillTapped: false,\n skipNextFetch: false,\n lastRawQuery: \"\",\n isFocused: false,\n };\n}\n\nexport class AIAutocomplete {\n private store = createStore<CoreState>(initialState());\n private _listboxId = stableId();\n private opts: CoreOptions;\n private fetchController: FetchController;\n private keyboardController: KeyboardController;\n private pillsController: PillsController;\n private modeController: ModeController | null = null;\n private container: HTMLElement;\n private unsubscribers: (() => void)[] = [];\n private derivedInProgress = false;\n private renderMode: RenderMode;\n private domRefs: DOMRefs | null = null;\n private dropdownRefs: { dropdown: HTMLElement } | null = null;\n private newParamTimer: number | undefined;\n private suggestionRemovalTimer: number | undefined;\n private externalListeners = new Set<(state: CoreState) => void>();\n private sessionId: string = crypto.randomUUID();\n\n constructor(container: HTMLElement, opts: CoreOptions = {}) {\n this.container = container;\n this.opts = opts;\n this.renderMode = opts.renderMode ?? \"full\";\n\n // Apply controlled initial values\n if (opts.value !== undefined) {\n this.store.set({ text: opts.value });\n }\n if (opts.completedParams !== undefined) {\n this.store.set({ completedParams: opts.completedParams });\n }\n\n // Controllers\n this.pillsController = new PillsController(this.store, {\n onPillSelected: ({ rawQuery, selectedPill, otherPills }) => {\n this.fireTelemetry(\"pill\", {\n raw_query: rawQuery,\n selected_pill: selectedPill,\n other_pills: otherPills,\n });\n },\n });\n\n this.fetchController = new FetchController(\n this.store,\n () => this.opts.apiConfig,\n () => this.opts.optionOverrides,\n () => this.opts.maskCompletedText,\n () => this.opts.onError,\n () => this.sessionId,\n {\n onAutoMatch: ({ active, matched, rawQuery }) => {\n this.fireTelemetry(\"option\", {\n raw_query: rawQuery,\n selected_option: matched.text,\n other_options: (active.options ?? [])\n .filter((o) => o.text !== matched.text)\n .map((o) => o.text),\n });\n },\n },\n );\n\n this.keyboardController = new KeyboardController(this.store, {\n columns: opts.columns ?? 2,\n listboxId: this.listboxId,\n getOnSubmit: () => this.opts.onSubmit,\n // Tier 1 (full) auto-resets after submit; Tier 2/3 leave it to the consumer.\n afterSubmit: this.renderMode === \"full\" ? () => this.reset() : undefined,\n selectOption: (option) => this.selectOption(option),\n });\n\n // Derived state recomputation\n this.unsubscribers.push(\n this.store.subscribe((next, prev) => {\n this.recomputeDerived(next, prev);\n }),\n );\n\n // Event callbacks\n this.unsubscribers.push(\n this.store.subscribe((next, prev) => {\n if (next.text !== prev.text) this.opts.onChange?.(next.text);\n if (next.completedParams !== prev.completedParams)\n this.opts.onParamsChange?.(next.completedParams);\n if (next.isFocused !== prev.isFocused) {\n if (next.isFocused) this.opts.onFocus?.();\n else this.opts.onBlur?.();\n }\n this.opts.onStateChange?.(next);\n }),\n );\n\n // Setup DOM based on render mode\n if (this.renderMode !== \"headless\") {\n injectStyles();\n this.setupContainer();\n }\n if (this.renderMode === \"full\") {\n this.buildAndRenderFull();\n } else if (this.renderMode === \"dropdown\") {\n this.buildAndRenderDropdown();\n }\n this.fetchController.start();\n }\n\n // === Public API ===\n\n focus() {\n this.domRefs?.textarea.focus();\n }\n\n blur() {\n this.domRefs?.textarea.blur();\n }\n\n reset() {\n // skipNextFetch suppresses the debounced fetch the FetchController would\n // otherwise schedule in response to text/params changing here — we issue\n // the empty fetch ourselves below so the new session starts immediately.\n this.store.set({\n ...initialState(),\n skipNextFetch: true,\n });\n this.sessionId = crypto.randomUUID();\n this.fetchController.doFetch(\"\", []);\n }\n\n destroy() {\n this.fetchController.dispose();\n this.modeController?.destroy();\n if (this.newParamTimer) clearTimeout(this.newParamTimer);\n if (this.suggestionRemovalTimer) clearTimeout(this.suggestionRemovalTimer);\n this.externalListeners.clear();\n for (const unsub of this.unsubscribers) unsub();\n this.unsubscribers = [];\n this.domRefs = null;\n this.dropdownRefs = null;\n if (this.renderMode !== \"headless\") {\n this.container.innerHTML = \"\";\n }\n }\n\n setMode(mode: AppearanceMode) {\n this.modeController?.setMode(mode);\n }\n\n setValue(text: string) {\n this.store.set({ text });\n }\n\n setCompletedParams(params: CompletedParamState[]) {\n this.store.set({ completedParams: params });\n }\n\n setActivePill(index: number) {\n this.pillsController.setActivePill(index);\n }\n\n removeLastParam() {\n this.pillsController.removeLastParam();\n }\n\n clearNewParamId() {\n this.store.set({ newParamId: null });\n }\n\n setActiveDropdownIndex(index: number) {\n this.store.set({ activeDropdownIndex: index });\n }\n\n handleTextChange(value: string) {\n this.handleChange(value);\n }\n\n handleKeyDown(e: KeyboardEvent) {\n this.keyboardController.handleKeyDown(e);\n }\n\n setFocused(focused: boolean) {\n if (this.store.get().isFocused === focused) return;\n this.store.set({ isFocused: focused });\n }\n\n /** Subscribe to state changes (fires after derived state is settled). Returns unsubscribe function. */\n subscribe(listener: (state: CoreState) => void): () => void {\n this.externalListeners.add(listener);\n return () => {\n this.externalListeners.delete(listener);\n };\n }\n\n getState(): CoreState {\n return this.store.get();\n }\n\n get listboxId(): string {\n return this._listboxId;\n }\n\n get isReady(): boolean {\n return this.store.get().isReady;\n }\n\n on(event: string, callback: (...args: unknown[]) => void): () => void {\n switch (event) {\n case \"submit\":\n this.opts.onSubmit = callback as CoreOptions[\"onSubmit\"];\n return () => {\n this.opts.onSubmit = undefined;\n };\n case \"error\":\n this.opts.onError = callback as CoreOptions[\"onError\"];\n return () => {\n this.opts.onError = undefined;\n };\n case \"change\":\n this.opts.onChange = callback as CoreOptions[\"onChange\"];\n return () => {\n this.opts.onChange = undefined;\n };\n case \"paramsChange\":\n this.opts.onParamsChange = callback as CoreOptions[\"onParamsChange\"];\n return () => {\n this.opts.onParamsChange = undefined;\n };\n case \"stateChange\":\n this.opts.onStateChange = callback as CoreOptions[\"onStateChange\"];\n return () => {\n this.opts.onStateChange = undefined;\n };\n case \"focus\":\n this.opts.onFocus = callback as CoreOptions[\"onFocus\"];\n return () => {\n this.opts.onFocus = undefined;\n };\n case \"blur\":\n this.opts.onBlur = callback as CoreOptions[\"onBlur\"];\n return () => {\n this.opts.onBlur = undefined;\n };\n default:\n return () => {};\n }\n }\n\n update(opts: Partial<CoreOptions>) {\n Object.assign(this.opts, opts);\n if (opts.mode !== undefined) {\n this.modeController?.setMode(opts.mode);\n }\n if (opts.optionsPosition !== undefined) {\n this.container.dataset.optionsPosition = opts.optionsPosition;\n }\n if (opts.animations !== undefined) {\n this.container.dataset.animations = opts.animations ? \"on\" : \"off\";\n }\n if (opts.pillPlacement !== undefined) {\n this.container.dataset.pillPlacement = opts.pillPlacement;\n this.store.set({});\n }\n if (opts.dropdownTrigger !== undefined || opts.closeDropdownOnBlur !== undefined) {\n // Trigger recompute so isDropdownOpen updates\n this.store.set({});\n }\n if (opts.value !== undefined) {\n this.store.set({ text: opts.value });\n }\n if (opts.completedParams !== undefined) {\n this.store.set({ completedParams: opts.completedParams });\n }\n }\n\n // === Public (for framework wrappers) ===\n\n selectOption(option: SuggestionOption) {\n const state = this.store.get();\n const activeSuggestion = state.actionableSuggestions[0];\n if (!activeSuggestion) return;\n\n const { rawQuery: telemetryRawQuery } = buildQuery(state.text, state.completedParams);\n this.fireTelemetry(\"option\", {\n raw_query: telemetryRawQuery,\n selected_option: option.text,\n other_options: state.filteredOptions.filter((o) => o.text !== option.text).map((o) => o.text),\n });\n\n const base = state.filterBase;\n let prefix = state.text.slice(0, base);\n\n const inputWasEmpty = prefix.length === 0 && state.text.length === 0;\n // The user is still typing within the server-provided placeholder (e.g. typed\n // \"Cre\" for placeholder \"Create a\"). Selecting an option here should keep the\n // placeholder rather than discard it — otherwise tapping \"email\" replaces\n // \"Cre\" with just \"email\" instead of \"Create a email\".\n const inputIsPlaceholderPrefix =\n prefix.length === 0 &&\n state.text.length > 0 &&\n state.placeholderText.length > 0 &&\n state.placeholderText.toLowerCase().startsWith(state.text.toLowerCase());\n if ((inputWasEmpty || inputIsPlaceholderPrefix) && state.placeholderText) {\n prefix = `${state.placeholderText} `;\n }\n\n const overlapChars = findPrefixOverlap(prefix, option.text);\n if (overlapChars > 0) {\n prefix = prefix.slice(0, prefix.length - overlapChars);\n }\n\n const needsSpace = prefix.length > 0 && prefix[prefix.length - 1] !== \" \";\n const newText = `${prefix}${needsSpace ? \" \" : \"\"}${option.text} `;\n const finalText =\n (inputWasEmpty || inputIsPlaceholderPrefix) && newText.length > 0\n ? newText[0].toUpperCase() + newText.slice(1)\n : newText;\n\n const optionStart = finalText.toLowerCase().lastIndexOf(option.text.toLowerCase());\n const optionInFinal =\n optionStart >= 0\n ? finalText.slice(optionStart, optionStart + option.text.length)\n : option.text;\n\n const completed: CompletedParamState = {\n id: crypto.randomUUID(),\n placeholder: \"\",\n type: activeSuggestion.type,\n text: optionInFinal,\n kind: option.kind,\n suggestionType: activeSuggestion.type,\n suggestionPlaceholder: activeSuggestion.text,\n options: activeSuggestion.options ?? [],\n metadata: option.metadata,\n };\n\n const remainingActionable = state.actionableSuggestions.length - 1;\n\n this.store.set((s) => ({\n text: finalText,\n filterBase: finalText.length,\n completedParams: [...s.completedParams, completed],\n newParamId: completed.id,\n pillTapped: false,\n activeDropdownIndex: -1,\n skipNextFetch: remainingActionable > 0,\n }));\n\n // Delay suggestion removal for animation\n this.suggestionRemovalTimer = window.setTimeout(() => {\n this.store.set((s) => ({\n suggestions: s.suggestions.filter((sg) => sg !== activeSuggestion),\n }));\n }, 400);\n }\n\n private fireTelemetry(type: \"pill\" | \"option\", queryData: Record<string, unknown>) {\n // Vanilla consumers don't pass `source` — derive from renderMode.\n // The React hook always uses renderMode \"headless\" but Tier 1 explicitly\n // passes source: \"full-sdk\" via opts to override.\n const source: TelemetrySource =\n this.opts.source ?? (this.renderMode === \"full\" ? \"full-sdk\" : \"headless-sdk\");\n void sendTelemetry({\n source,\n sessionId: this.sessionId,\n type,\n queryData,\n apiConfig: this.opts.apiConfig,\n });\n }\n\n private recomputeDerived(next: CoreState, _prev: CoreState) {\n if (this.derivedInProgress) return;\n this.derivedInProgress = true;\n const segments = deriveSegments(next.text, next.completedParams);\n const actionableSuggestions = next.suggestions.filter((s) => s.type !== \"placeholder\");\n const activeSuggestion = actionableSuggestions[0] as Suggestion | undefined;\n const overrideFn = activeSuggestion\n ? this.opts.optionOverrides?.[activeSuggestion.type]\n : undefined;\n\n // Clamp filterBase so it never exceeds text length (matches old React behavior)\n const clampedFilterBase = Math.min(next.filterBase, next.text.length);\n // When filterBase is 0 and no fetch has set it yet, don't filter by typed text —\n // the user is still typing the initial query and no server context exists\n const hasServerContext = next.lastRawQuery !== \"\" || clampedFilterBase > 0;\n const filterQuery = hasServerContext\n ? extractFilterQuery(next.text, clampedFilterBase, next.filterInProgress)\n : \"\";\n const baseOptions = activeSuggestion\n ? overrideFn\n ? overrideFn(filterQuery.trim())\n : (activeSuggestion.options ?? [])\n : [];\n const filteredOptions = filterOptions(baseOptions, filterQuery);\n\n const placeholderText = next.suggestions\n .filter((s) => s.type === \"placeholder\")\n .map((s) => s.text)\n .join(\" \");\n\n const trigger = this.opts.dropdownTrigger ?? \"auto\";\n const closeOnBlur = this.opts.closeDropdownOnBlur ?? true;\n let isDropdownOpen = false;\n if (trigger === \"auto\") {\n const focusGate = closeOnBlur ? next.isFocused : true;\n isDropdownOpen = !next.isLoading && filteredOptions.length > 0 && focusGate;\n } else if (trigger === \"manual\") {\n isDropdownOpen = !next.isLoading && filteredOptions.length > 0 && next.pillTapped;\n }\n\n this.store.set({\n segments,\n actionableSuggestions,\n filteredOptions,\n placeholderText,\n isDropdownOpen,\n });\n this.derivedInProgress = false;\n\n // Notify external listeners after derived state is settled\n const settled = this.store.get();\n for (const listener of this.externalListeners) {\n listener(settled);\n }\n }\n\n private setupContainer() {\n this.container.classList.add(\"magicx-aia\");\n // In dropdown mode, pills are always in the dropdown\n this.container.dataset.pillPlacement =\n this.renderMode === \"dropdown\" ? \"dropdown\" : (this.opts.pillPlacement ?? \"inline\");\n this.container.dataset.optionsPosition = this.opts.optionsPosition ?? \"below\";\n this.container.dataset.animations = (this.opts.animations ?? true) ? \"on\" : \"off\";\n\n // ModeController\n this.modeController = new ModeController(this.container, this.opts.mode ?? \"auto\");\n }\n\n private buildAndRenderFull() {\n const self = this;\n const renderOpts = {\n store: this.store,\n listboxId: this.listboxId,\n get pillPlacement() {\n return (self.opts.pillPlacement ?? \"inline\") as \"inline\" | \"dropdown\";\n },\n get onSubmit() {\n return self.opts.onSubmit;\n },\n // Tier 1 only (this code path runs only for renderMode === \"full\").\n afterSubmit: () => self.reset(),\n submitButton: this.opts.submitButton,\n autoFocus: this.opts.autoFocus ?? true,\n selectOption: (option: SuggestionOption) => this.selectOption(option),\n setActivePill: (index: number) => this.pillsController.setActivePill(index),\n handleKeyDown: (e: KeyboardEvent) => this.keyboardController.handleKeyDown(e),\n handleChange: (value: string) => this.handleChange(value),\n };\n\n this.domRefs = buildDOM(this.container, renderOpts);\n\n this.subscribeBatchedRender(() => {\n if (this.domRefs) {\n updateDOM(this.domRefs, this.store.get(), renderOpts);\n }\n });\n\n // Initial render\n updateDOM(this.domRefs, this.store.get(), renderOpts);\n this.subscribeNewParamTimer();\n }\n\n private buildAndRenderDropdown() {\n const dropdownOpts = {\n store: this.store,\n listboxId: this.listboxId,\n selectOption: (option: SuggestionOption) => this.selectOption(option),\n setActivePill: (index: number) => this.pillsController.setActivePill(index),\n };\n\n this.dropdownRefs = buildDropdownOnly(this.container, dropdownOpts);\n\n this.subscribeBatchedRender(() => {\n if (this.dropdownRefs) {\n updateDropdownOnly(this.dropdownRefs, this.store.get(), dropdownOpts);\n }\n });\n\n // Initial render\n updateDropdownOnly(this.dropdownRefs, this.store.get(), dropdownOpts);\n this.subscribeNewParamTimer();\n }\n\n /** Batched render subscriber — coalesces multiple store.set calls into one DOM update. */\n private subscribeBatchedRender(render: () => void) {\n let scheduled = false;\n this.unsubscribers.push(\n this.store.subscribe(() => {\n if (scheduled) return;\n scheduled = true;\n queueMicrotask(() => {\n scheduled = false;\n render();\n });\n }),\n );\n }\n\n /** Auto-clear newParamId after shimmer animation. */\n private subscribeNewParamTimer() {\n this.unsubscribers.push(\n this.store.subscribe((next, prev) => {\n if (next.newParamId && next.newParamId !== prev.newParamId) {\n if (this.newParamTimer) clearTimeout(this.newParamTimer);\n this.newParamTimer = window.setTimeout(() => {\n this.store.set({ newParamId: null });\n }, 650);\n }\n }),\n );\n }\n\n private handleChange(newValue: string) {\n const state = this.store.get();\n this.store.set({\n text: newValue,\n pillTapped: false,\n activeDropdownIndex: -1,\n });\n\n const { valid, invalid } = reconcileParams(newValue, state.completedParams);\n if (invalid.length > 0) {\n this.store.set((s) => ({\n completedParams: valid,\n suggestions: [\n ...invalid.map((param) => ({\n type: param.suggestionType,\n text: param.suggestionPlaceholder,\n required: true,\n options: param.options,\n })),\n ...s.suggestions,\n ],\n }));\n }\n }\n}\n"],"mappings":"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AA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA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","names":["forwardRef","useCallback","useEffect","useImperativeHandle","useRef","s","AIAutocomplete_module_css_default","s","AIAutocompleteDropdown_module_css_default","s","PillList_module_css_default","jsx","getPillOpacity","index","PillList","pills","activePillIndex","onSelectPill","rounded","PillList_module_css_default","pill","i","useEffect","useLayoutEffect","useRef","useState","s","SuggestionGrid_module_css_default","useEffect","useRef","useState","s","SuggestionItem_module_css_default","jsx","jsxs","SuggestionItem","option","isHighlighted","onSelect","onHighlight","id","pressed","setPressed","useState","timerRef","useRef","useEffect","handleSelect","className","SuggestionItem_module_css_default","e","jsx","SuggestionGrid","options","activeIndex","onSelect","onHighlight","listboxId","gridRef","useRef","hasBottomOverflow","setHasBottomOverflow","useState","useEffect","el","update","resizeObserver","useLayoutEffect","SuggestionGrid_module_css_default","option","i","SuggestionItem","jsx","jsxs","AIAutocompleteDropdown","suggestions","activeIndex","onSelect","onHighlight","isOpen","id","className","pills","onPillClick","showPills","options","hasPills","isVisible","AIAutocompleteDropdown_module_css_default","e","PillList","SuggestionGrid","s","useCallback","useEffect","useRef","useState","buildQuery","text","completedParams","result","typeCounts","updatedParams","param","count","placeholder","index","extractFilterQuery","text","filterBase","isInProgress","rawRegion","spaceIdx","findPrefixOverlap","prefix","optionText","trimmed","words","optionLower","i","candidate","suffixStart","filterOptions","options","query","lower","o","findExactMatch","ModeController","container","mode","deriveSegments","text","completedParams","result","pos","param","idx","remaining","reconcileParams","valid","invalid","TokenManager","config","forceRefresh","result","DEFAULT_API_ORIGIN","DEFAULT_SUGGEST_ENDPOINT","tokenManagers","isAccessTokenConfig","config","getApiKeyConfig","getTokenManager","manager","TokenManager","buildHeaders","apiConfig","buildApiKeyAuthHeader","apiKeyConfig","apiKey","deriveTelemetryEndpoint","suggestEndpoint","DEFAULT_SUGGEST_ENDPOINT","resolveAuthHeader","apiConfig","isAccessTokenConfig","getTokenManager","buildApiKeyAuthHeader","sendTelemetry","event","endpoint","headers","buildHeaders","authHeader","body","SDK_VERSION","hasWarnedMissingKey","generateRequestId","toWireParam","param","includeText","buildRequestBody","rawQuery","completedParams","sessionId","rawCount","p","contactAccountCount","doFetch","endpoint","headers","token","body","signal","fetchSuggestions","options","apiConfig","buildHeaders","DEFAULT_SUGGEST_ENDPOINT","jsonBody","isAccessTokenConfig","manager","getTokenManager","response","newToken","authHeader","buildApiKeyAuthHeader","applyOptionOverrides","suggestions","overrides","s","fn","extra","existingTexts","o","deduped","DEBOUNCE_MS","SLOW_DEBOUNCE_MS","MIN_CHARS_DIFF","FetchController","store","getApiConfig","getOptionOverrides","getMaskCompletedText","getOnError","getSessionId","callbacks","prevText","prevParams","next","rawQuery","completed","controller","version","state","textAtRequest","s","res","fetchSuggestions","newSuggestions","applyOptionOverrides","input","lastInput","currentText","filterBase","filterInProgress","inProgressIdx","active","extraParam","query","extractFilterQuery","match","findExactMatch","err","caughtError","attemptFetch","minDiff","currentQuery","sg","tappableFiltered","filterOptions","o","hasExactMatch","isInFilterZone","placeholderText","updatedParams","buildQuery","isDeleting","charDiff","KeyboardController","store","ctx","state","listboxId","getOnSubmit","columns","onSubmit","tappableIndices","target","currentPos","nextPos","prevPos","rightNeighbor","leftNeighbor","rawQuery","finalParams","buildQuery","placeholderVisible","hasHighlightedOption","placeholderSuggestion","s","sg","firstTappableIdx","o","tappable","i","buckets","grid","tracks","index","options","optionEl","actionable","moved","rest","_","placeholders","PillsController","store","callbacks","index","state","actionable","s","moved","rest","_","i","placeholders","rawQuery","buildQuery","lastParam","restoredSuggestion","getPillOpacity","index","renderPills","container","pills","activePillIndex","onSelectPill","rounded","list","existing","btn","used","i","pill","key","createDropdown","listboxId","dropdown","e","renderDropdown","state","filteredOptions","activeIndex","isOpen","pills","showPills","onSelect","onHighlight","onPillClick","hasPills","pillBar","renderPills","grid","renderOptions","options","optionsKey","o","lastKey","listChanged","fragment","i","option","item","createOptionElement","items","isHighlighted","index","classes","streaks","streaksVert","content","tag","buildDropdownOnly","container","opts","dropdown","createDropdown","updateDropdownOnly","refs","state","renderDropdown","renderSegments","sizer","segments","newParamId","isEmpty","placeholderText","sizerText","placeholder","segmentKey","s","lastKey","lastParamId","seg","span","SUBMIT_SVG","buildDOM","container","opts","listboxId","dropdown","createDropdown","inputWrapper","editor","sizer","inlinePillContainer","textarea","submitButton","submitTarget","raw","newValue","e","state","rawQuery","finalParams","buildQuery","updateDOM","refs","pillPlacement","setActivePill","selectOption","store","activeDescendant","canSubmit","renderSegments","renderPills","renderDropdown","i","createStore","initial","state","listeners","patch","resolved","next","prev","l","listener","injected","injectStyles","style","STYLES","idCounter","stableId","initialState","AIAutocomplete","container","opts","createStore","PillsController","rawQuery","selectedPill","otherPills","FetchController","active","matched","o","KeyboardController","option","next","prev","injectStyles","unsub","mode","text","params","index","value","focused","listener","event","callback","state","activeSuggestion","telemetryRawQuery","buildQuery","base","prefix","inputWasEmpty","inputIsPlaceholderPrefix","overlapChars","findPrefixOverlap","needsSpace","newText","finalText","optionStart","optionInFinal","completed","remainingActionable","s","sg","type","queryData","source","sendTelemetry","_prev","segments","deriveSegments","actionableSuggestions","overrideFn","clampedFilterBase","filterQuery","extractFilterQuery","baseOptions","filteredOptions","filterOptions","placeholderText","trigger","closeOnBlur","isDropdownOpen","focusGate","settled","ModeController","self","renderOpts","e","buildDOM","updateDOM","dropdownOpts","buildDropdownOnly","updateDropdownOnly","render","scheduled","newValue","valid","invalid","reconcileParams","param","useAIAutocomplete","onSubmit","onError","optionOverrides","maskCompletedText","apiConfig","columns","dropdownTrigger","closeDropdownOnBlur","onFocus","onBlur","controlledValue","controlledParams","onChangeProp","onParamsChange","source","instanceRef","useRef","coreState","setCoreState","useState","onSubmitRef","onErrorRef","onChangeRef","onParamsChangeRef","onFocusRef","onBlurRef","useEffect","instance","AIAutocomplete","args","unsub","state","noop","useCallback","apiConfigJson","prevOverridesRef","overridesVersion","prev","next","prevKeys","nextKeys","k","handleChange","e","raw","newValue","handleKeyDown","handleFocus","handleBlur","setActivePill","index","removeLastParam","clearNewParamId","reset","selectOption","option","setActiveDropdownIndex","text","completedParams","actionableSuggestions","activeSuggestion","filteredOptions","activeDescendantId","jsx","jsxs","resolveInitialMode","mode","AIAutocomplete","forwardRef","onSubmit","onError","optionOverrides","maskCompletedText","className","apiConfig","columns","pillPlacement","optionsPosition","animations","dropdownTrigger","closeDropdownOnBlur","autoFocus","onFocus","onBlur","value","controlledParams","onChangeProp","onParamsChange","submitButton","ref","containerRef","useRef","textareaRef","handleSubmitRef","modeControllerRef","useEffect","el","ModeController","completedParams","suggestionPills","setActivePill","segments","newParamId","clearNewParamId","inputProps","dropdownProps","reset","useAIAutocomplete","result","focusHandler","ta","timeoutId","useImperativeHandle","m","handleContainerClick","canSubmit","handleSubmit","useCallback","rawQuery","finalParams","buildQuery","onChange","inputPlaceholder","restProps","isEmpty","showInlinePills","showDropdownPills","AIAutocomplete_module_css_default","AIAutocompleteDropdown","seg","i","cls","PillList","e"]}