@12-apps/ui 6.45.3 → 6.45.4

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,9 +1,9 @@
1
1
  import {
2
2
  Autocomplete,
3
3
  Autocomplete_default
4
- } from "../../../../chunk-PXGURBIU.js";
4
+ } from "../../../../chunk-JBGCGYEC.js";
5
5
  import "../../../../chunk-XBLFK2FL.js";
6
- import "../../../../chunk-YWJZPN5C.js";
6
+ import "../../../../chunk-SY5FYBAF.js";
7
7
  import "../../../../chunk-PELRSZFU.js";
8
8
  import "../../../../chunk-JXS56EW5.js";
9
9
  import "../../../../chunk-M47ZOUGF.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  useAutocomplete
3
- } from "../../../../chunk-YWJZPN5C.js";
3
+ } from "../../../../chunk-SY5FYBAF.js";
4
4
  import "../../../../chunk-PELRSZFU.js";
5
5
  import "../../../../chunk-JXS56EW5.js";
6
6
  import "../../../../chunk-PZ5AY32C.js";
@@ -146,9 +146,9 @@ import "../../../chunk-O7QPPJAK.js";
146
146
  import "../../../chunk-2LXHUGYB.js";
147
147
  import {
148
148
  Autocomplete
149
- } from "../../../chunk-PXGURBIU.js";
149
+ } from "../../../chunk-JBGCGYEC.js";
150
150
  import "../../../chunk-XBLFK2FL.js";
151
- import "../../../chunk-YWJZPN5C.js";
151
+ import "../../../chunk-SY5FYBAF.js";
152
152
  import "../../../chunk-PELRSZFU.js";
153
153
  import "../../../chunk-JXS56EW5.js";
154
154
  import "../../../chunk-BO6S47KI.js";
@@ -387,9 +387,9 @@ import "../../chunk-O7QPPJAK.js";
387
387
  import "../../chunk-2LXHUGYB.js";
388
388
  import {
389
389
  Autocomplete
390
- } from "../../chunk-PXGURBIU.js";
390
+ } from "../../chunk-JBGCGYEC.js";
391
391
  import "../../chunk-XBLFK2FL.js";
392
- import "../../chunk-YWJZPN5C.js";
392
+ import "../../chunk-SY5FYBAF.js";
393
393
  import "../../chunk-PELRSZFU.js";
394
394
  import "../../chunk-JXS56EW5.js";
395
395
  import "../../chunk-BO6S47KI.js";
@@ -6,7 +6,7 @@ import {
6
6
  } from "./chunk-XBLFK2FL.js";
