/** * 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 * * * * * * }>Rename * * }> * Delete * * * * ``` * * 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