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

Sign up to get free protection for your applications and to get access to all the features.
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
+ })