7
7
  import {
8
8
  useAutocomplete
9
- } from "./chunk-YWJZPN5C.js";
9
+ } from "./chunk-SY5FYBAF.js";
10
10
  import {
11
11
  defaultGetKey,
12
12
  defaultGetLabel,
@@ -131,4 +131,4 @@ export {
131
131
  Autocomplete,
132
132
  Autocomplete_default
133
133
  };
134
- //# sourceMappingURL=chunk-PXGURBIU.js.map
134
+ //# sourceMappingURL=chunk-JBGCGYEC.js.map
@@ -163,15 +163,15 @@ function commitMultiSelect(item, p, s, onChange) {
163
163
  onChange("");
164
164
  setDeliberateClose(s, false);
165
165
  }
166
- function commitSingleSelect(item, p, s, onChange) {
166
+ function commitSingleSelect(item, p, s) {
167
167
  const label = (p.getLabel ?? defaultGetLabel)(item);
168
168
  s.setInputValue(label);
169
- onChange(label);
169
+ p.onChange(label);
170
170
  }
171
171
  function commitPick(item, linkUrl, p, s, onChange) {
172
172
  if (linkUrl !== null) (p.openLink ?? defaultOpenLink)(linkUrl, item);
173
173
  else if (p.multiple) commitMultiSelect(item, p, s, onChange);
174
- else commitSingleSelect(item, p, s, onChange);
174
+ else commitSingleSelect(item, p, s);
175
175
  }
176
176
  function runSelectItem(item, p, s, onChange) {
177
177
  const url = (p.getUrl ?? defaultGetUrl)(item);
@@ -284,4 +284,4 @@ function useAutocomplete(p) {
284
284
  export {
285
285
  useAutocomplete
286
286
  };
287
- //# sourceMappingURL=chunk-YWJZPN5C.js.map
287
+ //# sourceMappingURL=chunk-SY5FYBAF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/form/Autocomplete/useAutocomplete.ts"],"sourcesContent":["import { useEffect, useId, useRef, useState } from 'react';\n\nimport {\n defaultGetKey,\n defaultGetLabel,\n defaultGetSuggestionType,\n defaultGetUrl,\n defaultOpenLink,\n filterSuggestions,\n firstGhostSuggestion,\n type MatchMode,\n} from './Autocomplete.helpers';\nimport { handleAutocompleteKey, type KeyContext } from './Autocomplete.keys';\nimport type { AutocompleteProps } from './Autocomplete.types';\n\ntype Setter<V> = React.Dispatch<React.SetStateAction<V>>;\n\n/** All mutable state + refs for one Autocomplete instance. */\ninterface AutocompleteState<T> {\n open: boolean;\n setOpen: Setter<boolean>;\n activeIndex: number;\n setActiveIndex: Setter<number>;\n ghost: string;\n setGhost: Setter<string>;\n inputValue: string;\n setInputValue: Setter<string>;\n composition: boolean;\n setComposition: Setter<boolean>;\n filteredSuggestions: T[];\n setFilteredSuggestions: Setter<T[]>;\n isInputFocused: boolean;\n setIsInputFocused: Setter<boolean>;\n justCompletedGhost: boolean;\n setJustCompletedGhost: Setter<boolean>;\n userClosedDropdown: boolean;\n setUserClosedDropdown: Setter<boolean>;\n /**\n * Mirrors `userClosedDropdown`, set synchronously wherever the state is\n * (see {@link setDeliberateClose}). An effect scheduled by one render and\n * flushed after a LATER render has already changed this flag reads a\n * stale, closed-over `userClosedDropdown` — but `.current` on a ref is\n * dereferenced live, so it always reflects the latest write regardless of\n * which render's closure is doing the reading (FUT-2780).\n */\n userClosedDropdownRef: React.RefObject<boolean>;\n inputRef: React.RefObject<HTMLInputElement | null>;\n listRef: React.RefObject<HTMLUListElement | null>;\n debounceRef: React.RefObject<number | undefined>;\n}\n\nfunction useAutocompleteState<T>(value: string, suggestions: T[]): AutocompleteState<T> {\n const [open, setOpen] = useState(false);\n const [activeIndex, setActiveIndex] = useState(-1);\n const [ghost, setGhost] = useState('');\n const [inputValue, setInputValue] = useState(value);\n const [composition, setComposition] = useState(false);\n const [filteredSuggestions, setFilteredSuggestions] = useState<T[]>(suggestions);\n const [isInputFocused, setIsInputFocused] = useState(false);\n const [justCompletedGhost, setJustCompletedGhost] = useState(false);\n const [userClosedDropdown, setUserClosedDropdown] = useState(false);\n const userClosedDropdownRef = useRef(false);\n const inputRef = useRef<HTMLInputElement>(null);\n const listRef = useRef<HTMLUListElement | null>(null);\n const debounceRef = useRef<number | undefined>(undefined);\n return {\n open, setOpen, activeIndex, setActiveIndex, ghost, setGhost, inputValue, setInputValue,\n composition, setComposition, filteredSuggestions, setFilteredSuggestions, isInputFocused,\n setIsInputFocused, justCompletedGhost, setJustCompletedGhost, userClosedDropdown,\n setUserClosedDropdown, userClosedDropdownRef, inputRef, listRef, debounceRef,\n };\n}\n\n/**\n * Set the \"this close was deliberate\" flag in both the ref effects read\n * synchronously (live, even from a stale closure) and the state the rest of\n * the component reads for render — every call site that touches\n * `userClosedDropdown` goes through this so the two never drift (FUT-2780).\n */\nfunction setDeliberateClose<T>(s: AutocompleteState<T>, closed: boolean): void {\n s.userClosedDropdownRef.current = closed;\n s.setUserClosedDropdown(closed);\n}\n\n// ---- effects (one tiny hook each; explicit params keep deps complete) --------\n\nfunction useValueSync(value: string, setInputValue: Setter<string>): void {\n useEffect(() => setInputValue(value), [value, setInputValue]);\n}\n\nfunction useDebounceCleanup(debounceRef: React.RefObject<number | undefined>): void {\n useEffect(\n () => () => {\n if (debounceRef.current) window.clearTimeout(debounceRef.current);\n },\n [debounceRef],\n );\n}\n\nfunction useScrollActiveIntoView(\n activeIndex: number,\n optionIdPrefix: string,\n listRef: React.RefObject<HTMLUListElement | null>,\n): void {\n useEffect(() => {\n if (activeIndex < 0 || !listRef.current) return;\n document\n .getElementById(`${optionIdPrefix}-${activeIndex}`)\n ?.scrollIntoView({ block: 'nearest' });\n }, [activeIndex, optionIdPrefix, listRef]);\n}\n\nfunction useGhostFlagReset(justCompletedGhost: boolean, setJustCompletedGhost: Setter<boolean>): void {\n useEffect(() => {\n if (!justCompletedGhost) return;\n const timer = setTimeout(() => setJustCompletedGhost(false), 50);\n return () => clearTimeout(timer);\n }, [justCompletedGhost, setJustCompletedGhost]);\n}\n\nfunction useLoadingOpen(\n isLoading: boolean,\n inputValue: string,\n disabled: boolean,\n userClosedDropdownRef: React.RefObject<boolean>,\n setOpen: Setter<boolean>,\n setActiveIndex: Setter<number>,\n): void {\n useEffect(() => {\n if (isLoading && inputValue.trim().length > 0 && !disabled && !userClosedDropdownRef.current) setOpen(true);\n if (disabled) {\n setOpen(false);\n setActiveIndex(-1);\n }\n }, [isLoading, inputValue, disabled, userClosedDropdownRef, setOpen, setActiveIndex]);\n}\n\n/** Inputs to the auto-open check, all primitive/stable so effect deps stay complete. */\ninterface AutoOpenArgs {\n inputValue: string;\n isInputFocused: boolean;\n composition: boolean;\n justCompletedGhost: boolean;\n userClosedDropdownRef: React.RefObject<boolean>;\n activeIndex: number;\n setOpen: Setter<boolean>;\n setActiveIndex: Setter<number>;\n}\n\n/** Auto-open the dropdown once local filtering has a fresh result set. */\nfunction maybeAutoOpen(a: AutoOpenArgs, hasResults: boolean): void {\n const canAutoOpen =\n a.inputValue.trim() &&\n a.isInputFocused &&\n !a.composition &&\n !a.justCompletedGhost &&\n !a.userClosedDropdownRef.current;\n if (!canAutoOpen) return;\n a.setOpen(true);\n if (hasResults && a.activeIndex === -1) a.setActiveIndex(0);\n}\n\nfunction useLocalFilter<T>(p: AutocompleteProps<T>, s: AutocompleteState<T>): void {\n const propSuggestions = p.suggestions;\n const getLabel = p.getLabel ?? defaultGetLabel;\n const matchMode: MatchMode = p.matchMode ?? 'contains';\n const async = Boolean(p.async);\n const {\n inputValue, isInputFocused, composition, justCompletedGhost, userClosedDropdown, activeIndex,\n setFilteredSuggestions, setOpen, setActiveIndex, userClosedDropdownRef,\n } = s;\n useEffect(() => {\n const suggestions = propSuggestions ?? [];\n if (async || !inputValue) {\n setFilteredSuggestions(suggestions);\n return;\n }\n const filtered = filterSuggestions(suggestions, inputValue, matchMode, getLabel);\n setFilteredSuggestions(filtered);\n maybeAutoOpen(\n { inputValue, isInputFocused, composition, justCompletedGhost, userClosedDropdownRef, activeIndex, setOpen, setActiveIndex },\n filtered.length > 0,\n );\n // `userClosedDropdown` (state) stays a dependency so this effect still\n // reruns on every change of it, same as before — only the VALUE read\n // inside `maybeAutoOpen` moved to the ref (see `userClosedDropdownRef`'s\n // doc comment).\n }, [\n propSuggestions, inputValue, async, getLabel, matchMode, isInputFocused, composition,\n justCompletedGhost, userClosedDropdown, activeIndex, setFilteredSuggestions, setOpen, setActiveIndex,\n userClosedDropdownRef,\n ]);\n}\n\nfunction useGhostText<T>(p: AutocompleteProps<T>, s: AutocompleteState<T>): void {\n const getLabel = p.getLabel ?? defaultGetLabel;\n const getType = p.getSuggestionType ?? defaultGetSuggestionType;\n const showGhost = p.showGhostText ?? true;\n const { inputValue, filteredSuggestions, isInputFocused, composition, setGhost } = s;\n useEffect(() => {\n if (!inputValue || !isInputFocused || composition || !showGhost) {\n setGhost('');\n return;\n }\n const first = firstGhostSuggestion(filteredSuggestions, inputValue, getLabel, getType);\n setGhost(first ? getLabel(first).slice(inputValue.length) : '');\n }, [inputValue, filteredSuggestions, isInputFocused, composition, showGhost, getLabel, getType, setGhost]);\n}\n\n// ---- selection (split by mode to keep each function under the complexity bar) -\n\nfunction commitMultiSelect<T>(item: T, p: AutocompleteProps<T>, s: AutocompleteState<T>, onChange: (v: string) => void): void {\n const getKey = p.getKey ?? defaultGetKey;\n const current = p.selectedItems ?? [];\n if (!current.some((sel) => getKey(sel) === getKey(item))) p.onSelectedItemsChange?.([...current, item]);\n s.setInputValue('');\n onChange('');\n setDeliberateClose(s, false);\n}\n\n/**\n * A single-select pick's own correction must land in the same tick as\n * `setInputValue(label)`, not up to `debounceMs` later — so it calls\n * `p.onChange` DIRECTLY rather than going through `debouncedOnChange`\n * (FUT-2860). `commitMultiSelect` is unaffected: it keeps calling the\n * debounced `onChange('')`, per the ticket's own decision.\n */\nfunction commitSingleSelect<T>(item: T, p: AutocompleteProps<T>, s: AutocompleteState<T>): void {\n const label = (p.getLabel ?? defaultGetLabel)(item);\n s.setInputValue(label);\n p.onChange(label);\n}\n\n/** Apply a pick: open a link suggestion, or commit a search one to the input. */\nfunction commitPick<T>(\n item: T,\n linkUrl: string | null,\n p: AutocompleteProps<T>,\n s: AutocompleteState<T>,\n onChange: (v: string) => void,\n): void {\n if (linkUrl !== null) (p.openLink ?? defaultOpenLink)(linkUrl, item);\n else if (p.multiple) commitMultiSelect(item, p, s, onChange);\n else commitSingleSelect(item, p, s);\n}\n\nfunction runSelectItem<T>(item: T, p: AutocompleteProps<T>, s: AutocompleteState<T>, onChange: (v: string) => void): void {\n const url = (p.getUrl ?? defaultGetUrl)(item);\n const isLink = (p.getSuggestionType ?? defaultGetSuggestionType)(item) === 'link' && Boolean(url);\n // A single-select pick (search or link) ends the current search: the list\n // stays closed until the user types again. `multiple` mode is unchanged —\n // commitMultiSelect already clears inputValue and resets the flag itself,\n // so the empty-input branch of the filter effect keeps the list closed.\n const isSingleSelectPick = isLink || !p.multiple;\n // Cancel a still-pending keystroke debounce BEFORE dispatching the pick, so\n // no branch below — including `openLink`, which never touches `onChange`\n // at all — can leave it armed to fire the STALE pre-pick text later\n // (FUT-2779 #1). `commitMultiSelect` already clears it as a side effect of\n // calling the same `debouncedOnChange`; `commitSingleSelect` bypasses that\n // path entirely now (FUT-2860), so this cancel is what covers IT and a\n // `link` pick (which skips `onChange` entirely) alike.\n if (s.debounceRef.current) window.clearTimeout(s.debounceRef.current);\n commitPick(item, isLink ? (url as string) : null, p, s, onChange);\n s.setOpen(false);\n s.setActiveIndex(-1);\n p.onSelect?.(item);\n s.inputRef.current?.focus();\n // Set LAST so a re-fired `onFocus` cannot clear the flag. The close itself\n // relies on the input never blurring during a pick (the option's\n // `onMouseDown` preventDefault, and Enter keeps focus): `onFocus` reopens a\n // non-empty input directly, without reading this flag. The REF half is set\n // in the same synchronous tick as the pick, so an effect scheduled by an\n // earlier keystroke — and still pending when this runs — reads the\n // up-to-date value instead of the one it closed over (FUT-2780).\n if (isSingleSelectPick) setDeliberateClose(s, true);\n}\n\nfunction buildKeyContext<T>(\n p: AutocompleteProps<T>,\n s: AutocompleteState<T>,\n selectItem: (item: T) => void,\n onChange: (v: string) => void,\n): KeyContext<T> {\n return {\n open: s.open, activeIndex: s.activeIndex, filteredSuggestions: s.filteredSuggestions,\n maxVisibleItems: p.maxVisibleItems ?? 10, allowFreeText: p.allowFreeText ?? true,\n inputValue: s.inputValue, ghost: s.ghost, isInputFocused: s.isInputFocused,\n multiple: Boolean(p.multiple), selectedItems: p.selectedItems ?? [],\n getLabel: p.getLabel ?? defaultGetLabel,\n getSuggestionType: p.getSuggestionType ?? defaultGetSuggestionType,\n setOpen: s.setOpen, setActiveIndex: s.setActiveIndex,\n setUserClosedDropdown: (closed: boolean) => setDeliberateClose(s, closed),\n setInputValue: s.setInputValue, setGhost: s.setGhost, setJustCompletedGhost: s.setJustCompletedGhost,\n debouncedOnChange: onChange, selectItem, onSelectedItemsChange: p.onSelectedItemsChange,\n };\n}\n\n/** The full view-model the presentational component renders. */\nexport interface AutocompleteView<T> {\n id: string;\n listId: string;\n optionIdPrefix: string;\n state: AutocompleteState<T>;\n visibleSuggestions: T[];\n activeDescendant: string | undefined;\n selectItem: (item: T) => void;\n removeSelectedItem: (item: T) => void;\n onKeyDown: (e: React.KeyboardEvent<HTMLInputElement>) => void;\n onInputChange: (e: React.ChangeEvent<HTMLInputElement>) => void;\n onFocus: () => void;\n onBlur: () => void;\n onClickAway: () => void;\n}\n\n/** Wire state, effects, and (plain, per-render) handlers for the Autocomplete component. */\nexport function useAutocomplete<T>(p: AutocompleteProps<T>): AutocompleteView<T> {\n const componentId = useId();\n const id = p.id || componentId;\n const optionIdPrefix = `${id}-option`;\n const s = useAutocompleteState<T>(p.value, p.suggestions ?? []);\n\n const debouncedOnChange = (val: string): void => {\n if (s.debounceRef.current) window.clearTimeout(s.debounceRef.current);\n s.debounceRef.current = window.setTimeout(() => p.onChange(val), p.debounceMs ?? 150);\n };\n\n useValueSync(p.value, s.setInputValue);\n useDebounceCleanup(s.debounceRef);\n useScrollActiveIntoView(s.activeIndex, optionIdPrefix, s.listRef);\n useGhostFlagReset(s.justCompletedGhost, s.setJustCompletedGhost);\n useLoadingOpen(\n Boolean(p.isLoading),\n s.inputValue,\n Boolean(p.disabled),\n s.userClosedDropdownRef,\n s.setOpen,\n s.setActiveIndex,\n );\n useLocalFilter(p, s);\n useGhostText(p, s);\n\n const selectItem = (item: T): void => runSelectItem(item, p, s, debouncedOnChange);\n\n return {\n id,\n listId: `${id}-listbox`,\n optionIdPrefix,\n state: s,\n visibleSuggestions: s.filteredSuggestions.slice(0, p.maxVisibleItems ?? 10),\n activeDescendant: s.activeIndex >= 0 ? `${optionIdPrefix}-${s.activeIndex}` : undefined,\n selectItem,\n removeSelectedItem: (item: T): void => {\n const getKey = p.getKey ?? defaultGetKey;\n p.onSelectedItemsChange?.((p.selectedItems ?? []).filter((sel) => getKey(sel) !== getKey(item)));\n s.inputRef.current?.focus();\n },\n onKeyDown: (e: React.KeyboardEvent<HTMLInputElement>): void =>\n handleAutocompleteKey(e, s.composition, buildKeyContext(p, s, selectItem, debouncedOnChange)),\n onInputChange: (e: React.ChangeEvent<HTMLInputElement>): void => {\n s.setInputValue(e.target.value);\n debouncedOnChange(e.target.value);\n if (!s.open || s.filteredSuggestions.length === 0) s.setActiveIndex(-1);\n setDeliberateClose(s, false);\n },\n // Unconditionally reopens on a non-empty input, unguarded by\n // `userClosedDropdownRef` — plausible on a touch device that blurs the\n // input on `touchstart` before a tap's own `click`/`mousedown` reaches the\n // option (FUT-2779 #2). Checked under Playwright touch emulation\n // (`hasTouch`/`isMobile` context, both the `.tap()` API and raw CDP\n // `Input.dispatchTouchEvent` at the option's coordinates) against this\n // Chromium build: `document.activeElement` never left the input across\n // the touch, so the reopen never happened — not reproduced, left\n // unguarded per the ticket's decision rather than fixed blind.\n onFocus: (): void => {\n s.setIsInputFocused(true);\n setDeliberateClose(s, false);\n if (!s.inputValue.trim()) return;\n s.setOpen(true);\n if (s.filteredSuggestions.length > 0 && s.activeIndex === -1) s.setActiveIndex(0);\n },\n onBlur: (): void => {\n window.setTimeout(() => s.setIsInputFocused(false), 150);\n },\n onClickAway: (): void => {\n s.setOpen(false);\n s.setActiveIndex(-1);\n setDeliberateClose(s, true);\n },\n };\n}\n"],"mappings":"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","names":[]}
@@ -2,9 +2,9 @@ import "../chunk-2LXHUGYB.js";
2
2
  import {
3
3
  Autocomplete,
4
4
  Autocomplete_default
5
- } from "../chunk-PXGURBIU.js";
5
+ } from "../chunk-JBGCGYEC.js";
6
6
  import "../chunk-XBLFK2FL.js";
7
- import "../chunk-YWJZPN5C.js";
7
+ import "../chunk-SY5FYBAF.js";
8
8
  import "../chunk-PELRSZFU.js";
9
9
  import "../chunk-JXS56EW5.js";
10
10
  import "../chunk-M47ZOUGF.js";
@@ -1 +1 @@
1
- {"version":3,"file":"useAutocomplete.d.ts","sourceRoot":"","sources":["../../../../../src/components/form/Autocomplete/useAutocomplete.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAE9D,KAAK,MAAM,CAAC,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;AAEzD,8DAA8D;AAC9D,UAAU,iBAAiB,CAAC,CAAC;IAC3B,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAC9B,WAAW,EAAE,OAAO,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IAChC,mBAAmB,EAAE,CAAC,EAAE,CAAC;IACzB,sBAAsB,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;IACpC,cAAc,EAAE,OAAO,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IACnC,kBAAkB,EAAE,OAAO,CAAC;IAC5B,qBAAqB,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IACvC,kBAAkB,EAAE,OAAO,CAAC;IAC5B,qBAAqB,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IACvC;;;;;;;OAOG;IACH,qBAAqB,EAAE,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IAChD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IACnD,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IAClD,WAAW,EAAE,KAAK,CAAC,SAAS,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;CAClD;AAiPD,gEAAgE;AAChE,MAAM,WAAW,gBAAgB,CAAC,CAAC;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC;IAC5B,kBAAkB,EAAE,CAAC,EAAE,CAAC;IACxB,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,UAAU,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,CAAC;IAC9B,kBAAkB,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,CAAC;IACtC,SAAS,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,gBAAgB,CAAC,KAAK,IAAI,CAAC;IAC9D,aAAa,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC,gBAAgB,CAAC,KAAK,IAAI,CAAC;IAChE,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,WAAW,EAAE,MAAM,IAAI,CAAC;CACzB;AAED,4FAA4F;AAC5F,wBAAgB,eAAe,CAAC,CAAC,EAAE,CAAC,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,CA0E/E"}
1
+ {"version":3,"file":"useAutocomplete.d.ts","sourceRoot":"","sources":["../../../../../src/components/form/Autocomplete/useAutocomplete.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAE9D,KAAK,MAAM,CAAC,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;AAEzD,8DAA8D;AAC9D,UAAU,iBAAiB,CAAC,CAAC;IAC3B,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAC9B,WAAW,EAAE,OAAO,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IAChC,mBAAmB,EAAE,CAAC,EAAE,CAAC;IACzB,sBAAsB,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;IACpC,cAAc,EAAE,OAAO,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IACnC,kBAAkB,EAAE,OAAO,CAAC;IAC5B,qBAAqB,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IACvC,kBAAkB,EAAE,OAAO,CAAC;IAC5B,qBAAqB,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IACvC;;;;;;;OAOG;IACH,qBAAqB,EAAE,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IAChD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IACnD,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IAClD,WAAW,EAAE,KAAK,CAAC,SAAS,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;CAClD;AAwPD,gEAAgE;AAChE,MAAM,WAAW,gBAAgB,CAAC,CAAC;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC;IAC5B,kBAAkB,EAAE,CAAC,EAAE,CAAC;IACxB,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,UAAU,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,CAAC;IAC9B,kBAAkB,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,CAAC;IACtC,SAAS,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,gBAAgB,CAAC,KAAK,IAAI,CAAC;IAC9D,aAAa,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC,gBAAgB,CAAC,KAAK,IAAI,CAAC;IAChE,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,WAAW,EAAE,MAAM,IAAI,CAAC;CACzB;AAED,4FAA4F;AAC5F,wBAAgB,eAAe,CAAC,CAAC,EAAE,CAAC,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,CA0E/E"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@12-apps/ui",
3
- "version": "6.45.3",
3
+ "version": "6.45.4",
4
4
  "license": "MIT",
5
5
  "packageManager": "pnpm@10.34.5",
6
6
  "type": "module",
@@ -218,10 +218,17 @@ function commitMultiSelect<T>(item: T, p: AutocompleteProps<T>, s: AutocompleteS
218
218
  setDeliberateClose(s, false);
219
219
  }
220
220
 
221
- function commitSingleSelect<T>(item: T, p: AutocompleteProps<T>, s: AutocompleteState<T>, onChange: (v: string) => void): void {
221
+ /**
222
+ * A single-select pick's own correction must land in the same tick as
223
+ * `setInputValue(label)`, not up to `debounceMs` later — so it calls
224
+ * `p.onChange` DIRECTLY rather than going through `debouncedOnChange`
225
+ * (FUT-2860). `commitMultiSelect` is unaffected: it keeps calling the
226
+ * debounced `onChange('')`, per the ticket's own decision.
227
+ */
228
+ function commitSingleSelect<T>(item: T, p: AutocompleteProps<T>, s: AutocompleteState<T>): void {
222
229
  const label = (p.getLabel ?? defaultGetLabel)(item);
223
230
  s.setInputValue(label);
224
- onChange(label);
231
+ p.onChange(label);
225
232
  }
226
233
 
227
234
  /** Apply a pick: open a link suggestion, or commit a search one to the input. */
@@ -234,7 +241,7 @@ function commitPick<T>(
234
241
  ): void {
235
242
  if (linkUrl !== null) (p.openLink ?? defaultOpenLink)(linkUrl, item);
236
243
  else if (p.multiple) commitMultiSelect(item, p, s, onChange);
237
- else commitSingleSelect(item, p, s, onChange);
244
+ else commitSingleSelect(item, p, s);
238
245
  }
239
246
 
240
247
  function runSelectItem<T>(item: T, p: AutocompleteProps<T>, s: AutocompleteState<T>, onChange: (v: string) => void): void {
@@ -248,10 +255,10 @@ function runSelectItem<T>(item: T, p: AutocompleteProps<T>, s: AutocompleteState
248
255
  // Cancel a still-pending keystroke debounce BEFORE dispatching the pick, so
249
256
  // no branch below — including `openLink`, which never touches `onChange`
250
257
  // at all — can leave it armed to fire the STALE pre-pick text later
251
- // (FUT-2779 #1). `commitSingleSelect`/`commitMultiSelect` already clear it
252
- // as a side effect of calling the same `debouncedOnChange`; this makes it
253
- // unconditional so a `link` pick (which skips `onChange` entirely) is
254
- // covered too.
258
+ // (FUT-2779 #1). `commitMultiSelect` already clears it as a side effect of
259
+ // calling the same `debouncedOnChange`; `commitSingleSelect` bypasses that
260
+ // path entirely now (FUT-2860), so this cancel is what covers IT and a
261
+ // `link` pick (which skips `onChange` entirely) alike.
255
262
  if (s.debounceRef.current) window.clearTimeout(s.debounceRef.current);
256
263
  commitPick(item, isLink ? (url as string) : null, p, s, onChange);
257
264
  s.setOpen(false);
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/form/Autocomplete/useAutocomplete.ts"],"sourcesContent":["import { useEffect, useId, useRef, useState } from 'react';\n\nimport {\n defaultGetKey,\n defaultGetLabel,\n defaultGetSuggestionType,\n defaultGetUrl,\n defaultOpenLink,\n filterSuggestions,\n firstGhostSuggestion,\n type MatchMode,\n} from './Autocomplete.helpers';\nimport { handleAutocompleteKey, type KeyContext } from './Autocomplete.keys';\nimport type { AutocompleteProps } from './Autocomplete.types';\n\ntype Setter<V> = React.Dispatch<React.SetStateAction<V>>;\n\n/** All mutable state + refs for one Autocomplete instance. */\ninterface AutocompleteState<T> {\n open: boolean;\n setOpen: Setter<boolean>;\n activeIndex: number;\n setActiveIndex: Setter<number>;\n ghost: string;\n setGhost: Setter<string>;\n inputValue: string;\n setInputValue: Setter<string>;\n composition: boolean;\n setComposition: Setter<boolean>;\n filteredSuggestions: T[];\n setFilteredSuggestions: Setter<T[]>;\n isInputFocused: boolean;\n setIsInputFocused: Setter<boolean>;\n justCompletedGhost: boolean;\n setJustCompletedGhost: Setter<boolean>;\n userClosedDropdown: boolean;\n setUserClosedDropdown: Setter<boolean>;\n /**\n * Mirrors `userClosedDropdown`, set synchronously wherever the state is\n * (see {@link setDeliberateClose}). An effect scheduled by one render and\n * flushed after a LATER render has already changed this flag reads a\n * stale, closed-over `userClosedDropdown` — but `.current` on a ref is\n * dereferenced live, so it always reflects the latest write regardless of\n * which render's closure is doing the reading (FUT-2780).\n */\n userClosedDropdownRef: React.RefObject<boolean>;\n inputRef: React.RefObject<HTMLInputElement | null>;\n listRef: React.RefObject<HTMLUListElement | null>;\n debounceRef: React.RefObject<number | undefined>;\n}\n\nfunction useAutocompleteState<T>(value: string, suggestions: T[]): AutocompleteState<T> {\n const [open, setOpen] = useState(false);\n const [activeIndex, setActiveIndex] = useState(-1);\n const [ghost, setGhost] = useState('');\n const [inputValue, setInputValue] = useState(value);\n const [composition, setComposition] = useState(false);\n const [filteredSuggestions, setFilteredSuggestions] = useState<T[]>(suggestions);\n const [isInputFocused, setIsInputFocused] = useState(false);\n const [justCompletedGhost, setJustCompletedGhost] = useState(false);\n const [userClosedDropdown, setUserClosedDropdown] = useState(false);\n const userClosedDropdownRef = useRef(false);\n const inputRef = useRef<HTMLInputElement>(null);\n const listRef = useRef<HTMLUListElement | null>(null);\n const debounceRef = useRef<number | undefined>(undefined);\n return {\n open, setOpen, activeIndex, setActiveIndex, ghost, setGhost, inputValue, setInputValue,\n composition, setComposition, filteredSuggestions, setFilteredSuggestions, isInputFocused,\n setIsInputFocused, justCompletedGhost, setJustCompletedGhost, userClosedDropdown,\n setUserClosedDropdown, userClosedDropdownRef, inputRef, listRef, debounceRef,\n };\n}\n\n/**\n * Set the \"this close was deliberate\" flag in both the ref effects read\n * synchronously (live, even from a stale closure) and the state the rest of\n * the component reads for render — every call site that touches\n * `userClosedDropdown` goes through this so the two never drift (FUT-2780).\n */\nfunction setDeliberateClose<T>(s: AutocompleteState<T>, closed: boolean): void {\n s.userClosedDropdownRef.current = closed;\n s.setUserClosedDropdown(closed);\n}\n\n// ---- effects (one tiny hook each; explicit params keep deps complete) --------\n\nfunction useValueSync(value: string, setInputValue: Setter<string>): void {\n useEffect(() => setInputValue(value), [value, setInputValue]);\n}\n\nfunction useDebounceCleanup(debounceRef: React.RefObject<number | undefined>): void {\n useEffect(\n () => () => {\n if (debounceRef.current) window.clearTimeout(debounceRef.current);\n },\n [debounceRef],\n );\n}\n\nfunction useScrollActiveIntoView(\n activeIndex: number,\n optionIdPrefix: string,\n listRef: React.RefObject<HTMLUListElement | null>,\n): void {\n useEffect(() => {\n if (activeIndex < 0 || !listRef.current) return;\n document\n .getElementById(`${optionIdPrefix}-${activeIndex}`)\n ?.scrollIntoView({ block: 'nearest' });\n }, [activeIndex, optionIdPrefix, listRef]);\n}\n\nfunction useGhostFlagReset(justCompletedGhost: boolean, setJustCompletedGhost: Setter<boolean>): void {\n useEffect(() => {\n if (!justCompletedGhost) return;\n const timer = setTimeout(() => setJustCompletedGhost(false), 50);\n return () => clearTimeout(timer);\n }, [justCompletedGhost, setJustCompletedGhost]);\n}\n\nfunction useLoadingOpen(\n isLoading: boolean,\n inputValue: string,\n disabled: boolean,\n userClosedDropdownRef: React.RefObject<boolean>,\n setOpen: Setter<boolean>,\n setActiveIndex: Setter<number>,\n): void {\n useEffect(() => {\n if (isLoading && inputValue.trim().length > 0 && !disabled && !userClosedDropdownRef.current) setOpen(true);\n if (disabled) {\n setOpen(false);\n setActiveIndex(-1);\n }\n }, [isLoading, inputValue, disabled, userClosedDropdownRef, setOpen, setActiveIndex]);\n}\n\n/** Inputs to the auto-open check, all primitive/stable so effect deps stay complete. */\ninterface AutoOpenArgs {\n inputValue: string;\n isInputFocused: boolean;\n composition: boolean;\n justCompletedGhost: boolean;\n userClosedDropdownRef: React.RefObject<boolean>;\n activeIndex: number;\n setOpen: Setter<boolean>;\n setActiveIndex: Setter<number>;\n}\n\n/** Auto-open the dropdown once local filtering has a fresh result set. */\nfunction maybeAutoOpen(a: AutoOpenArgs, hasResults: boolean): void {\n const canAutoOpen =\n a.inputValue.trim() &&\n a.isInputFocused &&\n !a.composition &&\n !a.justCompletedGhost &&\n !a.userClosedDropdownRef.current;\n if (!canAutoOpen) return;\n a.setOpen(true);\n if (hasResults && a.activeIndex === -1) a.setActiveIndex(0);\n}\n\nfunction useLocalFilter<T>(p: AutocompleteProps<T>, s: AutocompleteState<T>): void {\n const propSuggestions = p.suggestions;\n const getLabel = p.getLabel ?? defaultGetLabel;\n const matchMode: MatchMode = p.matchMode ?? 'contains';\n const async = Boolean(p.async);\n const {\n inputValue, isInputFocused, composition, justCompletedGhost, userClosedDropdown, activeIndex,\n setFilteredSuggestions, setOpen, setActiveIndex, userClosedDropdownRef,\n } = s;\n useEffect(() => {\n const suggestions = propSuggestions ?? [];\n if (async || !inputValue) {\n setFilteredSuggestions(suggestions);\n return;\n }\n const filtered = filterSuggestions(suggestions, inputValue, matchMode, getLabel);\n setFilteredSuggestions(filtered);\n maybeAutoOpen(\n { inputValue, isInputFocused, composition, justCompletedGhost, userClosedDropdownRef, activeIndex, setOpen, setActiveIndex },\n filtered.length > 0,\n );\n // `userClosedDropdown` (state) stays a dependency so this effect still\n // reruns on every change of it, same as before — only the VALUE read\n // inside `maybeAutoOpen` moved to the ref (see `userClosedDropdownRef`'s\n // doc comment).\n }, [\n propSuggestions, inputValue, async, getLabel, matchMode, isInputFocused, composition,\n justCompletedGhost, userClosedDropdown, activeIndex, setFilteredSuggestions, setOpen, setActiveIndex,\n userClosedDropdownRef,\n ]);\n}\n\nfunction useGhostText<T>(p: AutocompleteProps<T>, s: AutocompleteState<T>): void {\n const getLabel = p.getLabel ?? defaultGetLabel;\n const getType = p.getSuggestionType ?? defaultGetSuggestionType;\n const showGhost = p.showGhostText ?? true;\n const { inputValue, filteredSuggestions, isInputFocused, composition, setGhost } = s;\n useEffect(() => {\n if (!inputValue || !isInputFocused || composition || !showGhost) {\n setGhost('');\n return;\n }\n const first = firstGhostSuggestion(filteredSuggestions, inputValue, getLabel, getType);\n setGhost(first ? getLabel(first).slice(inputValue.length) : '');\n }, [inputValue, filteredSuggestions, isInputFocused, composition, showGhost, getLabel, getType, setGhost]);\n}\n\n// ---- selection (split by mode to keep each function under the complexity bar) -\n\nfunction commitMultiSelect<T>(item: T, p: AutocompleteProps<T>, s: AutocompleteState<T>, onChange: (v: string) => void): void {\n const getKey = p.getKey ?? defaultGetKey;\n const current = p.selectedItems ?? [];\n if (!current.some((sel) => getKey(sel) === getKey(item))) p.onSelectedItemsChange?.([...current, item]);\n s.setInputValue('');\n onChange('');\n setDeliberateClose(s, false);\n}\n\nfunction commitSingleSelect<T>(item: T, p: AutocompleteProps<T>, s: AutocompleteState<T>, onChange: (v: string) => void): void {\n const label = (p.getLabel ?? defaultGetLabel)(item);\n s.setInputValue(label);\n onChange(label);\n}\n\n/** Apply a pick: open a link suggestion, or commit a search one to the input. */\nfunction commitPick<T>(\n item: T,\n linkUrl: string | null,\n p: AutocompleteProps<T>,\n s: AutocompleteState<T>,\n onChange: (v: string) => void,\n): void {\n if (linkUrl !== null) (p.openLink ?? defaultOpenLink)(linkUrl, item);\n else if (p.multiple) commitMultiSelect(item, p, s, onChange);\n else commitSingleSelect(item, p, s, onChange);\n}\n\nfunction runSelectItem<T>(item: T, p: AutocompleteProps<T>, s: AutocompleteState<T>, onChange: (v: string) => void): void {\n const url = (p.getUrl ?? defaultGetUrl)(item);\n const isLink = (p.getSuggestionType ?? defaultGetSuggestionType)(item) === 'link' && Boolean(url);\n // A single-select pick (search or link) ends the current search: the list\n // stays closed until the user types again. `multiple` mode is unchanged —\n // commitMultiSelect already clears inputValue and resets the flag itself,\n // so the empty-input branch of the filter effect keeps the list closed.\n const isSingleSelectPick = isLink || !p.multiple;\n // Cancel a still-pending keystroke debounce BEFORE dispatching the pick, so\n // no branch below — including `openLink`, which never touches `onChange`\n // at all — can leave it armed to fire the STALE pre-pick text later\n // (FUT-2779 #1). `commitSingleSelect`/`commitMultiSelect` already clear it\n // as a side effect of calling the same `debouncedOnChange`; this makes it\n // unconditional so a `link` pick (which skips `onChange` entirely) is\n // covered too.\n if (s.debounceRef.current) window.clearTimeout(s.debounceRef.current);\n commitPick(item, isLink ? (url as string) : null, p, s, onChange);\n s.setOpen(false);\n s.setActiveIndex(-1);\n p.onSelect?.(item);\n s.inputRef.current?.focus();\n // Set LAST so a re-fired `onFocus` cannot clear the flag. The close itself\n // relies on the input never blurring during a pick (the option's\n // `onMouseDown` preventDefault, and Enter keeps focus): `onFocus` reopens a\n // non-empty input directly, without reading this flag. The REF half is set\n // in the same synchronous tick as the pick, so an effect scheduled by an\n // earlier keystroke — and still pending when this runs — reads the\n // up-to-date value instead of the one it closed over (FUT-2780).\n if (isSingleSelectPick) setDeliberateClose(s, true);\n}\n\nfunction buildKeyContext<T>(\n p: AutocompleteProps<T>,\n s: AutocompleteState<T>,\n selectItem: (item: T) => void,\n onChange: (v: string) => void,\n): KeyContext<T> {\n return {\n open: s.open, activeIndex: s.activeIndex, filteredSuggestions: s.filteredSuggestions,\n maxVisibleItems: p.maxVisibleItems ?? 10, allowFreeText: p.allowFreeText ?? true,\n inputValue: s.inputValue, ghost: s.ghost, isInputFocused: s.isInputFocused,\n multiple: Boolean(p.multiple), selectedItems: p.selectedItems ?? [],\n getLabel: p.getLabel ?? defaultGetLabel,\n getSuggestionType: p.getSuggestionType ?? defaultGetSuggestionType,\n setOpen: s.setOpen, setActiveIndex: s.setActiveIndex,\n setUserClosedDropdown: (closed: boolean) => setDeliberateClose(s, closed),\n setInputValue: s.setInputValue, setGhost: s.setGhost, setJustCompletedGhost: s.setJustCompletedGhost,\n debouncedOnChange: onChange, selectItem, onSelectedItemsChange: p.onSelectedItemsChange,\n };\n}\n\n/** The full view-model the presentational component renders. */\nexport interface AutocompleteView<T> {\n id: string;\n listId: string;\n optionIdPrefix: string;\n state: AutocompleteState<T>;\n visibleSuggestions: T[];\n activeDescendant: string | undefined;\n selectItem: (item: T) => void;\n removeSelectedItem: (item: T) => void;\n onKeyDown: (e: React.KeyboardEvent<HTMLInputElement>) => void;\n onInputChange: (e: React.ChangeEvent<HTMLInputElement>) => void;\n onFocus: () => void;\n onBlur: () => void;\n onClickAway: () => void;\n}\n\n/** Wire state, effects, and (plain, per-render) handlers for the Autocomplete component. */\nexport function useAutocomplete<T>(p: AutocompleteProps<T>): AutocompleteView<T> {\n const componentId = useId();\n const id = p.id || componentId;\n const optionIdPrefix = `${id}-option`;\n const s = useAutocompleteState<T>(p.value, p.suggestions ?? []);\n\n const debouncedOnChange = (val: string): void => {\n if (s.debounceRef.current) window.clearTimeout(s.debounceRef.current);\n s.debounceRef.current = window.setTimeout(() => p.onChange(val), p.debounceMs ?? 150);\n };\n\n useValueSync(p.value, s.setInputValue);\n useDebounceCleanup(s.debounceRef);\n useScrollActiveIntoView(s.activeIndex, optionIdPrefix, s.listRef);\n useGhostFlagReset(s.justCompletedGhost, s.setJustCompletedGhost);\n useLoadingOpen(\n Boolean(p.isLoading),\n s.inputValue,\n Boolean(p.disabled),\n s.userClosedDropdownRef,\n s.setOpen,\n s.setActiveIndex,\n );\n useLocalFilter(p, s);\n useGhostText(p, s);\n\n const selectItem = (item: T): void => runSelectItem(item, p, s, debouncedOnChange);\n\n return {\n id,\n listId: `${id}-listbox`,\n optionIdPrefix,\n state: s,\n visibleSuggestions: s.filteredSuggestions.slice(0, p.maxVisibleItems ?? 10),\n activeDescendant: s.activeIndex >= 0 ? `${optionIdPrefix}-${s.activeIndex}` : undefined,\n selectItem,\n removeSelectedItem: (item: T): void => {\n const getKey = p.getKey ?? defaultGetKey;\n p.onSelectedItemsChange?.((p.selectedItems ?? []).filter((sel) => getKey(sel) !== getKey(item)));\n s.inputRef.current?.focus();\n },\n onKeyDown: (e: React.KeyboardEvent<HTMLInputElement>): void =>\n handleAutocompleteKey(e, s.composition, buildKeyContext(p, s, selectItem, debouncedOnChange)),\n onInputChange: (e: React.ChangeEvent<HTMLInputElement>): void => {\n s.setInputValue(e.target.value);\n debouncedOnChange(e.target.value);\n if (!s.open || s.filteredSuggestions.length === 0) s.setActiveIndex(-1);\n setDeliberateClose(s, false);\n },\n // Unconditionally reopens on a non-empty input, unguarded by\n // `userClosedDropdownRef` — plausible on a touch device that blurs the\n // input on `touchstart` before a tap's own `click`/`mousedown` reaches the\n // option (FUT-2779 #2). Checked under Playwright touch emulation\n // (`hasTouch`/`isMobile` context, both the `.tap()` API and raw CDP\n // `Input.dispatchTouchEvent` at the option's coordinates) against this\n // Chromium build: `document.activeElement` never left the input across\n // the touch, so the reopen never happened — not reproduced, left\n // unguarded per the ticket's decision rather than fixed blind.\n onFocus: (): void => {\n s.setIsInputFocused(true);\n setDeliberateClose(s, false);\n if (!s.inputValue.trim()) return;\n s.setOpen(true);\n if (s.filteredSuggestions.length > 0 && s.activeIndex === -1) s.setActiveIndex(0);\n },\n onBlur: (): void => {\n window.setTimeout(() => s.setIsInputFocused(false), 150);\n },\n onClickAway: (): void => {\n s.setOpen(false);\n s.setActiveIndex(-1);\n setDeliberateClose(s, true);\n },\n };\n}\n"],"mappings":"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","names":[]}