import * as React from 'react'; import { useCallback, useState } from 'react'; import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu'; import { cn, createPrimitiveElement, withCn, withProps, withRef, withVariants, } from '@udecode/cn'; import { cva } from 'class-variance-authority'; import { Check, ChevronRight } from 'lucide-react'; export const DropdownMenu = DropdownMenuPrimitive.Root; export const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger; export const DropdownMenuGroup = React.forwardRef< HTMLDivElement, { label?: React.ReactNode } & React.ComponentPropsWithoutRef< typeof DropdownMenuPrimitive.Group > >(({ label, ...props }, ref) => { return ( <> {label && {label}} {props.children} ); }); DropdownMenuGroup.displayName = 'DropdownMenuGroup'; export const DropdownMenuPortal = DropdownMenuPrimitive.Portal; export const DropdownMenuSub = DropdownMenuPrimitive.Sub; export const DropdownMenuRadioGroup = React.forwardRef< HTMLDivElement, { label?: React.ReactNode } & React.ComponentPropsWithoutRef< typeof DropdownMenuPrimitive.RadioGroup > >(({ label, ...props }, ref) => { return ( <> {label && {label}} {props.children} ); }); DropdownMenuRadioGroup.displayName = 'DropdownMenuRadioGroup'; export const DropdownMenuSubTrigger = withRef< typeof DropdownMenuPrimitive.SubTrigger, { inset?: boolean; } >(({ children, className, inset, ...props }, ref) => ( {children} )); export const DropdownMenuSubContent = withCn( DropdownMenuPrimitive.SubContent, 'data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-32 overflow-hidden rounded-md border bg-popover py-1 text-popover-foreground shadow-lg data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95', ); const DropdownMenuContentVariants = withProps(DropdownMenuPrimitive.Content, { className: cn( 'data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-32 overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95', ), sideOffset: 4, }); export const DropdownMenuContent = withRef< typeof DropdownMenuPrimitive.Content >(({ ...props }, ref) => ( { e.preventDefault(); }} {...props} /> )); const menuItemVariants = cva( 'relative mx-1 flex cursor-pointer items-center gap-2 rounded-sm px-2 py-1 text-sm transition-colors outline-none select-none focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0', { variants: { inset: { true: 'pl-8', }, }, }, ); export const DropdownMenuItem = withVariants( DropdownMenuPrimitive.Item, menuItemVariants, ['inset'], ); export const DropdownMenuCheckboxItem = withRef< typeof DropdownMenuPrimitive.CheckboxItem >(({ children, className, ...props }, ref) => ( {children} )); export const DropdownMenuRadioItem = withRef< typeof DropdownMenuPrimitive.RadioItem, { hideIcon?: boolean; } >(({ children, className, hideIcon, ...props }, ref) => ( {!hideIcon && ( )} {children} )); const dropdownMenuLabelVariants = cva( cn( 'mx-1 px-2 pt-1.5 pb-2 text-xs font-semibold text-muted-foreground select-none', ), { variants: { inset: { true: 'pl-8', }, }, }, ); export const DropdownMenuLabel = withVariants( DropdownMenuPrimitive.Label, dropdownMenuLabelVariants, ['inset'], ); export const DropdownMenuSeparator = withCn( DropdownMenuPrimitive.Separator, '-mx-1 my-1 h-px bg-muted', ); export const DropdownMenuShortcut = withCn( createPrimitiveElement('span'), 'ml-auto text-xs tracking-widest opacity-60', ); export const useOpenState = () => { const [open, setOpen] = useState(false); const onOpenChange = useCallback( (_value = !open) => { setOpen(_value); }, [open], ); return { open, onOpenChange, }; };