input.tsx 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  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 = Number.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-8 w-full p-2 rounded-lg system-xs-regular text-components-input-text-filled bg-components-input-bg-normal
  48. caret-[#295eff] border border-transparent
  49. hover:bg-components-input-bg-hover hover:border hover:border-components-input-border-hover
  50. focus-visible:outline-none focus:bg-components-inout-border-active focus:border focus:border-components-input-border-active
  51. focus:shadow-xs focus:shadow-shadow-shadow-3
  52. placeholder:text-components-input-text-placeholder'
  53. placeholder={placeholder}
  54. />
  55. )
  56. }
  57. export default React.memo(Input)