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

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/** 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"]}
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/core/dom/cursorUtils.ts","../src/core/render/renderEditable.ts","../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/renderInput.ts","../src/core/state.ts","../src/core/styleInjector.ts","../src/core/AIAutocomplete.ts"],"sourcesContent":["import {\n forwardRef,\n type KeyboardEvent as ReactKeyboardEvent,\n useCallback,\n useEffect,\n useImperativeHandle,\n useLayoutEffect,\n useRef,\n} from \"react\";\nimport styles from \"./AIAutocomplete.module.css\";\nimport { AIAutocompleteDropdown } from \"./AIAutocompleteDropdown\";\nimport \"./appearance.css\";\nimport { PillList } from \"./components/PillList\";\nimport {\n extractPlainText,\n getCursorOffset,\n plainTextLength,\n setCursorOffset,\n} from \"./core/dom/cursorUtils\";\nimport { renderEditableContent } from \"./core/render/renderEditable\";\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\nlet plaintextOnlyCache: boolean | undefined;\nfunction supportsPlaintextOnly(): boolean {\n if (plaintextOnlyCache !== undefined) return plaintextOnlyCache;\n if (typeof document === \"undefined\") return false;\n const probe = document.createElement(\"div\");\n probe.setAttribute(\"contenteditable\", \"plaintext-only\");\n plaintextOnlyCache = probe.contentEditable === \"plaintext-only\";\n return plaintextOnlyCache;\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 inputRef = useRef<HTMLDivElement>(null);\n const handleSubmitRef = useRef<(result: AutocompleteResult) => void>(() => {});\n const modeControllerRef = useRef<ModeController | null>(null);\n const composingRef = useRef(false);\n const lastSeenParamIdRef = useRef<string>(\"\");\n const lastEditingIdRef = useRef<string>(\"\");\n const caretOffsetRef = useRef<number | null>(null);\n // Set in the input event handler; selectionchange suppresses post-input\n // caret-move tracking within this window so typing doesn't get treated\n // as navigation.\n const lastInputAtRef = useRef(0);\n\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 handleSetCursor = useCallback((offset: number) => {\n const el = inputRef.current;\n if (el) setCursorOffset(el, offset);\n }, []);\n\n const {\n completedParams,\n suggestionPills,\n setActivePill,\n segments,\n newParamId,\n clearNewParamId,\n placeholderText,\n isFocused,\n isDropdownOpen,\n isLoading,\n activeIndex,\n listboxId,\n handleTextChange,\n handleKeyDown,\n setFocused,\n editingParam,\n editingAnchor,\n caretOffset,\n startEditingParam,\n handleCaretAfterInput,\n handleCaretMove,\n replaceEditingRange,\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 setCursor: handleSetCursor,\n });\n\n caretOffsetRef.current = caretOffset;\n\n // Auto-focus on mount once the hook's instance is ready.\n useEffect(() => {\n if (!autoFocus) return;\n const el = inputRef.current;\n if (!el) return;\n if (document.activeElement === el) {\n setFocused(true);\n } else {\n el.focus();\n }\n }, [autoFocus, setFocused]);\n\n // Shimmer auto-clear after the animation finishes.\n useEffect(() => {\n if (!newParamId) return;\n const t = window.setTimeout(() => clearNewParamId(), 650);\n return () => window.clearTimeout(t);\n }, [newParamId, clearNewParamId]);\n\n // `selectionchange` is the canonical signal for \"caret moved\" in\n // contentEditable land. Anchored inside the editor: a caret that lands\n // inside a `<strong>` triggers re-edit mode; a caret that leaves the\n // current editing region exits it.\n useEffect(() => {\n const el = inputRef.current;\n if (!el) return;\n const doc = el.ownerDocument ?? document;\n const onSelectionChange = () => {\n const sel = doc.getSelection();\n if (!sel || sel.rangeCount === 0) return;\n if (!sel.anchorNode || !el.contains(sel.anchorNode)) return;\n const anchor = sel.anchorNode;\n const startEl =\n anchor.nodeType === Node.ELEMENT_NODE ? (anchor as Element) : anchor.parentElement;\n const strong = startEl?.closest<HTMLElement>('strong[data-seg=\"completed\"][data-param-id]');\n const enclosing = strong?.dataset.paramId ?? null;\n if (enclosing && enclosing !== editingParam?.id) {\n startEditingParam(enclosing);\n return;\n }\n if (performance.now() - lastInputAtRef.current < 50) return;\n handleCaretMove(getCursorOffset(el));\n };\n doc.addEventListener(\"selectionchange\", onSelectionChange);\n return () => doc.removeEventListener(\"selectionchange\", onSelectionChange);\n }, [editingParam, startEditingParam, handleCaretMove]);\n\n // Render segments imperatively into the contentEditable. useLayoutEffect\n // runs before paint so the caret is restored without a one-frame flicker.\n useLayoutEffect(() => {\n const el = inputRef.current;\n if (!el) return;\n renderEditableContent({\n input: el,\n segments,\n newParamId,\n editingParamId: editingParam?.id ?? null,\n placeholderText: placeholderText ?? \"\",\n isFocused,\n });\n }, [segments, newParamId, editingParam, placeholderText, isFocused]);\n\n // After a fresh option selection (newParamId changed), refocus the editor\n // and place the caret at the end. Mirrors the vanilla core's `justSelected`\n // logic in renderInput.ts — clicking a dropdown option moves focus to the\n // option button, and we want to return it to the editor so typing can\n // continue immediately.\n useLayoutEffect(() => {\n const previous = lastSeenParamIdRef.current;\n const current = newParamId ?? \"\";\n lastSeenParamIdRef.current = current;\n if (!current || current === previous) return;\n const el = inputRef.current;\n if (!el) return;\n el.focus();\n // Every promote path stamps `caretOffset` with the position right\n // after the new param's trailing space, so use it. Read via ref so the\n // effect stays gated on newParamId (not every caret-move).\n const desired = caretOffsetRef.current ?? plainTextLength(el);\n setCursorOffset(el, desired);\n }, [newParamId]);\n\n // On re-edit-mode entry, park the caret just BEFORE the bold strong so\n // typing/backspace via the `beforeinput` intercept replaces the param\n // cleanly (instead of inserting mid-letter inside the bold span).\n useLayoutEffect(() => {\n const previous = lastEditingIdRef.current;\n const current = editingParam?.id ?? \"\";\n lastEditingIdRef.current = current;\n if (!current || current === previous || editingAnchor == null) return;\n const el = inputRef.current;\n if (!el) return;\n setCursorOffset(el, editingAnchor);\n }, [editingParam, editingAnchor]);\n\n useImperativeHandle(\n ref,\n () => ({\n focus: () => inputRef.current?.focus(),\n blur: () => inputRef.current?.blur(),\n reset,\n setMode: (m) => modeControllerRef.current?.setMode(m),\n }),\n [reset],\n );\n\n const fireInput = useCallback(() => {\n if (composingRef.current) return;\n const el = inputRef.current;\n if (!el) return;\n const raw = extractPlainText(el);\n const shouldCapitalize = raw.length > 0 && raw[0] !== raw[0].toUpperCase();\n const next = shouldCapitalize ? raw[0].toUpperCase() + raw.slice(1) : raw;\n handleTextChange(next);\n }, [handleTextChange]);\n\n const handleInputEvent = useCallback(() => {\n lastInputAtRef.current = performance.now();\n fireInput();\n const el = inputRef.current;\n if (el) handleCaretAfterInput(getCursorOffset(el));\n }, [fireInput, handleCaretAfterInput]);\n\n // React's synthetic `onBeforeInput` is wired to the legacy `textInput`\n // event and doesn't reliably fire for `delete*` input types, so we\n // attach a native `beforeinput` listener directly on the editor.\n useEffect(() => {\n const el = inputRef.current;\n if (!el) return;\n const onBeforeInput = (e: Event) => {\n const inputEvent = e as InputEvent;\n const t = inputEvent.inputType;\n if (t === \"insertParagraph\" || t === \"insertLineBreak\" || t === \"insertFromDrop\") {\n e.preventDefault();\n return;\n }\n if (t.startsWith(\"insert\") || t.startsWith(\"delete\")) {\n const replacement = t.startsWith(\"delete\") ? \"\" : (inputEvent.data ?? \"\");\n if (replaceEditingRange(replacement)) {\n e.preventDefault();\n }\n }\n };\n el.addEventListener(\"beforeinput\", onBeforeInput);\n return () => el.removeEventListener(\"beforeinput\", onBeforeInput);\n }, [replaceEditingRange]);\n\n const handleCompositionStart = useCallback(() => {\n composingRef.current = true;\n }, []);\n\n const handleCompositionEnd = useCallback(() => {\n composingRef.current = false;\n fireInput();\n }, [fireInput]);\n\n const handlePaste = useCallback(\n (e: React.ClipboardEvent<HTMLDivElement>) => {\n e.preventDefault();\n const el = inputRef.current;\n if (!el) return;\n const text = (e.clipboardData.getData(\"text/plain\") ?? \"\").replace(/\\r?\\n/g, \" \");\n if (!text) return;\n const doc = el.ownerDocument ?? document;\n const sel = doc.getSelection();\n if (!sel || sel.rangeCount === 0) return;\n const range = sel.getRangeAt(0);\n if (!el.contains(range.startContainer)) return;\n range.deleteContents();\n const node = doc.createTextNode(text);\n range.insertNode(node);\n range.setStartAfter(node);\n range.collapse(true);\n sel.removeAllRanges();\n sel.addRange(range);\n fireInput();\n },\n [fireInput],\n );\n\n const handleKeyDownReact = useCallback(\n (e: ReactKeyboardEvent<HTMLDivElement>) => handleKeyDown(e),\n [handleKeyDown],\n );\n\n const canSubmit = !!segments.length || completedParams.length > 0;\n\n const handleSubmit = useCallback(() => {\n if (!canSubmit) return;\n const text = inputRef.current ? extractPlainText(inputRef.current) : \"\";\n const { rawQuery, completedParams: finalParams } = buildQuery(text, completedParams);\n onSubmit({\n query: text.trim(),\n raw_query: rawQuery,\n completed_params: finalParams,\n });\n reset();\n }, [canSubmit, completedParams, onSubmit, reset]);\n\n handleSubmitRef.current = handleSubmit;\n\n const handleWrapperClick = useCallback((e: React.MouseEvent<HTMLDivElement>) => {\n // Clicking a pill activates it; don't steal focus away from where it lands.\n const target = e.target as HTMLElement | null;\n if (target?.closest(\"[data-aia-pill]\")) return;\n inputRef.current?.focus();\n }, []);\n\n const showInlinePills = pillPlacement === \"inline\";\n const showDropdownPills = pillPlacement === \"dropdown\";\n const activeDescendantId = activeIndex >= 0 ? `${listboxId}-option-${activeIndex}` : undefined;\n const ceMode = supportsPlaintextOnly() ? \"plaintext-only\" : \"true\";\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 editor focus */}\n {/* biome-ignore lint/a11y/noStaticElementInteractions: wrapper delegates focus to editor */}\n <div className={styles.inputWrapper} onClick={handleWrapperClick}>\n <div className={styles.editorArea} data-aia-editor=\"\">\n <div\n ref={inputRef}\n className={styles.input}\n data-aia-input=\"\"\n contentEditable={ceMode as unknown as boolean}\n suppressContentEditableWarning\n tabIndex={0}\n role=\"combobox\"\n aria-autocomplete=\"list\"\n aria-haspopup=\"listbox\"\n aria-controls={listboxId}\n aria-expanded={isDropdownOpen}\n aria-activedescendant={activeDescendantId}\n spellCheck\n enterKeyHint=\"send\"\n onInput={handleInputEvent}\n onKeyDown={handleKeyDownReact}\n onCompositionStart={handleCompositionStart}\n onCompositionEnd={handleCompositionEnd}\n onPaste={handlePaste}\n onFocus={() => setFocused(true)}\n onBlur={() => setFocused(false)}\n />\n {showInlinePills && (isLoading || suggestionPills.length > 0) && (\n <span className={styles.pillListContainer} data-aia-pill-list-container=\"\">\n <PillList\n pills={suggestionPills}\n activePillIndex={0}\n onSelectPill={setActivePill}\n loading={isLoading}\n />\n </span>\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 /* Inherits the host page's font by default. Consumers can pin a specific\n font on the library via \\`--aia-font-family: 'Custom Font'\\` without\n affecting the surrounding page. */\n font-family: var(--aia-font-family, inherit);\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 min-height: 38px;\n line-height: 38px;\n font-family: inherit;\n font-size: var(--aia-written-text-font-size, 19px);\n white-space: pre-wrap;\n word-break: break-word;\n overflow-wrap: anywhere;\n}\n\n.AIAutocomplete-module_input_IW-P- {\n display: inline;\n outline: 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-weight: 200;\n}\n\n/* Completed params render as inline bold runs. \\`:where()\\` keeps specificity\n at (0,2,0) so consumers can override without \\`!important\\`. */\n:where(.AIAutocomplete-module_input_IW-P-) strong {\n font-weight: 500;\n letter-spacing: -0.01em;\n}\n\n/* Re-edit highlight — the editing class is written by the shared renderer\n (a global string), so target it via an attribute selector to bypass\n CSS Modules' class-name hashing. */\n:where(.AIAutocomplete-module_input_IW-P-) strong[class~=\"magicx-aia-segment--editing\"] {\n outline: 1.5px solid var(--aia-edit-outline, currentColor);\n outline-offset: 1px;\n border-radius: 4px;\n caret-color: transparent;\n}\n\n:where(.AIAutocomplete-module_input_IW-P-) strong[class~=\"magicx-aia-segment--editing\"]::selection {\n background: transparent;\n color: inherit;\n}\n:where(.AIAutocomplete-module_input_IW-P-) strong[class~=\"magicx-aia-segment--editing\"]::-moz-selection {\n background: transparent;\n color: inherit;\n}\n\n/* Placeholder via ::before so it doesn't enter the editable DOM. */\n.AIAutocomplete-module_input_IW-P-[data-aia-empty=\"true\"][data-placeholder]::before {\n content: attr(data-placeholder);\n color: var(--aia-color-text-muted, #c1c4cb);\n opacity: 0.7;\n pointer-events: none;\n}\n\n/* Empty inline contentEditables have no inline box for the caret to render\n in. Switch to inline-block (min-width matches the caret line) when empty,\n so the caret stays visible while focused. */\n.AIAutocomplete-module_input_IW-P-[data-aia-empty=\"true\"] {\n display: inline-block;\n min-width: 1px;\n vertical-align: top;\n}\n\n.AIAutocomplete-module_pillListContainer_h92IA {\n display: inline;\n margin-left: 8px;\n}\n\n.AIAutocomplete-module_pillListContainer_h92IA:empty {\n margin-left: 0;\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. The shimmer span wraps the\n bold completion text inside the editor; a moving gradient clipped to the\n text shape produces the sweep effect. */\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 document.head.appendChild(s);\n}\nexport default {\"container\":\"AIAutocomplete-module_container_KKjFU\",\"inputWrapper\":\"AIAutocomplete-module_inputWrapper_FLq1b\",\"editorArea\":\"AIAutocomplete-module_editorArea_7rBWq\",\"input\":\"AIAutocomplete-module_input_IW-P-\",\"pillListContainer\":\"AIAutocomplete-module_pillListContainer_h92IA\",\"submitButton\":\"AIAutocomplete-module_submitButton_sl1Mi\",\"submitSlot\":\"AIAutocomplete-module_submitSlot_GhuCM\",\"shimmerRevealed\":\"AIAutocomplete-module_shimmerRevealed_RR8dp\",\"shimmerSweep\":\"AIAutocomplete-module_shimmerSweep_ARCon\",\"textShimmer\":\"AIAutocomplete-module_textShimmer_eCLdq\"};","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/* --- Loading skeleton --- */\n.AIAutocompleteDropdown-module_skeleton_XiH2s {\n display: flex;\n flex-direction: column;\n gap: 20px;\n padding: 25px;\n}\n\n.AIAutocompleteDropdown-module_skeletonPills_KFzRs {\n display: flex;\n gap: 5px;\n align-items: center;\n}\n\n.AIAutocompleteDropdown-module_skeletonPill_JdDM3 {\n display: inline-block;\n height: 30px;\n border-radius: 999px;\n background: var(--aia-skeleton-bg, var(--aia-pill-bg, rgba(189, 189, 189, 0.51)));\n opacity: 0.5;\n animation: AIAutocompleteDropdown-module_aiaSkeletonPulse_G8W7q 1.4s ease-in-out infinite;\n}\n\n.AIAutocompleteDropdown-module_skeletonPills_KFzRs .AIAutocompleteDropdown-module_skeletonPill_JdDM3:nth-child(2) {\n opacity: 0.3;\n}\n\n.AIAutocompleteDropdown-module_skeletonBars_HVr9C {\n display: flex;\n flex-direction: column;\n gap: 20px;\n}\n\n.AIAutocompleteDropdown-module_skeletonBar_O3xIx {\n display: block;\n height: 19px;\n border-radius: 999px;\n background: var(--aia-skeleton-bg, var(--aia-pill-bg, rgba(189, 189, 189, 0.51)));\n opacity: 0.5;\n animation: AIAutocompleteDropdown-module_aiaSkeletonPulse_G8W7q 1.4s ease-in-out infinite;\n}\n\n.AIAutocompleteDropdown-module_skeletonBar_O3xIx:nth-child(2) {\n animation-delay: 150ms;\n}\n\n.AIAutocompleteDropdown-module_skeletonBar_O3xIx:nth-child(3) {\n animation-delay: 300ms;\n}\n\n@keyframes AIAutocompleteDropdown-module_aiaSkeletonPulse_G8W7q {\n 0%,\n 100% {\n opacity: 0.5;\n }\n 50% {\n opacity: 0.25;\n }\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\",\"skeleton\":\"AIAutocompleteDropdown-module_skeleton_XiH2s\",\"skeletonPills\":\"AIAutocompleteDropdown-module_skeletonPills_KFzRs\",\"skeletonPill\":\"AIAutocompleteDropdown-module_skeletonPill_JdDM3\",\"aiaSkeletonPulse\":\"AIAutocompleteDropdown-module_aiaSkeletonPulse_G8W7q\",\"skeletonBars\":\"AIAutocompleteDropdown-module_skeletonBars_HVr9C\",\"skeletonBar\":\"AIAutocompleteDropdown-module_skeletonBar_O3xIx\"};","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: inherit;\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_skeleton_Lp8x6 {\n pointer-events: none;\n cursor: default;\n height: 30px;\n padding: 0;\n background: var(--aia-skeleton-bg, var(--aia-pill-bg, rgba(189, 189, 189, 0.51)));\n box-shadow: none;\n backdrop-filter: none;\n animation: PillList-module_skeletonPulse_xZ8Yf 1.4s ease-in-out infinite;\n}\n\n@keyframes PillList-module_skeletonPulse_xZ8Yf {\n 0%,\n 100% {\n filter: brightness(1);\n }\n 50% {\n filter: brightness(0.7);\n }\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\",\"skeleton\":\"PillList-module_skeleton_Lp8x6\",\"skeletonPulse\":\"PillList-module_skeletonPulse_xZ8Yf\",\"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 /** Render skeleton placeholder pills (no text, no click). Default: false. */\n loading?: boolean;\n}\n\nconst SKELETON_PILL_WIDTHS = [125, 69];\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({\n pills,\n activePillIndex,\n onSelectPill,\n rounded,\n loading,\n}: PillListProps) {\n if (loading) {\n return (\n <span className={styles.list} data-aia-pill-list-loading=\"\">\n {SKELETON_PILL_WIDTHS.map((w, i) => (\n <span\n key={`skel-${w}`}\n data-aia-pill-skeleton=\"\"\n className={`${styles.pill} ${rounded ? styles.rounded : \"\"} ${styles.skeleton}`}\n style={{ width: w, opacity: getPillOpacity(i) }}\n />\n ))}\n </span>\n );\n }\n\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 tabIndex={-1}\n contentEditable={false}\n suppressContentEditableWarning\n className={`${styles.pill} ${rounded ? styles.rounded : \"\"} ${i === activePillIndex ? styles.active : \"\"}`}\n style={{ opacity: getPillOpacity(i) }}\n // Prevent the browser from moving focus from the editable to this\n // button on mousedown; the click handler still fires.\n onMouseDown={(e) => e.preventDefault()}\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 /* Pack rows from the top instead of stretching to fill the grid container. */\n grid-auto-rows: min-content;\n align-content: start;\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 /* Top-align so single-line and multi-line options in the same row share\n the same baseline at the top edge of the cell. */\n align-items: flex-start;\n font-family: inherit;\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\nconst SKELETON_BAR_WIDTHS = [159, 119, 164];\nconst SKELETON_PILL_WIDTHS = [115, 122];\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 isLoading = false,\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 = isOpen && (isLoading || hasOptions || hasPills);\n\n return (\n <div\n id={id}\n role=\"listbox\"\n data-aia-dropdown=\"\"\n data-aia-loading={isLoading ? \"\" : undefined}\n className={`${styles.dropdown} ${isVisible ? styles.visible : \"\"} ${className ?? \"\"}`}\n onMouseDown={(e) => e.preventDefault()}\n >\n {isLoading ? (\n <div className={styles.skeleton} data-aia-skeleton=\"\">\n {showPills && (\n <div className={styles.skeletonPills} data-aia-skeleton-pills=\"\">\n {SKELETON_PILL_WIDTHS.map((w) => (\n <span key={`pill-${w}`} className={styles.skeletonPill} style={{ width: w }} />\n ))}\n </div>\n )}\n <div className={styles.skeletonBars}>\n {SKELETON_BAR_WIDTHS.map((w) => (\n <span key={`bar-${w}`} className={styles.skeletonBar} style={{ width: w }} />\n ))}\n </div>\n </div>\n ) : (\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 </>\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-skeleton-bg: rgba(189, 189, 189, 0.51);\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-skeleton-bg: #333539;\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 {};","/**\n * Plain-text caret utilities for contentEditable elements.\n *\n * Offsets are measured in plain-text characters that come from the editable\n * region only — subtrees inside `[contenteditable=\"false\"]` (e.g. pills)\n * contribute zero characters. Callers can think in string offsets without\n * touching DOM Ranges directly.\n */\n\nconst NON_EDITABLE_SELECTOR = '[contenteditable=\"false\"]';\n\ninterface GraphemeSegmenter {\n segment(input: string): Iterable<{ index: number; segment: string }>;\n}\n\nlet segmenter: GraphemeSegmenter | null | undefined;\nfunction getGraphemeSegmenter(): GraphemeSegmenter | null {\n if (segmenter !== undefined) return segmenter;\n // Intl.Segmenter is ES2022; lib target is ES2020. Access via globalThis to\n // avoid a hard compile dependency on the newer lib.\n const Segmenter = (globalThis as { Intl: typeof Intl & { Segmenter?: unknown } }).Intl\n .Segmenter as undefined | (new (locale?: string, options?: object) => GraphemeSegmenter);\n if (!Segmenter) {\n segmenter = null;\n return null;\n }\n try {\n segmenter = new Segmenter(undefined, { granularity: \"grapheme\" });\n } catch {\n segmenter = null;\n }\n return segmenter ?? null;\n}\n\nfunction isInsideNonEditable(node: Node, root: HTMLElement): boolean {\n let n: Node | null = node;\n while (n && n !== root) {\n if (n.nodeType === Node.ELEMENT_NODE) {\n const el = n as HTMLElement;\n if (el.matches(NON_EDITABLE_SELECTOR)) return true;\n }\n n = n.parentNode;\n }\n return false;\n}\n\nfunction createTextWalker(root: HTMLElement): TreeWalker {\n return (root.ownerDocument ?? document).createTreeWalker(root, NodeFilter.SHOW_TEXT, {\n acceptNode(node) {\n return isInsideNonEditable(node, root) ? NodeFilter.FILTER_REJECT : NodeFilter.FILTER_ACCEPT;\n },\n });\n}\n\nexport function extractPlainText(root: HTMLElement): string {\n const walker = createTextWalker(root);\n let out = \"\";\n let node = walker.nextNode() as Text | null;\n while (node) {\n out += node.data;\n node = walker.nextNode() as Text | null;\n }\n return out;\n}\n\nexport function plainTextLength(root: HTMLElement): number {\n const walker = createTextWalker(root);\n let total = 0;\n let node = walker.nextNode() as Text | null;\n while (node) {\n total += node.data.length;\n node = walker.nextNode() as Text | null;\n }\n return total;\n}\n\n/**\n * Read the current caret offset (in plain-text characters) within `root`.\n * Returns null when no selection is anchored inside `root`.\n */\nexport function getCursorOffset(root: HTMLElement): number | null {\n const sel = (root.ownerDocument ?? document).getSelection();\n if (!sel || sel.rangeCount === 0) return null;\n const anchorNode = sel.anchorNode;\n const anchorOffset = sel.anchorOffset;\n if (!anchorNode || !root.contains(anchorNode)) return null;\n\n // When the anchor is the editable itself (or an element child), interpret\n // anchorOffset as a child index and sum text lengths up to that child.\n if (anchorNode.nodeType === Node.ELEMENT_NODE) {\n const el = anchorNode as Element;\n if (isInsideNonEditable(el, root) && el !== root) return null;\n let offset = 0;\n for (let i = 0; i < anchorOffset && i < el.childNodes.length; i++) {\n offset += plainTextLengthOfSubtree(el.childNodes[i], root);\n }\n // Add lengths of previous siblings + ancestors up to root.\n return offset + offsetBeforeNode(el, root);\n }\n\n if (anchorNode.nodeType !== Node.TEXT_NODE) return null;\n if (isInsideNonEditable(anchorNode, root)) return null;\n\n return offsetBeforeNode(anchorNode, root) + anchorOffset;\n}\n\nfunction plainTextLengthOfSubtree(node: Node, root: HTMLElement): number {\n if (node.nodeType === Node.TEXT_NODE) {\n return isInsideNonEditable(node, root) ? 0 : (node as Text).data.length;\n }\n if (node.nodeType !== Node.ELEMENT_NODE) return 0;\n const el = node as HTMLElement;\n if (el.matches(NON_EDITABLE_SELECTOR)) return 0;\n let total = 0;\n for (const child of Array.from(el.childNodes)) {\n total += plainTextLengthOfSubtree(child, root);\n }\n return total;\n}\n\nfunction offsetBeforeNode(target: Node, root: HTMLElement): number {\n const walker = createTextWalker(root);\n let total = 0;\n let node = walker.nextNode() as Text | null;\n while (node) {\n if (node === target) return total;\n // If target is an ancestor element of this text node, we've already passed it.\n if (target.nodeType === Node.ELEMENT_NODE && (target as Element).contains(node)) {\n return total;\n }\n total += node.data.length;\n node = walker.nextNode() as Text | null;\n }\n return total;\n}\n\n/**\n * Set the caret at the given plain-text offset within `root`.\n *\n * Boundary policy: when the offset falls at the seam between text nodes, the\n * caret is placed at the START of the *following* text node so newly typed\n * characters do not inherit a preceding `<strong>`'s bold styling. When the\n * caret would land at the trailing edge of a text node inside a `<strong>`\n * with no following text node, we use `setStartAfter(strong)` so the caret\n * sits OUTSIDE the bold subtree — otherwise a caret at the end of a strong's\n * text is still \"inside\" the strong, which would falsely trigger re-edit mode.\n */\nexport function setCursorOffset(root: HTMLElement, offset: number): void {\n const doc = root.ownerDocument ?? document;\n const sel = doc.getSelection();\n if (!sel) return;\n\n const clamped = Math.max(0, Math.min(offset, plainTextLength(root)));\n const walker = createTextWalker(root);\n let cumulative = 0;\n let target: Text | null = null;\n let targetOffset = 0;\n let node = walker.nextNode() as Text | null;\n let lastNode: Text | null = null;\n\n while (node) {\n const len = node.data.length;\n if (clamped < cumulative + len) {\n target = node;\n targetOffset = clamped - cumulative;\n break;\n }\n if (clamped === cumulative + len) {\n const next = walker.nextNode() as Text | null;\n if (next) {\n // Prefer the start of the following text node so the caret sits past\n // any preceding `<strong>` boundary.\n target = next;\n targetOffset = 0;\n } else {\n target = node;\n targetOffset = len;\n }\n break;\n }\n cumulative += len;\n lastNode = node;\n node = walker.nextNode() as Text | null;\n }\n\n const range = doc.createRange();\n if (target) {\n // Boundary policy: the caret must never land at the leading or trailing\n // edge of a `<strong>`'s text node — visually it sits AT the boundary\n // but the DOM anchor is still INSIDE the strong, which would falsely\n // trigger re-edit mode. Hop OUT of the strong at those boundaries.\n const strongParent = target.parentElement?.closest<HTMLElement>('strong[data-seg=\"completed\"]');\n if (strongParent && strongParent !== root && root.contains(strongParent)) {\n if (targetOffset === 0) {\n range.setStartBefore(strongParent);\n } else if (targetOffset === target.data.length) {\n range.setStartAfter(strongParent);\n } else {\n range.setStart(target, targetOffset);\n }\n } else {\n range.setStart(target, targetOffset);\n }\n } else if (lastNode) {\n range.setStart(lastNode, lastNode.data.length);\n } else {\n range.setStart(root, 0);\n }\n range.collapse(true);\n sel.removeAllRanges();\n sel.addRange(range);\n}\n\n/**\n * True when the caret offset equals the editable's plain-text length —\n * meaning the only content to the right is non-editable (e.g. trailing pills).\n */\nexport function cursorIsAtEnd(root: HTMLElement): boolean {\n const offset = getCursorOffset(root);\n if (offset == null) return false;\n return offset >= plainTextLength(root);\n}\n\n/**\n * Step back one grapheme from a plain-text offset, falling back to one UTF-16\n * code unit when Intl.Segmenter is unavailable. Used by Backspace handling so\n * emoji and combining marks are deleted as a single user-perceived character.\n */\nexport function previousGraphemeBoundary(text: string, offset: number): number {\n if (offset <= 0) return 0;\n const seg = getGraphemeSegmenter();\n if (!seg) return offset - 1;\n const slice = text.slice(0, offset);\n let last = 0;\n for (const { index } of seg.segment(slice)) {\n if (index < offset) last = index;\n }\n return last;\n}\n","import type { Segment } from \"../../types\";\nimport { getCursorOffset, setCursorOffset } from \"../dom/cursorUtils\";\n\ninterface RenderEditableArgs {\n input: HTMLElement;\n segments: Segment[];\n newParamId: string | null;\n /** When set, the matching `<strong>` is decorated with the editing class. */\n editingParamId: string | null;\n placeholderText: string;\n isFocused: boolean;\n}\n\n/**\n * Renders text segments — including bold `<strong>` runs for completed params\n * — into the contentEditable input. Pills are NOT rendered here; they live as\n * a sibling element so the editable's subtree never contains non-editable\n * children. See renderInput.ts for the pill list placement.\n *\n * Skips rebuilds when the segment key is unchanged so an in-flight shimmer\n * animation isn't interrupted by unrelated state churn.\n */\nexport function renderEditableContent(args: RenderEditableArgs) {\n const { input, segments, newParamId, editingParamId, placeholderText, isFocused } = args;\n\n const empty = segments.length === 0;\n input.dataset.aiaEmpty = empty ? \"true\" : \"false\";\n if (empty && placeholderText) {\n input.dataset.placeholder = placeholderText;\n } else {\n delete input.dataset.placeholder;\n }\n\n const segKey = segments.map((s) => `${s.type}:${s.value}`).join(\"\\0\");\n const lastSegKey = input.dataset.segKey ?? \"\";\n const lastNewParamId = input.dataset.newParamId ?? \"\";\n const lastEditingParamId = input.dataset.editingParamId ?? \"\";\n if (\n segKey === lastSegKey &&\n (newParamId ?? \"\") === lastNewParamId &&\n (editingParamId ?? \"\") === lastEditingParamId\n ) {\n return;\n }\n\n const savedOffset = isFocused ? getCursorOffset(input) : null;\n input.dataset.segKey = segKey;\n input.dataset.newParamId = newParamId ?? \"\";\n input.dataset.editingParamId = editingParamId ?? \"\";\n\n const doc = input.ownerDocument ?? document;\n const frag = doc.createDocumentFragment();\n let newLength = 0;\n for (const seg of segments) {\n newLength += seg.value.length;\n if (seg.type === \"completed\") {\n const strong = doc.createElement(\"strong\");\n strong.dataset.seg = \"completed\";\n strong.dataset.paramId = seg.param.id;\n const isNew = seg.param.id === newParamId;\n const isEditing = seg.param.id === editingParamId;\n const classes = [\"magicx-aia-segment\", \"magicx-aia-segment--completed\"];\n if (isNew) classes.push(\"magicx-aia-shimmer-revealed\", \"magicx-aia-shimmer-sweep\");\n if (isEditing) classes.push(\"magicx-aia-segment--editing\");\n strong.className = classes.join(\" \");\n strong.textContent = seg.value;\n frag.appendChild(strong);\n } else {\n frag.appendChild(doc.createTextNode(seg.value));\n }\n }\n input.replaceChildren(frag);\n input.dataset.aiaTextLength = String(newLength);\n\n if (savedOffset != null) {\n // Restore the caret to where the browser left it (clamped to the new\n // text length). Callers that need the caret at a specific position\n // (e.g. Tab-on-placeholder, edit-mode replacement) schedule their own\n // `setCursorOffset` via `queueMicrotask` after the store mutation.\n setCursorOffset(input, Math.max(0, Math.min(savedOffset, newLength)));\n }\n}\n","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 setCursor,\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 const setCursorRef = useRef(setCursor);\n setCursorRef.current = setCursor;\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 setCursor: (offset) => setCursorRef.current?.(offset),\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 // Tier 1 helpers — element-agnostic versions usable on a contentEditable div.\n const handleTextChange = useCallback(\n (value: string) => instance?.handleTextChange(value),\n [instance],\n );\n const handleKeyDownT1 = useCallback(\n (e: KeyboardEvent<HTMLElement> | globalThis.KeyboardEvent) => {\n if (!instance) return;\n const native = \"nativeEvent\" in e ? e.nativeEvent : e;\n instance.handleKeyDown(native);\n },\n [instance],\n );\n const setFocused = useCallback((focused: boolean) => instance?.setFocused(focused), [instance]);\n\n // Tier 1 re-edit helpers.\n const startEditingParam = useCallback(\n (paramId: string) => instance?.startEditingParam(paramId),\n [instance],\n );\n const exitEditMode = useCallback(() => instance?.exitEditMode(), [instance]);\n const handleCaretAfterInput = useCallback(\n (offset: number | null) => instance?.handleCaretAfterInput(offset),\n [instance],\n );\n const handleCaretMove = useCallback(\n (offset: number | null) => instance?.handleCaretMove(offset),\n [instance],\n );\n const replaceEditingRange = useCallback(\n (replacement: string) => instance?.replaceEditingRange(replacement) ?? false,\n [instance],\n );\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 isFocused: false,\n isDropdownOpen: false,\n placeholderText: \"\",\n listboxId: \"\",\n error: null,\n handleTextChange: noop,\n handleKeyDown: noop,\n setFocused: noop,\n editingParam: null,\n editingAnchor: null,\n caretOffset: null,\n startEditingParam: noop,\n exitEditMode: noop,\n handleCaretAfterInput: noop,\n handleCaretMove: noop,\n replaceEditingRange: () => false,\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 // In re-edit mode, the dropdown's pill bar shows a synthetic pill built\n // from the edited param's cached suggestion metadata. The options grid\n // shows the cached options regardless of the latest server response.\n const editingParam = state.editingParam;\n const dropdownPill: Suggestion | null = editingParam\n ? {\n type: editingParam.suggestionType,\n text: editingParam.suggestionPlaceholder,\n required: true,\n options: editingParam.options,\n }\n : null;\n const dropdownActivePill = dropdownPill ?? activeSuggestion;\n const dropdownPills = dropdownPill ? [dropdownPill] : actionableSuggestions;\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 isFocused: state.isFocused,\n isDropdownOpen: state.isDropdownOpen,\n placeholderText: state.placeholderText,\n listboxId: instance.listboxId,\n error: state.error,\n handleTextChange,\n handleKeyDown: handleKeyDownT1,\n setFocused,\n editingParam,\n editingAnchor: state.editingAnchor,\n caretOffset: state.caretOffset,\n startEditingParam,\n exitEditMode,\n handleCaretAfterInput,\n handleCaretMove,\n replaceEditingRange,\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: dropdownActivePill ? [{ ...dropdownActivePill, options: filteredOptions }] : [],\n activeIndex: state.activeDropdownIndex,\n onSelect: selectOption,\n onHighlight: setActiveDropdownIndex,\n isOpen: state.isDropdownOpen,\n id: instance.listboxId,\n pills: dropdownPills,\n onPillClick: setActivePill,\n // Re-edit shows cached options for the edited param — fetches can still\n // run in the background, but the skeleton would clobber the cached UI.\n isLoading: state.isLoading && !state.editingParam,\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 * Returns a filter base that respects the server-suggested placeholder. When\n * `filterBase` hasn't been set by a fetch yet (still 0) and `text` starts with\n * `placeholderText`, the placeholder occupies the same role as `filterBase` —\n * the user's filter query is whatever they typed past it. Returns `filterBase`\n * unchanged otherwise.\n */\nexport function effectiveFilterBase(\n text: string,\n filterBase: number,\n placeholderText: string,\n): number {\n if (filterBase > 0 || !placeholderText) return filterBase;\n if (text.toLowerCase().startsWith(placeholderText.toLowerCase())) {\n return placeholderText.length;\n }\n return filterBase;\n}\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 {\n effectiveFilterBase,\n extractFilterQuery,\n filterOptions,\n findExactMatch,\n} 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 textAtRequest = this.store.get().text.length;\n\n this.store.set({ isLoading: true, 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 placeholderText = s.suggestions\n .filter((sg: Suggestion) => sg.type === \"placeholder\")\n .map((sg: Suggestion) => sg.text)\n .join(\" \");\n const effBase = effectiveFilterBase(s.text, s.filterBase, placeholderText);\n const currentQuery = extractFilterQuery(s.text, effBase, 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 (\n s.completedParams.length === 0 &&\n s.text.length > 0 &&\n placeholderText.length > 0 &&\n placeholderText.toLowerCase().startsWith(s.text.toLowerCase())\n ) {\n return false;\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 { cursorIsAtEnd, getCursorOffset, setCursorOffset } from \"../dom/cursorUtils\";\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 * Tier 1 only: remove a completed param at the given caret offset, returning\n * true when a param was removed. Tier 2 consumers can omit this — Backspace\n * falls back to the browser default in their own input element.\n */\n removeParamAtCaret?: (offset: number) => boolean;\n /** Tier 1 only: exit re-edit mode (Escape, arrow-key escape). */\n exitEditMode?: () => void;\n}\n\n/**\n * Returns true when the caret in the event target sits at the end of its\n * editable content. Works for both `<textarea>`/`<input>` (Tier 2 consumer\n * inputs) and our contentEditable Tier 1 editor.\n */\nfunction isCursorAtEnd(target: EventTarget | null): boolean {\n if (target instanceof HTMLTextAreaElement || target instanceof HTMLInputElement) {\n return target.selectionStart != null && target.selectionStart === target.value.length;\n }\n if (target instanceof HTMLElement && target.hasAttribute(\"data-aia-input\")) {\n return cursorIsAtEnd(target);\n }\n return false;\n}\n\nfunction getEditableCaretOffset(target: EventTarget | null): number | null {\n if (target instanceof HTMLElement && target.hasAttribute(\"data-aia-input\")) {\n return getCursorOffset(target);\n }\n return null;\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 cursorAtEnd = isCursorAtEnd(e.target);\n // While re-editing a bold param, the dropdown is showing cached\n // options for it — ArrowDown should descend into them regardless of\n // whether the caret is \"at end\" of the input.\n const inEditMode = !!state.editingParam;\n if (!cursorAtEnd && !inEditMode && 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 // When a dropdown option is highlighted, arrows navigate the grid\n // only — the caret in the editor stays put. Always preventDefault so\n // a press at the rightmost column doesn't fall through to caret\n // movement.\n if (state.activeDropdownIndex >= 0) {\n e.preventDefault();\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 this.store.set({ activeDropdownIndex: rightNeighbor });\n }\n }\n break;\n }\n // No highlight → arrow keys move the caret. In re-edit mode that\n // means collapse the highlight to the param's trailing edge and exit.\n if (state.editingParam && e.target instanceof HTMLElement && state.editingTail != null) {\n e.preventDefault();\n const editor = e.target.closest<HTMLElement>(\"[data-aia-input]\") ?? e.target;\n const tail = state.editingTail;\n this.ctx.exitEditMode?.();\n setCursorOffset(editor, tail);\n break;\n }\n const atEnd = isCursorAtEnd(e.target);\n if (atEnd && state.actionableSuggestions.length > 1) {\n e.preventDefault();\n this.pillsSetActivePill(1);\n }\n break;\n }\n case \"ArrowLeft\": {\n // When a dropdown option is highlighted, arrows navigate the grid\n // only — the caret stays put. Always preventDefault so a press at\n // the leftmost column doesn't fall through to caret movement.\n if (state.activeDropdownIndex >= 0) {\n e.preventDefault();\n if (state.activeDropdownIndex % columns > 0) {\n const leftNeighbor = state.activeDropdownIndex - 1;\n if (leftNeighbor >= 0 && state.filteredOptions[leftNeighbor]?.is_tappable) {\n this.store.set({ activeDropdownIndex: leftNeighbor });\n }\n }\n break;\n }\n // No highlight → arrow keys move the caret.\n if (state.editingParam && e.target instanceof HTMLElement && state.editingAnchor != null) {\n e.preventDefault();\n const editor = e.target.closest<HTMLElement>(\"[data-aia-input]\") ?? e.target;\n const anchor = state.editingAnchor;\n this.ctx.exitEditMode?.();\n setCursorOffset(editor, anchor);\n break;\n }\n break;\n }\n case \"Backspace\": {\n // In re-edit mode the entire bold param is selected; the browser's\n // default Backspace handles deletion of the selected range. Skip\n // removeParamAtCaret so we don't double-handle.\n if (state.editingParam) break;\n if (!this.ctx.removeParamAtCaret) break;\n const offset = getEditableCaretOffset(e.target);\n if (offset == null) break;\n if (this.ctx.removeParamAtCaret(offset)) {\n e.preventDefault();\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 // Tab on a placeholder commits the suggested text as plain typed\n // text — it is NOT a completed param, so it does not render bold.\n // The placeholder suggestion is dropped so it stops showing.\n e.preventDefault();\n const filledText = state.placeholderText;\n this.store.set((s) => ({\n text: filledText,\n filterBase: filledText.length,\n suggestions: s.suggestions.filter((sg) => sg.type !== \"placeholder\"),\n }));\n // Park caret at the end of the just-filled text. queueMicrotask\n // runs AFTER the batched-render microtask so we override the\n // renderer's default caret-clamp.\n if (e.target instanceof HTMLElement) {\n const editor = e.target.closest<HTMLElement>(\"[data-aia-input]\") ?? e.target;\n queueMicrotask(() => setCursorOffset(editor, filledText.length));\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 if (state.editingParam && e.target instanceof HTMLElement && state.editingTail != null) {\n const editor = e.target.closest<HTMLElement>(\"[data-aia-input]\") ?? e.target;\n const tail = state.editingTail;\n this.ctx.exitEditMode?.();\n setCursorOffset(editor, tail);\n }\n this.store.set({ activeDropdownIndex: -1 });\n break;\n }\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 { 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 this.store.set((s) => ({\n completedParams: s.completedParams.slice(0, -1),\n activeDropdownIndex: -1,\n }));\n }\n}\n","import type { Suggestion } from \"../../types\";\n\nconst SKELETON_PILL_WIDTHS = [125, 69];\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 loading = 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 if (loading) {\n list.setAttribute(\"data-aia-pill-list-loading\", \"\");\n // Skeleton path — empty placeholder pills, no diffing needed.\n list.innerHTML = \"\";\n for (let i = 0; i < SKELETON_PILL_WIDTHS.length; i++) {\n const width = SKELETON_PILL_WIDTHS[i];\n const span = document.createElement(\"span\");\n span.setAttribute(\"data-aia-pill-skeleton\", \"\");\n span.className = `magicx-aia-pill magicx-aia-pill--skeleton${rounded ? \" magicx-aia-pill--rounded\" : \"\"}`;\n span.style.width = `${width}px`;\n span.style.opacity = String(getPillOpacity(i));\n list.appendChild(span);\n }\n return;\n }\n\n list.removeAttribute(\"data-aia-pill-list-loading\");\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 || btn.tagName !== \"BUTTON\") {\n btn?.remove();\n btn = document.createElement(\"button\");\n btn.type = \"button\";\n btn.tabIndex = -1;\n btn.dataset.pillKey = key;\n btn.setAttribute(\"data-aia-pill\", \"\");\n btn.setAttribute(\"contenteditable\", \"false\");\n btn.textContent = pill.text;\n // Prevent the browser from moving focus from the editable to the pill\n // button on mousedown. The click handler still fires; focus stays put.\n btn.addEventListener(\"mousedown\", (e) => e.preventDefault());\n }\n\n btn.className = `magicx-aia-pill${rounded ? \" magicx-aia-pill--rounded\" : \"\"}${i === activePillIndex ? \" magicx-aia-pill--active\" : \"\"}`;\n btn.style.width = \"\";\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 // Remove any leftover skeleton spans from a prior render\n for (const skel of list.querySelectorAll<HTMLElement>(\"[data-aia-pill-skeleton]\")) {\n skel.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\nconst SKELETON_BAR_WIDTHS = [159, 119, 164];\nconst SKELETON_PILL_WIDTHS = [115, 122];\n\ninterface DropdownState {\n suggestions: Suggestion[];\n filteredOptions: SuggestionOption[];\n activeIndex: number;\n isOpen: boolean;\n isLoading: 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 isLoading,\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 = isOpen && (isLoading || hasOptions || 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 if (isLoading) {\n dropdown.setAttribute(\"data-aia-loading\", \"\");\n } else {\n dropdown.removeAttribute(\"data-aia-loading\");\n }\n\n // --- Skeleton (loading state) ---\n let skeleton = dropdown.querySelector<HTMLElement>(\".magicx-aia-skeleton\");\n if (isLoading) {\n // Clear the live pill bar & grid so the skeleton is the sole content.\n dropdown.querySelector<HTMLElement>(\".magicx-aia-pill-bar\")?.remove();\n dropdown.querySelector<HTMLElement>(\".magicx-aia-grid\")?.remove();\n if (!skeleton) {\n skeleton = createSkeleton(showPills);\n dropdown.appendChild(skeleton);\n } else {\n // Sync skeleton-pills row presence with the current showPills value.\n const existingPills = skeleton.querySelector(\".magicx-aia-skeleton-pills\");\n if (showPills && !existingPills) {\n skeleton.insertBefore(createSkeletonPills(), skeleton.firstChild);\n } else if (!showPills && existingPills) {\n existingPills.remove();\n }\n }\n return;\n }\n\n // Not loading — drop the skeleton if present.\n if (skeleton) skeleton.remove();\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 createSkeleton(showPills: boolean): HTMLElement {\n const skeleton = document.createElement(\"div\");\n skeleton.className = \"magicx-aia-skeleton\";\n skeleton.setAttribute(\"data-aia-skeleton\", \"\");\n if (showPills) skeleton.appendChild(createSkeletonPills());\n const bars = document.createElement(\"div\");\n bars.className = \"magicx-aia-skeleton-bars\";\n for (const width of SKELETON_BAR_WIDTHS) {\n const bar = document.createElement(\"span\");\n bar.className = \"magicx-aia-skeleton-bar\";\n bar.style.width = `${width}px`;\n bars.appendChild(bar);\n }\n skeleton.appendChild(bars);\n return skeleton;\n}\n\nfunction createSkeletonPills(): HTMLElement {\n const row = document.createElement(\"div\");\n row.className = \"magicx-aia-skeleton-pills\";\n row.setAttribute(\"data-aia-skeleton-pills\", \"\");\n for (const width of SKELETON_PILL_WIDTHS) {\n const pill = document.createElement(\"span\");\n pill.className = \"magicx-aia-skeleton-pill\";\n pill.style.width = `${width}px`;\n row.appendChild(pill);\n }\n return row;\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 // Re-edit shows cached options — skeleton would clobber that UI.\n isLoading: state.isLoading && !state.editingParam,\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 { AutocompleteResult, Suggestion } from \"../../types\";\nimport { buildQuery } from \"../../utils/buildQuery\";\nimport { extractPlainText, getCursorOffset, setCursorOffset } from \"../dom/cursorUtils\";\nimport type { Store } from \"../state\";\nimport type { CoreState } from \"../types\";\nimport { createDropdown, renderDropdown } from \"./renderDropdown\";\nimport { renderEditableContent } from \"./renderEditable\";\nimport { clearPills, renderPills } from \"./renderPills\";\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 /** Re-edit entry: triggered when caret enters a bold completed param. */\n startEditingParam: (paramId: string) => void;\n /** Re-edit caret-tracking after an input event (extends edit tail). */\n handleCaretAfterInput: (offset: number | null) => void;\n /** Re-edit caret-tracking on selection-only moves (may exit edit mode). */\n handleCaretMove: (offset: number | null) => void;\n /** Re-edit beforeinput intercept: replace the editing range atomically. */\n replaceEditingRange: (replacement: string) => boolean;\n}\n\nexport interface DOMRefs {\n input: HTMLDivElement;\n /** Non-editable inline pill list rendered as a sibling of the editable. */\n inlinePillContainer: HTMLSpanElement;\n dropdown: 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 /** Aborts all listeners attached during buildDOM. */\n abort: AbortController;\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\nfunction supportsPlaintextOnly(): boolean {\n const probe = document.createElement(\"div\");\n probe.setAttribute(\"contenteditable\", \"plaintext-only\");\n return probe.contentEditable === \"plaintext-only\";\n}\n\nexport function buildDOM(container: HTMLElement, opts: RenderInputOptions): DOMRefs {\n const { listboxId } = opts;\n\n const dropdown = createDropdown(listboxId);\n container.appendChild(dropdown);\n\n const inputWrapper = document.createElement(\"div\");\n inputWrapper.className = \"magicx-aia-input-wrapper\";\n container.appendChild(inputWrapper);\n\n const editor = document.createElement(\"div\");\n editor.className = \"magicx-aia-editor\";\n editor.setAttribute(\"data-aia-editor\", \"\");\n inputWrapper.appendChild(editor);\n\n const input = document.createElement(\"div\");\n input.className = \"magicx-aia-input\";\n input.setAttribute(\"data-aia-input\", \"\");\n input.setAttribute(\"contenteditable\", supportsPlaintextOnly() ? \"plaintext-only\" : \"true\");\n input.setAttribute(\"role\", \"combobox\");\n input.setAttribute(\"aria-autocomplete\", \"list\");\n input.setAttribute(\"aria-haspopup\", \"listbox\");\n input.setAttribute(\"aria-controls\", listboxId);\n input.setAttribute(\"aria-expanded\", \"false\");\n input.setAttribute(\"spellcheck\", \"true\");\n input.setAttribute(\"enterkeyhint\", \"send\");\n editor.appendChild(input);\n\n // Pills sit as a sibling of the editable — they're never inside a\n // contentEditable subtree, so there's no risk of them becoming part of the\n // typing surface. Layout (CSS) keeps them visually adjacent to the text.\n const inlinePillContainer = document.createElement(\"span\");\n inlinePillContainer.className = \"magicx-aia-pill-list-container\";\n inlinePillContainer.setAttribute(\"data-aia-pill-list-container\", \"\");\n editor.appendChild(inlinePillContainer);\n\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 const abort = new AbortController();\n const { signal } = abort;\n\n let composing = false;\n // Tracks when an input event has just fired so the immediately-following\n // selectionchange knows to extend the edit tail rather than treat the\n // caret move as a navigation event.\n let lastInputAt = 0;\n\n const fireInput = () => {\n const raw = extractPlainText(input);\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 const findEnclosingParamId = (): string | null => {\n const sel = (input.ownerDocument ?? document).getSelection();\n if (!sel || sel.rangeCount === 0) return null;\n const anchor = sel.anchorNode;\n if (!anchor || !input.contains(anchor)) return null;\n const startEl =\n anchor.nodeType === Node.ELEMENT_NODE ? (anchor as Element) : anchor.parentElement;\n const strong = startEl?.closest<HTMLElement>('strong[data-seg=\"completed\"][data-param-id]');\n return strong?.dataset.paramId ?? null;\n };\n\n inputWrapper.addEventListener(\n \"click\",\n (e) => {\n // Clicking a pill button should activate the pill, not steal focus.\n if ((e.target as HTMLElement | null)?.closest(\"[data-aia-pill]\")) return;\n input.focus();\n },\n { signal },\n );\n\n input.addEventListener(\n \"input\",\n () => {\n if (composing) return;\n lastInputAt = performance.now();\n fireInput();\n // After typing, extend the edit tail to the new caret position so the\n // user can keep typing past the param's original end without exiting.\n opts.handleCaretAfterInput(getCursorOffset(input));\n },\n { signal },\n );\n\n // selectionchange fires on the document (Selection API doesn't bubble to\n // elements). Filter to selections anchored inside our editor, then route\n // the caret state into the core. A short cooldown after `input` events\n // avoids treating the post-typing caret position as a \"move\" that would\n // exit edit mode.\n const doc = input.ownerDocument ?? document;\n doc.addEventListener(\n \"selectionchange\",\n () => {\n const sel = doc.getSelection();\n if (!sel || sel.rangeCount === 0) return;\n if (!input.contains(sel.anchorNode!)) return;\n const enclosing = findEnclosingParamId();\n const editingId = opts.store.get().editingParam?.id ?? null;\n if (enclosing && enclosing !== editingId) {\n opts.startEditingParam(enclosing);\n return;\n }\n if (performance.now() - lastInputAt < 50) {\n // Just-typed: caret move handled by handleCaretAfterInput above.\n return;\n }\n opts.handleCaretMove(getCursorOffset(input));\n },\n { signal },\n );\n\n input.addEventListener(\n \"compositionstart\",\n () => {\n composing = true;\n },\n { signal },\n );\n input.addEventListener(\n \"compositionend\",\n () => {\n composing = false;\n fireInput();\n },\n { signal },\n );\n\n input.addEventListener(\n \"beforeinput\",\n (e) => {\n const inputEvent = e as InputEvent;\n const t = inputEvent.inputType;\n if (t === \"insertParagraph\" || t === \"insertLineBreak\" || t === \"insertFromDrop\") {\n e.preventDefault();\n return;\n }\n // Re-edit mode atomic-replace: while the edited param's `<strong>` is\n // still in the DOM, swap the whole thing for whatever the user is\n // about to insert (or empty, for deletes). Without this, typing or\n // backspace would land inside the bold span instead of replacing it.\n if (t.startsWith(\"insert\") || t.startsWith(\"delete\")) {\n const replacement = t.startsWith(\"delete\") ? \"\" : (inputEvent.data ?? \"\");\n if (opts.replaceEditingRange(replacement)) {\n e.preventDefault();\n }\n }\n },\n { signal },\n );\n\n input.addEventListener(\n \"paste\",\n (e) => {\n e.preventDefault();\n const text = (e.clipboardData?.getData(\"text/plain\") ?? \"\").replace(/\\r?\\n/g, \" \");\n if (!text) return;\n const doc = input.ownerDocument ?? document;\n const sel = doc.getSelection();\n if (!sel || sel.rangeCount === 0) return;\n const range = sel.getRangeAt(0);\n if (!input.contains(range.startContainer)) return;\n range.deleteContents();\n const node = doc.createTextNode(text);\n range.insertNode(node);\n range.setStartAfter(node);\n range.collapse(true);\n sel.removeAllRanges();\n sel.addRange(range);\n fireInput();\n },\n { signal },\n );\n\n input.addEventListener(\"keydown\", (e) => opts.handleKeyDown(e), { signal });\n\n input.addEventListener(\"focus\", () => opts.store.set({ isFocused: true }), { signal });\n input.addEventListener(\"blur\", () => opts.store.set({ isFocused: false }), { signal });\n\n if (submitTarget) {\n submitTarget.addEventListener(\n \"click\",\n (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 { signal },\n );\n }\n\n if (opts.autoFocus !== false) {\n input.focus();\n }\n\n return { input, inlinePillContainer, dropdown, submitButton, abort };\n}\n\nexport function updateDOM(refs: DOMRefs, state: CoreState, opts: RenderInputOptions) {\n const { input, inlinePillContainer, dropdown, submitButton } = refs;\n const { pillPlacement, setActivePill, selectOption, store } = opts;\n\n input.setAttribute(\"aria-expanded\", String(state.isDropdownOpen));\n const activeDescendant =\n state.activeDropdownIndex >= 0 ? `${opts.listboxId}-option-${state.activeDropdownIndex}` : \"\";\n if (activeDescendant) {\n input.setAttribute(\"aria-activedescendant\", activeDescendant);\n } else {\n input.removeAttribute(\"aria-activedescendant\");\n }\n\n if (submitButton) {\n const canSubmit = !!state.text || state.completedParams.length > 0;\n submitButton.disabled = !canSubmit;\n }\n\n // Detect a fresh option selection BEFORE renderEditableContent mutates the\n // dataset. `newParamId` is set by selectOption() each time a suggestion\n // becomes a completed param. We compare against the last id the DOM saw so\n // the focus/caret jump only fires once per selection (not on every render\n // during the 650ms shimmer window).\n const previousParamId = input.dataset.newParamId ?? \"\";\n const justSelected = state.newParamId !== null && state.newParamId !== previousParamId;\n\n renderEditableContent({\n input,\n segments: state.segments,\n newParamId: state.newParamId,\n editingParamId: state.editingParam?.id ?? null,\n placeholderText: state.placeholderText,\n isFocused: state.isFocused,\n });\n\n if (pillPlacement === \"inline\") {\n const inlineLoading = state.isLoading && !state.editingParam;\n if (inlineLoading || state.actionableSuggestions.length > 0) {\n renderPills(\n inlinePillContainer,\n state.actionableSuggestions,\n 0,\n setActivePill,\n false,\n inlineLoading,\n );\n } else {\n clearPills(inlinePillContainer);\n }\n } else {\n clearPills(inlinePillContainer);\n }\n\n if (justSelected) {\n // After option selection, focus jumped to the clicked dropdown option\n // (or stayed on the editor via the dropdown's mousedown preventDefault).\n // Either way, bring focus to the editable and park the caret at the\n // position the promoter chose — typically right after the new param's\n // trailing space. Falls back to end-of-input for safety.\n input.focus();\n setCursorOffset(input, state.caretOffset ?? state.text.length);\n } else if (state.isFocused) {\n // Controlled-mode setValue / programmatic reset: keep the caret at the\n // end when DOM text diverges from state. Skip when not focused so we\n // don't steal focus on unrelated state churn.\n const domText = extractPlainText(input);\n if (domText !== state.text) {\n setCursorOffset(input, state.text.length);\n }\n }\n\n // In re-edit mode, the dropdown's pill bar shows a synthetic pill built\n // from the edited param's cached suggestion metadata (regardless of the\n // latest server suggestions). Inline pills are unaffected — they still\n // reflect the live actionable suggestions.\n const dropdownPill: Suggestion | null = state.editingParam\n ? {\n type: state.editingParam.suggestionType,\n text: state.editingParam.suggestionPlaceholder,\n required: true,\n options: state.editingParam.options,\n }\n : null;\n const dropdownActivePill = dropdownPill ?? state.actionableSuggestions[0];\n\n renderDropdown(dropdown, {\n suggestions: dropdownActivePill\n ? [{ ...dropdownActivePill, options: state.filteredOptions }]\n : [],\n filteredOptions: state.filteredOptions,\n activeIndex: state.activeDropdownIndex,\n isOpen: state.isDropdownOpen,\n // Re-edit shows cached options — skeleton would clobber that UI.\n isLoading: state.isLoading && !state.editingParam,\n listboxId: opts.listboxId,\n pills: dropdownPill ? [dropdownPill] : 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 {\n effectiveFilterBase,\n extractFilterQuery,\n filterOptions,\n findExactMatch,\n findPrefixOverlap,\n} 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 { previousGraphemeBoundary, setCursorOffset } from \"./dom/cursorUtils\";\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 editingParam: null,\n editingAnchor: null,\n editingTail: null,\n caretOffset: null,\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 removeParamAtCaret: (offset) => this.removeParamAtCaret(offset),\n exitEditMode: () => this.exitEditMode(),\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?.input.focus();\n }\n\n blur() {\n this.domRefs?.input.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?.abort.abort();\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 /**\n * Backspace inside a completed param: drop the param's \"completed\" status so\n * it renders as plain (un-bold) text, AND remove one grapheme before the\n * caret — same single-character delete a normal Backspace would do. The\n * remaining text stays in the input so the user can continue editing what\n * they had typed instead of losing the whole phrase.\n *\n * Returns true when a param was reconciled (caller should `preventDefault`).\n */\n removeParamAtCaret(offset: number): boolean {\n const state = this.store.get();\n const { text, completedParams } = state;\n let pos = 0;\n for (let i = 0; i < completedParams.length; i++) {\n const param = completedParams[i];\n const idx = text.indexOf(param.text, pos);\n if (idx === -1) continue;\n const paramStart = idx;\n const paramEnd = idx + param.text.length;\n if (offset > paramStart && offset <= paramEnd) {\n const deleteStart = previousGraphemeBoundary(text, offset);\n const newText = text.slice(0, deleteStart) + text.slice(offset);\n const newParams = completedParams.filter((_, j) => j !== i);\n this.store.set((s) => ({\n text: newText,\n filterBase: Math.min(s.filterBase, newText.length),\n completedParams: newParams,\n pillTapped: false,\n activeDropdownIndex: -1,\n }));\n this.scheduleSetCursor(deleteStart);\n return true;\n }\n pos = paramEnd;\n }\n return false;\n }\n\n /**\n * Set the editor caret at the given plain-text offset. Uses the core's own\n * `domRefs.input` in \"full\" mode; falls back to the wrapper-provided\n * `setCursor` callback in \"headless\" mode where the wrapper owns the DOM.\n */\n private scheduleSetCursor(offset: number) {\n queueMicrotask(() => {\n const refs = this.domRefs;\n if (refs) {\n setCursorOffset(refs.input, offset);\n } else {\n this.opts.setCursor?.(offset);\n }\n });\n }\n\n clearNewParamId() {\n this.store.set({ newParamId: null });\n }\n\n /**\n * Enter re-edit mode for the bold completed param with the given id. The\n * caller is responsible for highlighting the param via the Selection API\n * (DOM concern). This method just sets the state snapshot so the dropdown\n * starts filtering the param's cached options.\n */\n startEditingParam(paramId: string) {\n const state = this.store.get();\n if (state.editingParam?.id === paramId) return;\n const param = state.completedParams.find((p) => p.id === paramId);\n if (!param) return;\n // Find the param's position in text (same approach as deriveSegments).\n let pos = 0;\n let anchor = -1;\n for (const p of state.completedParams) {\n const idx = state.text.indexOf(p.text, pos);\n if (idx === -1) continue;\n if (p.id === paramId) {\n anchor = idx;\n break;\n }\n pos = idx + p.text.length;\n }\n if (anchor < 0) return;\n this.store.set({\n editingParam: param,\n editingAnchor: anchor,\n editingTail: anchor + param.text.length,\n caretOffset: anchor + param.text.length,\n activeDropdownIndex: -1,\n });\n }\n\n /**\n * Replace the editing range (`text[editingAnchor..editingTail]`) with the\n * given replacement. Used by the DOM layer's `beforeinput` intercept: while\n * the edited param's strong still exists in `completedParams`, typing or\n * backspace should swap the WHOLE param atomically (instead of inserting\n * one char into the bold span). Returns true when the replacement was\n * applied — callers should `preventDefault` only in that case.\n */\n replaceEditingRange(replacement: string): boolean {\n const state = this.store.get();\n const editing = state.editingParam;\n const anchor = state.editingAnchor;\n const tail = state.editingTail;\n if (!editing || anchor == null || tail == null) return false;\n // Only intercept while the param's strong is still in the DOM (i.e. it\n // hasn't already been replaced by an earlier keystroke).\n if (!state.completedParams.some((p) => p.id === editing.id)) return false;\n const newText = state.text.slice(0, anchor) + replacement + state.text.slice(tail);\n const newTail = anchor + replacement.length;\n this.store.set((s) => ({\n text: newText,\n completedParams: s.completedParams.filter((p) => p.id !== editing.id),\n editingTail: newTail,\n caretOffset: newTail,\n activeDropdownIndex: -1,\n }));\n this.scheduleSetCursor(newTail);\n this.maybePromoteEditExactMatch();\n return true;\n }\n\n /** Clear re-edit state. Selection collapsing is a DOM concern handled by the caller. */\n exitEditMode() {\n const state = this.store.get();\n if (!state.editingParam) return;\n this.store.set({\n editingParam: null,\n editingAnchor: null,\n editingTail: null,\n activeDropdownIndex: -1,\n });\n }\n\n /**\n * Update caret offset after a text-input event. While in edit mode, extends\n * `editingTail` to keep up with the user typing past the previous tail.\n * Exits edit mode if the user backspaced past `editingAnchor` (deleting a\n * character before where the edit started).\n */\n handleCaretAfterInput(offset: number | null) {\n const state = this.store.get();\n const patch: Partial<CoreState> = { caretOffset: offset };\n if (state.editingParam && state.editingAnchor != null && offset != null) {\n if (offset < state.editingAnchor) {\n patch.editingParam = null;\n patch.editingAnchor = null;\n patch.editingTail = null;\n patch.activeDropdownIndex = -1;\n } else if (state.editingTail != null) {\n patch.editingTail = Math.max(state.editingTail, offset);\n }\n }\n this.store.set(patch);\n this.maybePromoteEditExactMatch();\n }\n\n /**\n * Update caret offset from a selection-move event that was NOT preceded by\n * an input event (so the user moved the cursor by click or arrows, not by\n * typing). Exits edit mode if the caret moved outside the edit region.\n */\n handleCaretMove(offset: number | null) {\n const state = this.store.get();\n if (\n state.editingParam &&\n state.editingAnchor != null &&\n state.editingTail != null &&\n offset != null &&\n (offset < state.editingAnchor || offset > state.editingTail)\n ) {\n this.store.set({\n caretOffset: offset,\n editingParam: null,\n editingAnchor: null,\n editingTail: null,\n activeDropdownIndex: -1,\n });\n return;\n }\n this.store.set({ caretOffset: offset });\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\n // Re-edit path: replace the highlighted bold param's range with the new\n // option. The new param inherits the *same* cached suggestion metadata\n // (suggestionType/placeholder/options), so re-editing it again would show\n // the same options. Bypasses the normal selectOption flow entirely.\n if (state.editingParam && state.editingAnchor != null && state.editingTail != null) {\n this.selectOptionInEditMode(option);\n return;\n }\n\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 caretOffset: finalText.length,\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 selectOptionInEditMode(option: SuggestionOption) {\n const state = this.store.get();\n const editing = state.editingParam;\n const anchor = state.editingAnchor;\n const tail = state.editingTail;\n if (!editing || anchor == null || tail == null) return;\n\n this.fireTelemetry(\"option\", {\n raw_query: buildQuery(state.text, state.completedParams).rawQuery,\n selected_option: option.text,\n other_options: editing.options.filter((o) => o.text !== option.text).map((o) => o.text),\n });\n\n const before = state.text.slice(0, anchor);\n const after = state.text.slice(tail);\n // Capitalize when replacing at the very start of the input — matches the\n // case-handling in the normal selectOption path for \"first letter of the\n // input is uppercase\".\n const optionText =\n anchor === 0 && option.text.length > 0\n ? option.text[0].toUpperCase() + option.text.slice(1)\n : option.text;\n // Preserve the trailing-space convention: a single space follows the\n // replaced text unless the next char already provides one.\n const needsTrailingSpace = after.length === 0 || after[0] !== \" \";\n const replacement = needsTrailingSpace ? `${optionText} ` : optionText;\n const newText = before + replacement + after;\n // Caret lands AFTER the trailing space — whether we just added it or it\n // was already there from the original text. Matches the normal\n // selectOption flow where the caret sits past the trailing space ready\n // to type the next word.\n const caretPos = anchor + replacement.length + (needsTrailingSpace ? 0 : 1);\n\n const newParam: CompletedParamState = {\n id: crypto.randomUUID(),\n placeholder: \"\",\n type: editing.suggestionType,\n text: optionText,\n kind: option.kind,\n suggestionType: editing.suggestionType,\n suggestionPlaceholder: editing.suggestionPlaceholder,\n options: editing.options,\n metadata: option.metadata,\n };\n const oldIdx = state.completedParams.findIndex((p) => p.id === editing.id);\n const params = state.completedParams.filter((p) => p.id !== editing.id);\n const insertAt = oldIdx >= 0 ? Math.min(oldIdx, params.length) : params.length;\n params.splice(insertAt, 0, newParam);\n\n this.store.set({\n text: newText,\n completedParams: params,\n newParamId: newParam.id,\n filterBase: caretPos,\n editingParam: null,\n editingAnchor: null,\n editingTail: null,\n caretOffset: caretPos,\n activeDropdownIndex: -1,\n pillTapped: false,\n skipNextFetch: true,\n });\n // Park the caret right after the replacement (not at end of text) once\n // the render microtask commits.\n this.scheduleSetCursor(caretPos);\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 const placeholderText = next.suggestions\n .filter((s) => s.type === \"placeholder\")\n .map((s) => s.text)\n .join(\" \");\n\n // Clamp filterBase so it never exceeds text length (matches old React behavior).\n // Promote the placeholder to filterBase when the user has typed through it —\n // the filter query should be just the text past the server-suggested prefix.\n const clampedFilterBase = effectiveFilterBase(\n next.text,\n Math.min(next.filterBase, next.text.length),\n placeholderText,\n );\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\n // Re-edit mode: dropdown filters the edited param's cached options instead\n // of the active suggestion's options. While the bold param's still in the\n // DOM (user just tapped it, hasn't typed yet), show the FULL cached list —\n // filtering by the param's own text would only match itself. Once the\n // user starts typing (param removed from completedParams), filter by what\n // they typed.\n const inEditMode = next.editingParam != null && next.editingAnchor != null;\n let filteredOptions: SuggestionOption[];\n if (inEditMode && next.editingParam && next.editingAnchor != null) {\n const editingId = next.editingParam.id;\n const paramStillPresent = next.completedParams.some((p) => p.id === editingId);\n const editCaret = next.caretOffset ?? next.editingAnchor;\n const editQuery = paramStillPresent ? \"\" : next.text.slice(next.editingAnchor, editCaret);\n filteredOptions = filterOptions(next.editingParam.options, editQuery);\n } else {\n filteredOptions = filterOptions(baseOptions, filterQuery);\n }\n\n const trigger = this.opts.dropdownTrigger ?? \"auto\";\n const closeOnBlur = this.opts.closeDropdownOnBlur ?? true;\n let isDropdownOpen = false;\n if (inEditMode) {\n // While re-editing, the dropdown is governed solely by whether cached\n // options match the query — focus/manual gates don't apply (the user\n // is in a deliberate edit interaction).\n const focusGate = closeOnBlur ? next.isFocused : true;\n isDropdownOpen = filteredOptions.length > 0 && focusGate;\n } else if (trigger === \"auto\") {\n const focusGate = closeOnBlur ? next.isFocused : true;\n // Outside re-edit, dropdown only opens when the caret is at the end of\n // the input — middle-of-text caret should NOT show suggestions. Trailing\n // whitespace is ignored so the dropdown stays open right after an option\n // selection (which appends a trailing space) or when the user pauses on\n // a word boundary.\n const trimmedEnd = next.text.replace(/\\s+$/, \"\").length;\n const caretAtEnd = next.caretOffset == null || next.caretOffset >= trimmedEnd;\n isDropdownOpen = (filteredOptions.length > 0 || next.isLoading) && focusGate && caretAtEnd;\n } else if (trigger === \"manual\") {\n isDropdownOpen = (filteredOptions.length > 0 || next.isLoading) && 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 startEditingParam: (id: string) => this.startEditingParam(id),\n handleCaretAfterInput: (offset: number | null) => this.handleCaretAfterInput(offset),\n handleCaretMove: (offset: number | null) => this.handleCaretMove(offset),\n replaceEditingRange: (replacement: string) => this.replaceEditingRange(replacement),\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({ completedParams: valid });\n }\n\n this.maybePromoteExactMatch(newValue);\n }\n\n /**\n * When the user has typed text that exactly matches (case-insensitive) one\n * of the active suggestion's options, promote it to a completed param right\n * away. The fetchController does the same check when the debounced fetch\n * lands; doing it instantly here means bold styling appears as soon as the\n * option is fully typed, without waiting 100–300ms for the round-trip.\n */\n private maybePromoteExactMatch(newValue: string) {\n const s = this.store.get();\n const actionable = s.suggestions.filter((sg) => sg.type !== \"placeholder\");\n const active = actionable[0];\n if (!active?.options) return;\n const placeholderText = s.suggestions\n .filter((sg) => sg.type === \"placeholder\")\n .map((sg) => sg.text)\n .join(\" \");\n const effBase = effectiveFilterBase(newValue, s.filterBase, placeholderText);\n const query = extractFilterQuery(newValue, effBase, s.filterInProgress);\n const match = findExactMatch(active.options, query);\n if (!match) return;\n // Preserve the case the user actually typed so deriveSegments (case-\n // sensitive indexOf) can still match the completed param inside newValue.\n const matchLower = match.text.toLowerCase();\n const optionStart = newValue.toLowerCase().lastIndexOf(matchLower);\n const paramStart =\n optionStart >= 0 ? optionStart : Math.max(0, newValue.length - match.text.length);\n const paramEnd = paramStart + match.text.length;\n const optionInText = newValue.slice(paramStart, paramEnd);\n // The user typed the option themselves — don't inject a trailing space.\n // If they wanted a space, they'd type one. (Auto-injecting one here\n // caused double-space states when the user added their own space, which\n // confused contentEditable's trailing-whitespace handling.)\n const newText = newValue;\n const hasTrailingSpace = paramEnd < newValue.length && newValue[paramEnd] === \" \";\n const caretPos = hasTrailingSpace ? paramEnd + 1 : paramEnd;\n const completed: CompletedParamState = {\n id: crypto.randomUUID(),\n placeholder: \"\",\n type: active.type,\n text: optionInText,\n kind: match.kind,\n suggestionType: active.type,\n suggestionPlaceholder: active.text,\n options: active.options ?? [],\n metadata: match.metadata,\n };\n this.store.set((prev) => ({\n text: newText,\n completedParams: [...prev.completedParams, completed],\n suggestions: prev.suggestions.filter((sg) => sg !== active),\n filterBase: caretPos,\n newParamId: completed.id,\n caretOffset: caretPos,\n activeDropdownIndex: -1,\n }));\n }\n\n /**\n * Edit-mode counterpart to {@link maybePromoteExactMatch}. When the user is\n * editing a bold completed param and the typed text exactly matches one of\n * that param's cached options, promote it back to a completed param (bold)\n * — same instant-bold affordance as the normal typing flow, just driven by\n * the edited param's cached options instead of the active suggestion.\n */\n private maybePromoteEditExactMatch() {\n const s = this.store.get();\n const editing = s.editingParam;\n const anchor = s.editingAnchor;\n const tail = s.editingTail;\n if (!editing || anchor == null || tail == null) return;\n // Skip while the original bold is still in completedParams (user hasn't\n // typed yet — the editQuery would just be the param's own text).\n if (s.completedParams.some((p) => p.id === editing.id)) return;\n const editQuery = s.text.slice(anchor, tail);\n const match = findExactMatch(editing.options, editQuery);\n if (!match) return;\n\n // Locate the matched portion within the edit region so we know where the\n // new param's text sits in the full input. Preserve the user's typed\n // casing so deriveSegments (case-sensitive indexOf) can still find it.\n const matchLower = match.text.toLowerCase();\n const matchStart = editQuery.toLowerCase().lastIndexOf(matchLower);\n const paramStart = anchor + Math.max(0, matchStart);\n const paramEnd = paramStart + match.text.length;\n const optionInText = s.text.slice(paramStart, paramEnd);\n\n // The user typed the option themselves — don't inject a trailing space.\n const newText = s.text;\n const hasTrailingSpace = paramEnd < s.text.length && s.text[paramEnd] === \" \";\n const caretPos = hasTrailingSpace ? paramEnd + 1 : paramEnd;\n\n const newParam: CompletedParamState = {\n id: crypto.randomUUID(),\n placeholder: \"\",\n type: editing.suggestionType,\n text: optionInText,\n kind: match.kind,\n suggestionType: editing.suggestionType,\n suggestionPlaceholder: editing.suggestionPlaceholder,\n options: editing.options,\n metadata: match.metadata,\n };\n\n // Insert at the correct text-order position. The editing param is already\n // gone from completedParams; walk the remaining params and insert before\n // the first one whose text sits past the edit region.\n let insertAt = s.completedParams.length;\n let scanPos = 0;\n for (let i = 0; i < s.completedParams.length; i++) {\n const idx = newText.indexOf(s.completedParams[i].text, scanPos);\n if (idx === -1) continue;\n if (idx >= caretPos) {\n insertAt = i;\n break;\n }\n scanPos = idx + s.completedParams[i].text.length;\n }\n const newParams = [...s.completedParams];\n newParams.splice(insertAt, 0, newParam);\n\n this.store.set(() => ({\n text: newText,\n completedParams: newParams,\n newParamId: newParam.id,\n filterBase: caretPos,\n editingParam: null,\n editingAnchor: null,\n editingTail: null,\n caretOffset: caretPos,\n activeDropdownIndex: -1,\n }));\n this.scheduleSetCursor(caretPos);\n }\n}\n"],"mappings":"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","names":["forwardRef","useCallback","useEffect","useImperativeHandle","useLayoutEffect","useRef","s","AIAutocomplete_module_css_default","s","AIAutocompleteDropdown_module_css_default","s","PillList_module_css_default","jsx","SKELETON_PILL_WIDTHS","getPillOpacity","index","PillList","pills","activePillIndex","onSelectPill","rounded","loading","PillList_module_css_default","w","pill","e","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","Fragment","jsx","jsxs","SKELETON_BAR_WIDTHS","SKELETON_PILL_WIDTHS","AIAutocompleteDropdown","suggestions","activeIndex","onSelect","onHighlight","isOpen","id","className","pills","onPillClick","showPills","isLoading","options","hasPills","hasOptions","isVisible","AIAutocompleteDropdown_module_css_default","e","w","PillList","SuggestionGrid","s","NON_EDITABLE_SELECTOR","segmenter","getGraphemeSegmenter","Segmenter","isInsideNonEditable","node","root","n","createTextWalker","extractPlainText","walker","out","plainTextLength","total","getCursorOffset","sel","anchorNode","anchorOffset","el","offset","plainTextLengthOfSubtree","offsetBeforeNode","child","target","setCursorOffset","doc","clamped","cumulative","targetOffset","lastNode","len","next","range","strongParent","cursorIsAtEnd","previousGraphemeBoundary","text","seg","slice","last","index","renderEditableContent","args","input","segments","newParamId","editingParamId","placeholderText","isFocused","empty","segKey","s","lastSegKey","lastNewParamId","lastEditingParamId","savedOffset","getCursorOffset","doc","frag","newLength","seg","strong","isNew","isEditing","classes","setCursorOffset","useCallback","useEffect","useRef","useState","buildQuery","text","completedParams","result","typeCounts","updatedParams","param","count","placeholder","index","effectiveFilterBase","text","filterBase","placeholderText","extractFilterQuery","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","textAtRequest","res","fetchSuggestions","newSuggestions","applyOptionOverrides","input","lastInput","currentText","filterBase","filterInProgress","inProgressIdx","active","s","extraParam","query","extractFilterQuery","match","findExactMatch","err","caughtError","attemptFetch","minDiff","placeholderText","sg","effBase","effectiveFilterBase","currentQuery","tappableFiltered","filterOptions","o","hasExactMatch","isInFilterZone","updatedParams","buildQuery","isDeleting","charDiff","isCursorAtEnd","target","cursorIsAtEnd","getEditableCaretOffset","getCursorOffset","KeyboardController","store","ctx","state","listboxId","getOnSubmit","columns","onSubmit","tappableIndices","cursorAtEnd","inEditMode","currentPos","nextPos","prevPos","rightNeighbor","editor","tail","setCursorOffset","leftNeighbor","anchor","offset","rawQuery","finalParams","buildQuery","placeholderVisible","hasHighlightedOption","filledText","s","sg","firstTappableIdx","o","tappable","i","buckets","grid","tracks","index","options","optionEl","actionable","moved","rest","_","placeholders","PillsController","store","callbacks","index","state","actionable","moved","rest","_","i","placeholders","rawQuery","buildQuery","s","SKELETON_PILL_WIDTHS","getPillOpacity","index","renderPills","container","pills","activePillIndex","onSelectPill","rounded","loading","list","i","width","span","existing","btn","used","pill","key","e","skel","clearPills","SKELETON_BAR_WIDTHS","SKELETON_PILL_WIDTHS","createDropdown","listboxId","dropdown","e","renderDropdown","state","filteredOptions","activeIndex","isOpen","isLoading","pills","showPills","onSelect","onHighlight","onPillClick","hasPills","hasOptions","skeleton","createSkeleton","existingPills","createSkeletonPills","pillBar","renderPills","grid","renderOptions","bars","width","bar","row","pill","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","i","SUBMIT_SVG","supportsPlaintextOnly","probe","buildDOM","container","opts","listboxId","dropdown","createDropdown","inputWrapper","editor","input","inlinePillContainer","submitButton","submitTarget","abort","signal","composing","lastInputAt","fireInput","raw","extractPlainText","newValue","findEnclosingParamId","sel","anchor","e","getCursorOffset","doc","enclosing","editingId","inputEvent","t","replacement","text","range","node","state","rawQuery","finalParams","buildQuery","updateDOM","refs","pillPlacement","setActivePill","selectOption","store","activeDescendant","canSubmit","previousParamId","justSelected","renderEditableContent","inlineLoading","renderPills","clearPills","setCursorOffset","dropdownPill","dropdownActivePill","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","offset","next","prev","injectStyles","unsub","mode","text","params","index","state","completedParams","pos","param","idx","paramStart","paramEnd","deleteStart","previousGraphemeBoundary","newText","newParams","_","j","s","refs","setCursorOffset","paramId","p","anchor","replacement","editing","tail","newTail","patch","value","focused","listener","event","callback","activeSuggestion","telemetryRawQuery","buildQuery","base","prefix","inputWasEmpty","inputIsPlaceholderPrefix","overlapChars","findPrefixOverlap","needsSpace","finalText","optionStart","optionInFinal","completed","remainingActionable","sg","before","after","optionText","needsTrailingSpace","caretPos","newParam","oldIdx","insertAt","type","queryData","source","sendTelemetry","_prev","segments","deriveSegments","actionableSuggestions","overrideFn","placeholderText","clampedFilterBase","effectiveFilterBase","filterQuery","extractFilterQuery","baseOptions","inEditMode","filteredOptions","editingId","paramStillPresent","editCaret","editQuery","filterOptions","trigger","closeOnBlur","isDropdownOpen","focusGate","trimmedEnd","caretAtEnd","settled","ModeController","self","renderOpts","e","id","buildDOM","updateDOM","dropdownOpts","buildDropdownOnly","updateDropdownOnly","render","scheduled","newValue","valid","invalid","reconcileParams","effBase","query","match","findExactMatch","matchLower","optionInText","matchStart","scanPos","i","useAIAutocomplete","onSubmit","onError","optionOverrides","maskCompletedText","apiConfig","columns","dropdownTrigger","closeDropdownOnBlur","onFocus","onBlur","controlledValue","controlledParams","onChangeProp","onParamsChange","source","setCursor","instanceRef","useRef","coreState","setCoreState","useState","onSubmitRef","onErrorRef","onChangeRef","onParamsChangeRef","onFocusRef","onBlurRef","setCursorRef","useEffect","instance","AIAutocomplete","args","offset","unsub","state","noop","useCallback","apiConfigJson","prevOverridesRef","overridesVersion","prev","next","prevKeys","nextKeys","k","handleChange","e","raw","newValue","handleKeyDown","handleFocus","handleBlur","handleTextChange","value","handleKeyDownT1","native","setFocused","focused","startEditingParam","paramId","exitEditMode","handleCaretAfterInput","handleCaretMove","replaceEditingRange","replacement","setActivePill","index","removeLastParam","clearNewParamId","reset","selectOption","option","setActiveDropdownIndex","text","completedParams","actionableSuggestions","activeSuggestion","filteredOptions","activeDescendantId","editingParam","dropdownPill","dropdownActivePill","dropdownPills","jsx","jsxs","resolveInitialMode","mode","plaintextOnlyCache","supportsPlaintextOnly","probe","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","inputRef","handleSubmitRef","modeControllerRef","composingRef","lastSeenParamIdRef","lastEditingIdRef","caretOffsetRef","lastInputAtRef","useEffect","el","ModeController","handleSetCursor","useCallback","offset","setCursorOffset","completedParams","suggestionPills","setActivePill","segments","newParamId","clearNewParamId","placeholderText","isFocused","isDropdownOpen","isLoading","activeIndex","listboxId","handleTextChange","handleKeyDown","setFocused","editingParam","editingAnchor","caretOffset","startEditingParam","handleCaretAfterInput","handleCaretMove","replaceEditingRange","dropdownProps","reset","useAIAutocomplete","result","t","doc","onSelectionChange","sel","anchor","enclosing","getCursorOffset","useLayoutEffect","renderEditableContent","previous","current","desired","plainTextLength","useImperativeHandle","m","fireInput","raw","extractPlainText","next","handleInputEvent","onBeforeInput","e","inputEvent","replacement","handleCompositionStart","handleCompositionEnd","handlePaste","text","range","node","handleKeyDownReact","canSubmit","handleSubmit","rawQuery","finalParams","buildQuery","handleWrapperClick","showInlinePills","showDropdownPills","activeDescendantId","ceMode","AIAutocomplete_module_css_default","AIAutocompleteDropdown","PillList"]}