'use client' import type { CompositionEventHandler, FocusEventHandler, InputEventHandler, ComponentProps, } from 'react' import { Input } from './ui/input' import { type FieldPath, type FieldValues, useFormContext } from 'react-hook-form' interface FormInpuProps< TFieldValues extends FieldValues, TFieldName extends FieldPath, > extends ComponentProps<'input'> { name: TFieldName format?: (value: string) => string sanitize?: (value: string) => string } export const FormInput = < TFieldValues extends FieldValues, TFieldName extends FieldPath, >({ name, format, sanitize, ...props }: FormInpuProps) => { const { onChange, onBlur, ...registerResult } = useFormContext().register( name, sanitize ? { setValueAs: sanitize } : undefined, ) const handleUpdate = (e: EventTarget & HTMLInputElement, value: string) => { const selectiondistance = e.value.length - (e.selectionEnd ?? 0) e.value = value const caretPos = value.length - selectiondistance e.setSelectionRange(caretPos, caretPos) } const handleInput: InputEventHandler = (e) => { if (e.nativeEvent.isComposing) { return } if (format) { handleUpdate(e.currentTarget, format(e.currentTarget.value)) } onChange(e) } const handleCompositionEnd: CompositionEventHandler | undefined = format ? (e) => handleUpdate(e.currentTarget, format(e.currentTarget.value)) : undefined const handleBlur: FocusEventHandler = (e) => { handleUpdate( e.currentTarget, format?.(sanitize?.(e.currentTarget.value) ?? e.currentTarget.value) ?? e.currentTarget.value, ) onBlur(e) } return ( ) }