src/Input/Input.tsx

Summary

Maintainability
A
0 mins
Test Coverage
import React, {
ChangeEvent,
InputHTMLAttributes,
useState,
forwardRef,
Ref,
useRef,
Dispatch
} from 'react'
 
import { Omit } from '../utils/types'
 
import { StyledInputProps, StyledContainer, AnimatedStyledInput } from './styled'
 
const makeHandleChange = (onChange: OnChange | undefined, setValid: Dispatch<boolean>) => {
return (event: ChangeEvent<HTMLInputElement>) => {
if (onChange) {
onChange(event.target.value, event)
event.target.checkValidity && setValid(event.target.checkValidity())
}
}
}
 
export type OmitOnChangeHTMLInputAttributes =
Omit<InputHTMLAttributes<HTMLInputElement>, 'onChange'>
 
export type OnChange<T = string, E = HTMLInputElement> = (value: T, event: ChangeEvent<E>) => void
 
export interface InputProps extends StyledInputProps, OmitOnChangeHTMLInputAttributes {
value?: string | number
onChange?: OnChange
required?: boolean
ref?: React.RefObject<HTMLInputElement> | null
disabled?: boolean
}
 
interface Props extends InputProps {
step?: number | string
type?: string
}
 
export const Input =
forwardRef(({
type = 'text',
onChange,
 
// Container props
onClick,
width,
 
// Container and Input props
inline,
 
// Rest goes to Input
...rest
}: Props, ref: Ref<HTMLInputElement>) => {
const [valid, setValid] = useState(true)
 
const containerRef = useRef<HTMLDivElement>(null)
 
const container = { onClick, width, inline }
 
return (
<StyledContainer ref={containerRef} {...container}>
<AnimatedStyledInput
ref={ref}
inline={inline}
type={type}
danger={!valid}
onChange={makeHandleChange(onChange, setValid)}
{...rest} />
</StyledContainer>
)
})