import { type ReactNode, type Ref } from 'react';
import { type MenuItemProps } from './Menu';
/**
* The list a text editor opens as you type — `/` for commands, `@` for people,
* `[` for a reference. UIG-31: Peek's four type-ahead menus, made one part.
*
* **Why it is not a `Combobox` or a `Menu`.** Base UI's lists need a text field
* of their own, and the text being completed is an editor, not an ``.
* So focus never leaves the text: the editor hands its arrow keys and Enter to
* this list through `handle`, and the list tells the editor which row is
* active (`aria-activedescendant`), the pattern Base UI's `Combobox` builds.
* If Base UI ever adds a list that can be driven from outside its own field,
* this part moves onto it.
*
* **What it owns**, all of it written once here instead of in every menu:
*
* - the box: the package `Popover`, anchored to the caret, above it and below
* when there is no room, clamped to the window, scrolling in the package's
* `ScrollArea` past `maxHeight`;
* - the highlighted row: ↑ and ↓ (wrapping at the ends), Enter to choose, the
* pointer moving the highlight, a press choosing without taking focus from
* the text, the highlight back on the first row whenever the list changes,
* and the highlighted row scrolled into view;
* - what a screen reader is told: the list is a `listbox`, each row an
* `option`, and the editor says it completes into this list and which row
* is active — all removed again when the list closes.
*
* What stays with the app: which rows exist, what choosing one does, and what
* each row shows (its label, face, keys, hint) — `row` returns the package
* `MenuItem`'s own props. With nothing to show there is no box at all.
*/
export interface SuggestionMenuRow {
label: string;
description?: string;
/** After the label, muted — `MenuItem`'s. */
aside?: string;
leading?: ReactNode;
/** What you would type — drawn as keys at the right, e.g. `#` for a heading. */
shortcut?: string;
/** Drawn at the right while the row is highlighted, e.g. ``. */
hint?: ReactNode;
/** `tall` for a row with a face and a second line — `MenuItem`'s own sizes. */
size?: MenuItemProps['size'];
}
export interface SuggestionMenuSection {
/** The section's heading. Without one, the rows stand alone. */
label?: string;
items: readonly T[];
/** On the heading row, as `MenuSection`'s. */
className?: string;
}
/** What the editor calls while the list is open. */
export interface SuggestionMenuHandle {
/** ↑, ↓ and Enter. `true` when the list used the key, so the editor must not. */
onKeyDown: (event: KeyboardEvent) => boolean;
}
export interface SuggestionMenuProps {
/** The caret's rect, from the editor. `null` closes the box. */
rect: DOMRect | null;
/** The editor's own element — told which row is active. Absent in a story. */
editorElement?: HTMLElement | null;
/** Names the list — "Commands", "People". */
ariaLabel: string;
/** The box's width, e.g. `w-[300px]`. */
width: string;
/** The cap before the rows scroll, e.g. `max-h-[400px]`. */
maxHeight: string;
sections: readonly SuggestionMenuSection[];
/** A stable key for a row. */
itemKey: (item: T) => string;
/** What a row shows. */
row: (item: T) => SuggestionMenuRow;
onSelect: (item: T) => void;
handle?: Ref;
}
export declare function SuggestionMenu({ rect, editorElement, ariaLabel, width, maxHeight, sections, itemKey, row, onSelect, handle }: SuggestionMenuProps): import("react").JSX.Element | null;
//# sourceMappingURL=SuggestionMenu.d.ts.map