input.tsx 1.6 KB

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