50 lines
1.7 KiB
TypeScript
50 lines
1.7 KiB
TypeScript
import _ from "lodash";
|
|
import { DetailedHTMLProps, FormHTMLAttributes } from "react";
|
|
import { twMerge } from "tailwind-merge";
|
|
|
|
type Props<T extends { [key: string]: any } = { [key: string]: any }> =
|
|
DetailedHTMLProps<FormHTMLAttributes<HTMLFormElement>, HTMLFormElement> & {
|
|
submitHandler?: (e: React.FormEvent<HTMLFormElement>, data: T) => void;
|
|
changeHandler?: (e: React.FormEvent<HTMLFormElement>, data: T) => void;
|
|
};
|
|
|
|
/**
|
|
* # Form Element
|
|
* @className twui-form
|
|
*/
|
|
export default function Form<
|
|
T extends { [key: string]: any } = { [key: string]: any }
|
|
>({ ...props }: Props<T>) {
|
|
const finalProps = _.omit(props, ["submitHandler", "changeHandler"]);
|
|
|
|
return (
|
|
<form
|
|
{...finalProps}
|
|
className={twMerge(
|
|
"flex flex-col items-stretch gap-2 w-full bg-transparent",
|
|
"twui-form",
|
|
props.className
|
|
)}
|
|
onSubmit={(e) => {
|
|
e.preventDefault();
|
|
const formEl = e.target as HTMLFormElement;
|
|
const formData = new FormData(formEl);
|
|
const data = Object.fromEntries(formData.entries()) as T;
|
|
props.submitHandler?.(e, data);
|
|
props.onSubmit?.(e);
|
|
}}
|
|
onChange={(e) => {
|
|
e.preventDefault();
|
|
const taregtEl = e.target as HTMLElement;
|
|
const formEl = taregtEl.closest("form") as HTMLFormElement;
|
|
const formData = new FormData(formEl);
|
|
const data = Object.fromEntries(formData.entries()) as T;
|
|
props.changeHandler?.(e, data);
|
|
props.onChange?.(e);
|
|
}}
|
|
>
|
|
{props.children}
|
|
</form>
|
|
);
|
|
}
|