@magicx-eng/ai-autocomplete-react 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +281 -129
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +281 -129
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -3
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/AIAutocomplete.tsx","css-module:/home/runner/work/ai-autocomplete-sdk-js/ai-autocomplete-sdk-js/packages/react/src/AIAutocomplete.module.css.js","css-module:/home/runner/work/ai-autocomplete-sdk-js/ai-autocomplete-sdk-js/packages/react/src/AIAutocompleteDropdown.module.css.js","css-module:/home/runner/work/ai-autocomplete-sdk-js/ai-autocomplete-sdk-js/packages/react/src/components/PillList.module.css.js","../src/components/PillList.tsx","../src/components/SuggestionGrid.tsx","css-module:/home/runner/work/ai-autocomplete-sdk-js/ai-autocomplete-sdk-js/packages/react/src/components/SuggestionGrid.module.css.js","../src/components/SuggestionItem.tsx","css-module:/home/runner/work/ai-autocomplete-sdk-js/ai-autocomplete-sdk-js/packages/react/src/components/SuggestionItem.module.css.js","../src/AIAutocompleteDropdown.tsx","plain-css:/home/runner/work/ai-autocomplete-sdk-js/ai-autocomplete-sdk-js/packages/react/src/appearance.css.js","../src/hooks/useAIAutocomplete.ts","../src/hooks/useContentEditableEditor.ts"],"sourcesContent":["export { AIAutocomplete } from \"./AIAutocomplete\";\nexport { AIAutocompleteDropdown } from \"./AIAutocompleteDropdown\";\nexport { useAIAutocomplete } from \"./hooks/useAIAutocomplete\";\nexport type {\n AccessTokenConfig,\n AccessTokenResult,\n AIAutocompleteDropdownProps,\n AIAutocompleteHandle,\n AIAutocompleteProps,\n APIConfig,\n APIKeyConfig,\n AppearanceMode,\n AutocompleteResult,\n CompletedParam,\n CompletedParamState,\n OptionOverrides,\n Segment,\n Suggestion,\n SuggestionOption,\n TaskKind,\n UseAIAutocompleteOptions,\n UseAIAutocompleteReturn,\n} from \"./types\";\n","import {\n forwardRef,\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 {\n type AppearanceMode,\n type AutocompleteResult,\n buildQuery,\n ModeController,\n setCursorOffset,\n} from \"@magicx-eng/ai-autocomplete-vanilla\";\nimport { PillList } from \"./components/PillList\";\nimport { useAIAutocomplete } from \"./hooks/useAIAutocomplete\";\nimport { useContentEditableEditor } from \"./hooks/useContentEditableEditor\";\nimport type { AIAutocompleteHandle, AIAutocompleteProps } from \"./types\";\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 showNonTappableOptions,\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 pillContainerRef = useRef<HTMLSpanElement>(null);\n const handleSubmitRef = useRef<(result: AutocompleteResult) => void>(() => {});\n const modeControllerRef = useRef<ModeController | null>(null);\n // Holds the editor's input *ref object* (not its current value) so the\n // setCursor callback — defined before useContentEditableEditor runs — can\n // dereference the live DOM element at call time without a one-render lag.\n const editorInputRefHolder = useRef<React.RefObject<HTMLDivElement> | null>(null);\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 = editorInputRefHolder.current?.current;\n if (!el) return;\n el.focus();\n 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 optionsPosition,\n closeDropdownOnBlur,\n showNonTappableOptions,\n onFocus,\n onBlur,\n value,\n completedParams: controlledParams,\n onChange: onChangeProp,\n onParamsChange,\n source: \"full-sdk\",\n setCursor: handleSetCursor,\n });\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 const activeDescendantId = activeIndex >= 0 ? `${listboxId}-option-${activeIndex}` : undefined;\n\n const { inputRef, editorProps, focus, blur, getPlainText } = useContentEditableEditor({\n segments,\n newParamId,\n editingParam,\n editingAnchor,\n caretOffset,\n placeholderText,\n isFocused,\n isDropdownOpen,\n listboxId,\n activeDescendantId,\n autoFocus,\n handleTextChange,\n handleKeyDown,\n handleCaretAfterInput,\n handleCaretMove,\n startEditingParam,\n replaceEditingRange,\n setFocused,\n });\n\n // Wire the holder to the hook's ref. The ref *object* is stable across\n // renders, so this assignment is idempotent and reaches the live DOM\n // element via `.current` without snapshotting null on the first render.\n editorInputRefHolder.current = inputRef;\n\n // The pill list sits inline-adjacent to the editor and carries an 8px\n // left margin so it doesn't butt against the editor's text. When the\n // editor's text fills its line and the pill list wraps to a new line,\n // that margin becomes a stray indent at the start of the wrapped line —\n // detect that case and drop the margin via a data attribute the CSS\n // keys off. The wrap detection (pill row's top vs editor's bottom)\n // already handles the placeholder-only case correctly: the placeholder\n // still occupies the editor's line box, so pills sitting beside it are\n // NOT wrapped and the margin stays.\n // biome-ignore lint/correctness/useExhaustiveDependencies: segments/suggestionPills/isLoading are intentional re-measure triggers, not reads\n useLayoutEffect(() => {\n const container = pillContainerRef.current;\n const editor = inputRef.current;\n if (!container || !editor) return;\n\n const update = () => {\n const inner = container.firstElementChild as HTMLElement | null;\n if (!inner) return;\n const cRect = inner.getBoundingClientRect();\n const eRect = editor.getBoundingClientRect();\n const wrapped = cRect.top >= eRect.bottom - 2;\n if (wrapped) container.setAttribute(\"data-aia-pill-wrapped\", \"\");\n else container.removeAttribute(\"data-aia-pill-wrapped\");\n };\n\n update();\n const ro = new ResizeObserver(update);\n ro.observe(editor);\n return () => ro.disconnect();\n }, [segments, suggestionPills.length, isLoading, inputRef]);\n\n useImperativeHandle(\n ref,\n () => ({\n focus,\n blur,\n reset,\n setMode: (m) => modeControllerRef.current?.setMode(m),\n }),\n [focus, blur, reset],\n );\n\n const canSubmit = !!segments.length || completedParams.length > 0;\n\n const handleSubmit = useCallback(() => {\n if (!canSubmit) return;\n const text = getPlainText();\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, getPlainText]);\n\n handleSubmitRef.current = handleSubmit;\n\n const handleWrapperClick = useCallback(\n (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 focus();\n },\n [focus],\n );\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 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 {...editorProps} className={styles.input} data-aia-input=\"\" />\n {showInlinePills && (isLoading || suggestionPills.length > 0) && (\n <span\n ref={pillContainerRef}\n className={styles.pillListContainer}\n data-aia-pill-list-container=\"\"\n >\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-67791514\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-67791514\";\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: 4px;\n}\n\n.AIAutocomplete-module_editorArea_7rBWq {\n position: relative;\n flex: 1;\n min-width: 0;\n min-height: 26.6px;\n line-height: 26.6px;\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: 250;\n /* Align the text's inline box with the pill list (also vertical-align: middle)\n so they share a vertical center when pills stretch the line box to ~36px. */\n vertical-align: middle;\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 background-color: color-mix(in srgb, var(--aia-edit-outline, currentColor) 20%, transparent);\n border-radius: 6px;\n padding: 2px 3px;\n /* Pull surrounding inline text back so the wider/taller fill doesn't shove\n the rest of the line — only the visible background grows. */\n margin: 0 -1.5px;\n caret-color: transparent;\n}\n\n/* In re-edit mode the caret is parked just *before* the bold strong (see\n useContentEditableEditor.ts) — that means it sits in the parent .input, not\n inside the strong, so the rule above doesn't hide it. Use :has() to hide\n the caret on the whole editor while any completed param is selected. */\n.AIAutocomplete-module_input_IW-P-:has(strong[class~=\"magicx-aia-segment--editing\"]) {\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}\n\n.AIAutocomplete-module_pillListContainer_h92IA {\n display: inline;\n margin-left: 8px;\n}\n\n.AIAutocomplete-module_pillListContainer_h92IA:empty,\n.AIAutocomplete-module_pillListContainer_h92IA[data-aia-pill-wrapped] {\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 a newly promoted completed param. The shared renderer\n (core/render/renderEditable.ts) stamps the global class names below onto\n the just-added <strong>; we match them via [class~=] to bypass CSS Modules'\n hashing — same trick as the editing-outline rule above. */\n:where(.AIAutocomplete-module_input_IW-P-) strong[class~=\"magicx-aia-shimmer-revealed\"] {\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:where(.AIAutocomplete-module_input_IW-P-) strong[class~=\"magicx-aia-shimmer-sweep\"] {\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\",\"textShimmer\":\"AIAutocomplete-module_textShimmer_eCLdq\"};","if (typeof document !== \"undefined\" && !document.getElementById(\"ac-style-3819c762\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-3819c762\";\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 3px 27px;\n overflow-x: auto;\n overflow-y: hidden;\n scrollbar-width: none;\n mask-image: linear-gradient(to right, #000 0, #000 calc(100% - 48px), transparent 100%);\n -webkit-mask-image: linear-gradient(to right, #000 0, #000 calc(100% - 48px), transparent 100%);\n}\n\n.AIAutocompleteDropdown-module_pillBar_pwTXe::-webkit-scrollbar {\n display: none;\n}\n\n/* --- Fallback loading skeleton (only when no pills/options are cached) --- */\n.AIAutocompleteDropdown-module_skeletonBars_HVr9C {\n display: flex;\n flex-direction: column;\n gap: 20px;\n padding: 25px;\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\",\"skeletonBars\":\"AIAutocompleteDropdown-module_skeletonBars_HVr9C\",\"skeletonBar\":\"AIAutocompleteDropdown-module_skeletonBar_O3xIx\",\"aiaSkeletonPulse\":\"AIAutocompleteDropdown-module_aiaSkeletonPulse_G8W7q\"};","if (typeof document !== \"undefined\" && !document.getElementById(\"ac-style-0fcb7940\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-0fcb7940\";\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}\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/* Loading skeleton — preserves the pill's exact box (same width and height)\n and just hides the text. The pill's native background acts as the visible\n shape; the pulse provides the shimmer. */\n.PillList-module_skeleton_Lp8x6 {\n pointer-events: none;\n cursor: default;\n color: transparent;\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.55);\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 /**\n * When true, the rendered pills become non-interactive shimmering skeletons.\n * Real pills (with their text) are rendered when provided so widths/positions\n * match the previous state; when `pills` is empty, fixed-width fallback\n * placeholders are rendered instead.\n */\n loading?: boolean;\n}\n\nconst FALLBACK_SKELETON_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 && pills.length === 0) {\n return (\n <span className={styles.list} data-aia-pill-list-loading=\"\">\n {FALLBACK_SKELETON_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} data-aia-pill-list-loading={loading ? \"\" : undefined}>\n {pills.map((pill, i) => (\n <button\n key={`${pill.type}-${pill.text}`}\n type=\"button\"\n data-aia-pill=\"\"\n data-aia-loading={loading ? \"\" : undefined}\n tabIndex={-1}\n contentEditable={false}\n suppressContentEditableWarning\n className={`${styles.pill} ${rounded ? styles.rounded : \"\"} ${i === activePillIndex && !loading ? styles.active : \"\"} ${loading ? styles.skeleton : \"\"}`}\n style={{ opacity: getPillOpacity(i) }}\n onMouseDown={(e) => e.preventDefault()}\n onClick={loading ? undefined : () => onSelectPill(i)}\n disabled={loading}\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 loading?: boolean;\n}\n\nexport function SuggestionGrid({\n options,\n activeIndex,\n onSelect,\n onHighlight,\n listboxId,\n loading,\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 loading={loading}\n />\n ))}\n </div>\n </div>\n );\n}\n","if (typeof document !== \"undefined\" && !document.getElementById(\"ac-style-ff33a0ab\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-ff33a0ab\";\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 loading?: boolean;\n}\n\nexport function SuggestionItem({\n option,\n isHighlighted,\n onSelect,\n onHighlight,\n id,\n loading,\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 (loading || !option.is_tappable || pressed) return;\n setPressed(true);\n onSelect(option);\n clearTimeout(timerRef.current);\n timerRef.current = setTimeout(() => setPressed(false), 500);\n };\n\n const className = [\n styles.item,\n isHighlighted && !loading ? 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 data-aia-loading={loading ? \"\" : undefined}\n aria-selected={isHighlighted}\n className={className}\n tabIndex={loading || !option.is_tappable ? -1 : 0}\n onClick={handleSelect}\n onKeyDown={(e) => {\n if (!loading && option.is_tappable && (e.key === \"Enter\" || e.key === \" \")) {\n e.preventDefault();\n handleSelect();\n }\n }}\n onMouseEnter={!loading && option.is_tappable ? onHighlight : undefined}\n >\n <div className={styles.streaks} />\n <div className={styles.streaksVert} />\n <span className={styles.content}>\n <span className={styles.text}>\n {option.icon ? `${option.icon} ${option.text}` : option.text}\n </span>\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-82820da7\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-82820da7\";\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 font-weight: 250;\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 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}\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}\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/* Loading state — preserve the row's exact dimensions. The content stays an\n inline span so the line box and padding match the non-loading state byte\n for byte. Just hide the text and apply a background as a skeleton bar; the\n pulse provides the shimmer. */\n.SuggestionItem-module_item_d4vpD[data-aia-loading] {\n cursor: default;\n animation: SuggestionItem-module_skeletonPulse_plvdD 1.4s ease-in-out infinite;\n}\n\n/* Skeleton fill is on the inner text span (a true inline element) so multi-\n line options wrap into one skeleton bar per line. The outer .content is a\n flex item — blockified by spec — so painting the background there would\n collapse all lines into one tall rectangle. \\`box-decoration-break: clone\\`\n makes the radius render cleanly on each line bar. */\n.SuggestionItem-module_item_d4vpD[data-aia-loading] .SuggestionItem-module_text_yqoh9 {\n color: transparent;\n background: var(--aia-skeleton-bg, var(--aia-pill-bg, rgba(189, 189, 189, 0.51)));\n border-radius: 999px;\n -webkit-box-decoration-break: clone;\n box-decoration-break: clone;\n}\n\n.SuggestionItem-module_item_d4vpD[data-aia-loading] .SuggestionItem-module_tag_e3Fwe {\n display: none;\n}\n\n@keyframes SuggestionItem-module_skeletonPulse_plvdD {\n 0%,\n 100% {\n filter: brightness(1);\n }\n 50% {\n filter: brightness(0.55);\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\",\"skeletonPulse\":\"SuggestionItem-module_skeletonPulse_plvdD\",\"text\":\"SuggestionItem-module_text_yqoh9\"};","import styles from \"./AIAutocompleteDropdown.module.css\";\nimport { PillList } from \"./components/PillList\";\nimport { SuggestionGrid } from \"./components/SuggestionGrid\";\nimport type { AIAutocompleteDropdownProps } from \"./types\";\n\nconst FALLBACK_SKELETON_BAR_WIDTHS = [159, 119, 164];\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 showsPills = showPills && pills && pills.length > 0 && onPillClick;\n const showsOptions = options.length > 0;\n // Guarantee at least one option bar during loading — if the cached state\n // had no options, render the fallback skeleton bars regardless of whether\n // pills are present, so the dropdown never shows pills with an empty body.\n const showsFallbackSkeleton = isLoading && !showsOptions;\n const isVisible = isOpen && (showsOptions || showsPills || isLoading);\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 {showPills && pills && pills.length > 0 && onPillClick && (\n <div className={styles.pillBar} data-aia-pillbar=\"\">\n <PillList\n pills={pills}\n activePillIndex={0}\n onSelectPill={onPillClick}\n rounded\n loading={isLoading}\n />\n </div>\n )}\n {showPills && (!pills || pills.length === 0) && isLoading && (\n <div className={styles.pillBar} data-aia-pillbar=\"\">\n <PillList pills={[]} activePillIndex={0} onSelectPill={() => {}} rounded loading />\n </div>\n )}\n {showsOptions && (\n <SuggestionGrid\n options={options}\n activeIndex={activeIndex}\n onSelect={onSelect}\n onHighlight={onHighlight}\n listboxId={id}\n loading={isLoading}\n />\n )}\n {showsFallbackSkeleton && (\n <div className={styles.skeletonBars} data-aia-skeleton-bars=\"\">\n {FALLBACK_SKELETON_BAR_WIDTHS.map((w) => (\n <span key={`bar-${w}`} className={styles.skeletonBar} style={{ width: w }} />\n ))}\n </div>\n )}\n </div>\n );\n}\n","if (typeof document !== \"undefined\" && !document.getElementById(\"ac-style-0ae03977\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-0ae03977\";\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/*\n * Library-scoped box-sizing reset. The SDK's pill / option / wrapper styles\n * mix explicit dimensions with padding (e.g. .magicx-aia-pill has height:36px\n * + padding:13px) and were authored assuming \\`border-box\\`. In consumer apps\n * without a global \\`* { box-sizing: border-box }\\` reset the pill rendered\n * ~62px tall instead of 36px. Scoping the reset to \\`.magicx-aia\\` descendants\n * keeps the library self-contained without leaking onto consumer markup.\n */\n:where(.magicx-aia, .magicx-aia *, .magicx-aia *::before, .magicx-aia *::after) {\n box-sizing: border-box;\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: #4f4f4f;\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: #b0b0b0;\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: 13px 27px 13px 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 AIAutocomplete as CoreAIAutocomplete,\n type CoreState,\n type Suggestion,\n type SuggestionOption,\n} from \"@magicx-eng/ai-autocomplete-vanilla\";\nimport {\n type ChangeEvent,\n type KeyboardEvent,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport type { UseAIAutocompleteOptions, UseAIAutocompleteReturn } from \"../types\";\n\n/**\n * Pre-mount / SSR fallback. Identical shape to the post-mount CoreState so\n * the hook's return is single-shaped — no `if (!instance) return ...` branch.\n * `isLoading: true` matches the historical SSR bail-out: consumers using\n * `isLoading` to render a skeleton see one on the first paint instead of a\n * flash of blank content while the mount effect creates the core instance.\n */\nconst EMPTY_STATE: CoreState = {\n text: \"\",\n completedParams: [],\n suggestions: [],\n activeDropdownIndex: -1,\n newParamId: null,\n isLoading: true,\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 inSelectionAnimation: false,\n};\n\ninterface CoreActions {\n handleTextChange: (value: string) => void;\n handleKeyDown: (e: KeyboardEvent<HTMLElement> | globalThis.KeyboardEvent) => void;\n setFocused: (focused: boolean) => void;\n startEditingParam: (paramId: string) => void;\n exitEditMode: () => void;\n handleCaretAfterInput: (offset: number | null) => void;\n handleCaretMove: (offset: number | null) => void;\n replaceEditingRange: (replacement: string) => boolean;\n setActivePill: (index: number) => void;\n removeLastParam: () => void;\n clearNewParamId: () => void;\n reset: () => void;\n selectOption: (option: SuggestionOption) => void;\n setActiveDropdownIndex: (index: number) => void;\n handleFocus: () => void;\n handleBlur: () => void;\n}\n\nexport function useAIAutocomplete({\n onSubmit,\n onError,\n optionOverrides,\n maskCompletedText,\n apiConfig,\n columns = 2,\n dropdownTrigger,\n optionsPosition,\n closeDropdownOnBlur,\n showNonTappableOptions,\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 caller-supplied callbacks. The CoreAIAutocomplete instance is\n // mount-only (created once); these refs let the stable proxy callbacks\n // inside it pick up the latest props on every render.\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 optionsPosition,\n closeDropdownOnBlur,\n showNonTappableOptions,\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 // Sync controlled value\n useEffect(() => {\n if (controlledValue !== undefined) instanceRef.current?.setValue(controlledValue);\n }, [controlledValue]);\n\n // Sync controlled params\n useEffect(() => {\n if (controlledParams !== undefined) instanceRef.current?.setCompletedParams(controlledParams);\n }, [controlledParams]);\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 instanceRef.current?.update({\n apiConfig,\n optionOverrides,\n dropdownTrigger,\n optionsPosition,\n closeDropdownOnBlur,\n showNonTappableOptions,\n });\n }, [\n apiConfigJson,\n overridesVersion.current,\n dropdownTrigger,\n optionsPosition,\n closeDropdownOnBlur,\n showNonTappableOptions,\n ]);\n\n // Single stable action surface. Built once via the useRef-with-null-init\n // pattern (the idiomatic \"create once, never recreate\" idiom in React — see\n // https://react.dev/reference/react/useRef). Every entry forwards to the\n // current core instance via `instanceRef.current` so the closure picks up\n // the live instance even though the actions object itself never changes.\n const actionsRef = useRef<CoreActions | null>(null);\n if (actionsRef.current === null) {\n actionsRef.current = {\n handleTextChange: (value) => instanceRef.current?.handleTextChange(value),\n handleKeyDown: (e) => {\n const native = \"nativeEvent\" in e ? e.nativeEvent : e;\n instanceRef.current?.handleKeyDown(native);\n },\n setFocused: (focused) => instanceRef.current?.setFocused(focused),\n startEditingParam: (paramId) => instanceRef.current?.startEditingParam(paramId),\n exitEditMode: () => instanceRef.current?.exitEditMode(),\n handleCaretAfterInput: (offset) => instanceRef.current?.handleCaretAfterInput(offset),\n handleCaretMove: (offset) => instanceRef.current?.handleCaretMove(offset),\n replaceEditingRange: (replacement) =>\n instanceRef.current?.replaceEditingRange(replacement) ?? false,\n setActivePill: (index) => instanceRef.current?.setActivePill(index),\n removeLastParam: () => instanceRef.current?.removeLastParam(),\n clearNewParamId: () => instanceRef.current?.clearNewParamId(),\n reset: () => instanceRef.current?.reset(),\n selectOption: (option) => instanceRef.current?.selectOption(option),\n setActiveDropdownIndex: (index) => instanceRef.current?.setActiveDropdownIndex(index),\n handleFocus: () => instanceRef.current?.setFocused(true),\n handleBlur: () => instanceRef.current?.setFocused(false),\n };\n }\n const actions = actionsRef.current;\n\n // textarea-specific adapter — capitalizes the first character on first\n // keystroke. Kept separate from `actions.handleTextChange` because the\n // capitalization rule belongs to the textarea host, not the core.\n const handleChange = useCallback((e: ChangeEvent<HTMLTextAreaElement>) => {\n const raw = e.target.value;\n const shouldCapitalize =\n raw.length > 0 &&\n !(e.nativeEvent as InputEvent)?.isComposing &&\n raw[0] !== raw[0].toUpperCase();\n const newValue = shouldCapitalize ? raw[0].toUpperCase() + raw.slice(1) : raw;\n instanceRef.current?.handleTextChange(newValue);\n }, []);\n\n const handleKeyDownTextarea = useCallback((e: KeyboardEvent<HTMLTextAreaElement>) => {\n instanceRef.current?.handleKeyDown(e.nativeEvent);\n }, []);\n\n // Snapshot the live instance + state for this render.\n const instance = instanceRef.current;\n const state = coreState ?? EMPTY_STATE;\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 listboxId = instance?.listboxId ?? \"\";\n\n const activeDescendantId =\n state.activeDropdownIndex >= 0 && instance\n ? `${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 // UI-visible loading — suppressed during the post-select streak animation\n // and during re-edit (cached options remain visible there). Pre-mount we\n // report loading=true so SSR / first-paint consumers render a skeleton\n // instead of a flash of blank content while the mount effect runs.\n const uiLoading =\n !instance || (state.isLoading && !state.editingParam && !state.inSelectionAnimation);\n\n return {\n completedParams,\n suggestionPills: actionableSuggestions,\n setActivePill: actions.setActivePill,\n removeLastParam: actions.removeLastParam,\n segments: state.segments,\n newParamId: state.newParamId,\n clearNewParamId: actions.clearNewParamId,\n suggestions: state.suggestions,\n activeIndex: state.activeDropdownIndex,\n isReady: state.isReady,\n isLoading: uiLoading,\n isFocused: state.isFocused,\n isDropdownOpen: state.isDropdownOpen,\n placeholderText: state.placeholderText,\n listboxId,\n error: state.error,\n handleTextChange: actions.handleTextChange,\n handleKeyDown: actions.handleKeyDown,\n setFocused: actions.setFocused,\n editingParam,\n editingAnchor: state.editingAnchor,\n caretOffset: state.caretOffset,\n startEditingParam: actions.startEditingParam,\n exitEditMode: actions.exitEditMode,\n handleCaretAfterInput: actions.handleCaretAfterInput,\n handleCaretMove: actions.handleCaretMove,\n replaceEditingRange: actions.replaceEditingRange,\n inputProps: {\n value: text,\n placeholder: state.placeholderText || undefined,\n onChange: handleChange,\n onKeyDown: handleKeyDownTextarea,\n onFocus: actions.handleFocus,\n onBlur: actions.handleBlur,\n role: \"combobox\" as const,\n \"aria-expanded\": state.isDropdownOpen,\n \"aria-activedescendant\": activeDescendantId,\n \"aria-autocomplete\": \"list\" as const,\n \"aria-controls\": listboxId,\n },\n reset: actions.reset,\n dropdownProps: {\n suggestions: dropdownActivePill\n ? [{ ...dropdownActivePill, options: state.filteredOptions }]\n : [],\n activeIndex: state.activeDropdownIndex,\n onSelect: actions.selectOption,\n onHighlight: actions.setActiveDropdownIndex,\n isOpen: state.isDropdownOpen,\n id: listboxId,\n pills: dropdownPills,\n onPillClick: actions.setActivePill,\n isLoading: uiLoading,\n },\n };\n}\n","import {\n type CompletedParamState,\n extractPlainText,\n getCursorOffset,\n plainTextLength,\n renderEditableContent,\n type Segment,\n setCursorOffset,\n} from \"@magicx-eng/ai-autocomplete-vanilla\";\nimport {\n type ClipboardEvent as ReactClipboardEvent,\n type KeyboardEvent as ReactKeyboardEvent,\n useCallback,\n useEffect,\n useLayoutEffect,\n useRef,\n} from \"react\";\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 interface UseContentEditableEditorOptions {\n /** Derived segments (text + bold completed-param runs) for the editor body. */\n segments: readonly Segment[];\n /** The most recently promoted param — shimmer + post-promote refocus key. */\n newParamId: string | null;\n /** The bold param currently being re-edited (or null). */\n editingParam: CompletedParamState | null;\n /** Plain-text offset where re-edit started; caret parks here on entry. */\n editingAnchor: number | null;\n /** Live caret offset within the editor, used by post-promote refocus. */\n caretOffset: number | null;\n /** Server-suggested placeholder (rendered via ::before when empty). */\n placeholderText: string;\n /** Whether the editor currently has focus — passes through to segment renderer. */\n isFocused: boolean;\n /** ARIA `aria-expanded` value for the input. */\n isDropdownOpen: boolean;\n /** ARIA `aria-controls` value pointing at the listbox. */\n listboxId: string;\n /** ARIA `aria-activedescendant` value pointing at the highlighted option (or undefined). */\n activeDescendantId: string | undefined;\n /** Focus the editor on mount (Tier 1 default). */\n autoFocus: boolean;\n /** Forwarded to the core whenever the plain-text content changes. */\n handleTextChange: (value: string) => void;\n /** Forwarded to the core for keyboard handling. */\n handleKeyDown: (e: ReactKeyboardEvent<HTMLElement> | globalThis.KeyboardEvent) => void;\n /** Forwarded to the core after each input event (extends edit tail, etc.). */\n handleCaretAfterInput: (offset: number | null) => void;\n /** Forwarded to the core on selectionchange (exits re-edit when caret leaves). */\n handleCaretMove: (offset: number | null) => void;\n /** Forwarded to the core when the caret lands inside a bold param's strong. */\n startEditingParam: (id: string) => void;\n /** Forwarded to the core during a `beforeinput` — atomic re-edit replacement. */\n replaceEditingRange: (replacement: string) => boolean;\n /** Forwarded to the core on native focus/blur. */\n setFocused: (focused: boolean) => void;\n}\n\nexport interface UseContentEditableEditorReturn {\n inputRef: React.RefObject<HTMLDivElement>;\n // Spread onto the contentEditable element; consumer supplies className.\n editorProps: {\n ref: React.RefObject<HTMLDivElement>;\n contentEditable: boolean;\n suppressContentEditableWarning: true;\n tabIndex: 0;\n role: \"combobox\";\n \"aria-autocomplete\": \"list\";\n \"aria-haspopup\": \"listbox\";\n \"aria-controls\": string;\n \"aria-expanded\": boolean;\n \"aria-activedescendant\": string | undefined;\n spellCheck: true;\n enterKeyHint: \"send\";\n onInput: () => void;\n onKeyDown: (e: ReactKeyboardEvent<HTMLDivElement>) => void;\n onCompositionStart: () => void;\n onCompositionEnd: () => void;\n onPaste: (e: ReactClipboardEvent<HTMLDivElement>) => void;\n onFocus: () => void;\n onBlur: () => void;\n };\n /** Current plain-text content of the editor (used by submit). */\n getPlainText: () => string;\n /** Imperative focus / blur (used by the parent's imperative handle). */\n focus: () => void;\n blur: () => void;\n}\n\n/**\n * Owns every concern that's specific to running the autocomplete on top of a\n * contentEditable host: composition state, caret tracking, selectionchange,\n * `beforeinput` interception, paste sanitization, plaintext-only feature\n * detection, segment rendering, post-promote refocus, and re-edit caret park.\n *\n * The hook stays React-agnostic above the contentEditable adapter — see\n * `core/render/renderEditable.ts` for the underlying DOM mutations. Callers\n * spread `editorProps` onto a `<div>` (className is theirs to provide).\n */\nexport function useContentEditableEditor(\n opts: UseContentEditableEditorOptions,\n): UseContentEditableEditorReturn {\n const {\n segments,\n newParamId,\n editingParam,\n editingAnchor,\n caretOffset,\n placeholderText,\n isFocused,\n isDropdownOpen,\n listboxId,\n activeDescendantId,\n autoFocus,\n handleTextChange,\n handleKeyDown,\n handleCaretAfterInput,\n handleCaretMove,\n startEditingParam,\n replaceEditingRange,\n setFocused,\n } = opts;\n\n const inputRef = useRef<HTMLDivElement>(null);\n const composingRef = useRef(false);\n const lastSeenParamIdRef = useRef(\"\");\n const lastEditingIdRef = useRef(\"\");\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 caretOffsetRef.current = caretOffset;\n\n // Auto-focus on mount once the host element is mounted.\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 // `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 // MUST run before the post-promote refocus + re-edit caret park effects\n // below — keep this declaration order.\n useLayoutEffect(() => {\n const el = inputRef.current;\n if (!el) return;\n renderEditableContent({\n input: el,\n segments: segments as Segment[],\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 of the just-promoted segment. Mirrors the\n // vanilla core's `justSelected` logic in renderInput.ts.\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 after\n // the new param's trailing space, so use it. Read via ref so the effect\n // 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 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 attach\n // 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: ReactClipboardEvent<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 handleFocus = useCallback(() => setFocused(true), [setFocused]);\n const handleBlur = useCallback(() => setFocused(false), [setFocused]);\n\n const focus = useCallback(() => inputRef.current?.focus(), []);\n const blur = useCallback(() => inputRef.current?.blur(), []);\n const getPlainText = useCallback(() => {\n const el = inputRef.current;\n return el ? extractPlainText(el) : \"\";\n }, []);\n\n const ceMode = supportsPlaintextOnly() ? \"plaintext-only\" : \"true\";\n\n return {\n inputRef,\n editorProps: {\n ref: inputRef,\n contentEditable: ceMode as unknown as boolean,\n suppressContentEditableWarning: true,\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: true,\n enterKeyHint: \"send\",\n onInput: handleInputEvent,\n onKeyDown: handleKeyDownReact,\n onCompositionStart: handleCompositionStart,\n onCompositionEnd: handleCompositionEnd,\n onPaste: handlePaste,\n onFocus: handleFocus,\n onBlur: handleBlur,\n },\n getPlainText,\n focus,\n blur,\n };\n}\n"],"mappings":"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","names":["index_exports","__export","AIAutocomplete","AIAutocompleteDropdown","useAIAutocomplete","__toCommonJS","import_react","s","AIAutocomplete_module_css_default","s","AIAutocompleteDropdown_module_css_default","s","PillList_module_css_default","import_jsx_runtime","FALLBACK_SKELETON_WIDTHS","getPillOpacity","index","PillList","pills","activePillIndex","onSelectPill","rounded","loading","PillList_module_css_default","w","i","pill","e","import_react","s","SuggestionGrid_module_css_default","import_react","s","SuggestionItem_module_css_default","import_jsx_runtime","SuggestionItem","option","isHighlighted","onSelect","onHighlight","id","loading","pressed","setPressed","timerRef","handleSelect","className","SuggestionItem_module_css_default","e","import_jsx_runtime","SuggestionGrid","options","activeIndex","onSelect","onHighlight","listboxId","loading","gridRef","hasBottomOverflow","setHasBottomOverflow","el","update","resizeObserver","SuggestionGrid_module_css_default","option","i","SuggestionItem","import_jsx_runtime","FALLBACK_SKELETON_BAR_WIDTHS","AIAutocompleteDropdown","suggestions","activeIndex","onSelect","onHighlight","isOpen","id","className","pills","onPillClick","showPills","isLoading","options","showsPills","showsOptions","showsFallbackSkeleton","isVisible","AIAutocompleteDropdown_module_css_default","e","PillList","SuggestionGrid","w","s","import_ai_autocomplete_vanilla","import_ai_autocomplete_vanilla","import_react","EMPTY_STATE","useAIAutocomplete","onSubmit","onError","optionOverrides","maskCompletedText","apiConfig","columns","dropdownTrigger","optionsPosition","closeDropdownOnBlur","showNonTappableOptions","onFocus","onBlur","controlledValue","controlledParams","onChangeProp","onParamsChange","source","setCursor","instanceRef","coreState","setCoreState","onSubmitRef","onErrorRef","onChangeRef","onParamsChangeRef","onFocusRef","onBlurRef","setCursorRef","instance","CoreAIAutocomplete","args","offset","unsub","state","apiConfigJson","prevOverridesRef","overridesVersion","prev","next","prevKeys","nextKeys","k","actionsRef","value","e","native","focused","paramId","replacement","index","option","actions","handleChange","raw","newValue","handleKeyDownTextarea","text","completedParams","actionableSuggestions","activeSuggestion","listboxId","activeDescendantId","editingParam","dropdownPill","dropdownActivePill","dropdownPills","uiLoading","import_ai_autocomplete_vanilla","import_react","plaintextOnlyCache","supportsPlaintextOnly","probe","useContentEditableEditor","opts","segments","newParamId","editingParam","editingAnchor","caretOffset","placeholderText","isFocused","isDropdownOpen","listboxId","activeDescendantId","autoFocus","handleTextChange","handleKeyDown","handleCaretAfterInput","handleCaretMove","startEditingParam","replaceEditingRange","setFocused","inputRef","composingRef","lastSeenParamIdRef","lastEditingIdRef","caretOffsetRef","lastInputAtRef","el","doc","onSelectionChange","sel","anchor","enclosing","previous","current","desired","fireInput","raw","next","handleInputEvent","onBeforeInput","e","inputEvent","t","replacement","handleCompositionStart","handleCompositionEnd","handlePaste","text","range","node","handleKeyDownReact","handleFocus","handleBlur","focus","blur","getPlainText","ceMode","import_jsx_runtime","resolveInitialMode","mode","AIAutocomplete","onSubmit","onError","optionOverrides","maskCompletedText","className","apiConfig","columns","pillPlacement","optionsPosition","animations","dropdownTrigger","closeDropdownOnBlur","showNonTappableOptions","autoFocus","onFocus","onBlur","value","controlledParams","onChangeProp","onParamsChange","submitButton","ref","containerRef","pillContainerRef","handleSubmitRef","modeControllerRef","editorInputRefHolder","el","handleSetCursor","offset","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","activeDescendantId","inputRef","editorProps","focus","blur","getPlainText","useContentEditableEditor","container","editor","update","inner","cRect","eRect","ro","m","canSubmit","handleSubmit","text","rawQuery","finalParams","handleWrapperClick","e","showInlinePills","showDropdownPills","AIAutocomplete_module_css_default","AIAutocompleteDropdown","PillList"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/AIAutocomplete.tsx","css-module:/home/runner/work/ai-autocomplete-sdk-js/ai-autocomplete-sdk-js/packages/react/src/AIAutocomplete.module.css.js","css-module:/home/runner/work/ai-autocomplete-sdk-js/ai-autocomplete-sdk-js/packages/react/src/AIAutocompleteDropdown.module.css.js","../src/components/DropdownFooter.tsx","plain-css:/home/runner/work/ai-autocomplete-sdk-js/ai-autocomplete-sdk-js/packages/react/src/layout/Cluster.css.js","../src/layout/Cluster.tsx","css-module:/home/runner/work/ai-autocomplete-sdk-js/ai-autocomplete-sdk-js/packages/react/src/components/DropdownFooter.module.css.js","css-module:/home/runner/work/ai-autocomplete-sdk-js/ai-autocomplete-sdk-js/packages/react/src/components/Pill.module.css.js","../src/components/Pill.tsx","css-module:/home/runner/work/ai-autocomplete-sdk-js/ai-autocomplete-sdk-js/packages/react/src/components/PillList.module.css.js","../src/components/PillList.tsx","../src/layout/Grid.tsx","plain-css:/home/runner/work/ai-autocomplete-sdk-js/ai-autocomplete-sdk-js/packages/react/src/layout/Grid.css.js","../src/components/SuggestionItem.tsx","css-module:/home/runner/work/ai-autocomplete-sdk-js/ai-autocomplete-sdk-js/packages/react/src/components/SuggestionItem.module.css.js","../src/components/SuggestionGrid.tsx","plain-css:/home/runner/work/ai-autocomplete-sdk-js/ai-autocomplete-sdk-js/packages/react/src/layout/Stack.css.js","../src/layout/Stack.tsx","../src/AIAutocompleteDropdown.tsx","plain-css:/home/runner/work/ai-autocomplete-sdk-js/ai-autocomplete-sdk-js/packages/react/src/appearance.css.js","css-module:/home/runner/work/ai-autocomplete-sdk-js/ai-autocomplete-sdk-js/packages/react/src/components/SubmitButton.module.css.js","../src/components/SubmitButton.tsx","../src/hooks/useAIAutocomplete.ts","../src/hooks/useContentEditableEditor.ts"],"sourcesContent":["export { AIAutocomplete } from \"./AIAutocomplete\";\nexport { AIAutocompleteDropdown } from \"./AIAutocompleteDropdown\";\nexport { useAIAutocomplete } from \"./hooks/useAIAutocomplete\";\nexport type {\n AccessTokenConfig,\n AccessTokenResult,\n AIAutocompleteDropdownProps,\n AIAutocompleteHandle,\n AIAutocompleteProps,\n APIConfig,\n APIKeyConfig,\n AppearanceMode,\n AutocompleteResult,\n CompletedParam,\n CompletedParamState,\n OptionOverrides,\n Segment,\n Suggestion,\n SuggestionOption,\n TaskKind,\n UseAIAutocompleteOptions,\n UseAIAutocompleteReturn,\n} from \"./types\";\n","import {\n forwardRef,\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 {\n type AppearanceMode,\n type AutocompleteResult,\n buildQuery,\n ModeController,\n setCursorOffset,\n} from \"@magicx-eng/ai-autocomplete-vanilla\";\nimport { PillList } from \"./components/PillList\";\nimport { SubmitButton } from \"./components/SubmitButton\";\nimport { useAIAutocomplete } from \"./hooks/useAIAutocomplete\";\nimport { useContentEditableEditor } from \"./hooks/useContentEditableEditor\";\nimport type { AIAutocompleteHandle, AIAutocompleteProps } from \"./types\";\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 showNonTappableOptions,\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 pillContainerRef = useRef<HTMLSpanElement>(null);\n const handleSubmitRef = useRef<(result: AutocompleteResult) => void>(() => {});\n const modeControllerRef = useRef<ModeController | null>(null);\n // Holds the editor's input *ref object* (not its current value) so the\n // setCursor callback — defined before useContentEditableEditor runs — can\n // dereference the live DOM element at call time without a one-render lag.\n const editorInputRefHolder = useRef<React.RefObject<HTMLDivElement> | null>(null);\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 = editorInputRefHolder.current?.current;\n if (!el) return;\n el.focus();\n 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 optionsPosition,\n closeDropdownOnBlur,\n showNonTappableOptions,\n onFocus,\n onBlur,\n value,\n completedParams: controlledParams,\n onChange: onChangeProp,\n onParamsChange,\n source: \"full-sdk\",\n setCursor: handleSetCursor,\n });\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 const activeDescendantId = activeIndex >= 0 ? `${listboxId}-option-${activeIndex}` : undefined;\n\n const { inputRef, editorProps, focus, blur, getPlainText } = useContentEditableEditor({\n segments,\n newParamId,\n editingParam,\n editingAnchor,\n caretOffset,\n placeholderText,\n isFocused,\n isDropdownOpen,\n listboxId,\n activeDescendantId,\n autoFocus,\n handleTextChange,\n handleKeyDown,\n handleCaretAfterInput,\n handleCaretMove,\n startEditingParam,\n replaceEditingRange,\n setFocused,\n });\n\n // Wire the holder to the hook's ref. The ref *object* is stable across\n // renders, so this assignment is idempotent and reaches the live DOM\n // element via `.current` without snapshotting null on the first render.\n editorInputRefHolder.current = inputRef;\n\n // The pill list sits inline-adjacent to the editor and carries an 8px\n // left margin so it doesn't butt against the editor's text. When the\n // editor's text fills its line and the pill list wraps to a new line,\n // that margin becomes a stray indent at the start of the wrapped line —\n // detect that case and drop the margin via a data attribute the CSS\n // keys off. The wrap detection (pill row's top vs editor's bottom)\n // already handles the placeholder-only case correctly: the placeholder\n // still occupies the editor's line box, so pills sitting beside it are\n // NOT wrapped and the margin stays.\n // biome-ignore lint/correctness/useExhaustiveDependencies: segments/suggestionPills/isLoading are intentional re-measure triggers, not reads\n useLayoutEffect(() => {\n const container = pillContainerRef.current;\n const editor = inputRef.current;\n if (!container || !editor) return;\n\n const update = () => {\n const inner = container.firstElementChild as HTMLElement | null;\n if (!inner) return;\n const cRect = inner.getBoundingClientRect();\n const eRect = editor.getBoundingClientRect();\n const wrapped = cRect.top >= eRect.bottom - 2;\n if (wrapped) container.setAttribute(\"data-aia-pill-wrapped\", \"\");\n else container.removeAttribute(\"data-aia-pill-wrapped\");\n };\n\n update();\n const ro = new ResizeObserver(update);\n ro.observe(editor);\n return () => ro.disconnect();\n }, [segments, suggestionPills.length, isLoading, inputRef]);\n\n useImperativeHandle(\n ref,\n () => ({\n focus,\n blur,\n reset,\n setMode: (m) => modeControllerRef.current?.setMode(m),\n }),\n [focus, blur, reset],\n );\n\n const canSubmit = !!segments.length || completedParams.length > 0;\n\n const handleSubmit = useCallback(() => {\n if (!canSubmit) return;\n const text = getPlainText();\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, getPlainText]);\n\n handleSubmitRef.current = handleSubmit;\n\n const handleWrapperClick = useCallback(\n (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 focus();\n },\n [focus],\n );\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 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 {...editorProps} className={styles.input} data-aia-input=\"\" />\n {showInlinePills && (isLoading || suggestionPills.length > 0) && (\n <span\n ref={pillContainerRef}\n className={styles.pillListContainer}\n data-aia-pill-list-container=\"\"\n >\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 <SubmitButton disabled={!canSubmit} onClick={handleSubmit} />\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-67791514\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-67791514\";\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: 19px 15px 20px 25px;\n border: 1px solid var(--aia-border, #b0b0b0);\n border-radius: 30px;\n background: var(--aia-surface, #ffffff);\n overflow: hidden;\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.AIAutocomplete-module_editorArea_7rBWq {\n position: relative;\n flex: 1;\n min-width: 0;\n min-height: 26.6px;\n line-height: 26.6px;\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: 250;\n /* Align the text's inline box with the pill list (also vertical-align: middle)\n so they share a vertical center when pills stretch the line box to ~36px. */\n vertical-align: middle;\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 background-color: color-mix(in srgb, var(--aia-edit-outline, currentColor) 20%, transparent);\n border-radius: 6px;\n padding: 2px 3px;\n /* Pull surrounding inline text back so the wider/taller fill doesn't shove\n the rest of the line — only the visible background grows. */\n margin: 0 -1.5px;\n caret-color: transparent;\n}\n\n/* In re-edit mode the caret is parked just *before* the bold strong (see\n useContentEditableEditor.ts) — that means it sits in the parent .input, not\n inside the strong, so the rule above doesn't hide it. Use :has() to hide\n the caret on the whole editor while any completed param is selected. */\n.AIAutocomplete-module_input_IW-P-:has(strong[class~=\"magicx-aia-segment--editing\"]) {\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}\n\n.AIAutocomplete-module_pillListContainer_h92IA {\n display: inline;\n margin-left: 8px;\n}\n\n.AIAutocomplete-module_pillListContainer_h92IA:empty,\n.AIAutocomplete-module_pillListContainer_h92IA[data-aia-pill-wrapped] {\n margin-left: 0;\n}\n\n.AIAutocomplete-module_submitSlot_GhuCM {\n display: contents;\n}\n\n/* Text shimmer on a newly promoted completed param. The shared renderer\n (core/render/renderEditable.ts) stamps the global class names below onto\n the just-added <strong>; we match them via [class~=] to bypass CSS Modules'\n hashing — same trick as the editing-outline rule above. */\n:where(.AIAutocomplete-module_input_IW-P-) strong[class~=\"magicx-aia-shimmer-revealed\"] {\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:where(.AIAutocomplete-module_input_IW-P-) strong[class~=\"magicx-aia-shimmer-sweep\"] {\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\",\"submitSlot\":\"AIAutocomplete-module_submitSlot_GhuCM\",\"textShimmer\":\"AIAutocomplete-module_textShimmer_eCLdq\"};","if (typeof document !== \"undefined\" && !document.getElementById(\"ac-style-3819c762\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-3819c762\";\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 box-sizing: border-box;\n padding: 15px 0;\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 /* Solid surface is the default (matches the Figma components). Opt into the\n frosted-glass look with data-aia-surface=\"glass\". */\n background: var(--aia-surface, #ffffff);\n border: 1px solid var(--aia-border, #b0b0b0);\n border-radius: 25px;\n}\n\n.AIAutocompleteDropdown-module_dropdown_yz2KC[data-aia-surface=\"glass\"] {\n background: transparent;\n border-color: transparent;\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}\n\n.AIAutocompleteDropdown-module_visible_QCoXj {\n opacity: 1;\n pointer-events: auto;\n}\n\n/* The dropdown owns only vertical (15px) padding; each child insets its own\n 15px horizontally so option highlights can span the full dropdown width. */\n.AIAutocompleteDropdown-module_pillBar_pwTXe {\n padding: 0 15px;\n overflow-x: auto;\n overflow-y: hidden;\n scrollbar-width: none;\n mask-image: linear-gradient(to right, #000 0, #000 calc(100% - 48px), transparent 100%);\n -webkit-mask-image: linear-gradient(to right, #000 0, #000 calc(100% - 48px), transparent 100%);\n}\n\n.AIAutocompleteDropdown-module_pillBar_pwTXe::-webkit-scrollbar {\n display: none;\n}\n\n/* --- Fallback loading skeleton (only when no pills/options are cached) --- */\n.AIAutocompleteDropdown-module_skeletonBars_HVr9C {\n display: flex;\n flex-direction: column;\n gap: 20px;\n padding: 10px 15px;\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\",\"skeletonBars\":\"AIAutocompleteDropdown-module_skeletonBars_HVr9C\",\"skeletonBar\":\"AIAutocompleteDropdown-module_skeletonBar_O3xIx\",\"aiaSkeletonPulse\":\"AIAutocompleteDropdown-module_aiaSkeletonPulse_G8W7q\"};","import { getFooterHint } from \"@magicx-eng/ai-autocomplete-vanilla\";\nimport { Cluster } from \"../layout/Cluster\";\nimport styles from \"./DropdownFooter.module.css\";\n\ninterface DropdownFooterProps {\n /**\n * Whether the user has tabbed to highlight an option at some point. Drives the\n * footer hint together with `isOptionHighlighted` — see {@link getFooterHint}.\n */\n hasTabbedToHighlight?: boolean;\n /**\n * Whether an option is currently highlighted. Takes priority: when true the\n * hint reads \"enter to proceed\".\n */\n isOptionHighlighted?: boolean;\n}\n\n// Dropdown chrome: a keyboard hint on the left, AI-Autocomplete branding on the\n// right, separated from the options above by a hairline divider.\nexport function DropdownFooter({\n hasTabbedToHighlight = false,\n isOptionHighlighted = false,\n}: DropdownFooterProps) {\n const { key, hint } = getFooterHint(hasTabbedToHighlight, isOptionHighlighted);\n return (\n <footer className={styles.footer} data-aia-footer=\"\">\n <div className={styles.divider} />\n <Cluster justify=\"between\" noWrap>\n <Cluster gap=\"5px\" className={styles.hintGroup}>\n <kbd className={styles.key}>{key}</kbd>\n <span className={styles.hint}>{hint}</span>\n </Cluster>\n <a\n className={styles.brandLink}\n href=\"https://ai-autocomplete.com\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n <span className={styles.brand}>AI</span>\n <span className={styles.badge}>Autocomplete</span>\n </a>\n </Cluster>\n </footer>\n );\n}\n","if (typeof document !== \"undefined\" && !document.getElementById(\"ac-style-5259a217\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-5259a217\";\n s.textContent = `@layer layout {\n .aia-cluster {\n display: flex;\n flex-wrap: wrap;\n gap: var(--aia-cluster-gap, 0.5rem);\n }\n /* Inline-level variant — used when the cluster must sit inline (e.g. inside\n a contentEditable). Rendered on a <span> so it's valid inline content. */\n .aia-cluster[data-inline] {\n display: inline-flex;\n }\n .aia-cluster[data-nowrap] {\n flex-wrap: nowrap;\n }\n .aia-cluster[data-align=\"start\"] {\n align-items: start;\n }\n .aia-cluster[data-align=\"center\"] {\n align-items: center;\n }\n .aia-cluster[data-align=\"end\"] {\n align-items: end;\n }\n .aia-cluster[data-align=\"baseline\"] {\n align-items: baseline;\n }\n .aia-cluster[data-justify=\"start\"] {\n justify-content: start;\n }\n .aia-cluster[data-justify=\"center\"] {\n justify-content: center;\n }\n .aia-cluster[data-justify=\"end\"] {\n justify-content: end;\n }\n .aia-cluster[data-justify=\"between\"] {\n justify-content: space-between;\n }\n .aia-cluster[data-justify=\"around\"] {\n justify-content: space-around;\n }\n}\n`;\n document.head.appendChild(s);\n}\nexport {};","import type { ComponentPropsWithoutRef, CSSProperties, ReactNode } from \"react\";\nimport \"./Cluster.css\";\n\ninterface ClusterProps extends Omit<ComponentPropsWithoutRef<\"div\">, \"className\"> {\n /** Gap between children. Any CSS length. Defaults to `0.5rem`. */\n gap?: string;\n /** Cross-axis alignment. Defaults to `center`. */\n align?: \"start\" | \"center\" | \"end\" | \"baseline\";\n /** Main-axis distribution. Defaults to `start`. */\n justify?: \"start\" | \"center\" | \"end\" | \"between\" | \"around\";\n /** When true, the wrapper does NOT flex-wrap (single-row clusters). */\n noWrap?: boolean;\n /** Render as an inline-level `<span>` (inline-flex) instead of a block `<div>`. */\n inline?: boolean;\n className?: string;\n children: ReactNode;\n}\n\n// Horizontal layout primitive — wraps when out of room. `noWrap` for single-row clusters. Internal.\nexport function Cluster({\n gap,\n align = \"center\",\n justify = \"start\",\n noWrap = false,\n inline = false,\n className,\n children,\n ...rest\n}: ClusterProps) {\n const style = gap ? ({ \"--aia-cluster-gap\": gap } as CSSProperties) : undefined;\n const props = {\n className: className ? `aia-cluster ${className}` : \"aia-cluster\",\n \"data-align\": align,\n \"data-justify\": justify,\n \"data-nowrap\": noWrap || undefined,\n \"data-inline\": inline || undefined,\n style,\n ...rest,\n };\n if (inline) return <span {...props}>{children}</span>;\n return <div {...props}>{children}</div>;\n}\n","if (typeof document !== \"undefined\" && !document.getElementById(\"ac-style-56b0c577\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-56b0c577\";\n s.textContent = `/* The footer insets its own 15px horizontally (the dropdown only pads\n vertically), so the divider spans the full footer width yet still stays clear\n of the dropdown's rounded edges. */\n.DropdownFooter-module_footer_qQQ7x {\n display: flex;\n flex-direction: column;\n gap: 12px;\n padding: 0 15px;\n}\n\n.DropdownFooter-module_divider_FlX4C {\n border-top: 0.5px solid var(--aia-footer-divider, rgba(176, 176, 176, 0.4));\n}\n\n.DropdownFooter-module_hintGroup_ZzbPf {\n min-width: 0;\n}\n\n.DropdownFooter-module_brandLink_r4f3R {\n display: inline-flex;\n align-items: center;\n gap: 2px;\n text-decoration: none;\n cursor: pointer;\n transition: opacity 150ms ease-out;\n}\n\n.DropdownFooter-module_brandLink_r4f3R:hover {\n opacity: 0.7;\n}\n\n.DropdownFooter-module_key_Bz1H- {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 30px;\n height: 22px;\n padding: 2px 6px;\n border: 0.5px solid var(--aia-footer-hint-color, #505050);\n border-radius: 5px;\n font-family: inherit;\n font-size: 12px;\n line-height: 18px;\n color: var(--aia-footer-hint-color, #505050);\n}\n\n.DropdownFooter-module_hint_GKEOH {\n font-family: inherit;\n font-size: 12px;\n line-height: 18px;\n color: var(--aia-footer-hint-color, #505050);\n}\n\n.DropdownFooter-module_brand_Al-lR {\n font-family: inherit;\n font-size: 10px;\n line-height: 18px;\n color: var(--aia-footer-brand-color, #b0b0b0);\n}\n\n.DropdownFooter-module_badge_Fk9vg {\n display: inline-flex;\n align-items: center;\n height: 23px;\n padding: 2.5px 5.5px;\n border: 0.36px solid var(--aia-footer-badge-border, rgba(189, 189, 189, 0.51));\n border-radius: 999px;\n font-family: inherit;\n font-size: 10px;\n line-height: 18px;\n color: var(--aia-footer-brand-color, #b0b0b0);\n}\n`;\n document.head.appendChild(s);\n}\nexport default {\"footer\":\"DropdownFooter-module_footer_qQQ7x\",\"divider\":\"DropdownFooter-module_divider_FlX4C\",\"hintGroup\":\"DropdownFooter-module_hintGroup_ZzbPf\",\"brandLink\":\"DropdownFooter-module_brandLink_r4f3R\",\"key\":\"DropdownFooter-module_key_Bz1H-\",\"hint\":\"DropdownFooter-module_hint_GKEOH\",\"brand\":\"DropdownFooter-module_brand_Al-lR\",\"badge\":\"DropdownFooter-module_badge_Fk9vg\"};","if (typeof document !== \"undefined\" && !document.getElementById(\"ac-style-04fef8d6\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-04fef8d6\";\n s.textContent = `.Pill-module_pill_3Rkw- {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n height: 38px;\n padding: 10px 12px;\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)) 30%,\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: Pill-module_fadeIn_Bbqtz 400ms cubic-bezier(0.4, 0, 0.2, 1) forwards;\n}\n\n.Pill-module_rounded_6WMps {\n border-radius: 999px;\n}\n\n/* Loading skeleton — preserves the pill's exact box (same width and height)\n and just hides the text. The pill's native background acts as the visible\n shape; the pulse provides the shimmer. */\n.Pill-module_skeleton_-u9-j {\n pointer-events: none;\n cursor: default;\n color: transparent;\n animation: Pill-module_skeletonPulse_xHh-7 1.4s ease-in-out infinite;\n}\n\n@keyframes Pill-module_skeletonPulse_xHh-7 {\n 0%,\n 100% {\n filter: brightness(1);\n }\n 50% {\n filter: brightness(0.55);\n }\n}\n\n@keyframes Pill-module_fadeIn_Bbqtz {\n from {\n opacity: 0;\n }\n}\n`;\n document.head.appendChild(s);\n}\nexport default {\"pill\":\"Pill-module_pill_3Rkw-\",\"fadeIn\":\"Pill-module_fadeIn_Bbqtz\",\"rounded\":\"Pill-module_rounded_6WMps\",\"skeleton\":\"Pill-module_skeleton_-u9-j\",\"skeletonPulse\":\"Pill-module_skeletonPulse_xHh-7\"};","import type { MouseEvent } from \"react\";\nimport styles from \"./Pill.module.css\";\n\n/**\n * Visual emphasis tier for a pill. Mirrors a pill's position in the\n * upcoming-params sequence: `active` is the param being filled next;\n * `upcoming` and `disabled` are progressively de-emphasized.\n */\nexport type PillState = \"active\" | \"upcoming\" | \"disabled\";\n\n/** Opacity applied per state. Kept here so `PillList` skeletons stay in sync. */\nexport const PILL_OPACITY: Record<PillState, number> = {\n active: 1,\n upcoming: 0.4,\n disabled: 0.2,\n};\n\ninterface PillProps {\n /** Pill label text. */\n label: string;\n /** Visual emphasis tier (drives opacity). */\n state: PillState;\n /** Renders the selection outline (the pill at the active index). */\n selected?: boolean;\n /** Capsule shape (fully rounded). Default: false. */\n rounded?: boolean;\n /** Non-interactive shimmering skeleton. */\n loading?: boolean;\n onClick?: () => void;\n}\n\nexport function Pill({ label, state, selected, rounded, loading, onClick }: PillProps) {\n const className = [\n styles.pill,\n rounded ? styles.rounded : \"\",\n selected && !loading ? styles.active : \"\",\n loading ? styles.skeleton : \"\",\n ]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <button\n type=\"button\"\n data-aia-pill=\"\"\n data-aia-loading={loading ? \"\" : undefined}\n tabIndex={-1}\n contentEditable={false}\n suppressContentEditableWarning\n className={className}\n style={{ opacity: PILL_OPACITY[state] }}\n onMouseDown={(e: MouseEvent) => e.preventDefault()}\n onClick={loading ? undefined : onClick}\n disabled={loading}\n >\n {label}\n </button>\n );\n}\n","if (typeof document !== \"undefined\" && !document.getElementById(\"ac-style-0fcb7940\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-0fcb7940\";\n s.textContent = `.PillList-module_list_qvLqO {\n position: relative;\n z-index: 1;\n pointer-events: auto;\n display: inline-flex;\n gap: 7px;\n align-items: center;\n vertical-align: middle;\n}\n`;\n document.head.appendChild(s);\n}\nexport default {\"list\":\"PillList-module_list_qvLqO\"};","import type { Suggestion } from \"../types\";\nimport { PILL_OPACITY, Pill, type PillState } from \"./Pill\";\nimport pillStyles from \"./Pill.module.css\";\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 * When true, the rendered pills become non-interactive shimmering skeletons.\n * Real pills (with their text) are rendered when provided so widths/positions\n * match the previous state; when `pills` is empty, fixed-width fallback\n * placeholders are rendered instead.\n */\n loading?: boolean;\n}\n\nconst FALLBACK_SKELETON_WIDTHS = [125, 69];\n\n/** Map a pill's index in the sequence to its emphasis tier. */\nfunction pillStateForIndex(index: number): PillState {\n if (index === 0) return \"active\";\n if (index === 1) return \"upcoming\";\n return \"disabled\";\n}\n\nexport function PillList({\n pills,\n activePillIndex,\n onSelectPill,\n rounded,\n loading,\n}: PillListProps) {\n if (loading && pills.length === 0) {\n return (\n <span className={styles.list} data-aia-pill-list-loading=\"\">\n {FALLBACK_SKELETON_WIDTHS.map((w, i) => (\n <span\n key={`skel-${w}`}\n data-aia-pill-skeleton=\"\"\n className={`${pillStyles.pill} ${rounded ? pillStyles.rounded : \"\"} ${pillStyles.skeleton}`}\n style={{ width: w, opacity: PILL_OPACITY[pillStateForIndex(i)] }}\n />\n ))}\n </span>\n );\n }\n\n return (\n <span className={styles.list} data-aia-pill-list-loading={loading ? \"\" : undefined}>\n {pills.map((pill, i) => (\n <Pill\n key={`${pill.type}-${pill.text}`}\n label={pill.text}\n state={pillStateForIndex(i)}\n selected={i === activePillIndex}\n rounded={rounded}\n loading={loading}\n onClick={() => onSelectPill(i)}\n />\n ))}\n </span>\n );\n}\n","import {\n type ComponentPropsWithoutRef,\n type CSSProperties,\n type ReactNode,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n} from \"react\";\nimport \"./Grid.css\";\n\ninterface GridProps extends Omit<ComponentPropsWithoutRef<\"div\">, \"className\"> {\n /** Minimum cell width. CSS length, e.g. \"16rem\". Columns auto-fit at runtime. */\n min?: string;\n /** Maximum cell width. CSS length. Defaults to `1fr` (stretch to fill). */\n max?: string;\n /** Gap between cells. Defaults to `0`. */\n gap?: string;\n /** Cap the height and scroll vertically when content overflows. */\n scroll?: boolean;\n /** Max height when `scroll`. CSS length. Defaults to `200px`. */\n maxHeight?: string;\n /** Show a bottom fade overlay while the grid has hidden overflow below. */\n fade?: boolean;\n className?: string;\n children: ReactNode;\n}\n\n// Intrinsic grid — auto-fits as many columns as fit between `min` and `max`\n// wide, wrapping to new rows when there's no more horizontal room. Optionally\n// scrolls (capped height) with a bottom fade indicator. Internal.\nexport function Grid({\n min = \"16rem\",\n max,\n gap,\n scroll = false,\n maxHeight,\n fade = false,\n className,\n children,\n ...rest\n}: GridProps) {\n const gridRef = useRef<HTMLDivElement>(null);\n const [hasBottomOverflow, setHasBottomOverflow] = useState(false);\n\n useEffect(() => {\n if (!fade) return;\n const el = gridRef.current;\n if (!el) return;\n const update = () => {\n setHasBottomOverflow(el.scrollHeight - el.scrollTop - el.clientHeight > 1);\n };\n el.addEventListener(\"scroll\", update, { passive: true });\n const resizeObserver = new ResizeObserver(update);\n resizeObserver.observe(el);\n return () => {\n el.removeEventListener(\"scroll\", update);\n resizeObserver.disconnect();\n };\n }, [fade]);\n\n // Re-measure synchronously when the content changes. ResizeObserver misses\n // this case (the grid hits max-height, so scrollHeight grows but the observed\n // box doesn't) and useEffect would leave a frame of stale fade.\n // biome-ignore lint/correctness/useExhaustiveDependencies: children is a trigger-only dep\n useLayoutEffect(() => {\n const el = gridRef.current;\n if (!fade || !el) return;\n setHasBottomOverflow(el.scrollHeight - el.scrollTop - el.clientHeight > 1);\n }, [fade, children]);\n\n const style: CSSProperties = { \"--aia-grid-min\": min } as CSSProperties;\n if (max) (style as Record<string, string>)[\"--aia-grid-max\"] = max;\n if (gap) (style as Record<string, string>)[\"--aia-grid-gap\"] = gap;\n if (maxHeight) (style as Record<string, string>)[\"--aia-grid-max-height\"] = maxHeight;\n\n // `className` and `...rest` always go on the outermost element so they can't\n // land on different nodes: the grid itself when not fading, the fade wrapper\n // when fading (mirrors Stack/Cluster, which spread rest on their single root).\n const grid = (\n <div\n ref={gridRef}\n className={!fade && className ? `aia-grid ${className}` : \"aia-grid\"}\n data-scroll={scroll || undefined}\n style={style}\n {...(fade ? {} : rest)}\n >\n {children}\n </div>\n );\n\n if (!fade) return grid;\n\n return (\n <div\n className={className ? `aia-grid-fade ${className}` : \"aia-grid-fade\"}\n data-fade={hasBottomOverflow ? \"\" : undefined}\n {...rest}\n >\n {grid}\n </div>\n );\n}\n","if (typeof document !== \"undefined\" && !document.getElementById(\"ac-style-948e58da\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-948e58da\";\n s.textContent = `@layer layout {\n .aia-grid {\n display: grid;\n grid-template-columns: repeat(\n auto-fit,\n minmax(min(var(--aia-grid-min), 100%), var(--aia-grid-max, 1fr))\n );\n gap: var(--aia-grid-gap, 0);\n }\n\n /* Scrollable variant — capped height with a styled thin scrollbar. Rows pack\n from the top instead of stretching to fill the container. */\n .aia-grid[data-scroll] {\n grid-auto-rows: min-content;\n align-content: start;\n justify-content: start;\n padding: var(--aia-grid-scroll-pad, 0);\n max-height: var(--aia-grid-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 .aia-grid[data-scroll]::-webkit-scrollbar {\n width: 6px;\n }\n .aia-grid[data-scroll]::-webkit-scrollbar-track {\n background: transparent;\n }\n .aia-grid[data-scroll]::-webkit-scrollbar-thumb {\n background: var(--aia-scrollbar-thumb, rgba(0, 0, 0, 0.3));\n border-radius: 3px;\n }\n\n /* Fade wrapper — bottom blur overlay shown while the grid overflows below. */\n .aia-grid-fade {\n position: relative;\n }\n .aia-grid-fade::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 .aia-grid-fade[data-fade]::after {\n opacity: 1;\n }\n}\n`;\n document.head.appendChild(s);\n}\nexport {};","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 loading?: boolean;\n}\n\nexport function SuggestionItem({\n option,\n isHighlighted,\n onSelect,\n onHighlight,\n id,\n loading,\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 (loading || !option.is_tappable || pressed) return;\n setPressed(true);\n onSelect(option);\n clearTimeout(timerRef.current);\n timerRef.current = setTimeout(() => setPressed(false), 500);\n };\n\n const className = [\n styles.item,\n isHighlighted && !loading ? 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 data-aia-loading={loading ? \"\" : undefined}\n aria-selected={isHighlighted}\n className={className}\n tabIndex={loading || !option.is_tappable ? -1 : 0}\n onClick={handleSelect}\n onKeyDown={(e) => {\n if (!loading && option.is_tappable && (e.key === \"Enter\" || e.key === \" \")) {\n e.preventDefault();\n handleSelect();\n }\n }}\n onMouseEnter={!loading && option.is_tappable ? onHighlight : undefined}\n >\n <div className={styles.streaks} />\n <div className={styles.streaksVert} />\n <span className={styles.content}>\n <span className={styles.text}>\n {option.icon ? `${option.icon} ${option.text}` : option.text}\n </span>\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-82820da7\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-82820da7\";\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 font-weight: 250;\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 border-radius: 12px;\n /* Symmetric 15px inset (matches Figma). The dropdown pads only vertically, so\n the option fills the full cell width — its highlight/border-streak animation\n reaches the dropdown edges while the text stays inset 15px. */\n padding: 10px 15px;\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}\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}\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/* Loading state — preserve the row's exact dimensions. The content stays an\n inline span so the line box and padding match the non-loading state byte\n for byte. Just hide the text and apply a background as a skeleton bar; the\n pulse provides the shimmer. */\n.SuggestionItem-module_item_d4vpD[data-aia-loading] {\n cursor: default;\n animation: SuggestionItem-module_skeletonPulse_plvdD 1.4s ease-in-out infinite;\n}\n\n/* Skeleton fill is on the inner text span (a true inline element) so multi-\n line options wrap into one skeleton bar per line. The outer .content is a\n flex item — blockified by spec — so painting the background there would\n collapse all lines into one tall rectangle. \\`box-decoration-break: clone\\`\n makes the radius render cleanly on each line bar. */\n.SuggestionItem-module_item_d4vpD[data-aia-loading] .SuggestionItem-module_text_yqoh9 {\n color: transparent;\n background: var(--aia-skeleton-bg, var(--aia-pill-bg, rgba(189, 189, 189, 0.51)));\n border-radius: 999px;\n -webkit-box-decoration-break: clone;\n box-decoration-break: clone;\n}\n\n.SuggestionItem-module_item_d4vpD[data-aia-loading] .SuggestionItem-module_tag_e3Fwe {\n display: none;\n}\n\n@keyframes SuggestionItem-module_skeletonPulse_plvdD {\n 0%,\n 100% {\n filter: brightness(1);\n }\n 50% {\n filter: brightness(0.55);\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\",\"skeletonPulse\":\"SuggestionItem-module_skeletonPulse_plvdD\",\"text\":\"SuggestionItem-module_text_yqoh9\"};","import { Grid } from \"../layout/Grid\";\nimport type { SuggestionOption } from \"../types\";\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 loading?: boolean;\n}\n\n/**\n * The dropdown's option grid: a thin wrapper that lays `SuggestionItem`s out\n * with the `Grid` layout primitive. `Grid` owns the auto-fit columns and the\n * capped-height scroll + bottom-fade behaviour, so this component only wires\n * each option to its highlight/select handlers and listbox-scoped id.\n */\nexport function SuggestionGrid({\n options,\n activeIndex,\n onSelect,\n onHighlight,\n listboxId,\n loading,\n}: SuggestionGridProps) {\n return (\n <Grid min=\"250px\" max=\"250px\" gap=\"0\" scroll fade>\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 loading={loading}\n />\n ))}\n </Grid>\n );\n}\n","if (typeof document !== \"undefined\" && !document.getElementById(\"ac-style-8414cd5f\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-8414cd5f\";\n s.textContent = `@layer layout {\n .aia-stack {\n display: flex;\n flex-direction: column;\n gap: var(--aia-stack-space, 0.5rem);\n }\n .aia-stack[data-align=\"start\"] {\n align-items: start;\n }\n .aia-stack[data-align=\"center\"] {\n align-items: center;\n }\n .aia-stack[data-align=\"end\"] {\n align-items: end;\n }\n /* data-align=\"stretch\" is the flex default — no rule needed. */\n}\n`;\n document.head.appendChild(s);\n}\nexport {};","import type { ComponentPropsWithoutRef, CSSProperties, ReactNode } from \"react\";\nimport \"./Stack.css\";\n\ninterface StackProps extends Omit<ComponentPropsWithoutRef<\"div\">, \"className\"> {\n /** Gap between children. Any CSS length. Defaults to `0.5rem`. */\n space?: string;\n /** Cross-axis alignment of children. Defaults to `stretch` (full width). */\n align?: \"start\" | \"center\" | \"end\" | \"stretch\";\n className?: string;\n children: ReactNode;\n}\n\n// Vertical layout primitive — children stack top-to-bottom with `space` gap. Internal.\nexport function Stack({ space, align = \"stretch\", className, children, ...rest }: StackProps) {\n const style = space ? ({ \"--aia-stack-space\": space } as CSSProperties) : undefined;\n return (\n <div\n className={className ? `aia-stack ${className}` : \"aia-stack\"}\n data-align={align}\n style={style}\n {...rest}\n >\n {children}\n </div>\n );\n}\n","import styles from \"./AIAutocompleteDropdown.module.css\";\nimport { DropdownFooter } from \"./components/DropdownFooter\";\nimport { PillList } from \"./components/PillList\";\nimport { SuggestionGrid } from \"./components/SuggestionGrid\";\nimport { Cluster } from \"./layout/Cluster\";\nimport { Stack } from \"./layout/Stack\";\nimport type { AIAutocompleteDropdownProps } from \"./types\";\n\nconst FALLBACK_SKELETON_BAR_WIDTHS = [159, 119, 164];\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 hasTabbedToHighlight = false,\n}: AIAutocompleteDropdownProps) {\n const activeSuggestion = suggestions[0];\n const options = activeSuggestion?.options ?? [];\n const isOptionHighlighted = activeIndex >= 0 && Boolean(options[activeIndex]?.is_tappable);\n const hasRealPills = Boolean(pills && pills.length > 0 && onPillClick);\n // Guarantee at least one option bar during loading — if the cached state\n // had no options, render the fallback skeleton bars regardless of whether\n // pills are present, so the dropdown never shows pills with an empty body.\n const showsRealPills = showPills && hasRealPills;\n const showsLoadingPills = showPills && !hasRealPills && isLoading;\n const showsPillBar = showsRealPills || showsLoadingPills;\n const showsOptions = options.length > 0;\n const showsFallbackSkeleton = isLoading && !showsOptions;\n const isVisible = isOpen && (showsOptions || showsRealPills || isLoading);\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 <Stack space=\"14px\">\n {showsPillBar && (\n <Cluster noWrap className={styles.pillBar} data-aia-pillbar=\"\">\n <PillList\n pills={pills ?? []}\n activePillIndex={0}\n onSelectPill={onPillClick ?? (() => {})}\n rounded\n loading={isLoading}\n />\n </Cluster>\n )}\n {showsOptions && (\n <SuggestionGrid\n options={options}\n activeIndex={activeIndex}\n onSelect={onSelect}\n onHighlight={onHighlight}\n listboxId={id}\n loading={isLoading}\n />\n )}\n {showsFallbackSkeleton && (\n <div className={styles.skeletonBars} data-aia-skeleton-bars=\"\">\n {FALLBACK_SKELETON_BAR_WIDTHS.map((w) => (\n <span key={`bar-${w}`} className={styles.skeletonBar} style={{ width: w }} />\n ))}\n </div>\n )}\n <DropdownFooter\n hasTabbedToHighlight={hasTabbedToHighlight}\n isOptionHighlighted={isOptionHighlighted}\n />\n </Stack>\n </div>\n );\n}\n","if (typeof document !== \"undefined\" && !document.getElementById(\"ac-style-0ae03977\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-0ae03977\";\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/*\n * Library-scoped box-sizing reset. The SDK's pill / option / wrapper styles\n * mix explicit dimensions with padding (e.g. .magicx-aia-pill has height:36px\n * + padding:13px) and were authored assuming \\`border-box\\`. In consumer apps\n * without a global \\`* { box-sizing: border-box }\\` reset the pill rendered\n * ~62px tall instead of 36px. Scoping the reset to \\`.magicx-aia\\` descendants\n * keeps the library self-contained without leaking onto consumer markup.\n */\n:where(.magicx-aia, .magicx-aia *, .magicx-aia *::before, .magicx-aia *::after) {\n box-sizing: border-box;\n}\n\n/* Light mode defaults (base) */\n:where(.magicx-aia),\n:where(.magicx-aia[data-mode=\"light\"]) {\n --aia-surface: #ffffff;\n --aia-border: #b0b0b0;\n --aia-pill-bg: #bdbdbd;\n --aia-pill-color: #333539;\n --aia-pill-font-size: 18px;\n\n --aia-option-bg: transparent;\n --aia-option-color: #505050;\n --aia-option-color-selected: #000000;\n --aia-option-font-size: 18px;\n\n --aia-written-text-color: #000000;\n --aia-written-text-font-size: 20px;\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 --aia-footer-divider: rgba(176, 176, 176, 0.4);\n --aia-footer-hint-color: #505050;\n --aia-footer-brand-color: #b0b0b0;\n --aia-footer-badge-border: rgba(189, 189, 189, 0.51);\n}\n\n/* Dark mode defaults */\n:where(.magicx-aia[data-mode=\"dark\"]) {\n --aia-surface: #000000;\n --aia-border: #505050;\n --aia-pill-bg: #bdbdbd;\n --aia-pill-color: #b0b0b0;\n --aia-pill-font-size: 18px;\n\n --aia-option-bg: transparent;\n --aia-option-color: #b0b0b0;\n --aia-option-color-selected: #ffffff;\n --aia-option-font-size: 18px;\n\n --aia-written-text-color: #ffffff;\n --aia-written-text-font-size: 20px;\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 --aia-footer-divider: rgba(255, 255, 255, 0.15);\n --aia-footer-hint-color: #b0b0b0;\n --aia-footer-brand-color: #505050;\n --aia-footer-badge-border: #505050;\n}\n\n/* optionsPosition: dropdown above the input. The sections live inside the\n dropdown's .aia-stack, so the reversal targets the stack (not the dropdown,\n whose only child is the stack). */\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}\n\n:where(.magicx-aia[data-options-position=\"above\"]) [data-aia-dropdown] .aia-stack {\n flex-direction: column-reverse;\n}\n\n/* The footer sits at the top when the dropdown is above, so flip its own\n internal stack too — the divider should sit BELOW the hint/branding row\n (between the footer and the options beneath it), not above it. The footer's\n own class is CSS-module-scoped, so target the stable data attribute. */\n:where(.magicx-aia[data-options-position=\"above\"]) [data-aia-dropdown] [data-aia-footer] {\n flex-direction: column-reverse;\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 {};","if (typeof document !== \"undefined\" && !document.getElementById(\"ac-style-fdee06e6\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-fdee06e6\";\n s.textContent = `.SubmitButton-module_submitButton_otz7H {\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.SubmitButton-module_submitButton_otz7H:hover {\n opacity: 0.85;\n}\n\n.SubmitButton-module_submitButton_otz7H:disabled {\n opacity: 0.4;\n cursor: default;\n}\n`;\n document.head.appendChild(s);\n}\nexport default {\"submitButton\":\"SubmitButton-module_submitButton_otz7H\"};","import styles from \"./SubmitButton.module.css\";\n\ninterface SubmitButtonProps {\n /** Disabled when there's nothing to submit. */\n disabled?: boolean;\n onClick: () => void;\n}\n\n/**\n * The default circular submit button (up-arrow). Tier 1 renders this when the\n * consumer doesn't supply a custom `submitButton`. Themed via `--aia-submit-*`.\n */\nexport function SubmitButton({ disabled, onClick }: SubmitButtonProps) {\n return (\n <button\n type=\"button\"\n data-aia-submit=\"\"\n className={styles.submitButton}\n disabled={disabled}\n onClick={(e) => {\n e.stopPropagation();\n onClick();\n }}\n aria-label=\"Submit\"\n >\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 18 18\" fill=\"none\" role=\"img\" aria-label=\"Submit\">\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}\n","import {\n AIAutocomplete as CoreAIAutocomplete,\n type CoreState,\n type Suggestion,\n type SuggestionOption,\n} from \"@magicx-eng/ai-autocomplete-vanilla\";\nimport {\n type ChangeEvent,\n type KeyboardEvent,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport type { UseAIAutocompleteOptions, UseAIAutocompleteReturn } from \"../types\";\n\n/**\n * Pre-mount / SSR fallback. Identical shape to the post-mount CoreState so\n * the hook's return is single-shaped — no `if (!instance) return ...` branch.\n * `isLoading: true` matches the historical SSR bail-out: consumers using\n * `isLoading` to render a skeleton see one on the first paint instead of a\n * flash of blank content while the mount effect creates the core instance.\n */\nconst EMPTY_STATE: CoreState = {\n text: \"\",\n completedParams: [],\n suggestions: [],\n activeDropdownIndex: -1,\n newParamId: null,\n isLoading: true,\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 inSelectionAnimation: false,\n hasTabbedToHighlight: false,\n};\n\ninterface CoreActions {\n handleTextChange: (value: string) => void;\n handleKeyDown: (e: KeyboardEvent<HTMLElement> | globalThis.KeyboardEvent) => void;\n setFocused: (focused: boolean) => void;\n startEditingParam: (paramId: string) => void;\n exitEditMode: () => void;\n handleCaretAfterInput: (offset: number | null) => void;\n handleCaretMove: (offset: number | null) => void;\n replaceEditingRange: (replacement: string) => boolean;\n setActivePill: (index: number) => void;\n removeLastParam: () => void;\n clearNewParamId: () => void;\n reset: () => void;\n selectOption: (option: SuggestionOption) => void;\n setActiveDropdownIndex: (index: number) => void;\n handleFocus: () => void;\n handleBlur: () => void;\n}\n\nexport function useAIAutocomplete({\n onSubmit,\n onError,\n optionOverrides,\n maskCompletedText,\n apiConfig,\n columns = 2,\n dropdownTrigger,\n optionsPosition,\n closeDropdownOnBlur,\n showNonTappableOptions,\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 caller-supplied callbacks. The CoreAIAutocomplete instance is\n // mount-only (created once); these refs let the stable proxy callbacks\n // inside it pick up the latest props on every render.\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 optionsPosition,\n closeDropdownOnBlur,\n showNonTappableOptions,\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 // Sync controlled value\n useEffect(() => {\n if (controlledValue !== undefined) instanceRef.current?.setValue(controlledValue);\n }, [controlledValue]);\n\n // Sync controlled params\n useEffect(() => {\n if (controlledParams !== undefined) instanceRef.current?.setCompletedParams(controlledParams);\n }, [controlledParams]);\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 instanceRef.current?.update({\n apiConfig,\n optionOverrides,\n dropdownTrigger,\n optionsPosition,\n closeDropdownOnBlur,\n showNonTappableOptions,\n });\n }, [\n apiConfigJson,\n overridesVersion.current,\n dropdownTrigger,\n optionsPosition,\n closeDropdownOnBlur,\n showNonTappableOptions,\n ]);\n\n // Single stable action surface. Built once via the useRef-with-null-init\n // pattern (the idiomatic \"create once, never recreate\" idiom in React — see\n // https://react.dev/reference/react/useRef). Every entry forwards to the\n // current core instance via `instanceRef.current` so the closure picks up\n // the live instance even though the actions object itself never changes.\n const actionsRef = useRef<CoreActions | null>(null);\n if (actionsRef.current === null) {\n actionsRef.current = {\n handleTextChange: (value) => instanceRef.current?.handleTextChange(value),\n handleKeyDown: (e) => {\n const native = \"nativeEvent\" in e ? e.nativeEvent : e;\n instanceRef.current?.handleKeyDown(native);\n },\n setFocused: (focused) => instanceRef.current?.setFocused(focused),\n startEditingParam: (paramId) => instanceRef.current?.startEditingParam(paramId),\n exitEditMode: () => instanceRef.current?.exitEditMode(),\n handleCaretAfterInput: (offset) => instanceRef.current?.handleCaretAfterInput(offset),\n handleCaretMove: (offset) => instanceRef.current?.handleCaretMove(offset),\n replaceEditingRange: (replacement) =>\n instanceRef.current?.replaceEditingRange(replacement) ?? false,\n setActivePill: (index) => instanceRef.current?.setActivePill(index),\n removeLastParam: () => instanceRef.current?.removeLastParam(),\n clearNewParamId: () => instanceRef.current?.clearNewParamId(),\n reset: () => instanceRef.current?.reset(),\n selectOption: (option) => instanceRef.current?.selectOption(option),\n setActiveDropdownIndex: (index) => instanceRef.current?.setActiveDropdownIndex(index),\n handleFocus: () => instanceRef.current?.setFocused(true),\n handleBlur: () => instanceRef.current?.setFocused(false),\n };\n }\n const actions = actionsRef.current;\n\n // textarea-specific adapter — capitalizes the first character on first\n // keystroke. Kept separate from `actions.handleTextChange` because the\n // capitalization rule belongs to the textarea host, not the core.\n const handleChange = useCallback((e: ChangeEvent<HTMLTextAreaElement>) => {\n const raw = e.target.value;\n const shouldCapitalize =\n raw.length > 0 &&\n !(e.nativeEvent as InputEvent)?.isComposing &&\n raw[0] !== raw[0].toUpperCase();\n const newValue = shouldCapitalize ? raw[0].toUpperCase() + raw.slice(1) : raw;\n instanceRef.current?.handleTextChange(newValue);\n }, []);\n\n const handleKeyDownTextarea = useCallback((e: KeyboardEvent<HTMLTextAreaElement>) => {\n instanceRef.current?.handleKeyDown(e.nativeEvent);\n }, []);\n\n // Snapshot the live instance + state for this render.\n const instance = instanceRef.current;\n const state = coreState ?? EMPTY_STATE;\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 listboxId = instance?.listboxId ?? \"\";\n\n const activeDescendantId =\n state.activeDropdownIndex >= 0 && instance\n ? `${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 // UI-visible loading — suppressed during the post-select streak animation\n // and during re-edit (cached options remain visible there). Pre-mount we\n // report loading=true so SSR / first-paint consumers render a skeleton\n // instead of a flash of blank content while the mount effect runs.\n const uiLoading =\n !instance || (state.isLoading && !state.editingParam && !state.inSelectionAnimation);\n\n return {\n completedParams,\n suggestionPills: actionableSuggestions,\n setActivePill: actions.setActivePill,\n removeLastParam: actions.removeLastParam,\n segments: state.segments,\n newParamId: state.newParamId,\n clearNewParamId: actions.clearNewParamId,\n suggestions: state.suggestions,\n activeIndex: state.activeDropdownIndex,\n isReady: state.isReady,\n isLoading: uiLoading,\n isFocused: state.isFocused,\n isDropdownOpen: state.isDropdownOpen,\n placeholderText: state.placeholderText,\n listboxId,\n error: state.error,\n handleTextChange: actions.handleTextChange,\n handleKeyDown: actions.handleKeyDown,\n setFocused: actions.setFocused,\n editingParam,\n editingAnchor: state.editingAnchor,\n caretOffset: state.caretOffset,\n startEditingParam: actions.startEditingParam,\n exitEditMode: actions.exitEditMode,\n handleCaretAfterInput: actions.handleCaretAfterInput,\n handleCaretMove: actions.handleCaretMove,\n replaceEditingRange: actions.replaceEditingRange,\n inputProps: {\n value: text,\n placeholder: state.placeholderText || undefined,\n onChange: handleChange,\n onKeyDown: handleKeyDownTextarea,\n onFocus: actions.handleFocus,\n onBlur: actions.handleBlur,\n role: \"combobox\" as const,\n \"aria-expanded\": state.isDropdownOpen,\n \"aria-activedescendant\": activeDescendantId,\n \"aria-autocomplete\": \"list\" as const,\n \"aria-controls\": listboxId,\n },\n reset: actions.reset,\n dropdownProps: {\n suggestions: dropdownActivePill\n ? [{ ...dropdownActivePill, options: state.filteredOptions }]\n : [],\n activeIndex: state.activeDropdownIndex,\n onSelect: actions.selectOption,\n onHighlight: actions.setActiveDropdownIndex,\n isOpen: state.isDropdownOpen,\n id: listboxId,\n pills: dropdownPills,\n onPillClick: actions.setActivePill,\n isLoading: uiLoading,\n hasTabbedToHighlight: state.hasTabbedToHighlight,\n },\n };\n}\n","import {\n type CompletedParamState,\n extractPlainText,\n getCursorOffset,\n plainTextLength,\n renderEditableContent,\n type Segment,\n setCursorOffset,\n} from \"@magicx-eng/ai-autocomplete-vanilla\";\nimport {\n type ClipboardEvent as ReactClipboardEvent,\n type KeyboardEvent as ReactKeyboardEvent,\n useCallback,\n useEffect,\n useLayoutEffect,\n useRef,\n} from \"react\";\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 interface UseContentEditableEditorOptions {\n /** Derived segments (text + bold completed-param runs) for the editor body. */\n segments: readonly Segment[];\n /** The most recently promoted param — shimmer + post-promote refocus key. */\n newParamId: string | null;\n /** The bold param currently being re-edited (or null). */\n editingParam: CompletedParamState | null;\n /** Plain-text offset where re-edit started; caret parks here on entry. */\n editingAnchor: number | null;\n /** Live caret offset within the editor, used by post-promote refocus. */\n caretOffset: number | null;\n /** Server-suggested placeholder (rendered via ::before when empty). */\n placeholderText: string;\n /** Whether the editor currently has focus — passes through to segment renderer. */\n isFocused: boolean;\n /** ARIA `aria-expanded` value for the input. */\n isDropdownOpen: boolean;\n /** ARIA `aria-controls` value pointing at the listbox. */\n listboxId: string;\n /** ARIA `aria-activedescendant` value pointing at the highlighted option (or undefined). */\n activeDescendantId: string | undefined;\n /** Focus the editor on mount (Tier 1 default). */\n autoFocus: boolean;\n /** Forwarded to the core whenever the plain-text content changes. */\n handleTextChange: (value: string) => void;\n /** Forwarded to the core for keyboard handling. */\n handleKeyDown: (e: ReactKeyboardEvent<HTMLElement> | globalThis.KeyboardEvent) => void;\n /** Forwarded to the core after each input event (extends edit tail, etc.). */\n handleCaretAfterInput: (offset: number | null) => void;\n /** Forwarded to the core on selectionchange (exits re-edit when caret leaves). */\n handleCaretMove: (offset: number | null) => void;\n /** Forwarded to the core when the caret lands inside a bold param's strong. */\n startEditingParam: (id: string) => void;\n /** Forwarded to the core during a `beforeinput` — atomic re-edit replacement. */\n replaceEditingRange: (replacement: string) => boolean;\n /** Forwarded to the core on native focus/blur. */\n setFocused: (focused: boolean) => void;\n}\n\nexport interface UseContentEditableEditorReturn {\n inputRef: React.RefObject<HTMLDivElement>;\n // Spread onto the contentEditable element; consumer supplies className.\n editorProps: {\n ref: React.RefObject<HTMLDivElement>;\n contentEditable: boolean;\n suppressContentEditableWarning: true;\n tabIndex: 0;\n role: \"combobox\";\n \"aria-autocomplete\": \"list\";\n \"aria-haspopup\": \"listbox\";\n \"aria-controls\": string;\n \"aria-expanded\": boolean;\n \"aria-activedescendant\": string | undefined;\n spellCheck: true;\n enterKeyHint: \"send\";\n onInput: () => void;\n onKeyDown: (e: ReactKeyboardEvent<HTMLDivElement>) => void;\n onCompositionStart: () => void;\n onCompositionEnd: () => void;\n onPaste: (e: ReactClipboardEvent<HTMLDivElement>) => void;\n onFocus: () => void;\n onBlur: () => void;\n };\n /** Current plain-text content of the editor (used by submit). */\n getPlainText: () => string;\n /** Imperative focus / blur (used by the parent's imperative handle). */\n focus: () => void;\n blur: () => void;\n}\n\n/**\n * Owns every concern that's specific to running the autocomplete on top of a\n * contentEditable host: composition state, caret tracking, selectionchange,\n * `beforeinput` interception, paste sanitization, plaintext-only feature\n * detection, segment rendering, post-promote refocus, and re-edit caret park.\n *\n * The hook stays React-agnostic above the contentEditable adapter — see\n * `core/render/renderEditable.ts` for the underlying DOM mutations. Callers\n * spread `editorProps` onto a `<div>` (className is theirs to provide).\n */\nexport function useContentEditableEditor(\n opts: UseContentEditableEditorOptions,\n): UseContentEditableEditorReturn {\n const {\n segments,\n newParamId,\n editingParam,\n editingAnchor,\n caretOffset,\n placeholderText,\n isFocused,\n isDropdownOpen,\n listboxId,\n activeDescendantId,\n autoFocus,\n handleTextChange,\n handleKeyDown,\n handleCaretAfterInput,\n handleCaretMove,\n startEditingParam,\n replaceEditingRange,\n setFocused,\n } = opts;\n\n const inputRef = useRef<HTMLDivElement>(null);\n const composingRef = useRef(false);\n const lastSeenParamIdRef = useRef(\"\");\n const lastEditingIdRef = useRef(\"\");\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 caretOffsetRef.current = caretOffset;\n\n // Auto-focus on mount once the host element is mounted.\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 // `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 // MUST run before the post-promote refocus + re-edit caret park effects\n // below — keep this declaration order.\n useLayoutEffect(() => {\n const el = inputRef.current;\n if (!el) return;\n renderEditableContent({\n input: el,\n segments: segments as Segment[],\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 of the just-promoted segment. Mirrors the\n // vanilla core's `justSelected` logic in renderInput.ts.\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 after\n // the new param's trailing space, so use it. Read via ref so the effect\n // 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 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 attach\n // 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: ReactClipboardEvent<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 handleFocus = useCallback(() => setFocused(true), [setFocused]);\n const handleBlur = useCallback(() => setFocused(false), [setFocused]);\n\n const focus = useCallback(() => inputRef.current?.focus(), []);\n const blur = useCallback(() => inputRef.current?.blur(), []);\n const getPlainText = useCallback(() => {\n const el = inputRef.current;\n return el ? extractPlainText(el) : \"\";\n }, []);\n\n const ceMode = supportsPlaintextOnly() ? \"plaintext-only\" : \"true\";\n\n return {\n inputRef,\n editorProps: {\n ref: inputRef,\n contentEditable: ceMode as unknown as boolean,\n suppressContentEditableWarning: true,\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: true,\n enterKeyHint: \"send\",\n onInput: handleInputEvent,\n onKeyDown: handleKeyDownReact,\n onCompositionStart: handleCompositionStart,\n onCompositionEnd: handleCompositionEnd,\n onPaste: handlePaste,\n onFocus: handleFocus,\n onBlur: handleBlur,\n },\n getPlainText,\n focus,\n blur,\n };\n}\n"],"mappings":"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","names":["index_exports","__export","AIAutocomplete","AIAutocompleteDropdown","useAIAutocomplete","__toCommonJS","import_react","s","AIAutocomplete_module_css_default","s","AIAutocompleteDropdown_module_css_default","import_ai_autocomplete_vanilla","s","import_jsx_runtime","Cluster","gap","align","justify","noWrap","inline","className","children","rest","style","props","s","DropdownFooter_module_css_default","import_jsx_runtime","DropdownFooter","hasTabbedToHighlight","isOptionHighlighted","key","hint","DropdownFooter_module_css_default","Cluster","s","Pill_module_css_default","import_jsx_runtime","PILL_OPACITY","Pill","label","state","selected","rounded","loading","onClick","className","Pill_module_css_default","e","s","PillList_module_css_default","import_jsx_runtime","FALLBACK_SKELETON_WIDTHS","pillStateForIndex","index","PillList","pills","activePillIndex","onSelectPill","rounded","loading","PillList_module_css_default","w","i","Pill_module_css_default","PILL_OPACITY","pill","Pill","import_react","s","import_jsx_runtime","Grid","min","max","gap","scroll","maxHeight","fade","className","children","rest","gridRef","hasBottomOverflow","setHasBottomOverflow","el","update","resizeObserver","style","grid","import_react","s","SuggestionItem_module_css_default","import_jsx_runtime","SuggestionItem","option","isHighlighted","onSelect","onHighlight","id","loading","pressed","setPressed","timerRef","handleSelect","className","SuggestionItem_module_css_default","e","import_jsx_runtime","SuggestionGrid","options","activeIndex","onSelect","onHighlight","listboxId","loading","Grid","option","i","SuggestionItem","s","import_jsx_runtime","Stack","space","align","className","children","rest","style","import_jsx_runtime","FALLBACK_SKELETON_BAR_WIDTHS","AIAutocompleteDropdown","suggestions","activeIndex","onSelect","onHighlight","isOpen","id","className","pills","onPillClick","showPills","isLoading","hasTabbedToHighlight","options","isOptionHighlighted","hasRealPills","showsRealPills","showsPillBar","showsOptions","showsFallbackSkeleton","isVisible","AIAutocompleteDropdown_module_css_default","e","Stack","Cluster","PillList","SuggestionGrid","w","DropdownFooter","s","import_ai_autocomplete_vanilla","s","SubmitButton_module_css_default","import_jsx_runtime","SubmitButton","disabled","onClick","SubmitButton_module_css_default","e","import_ai_autocomplete_vanilla","import_react","EMPTY_STATE","useAIAutocomplete","onSubmit","onError","optionOverrides","maskCompletedText","apiConfig","columns","dropdownTrigger","optionsPosition","closeDropdownOnBlur","showNonTappableOptions","onFocus","onBlur","controlledValue","controlledParams","onChangeProp","onParamsChange","source","setCursor","instanceRef","coreState","setCoreState","onSubmitRef","onErrorRef","onChangeRef","onParamsChangeRef","onFocusRef","onBlurRef","setCursorRef","instance","CoreAIAutocomplete","args","offset","unsub","state","apiConfigJson","prevOverridesRef","overridesVersion","prev","next","prevKeys","nextKeys","k","actionsRef","value","e","native","focused","paramId","replacement","index","option","actions","handleChange","raw","newValue","handleKeyDownTextarea","text","completedParams","actionableSuggestions","activeSuggestion","listboxId","activeDescendantId","editingParam","dropdownPill","dropdownActivePill","dropdownPills","uiLoading","import_ai_autocomplete_vanilla","import_react","plaintextOnlyCache","supportsPlaintextOnly","probe","useContentEditableEditor","opts","segments","newParamId","editingParam","editingAnchor","caretOffset","placeholderText","isFocused","isDropdownOpen","listboxId","activeDescendantId","autoFocus","handleTextChange","handleKeyDown","handleCaretAfterInput","handleCaretMove","startEditingParam","replaceEditingRange","setFocused","inputRef","composingRef","lastSeenParamIdRef","lastEditingIdRef","caretOffsetRef","lastInputAtRef","el","doc","onSelectionChange","sel","anchor","enclosing","previous","current","desired","fireInput","raw","next","handleInputEvent","onBeforeInput","e","inputEvent","t","replacement","handleCompositionStart","handleCompositionEnd","handlePaste","text","range","node","handleKeyDownReact","handleFocus","handleBlur","focus","blur","getPlainText","ceMode","import_jsx_runtime","resolveInitialMode","mode","AIAutocomplete","onSubmit","onError","optionOverrides","maskCompletedText","className","apiConfig","columns","pillPlacement","optionsPosition","animations","dropdownTrigger","closeDropdownOnBlur","showNonTappableOptions","autoFocus","onFocus","onBlur","value","controlledParams","onChangeProp","onParamsChange","submitButton","ref","containerRef","pillContainerRef","handleSubmitRef","modeControllerRef","editorInputRefHolder","el","handleSetCursor","offset","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","activeDescendantId","inputRef","editorProps","focus","blur","getPlainText","useContentEditableEditor","container","editor","update","inner","cRect","eRect","ro","m","canSubmit","handleSubmit","text","rawQuery","finalParams","handleWrapperClick","e","showInlinePills","showDropdownPills","AIAutocomplete_module_css_default","AIAutocompleteDropdown","PillList","SubmitButton"]}
|