import type { TextInput } from 'react-native'; import { ReactStore } from '../../store/ReactStore'; import { type ItemEqualityComparer } from '../../internals/itemEquality'; import { PopupTriggerMap } from '../../utils/popups/PopupTriggerMap'; import type { ComboboxRoot } from '../root/ComboboxRoot'; /** * The items to filter and choose from: strings, `{ value, label }` records for * non-string values, or `{ label, items }` records to group them. */ export type ComboboxItems = ReadonlyArray; }>; export interface ComboboxItem { value: unknown; label: string; } /** * A group of items, which is what `Combobox.Group` renders. Its `value` defaults * to its label, and is only ever an identity — a group is never selectable. */ export interface ComboboxItemGroup { value: unknown; label: string; items: ComboboxItem[]; } /** * An entry in the list: either a selectable item or a group of them. */ export type ComboboxEntry = ComboboxItem | ComboboxItemGroup; /** Whether a list entry is a group rather than a selectable item. */ export declare function isComboboxGroup(entry: ComboboxEntry): entry is ComboboxItemGroup; /** Normalizes the `items` prop into `{ value, label }` records and groups. */ export declare function normalizeComboboxItems(items: ComboboxItems | undefined): ComboboxEntry[]; /** * Every selectable item in the list, groups flattened away. Selection is always * resolved against this — a group is a rendering concern, not a value. */ export declare function flattenComboboxEntries(entries: ComboboxEntry[]): ComboboxItem[]; /** * The selected value(s) resolved back to `{ value, label }` records — what * `Combobox.Value`, `Combobox.Chips` and `Combobox.Clear` all render from. * * A value with no matching item still gets a record, labeled by stringifying it, * so a selection made before `items` caught up is never dropped. Single * selection resolves to zero or one record. */ export declare function resolveComboboxSelection(items: ComboboxItem[], value: unknown, multiple: boolean, comparer?: ItemEqualityComparer): ComboboxItem[]; export type State = { /** * The uncontrolled open state. Read through the `open` selector, which * resolves the controlled prop first. */ open: boolean; /** * The controlled `open` prop, when provided. */ openProp: boolean | undefined; /** * The uncontrolled selected value. Read through the `value` selector. */ value: unknown; /** * The controlled `value` prop, when provided. */ valueProp: unknown; /** * The uncontrolled input text. Read through the `inputValue` selector. */ inputValue: string; /** * The controlled `inputValue` prop, when provided. */ inputValueProp: string | undefined; /** * Every item, normalized. */ items: ComboboxItem[]; /** * `'combobox'` selects a value and shows its label; `'autocomplete'` is free * text with suggestions, where the typed string is the value. */ mode: 'combobox' | 'autocomplete'; /** * Whether more than one item can be selected, which makes `value` an array. * Only meaningful in `'combobox'` mode — an autocomplete has no selection. */ multiple: boolean; /** * How an item's value is matched against the selection. Defaults to * `Object.is`, so object values need one of their own. */ isItemEqualToValue: ItemEqualityComparer; disabled: boolean; disablePointerDismissal: boolean; /** * Whether focusing the input opens the list. */ openOnFocus: boolean; /** * Whether the next focus of the input should be ignored by `openOnFocus`. * * Choosing an item closes the list, and the input's `blur()` cannot take * effect while the Modal still holds focus. When the Modal goes away, focus * returns to the input and `openOnFocus` would reopen the list the user just * dismissed. This is armed by that close and spent by the focus it causes. */ suppressFocusOpen: boolean; /** * `Combobox.Trigger`'s native node, carried across the portal boundary. */ triggerNode: unknown; /** * The trigger's measured width, used to size the popup. */ triggerWidth: number | undefined; /** * The trigger's measured height. */ triggerHeight: number | undefined; /** * `Combobox.Input`'s native node, and its measurements. * * The input is the anchor of a plain combobox, but it is *inside the popup* * in the trigger shape — so it cannot share `triggerNode`. It mounts later * than the trigger does, and it would win: the popup would be positioned * against an element it contains, and would walk across the screen each time * it opened. The positioner prefers the trigger and falls back to these. */ inputNode: unknown; inputWidth: number | undefined; inputHeight: number | undefined; update: (() => void) | undefined; /** * Ref to the input element, for programmatic blur. */ inputRef: React.RefObject | undefined; /** * The payload of the trigger the popup was opened by, handed to the root's * children when they are a function. */ payload: unknown; /** * The id of the trigger the popup is associated with, or `null` for none. */ triggerId: string | null; /** * The controlled `triggerId` prop, when provided. */ triggerIdProp: string | null | undefined; }; type Context = { onOpenChange: ((open: boolean, eventDetails: ComboboxRoot.ChangeEventDetails) => void) | undefined; /** * Called once an enter or exit animation has settled, reported by the consumer * through `settled(open)`. zest does not animate anything, so it cannot know * when an animation ends — the consumer drives it and owns the signal. */ onOpenChangeComplete: ((open: boolean, eventDetails: ComboboxRoot.ChangeEventDetails) => void) | undefined; onValueChange: ((value: any, eventDetails: ComboboxRoot.ChangeEventDetails) => void) | undefined; onInputValueChange: ((value: string, eventDetails: ComboboxRoot.ChangeEventDetails) => void) | undefined; /** * Every trigger bound to this root, by id. A handle resolves `open(id)` * through this, which is what lets an input rendered outside the root open it. */ triggerNodes: PopupTriggerMap; }; declare const selectors: { open: (state: State) => boolean; value: (state: State) => unknown; inputValue: (state: State) => string; items: (state: State) => ComboboxItem[]; mode: (state: State) => "combobox" | "autocomplete"; multiple: (state: State) => boolean; isItemEqualToValue: (state: State) => ItemEqualityComparer; /** * Whether one item's value is selected. * * Items subscribe to this boolean rather than to the whole selection, so * choosing one row in a long list re-renders only the rows whose answer * actually changed — not every row. `useSyncExternalStore` bails out on an * unchanged value, which is what makes that work. */ isSelected: (args_0: State, itemValue: unknown) => boolean; disabled: (state: State) => boolean; disablePointerDismissal: (state: State) => boolean; openOnFocus: (state: State) => boolean; suppressFocusOpen: (state: State) => boolean; triggerNode: (state: State) => unknown; triggerWidth: (state: State) => number | undefined; triggerHeight: (state: State) => number | undefined; inputNode: (state: State) => unknown; inputWidth: (state: State) => number | undefined; inputHeight: (state: State) => number | undefined; update: (state: State) => (() => void) | undefined; inputRef: (state: State) => import("react").RefObject | undefined; payload: (state: State) => unknown; triggerId: (state: State) => string | null; }; /** * The store behind `Combobox.Root` and `Autocomplete.Root`. * * It follows the same controlled-prop and cancelable-event contract as the other * popup families: every change fires its callback first and only commits the * uncontrolled key when the consumer has not called `eventDetails.cancel()`. */ export declare class ComboboxStore extends ReactStore, Context, typeof selectors> { constructor(initialState?: Partial); setOpen: (nextOpen: boolean, eventDetails: ComboboxRoot.ChangeEventDetails) => void; /** * Reports that the enter or exit animation for `open` has settled. zest never * animates, so only the consumer knows when their animation finished; calling * this fires `onOpenChangeComplete` with the reason of the last committed * change. Fire-once per settle: a repeated call with the same value is ignored. */ settled: (open: boolean) => void; /** * The event details of the last committed open/close, for `onOpenChangeComplete`. */ private lastChangeEventDetails; /** * The last value `settled` fired for, so the same settle is not reported twice. */ private lastSettledOpen; setValue: (nextValue: unknown, eventDetails: ComboboxRoot.ChangeEventDetails) => void; setInputValue: (nextValue: string, eventDetails: ComboboxRoot.ChangeEventDetails) => void; /** * Reflects a value the consumer changed from outside into the input text. * * This is not a change the consumer made through the combobox, so it fires no * callback — it writes the uncontrolled key directly. */ reflectInputValue: (nextValue: string) => void; /** * Selects an item: records the value, fills the input with its label, and * closes the popup. * * One `eventDetails` object is shared by all three, so canceling in any * handler stops the rest — the same contract the group components use. * * A `multiple` combobox toggles the value instead, and neither fills the input * nor closes: picking one of many is rarely the end of the interaction. The * exception is a list the user has filtered — there, upstream treats the * selection as the end of that query and closes, which drops the query * through `setOpen`. */ selectItem: (item: ComboboxItem, eventDetails: ComboboxRoot.ChangeEventDetails) => void; /** * Whether this focus is the one caused by a selection closing the list, and * spends the flag if so. Anything else opens normally. */ consumeSuppressedFocus: () => boolean; /** * Clears the selection and the input text, as `Combobox.Clear` does. * * The two share one `eventDetails`, so canceling in `onValueChange` also * leaves the input alone. */ clear: (eventDetails: ComboboxRoot.ChangeEventDetails) => void; } export {}; //# sourceMappingURL=ComboboxStore.d.ts.map