/**
* Menu — the list of things you can do to something.
*
* It is not a Select, and the difference is what the rows *are*. A select's
* rows are values: picking one answers a question the form asked, and the
* trigger then shows the answer. A menu's rows are verbs — rename, duplicate,
* delete — and the trigger goes on saying the same thing afterwards, because
* nothing about it was chosen. Anything built out of a popover and a column of
* pressables ends up re-deriving that distinction by hand, and re-deriving the
* roles, the dismiss-on-select rule and the destructive colour with it.
*
* ```tsx
*
* ```
*
* The panel is a `Popover` underneath, so the menu inherits its measuring,
* flipping and edge-clamping rather than owning a second copy of them — a menu
* near the bottom of the screen opens upwards for the same reason a popover
* does, and `presentation="bottom-sheet"` moves the same rows into a sheet.
*
* Submenus expand in place rather than flying out sideways. A flyout needs a
* pointer to travel from the parent row to the child panel without crossing
* anything that would close it; a finger has no such path, and a second panel
* hanging off the first is usually the thing that pushes a menu off the edge
* of a phone. Opening downwards into the panel keeps every row under the
* thumb that opened it.
*/
import { type ReactElement, type ReactNode } from 'react';
import { type PressableProps, type ViewProps } from 'react-native';
import { type PopoverContentProps, type PopoverProps } from '../popover/index.js';
export type MenuItemVariant = 'default' | 'destructive';
export interface MenuProps extends PopoverProps {
/**
* Tick the haptic engine as a row is chosen. Needs the optional
* `expo-haptics`, and is silent without it.
*/
haptics?: boolean;
}
declare function MenuRoot({ children, open, onOpenChange, defaultOpen, haptics, ...props }: MenuProps): import("react").JSX.Element;
export interface MenuTriggerProps {
children: ReactElement<{
onPress?: (...args: unknown[]) => void;
}>;
}
/** Wraps a single child and opens the menu on press. Also what gets measured. */
declare function MenuTrigger({ children }: MenuTriggerProps): import("react").JSX.Element;
declare namespace MenuTrigger {
var displayName: string;
}
export interface MenuContentProps extends Omit {
children?: ReactNode;
/**
* Scroll the rows when there are more of them than fit on screen. On by
* default, unlike the popover it is built on: a menu is a list, its length
* is usually a `map` over data rather than something written out by hand,
* and a row that cannot be reached is a row that may as well not exist.
*/
scrollable?: boolean;
}
/**
* The panel, and the thing screen readers announce as a menu.
*
* Its padding is the row gutter rather than the popover's content padding —
* rows run to the panel's inner edge so that a pressed row's highlight reads
* as part of the panel instead of a floating chip inside it.
*
* The surface is a layer rather than a background on the panel itself, so that
* a caller can put something *behind* the rows. Pass a `Menu.Background` of
* your own with a gradient, an image or a blur inside it and it replaces the
* default one; pass nothing and the default is drawn for you.
*/
declare function MenuContent({ className, children, scrollable, ...props }: MenuContentProps): import("react").JSX.Element;
declare namespace MenuContent {
var displayName: string;
}
export interface MenuBackgroundProps extends ViewProps {
className?: string;
/**
* What the panel is made of. A gradient, an image, a blur view — anything
* that fills. Left empty it is the plain overlay surface.
*/
children?: ReactNode;
}
/**
* The panel's surface, drawn behind every row.
*
* It exists as a part rather than as a background on the panel because a
* background cannot be got behind. A menu that wants to be frosted, tinted or
* gradient-filled needs something under the rows and over nothing, and
* `overflow-hidden` on the panel is what keeps whatever that is inside the
* corner radius.
*/
export declare function MenuBackground({ className, children, ...props }: MenuBackgroundProps): import("react").JSX.Element;
export declare namespace MenuBackground {
var displayName: string;
}
export interface MenuLabelProps extends ViewProps {
className?: string;
/** Line the text up with rows that carry an icon or an indicator. */
inset?: boolean;
children?: ReactNode;
}
/** Non-interactive heading over a run of rows. */
export declare function MenuLabel({ className, inset, children, ...props }: MenuLabelProps): import("react").JSX.Element;
export declare namespace MenuLabel {
var displayName: string;
}
export interface MenuSeparatorProps extends ViewProps {
className?: string;
}
/** Hairline between two runs of rows. */
export declare function MenuSeparator({ className, ...props }: MenuSeparatorProps): import("react").JSX.Element;
export declare namespace MenuSeparator {
var displayName: string;
}
export interface MenuItemProps extends Omit {
className?: string;
/** The row's label. */
children?: ReactNode;
/** Leading glyph, drawn in the indicator column. */
icon?: ReactNode;
/** Second line under the label, for a row whose effect needs a sentence. */
description?: string;
/** Right-aligned hint, for a row that also has a keyboard or gesture shortcut. */
shortcut?: string;
/**
* Element pinned to the row's trailing edge, after the shortcut. For the
* things a shortcut string cannot be — a chevron, a badge, a small avatar.
*/
trailing?: ReactNode;
/** `destructive` colours the row for an action that removes something. */
variant?: MenuItemVariant;
/** Line the label up with rows that carry an icon, without drawing one. */
inset?: boolean;
disabled?: boolean;
/**
* Dismiss the menu once the row has run. Default true — a menu of verbs has
* done its job the moment one is chosen. Turn it off for a row that toggles
* something the user is likely to toggle twice.
*/
closeOnSelect?: boolean;
onSelect?: () => void;
}
/**
* One row of the menu.
*
* `onSelect` rather than `onPress` is the handler that closes the panel:
* `onPress` is still forwarded and still fires, so a row can keep whatever
* press behaviour it had, but the dismissal is tied to the semantic event so
* that a row which is disabled or which opts out via `closeOnSelect` behaves
* the same either way.
*/
export declare function MenuItem({ className, children, icon, description, shortcut, trailing, variant, inset, disabled, closeOnSelect, onSelect, onPress, onPressIn, onPressOut, ...props }: MenuItemProps): import("react").JSX.Element;
export declare namespace MenuItem {
var displayName: string;
}
export interface MenuCheckboxItemProps extends Omit {
checked?: boolean;
onCheckedChange?: (checked: boolean) => void;
}
/**
* A row that carries a state instead of running an action.
*
* It keeps the menu open by default, which is the opposite of `Menu.Item` and
* deliberately so: a set of toggles is nearly always set more than one at a
* time, and closing after each one turns three taps into six.
*/
export declare function MenuCheckboxItem({ checked, onCheckedChange, onSelect, closeOnSelect, ...props }: MenuCheckboxItemProps): import("react").JSX.Element;
export declare namespace MenuCheckboxItem {
var displayName: string;
}
export interface MenuRadioGroupProps extends ViewProps {
className?: string;
value?: string;
onValueChange?: (value: string) => void;
children?: ReactNode;
}
/** A run of rows of which exactly one is chosen. */
export declare function MenuRadioGroup({ value, onValueChange, className, children, ...props }: MenuRadioGroupProps): import("react").JSX.Element;
export declare namespace MenuRadioGroup {
var displayName: string;
}
export type MenuRadioIndicator = 'check' | 'dot';
export interface MenuRadioItemProps extends Omit {
value: string;
/** `check` marks the chosen row, `dot` is quieter beside a list of nouns. */
indicator?: MenuRadioIndicator;
}
/** One option inside a `Menu.RadioGroup`. */
export declare function MenuRadioItem({ value, indicator, onSelect, closeOnSelect, ...props }: MenuRadioItemProps): import("react").JSX.Element;
export declare namespace MenuRadioItem {
var displayName: string;
}
export interface MenuSubProps {
children?: ReactNode;
defaultOpen?: boolean;
open?: boolean;
onOpenChange?: (open: boolean) => void;
}
/** Groups a `Menu.SubTrigger` with the rows it reveals. */
export declare function MenuSub({ children, defaultOpen, open, onOpenChange }: MenuSubProps): import("react").JSX.Element;
export declare namespace MenuSub {
var displayName: string;
}
export interface MenuSubTriggerProps extends Omit {
}
/**
* The row that opens a submenu.
*
* Its chevron points along the reading direction while closed and turns to
* point down once open, so the row states which way its rows will appear
* rather than only that it has some.
*/
export declare function MenuSubTrigger({ className, children, icon, onSelect, ...props }: MenuSubTriggerProps): import("react").JSX.Element;
export declare namespace MenuSubTrigger {
var displayName: string;
}
export interface MenuSubContentProps extends ViewProps {
className?: string;
children?: ReactNode;
}
/**
* The rows a submenu reveals, opening in place.
*
* The height is animated from a measurement rather than left to a layout
* animation, and the measured copy is absolutely positioned so it always lays
* out at its natural size — a child of a view whose height is mid-animation
* would otherwise report the animated height back, and the panel would settle
* at whatever it happened to measure on the first frame.
*/
export declare function MenuSubContent({ className, children, ...props }: MenuSubContentProps): import("react").JSX.Element;
export declare namespace MenuSubContent {
var displayName: string;
}
export declare const Menu: typeof MenuRoot & {
Trigger: typeof MenuTrigger;
Content: typeof MenuContent;
Background: typeof MenuBackground;
Label: typeof MenuLabel;
Item: typeof MenuItem;
CheckboxItem: typeof MenuCheckboxItem;
RadioGroup: typeof MenuRadioGroup;
RadioItem: typeof MenuRadioItem;
Separator: typeof MenuSeparator;
Sub: typeof MenuSub;
SubTrigger: typeof MenuSubTrigger;
SubContent: typeof MenuSubContent;
};
export {};
//# sourceMappingURL=index.d.ts.map