Input.tsx 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. import type { FC } from 'react'
  2. import { useContext } from 'use-context-selector'
  3. import type { Field, FormValue } from '../declarations'
  4. import { ValidatedSuccessIcon } from '../../key-validator/ValidateStatus'
  5. import { ValidatedStatus } from '../../key-validator/declarations'
  6. import type { ValidatedStatusState } from '../../key-validator/declarations'
  7. import I18n from '@/context/i18n'
  8. type InputProps = {
  9. field: Field
  10. value: FormValue
  11. onChange: (v: FormValue) => void
  12. onFocus: () => void
  13. validatedStatusState: ValidatedStatusState
  14. }
  15. const Input: FC<InputProps> = ({
  16. field,
  17. value,
  18. onChange,
  19. onFocus,
  20. validatedStatusState,
  21. }) => {
  22. const { locale } = useContext(I18n)
  23. const showValidatedIcon = validatedStatusState.status === ValidatedStatus.Success && value[field.key]
  24. const getValidatedIcon = () => {
  25. if (showValidatedIcon)
  26. return <div className='absolute top-2.5 right-2.5'><ValidatedSuccessIcon /></div>
  27. }
  28. const handleChange = (v: string) => {
  29. const newFormValue = { ...value, [field.key]: v }
  30. onChange(newFormValue)
  31. }
  32. return (
  33. <div className='relative'>
  34. <input
  35. tabIndex={-1}
  36. className={`
  37. block px-3 w-full h-9 bg-gray-100 text-sm rounded-lg border border-transparent
  38. appearance-none outline-none caret-primary-600
  39. hover:border-[rgba(0,0,0,0.08)] hover:bg-gray-50
  40. focus:bg-white focus:border-gray-300 focus:shadow-xs
  41. placeholder:text-sm placeholder:text-gray-400
  42. ${showValidatedIcon && 'pr-[30px]'}
  43. `}
  44. placeholder={field?.placeholder?.[locale] || ''}
  45. onChange={e => handleChange(e.target.value)}
  46. onFocus={onFocus}
  47. value={value[field.key] || ''}
  48. />
  49. {getValidatedIcon()}
  50. </div>
  51. )
  52. }
  53. export default Input