You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

index.tsx 3.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import type { CSSProperties } from 'react'
  2. import React from 'react'
  3. import { useTranslation } from 'react-i18next'
  4. import { RiCloseCircleFill, RiErrorWarningLine, RiSearchLine } from '@remixicon/react'
  5. import { type VariantProps, cva } from 'class-variance-authority'
  6. import cn from '@/utils/classnames'
  7. import { noop } from 'lodash-es'
  8. export const inputVariants = cva(
  9. '',
  10. {
  11. variants: {
  12. size: {
  13. regular: 'px-3 radius-md system-sm-regular',
  14. large: 'px-4 radius-lg system-md-regular',
  15. },
  16. },
  17. defaultVariants: {
  18. size: 'regular',
  19. },
  20. },
  21. )
  22. export type InputProps = {
  23. showLeftIcon?: boolean
  24. showClearIcon?: boolean
  25. onClear?: () => void
  26. disabled?: boolean
  27. destructive?: boolean
  28. wrapperClassName?: string
  29. styleCss?: CSSProperties
  30. unit?: string
  31. ref?: React.Ref<HTMLInputElement>
  32. } & Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size'> & VariantProps<typeof inputVariants>
  33. const Input = ({
  34. size,
  35. disabled,
  36. destructive,
  37. showLeftIcon,
  38. showClearIcon,
  39. onClear,
  40. wrapperClassName,
  41. className,
  42. styleCss,
  43. value,
  44. placeholder,
  45. onChange = noop,
  46. unit,
  47. ref,
  48. ...props
  49. }: InputProps) => {
  50. const { t } = useTranslation()
  51. return (
  52. <div className={cn('relative w-full', wrapperClassName)}>
  53. {showLeftIcon && <RiSearchLine className={cn('absolute left-2 top-1/2 h-4 w-4 -translate-y-1/2 text-components-input-text-placeholder')} />}
  54. <input
  55. ref={ref}
  56. style={styleCss}
  57. className={cn(
  58. 'w-full appearance-none border border-transparent bg-components-input-bg-normal py-[7px] text-components-input-text-filled caret-primary-600 outline-none placeholder:text-components-input-text-placeholder hover:border-components-input-border-hover hover:bg-components-input-bg-hover focus:border-components-input-border-active focus:bg-components-input-bg-active focus:shadow-xs',
  59. inputVariants({ size }),
  60. showLeftIcon && 'pl-[26px]',
  61. showLeftIcon && size === 'large' && 'pl-7',
  62. showClearIcon && value && 'pr-[26px]',
  63. showClearIcon && value && size === 'large' && 'pr-7',
  64. destructive && 'pr-[26px]',
  65. destructive && size === 'large' && 'pr-7',
  66. disabled && 'cursor-not-allowed border-transparent bg-components-input-bg-disabled text-components-input-text-filled-disabled hover:border-transparent hover:bg-components-input-bg-disabled',
  67. destructive && 'border-components-input-border-destructive bg-components-input-bg-destructive text-components-input-text-filled hover:border-components-input-border-destructive hover:bg-components-input-bg-destructive focus:border-components-input-border-destructive focus:bg-components-input-bg-destructive',
  68. className,
  69. )}
  70. placeholder={placeholder ?? (showLeftIcon
  71. ? (t('common.operation.search') || '')
  72. : (t('common.placeholder.input') || ''))}
  73. value={value}
  74. onChange={onChange}
  75. disabled={disabled}
  76. {...props}
  77. />
  78. {showClearIcon && value && !disabled && !destructive && (
  79. <div className={cn('group absolute right-2 top-1/2 -translate-y-1/2 cursor-pointer p-[1px]')} onClick={onClear}>
  80. <RiCloseCircleFill className='h-3.5 w-3.5 cursor-pointer text-text-quaternary group-hover:text-text-tertiary' />
  81. </div>
  82. )}
  83. {destructive && (
  84. <RiErrorWarningLine className='absolute right-2 top-1/2 h-4 w-4 -translate-y-1/2 text-text-destructive-secondary' />
  85. )}
  86. {
  87. unit && (
  88. <div className='system-sm-regular absolute right-2 top-1/2 -translate-y-1/2 text-text-tertiary'>
  89. {unit}
  90. </div>
  91. )
  92. }
  93. </div>
  94. )
  95. }
  96. Input.displayName = 'Input'
  97. export default Input