import { ChangeEvent, HTMLInputTypeAttribute, ReactNode, useMemo, useRef } from "react"
import { cn, getValidNumber, isValidNumber } from "@/lib/utils"
import { Input } from "../ui/input"
import { FormField } from "./FormField"
export function FormInput({
label,
className,
placeholder,
value,
minValue,
maxValue,
defaultValue,
disabled,
onChange,
horizontal,
type,
centered,
// ...props
}: {
label?: ReactNode
className?: string
placeholder?: ReactNode
value?: T
minValue?: T
maxValue?: T
defaultValue?: T
disabled?: boolean
onChange?: (newValue: T) => void
horizontal?: boolean
type?: HTMLInputTypeAttribute
centered?: boolean
}
// & Omit, "value" | "defaultValue" | "placeholder" | "type" | "className" | "disabled" | "onChange">
// & ComponentProps
) {
const isNumberInput =
typeof defaultValue === "number"
|| typeof value === "number"
const isTextInput =
typeof defaultValue === "string"
|| typeof value === "number"
// we try to use the type provided by the user if possible,
// otherwise we "guess" it
const inputType: HTMLInputTypeAttribute = type ||
(
isNumberInput ? "number"
: isTextInput ? "text"
: "text"
)
const ref = useRef(null)
const handleChange = useMemo(() => (event: ChangeEvent) => {
if (disabled) {
return
}
if (!onChange) {
return
}
const rawStringValue = `${event.currentTarget.value || ""}`
// this could be refactorer maybe
if (isNumberInput) {
const validMinValue: number = minValue && isValidNumber(minValue) ? (minValue as number) : 0
const validMaxValue: number = maxValue && isValidNumber(maxValue) ? (maxValue as number) : 1
const validDefaultValue: number = defaultValue && isValidNumber(defaultValue) ? (defaultValue as number) : 0
const numericValue = getValidNumber(
rawStringValue,
validMinValue,
validMaxValue,
validDefaultValue,
)
onChange(numericValue as T)
} else {
onChange(rawStringValue as T)
}
}, [isNumberInput, isTextInput, minValue, maxValue, defaultValue])
return (
{label}:>}
horizontal={horizontal}
centered={centered}
>
)
}