@becklyn/forms 1.0.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 (201) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +281 -0
  3. package/dist/cjs/components/FormBuilder.d.ts +3 -0
  4. package/dist/cjs/components/FormBuilder.d.ts.map +1 -0
  5. package/dist/cjs/components/FormBuilder.js +22 -0
  6. package/dist/cjs/components/FormCustom.d.ts +10 -0
  7. package/dist/cjs/components/FormCustom.d.ts.map +1 -0
  8. package/dist/cjs/components/FormCustom.js +13 -0
  9. package/dist/cjs/components/FormEntry.d.ts +10 -0
  10. package/dist/cjs/components/FormEntry.d.ts.map +1 -0
  11. package/dist/cjs/components/FormEntry.js +46 -0
  12. package/dist/cjs/components/FormField.d.ts +10 -0
  13. package/dist/cjs/components/FormField.d.ts.map +1 -0
  14. package/dist/cjs/components/FormField.js +79 -0
  15. package/dist/cjs/components/FormRow.d.ts +10 -0
  16. package/dist/cjs/components/FormRow.d.ts.map +1 -0
  17. package/dist/cjs/components/FormRow.js +13 -0
  18. package/dist/cjs/components/FormSection.d.ts +10 -0
  19. package/dist/cjs/components/FormSection.d.ts.map +1 -0
  20. package/dist/cjs/components/FormSection.js +13 -0
  21. package/dist/cjs/components/FormWatch.d.ts +8 -0
  22. package/dist/cjs/components/FormWatch.d.ts.map +1 -0
  23. package/dist/cjs/components/FormWatch.js +14 -0
  24. package/dist/cjs/condition/index.d.ts +3 -0
  25. package/dist/cjs/condition/index.d.ts.map +1 -0
  26. package/dist/cjs/condition/index.js +29 -0
  27. package/dist/cjs/context/FormProvider.d.ts +7 -0
  28. package/dist/cjs/context/FormProvider.d.ts.map +1 -0
  29. package/dist/cjs/context/FormProvider.js +24 -0
  30. package/dist/cjs/context/context.d.ts +15 -0
  31. package/dist/cjs/context/context.d.ts.map +1 -0
  32. package/dist/cjs/context/context.js +7 -0
  33. package/dist/cjs/context/data/FormDataProvider.d.ts +19 -0
  34. package/dist/cjs/context/data/FormDataProvider.d.ts.map +1 -0
  35. package/dist/cjs/context/data/FormDataProvider.js +39 -0
  36. package/dist/cjs/context/data/context.d.ts +13 -0
  37. package/dist/cjs/context/data/context.d.ts.map +1 -0
  38. package/dist/cjs/context/data/context.js +6 -0
  39. package/dist/cjs/context/data/index.d.ts +2 -0
  40. package/dist/cjs/context/data/index.d.ts.map +1 -0
  41. package/dist/cjs/context/data/index.js +2 -0
  42. package/dist/cjs/context/index.d.ts +4 -0
  43. package/dist/cjs/context/index.d.ts.map +1 -0
  44. package/dist/cjs/context/index.js +22 -0
  45. package/dist/cjs/guard/index.d.ts +6 -0
  46. package/dist/cjs/guard/index.d.ts.map +1 -0
  47. package/dist/cjs/guard/index.js +21 -0
  48. package/dist/cjs/hoc/withForm.d.ts +7 -0
  49. package/dist/cjs/hoc/withForm.d.ts.map +1 -0
  50. package/dist/cjs/hoc/withForm.js +14 -0
  51. package/dist/cjs/hoc/withFormData.d.ts +7 -0
  52. package/dist/cjs/hoc/withFormData.d.ts.map +1 -0
  53. package/dist/cjs/hoc/withFormData.js +14 -0
  54. package/dist/cjs/hook/useFormData.d.ts +5 -0
  55. package/dist/cjs/hook/useFormData.d.ts.map +1 -0
  56. package/dist/cjs/hook/useFormData.js +18 -0
  57. package/dist/cjs/hook/useFormErrors.d.ts +3 -0
  58. package/dist/cjs/hook/useFormErrors.d.ts.map +1 -0
  59. package/dist/cjs/hook/useFormErrors.js +14 -0
  60. package/dist/cjs/hook/useFormStore.d.ts +8 -0
  61. package/dist/cjs/hook/useFormStore.d.ts.map +1 -0
  62. package/dist/cjs/hook/useFormStore.js +26 -0
  63. package/dist/cjs/hook/useFormValidations.d.ts +9 -0
  64. package/dist/cjs/hook/useFormValidations.d.ts.map +1 -0
  65. package/dist/cjs/hook/useFormValidations.js +48 -0
  66. package/dist/cjs/hook/useRefEffect.d.ts +2 -0
  67. package/dist/cjs/hook/useRefEffect.d.ts.map +1 -0
  68. package/dist/cjs/hook/useRefEffect.js +10 -0
  69. package/dist/cjs/style/index.d.ts +7 -0
  70. package/dist/cjs/style/index.d.ts.map +1 -0
  71. package/dist/cjs/style/index.js +59 -0
  72. package/dist/cjs/type/common.d.ts +7 -0
  73. package/dist/cjs/type/common.d.ts.map +1 -0
  74. package/dist/cjs/type/common.js +2 -0
  75. package/dist/cjs/type/condition.d.ts +3 -0
  76. package/dist/cjs/type/condition.d.ts.map +1 -0
  77. package/dist/cjs/type/condition.js +2 -0
  78. package/dist/cjs/type/config.d.ts +18 -0
  79. package/dist/cjs/type/config.d.ts.map +1 -0
  80. package/dist/cjs/type/config.js +2 -0
  81. package/dist/cjs/type/extract.d.ts +25 -0
  82. package/dist/cjs/type/extract.d.ts.map +1 -0
  83. package/dist/cjs/type/extract.js +2 -0
  84. package/dist/cjs/type/field.d.ts +30 -0
  85. package/dist/cjs/type/field.d.ts.map +1 -0
  86. package/dist/cjs/type/field.js +2 -0
  87. package/dist/cjs/type/form.d.ts +30 -0
  88. package/dist/cjs/type/form.d.ts.map +1 -0
  89. package/dist/cjs/type/form.js +2 -0
  90. package/dist/cjs/type/index.d.ts +8 -0
  91. package/dist/cjs/type/index.d.ts.map +1 -0
  92. package/dist/cjs/type/index.js +23 -0
  93. package/dist/cjs/type/validation.d.ts +14 -0
  94. package/dist/cjs/type/validation.d.ts.map +1 -0
  95. package/dist/cjs/type/validation.js +2 -0
  96. package/dist/cjs/util/index.d.ts +11 -0
  97. package/dist/cjs/util/index.d.ts.map +1 -0
  98. package/dist/cjs/util/index.js +97 -0
  99. package/dist/cjs/validation/index.d.ts +4 -0
  100. package/dist/cjs/validation/index.d.ts.map +1 -0
  101. package/dist/cjs/validation/index.js +57 -0
  102. package/dist/es/components/FormBuilder.d.ts +3 -0
  103. package/dist/es/components/FormBuilder.d.ts.map +1 -0
  104. package/dist/es/components/FormBuilder.js +22 -0
  105. package/dist/es/components/FormCustom.d.ts +10 -0
  106. package/dist/es/components/FormCustom.d.ts.map +1 -0
  107. package/dist/es/components/FormCustom.js +13 -0
  108. package/dist/es/components/FormEntry.d.ts +10 -0
  109. package/dist/es/components/FormEntry.d.ts.map +1 -0
  110. package/dist/es/components/FormEntry.js +46 -0
  111. package/dist/es/components/FormField.d.ts +10 -0
  112. package/dist/es/components/FormField.d.ts.map +1 -0
  113. package/dist/es/components/FormField.js +78 -0
  114. package/dist/es/components/FormRow.d.ts +10 -0
  115. package/dist/es/components/FormRow.d.ts.map +1 -0
  116. package/dist/es/components/FormRow.js +13 -0
  117. package/dist/es/components/FormSection.d.ts +10 -0
  118. package/dist/es/components/FormSection.d.ts.map +1 -0
  119. package/dist/es/components/FormSection.js +13 -0
  120. package/dist/es/components/FormWatch.d.ts +8 -0
  121. package/dist/es/components/FormWatch.d.ts.map +1 -0
  122. package/dist/es/components/FormWatch.js +14 -0
  123. package/dist/es/condition/index.d.ts +3 -0
  124. package/dist/es/condition/index.d.ts.map +1 -0
  125. package/dist/es/condition/index.js +28 -0
  126. package/dist/es/context/FormProvider.d.ts +7 -0
  127. package/dist/es/context/FormProvider.d.ts.map +1 -0
  128. package/dist/es/context/FormProvider.js +27 -0
  129. package/dist/es/context/context.d.ts +15 -0
  130. package/dist/es/context/context.d.ts.map +1 -0
  131. package/dist/es/context/context.js +7 -0
  132. package/dist/es/context/data/FormDataProvider.d.ts +19 -0
  133. package/dist/es/context/data/FormDataProvider.d.ts.map +1 -0
  134. package/dist/es/context/data/FormDataProvider.js +30 -0
  135. package/dist/es/context/data/context.d.ts +13 -0
  136. package/dist/es/context/data/context.d.ts.map +1 -0
  137. package/dist/es/context/data/context.js +6 -0
  138. package/dist/es/context/data/index.d.ts +2 -0
  139. package/dist/es/context/data/index.d.ts.map +1 -0
  140. package/dist/es/context/data/index.js +2 -0
  141. package/dist/es/context/index.d.ts +4 -0
  142. package/dist/es/context/index.d.ts.map +1 -0
  143. package/dist/es/context/index.js +22 -0
  144. package/dist/es/guard/index.d.ts +6 -0
  145. package/dist/es/guard/index.d.ts.map +1 -0
  146. package/dist/es/guard/index.js +21 -0
  147. package/dist/es/hoc/withForm.d.ts +7 -0
  148. package/dist/es/hoc/withForm.d.ts.map +1 -0
  149. package/dist/es/hoc/withForm.js +14 -0
  150. package/dist/es/hoc/withFormData.d.ts +7 -0
  151. package/dist/es/hoc/withFormData.d.ts.map +1 -0
  152. package/dist/es/hoc/withFormData.js +14 -0
  153. package/dist/es/hook/useFormData.d.ts +5 -0
  154. package/dist/es/hook/useFormData.d.ts.map +1 -0
  155. package/dist/es/hook/useFormData.js +18 -0
  156. package/dist/es/hook/useFormErrors.d.ts +3 -0
  157. package/dist/es/hook/useFormErrors.d.ts.map +1 -0
  158. package/dist/es/hook/useFormErrors.js +14 -0
  159. package/dist/es/hook/useFormStore.d.ts +8 -0
  160. package/dist/es/hook/useFormStore.d.ts.map +1 -0
  161. package/dist/es/hook/useFormStore.js +26 -0
  162. package/dist/es/hook/useFormValidations.d.ts +9 -0
  163. package/dist/es/hook/useFormValidations.d.ts.map +1 -0
  164. package/dist/es/hook/useFormValidations.js +48 -0
  165. package/dist/es/hook/useRefEffect.d.ts +2 -0
  166. package/dist/es/hook/useRefEffect.d.ts.map +1 -0
  167. package/dist/es/hook/useRefEffect.js +10 -0
  168. package/dist/es/style/index.d.ts +7 -0
  169. package/dist/es/style/index.d.ts.map +1 -0
  170. package/dist/es/style/index.js +59 -0
  171. package/dist/es/type/common.d.ts +7 -0
  172. package/dist/es/type/common.d.ts.map +1 -0
  173. package/dist/es/type/common.js +2 -0
  174. package/dist/es/type/condition.d.ts +3 -0
  175. package/dist/es/type/condition.d.ts.map +1 -0
  176. package/dist/es/type/condition.js +2 -0
  177. package/dist/es/type/config.d.ts +18 -0
  178. package/dist/es/type/config.d.ts.map +1 -0
  179. package/dist/es/type/config.js +2 -0
  180. package/dist/es/type/extract.d.ts +25 -0
  181. package/dist/es/type/extract.d.ts.map +1 -0
  182. package/dist/es/type/extract.js +2 -0
  183. package/dist/es/type/field.d.ts +30 -0
  184. package/dist/es/type/field.d.ts.map +1 -0
  185. package/dist/es/type/field.js +2 -0
  186. package/dist/es/type/form.d.ts +30 -0
  187. package/dist/es/type/form.d.ts.map +1 -0
  188. package/dist/es/type/form.js +2 -0
  189. package/dist/es/type/index.d.ts +8 -0
  190. package/dist/es/type/index.d.ts.map +1 -0
  191. package/dist/es/type/index.js +23 -0
  192. package/dist/es/type/validation.d.ts +14 -0
  193. package/dist/es/type/validation.d.ts.map +1 -0
  194. package/dist/es/type/validation.js +2 -0
  195. package/dist/es/util/index.d.ts +11 -0
  196. package/dist/es/util/index.d.ts.map +1 -0
  197. package/dist/es/util/index.js +100 -0
  198. package/dist/es/validation/index.d.ts +4 -0
  199. package/dist/es/validation/index.d.ts.map +1 -0
  200. package/dist/es/validation/index.js +57 -0
  201. package/package.json +100 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Becklyn Studios
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,281 @@
1
+ ## Table of Contents
2
+
3
+ 1. [Introduction](#introduction)
4
+ 2. [Getting Started](#getting-started)
5
+ 1. [Install dependencies](#1-install-dependencies)
6
+ 2. [Create a field component](#2-create-a-field-component)
7
+ 3. [Create a form config](#3-create-a-form-config)
8
+ 4. [Render the form](#4-render-the-form)
9
+ 3. [Typescript](#typescript)
10
+ 1. [Providing your own types](#providing-your-own-types)
11
+ 1. [Define the field config](#1-define-the-field-config)
12
+ 2. [Build intermediate type](#2-build-intermediate-type)
13
+ 3. [Patch form fields](#3-patch-form-fields)
14
+ 2. [Infer form config](#infer-form-config)
15
+ 4. [Guides](#guides)
16
+ 1. [Multistep](#multistep)
17
+
18
+ ## Introduction
19
+
20
+ This form lib is most likely overkill if your project requires a single static form with a few fields. If your project is build on highly dynamic forms it will help you to abstract most of the UI part and logic while keeping everything consistent.
21
+
22
+ It does so by following a config first approach. The idea is that after your first form, the following are created by writing a `FormConfig` only - something like this for a form with a single email input field:
23
+
24
+ ```typescript
25
+ export const forgotPasswordFormConfig = createFormConfig([
26
+ {
27
+ type: "text",
28
+ name: "email",
29
+ validations: [
30
+ {
31
+ validation: validateEmail,
32
+ },
33
+ ],
34
+ fieldConfig: {
35
+ placeholder: "E-Mail Adresse",
36
+ },
37
+ },
38
+ ]);
39
+ ```
40
+
41
+ ## Getting Started
42
+
43
+ ### 1. Install dependencies
44
+
45
+ ```
46
+ npm i --save @becklyn/forms
47
+ ```
48
+
49
+ ### 2. Create a field component
50
+
51
+ Create a single component to handle rendering all of your different input components. It will be called by the `FormBuilder` including the respective field's props.
52
+
53
+ ```tsx
54
+ export const FieldComponent: React.FC<FormBuilderChildrenProps> = ({
55
+ value,
56
+ error,
57
+ field,
58
+ onInput,
59
+ onBlur,
60
+ }) => {
61
+ const id = useId();
62
+
63
+ switch (field.type) {
64
+ case "text": {
65
+ const { name, fieldConfig } = field;
66
+ return (
67
+ <Text
68
+ {...fieldConfig}
69
+ id={id}
70
+ name={name}
71
+ value={value}
72
+ error={error}
73
+ onValueChanged={onInput}
74
+ onBlur={onBlur}
75
+ />
76
+ );
77
+ }
78
+ case "select": {
79
+ const { name, fieldConfig } = field;
80
+ return (
81
+ <Select
82
+ {...fieldConfig}
83
+ id={id}
84
+ value={value}
85
+ error={error}
86
+ onBlur={onBlur}
87
+ onSelect={onInput}
88
+ />
89
+ );
90
+ }
91
+ }
92
+ };
93
+ ```
94
+
95
+ ### 3. Create a form config
96
+
97
+ ```typescript
98
+ export const forgotPasswordFormConfig = createFormConfig([
99
+ {
100
+ type: "text",
101
+ name: "email",
102
+ validations: [
103
+ {
104
+ validation: validateEmail,
105
+ },
106
+ ],
107
+ fieldConfig: {
108
+ placeholder: "E-Mail Adresse",
109
+ },
110
+ },
111
+ ]);
112
+ ```
113
+
114
+ ### 4. Render the form
115
+
116
+ To render your form config the FormBuilder needs to be a descendant of `FormProvider` (or a component using `withForm`). An implementation could look something like this where the majority can easily be abstracted.
117
+
118
+ ```tsx
119
+ export const FormRenderer: React.FC = () => {
120
+ return <FormBuilder>{props => <WizardField {...props} />}</FormBuilder>;
121
+ };
122
+
123
+ export const LoginFormHandler = withForm(() => {
124
+ const { validateForm } = useForm();
125
+
126
+ const handleSubmit = (e: React.FormEvent) => {
127
+ e.preventDefault();
128
+ const formErrors = validateForm();
129
+
130
+ if (formErrors) {
131
+ return;
132
+ }
133
+ };
134
+
135
+ return (
136
+ <form onSubmit={handleSubmit}>
137
+ <FormRenderer />
138
+ <button type="submit">Submit</button>
139
+ </form>
140
+ );
141
+ });
142
+
143
+ export const SomeComponent: React.FC = () => {
144
+ return <LoginFormHandler config={forgotPasswordFormConfig} />;
145
+ };
146
+ ```
147
+
148
+ ## Typescript
149
+
150
+ ### Providing your own types
151
+
152
+ Each field comes with default props (e.g `id`, `value`, `onValueChanged`), however it is also possible to pass additional props via `fieldConfig` that are relevant based on the type of the field (e.g `maxLength` for a text input).
153
+
154
+ #### 1. Define the field config
155
+
156
+ Your fields should export a config interface that includes all the specific props for that field:
157
+
158
+ ```typescript
159
+ export interface TextFieldConfig {
160
+ placeholder: string;
161
+ label?: string;
162
+ maxLength?: number;
163
+ }
164
+ ```
165
+
166
+ #### 2. Build intermediate type
167
+
168
+ Create an intermediate type that forms can consume:
169
+
170
+ ```typescript
171
+ export type FormFieldText = FormFieldBasicConfig<"text", TextFieldConfig>;
172
+ ```
173
+
174
+ The first parameter specifies to which field the fieldConfig will be applied. Here `"text"` means that in your config, if you add `type: "text"`, the `fieldConfig` will expect props specified in `TextFieldConfig`.
175
+
176
+ #### 3. Patch form fields
177
+
178
+ To overwrite the `FormFieldConfig` you can patch the interface using module augmentation:
179
+
180
+ ```typescript
181
+ declare module "@becklyn/forms" {
182
+ interface CustomFormFieldConfig {
183
+ fields: FormFieldText | FormFieldNumber;
184
+ }
185
+ }
186
+ ```
187
+
188
+ ### Infer form config
189
+
190
+ To be able to infer a form config's type <ins>it must be readonly</ins>. You can use the following helper to infer your config:
191
+
192
+ ```typescript
193
+ type ForgotPasswordConfig = FormInfer<typeof forgotPasswordFormConfig>;
194
+ ```
195
+
196
+ <b>In case your types are not inferred correctly, immutability should be checked first:</b>
197
+
198
+ - Make sure you do not assert a type
199
+ - Object literals must be readonly
200
+ - Array literals must be readonly tuples
201
+
202
+ While this is true using `createFormConfig`, parts of your config that are rendered conditionally or created with a custom util function such as `createArray` might not be caught if not done properly. For custom functions make sure you are using generic type assertion with `const`. To help out with conditional rendering, a function called `eitherOr` is provided.
203
+
204
+ ```typescript
205
+ useMemo(() => {
206
+ return createFormConfig([
207
+ // Render a or b
208
+ eitherOr(
209
+ someCondition,
210
+ {
211
+ type: "text",
212
+ name: "email",
213
+ fieldConfig: {
214
+ placeholder: "E-Mail Adresse",
215
+ },
216
+ },
217
+ {
218
+ type: "text",
219
+ name: "phone",
220
+ fieldConfig: {
221
+ placeholder: "Telefonnummer",
222
+ },
223
+ }
224
+ ),
225
+ // Render a conditionally
226
+ eitherOr(
227
+ someCondition && {
228
+ type: "text",
229
+ name: "phone",
230
+ fieldConfig: {
231
+ placeholder: "Telefonnummer",
232
+ },
233
+ }
234
+ ),
235
+ ]);
236
+ }, [someCondition]);
237
+ ```
238
+
239
+ ## Guides
240
+
241
+ ### Multistep
242
+
243
+ Multistep can be achieved easily and abstracted into a custom component. The concept is simple: there's one parent provider handling all data and a child provider per step reporting to the parent.
244
+ While this lib handles the data, validations etc., you must still handle the multistep logic yourself.
245
+
246
+ ```tsx
247
+ const Step = withForm(() => {
248
+ const { validateForm } = useForm();
249
+
250
+ const handleSubmit = (e: React.FormEvent) => {
251
+ e.preventDefault();
252
+ const formErrors = validateForm();
253
+
254
+ if (formErrors) {
255
+ return;
256
+ }
257
+
258
+ // go to next step or submit form
259
+ };
260
+
261
+ return (
262
+ <form onSubmit={handleSubmit}>
263
+ <FormRenderer />
264
+ </form>
265
+ );
266
+ });
267
+
268
+ const MultiStep = withForm(() => {
269
+ // your custom hook
270
+ const { step } = useMultiStep();
271
+
272
+ switch (step) {
273
+ case 1:
274
+ return <Step config={firstStepConfig} inheritData />;
275
+ case 2:
276
+ return <Step config={secondStepConfig} inheritData />;
277
+ case 3:
278
+ return <Step config={thirdStepConfig} inheritData />;
279
+ }
280
+ });
281
+ ```
@@ -0,0 +1,3 @@
1
+ import { FormBuilderProps } from "../type";
2
+ export declare const FormBuilder: import("react").NamedExoticComponent<FormBuilderProps>;
3
+ //# sourceMappingURL=FormBuilder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FormBuilder.d.ts","sourceRoot":"","sources":["../../../components/FormBuilder.tsx"],"names":[],"mappings":"AASA,OAAO,EAAyB,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAUlE,eAAO,MAAM,WAAW,wDAoBvB,CAAC"}
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FormBuilder = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const context_1 = require("../context/data/context");
7
+ const guard_1 = require("../guard");
8
+ const style_1 = require("../style");
9
+ const FormEntry_1 = require("./FormEntry");
10
+ const DefaultComponents = {
11
+ BuilderWrapper: style_1.DefaultBuilderWrapper,
12
+ SectionWrapper: style_1.DefaultSectionWrapper,
13
+ RowWrapper: style_1.DefaultRowWrapper,
14
+ FieldWrapper: style_1.DefaultFieldWrapper,
15
+ };
16
+ exports.FormBuilder = (0, react_1.memo)(({ Components = DefaultComponents, children }) => {
17
+ const { BuilderWrapper } = Components;
18
+ const { config } = (0, react_1.useContext)(context_1.FormConfigContext);
19
+ const Wrapper = BuilderWrapper !== null && BuilderWrapper !== void 0 ? BuilderWrapper : style_1.DefaultBuilderWrapper;
20
+ return ((0, jsx_runtime_1.jsx)(Wrapper, { children: config.map((entry, index) => ((0, jsx_runtime_1.jsx)(FormEntry_1.FormEntry, { entry: entry, Components: Object.assign(Object.assign({}, DefaultComponents), Components), children: children }, index + ((0, guard_1.entryIsField)(entry) ? entry.name : "")))) }));
21
+ });
22
+ exports.FormBuilder.displayName = "FormBuilder";
@@ -0,0 +1,10 @@
1
+ import React from "react";
2
+ import { FormBuilderComponents, FormBuilderProps, FormCustomConfig } from "../type";
3
+ interface FormCustomProps {
4
+ Components: FormBuilderComponents;
5
+ custom: FormCustomConfig;
6
+ children: FormBuilderProps["children"];
7
+ }
8
+ export declare const FormCustom: React.FC<FormCustomProps>;
9
+ export {};
10
+ //# sourceMappingURL=FormCustom.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FormCustom.d.ts","sourceRoot":"","sources":["../../../components/FormCustom.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAGpF,UAAU,eAAe;IACrB,UAAU,EAAE,qBAAqB,CAAC;IAClC,MAAM,EAAE,gBAAgB,CAAC;IACzB,QAAQ,EAAE,gBAAgB,CAAC,UAAU,CAAC,CAAC;CAC1C;AAED,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAYhD,CAAC"}
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.FormCustom = void 0;
7
+ const jsx_runtime_1 = require("react/jsx-runtime");
8
+ const react_1 = __importDefault(require("react"));
9
+ const FormEntry_1 = require("./FormEntry");
10
+ const FormCustom = ({ Components, custom, children }) => {
11
+ return ((0, jsx_runtime_1.jsx)(react_1.default.Fragment, { children: custom.wrapper(custom.content.map((entry, index) => ((0, jsx_runtime_1.jsx)(FormEntry_1.FormEntry, { entry: entry, Components: Components, children: children }, index)))) }));
12
+ };
13
+ exports.FormCustom = FormCustom;
@@ -0,0 +1,10 @@
1
+ import React from "react";
2
+ import { FormBuilderComponents, FormBuilderProps, FormEntryConfig } from "../type";
3
+ interface FormEntryProps {
4
+ Components: FormBuilderComponents;
5
+ entry: FormEntryConfig;
6
+ children: FormBuilderProps["children"];
7
+ }
8
+ export declare const FormEntry: React.FC<FormEntryProps>;
9
+ export {};
10
+ //# sourceMappingURL=FormEntry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FormEntry.d.ts","sourceRoot":"","sources":["../../../components/FormEntry.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA2C,MAAM,OAAO,CAAC;AAGhE,OAAO,EAAE,qBAAqB,EAAE,gBAAgB,EAAY,eAAe,EAAE,MAAM,SAAS,CAAC;AAO7F,UAAU,cAAc;IACpB,UAAU,EAAE,qBAAqB,CAAC;IAClC,KAAK,EAAE,eAAe,CAAC;IACvB,QAAQ,EAAE,gBAAgB,CAAC,UAAU,CAAC,CAAC;CAC1C;AAED,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,cAAc,CA2D9C,CAAC"}
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FormEntry = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const condition_1 = require("../condition");
7
+ const context_1 = require("../context");
8
+ const util_1 = require("../util");
9
+ const FormCustom_1 = require("./FormCustom");
10
+ const FormField_1 = require("./FormField");
11
+ const FormRow_1 = require("./FormRow");
12
+ const FormSection_1 = require("./FormSection");
13
+ const FormEntry = ({ Components, entry, children }) => {
14
+ const { data, fieldConfigs } = (0, context_1.useForm)();
15
+ const getHasChildren = (0, react_1.useCallback)((formData) => {
16
+ switch (entry.type) {
17
+ case "custom":
18
+ case "section":
19
+ case "row":
20
+ return (0, util_1.someFieldConfigs)([entry], field => (0, condition_1.fieldFulfillsConditions)(field, fieldConfigs, formData));
21
+ default:
22
+ return (0, condition_1.fieldFulfillsConditions)(entry, fieldConfigs, formData);
23
+ }
24
+ }, [entry, fieldConfigs]);
25
+ const [hasChildren, setHasChildren] = (0, react_1.useState)(getHasChildren(data.get()));
26
+ (0, react_1.useEffect)(() => {
27
+ const remove = data.subscribe(() => {
28
+ setHasChildren(getHasChildren(data.get()));
29
+ });
30
+ return () => remove();
31
+ }, [getHasChildren, data]);
32
+ if (!hasChildren) {
33
+ return null;
34
+ }
35
+ switch (entry.type) {
36
+ case "custom":
37
+ return ((0, jsx_runtime_1.jsx)(FormCustom_1.FormCustom, { custom: entry, Components: Components, children: children }));
38
+ case "section":
39
+ return ((0, jsx_runtime_1.jsx)(FormSection_1.FormSection, { section: entry, Components: Components, children: children }));
40
+ case "row":
41
+ return ((0, jsx_runtime_1.jsx)(FormRow_1.FormRow, { row: entry, Components: Components, children: children }));
42
+ default:
43
+ return ((0, jsx_runtime_1.jsx)(FormField_1.FormField, { field: entry, Components: Components, children: children }));
44
+ }
45
+ };
46
+ exports.FormEntry = FormEntry;
@@ -0,0 +1,10 @@
1
+ import React from "react";
2
+ import { FormBuilderComponents, FormBuilderProps, FormFieldConfig } from "../type";
3
+ interface FormFieldProps {
4
+ Components: FormBuilderComponents;
5
+ field: FormFieldConfig;
6
+ children: FormBuilderProps["children"];
7
+ }
8
+ export declare const FormField: React.FC<FormFieldProps>;
9
+ export {};
10
+ //# sourceMappingURL=FormField.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FormField.d.ts","sourceRoot":"","sources":["../../../components/FormField.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA+B,MAAM,OAAO,CAAC;AAIpD,OAAO,EAEH,qBAAqB,EACrB,gBAAgB,EAChB,eAAe,EAClB,MAAM,SAAS,CAAC;AAEjB,UAAU,cAAc;IACpB,UAAU,EAAE,qBAAqB,CAAC;IAClC,KAAK,EAAE,eAAe,CAAC;IACvB,QAAQ,EAAE,gBAAgB,CAAC,UAAU,CAAC,CAAC;CAC1C;AAED,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,cAAc,CA4G9C,CAAC"}
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FormField = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const context_1 = require("../context");
7
+ const useFormData_1 = require("../hook/useFormData");
8
+ const useFormErrors_1 = require("../hook/useFormErrors");
9
+ const FormField = ({ Components, field, children }) => {
10
+ const { editData, validationStrategy: contextValidationStrategy, validateField, onInput, } = (0, context_1.useForm)();
11
+ const { name, columns, conditions, validations, valueFn, validationStrategy: fieldValidationStrategy, onInput: onFieldInput, fieldConfig: fieldConfigFunc, } = field;
12
+ const validationStrategy = (0, react_1.useMemo)(() => [fieldValidationStrategy, contextValidationStrategy], [fieldValidationStrategy, contextValidationStrategy]);
13
+ const hasValueFn = !!valueFn;
14
+ const hasConditions = !!conditions && Object.keys(conditions).length > 0;
15
+ const hasFieldConfigFunc = typeof fieldConfigFunc === "function";
16
+ const hasValidationFunc = !!validations && validations.some(({ validation }) => typeof validation === "function");
17
+ const rerenderWithData = hasValueFn || hasConditions || hasFieldConfigFunc || hasValidationFunc;
18
+ const [data, setStore, getStore] = (0, useFormData_1.useFormData)(rerenderWithData ? store => store : store => store[name]);
19
+ const [fieldError] = (0, useFormErrors_1.useFormErrors)(store => store[name]);
20
+ const value = rerenderWithData ? data[name] : data;
21
+ const normalizedValue = valueFn ? valueFn(data) : value;
22
+ const fieldConfig = hasFieldConfigFunc
23
+ ? fieldConfigFunc({ value: normalizedValue, data })
24
+ : fieldConfigFunc;
25
+ const handleInput = (0, react_1.useCallback)(value => {
26
+ let normalizedValue;
27
+ if (onFieldInput) {
28
+ normalizedValue = onFieldInput({
29
+ value,
30
+ field,
31
+ previousData: getStore(),
32
+ });
33
+ }
34
+ else if (onInput) {
35
+ normalizedValue = onInput({
36
+ value,
37
+ field,
38
+ previousData: getStore(),
39
+ });
40
+ }
41
+ else {
42
+ normalizedValue = { [field.name]: value };
43
+ }
44
+ editData.set(normalizedValue);
45
+ setStore(normalizedValue);
46
+ },
47
+ // eslint-disable-next-line react-hooks/exhaustive-deps
48
+ [field, setStore, getStore, onFieldInput, onInput]);
49
+ const handleBlur = (0, react_1.useCallback)(() => {
50
+ if (!validations || !validationStrategy.includes("blur")) {
51
+ return;
52
+ }
53
+ validateField(field);
54
+ }, [field, validations, validationStrategy, validateField]);
55
+ const fieldInputError = (() => {
56
+ var _a;
57
+ if (!validations || !validationStrategy.includes("input")) {
58
+ return;
59
+ }
60
+ const editValue = editData.get()[field.name];
61
+ if (editValue === undefined) {
62
+ return;
63
+ }
64
+ return (_a = validateField(field)) !== null && _a !== void 0 ? _a : undefined;
65
+ })();
66
+ const childrenProps = {
67
+ value: normalizedValue,
68
+ error: fieldError || fieldInputError,
69
+ onInput: handleInput,
70
+ onBlur: handleBlur,
71
+ field: Object.assign(Object.assign({}, field), { fieldConfig }),
72
+ };
73
+ const { FieldWrapper } = Components;
74
+ if (!FieldWrapper) {
75
+ throw new Error("No field component found");
76
+ }
77
+ return (0, jsx_runtime_1.jsx)(FieldWrapper, { columns: columns, children: children(childrenProps) });
78
+ };
79
+ exports.FormField = FormField;
@@ -0,0 +1,10 @@
1
+ import React from "react";
2
+ import { FormBuilderComponents, FormBuilderProps, FormRowConfig } from "../type";
3
+ interface FormRowProps {
4
+ Components: FormBuilderComponents;
5
+ row: FormRowConfig;
6
+ children: FormBuilderProps["children"];
7
+ }
8
+ export declare const FormRow: React.FC<FormRowProps>;
9
+ export {};
10
+ //# sourceMappingURL=FormRow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FormRow.d.ts","sourceRoot":"","sources":["../../../components/FormRow.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAGjF,UAAU,YAAY;IAClB,UAAU,EAAE,qBAAqB,CAAC;IAClC,GAAG,EAAE,aAAa,CAAC;IACnB,QAAQ,EAAE,gBAAgB,CAAC,UAAU,CAAC,CAAC;CAC1C;AAED,eAAO,MAAM,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,YAAY,CAgB1C,CAAC"}
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FormRow = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const FormEntry_1 = require("./FormEntry");
6
+ const FormRow = ({ Components, row, children }) => {
7
+ const { RowWrapper } = Components;
8
+ if (!RowWrapper) {
9
+ throw new Error(`No row component found.`);
10
+ }
11
+ return ((0, jsx_runtime_1.jsx)(RowWrapper, { children: row.content.map((entry, index) => ((0, jsx_runtime_1.jsx)(FormEntry_1.FormEntry, { entry: entry, Components: Components, children: children }, index))) }));
12
+ };
13
+ exports.FormRow = FormRow;
@@ -0,0 +1,10 @@
1
+ import React from "react";
2
+ import { FormBuilderComponents, FormBuilderProps, FormSectionConfig } from "../type";
3
+ interface FormSectionProps {
4
+ Components: FormBuilderComponents;
5
+ section: FormSectionConfig;
6
+ children: FormBuilderProps["children"];
7
+ }
8
+ export declare const FormSection: React.FC<FormSectionProps>;
9
+ export {};
10
+ //# sourceMappingURL=FormSection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FormSection.d.ts","sourceRoot":"","sources":["../../../components/FormSection.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAGrF,UAAU,gBAAgB;IACtB,UAAU,EAAE,qBAAqB,CAAC;IAClC,OAAO,EAAE,iBAAiB,CAAC;IAC3B,QAAQ,EAAE,gBAAgB,CAAC,UAAU,CAAC,CAAC;CAC1C;AAED,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CAgBlD,CAAC"}
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FormSection = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const FormEntry_1 = require("./FormEntry");
6
+ const FormSection = ({ Components, section, children }) => {
7
+ const { SectionWrapper } = Components;
8
+ if (!SectionWrapper) {
9
+ throw new Error(`No section component found.`);
10
+ }
11
+ return ((0, jsx_runtime_1.jsx)(SectionWrapper, { children: section.content.map((entry, index) => ((0, jsx_runtime_1.jsx)(FormEntry_1.FormEntry, { entry: entry, Components: Components, children: children }, index))) }));
12
+ };
13
+ exports.FormSection = FormSection;
@@ -0,0 +1,8 @@
1
+ import React, { ReactNode } from "react";
2
+ interface WatchFormValueProps {
3
+ name?: string;
4
+ children: (value: any) => ReactNode;
5
+ }
6
+ export declare const FormWatch: React.FC<WatchFormValueProps>;
7
+ export {};
8
+ //# sourceMappingURL=FormWatch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FormWatch.d.ts","sourceRoot":"","sources":["../../../components/FormWatch.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGzC,UAAU,mBAAmB;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,QAAQ,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,SAAS,CAAC;CACvC;AAED,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAInD,CAAC"}
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.FormWatch = void 0;
7
+ const jsx_runtime_1 = require("react/jsx-runtime");
8
+ const react_1 = __importDefault(require("react"));
9
+ const useFormData_1 = require("../hook/useFormData");
10
+ const FormWatch = ({ name, children }) => {
11
+ const [value] = (0, useFormData_1.useFormData)(store => (name ? store[name] : store));
12
+ return (0, jsx_runtime_1.jsx)(react_1.default.Fragment, { children: children(value) });
13
+ };
14
+ exports.FormWatch = FormWatch;
@@ -0,0 +1,3 @@
1
+ import { FormData, FormFieldConfig } from "../type";
2
+ export declare const fieldFulfillsConditions: ({ conditions }: Pick<FormFieldConfig, "conditions">, fieldConfigs: Record<string, FormFieldConfig>, data: FormData) => boolean;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../condition/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,QAAQ,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAEpE,eAAO,MAAM,uBAAuB,mBAChB,IAAI,CAAC,eAAe,EAAE,YAAY,CAAC,gBACrC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,QACvC,QAAQ,KACf,OAUF,CAAC"}
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fieldFulfillsConditions = void 0;
4
+ const fieldFulfillsConditions = ({ conditions }, fieldConfigs, data) => {
5
+ if (!conditions) {
6
+ return true;
7
+ }
8
+ return conditions.every(condition => {
9
+ return condition instanceof Array
10
+ ? condition.some(c => fulfillsConditions(c, fieldConfigs, data))
11
+ : fulfillsConditions(condition, fieldConfigs, data);
12
+ });
13
+ };
14
+ exports.fieldFulfillsConditions = fieldFulfillsConditions;
15
+ const fulfillsConditions = (conditions, fieldConfigs, data) => {
16
+ return Object.entries(conditions).every(([key, condition]) => {
17
+ var _a;
18
+ const { valueFn } = (_a = fieldConfigs[key]) !== null && _a !== void 0 ? _a : {};
19
+ const value = valueFn ? valueFn(data) : data[key];
20
+ switch (typeof condition) {
21
+ case "function":
22
+ return condition(value);
23
+ case "string":
24
+ return value === condition;
25
+ default:
26
+ return !!value === condition;
27
+ }
28
+ });
29
+ };
@@ -0,0 +1,7 @@
1
+ export declare const FormProvider: {
2
+ (props: import("./data").FormProviderProps & {
3
+ children?: import("react").ReactNode | undefined;
4
+ }): import("react/jsx-runtime").JSX.Element;
5
+ displayName: string;
6
+ };
7
+ //# sourceMappingURL=FormProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FormProvider.d.ts","sourceRoot":"","sources":["../../../context/FormProvider.tsx"],"names":[],"mappings":"AAOA,eAAO,MAAM,YAAY;;;;;CA2BxB,CAAC"}