draupnir4all-web

git clone git://archive.git.mtrnord.blog/MTRNord/draupnir4all-web.git
Log | Files | Refs | README | LICENSE

dropdown-menu.tsx (6445B)


      1 "use client"
      2 
      3 import { Root, Trigger, Group, Portal, Sub, RadioGroup, SubTrigger, Content, Item, SubContent, CheckboxItem, ItemIndicator, RadioItem, Label, Separator } from "@radix-ui/react-dropdown-menu"
      4 import { Check, ChevronRight, Circle } from "lucide-react"
      5 
      6 import { cn } from "@/lib/utils"
      7 import { forwardRef, ComponentRef, ComponentPropsWithoutRef, HTMLAttributes } from "react"
      8 
      9 const DropdownMenu = Root
     10 
     11 const DropdownMenuTrigger = Trigger
     12 
     13 const DropdownMenuGroup = Group
     14 
     15 const DropdownMenuPortal = Portal
     16 
     17 const DropdownMenuSub = Sub
     18 
     19 const DropdownMenuRadioGroup = RadioGroup
     20 
     21 const DropdownMenuSubTrigger = forwardRef<
     22   ComponentRef<typeof SubTrigger>,
     23   ComponentPropsWithoutRef<typeof SubTrigger> & {
     24     inset?: boolean
     25   }
     26 >(({ className, inset, children, ...props }, ref) => (
     27   <SubTrigger
     28     ref={ref}
     29     className={cn(
     30       "flex cursor-default gap-2 select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
     31       inset && "pl-8",
     32       className
     33     )}
     34     {...props}
     35   >
     36     {children}
     37     <ChevronRight className="ml-auto" />
     38   </SubTrigger>
     39 ))
     40 DropdownMenuSubTrigger.displayName =
     41   SubTrigger.displayName
     42 
     43 const DropdownMenuSubContent = forwardRef<
     44   ComponentRef<typeof SubContent>,
     45   ComponentPropsWithoutRef<typeof SubContent>
     46 >(({ className, ...props }, ref) => (
     47   <SubContent
     48     ref={ref}
     49     className={cn(
     50       "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 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",
     51       className
     52     )}
     53     {...props}
     54   />
     55 ))
     56 DropdownMenuSubContent.displayName =
     57   SubContent.displayName
     58 
     59 const DropdownMenuContent = forwardRef<
     60   ComponentRef<typeof Content>,
     61   ComponentPropsWithoutRef<typeof Content>
     62 >(({ className, sideOffset = 4, ...props }, ref) => (
     63   <Portal>
     64     <Content
     65       ref={ref}
     66       sideOffset={sideOffset}
     67       className={cn(
     68         "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 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",
     69         className
     70       )}
     71       {...props}
     72     />
     73   </Portal>
     74 ))
     75 DropdownMenuContent.displayName = Content.displayName
     76 
     77 const DropdownMenuItem = forwardRef<
     78   ComponentRef<typeof Item>,
     79   ComponentPropsWithoutRef<typeof Item> & {
     80     inset?: boolean
     81   }
     82 >(({ className, inset, ...props }, ref) => (
     83   <Item
     84     ref={ref}
     85     className={cn(
     86       "relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors 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",
     87       inset && "pl-8",
     88       className
     89     )}
     90     {...props}
     91   />
     92 ))
     93 DropdownMenuItem.displayName = Item.displayName
     94 
     95 const DropdownMenuCheckboxItem = forwardRef<
     96   ComponentRef<typeof CheckboxItem>,
     97   ComponentPropsWithoutRef<typeof CheckboxItem>
     98 >(({ className, children, checked, ...props }, ref) => (
     99   <CheckboxItem
    100     ref={ref}
    101     className={cn(
    102       "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
    103       className
    104     )}
    105     checked={checked}
    106     {...props}
    107   >
    108     <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
    109       <ItemIndicator>
    110         <Check className="h-4 w-4" />
    111       </ItemIndicator>
    112     </span>
    113     {children}
    114   </CheckboxItem>
    115 ))
    116 DropdownMenuCheckboxItem.displayName =
    117   CheckboxItem.displayName
    118 
    119 const DropdownMenuRadioItem = forwardRef<
    120   ComponentRef<typeof RadioItem>,
    121   ComponentPropsWithoutRef<typeof RadioItem>
    122 >(({ className, children, ...props }, ref) => (
    123   <RadioItem
    124     ref={ref}
    125     className={cn(
    126       "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
    127       className
    128     )}
    129     {...props}
    130   >
    131     <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
    132       <ItemIndicator>
    133         <Circle className="h-2 w-2 fill-current" />
    134       </ItemIndicator>
    135     </span>
    136     {children}
    137   </RadioItem>
    138 ))
    139 DropdownMenuRadioItem.displayName = RadioItem.displayName
    140 
    141 const DropdownMenuLabel = forwardRef<
    142   ComponentRef<typeof Label>,
    143   ComponentPropsWithoutRef<typeof Label> & {
    144     inset?: boolean
    145   }
    146 >(({ className, inset, ...props }, ref) => (
    147   <Label
    148     ref={ref}
    149     className={cn(
    150       "px-2 py-1.5 text-sm font-semibold",
    151       inset && "pl-8",
    152       className
    153     )}
    154     {...props}
    155   />
    156 ))
    157 DropdownMenuLabel.displayName = Label.displayName
    158 
    159 const DropdownMenuSeparator = forwardRef<
    160   ComponentRef<typeof Separator>,
    161   ComponentPropsWithoutRef<typeof Separator>
    162 >(({ className, ...props }, ref) => (
    163   <Separator
    164     ref={ref}
    165     className={cn("-mx-1 my-1 h-px bg-muted", className)}
    166     {...props}
    167   />
    168 ))
    169 DropdownMenuSeparator.displayName = Separator.displayName
    170 
    171 const DropdownMenuShortcut = ({
    172   className,
    173   ...props
    174 }: HTMLAttributes<HTMLSpanElement>) => {
    175   return (
    176     <span
    177       className={cn("ml-auto text-xs tracking-widest opacity-60", className)}
    178       {...props}
    179     />
    180   )
    181 }
    182 DropdownMenuShortcut.displayName = "DropdownMenuShortcut"
    183 
    184 export {
    185   DropdownMenu,
    186   DropdownMenuTrigger,
    187   DropdownMenuContent,
    188   DropdownMenuItem,
    189   DropdownMenuCheckboxItem,
    190   DropdownMenuRadioItem,
    191   DropdownMenuLabel,
    192   DropdownMenuSeparator,
    193   DropdownMenuShortcut,
    194   DropdownMenuGroup,
    195   DropdownMenuPortal,
    196   DropdownMenuSub,
    197   DropdownMenuSubContent,
    198   DropdownMenuSubTrigger,
    199   DropdownMenuRadioGroup,
    200 }