react-f0rm 1.1.0 → 1.2.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 +152 -32
- package/dist/devtools/index.cjs.js +1 -1
- package/dist/devtools/index.cjs.js.map +1 -1
- package/dist/devtools/index.d.ts +2 -2
- package/dist/devtools/index.mjs +1 -1
- package/dist/devtools/index.mjs.map +1 -1
- package/dist/errors-CxSjrWJO.cjs.js +2 -0
- package/dist/errors-CxSjrWJO.cjs.js.map +1 -0
- package/dist/errors-CzWtwjO0.mjs +2 -0
- package/dist/errors-CzWtwjO0.mjs.map +1 -0
- package/dist/form-CvmWHUrd.d.ts +423 -0
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +786 -102
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +801 -354
- package/dist/index.umd.js.map +1 -1
- package/dist/index.umd.min.js +2 -2
- package/dist/index.umd.min.js.map +1 -1
- package/dist/persist.cjs.js +2 -0
- package/dist/persist.cjs.js.map +1 -0
- package/dist/persist.d.ts +49 -0
- package/dist/persist.mjs +2 -0
- package/dist/persist.mjs.map +1 -0
- package/dist/resolvers/standard-schema.cjs.js +1 -1
- package/dist/resolvers/standard-schema.cjs.js.map +1 -1
- package/dist/resolvers/standard-schema.d.ts +7 -5
- package/dist/resolvers/standard-schema.mjs +1 -1
- package/dist/resolvers/standard-schema.mjs.map +1 -1
- package/dist/resolvers/yup.cjs.js +1 -1
- package/dist/resolvers/yup.cjs.js.map +1 -1
- package/dist/resolvers/yup.d.ts +1 -1
- package/dist/resolvers/yup.mjs +1 -1
- package/dist/resolvers/yup.mjs.map +1 -1
- package/dist/resolvers/zod.cjs.js +1 -1
- package/dist/resolvers/zod.cjs.js.map +1 -1
- package/dist/resolvers/zod.d.ts +1 -1
- package/dist/resolvers/zod.mjs +1 -1
- package/dist/resolvers/zod.mjs.map +1 -1
- package/dist/server/index.cjs.js +2 -0
- package/dist/server/index.cjs.js.map +1 -0
- package/dist/server/index.d.ts +77 -0
- package/dist/server/index.mjs +2 -0
- package/dist/server/index.mjs.map +1 -0
- package/dist/validate-B1Gdjeaq.mjs +2 -0
- package/dist/validate-B1Gdjeaq.mjs.map +1 -0
- package/dist/validate-CUmNZqg6.d.ts +238 -0
- package/dist/validate-DAfz8Nbb.cjs.js +2 -0
- package/dist/validate-DAfz8Nbb.cjs.js.map +1 -0
- package/dist/values-B1IV-6V4.mjs +2 -0
- package/dist/values-B1IV-6V4.mjs.map +1 -0
- package/dist/values-CDNAYEOB.cjs.js +2 -0
- package/dist/values-CDNAYEOB.cjs.js.map +1 -0
- package/package.json +71 -24
- package/dist/form-BGWPwts2.mjs +0 -2
- package/dist/form-BGWPwts2.mjs.map +0 -1
- package/dist/form-BiDaJLjD.d.ts +0 -826
- package/dist/form-DwuY91QB.cjs.js +0 -2
- package/dist/form-DwuY91QB.cjs.js.map +0 -1
- package/dist/validate-2XUilILy.d.ts +0 -22
package/dist/index.umd.js
CHANGED
|
@@ -23,6 +23,67 @@
|
|
|
23
23
|
|
|
24
24
|
var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
|
|
25
25
|
|
|
26
|
+
function _arrayLikeToArray(r, a) {
|
|
27
|
+
(null == a || a > r.length) && (a = r.length);
|
|
28
|
+
for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
|
|
29
|
+
return n;
|
|
30
|
+
}
|
|
31
|
+
function _createForOfIteratorHelper(r, e) {
|
|
32
|
+
var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
|
|
33
|
+
if (!t) {
|
|
34
|
+
if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e) {
|
|
35
|
+
t && (r = t);
|
|
36
|
+
var n = 0,
|
|
37
|
+
F = function () {};
|
|
38
|
+
return {
|
|
39
|
+
s: F,
|
|
40
|
+
n: function () {
|
|
41
|
+
return n >= r.length ? {
|
|
42
|
+
done: true
|
|
43
|
+
} : {
|
|
44
|
+
done: false,
|
|
45
|
+
value: r[n++]
|
|
46
|
+
};
|
|
47
|
+
},
|
|
48
|
+
e: function (r) {
|
|
49
|
+
throw r;
|
|
50
|
+
},
|
|
51
|
+
f: F
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
55
|
+
}
|
|
56
|
+
var o,
|
|
57
|
+
a = true,
|
|
58
|
+
u = false;
|
|
59
|
+
return {
|
|
60
|
+
s: function () {
|
|
61
|
+
t = t.call(r);
|
|
62
|
+
},
|
|
63
|
+
n: function () {
|
|
64
|
+
var r = t.next();
|
|
65
|
+
return a = r.done, r;
|
|
66
|
+
},
|
|
67
|
+
e: function (r) {
|
|
68
|
+
u = true, o = r;
|
|
69
|
+
},
|
|
70
|
+
f: function () {
|
|
71
|
+
try {
|
|
72
|
+
a || null == t.return || t.return();
|
|
73
|
+
} finally {
|
|
74
|
+
if (u) throw o;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
function _unsupportedIterableToArray(r, a) {
|
|
80
|
+
if (r) {
|
|
81
|
+
if ("string" == typeof r) return _arrayLikeToArray(r, a);
|
|
82
|
+
var t = {}.toString.call(r).slice(8, -1);
|
|
83
|
+
return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
26
87
|
function getSet(ee, key) {
|
|
27
88
|
var set = ee.get(key);
|
|
28
89
|
if (set) return set;
|
|
@@ -30,31 +91,101 @@
|
|
|
30
91
|
ee.set(key, newSet);
|
|
31
92
|
return newSet;
|
|
32
93
|
}
|
|
94
|
+
|
|
95
|
+
// DEV-only listener-leak warning. Checked via process.env.NODE_ENV because the
|
|
96
|
+
// build pipeline has no compile-time constant injection; the typeof guard
|
|
97
|
+
// keeps direct browser usage of the UMD build safe. In production the whole
|
|
98
|
+
// machinery is skipped and `on` only pays one boolean test.
|
|
99
|
+
var DEV = typeof process !== 'undefined' && process.env && process.env.NODE_ENV !== 'production';
|
|
100
|
+
var DEFAULT_MAX_LISTENERS = 10;
|
|
101
|
+
var maxListenersMap = new WeakMap();
|
|
102
|
+
var warnedKeysMap = new WeakMap();
|
|
103
|
+
function _setMaxListeners(ee, n) {
|
|
104
|
+
maxListenersMap.set(ee, n);
|
|
105
|
+
}
|
|
106
|
+
function checkMaxListeners(ee, key, size) {
|
|
107
|
+
var max = maxListenersMap.get(ee);
|
|
108
|
+
if (max === undefined) max = DEFAULT_MAX_LISTENERS;
|
|
109
|
+
if (max <= 0 || size <= max) return;
|
|
110
|
+
var warnedKeys = warnedKeysMap.get(ee);
|
|
111
|
+
if (!warnedKeys) {
|
|
112
|
+
warnedKeys = new Set();
|
|
113
|
+
warnedKeysMap.set(ee, warnedKeys);
|
|
114
|
+
}
|
|
115
|
+
if (warnedKeys.has(key)) return;
|
|
116
|
+
warnedKeys.add(key);
|
|
117
|
+
// eslint-disable-next-line no-console
|
|
118
|
+
console.warn("Possible event-emitter memory leak: ".concat(size, " \"").concat(String(key), "\" listeners added. ") + "Use setMaxListeners(ee, n) to raise the limit, or 0 to disable this warning.");
|
|
119
|
+
}
|
|
120
|
+
var errorEvent = Symbol('error');
|
|
33
121
|
function create$2() {
|
|
34
122
|
return new Map();
|
|
35
123
|
}
|
|
124
|
+
|
|
125
|
+
// A throwing handler must not stop its peers: errors are collected while the
|
|
126
|
+
// remaining handlers still run, then reported through emitError (the
|
|
127
|
+
// errorEvent channel). If no error handler is subscribed either, the first
|
|
128
|
+
// collected error is rethrown to the emit caller instead of being swallowed.
|
|
129
|
+
// Iteration follows Set semantics: a listener added while this emit runs is
|
|
130
|
+
// still visited by that same emit, and a listener removed before it is
|
|
131
|
+
// visited is skipped. Removing a whole key (off/removeAllListeners) does not
|
|
132
|
+
// affect an emit already in flight.
|
|
36
133
|
function emit(ee, key) {
|
|
37
134
|
for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
|
|
38
135
|
args[_key - 2] = arguments[_key];
|
|
39
136
|
}
|
|
40
|
-
|
|
41
|
-
|
|
137
|
+
var set = ee.get(key);
|
|
138
|
+
if (!set || !set.size) return;
|
|
139
|
+
var errors;
|
|
140
|
+
set.forEach(function (h) {
|
|
141
|
+
try {
|
|
142
|
+
h.apply(void 0, args);
|
|
143
|
+
} catch (err) {
|
|
144
|
+
if (errors) errors.push(err);else errors = [err];
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
if (errors) {
|
|
148
|
+
var _iterator = _createForOfIteratorHelper(errors),
|
|
149
|
+
_step;
|
|
150
|
+
try {
|
|
151
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
152
|
+
var err = _step.value;
|
|
153
|
+
emitError(ee, err);
|
|
154
|
+
}
|
|
155
|
+
} catch (err) {
|
|
156
|
+
_iterator.e(err);
|
|
157
|
+
} finally {
|
|
158
|
+
_iterator.f();
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
function emitError(ee, err) {
|
|
163
|
+
var handlerSet = ee.get(errorEvent);
|
|
164
|
+
if (!handlerSet || !handlerSet.size) throw err;
|
|
165
|
+
handlerSet.forEach(function (h) {
|
|
166
|
+
return h(err);
|
|
42
167
|
});
|
|
43
168
|
}
|
|
44
169
|
function on(ee, key, handler) {
|
|
45
170
|
var set = getSet(ee, key);
|
|
46
171
|
set.add(handler);
|
|
172
|
+
if (DEV) checkMaxListeners(ee, key, set.size);
|
|
47
173
|
return function () {
|
|
48
174
|
return set.delete(handler);
|
|
49
175
|
};
|
|
50
176
|
}
|
|
51
177
|
|
|
178
|
+
const PATH_CACHE_LIMIT = 1e4;
|
|
52
179
|
const pathCache = /* @__PURE__ */ new Map();
|
|
53
180
|
function normalizePath(path) {
|
|
54
181
|
if (Array.isArray(path)) return path;
|
|
55
182
|
const cached = pathCache.get(path);
|
|
56
183
|
if (cached) return cached;
|
|
57
184
|
const value = parsePath(path);
|
|
185
|
+
if (pathCache.size >= PATH_CACHE_LIMIT) {
|
|
186
|
+
const oldest = pathCache.keys().next();
|
|
187
|
+
if (!oldest.done) pathCache.delete(oldest.value);
|
|
188
|
+
}
|
|
58
189
|
pathCache.set(path, value);
|
|
59
190
|
return value;
|
|
60
191
|
}
|
|
@@ -225,110 +356,59 @@
|
|
|
225
356
|
return { value, key: JSON.stringify(value) };
|
|
226
357
|
}
|
|
227
358
|
|
|
228
|
-
const VALIDATION_OUTCOME = /* @__PURE__ */ Symbol("validation-outcome");
|
|
229
|
-
function create(options) {
|
|
230
|
-
const emitter = create$2();
|
|
231
|
-
return {
|
|
232
|
-
emitter,
|
|
233
|
-
...options,
|
|
234
|
-
mode: options?.mode ?? "onSubmit",
|
|
235
|
-
reValidateMode: options?.reValidateMode ?? "onChange",
|
|
236
|
-
disabled: options?.disabled ?? false,
|
|
237
|
-
validateDeps: options?.validateDeps ? new Set(options.validateDeps.map((dep) => create$1(dep).key)) : void 0,
|
|
238
|
-
initialValues: options?.initialValues ?? {},
|
|
239
|
-
values: /* @__PURE__ */ new Map(),
|
|
240
|
-
deleted: /* @__PURE__ */ new Set(),
|
|
241
|
-
errors: /* @__PURE__ */ new Map(),
|
|
242
|
-
touched: /* @__PURE__ */ new Set(),
|
|
243
|
-
validators: /* @__PURE__ */ new Map(),
|
|
244
|
-
changeHandlers: /* @__PURE__ */ new Map(),
|
|
245
|
-
validating: /* @__PURE__ */ new Set(),
|
|
246
|
-
parsedValues: void 0,
|
|
247
|
-
isSubmitting: false,
|
|
248
|
-
submitCount: 0,
|
|
249
|
-
isSubmitSuccessful: void 0
|
|
250
|
-
};
|
|
251
|
-
}
|
|
252
359
|
const valuesCaches = /* @__PURE__ */ new WeakMap();
|
|
253
360
|
function bumpValuesVersion(form) {
|
|
254
361
|
const cache = valuesCaches.get(form);
|
|
255
362
|
if (cache) cache.version++;
|
|
256
363
|
}
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
} else if (cache.version > 0) {
|
|
263
|
-
cache.result = computeValues(form);
|
|
264
|
-
cache.version = 0;
|
|
265
|
-
}
|
|
266
|
-
return cache.result;
|
|
364
|
+
const dirtyBaselines = /* @__PURE__ */ new WeakMap();
|
|
365
|
+
function getDirtyBaseline(form, key, segments) {
|
|
366
|
+
const baselines = dirtyBaselines.get(form);
|
|
367
|
+
if (baselines?.has(key)) return baselines.get(key);
|
|
368
|
+
return get(form.initialValues, segments);
|
|
267
369
|
}
|
|
268
|
-
function
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
merged = setOwned(merged, JSON.parse(key), value, owned);
|
|
274
|
-
}
|
|
275
|
-
for (const key of deleted) {
|
|
276
|
-
merged = unset(merged, JSON.parse(key));
|
|
370
|
+
function setDirtyBaseline(form, { key }, value) {
|
|
371
|
+
let baselines = dirtyBaselines.get(form);
|
|
372
|
+
if (!baselines) {
|
|
373
|
+
baselines = /* @__PURE__ */ new Map();
|
|
374
|
+
dirtyBaselines.set(form, baselines);
|
|
277
375
|
}
|
|
278
|
-
|
|
279
|
-
}
|
|
280
|
-
function getValue(form, name) {
|
|
281
|
-
return getValueByPath(form, create$1(name));
|
|
376
|
+
baselines.set(key, value);
|
|
282
377
|
}
|
|
283
|
-
function
|
|
284
|
-
const
|
|
285
|
-
if (
|
|
286
|
-
|
|
287
|
-
for (
|
|
288
|
-
|
|
289
|
-
if (values.has(ancestorKey)) {
|
|
290
|
-
return get(values.get(ancestorKey), segments.slice(i));
|
|
291
|
-
}
|
|
378
|
+
function pruneDirtyBaselines(form, { key }) {
|
|
379
|
+
const baselines = dirtyBaselines.get(form);
|
|
380
|
+
if (!baselines?.size) return;
|
|
381
|
+
const stem = `${key.slice(0, -1)},`;
|
|
382
|
+
for (const baselineKey of baselines.keys()) {
|
|
383
|
+
if (baselineKey.startsWith(stem)) baselines.delete(baselineKey);
|
|
292
384
|
}
|
|
293
|
-
return get(parsedValues ?? initialValues, segments);
|
|
294
385
|
}
|
|
295
|
-
function
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
values.set(path.key, value);
|
|
301
|
-
pruneDescendantKeys(values, path);
|
|
302
|
-
reviveBranch(deleted, path);
|
|
303
|
-
pruneDirtyBaselines(form, path);
|
|
304
|
-
if (options?.shouldDirty === false) setDirtyBaseline(form, path, value);
|
|
305
|
-
bumpDirtyVersion(form);
|
|
306
|
-
bumpValuesVersion(form);
|
|
307
|
-
if (options?.shouldTouch) setTouchedByPath(form, path);
|
|
308
|
-
if (options?.shouldValidate) form.validators.get(path.key)?.();
|
|
309
|
-
emit(emitter, "change", path);
|
|
386
|
+
function clearDirtyBaselines(form, key) {
|
|
387
|
+
const baselines = dirtyBaselines.get(form);
|
|
388
|
+
if (!baselines) return;
|
|
389
|
+
if (key === void 0) baselines.clear();
|
|
390
|
+
else baselines.delete(key);
|
|
310
391
|
}
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
reviveBranch(deleted, path);
|
|
316
|
-
pruneDirtyBaselines(form, path);
|
|
317
|
-
bumpDirtyVersion(form);
|
|
318
|
-
bumpValuesVersion(form);
|
|
392
|
+
const dirtyFieldsCaches = /* @__PURE__ */ new WeakMap();
|
|
393
|
+
function bumpDirtyVersion(form) {
|
|
394
|
+
const cache = dirtyFieldsCaches.get(form);
|
|
395
|
+
if (cache) cache.version++;
|
|
319
396
|
}
|
|
320
|
-
function
|
|
321
|
-
|
|
397
|
+
function isSegmentsPath(name) {
|
|
398
|
+
return name.some((part) => typeof part === "number");
|
|
322
399
|
}
|
|
323
|
-
function
|
|
324
|
-
|
|
400
|
+
function isFieldError(value) {
|
|
401
|
+
return !!value && typeof value === "object" && typeof value.type === "string" && typeof value.message === "string";
|
|
325
402
|
}
|
|
326
|
-
function
|
|
327
|
-
if (
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
403
|
+
function setParsedValues(form, values) {
|
|
404
|
+
if (values === void 0 || values === form.parsedValues) return;
|
|
405
|
+
form.parsedValues = values;
|
|
406
|
+
bumpValuesVersion(form);
|
|
407
|
+
emit(form.emitter, "change");
|
|
331
408
|
}
|
|
409
|
+
|
|
410
|
+
const FORM_ERROR = "_form";
|
|
411
|
+
const VALIDATION_OUTCOME = /* @__PURE__ */ Symbol("validation-outcome");
|
|
332
412
|
function getError(form, name) {
|
|
333
413
|
return getErrorByPath(form, create$1(name));
|
|
334
414
|
}
|
|
@@ -353,29 +433,6 @@
|
|
|
353
433
|
function getFirstError({ errors }) {
|
|
354
434
|
return errors.values().next().value?.[0]?.message;
|
|
355
435
|
}
|
|
356
|
-
function getFieldState(form, name) {
|
|
357
|
-
const path = create$1(name);
|
|
358
|
-
const { values, touched, validating } = form;
|
|
359
|
-
const live = values.get(path.key);
|
|
360
|
-
return {
|
|
361
|
-
value: getValueByPath(form, path),
|
|
362
|
-
error: getErrorByPath(form, path),
|
|
363
|
-
errors: getFieldErrorsByPath(form, path),
|
|
364
|
-
// Same rule as getDirtyFields, committed baselines included: the field
|
|
365
|
-
// is dirty while its live value differs from its effective baseline.
|
|
366
|
-
isDirty: values.has(path.key) && getDirtyBaseline(form, path.key, path.value) !== live,
|
|
367
|
-
isTouched: touched.has(path.key),
|
|
368
|
-
isValidating: validating.has(path.key)
|
|
369
|
-
};
|
|
370
|
-
}
|
|
371
|
-
function unsetValidatingByPath({ emitter, validating }, path) {
|
|
372
|
-
validating.delete(path.key);
|
|
373
|
-
emit(emitter, "validating", path);
|
|
374
|
-
}
|
|
375
|
-
function setValidatingByPath({ emitter, validating }, path) {
|
|
376
|
-
validating.add(path.key);
|
|
377
|
-
emit(emitter, "validating", path);
|
|
378
|
-
}
|
|
379
436
|
function setError(form, name, error) {
|
|
380
437
|
setErrorByPath(form, create$1(name), error);
|
|
381
438
|
}
|
|
@@ -425,6 +482,10 @@
|
|
|
425
482
|
);
|
|
426
483
|
}
|
|
427
484
|
}
|
|
485
|
+
function hasErrors({ errors }) {
|
|
486
|
+
return errors.size > 0;
|
|
487
|
+
}
|
|
488
|
+
|
|
428
489
|
function setTouched(form, name) {
|
|
429
490
|
setTouchedByPath(form, create$1(name));
|
|
430
491
|
}
|
|
@@ -439,97 +500,111 @@
|
|
|
439
500
|
function hasTouchedByPath({ touched }, path) {
|
|
440
501
|
return touched.has(path.key);
|
|
441
502
|
}
|
|
442
|
-
function
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
return dirty;
|
|
448
|
-
}
|
|
449
|
-
function forEachDirtyField(form, fn) {
|
|
450
|
-
for (const [key, value] of form.values) {
|
|
451
|
-
const path = JSON.parse(key);
|
|
452
|
-
if (getDirtyBaseline(form, key, path) !== value) fn(path.join("."));
|
|
453
|
-
}
|
|
503
|
+
function getTouchedFields({ touched }) {
|
|
504
|
+
return Array.from(
|
|
505
|
+
touched,
|
|
506
|
+
(key) => JSON.parse(key).join(".")
|
|
507
|
+
);
|
|
454
508
|
}
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
const baselines = dirtyBaselines.get(form);
|
|
458
|
-
if (baselines?.has(key)) return baselines.get(key);
|
|
459
|
-
return get(form.initialValues, segments);
|
|
509
|
+
function isTouched({ touched }) {
|
|
510
|
+
return touched.size > 0;
|
|
460
511
|
}
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
512
|
+
|
|
513
|
+
function getValues(form) {
|
|
514
|
+
let cache = valuesCaches.get(form);
|
|
515
|
+
if (!cache) {
|
|
516
|
+
cache = { version: 0, result: computeValues(form) };
|
|
517
|
+
valuesCaches.set(form, cache);
|
|
518
|
+
} else if (cache.version > 0) {
|
|
519
|
+
cache.result = computeValues(form);
|
|
520
|
+
cache.version = 0;
|
|
466
521
|
}
|
|
467
|
-
|
|
522
|
+
return cache.result;
|
|
468
523
|
}
|
|
469
|
-
function
|
|
470
|
-
const
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
for (const
|
|
474
|
-
|
|
524
|
+
function computeValues(form) {
|
|
525
|
+
const { initialValues, parsedValues, values, deleted } = form;
|
|
526
|
+
const owned = /* @__PURE__ */ new Set();
|
|
527
|
+
let merged = parsedValues ?? initialValues;
|
|
528
|
+
for (const [key, value] of values) {
|
|
529
|
+
merged = setOwned(merged, JSON.parse(key), value, owned);
|
|
475
530
|
}
|
|
531
|
+
for (const key of deleted) {
|
|
532
|
+
merged = unset(merged, JSON.parse(key));
|
|
533
|
+
}
|
|
534
|
+
return merged;
|
|
476
535
|
}
|
|
477
|
-
function
|
|
478
|
-
|
|
479
|
-
if (!baselines) return;
|
|
480
|
-
if (key === void 0) baselines.clear();
|
|
481
|
-
else baselines.delete(key);
|
|
536
|
+
function getValue(form, name) {
|
|
537
|
+
return getValueByPath(form, create$1(name));
|
|
482
538
|
}
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
if (
|
|
539
|
+
function getValueByPath({ initialValues, parsedValues, values, deleted }, path) {
|
|
540
|
+
const { key, value: segments } = path;
|
|
541
|
+
if (values.has(key)) return values.get(key);
|
|
542
|
+
if (deleted.has(key)) return void 0;
|
|
543
|
+
for (let i = segments.length - 1; i > 0; i--) {
|
|
544
|
+
const ancestorKey = JSON.stringify(segments.slice(0, i));
|
|
545
|
+
if (values.has(ancestorKey)) {
|
|
546
|
+
return get(values.get(ancestorKey), segments.slice(i));
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
return get(parsedValues ?? initialValues, segments);
|
|
487
550
|
}
|
|
488
|
-
function
|
|
489
|
-
|
|
490
|
-
forEachDirtyField(form, (key) => {
|
|
491
|
-
dirtyFields[key] = true;
|
|
492
|
-
});
|
|
493
|
-
return dirtyFields;
|
|
551
|
+
function setValue(form, name, value, options) {
|
|
552
|
+
setValueByPath(form, create$1(name), value, options);
|
|
494
553
|
}
|
|
495
|
-
function
|
|
496
|
-
const
|
|
497
|
-
|
|
498
|
-
|
|
554
|
+
function setValueByPath(form, path, value, options) {
|
|
555
|
+
const { emitter, values, deleted } = form;
|
|
556
|
+
values.set(path.key, value);
|
|
557
|
+
pruneDescendantKeys(values, path);
|
|
558
|
+
reviveBranch(deleted, path);
|
|
559
|
+
pruneDirtyBaselines(form, path);
|
|
560
|
+
if (options?.shouldDirty === false) setDirtyBaseline(form, path, value);
|
|
561
|
+
bumpDirtyVersion(form);
|
|
562
|
+
bumpValuesVersion(form);
|
|
563
|
+
if (options?.shouldTouch) setTouchedByPath(form, path);
|
|
564
|
+
if (options?.shouldValidate) form.validators.get(path.key)?.();
|
|
565
|
+
emit(emitter, "change", path);
|
|
499
566
|
}
|
|
500
|
-
function
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
cache.version = 0;
|
|
509
|
-
}
|
|
510
|
-
return cache.result;
|
|
567
|
+
function seedValueByPath(form, path, value) {
|
|
568
|
+
const { values, deleted } = form;
|
|
569
|
+
values.set(path.key, value);
|
|
570
|
+
pruneDescendantKeys(values, path);
|
|
571
|
+
reviveBranch(deleted, path);
|
|
572
|
+
pruneDirtyBaselines(form, path);
|
|
573
|
+
bumpDirtyVersion(form);
|
|
574
|
+
bumpValuesVersion(form);
|
|
511
575
|
}
|
|
512
|
-
function
|
|
513
|
-
|
|
514
|
-
touched,
|
|
515
|
-
(key) => JSON.parse(key).join(".")
|
|
516
|
-
);
|
|
576
|
+
function emitChangeByPath({ emitter }, path) {
|
|
577
|
+
emit(emitter, "change", path);
|
|
517
578
|
}
|
|
518
|
-
function
|
|
519
|
-
|
|
579
|
+
function getFieldState(form, name) {
|
|
580
|
+
const path = create$1(name);
|
|
581
|
+
const { values, touched, validating } = form;
|
|
582
|
+
const live = values.get(path.key);
|
|
583
|
+
return {
|
|
584
|
+
value: getValueByPath(form, path),
|
|
585
|
+
error: getErrorByPath(form, path),
|
|
586
|
+
errors: getFieldErrorsByPath(form, path),
|
|
587
|
+
// Same rule as getDirtyFields, committed baselines included: the field
|
|
588
|
+
// is dirty while its live value differs from its effective baseline.
|
|
589
|
+
isDirty: values.has(path.key) && getDirtyBaseline(form, path.key, path.value) !== live,
|
|
590
|
+
isTouched: touched.has(path.key),
|
|
591
|
+
isValidating: validating.has(path.key)
|
|
592
|
+
};
|
|
520
593
|
}
|
|
521
|
-
function removeField(form, name) {
|
|
522
|
-
removeFieldByPath(form, create$1(name));
|
|
594
|
+
function removeField(form, name, options) {
|
|
595
|
+
removeFieldByPath(form, create$1(name), options);
|
|
523
596
|
}
|
|
524
|
-
function removeFieldByPath(form, path) {
|
|
597
|
+
function removeFieldByPath(form, path, options) {
|
|
525
598
|
const { key, value: segments } = path;
|
|
526
599
|
const { emitter, values, touched, errors, validating, deleted } = form;
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
600
|
+
if (!options?.keepValue && !options?.keepDirty) {
|
|
601
|
+
values.delete(key);
|
|
602
|
+
clearDirtyBaselines(form, key);
|
|
603
|
+
if (!hasLiveBranch(values, segments)) deleted.add(key);
|
|
604
|
+
}
|
|
605
|
+
if (!options?.keepTouched) touched.delete(key);
|
|
606
|
+
if (!options?.keepError) errors.delete(key);
|
|
530
607
|
validating.delete(key);
|
|
531
|
-
clearDirtyBaselines(form, key);
|
|
532
|
-
if (!hasLiveBranch(values, segments)) deleted.add(key);
|
|
533
608
|
bumpDirtyVersion(form);
|
|
534
609
|
bumpValuesVersion(form);
|
|
535
610
|
emit(emitter, "change", path);
|
|
@@ -575,17 +650,37 @@
|
|
|
575
650
|
bumpValuesVersion(form);
|
|
576
651
|
emit(form.emitter, "change");
|
|
577
652
|
}
|
|
653
|
+
function collectValueLeaves(node, segments, out) {
|
|
654
|
+
if (node !== null && typeof node === "object") {
|
|
655
|
+
if (Array.isArray(node)) {
|
|
656
|
+
for (let i = 0; i < node.length; i++) {
|
|
657
|
+
collectValueLeaves(node[i], [...segments, i], out);
|
|
658
|
+
}
|
|
659
|
+
return;
|
|
660
|
+
}
|
|
661
|
+
const keys = Object.keys(node);
|
|
662
|
+
if (keys.length > 0) {
|
|
663
|
+
for (const k of keys) {
|
|
664
|
+
collectValueLeaves(node[k], [...segments, k], out);
|
|
665
|
+
}
|
|
666
|
+
return;
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
out.push({ segments, value: node });
|
|
670
|
+
}
|
|
578
671
|
function reset(form, initialValues, options) {
|
|
579
|
-
const
|
|
580
|
-
if (options?.
|
|
672
|
+
const keptValues = [];
|
|
673
|
+
if (options?.keepValues) {
|
|
674
|
+
collectValueLeaves(getValues(form), [], keptValues);
|
|
675
|
+
} else if (options?.keepDirtyValues) {
|
|
581
676
|
for (const [key, value] of form.values) {
|
|
582
677
|
const segments = JSON.parse(key);
|
|
583
678
|
if (getDirtyBaseline(form, key, segments) !== value) {
|
|
584
|
-
|
|
679
|
+
keptValues.push({ segments, value });
|
|
585
680
|
}
|
|
586
681
|
}
|
|
587
682
|
}
|
|
588
|
-
form.initialValues = initialValues;
|
|
683
|
+
form.initialValues = options?.keepDefaultValues ? form.initialValues : initialValues ?? form.initialValues;
|
|
589
684
|
form.parsedValues = void 0;
|
|
590
685
|
if (!options?.keepErrors) clearErrors(form);
|
|
591
686
|
const { emitter, touched, values, deleted, validating } = form;
|
|
@@ -599,7 +694,7 @@
|
|
|
599
694
|
if (!options?.keepIsSubmitted) form.isSubmitSuccessful = void 0;
|
|
600
695
|
bumpDirtyVersion(form);
|
|
601
696
|
bumpValuesVersion(form);
|
|
602
|
-
for (const { segments, value } of
|
|
697
|
+
for (const { segments, value } of keptValues) {
|
|
603
698
|
setValueByPath(form, create$1(segments), value);
|
|
604
699
|
}
|
|
605
700
|
emit(emitter, "change");
|
|
@@ -634,10 +729,172 @@
|
|
|
634
729
|
bumpDirtyVersion(form);
|
|
635
730
|
bumpValuesVersion(form);
|
|
636
731
|
}
|
|
637
|
-
|
|
638
|
-
|
|
732
|
+
|
|
733
|
+
function isDirty(form) {
|
|
734
|
+
let dirty = false;
|
|
735
|
+
forEachDirtyField(form, () => {
|
|
736
|
+
dirty = true;
|
|
737
|
+
});
|
|
738
|
+
return dirty;
|
|
739
|
+
}
|
|
740
|
+
function forEachDirtyField(form, fn) {
|
|
741
|
+
for (const [key, value] of form.values) {
|
|
742
|
+
const path = JSON.parse(key);
|
|
743
|
+
if (getDirtyBaseline(form, key, path) !== value) fn(path.join("."));
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
function computeDirtyFields(form) {
|
|
747
|
+
const dirtyFields = {};
|
|
748
|
+
forEachDirtyField(form, (key) => {
|
|
749
|
+
dirtyFields[key] = true;
|
|
750
|
+
});
|
|
751
|
+
return dirtyFields;
|
|
752
|
+
}
|
|
753
|
+
function sameDirtyKeys(a, b) {
|
|
754
|
+
const aKeys = Object.keys(a);
|
|
755
|
+
if (aKeys.length !== Object.keys(b).length) return false;
|
|
756
|
+
return aKeys.every((key) => b[key] === true);
|
|
757
|
+
}
|
|
758
|
+
function getDirtyFields(form) {
|
|
759
|
+
let cache = dirtyFieldsCaches.get(form);
|
|
760
|
+
if (!cache) {
|
|
761
|
+
cache = { version: 0, result: computeDirtyFields(form) };
|
|
762
|
+
dirtyFieldsCaches.set(form, cache);
|
|
763
|
+
} else if (cache.version > 0) {
|
|
764
|
+
const result = computeDirtyFields(form);
|
|
765
|
+
if (!sameDirtyKeys(cache.result, result)) cache.result = result;
|
|
766
|
+
cache.version = 0;
|
|
767
|
+
}
|
|
768
|
+
return cache.result;
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
function unsetValidatingByPath({ emitter, validating }, path) {
|
|
772
|
+
validating.delete(path.key);
|
|
773
|
+
emit(emitter, "validating", path);
|
|
774
|
+
}
|
|
775
|
+
function setValidatingByPath({ emitter, validating }, path) {
|
|
776
|
+
validating.add(path.key);
|
|
777
|
+
emit(emitter, "validating", path);
|
|
778
|
+
}
|
|
779
|
+
function registerValidatorByPath(form, path, registration) {
|
|
780
|
+
let timer = null;
|
|
781
|
+
let controller = null;
|
|
782
|
+
let marked = false;
|
|
783
|
+
let lock = null;
|
|
784
|
+
let errorSource = null;
|
|
785
|
+
const hasErrors2 = (errors) => errors !== void 0 && !(Array.isArray(errors) && errors.length === 0);
|
|
786
|
+
const mark = () => {
|
|
787
|
+
if (marked) return;
|
|
788
|
+
marked = true;
|
|
789
|
+
setValidatingByPath(form, path);
|
|
790
|
+
};
|
|
791
|
+
const unmark = () => {
|
|
792
|
+
if (!marked) return;
|
|
793
|
+
marked = false;
|
|
794
|
+
unsetValidatingByPath(form, path);
|
|
795
|
+
};
|
|
796
|
+
const runSync = () => {
|
|
797
|
+
const sync = registration.sync();
|
|
798
|
+
if (!sync) return false;
|
|
799
|
+
const errors = sync(getValueByPath(form, path), { form, path });
|
|
800
|
+
if (!hasErrors2(errors)) {
|
|
801
|
+
if (!registration.validate() || errorSource === "sync") {
|
|
802
|
+
setErrorByPath(form, path, void 0);
|
|
803
|
+
errorSource = null;
|
|
804
|
+
}
|
|
805
|
+
return false;
|
|
806
|
+
}
|
|
807
|
+
setErrorByPath(form, path, errors);
|
|
808
|
+
errorSource = "sync";
|
|
809
|
+
return true;
|
|
810
|
+
};
|
|
811
|
+
const supersede = () => {
|
|
812
|
+
if (timer !== null) {
|
|
813
|
+
clearTimeout(timer);
|
|
814
|
+
timer = null;
|
|
815
|
+
}
|
|
816
|
+
controller?.abort();
|
|
817
|
+
lock = {};
|
|
818
|
+
};
|
|
819
|
+
const runValidator = () => {
|
|
820
|
+
const fn = registration.validate();
|
|
821
|
+
if (!fn) {
|
|
822
|
+
unmark();
|
|
823
|
+
return;
|
|
824
|
+
}
|
|
825
|
+
controller?.abort();
|
|
826
|
+
controller = new AbortController();
|
|
827
|
+
const round = lock = {};
|
|
828
|
+
let result;
|
|
829
|
+
try {
|
|
830
|
+
result = fn(getValueByPath(form, path), {
|
|
831
|
+
form,
|
|
832
|
+
path,
|
|
833
|
+
signal: controller.signal
|
|
834
|
+
});
|
|
835
|
+
} catch (e) {
|
|
836
|
+
unmark();
|
|
837
|
+
throw e;
|
|
838
|
+
}
|
|
839
|
+
if (!isPromise(result)) {
|
|
840
|
+
setErrorByPath(form, path, result);
|
|
841
|
+
errorSource = hasErrors2(result) ? "validator" : null;
|
|
842
|
+
unmark();
|
|
843
|
+
return;
|
|
844
|
+
}
|
|
845
|
+
mark();
|
|
846
|
+
result.then(
|
|
847
|
+
(error) => {
|
|
848
|
+
if (lock === round) {
|
|
849
|
+
setErrorByPath(form, path, error);
|
|
850
|
+
errorSource = hasErrors2(error) ? "validator" : null;
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
).catch(() => {
|
|
854
|
+
}).finally(() => {
|
|
855
|
+
if (lock === round) {
|
|
856
|
+
unmark();
|
|
857
|
+
lock = null;
|
|
858
|
+
}
|
|
859
|
+
});
|
|
860
|
+
};
|
|
861
|
+
const run = () => {
|
|
862
|
+
timer = null;
|
|
863
|
+
if (runSync()) {
|
|
864
|
+
supersede();
|
|
865
|
+
unmark();
|
|
866
|
+
return;
|
|
867
|
+
}
|
|
868
|
+
runValidator();
|
|
869
|
+
};
|
|
870
|
+
const kick = () => {
|
|
871
|
+
if (runSync()) {
|
|
872
|
+
supersede();
|
|
873
|
+
unmark();
|
|
874
|
+
return;
|
|
875
|
+
}
|
|
876
|
+
if (!registration.validate()) return;
|
|
877
|
+
const debounce = registration.debounce();
|
|
878
|
+
if (debounce > 0) {
|
|
879
|
+
if (timer !== null) clearTimeout(timer);
|
|
880
|
+
else mark();
|
|
881
|
+
timer = setTimeout(run, debounce);
|
|
882
|
+
return;
|
|
883
|
+
}
|
|
884
|
+
runValidator();
|
|
885
|
+
};
|
|
886
|
+
form.validators.set(path.key, kick);
|
|
887
|
+
return () => {
|
|
888
|
+
form.validators.delete(path.key);
|
|
889
|
+
if (timer !== null) {
|
|
890
|
+
clearTimeout(timer);
|
|
891
|
+
timer = null;
|
|
892
|
+
}
|
|
893
|
+
unmark();
|
|
894
|
+
controller?.abort();
|
|
895
|
+
};
|
|
639
896
|
}
|
|
640
|
-
async function trigger(form, name) {
|
|
897
|
+
async function trigger(form, name, options) {
|
|
641
898
|
const settle = (keys2) => waitUntil(
|
|
642
899
|
form.emitter,
|
|
643
900
|
"validating",
|
|
@@ -648,18 +905,25 @@
|
|
|
648
905
|
form.validators.forEach((validator) => validator());
|
|
649
906
|
await settle();
|
|
650
907
|
if (form.validate) await runFormValidate(form);
|
|
908
|
+
if (options?.shouldTouch) touchKeys(form, [...form.validators.keys()]);
|
|
909
|
+
if (options?.shouldFocus) {
|
|
910
|
+
const firstKey = form.errors.keys().next().value;
|
|
911
|
+
if (firstKey !== void 0) emit(form.emitter, "focusError", firstKey);
|
|
912
|
+
}
|
|
651
913
|
return !hasErrors(form);
|
|
652
914
|
}
|
|
653
915
|
const keys = typeof name === "string" || isSegmentsPath(name) ? [create$1(name).key] : name.map((one) => create$1(one).key);
|
|
654
916
|
keys.forEach((key) => form.validators.get(key)?.());
|
|
655
917
|
await settle(keys);
|
|
918
|
+
if (options?.shouldTouch) touchKeys(form, keys);
|
|
919
|
+
if (options?.shouldFocus) {
|
|
920
|
+
const firstKey = keys.find((key) => form.errors.has(key));
|
|
921
|
+
if (firstKey !== void 0) emit(form.emitter, "focusError", firstKey);
|
|
922
|
+
}
|
|
656
923
|
return keys.every((key) => !form.errors.has(key));
|
|
657
924
|
}
|
|
658
|
-
function
|
|
659
|
-
|
|
660
|
-
}
|
|
661
|
-
function isFieldError(value) {
|
|
662
|
-
return !!value && typeof value === "object" && typeof value.type === "string" && typeof value.message === "string";
|
|
925
|
+
function touchKeys(form, keys) {
|
|
926
|
+
keys.forEach((key) => setTouchedByPath(form, create$1(JSON.parse(key))));
|
|
663
927
|
}
|
|
664
928
|
function setFormErrors(form, result, segments = [], footprint) {
|
|
665
929
|
Object.entries(result).forEach(([key, value]) => {
|
|
@@ -689,12 +953,6 @@
|
|
|
689
953
|
const stored = form.errors.get(path.key);
|
|
690
954
|
if (stored) footprint.set(path.key, stored);
|
|
691
955
|
}
|
|
692
|
-
function setParsedValues(form, values) {
|
|
693
|
-
if (values === void 0 || values === form.parsedValues) return;
|
|
694
|
-
form.parsedValues = values;
|
|
695
|
-
bumpValuesVersion(form);
|
|
696
|
-
emit(form.emitter, "change");
|
|
697
|
-
}
|
|
698
956
|
function applyValidateResult(form, result) {
|
|
699
957
|
const footprint = form.validateDeps ? getFormErrorFootprint(form) : void 0;
|
|
700
958
|
if (footprint) {
|
|
@@ -892,6 +1150,55 @@
|
|
|
892
1150
|
async function validate(form) {
|
|
893
1151
|
return ensureValidate(form).catch((e) => e.message);
|
|
894
1152
|
}
|
|
1153
|
+
|
|
1154
|
+
const fieldModes = /* @__PURE__ */ new WeakMap();
|
|
1155
|
+
function changeValue(form, name, value, options) {
|
|
1156
|
+
changeValueByPath(form, create$1(name), value, options);
|
|
1157
|
+
}
|
|
1158
|
+
function changeValueByPath(form, path, value, options) {
|
|
1159
|
+
if (options?.shouldDirty === false) setDirtyBaseline(form, path, value);
|
|
1160
|
+
if (fieldModes.get(form)?.get(path.key)) {
|
|
1161
|
+
userChangeByPath(form, path, value);
|
|
1162
|
+
} else {
|
|
1163
|
+
setValueByPath(form, path, value, options);
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
function registerFieldMode(form, path, mode) {
|
|
1167
|
+
let modes = fieldModes.get(form);
|
|
1168
|
+
if (!modes) {
|
|
1169
|
+
modes = /* @__PURE__ */ new Map();
|
|
1170
|
+
fieldModes.set(form, modes);
|
|
1171
|
+
}
|
|
1172
|
+
const displaced = modes.has(path.key);
|
|
1173
|
+
const token = {};
|
|
1174
|
+
modes.set(path.key, { mode, token });
|
|
1175
|
+
return { token, displaced };
|
|
1176
|
+
}
|
|
1177
|
+
function unregisterFieldMode(form, path, token) {
|
|
1178
|
+
const modes = fieldModes.get(form);
|
|
1179
|
+
const entry = modes?.get(path.key);
|
|
1180
|
+
if (modes && entry && entry.token === token) modes.delete(path.key);
|
|
1181
|
+
}
|
|
1182
|
+
function runUserChangeGate(form, path, mode) {
|
|
1183
|
+
if (mode === "onChange" || mode === "all" || mode === "onTouched" && hasTouchedByPath(form, path) || getFieldErrorsByPath(form, path).length > 0 && form.reValidateMode === "onChange")
|
|
1184
|
+
form.validators.get(path.key)?.();
|
|
1185
|
+
revalidateFormOnChange(form, path, mode);
|
|
1186
|
+
revalidateDependentsOnChange(form, path, mode);
|
|
1187
|
+
}
|
|
1188
|
+
function userChangeByPath(form, path, value) {
|
|
1189
|
+
setValueByPath(form, path, value);
|
|
1190
|
+
const entry = fieldModes.get(form)?.get(path.key);
|
|
1191
|
+
if (entry) runUserChangeGate(form, path, entry.mode ?? form.mode);
|
|
1192
|
+
}
|
|
1193
|
+
function userBlur(form, path) {
|
|
1194
|
+
setTouchedByPath(form, path);
|
|
1195
|
+
const entry = fieldModes.get(form)?.get(path.key);
|
|
1196
|
+
if (!entry) return;
|
|
1197
|
+
const mode = entry.mode ?? form.mode;
|
|
1198
|
+
if (mode === "onBlur" || mode === "onTouched" || mode === "all" || getFieldErrorsByPath(form, path).length > 0 && form.reValidateMode === "onBlur")
|
|
1199
|
+
form.validators.get(path.key)?.();
|
|
1200
|
+
}
|
|
1201
|
+
|
|
895
1202
|
function setIsSubmitting(form, value) {
|
|
896
1203
|
form.isSubmitting = value;
|
|
897
1204
|
emit(form.emitter, "submitting");
|
|
@@ -938,6 +1245,7 @@
|
|
|
938
1245
|
onSubmit,
|
|
939
1246
|
onValidSubmit,
|
|
940
1247
|
onInvalidSubmit,
|
|
1248
|
+
onAction,
|
|
941
1249
|
shouldFocusError = true
|
|
942
1250
|
} = options ?? {};
|
|
943
1251
|
return async (e) => {
|
|
@@ -974,6 +1282,7 @@
|
|
|
974
1282
|
const submitted = getValues(form);
|
|
975
1283
|
if (onSubmit) await onSubmit(submitted, e);
|
|
976
1284
|
if (onValidSubmit) await onValidSubmit(submitted, e);
|
|
1285
|
+
if (onAction) await onAction(submitted, e);
|
|
977
1286
|
setSubmitSuccessful(form, true);
|
|
978
1287
|
} catch {
|
|
979
1288
|
setSubmitSuccessful(form, false);
|
|
@@ -982,12 +1291,58 @@
|
|
|
982
1291
|
}
|
|
983
1292
|
};
|
|
984
1293
|
}
|
|
1294
|
+
|
|
985
1295
|
function setFocus(form, name, options) {
|
|
986
1296
|
const { key } = create$1(name);
|
|
987
1297
|
if (options) emit(form.emitter, "focusError", key, options);
|
|
988
1298
|
else emit(form.emitter, "focusError", key);
|
|
989
1299
|
}
|
|
990
1300
|
|
|
1301
|
+
function create(options) {
|
|
1302
|
+
const emitter = create$2();
|
|
1303
|
+
_setMaxListeners(emitter, 0);
|
|
1304
|
+
let source = options?.initialValues ?? {};
|
|
1305
|
+
if (typeof source === "function") source = source();
|
|
1306
|
+
const form = {
|
|
1307
|
+
emitter,
|
|
1308
|
+
...options,
|
|
1309
|
+
mode: options?.mode ?? "onSubmit",
|
|
1310
|
+
reValidateMode: options?.reValidateMode ?? "onChange",
|
|
1311
|
+
disabled: options?.disabled ?? false,
|
|
1312
|
+
validateDeps: options?.validateDeps ? new Set(options.validateDeps.map((dep) => create$1(dep).key)) : void 0,
|
|
1313
|
+
initialValues: {},
|
|
1314
|
+
values: /* @__PURE__ */ new Map(),
|
|
1315
|
+
deleted: /* @__PURE__ */ new Set(),
|
|
1316
|
+
errors: /* @__PURE__ */ new Map(),
|
|
1317
|
+
touched: /* @__PURE__ */ new Set(),
|
|
1318
|
+
validators: /* @__PURE__ */ new Map(),
|
|
1319
|
+
validating: /* @__PURE__ */ new Set(),
|
|
1320
|
+
parsedValues: void 0,
|
|
1321
|
+
isSubmitting: false,
|
|
1322
|
+
submitCount: 0,
|
|
1323
|
+
isSubmitSuccessful: void 0,
|
|
1324
|
+
isLoading: false
|
|
1325
|
+
};
|
|
1326
|
+
if (isPromise(source)) {
|
|
1327
|
+
form.isLoading = true;
|
|
1328
|
+
emit(emitter, "loading");
|
|
1329
|
+
Promise.resolve(source).then(
|
|
1330
|
+
(resolved) => {
|
|
1331
|
+
form.isLoading = false;
|
|
1332
|
+
emit(emitter, "loading");
|
|
1333
|
+
setInitialValues(form, resolved ?? {});
|
|
1334
|
+
},
|
|
1335
|
+
(error) => {
|
|
1336
|
+
form.isLoading = false;
|
|
1337
|
+
emit(emitter, "loading");
|
|
1338
|
+
}
|
|
1339
|
+
);
|
|
1340
|
+
} else {
|
|
1341
|
+
form.initialValues = source;
|
|
1342
|
+
}
|
|
1343
|
+
return form;
|
|
1344
|
+
}
|
|
1345
|
+
|
|
991
1346
|
function defaultMessage(type, bound) {
|
|
992
1347
|
switch (type) {
|
|
993
1348
|
case "required":
|
|
@@ -1297,6 +1652,9 @@
|
|
|
1297
1652
|
seededRef.current = { done: false, source: void 0 };
|
|
1298
1653
|
React.useEffect(() => {
|
|
1299
1654
|
if (initialValues === void 0) return;
|
|
1655
|
+
if (typeof initialValues === "function" || isPromise(initialValues)) {
|
|
1656
|
+
return;
|
|
1657
|
+
}
|
|
1300
1658
|
const seeded = seededRef.current;
|
|
1301
1659
|
if (seeded.done && (seeded.source === initialValues || isEqual(seeded.source, initialValues))) {
|
|
1302
1660
|
return;
|
|
@@ -1321,12 +1679,14 @@
|
|
|
1321
1679
|
}, [form, values]);
|
|
1322
1680
|
return form;
|
|
1323
1681
|
}
|
|
1324
|
-
function useWatchCore(subscribeFactory, getter) {
|
|
1682
|
+
function useWatchCore(subscribeFactory, getter, isEqual2) {
|
|
1325
1683
|
const cacheRef = React.useRef(null);
|
|
1326
1684
|
if (cacheRef.current === null) cacheRef.current = { hasValue: false };
|
|
1327
1685
|
const cache = cacheRef.current;
|
|
1328
1686
|
const getterRef = React.useRef(getter);
|
|
1329
1687
|
getterRef.current = getter;
|
|
1688
|
+
const isEqualRef = React.useRef(isEqual2);
|
|
1689
|
+
isEqualRef.current = isEqual2;
|
|
1330
1690
|
const getSnapshot = React.useCallback(() => {
|
|
1331
1691
|
if (!cache.hasValue) {
|
|
1332
1692
|
cache.value = getterRef.current();
|
|
@@ -1338,6 +1698,14 @@
|
|
|
1338
1698
|
(notify) => {
|
|
1339
1699
|
cache.hasValue = false;
|
|
1340
1700
|
const invalidate = () => {
|
|
1701
|
+
const compare = isEqualRef.current;
|
|
1702
|
+
if (compare && cache.hasValue) {
|
|
1703
|
+
const next = getterRef.current();
|
|
1704
|
+
if (compare(cache.value, next)) return;
|
|
1705
|
+
cache.value = next;
|
|
1706
|
+
notify();
|
|
1707
|
+
return;
|
|
1708
|
+
}
|
|
1341
1709
|
cache.hasValue = false;
|
|
1342
1710
|
notify();
|
|
1343
1711
|
};
|
|
@@ -1347,12 +1715,13 @@
|
|
|
1347
1715
|
);
|
|
1348
1716
|
return shimExports.useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
1349
1717
|
}
|
|
1350
|
-
function useWatch(
|
|
1718
|
+
function useWatch(formOrEmitter, event, getter, isEqual2) {
|
|
1719
|
+
const emitter = "emitter" in formOrEmitter ? formOrEmitter.emitter : formOrEmitter;
|
|
1351
1720
|
const subscribeFactory = React.useCallback(
|
|
1352
1721
|
(invalidate) => on(emitter, event, invalidate),
|
|
1353
1722
|
[emitter, event]
|
|
1354
1723
|
);
|
|
1355
|
-
return useWatchCore(subscribeFactory, getter);
|
|
1724
|
+
return useWatchCore(subscribeFactory, getter, isEqual2);
|
|
1356
1725
|
}
|
|
1357
1726
|
function useValue(form, name) {
|
|
1358
1727
|
return useValueByPath(form, create$1(name));
|
|
@@ -1410,19 +1779,71 @@
|
|
|
1410
1779
|
);
|
|
1411
1780
|
}
|
|
1412
1781
|
function useIsDirty(form) {
|
|
1413
|
-
return useWatch(form
|
|
1782
|
+
return useWatch(form, "change", isDirty.bind(null, form));
|
|
1414
1783
|
}
|
|
1415
1784
|
function useDirtyFields(form) {
|
|
1416
|
-
return useWatch(form
|
|
1785
|
+
return useWatch(form, "change", getDirtyFields.bind(null, form));
|
|
1417
1786
|
}
|
|
1418
1787
|
function useTouchedFields(form) {
|
|
1419
|
-
return useWatch(form
|
|
1788
|
+
return useWatch(form, "touched", getTouchedFields.bind(null, form));
|
|
1789
|
+
}
|
|
1790
|
+
const FORM_STATE_EVENTS = [
|
|
1791
|
+
"change",
|
|
1792
|
+
"errors",
|
|
1793
|
+
"touched",
|
|
1794
|
+
"validating",
|
|
1795
|
+
"submitting",
|
|
1796
|
+
"submitCount",
|
|
1797
|
+
"submitSuccessful",
|
|
1798
|
+
"disabled",
|
|
1799
|
+
"loading"
|
|
1800
|
+
];
|
|
1801
|
+
function getFormState(form) {
|
|
1802
|
+
return {
|
|
1803
|
+
isDirty: isDirty(form),
|
|
1804
|
+
dirtyFields: getDirtyFields(form),
|
|
1805
|
+
isTouched: form.touched.size > 0,
|
|
1806
|
+
touchedFields: getTouchedFields(form),
|
|
1807
|
+
hasErrors: hasErrors(form),
|
|
1808
|
+
isValid: !hasErrors(form),
|
|
1809
|
+
isSubmitting: form.isSubmitting,
|
|
1810
|
+
isValidating: form.validating.size > 0,
|
|
1811
|
+
isSubmitSuccessful: form.isSubmitSuccessful,
|
|
1812
|
+
submitCount: form.submitCount,
|
|
1813
|
+
isLoading: form.isLoading,
|
|
1814
|
+
disabled: form.disabled
|
|
1815
|
+
};
|
|
1816
|
+
}
|
|
1817
|
+
function isSameFormState(a, b) {
|
|
1818
|
+
const sameTouched = a.touchedFields.length === b.touchedFields.length && a.touchedFields.every((path, i) => path === b.touchedFields[i]);
|
|
1819
|
+
return a.isDirty === b.isDirty && a.dirtyFields === b.dirtyFields && a.isTouched === b.isTouched && sameTouched && a.hasErrors === b.hasErrors && a.isValid === b.isValid && a.isSubmitting === b.isSubmitting && a.isValidating === b.isValidating && a.isSubmitSuccessful === b.isSubmitSuccessful && a.submitCount === b.submitCount && a.isLoading === b.isLoading && a.disabled === b.disabled;
|
|
1820
|
+
}
|
|
1821
|
+
function useFormState(form) {
|
|
1822
|
+
const getter = React.useCallback(() => getFormState(form), [form]);
|
|
1823
|
+
const subscribeFactory = React.useCallback(
|
|
1824
|
+
(invalidate) => {
|
|
1825
|
+
const offs = FORM_STATE_EVENTS.map(
|
|
1826
|
+
(event) => on(form.emitter, event, invalidate)
|
|
1827
|
+
);
|
|
1828
|
+
return () => {
|
|
1829
|
+
for (const off of offs) off();
|
|
1830
|
+
};
|
|
1831
|
+
},
|
|
1832
|
+
[form.emitter]
|
|
1833
|
+
);
|
|
1834
|
+
return useWatchCore(subscribeFactory, getter, isSameFormState);
|
|
1420
1835
|
}
|
|
1421
1836
|
function useHasErrors(form) {
|
|
1422
|
-
return useWatch(form
|
|
1837
|
+
return useWatch(form, "errors", hasErrors.bind(null, form));
|
|
1838
|
+
}
|
|
1839
|
+
function useIsValid(form) {
|
|
1840
|
+
return useWatch(form, "errors", () => !hasErrors(form));
|
|
1423
1841
|
}
|
|
1424
1842
|
function useIsSubmitting(form) {
|
|
1425
|
-
return useWatch(form
|
|
1843
|
+
return useWatch(form, "submitting", () => form.isSubmitting);
|
|
1844
|
+
}
|
|
1845
|
+
function useIsLoading(form) {
|
|
1846
|
+
return useWatch(form, "loading", () => form.isLoading);
|
|
1426
1847
|
}
|
|
1427
1848
|
function useCanSubmit(form) {
|
|
1428
1849
|
const { emitter } = form;
|
|
@@ -1443,7 +1864,23 @@
|
|
|
1443
1864
|
);
|
|
1444
1865
|
}
|
|
1445
1866
|
function useSubmitCount(form) {
|
|
1446
|
-
return useWatch(form
|
|
1867
|
+
return useWatch(form, "submitCount", () => form.submitCount);
|
|
1868
|
+
}
|
|
1869
|
+
function useIsValidating(form) {
|
|
1870
|
+
return useWatch(form, "validating", () => form.validating.size > 0);
|
|
1871
|
+
}
|
|
1872
|
+
function useIsSubmitSuccessful(form) {
|
|
1873
|
+
return useWatch(
|
|
1874
|
+
form.emitter,
|
|
1875
|
+
"submitSuccessful",
|
|
1876
|
+
() => !!form.isSubmitSuccessful
|
|
1877
|
+
);
|
|
1878
|
+
}
|
|
1879
|
+
function useFormError(form) {
|
|
1880
|
+
return useErrorByPath(form, create$1(FORM_ERROR))?.message;
|
|
1881
|
+
}
|
|
1882
|
+
function useFormErrors(form) {
|
|
1883
|
+
return useFieldErrorsByPath(form, create$1(FORM_ERROR));
|
|
1447
1884
|
}
|
|
1448
1885
|
|
|
1449
1886
|
function usePath(name) {
|
|
@@ -1468,92 +1905,29 @@
|
|
|
1468
1905
|
const contextForm = React.useContext(FormContext);
|
|
1469
1906
|
const form = formProp || contextForm;
|
|
1470
1907
|
if (!form) throw new Error("no form provided");
|
|
1471
|
-
const lockRef = React.useRef(null);
|
|
1472
1908
|
const validateRef = React.useRef(validate);
|
|
1473
1909
|
validateRef.current = validate;
|
|
1474
1910
|
const debounceRef = React.useRef(options?.debounce ?? 0);
|
|
1475
1911
|
debounceRef.current = options?.debounce ?? 0;
|
|
1476
|
-
React.
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
marked = false;
|
|
1488
|
-
unsetValidatingByPath(form, path);
|
|
1489
|
-
};
|
|
1490
|
-
const run = () => {
|
|
1491
|
-
timer = null;
|
|
1492
|
-
const fn = validateRef.current;
|
|
1493
|
-
if (!fn) {
|
|
1494
|
-
unmark();
|
|
1495
|
-
return;
|
|
1496
|
-
}
|
|
1497
|
-
controller?.abort();
|
|
1498
|
-
controller = new AbortController();
|
|
1499
|
-
const lock = lockRef.current = {};
|
|
1500
|
-
let result;
|
|
1501
|
-
try {
|
|
1502
|
-
result = fn(getValueByPath(form, path), {
|
|
1503
|
-
form,
|
|
1504
|
-
path,
|
|
1505
|
-
signal: controller.signal
|
|
1506
|
-
});
|
|
1507
|
-
} catch (e) {
|
|
1508
|
-
unmark();
|
|
1509
|
-
throw e;
|
|
1510
|
-
}
|
|
1511
|
-
if (!isPromise(result)) {
|
|
1512
|
-
setErrorByPath(form, path, result);
|
|
1513
|
-
unmark();
|
|
1514
|
-
return;
|
|
1515
|
-
}
|
|
1516
|
-
mark();
|
|
1517
|
-
result.then(
|
|
1518
|
-
(error) => {
|
|
1519
|
-
if (lock === lockRef.current) {
|
|
1520
|
-
setErrorByPath(form, path, error);
|
|
1521
|
-
}
|
|
1522
|
-
}
|
|
1523
|
-
).catch(() => {
|
|
1524
|
-
}).finally(() => {
|
|
1525
|
-
if (lock === lockRef.current) {
|
|
1526
|
-
unmark();
|
|
1527
|
-
lockRef.current = null;
|
|
1528
|
-
}
|
|
1529
|
-
});
|
|
1530
|
-
};
|
|
1531
|
-
const validator = () => {
|
|
1532
|
-
const debounce = debounceRef.current;
|
|
1533
|
-
if (debounce > 0) {
|
|
1534
|
-
if (timer !== null) clearTimeout(timer);
|
|
1535
|
-
else mark();
|
|
1536
|
-
timer = setTimeout(run, debounce);
|
|
1537
|
-
return;
|
|
1538
|
-
}
|
|
1539
|
-
run();
|
|
1540
|
-
};
|
|
1541
|
-
form.validators.set(path.key, validator);
|
|
1542
|
-
return () => {
|
|
1543
|
-
form.validators.delete(path.key);
|
|
1544
|
-
if (timer !== null) {
|
|
1545
|
-
clearTimeout(timer);
|
|
1546
|
-
timer = null;
|
|
1547
|
-
}
|
|
1548
|
-
unmark();
|
|
1549
|
-
controller?.abort();
|
|
1550
|
-
};
|
|
1551
|
-
}, [form, path.key]);
|
|
1912
|
+
const syncRef = React.useRef(options?.sync);
|
|
1913
|
+
syncRef.current = options?.sync;
|
|
1914
|
+
React.useEffect(
|
|
1915
|
+
() => registerValidatorByPath(form, path, {
|
|
1916
|
+
validate: () => validateRef.current,
|
|
1917
|
+
debounce: () => debounceRef.current,
|
|
1918
|
+
sync: () => syncRef.current
|
|
1919
|
+
}),
|
|
1920
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps -- deps are `path.key` on purpose: usePath returns a stable Path per key, so re-subscribing on key (not object identity) is enough
|
|
1921
|
+
[form, path.key]
|
|
1922
|
+
);
|
|
1552
1923
|
return useStageFn(() => form.validators.get(path.key)?.());
|
|
1553
1924
|
}
|
|
1554
1925
|
|
|
1926
|
+
function hasRuleConstraints(rules) {
|
|
1927
|
+
return rules.required !== void 0 || rules.min !== void 0 || rules.max !== void 0 || rules.minLength !== void 0 || rules.maxLength !== void 0 || rules.pattern !== void 0;
|
|
1928
|
+
}
|
|
1555
1929
|
function combineRulesAndValidate(rules, validate) {
|
|
1556
|
-
if (!rules) return validate;
|
|
1930
|
+
if (!rules || !hasRuleConstraints(rules)) return validate;
|
|
1557
1931
|
const ruleValidator = rulesToValidator(rules);
|
|
1558
1932
|
if (!validate) return ruleValidator;
|
|
1559
1933
|
return (value, meta) => {
|
|
@@ -1585,6 +1959,25 @@
|
|
|
1585
1959
|
}, [errors, delay, shown]);
|
|
1586
1960
|
return delay === void 0 ? errors : shown;
|
|
1587
1961
|
}
|
|
1962
|
+
function useFieldValue(form, path, uncontrolled) {
|
|
1963
|
+
const snapshotRef = React.useRef({
|
|
1964
|
+
has: false,
|
|
1965
|
+
value: void 0
|
|
1966
|
+
});
|
|
1967
|
+
const getter = React.useCallback(() => {
|
|
1968
|
+
if (!uncontrolled) return getValueByPath(form, path);
|
|
1969
|
+
if (!snapshotRef.current.has) {
|
|
1970
|
+
snapshotRef.current = { has: true, value: getValueByPath(form, path) };
|
|
1971
|
+
}
|
|
1972
|
+
return snapshotRef.current.value;
|
|
1973
|
+
}, [uncontrolled, form, path]);
|
|
1974
|
+
const subscribeFactory = React.useCallback(
|
|
1975
|
+
(invalidate) => uncontrolled ? () => {
|
|
1976
|
+
} : onPathEvent(form.emitter, "change", path, "leaf", invalidate),
|
|
1977
|
+
[uncontrolled, form.emitter, path]
|
|
1978
|
+
);
|
|
1979
|
+
return useWatchCore(subscribeFactory, getter);
|
|
1980
|
+
}
|
|
1588
1981
|
function useFieldCore({
|
|
1589
1982
|
form: f1,
|
|
1590
1983
|
name,
|
|
@@ -1596,6 +1989,7 @@
|
|
|
1596
1989
|
validateDeps,
|
|
1597
1990
|
delayError,
|
|
1598
1991
|
disabled,
|
|
1992
|
+
uncontrolled,
|
|
1599
1993
|
mode: modeOption
|
|
1600
1994
|
}, Context) {
|
|
1601
1995
|
const contextForm = React.useContext(Context);
|
|
@@ -1613,35 +2007,23 @@
|
|
|
1613
2007
|
seededRef.current = false;
|
|
1614
2008
|
emitChangeByPath(form, path);
|
|
1615
2009
|
});
|
|
1616
|
-
const
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
debounce: validateDebounce
|
|
1622
|
-
}
|
|
1623
|
-
);
|
|
2010
|
+
const restRules = rules ? { ...rules, required: void 0 } : void 0;
|
|
2011
|
+
useValidate(combineRulesAndValidate(restRules, validate), path, form, {
|
|
2012
|
+
debounce: validateDebounce,
|
|
2013
|
+
sync: rules && rules.required !== void 0 ? rulesToValidator({ required: rules.required }) : void 0
|
|
2014
|
+
});
|
|
1624
2015
|
const liveErrors = useFieldErrorsByPath(form, path);
|
|
1625
2016
|
const errors = useDelayedErrors(liveErrors, delayError);
|
|
1626
2017
|
const errorObject = errors[0];
|
|
1627
2018
|
const error = errorObject?.message;
|
|
1628
|
-
const value =
|
|
1629
|
-
const formDisabled = useWatch(form
|
|
1630
|
-
const
|
|
1631
|
-
const
|
|
1632
|
-
setValueByPath(form, path, v);
|
|
1633
|
-
if (mode === "onChange" || mode === "all" || mode === "onTouched" && hasTouchedByPath(form, path) || liveErrors.length > 0 && form.reValidateMode === "onChange")
|
|
1634
|
-
validator();
|
|
1635
|
-
revalidateFormOnChange(form, path, mode);
|
|
1636
|
-
revalidateDependentsOnChange(form, path, mode);
|
|
1637
|
-
});
|
|
2019
|
+
const value = useFieldValue(form, path, !!uncontrolled);
|
|
2020
|
+
const formDisabled = useWatch(form, "disabled", () => form.disabled);
|
|
2021
|
+
const onChange = useStageFn((v) => userChangeByPath(form, path, v));
|
|
2022
|
+
const onBlur = useStageFn(() => userBlur(form, path));
|
|
1638
2023
|
React.useEffect(() => {
|
|
1639
|
-
form
|
|
1640
|
-
return () =>
|
|
1641
|
-
|
|
1642
|
-
form.changeHandlers.delete(path.key);
|
|
1643
|
-
};
|
|
1644
|
-
}, [form, path.key, onChange]);
|
|
2024
|
+
const { token, displaced } = registerFieldMode(form, path, modeOption);
|
|
2025
|
+
return () => unregisterFieldMode(form, path, token);
|
|
2026
|
+
}, [form, path.key, modeOption]);
|
|
1645
2027
|
const depsKey = validateDeps?.length ? validateDeps.join("\n") : void 0;
|
|
1646
2028
|
React.useEffect(() => {
|
|
1647
2029
|
if (!depsKey) return;
|
|
@@ -1649,14 +2031,29 @@
|
|
|
1649
2031
|
registerFieldValidateDeps(form, path.key, depKeys);
|
|
1650
2032
|
return () => unregisterFieldValidateDeps(form, path.key, depKeys);
|
|
1651
2033
|
}, [form, path.key, depsKey]);
|
|
1652
|
-
const
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
2034
|
+
const elementRef = React.useRef(null);
|
|
2035
|
+
const focusRef = React.useCallback((el) => {
|
|
2036
|
+
elementRef.current = el;
|
|
2037
|
+
}, []);
|
|
2038
|
+
React.useEffect(
|
|
2039
|
+
() => on(
|
|
2040
|
+
form.emitter,
|
|
2041
|
+
"focusError",
|
|
2042
|
+
(key, options) => {
|
|
2043
|
+
if (key !== path.key) return;
|
|
2044
|
+
const el = elementRef.current;
|
|
2045
|
+
if (!el || typeof el.focus !== "function") return;
|
|
2046
|
+
el.focus();
|
|
2047
|
+
if (options?.shouldSelect && typeof el.select === "function") {
|
|
2048
|
+
el.select();
|
|
2049
|
+
}
|
|
2050
|
+
}
|
|
2051
|
+
),
|
|
2052
|
+
[form, path.key]
|
|
2053
|
+
);
|
|
1657
2054
|
React.useEffect(
|
|
1658
2055
|
() => () => {
|
|
1659
|
-
if (shouldUnregister !== false) {
|
|
2056
|
+
if ((shouldUnregister ?? form.shouldUnregister) !== false) {
|
|
1660
2057
|
removeFieldByPath(form, path);
|
|
1661
2058
|
}
|
|
1662
2059
|
},
|
|
@@ -1671,7 +2068,8 @@
|
|
|
1671
2068
|
onChange,
|
|
1672
2069
|
onBlur,
|
|
1673
2070
|
name: path.key,
|
|
1674
|
-
disabled: formDisabled || !!disabled
|
|
2071
|
+
disabled: formDisabled || !!disabled,
|
|
2072
|
+
focusRef
|
|
1675
2073
|
};
|
|
1676
2074
|
}
|
|
1677
2075
|
function useField(options) {
|
|
@@ -1900,29 +2298,72 @@
|
|
|
1900
2298
|
return group;
|
|
1901
2299
|
}
|
|
1902
2300
|
|
|
2301
|
+
function appendFormDataValue(fd, key, value) {
|
|
2302
|
+
if (value == null) return;
|
|
2303
|
+
if (Array.isArray(value)) {
|
|
2304
|
+
for (const item of value) appendFormDataValue(fd, key, item);
|
|
2305
|
+
return;
|
|
2306
|
+
}
|
|
2307
|
+
if (typeof FileList !== "undefined" && value instanceof FileList) {
|
|
2308
|
+
for (let i = 0; i < value.length; i++) fd.append(key, value.item(i));
|
|
2309
|
+
return;
|
|
2310
|
+
}
|
|
2311
|
+
if (typeof File !== "undefined" && value instanceof File) {
|
|
2312
|
+
fd.append(key, value, value.name);
|
|
2313
|
+
return;
|
|
2314
|
+
}
|
|
2315
|
+
if (typeof Blob !== "undefined" && value instanceof Blob) {
|
|
2316
|
+
fd.append(key, value);
|
|
2317
|
+
return;
|
|
2318
|
+
}
|
|
2319
|
+
if (value instanceof Date) {
|
|
2320
|
+
fd.append(key, value.toISOString());
|
|
2321
|
+
return;
|
|
2322
|
+
}
|
|
2323
|
+
fd.append(
|
|
2324
|
+
key,
|
|
2325
|
+
typeof value === "object" ? JSON.stringify(value) : String(value)
|
|
2326
|
+
);
|
|
2327
|
+
}
|
|
2328
|
+
function formDataFromValues(values) {
|
|
2329
|
+
const fd = new FormData();
|
|
2330
|
+
for (const key of Object.keys(values)) {
|
|
2331
|
+
appendFormDataValue(fd, key, values[key]);
|
|
2332
|
+
}
|
|
2333
|
+
return fd;
|
|
2334
|
+
}
|
|
2335
|
+
|
|
1903
2336
|
function Form({
|
|
1904
2337
|
form: f1,
|
|
1905
2338
|
context,
|
|
1906
2339
|
initialValues,
|
|
1907
2340
|
values,
|
|
2341
|
+
shouldUnregister,
|
|
1908
2342
|
onSubmit,
|
|
1909
2343
|
onValidSubmit,
|
|
1910
2344
|
onInvalidSubmit,
|
|
2345
|
+
action,
|
|
1911
2346
|
shouldFocusError,
|
|
1912
2347
|
...props
|
|
1913
2348
|
}) {
|
|
1914
|
-
const f2 = useForm({ initialValues, values });
|
|
2349
|
+
const f2 = useForm({ initialValues, values, shouldUnregister });
|
|
1915
2350
|
const form = f1 || f2;
|
|
1916
2351
|
const submit = handleSubmit(form, {
|
|
1917
2352
|
onSubmit,
|
|
1918
2353
|
onValidSubmit,
|
|
1919
2354
|
onInvalidSubmit,
|
|
1920
|
-
shouldFocusError
|
|
2355
|
+
shouldFocusError,
|
|
2356
|
+
onAction: action ? (values2) => action(formDataFromValues(values2)) : void 0
|
|
1921
2357
|
});
|
|
1922
2358
|
const { Provider } = context ?? FormContext;
|
|
1923
2359
|
return /* @__PURE__ */ React__namespace.createElement(Provider, { value: form }, /* @__PURE__ */ React__namespace.createElement("form", { ...props, noValidate: true, onSubmit: submit }));
|
|
1924
2360
|
}
|
|
1925
2361
|
|
|
2362
|
+
function FormField({ children, ...options }) {
|
|
2363
|
+
const field = useField(options);
|
|
2364
|
+
return children(field);
|
|
2365
|
+
}
|
|
2366
|
+
|
|
1926
2367
|
function setRef(ref, value) {
|
|
1927
2368
|
if (typeof ref === "function") {
|
|
1928
2369
|
ref(value);
|
|
@@ -1960,25 +2401,19 @@
|
|
|
1960
2401
|
disabled,
|
|
1961
2402
|
delayError,
|
|
1962
2403
|
mode,
|
|
2404
|
+
uncontrolled,
|
|
1963
2405
|
...props
|
|
1964
2406
|
}, ref) => {
|
|
1965
2407
|
const innerRef = React__namespace.useRef(null);
|
|
1966
2408
|
const [nativeInvalidCount, setNativeInvalidCount] = React__namespace.useState(0);
|
|
1967
|
-
const mergedRef = React__namespace.useCallback(
|
|
1968
|
-
(node) => {
|
|
1969
|
-
innerRef.current = node;
|
|
1970
|
-
setRef(ref, node);
|
|
1971
|
-
},
|
|
1972
|
-
[ref]
|
|
1973
|
-
);
|
|
1974
2409
|
const {
|
|
1975
2410
|
value,
|
|
1976
2411
|
onChange,
|
|
1977
2412
|
onBlur,
|
|
1978
2413
|
error,
|
|
1979
|
-
form,
|
|
1980
2414
|
name: fieldKey,
|
|
1981
|
-
disabled: isDisabled
|
|
2415
|
+
disabled: isDisabled,
|
|
2416
|
+
focusRef
|
|
1982
2417
|
} = useField({
|
|
1983
2418
|
name,
|
|
1984
2419
|
form: formProp,
|
|
@@ -1989,6 +2424,9 @@
|
|
|
1989
2424
|
delayError,
|
|
1990
2425
|
disabled,
|
|
1991
2426
|
mode,
|
|
2427
|
+
// File inputs cannot be value-controlled at all — force the
|
|
2428
|
+
// uncontrolled path so no `value` prop ever reaches the element.
|
|
2429
|
+
uncontrolled: uncontrolled || props.type === "file",
|
|
1992
2430
|
validate: (...params) => {
|
|
1993
2431
|
const el = innerRef.current;
|
|
1994
2432
|
if (el && typeof el.checkValidity === "function") {
|
|
@@ -2001,6 +2439,14 @@
|
|
|
2001
2439
|
if (validate) return validate(...params);
|
|
2002
2440
|
}
|
|
2003
2441
|
});
|
|
2442
|
+
const mergedRef = React__namespace.useCallback(
|
|
2443
|
+
(node) => {
|
|
2444
|
+
innerRef.current = node;
|
|
2445
|
+
focusRef(node);
|
|
2446
|
+
setRef(ref, node);
|
|
2447
|
+
},
|
|
2448
|
+
[ref, focusRef]
|
|
2449
|
+
);
|
|
2004
2450
|
const Component = as || "input";
|
|
2005
2451
|
React__namespace.useEffect(() => {
|
|
2006
2452
|
const el = innerRef.current;
|
|
@@ -2015,23 +2461,9 @@
|
|
|
2015
2461
|
React__namespace.useEffect(() => {
|
|
2016
2462
|
if (nativeInvalidCount > 0) innerRef.current?.reportValidity();
|
|
2017
2463
|
}, [nativeInvalidCount]);
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
"focusError",
|
|
2022
|
-
(key, options) => {
|
|
2023
|
-
if (key !== fieldKey) return;
|
|
2024
|
-
const el = innerRef.current;
|
|
2025
|
-
if (!el || typeof el.focus !== "function") return;
|
|
2026
|
-
el.focus();
|
|
2027
|
-
if (options?.shouldSelect && typeof el.select === "function") {
|
|
2028
|
-
el.select();
|
|
2029
|
-
}
|
|
2030
|
-
}
|
|
2031
|
-
),
|
|
2032
|
-
[form, fieldKey]
|
|
2033
|
-
);
|
|
2034
|
-
const toValue = eventToValue ?? ((e) => e.target.value);
|
|
2464
|
+
const isFile = props.type === "file";
|
|
2465
|
+
const toValue = eventToValue ?? (isFile ? (e) => e.target.files : (e) => e.target.value);
|
|
2466
|
+
const valueProps = valueToProps ? valueToProps(value) : isFile ? {} : uncontrolled ? { defaultValue: value } : { value };
|
|
2035
2467
|
const errorId = errorIdFromKey(fieldKey);
|
|
2036
2468
|
return /* @__PURE__ */ React__namespace.createElement(React__namespace.Fragment, null, /* @__PURE__ */ React__namespace.createElement(
|
|
2037
2469
|
Component,
|
|
@@ -2040,7 +2472,7 @@
|
|
|
2040
2472
|
name: fieldKey,
|
|
2041
2473
|
onBlur,
|
|
2042
2474
|
...asProps,
|
|
2043
|
-
...
|
|
2475
|
+
...valueProps,
|
|
2044
2476
|
...ariaProps(error, fieldKey, props),
|
|
2045
2477
|
disabled: isDisabled,
|
|
2046
2478
|
onChange: (e) => onChange(toValue(e)),
|
|
@@ -2160,9 +2592,11 @@
|
|
|
2160
2592
|
exports.Checkbox = Checkbox;
|
|
2161
2593
|
exports.CheckboxGroupContext = CheckboxGroupContext;
|
|
2162
2594
|
exports.CheckboxGroupProvider = CheckboxGroupProvider;
|
|
2595
|
+
exports.FORM_ERROR = FORM_ERROR;
|
|
2163
2596
|
exports.Field = Field;
|
|
2164
2597
|
exports.Form = Form;
|
|
2165
2598
|
exports.FormContext = FormContext;
|
|
2599
|
+
exports.FormField = FormField;
|
|
2166
2600
|
exports.FormProvider = FormProvider;
|
|
2167
2601
|
exports.Select = Select;
|
|
2168
2602
|
exports.VALIDATION_OUTCOME = VALIDATION_OUTCOME;
|
|
@@ -2193,7 +2627,9 @@
|
|
|
2193
2627
|
exports.incrementSubmitCount = incrementSubmitCount;
|
|
2194
2628
|
exports.isDirty = isDirty;
|
|
2195
2629
|
exports.isTouched = isTouched;
|
|
2630
|
+
exports.registerFieldMode = registerFieldMode;
|
|
2196
2631
|
exports.registerFieldValidateDeps = registerFieldValidateDeps;
|
|
2632
|
+
exports.registerValidatorByPath = registerValidatorByPath;
|
|
2197
2633
|
exports.removeField = removeField;
|
|
2198
2634
|
exports.removeFieldByPath = removeFieldByPath;
|
|
2199
2635
|
exports.reset = reset;
|
|
@@ -2216,6 +2652,7 @@
|
|
|
2216
2652
|
exports.setValueByPath = setValueByPath;
|
|
2217
2653
|
exports.subscribe = subscribe;
|
|
2218
2654
|
exports.trigger = trigger;
|
|
2655
|
+
exports.unregisterFieldMode = unregisterFieldMode;
|
|
2219
2656
|
exports.unregisterFieldValidateDeps = unregisterFieldValidateDeps;
|
|
2220
2657
|
exports.unsetValidatingByPath = unsetValidatingByPath;
|
|
2221
2658
|
exports.useCanSubmit = useCanSubmit;
|
|
@@ -2230,9 +2667,16 @@
|
|
|
2230
2667
|
exports.useFieldErrorsByPath = useFieldErrorsByPath;
|
|
2231
2668
|
exports.useForm = useForm;
|
|
2232
2669
|
exports.useFormContext = useFormContext;
|
|
2670
|
+
exports.useFormError = useFormError;
|
|
2671
|
+
exports.useFormErrors = useFormErrors;
|
|
2672
|
+
exports.useFormState = useFormState;
|
|
2233
2673
|
exports.useHasErrors = useHasErrors;
|
|
2234
2674
|
exports.useIsDirty = useIsDirty;
|
|
2675
|
+
exports.useIsLoading = useIsLoading;
|
|
2676
|
+
exports.useIsSubmitSuccessful = useIsSubmitSuccessful;
|
|
2235
2677
|
exports.useIsSubmitting = useIsSubmitting;
|
|
2678
|
+
exports.useIsValid = useIsValid;
|
|
2679
|
+
exports.useIsValidating = useIsValidating;
|
|
2236
2680
|
exports.useSubmitCount = useSubmitCount;
|
|
2237
2681
|
exports.useTouched = useTouched;
|
|
2238
2682
|
exports.useTouchedByPath = useTouchedByPath;
|
|
@@ -2240,6 +2684,9 @@
|
|
|
2240
2684
|
exports.useValue = useValue;
|
|
2241
2685
|
exports.useValueByPath = useValueByPath;
|
|
2242
2686
|
exports.useWatch = useWatch;
|
|
2687
|
+
exports.useWatchCore = useWatchCore;
|
|
2688
|
+
exports.userBlur = userBlur;
|
|
2689
|
+
exports.userChangeByPath = userChangeByPath;
|
|
2243
2690
|
exports.validate = validate;
|
|
2244
2691
|
|
|
2245
2692
|
}));
|