select.tsx (4955B)
1 "use client" 2 3 import { Root, Group, Value, Trigger, Icon, ScrollUpButton, ScrollDownButton, Content, Portal, Viewport, Label, Item, ItemIndicator, ItemText, Separator } from "@radix-ui/react-select" 4 import { Check, ChevronDown, ChevronUp } from "lucide-react" 5 6 import { cn } from "@/lib/utils" 7 import React, { forwardRef, ComponentRef, ComponentPropsWithoutRef } from "react" 8 9 const Select = Root 10 11 const SelectGroup = Group 12 13 const SelectValue = Value 14 15 const SelectTrigger = forwardRef< 16 ComponentRef<typeof Trigger>, 17 ComponentPropsWithoutRef<typeof Trigger> 18 >(({ className, children, ...props }, ref) => ( 19 <Trigger 20 ref={ref} 21 className={cn( 22 "flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1", 23 className 24 )} 25 {...props} 26 > 27 {children} 28 <Icon asChild> 29 <ChevronDown className="h-4 w-4 opacity-50" /> 30 </Icon> 31 </Trigger> 32 )) 33 SelectTrigger.displayName = Trigger.displayName 34 35 const SelectScrollUpButton = forwardRef< 36 ComponentRef<typeof ScrollUpButton>, 37 ComponentPropsWithoutRef<typeof ScrollUpButton> 38 >(({ className, ...props }, ref) => ( 39 <ScrollUpButton 40 ref={ref} 41 className={cn( 42 "flex cursor-default items-center justify-center py-1", 43 className 44 )} 45 {...props} 46 > 47 <ChevronUp className="h-4 w-4" /> 48 </ScrollUpButton> 49 )) 50 SelectScrollUpButton.displayName = ScrollUpButton.displayName 51 52 const SelectScrollDownButton = forwardRef< 53 ComponentRef<typeof ScrollDownButton>, 54 ComponentPropsWithoutRef<typeof ScrollDownButton> 55 >(({ className, ...props }, ref) => ( 56 <ScrollDownButton 57 ref={ref} 58 className={cn( 59 "flex cursor-default items-center justify-center py-1", 60 className 61 )} 62 {...props} 63 > 64 <ChevronDown className="h-4 w-4" /> 65 </ScrollDownButton> 66 )) 67 SelectScrollDownButton.displayName = 68 ScrollDownButton.displayName 69 70 const SelectContent = forwardRef< 71 ComponentRef<typeof Content>, 72 ComponentPropsWithoutRef<typeof Content> 73 >(({ className, children, position = "popper", ...props }, ref) => ( 74 <Portal> 75 <Content 76 ref={ref} 77 className={cn( 78 "relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover 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", 79 position === "popper" && 80 "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1", 81 className 82 )} 83 position={position} 84 {...props} 85 > 86 <SelectScrollUpButton /> 87 <Viewport 88 className={cn( 89 "p-1", 90 position === "popper" && 91 "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]" 92 )} 93 > 94 {children} 95 </Viewport> 96 <SelectScrollDownButton /> 97 </Content> 98 </Portal> 99 )) 100 SelectContent.displayName = Content.displayName 101 102 const SelectLabel = forwardRef< 103 ComponentRef<typeof Label>, 104 ComponentPropsWithoutRef<typeof Label> 105 >(({ className, ...props }, ref) => ( 106 <Label 107 ref={ref} 108 className={cn("py-1.5 pl-8 pr-2 text-sm font-semibold", className)} 109 {...props} 110 /> 111 )) 112 SelectLabel.displayName = Label.displayName 113 114 const SelectItem = forwardRef< 115 ComponentRef<typeof Item>, 116 ComponentPropsWithoutRef<typeof Item> 117 >(({ className, children, ...props }, ref) => ( 118 <Item 119 ref={ref} 120 className={cn( 121 "relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50", 122 className 123 )} 124 {...props} 125 > 126 <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center"> 127 <ItemIndicator> 128 <Check className="h-4 w-4" /> 129 </ItemIndicator> 130 </span> 131 132 <ItemText>{children}</ItemText> 133 </Item> 134 )) 135 SelectItem.displayName = Item.displayName 136 137 const SelectSeparator = forwardRef< 138 ComponentRef<typeof Separator>, 139 ComponentPropsWithoutRef<typeof Separator> 140 >(({ className, ...props }, ref) => ( 141 <Separator 142 ref={ref} 143 className={cn("-mx-1 my-1 h-px bg-muted", className)} 144 {...props} 145 /> 146 )) 147 SelectSeparator.displayName = Separator.displayName 148 149 export { 150 Select, 151 SelectGroup, 152 SelectValue, 153 SelectTrigger, 154 SelectContent, 155 SelectLabel, 156 SelectItem, 157 SelectSeparator, 158 SelectScrollUpButton, 159 SelectScrollDownButton, 160 }