'use client'; import * as React from 'react'; import { MenuRoot } from '../../menu/root/MenuRoot'; import { ContextMenuRootContext, type ContextMenuAnchorPoint } from './ContextMenuRootContext'; /** * Groups the parts of a context menu — a menu opened by long-pressing an area * rather than tapping a button. * Doesn't render its own element. * * A context menu is a `Menu.Root` anchored to the point where the long press * landed instead of to a trigger element. It reuses every menu part except the * trigger and positioner, which are its own. * * **Adapted from upstream.** The web version opens on right-click *or* long * press and tracks a virtual cursor; a touch screen only has the long press. */ export function ContextMenuRoot(props: ContextMenuRoot.Props) { const [anchor, setAnchor] = React.useState({ x: 0, y: 0 }); const contextValue: ContextMenuRootContext = React.useMemo( () => ({ anchor, setAnchor }), [anchor], ); return ( ); } export interface ContextMenuRootState {} export interface ContextMenuRootProps extends Omit< MenuRoot.Props, 'handle' | 'triggerId' | 'defaultTriggerId' | 'children' > { children?: React.ReactNode; } export namespace ContextMenuRoot { export type State = ContextMenuRootState; export type Props = ContextMenuRootProps; /** * A context menu is a menu, so it reuses the menu's action and event * contracts — a consumer should not have to reach for `Menu.Root`'s types to * type a `ContextMenu.Root` handler. */ export type Actions = MenuRoot.Actions; export type ChangeEventReason = MenuRoot.ChangeEventReason; export type ChangeEventDetails = MenuRoot.ChangeEventDetails; }