import { useRef, type InputHTMLAttributes } from "react";
type defaultValues = Record;
interface Props {
initialValues?: Partial;
}
type InputElements =
| HTMLInputElement
| HTMLSelectElement
| HTMLTextAreaElement
;
interface UseFormReturns {
getValue: () => T;
setValue: (name: keyof T, value: string | number) => void;
setValues: (values: Partial) => void;
bindInput: (name: keyof T) => InputHTMLAttributes;
// onSubmit: (values: T) => (ev: React.FormEvent) => void
onSubmit: (fn: (values: T) => void) => (ev: React.FormEvent) => void
}
const isCheckBox = (el: HTMLElement) => {
return el instanceof HTMLInputElement && el.type === "checkbox";
}
function useForm({ initialValues }: Props) {
const inputs = useRef>>({});
const values = useRef({ ...initialValues } as T);
const inst = useRef>();
if (!inst.current) {
const getValue = () => {
return values.current;
}
const setValue = (name, value) => {
const el = inputs.current[name];
console.log(el, name);
if (el) {
values.current[name as keyof T] = value;
if (el instanceof HTMLInputElement && el.type === "checkbox") {
el.checked = value;
return;
}
inputs.current[name].value = value;
}
}
const setValues = (values) => {
Object.keys(values).forEach((key) => {
setValue(key, values[key]);
});
}
const bindInput = (name: string) => {
return {
name,
id: name,
ref: (target) => {
console.log('ref', target);
if (target) {
inputs.current[name as keyof T] = target;
if (isCheckBox(target)) {
target.checked = initialValues?.[name];
}
else if (name in initialValues) {
target.value = initialValues[name];
}
}
},
onChange: (ev) => {
const { name, value, checked } = ev.target;
if (isCheckBox(ev.target)) {
values.current[name as keyof T] = checked;
return;
}
values.current[name as keyof T] = value;
},
}
}
const onSubmit = (fn: (values: T) => void) => {
return (ev: React.FormEvent) => {
ev.preventDefault();
fn(getValue());
}
}
inst.current = {
getValue,
setValue,
setValues,
bindInput,
onSubmit,
};
}
return inst.current;
}
export default useForm;