@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.
- package/dist/_internal/components/form/Autocomplete/Autocomplete.js +2 -2
- package/dist/_internal/components/form/Autocomplete/useAutocomplete.js +1 -1
- package/dist/_internal/components/form/index.js +2 -2
- package/dist/_internal/components/index.js +2 -2
- package/dist/{chunk-PXGURBIU.js → chunk-JBGCGYEC.js} +2 -2
- package/dist/{chunk-YWJZPN5C.js → chunk-SY5FYBAF.js} +4 -4
- package/dist/chunk-SY5FYBAF.js.map +1 -0
- package/dist/form/Autocomplete.js +2 -2
- package/dist/types/components/form/Autocomplete/useAutocomplete.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/form/Autocomplete/useAutocomplete.ts +14 -7
- package/dist/chunk-YWJZPN5C.js.map +0 -1
- /package/dist/{chunk-PXGURBIU.js.map → chunk-JBGCGYEC.js.map} +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Autocomplete,
|
|
3
3
|
Autocomplete_default
|
|
4
|
-
} from "../../../../chunk-
|
|
4
|
+
} from "../../../../chunk-JBGCGYEC.js";
|
|
5
5
|
import "../../../../chunk-XBLFK2FL.js";
|
|
6
|
-
import "../../../../chunk-
|
|
6
|
+
import "../../../../chunk-SY5FYBAF.js";
|
|
7
7
|
import "../../../../chunk-PELRSZFU.js";
|
|
8
8
|
import "../../../../chunk-JXS56EW5.js";
|
|
9
9
|
import "../../../../chunk-M47ZOUGF.js";
|
|
@@ -146,9 +146,9 @@ import "../../../chunk-O7QPPJAK.js";
|
|
|
146
146
|
import "../../../chunk-2LXHUGYB.js";
|
|
147
147
|
import {
|
|
148
148
|
Autocomplete
|
|
149
|
-
} from "../../../chunk-
|
|
149
|
+
} from "../../../chunk-JBGCGYEC.js";
|
|
150
150
|
import "../../../chunk-XBLFK2FL.js";
|
|
151
|
-
import "../../../chunk-
|
|
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-
|
|
390
|
+
} from "../../chunk-JBGCGYEC.js";
|
|
391
391
|
import "../../chunk-XBLFK2FL.js";
|
|
392
|
-
import "../../chunk-
|
|
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-
|
|
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-
|
|
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
|
|
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
|
|
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-
|
|
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-
|
|
5
|
+
} from "../chunk-JBGCGYEC.js";
|
|
6
6
|
import "../chunk-XBLFK2FL.js";
|
|
7
|
-
import "../chunk-
|
|
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;
|
|
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
|
@@ -218,10 +218,17 @@ function commitMultiSelect<T>(item: T, p: AutocompleteProps<T>, s: AutocompleteS
|
|
|
218
218
|
setDeliberateClose(s, false);
|
|
219
219
|
}
|
|
220
220
|
|
|
221
|
-
|
|
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
|
|
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). `
|
|
252
|
-
//
|
|
253
|
-
//
|
|
254
|
-
//
|
|
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":[]}
|
|
File without changes
|