diff --git a/dist/form.js b/dist/form.js
new file mode 100644
index 0000000..5642d36
--- /dev/null
+++ b/dist/form.js
@@ -0,0 +1,392 @@
+import { jsx as n, jsxs as y } from "react/jsx-runtime";
+import { Input as P, Checkbox as ee, Textarea as re, RadioGroup as te, HStack as ne, Radio as oe, Modal as le, ModalOverlay as ie, ModalContent as ce, ModalHeader as ue, ModalCloseButton as se, ModalBody as ae, VStack as de, SimpleGrid as fe, ModalFooter as pe, Button as G, FormControl as be, FormLabel as me, FormErrorMessage as ve, useDisclosure as xe } from "@chakra-ui/react";
+import { createContext as Fe, useContext as ge, useMemo as x, useRef as he, useEffect as H, useState as Se, useCallback as I } from "react";
+import { Controller as z, useForm as ke, useWatch as Re } from "react-hook-form";
+import { Select as Me } from "chakra-react-select";
+const Ce = {}, C = {
+ create: {
+ titlePrefix: "افزودن",
+ submitText: "ثبت"
+ },
+ edit: {
+ titlePrefix: "ویرایش",
+ submitText: "ویرایش"
+ }
+}, U = Fe(null);
+function ye({ 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 m() {
+ const e = ge(U);
+ if (!e)
+ throw new Error("Field باید داخل FormModal استفاده شود.");
+ return e;
+}
+function _(e = []) {
+ return e.map((r) => ({
+ label: r.label ?? r.name,
+ value: String(r.value ?? r.id)
+ }));
+}
+function g({ name: e, label: r, showWhen: t, children: o }) {
+ var s;
+ const { errors: i, control: u } = m(), c = Re({
+ control: u,
+ name: t == null ? void 0 : t.name
+ });
+ return x(() => t ? typeof t == "function" ? t({
+ value: c
+ }) : c === t.value : !0, [t, c]) ? /* @__PURE__ */ y(be, { isInvalid: !!i[e], children: [
+ r && /* @__PURE__ */ n(me, { fontSize: "sm", fontWeight: "bold", children: r }),
+ o,
+ /* @__PURE__ */ n(ve, { children: (s = i[e]) == null ? void 0 : s.message })
+ ] }) : null;
+}
+function Ve({
+ name: e,
+ label: r,
+ required: t,
+ validate: o,
+ rules: i,
+ showWhen: u,
+ placeholder: c,
+ ...l
+}) {
+ const { register: s } = m();
+ return /* @__PURE__ */ n(g, { name: e, label: r, showWhen: u, children: /* @__PURE__ */ n(
+ P,
+ {
+ borderRadius: "xl",
+ placeholder: c,
+ ...s(e, F({ required: t, validate: o, rules: i })),
+ ...l
+ }
+ ) });
+}
+function Ee({
+ name: e,
+ label: r,
+ required: t,
+ validate: o,
+ rules: i,
+ showWhen: u,
+ placeholder: c,
+ ...l
+}) {
+ const { register: s } = m();
+ return /* @__PURE__ */ n(g, { name: e, label: r, showWhen: u, children: /* @__PURE__ */ n(
+ 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: d = !0,
+ ...p
+}) {
+ const { control: f, setValue: a } = m(), k = _(l);
+ return /* @__PURE__ */ n(g, { name: e, label: r, showWhen: u, children: /* @__PURE__ */ n(
+ z,
+ {
+ name: e,
+ control: f,
+ rules: F({ required: t, validate: o, rules: i }),
+ render: ({ field: S }) => {
+ const V = k.find(
+ (v) => String(v.value) === String(S.value)
+ ) ?? null;
+ return /* @__PURE__ */ n(
+ Me,
+ {
+ ...p,
+ value: V,
+ options: k,
+ placeholder: c,
+ isClearable: d,
+ onChange: (v) => {
+ const R = (v == null ? void 0 : v.value) ?? "";
+ S.onChange(R), s == null || s({
+ value: R,
+ setValue: a
+ });
+ }
+ }
+ );
+ }
+ }
+ ) });
+}
+function Ie({
+ name: e,
+ label: r,
+ required: t,
+ validate: o,
+ rules: i,
+ showWhen: u,
+ options: c = [],
+ onChange: l
+}) {
+ const { control: s, setValue: d } = m(), p = _(c);
+ return /* @__PURE__ */ n(g, { name: e, label: r, showWhen: u, children: /* @__PURE__ */ n(
+ z,
+ {
+ name: e,
+ control: s,
+ rules: F({ required: t, validate: o, rules: i }),
+ render: ({ field: f }) => /* @__PURE__ */ n(
+ te,
+ {
+ value: f.value,
+ onChange: (a) => {
+ f.onChange(a), l == null || l({
+ value: a,
+ setValue: d
+ });
+ },
+ children: /* @__PURE__ */ n(ne, { pt: "8px", spacing: 3, children: p.map((a) => /* @__PURE__ */ n(oe, { value: a.value, children: a.label }, a.value)) })
+ }
+ )
+ }
+ ) });
+}
+function Pe({
+ name: e,
+ label: r,
+ required: t,
+ validate: o,
+ rules: i,
+ showWhen: u,
+ children: c,
+ onChange: l
+}) {
+ const { control: s, setValue: d } = m();
+ return /* @__PURE__ */ n(g, { name: e, label: r, showWhen: u, children: /* @__PURE__ */ n(
+ z,
+ {
+ name: e,
+ control: s,
+ rules: F({ required: t, validate: o, rules: i }),
+ render: ({ field: p }) => /* @__PURE__ */ n(
+ ee,
+ {
+ isChecked: !!p.value,
+ onChange: (f) => {
+ const a = f.target.checked;
+ p.onChange(a), l == null || l({
+ value: a,
+ setValue: d
+ });
+ },
+ children: c ?? r
+ }
+ )
+ }
+ ) });
+}
+function ze({
+ name: e,
+ label: r,
+ required: t,
+ validate: o,
+ rules: i,
+ showWhen: u,
+ ...c
+}) {
+ const { register: l } = m();
+ return /* @__PURE__ */ n(g, { name: e, label: r, showWhen: u, children: /* @__PURE__ */ n(
+ P,
+ {
+ type: "file",
+ borderRadius: "xl",
+ ...l(e, F({ required: t, validate: o, rules: i })),
+ ...c
+ }
+ ) });
+}
+function De({
+ name: e,
+ label: r,
+ required: t,
+ validate: o,
+ rules: i,
+ showWhen: u,
+ ...c
+}) {
+ const { register: l } = m();
+ return /* @__PURE__ */ n(g, { name: e, label: r, showWhen: u, children: /* @__PURE__ */ n(
+ P,
+ {
+ type: "date",
+ borderRadius: "xl",
+ ...l(e, F({ required: t, validate: o, rules: i })),
+ ...c
+ }
+ ) });
+}
+const Ae = {
+ Input: Ve,
+ Select: Be,
+ Radio: Ie,
+ Textarea: Ee,
+ Check: Pe,
+ Filepicker: ze,
+ Datepicker: De,
+ useForm: m
+};
+function Ge({
+ isOpen: e,
+ close: r,
+ item: t = null,
+ entityName: o = "آیتم",
+ title: i,
+ createTitle: u,
+ editTitle: c,
+ submitText: l,
+ createSubmitText: s,
+ editSubmitText: d,
+ defaultValues: p = Ce,
+ getDefaultValues: f,
+ resetKey: a,
+ onSubmit: k,
+ transformValues: S,
+ children: V,
+ isLoading: v = !1,
+ size: R = "lg",
+ columns: Y = { base: 1, md: 2 }
+}) {
+ const b = !!t, h = 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 ? d ?? C.edit.submitText : s ?? C.create.submitText), [l, d, s, b]), M = x(() => typeof f == "function" ? f({
+ item: t,
+ mode: h,
+ isEdit: b
+ }) : p, [f, p, t, h, b]), E = he(M);
+ H(() => {
+ E.current = M;
+ }, [M]);
+ const K = x(() => a || ye({
+ item: t,
+ mode: h
+ }), [a, t, h]), Q = ke({
+ defaultValues: M
+ }), {
+ handleSubmit: X,
+ reset: B,
+ register: D,
+ control: L,
+ setValue: O,
+ watch: T,
+ formState: { isSubmitting: Z, errors: $ }
+ } = Q;
+ H(() => {
+ e && B(E.current);
+ }, [e, K, B]);
+ const j = () => {
+ B(E.current), r();
+ }, q = X(async (A) => {
+ const W = typeof S == "function" ? S({
+ values: A,
+ item: t,
+ mode: h,
+ isEdit: b
+ }) : A;
+ await k({
+ values: W,
+ item: t,
+ mode: h,
+ isEdit: b
+ });
+ }), N = x(
+ () => ({
+ register: D,
+ control: L,
+ setValue: O,
+ watch: T,
+ errors: $
+ }),
+ [D, L, O, T, $]
+ );
+ return /* @__PURE__ */ y(le, { isOpen: e, onClose: j, isCentered: !0, size: R, children: [
+ /* @__PURE__ */ n(ie, { backdropFilter: "blur(6px)" }),
+ /* @__PURE__ */ y(
+ ce,
+ {
+ as: "form",
+ onSubmit: q,
+ borderRadius: "2xl",
+ overflow: "visible",
+ children: [
+ /* @__PURE__ */ n(
+ ue,
+ {
+ bgGradient: "linear(to-l, blue.600, facebook.500)",
+ color: "white",
+ fontSize: "md",
+ fontWeight: "black",
+ children: w
+ }
+ ),
+ /* @__PURE__ */ n(se, { color: "white" }),
+ /* @__PURE__ */ n(ae, { py: 5, children: /* @__PURE__ */ n(U.Provider, { value: N, children: /* @__PURE__ */ n(de, { spacing: 4, alignItems: "stretch", children: /* @__PURE__ */ n(fe, { columns: Y, spacing: 4, children: V }) }) }) }),
+ /* @__PURE__ */ y(pe, { gap: 2, bg: "gray.50", children: [
+ /* @__PURE__ */ n(G, { type: "button", variant: "ghost", onClick: j, children: "انصراف" }),
+ /* @__PURE__ */ n(
+ G,
+ {
+ type: "submit",
+ colorScheme: "blue",
+ borderRadius: "xl",
+ isLoading: Z || v,
+ children: J
+ }
+ )
+ ] })
+ ]
+ }
+ )
+ ] });
+}
+function He() {
+ const { isOpen: e, onOpen: r, onClose: t } = xe(), [o, i] = Se(null), u = I(() => {
+ i(null), r();
+ }, [r]), c = I(
+ (d) => {
+ i(d), r();
+ },
+ [r]
+ ), l = I(() => {
+ i(null), t();
+ }, [t]), s = !!o;
+ return x(
+ () => ({
+ isOpen: e,
+ item: o,
+ isEdit: s,
+ isCreate: !s,
+ openCreate: u,
+ openEdit: c,
+ close: l
+ }),
+ [e, o, s, u, c, l]
+ );
+}
+export {
+ Ae as Field,
+ Ge as FormModal,
+ He as useFormModal
+};
diff --git a/package.json b/package.json
index 5f7afea..09ce615 100644
--- a/package.json
+++ b/package.json
@@ -10,7 +10,8 @@
"./pagination": "./dist/pagination.js",
"./layout": "./dist/layout.js",
"./core": "./dist/core.js",
- "./table": "./dist/table.js"
+ "./table": "./dist/table.js",
+ "./form": "./dist/form.js"
},
"files": [
"dist"
@@ -29,7 +30,9 @@
"keycloak-js": "^26.0.0",
"react": "^18.0.0 || ^19.0.0",
"react-dom": "^18.0.0 || ^19.0.0",
- "react-icons": "^5.0.0"
+ "react-icons": "^5.0.0",
+ "react-hook-form": "^7.0.0",
+ "chakra-react-select": "^5.0.0"
},
"peerDependenciesMeta": {
"@chakra-ui/react": {
@@ -64,6 +67,12 @@
},
"react-icons": {
"optional": true
+ },
+ "react-hook-form": {
+ "optional": true
+ },
+ "chakra-react-select": {
+ "optional": true
}
},
"devDependencies": {
@@ -79,7 +88,9 @@
"react": "^18.0.0",
"react-dom": "^18.0.0",
"react-icons": "^5.0.0",
- "vite": "5.4.19"
+ "vite": "5.4.19",
+ "react-hook-form": "^7.0.0",
+ "chakra-react-select": "^5.0.0"
},
"dependencies": {}
}
diff --git a/src/form/FormModal.jsx b/src/form/FormModal.jsx
new file mode 100644
index 0000000..3bdd63e
--- /dev/null
+++ b/src/form/FormModal.jsx
@@ -0,0 +1,574 @@
+import {
+ Button,
+ Checkbox,
+ FormControl,
+ FormErrorMessage,
+ FormLabel,
+ HStack,
+ Input,
+ Modal,
+ ModalBody,
+ ModalCloseButton,
+ ModalContent,
+ ModalFooter,
+ ModalHeader,
+ ModalOverlay,
+ Radio,
+ RadioGroup,
+ Select,
+ SimpleGrid,
+ Textarea,
+ VStack,
+} from "@chakra-ui/react";
+import { createContext, useContext, useEffect, useMemo, useRef } from "react";
+import { Controller, useForm, useWatch } from "react-hook-form";
+import { Select as ChakraReactSelect } from "chakra-react-select";
+
+const EMPTY_DEFAULT_VALUES = {};
+
+const defaultActionLabels = {
+ create: {
+ titlePrefix: "افزودن",
+ submitText: "ثبت",
+ },
+ edit: {
+ titlePrefix: "ویرایش",
+ submitText: "ویرایش",
+ },
+};
+
+const FormModalContext = createContext(null);
+
+// ----- utils -----
+
+function getDefaultResetKey({ item, mode }) {
+ if (!item) return mode;
+
+ return [mode, item.rowId, item.entityId, item.id].filter(Boolean).join("-");
+}
+
+function getRules({ required, validate, rules }) {
+ const finalRules = { ...(rules ?? {}) };
+
+ if (required) {
+ finalRules.required =
+ typeof required === "string" ? required : "این فیلد الزامی است.";
+ }
+
+ if (validate) {
+ finalRules.validate = validate;
+ }
+
+ return finalRules;
+}
+
+function useFormModalContext() {
+ const context = useContext(FormModalContext);
+
+ if (!context) {
+ throw new Error("Field باید داخل FormModal استفاده شود.");
+ }
+
+ return context;
+}
+
+function normalizeOptions(options = []) {
+ return options.map((option) => ({
+ label: option.label ?? option.name,
+ value: String(option.value ?? option.id),
+ }));
+}
+
+// ----- field wrapper -----
+
+function FieldWrapper({ name, label, showWhen, children }) {
+ const { errors, control } = useFormModalContext();
+
+ const watchedValue = useWatch({
+ control,
+ name: showWhen?.name,
+ });
+
+ const isVisible = useMemo(() => {
+ if (!showWhen) return true;
+
+ if (typeof showWhen === "function") {
+ return showWhen({
+ value: watchedValue,
+ });
+ }
+
+ return watchedValue === showWhen.value;
+ }, [showWhen, watchedValue]);
+
+ if (!isVisible) return null;
+
+ return (
+
+ {label && (
+
+ {label}
+
+ )}
+
+ {children}
+
+ {errors[name]?.message}
+
+ );
+}
+
+// ----- fields -----
+
+function InputField({
+ name,
+ label,
+ required,
+ validate,
+ rules,
+ showWhen,
+ placeholder,
+ ...props
+}) {
+ const { register } = useFormModalContext();
+
+ return (
+
+
+
+ );
+}
+
+function TextareaField({
+ name,
+ label,
+ required,
+ validate,
+ rules,
+ showWhen,
+ placeholder,
+ ...props
+}) {
+ const { register } = useFormModalContext();
+
+ return (
+
+
+
+ );
+}
+
+function SelectField({
+ name,
+ label,
+ required,
+ validate,
+ rules,
+ showWhen,
+ placeholder = "انتخاب کنید",
+ options = [],
+ onChange,
+ isClearable = true,
+ ...props
+}) {
+ const { control, setValue } = useFormModalContext();
+ const normalizedOptions = normalizeOptions(options);
+
+ return (
+
+ {
+ const selectedOption =
+ normalizedOptions.find(
+ (option) => String(option.value) === String(field.value),
+ ) ?? null;
+
+ return (
+ {
+ const value = selected?.value ?? "";
+
+ field.onChange(value);
+
+ onChange?.({
+ value,
+ setValue,
+ });
+ }}
+ />
+ );
+ }}
+ />
+
+ );
+}
+
+function RadioField({
+ name,
+ label,
+ required,
+ validate,
+ rules,
+ showWhen,
+ options = [],
+ onChange,
+}) {
+ const { control, setValue } = useFormModalContext();
+ const normalizedOptions = normalizeOptions(options);
+
+ return (
+
+ (
+ {
+ field.onChange(value);
+
+ onChange?.({
+ value,
+ setValue,
+ });
+ }}
+ >
+
+ {normalizedOptions.map((option) => (
+
+ {option.label}
+
+ ))}
+
+
+ )}
+ />
+
+ );
+}
+
+function CheckField({
+ name,
+ label,
+ required,
+ validate,
+ rules,
+ showWhen,
+ children,
+ onChange,
+}) {
+ const { control, setValue } = useFormModalContext();
+
+ return (
+
+ (
+ {
+ const checked = event.target.checked;
+
+ field.onChange(checked);
+
+ onChange?.({
+ value: checked,
+ setValue,
+ });
+ }}
+ >
+ {children ?? label}
+
+ )}
+ />
+
+ );
+}
+
+function FilepickerField({
+ name,
+ label,
+ required,
+ validate,
+ rules,
+ showWhen,
+ ...props
+}) {
+ const { register } = useFormModalContext();
+
+ return (
+
+
+
+ );
+}
+
+function DatepickerField({
+ name,
+ label,
+ required,
+ validate,
+ rules,
+ showWhen,
+ ...props
+}) {
+ const { register } = useFormModalContext();
+
+ return (
+
+
+
+ );
+}
+
+export const Field = {
+ Input: InputField,
+ Select: SelectField,
+ Radio: RadioField,
+ Textarea: TextareaField,
+ Check: CheckField,
+ Filepicker: FilepickerField,
+ Datepicker: DatepickerField,
+ useForm: useFormModalContext,
+};
+
+// ----- form modal -----
+
+export function FormModal({
+ isOpen,
+ close,
+
+ item = null,
+ entityName = "آیتم",
+
+ title,
+ createTitle,
+ editTitle,
+
+ submitText,
+ createSubmitText,
+ editSubmitText,
+
+ defaultValues = EMPTY_DEFAULT_VALUES,
+ getDefaultValues,
+
+ resetKey,
+
+ onSubmit,
+ transformValues,
+
+ children,
+
+ isLoading = false,
+ size = "lg",
+ columns = { base: 1, md: 2 },
+}) {
+ const isEdit = Boolean(item);
+ const mode = isEdit ? "edit" : "create";
+
+ // ----- title -----
+
+ const resolvedTitle = useMemo(() => {
+ if (title) return title;
+
+ if (isEdit) {
+ return (
+ editTitle ?? `${defaultActionLabels.edit.titlePrefix} ${entityName}`
+ );
+ }
+
+ return (
+ createTitle ?? `${defaultActionLabels.create.titlePrefix} ${entityName}`
+ );
+ }, [title, editTitle, createTitle, entityName, isEdit]);
+
+ // ----- submit text -----
+
+ const resolvedSubmitText = useMemo(() => {
+ if (submitText) return submitText;
+
+ if (isEdit) {
+ return editSubmitText ?? defaultActionLabels.edit.submitText;
+ }
+
+ return createSubmitText ?? defaultActionLabels.create.submitText;
+ }, [submitText, editSubmitText, createSubmitText, isEdit]);
+
+ // ----- default values -----
+
+ const resolvedDefaultValues = useMemo(() => {
+ if (typeof getDefaultValues === "function") {
+ return getDefaultValues({
+ item,
+ mode,
+ isEdit,
+ });
+ }
+
+ return defaultValues;
+ }, [getDefaultValues, defaultValues, item, mode, isEdit]);
+
+ const latestDefaultValuesRef = useRef(resolvedDefaultValues);
+
+ useEffect(() => {
+ latestDefaultValuesRef.current = resolvedDefaultValues;
+ }, [resolvedDefaultValues]);
+
+ // ----- reset key -----
+
+ const resolvedResetKey = useMemo(() => {
+ if (resetKey) return resetKey;
+
+ return getDefaultResetKey({
+ item,
+ mode,
+ });
+ }, [resetKey, item, mode]);
+
+ // ----- form -----
+
+ const methods = useForm({
+ defaultValues: resolvedDefaultValues,
+ });
+
+ const {
+ handleSubmit,
+ reset,
+ register,
+ control,
+ setValue,
+ watch,
+ formState: { isSubmitting, errors },
+ } = methods;
+
+ // ----- reset on open -----
+
+ useEffect(() => {
+ if (!isOpen) return;
+
+ reset(latestDefaultValuesRef.current);
+ }, [isOpen, resolvedResetKey, reset]);
+
+ // ----- close -----
+
+ const handleClose = () => {
+ reset(latestDefaultValuesRef.current);
+ close();
+ };
+
+ // ----- submit -----
+
+ const handleFormSubmit = handleSubmit(async (values) => {
+ const finalValues =
+ typeof transformValues === "function"
+ ? transformValues({
+ values,
+ item,
+ mode,
+ isEdit,
+ })
+ : values;
+
+ await onSubmit({
+ values: finalValues,
+ item,
+ mode,
+ isEdit,
+ });
+ });
+
+ // ----- context -----
+
+ const contextValue = useMemo(
+ () => ({
+ register,
+ control,
+ setValue,
+ watch,
+ errors,
+ }),
+ [register, control, setValue, watch, errors],
+ );
+
+ // ----- jsx -----
+
+ return (
+
+
+
+
+
+ {resolvedTitle}
+
+
+
+
+
+
+
+
+ {children}
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/form/index.js b/src/form/index.js
new file mode 100644
index 0000000..acfa0b3
--- /dev/null
+++ b/src/form/index.js
@@ -0,0 +1,2 @@
+export { FormModal, Field } from "./FormModal.jsx";
+export { useFormModal } from "./useFormModal.jsx";
diff --git a/src/form/useFormModal.jsx b/src/form/useFormModal.jsx
new file mode 100644
index 0000000..e6bc0d9
--- /dev/null
+++ b/src/form/useFormModal.jsx
@@ -0,0 +1,40 @@
+import { useCallback, useMemo, useState } from "react";
+import { useDisclosure } from "@chakra-ui/react";
+
+export function useFormModal() {
+ const { isOpen, onOpen, onClose } = useDisclosure();
+ const [item, setItem] = useState(null);
+
+ const openCreate = useCallback(() => {
+ setItem(null);
+ onOpen();
+ }, [onOpen]);
+
+ const openEdit = useCallback(
+ (selectedItem) => {
+ setItem(selectedItem);
+ onOpen();
+ },
+ [onOpen],
+ );
+
+ const close = useCallback(() => {
+ setItem(null);
+ onClose();
+ }, [onClose]);
+
+ const isEdit = Boolean(item);
+
+ return useMemo(
+ () => ({
+ isOpen,
+ item,
+ isEdit,
+ isCreate: !isEdit,
+ openCreate,
+ openEdit,
+ close,
+ }),
+ [isOpen, item, isEdit, openCreate, openEdit, close],
+ );
+}
\ No newline at end of file
diff --git a/vite.config.js b/vite.config.js
index 3c69093..9a39a1b 100644
--- a/vite.config.js
+++ b/vite.config.js
@@ -19,6 +19,9 @@ const externalPackages = [
"@tanstack/react-table",
"react-icons",
+
+ "react-hook-form",
+ "chakra-react-select",
];
export default defineConfig({
@@ -33,6 +36,7 @@ export default defineConfig({
layout: path.resolve(process.cwd(), "src/layout/index.js"),
core: path.resolve(process.cwd(), "src/core/index.js"),
table: path.resolve(process.cwd(), "src/table/index.js"),
+ form: path.resolve(process.cwd(), "src/form/index.js"),
},
formats: ["es"],
},