UNPKG

@base-ui/react

Version:

Base UI is a library of headless ('unstyled') React components and low-level hooks. You gain complete control over your app's CSS and accessibility features.

424 lines 18.3 kB
import * as React from 'react'; import { ReactStore } from '@base-ui/utils/store'; import type { InteractionType } from '@base-ui/utils/useEnhancedClickHandler'; import { MenuParent, MenuRoot } from "../root/MenuRoot.js"; import { FloatingTreeStore } from "../../floating-ui-react/components/FloatingTreeStore.js"; import { HTMLProps } from "../../internals/types.js"; import type { AdaptiveOriginMiddleware } from "../../utils/adaptiveOriginConstants.js"; import { PopupStoreContext, PopupStoreState, type PopupTriggerStoreKeys } from "../../utils/popups/index.js"; export type State<Payload> = PopupStoreState<Payload> & { disabled: boolean; modal: boolean; openMethod: InteractionType | null; allowMouseEnter: boolean; highlightItemOnHover: boolean; parent: MenuParent; rootId: string | undefined; activeIndex: number | null; hoverEnabled: boolean; instantType: 'dismiss' | 'click' | 'group' | 'trigger-change' | undefined; openChangeReason: MenuRoot.ChangeEventReason | null; floatingTreeRoot: FloatingTreeStore; floatingNodeId: string | undefined; floatingParentNodeId: string | null; itemProps: HTMLProps; closeDelay: number; keyboardEventRelay: ((event: React.KeyboardEvent<any>) => void) | undefined; adaptiveOrigin: AdaptiveOriginMiddleware | undefined; }; type Context = PopupStoreContext<MenuRoot.ChangeEventDetails> & { readonly positionerRef: React.RefObject<HTMLElement | null>; readonly popupRef: React.RefObject<HTMLElement | null>; readonly typingRef: React.RefObject<boolean>; readonly itemDomElements: React.RefObject<(HTMLElement | null)[]>; readonly itemLabels: React.RefObject<(string | null)[]>; allowMouseUpTriggerRef: React.RefObject<boolean>; readonly triggerFocusTargetRef: React.RefObject<HTMLElement | null>; readonly beforeContentFocusGuardRef: React.RefObject<HTMLElement | null>; }; declare const selectors: { open: (state: { open: boolean; readonly openProp: boolean | undefined; mounted: boolean; transitionStatus: import("../../internals/useTransitionStatus.js").TransitionStatus; floatingRootContext: import("../../floating-ui-react/index.js").FloatingRootContext; floatingId: string | undefined; triggerCount: number; preventUnmountingOnClose: boolean; payload: unknown; activeTriggerId: string | null; activeTriggerElement: Element | null; readonly triggerIdProp: string | null | undefined; popupElement: HTMLElement | null; positionerElement: HTMLElement | null; activeTriggerProps: HTMLProps; inactiveTriggerProps: HTMLProps; popupProps: HTMLProps; }) => boolean; mounted: (state: { open: boolean; readonly openProp: boolean | undefined; mounted: boolean; transitionStatus: import("../../internals/useTransitionStatus.js").TransitionStatus; floatingRootContext: import("../../floating-ui-react/index.js").FloatingRootContext; floatingId: string | undefined; triggerCount: number; preventUnmountingOnClose: boolean; payload: unknown; activeTriggerId: string | null; activeTriggerElement: Element | null; readonly triggerIdProp: string | null | undefined; popupElement: HTMLElement | null; positionerElement: HTMLElement | null; activeTriggerProps: HTMLProps; inactiveTriggerProps: HTMLProps; popupProps: HTMLProps; }) => boolean; transitionStatus: (state: { open: boolean; readonly openProp: boolean | undefined; mounted: boolean; transitionStatus: import("../../internals/useTransitionStatus.js").TransitionStatus; floatingRootContext: import("../../floating-ui-react/index.js").FloatingRootContext; floatingId: string | undefined; triggerCount: number; preventUnmountingOnClose: boolean; payload: unknown; activeTriggerId: string | null; activeTriggerElement: Element | null; readonly triggerIdProp: string | null | undefined; popupElement: HTMLElement | null; positionerElement: HTMLElement | null; activeTriggerProps: HTMLProps; inactiveTriggerProps: HTMLProps; popupProps: HTMLProps; }) => import("../../internals/useTransitionStatus.js").TransitionStatus; floatingRootContext: (state: { open: boolean; readonly openProp: boolean | undefined; mounted: boolean; transitionStatus: import("../../internals/useTransitionStatus.js").TransitionStatus; floatingRootContext: import("../../floating-ui-react/index.js").FloatingRootContext; floatingId: string | undefined; triggerCount: number; preventUnmountingOnClose: boolean; payload: unknown; activeTriggerId: string | null; activeTriggerElement: Element | null; readonly triggerIdProp: string | null | undefined; popupElement: HTMLElement | null; positionerElement: HTMLElement | null; activeTriggerProps: HTMLProps; inactiveTriggerProps: HTMLProps; popupProps: HTMLProps; }) => import("../../floating-ui-react/components/FloatingRootStore.js").FloatingRootStore; triggerCount: (state: { open: boolean; readonly openProp: boolean | undefined; mounted: boolean; transitionStatus: import("../../internals/useTransitionStatus.js").TransitionStatus; floatingRootContext: import("../../floating-ui-react/index.js").FloatingRootContext; floatingId: string | undefined; triggerCount: number; preventUnmountingOnClose: boolean; payload: unknown; activeTriggerId: string | null; activeTriggerElement: Element | null; readonly triggerIdProp: string | null | undefined; popupElement: HTMLElement | null; positionerElement: HTMLElement | null; activeTriggerProps: HTMLProps; inactiveTriggerProps: HTMLProps; popupProps: HTMLProps; }) => number; preventUnmountingOnClose: (state: { open: boolean; readonly openProp: boolean | undefined; mounted: boolean; transitionStatus: import("../../internals/useTransitionStatus.js").TransitionStatus; floatingRootContext: import("../../floating-ui-react/index.js").FloatingRootContext; floatingId: string | undefined; triggerCount: number; preventUnmountingOnClose: boolean; payload: unknown; activeTriggerId: string | null; activeTriggerElement: Element | null; readonly triggerIdProp: string | null | undefined; popupElement: HTMLElement | null; positionerElement: HTMLElement | null; activeTriggerProps: HTMLProps; inactiveTriggerProps: HTMLProps; popupProps: HTMLProps; }) => boolean; payload: (state: { open: boolean; readonly openProp: boolean | undefined; mounted: boolean; transitionStatus: import("../../internals/useTransitionStatus.js").TransitionStatus; floatingRootContext: import("../../floating-ui-react/index.js").FloatingRootContext; floatingId: string | undefined; triggerCount: number; preventUnmountingOnClose: boolean; payload: unknown; activeTriggerId: string | null; activeTriggerElement: Element | null; readonly triggerIdProp: string | null | undefined; popupElement: HTMLElement | null; positionerElement: HTMLElement | null; activeTriggerProps: HTMLProps; inactiveTriggerProps: HTMLProps; popupProps: HTMLProps; }) => unknown; activeTriggerId: (state: { open: boolean; readonly openProp: boolean | undefined; mounted: boolean; transitionStatus: import("../../internals/useTransitionStatus.js").TransitionStatus; floatingRootContext: import("../../floating-ui-react/index.js").FloatingRootContext; floatingId: string | undefined; triggerCount: number; preventUnmountingOnClose: boolean; payload: unknown; activeTriggerId: string | null; activeTriggerElement: Element | null; readonly triggerIdProp: string | null | undefined; popupElement: HTMLElement | null; positionerElement: HTMLElement | null; activeTriggerProps: HTMLProps; inactiveTriggerProps: HTMLProps; popupProps: HTMLProps; }) => string | null; activeTriggerElement: (state: { open: boolean; readonly openProp: boolean | undefined; mounted: boolean; transitionStatus: import("../../internals/useTransitionStatus.js").TransitionStatus; floatingRootContext: import("../../floating-ui-react/index.js").FloatingRootContext; floatingId: string | undefined; triggerCount: number; preventUnmountingOnClose: boolean; payload: unknown; activeTriggerId: string | null; activeTriggerElement: Element | null; readonly triggerIdProp: string | null | undefined; popupElement: HTMLElement | null; positionerElement: HTMLElement | null; activeTriggerProps: HTMLProps; inactiveTriggerProps: HTMLProps; popupProps: HTMLProps; }) => Element | null; popupId: (state: { open: boolean; readonly openProp: boolean | undefined; mounted: boolean; transitionStatus: import("../../internals/useTransitionStatus.js").TransitionStatus; floatingRootContext: import("../../floating-ui-react/index.js").FloatingRootContext; floatingId: string | undefined; triggerCount: number; preventUnmountingOnClose: boolean; payload: unknown; activeTriggerId: string | null; activeTriggerElement: Element | null; readonly triggerIdProp: string | null | undefined; popupElement: HTMLElement | null; positionerElement: HTMLElement | null; activeTriggerProps: HTMLProps; inactiveTriggerProps: HTMLProps; popupProps: HTMLProps; }) => string | undefined; isTriggerActive: (state: { open: boolean; readonly openProp: boolean | undefined; mounted: boolean; transitionStatus: import("../../internals/useTransitionStatus.js").TransitionStatus; floatingRootContext: import("../../floating-ui-react/index.js").FloatingRootContext; floatingId: string | undefined; triggerCount: number; preventUnmountingOnClose: boolean; payload: unknown; activeTriggerId: string | null; activeTriggerElement: Element | null; readonly triggerIdProp: string | null | undefined; popupElement: HTMLElement | null; positionerElement: HTMLElement | null; activeTriggerProps: HTMLProps; inactiveTriggerProps: HTMLProps; popupProps: HTMLProps; }, triggerId: string | undefined) => boolean; isOpenedByTrigger: (state: { open: boolean; readonly openProp: boolean | undefined; mounted: boolean; transitionStatus: import("../../internals/useTransitionStatus.js").TransitionStatus; floatingRootContext: import("../../floating-ui-react/index.js").FloatingRootContext; floatingId: string | undefined; triggerCount: number; preventUnmountingOnClose: boolean; payload: unknown; activeTriggerId: string | null; activeTriggerElement: Element | null; readonly triggerIdProp: string | null | undefined; popupElement: HTMLElement | null; positionerElement: HTMLElement | null; activeTriggerProps: HTMLProps; inactiveTriggerProps: HTMLProps; popupProps: HTMLProps; }, triggerId: string | undefined) => boolean; isMountedByTrigger: (state: { open: boolean; readonly openProp: boolean | undefined; mounted: boolean; transitionStatus: import("../../internals/useTransitionStatus.js").TransitionStatus; floatingRootContext: import("../../floating-ui-react/index.js").FloatingRootContext; floatingId: string | undefined; triggerCount: number; preventUnmountingOnClose: boolean; payload: unknown; activeTriggerId: string | null; activeTriggerElement: Element | null; readonly triggerIdProp: string | null | undefined; popupElement: HTMLElement | null; positionerElement: HTMLElement | null; activeTriggerProps: HTMLProps; inactiveTriggerProps: HTMLProps; popupProps: HTMLProps; }, triggerId: string | undefined) => boolean; triggerProps: (state: { open: boolean; readonly openProp: boolean | undefined; mounted: boolean; transitionStatus: import("../../internals/useTransitionStatus.js").TransitionStatus; floatingRootContext: import("../../floating-ui-react/index.js").FloatingRootContext; floatingId: string | undefined; triggerCount: number; preventUnmountingOnClose: boolean; payload: unknown; activeTriggerId: string | null; activeTriggerElement: Element | null; readonly triggerIdProp: string | null | undefined; popupElement: HTMLElement | null; positionerElement: HTMLElement | null; activeTriggerProps: HTMLProps; inactiveTriggerProps: HTMLProps; popupProps: HTMLProps; }, isActive: boolean) => HTMLProps; triggerPopupId: (state: { open: boolean; readonly openProp: boolean | undefined; mounted: boolean; transitionStatus: import("../../internals/useTransitionStatus.js").TransitionStatus; floatingRootContext: import("../../floating-ui-react/index.js").FloatingRootContext; floatingId: string | undefined; triggerCount: number; preventUnmountingOnClose: boolean; payload: unknown; activeTriggerId: string | null; activeTriggerElement: Element | null; readonly triggerIdProp: string | null | undefined; popupElement: HTMLElement | null; positionerElement: HTMLElement | null; activeTriggerProps: HTMLProps; inactiveTriggerProps: HTMLProps; popupProps: HTMLProps; }, triggerId: string | undefined) => string | undefined; popupProps: (state: { open: boolean; readonly openProp: boolean | undefined; mounted: boolean; transitionStatus: import("../../internals/useTransitionStatus.js").TransitionStatus; floatingRootContext: import("../../floating-ui-react/index.js").FloatingRootContext; floatingId: string | undefined; triggerCount: number; preventUnmountingOnClose: boolean; payload: unknown; activeTriggerId: string | null; activeTriggerElement: Element | null; readonly triggerIdProp: string | null | undefined; popupElement: HTMLElement | null; positionerElement: HTMLElement | null; activeTriggerProps: HTMLProps; inactiveTriggerProps: HTMLProps; popupProps: HTMLProps; }) => HTMLProps; popupElement: (state: { open: boolean; readonly openProp: boolean | undefined; mounted: boolean; transitionStatus: import("../../internals/useTransitionStatus.js").TransitionStatus; floatingRootContext: import("../../floating-ui-react/index.js").FloatingRootContext; floatingId: string | undefined; triggerCount: number; preventUnmountingOnClose: boolean; payload: unknown; activeTriggerId: string | null; activeTriggerElement: Element | null; readonly triggerIdProp: string | null | undefined; popupElement: HTMLElement | null; positionerElement: HTMLElement | null; activeTriggerProps: HTMLProps; inactiveTriggerProps: HTMLProps; popupProps: HTMLProps; }) => HTMLElement | null; positionerElement: (state: { open: boolean; readonly openProp: boolean | undefined; mounted: boolean; transitionStatus: import("../../internals/useTransitionStatus.js").TransitionStatus; floatingRootContext: import("../../floating-ui-react/index.js").FloatingRootContext; floatingId: string | undefined; triggerCount: number; preventUnmountingOnClose: boolean; payload: unknown; activeTriggerId: string | null; activeTriggerElement: Element | null; readonly triggerIdProp: string | null | undefined; popupElement: HTMLElement | null; positionerElement: HTMLElement | null; activeTriggerProps: HTMLProps; inactiveTriggerProps: HTMLProps; popupProps: HTMLProps; }) => HTMLElement | null; disabled: (state: State<unknown>) => boolean; modal: (state: State<unknown>) => boolean; openMethod: (state: State<unknown>) => InteractionType | null; allowMouseEnter: (state: State<unknown>) => boolean; highlightItemOnHover: (state: State<unknown>) => boolean; parent: (state: State<unknown>) => MenuParent; rootId: (state: State<unknown>) => string | undefined; activeIndex: (state: State<unknown>) => number | null; isActive: (state: State<unknown>, itemIndex: number) => boolean; hoverEnabled: (state: State<unknown>) => boolean; instantType: (state: State<unknown>) => "click" | "dismiss" | "group" | "trigger-change" | undefined; lastOpenChangeReason: (state: State<unknown>) => import("../index.js").MenuRootChangeEventReason | null; floatingTreeRoot: (state: State<unknown>) => FloatingTreeStore; floatingNodeId: (state: State<unknown>) => string | undefined; floatingParentNodeId: (state: State<unknown>) => string | null; itemProps: (state: State<unknown>) => HTMLProps; closeDelay: (state: State<unknown>) => number; adaptiveOrigin: (state: State<unknown>) => AdaptiveOriginMiddleware | undefined; keyboardEventRelay: (state: State<unknown>) => React.KeyboardEventHandler<any> | undefined; }; type Selectors = typeof selectors; /** * The store view that detached handle-backed triggers read from. Both the real `MenuStore` and the * inert fallback store satisfy it, so a trigger can read from whichever store the handle currently * exposes. Narrowed to the members a trigger actually uses the trigger-data members plus `setOpen` * (called by the focus guards) so the exposed surface can't bypass the open-change pipeline; on * the detached fallback store every one of these mutations is a no-op. */ export type MenuHandleStore<Payload> = Pick<MenuStore<Payload>, PopupTriggerStoreKeys | 'setOpen'>; export declare class MenuStore<Payload> extends ReactStore<Readonly<State<Payload>>, Context, Selectors> { constructor(initialState?: Partial<State<Payload>>); setOpen(open: boolean, eventDetails: Omit<MenuRoot.ChangeEventDetails, 'preventUnmountOnClose'>): void; private unsubscribeParentListener; } /** * Creates the inert fallback store used by detached handle-backed triggers while no `Menu.Root` is * attached. It preserves a menu-specific trigger registry in context so detached triggers can * register before migrating to the live root store. `setOpen` is a no-op (matching the inert * reads/writes of `NullStore`), so a trigger can hand the store to focus-guard helpers that expect * `setOpen` without it ever taking effect while detached. */ export declare function createNullMenuStore<Payload>(): MenuHandleStore<Payload>; export {};