@saas-ui/forms 2.0.0-next.2 → 2.0.0-next.21
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +194 -0
- package/README.md +53 -6
- package/dist/ajv/index.d.ts +24 -11
- package/dist/ajv/index.js +7 -9
- package/dist/ajv/index.js.map +1 -1
- package/dist/ajv/index.mjs +7 -10
- package/dist/ajv/index.mjs.map +1 -1
- package/dist/index.d.ts +519 -280
- package/dist/index.js +777 -696
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +756 -676
- package/dist/index.mjs.map +1 -1
- package/dist/yup/index.d.ts +525 -21
- package/dist/yup/index.js +21 -9
- package/dist/yup/index.js.map +1 -1
- package/dist/yup/index.mjs +21 -10
- package/dist/yup/index.mjs.map +1 -1
- package/dist/zod/index.d.ts +525 -12
- package/dist/zod/index.js +21 -1
- package/dist/zod/index.js.map +1 -1
- package/dist/zod/index.mjs +21 -3
- package/dist/zod/index.mjs.map +1 -1
- package/package.json +33 -10
- package/src/array-field.tsx +88 -48
- package/src/auto-form.tsx +7 -3
- package/src/base-field.tsx +54 -0
- package/src/create-field.tsx +144 -0
- package/src/create-form.tsx +68 -0
- package/src/create-step-form.tsx +100 -0
- package/src/default-fields.tsx +163 -0
- package/src/display-field.tsx +9 -11
- package/src/display-if.tsx +20 -13
- package/src/field-resolver.ts +10 -8
- package/src/field.tsx +18 -445
- package/src/fields-context.tsx +23 -0
- package/src/fields.tsx +34 -21
- package/src/form-context.tsx +84 -0
- package/src/form.tsx +77 -55
- package/src/index.ts +58 -4
- package/src/input-right-button/input-right-button.stories.tsx +1 -1
- package/src/input-right-button/input-right-button.tsx +0 -2
- package/src/layout.tsx +16 -11
- package/src/number-input/number-input.tsx +9 -5
- package/src/object-field.tsx +35 -13
- package/src/password-input/password-input.stories.tsx +23 -2
- package/src/password-input/password-input.tsx +6 -6
- package/src/pin-input/pin-input.tsx +1 -5
- package/src/radio/radio-input.stories.tsx +1 -1
- package/src/radio/radio-input.tsx +12 -10
- package/src/select/native-select.tsx +1 -4
- package/src/select/select-context.tsx +130 -0
- package/src/select/select.stories.tsx +116 -85
- package/src/select/select.test.tsx +1 -1
- package/src/select/select.tsx +162 -146
- package/src/step-form.tsx +76 -76
- package/src/submit-button.tsx +5 -1
- package/src/types.ts +149 -0
- package/src/use-array-field.tsx +9 -3
- package/src/use-step-form.tsx +54 -9
- package/src/utils.ts +23 -1
- package/src/watch-field.tsx +2 -6
- /package/src/radio/{radio.test.tsx → radio-input.test.tsx} +0 -0
package/dist/zod/index.js
CHANGED
@@ -75,16 +75,36 @@ var zodParseMeta = (meta) => {
|
|
75
75
|
}
|
76
76
|
};
|
77
77
|
var createZodForm = (options) => {
|
78
|
-
|
78
|
+
const ZodForm = forms.createForm({
|
79
79
|
resolver: (schema) => zod.zodResolver(schema, options == null ? void 0 : options.schemaOptions, options == null ? void 0 : options.resolverOptions),
|
80
|
+
fieldResolver: zodFieldResolver,
|
80
81
|
...options
|
81
82
|
});
|
83
|
+
ZodForm.displayName = "ZodForm";
|
84
|
+
ZodForm.id = "ZodForm";
|
85
|
+
return ZodForm;
|
82
86
|
};
|
87
|
+
var createZodStepForm = (options) => {
|
88
|
+
const ZodStepForm = forms.createStepForm({
|
89
|
+
resolver: (schema) => zod.zodResolver(schema, options == null ? void 0 : options.schemaOptions, options == null ? void 0 : options.resolverOptions),
|
90
|
+
fieldResolver: zodFieldResolver,
|
91
|
+
...options
|
92
|
+
});
|
93
|
+
ZodStepForm.displayName = "ZodStepForm";
|
94
|
+
ZodStepForm.id = "ZodStepForm";
|
95
|
+
return ZodStepForm;
|
96
|
+
};
|
97
|
+
|
98
|
+
// zod/src/index.ts
|
99
|
+
var Form = createZodForm();
|
100
|
+
var StepForm = createZodStepForm();
|
83
101
|
|
84
102
|
Object.defineProperty(exports, 'zodResolver', {
|
85
103
|
enumerable: true,
|
86
104
|
get: function () { return zod.zodResolver; }
|
87
105
|
});
|
106
|
+
exports.Form = Form;
|
107
|
+
exports.StepForm = StepForm;
|
88
108
|
exports.createZodForm = createZodForm;
|
89
109
|
exports.getFieldsFromSchema = getFieldsFromSchema;
|
90
110
|
exports.getNestedSchema = getNestedSchema;
|
package/dist/zod/index.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../zod/src/zod-resolver.ts","../../zod/src/create-zod-form.ts"],"names":[],"mappings":";AACA,SAAS,mBAAmB;AAC5B,SAAS,WAAW;AAUpB,IAAM,UAAU,CAAC,UAAwB;AACvC,UAAQ,MAAM,KAAK,UAAU;AAAA,IAC3B,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL;AACE,aAAO;AAAA,EACX;AACF;AAEA,IAAM,iBAAiB,CAAC,OAAY,SAAiB;AA5BrD;AA6BE,UAAO,WAAM,KAAK,
|
1
|
+
{"version":3,"sources":["../../zod/src/zod-resolver.ts","../../zod/src/create-zod-form.ts","../../zod/src/create-zod-step-form.ts","../../zod/src/index.ts"],"names":[],"mappings":";AACA,SAAS,mBAAmB;AAC5B,SAAS,WAAW;AAUpB,IAAM,UAAU,CAAC,UAAwB;AACvC,UAAQ,MAAM,KAAK,UAAU;AAAA,IAC3B,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL;AACE,aAAO;AAAA,EACX;AACF;AAEA,IAAM,iBAAiB,CAAC,OAAY,SAAiB;AA5BrD;AA6BE,UAAO,WAAM,KAAK,IAAI,MAAf,mBAAkB;AAC3B;AAQO,IAAM,sBAAsB,CAAC,WAAuC;AACzE,QAAM,SAAuB,CAAC;AAE9B,MAAI,eAAoC,CAAC;AACzC,MAAI,OAAO,KAAK,aAAa,YAAY;AACvC,mBAAe,OAAO,KAAK,KAAK;AAAA,EAClC,WAAW,OAAO,KAAK,aAAa,aAAa;AAC/C,mBAAe,OAAO,KAAK,MAAM;AAAA,EACnC,OAAO;AACL,WAAO;AAAA,EACT;AAEA,aAAW,QAAQ,cAAc;AAC/B,UAAM,QAAQ,aAAa,IAAI;AAE/B,UAAM,UAAmB,CAAC;AAC1B,QAAI,MAAM,KAAK,aAAa,YAAY;AACtC,cAAQ,MAAM,eAAe,OAAO,WAAW;AAC/C,cAAQ,MAAM,eAAe,OAAO,WAAW;AAAA,IACjD;AAEA,UAAM,OAAO,MAAM,eAAe,aAAa,MAAM,WAAW;AAEhE,WAAO,KAAK;AAAA,MACV;AAAA,MACA,QAAO,6BAAM,UAAS,MAAM,eAAe;AAAA,MAC3C,OAAM,6BAAM,SAAQ,QAAQ,KAAK;AAAA,MACjC,GAAG;AAAA,IACL,CAAC;AAAA,EACH;AACA,SAAO;AACT;AAEO,IAAM,kBAAkB,CAAC,QAAsB,SAAiB;AACrE,SAAO,IAAI,OAAO,KAAK,MAAM,GAAG,IAAI;AACtC;AAEO,IAAM,mBAAmB,CAAyB,WAAc;AACrE,SAAO;AAAA,IACL,YAAY;AACV,aAAO,oBAAoB,MAAM;AAAA,IACnC;AAAA,IACA,gBAAgB,MAAc;AAC5B,aAAO,oBAAoB,gBAAgB,QAAQ,IAAI,CAAC;AAAA,IAC1D;AAAA,EACF;AACF;AAOO,IAAM,UAAU,CAAC,SAAkB;AACxC,SAAO,KAAK,UAAU,IAAI;AAC5B;AAEO,IAAM,eAAe,CAAC,SAAiB;AAC5C,MAAI;AACF,WAAO,KAAK,MAAM,IAAI;AAAA,EACxB,SAAS,GAAP;AACA,WAAO;AAAA,EACT;AACF;;;ACrGA;AAAA,EACE;AAAA,OAKK;AAkCA,IAAM,gBAAgB,CAC3B,YACG;AACH,QAAM,UAAU,WAAW;AAAA,IACzB,UAAU,CAAC,WACT,YAAY,QAAQ,mCAAS,eAAe,mCAAS,eAAe;AAAA,IACtE,eAAe;AAAA,IACf,GAAG;AAAA,EACL,CAAC;AAED,UAAQ,cAAc;AACtB,UAAQ,KAAK;AAEb,SAAO;AACT;;;ACtDA;AAAA,EAEE;AAAA,OAGK;AA6CA,IAAM,oBAAoB,CAC/B,YACG;AACH,QAAM,cAAc,eAAmC;AAAA,IACrD,UAAU,CAAC,WACT,YAAY,QAAQ,mCAAS,eAAe,mCAAS,eAAe;AAAA,IACtE,eAAe;AAAA,IACf,GAAG;AAAA,EACL,CAAC;AAED,cAAY,cAAc;AAC1B,cAAY,KAAK;AAEjB,SAAO;AACT;;;AClDO,IAAM,OAAO,cAAc;AAE3B,IAAM,WAAW,kBAAkB","sourcesContent":["import * as z from 'zod'\nimport { zodResolver } from '@hookform/resolvers/zod'\nimport { get } from '@chakra-ui/utils'\nimport { FieldProps } from '@saas-ui/forms'\n\nexport { zodResolver }\n\nexport type Options = {\n min?: number\n max?: number\n}\n\nconst getType = (field: z.ZodTypeAny) => {\n switch (field._def.typeName) {\n case 'ZodArray':\n return 'array'\n case 'ZodObject':\n return 'object'\n case 'ZodNumber':\n return 'number'\n case 'ZodDate':\n return 'date'\n case 'ZodString':\n default:\n return 'text'\n }\n}\n\nconst getArrayOption = (field: any, name: string) => {\n return field._def[name]?.value\n}\n\n/**\n * A helper function to render forms automatically based on a Yup schema\n *\n * @param schema The Yup schema\n * @returns {FieldProps[]}\n */\nexport const getFieldsFromSchema = (schema: z.ZodTypeAny): FieldProps[] => {\n const fields: FieldProps[] = []\n\n let schemaFields: Record<string, any> = {}\n if (schema._def.typeName === 'ZodArray') {\n schemaFields = schema._def.type.shape\n } else if (schema._def.typeName === 'ZodObject') {\n schemaFields = schema._def.shape()\n } else {\n return fields\n }\n\n for (const name in schemaFields) {\n const field = schemaFields[name]\n\n const options: Options = {}\n if (field._def.typeName === 'ZodArray') {\n options.min = getArrayOption(field, 'minLength')\n options.max = getArrayOption(field, 'maxLength')\n }\n\n const meta = field.description && zodParseMeta(field.description)\n\n fields.push({\n name,\n label: meta?.label || field.description || name,\n type: meta?.type || getType(field),\n ...options,\n })\n }\n return fields\n}\n\nexport const getNestedSchema = (schema: z.ZodTypeAny, path: string) => {\n return get(schema._def.shape(), path)\n}\n\nexport const zodFieldResolver = <T extends z.ZodTypeAny>(schema: T) => {\n return {\n getFields() {\n return getFieldsFromSchema(schema)\n },\n getNestedFields(name: string) {\n return getFieldsFromSchema(getNestedSchema(schema, name))\n },\n }\n}\n\nexport interface ZodMeta {\n label: string\n type?: string\n}\n\nexport const zodMeta = (meta: ZodMeta) => {\n return JSON.stringify(meta)\n}\n\nexport const zodParseMeta = (meta: string) => {\n try {\n return JSON.parse(meta)\n } catch (e) {\n return meta\n }\n}\n","import {\n createForm,\n CreateFormProps,\n WithFields,\n FormProps,\n FieldValues,\n} from '@saas-ui/forms'\nimport { zodFieldResolver, zodResolver } from './zod-resolver'\nimport { z } from 'zod'\n\ntype ResolverArgs = Parameters<typeof zodResolver>\n\nexport interface CreateZodFormProps<FieldDefs>\n extends CreateFormProps<FieldDefs> {\n schemaOptions?: ResolverArgs[1]\n resolverOptions?: ResolverArgs[2]\n}\n\nexport type ZodFormType<\n FieldDefs,\n ExtraProps = object,\n ExtraOverrides = object,\n Type extends 'zod' = 'zod'\n> = (<\n TSchema extends z.AnyZodObject = z.AnyZodObject,\n TFieldValues extends z.infer<TSchema> = z.infer<TSchema>,\n TContext extends object = object\n>(\n props: WithFields<\n FormProps<TSchema, TFieldValues, TContext>,\n FieldDefs,\n ExtraOverrides\n > & {\n ref?: React.ForwardedRef<HTMLFormElement>\n } & ExtraProps\n) => React.ReactElement) & {\n displayName?: string\n id?: string\n}\n\nexport const createZodForm = <FieldDefs>(\n options?: CreateZodFormProps<FieldDefs>\n) => {\n const ZodForm = createForm({\n resolver: (schema: any) =>\n zodResolver(schema, options?.schemaOptions, options?.resolverOptions),\n fieldResolver: zodFieldResolver,\n ...options,\n })\n\n ZodForm.displayName = 'ZodForm'\n ZodForm.id = 'ZodForm'\n\n return ZodForm as ZodFormType<FieldDefs>\n}\n","import {\n CreateFormProps,\n createStepForm,\n StepsOptions,\n UseStepFormProps,\n} from '@saas-ui/forms'\nimport { zodFieldResolver, zodResolver } from './zod-resolver'\nimport { AnyZodObject, z } from 'zod'\nimport React from 'react'\n\ntype ResolverArgs = Parameters<typeof zodResolver>\n\nexport interface CreateZodFormProps<FieldDefs>\n extends CreateFormProps<FieldDefs> {\n schemaOptions?: ResolverArgs[1]\n resolverOptions?: ResolverArgs[2]\n}\n\ntype InferStepType<T extends Required<StepsOptions<AnyZodObject>>> = T extends [\n infer Step,\n ...infer Rest\n]\n ? Step extends { schema: AnyZodObject }\n ? z.infer<Step['schema']> &\n (Rest extends Required<StepsOptions<AnyZodObject>>\n ? InferStepType<Rest>\n : object)\n : object\n : object\n\ntype ZodStepFormType<\n FieldDefs,\n ExtraProps = object,\n ExtraOverrides = object\n> = (<\n TSteps extends Required<StepsOptions<AnyZodObject>> = Required<\n StepsOptions<AnyZodObject>\n >,\n TFieldValues extends InferStepType<TSteps> = InferStepType<TSteps>,\n TContext extends object = object\n>(\n props: UseStepFormProps<TSteps, TFieldValues, TContext> & {\n steps: TSteps\n ref?: React.ForwardedRef<HTMLFormElement>\n }\n) => React.ReactElement) & {\n displayName?: string\n id?: string\n}\n\nexport const createZodStepForm = <FieldDefs>(\n options?: CreateZodFormProps<FieldDefs>\n) => {\n const ZodStepForm = createStepForm<any, any, any, any>({\n resolver: (schema: any) =>\n zodResolver(schema, options?.schemaOptions, options?.resolverOptions),\n fieldResolver: zodFieldResolver,\n ...options,\n })\n\n ZodStepForm.displayName = 'ZodStepForm'\n ZodStepForm.id = 'ZodStepForm'\n\n return ZodStepForm as ZodStepFormType<FieldDefs>\n}\n","export {\n zodResolver,\n getFieldsFromSchema,\n getNestedSchema,\n zodFieldResolver,\n zodMeta,\n zodParseMeta,\n} from './zod-resolver'\nexport type { Options, ZodMeta } from './zod-resolver'\nexport { createZodForm, type ZodFormType } from './create-zod-form'\n\nimport { createZodForm } from './create-zod-form'\nimport { createZodStepForm } from './create-zod-step-form'\n\nexport const Form = createZodForm()\n\nexport const StepForm = createZodStepForm()\n"]}
|
package/dist/zod/index.mjs
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
import { zodResolver } from '@hookform/resolvers/zod';
|
2
2
|
export { zodResolver } from '@hookform/resolvers/zod';
|
3
3
|
import { get } from '@chakra-ui/utils';
|
4
|
-
import { createForm } from '@saas-ui/forms';
|
4
|
+
import { createForm, createStepForm } from '@saas-ui/forms';
|
5
5
|
|
6
6
|
// zod/src/zod-resolver.ts
|
7
7
|
var getType = (field) => {
|
@@ -74,12 +74,30 @@ var zodParseMeta = (meta) => {
|
|
74
74
|
}
|
75
75
|
};
|
76
76
|
var createZodForm = (options) => {
|
77
|
-
|
77
|
+
const ZodForm = createForm({
|
78
78
|
resolver: (schema) => zodResolver(schema, options == null ? void 0 : options.schemaOptions, options == null ? void 0 : options.resolverOptions),
|
79
|
+
fieldResolver: zodFieldResolver,
|
79
80
|
...options
|
80
81
|
});
|
82
|
+
ZodForm.displayName = "ZodForm";
|
83
|
+
ZodForm.id = "ZodForm";
|
84
|
+
return ZodForm;
|
81
85
|
};
|
86
|
+
var createZodStepForm = (options) => {
|
87
|
+
const ZodStepForm = createStepForm({
|
88
|
+
resolver: (schema) => zodResolver(schema, options == null ? void 0 : options.schemaOptions, options == null ? void 0 : options.resolverOptions),
|
89
|
+
fieldResolver: zodFieldResolver,
|
90
|
+
...options
|
91
|
+
});
|
92
|
+
ZodStepForm.displayName = "ZodStepForm";
|
93
|
+
ZodStepForm.id = "ZodStepForm";
|
94
|
+
return ZodStepForm;
|
95
|
+
};
|
96
|
+
|
97
|
+
// zod/src/index.ts
|
98
|
+
var Form = createZodForm();
|
99
|
+
var StepForm = createZodStepForm();
|
82
100
|
|
83
|
-
export { createZodForm, getFieldsFromSchema, getNestedSchema, zodFieldResolver, zodMeta, zodParseMeta };
|
101
|
+
export { Form, StepForm, createZodForm, getFieldsFromSchema, getNestedSchema, zodFieldResolver, zodMeta, zodParseMeta };
|
84
102
|
//# sourceMappingURL=out.js.map
|
85
103
|
//# sourceMappingURL=index.mjs.map
|
package/dist/zod/index.mjs.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../zod/src/zod-resolver.ts","../../zod/src/create-zod-form.ts"],"names":[],"mappings":";AACA,SAAS,mBAAmB;AAC5B,SAAS,WAAW;AAUpB,IAAM,UAAU,CAAC,UAAwB;AACvC,UAAQ,MAAM,KAAK,UAAU;AAAA,IAC3B,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL;AACE,aAAO;AAAA,EACX;AACF;AAEA,IAAM,iBAAiB,CAAC,OAAY,SAAiB;AA5BrD;AA6BE,UAAO,WAAM,KAAK,
|
1
|
+
{"version":3,"sources":["../../zod/src/zod-resolver.ts","../../zod/src/create-zod-form.ts","../../zod/src/create-zod-step-form.ts","../../zod/src/index.ts"],"names":[],"mappings":";AACA,SAAS,mBAAmB;AAC5B,SAAS,WAAW;AAUpB,IAAM,UAAU,CAAC,UAAwB;AACvC,UAAQ,MAAM,KAAK,UAAU;AAAA,IAC3B,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL;AACE,aAAO;AAAA,EACX;AACF;AAEA,IAAM,iBAAiB,CAAC,OAAY,SAAiB;AA5BrD;AA6BE,UAAO,WAAM,KAAK,IAAI,MAAf,mBAAkB;AAC3B;AAQO,IAAM,sBAAsB,CAAC,WAAuC;AACzE,QAAM,SAAuB,CAAC;AAE9B,MAAI,eAAoC,CAAC;AACzC,MAAI,OAAO,KAAK,aAAa,YAAY;AACvC,mBAAe,OAAO,KAAK,KAAK;AAAA,EAClC,WAAW,OAAO,KAAK,aAAa,aAAa;AAC/C,mBAAe,OAAO,KAAK,MAAM;AAAA,EACnC,OAAO;AACL,WAAO;AAAA,EACT;AAEA,aAAW,QAAQ,cAAc;AAC/B,UAAM,QAAQ,aAAa,IAAI;AAE/B,UAAM,UAAmB,CAAC;AAC1B,QAAI,MAAM,KAAK,aAAa,YAAY;AACtC,cAAQ,MAAM,eAAe,OAAO,WAAW;AAC/C,cAAQ,MAAM,eAAe,OAAO,WAAW;AAAA,IACjD;AAEA,UAAM,OAAO,MAAM,eAAe,aAAa,MAAM,WAAW;AAEhE,WAAO,KAAK;AAAA,MACV;AAAA,MACA,QAAO,6BAAM,UAAS,MAAM,eAAe;AAAA,MAC3C,OAAM,6BAAM,SAAQ,QAAQ,KAAK;AAAA,MACjC,GAAG;AAAA,IACL,CAAC;AAAA,EACH;AACA,SAAO;AACT;AAEO,IAAM,kBAAkB,CAAC,QAAsB,SAAiB;AACrE,SAAO,IAAI,OAAO,KAAK,MAAM,GAAG,IAAI;AACtC;AAEO,IAAM,mBAAmB,CAAyB,WAAc;AACrE,SAAO;AAAA,IACL,YAAY;AACV,aAAO,oBAAoB,MAAM;AAAA,IACnC;AAAA,IACA,gBAAgB,MAAc;AAC5B,aAAO,oBAAoB,gBAAgB,QAAQ,IAAI,CAAC;AAAA,IAC1D;AAAA,EACF;AACF;AAOO,IAAM,UAAU,CAAC,SAAkB;AACxC,SAAO,KAAK,UAAU,IAAI;AAC5B;AAEO,IAAM,eAAe,CAAC,SAAiB;AAC5C,MAAI;AACF,WAAO,KAAK,MAAM,IAAI;AAAA,EACxB,SAAS,GAAP;AACA,WAAO;AAAA,EACT;AACF;;;ACrGA;AAAA,EACE;AAAA,OAKK;AAkCA,IAAM,gBAAgB,CAC3B,YACG;AACH,QAAM,UAAU,WAAW;AAAA,IACzB,UAAU,CAAC,WACT,YAAY,QAAQ,mCAAS,eAAe,mCAAS,eAAe;AAAA,IACtE,eAAe;AAAA,IACf,GAAG;AAAA,EACL,CAAC;AAED,UAAQ,cAAc;AACtB,UAAQ,KAAK;AAEb,SAAO;AACT;;;ACtDA;AAAA,EAEE;AAAA,OAGK;AA6CA,IAAM,oBAAoB,CAC/B,YACG;AACH,QAAM,cAAc,eAAmC;AAAA,IACrD,UAAU,CAAC,WACT,YAAY,QAAQ,mCAAS,eAAe,mCAAS,eAAe;AAAA,IACtE,eAAe;AAAA,IACf,GAAG;AAAA,EACL,CAAC;AAED,cAAY,cAAc;AAC1B,cAAY,KAAK;AAEjB,SAAO;AACT;;;AClDO,IAAM,OAAO,cAAc;AAE3B,IAAM,WAAW,kBAAkB","sourcesContent":["import * as z from 'zod'\nimport { zodResolver } from '@hookform/resolvers/zod'\nimport { get } from '@chakra-ui/utils'\nimport { FieldProps } from '@saas-ui/forms'\n\nexport { zodResolver }\n\nexport type Options = {\n min?: number\n max?: number\n}\n\nconst getType = (field: z.ZodTypeAny) => {\n switch (field._def.typeName) {\n case 'ZodArray':\n return 'array'\n case 'ZodObject':\n return 'object'\n case 'ZodNumber':\n return 'number'\n case 'ZodDate':\n return 'date'\n case 'ZodString':\n default:\n return 'text'\n }\n}\n\nconst getArrayOption = (field: any, name: string) => {\n return field._def[name]?.value\n}\n\n/**\n * A helper function to render forms automatically based on a Yup schema\n *\n * @param schema The Yup schema\n * @returns {FieldProps[]}\n */\nexport const getFieldsFromSchema = (schema: z.ZodTypeAny): FieldProps[] => {\n const fields: FieldProps[] = []\n\n let schemaFields: Record<string, any> = {}\n if (schema._def.typeName === 'ZodArray') {\n schemaFields = schema._def.type.shape\n } else if (schema._def.typeName === 'ZodObject') {\n schemaFields = schema._def.shape()\n } else {\n return fields\n }\n\n for (const name in schemaFields) {\n const field = schemaFields[name]\n\n const options: Options = {}\n if (field._def.typeName === 'ZodArray') {\n options.min = getArrayOption(field, 'minLength')\n options.max = getArrayOption(field, 'maxLength')\n }\n\n const meta = field.description && zodParseMeta(field.description)\n\n fields.push({\n name,\n label: meta?.label || field.description || name,\n type: meta?.type || getType(field),\n ...options,\n })\n }\n return fields\n}\n\nexport const getNestedSchema = (schema: z.ZodTypeAny, path: string) => {\n return get(schema._def.shape(), path)\n}\n\nexport const zodFieldResolver = <T extends z.ZodTypeAny>(schema: T) => {\n return {\n getFields() {\n return getFieldsFromSchema(schema)\n },\n getNestedFields(name: string) {\n return getFieldsFromSchema(getNestedSchema(schema, name))\n },\n }\n}\n\nexport interface ZodMeta {\n label: string\n type?: string\n}\n\nexport const zodMeta = (meta: ZodMeta) => {\n return JSON.stringify(meta)\n}\n\nexport const zodParseMeta = (meta: string) => {\n try {\n return JSON.parse(meta)\n } catch (e) {\n return meta\n }\n}\n","import {\n createForm,\n CreateFormProps,\n WithFields,\n FormProps,\n FieldValues,\n} from '@saas-ui/forms'\nimport { zodFieldResolver, zodResolver } from './zod-resolver'\nimport { z } from 'zod'\n\ntype ResolverArgs = Parameters<typeof zodResolver>\n\nexport interface CreateZodFormProps<FieldDefs>\n extends CreateFormProps<FieldDefs> {\n schemaOptions?: ResolverArgs[1]\n resolverOptions?: ResolverArgs[2]\n}\n\nexport type ZodFormType<\n FieldDefs,\n ExtraProps = object,\n ExtraOverrides = object,\n Type extends 'zod' = 'zod'\n> = (<\n TSchema extends z.AnyZodObject = z.AnyZodObject,\n TFieldValues extends z.infer<TSchema> = z.infer<TSchema>,\n TContext extends object = object\n>(\n props: WithFields<\n FormProps<TSchema, TFieldValues, TContext>,\n FieldDefs,\n ExtraOverrides\n > & {\n ref?: React.ForwardedRef<HTMLFormElement>\n } & ExtraProps\n) => React.ReactElement) & {\n displayName?: string\n id?: string\n}\n\nexport const createZodForm = <FieldDefs>(\n options?: CreateZodFormProps<FieldDefs>\n) => {\n const ZodForm = createForm({\n resolver: (schema: any) =>\n zodResolver(schema, options?.schemaOptions, options?.resolverOptions),\n fieldResolver: zodFieldResolver,\n ...options,\n })\n\n ZodForm.displayName = 'ZodForm'\n ZodForm.id = 'ZodForm'\n\n return ZodForm as ZodFormType<FieldDefs>\n}\n","import {\n CreateFormProps,\n createStepForm,\n StepsOptions,\n UseStepFormProps,\n} from '@saas-ui/forms'\nimport { zodFieldResolver, zodResolver } from './zod-resolver'\nimport { AnyZodObject, z } from 'zod'\nimport React from 'react'\n\ntype ResolverArgs = Parameters<typeof zodResolver>\n\nexport interface CreateZodFormProps<FieldDefs>\n extends CreateFormProps<FieldDefs> {\n schemaOptions?: ResolverArgs[1]\n resolverOptions?: ResolverArgs[2]\n}\n\ntype InferStepType<T extends Required<StepsOptions<AnyZodObject>>> = T extends [\n infer Step,\n ...infer Rest\n]\n ? Step extends { schema: AnyZodObject }\n ? z.infer<Step['schema']> &\n (Rest extends Required<StepsOptions<AnyZodObject>>\n ? InferStepType<Rest>\n : object)\n : object\n : object\n\ntype ZodStepFormType<\n FieldDefs,\n ExtraProps = object,\n ExtraOverrides = object\n> = (<\n TSteps extends Required<StepsOptions<AnyZodObject>> = Required<\n StepsOptions<AnyZodObject>\n >,\n TFieldValues extends InferStepType<TSteps> = InferStepType<TSteps>,\n TContext extends object = object\n>(\n props: UseStepFormProps<TSteps, TFieldValues, TContext> & {\n steps: TSteps\n ref?: React.ForwardedRef<HTMLFormElement>\n }\n) => React.ReactElement) & {\n displayName?: string\n id?: string\n}\n\nexport const createZodStepForm = <FieldDefs>(\n options?: CreateZodFormProps<FieldDefs>\n) => {\n const ZodStepForm = createStepForm<any, any, any, any>({\n resolver: (schema: any) =>\n zodResolver(schema, options?.schemaOptions, options?.resolverOptions),\n fieldResolver: zodFieldResolver,\n ...options,\n })\n\n ZodStepForm.displayName = 'ZodStepForm'\n ZodStepForm.id = 'ZodStepForm'\n\n return ZodStepForm as ZodStepFormType<FieldDefs>\n}\n","export {\n zodResolver,\n getFieldsFromSchema,\n getNestedSchema,\n zodFieldResolver,\n zodMeta,\n zodParseMeta,\n} from './zod-resolver'\nexport type { Options, ZodMeta } from './zod-resolver'\nexport { createZodForm, type ZodFormType } from './create-zod-form'\n\nimport { createZodForm } from './create-zod-form'\nimport { createZodStepForm } from './create-zod-step-form'\n\nexport const Form = createZodForm()\n\nexport const StepForm = createZodStepForm()\n"]}
|
package/package.json
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
{
|
2
2
|
"name": "@saas-ui/forms",
|
3
|
-
"version": "2.0.0-next.
|
3
|
+
"version": "2.0.0-next.21",
|
4
4
|
"description": "Fully functional forms for Chakra UI.",
|
5
5
|
"source": "src/index.ts",
|
6
6
|
"exports": {
|
7
7
|
".": {
|
8
8
|
"require": "./dist/index.js",
|
9
|
+
"types": "./dist/index.d.ts",
|
9
10
|
"import": "./dist/index.mjs"
|
10
11
|
},
|
11
12
|
"./src": {
|
@@ -13,6 +14,7 @@
|
|
13
14
|
},
|
14
15
|
"./yup": {
|
15
16
|
"require": "./dist/yup/index.js",
|
17
|
+
"types": "./dist/yup/index.d.ts",
|
16
18
|
"import": "./dist/yup/index.mjs"
|
17
19
|
},
|
18
20
|
"./yup/src": {
|
@@ -20,6 +22,7 @@
|
|
20
22
|
},
|
21
23
|
"./zod": {
|
22
24
|
"require": "./dist/zod/index.js",
|
25
|
+
"types": "./dist/zod/index.d.ts",
|
23
26
|
"import": "./dist/zod/index.mjs"
|
24
27
|
},
|
25
28
|
"./zod/src": {
|
@@ -27,12 +30,26 @@
|
|
27
30
|
},
|
28
31
|
"./ajv": {
|
29
32
|
"require": "./dist/ajv/index.js",
|
33
|
+
"types": "./dist/ajv/index.d.ts",
|
30
34
|
"import": "./dist/ajv/index.mjs"
|
31
35
|
},
|
32
36
|
"./ajv/src": {
|
33
37
|
"default": "./ajv/src/index.ts"
|
34
38
|
}
|
35
39
|
},
|
40
|
+
"typesVersions": {
|
41
|
+
"*": {
|
42
|
+
"ajv": [
|
43
|
+
"./dist/ajv/index.d.ts"
|
44
|
+
],
|
45
|
+
"yup": [
|
46
|
+
"./dist/yup/index.d.ts"
|
47
|
+
],
|
48
|
+
"zod": [
|
49
|
+
"./dist/zod/index.d.ts"
|
50
|
+
]
|
51
|
+
}
|
52
|
+
},
|
36
53
|
"main": "./dist/index.js",
|
37
54
|
"module": "./dist/index.mjs",
|
38
55
|
"types": "./dist/index.d.ts",
|
@@ -45,7 +62,8 @@
|
|
45
62
|
"build:ajv": "tsup ajv/src/index.ts --config ajv/tsup.config.ts",
|
46
63
|
"lint": "eslint src --ext .ts,.tsx,.js,.jsx --config ../../.eslintrc.js",
|
47
64
|
"lint:staged": "lint-staged --allow-empty --config ../../lint-staged.config.js",
|
48
|
-
"typecheck": "tsc --noEmit"
|
65
|
+
"typecheck": "tsc --noEmit",
|
66
|
+
"tsd": "tsd"
|
49
67
|
},
|
50
68
|
"files": [
|
51
69
|
"dist",
|
@@ -83,11 +101,11 @@
|
|
83
101
|
"url": "https://storybook.saas-ui.dev"
|
84
102
|
},
|
85
103
|
"dependencies": {
|
86
|
-
"@chakra-ui/
|
87
|
-
"@chakra-ui/
|
88
|
-
"@
|
89
|
-
"@saas-ui/core": "2.0.0-next.
|
90
|
-
"react-hook-form": "^7.43.
|
104
|
+
"@chakra-ui/react-utils": "^2.0.12",
|
105
|
+
"@chakra-ui/utils": "^2.0.15",
|
106
|
+
"@hookform/resolvers": "^3.1.0",
|
107
|
+
"@saas-ui/core": "2.0.0-next.18",
|
108
|
+
"react-hook-form": "^7.43.9"
|
91
109
|
},
|
92
110
|
"peerDependencies": {
|
93
111
|
"@chakra-ui/react": ">=2.4.9",
|
@@ -98,10 +116,15 @@
|
|
98
116
|
"react-dom": ">=18.0.0"
|
99
117
|
},
|
100
118
|
"devDependencies": {
|
101
|
-
"@hookform/resolvers": "^2.9.3",
|
102
119
|
"@types/json-schema": "^7.0.11",
|
103
120
|
"ajv": "^8.12.0",
|
104
|
-
"
|
105
|
-
"
|
121
|
+
"ajv-errors": "^3.0.0",
|
122
|
+
"json-schema-to-ts": "^2.8.2",
|
123
|
+
"tsd": "^0.28.1",
|
124
|
+
"yup": "^1.1.1",
|
125
|
+
"zod": "^3.21.4"
|
126
|
+
},
|
127
|
+
"tsd": {
|
128
|
+
"directory": "tests"
|
106
129
|
}
|
107
130
|
}
|
package/src/array-field.tsx
CHANGED
@@ -7,11 +7,11 @@ import {
|
|
7
7
|
Button,
|
8
8
|
ButtonProps,
|
9
9
|
} from '@chakra-ui/react'
|
10
|
-
import {
|
11
|
-
import { AddIcon, MinusIcon } from '@chakra-ui/icons'
|
10
|
+
import { PlusIcon, MinusIcon } from '@saas-ui/core/icons'
|
12
11
|
|
13
12
|
import { FormLayout, FormLayoutProps } from './layout'
|
14
|
-
import { BaseField
|
13
|
+
import { BaseField } from './base-field'
|
14
|
+
import { BaseFieldProps } from './types'
|
15
15
|
|
16
16
|
import { mapNestedFields } from './utils'
|
17
17
|
|
@@ -27,6 +27,10 @@ import {
|
|
27
27
|
useArrayFieldAddButton,
|
28
28
|
UseArrayFieldReturn,
|
29
29
|
} from './use-array-field'
|
30
|
+
import { FieldPath, FieldValues } from 'react-hook-form'
|
31
|
+
import { isFunction } from '@chakra-ui/utils'
|
32
|
+
import { MaybeRenderProp } from '@chakra-ui/react-utils'
|
33
|
+
import { useFieldProps } from './form-context'
|
30
34
|
|
31
35
|
export interface ArrayFieldButtonProps extends ButtonProps {}
|
32
36
|
|
@@ -53,7 +57,11 @@ interface ArrayFieldRowProps extends FormLayoutProps {
|
|
53
57
|
*/
|
54
58
|
children: React.ReactNode
|
55
59
|
}
|
56
|
-
|
60
|
+
/**
|
61
|
+
* Render prop component, to get access to the internal fields state. Must be a child of ArrayFieldContainer.
|
62
|
+
*
|
63
|
+
* @see Docs https://saas-ui.dev/docs/components/forms/array-field
|
64
|
+
*/
|
57
65
|
export const ArrayFieldRow: React.FC<ArrayFieldRowProps> = ({
|
58
66
|
children,
|
59
67
|
index,
|
@@ -67,9 +75,7 @@ export const ArrayFieldRow: React.FC<ArrayFieldRowProps> = ({
|
|
67
75
|
)
|
68
76
|
}
|
69
77
|
|
70
|
-
|
71
|
-
ArrayFieldRow.displayName = 'ArrayFieldRow'
|
72
|
-
}
|
78
|
+
ArrayFieldRow.displayName = 'ArrayFieldRow'
|
73
79
|
|
74
80
|
export interface ArrayFieldRowFieldsProps extends FormLayoutProps {
|
75
81
|
/**
|
@@ -85,7 +91,11 @@ export interface ArrayFieldRowFieldsProps extends FormLayoutProps {
|
|
85
91
|
*/
|
86
92
|
children: React.ReactNode
|
87
93
|
}
|
88
|
-
|
94
|
+
/**
|
95
|
+
* Add the name prefix to the fields and acts as a horizontal form layout by default.
|
96
|
+
*
|
97
|
+
* @see Docs https://saas-ui.dev/docs/components/forms/array-field
|
98
|
+
*/
|
89
99
|
export const ArrayFieldRowFields: React.FC<ArrayFieldRowFieldsProps> = ({
|
90
100
|
children,
|
91
101
|
...layoutProps
|
@@ -98,13 +108,17 @@ export const ArrayFieldRowFields: React.FC<ArrayFieldRowFieldsProps> = ({
|
|
98
108
|
)
|
99
109
|
}
|
100
110
|
|
101
|
-
|
102
|
-
ArrayFieldRowFields.displayName = 'ArrayFieldRowFields'
|
103
|
-
}
|
111
|
+
ArrayFieldRowFields.displayName = 'ArrayFieldRowFields'
|
104
112
|
|
113
|
+
/**
|
114
|
+
* The row container component providers row context.
|
115
|
+
*
|
116
|
+
* @see Docs https://saas-ui.dev/docs/components/forms/array-field
|
117
|
+
*/
|
105
118
|
export const ArrayFieldRowContainer: React.FC<ArrayFieldRowProps> = ({
|
106
119
|
children,
|
107
120
|
index,
|
121
|
+
...rest
|
108
122
|
}) => {
|
109
123
|
const context = useArrayFieldRow({ index })
|
110
124
|
|
@@ -118,15 +132,20 @@ export const ArrayFieldRowContainer: React.FC<ArrayFieldRowProps> = ({
|
|
118
132
|
|
119
133
|
return (
|
120
134
|
<ArrayFieldRowProvider value={context}>
|
121
|
-
<chakra.div __css={styles}>
|
135
|
+
<chakra.div {...rest} __css={styles}>
|
136
|
+
{children}
|
137
|
+
</chakra.div>
|
122
138
|
</ArrayFieldRowProvider>
|
123
139
|
)
|
124
140
|
}
|
125
141
|
|
126
|
-
|
127
|
-
ArrayFieldRowContainer.displayName = 'ArrayFieldRowContainer'
|
128
|
-
}
|
142
|
+
ArrayFieldRowContainer.displayName = 'ArrayFieldRowContainer'
|
129
143
|
|
144
|
+
/**
|
145
|
+
* The default remove button.
|
146
|
+
*
|
147
|
+
* @see Docs https://saas-ui.dev/docs/components/forms/array-field
|
148
|
+
*/
|
130
149
|
export const ArrayFieldRemoveButton: React.FC<ArrayFieldButtonProps> = (
|
131
150
|
props
|
132
151
|
) => {
|
@@ -137,10 +156,13 @@ export const ArrayFieldRemoveButton: React.FC<ArrayFieldButtonProps> = (
|
|
137
156
|
)
|
138
157
|
}
|
139
158
|
|
140
|
-
|
141
|
-
ArrayFieldRemoveButton.displayName = 'ArrayFieldRemoveButton'
|
142
|
-
}
|
159
|
+
ArrayFieldRemoveButton.displayName = 'ArrayFieldRemoveButton'
|
143
160
|
|
161
|
+
/**
|
162
|
+
* The default add button.
|
163
|
+
*
|
164
|
+
* @see Docs https://saas-ui.dev/docs/components/forms/array-field
|
165
|
+
*/
|
144
166
|
export const ArrayFieldAddButton: React.FC<ArrayFieldButtonProps> = (props) => {
|
145
167
|
return (
|
146
168
|
<Button
|
@@ -149,36 +171,48 @@ export const ArrayFieldAddButton: React.FC<ArrayFieldButtonProps> = (props) => {
|
|
149
171
|
{...useArrayFieldAddButton()}
|
150
172
|
{...props}
|
151
173
|
>
|
152
|
-
{props.children || <
|
174
|
+
{props.children || <PlusIcon />}
|
153
175
|
</Button>
|
154
176
|
)
|
155
177
|
}
|
156
178
|
|
157
|
-
|
158
|
-
ArrayFieldAddButton.displayName = 'ArrayFieldAddButton'
|
159
|
-
}
|
179
|
+
ArrayFieldAddButton.displayName = 'ArrayFieldAddButton'
|
160
180
|
|
161
|
-
export interface ArrayFieldProps
|
162
|
-
extends
|
163
|
-
|
181
|
+
export interface ArrayFieldProps<
|
182
|
+
TFieldValues extends FieldValues = FieldValues,
|
183
|
+
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>
|
184
|
+
> extends ArrayFieldOptions<TFieldValues, TName>,
|
185
|
+
Omit<
|
186
|
+
BaseFieldProps<TFieldValues, TName>,
|
187
|
+
'name' | 'defaultValue' | 'children'
|
188
|
+
> {
|
189
|
+
children: MaybeRenderProp<ArrayField[]>
|
190
|
+
}
|
164
191
|
|
192
|
+
/**
|
193
|
+
* The wrapper component that composes the default ArrayField functionality.
|
194
|
+
*
|
195
|
+
* @see Docs https://saas-ui.dev/docs/components/forms/array-field
|
196
|
+
*/
|
165
197
|
export const ArrayField = forwardRef(
|
166
198
|
(props: ArrayFieldProps, ref: React.ForwardedRef<UseArrayFieldReturn>) => {
|
167
199
|
const { children, ...containerProps } = props
|
168
200
|
|
201
|
+
const rowFn = isFunction(children)
|
202
|
+
? children
|
203
|
+
: (fields: ArrayField[]) => (
|
204
|
+
<>
|
205
|
+
{fields.map(({ id }, index: number) => (
|
206
|
+
<ArrayFieldRow key={id} index={index}>
|
207
|
+
{children}
|
208
|
+
</ArrayFieldRow>
|
209
|
+
)) || null}
|
210
|
+
</>
|
211
|
+
)
|
212
|
+
|
169
213
|
return (
|
170
214
|
<ArrayFieldContainer ref={ref} {...containerProps}>
|
171
|
-
<ArrayFieldRows>
|
172
|
-
{(fields: ArrayField[]) => (
|
173
|
-
<>
|
174
|
-
{fields.map(({ id }, index: number) => (
|
175
|
-
<ArrayFieldRow key={id} index={index}>
|
176
|
-
{children}
|
177
|
-
</ArrayFieldRow>
|
178
|
-
))}
|
179
|
-
</>
|
180
|
-
)}
|
181
|
-
</ArrayFieldRows>
|
215
|
+
<ArrayFieldRows>{rowFn as any}</ArrayFieldRows>
|
182
216
|
<ArrayFieldAddButton />
|
183
217
|
</ArrayFieldContainer>
|
184
218
|
)
|
@@ -191,9 +225,7 @@ export const ArrayField = forwardRef(
|
|
191
225
|
displayName: string
|
192
226
|
}
|
193
227
|
|
194
|
-
|
195
|
-
ArrayField.displayName = 'ArrayField'
|
196
|
-
}
|
228
|
+
ArrayField.displayName = 'ArrayField'
|
197
229
|
|
198
230
|
export interface ArrayFieldRowsProps {
|
199
231
|
children: (fields: ArrayField[]) => React.ReactElement | null
|
@@ -206,10 +238,18 @@ export const ArrayFieldRows = ({
|
|
206
238
|
return children(fields)
|
207
239
|
}
|
208
240
|
|
209
|
-
|
210
|
-
|
241
|
+
ArrayFieldRows.displayName = 'ArrayFieldRows'
|
242
|
+
|
243
|
+
export interface ArrayFieldContainerProps
|
244
|
+
extends Omit<ArrayFieldProps, 'children'> {
|
245
|
+
children: React.ReactNode
|
211
246
|
}
|
212
247
|
|
248
|
+
/**
|
249
|
+
* The container component provides context and state management.
|
250
|
+
*
|
251
|
+
* @see Docs https://saas-ui.dev/docs/components/forms/array-field
|
252
|
+
*/
|
213
253
|
export const ArrayFieldContainer = React.forwardRef(
|
214
254
|
(
|
215
255
|
{
|
@@ -220,15 +260,17 @@ export const ArrayFieldContainer = React.forwardRef(
|
|
220
260
|
max,
|
221
261
|
children,
|
222
262
|
...fieldProps
|
223
|
-
}:
|
263
|
+
}: ArrayFieldContainerProps,
|
224
264
|
ref: React.ForwardedRef<UseArrayFieldReturn>
|
225
265
|
) => {
|
266
|
+
const overrides = useFieldProps(name)
|
267
|
+
|
226
268
|
const context = useArrayField({
|
227
269
|
name,
|
228
270
|
defaultValue,
|
229
271
|
keyName,
|
230
|
-
min,
|
231
|
-
max,
|
272
|
+
min: min || (overrides as any)?.min,
|
273
|
+
max: max || (overrides as any)?.max,
|
232
274
|
})
|
233
275
|
|
234
276
|
// This exposes the useArrayField api through the forwarded ref
|
@@ -236,7 +278,7 @@ export const ArrayFieldContainer = React.forwardRef(
|
|
236
278
|
|
237
279
|
return (
|
238
280
|
<ArrayFieldProvider value={context}>
|
239
|
-
<BaseField name={name} {...fieldProps}>
|
281
|
+
<BaseField name={name} {...fieldProps} {...overrides}>
|
240
282
|
{children}
|
241
283
|
</BaseField>
|
242
284
|
</ArrayFieldProvider>
|
@@ -244,6 +286,4 @@ export const ArrayFieldContainer = React.forwardRef(
|
|
244
286
|
}
|
245
287
|
)
|
246
288
|
|
247
|
-
|
248
|
-
ArrayFieldContainer.displayName = 'ArrayFieldContainer'
|
249
|
-
}
|
289
|
+
ArrayFieldContainer.displayName = 'ArrayFieldContainer'
|
package/src/auto-form.tsx
CHANGED
@@ -4,7 +4,7 @@ import { forwardRef } from '@chakra-ui/react'
|
|
4
4
|
|
5
5
|
import { Form, FormProps } from './form'
|
6
6
|
import { FormLayout } from './layout'
|
7
|
-
import {
|
7
|
+
import { AutoFields } from './fields'
|
8
8
|
import { SubmitButton } from './submit-button'
|
9
9
|
|
10
10
|
interface AutoFormOptions {
|
@@ -32,7 +32,11 @@ export interface AutoFormProps<
|
|
32
32
|
AutoFormOptions {
|
33
33
|
children?: React.ReactNode
|
34
34
|
}
|
35
|
-
|
35
|
+
/**
|
36
|
+
* The wrapper component that manages context and state.
|
37
|
+
*
|
38
|
+
* @see Docs https://saas-ui.dev/docs/components/forms/auto-form
|
39
|
+
*/
|
36
40
|
export const AutoForm = forwardRef(
|
37
41
|
<
|
38
42
|
TFieldValues extends FieldValues = FieldValues,
|
@@ -52,7 +56,7 @@ export const AutoForm = forwardRef(
|
|
52
56
|
return (
|
53
57
|
<Form {...rest} schema={schema} ref={ref}>
|
54
58
|
<FormLayout>
|
55
|
-
{<
|
59
|
+
{<AutoFields schema={schema} fieldResolver={fieldResolver} />}
|
56
60
|
{submitLabel && <SubmitButton>{submitLabel}</SubmitButton>}
|
57
61
|
{children}
|
58
62
|
</FormLayout>
|
@@ -0,0 +1,54 @@
|
|
1
|
+
import * as React from 'react'
|
2
|
+
import { FormState, get } from 'react-hook-form'
|
3
|
+
|
4
|
+
import {
|
5
|
+
Box,
|
6
|
+
FormControl,
|
7
|
+
FormLabel,
|
8
|
+
FormHelperText,
|
9
|
+
FormErrorMessage,
|
10
|
+
} from '@chakra-ui/react'
|
11
|
+
|
12
|
+
import { useFormContext } from './form-context'
|
13
|
+
|
14
|
+
import { BaseFieldProps, FieldProps } from './types'
|
15
|
+
|
16
|
+
const getError = (name: string, formState: FormState<{ [x: string]: any }>) => {
|
17
|
+
return get(formState.errors, name)
|
18
|
+
}
|
19
|
+
|
20
|
+
const isTouched = (
|
21
|
+
name: string,
|
22
|
+
formState: FormState<{ [x: string]: any }>
|
23
|
+
) => {
|
24
|
+
return get(formState.touchedFields, name)
|
25
|
+
}
|
26
|
+
|
27
|
+
/**
|
28
|
+
* The default BaseField component
|
29
|
+
* Composes the Chakra UI FormControl component, with FormLabel, FormHelperText and FormErrorMessage.
|
30
|
+
*/
|
31
|
+
export const BaseField: React.FC<BaseFieldProps> = (props) => {
|
32
|
+
const { name, label, help, hideLabel, children, ...controlProps } = props
|
33
|
+
|
34
|
+
const { formState } = useFormContext()
|
35
|
+
|
36
|
+
const error = getError(name, formState)
|
37
|
+
|
38
|
+
return (
|
39
|
+
<FormControl {...controlProps} isInvalid={!!error}>
|
40
|
+
{label && !hideLabel ? <FormLabel>{label}</FormLabel> : null}
|
41
|
+
<Box>
|
42
|
+
{children}
|
43
|
+
{help && !error?.message ? (
|
44
|
+
<FormHelperText>{help}</FormHelperText>
|
45
|
+
) : null}
|
46
|
+
{error?.message && (
|
47
|
+
<FormErrorMessage>{error?.message}</FormErrorMessage>
|
48
|
+
)}
|
49
|
+
</Box>
|
50
|
+
</FormControl>
|
51
|
+
)
|
52
|
+
}
|
53
|
+
|
54
|
+
BaseField.displayName = 'BaseField'
|