input.tsx 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. import { Input as TaroInput, InputProps as TaroInputProps, View, Text } from '@tarojs/components'
  2. import { cn } from '@/utils/cn'
  3. import { cva, type VariantProps } from 'class-variance-authority'
  4. import { forwardRef } from 'react'
  5. const inputVariants = cva(
  6. 'flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-base ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
  7. {
  8. variants: {
  9. variant: {
  10. default: 'border-gray-300 focus:border-blue-500 focus:ring-blue-500',
  11. outline: 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',
  12. filled: 'border-none bg-gray-50 hover:bg-gray-100',
  13. },
  14. size: {
  15. default: 'h-10 px-3 py-2',
  16. sm: 'h-9 px-2 text-sm',
  17. lg: 'h-11 px-4 text-lg',
  18. icon: 'h-10 w-10',
  19. },
  20. },
  21. defaultVariants: {
  22. variant: 'default',
  23. size: 'default',
  24. },
  25. }
  26. )
  27. export interface InputProps extends Omit<TaroInputProps, 'className'>, VariantProps<typeof inputVariants> {
  28. className?: string
  29. leftIcon?: string
  30. rightIcon?: string
  31. error?: boolean
  32. errorMessage?: string
  33. onLeftIconClick?: () => void
  34. onRightIconClick?: () => void
  35. }
  36. const Input = forwardRef<any, InputProps>(
  37. ({ className, variant, size, leftIcon, rightIcon, error, errorMessage, onLeftIconClick, onRightIconClick, ...props }, ref) => {
  38. return (
  39. <View className="w-full">
  40. <View className="relative">
  41. {leftIcon && (
  42. <View
  43. className={cn(
  44. "absolute left-3 top-1/2 -translate-y-1/2",
  45. onLeftIconClick ? "cursor-pointer" : "pointer-events-none"
  46. )}
  47. onClick={onLeftIconClick}
  48. >
  49. <View className={cn('w-5 h-5 text-gray-400', leftIcon)} />
  50. </View>
  51. )}
  52. <TaroInput
  53. ref={ref}
  54. className={cn(
  55. inputVariants({ variant, size, className }),
  56. error && 'border-red-500 focus:border-red-500 focus:ring-red-500',
  57. leftIcon && 'pl-10',
  58. rightIcon && 'pr-10',
  59. )}
  60. {...props}
  61. />
  62. {rightIcon && (
  63. <View
  64. className={cn(
  65. "absolute right-3 top-1/2 -translate-y-1/2",
  66. onRightIconClick ? "cursor-pointer" : "pointer-events-none"
  67. )}
  68. onClick={onRightIconClick}
  69. >
  70. <View className={cn('w-5 h-5 text-gray-400', rightIcon)} />
  71. </View>
  72. )}
  73. </View>
  74. {error && errorMessage && (
  75. <Text className="mt-1 text-sm text-red-600">{errorMessage}</Text>
  76. )}
  77. </View>
  78. )
  79. }
  80. )
  81. Input.displayName = 'Input'
  82. export { Input, inputVariants }