@saas-ui/forms 1.5.2 → 2.0.0-next.0

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.
Files changed (112) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/ajv/index.d.ts +21 -2
  3. package/dist/ajv/index.js +31 -2
  4. package/dist/ajv/index.js.map +1 -1
  5. package/dist/ajv/index.mjs +25 -0
  6. package/dist/ajv/index.mjs.map +1 -0
  7. package/dist/index.d.ts +606 -19
  8. package/dist/index.js +1251 -2
  9. package/dist/index.js.map +1 -1
  10. package/dist/index.mjs +1140 -0
  11. package/dist/index.mjs.map +1 -0
  12. package/dist/yup/index.d.ts +41 -2
  13. package/dist/yup/index.js +95 -2
  14. package/dist/yup/index.js.map +1 -1
  15. package/dist/yup/index.mjs +86 -0
  16. package/dist/yup/index.mjs.map +1 -0
  17. package/dist/zod/index.d.ts +38 -2
  18. package/dist/zod/index.js +95 -2
  19. package/dist/zod/index.js.map +1 -1
  20. package/dist/zod/index.mjs +85 -0
  21. package/dist/zod/index.mjs.map +1 -0
  22. package/package.json +18 -28
  23. package/src/array-field.tsx +20 -13
  24. package/src/auto-form.tsx +13 -19
  25. package/src/field-resolver.ts +1 -1
  26. package/src/field.tsx +4 -9
  27. package/src/fields.tsx +1 -3
  28. package/src/form.tsx +70 -26
  29. package/src/index.ts +3 -1
  30. package/src/input-right-button/index.ts +1 -0
  31. package/src/input-right-button/input-right-button.stories.tsx +47 -0
  32. package/src/input-right-button/input-right-button.test.tsx +12 -0
  33. package/src/input-right-button/input-right-button.tsx +26 -0
  34. package/src/layout.tsx +1 -1
  35. package/src/number-input/index.ts +1 -0
  36. package/src/number-input/number-input.stories.tsx +39 -0
  37. package/src/number-input/number-input.test.tsx +6 -0
  38. package/src/number-input/number-input.tsx +56 -0
  39. package/src/object-field.tsx +1 -1
  40. package/src/password-input/index.ts +1 -0
  41. package/src/password-input/password-input.stories.tsx +50 -0
  42. package/src/password-input/password-input.test.tsx +20 -0
  43. package/src/password-input/password-input.tsx +69 -0
  44. package/src/pin-input/index.ts +1 -0
  45. package/src/pin-input/pin-input.stories.tsx +38 -0
  46. package/src/pin-input/pin-input.test.tsx +6 -0
  47. package/src/pin-input/pin-input.tsx +50 -0
  48. package/src/radio/index.ts +1 -0
  49. package/src/radio/radio-input.stories.tsx +45 -0
  50. package/src/radio/radio-input.tsx +58 -0
  51. package/src/radio/radio.test.tsx +6 -0
  52. package/src/select/index.ts +2 -0
  53. package/src/select/native-select.tsx +42 -0
  54. package/src/select/select.stories.tsx +144 -0
  55. package/src/select/select.test.tsx +8 -0
  56. package/src/select/select.tsx +185 -0
  57. package/src/step-form.tsx +24 -13
  58. package/src/submit-button.tsx +32 -38
  59. package/src/use-step-form.tsx +1 -1
  60. package/ajv/package.json +0 -28
  61. package/dist/ajv/ajv-resolver.d.ts +0 -11
  62. package/dist/ajv/ajv-resolver.d.ts.map +0 -1
  63. package/dist/ajv/index.d.ts.map +0 -1
  64. package/dist/ajv/index.modern.mjs +0 -2
  65. package/dist/ajv/index.modern.mjs.map +0 -1
  66. package/dist/array-field.d.ts +0 -64
  67. package/dist/array-field.d.ts.map +0 -1
  68. package/dist/auto-form.d.ts +0 -32
  69. package/dist/auto-form.d.ts.map +0 -1
  70. package/dist/display-field.d.ts +0 -10
  71. package/dist/display-field.d.ts.map +0 -1
  72. package/dist/display-if.d.ts +0 -15
  73. package/dist/display-if.d.ts.map +0 -1
  74. package/dist/field-resolver.d.ts +0 -13
  75. package/dist/field-resolver.d.ts.map +0 -1
  76. package/dist/field.d.ts +0 -147
  77. package/dist/field.d.ts.map +0 -1
  78. package/dist/fields.d.ts +0 -9
  79. package/dist/fields.d.ts.map +0 -1
  80. package/dist/form.d.ts +0 -44
  81. package/dist/form.d.ts.map +0 -1
  82. package/dist/index.d.ts.map +0 -1
  83. package/dist/index.modern.mjs +0 -2
  84. package/dist/index.modern.mjs.map +0 -1
  85. package/dist/layout.d.ts +0 -14
  86. package/dist/layout.d.ts.map +0 -1
  87. package/dist/object-field.d.ts +0 -12
  88. package/dist/object-field.d.ts.map +0 -1
  89. package/dist/step-form.d.ts +0 -38
  90. package/dist/step-form.d.ts.map +0 -1
  91. package/dist/submit-button.d.ts +0 -20
  92. package/dist/submit-button.d.ts.map +0 -1
  93. package/dist/use-array-field.d.ts +0 -95
  94. package/dist/use-array-field.d.ts.map +0 -1
  95. package/dist/use-step-form.d.ts +0 -40
  96. package/dist/use-step-form.d.ts.map +0 -1
  97. package/dist/utils.d.ts +0 -3
  98. package/dist/utils.d.ts.map +0 -1
  99. package/dist/watch-field.d.ts +0 -11
  100. package/dist/watch-field.d.ts.map +0 -1
  101. package/dist/yup/index.d.ts.map +0 -1
  102. package/dist/yup/index.modern.mjs +0 -2
  103. package/dist/yup/index.modern.mjs.map +0 -1
  104. package/dist/yup/yup-resolver.d.ts +0 -29
  105. package/dist/yup/yup-resolver.d.ts.map +0 -1
  106. package/dist/zod/index.d.ts.map +0 -1
  107. package/dist/zod/index.modern.mjs +0 -2
  108. package/dist/zod/index.modern.mjs.map +0 -1
  109. package/dist/zod/zod-resolver.d.ts +0 -35
  110. package/dist/zod/zod-resolver.d.ts.map +0 -1
  111. package/yup/package.json +0 -26
  112. package/zod/package.json +0 -27
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../zod/src/zod-resolver.ts"],"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 const zodForm = <T extends z.ZodTypeAny>(\n schema: T,\n schemaOptions = {},\n resolverOptions = {}\n) => {\n return {\n schema,\n resolver: zodResolver(schema, schemaOptions, resolverOptions),\n fieldResolver: zodFieldResolver(schema),\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"],"names":["getType","field","_def","typeName","getArrayOption","name","_field$_def$name","value","getFieldsFromSchema","schema","fields","schemaFields","type","shape","options","min","max","meta","description","zodParseMeta","push","label","getNestedSchema","path","get","zodFieldResolver","getFields","getNestedFields","JSON","parse","e","schemaOptions","resolverOptions","resolver","zodResolver","fieldResolver","stringify"],"mappings":"2SAYA,IAAMA,EAAU,SAACC,GACf,OAAQA,EAAMC,KAAKC,UACjB,IAAK,WACH,MAAO,QACT,IAAK,YACH,MAAO,SACT,IAAK,YACH,MAAO,SACT,IAAK,UACH,MAAO,OAET,QACE,MAAO,OAEb,EAEoBC,EAAG,SAACH,EAAYI,SAClC,OAAO,OAAAJ,EAAAA,EAAMC,KAAKG,SAAX,EAAAC,EAAkBC,KAC3B,EAQaC,EAAsB,SAACC,GAClC,IAAMC,EAAuB,GAEzBC,EAAoC,CAAA,EACxC,GAA6B,aAAzBF,EAAOP,KAAKC,SACdQ,EAAeF,EAAOP,KAAKU,KAAKC,UACvBJ,IAAyB,cAAzBA,EAAOP,KAAKC,SAGrB,OACDO,EAHCC,EAAeF,EAAOP,KAAKW,OAG5B,CAED,IAAK,SAAcF,EAAc,CAC/B,IAAMV,EAAQU,EAAaN,GAEdS,EAAY,CAAE,EACC,aAAxBb,EAAMC,KAAKC,WACbW,EAAQC,IAAMX,EAAeH,EAAO,aACpCa,EAAQE,IAAMZ,EAAeH,EAAO,cAGtC,IAAUgB,EAAGhB,EAAMiB,aAAeC,EAAalB,EAAMiB,aAErDR,EAAOU,KACLf,EAAAA,CAAAA,KAAAA,EACAgB,OAAOJ,MAAAA,OAAAA,EAAAA,EAAMI,QAASpB,EAAMiB,aAAeb,EAC3CO,MAAMK,MAAAA,OAAAA,EAAAA,EAAML,OAAQZ,EAAQC,IACzBa,GAEN,CACD,OACFJ,CAAA,EAE4BY,EAAG,SAACb,EAAsBc,GACpD,OAAUC,MAACf,EAAOP,KAAKW,QAASU,EAClC,EAEaE,EAAmB,SAAyBhB,GACvD,MAAO,CACLiB,qBACE,OAA0BlB,EAACC,EAC7B,EACAkB,gBAAgBtB,SAAAA,GACd,OAA0BG,EAACc,EAAgBb,EAAQJ,GACrD,EAEJ,EAuByBc,EAAG,SAACF,GAC3B,IACE,OAAWW,KAACC,MAAMZ,EAGnB,CAFC,MAAOa,GACP,OACDb,CAAA,CACH,uMA3BuB,SACrBR,EACAsB,EACAC,GAEA,YAHa,IAAbD,IAAAA,EAAgB,CAAA,QACD,IAAfC,IAAAA,EAAkB,CAAA,GAEX,CACLvB,OAAAA,EACAwB,SAAUC,EAAAA,YAAYzB,EAAQsB,EAAeC,GAC7CG,cAAeV,EAAiBhB,GAEpC,kBAOuB,SAACQ,GACtB,OAAWW,KAACQ,UAAUnB,EACxB"}
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,UAAX,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;AAE3B,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,SAAS,kBAA8C;AAWhD,IAAM,gBAAgB,CAAC,YAAiC;AAC7D,SAAO,WAA2B;AAAA,IAChC,UAAU,CAAC,WACT,YAAY,QAAQ,mCAAS,eAAe,mCAAS,eAAe;AAAA,IACtE,GAAG;AAAA,EACL,CAAC;AAMH","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 { createForm, CreateFormProps, FormProps } from '@saas-ui/forms'\nimport { zodResolver } from './zod-resolver'\nimport { z } from 'zod'\n\ntype ResolverArgs = Parameters<typeof zodResolver>\n\nexport interface CreateZodFormProps extends CreateFormProps {\n schemaOptions?: ResolverArgs[1]\n resolverOptions?: ResolverArgs[2]\n}\n\nexport const createZodForm = (options?: CreateZodFormProps) => {\n return createForm<z.AnyZodObject>({\n resolver: (schema) =>\n zodResolver(schema, options?.schemaOptions, options?.resolverOptions),\n ...options,\n }) as <\n TSchema extends z.AnyZodObject = z.AnyZodObject,\n TContext extends object = object\n >(\n props: FormProps<z.infer<TSchema>, TContext, TSchema>\n ) => React.ReactElement\n}\n"]}
@@ -0,0 +1,85 @@
1
+ import { zodResolver } from '@hookform/resolvers/zod';
2
+ export { zodResolver } from '@hookform/resolvers/zod';
3
+ import { get } from '@chakra-ui/utils';
4
+ import { createForm } from '@saas-ui/forms';
5
+
6
+ // zod/src/zod-resolver.ts
7
+ var getType = (field) => {
8
+ switch (field._def.typeName) {
9
+ case "ZodArray":
10
+ return "array";
11
+ case "ZodObject":
12
+ return "object";
13
+ case "ZodNumber":
14
+ return "number";
15
+ case "ZodDate":
16
+ return "date";
17
+ case "ZodString":
18
+ default:
19
+ return "text";
20
+ }
21
+ };
22
+ var getArrayOption = (field, name) => {
23
+ var _a;
24
+ return (_a = field._def[name]) == null ? void 0 : _a.value;
25
+ };
26
+ var getFieldsFromSchema = (schema) => {
27
+ const fields = [];
28
+ let schemaFields = {};
29
+ if (schema._def.typeName === "ZodArray") {
30
+ schemaFields = schema._def.type.shape;
31
+ } else if (schema._def.typeName === "ZodObject") {
32
+ schemaFields = schema._def.shape();
33
+ } else {
34
+ return fields;
35
+ }
36
+ for (const name in schemaFields) {
37
+ const field = schemaFields[name];
38
+ const options = {};
39
+ if (field._def.typeName === "ZodArray") {
40
+ options.min = getArrayOption(field, "minLength");
41
+ options.max = getArrayOption(field, "maxLength");
42
+ }
43
+ const meta = field.description && zodParseMeta(field.description);
44
+ fields.push({
45
+ name,
46
+ label: (meta == null ? void 0 : meta.label) || field.description || name,
47
+ type: (meta == null ? void 0 : meta.type) || getType(field),
48
+ ...options
49
+ });
50
+ }
51
+ return fields;
52
+ };
53
+ var getNestedSchema = (schema, path) => {
54
+ return get(schema._def.shape(), path);
55
+ };
56
+ var zodFieldResolver = (schema) => {
57
+ return {
58
+ getFields() {
59
+ return getFieldsFromSchema(schema);
60
+ },
61
+ getNestedFields(name) {
62
+ return getFieldsFromSchema(getNestedSchema(schema, name));
63
+ }
64
+ };
65
+ };
66
+ var zodMeta = (meta) => {
67
+ return JSON.stringify(meta);
68
+ };
69
+ var zodParseMeta = (meta) => {
70
+ try {
71
+ return JSON.parse(meta);
72
+ } catch (e) {
73
+ return meta;
74
+ }
75
+ };
76
+ var createZodForm = (options) => {
77
+ return createForm({
78
+ resolver: (schema) => zodResolver(schema, options == null ? void 0 : options.schemaOptions, options == null ? void 0 : options.resolverOptions),
79
+ ...options
80
+ });
81
+ };
82
+
83
+ export { createZodForm, getFieldsFromSchema, getNestedSchema, zodFieldResolver, zodMeta, zodParseMeta };
84
+ //# sourceMappingURL=out.js.map
85
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +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,UAAX,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;AAE3B,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,SAAS,kBAA8C;AAWhD,IAAM,gBAAgB,CAAC,YAAiC;AAC7D,SAAO,WAA2B;AAAA,IAChC,UAAU,CAAC,WACT,YAAY,QAAQ,mCAAS,eAAe,mCAAS,eAAe;AAAA,IACtE,GAAG;AAAA,EACL,CAAC;AAMH","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 { createForm, CreateFormProps, FormProps } from '@saas-ui/forms'\nimport { zodResolver } from './zod-resolver'\nimport { z } from 'zod'\n\ntype ResolverArgs = Parameters<typeof zodResolver>\n\nexport interface CreateZodFormProps extends CreateFormProps {\n schemaOptions?: ResolverArgs[1]\n resolverOptions?: ResolverArgs[2]\n}\n\nexport const createZodForm = (options?: CreateZodFormProps) => {\n return createForm<z.AnyZodObject>({\n resolver: (schema) =>\n zodResolver(schema, options?.schemaOptions, options?.resolverOptions),\n ...options,\n }) as <\n TSchema extends z.AnyZodObject = z.AnyZodObject,\n TContext extends object = object\n >(\n props: FormProps<z.infer<TSchema>, TContext, TSchema>\n ) => React.ReactElement\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saas-ui/forms",
3
- "version": "1.5.2",
3
+ "version": "2.0.0-next.0",
4
4
  "description": "Fully functional forms for Chakra UI.",
5
5
  "source": "src/index.ts",
6
6
  "exports": {
@@ -39,23 +39,17 @@
39
39
  "scripts": {
40
40
  "clean": "rimraf --no-glob ./dist",
41
41
  "build": "yarn build:package && yarn build:yup && yarn build:zod && yarn build:ajv",
42
- "build:package": "yarn clean && cross-env NODE_ENV=production microbundle --tsconfig ./tsconfig.json --jsx React.createElement --jsxFragment React.Fragment -f cjs,modern --compress",
43
- "build:yup": "cross-env NODE_ENV=production microbundle --cwd yup --tsconfig ./yup/tsconfig.json -f cjs,modern --compress",
44
- "build:zod": "cross-env NODE_ENV=production microbundle --cwd zod --tsconfig ./zod/tsconfig.json -f cjs,modern --compress",
45
- "build:ajv": "cross-env NODE_ENV=production microbundle --cwd ajv --tsconfig ./ajv/tsconfig.json -f cjs,modern --compress",
42
+ "build:package": "tsup src/index.ts --config tsup.config.ts",
43
+ "build:yup": "tsup yup/src/index.ts --config yup/tsup.config.ts",
44
+ "build:zod": "tsup zod/src/index.ts --config zod/tsup.config.ts",
45
+ "build:ajv": "tsup ajv/src/index.ts --config ajv/tsup.config.ts",
46
46
  "lint": "eslint src --ext .ts,.tsx,.js,.jsx --config ../../.eslintrc.js",
47
47
  "lint:staged": "lint-staged --allow-empty --config ../../lint-staged.config.js",
48
48
  "typecheck": "tsc --noEmit"
49
49
  },
50
50
  "files": [
51
51
  "dist",
52
- "src",
53
- "yup/package.json",
54
- "yup/src",
55
- "zod/package.json",
56
- "zod/src",
57
- "ajv/package.json",
58
- "ajv/src"
52
+ "src"
59
53
  ],
60
54
  "sideEffects": false,
61
55
  "publishConfig": {
@@ -92,26 +86,22 @@
92
86
  "@chakra-ui/icons": "^2.0.16",
93
87
  "@chakra-ui/react-utils": "^2.0.11",
94
88
  "@chakra-ui/utils": "^2.0.14",
95
- "@hookform/resolvers": "^2.9.10",
96
- "@saas-ui/button": "1.4.0",
97
- "@saas-ui/input-right-button": "1.4.0",
98
- "@saas-ui/number-input": "1.4.0",
99
- "@saas-ui/password-input": "1.4.0",
100
- "@saas-ui/pin-input": "1.4.0",
101
- "@saas-ui/radio": "1.4.1",
102
- "@saas-ui/react-utils": "1.2.0",
103
- "@saas-ui/select": "1.4.0",
104
- "@saas-ui/stepper": "1.4.0",
105
- "react-hook-form": "^7.42.1"
89
+ "@saas-ui/core": "2.0.0-next.0",
90
+ "react-hook-form": "^7.43.0"
106
91
  },
107
92
  "peerDependencies": {
108
- "@chakra-ui/react": ">=2.4.6",
109
- "@chakra-ui/system": ">=2.3.8",
110
- "react": ">=18.0.0"
93
+ "@chakra-ui/react": ">=2.4.9",
94
+ "@emotion/react": ">=11.0.0",
95
+ "@emotion/styled": ">=11.0.0",
96
+ "framer-motion": ">=6.0.0",
97
+ "react": ">=18.0.0",
98
+ "react-dom": ">=18.0.0"
111
99
  },
112
100
  "devDependencies": {
113
- "ajv": "^8.11.2",
101
+ "@hookform/resolvers": "^2.9.3",
102
+ "@types/json-schema": "^7.0.11",
103
+ "ajv": "^8.12.0",
114
104
  "yup": "^0.32.11",
115
- "zod": "^3.19.1"
105
+ "zod": "^3.20.2"
116
106
  }
117
107
  }
@@ -1,9 +1,14 @@
1
1
  import * as React from 'react'
2
2
 
3
- import { chakra, ResponsiveValue, forwardRef } from '@chakra-ui/system'
3
+ import {
4
+ chakra,
5
+ ResponsiveValue,
6
+ forwardRef,
7
+ Button,
8
+ ButtonProps,
9
+ } from '@chakra-ui/react'
4
10
  import { __DEV__ } from '@chakra-ui/utils'
5
11
  import { AddIcon, MinusIcon } from '@chakra-ui/icons'
6
- import { IconButton, ButtonProps } from '@saas-ui/button'
7
12
 
8
13
  import { FormLayout, FormLayoutProps } from './layout'
9
14
  import { BaseField, FieldProps } from './field'
@@ -23,6 +28,8 @@ import {
23
28
  UseArrayFieldReturn,
24
29
  } from './use-array-field'
25
30
 
31
+ export interface ArrayFieldButtonProps extends ButtonProps {}
32
+
26
33
  interface ArrayField {
27
34
  id: string
28
35
  [key: string]: unknown
@@ -120,14 +127,13 @@ if (__DEV__) {
120
127
  ArrayFieldRowContainer.displayName = 'ArrayFieldRowContainer'
121
128
  }
122
129
 
123
- export const ArrayFieldRemoveButton: React.FC<ButtonProps> = (props) => {
130
+ export const ArrayFieldRemoveButton: React.FC<ArrayFieldButtonProps> = (
131
+ props
132
+ ) => {
124
133
  return (
125
- <IconButton
126
- icon={<MinusIcon />}
127
- aria-label="Remove row"
128
- {...useArrayFieldRemoveButton()}
129
- {...props}
130
- />
134
+ <Button aria-label="Remove row" {...useArrayFieldRemoveButton()} {...props}>
135
+ {props.children || <MinusIcon />}
136
+ </Button>
131
137
  )
132
138
  }
133
139
 
@@ -135,15 +141,16 @@ if (__DEV__) {
135
141
  ArrayFieldRemoveButton.displayName = 'ArrayFieldRemoveButton'
136
142
  }
137
143
 
138
- export const ArrayFieldAddButton: React.FC<ButtonProps> = (props) => {
144
+ export const ArrayFieldAddButton: React.FC<ArrayFieldButtonProps> = (props) => {
139
145
  return (
140
- <IconButton
141
- icon={<AddIcon />}
146
+ <Button
142
147
  aria-label="Add row"
143
148
  float="right"
144
149
  {...useArrayFieldAddButton()}
145
150
  {...props}
146
- />
151
+ >
152
+ {props.children || <AddIcon />}
153
+ </Button>
147
154
  )
148
155
  }
149
156
 
package/src/auto-form.tsx CHANGED
@@ -1,13 +1,11 @@
1
1
  import * as React from 'react'
2
- import { FieldValues, UseFormReturn } from 'react-hook-form'
2
+ import { FieldValues } from 'react-hook-form'
3
3
  import { forwardRef } from '@chakra-ui/react'
4
- import { __DEV__ } from '@chakra-ui/utils'
5
4
 
6
5
  import { Form, FormProps } from './form'
7
6
  import { FormLayout } from './layout'
8
7
  import { Fields } from './fields'
9
8
  import { SubmitButton } from './submit-button'
10
- import { FieldResolver } from '.'
11
9
 
12
10
  interface AutoFormOptions {
13
11
  /**
@@ -27,16 +25,21 @@ interface AutoFormOptions {
27
25
  fieldResolver?: any
28
26
  }
29
27
 
30
- export interface AutoFormProps<TFieldValues extends FieldValues>
31
- extends Omit<FormProps<TFieldValues>, 'schema' | 'children'>,
28
+ export interface AutoFormProps<
29
+ TFieldValues extends FieldValues,
30
+ TContext extends object = object
31
+ > extends Omit<FormProps<TFieldValues, TContext>, 'schema' | 'children'>,
32
32
  AutoFormOptions {
33
33
  children?: React.ReactNode
34
34
  }
35
35
 
36
36
  export const AutoForm = forwardRef(
37
- <TFieldValues extends FieldValues = FieldValues>(
38
- props: AutoFormProps<TFieldValues>,
39
- ref: React.ForwardedRef<UseFormReturn<TFieldValues>>
37
+ <
38
+ TFieldValues extends FieldValues = FieldValues,
39
+ TContext extends object = object
40
+ >(
41
+ props: AutoFormProps<TFieldValues, TContext>,
42
+ ref: React.ForwardedRef<HTMLFormElement>
40
43
  ) => {
41
44
  const {
42
45
  schema,
@@ -56,15 +59,6 @@ export const AutoForm = forwardRef(
56
59
  </Form>
57
60
  )
58
61
  }
59
- ) as (<TFieldValues extends FieldValues>(
60
- props: AutoFormProps<TFieldValues> & {
61
- ref?: React.ForwardedRef<UseFormReturn<TFieldValues>>
62
- }
63
- ) => React.ReactElement) & {
64
- displayName?: string
65
- getFieldResolver?: (schema: any) => FieldResolver
66
- }
62
+ )
67
63
 
68
- if (__DEV__) {
69
- AutoForm.displayName = 'AutoForm'
70
- }
64
+ AutoForm.displayName = 'AutoForm'
@@ -20,7 +20,7 @@ const mapFields = (schema: ObjectSchema): FieldProps[] =>
20
20
  return {
21
21
  ...field,
22
22
  name,
23
- label: label || title, // json schema compatibility
23
+ label: label || title || name, // json schema compatibility
24
24
  }
25
25
  })
26
26
 
package/src/field.tsx CHANGED
@@ -35,16 +35,11 @@ import {
35
35
  } from '@chakra-ui/react'
36
36
  import { __DEV__, FocusableElement, callAllHandlers } from '@chakra-ui/utils'
37
37
 
38
- import { NumberInput, NumberInputProps } from '@saas-ui/number-input'
39
- import { PasswordInput, PasswordInputProps } from '@saas-ui/password-input'
40
- import { RadioInput, RadioInputProps } from '@saas-ui/radio'
38
+ import { NumberInput, NumberInputProps } from './number-input'
39
+ import { PasswordInput, PasswordInputProps } from './password-input'
40
+ import { RadioInput, RadioInputProps } from './radio'
41
41
 
42
- import {
43
- Select,
44
- SelectProps,
45
- NativeSelect,
46
- NativeSelectProps,
47
- } from '@saas-ui/select'
42
+ import { Select, SelectProps, NativeSelect, NativeSelectProps } from './select'
48
43
 
49
44
  export interface Option {
50
45
  value: string
package/src/fields.tsx CHANGED
@@ -77,6 +77,4 @@ export const Fields: React.FC<FieldsProps> = ({
77
77
  )
78
78
  }
79
79
 
80
- if (__DEV__) {
81
- Fields.displayName = 'Fields'
82
- }
80
+ Fields.displayName = 'Fields'
package/src/form.tsx CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as React from 'react'
2
2
 
3
3
  import { chakra, HTMLChakraProps, forwardRef } from '@chakra-ui/react'
4
- import { cx, MaybeFunction, runIfFn, __DEV__ } from '@chakra-ui/utils'
4
+ import { cx, runIfFn, __DEV__ } from '@chakra-ui/utils'
5
5
 
6
6
  import {
7
7
  useForm,
@@ -13,7 +13,6 @@ import {
13
13
  SubmitErrorHandler,
14
14
  ResolverOptions,
15
15
  ResolverResult,
16
- ChangeHandler,
17
16
  WatchObserver,
18
17
  } from 'react-hook-form'
19
18
  import { objectFieldResolver, FieldResolver } from './field-resolver'
@@ -21,14 +20,24 @@ import { MaybeRenderProp } from '@chakra-ui/react-utils'
21
20
 
22
21
  export type { UseFormReturn, FieldValues, SubmitHandler }
23
22
 
24
- interface FormOptions<
23
+ import { Field as DefaultField, FieldProps } from './field'
24
+
25
+ interface FormRenderContext<
25
26
  TFieldValues extends FieldValues = FieldValues,
26
27
  TContext extends object = object
28
+ > extends UseFormReturn<TFieldValues, TContext> {
29
+ Field: React.FC<FieldProps<TFieldValues>>
30
+ }
31
+
32
+ interface FormOptions<
33
+ TFieldValues extends FieldValues = FieldValues,
34
+ TContext extends object = object,
35
+ TSchema = any
27
36
  > {
28
37
  /**
29
- * The form schema, currently supports Yup schema only.
38
+ * The form schema, supports Yup, Zod, and AJV.
30
39
  */
31
- schema?: any
40
+ schema?: TSchema
32
41
  /**
33
42
  * Triggers when any of the field change.
34
43
  */
@@ -42,34 +51,34 @@ interface FormOptions<
42
51
  */
43
52
  onError?: SubmitErrorHandler<TFieldValues>
44
53
  /**
45
- * Ref on the HTMLFormElement.
54
+ * The Hook Form state ref.
46
55
  */
47
- formRef?: React.RefObject<HTMLFormElement>
56
+ formRef?: React.RefObject<UseFormReturn<TFieldValues, TContext>>
48
57
  /**
49
58
  * The form children, can be a render prop or a ReactNode.
50
59
  */
51
- children?: MaybeRenderProp<UseFormReturn<TFieldValues, TContext>>
60
+ children?: MaybeRenderProp<FormRenderContext<TFieldValues, TContext>>
52
61
  }
53
62
 
54
- // @todo Figure out how to pass down FieldValues to all Field components, if at all possible.
55
-
56
63
  export interface FormProps<
57
64
  TFieldValues extends FieldValues = FieldValues,
58
- TContext extends object = object
65
+ TContext extends object = object,
66
+ TSchema = any
59
67
  > extends UseFormProps<TFieldValues, TContext>,
60
68
  Omit<
61
69
  HTMLChakraProps<'form'>,
62
70
  'children' | 'onChange' | 'onSubmit' | 'onError'
63
71
  >,
64
- FormOptions<TFieldValues, TContext> {}
72
+ FormOptions<TFieldValues, TContext, TSchema> {}
65
73
 
66
74
  export const Form = forwardRef(
67
75
  <
68
76
  TFieldValues extends FieldValues = FieldValues,
69
- TContext extends object = object
77
+ TContext extends object = object,
78
+ TSchema = any
70
79
  >(
71
- props: FormProps<TFieldValues, TContext>,
72
- ref: React.ForwardedRef<UseFormReturn<TFieldValues, TContext>>
80
+ props: FormProps<TFieldValues, TContext, TSchema>,
81
+ ref: React.ForwardedRef<HTMLFormElement>
73
82
  ) => {
74
83
  const {
75
84
  mode = 'all',
@@ -82,6 +91,9 @@ export const Form = forwardRef(
82
91
  delayError,
83
92
  schema,
84
93
  defaultValues,
94
+ values,
95
+ context,
96
+ resetOptions,
85
97
  onChange,
86
98
  onSubmit,
87
99
  onError,
@@ -94,23 +106,26 @@ export const Form = forwardRef(
94
106
  mode,
95
107
  resolver,
96
108
  defaultValues,
109
+ values,
97
110
  reValidateMode,
98
111
  shouldFocusError,
99
112
  shouldUnregister,
100
113
  shouldUseNativeValidation,
101
114
  criteriaMode,
102
115
  delayError,
116
+ context,
117
+ resetOptions,
103
118
  }
104
119
 
105
120
  if (schema && !resolver) {
106
- form.resolver = Form.getResolver?.<TFieldValues, TContext>(schema)
121
+ form.resolver = Form.getResolver?.(schema)
107
122
  }
108
123
 
109
124
  const methods = useForm<TFieldValues, TContext>(form)
110
125
  const { handleSubmit } = methods
111
126
 
112
127
  // This exposes the useForm api through the forwarded ref
113
- React.useImperativeHandle(ref, () => methods, [ref, methods])
128
+ React.useImperativeHandle(formRef, () => methods, [formRef, methods])
114
129
 
115
130
  React.useEffect(() => {
116
131
  let subscription: any
@@ -120,22 +135,34 @@ export const Form = forwardRef(
120
135
  return () => subscription?.unsubscribe()
121
136
  }, [methods, onChange])
122
137
 
138
+ const Field: React.FC<FieldProps<TFieldValues>> = React.useMemo(
139
+ () => (props) => <DefaultField<TFieldValues> {...props} />,
140
+ []
141
+ )
142
+
123
143
  return (
124
144
  <FormProvider {...methods}>
125
145
  <chakra.form
126
- ref={formRef}
146
+ ref={ref}
127
147
  onSubmit={handleSubmit(onSubmit, onError)}
128
148
  {...rest}
129
- className={cx('saas-form', props.className)}
149
+ className={cx('sui-form', props.className)}
130
150
  >
131
- {runIfFn(children, methods)}
151
+ {runIfFn(children, {
152
+ Field,
153
+ ...methods,
154
+ })}
132
155
  </chakra.form>
133
156
  </FormProvider>
134
157
  )
135
158
  }
136
- ) as (<TFieldValues extends FieldValues, TContext extends object = object>(
137
- props: FormProps<TFieldValues> & {
138
- ref?: React.ForwardedRef<UseFormReturn<TFieldValues>>
159
+ ) as (<
160
+ TFieldValues extends FieldValues,
161
+ TContext extends object = object,
162
+ TSchema = any
163
+ >(
164
+ props: FormProps<TFieldValues, TContext, TSchema> & {
165
+ ref?: React.ForwardedRef<HTMLFormElement>
139
166
  }
140
167
  ) => React.ReactElement) & {
141
168
  displayName?: string
@@ -145,9 +172,7 @@ export const Form = forwardRef(
145
172
 
146
173
  Form.getFieldResolver = objectFieldResolver
147
174
 
148
- if (__DEV__) {
149
- Form.displayName = 'Form'
150
- }
175
+ Form.displayName = 'Form'
151
176
 
152
177
  export type GetResolver = <
153
178
  TFieldValues extends FieldValues,
@@ -161,3 +186,22 @@ export type GetResolver = <
161
186
  ) => Promise<ResolverResult<TFieldValues>>
162
187
 
163
188
  export type GetFieldResolver = (schema: any) => FieldResolver
189
+
190
+ export interface CreateFormProps {
191
+ resolver?: GetResolver
192
+ }
193
+
194
+ export function createForm<Schema = any>({ resolver }: CreateFormProps) {
195
+ const CreateForm = <
196
+ TFieldValues extends FieldValues,
197
+ TContext extends object = object,
198
+ TSchema extends Schema = Schema
199
+ >(
200
+ props: FormProps<TFieldValues, TContext, TSchema>
201
+ ) => {
202
+ const { schema, ...rest } = props
203
+ return <Form resolver={resolver?.(props.schema)} {...rest} />
204
+ }
205
+
206
+ return CreateForm
207
+ }
package/src/index.ts CHANGED
@@ -13,7 +13,9 @@ export * from './step-form'
13
13
  export * from './use-step-form'
14
14
  export * from './field-resolver'
15
15
  export * from './watch-field'
16
- export * from '@saas-ui/input-right-button'
16
+ export * from './input-right-button'
17
+ export * from './select'
18
+ export * from './password-input'
17
19
 
18
20
  export type {
19
21
  BatchFieldArrayUpdate,
@@ -0,0 +1 @@
1
+ export * from './input-right-button'
@@ -0,0 +1,47 @@
1
+ import {
2
+ Container,
3
+ Input,
4
+ InputGroup,
5
+ Icon,
6
+ FormControl,
7
+ FormLabel,
8
+ } from '@chakra-ui/react'
9
+ import * as React from 'react'
10
+
11
+ import { ComponentStory } from '@storybook/react'
12
+
13
+ import { InputRightButton } from '../src'
14
+
15
+ import { FiEye } from 'react-icons/fi'
16
+
17
+ export default {
18
+ title: 'Components/Forms/InputRightButton',
19
+ decorators: [
20
+ (Story: any) => (
21
+ <Container mt="40px">
22
+ <Story />
23
+ </Container>
24
+ ),
25
+ ],
26
+ }
27
+
28
+ const Template: ComponentStory<typeof InputRightButton> = (args) => (
29
+ <FormControl>
30
+ <FormLabel>Input Right Button</FormLabel>
31
+ <InputGroup>
32
+ <Input />
33
+ <InputRightButton {...args} />
34
+ </InputGroup>
35
+ </FormControl>
36
+ )
37
+
38
+ export const Basic = Template.bind({})
39
+ Basic.args = {
40
+ label: 'Save',
41
+ }
42
+
43
+ export const WithIcon = Template.bind({})
44
+ WithIcon.args = {
45
+ children: <Icon as={FiEye} />,
46
+ 'aria-label': 'Show password',
47
+ }
@@ -0,0 +1,12 @@
1
+ import * as React from 'react'
2
+
3
+ import { render, testStories } from '@saas-ui/test-utils'
4
+ import * as stories from './input-right-button.stories'
5
+
6
+ const { Basic } = testStories<typeof stories>(stories)
7
+
8
+ test('should render a label', async () => {
9
+ const { getByText } = render(<Basic />)
10
+
11
+ expect(getByText('Save')).toBeVisible()
12
+ })