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