select.tsx 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. import * as React from 'react'
  2. import * as SelectPrimitive from '@radix-ui/react-select'
  3. import { Check, ChevronDown, ChevronUp } from 'lucide-react'
  4. // @ts-ignore
  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. 'ui__select-trigger',
  17. 'flex h-10 w-full items-center justify-between rounded-md border ' +
  18. 'border-input bg-background px-3 py-2 text-sm ring-offset-background ' +
  19. 'placeholder:text-muted-foreground focus:outline-none focus:ring-2 ' +
  20. 'focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed ' +
  21. 'disabled:opacity-50 [&>span]:line-clamp-1',
  22. className
  23. )}
  24. {...props}
  25. >
  26. {children}
  27. <SelectPrimitive.Icon asChild>
  28. <ChevronDown className="h-4 w-4 opacity-50"/>
  29. </SelectPrimitive.Icon>
  30. </SelectPrimitive.Trigger>
  31. ))
  32. SelectTrigger.displayName = SelectPrimitive.Trigger.displayName
  33. const SelectScrollUpButton = React.forwardRef<
  34. React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,
  35. React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>
  36. >(({ className, ...props }, ref) => (
  37. <SelectPrimitive.ScrollUpButton
  38. ref={ref}
  39. className={cn(
  40. 'ui__select-up-button flex cursor-default items-center justify-center py-1',
  41. className
  42. )}
  43. {...props}
  44. >
  45. <ChevronUp className="h-4 w-4"/>
  46. </SelectPrimitive.ScrollUpButton>
  47. ))
  48. SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName
  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. 'ui__select-down-button 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. const SelectContent = React.forwardRef<
  67. React.ElementRef<typeof SelectPrimitive.Content>,
  68. React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
  69. >(({ className, children, position = 'popper', ...props }, ref) => (
  70. <SelectPrimitive.Portal>
  71. <SelectPrimitive.Content
  72. ref={ref}
  73. className={cn(
  74. 'ui__select-content',
  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. const SelectLabel = React.forwardRef<
  99. React.ElementRef<typeof SelectPrimitive.Label>,
  100. React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>
  101. >(({ className, ...props }, ref) => (
  102. <SelectPrimitive.Label
  103. ref={ref}
  104. className={cn('ui__select-label py-1.5 pl-8 pr-2 text-sm font-semibold', className)}
  105. {...props}
  106. />
  107. ))
  108. SelectLabel.displayName = SelectPrimitive.Label.displayName
  109. const SelectItem = React.forwardRef<
  110. React.ElementRef<typeof SelectPrimitive.Item>,
  111. React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>
  112. >(({ className, children, ...props }, ref) => (
  113. <SelectPrimitive.Item
  114. ref={ref}
  115. className={cn(
  116. 'ui__select-item',
  117. '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',
  118. className
  119. )}
  120. {...props}
  121. >
  122. <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
  123. <SelectPrimitive.ItemIndicator>
  124. <Check className="h-4 w-4"/>
  125. </SelectPrimitive.ItemIndicator>
  126. </span>
  127. <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
  128. </SelectPrimitive.Item>
  129. ))
  130. SelectItem.displayName = SelectPrimitive.Item.displayName
  131. const SelectSeparator = React.forwardRef<
  132. React.ElementRef<typeof SelectPrimitive.Separator>,
  133. React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>
  134. >(({ className, ...props }, ref) => (
  135. <SelectPrimitive.Separator
  136. ref={ref}
  137. className={cn('ui__select-separator -mx-1 my-1 h-px bg-muted', className)}
  138. {...props}
  139. />
  140. ))
  141. SelectSeparator.displayName = SelectPrimitive.Separator.displayName
  142. export {
  143. Select,
  144. SelectGroup,
  145. SelectValue,
  146. SelectTrigger,
  147. SelectContent,
  148. SelectLabel,
  149. SelectItem,
  150. SelectSeparator,
  151. SelectScrollUpButton,
  152. SelectScrollDownButton,
  153. }