@saas-ui/forms 2.0.0-next.2 → 2.0.0-next.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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'
|