update FormModal

This commit is contained in:
Mohamadzadeh 2026-06-21 16:13:51 +03:30
parent a1b7dc4338
commit 5d799ce84f
2 changed files with 244 additions and 193 deletions

389
dist/form.js vendored
View File

@ -1,8 +1,8 @@
import { jsx as n, jsxs as M } from "react/jsx-runtime";
import { Input as I, Checkbox as ee, Textarea as re, RadioGroup as te, HStack as ne, Radio as oe, Select as le, Modal as ie, ModalOverlay as ce, ModalContent as ue, ModalHeader as se, ModalCloseButton as ae, ModalBody as de, VStack as fe, SimpleGrid as pe, ModalFooter as be, Button as A, FormControl as ve, FormLabel as me, FormErrorMessage as xe, useDisclosure as Fe } from "@chakra-ui/react";
import { useContext as he, useMemo as x, useRef as ge, useEffect as G, createContext as ke, useState as Re, useCallback as B } from "react";
import { Controller as P, useForm as Se, useWatch as Ce } from "react-hook-form";
const Me = {}, C = {
import { jsx as l, jsxs as R } from "react/jsx-runtime";
import { Input as I, Checkbox as ee, Textarea as re, RadioGroup as te, HStack as le, Radio as ne, Select as oe, Modal as ie, ModalOverlay as ce, ModalContent as ue, ModalHeader as se, ModalCloseButton as ae, ModalBody as de, VStack as fe, SimpleGrid as be, ModalFooter as pe, Button as A, FormControl as ve, FormLabel as me, FormErrorMessage as xe, useDisclosure as Fe } from "@chakra-ui/react";
import { useContext as he, useMemo as m, useRef as ge, useEffect as G, createContext as ke, useState as Se, useCallback as E } from "react";
import { Controller as P, useForm as ye, useWatch as Re } from "react-hook-form";
const Me = {}, y = {
create: {
titlePrefix: "افزودن",
submitText: "ثبت"
@ -12,12 +12,12 @@ const Me = {}, C = {
submitText: "ویرایش"
}
}, H = ke(null);
function ye({ item: e, mode: r }) {
function Ce({ item: e, mode: r }) {
return e ? [r, e.rowId, e.entityId, e.id].filter(Boolean).join("-") : r;
}
function F({ required: e, validate: r, rules: t }) {
const o = { ...t ?? {} };
return e && (o.required = typeof e == "string" ? e : "این فیلد الزامی است."), r && (o.validate = r), o;
function x({ required: e, validate: r, rules: t }) {
const n = { ...t ?? {} };
return e && (n.required = typeof e == "string" ? e : "این فیلد الزامی است."), r && (n.validate = r), n;
}
function v() {
const e = he(H);
@ -26,43 +26,68 @@ function v() {
return e;
}
function U(e = []) {
return e.map((r) => ({
label: r.label ?? r.name,
value: String(r.value ?? r.id)
}));
return e.map((r, t) => {
if (typeof r != "object" || r === null) {
const o = String(r);
return {
key: o,
label: o,
value: o,
disabled: !1
};
}
function h({ name: e, label: r, showWhen: t, children: o }) {
const n = r.value ?? r.id;
return {
key: String(r.key ?? n ?? t),
label: r.label ?? r.name ?? n,
value: String(n),
disabled: !!r.disabled
};
});
}
function Ve({ options: e = [] }) {
return e.map((r, t) => /* @__PURE__ */ l(
"option",
{
value: r.value,
disabled: r.disabled,
children: r.label
},
`${r.key}-${t}`
));
}
function F({ name: e, label: r, showWhen: t, children: n }) {
var s;
const { errors: i, control: u } = v(), c = Ce({
const { errors: o, control: u } = v(), c = Re({
control: u,
name: t == null ? void 0 : t.name
});
return x(() => t ? typeof t == "function" ? t({
return m(() => t ? typeof t == "function" ? t({
value: c
}) : c === t.value : !0, [t, c]) ? /* @__PURE__ */ M(ve, { isInvalid: !!i[e], children: [
r && /* @__PURE__ */ n(me, { fontSize: "sm", fontWeight: "bold", children: r }),
o,
/* @__PURE__ */ n(xe, { children: (s = i[e]) == null ? void 0 : s.message })
}) : c === t.value : !0, [t, c]) ? /* @__PURE__ */ R(ve, { isInvalid: !!o[e], children: [
r && /* @__PURE__ */ l(me, { fontSize: "sm", fontWeight: "bold", children: r }),
n,
/* @__PURE__ */ l(xe, { children: (s = o[e]) == null ? void 0 : s.message })
] }) : null;
}
function Ve({
function Be({
name: e,
label: r,
required: t,
validate: o,
rules: i,
validate: n,
rules: o,
showWhen: u,
placeholder: c,
...l
...i
}) {
const { register: s } = v();
return /* @__PURE__ */ n(h, { name: e, label: r, showWhen: u, children: /* @__PURE__ */ n(
return /* @__PURE__ */ l(F, { name: e, label: r, showWhen: u, children: /* @__PURE__ */ l(
I,
{
borderRadius: "xl",
placeholder: c,
...s(e, F({ required: t, validate: o, rules: i })),
...l
...s(e, x({ required: t, validate: n, rules: o })),
...i
}
) });
}
@ -70,60 +95,20 @@ function Ee({
name: e,
label: r,
required: t,
validate: o,
rules: i,
validate: n,
rules: o,
showWhen: u,
placeholder: c,
...l
...i
}) {
const { register: s } = v();
return /* @__PURE__ */ n(h, { name: e, label: r, showWhen: u, children: /* @__PURE__ */ n(
return /* @__PURE__ */ l(F, { name: e, label: r, showWhen: u, children: /* @__PURE__ */ l(
re,
{
borderRadius: "xl",
placeholder: c,
...s(e, F({ required: t, validate: o, rules: i })),
...l
}
) });
}
function Be({
name: e,
label: r,
required: t,
validate: o,
rules: i,
showWhen: u,
placeholder: c = "انتخاب کنید",
options: l = [],
onChange: s,
isClearable: f = !0,
...p
}) {
const { control: d, setValue: a } = v(), y = U(l);
return /* @__PURE__ */ n(h, { name: e, label: r, showWhen: u, children: /* @__PURE__ */ n(
P,
{
name: e,
control: d,
rules: F({ required: t, validate: o, rules: i }),
render: ({ field: k }) => /* @__PURE__ */ n(
le,
{
borderRadius: "xl",
placeholder: c,
value: k.value ?? "",
onChange: (m) => {
const R = m.target.value;
k.onChange(R), s == null || s({
value: R,
setValue: a
});
},
...p,
children: y.map((m) => /* @__PURE__ */ n("option", { value: m.value, children: m.label }, m.value))
}
)
...s(e, x({ required: t, validate: n, rules: o })),
...i
}
) });
}
@ -131,30 +116,37 @@ function Ie({
name: e,
label: r,
required: t,
validate: o,
rules: i,
validate: n,
rules: o,
showWhen: u,
options: c = [],
onChange: l
placeholder: c = "انتخاب کنید",
options: i = [],
onChange: s,
isClearable: d = !0,
...b
}) {
const { control: s, setValue: f } = v(), p = U(c);
return /* @__PURE__ */ n(h, { name: e, label: r, showWhen: u, children: /* @__PURE__ */ n(
const { control: f, setValue: a } = v(), M = m(() => U(i), [i]);
return /* @__PURE__ */ l(F, { name: e, label: r, showWhen: u, children: /* @__PURE__ */ l(
P,
{
name: e,
control: s,
rules: F({ required: t, validate: o, rules: i }),
render: ({ field: d }) => /* @__PURE__ */ n(
te,
control: f,
rules: x({ required: t, validate: n, rules: o }),
render: ({ field: g }) => /* @__PURE__ */ l(
oe,
{
value: d.value,
onChange: (a) => {
d.onChange(a), l == null || l({
value: a,
setValue: f
borderRadius: "xl",
placeholder: d ? c : void 0,
value: g.value ?? "",
onChange: (C) => {
const k = C.target.value;
g.onChange(k), s == null || s({
value: k,
setValue: a
});
},
children: /* @__PURE__ */ n(ne, { pt: "8px", spacing: 3, children: p.map((a) => /* @__PURE__ */ n(oe, { value: a.value, children: a.label }, a.value)) })
...b,
children: /* @__PURE__ */ l(Ve, { options: M })
}
)
}
@ -164,28 +156,61 @@ function Pe({
name: e,
label: r,
required: t,
validate: o,
rules: i,
validate: n,
rules: o,
showWhen: u,
children: c,
onChange: l
options: c = [],
onChange: i
}) {
const { control: s, setValue: f } = v();
return /* @__PURE__ */ n(h, { name: e, label: r, showWhen: u, children: /* @__PURE__ */ n(
const { control: s, setValue: d } = v(), b = U(c);
return /* @__PURE__ */ l(F, { name: e, label: r, showWhen: u, children: /* @__PURE__ */ l(
P,
{
name: e,
control: s,
rules: F({ required: t, validate: o, rules: i }),
render: ({ field: p }) => /* @__PURE__ */ n(
rules: x({ required: t, validate: n, rules: o }),
render: ({ field: f }) => /* @__PURE__ */ l(
te,
{
value: f.value,
onChange: (a) => {
f.onChange(a), i == null || i({
value: a,
setValue: d
});
},
children: /* @__PURE__ */ l(le, { pt: "8px", spacing: 3, children: b.map((a) => /* @__PURE__ */ l(ne, { value: a.value, children: a.label }, a.value)) })
}
)
}
) });
}
function $e({
name: e,
label: r,
required: t,
validate: n,
rules: o,
showWhen: u,
children: c,
onChange: i
}) {
const { control: s, setValue: d } = v();
return /* @__PURE__ */ l(F, { name: e, label: r, showWhen: u, children: /* @__PURE__ */ l(
P,
{
name: e,
control: s,
rules: x({ required: t, validate: n, rules: o }),
render: ({ field: b }) => /* @__PURE__ */ l(
ee,
{
isChecked: !!p.value,
onChange: (d) => {
const a = d.target.checked;
p.onChange(a), l == null || l({
isChecked: !!b.value,
onChange: (f) => {
const a = f.target.checked;
b.onChange(a), i == null || i({
value: a,
setValue: f
setValue: d
});
},
children: c ?? r
@ -198,18 +223,18 @@ function ze({
name: e,
label: r,
required: t,
validate: o,
rules: i,
validate: n,
rules: o,
showWhen: u,
...c
}) {
const { register: l } = v();
return /* @__PURE__ */ n(h, { name: e, label: r, showWhen: u, children: /* @__PURE__ */ n(
const { register: i } = v();
return /* @__PURE__ */ l(F, { name: e, label: r, showWhen: u, children: /* @__PURE__ */ l(
I,
{
type: "file",
borderRadius: "xl",
...l(e, F({ required: t, validate: o, rules: i })),
...i(e, x({ required: t, validate: n, rules: o })),
...c
}
) });
@ -218,106 +243,106 @@ function De({
name: e,
label: r,
required: t,
validate: o,
rules: i,
validate: n,
rules: o,
showWhen: u,
...c
}) {
const { register: l } = v();
return /* @__PURE__ */ n(h, { name: e, label: r, showWhen: u, children: /* @__PURE__ */ n(
const { register: i } = v();
return /* @__PURE__ */ l(F, { name: e, label: r, showWhen: u, children: /* @__PURE__ */ l(
I,
{
type: "date",
borderRadius: "xl",
...l(e, F({ required: t, validate: o, rules: i })),
...i(e, x({ required: t, validate: n, rules: o })),
...c
}
) });
}
const je = {
Input: Ve,
Select: Be,
Radio: Ie,
const Ae = {
Input: Be,
Select: Ie,
Radio: Pe,
Textarea: Ee,
Check: Pe,
Check: $e,
Filepicker: ze,
Datepicker: De,
useForm: v
};
function Ae({
function Ge({
isOpen: e,
close: r,
item: t = null,
entityName: o = "آیتم",
title: i,
entityName: n = "آیتم",
title: o,
createTitle: u,
editTitle: c,
submitText: l,
submitText: i,
createSubmitText: s,
editSubmitText: f,
defaultValues: p = Me,
getDefaultValues: d,
editSubmitText: d,
defaultValues: b = Me,
getDefaultValues: f,
resetKey: a,
onSubmit: y,
transformValues: k,
children: m,
isLoading: R = !1,
onSubmit: M,
transformValues: g,
children: C,
isLoading: k = !1,
size: _ = "lg",
columns: Y = { base: 1, md: 2 }
}) {
const b = !!t, g = b ? "edit" : "create", w = x(() => i || (b ? c ?? `${C.edit.titlePrefix} ${o}` : u ?? `${C.create.titlePrefix} ${o}`), [i, c, u, o, b]), J = x(() => l || (b ? f ?? C.edit.submitText : s ?? C.create.submitText), [l, f, s, b]), S = x(() => typeof d == "function" ? d({
const p = !!t, h = p ? "edit" : "create", w = m(() => o || (p ? c ?? `${y.edit.titlePrefix} ${n}` : u ?? `${y.create.titlePrefix} ${n}`), [o, c, u, n, p]), J = m(() => i || (p ? d ?? y.edit.submitText : s ?? y.create.submitText), [i, d, s, p]), S = m(() => typeof f == "function" ? f({
item: t,
mode: g,
isEdit: b
}) : p, [d, p, t, g, b]), V = ge(S);
mode: h,
isEdit: p
}) : b, [f, b, t, h, p]), V = ge(S);
G(() => {
V.current = S;
}, [S]);
const K = x(() => a || ye({
const K = m(() => a || Ce({
item: t,
mode: g
}), [a, t, g]), Q = Se({
mode: h
}), [a, t, h]), Q = ye({
defaultValues: S
}), {
handleSubmit: X,
reset: E,
register: z,
control: D,
setValue: L,
watch: T,
reset: B,
register: $,
control: z,
setValue: D,
watch: L,
formState: { isSubmitting: Z, errors: O }
} = Q;
G(() => {
e && E(V.current);
}, [e, K, E]);
const $ = () => {
E(V.current), r();
e && B(V.current);
}, [e, K, B]);
const T = () => {
B(V.current), r();
}, q = X(async (j) => {
const W = typeof k == "function" ? k({
const W = typeof g == "function" ? g({
values: j,
item: t,
mode: g,
isEdit: b
mode: h,
isEdit: p
}) : j;
await y({
await M({
values: W,
item: t,
mode: g,
isEdit: b
mode: h,
isEdit: p
});
}), N = x(
}), N = m(
() => ({
register: z,
control: D,
setValue: L,
watch: T,
register: $,
control: z,
setValue: D,
watch: L,
errors: O
}),
[z, D, L, T, O]
[$, z, D, L, O]
);
return /* @__PURE__ */ M(ie, { isOpen: e, onClose: $, isCentered: !0, size: _, children: [
/* @__PURE__ */ n(ce, { backdropFilter: "blur(6px)" }),
/* @__PURE__ */ M(
return /* @__PURE__ */ R(ie, { isOpen: e, onClose: T, isCentered: !0, size: _, children: [
/* @__PURE__ */ l(ce, { backdropFilter: "blur(6px)" }),
/* @__PURE__ */ R(
ue,
{
as: "form",
@ -325,7 +350,7 @@ function Ae({
borderRadius: "2xl",
overflow: "visible",
children: [
/* @__PURE__ */ n(
/* @__PURE__ */ l(
se,
{
bgGradient: "linear(to-l, blue.600, facebook.500)",
@ -335,17 +360,17 @@ function Ae({
children: w
}
),
/* @__PURE__ */ n(ae, { color: "white" }),
/* @__PURE__ */ n(de, { py: 5, children: /* @__PURE__ */ n(H.Provider, { value: N, children: /* @__PURE__ */ n(fe, { spacing: 4, alignItems: "stretch", children: /* @__PURE__ */ n(pe, { columns: Y, spacing: 4, children: m }) }) }) }),
/* @__PURE__ */ M(be, { gap: 2, bg: "gray.50", children: [
/* @__PURE__ */ n(A, { type: "button", variant: "ghost", onClick: $, children: "انصراف" }),
/* @__PURE__ */ n(
/* @__PURE__ */ l(ae, { color: "white" }),
/* @__PURE__ */ l(de, { py: 5, children: /* @__PURE__ */ l(H.Provider, { value: N, children: /* @__PURE__ */ l(fe, { spacing: 4, alignItems: "stretch", children: /* @__PURE__ */ l(be, { columns: Y, spacing: 4, children: C }) }) }) }),
/* @__PURE__ */ R(pe, { gap: 2, bg: "gray.50", children: [
/* @__PURE__ */ l(A, { type: "button", variant: "ghost", onClick: T, children: "انصراف" }),
/* @__PURE__ */ l(
A,
{
type: "submit",
colorScheme: "blue",
borderRadius: "xl",
isLoading: Z || R,
isLoading: Z || k,
children: J
}
)
@ -355,32 +380,32 @@ function Ae({
)
] });
}
function Ge() {
const { isOpen: e, onOpen: r, onClose: t } = Fe(), [o, i] = Re(null), u = B(() => {
i(null), r();
}, [r]), c = B(
(f) => {
i(f), r();
function He() {
const { isOpen: e, onOpen: r, onClose: t } = Fe(), [n, o] = Se(null), u = E(() => {
o(null), r();
}, [r]), c = E(
(d) => {
o(d), r();
},
[r]
), l = B(() => {
i(null), t();
}, [t]), s = !!o;
return x(
), i = E(() => {
o(null), t();
}, [t]), s = !!n;
return m(
() => ({
isOpen: e,
item: o,
item: n,
isEdit: s,
isCreate: !s,
openCreate: u,
openEdit: c,
close: l
close: i
}),
[e, o, s, u, c, l]
[e, n, s, u, c, i]
);
}
export {
je as Field,
Ae as FormModal,
Ge as useFormModal
Ae as Field,
Ge as FormModal,
He as useFormModal
};

View File

@ -72,10 +72,39 @@ function useFormModalContext() {
}
function normalizeOptions(options = []) {
return options.map((option) => ({
label: option.label ?? option.name,
value: String(option.value ?? option.id),
}));
return options.map((option, index) => {
if (typeof option !== "object" || option === null) {
const value = String(option);
return {
key: value,
label: value,
value,
disabled: false,
};
}
const value = option.value ?? option.id;
return {
key: String(option.key ?? value ?? index),
label: option.label ?? option.name ?? value,
value: String(value),
disabled: Boolean(option.disabled),
};
});
}
function NativeSelectOptions({ options = [] }) {
return options.map((option, index) => (
<option
key={`${option.key}-${index}`}
value={option.value}
disabled={option.disabled}
>
{option.label}
</option>
));
}
// ----- field wrapper -----
@ -181,7 +210,8 @@ function SelectField({
...props
}) {
const { control, setValue } = useFormModalContext();
const normalizedOptions = normalizeOptions(options);
const normalizedOptions = useMemo(() => normalizeOptions(options), [options]);
return (
<FieldWrapper name={name} label={label} showWhen={showWhen}>
@ -192,7 +222,7 @@ function SelectField({
render={({ field }) => (
<Select
borderRadius="xl"
placeholder={placeholder}
placeholder={isClearable ? placeholder : undefined}
value={field.value ?? ""}
onChange={(event) => {
const value = event.target.value;
@ -206,11 +236,7 @@ function SelectField({
}}
{...props}
>
{normalizedOptions.map((option) => (
<option key={option.value} value={option.value}>
{option.label}
</option>
))}
<NativeSelectOptions options={normalizedOptions} />
</Select>
)}
/>