@magicx-eng/ai-autocomplete-react 0.6.5 → 0.6.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/AIAutocomplete.tsx","css-module:/home/runner/work/ai-autocomplete-sdk-js/ai-autocomplete-sdk-js/packages/react/src/AIAutocomplete.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","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/ParamPill.module.css.js","../src/components/ParamPill.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","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":["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 = \"dropdown\",\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 isActivePillSelected,\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 activeSelected={isActivePillSelected}\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: 12px 16px;\n border: 1px solid var(--aia-border, #b0b0b0);\n border-radius: 20px;\n background: var(--aia-surface, #ffffff);\n box-shadow: var(--aia-shadow, none);\n overflow: hidden;\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.AIAutocomplete-module_editorArea_7rBWq {\n position: relative;\n flex: 1;\n min-width: 0;\n min-height: 19px;\n line-height: 19px;\n font-family: inherit;\n font-size: var(--aia-written-text-font-size, 14px);\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: 300;\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 pills (Figma \"RichTextPill\") — a compact\n ~26px chip with regular-weight primary-color text on a faint-gray fill.\n inline-block gives the padding/radius a box while the text stays part of the\n editable plain text (the caret system counts characters inside this\n <strong>). The completed class is stamped by the shared renderer as a global\n string, so match it via [class~=] to bypass CSS Modules' hashing. */\n:where(.AIAutocomplete-module_input_IW-P-) strong[class~=\"magicx-aia-segment--completed\"] {\n display: inline-block;\n padding: 4px 6px;\n border-radius: 999px;\n background: var(--aia-completed-pill-bg, rgba(189, 189, 189, 0.15));\n color: var(--aia-completed-pill-color, var(--aia-written-text-color, #fff));\n font-size: var(--aia-pill-font-size, 14px);\n font-weight: 400;\n line-height: normal;\n white-space: nowrap;\n /* Small vertical breathing room so wrapped rows of pills don't touch. */\n margin: 2px 0;\n /* baseline (not middle) so the pill's text shares the surrounding text's\n baseline exactly. middle aligns the chip box to the parent's x-height\n midpoint, which font ascent/descent asymmetry turns into the pill text\n sitting ~1-2px below the adjacent text. The symmetric 4px padding keeps\n the capsule optically centered around the text on its own. */\n vertical-align: baseline;\n cursor: pointer;\n /* Smooth hover fade. Neutralized by the data-animations=\"off\" block. */\n transition: background-color 150ms ease;\n}\n\n/* Hover highlight — a slightly stronger fill so a pointed-at pill reads as\n tappable. Declared between the base and editing rules so editing wins. */\n:where(.AIAutocomplete-module_input_IW-P-) strong[class~=\"magicx-aia-segment--completed\"]:hover {\n background: var(--aia-completed-pill-bg-active, rgba(189, 189, 189, 0.35));\n}\n\n/* Re-edit highlight — applied to the completed pill being re-edited (after a\n tap). Reuses the exact hover fill so the highlight persists from tap until an\n option is selected. Hides the native caret; cursor switches to text since the\n pill is in text-replacement mode. The editing class is written by the shared\n renderer (a global string), so target it via an attribute selector to bypass\n CSS Modules' hashing. Declared last so it wins on a strong carrying both\n classes. */\n:where(.AIAutocomplete-module_input_IW-P-) strong[class~=\"magicx-aia-segment--editing\"] {\n background: var(--aia-completed-pill-bg-active, rgba(189, 189, 189, 0.35));\n caret-color: transparent;\n cursor: text;\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/* Promotion reveal on a newly promoted completed param. The shared renderer\n (core/render/renderEditable.ts) stamps the global shimmer classes onto the\n just-added <strong>; we match them via [class~=] to bypass CSS Modules'\n hashing. Completed params are now pills with a solid background, so the old\n text-clip gradient shimmer can't be used (background-clip: text would wipe\n the pill background). The reveal is a simple fade-in of the whole pill,\n riding on shimmer-sweep so it only plays on genuine promotions. */\n:where(.AIAutocomplete-module_input_IW-P-) strong[class~=\"magicx-aia-shimmer-sweep\"] {\n animation: AIAutocomplete-module_aiaPillReveal_wf05b 400ms cubic-bezier(0.4, 0, 0.2, 1) forwards;\n}\n\n@keyframes AIAutocomplete-module_aiaPillReveal_wf05b {\n from {\n opacity: 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\",\"aiaPillReveal\":\"AIAutocomplete-module_aiaPillReveal_wf05b\"};","import { useEffect, useRef, useState } from \"react\";\n// Self-inject the appearance layer (design tokens, box-sizing reset, and the\n// optionsPosition=\"above\" layout-reversal rules). Tier 1 already imports this,\n// but headless consumers render only this dropdown — importing it here means\n// they get correct styling and a working `optionsPosition` with no extra setup.\nimport \"./appearance.css\";\nimport 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\n/**\n * Resolve the `mode` prop to a concrete `\"light\" | \"dark\"` (or `undefined` when\n * unset, meaning \"don't self-scope — inherit from a `.magicx-aia` ancestor\").\n * `\"auto\"` tracks `prefers-color-scheme` live.\n */\nfunction useResolvedMode(\n mode: \"light\" | \"dark\" | \"auto\" | undefined,\n): \"light\" | \"dark\" | undefined {\n const prefersDark = () =>\n typeof window !== \"undefined\" &&\n typeof window.matchMedia === \"function\" &&\n window.matchMedia(\"(prefers-color-scheme: dark)\").matches;\n const [systemDark, setSystemDark] = useState(prefersDark);\n\n useEffect(() => {\n if (\n mode !== \"auto\" ||\n typeof window === \"undefined\" ||\n typeof window.matchMedia !== \"function\"\n ) {\n return;\n }\n const mq = window.matchMedia(\"(prefers-color-scheme: dark)\");\n const onChange = () => setSystemDark(mq.matches);\n mq.addEventListener(\"change\", onChange);\n return () => mq.removeEventListener(\"change\", onChange);\n }, [mode]);\n\n if (mode === undefined) return undefined;\n if (mode === \"auto\") return systemDark ? \"dark\" : \"light\";\n return mode;\n}\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 activeSelected = false,\n isLoading = false,\n isInputEmpty = false,\n optionsPosition = \"below\",\n mode,\n}: AIAutocompleteDropdownProps) {\n // When `mode` is set, self-scope: add `magicx-aia` + `data-mode` to our own\n // root so the dropdown is styled without a `.magicx-aia` wrapper. When unset,\n // stay class-less and inherit from an ancestor (Tier 1 / a custom wrapper).\n const resolvedMode = useResolvedMode(mode);\n const selfScope = resolvedMode !== undefined;\n\n // Visibility is computed from the CURRENT props and drives the opacity fade.\n const liveOptions = suggestions[0]?.options ?? [];\n const liveHasRealPills = Boolean(pills && pills.length > 0 && onPillClick);\n const isVisible =\n isOpen && (liveOptions.length > 0 || (showPills && liveHasRealPills) || isLoading);\n\n // Freeze the content-driving values while the dropdown is open. When it\n // closes we render this frozen snapshot during the 400ms opacity fade, so the\n // whole populated dropdown fades out as one. Otherwise the pills/options\n // unmount the instant the underlying state empties (e.g. skipping the last\n // pill with →), leaving the always-present footer alone for a flash of a\n // footer-only \"no options\" box. Content is refreshed on the next open.\n const snapshot = {\n suggestions,\n activeIndex,\n pills,\n showPills,\n activeSelected,\n isLoading,\n isInputEmpty,\n };\n const lastVisibleRef = useRef(snapshot);\n if (isVisible) lastVisibleRef.current = snapshot;\n const content = isVisible ? snapshot : lastVisibleRef.current;\n\n const activeSuggestion = content.suggestions[0];\n const options = activeSuggestion?.options ?? [];\n const isOptionHighlighted =\n content.activeIndex >= 0 && Boolean(options[content.activeIndex]?.is_tappable);\n const hasRealPills = Boolean(content.pills && content.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 = content.showPills && hasRealPills;\n const showsLoadingPills = content.showPills && !hasRealPills && content.isLoading;\n const showsPillBar = showsRealPills || showsLoadingPills;\n const showsOptions = options.length > 0;\n const showsFallbackSkeleton = content.isLoading && !showsOptions;\n\n return (\n <div\n id={id}\n role=\"listbox\"\n data-aia-dropdown=\"\"\n data-options-position={optionsPosition}\n data-mode={resolvedMode}\n data-aia-loading={content.isLoading ? \"\" : undefined}\n className={`${selfScope ? \"magicx-aia \" : \"\"}${styles.dropdown} ${isVisible ? styles.visible : \"\"} ${className ?? \"\"}`}\n onMouseDown={(e) => e.preventDefault()}\n >\n <Stack space=\"8px\">\n {showsPillBar && (\n <Cluster noWrap className={styles.pillBar} data-aia-pillbar=\"\">\n <PillList\n pills={content.pills ?? []}\n activePillIndex={0}\n activeSelected={content.activeSelected}\n onSelectPill={onPillClick ?? (() => {})}\n rounded\n loading={content.isLoading}\n />\n </Cluster>\n )}\n {showsOptions && (\n <SuggestionGrid\n options={options}\n activeIndex={content.activeIndex}\n onSelect={onSelect}\n onHighlight={onHighlight}\n listboxId={id}\n loading={content.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 isOptionHighlighted={isOptionHighlighted}\n isInputEmpty={content.isInputEmpty}\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/*\n * Primitive color ramp — single source of truth, mirroring the Figma\n * \"Primitives\" collection. INTERNAL: theme via the public --aia-* vars below,\n * not these. Mode-independent (raw values; the same in light and dark).\n */\n:where(.magicx-aia) {\n --aia-primitive-neutral-0: #000000;\n --aia-primitive-neutral-250: #323232;\n --aia-primitive-neutral-300: #333539;\n --aia-primitive-neutral-400: #4a4a4a;\n --aia-primitive-neutral-500: #505050;\n --aia-primitive-neutral-700: #b0b0b0;\n --aia-primitive-neutral-750: #bdbdbd;\n --aia-primitive-neutral-900: #e7e7e7;\n --aia-primitive-neutral-1000: #ffffff;\n --aia-primitive-blue-50: #eef2ff;\n --aia-primitive-neutral-750-a50: rgba(189, 189, 189, 0.51);\n --aia-primitive-neutral-750-a35: rgba(189, 189, 189, 0.35);\n --aia-primitive-neutral-750-a30: rgba(189, 189, 189, 0.3);\n --aia-primitive-neutral-750-a15: rgba(189, 189, 189, 0.15);\n --aia-primitive-neutral-700-a40: rgba(176, 176, 176, 0.4);\n}\n\n/* Light mode defaults (base) — public --aia-* vars resolve to primitives */\n:where(.magicx-aia),\n:where(.magicx-aia[data-mode=\"light\"]) {\n --aia-surface: var(--aia-primitive-neutral-1000);\n --aia-border: rgba(17, 24, 39, 0.14); /* subtle slate hairline (off-palette) */\n /* Elevation for the input container (.inputWrapper). */\n --aia-shadow:\n inset 0 1px 0 rgba(255, 255, 255, 0.9), 0 1px 2px rgba(16, 24, 40, 0.1),\n 0 8px 24px rgba(16, 24, 40, 0.16);\n --aia-dropdown-border: var(\n --aia-primitive-neutral-900\n ); /* was #e5e7eb — snapped to palette (Δ2) */\n --aia-dropdown-shadow: 0 8px 12px rgba(0, 0, 0, 0.1);\n /* Suggestion pills (Figma \"ParamPill\"): transparent fill + dashed border;\n per-pill opacity via getPillOpacity. */\n --aia-pill-bg: var(--aia-primitive-neutral-750);\n --aia-pill-color: var(--aia-primitive-neutral-300);\n --aia-pill-border: var(--aia-primitive-neutral-750-a30);\n --aia-pill-font-size: 14px;\n\n /* Completed params (Figma \"RichTextPill\"): compact faint-gray chip with\n primary-color regular-weight text. -active is the hover / tapped (re-edit)\n highlight — an alpha over the input background, so one value works in both\n themes. */\n --aia-completed-pill-bg: var(--aia-primitive-neutral-750-a15);\n --aia-completed-pill-bg-active: var(--aia-primitive-neutral-750-a35);\n --aia-completed-pill-color: var(--aia-primitive-neutral-0);\n\n --aia-option-bg: var(--aia-primitive-blue-50);\n --aia-option-color: var(--aia-primitive-neutral-500);\n --aia-option-color-selected: var(--aia-primitive-neutral-0);\n --aia-option-font-size: 14px;\n\n --aia-written-text-color: var(--aia-primitive-neutral-0);\n --aia-written-text-font-size: 14px;\n --aia-caret-color: var(--aia-written-text-color, #000000);\n\n --aia-submit-bg: var(--aia-primitive-neutral-0);\n --aia-submit-color: var(--aia-primitive-neutral-1000);\n\n --aia-color-text-muted: #6b7280; /* off shared palette (slate) */\n\n --aia-skeleton-bg: var(--aia-primitive-neutral-750-a50);\n\n --aia-streak-rgb: 99, 102, 241; /* off shared palette (indigo effect) */\n --aia-streak-glass-bg: rgba(99, 102, 241, 0.1);\n\n --aia-footer-hint-color: var(--aia-primitive-neutral-500);\n --aia-footer-brand-color: var(--aia-primitive-neutral-700);\n --aia-footer-badge-border: var(--aia-primitive-neutral-750-a50);\n}\n\n/* Dark mode defaults */\n:where(.magicx-aia[data-mode=\"dark\"]) {\n --aia-surface: var(--aia-primitive-neutral-0);\n --aia-border: var(--aia-primitive-neutral-500);\n /* Elevation for the input container (.inputWrapper) — tuned for dark surfaces:\n a faint top highlight + deeper ambient shadows. */\n --aia-shadow:\n inset 0 1px 0 rgba(255, 255, 255, 0.06), 0 1px 2px rgba(0, 0, 0, 0.4),\n 0 8px 24px rgba(0, 0, 0, 0.5);\n --aia-dropdown-border: var(\n --aia-primitive-neutral-400\n ); /* was #484848 — snapped to palette (Δ2) */\n --aia-dropdown-shadow: 0 8px 12px rgba(0, 0, 0, 0.1);\n /* Suggestion pills (Figma \"ParamPill\"): transparent fill + dashed border. */\n --aia-pill-bg: var(--aia-primitive-neutral-750);\n --aia-pill-color: var(--aia-primitive-neutral-700);\n --aia-pill-border: var(--aia-primitive-neutral-750-a30);\n --aia-pill-font-size: 14px;\n\n /* Completed params (Figma \"RichTextPill\") — dark theme (design source):\n white text on a faint-gray chip. -active is the hover / tapped highlight. */\n --aia-completed-pill-bg: var(--aia-primitive-neutral-750-a15);\n --aia-completed-pill-bg-active: var(--aia-primitive-neutral-750-a35);\n --aia-completed-pill-color: var(--aia-primitive-neutral-1000);\n\n --aia-option-bg: var(--aia-primitive-neutral-250);\n --aia-option-color: var(--aia-primitive-neutral-700);\n --aia-option-color-selected: var(--aia-primitive-neutral-1000);\n --aia-option-font-size: 14px;\n\n --aia-written-text-color: var(--aia-primitive-neutral-1000);\n --aia-written-text-font-size: 14px;\n --aia-caret-color: var(--aia-written-text-color, #ffffff);\n\n --aia-submit-bg: var(--aia-primitive-neutral-1000);\n --aia-submit-color: var(--aia-primitive-neutral-0);\n\n --aia-color-text-muted: #c1c4cb; /* off shared palette (slate) */\n\n --aia-skeleton-bg: var(--aia-primitive-neutral-300);\n\n --aia-streak-rgb: 255, 255, 255;\n --aia-streak-glass-bg: rgba(255, 255, 255, 0.1);\n\n --aia-footer-hint-color: var(--aia-primitive-neutral-700);\n --aia-footer-brand-color: var(--aia-primitive-neutral-500);\n --aia-footer-badge-border: var(--aia-primitive-neutral-500);\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 Two forms are supported:\n 1. ancestor form — Tier 1 sets data-options-position on the .magicx-aia\n container and the dropdown is a descendant.\n 2. self form — headless consumers spread \\`optionsPosition\\` from the hook's\n dropdownProps, so the attribute lands on the dropdown element itself.\n This lets the dropdown position above with NO wrapper attribute and no\n hand-copied CSS. */\n:where(.magicx-aia[data-options-position=\"above\"]) [data-aia-dropdown],\n[data-aia-dropdown][data-options-position=\"above\"] {\n top: auto;\n bottom: 100%;\n margin-top: 0;\n margin-bottom: var(--aia-dropdown-offset, 13px);\n}\n\n:where(.magicx-aia[data-options-position=\"above\"]) [data-aia-dropdown] .aia-stack,\n[data-aia-dropdown][data-options-position=\"above\"] .aia-stack {\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-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: 544px;\n /* Gap between the input box and the dropdown. Tunable via --aia-dropdown-offset. */\n margin-top: var(--aia-dropdown-offset, 13px);\n display: flex;\n flex-direction: column;\n box-sizing: border-box;\n padding: 10px 8px;\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-dropdown-border, #e5e7eb);\n border-radius: 18px;\n box-shadow: var(--aia-dropdown-shadow, 0 8px 12px rgba(0, 0, 0, 0.1));\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 container owns the 10px/8px edge padding and the 8px section\n gaps (matching Figma); the pill row adds none — just horizontal scroll + fade. */\n.AIAutocompleteDropdown-module_pillBar_pwTXe {\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: 7px 8px;\n}\n\n.AIAutocompleteDropdown-module_skeletonBar_O3xIx {\n display: block;\n height: 14px;\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 an option is currently highlighted. Takes priority: when true the\n * hint reads \"enter to proceed\".\n */\n isOptionHighlighted?: boolean;\n /**\n * Whether the input has no typed text. When true (and no option is\n * highlighted) the hint reads \"tab to select\" — see {@link getFooterHint}.\n */\n isInputEmpty?: boolean;\n}\n\n// Dropdown chrome: a keyboard hint on the left, AI-Autocomplete branding on the\n// right.\nexport function DropdownFooter({\n isOptionHighlighted = false,\n isInputEmpty = false,\n}: DropdownFooterProps) {\n const { key, hint } = getFooterHint(isOptionHighlighted, isInputEmpty);\n return (\n <footer className={styles.footer} data-aia-footer=\"\">\n <Cluster justify=\"between\" noWrap className={styles.row}>\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 adds its own 8px horizontal inset so it stays clear of the\n dropdown's rounded edges. The top inset (--aia-footer-gap) adds breathing\n room above the hint/branding row so the footer doesn't butt against the last\n option row — additive to the dropdown's 8px section gap. */\n.DropdownFooter-module_footer_qQQ7x {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: var(--aia-footer-gap, 8px) 8px 0;\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: 11px;\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: 11px;\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.5px 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/* Mobile footer variant (Figma \"Mobile\"): on phone-width viewports drop the\n keyboard hint (\"tab to select\" is meaningless on touch), leaving only the\n AI-Autocomplete brand pinned to the right. */\n@media (max-width: 768px) {\n .DropdownFooter-module_hintGroup_ZzbPf {\n display: none;\n }\n .DropdownFooter-module_row_BgZ6Q {\n justify-content: flex-end;\n }\n}\n`;\n document.head.appendChild(s);\n}\nexport default {\"footer\":\"DropdownFooter-module_footer_qQQ7x\",\"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\",\"row\":\"DropdownFooter-module_row_BgZ6Q\"};","if (typeof document !== \"undefined\" && !document.getElementById(\"ac-style-199d0432\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-199d0432\";\n s.textContent = `/* ParamPill (Figma \"ParamPill\") — unfilled suggestion pill: transparent fill\n with a dashed border. ~28px via 6px padding + 14px text + the 1px border\n (border-box). */\n.ParamPill-module_pill_6Ga7S {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 6px;\n border: 1px dashed var(--aia-pill-border, rgba(189, 189, 189, 0.3));\n border-radius: 999px;\n background: transparent;\n color: var(--aia-pill-color, var(--aia-color-text-muted, #c1c4cb));\n font-family: inherit;\n font-size: var(--aia-pill-font-size, 14px);\n font-weight: 500;\n line-height: normal;\n cursor: pointer;\n white-space: nowrap;\n animation: ParamPill-module_fadeIn_Ux4eQ 400ms cubic-bezier(0.4, 0, 0.2, 1) forwards;\n}\n\n.ParamPill-module_rounded_y7xA9 {\n border-radius: 999px;\n}\n\n/* Loading skeleton — preserves the pill's exact box (same width and height)\n and hides the text. The base pill is now transparent, so fill the interior\n with the skeleton color (inside the dashed border) and pulse it so it still\n reads as a loading chip. */\n.ParamPill-module_skeleton_57P0T {\n pointer-events: none;\n cursor: default;\n color: transparent;\n background: var(--aia-skeleton-bg, var(--aia-pill-bg, rgba(189, 189, 189, 0.51)));\n animation: ParamPill-module_skeletonPulse_xGcUy 1.4s ease-in-out infinite;\n}\n\n@keyframes ParamPill-module_skeletonPulse_xGcUy {\n 0%,\n 100% {\n filter: brightness(1);\n }\n 50% {\n filter: brightness(0.55);\n }\n}\n\n@keyframes ParamPill-module_fadeIn_Ux4eQ {\n from {\n opacity: 0;\n }\n}\n`;\n document.head.appendChild(s);\n}\nexport default {\"pill\":\"ParamPill-module_pill_6Ga7S\",\"fadeIn\":\"ParamPill-module_fadeIn_Ux4eQ\",\"rounded\":\"ParamPill-module_rounded_y7xA9\",\"skeleton\":\"ParamPill-module_skeleton_57P0T\",\"skeletonPulse\":\"ParamPill-module_skeletonPulse_xGcUy\"};","import type { MouseEvent } from \"react\";\nimport styles from \"./ParamPill.module.css\";\n\n/**\n * Visual emphasis tier for a pill. The selected (active) pill renders in the\n * `selected` state; every other pill takes its tier from its position in the\n * upcoming-params sequence — `first`, `next`, then `last` for the rest —\n * progressively de-emphasized.\n */\nexport type PillState = \"selected\" | \"first\" | \"next\" | \"last\";\n\n/** Opacity applied per state. Kept here so `PillList` skeletons stay in sync. */\nexport const PARAM_PILL_OPACITY: Record<PillState, number> = {\n selected: 1,\n first: 0.7,\n next: 0.4,\n last: 0.2,\n};\n\ninterface ParamPillProps {\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\n/**\n * ParamPill — the unfilled suggestion pill (Figma component \"ParamPill\",\n * formerly \"Pill\"). Rendered in the dropdown pill-bar and the inline pill list.\n */\nexport function ParamPill({ label, state, rounded, loading, onClick }: ParamPillProps) {\n const className = [styles.pill, rounded ? styles.rounded : \"\", loading ? styles.skeleton : \"\"]\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: PARAM_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 padding: 0 8px;\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 { PARAM_PILL_OPACITY, ParamPill, type PillState } from \"./ParamPill\";\nimport pillStyles from \"./ParamPill.module.css\";\nimport styles from \"./PillList.module.css\";\n\ninterface PillListProps {\n pills: Suggestion[];\n activePillIndex: number;\n onSelectPill: (index: number) => void;\n /**\n * Whether the active pill should render in the `selected` state (full\n * opacity) rather than its positional `first` tier. In `auto` dropdown mode\n * this is true only while a dropdown option is highlighted; in `manual` mode\n * it becomes true once the user taps a pill. Default: false.\n */\n activeSelected?: boolean;\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/**\n * Map a pill's index to its positional emphasis tier. The selected (active)\n * pill is handled separately — only the at-most-three positions get a tier\n * here: first, next, then last for everything after.\n */\nfunction pillStateForIndex(index: number): PillState {\n if (index === 0) return \"first\";\n if (index === 1) return \"next\";\n return \"last\";\n}\n\nexport function PillList({\n pills,\n activePillIndex,\n onSelectPill,\n activeSelected,\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: PARAM_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 // The active pill is \"selected\" only when activeSelected is set;\n // otherwise it shows its positional tier (first/next/last).\n const selected = Boolean(activeSelected) && i === activePillIndex;\n return (\n <ParamPill\n key={`${pill.type}-${pill.text}`}\n label={pill.text}\n state={selected ? \"selected\" : pillStateForIndex(i)}\n selected={selected}\n rounded={rounded}\n loading={loading}\n onClick={() => onSelectPill(i)}\n />\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 `120px`. */\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, 120px);\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 gradient overlay shown while the grid overflows\n below: overflowing options fade into the dropdown surface color. */\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: 30%;\n pointer-events: none;\n opacity: 0;\n transition: opacity 150ms ease-out;\n background: linear-gradient(to bottom, transparent, var(--aia-surface, #ffffff));\n }\n .aia-grid-fade[data-fade]::after {\n opacity: 1;\n }\n\n /* Glass surface has no solid color to fade into, so skip the fade entirely. */\n [data-aia-surface=\"glass\"] .aia-grid-fade::after {\n display: none;\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, 14px);\n font-weight: 300;\n line-height: 18px;\n color: var(--aia-option-color, var(--aia-color-text-muted, #c1c4cb));\n white-space: normal;\n word-break: break-word;\n /* 8px radius on the highlighted fill (--aia-option-bg), matching the Figma\n SuggestionItem selection. The 7px/8px inset is the item's own padding. */\n border-radius: 8px;\n padding: 7px 8px;\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 font-weight: 500;\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","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: 32px;\n height: 32px;\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/* Disabled (empty input) keeps the solid themed look by default — the disabled\n tokens fall back to the enabled ones, so a consumer's themed color is never\n washed out. Opt into a faded/dimmed rest state by setting\n --aia-submit-bg-disabled / --aia-submit-color-disabled. */\n.SubmitButton-module_submitButton_otz7H:disabled {\n background: var(\n --aia-submit-bg-disabled,\n var(--aia-submit-bg, var(--aia-color-text-default, #fff))\n );\n color: var(\n --aia-submit-color-disabled,\n var(--aia-submit-color, var(--aia-color-bg-default, #000))\n );\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 isActivePillSelected: 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 isActivePillSelected: state.isActivePillSelected,\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 activeSelected: state.isActivePillSelected,\n onPillClick: actions.setActivePill,\n isLoading: uiLoading,\n isInputEmpty: text.trim().length === 0,\n // Flow the configured position into the dropdown so a headless consumer\n // who spreads `dropdownProps` gets above/below placement + layout reversal\n // automatically — no wrapper attribute or hand-copied CSS required.\n optionsPosition: optionsPosition ?? \"below\",\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 // Focusing an empty contentEditable doesn't always create a selection\n // Range, so no caret blinks until the user clicks. Place a collapsed caret\n // at the start so the field is visibly ready immediately. Skip if the caret\n // already sits inside the editor (e.g. the user clicked before this ran).\n const doc = el.ownerDocument ?? document;\n const sel = doc.getSelection();\n const caretInside = sel && sel.rangeCount > 0 && el.contains(sel.anchorNode);\n if (sel && !caretInside) {\n const range = doc.createRange();\n range.selectNodeContents(el);\n range.collapse(true);\n sel.removeAllRanges();\n sel.addRange(range);\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":["forwardRef","useCallback","useEffect","useImperativeHandle","useLayoutEffect","useRef","s","AIAutocomplete_module_css_default","useEffect","useRef","useState","s","s","AIAutocompleteDropdown_module_css_default","getFooterHint","s","jsx","Cluster","gap","align","justify","noWrap","inline","className","children","rest","style","props","s","DropdownFooter_module_css_default","jsx","jsxs","DropdownFooter","isOptionHighlighted","isInputEmpty","key","hint","getFooterHint","DropdownFooter_module_css_default","Cluster","s","ParamPill_module_css_default","jsx","PARAM_PILL_OPACITY","ParamPill","label","state","rounded","loading","onClick","className","ParamPill_module_css_default","e","s","PillList_module_css_default","jsx","FALLBACK_SKELETON_WIDTHS","pillStateForIndex","index","PillList","pills","activePillIndex","onSelectPill","activeSelected","rounded","loading","PillList_module_css_default","w","i","ParamPill_module_css_default","PARAM_PILL_OPACITY","pill","selected","ParamPill","useEffect","useLayoutEffect","useRef","useState","s","jsx","Grid","min","max","gap","scroll","maxHeight","fade","className","children","rest","gridRef","useRef","hasBottomOverflow","setHasBottomOverflow","useState","useEffect","el","update","resizeObserver","useLayoutEffect","style","grid","useEffect","useRef","useState","s","SuggestionItem_module_css_default","jsx","jsxs","SuggestionItem","option","isHighlighted","onSelect","onHighlight","id","loading","pressed","setPressed","useState","timerRef","useRef","useEffect","handleSelect","className","SuggestionItem_module_css_default","e","jsx","SuggestionGrid","options","activeIndex","onSelect","onHighlight","listboxId","loading","Grid","option","i","SuggestionItem","s","jsx","Stack","space","align","className","children","rest","style","jsx","jsxs","FALLBACK_SKELETON_BAR_WIDTHS","useResolvedMode","mode","prefersDark","systemDark","setSystemDark","useState","useEffect","mq","onChange","AIAutocompleteDropdown","suggestions","activeIndex","onSelect","onHighlight","isOpen","id","className","pills","onPillClick","showPills","activeSelected","isLoading","isInputEmpty","optionsPosition","resolvedMode","selfScope","liveOptions","liveHasRealPills","isVisible","snapshot","lastVisibleRef","useRef","content","options","isOptionHighlighted","hasRealPills","showsRealPills","showsLoadingPills","showsPillBar","showsOptions","showsFallbackSkeleton","AIAutocompleteDropdown_module_css_default","e","Stack","Cluster","PillList","SuggestionGrid","w","DropdownFooter","buildQuery","ModeController","setCursorOffset","s","SubmitButton_module_css_default","jsx","SubmitButton","disabled","onClick","SubmitButton_module_css_default","e","CoreAIAutocomplete","useCallback","useEffect","useRef","useState","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","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","extractPlainText","getCursorOffset","plainTextLength","renderEditableContent","setCursorOffset","useCallback","useEffect","useLayoutEffect","useRef","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","sel","caretInside","range","onSelectionChange","anchor","enclosing","previous","current","desired","fireInput","raw","next","handleInputEvent","onBeforeInput","e","inputEvent","t","replacement","handleCompositionStart","handleCompositionEnd","handlePaste","text","node","handleKeyDownReact","handleFocus","handleBlur","focus","blur","getPlainText","ceMode","jsx","jsxs","resolveInitialMode","mode","AIAutocomplete","forwardRef","onSubmit","onError","optionOverrides","maskCompletedText","className","apiConfig","columns","pillPlacement","optionsPosition","animations","dropdownTrigger","closeDropdownOnBlur","showNonTappableOptions","autoFocus","onFocus","onBlur","value","controlledParams","onChangeProp","onParamsChange","submitButton","ref","containerRef","useRef","pillContainerRef","handleSubmitRef","modeControllerRef","editorInputRefHolder","useEffect","el","ModeController","handleSetCursor","useCallback","offset","setCursorOffset","completedParams","suggestionPills","setActivePill","segments","newParamId","clearNewParamId","placeholderText","isFocused","isDropdownOpen","isActivePillSelected","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","useLayoutEffect","container","editor","update","inner","cRect","eRect","ro","useImperativeHandle","m","canSubmit","handleSubmit","text","rawQuery","finalParams","buildQuery","handleWrapperClick","e","showInlinePills","showDropdownPills","AIAutocomplete_module_css_default","AIAutocompleteDropdown","PillList","SubmitButton"]}
1
+ {"version":3,"sources":["../src/AIAutocomplete.tsx","css-module:/home/runner/work/ai-autocomplete-sdk-js/ai-autocomplete-sdk-js/packages/react/src/AIAutocomplete.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","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/ParamPill.module.css.js","../src/components/ParamPill.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","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":["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 = \"dropdown\",\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 isActivePillSelected,\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 activeSelected={isActivePillSelected}\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: 12px 16px;\n border: 1px solid var(--aia-border, #b0b0b0);\n border-radius: 20px;\n background: var(--aia-surface, #ffffff);\n box-shadow: var(--aia-shadow, none);\n overflow: hidden;\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.AIAutocomplete-module_editorArea_7rBWq {\n position: relative;\n flex: 1;\n min-width: 0;\n min-height: 19px;\n line-height: 19px;\n font-family: inherit;\n font-size: var(--aia-written-text-font-size, 14px);\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: 300;\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 pills (Figma \"RichTextPill\") — a compact\n ~26px chip with regular-weight primary-color text on a faint-gray fill.\n inline-block gives the padding/radius a box while the text stays part of the\n editable plain text (the caret system counts characters inside this\n <strong>). The completed class is stamped by the shared renderer as a global\n string, so match it via [class~=] to bypass CSS Modules' hashing. */\n:where(.AIAutocomplete-module_input_IW-P-) strong[class~=\"magicx-aia-segment--completed\"] {\n display: inline-block;\n padding: 4px 6px;\n border-radius: 999px;\n background: var(--aia-completed-pill-bg, rgba(189, 189, 189, 0.15));\n color: var(--aia-completed-pill-color, var(--aia-written-text-color, #fff));\n font-size: var(--aia-pill-font-size, 14px);\n font-weight: 400;\n line-height: normal;\n white-space: nowrap;\n /* Small vertical breathing room so wrapped rows of pills don't touch. */\n margin: 2px 0;\n /* baseline (not middle) so the pill's text shares the surrounding text's\n baseline exactly. middle aligns the chip box to the parent's x-height\n midpoint, which font ascent/descent asymmetry turns into the pill text\n sitting ~1-2px below the adjacent text. The symmetric 4px padding keeps\n the capsule optically centered around the text on its own. */\n vertical-align: baseline;\n cursor: pointer;\n /* Smooth hover fade. Neutralized by the data-animations=\"off\" block. */\n transition: background-color 150ms ease;\n}\n\n/* Hover highlight — a slightly stronger fill so a pointed-at pill reads as\n tappable. Declared between the base and editing rules so editing wins. */\n:where(.AIAutocomplete-module_input_IW-P-) strong[class~=\"magicx-aia-segment--completed\"]:hover {\n background: var(--aia-completed-pill-bg-active, rgba(189, 189, 189, 0.35));\n}\n\n/* Re-edit highlight — applied to the completed pill being re-edited (after a\n tap). Reuses the exact hover fill so the highlight persists from tap until an\n option is selected. Hides the native caret; cursor switches to text since the\n pill is in text-replacement mode. The editing class is written by the shared\n renderer (a global string), so target it via an attribute selector to bypass\n CSS Modules' hashing. Declared last so it wins on a strong carrying both\n classes. */\n:where(.AIAutocomplete-module_input_IW-P-) strong[class~=\"magicx-aia-segment--editing\"] {\n background: var(--aia-completed-pill-bg-active, rgba(189, 189, 189, 0.35));\n caret-color: transparent;\n cursor: text;\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/* Promotion reveal on a newly promoted completed param. The shared renderer\n (core/render/renderEditable.ts) stamps the global shimmer classes onto the\n just-added <strong>; we match them via [class~=] to bypass CSS Modules'\n hashing. Completed params are now pills with a solid background, so the old\n text-clip gradient shimmer can't be used (background-clip: text would wipe\n the pill background). The reveal is a simple fade-in of the whole pill,\n riding on shimmer-sweep so it only plays on genuine promotions. */\n:where(.AIAutocomplete-module_input_IW-P-) strong[class~=\"magicx-aia-shimmer-sweep\"] {\n animation: AIAutocomplete-module_aiaPillReveal_wf05b 400ms cubic-bezier(0.4, 0, 0.2, 1) forwards;\n}\n\n@keyframes AIAutocomplete-module_aiaPillReveal_wf05b {\n from {\n opacity: 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\",\"aiaPillReveal\":\"AIAutocomplete-module_aiaPillReveal_wf05b\"};","import { useEffect, useRef, useState } from \"react\";\n// Self-inject the appearance layer (design tokens, box-sizing reset, and the\n// optionsPosition=\"above\" layout-reversal rules). Tier 1 already imports this,\n// but headless consumers render only this dropdown — importing it here means\n// they get correct styling and a working `optionsPosition` with no extra setup.\nimport \"./appearance.css\";\nimport 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\n/**\n * Resolve the `mode` prop to a concrete `\"light\" | \"dark\"` (or `undefined` when\n * unset, meaning \"don't self-scope — inherit from a `.magicx-aia` ancestor\").\n * `\"auto\"` tracks `prefers-color-scheme` live.\n */\nfunction useResolvedMode(\n mode: \"light\" | \"dark\" | \"auto\" | undefined,\n): \"light\" | \"dark\" | undefined {\n const prefersDark = () =>\n typeof window !== \"undefined\" &&\n typeof window.matchMedia === \"function\" &&\n window.matchMedia(\"(prefers-color-scheme: dark)\").matches;\n const [systemDark, setSystemDark] = useState(prefersDark);\n\n useEffect(() => {\n if (\n mode !== \"auto\" ||\n typeof window === \"undefined\" ||\n typeof window.matchMedia !== \"function\"\n ) {\n return;\n }\n const mq = window.matchMedia(\"(prefers-color-scheme: dark)\");\n const onChange = () => setSystemDark(mq.matches);\n mq.addEventListener(\"change\", onChange);\n return () => mq.removeEventListener(\"change\", onChange);\n }, [mode]);\n\n if (mode === undefined) return undefined;\n if (mode === \"auto\") return systemDark ? \"dark\" : \"light\";\n return mode;\n}\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 activeSelected = false,\n isLoading = false,\n isInputEmpty = false,\n optionsPosition = \"below\",\n mode,\n}: AIAutocompleteDropdownProps) {\n // When `mode` is set, self-scope: add `magicx-aia` + `data-mode` to our own\n // root so the dropdown is styled without a `.magicx-aia` wrapper. When unset,\n // stay class-less and inherit from an ancestor (Tier 1 / a custom wrapper).\n const resolvedMode = useResolvedMode(mode);\n const selfScope = resolvedMode !== undefined;\n\n // Visibility is computed from the CURRENT props and drives the opacity fade.\n const liveOptions = suggestions[0]?.options ?? [];\n const liveHasRealPills = Boolean(pills && pills.length > 0 && onPillClick);\n const isVisible =\n isOpen && (liveOptions.length > 0 || (showPills && liveHasRealPills) || isLoading);\n\n // Freeze the content-driving values while the dropdown is open. When it\n // closes we render this frozen snapshot during the 400ms opacity fade, so the\n // whole populated dropdown fades out as one. Otherwise the pills/options\n // unmount the instant the underlying state empties (e.g. skipping the last\n // pill with →), leaving the always-present footer alone for a flash of a\n // footer-only \"no options\" box. Content is refreshed on the next open.\n const snapshot = {\n suggestions,\n activeIndex,\n pills,\n showPills,\n activeSelected,\n isLoading,\n isInputEmpty,\n };\n const lastVisibleRef = useRef(snapshot);\n if (isVisible) lastVisibleRef.current = snapshot;\n const content = isVisible ? snapshot : lastVisibleRef.current;\n\n const activeSuggestion = content.suggestions[0];\n const options = activeSuggestion?.options ?? [];\n const isOptionHighlighted =\n content.activeIndex >= 0 && Boolean(options[content.activeIndex]?.is_tappable);\n const hasRealPills = Boolean(content.pills && content.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 = content.showPills && hasRealPills;\n const showsLoadingPills = content.showPills && !hasRealPills && content.isLoading;\n const showsPillBar = showsRealPills || showsLoadingPills;\n const showsOptions = options.length > 0;\n const showsFallbackSkeleton = content.isLoading && !showsOptions;\n\n return (\n <div\n id={id}\n role=\"listbox\"\n data-aia-dropdown=\"\"\n data-options-position={optionsPosition}\n data-mode={resolvedMode}\n data-aia-loading={content.isLoading ? \"\" : undefined}\n className={`${selfScope ? \"magicx-aia \" : \"\"}${styles.dropdown} ${isVisible ? styles.visible : \"\"} ${className ?? \"\"}`}\n onMouseDown={(e) => e.preventDefault()}\n >\n <Stack space=\"8px\">\n {showsPillBar && (\n <Cluster noWrap className={styles.pillBar} data-aia-pillbar=\"\">\n <PillList\n pills={content.pills ?? []}\n activePillIndex={0}\n activeSelected={content.activeSelected}\n onSelectPill={onPillClick ?? (() => {})}\n rounded\n loading={content.isLoading}\n />\n </Cluster>\n )}\n {showsOptions && (\n <SuggestionGrid\n options={options}\n activeIndex={content.activeIndex}\n onSelect={onSelect}\n onHighlight={onHighlight}\n listboxId={id}\n loading={content.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 isOptionHighlighted={isOptionHighlighted}\n isInputEmpty={content.isInputEmpty}\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/*\n * Primitive color ramp — single source of truth, mirroring the Figma\n * \"Primitives\" collection. INTERNAL: theme via the public --aia-* vars below,\n * not these. Mode-independent (raw values; the same in light and dark).\n */\n:where(.magicx-aia) {\n --aia-primitive-neutral-0: #000000;\n --aia-primitive-neutral-250: #323232;\n --aia-primitive-neutral-300: #333539;\n --aia-primitive-neutral-400: #4a4a4a;\n --aia-primitive-neutral-500: #505050;\n --aia-primitive-neutral-700: #b0b0b0;\n --aia-primitive-neutral-750: #bdbdbd;\n --aia-primitive-neutral-900: #e7e7e7;\n --aia-primitive-neutral-1000: #ffffff;\n --aia-primitive-blue-50: #eef2ff;\n --aia-primitive-neutral-750-a50: rgba(189, 189, 189, 0.51);\n --aia-primitive-neutral-750-a35: rgba(189, 189, 189, 0.35);\n --aia-primitive-neutral-750-a30: rgba(189, 189, 189, 0.3);\n --aia-primitive-neutral-750-a15: rgba(189, 189, 189, 0.15);\n --aia-primitive-neutral-700-a40: rgba(176, 176, 176, 0.4);\n}\n\n/* Light mode defaults (base) — public --aia-* vars resolve to primitives */\n:where(.magicx-aia),\n:where(.magicx-aia[data-mode=\"light\"]) {\n --aia-surface: var(--aia-primitive-neutral-1000);\n --aia-border: rgba(17, 24, 39, 0.14); /* subtle slate hairline (off-palette) */\n /* Elevation for the input container (.inputWrapper). */\n --aia-shadow:\n inset 0 1px 0 rgba(255, 255, 255, 0.9), 0 1px 2px rgba(16, 24, 40, 0.1),\n 0 8px 24px rgba(16, 24, 40, 0.16);\n --aia-dropdown-border: var(\n --aia-primitive-neutral-900\n ); /* was #e5e7eb — snapped to palette (Δ2) */\n --aia-dropdown-shadow: 0 8px 12px rgba(0, 0, 0, 0.1);\n /* Suggestion pills (Figma \"ParamPill\"): transparent fill + dashed border;\n per-pill opacity via getPillOpacity. */\n --aia-pill-bg: var(--aia-primitive-neutral-750);\n --aia-pill-color: var(--aia-primitive-neutral-300);\n --aia-pill-border: var(--aia-primitive-neutral-750-a30);\n --aia-pill-font-size: 14px;\n\n /* Completed params (Figma \"RichTextPill\"): compact faint-gray chip with\n primary-color regular-weight text. -active is the hover / tapped (re-edit)\n highlight — an alpha over the input background, so one value works in both\n themes. */\n --aia-completed-pill-bg: var(--aia-primitive-neutral-750-a15);\n --aia-completed-pill-bg-active: var(--aia-primitive-neutral-750-a35);\n --aia-completed-pill-color: var(--aia-primitive-neutral-0);\n\n --aia-option-bg: var(--aia-primitive-blue-50);\n --aia-option-color: var(--aia-primitive-neutral-500);\n --aia-option-color-selected: var(--aia-primitive-neutral-0);\n --aia-option-font-size: 14px;\n\n --aia-written-text-color: var(--aia-primitive-neutral-0);\n --aia-written-text-font-size: 14px;\n --aia-caret-color: var(--aia-written-text-color, #000000);\n\n --aia-submit-bg: var(--aia-primitive-neutral-0);\n --aia-submit-color: var(--aia-primitive-neutral-1000);\n\n --aia-color-text-muted: #6b7280; /* off shared palette (slate) */\n\n --aia-skeleton-bg: var(--aia-primitive-neutral-750-a50);\n\n --aia-streak-rgb: 99, 102, 241; /* off shared palette (indigo effect) */\n --aia-streak-glass-bg: rgba(99, 102, 241, 0.1);\n\n --aia-footer-hint-color: var(--aia-primitive-neutral-500);\n --aia-footer-brand-color: var(--aia-primitive-neutral-700);\n --aia-footer-badge-border: var(--aia-primitive-neutral-750-a50);\n}\n\n/* Dark mode defaults */\n:where(.magicx-aia[data-mode=\"dark\"]) {\n --aia-surface: var(--aia-primitive-neutral-0);\n --aia-border: var(--aia-primitive-neutral-500);\n /* Elevation for the input container (.inputWrapper) — tuned for dark surfaces:\n a faint top highlight + deeper ambient shadows. */\n --aia-shadow:\n inset 0 1px 0 rgba(255, 255, 255, 0.06), 0 1px 2px rgba(0, 0, 0, 0.4),\n 0 8px 24px rgba(0, 0, 0, 0.5);\n --aia-dropdown-border: var(\n --aia-primitive-neutral-400\n ); /* was #484848 — snapped to palette (Δ2) */\n --aia-dropdown-shadow: 0 8px 12px rgba(0, 0, 0, 0.1);\n /* Suggestion pills (Figma \"ParamPill\"): transparent fill + dashed border. */\n --aia-pill-bg: var(--aia-primitive-neutral-750);\n --aia-pill-color: var(--aia-primitive-neutral-700);\n --aia-pill-border: var(--aia-primitive-neutral-750-a30);\n --aia-pill-font-size: 14px;\n\n /* Completed params (Figma \"RichTextPill\") — dark theme (design source):\n white text on a faint-gray chip. -active is the hover / tapped highlight. */\n --aia-completed-pill-bg: var(--aia-primitive-neutral-750-a15);\n --aia-completed-pill-bg-active: var(--aia-primitive-neutral-750-a35);\n --aia-completed-pill-color: var(--aia-primitive-neutral-1000);\n\n --aia-option-bg: var(--aia-primitive-neutral-250);\n --aia-option-color: var(--aia-primitive-neutral-700);\n --aia-option-color-selected: var(--aia-primitive-neutral-1000);\n --aia-option-font-size: 14px;\n\n --aia-written-text-color: var(--aia-primitive-neutral-1000);\n --aia-written-text-font-size: 14px;\n --aia-caret-color: var(--aia-written-text-color, #ffffff);\n\n --aia-submit-bg: var(--aia-primitive-neutral-1000);\n --aia-submit-color: var(--aia-primitive-neutral-0);\n\n --aia-color-text-muted: #c1c4cb; /* off shared palette (slate) */\n\n --aia-skeleton-bg: var(--aia-primitive-neutral-300);\n\n --aia-streak-rgb: 255, 255, 255;\n --aia-streak-glass-bg: rgba(255, 255, 255, 0.1);\n\n --aia-footer-hint-color: var(--aia-primitive-neutral-700);\n --aia-footer-brand-color: var(--aia-primitive-neutral-500);\n --aia-footer-badge-border: var(--aia-primitive-neutral-500);\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 Two forms are supported:\n 1. ancestor form — Tier 1 sets data-options-position on the .magicx-aia\n container and the dropdown is a descendant.\n 2. self form — headless consumers spread \\`optionsPosition\\` from the hook's\n dropdownProps, so the attribute lands on the dropdown element itself.\n This lets the dropdown position above with NO wrapper attribute and no\n hand-copied CSS. */\n:where(.magicx-aia[data-options-position=\"above\"]) [data-aia-dropdown],\n[data-aia-dropdown][data-options-position=\"above\"] {\n top: auto;\n bottom: 100%;\n margin-top: 0;\n margin-bottom: var(--aia-dropdown-offset, 13px);\n}\n\n:where(.magicx-aia[data-options-position=\"above\"]) [data-aia-dropdown] .aia-stack,\n[data-aia-dropdown][data-options-position=\"above\"] .aia-stack {\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-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: 544px;\n /* Gap between the input box and the dropdown. Tunable via --aia-dropdown-offset. */\n margin-top: var(--aia-dropdown-offset, 13px);\n display: flex;\n flex-direction: column;\n box-sizing: border-box;\n padding: 10px 8px;\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-dropdown-border, #e5e7eb);\n border-radius: 18px;\n box-shadow: var(--aia-dropdown-shadow, 0 8px 12px rgba(0, 0, 0, 0.1));\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 container owns the 10px/8px edge padding and the 8px section\n gaps (matching Figma); the pill row adds none — just horizontal scroll + fade. */\n.AIAutocompleteDropdown-module_pillBar_pwTXe {\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: 7px 8px;\n}\n\n.AIAutocompleteDropdown-module_skeletonBar_O3xIx {\n display: block;\n height: 14px;\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 {\n ATTRIBUTION_URL,\n buildAttributionUrl,\n getFooterHint,\n} from \"@magicx-eng/ai-autocomplete-vanilla\";\nimport { useEffect, useState } from \"react\";\nimport { Cluster } from \"../layout/Cluster\";\nimport styles from \"./DropdownFooter.module.css\";\n\ninterface DropdownFooterProps {\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 * Whether the input has no typed text. When true (and no option is\n * highlighted) the hint reads \"tab to select\" — see {@link getFooterHint}.\n */\n isInputEmpty?: boolean;\n}\n\n// Dropdown chrome: a keyboard hint on the left, AI-Autocomplete branding on the\n// right.\nexport function DropdownFooter({\n isOptionHighlighted = false,\n isInputEmpty = false,\n}: DropdownFooterProps) {\n const { key, hint } = getFooterHint(isOptionHighlighted, isInputEmpty);\n // Initial state is the bare base URL so it matches server-rendered output (no\n // hydration mismatch); the effect appends utm_source after mount on the client.\n const [brandHref, setBrandHref] = useState(ATTRIBUTION_URL);\n useEffect(() => {\n setBrandHref(buildAttributionUrl());\n }, []);\n return (\n <footer className={styles.footer} data-aia-footer=\"\">\n <Cluster justify=\"between\" noWrap className={styles.row}>\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 className={styles.brandLink} href={brandHref} target=\"_blank\" rel=\"noopener noreferrer\">\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 adds its own 8px horizontal inset so it stays clear of the\n dropdown's rounded edges. The top inset (--aia-footer-gap) adds breathing\n room above the hint/branding row so the footer doesn't butt against the last\n option row — additive to the dropdown's 8px section gap. */\n.DropdownFooter-module_footer_qQQ7x {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: var(--aia-footer-gap, 8px) 8px 0;\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: 11px;\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: 11px;\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.5px 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/* Mobile footer variant (Figma \"Mobile\"): on phone-width viewports drop the\n keyboard hint (\"tab to select\" is meaningless on touch), leaving only the\n AI-Autocomplete brand pinned to the right. */\n@media (max-width: 768px) {\n .DropdownFooter-module_hintGroup_ZzbPf {\n display: none;\n }\n .DropdownFooter-module_row_BgZ6Q {\n justify-content: flex-end;\n }\n}\n`;\n document.head.appendChild(s);\n}\nexport default {\"footer\":\"DropdownFooter-module_footer_qQQ7x\",\"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\",\"row\":\"DropdownFooter-module_row_BgZ6Q\"};","if (typeof document !== \"undefined\" && !document.getElementById(\"ac-style-199d0432\")) {\n const s = document.createElement(\"style\");\n s.id = \"ac-style-199d0432\";\n s.textContent = `/* ParamPill (Figma \"ParamPill\") — unfilled suggestion pill: transparent fill\n with a dashed border. ~28px via 6px padding + 14px text + the 1px border\n (border-box). */\n.ParamPill-module_pill_6Ga7S {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 6px;\n border: 1px dashed var(--aia-pill-border, rgba(189, 189, 189, 0.3));\n border-radius: 999px;\n background: transparent;\n color: var(--aia-pill-color, var(--aia-color-text-muted, #c1c4cb));\n font-family: inherit;\n font-size: var(--aia-pill-font-size, 14px);\n font-weight: 500;\n line-height: normal;\n cursor: pointer;\n white-space: nowrap;\n animation: ParamPill-module_fadeIn_Ux4eQ 400ms cubic-bezier(0.4, 0, 0.2, 1) forwards;\n}\n\n.ParamPill-module_rounded_y7xA9 {\n border-radius: 999px;\n}\n\n/* Loading skeleton — preserves the pill's exact box (same width and height)\n and hides the text. The base pill is now transparent, so fill the interior\n with the skeleton color (inside the dashed border) and pulse it so it still\n reads as a loading chip. */\n.ParamPill-module_skeleton_57P0T {\n pointer-events: none;\n cursor: default;\n color: transparent;\n background: var(--aia-skeleton-bg, var(--aia-pill-bg, rgba(189, 189, 189, 0.51)));\n animation: ParamPill-module_skeletonPulse_xGcUy 1.4s ease-in-out infinite;\n}\n\n@keyframes ParamPill-module_skeletonPulse_xGcUy {\n 0%,\n 100% {\n filter: brightness(1);\n }\n 50% {\n filter: brightness(0.55);\n }\n}\n\n@keyframes ParamPill-module_fadeIn_Ux4eQ {\n from {\n opacity: 0;\n }\n}\n`;\n document.head.appendChild(s);\n}\nexport default {\"pill\":\"ParamPill-module_pill_6Ga7S\",\"fadeIn\":\"ParamPill-module_fadeIn_Ux4eQ\",\"rounded\":\"ParamPill-module_rounded_y7xA9\",\"skeleton\":\"ParamPill-module_skeleton_57P0T\",\"skeletonPulse\":\"ParamPill-module_skeletonPulse_xGcUy\"};","import type { MouseEvent } from \"react\";\nimport styles from \"./ParamPill.module.css\";\n\n/**\n * Visual emphasis tier for a pill. The selected (active) pill renders in the\n * `selected` state; every other pill takes its tier from its position in the\n * upcoming-params sequence — `first`, `next`, then `last` for the rest —\n * progressively de-emphasized.\n */\nexport type PillState = \"selected\" | \"first\" | \"next\" | \"last\";\n\n/** Opacity applied per state. Kept here so `PillList` skeletons stay in sync. */\nexport const PARAM_PILL_OPACITY: Record<PillState, number> = {\n selected: 1,\n first: 0.7,\n next: 0.4,\n last: 0.2,\n};\n\ninterface ParamPillProps {\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\n/**\n * ParamPill — the unfilled suggestion pill (Figma component \"ParamPill\",\n * formerly \"Pill\"). Rendered in the dropdown pill-bar and the inline pill list.\n */\nexport function ParamPill({ label, state, rounded, loading, onClick }: ParamPillProps) {\n const className = [styles.pill, rounded ? styles.rounded : \"\", loading ? styles.skeleton : \"\"]\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: PARAM_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 padding: 0 8px;\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 { PARAM_PILL_OPACITY, ParamPill, type PillState } from \"./ParamPill\";\nimport pillStyles from \"./ParamPill.module.css\";\nimport styles from \"./PillList.module.css\";\n\ninterface PillListProps {\n pills: Suggestion[];\n activePillIndex: number;\n onSelectPill: (index: number) => void;\n /**\n * Whether the active pill should render in the `selected` state (full\n * opacity) rather than its positional `first` tier. In `auto` dropdown mode\n * this is true only while a dropdown option is highlighted; in `manual` mode\n * it becomes true once the user taps a pill. Default: false.\n */\n activeSelected?: boolean;\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/**\n * Map a pill's index to its positional emphasis tier. The selected (active)\n * pill is handled separately — only the at-most-three positions get a tier\n * here: first, next, then last for everything after.\n */\nfunction pillStateForIndex(index: number): PillState {\n if (index === 0) return \"first\";\n if (index === 1) return \"next\";\n return \"last\";\n}\n\nexport function PillList({\n pills,\n activePillIndex,\n onSelectPill,\n activeSelected,\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: PARAM_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 // The active pill is \"selected\" only when activeSelected is set;\n // otherwise it shows its positional tier (first/next/last).\n const selected = Boolean(activeSelected) && i === activePillIndex;\n return (\n <ParamPill\n key={`${pill.type}-${pill.text}`}\n label={pill.text}\n state={selected ? \"selected\" : pillStateForIndex(i)}\n selected={selected}\n rounded={rounded}\n loading={loading}\n onClick={() => onSelectPill(i)}\n />\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 `120px`. */\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, 120px);\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 gradient overlay shown while the grid overflows\n below: overflowing options fade into the dropdown surface color. */\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: 30%;\n pointer-events: none;\n opacity: 0;\n transition: opacity 150ms ease-out;\n background: linear-gradient(to bottom, transparent, var(--aia-surface, #ffffff));\n }\n .aia-grid-fade[data-fade]::after {\n opacity: 1;\n }\n\n /* Glass surface has no solid color to fade into, so skip the fade entirely. */\n [data-aia-surface=\"glass\"] .aia-grid-fade::after {\n display: none;\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, 14px);\n font-weight: 300;\n line-height: 18px;\n color: var(--aia-option-color, var(--aia-color-text-muted, #c1c4cb));\n white-space: normal;\n word-break: break-word;\n /* 8px radius on the highlighted fill (--aia-option-bg), matching the Figma\n SuggestionItem selection. The 7px/8px inset is the item's own padding. */\n border-radius: 8px;\n padding: 7px 8px;\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 font-weight: 500;\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","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: 32px;\n height: 32px;\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/* Disabled (empty input) keeps the solid themed look by default — the disabled\n tokens fall back to the enabled ones, so a consumer's themed color is never\n washed out. Opt into a faded/dimmed rest state by setting\n --aia-submit-bg-disabled / --aia-submit-color-disabled. */\n.SubmitButton-module_submitButton_otz7H:disabled {\n background: var(\n --aia-submit-bg-disabled,\n var(--aia-submit-bg, var(--aia-color-text-default, #fff))\n );\n color: var(\n --aia-submit-color-disabled,\n var(--aia-submit-color, var(--aia-color-bg-default, #000))\n );\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 isActivePillSelected: 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 isActivePillSelected: state.isActivePillSelected,\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 activeSelected: state.isActivePillSelected,\n onPillClick: actions.setActivePill,\n isLoading: uiLoading,\n isInputEmpty: text.trim().length === 0,\n // Flow the configured position into the dropdown so a headless consumer\n // who spreads `dropdownProps` gets above/below placement + layout reversal\n // automatically — no wrapper attribute or hand-copied CSS required.\n optionsPosition: optionsPosition ?? \"below\",\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 // Focusing an empty contentEditable doesn't always create a selection\n // Range, so no caret blinks until the user clicks. Place a collapsed caret\n // at the start so the field is visibly ready immediately. Skip if the caret\n // already sits inside the editor (e.g. the user clicked before this ran).\n const doc = el.ownerDocument ?? document;\n const sel = doc.getSelection();\n const caretInside = sel && sel.rangeCount > 0 && el.contains(sel.anchorNode);\n if (sel && !caretInside) {\n const range = doc.createRange();\n range.selectNodeContents(el);\n range.collapse(true);\n sel.removeAllRanges();\n sel.addRange(range);\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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AAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA+VhB,SAAS,KAAK,YAAYA,CAAC,CAC7B,CACA,IAAOC,EAAQ,CAAC,KAAO,mCAAmC,OAAS,qCAAqC,QAAU,sCAAsC,SAAW,uCAAuC,YAAc,0CAA0C,YAAc,0CAA0C,IAAM,kCAAkC,QAAU,sCAAsC,UAAY,wCAAwC,QAAU,sCAAsC,QAAU,sCAAsC,YAAc,0CAA0C,iBAAmB,+CAA+C,gBAAkB,8CAA8C,aAAe,2CAA2C,eAAiB,6CAA6C,cAAgB,4CAA4C,KAAO,kCAAkC,EDrSv7B,cAAAC,GAEA,QAAAC,OAFA,oBAlDC,SAASC,GAAe,CAC7B,OAAAC,EACA,cAAAC,EACA,SAAAC,EACA,YAAAC,EACA,GAAAC,EACA,QAAAC,CACF,EAAwB,CACtB,GAAM,CAACC,EAASC,CAAU,EAAIC,GAAS,EAAK,EACtCC,EAAWC,GAAkD,MAAS,EAE5EC,GAAU,IACD,IAAM,aAAaF,EAAS,OAAO,EACzC,CAAC,CAAC,EAEL,IAAMG,EAAe,IAAM,CACrBP,GAAW,CAACL,EAAO,aAAeM,IACtCC,EAAW,EAAI,EACfL,EAASF,CAAM,EACf,aAAaS,EAAS,OAAO,EAC7BA,EAAS,QAAU,WAAW,IAAMF,EAAW,EAAK,EAAG,GAAG,EAC5D,EAEMM,EAAY,CAChBC,EAAO,KACPb,GAAiB,CAACI,EAAUS,EAAO,YAAc,GACjDd,EAAO,YAAcc,EAAO,SAAWA,EAAO,YAC9CR,EAAUQ,EAAO,QAAU,EAC7B,EACG,OAAO,OAAO,EACd,KAAK,GAAG,EAEX,OACEhB,GAAC,OACC,GAAIM,EACJ,KAAK,SACL,kBAAgB,GAChB,mBAAkBC,EAAU,GAAK,OACjC,gBAAeJ,EACf,UAAWY,EACX,SAAUR,GAAW,CAACL,EAAO,YAAc,GAAK,EAChD,QAASY,EACT,UAAYG,GAAM,CACZ,CAACV,GAAWL,EAAO,cAAgBe,EAAE,MAAQ,SAAWA,EAAE,MAAQ,OACpEA,EAAE,eAAe,EACjBH,EAAa,EAEjB,EACA,aAAc,CAACP,GAAWL,EAAO,YAAcG,EAAc,OAE7D,UAAAN,GAAC,OAAI,UAAWiB,EAAO,QAAS,EAChCjB,GAAC,OAAI,UAAWiB,EAAO,YAAa,EACpChB,GAAC,QAAK,UAAWgB,EAAO,QACtB,UAAAjB,GAAC,QAAK,UAAWiB,EAAO,KACrB,SAAAd,EAAO,KAAO,GAAGA,EAAO,IAAI,IAAIA,EAAO,IAAI,GAAKA,EAAO,KAC1D,EACCA,EAAO,KAAOH,GAAC,QAAK,UAAWiB,EAAO,IAAM,SAAAd,EAAO,IAAI,GAC1D,GACF,CAEJ,CE3CQ,cAAAgB,OAAA,oBAXD,SAASC,GAAe,CAC7B,QAAAC,EACA,YAAAC,EACA,SAAAC,EACA,YAAAC,EACA,UAAAC,EACA,QAAAC,CACF,EAAwB,CACtB,OACEP,GAACQ,GAAA,CAAK,IAAI,QAAQ,IAAI,QAAQ,IAAI,IAAI,OAAM,GAAC,KAAI,GAC9C,SAAAN,EAAQ,IAAI,CAACO,EAAQC,IACpBV,GAACW,GAAA,CAEC,OAAQF,EACR,cAAeC,IAAMP,EACrB,SAAUC,EACV,YAAa,IAAMC,EAAYK,CAAC,EAChC,GAAI,GAAGJ,CAAS,WAAWI,CAAC,GAC5B,QAASH,GANJE,EAAO,IAOd,CACD,EACH,CAEJ,CC1CA,GAAI,OAAO,SAAa,KAAe,CAAC,SAAS,eAAe,mBAAmB,EAAG,CACpF,IAAMG,EAAI,SAAS,cAAc,OAAO,EACxCA,EAAE,GAAK,oBACPA,EAAE,YAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBhB,SAAS,KAAK,YAAYA,CAAC,CAC7B,CCNI,cAAAC,OAAA,oBAHG,SAASC,GAAM,CAAE,MAAAC,EAAO,MAAAC,EAAQ,UAAW,UAAAC,EAAW,SAAAC,EAAU,GAAGC,CAAK,EAAe,CAC5F,IAAMC,EAAQL,EAAS,CAAE,oBAAqBA,CAAM,EAAsB,OAC1E,OACEF,GAAC,OACC,UAAWI,EAAY,aAAaA,CAAS,GAAK,YAClD,aAAYD,EACZ,MAAOI,EACN,GAAGD,EAEH,SAAAD,EACH,CAEJ,CjBiGM,OAGM,OAAAG,GAHN,QAAAC,OAAA,oBA5GN,IAAMC,GAA+B,CAAC,IAAK,IAAK,GAAG,EAOnD,SAASC,GACPC,EAC8B,CAC9B,IAAMC,EAAc,IAClB,OAAO,OAAW,KAClB,OAAO,OAAO,YAAe,YAC7B,OAAO,WAAW,8BAA8B,EAAE,QAC9C,CAACC,EAAYC,CAAa,EAAIC,GAASH,CAAW,EAgBxD,GAdAI,GAAU,IAAM,CACd,GACEL,IAAS,QACT,OAAO,OAAW,KAClB,OAAO,OAAO,YAAe,WAE7B,OAEF,IAAMM,EAAK,OAAO,WAAW,8BAA8B,EACrDC,EAAW,IAAMJ,EAAcG,EAAG,OAAO,EAC/C,OAAAA,EAAG,iBAAiB,SAAUC,CAAQ,EAC/B,IAAMD,EAAG,oBAAoB,SAAUC,CAAQ,CACxD,EAAG,CAACP,CAAI,CAAC,EAELA,IAAS,OACb,OAAIA,IAAS,OAAeE,EAAa,OAAS,QAC3CF,CACT,CAEO,SAASQ,GAAuB,CACrC,YAAAC,EACA,YAAAC,EACA,SAAAC,EACA,YAAAC,EACA,OAAAC,EACA,GAAAC,EACA,UAAAC,EACA,MAAAC,EACA,YAAAC,EACA,UAAAC,EAAY,GACZ,eAAAC,EAAiB,GACjB,UAAAC,EAAY,GACZ,aAAAC,EAAe,GACf,gBAAAC,EAAkB,QAClB,KAAAtB,CACF,EAAgC,CAI9B,IAAMuB,EAAexB,GAAgBC,CAAI,EACnCwB,EAAYD,IAAiB,OAG7BE,EAAchB,EAAY,CAAC,GAAG,SAAW,CAAC,EAC1CiB,EAAmB,GAAQV,GAASA,EAAM,OAAS,GAAKC,GACxDU,EACJd,IAAWY,EAAY,OAAS,GAAMP,GAAaQ,GAAqBN,GAQpEQ,EAAW,CACf,YAAAnB,EACA,YAAAC,EACA,MAAAM,EACA,UAAAE,EACA,eAAAC,EACA,UAAAC,EACA,aAAAC,CACF,EACMQ,EAAiBC,GAAOF,CAAQ,EAClCD,IAAWE,EAAe,QAAUD,GACxC,IAAMG,EAAUJ,EAAYC,EAAWC,EAAe,QAGhDG,EADmBD,EAAQ,YAAY,CAAC,GACZ,SAAW,CAAC,EACxCE,EACJF,EAAQ,aAAe,GAAK,EAAQC,EAAQD,EAAQ,WAAW,GAAG,YAC9DG,EAAe,GAAQH,EAAQ,OAASA,EAAQ,MAAM,OAAS,GAAKd,GAIpEkB,EAAiBJ,EAAQ,WAAaG,EACtCE,EAAoBL,EAAQ,WAAa,CAACG,GAAgBH,EAAQ,UAClEM,EAAeF,GAAkBC,EACjCE,EAAeN,EAAQ,OAAS,EAChCO,EAAwBR,EAAQ,WAAa,CAACO,EAEpD,OACE1C,GAAC,OACC,GAAIkB,EACJ,KAAK,UACL,oBAAkB,GAClB,wBAAuBQ,EACvB,YAAWC,EACX,mBAAkBQ,EAAQ,UAAY,GAAK,OAC3C,UAAW,GAAGP,EAAY,cAAgB,EAAE,GAAGgB,GAAO,QAAQ,IAAIb,EAAYa,GAAO,QAAU,EAAE,IAAIzB,GAAa,EAAE,GACpH,YAAc0B,GAAMA,EAAE,eAAe,EAErC,SAAA5C,GAAC6C,GAAA,CAAM,MAAM,MACV,UAAAL,GACCzC,GAAC+C,GAAA,CAAQ,OAAM,GAAC,UAAWH,GAAO,QAAS,mBAAiB,GAC1D,SAAA5C,GAACgD,GAAA,CACC,MAAOb,EAAQ,OAAS,CAAC,EACzB,gBAAiB,EACjB,eAAgBA,EAAQ,eACxB,aAAcd,IAAgB,IAAM,CAAC,GACrC,QAAO,GACP,QAASc,EAAQ,UACnB,EACF,EAEDO,GACC1C,GAACiD,GAAA,CACC,QAASb,EACT,YAAaD,EAAQ,YACrB,SAAUpB,EACV,YAAaC,EACb,UAAWE,EACX,QAASiB,EAAQ,UACnB,EAEDQ,GACC3C,GAAC,OAAI,UAAW4C,GAAO,aAAc,yBAAuB,GACzD,SAAA1C,GAA6B,IAAKgD,GACjClD,GAAC,QAAsB,UAAW4C,GAAO,YAAa,MAAO,CAAE,MAAOM,CAAE,GAA7D,OAAOA,CAAC,EAAwD,CAC5E,EACH,EAEFlD,GAACmD,GAAA,CACC,oBAAqBd,EACrB,aAAcF,EAAQ,aACxB,GACF,EACF,CAEJ,CFpJA,OAGE,cAAAiB,GACA,kBAAAC,GACA,mBAAAC,OACK,sCoBjBP,GAAI,OAAO,SAAa,KAAe,CAAC,SAAS,eAAe,mBAAmB,EAAG,CACpF,IAAMC,EAAI,SAAS,cAAc,OAAO,EACxCA,EAAE,GAAK,oBACPA,EAAE,YAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoChB,SAAS,KAAK,YAAYA,CAAC,CAC7B,CACA,IAAOC,GAAQ,CAAC,aAAe,wCAAwC,ECf/D,cAAAC,OAAA,oBAdD,SAASC,GAAa,CAAE,SAAAC,EAAU,QAAAC,CAAQ,EAAsB,CACrE,OACEH,GAAC,UACC,KAAK,SACL,kBAAgB,GAChB,UAAWI,GAAO,aAClB,SAAUF,EACV,QAAUG,GAAM,CACdA,EAAE,gBAAgB,EAClBF,EAAQ,CACV,EACA,aAAW,SAEX,SAAAH,GAAC,OAAI,MAAM,KAAK,OAAO,KAAK,QAAQ,YAAY,KAAK,OAAO,KAAK,MAAM,aAAW,SAChF,SAAAA,GAAC,QACC,EAAE,2BACF,OAAO,eACP,YAAY,IACZ,cAAc,QACd,eAAe,QACjB,EACF,EACF,CAEJ,CCpCA,OACE,kBAAkBM,OAIb,sCACP,OAGE,eAAAC,GACA,aAAAC,GACA,UAAAC,EACA,YAAAC,OACK,QAUP,IAAMC,GAAyB,CAC7B,KAAM,GACN,gBAAiB,CAAC,EAClB,YAAa,CAAC,EACd,oBAAqB,GACrB,WAAY,KACZ,UAAW,GACX,QAAS,GACT,MAAO,KACP,SAAU,CAAC,EACX,sBAAuB,CAAC,EACxB,gBAAiB,CAAC,EAClB,gBAAiB,GACjB,eAAgB,GAChB,qBAAsB,GACtB,WAAY,EACZ,iBAAkB,GAClB,WAAY,GACZ,cAAe,GACf,aAAc,GACd,UAAW,GACX,aAAc,KACd,cAAe,KACf,YAAa,KACb,YAAa,KACb,qBAAsB,EACxB,EAqBO,SAASC,GAAkB,CAChC,SAAAC,EACA,QAAAC,EACA,gBAAAC,EACA,kBAAAC,EACA,UAAAC,EACA,QAAAC,EAAU,EACV,gBAAAC,EACA,gBAAAC,EACA,oBAAAC,EACA,uBAAAC,EACA,QAAAC,EACA,OAAAC,EACA,MAAOC,EACP,gBAAiBC,EACjB,SAAUC,EACV,eAAAC,EACA,OAAAC,EACA,UAAAC,CACF,EAAsD,CACpD,IAAMC,EAActB,EAAkC,IAAI,EACpD,CAACuB,EAAWC,CAAY,EAAIvB,GAA2B,IAAI,EAK3DwB,EAAczB,EAAOI,CAAQ,EACnCqB,EAAY,QAAUrB,EACtB,IAAMsB,EAAa1B,EAAOK,CAAO,EACjCqB,EAAW,QAAUrB,EACrB,IAAMsB,EAAc3B,EAAOkB,CAAY,EACvCS,EAAY,QAAUT,EACtB,IAAMU,EAAoB5B,EAAOmB,CAAc,EAC/CS,EAAkB,QAAUT,EAC5B,IAAMU,EAAa7B,EAAOc,CAAO,EACjCe,EAAW,QAAUf,EACrB,IAAMgB,EAAY9B,EAAOe,CAAM,EAC/Be,EAAU,QAAUf,EACpB,IAAMgB,EAAe/B,EAAOqB,CAAS,EACrCU,EAAa,QAAUV,EAOvBtB,GAAU,IAAM,CACd,GAAI,OAAO,SAAa,IAAa,OACrC,IAAMiC,EAAW,IAAInC,GAAmB,SAAS,cAAc,KAAK,EAAG,CACrE,WAAY,WACZ,UAAAW,EACA,gBAAAF,EACA,kBAAAC,EACA,QAAAE,EACA,gBAAAC,EACA,gBAAAC,EACA,oBAAAC,EACA,uBAAAC,EACA,OAAAO,EACA,MAAOJ,EACP,gBAAiBC,EACjB,SAAU,IAAIgB,IAASR,EAAY,UAAU,GAAGQ,CAAI,EACpD,QAAS,IAAIA,IAASP,EAAW,UAAU,GAAGO,CAAI,EAClD,SAAU,IAAIA,IAASN,EAAY,UAAU,GAAGM,CAAI,EACpD,eAAgB,IAAIA,IAASL,EAAkB,UAAU,GAAGK,CAAI,EAChE,QAAS,IAAMJ,EAAW,UAAU,EACpC,OAAQ,IAAMC,EAAU,UAAU,EAClC,UAAYI,GAAWH,EAAa,UAAUG,CAAM,CACtD,CAAC,EACDZ,EAAY,QAAUU,EACtBR,EAAaQ,EAAS,SAAS,CAAC,EAChC,IAAMG,EAAQH,EAAS,UAAWI,GAAUZ,EAAaY,CAAK,CAAC,EAC/D,MAAO,IAAM,CACXD,EAAM,EACNH,EAAS,QAAQ,EACbV,EAAY,UAAYU,IAAUV,EAAY,QAAU,KAC9D,CACF,EAAG,CAAC,CAAC,EAGLvB,GAAU,IAAM,CACViB,IAAoB,QAAWM,EAAY,SAAS,SAASN,CAAe,CAClF,EAAG,CAACA,CAAe,CAAC,EAGpBjB,GAAU,IAAM,CACVkB,IAAqB,QAAWK,EAAY,SAAS,mBAAmBL,CAAgB,CAC9F,EAAG,CAACA,CAAgB,CAAC,EAGrB,IAAMoB,EAAgB,KAAK,UAAU7B,GAAa,IAAI,EAChD8B,EAAmBtC,EAAOM,CAAe,EACzCiC,EAAmBvC,EAAO,CAAC,EACjC,GAAIM,IAAoBgC,EAAiB,QAAS,CAChD,IAAME,EAAOF,EAAiB,QACxBG,EAAOnC,EACPoC,EAAW,OAAO,KAAKF,GAAQ,CAAC,CAAC,EACjCG,GAAW,OAAO,KAAKF,GAAQ,CAAC,CAAC,GAErCC,EAAS,SAAWC,GAAS,QAC7BA,GAAS,KACNC,IACC,CAAEJ,IAAmCI,EAAC,GACrCH,EAAiCG,EAAC,IAAOJ,EAAiCI,EAAC,CAChF,IAEAL,EAAiB,UAEnBD,EAAiB,QAAUhC,CAC7B,CAEAP,GAAU,IAAM,CACduB,EAAY,SAAS,OAAO,CAC1B,UAAAd,EACA,gBAAAF,EACA,gBAAAI,EACA,gBAAAC,EACA,oBAAAC,EACA,uBAAAC,CACF,CAAC,CACH,EAAG,CACDwB,EACAE,EAAiB,QACjB7B,EACAC,EACAC,EACAC,CACF,CAAC,EAOD,IAAMgC,EAAa7C,EAA2B,IAAI,EAC9C6C,EAAW,UAAY,OACzBA,EAAW,QAAU,CACnB,iBAAmBC,GAAUxB,EAAY,SAAS,iBAAiBwB,CAAK,EACxE,cAAgBC,GAAM,CACpB,IAAMC,EAAS,gBAAiBD,EAAIA,EAAE,YAAcA,EACpDzB,EAAY,SAAS,cAAc0B,CAAM,CAC3C,EACA,WAAaC,GAAY3B,EAAY,SAAS,WAAW2B,CAAO,EAChE,kBAAoBC,GAAY5B,EAAY,SAAS,kBAAkB4B,CAAO,EAC9E,aAAc,IAAM5B,EAAY,SAAS,aAAa,EACtD,sBAAwBY,GAAWZ,EAAY,SAAS,sBAAsBY,CAAM,EACpF,gBAAkBA,GAAWZ,EAAY,SAAS,gBAAgBY,CAAM,EACxE,oBAAsBiB,GACpB7B,EAAY,SAAS,oBAAoB6B,CAAW,GAAK,GAC3D,cAAgBC,GAAU9B,EAAY,SAAS,cAAc8B,CAAK,EAClE,gBAAiB,IAAM9B,EAAY,SAAS,gBAAgB,EAC5D,gBAAiB,IAAMA,EAAY,SAAS,gBAAgB,EAC5D,MAAO,IAAMA,EAAY,SAAS,MAAM,EACxC,aAAe+B,GAAW/B,EAAY,SAAS,aAAa+B,CAAM,EAClE,uBAAyBD,GAAU9B,EAAY,SAAS,uBAAuB8B,CAAK,EACpF,YAAa,IAAM9B,EAAY,SAAS,WAAW,EAAI,EACvD,WAAY,IAAMA,EAAY,SAAS,WAAW,EAAK,CACzD,GAEF,IAAMgC,EAAUT,EAAW,QAKrBU,EAAezD,GAAaiD,GAAwC,CACxE,IAAMS,EAAMT,EAAE,OAAO,MAKfU,GAHJD,EAAI,OAAS,GACb,CAAET,EAAE,aAA4B,aAChCS,EAAI,CAAC,IAAMA,EAAI,CAAC,EAAE,YAAY,EACIA,EAAI,CAAC,EAAE,YAAY,EAAIA,EAAI,MAAM,CAAC,EAAIA,EAC1ElC,EAAY,SAAS,iBAAiBmC,EAAQ,CAChD,EAAG,CAAC,CAAC,EAECC,GAAwB5D,GAAaiD,GAA0C,CACnFzB,EAAY,SAAS,cAAcyB,EAAE,WAAW,CAClD,EAAG,CAAC,CAAC,EAGCf,EAAWV,EAAY,QACvBc,EAAQb,GAAarB,GACrByD,EAAO3C,IAAoB,OAAYA,EAAkBoB,EAAM,KAC/DwB,EAAkB3C,IAAqB,OAAYA,EAAmBmB,EAAM,gBAE5EyB,EAAwBzB,EAAM,sBAC9B0B,EAA2CD,EAAsB,CAAC,EAClEE,EAAY/B,GAAU,WAAa,GAEnCgC,EACJ5B,EAAM,qBAAuB,GAAKJ,EAC9B,GAAG+B,CAAS,WAAW3B,EAAM,mBAAmB,GAChD,OAKA6B,EAAe7B,EAAM,aACrB8B,EAAkCD,EACpC,CACE,KAAMA,EAAa,eACnB,KAAMA,EAAa,sBACnB,SAAU,GACV,QAASA,EAAa,OACxB,EACA,KACEE,GAAqBD,GAAgBJ,EACrCM,GAAgBF,EAAe,CAACA,CAAY,EAAIL,EAMhDQ,GACJ,CAACrC,GAAaI,EAAM,WAAa,CAACA,EAAM,cAAgB,CAACA,EAAM,qBAEjE,MAAO,CACL,gBAAAwB,EACA,gBAAiBC,EACjB,cAAeP,EAAQ,cACvB,gBAAiBA,EAAQ,gBACzB,SAAUlB,EAAM,SAChB,WAAYA,EAAM,WAClB,gBAAiBkB,EAAQ,gBACzB,YAAalB,EAAM,YACnB,YAAaA,EAAM,oBACnB,QAASA,EAAM,QACf,UAAWiC,GACX,UAAWjC,EAAM,UACjB,eAAgBA,EAAM,eACtB,qBAAsBA,EAAM,qBAC5B,gBAAiBA,EAAM,gBACvB,UAAA2B,EACA,MAAO3B,EAAM,MACb,iBAAkBkB,EAAQ,iBAC1B,cAAeA,EAAQ,cACvB,WAAYA,EAAQ,WACpB,aAAAW,EACA,cAAe7B,EAAM,cACrB,YAAaA,EAAM,YACnB,kBAAmBkB,EAAQ,kBAC3B,aAAcA,EAAQ,aACtB,sBAAuBA,EAAQ,sBAC/B,gBAAiBA,EAAQ,gBACzB,oBAAqBA,EAAQ,oBAC7B,WAAY,CACV,MAAOK,EACP,YAAavB,EAAM,iBAAmB,OACtC,SAAUmB,EACV,UAAWG,GACX,QAASJ,EAAQ,YACjB,OAAQA,EAAQ,WAChB,KAAM,WACN,gBAAiBlB,EAAM,eACvB,wBAAyB4B,EACzB,oBAAqB,OACrB,gBAAiBD,CACnB,EACA,MAAOT,EAAQ,MACf,cAAe,CACb,YAAaa,GACT,CAAC,CAAE,GAAGA,GAAoB,QAAS/B,EAAM,eAAgB,CAAC,EAC1D,CAAC,EACL,YAAaA,EAAM,oBACnB,SAAUkB,EAAQ,aAClB,YAAaA,EAAQ,uBACrB,OAAQlB,EAAM,eACd,GAAI2B,EACJ,MAAOK,GACP,eAAgBhC,EAAM,qBACtB,YAAakB,EAAQ,cACrB,UAAWe,GACX,aAAcV,EAAK,KAAK,EAAE,SAAW,EAIrC,gBAAiBhD,GAAmB,OACtC,CACF,CACF,CC5VA,OAEE,oBAAA2D,GACA,mBAAAC,GACA,mBAAAC,GACA,yBAAAC,GAEA,mBAAAC,OACK,sCACP,OAGE,eAAAC,EACA,aAAAC,GACA,mBAAAC,GACA,UAAAC,OACK,QAEP,IAAIC,GACJ,SAASC,IAAiC,CACxC,GAAID,KAAuB,OAAW,OAAOA,GAC7C,GAAI,OAAO,SAAa,IAAa,MAAO,GAC5C,IAAME,EAAQ,SAAS,cAAc,KAAK,EAC1C,OAAAA,EAAM,aAAa,kBAAmB,gBAAgB,EACtDF,GAAqBE,EAAM,kBAAoB,iBACxCF,EACT,CAkFO,SAASG,GACdC,EACgC,CAChC,GAAM,CACJ,SAAAC,EACA,WAAAC,EACA,aAAAC,EACA,cAAAC,EACA,YAAAC,EACA,gBAAAC,EACA,UAAAC,EACA,eAAAC,EACA,UAAAC,EACA,mBAAAC,EACA,UAAAC,EACA,iBAAAC,EACA,cAAAC,EACA,sBAAAC,EACA,gBAAAC,EACA,kBAAAC,EACA,oBAAAC,EACA,WAAAC,CACF,EAAIlB,EAEEmB,EAAWxB,GAAuB,IAAI,EACtCyB,EAAezB,GAAO,EAAK,EAC3B0B,EAAqB1B,GAAO,EAAE,EAC9B2B,EAAmB3B,GAAO,EAAE,EAC5B4B,EAAiB5B,GAAsB,IAAI,EAI3C6B,EAAiB7B,GAAO,CAAC,EAE/B4B,EAAe,QAAUlB,EAGzBZ,GAAU,IAAM,CACd,GAAI,CAACkB,EAAW,OAChB,IAAMc,EAAKN,EAAS,QACpB,GAAI,CAACM,EAAI,OACL,SAAS,gBAAkBA,EAC7BP,EAAW,EAAI,EAEfO,EAAG,MAAM,EAMX,IAAMC,EAAMD,EAAG,eAAiB,SAC1BE,EAAMD,EAAI,aAAa,EACvBE,EAAcD,GAAOA,EAAI,WAAa,GAAKF,EAAG,SAASE,EAAI,UAAU,EAC3E,GAAIA,GAAO,CAACC,EAAa,CACvB,IAAMC,EAAQH,EAAI,YAAY,EAC9BG,EAAM,mBAAmBJ,CAAE,EAC3BI,EAAM,SAAS,EAAI,EACnBF,EAAI,gBAAgB,EACpBA,EAAI,SAASE,CAAK,CACpB,CACF,EAAG,CAAClB,EAAWO,CAAU,CAAC,EAM1BzB,GAAU,IAAM,CACd,IAAMgC,EAAKN,EAAS,QACpB,GAAI,CAACM,EAAI,OACT,IAAMC,EAAMD,EAAG,eAAiB,SAC1BK,EAAoB,IAAM,CAC9B,IAAMH,EAAMD,EAAI,aAAa,EAE7B,GADI,CAACC,GAAOA,EAAI,aAAe,GAC3B,CAACA,EAAI,YAAc,CAACF,EAAG,SAASE,EAAI,UAAU,EAAG,OACrD,IAAMI,EAASJ,EAAI,WAIbK,GAFJD,EAAO,WAAa,KAAK,aAAgBA,EAAqBA,EAAO,gBAC/C,QAAqB,6CAA6C,GAChE,QAAQ,SAAW,KAC7C,GAAIC,GAAaA,IAAc7B,GAAc,GAAI,CAC/Ca,EAAkBgB,CAAS,EAC3B,MACF,CACI,YAAY,IAAI,EAAIR,EAAe,QAAU,IACjDT,EAAgB3B,GAAgBqC,CAAE,CAAC,CACrC,EACA,OAAAC,EAAI,iBAAiB,kBAAmBI,CAAiB,EAClD,IAAMJ,EAAI,oBAAoB,kBAAmBI,CAAiB,CAC3E,EAAG,CAAC3B,EAAca,EAAmBD,CAAe,CAAC,EAMrDrB,GAAgB,IAAM,CACpB,IAAM+B,EAAKN,EAAS,QACfM,GACLnC,GAAsB,CACpB,MAAOmC,EACP,SAAUxB,EACV,WAAAC,EACA,eAAgBC,GAAc,IAAM,KACpC,gBAAiBG,GAAmB,GACpC,UAAAC,CACF,CAAC,CACH,EAAG,CAACN,EAAUC,EAAYC,EAAcG,EAAiBC,CAAS,CAAC,EAKnEb,GAAgB,IAAM,CACpB,IAAMuC,EAAWZ,EAAmB,QAC9Ba,EAAUhC,GAAc,GAE9B,GADAmB,EAAmB,QAAUa,EACzB,CAACA,GAAWA,IAAYD,EAAU,OACtC,IAAMR,EAAKN,EAAS,QACpB,GAAI,CAACM,EAAI,OACTA,EAAG,MAAM,EAIT,IAAMU,EAAUZ,EAAe,SAAWlC,GAAgBoC,CAAE,EAC5DlC,GAAgBkC,EAAIU,CAAO,CAC7B,EAAG,CAACjC,CAAU,CAAC,EAKfR,GAAgB,IAAM,CACpB,IAAMuC,EAAWX,EAAiB,QAC5BY,EAAU/B,GAAc,IAAM,GAEpC,GADAmB,EAAiB,QAAUY,EACvB,CAACA,GAAWA,IAAYD,GAAY7B,GAAiB,KAAM,OAC/D,IAAMqB,EAAKN,EAAS,QACfM,GACLlC,GAAgBkC,EAAIrB,CAAa,CACnC,EAAG,CAACD,EAAcC,CAAa,CAAC,EAEhC,IAAMgC,EAAY5C,EAAY,IAAM,CAClC,GAAI4B,EAAa,QAAS,OAC1B,IAAMK,EAAKN,EAAS,QACpB,GAAI,CAACM,EAAI,OACT,IAAMY,EAAMlD,GAAiBsC,CAAE,EAEzBa,EADmBD,EAAI,OAAS,GAAKA,EAAI,CAAC,IAAMA,EAAI,CAAC,EAAE,YAAY,EACzCA,EAAI,CAAC,EAAE,YAAY,EAAIA,EAAI,MAAM,CAAC,EAAIA,EACtEzB,EAAiB0B,CAAI,CACvB,EAAG,CAAC1B,CAAgB,CAAC,EAEf2B,EAAmB/C,EAAY,IAAM,CACzCgC,EAAe,QAAU,YAAY,IAAI,EACzCY,EAAU,EACV,IAAMX,EAAKN,EAAS,QAChBM,GAAIX,EAAsB1B,GAAgBqC,CAAE,CAAC,CACnD,EAAG,CAACW,EAAWtB,CAAqB,CAAC,EAKrCrB,GAAU,IAAM,CACd,IAAMgC,EAAKN,EAAS,QACpB,GAAI,CAACM,EAAI,OACT,IAAMe,EAAiBC,GAAa,CAClC,IAAMC,EAAaD,EACbE,EAAID,EAAW,UACrB,GAAIC,IAAM,mBAAqBA,IAAM,mBAAqBA,IAAM,iBAAkB,CAChFF,EAAE,eAAe,EACjB,MACF,CACA,GAAIE,EAAE,WAAW,QAAQ,GAAKA,EAAE,WAAW,QAAQ,EAAG,CACpD,IAAMC,EAAcD,EAAE,WAAW,QAAQ,EAAI,GAAMD,EAAW,MAAQ,GAClEzB,EAAoB2B,CAAW,GACjCH,EAAE,eAAe,CAErB,CACF,EACA,OAAAhB,EAAG,iBAAiB,cAAee,CAAa,EACzC,IAAMf,EAAG,oBAAoB,cAAee,CAAa,CAClE,EAAG,CAACvB,CAAmB,CAAC,EAExB,IAAM4B,EAAyBrD,EAAY,IAAM,CAC/C4B,EAAa,QAAU,EACzB,EAAG,CAAC,CAAC,EAEC0B,EAAuBtD,EAAY,IAAM,CAC7C4B,EAAa,QAAU,GACvBgB,EAAU,CACZ,EAAG,CAACA,CAAS,CAAC,EAERW,EAAcvD,EACjBiD,GAA2C,CAC1CA,EAAE,eAAe,EACjB,IAAMhB,EAAKN,EAAS,QACpB,GAAI,CAACM,EAAI,OACT,IAAMuB,GAAQP,EAAE,cAAc,QAAQ,YAAY,GAAK,IAAI,QAAQ,SAAU,GAAG,EAChF,GAAI,CAACO,EAAM,OACX,IAAMtB,EAAMD,EAAG,eAAiB,SAC1BE,EAAMD,EAAI,aAAa,EAC7B,GAAI,CAACC,GAAOA,EAAI,aAAe,EAAG,OAClC,IAAME,EAAQF,EAAI,WAAW,CAAC,EAC9B,GAAI,CAACF,EAAG,SAASI,EAAM,cAAc,EAAG,OACxCA,EAAM,eAAe,EACrB,IAAMoB,EAAOvB,EAAI,eAAesB,CAAI,EACpCnB,EAAM,WAAWoB,CAAI,EACrBpB,EAAM,cAAcoB,CAAI,EACxBpB,EAAM,SAAS,EAAI,EACnBF,EAAI,gBAAgB,EACpBA,EAAI,SAASE,CAAK,EAClBO,EAAU,CACZ,EACA,CAACA,CAAS,CACZ,EAEMc,EAAqB1D,EACxBiD,GAA0C5B,EAAc4B,CAAC,EAC1D,CAAC5B,CAAa,CAChB,EAEMsC,EAAc3D,EAAY,IAAM0B,EAAW,EAAI,EAAG,CAACA,CAAU,CAAC,EAC9DkC,EAAa5D,EAAY,IAAM0B,EAAW,EAAK,EAAG,CAACA,CAAU,CAAC,EAE9DmC,EAAQ7D,EAAY,IAAM2B,EAAS,SAAS,MAAM,EAAG,CAAC,CAAC,EACvDmC,GAAO9D,EAAY,IAAM2B,EAAS,SAAS,KAAK,EAAG,CAAC,CAAC,EACrDoC,EAAe/D,EAAY,IAAM,CACrC,IAAMiC,EAAKN,EAAS,QACpB,OAAOM,EAAKtC,GAAiBsC,CAAE,EAAI,EACrC,EAAG,CAAC,CAAC,EAEC+B,EAAS3D,GAAsB,EAAI,iBAAmB,OAE5D,MAAO,CACL,SAAAsB,EACA,YAAa,CACX,IAAKA,EACL,gBAAiBqC,EACjB,+BAAgC,GAChC,SAAU,EACV,KAAM,WACN,oBAAqB,OACrB,gBAAiB,UACjB,gBAAiB/C,EACjB,gBAAiBD,EACjB,wBAAyBE,EACzB,WAAY,GACZ,aAAc,OACd,QAAS6B,EACT,UAAWW,EACX,mBAAoBL,EACpB,iBAAkBC,EAClB,QAASC,EACT,QAASI,EACT,OAAQC,CACV,EACA,aAAAG,EACA,MAAAF,EACA,KAAAC,EACF,CACF,CvBlHQ,cAAAG,GAIE,QAAAC,OAJF,oBAlOR,SAASC,GAAmBC,EAAwC,CAClE,OAAIA,IAAS,OAAeA,EACxB,OAAO,OAAW,KACf,OAAO,WAAW,8BAA8B,EAAE,QADf,OACkC,OAC9E,CAEO,IAAMC,GAAiBC,GAC5B,SACE,CACE,SAAAC,EACA,QAAAC,EACA,gBAAAC,EACA,kBAAAC,EACA,UAAAC,EACA,UAAAC,EACA,QAAAC,EACA,cAAAC,EAAgB,WAChB,KAAAV,EAAO,OACP,gBAAAW,EAAkB,QAClB,WAAAC,EAAa,GACb,gBAAAC,EACA,oBAAAC,EACA,uBAAAC,EACA,UAAAC,EAAY,GACZ,QAAAC,EACA,OAAAC,EACA,MAAAC,EACA,gBAAiBC,EACjB,SAAUC,EACV,eAAAC,EACA,aAAAC,CACF,EACAC,EACA,CACA,IAAMC,EAAeC,GAAuB,IAAI,EAC1CC,EAAmBD,GAAwB,IAAI,EAC/CE,EAAkBF,GAA6C,IAAM,CAAC,CAAC,EACvEG,EAAoBH,GAA8B,IAAI,EAItDI,EAAuBJ,GAA+C,IAAI,EAEhFK,GAAU,IAAM,CACd,IAAMC,EAAKP,EAAa,QACxB,GAAKO,EACL,OAAIH,EAAkB,QACpBA,EAAkB,QAAQ,QAAQ7B,CAAI,EAEtC6B,EAAkB,QAAU,IAAII,GAAeD,EAAIhC,CAAI,EAElD,IAAM,CACX6B,EAAkB,SAAS,QAAQ,EACnCA,EAAkB,QAAU,IAC9B,CACF,EAAG,CAAC7B,CAAI,CAAC,EAET,IAAMkC,EAAkBC,GAAaC,GAAmB,CACtD,IAAMJ,EAAKF,EAAqB,SAAS,QACpCE,IACLA,EAAG,MAAM,EACTK,GAAgBL,EAAII,CAAM,EAC5B,EAAG,CAAC,CAAC,EAEC,CACJ,gBAAAE,EACA,gBAAAC,EACA,cAAAC,EACA,SAAAC,EACA,WAAAC,GACA,gBAAAC,EACA,gBAAAC,EACA,UAAAC,EACA,eAAAC,EACA,qBAAAC,EACA,UAAAC,EACA,YAAAC,EACA,UAAAC,EACA,iBAAAC,EACA,cAAAC,EACA,WAAAC,GACA,aAAAC,GACA,cAAAC,GACA,YAAAC,EACA,kBAAAC,EACA,sBAAAC,EACA,gBAAAC,GACA,oBAAAC,GACA,cAAAC,GACA,MAAAC,EACF,EAAIC,GAAkB,CACpB,SAAWC,GAAWpC,EAAgB,QAAQoC,CAAM,EACpD,QAAA5D,EACA,gBAAAC,EACA,kBAAAC,EACA,UAAAE,EACA,QAAAC,EACA,gBAAAI,EACA,gBAAAF,EACA,oBAAAG,EACA,uBAAAC,EACA,QAAAE,EACA,OAAAC,EACA,MAAAC,EACA,gBAAiBC,EACjB,SAAUC,EACV,eAAAC,EACA,OAAQ,WACR,UAAWY,CACb,CAAC,EAGDH,GAAU,IAAM,CACd,GAAI,CAACW,GAAY,OACjB,IAAMuB,EAAI,OAAO,WAAW,IAAMtB,EAAgB,EAAG,GAAG,EACxD,MAAO,IAAM,OAAO,aAAasB,CAAC,CACpC,EAAG,CAACvB,GAAYC,CAAe,CAAC,EAEhC,IAAMuB,GAAqBjB,GAAe,EAAI,GAAGC,CAAS,WAAWD,CAAW,GAAK,OAE/E,CAAE,SAAAkB,GAAU,YAAAC,GAAa,MAAAC,GAAO,KAAAC,GAAM,aAAAC,EAAa,EAAIC,GAAyB,CACpF,SAAA/B,EACA,WAAAC,GACA,aAAAY,GACA,cAAAC,GACA,YAAAC,EACA,gBAAAZ,EACA,UAAAC,EACA,eAAAC,EACA,UAAAI,EACA,mBAAAgB,GACA,UAAAlD,EACA,iBAAAmC,EACA,cAAAC,EACA,sBAAAM,EACA,gBAAAC,GACA,kBAAAF,EACA,oBAAAG,GACA,WAAAP,EACF,CAAC,EAKDvB,EAAqB,QAAUqC,GAY/BM,GAAgB,IAAM,CACpB,IAAMC,EAAY/C,EAAiB,QAC7BgD,EAASR,GAAS,QACxB,GAAI,CAACO,GAAa,CAACC,EAAQ,OAE3B,IAAMC,GAAS,IAAM,CACnB,IAAMC,GAAQH,EAAU,kBACxB,GAAI,CAACG,GAAO,OACZ,IAAMC,GAAQD,GAAM,sBAAsB,EACpCE,GAAQJ,EAAO,sBAAsB,EAC3BG,GAAM,KAAOC,GAAM,OAAS,EAC/BL,EAAU,aAAa,wBAAyB,EAAE,EAC1DA,EAAU,gBAAgB,uBAAuB,CACxD,EAEAE,GAAO,EACP,IAAMI,GAAK,IAAI,eAAeJ,EAAM,EACpC,OAAAI,GAAG,QAAQL,CAAM,EACV,IAAMK,GAAG,WAAW,CAC7B,EAAG,CAACvC,EAAUF,EAAgB,OAAQS,EAAWmB,EAAQ,CAAC,EAE1Dc,GACEzD,EACA,KAAO,CACL,MAAA6C,GACA,KAAAC,GACA,MAAAR,GACA,QAAUoB,GAAMrD,EAAkB,SAAS,QAAQqD,CAAC,CACtD,GACA,CAACb,GAAOC,GAAMR,EAAK,CACrB,EAEA,IAAMqB,GAAY,CAAC,CAAC1C,EAAS,QAAUH,EAAgB,OAAS,EAE1D8C,GAAejD,GAAY,IAAM,CACrC,GAAI,CAACgD,GAAW,OAChB,IAAME,EAAOd,GAAa,EACpB,CAAE,SAAAe,EAAU,gBAAiBC,EAAY,EAAIC,GAAWH,EAAM/C,CAAe,EACnFnC,EAAS,CACP,MAAOkF,EAAK,KAAK,EACjB,UAAWC,EACX,iBAAkBC,EACpB,CAAC,EACDzB,GAAM,CACR,EAAG,CAACqB,GAAW7C,EAAiBnC,EAAU2D,GAAOS,EAAY,CAAC,EAE9D3C,EAAgB,QAAUwD,GAE1B,IAAMK,GAAqBtD,GACxBuD,GAAwC,CAExBA,EAAE,QACL,QAAQ,iBAAiB,GACrCrB,GAAM,CACR,EACA,CAACA,EAAK,CACR,EAEMsB,GAAkBjF,IAAkB,SACpCkF,GAAoBlF,IAAkB,WAE5C,OACEZ,GAAC,OACC,IAAK2B,EACL,UAAW,cAAcoE,GAAO,SAAS,IAAItF,GAAa,EAAE,GAC5D,sBAAqBG,EACrB,wBAAuBC,EACvB,kBAAiBC,EAAa,KAAO,MACrC,YAAWb,GAAmBC,CAAI,EAElC,UAAAH,GAACiG,GAAA,CAAwB,GAAGjC,GAAe,UAAW+B,GAAmB,EAGzE9F,GAAC,OAAI,UAAW+F,GAAO,aAAc,QAASJ,GAC5C,UAAA3F,GAAC,OAAI,UAAW+F,GAAO,WAAY,kBAAgB,GACjD,UAAAhG,GAAC,OAAK,GAAGuE,GAAa,UAAWyB,GAAO,MAAO,iBAAe,GAAG,EAChEF,KAAoB3C,GAAaT,EAAgB,OAAS,IACzD1C,GAAC,QACC,IAAK8B,EACL,UAAWkE,GAAO,kBAClB,+BAA6B,GAE7B,SAAAhG,GAACkG,GAAA,CACC,MAAOxD,EACP,gBAAiB,EACjB,eAAgBQ,EAChB,aAAcP,EACd,QAASQ,EACX,EACF,GAEJ,EACCzB,IAAiB,KAAO,KAAOA,IAAiB,OAC/C1B,GAACmG,GAAA,CAAa,SAAU,CAACb,GAAW,QAASC,GAAc,EAI3DvF,GAAC,QACC,kBAAgB,GAChB,UAAWgG,GAAO,WAClB,QAAUH,GAAM,CACTP,KACLO,EAAE,gBAAgB,EAClBN,GAAa,EACf,EAEC,SAAA7D,EACH,GAEJ,GACF,CAEJ,CACF","names":["forwardRef","useCallback","useEffect","useImperativeHandle","useLayoutEffect","useRef","s","AIAutocomplete_module_css_default","useEffect","useRef","useState","s","s","AIAutocompleteDropdown_module_css_default","ATTRIBUTION_URL","buildAttributionUrl","getFooterHint","useEffect","useState","s","jsx","Cluster","gap","align","justify","noWrap","inline","className","children","rest","style","props","s","DropdownFooter_module_css_default","jsx","jsxs","DropdownFooter","isOptionHighlighted","isInputEmpty","key","hint","getFooterHint","brandHref","setBrandHref","useState","ATTRIBUTION_URL","useEffect","buildAttributionUrl","DropdownFooter_module_css_default","Cluster","s","ParamPill_module_css_default","jsx","PARAM_PILL_OPACITY","ParamPill","label","state","rounded","loading","onClick","className","ParamPill_module_css_default","e","s","PillList_module_css_default","jsx","FALLBACK_SKELETON_WIDTHS","pillStateForIndex","index","PillList","pills","activePillIndex","onSelectPill","activeSelected","rounded","loading","PillList_module_css_default","w","i","ParamPill_module_css_default","PARAM_PILL_OPACITY","pill","selected","ParamPill","useEffect","useLayoutEffect","useRef","useState","s","jsx","Grid","min","max","gap","scroll","maxHeight","fade","className","children","rest","gridRef","useRef","hasBottomOverflow","setHasBottomOverflow","useState","useEffect","el","update","resizeObserver","useLayoutEffect","style","grid","useEffect","useRef","useState","s","SuggestionItem_module_css_default","jsx","jsxs","SuggestionItem","option","isHighlighted","onSelect","onHighlight","id","loading","pressed","setPressed","useState","timerRef","useRef","useEffect","handleSelect","className","SuggestionItem_module_css_default","e","jsx","SuggestionGrid","options","activeIndex","onSelect","onHighlight","listboxId","loading","Grid","option","i","SuggestionItem","s","jsx","Stack","space","align","className","children","rest","style","jsx","jsxs","FALLBACK_SKELETON_BAR_WIDTHS","useResolvedMode","mode","prefersDark","systemDark","setSystemDark","useState","useEffect","mq","onChange","AIAutocompleteDropdown","suggestions","activeIndex","onSelect","onHighlight","isOpen","id","className","pills","onPillClick","showPills","activeSelected","isLoading","isInputEmpty","optionsPosition","resolvedMode","selfScope","liveOptions","liveHasRealPills","isVisible","snapshot","lastVisibleRef","useRef","content","options","isOptionHighlighted","hasRealPills","showsRealPills","showsLoadingPills","showsPillBar","showsOptions","showsFallbackSkeleton","AIAutocompleteDropdown_module_css_default","e","Stack","Cluster","PillList","SuggestionGrid","w","DropdownFooter","buildQuery","ModeController","setCursorOffset","s","SubmitButton_module_css_default","jsx","SubmitButton","disabled","onClick","SubmitButton_module_css_default","e","CoreAIAutocomplete","useCallback","useEffect","useRef","useState","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","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","extractPlainText","getCursorOffset","plainTextLength","renderEditableContent","setCursorOffset","useCallback","useEffect","useLayoutEffect","useRef","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","sel","caretInside","range","onSelectionChange","anchor","enclosing","previous","current","desired","fireInput","raw","next","handleInputEvent","onBeforeInput","e","inputEvent","t","replacement","handleCompositionStart","handleCompositionEnd","handlePaste","text","node","handleKeyDownReact","handleFocus","handleBlur","focus","blur","getPlainText","ceMode","jsx","jsxs","resolveInitialMode","mode","AIAutocomplete","forwardRef","onSubmit","onError","optionOverrides","maskCompletedText","className","apiConfig","columns","pillPlacement","optionsPosition","animations","dropdownTrigger","closeDropdownOnBlur","showNonTappableOptions","autoFocus","onFocus","onBlur","value","controlledParams","onChangeProp","onParamsChange","submitButton","ref","containerRef","useRef","pillContainerRef","handleSubmitRef","modeControllerRef","editorInputRefHolder","useEffect","el","ModeController","handleSetCursor","useCallback","offset","setCursorOffset","completedParams","suggestionPills","setActivePill","segments","newParamId","clearNewParamId","placeholderText","isFocused","isDropdownOpen","isActivePillSelected","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","useLayoutEffect","container","editor","update","inner","cRect","eRect","ro","useImperativeHandle","m","canSubmit","handleSubmit","text","rawQuery","finalParams","buildQuery","handleWrapperClick","e","showInlinePills","showDropdownPills","AIAutocomplete_module_css_default","AIAutocompleteDropdown","PillList","SubmitButton"]}