select.tsx 5.5 KB

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