@rebasepro/formex 0.4.0 → 0.6.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.
- package/README.md +87 -147
- package/dist/Formex.d.ts +1 -1
- package/dist/index.es.js +311 -475
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +365 -505
- package/dist/index.umd.js.map +1 -1
- package/package.json +10 -11
- package/src/utils.ts +1 -1
package/dist/index.umd.js
CHANGED
|
@@ -1,506 +1,366 @@
|
|
|
1
1
|
(function(global, factory) {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
} else {
|
|
368
|
-
delete newErrors[key_0];
|
|
369
|
-
}
|
|
370
|
-
return newErrors;
|
|
371
|
-
});
|
|
372
|
-
}, []);
|
|
373
|
-
const setFieldTouched = React.useCallback((key_1, touched, shouldValidate_0) => {
|
|
374
|
-
setTouchedState((prev) => ({
|
|
375
|
-
...prev,
|
|
376
|
-
[key_1]: touched
|
|
377
|
-
}));
|
|
378
|
-
if (shouldValidate_0) {
|
|
379
|
-
validate();
|
|
380
|
-
}
|
|
381
|
-
}, [validate]);
|
|
382
|
-
const handleChange = React.useCallback((event) => {
|
|
383
|
-
const target = event.target;
|
|
384
|
-
let value_0;
|
|
385
|
-
if (target.type === "checkbox") {
|
|
386
|
-
value_0 = target.checked;
|
|
387
|
-
} else if (target.type === "number") {
|
|
388
|
-
value_0 = target.valueAsNumber;
|
|
389
|
-
} else {
|
|
390
|
-
value_0 = target.value;
|
|
391
|
-
}
|
|
392
|
-
const name = target.name;
|
|
393
|
-
setFieldValue(name, value_0, validateOnChange);
|
|
394
|
-
setFieldTouched(name, true);
|
|
395
|
-
}, [setFieldValue, setFieldTouched, validateOnChange]);
|
|
396
|
-
const handleBlur = React.useCallback((event_0) => {
|
|
397
|
-
const target_0 = event_0.target;
|
|
398
|
-
const name_0 = target_0.name;
|
|
399
|
-
setFieldTouched(name_0, true);
|
|
400
|
-
}, [setFieldTouched]);
|
|
401
|
-
const submit = React.useCallback(async (e) => {
|
|
402
|
-
e?.preventDefault();
|
|
403
|
-
e?.stopPropagation();
|
|
404
|
-
setIsSubmitting(true);
|
|
405
|
-
setSubmitCount((prev_0) => prev_0 + 1);
|
|
406
|
-
const validationErrors_0 = await validation?.(valuesRef.current);
|
|
407
|
-
if (validationErrors_0 && Object.keys(validationErrors_0).length > 0) {
|
|
408
|
-
setErrors(validationErrors_0);
|
|
409
|
-
} else {
|
|
410
|
-
setErrors({});
|
|
411
|
-
await onSubmit?.(valuesRef.current, controllerRef.current);
|
|
412
|
-
}
|
|
413
|
-
setIsSubmitting(false);
|
|
414
|
-
setVersion((prev_1) => prev_1 + 1);
|
|
415
|
-
}, [onSubmit, validation]);
|
|
416
|
-
const resetForm = React.useCallback((props) => {
|
|
417
|
-
const {
|
|
418
|
-
submitCount: submitCountProp,
|
|
419
|
-
values: valuesProp,
|
|
420
|
-
errors: errorsProp,
|
|
421
|
-
touched: touchedProp
|
|
422
|
-
} = props ?? {};
|
|
423
|
-
valuesRef.current = valuesProp ?? initialValuesRef.current;
|
|
424
|
-
initialValuesRef.current = valuesProp ?? initialValuesRef.current;
|
|
425
|
-
setValuesInner(valuesProp ?? initialValuesRef.current);
|
|
426
|
-
setErrors(errorsProp ?? {});
|
|
427
|
-
setTouchedState(touchedProp ?? initialTouched ?? {});
|
|
428
|
-
setDirty(false);
|
|
429
|
-
setSubmitCount(submitCountProp ?? 0);
|
|
430
|
-
setVersion((prev_2) => prev_2 + 1);
|
|
431
|
-
onReset?.(controllerRef.current);
|
|
432
|
-
historyRef.current = [valuesProp ?? initialValuesRef.current];
|
|
433
|
-
historyIndexRef.current = 0;
|
|
434
|
-
}, [onReset, initialTouched]);
|
|
435
|
-
const undo = React.useCallback(() => {
|
|
436
|
-
if (historyIndexRef.current > 0) {
|
|
437
|
-
const newIndex = historyIndexRef.current - 1;
|
|
438
|
-
const newValues_1 = historyRef.current[newIndex];
|
|
439
|
-
setValuesInner(newValues_1);
|
|
440
|
-
valuesRef.current = newValues_1;
|
|
441
|
-
historyIndexRef.current = newIndex;
|
|
442
|
-
setDirty(!fastEquals.deepEqual(initialValuesRef.current, newValues_1));
|
|
443
|
-
callDebouncedOnValuesChange(newValues_1);
|
|
444
|
-
}
|
|
445
|
-
}, [callDebouncedOnValuesChange]);
|
|
446
|
-
const redo = React.useCallback(() => {
|
|
447
|
-
if (historyIndexRef.current < historyRef.current.length - 1) {
|
|
448
|
-
const newIndex_0 = historyIndexRef.current + 1;
|
|
449
|
-
const newValues_2 = historyRef.current[newIndex_0];
|
|
450
|
-
setValuesInner(newValues_2);
|
|
451
|
-
valuesRef.current = newValues_2;
|
|
452
|
-
historyIndexRef.current = newIndex_0;
|
|
453
|
-
setDirty(!fastEquals.deepEqual(initialValuesRef.current, newValues_2));
|
|
454
|
-
callDebouncedOnValuesChange(newValues_2);
|
|
455
|
-
}
|
|
456
|
-
}, [callDebouncedOnValuesChange]);
|
|
457
|
-
const controllerRef = React.useRef({});
|
|
458
|
-
const controller = React.useMemo(() => ({
|
|
459
|
-
values,
|
|
460
|
-
initialValues: initialValuesRef.current,
|
|
461
|
-
handleChange,
|
|
462
|
-
isSubmitting,
|
|
463
|
-
setSubmitting: setIsSubmitting,
|
|
464
|
-
setValues,
|
|
465
|
-
setFieldValue,
|
|
466
|
-
errors,
|
|
467
|
-
setFieldError,
|
|
468
|
-
touched: touchedState,
|
|
469
|
-
setFieldTouched,
|
|
470
|
-
setTouched: setTouchedState,
|
|
471
|
-
dirty,
|
|
472
|
-
setDirty,
|
|
473
|
-
handleSubmit: submit,
|
|
474
|
-
submitCount,
|
|
475
|
-
setSubmitCount,
|
|
476
|
-
handleBlur,
|
|
477
|
-
validate,
|
|
478
|
-
isValidating,
|
|
479
|
-
resetForm,
|
|
480
|
-
version,
|
|
481
|
-
debugId: debugIdRef.current,
|
|
482
|
-
undo,
|
|
483
|
-
redo,
|
|
484
|
-
canUndo: historyIndexRef.current > 0,
|
|
485
|
-
canRedo: historyIndexRef.current < historyRef.current.length - 1
|
|
486
|
-
}), [values, errors, touchedState, dirty, isSubmitting, submitCount, isValidating, version, handleChange, handleBlur, setValues, setFieldValue, setFieldTouched, setTouchedState, setFieldError, validate, submit, resetForm, undo, redo]);
|
|
487
|
-
React.useEffect(() => {
|
|
488
|
-
controllerRef.current = controller;
|
|
489
|
-
}, [controller]);
|
|
490
|
-
return controller;
|
|
491
|
-
}
|
|
492
|
-
exports2.Field = Field;
|
|
493
|
-
exports2.Formex = Formex;
|
|
494
|
-
exports2.clone = clone;
|
|
495
|
-
exports2.getIn = getIn;
|
|
496
|
-
exports2.isEmptyArray = isEmptyArray;
|
|
497
|
-
exports2.isFunction = isFunction;
|
|
498
|
-
exports2.isInteger = isInteger;
|
|
499
|
-
exports2.isNaN = isNaN;
|
|
500
|
-
exports2.isObject = isObject;
|
|
501
|
-
exports2.setIn = setIn;
|
|
502
|
-
exports2.useCreateFormex = useCreateFormex;
|
|
503
|
-
exports2.useFormex = useFormex;
|
|
504
|
-
Object.defineProperty(exports2, Symbol.toStringTag, { value: "Module" });
|
|
505
|
-
}));
|
|
506
|
-
//# sourceMappingURL=index.umd.js.map
|
|
2
|
+
typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("react"), require("react/jsx-runtime"), require("fast-equals")) : typeof define === "function" && define.amd ? define([
|
|
3
|
+
"exports",
|
|
4
|
+
"react",
|
|
5
|
+
"react/jsx-runtime",
|
|
6
|
+
"fast-equals"
|
|
7
|
+
], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global.Formex = {}, global.react, global.react_jsx_runtime, global.fastEquals));
|
|
8
|
+
})(this, function(exports, react, react_jsx_runtime, fast_equals) {
|
|
9
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
10
|
+
//#region \0rolldown/runtime.js
|
|
11
|
+
var __create = Object.create;
|
|
12
|
+
var __defProp = Object.defineProperty;
|
|
13
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
14
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
15
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
16
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
17
|
+
var __copyProps = (to, from, except, desc) => {
|
|
18
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
19
|
+
key = keys[i];
|
|
20
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
21
|
+
get: ((k) => from[k]).bind(null, key),
|
|
22
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
return to;
|
|
26
|
+
};
|
|
27
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
28
|
+
value: mod,
|
|
29
|
+
enumerable: true
|
|
30
|
+
}) : target, mod));
|
|
31
|
+
//#endregion
|
|
32
|
+
react = __toESM(react, 1);
|
|
33
|
+
//#region src/Formex.tsx
|
|
34
|
+
var FormexContext = react.default.createContext(null);
|
|
35
|
+
var useFormex = () => {
|
|
36
|
+
const ctx = (0, react.useContext)(FormexContext);
|
|
37
|
+
if (!ctx) throw new Error("useFormex must be used within a Formex provider");
|
|
38
|
+
return ctx;
|
|
39
|
+
};
|
|
40
|
+
var Formex = ({ value, children }) => {
|
|
41
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FormexContext.Provider, {
|
|
42
|
+
value,
|
|
43
|
+
children
|
|
44
|
+
});
|
|
45
|
+
};
|
|
46
|
+
//#endregion
|
|
47
|
+
//#region src/utils.ts
|
|
48
|
+
/** @private is the value an empty array? */
|
|
49
|
+
var isEmptyArray = (value) => Array.isArray(value) && value.length === 0;
|
|
50
|
+
/** @private is the given object a Function? */
|
|
51
|
+
var isFunction = (obj) => typeof obj === "function";
|
|
52
|
+
/** @private is the given object an Object? */
|
|
53
|
+
var isObject = (obj) => obj !== null && typeof obj === "object";
|
|
54
|
+
/** @private is the given object an integer? */
|
|
55
|
+
var isInteger = (obj) => String(Math.floor(Number(obj))) === obj;
|
|
56
|
+
/** @private is the given object a NaN? */
|
|
57
|
+
var isNaN = (obj) => obj !== obj;
|
|
58
|
+
/**
|
|
59
|
+
* Deeply get a value from an object via its path.
|
|
60
|
+
*/
|
|
61
|
+
function getIn(obj, key, def, p = 0) {
|
|
62
|
+
const path = toPath(key);
|
|
63
|
+
let current = obj;
|
|
64
|
+
while (current && p < path.length) current = current[path[p++]];
|
|
65
|
+
if (p !== path.length && !current) return def;
|
|
66
|
+
return current === void 0 ? def : current;
|
|
67
|
+
}
|
|
68
|
+
function setIn(obj, path, value) {
|
|
69
|
+
const res = clone(obj);
|
|
70
|
+
let resVal = res;
|
|
71
|
+
let i = 0;
|
|
72
|
+
const pathArray = toPath(path);
|
|
73
|
+
for (; i < pathArray.length - 1; i++) {
|
|
74
|
+
const currentPath = pathArray[i];
|
|
75
|
+
const currentObj = getIn(obj, pathArray.slice(0, i + 1));
|
|
76
|
+
if (currentObj && (isObject(currentObj) || Array.isArray(currentObj))) resVal = resVal[currentPath] = clone(currentObj);
|
|
77
|
+
else {
|
|
78
|
+
const nextPath = pathArray[i + 1];
|
|
79
|
+
resVal = resVal[currentPath] = isInteger(nextPath) && Number(nextPath) >= 0 ? [] : {};
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
if ((i === 0 ? obj : resVal)[pathArray[i]] === value) return obj;
|
|
83
|
+
if (value === void 0) delete resVal[pathArray[i]];
|
|
84
|
+
else resVal[pathArray[i]] = value;
|
|
85
|
+
if (i === 0 && value === void 0) delete res[pathArray[i]];
|
|
86
|
+
return res;
|
|
87
|
+
}
|
|
88
|
+
function clone(value) {
|
|
89
|
+
if (Array.isArray(value)) return [...value];
|
|
90
|
+
else if (typeof value === "object" && value !== null) {
|
|
91
|
+
if (Object.getPrototypeOf(value) !== Object.prototype) return value;
|
|
92
|
+
return { ...value };
|
|
93
|
+
} else return value;
|
|
94
|
+
}
|
|
95
|
+
function toPath(value) {
|
|
96
|
+
if (Array.isArray(value)) return value;
|
|
97
|
+
return value.replace(/\[(\d+)]/g, ".$1").replace(/^\./, "").replace(/\.$/, "").split(".");
|
|
98
|
+
}
|
|
99
|
+
//#endregion
|
|
100
|
+
//#region src/Field.tsx
|
|
101
|
+
function Field({ validate, name, children, as: is, className, ...props }) {
|
|
102
|
+
const formex = useFormex();
|
|
103
|
+
const field = getFieldProps({
|
|
104
|
+
name,
|
|
105
|
+
...props
|
|
106
|
+
}, formex);
|
|
107
|
+
if (isFunction(children)) return children({
|
|
108
|
+
field,
|
|
109
|
+
form: formex
|
|
110
|
+
});
|
|
111
|
+
const asElement = is || "input";
|
|
112
|
+
if (typeof asElement === "string") {
|
|
113
|
+
const { innerRef, ...rest } = props;
|
|
114
|
+
return react.createElement(asElement, {
|
|
115
|
+
ref: innerRef,
|
|
116
|
+
...field,
|
|
117
|
+
...rest,
|
|
118
|
+
className
|
|
119
|
+
}, children);
|
|
120
|
+
}
|
|
121
|
+
return react.createElement(asElement, {
|
|
122
|
+
...field,
|
|
123
|
+
...props,
|
|
124
|
+
className
|
|
125
|
+
}, children);
|
|
126
|
+
}
|
|
127
|
+
var getFieldProps = (nameOrOptions, formex) => {
|
|
128
|
+
const name = typeof nameOrOptions === "string" ? nameOrOptions : nameOrOptions.name;
|
|
129
|
+
const valueState = getIn(formex.values, name);
|
|
130
|
+
const field = {
|
|
131
|
+
name,
|
|
132
|
+
value: valueState,
|
|
133
|
+
onChange: formex.handleChange,
|
|
134
|
+
onBlur: formex.handleBlur
|
|
135
|
+
};
|
|
136
|
+
if (typeof nameOrOptions !== "string") {
|
|
137
|
+
const { type, value: valueProp, as: is, multiple } = nameOrOptions;
|
|
138
|
+
if (type === "checkbox") if (valueProp === void 0) field.checked = !!valueState;
|
|
139
|
+
else {
|
|
140
|
+
field.checked = !!(Array.isArray(valueState) && ~valueState.indexOf(valueProp));
|
|
141
|
+
field.value = valueProp;
|
|
142
|
+
}
|
|
143
|
+
else if (type === "radio") {
|
|
144
|
+
field.checked = valueState === valueProp;
|
|
145
|
+
field.value = valueProp;
|
|
146
|
+
} else if (is === "select" && multiple) {
|
|
147
|
+
field.value = field.value || [];
|
|
148
|
+
field.multiple = true;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return field;
|
|
152
|
+
};
|
|
153
|
+
//#endregion
|
|
154
|
+
//#region src/useCreateFormex.tsx
|
|
155
|
+
function useCreateFormex({ initialValues, initialErrors, initialDirty, initialTouched, validation, validateOnChange = false, validateOnInitialRender = false, onSubmit, onReset, onValuesChangeDeferred, debugId }) {
|
|
156
|
+
const initialValuesRef = (0, react.useRef)(initialValues);
|
|
157
|
+
const valuesRef = (0, react.useRef)(initialValues);
|
|
158
|
+
const debugIdRef = (0, react.useRef)(debugId);
|
|
159
|
+
const [values, setValuesInner] = (0, react.useState)(initialValues);
|
|
160
|
+
const [touchedState, setTouchedState] = (0, react.useState)(initialTouched ?? {});
|
|
161
|
+
const [errors, setErrors] = (0, react.useState)(initialErrors ?? {});
|
|
162
|
+
const [dirty, setDirty] = (0, react.useState)(initialDirty ?? false);
|
|
163
|
+
const [submitCount, setSubmitCount] = (0, react.useState)(0);
|
|
164
|
+
const [isSubmitting, setIsSubmitting] = (0, react.useState)(false);
|
|
165
|
+
const [isValidating, setIsValidating] = (0, react.useState)(false);
|
|
166
|
+
const [version, setVersion] = (0, react.useState)(0);
|
|
167
|
+
const onValuesChangeRef = (0, react.useRef)(onValuesChangeDeferred);
|
|
168
|
+
onValuesChangeRef.current = onValuesChangeDeferred;
|
|
169
|
+
const debounceTimeoutRef = (0, react.useRef)(void 0);
|
|
170
|
+
const callDebouncedOnValuesChange = (0, react.useCallback)((values) => {
|
|
171
|
+
if (onValuesChangeRef.current) {
|
|
172
|
+
if (debounceTimeoutRef.current) clearTimeout(debounceTimeoutRef.current);
|
|
173
|
+
debounceTimeoutRef.current = setTimeout(() => {
|
|
174
|
+
onValuesChangeRef.current?.(values, controllerRef.current);
|
|
175
|
+
}, 300);
|
|
176
|
+
}
|
|
177
|
+
}, []);
|
|
178
|
+
const historyRef = (0, react.useRef)([initialValues]);
|
|
179
|
+
const historyIndexRef = (0, react.useRef)(0);
|
|
180
|
+
(0, react.useEffect)(() => {
|
|
181
|
+
if (validateOnInitialRender) validate();
|
|
182
|
+
}, []);
|
|
183
|
+
const setValues = (0, react.useCallback)((newValues) => {
|
|
184
|
+
valuesRef.current = newValues;
|
|
185
|
+
setValuesInner(newValues);
|
|
186
|
+
setDirty(!(0, fast_equals.deepEqual)(initialValuesRef.current, newValues));
|
|
187
|
+
const newHistory = historyRef.current.slice(0, historyIndexRef.current + 1);
|
|
188
|
+
newHistory.push(newValues);
|
|
189
|
+
historyRef.current = newHistory;
|
|
190
|
+
historyIndexRef.current = newHistory.length - 1;
|
|
191
|
+
callDebouncedOnValuesChange(newValues);
|
|
192
|
+
}, [callDebouncedOnValuesChange]);
|
|
193
|
+
const validate = (0, react.useCallback)(async () => {
|
|
194
|
+
setIsValidating(true);
|
|
195
|
+
const validationErrors = await validation?.(valuesRef.current);
|
|
196
|
+
setErrors(validationErrors ?? {});
|
|
197
|
+
setIsValidating(false);
|
|
198
|
+
return validationErrors;
|
|
199
|
+
}, [validation]);
|
|
200
|
+
const setFieldValue = (0, react.useCallback)((key, value, shouldValidate) => {
|
|
201
|
+
const newValues = setIn(valuesRef.current, key, value);
|
|
202
|
+
valuesRef.current = newValues;
|
|
203
|
+
setValuesInner(newValues);
|
|
204
|
+
if (!(0, fast_equals.deepEqual)(getIn(initialValuesRef.current, key), value)) setDirty(true);
|
|
205
|
+
if (shouldValidate) validate();
|
|
206
|
+
const newHistory = historyRef.current.slice(0, historyIndexRef.current + 1);
|
|
207
|
+
newHistory.push(newValues);
|
|
208
|
+
historyRef.current = newHistory;
|
|
209
|
+
historyIndexRef.current = newHistory.length - 1;
|
|
210
|
+
callDebouncedOnValuesChange(newValues);
|
|
211
|
+
}, [validate, callDebouncedOnValuesChange]);
|
|
212
|
+
const setFieldError = (0, react.useCallback)((key, error) => {
|
|
213
|
+
setErrors((prevErrors) => {
|
|
214
|
+
const newErrors = { ...prevErrors };
|
|
215
|
+
if (error) newErrors[key] = error;
|
|
216
|
+
else delete newErrors[key];
|
|
217
|
+
return newErrors;
|
|
218
|
+
});
|
|
219
|
+
}, []);
|
|
220
|
+
const setFieldTouched = (0, react.useCallback)((key, touched, shouldValidate) => {
|
|
221
|
+
setTouchedState((prev) => ({
|
|
222
|
+
...prev,
|
|
223
|
+
[key]: touched
|
|
224
|
+
}));
|
|
225
|
+
if (shouldValidate) validate();
|
|
226
|
+
}, [validate]);
|
|
227
|
+
const handleChange = (0, react.useCallback)((event) => {
|
|
228
|
+
const target = event.target;
|
|
229
|
+
let value;
|
|
230
|
+
if (target.type === "checkbox") value = target.checked;
|
|
231
|
+
else if (target.type === "number") value = target.valueAsNumber;
|
|
232
|
+
else value = target.value;
|
|
233
|
+
const name = target.name;
|
|
234
|
+
setFieldValue(name, value, validateOnChange);
|
|
235
|
+
setFieldTouched(name, true);
|
|
236
|
+
}, [
|
|
237
|
+
setFieldValue,
|
|
238
|
+
setFieldTouched,
|
|
239
|
+
validateOnChange
|
|
240
|
+
]);
|
|
241
|
+
const handleBlur = (0, react.useCallback)((event) => {
|
|
242
|
+
const name = event.target.name;
|
|
243
|
+
setFieldTouched(name, true);
|
|
244
|
+
}, [setFieldTouched]);
|
|
245
|
+
const submit = (0, react.useCallback)(async (e) => {
|
|
246
|
+
e?.preventDefault();
|
|
247
|
+
e?.stopPropagation();
|
|
248
|
+
setIsSubmitting(true);
|
|
249
|
+
setSubmitCount((prev) => prev + 1);
|
|
250
|
+
const validationErrors = await validation?.(valuesRef.current);
|
|
251
|
+
if (validationErrors && Object.keys(validationErrors).length > 0) setErrors(validationErrors);
|
|
252
|
+
else {
|
|
253
|
+
setErrors({});
|
|
254
|
+
await onSubmit?.(valuesRef.current, controllerRef.current);
|
|
255
|
+
}
|
|
256
|
+
setIsSubmitting(false);
|
|
257
|
+
setVersion((prev) => prev + 1);
|
|
258
|
+
}, [onSubmit, validation]);
|
|
259
|
+
const resetForm = (0, react.useCallback)((props) => {
|
|
260
|
+
const { submitCount: submitCountProp, values: valuesProp, errors: errorsProp, touched: touchedProp } = props ?? {};
|
|
261
|
+
valuesRef.current = valuesProp ?? initialValuesRef.current;
|
|
262
|
+
initialValuesRef.current = valuesProp ?? initialValuesRef.current;
|
|
263
|
+
setValuesInner(valuesProp ?? initialValuesRef.current);
|
|
264
|
+
setErrors(errorsProp ?? {});
|
|
265
|
+
setTouchedState(touchedProp ?? initialTouched ?? {});
|
|
266
|
+
setDirty(false);
|
|
267
|
+
setSubmitCount(submitCountProp ?? 0);
|
|
268
|
+
setVersion((prev) => prev + 1);
|
|
269
|
+
onReset?.(controllerRef.current);
|
|
270
|
+
historyRef.current = [valuesProp ?? initialValuesRef.current];
|
|
271
|
+
historyIndexRef.current = 0;
|
|
272
|
+
}, [onReset, initialTouched]);
|
|
273
|
+
const undo = (0, react.useCallback)(() => {
|
|
274
|
+
if (historyIndexRef.current > 0) {
|
|
275
|
+
const newIndex = historyIndexRef.current - 1;
|
|
276
|
+
const newValues = historyRef.current[newIndex];
|
|
277
|
+
setValuesInner(newValues);
|
|
278
|
+
valuesRef.current = newValues;
|
|
279
|
+
historyIndexRef.current = newIndex;
|
|
280
|
+
setDirty(!(0, fast_equals.deepEqual)(initialValuesRef.current, newValues));
|
|
281
|
+
callDebouncedOnValuesChange(newValues);
|
|
282
|
+
}
|
|
283
|
+
}, [callDebouncedOnValuesChange]);
|
|
284
|
+
const redo = (0, react.useCallback)(() => {
|
|
285
|
+
if (historyIndexRef.current < historyRef.current.length - 1) {
|
|
286
|
+
const newIndex = historyIndexRef.current + 1;
|
|
287
|
+
const newValues = historyRef.current[newIndex];
|
|
288
|
+
setValuesInner(newValues);
|
|
289
|
+
valuesRef.current = newValues;
|
|
290
|
+
historyIndexRef.current = newIndex;
|
|
291
|
+
setDirty(!(0, fast_equals.deepEqual)(initialValuesRef.current, newValues));
|
|
292
|
+
callDebouncedOnValuesChange(newValues);
|
|
293
|
+
}
|
|
294
|
+
}, [callDebouncedOnValuesChange]);
|
|
295
|
+
const controllerRef = (0, react.useRef)({});
|
|
296
|
+
const controller = (0, react.useMemo)(() => ({
|
|
297
|
+
values,
|
|
298
|
+
initialValues: initialValuesRef.current,
|
|
299
|
+
handleChange,
|
|
300
|
+
isSubmitting,
|
|
301
|
+
setSubmitting: setIsSubmitting,
|
|
302
|
+
setValues,
|
|
303
|
+
setFieldValue,
|
|
304
|
+
errors,
|
|
305
|
+
setFieldError,
|
|
306
|
+
touched: touchedState,
|
|
307
|
+
setFieldTouched,
|
|
308
|
+
setTouched: setTouchedState,
|
|
309
|
+
dirty,
|
|
310
|
+
setDirty,
|
|
311
|
+
handleSubmit: submit,
|
|
312
|
+
submitCount,
|
|
313
|
+
setSubmitCount,
|
|
314
|
+
handleBlur,
|
|
315
|
+
validate,
|
|
316
|
+
isValidating,
|
|
317
|
+
resetForm,
|
|
318
|
+
version,
|
|
319
|
+
debugId: debugIdRef.current,
|
|
320
|
+
undo,
|
|
321
|
+
redo,
|
|
322
|
+
canUndo: historyIndexRef.current > 0,
|
|
323
|
+
canRedo: historyIndexRef.current < historyRef.current.length - 1
|
|
324
|
+
}), [
|
|
325
|
+
values,
|
|
326
|
+
errors,
|
|
327
|
+
touchedState,
|
|
328
|
+
dirty,
|
|
329
|
+
isSubmitting,
|
|
330
|
+
submitCount,
|
|
331
|
+
isValidating,
|
|
332
|
+
version,
|
|
333
|
+
handleChange,
|
|
334
|
+
handleBlur,
|
|
335
|
+
setValues,
|
|
336
|
+
setFieldValue,
|
|
337
|
+
setFieldTouched,
|
|
338
|
+
setTouchedState,
|
|
339
|
+
setFieldError,
|
|
340
|
+
validate,
|
|
341
|
+
submit,
|
|
342
|
+
resetForm,
|
|
343
|
+
undo,
|
|
344
|
+
redo
|
|
345
|
+
]);
|
|
346
|
+
(0, react.useEffect)(() => {
|
|
347
|
+
controllerRef.current = controller;
|
|
348
|
+
}, [controller]);
|
|
349
|
+
return controller;
|
|
350
|
+
}
|
|
351
|
+
//#endregion
|
|
352
|
+
exports.Field = Field;
|
|
353
|
+
exports.Formex = Formex;
|
|
354
|
+
exports.clone = clone;
|
|
355
|
+
exports.getIn = getIn;
|
|
356
|
+
exports.isEmptyArray = isEmptyArray;
|
|
357
|
+
exports.isFunction = isFunction;
|
|
358
|
+
exports.isInteger = isInteger;
|
|
359
|
+
exports.isNaN = isNaN;
|
|
360
|
+
exports.isObject = isObject;
|
|
361
|
+
exports.setIn = setIn;
|
|
362
|
+
exports.useCreateFormex = useCreateFormex;
|
|
363
|
+
exports.useFormex = useFormex;
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
//# sourceMappingURL=index.umd.js.map
|