/**
* Select — a picker with one trigger and three ways of showing its options.
*
* Which one is right depends on what surrounds the trigger, not on what the
* options are, which is why it is a prop rather than three components:
*
* - `sheet` (default) takes the bottom of the screen. Best for a long list, or
* on a small screen where an anchored panel would cover the thing you are
* choosing for.
* - `inline` expands the list in normal layout flow. Everything below moves
* down. Right inside a settings list, where that reads as the row growing;
* wrong anywhere the shift is jarring.
* - `overlay` floats the list above the page through a portal, anchored to the
* trigger and flipped above it when there is no room below. Nothing else on
* the screen moves.
*
* ```tsx
*
* ```
*
* Past a couple of dozen options, scrolling stops being a way of finding
* anything: pass `searchable` and the list gets a filter above it, matching on
* the option labels. The filter narrows what is *shown* — the declared options
* are still the source of truth, so nothing has to be lifted into state to make
* it work.
*
* A list long enough to need a filter is usually long enough to want dividing,
* so options can be wrapped in `Select.Group` under a heading. Grouping is
* presentational — the value is still a flat string — and the filter reaches
* through it, dropping any group the query empties rather than leaving a
* heading standing over nothing.
*/
import { type ReactNode } from 'react';
export type SelectPresentation = 'sheet' | 'inline' | 'overlay';
/**
* The filter field's text, from inside an open Select.
*
* Select can only filter the options it renders itself. A caller who hands it
* a virtualized list is rendering their own rows, from their own data, and
* this is how they get the query to filter that data with — `Select.Item`
* still works wherever those rows put it, because selection travels by
* context rather than by position.
*
* ```tsx
* function Options() {
* const { query } = useSelectSearch();
* const rows = useMemo(() => filter(timezones, query), [query]);
* return (
* }
* />
* );
* }
* ```
*
* `setQuery` is there for a caller who wants to clear or seed the field.
*/
export declare function useSelectSearch(): {
query: string;
setQuery: (query: string) => void;
};
export interface SelectItemProps {
value: string;
label: string;
/** Extra classes for the option row. */
className?: string;
/** Extra classes for the option's label. */
labelClassName?: string;
/**
* Shows the option but refuses it — a plan above the current tier, a region
* with nothing in stock. Kept in the list rather than dropped from it, because
* an option that vanishes reads as one that never existed.
*/
disabled?: boolean;
}
/** Declarative option. Rendered inside whichever surface is presenting. */
declare function SelectItem({ value, label, disabled, className, labelClassName }: SelectItemProps): import("react").JSX.Element;
declare namespace SelectItem {
var displayName: string;
}
export interface SelectGroupProps {
/**
* Heading over the run of options. Announced as a header, so a screen reader
* reaching the group is told what it is before walking into it.
*/
label?: string;
/** Extra classes for the group wrapper. */
className?: string;
/** Extra classes for the heading. */
labelClassName?: string;
children: ReactNode;
}
/**
* A titled run of options.
*
* Purely a way of arranging the list: a grouped Select still reports one flat
* string, and `Select.Item` needs to know nothing about being inside one.
*/
declare function SelectGroup({ label, className, labelClassName, children }: SelectGroupProps): import("react").JSX.Element;
declare namespace SelectGroup {
var displayName: string;
}
export interface SelectProps {
/**
* Extra classes for the wrapper around the trigger — the box the select
* occupies in your layout, which is where margins and widths belong. To
* restyle the field itself, use `triggerClassName`.
*/
className?: string;
/** The selected option's `value`. Leave unset for the placeholder. */
value?: string;
/**
* What the trigger shows for the current `value`.
*
* Select reads the label off its `Select.Item` children, which it cannot do
* when a list component renders those rows — the elements do not exist until
* the list decides to draw them, and the selected one may be scrolled far
* out of view. Pass the label yourself in that case; otherwise leave it
* unset and the trigger will find it.
*/
valueLabel?: string;
/** Called with the `value` of the option that was picked. */
onValueChange: (value: string) => void;
/** Shown on the trigger while nothing is selected. */
placeholder?: string;
/** Refuses the trigger and dims it. The options cannot be opened. */
disabled?: boolean;
/** Extra classes for the trigger — the field you press to open the list. */
triggerClassName?: string;
/** Extra classes for the selected option's text on the trigger. */
valueClassName?: string;
/** Extra classes for the placeholder text on the trigger. */
placeholderClassName?: string;
/**
* Extra classes for the surface the options sit on. In `sheet` the sheet is
* that surface, so this reaches the block of options inside it instead.
*/
listClassName?: string;
/** Extra classes for the row the filter field sits in. `searchable` only. */
searchClassName?: string;
/** Extra classes for the filter field itself. `searchable` only. */
searchInputClassName?: string;
/**
* Extra classes for the box drawn around the filter field — its fill, border
* and radius. `searchable` only.
*/
searchContainerClassName?: string;
/** Extra classes for the message shown when the filter matches nothing. */
emptyClassName?: string;
/**
* Where the options appear. `sheet` takes the bottom of the screen, `inline`
* expands the list in layout flow, `overlay` floats it above the page
* anchored to the trigger.
*/
presentation?: SelectPresentation;
/** Sheet title shown above the options. `sheet` presentation only. */
title?: string;
/**
* Width of the floating list. `trigger` matches the trigger, `content` sizes
* to the longest option, or pass a pixel value. `overlay` only.
*/
contentWidth?: 'trigger' | 'content' | number;
/** Gap between the trigger and the floating list. `overlay` only. */
offset?: number;
/** Called when the options open or close. */
onOpenChange?: (open: boolean) => void;
/**
* Put a filter above the options, matching case-insensitively on any part of
* an option's label. For a list long enough that scrolling it is not finding
* anything — countries, currencies, a repository's branches.
*
* The field is not focused on open: on a phone that would throw the keyboard
* over the very list you are trying to look at.
*/
searchable?: boolean;
/** Placeholder for the filter field. `searchable` only. */
searchPlaceholder?: string;
/** Shown in place of the list when the filter matches nothing. */
emptyMessage?: string;
/**
* Render the platform's own picker instead of the trigger-and-list pair.
* Requires the optional `@expo/ui` package; without it this prop does
* nothing.
*
* **Theme tokens do not apply** — the platform draws the picker, so
* `className`, `title` and `presentation` are ignored. `Select.Item`
* children still declare the options.
*/
native?: boolean;
/**
* Native picker style. `menu` is a compact button opening a dropdown;
* `wheel` is an always-visible rotor (iOS; falls back to `menu` elsewhere).
*/
nativeAppearance?: 'menu' | 'wheel';
children: ReactNode;
}
declare function SelectRoot({ className, value, valueLabel, onValueChange, placeholder, disabled, triggerClassName, valueClassName, placeholderClassName, listClassName, searchClassName, searchInputClassName, searchContainerClassName, emptyClassName, presentation, title, contentWidth, offset, onOpenChange, searchable, searchPlaceholder, emptyMessage, native, nativeAppearance, children, }: SelectProps): import("react").JSX.Element;
export declare const Select: typeof SelectRoot & {
Item: typeof SelectItem;
Group: typeof SelectGroup;
};
export {};
//# sourceMappingURL=index.d.ts.map