import { ReactNode, useCallback, useEffect, useState } from "react"; import { BaseFormLocal, default_base_form_local } from "./types"; import { useLocal } from "lib/utils/use-local"; import { FieldLocal, FieldProp, fieldType } from "../typings"; export type BaseFormProps = { data: T; className?: string; on_submit?: (form: BaseFormLocal) => Promise | any; children: ReactNode | ((form: BaseFormLocal) => ReactNode); render?: () => void; is_form?: boolean; }; export const BaseForm = >( props: BaseFormProps ) => { const { data, children, className, on_submit, render } = props; const form = useLocal({ ...default_base_form_local }) as BaseFormLocal; if (render) { form.render = render; } form.submit = useCallback(async () => { if (form.status === "ready") { form.status = "submitting"; form.render(); const result = await on_submit?.(form); setTimeout(() => { form.status = "ready"; form.render(); }, 1000); return result; } }, [on_submit]); form.createArg = (arg) => { const prop: FieldProp = { name: arg.name, on_load: arg.onLoad, sub_type: arg.subType, } as any; if (arg.onChange) prop.on_change = arg.onChange; return prop; }; form.createField = (arg) => { if (form.fields[arg.name]) return form.fields[arg.name]; const prop: FieldLocal = { name: arg.name, label: typeof arg.label !== "undefined" ? arg.label : arg.name, render: arg.render || form.render, width: "auto", prefix: arg.prefix, } as any; form.fields[arg.name] = prop; return prop; }; form.createFm = () => { if (form.fm) { form.fm.data = form.data; return form.fm; } let size = "full"; if (form.internal.width > 650) { size = "half"; } form.fm = { data: form.data, props: { label_mode: "vertical" }, error: { get: () => { return []; }, }, submit: () => on_submit?.(form), size: { field: size }, render: form.render, } as any; return form.fm as any; }; form.fieldProps = (arg) => { return { fm: form.createFm(), arg: form.createArg(arg), field: form.createField(arg), }; }; useEffect(() => { form.data = data; form.render(); if (form.internal.width === 0) { setTimeout(() => { form.render(); }, 1000); } }, [data]); if (form.status === "init") { form.status = "ready"; } if (typeof props.is_form === "boolean") { if (!props.is_form) { return (
{typeof children === "function" ? children(form) : children}
); } } return (
{ e.preventDefault(); e.stopPropagation(); form.submit(); }} className={cx( "form c-flex-1 c-flex c-flex-col c-w-full c-h-full c-relative c-overflow-auto", className )} >
{ if (el?.offsetWidth) { form.internal.width = el?.offsetWidth; form.createFm(); } }} > {form.internal.width > 0 && ( <>{typeof children === "function" ? children(form) : children} )}
); };