input.tsx 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. 'use client'
  2. import type { FC } from 'react'
  3. import React, { useCallback } from 'react'
  4. type Props = {
  5. value: string | number
  6. onChange: (value: string | number) => void
  7. placeholder?: string
  8. isNumber?: boolean
  9. }
  10. const MIN_VALUE = 0
  11. const Input: FC<Props> = ({
  12. value,
  13. onChange,
  14. placeholder = '',
  15. isNumber = false,
  16. }) => {
  17. const handleChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
  18. const value = e.target.value
  19. if (isNumber) {
  20. let numberValue = parseInt(value, 10) // integer only
  21. if (isNaN(numberValue)) {
  22. onChange('')
  23. return
  24. }
  25. if (numberValue < MIN_VALUE)
  26. numberValue = MIN_VALUE
  27. onChange(numberValue)
  28. return
  29. }
  30. onChange(value)
  31. }, [isNumber, onChange])
  32. const otherOption = (() => {
  33. if (isNumber) {
  34. return {
  35. min: MIN_VALUE,
  36. }
  37. }
  38. return {
  39. }
  40. })()
  41. return (
  42. <input
  43. type={isNumber ? 'number' : 'text'}
  44. {...otherOption}
  45. value={value}
  46. onChange={handleChange}
  47. className='flex h-9 w-full py-1 px-2 rounded-lg text-xs leading-normal bg-gray-100 caret-primary-600 hover:bg-gray-100 focus:ring-1 focus:ring-inset focus:ring-gray-200 focus-visible:outline-none focus:bg-gray-50 placeholder:text-gray-400'
  48. placeholder={placeholder}
  49. />
  50. )
  51. }
  52. export default React.memo(Input)