prasi-lib/comps/form/field/Field.tsx

84 lines
2.3 KiB
TypeScript
Executable File

import { FC, useEffect } from "react";
import { FieldProp } from "../typings";
import { useField } from "../utils/use-field";
import { validate } from "../utils/validate";
import { FieldInput } from "./FieldInput";
import { Label } from "./Label";
import { useLocal } from "@/utils/use-local";
export const Field: FC<FieldProp> = (arg) => {
const { fm } = arg;
const field = useField(arg);
const name = typeof field.name === 'function' ? field.name() : field.name;
const local = useLocal({ prev_val: fm.data[name] });
const mode = fm.props.label_mode;
const w = field.width;
useEffect(() => {
if (local.prev_val !== fm.data[name]) {
validate(field, fm);
fm.events.on_change(name, fm.data[name]);
fm.render();
}
}, [fm.data[name]]);
if (field.status === "init" && !isEditor) return null;
const errors = fm.error.get(name);
const props = { ...arg.props };
delete props.className;
return (
<label
className={cx(
"field",
"c-flex",
css`
padding: 5px 0px 0px 10px;
`,
w === "auto" && fm.size.field === "full" && "c-w-full",
w === "auto" && fm.size.field === "half" && "c-w-1/2",
w === "full" && "c-w-full",
w === "¾" && "c-w-3/4",
w === "½" && "c-w-1/2",
w === "⅓" && "c-w-1/3",
w === "¼" && "c-w-1/4",
mode === "horizontal" && "c-flex-row c-items-center",
mode === "vertical" && "c-flex-col c-space-y-1"
)}
{...props}
>
{mode !== "hidden" && <Label field={field} fm={fm} />}
<div className="field-inner c-flex c-flex-1 c-flex-col">
<FieldInput
field={field}
fm={fm}
PassProp={arg.PassProp}
child={arg.child}
_meta={arg._meta}
_item={arg._item}
_sync={arg._sync}
arg={arg}
/>
{field.desc && (
<div className={cx("c-p-2 c-text-xs", errors.length > 0 && "c-pb-1")}>
{field.desc}
</div>
)}
{errors.length > 0 && (
<div
className={cx(
"c-p-2 c-text-xs c-text-red-600",
field.desc && "c-pt-0"
)}
>
{errors.map((err) => {
return <div>{err}</div>;
})}
</div>
)}
</div>
</label>
);
};