import React, { forwardRef } from 'react'; import { ContextMenu as BaseContextMenu } from '@base-ui/react/context-menu'; import cs from 'classnames'; import classes from './ContextMenu.module.scss'; type TriggerBaseProps = Omit< React.ComponentPropsWithoutRef, 'children' | 'render' >; type TriggerProps = TriggerBaseProps & { asChild?: boolean; children: React.ReactNode; }; type TriggerComponent = React.ForwardRefExoticComponent< TriggerProps & React.RefAttributes >; const Trigger: TriggerComponent = forwardRef((props, ref) => { const { asChild = false, children, ...rest } = props; if (asChild && !React.isValidElement(children)) { if (process.env.NODE_ENV !== 'production') { throw new Error('ContextMenu.Trigger with asChild expects a single valid React element.'); } return null; } const render = asChild ? (children as React.ReactElement) : undefined; return ( {asChild ? undefined : children} ); }); Trigger.displayName = 'ContextMenu.Trigger'; type PositionerProps = React.ComponentPropsWithoutRef; type PositionerComponent = React.ForwardRefExoticComponent< PositionerProps & React.RefAttributes >; const Positioner: PositionerComponent = forwardRef((props, ref) => { const { className, ...rest } = props; return ( ); }); Positioner.displayName = 'ContextMenu.Positioner'; type PopupProps = React.ComponentPropsWithoutRef; type PopupComponent = React.ForwardRefExoticComponent< PopupProps & React.RefAttributes >; const Popup: PopupComponent = forwardRef((props, ref) => { const { className, ...rest } = props; return ( ); }); Popup.displayName = 'ContextMenu.Popup'; interface PortalProps extends React.ComponentPropsWithoutRef { children?: React.ReactNode; } const Portal = (props: PortalProps) => { const { children, ...rest } = props; return ( {children} ); }; Portal.displayName = 'ContextMenu.Portal'; interface ContextMenuItemProps extends React.ComponentPropsWithoutRef { destructive?: boolean; icon?: React.ReactNode; } type ItemComponent = React.ForwardRefExoticComponent< ContextMenuItemProps & React.RefAttributes >; const Item: ItemComponent = forwardRef((props, ref) => { const { destructive = false, icon, className, children, ...rest } = props; return ( {icon != null && {icon}} {children} ); }); Item.displayName = 'ContextMenu.Item'; type SeparatorProps = React.ComponentPropsWithoutRef; type SeparatorComponent = React.ForwardRefExoticComponent< SeparatorProps & React.RefAttributes >; const Separator: SeparatorComponent = forwardRef((props, ref) => { const { className, ...rest } = props; return ( ); }); Separator.displayName = 'ContextMenu.Separator'; interface GroupProps extends React.ComponentPropsWithoutRef { label?: string; } type GroupComponent = React.ForwardRefExoticComponent< GroupProps & React.RefAttributes >; const Group: GroupComponent = forwardRef((props, ref) => { const { label, className, children, ...rest } = props; return ( {label && ( {label} )} {children} ); }); Group.displayName = 'ContextMenu.Group'; interface ContextMenuComponent { Root: typeof BaseContextMenu.Root; Trigger: typeof Trigger; Portal: typeof Portal; Positioner: typeof Positioner; Popup: typeof Popup; Item: typeof Item; Separator: typeof Separator; Group: typeof Group; } export const ContextMenu: ContextMenuComponent = { Root: BaseContextMenu.Root, Trigger, Portal, Positioner, Popup, Item, Separator, Group, };