'use client' import * as React from 'react' import { Menu as BaseMenu } from '@base-ui/react/menu' import { useReducedMotion } from '../../hooks/use-reduced-motion' import { cn } from '../../internal/utils' import { type FloatingContentProps, splitFloatingProps } from '../../internal/floating' import { navigationLinkVariants } from '../navigation/navigation-link-variants' type DropdownMenuSize = 'sm' | 'md' | 'lg' interface DropdownMenuContextValue { size: DropdownMenuSize reducedMotion: boolean } const DropdownMenuContext = React.createContext(null) function useDropdownMenuContext() { const ctx = React.useContext(DropdownMenuContext) if (!ctx) { throw new Error('DropdownMenu sub-components must be rendered inside ') } return ctx } type BaseRootProps = React.ComponentProps interface DropdownMenuProps extends BaseRootProps { /** * Scales the popup radius, item padding, and icon size. * @default 'md' */ size?: DropdownMenuSize } function DropdownMenu({ size = 'md', children, ...rest }: DropdownMenuProps) { const reducedMotion = useReducedMotion() const ctx = React.useMemo(() => ({ size, reducedMotion }), [size, reducedMotion]) return ( {children} ) } type DropdownMenuTriggerProps = React.ComponentProps function DropdownMenuTrigger({ className, ...props }: DropdownMenuTriggerProps) { return } const POPUP_SIZE: Record = { sm: 'min-w-40 rounded-md', md: 'min-w-48 rounded-lg', lg: 'min-w-56 rounded-xl', } const ICON_SIZE: Record = { sm: 'size-4', md: 'size-4.5', lg: 'size-5', } function popupClassName(size: DropdownMenuSize, className?: string) { return cn( 'max-h-(--available-height) w-(--anchor-width) bg-background border-border-overlay flex flex-col border shadow-2xl outline-none', POPUP_SIZE[size], 'origin-(--transform-origin)', 'motion-safe:transition-[opacity,scale] motion-safe:duration-200 motion-safe:ease-[cubic-bezier(0.175,0.885,0.32,1.5)]', 'data-starting-style:motion-safe:scale-90 data-starting-style:motion-safe:opacity-0', 'data-ending-style:motion-safe:scale-95 data-ending-style:motion-safe:opacity-0 data-ending-style:motion-safe:duration-100 data-ending-style:motion-safe:ease-out', className, ) } type DropdownMenuFloatingProps = FloatingContentProps< React.ComponentProps, React.ComponentProps > type DropdownMenuContentProps = Omit, 'className'> & DropdownMenuFloatingProps & { /** Extra classes on the popup. */ className?: string } function DropdownMenuContent({ className, children, ...props }: DropdownMenuContentProps) { const { size } = useDropdownMenuContext() const { positioner, portal, popup } = splitFloatingProps(props) return (
{children}
) } const ITEM_BASE = 'w-full outline-hidden' const ITEM_TEXT: Record = { sm: 'gap-1', md: 'gap-1.5', lg: 'gap-1.5', } type DropdownMenuItemProps = React.ComponentProps function DropdownMenuItem({ className, ...props }: DropdownMenuItemProps) { const { size } = useDropdownMenuContext() return ( ) } type DropdownMenuLinkItemProps = React.ComponentProps function DropdownMenuLinkItem({ className, ...props }: DropdownMenuLinkItemProps) { const { size } = useDropdownMenuContext() return ( ) } type DropdownMenuGroupProps = React.ComponentProps function DropdownMenuGroup(props: DropdownMenuGroupProps) { return } type DropdownMenuGroupLabelProps = React.ComponentProps const GROUP_LABEL_SIZE: Record = { sm: 'px-2.5 pt-1.5 pb-1 text-xs', md: 'px-3 pt-2 pb-1.25 text-sm', lg: 'px-3.5 pt-2.5 pb-1.5 text-base', } function DropdownMenuGroupLabel({ className, ...props }: DropdownMenuGroupLabelProps) { const { size } = useDropdownMenuContext() return ( ) } type DropdownMenuSeparatorProps = React.ComponentProps function DropdownMenuSeparator({ className, ...props }: DropdownMenuSeparatorProps) { return ( ) } type DropdownMenuRadioGroupProps = React.ComponentProps function DropdownMenuRadioGroup(props: DropdownMenuRadioGroupProps) { return } type DropdownMenuRadioItemProps = React.ComponentProps function DropdownMenuRadioItem({ className, children, ...props }: DropdownMenuRadioItemProps) { const { size, reducedMotion } = useDropdownMenuContext() return ( {children} ) } type DropdownMenuCheckboxItemProps = React.ComponentProps function DropdownMenuCheckboxItem({ className, children, ...props }: DropdownMenuCheckboxItemProps) { const { size, reducedMotion } = useDropdownMenuContext() return ( {children} ) } type DropdownMenuSubProps = React.ComponentProps function DropdownMenuSub(props: DropdownMenuSubProps) { return } type DropdownMenuSubTriggerProps = React.ComponentProps function DropdownMenuSubTrigger({ className, children, ...props }: DropdownMenuSubTriggerProps) { const { size } = useDropdownMenuContext() return ( {children} ) } type DropdownMenuSubContentProps = Omit, 'className'> & DropdownMenuFloatingProps & { /** Extra classes on the submenu popup. */ className?: string } function DropdownMenuSubContent({ className, children, ...props }: DropdownMenuSubContentProps) { const { size } = useDropdownMenuContext() const { positioner, portal, popup } = splitFloatingProps(props) return (
{children}
) } interface IconProps extends React.SVGProps {} function CheckIcon({ className, ...props }: IconProps) { return ( ) } function ChevronEndIcon(props: IconProps) { return ( ) } export { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuGroup, DropdownMenuGroupLabel, DropdownMenuItem, DropdownMenuLinkItem, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuCheckboxItem, DropdownMenuSeparator, DropdownMenuSub, DropdownMenuSubTrigger, DropdownMenuSubContent, } export type { DropdownMenuProps, DropdownMenuTriggerProps, DropdownMenuContentProps, DropdownMenuGroupProps, DropdownMenuGroupLabelProps, DropdownMenuItemProps, DropdownMenuLinkItemProps, DropdownMenuRadioGroupProps, DropdownMenuRadioItemProps, DropdownMenuCheckboxItemProps, DropdownMenuSeparatorProps, DropdownMenuSubProps, DropdownMenuSubTriggerProps, DropdownMenuSubContentProps, }