react-f0rm 0.2.2 → 0.3.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 +527 -33
- package/dist/devtools/index.cjs.js +737 -0
- package/dist/devtools/index.cjs.js.map +1 -0
- package/dist/devtools/index.d.ts +33 -0
- package/dist/devtools/index.mjs +717 -0
- package/dist/devtools/index.mjs.map +1 -0
- package/dist/form-61297bc0.d.ts +578 -0
- package/dist/form-94c70b4b.mjs +378 -0
- package/dist/form-94c70b4b.mjs.map +1 -0
- package/dist/form-b9441d8c.cjs.js +387 -0
- package/dist/form-b9441d8c.cjs.js.map +1 -0
- package/dist/index.cjs.js +1257 -157
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +357 -53
- package/dist/index.mjs +1676 -0
- package/dist/index.mjs.map +1 -0
- package/dist/index.umd.js +1257 -157
- 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/resolvers/standard-schema.cjs.js +90 -0
- package/dist/resolvers/standard-schema.cjs.js.map +1 -0
- package/dist/resolvers/standard-schema.d.ts +66 -0
- package/dist/resolvers/standard-schema.mjs +86 -0
- package/dist/resolvers/standard-schema.mjs.map +1 -0
- package/dist/resolvers/yup.cjs.js +12 -2
- package/dist/resolvers/yup.cjs.js.map +1 -1
- package/dist/resolvers/yup.d.ts +2 -2
- package/dist/resolvers/yup.mjs +23 -0
- package/dist/resolvers/yup.mjs.map +1 -0
- package/dist/resolvers/zod.cjs.js +14 -1
- package/dist/resolvers/zod.cjs.js.map +1 -1
- package/dist/resolvers/zod.d.ts +2 -2
- package/dist/resolvers/zod.mjs +23 -0
- package/dist/resolvers/zod.mjs.map +1 -0
- package/dist/validate-148fe167.d.ts +22 -0
- package/package.json +34 -8
- package/dist/form-d06e6444.d.ts +0 -201
- package/dist/index.esm.js +0 -593
- package/dist/index.esm.js.map +0 -1
- package/dist/resolvers/yup.esm.js +0 -13
- package/dist/resolvers/yup.esm.js.map +0 -1
- package/dist/resolvers/zod.esm.js +0 -10
- package/dist/resolvers/zod.esm.js.map +0 -1
- package/dist/validate-0f17f86a.d.ts +0 -8
package/dist/index.umd.js
CHANGED
|
@@ -49,9 +49,56 @@
|
|
|
49
49
|
};
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
const pathCache = /* @__PURE__ */ new Map();
|
|
52
53
|
function normalizePath(path) {
|
|
53
54
|
if (Array.isArray(path)) return path;
|
|
54
|
-
|
|
55
|
+
const cached = pathCache.get(path);
|
|
56
|
+
if (cached) return cached;
|
|
57
|
+
const value = parsePath(path);
|
|
58
|
+
pathCache.set(path, value);
|
|
59
|
+
return value;
|
|
60
|
+
}
|
|
61
|
+
function parsePath(path) {
|
|
62
|
+
const result = [];
|
|
63
|
+
let identifier = "";
|
|
64
|
+
const flushIdentifier = () => {
|
|
65
|
+
result.push(identifier);
|
|
66
|
+
identifier = "";
|
|
67
|
+
};
|
|
68
|
+
for (let i = 0; i < path.length; i++) {
|
|
69
|
+
const char = path[i];
|
|
70
|
+
if (char === ".") {
|
|
71
|
+
if (identifier !== "") flushIdentifier();
|
|
72
|
+
} else if (char === "[") {
|
|
73
|
+
if (identifier !== "") flushIdentifier();
|
|
74
|
+
const quote = path[i + 1];
|
|
75
|
+
if (quote === '"' || quote === "'") {
|
|
76
|
+
const close = path.indexOf(quote, i + 2);
|
|
77
|
+
if (close === -1) {
|
|
78
|
+
throw new TypeError(`Unterminated quote in path: ${path}`);
|
|
79
|
+
}
|
|
80
|
+
if (path[close + 1] !== "]") {
|
|
81
|
+
throw new TypeError(
|
|
82
|
+
`Expected "]" after quoted segment in path: ${path}`
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
result.push(path.slice(i + 2, close));
|
|
86
|
+
i = close + 1;
|
|
87
|
+
} else {
|
|
88
|
+
const close = path.indexOf("]", i + 1);
|
|
89
|
+
if (close === -1) {
|
|
90
|
+
throw new TypeError(`Unterminated bracket in path: ${path}`);
|
|
91
|
+
}
|
|
92
|
+
const content = path.slice(i + 1, close);
|
|
93
|
+
result.push(/^-?\d+$/.test(content) ? Number(content) : content);
|
|
94
|
+
i = close;
|
|
95
|
+
}
|
|
96
|
+
} else {
|
|
97
|
+
identifier += char;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (identifier !== "" || result.length === 0) flushIdentifier();
|
|
101
|
+
return result;
|
|
55
102
|
}
|
|
56
103
|
function get(values, path) {
|
|
57
104
|
return path.reduce((current, p) => {
|
|
@@ -59,6 +106,24 @@
|
|
|
59
106
|
return current[p];
|
|
60
107
|
}, values);
|
|
61
108
|
}
|
|
109
|
+
function unset(values, path) {
|
|
110
|
+
if (!path.length || values == null) return values;
|
|
111
|
+
const [prop, ...props] = path;
|
|
112
|
+
if (props.length) {
|
|
113
|
+
const next = unset(values[prop], props);
|
|
114
|
+
return next === values[prop] ? values : set(values, path, next);
|
|
115
|
+
}
|
|
116
|
+
if (Array.isArray(values)) {
|
|
117
|
+
if (!(prop in values)) return values;
|
|
118
|
+
const arr = values.slice();
|
|
119
|
+
delete arr[prop];
|
|
120
|
+
return arr;
|
|
121
|
+
}
|
|
122
|
+
if (typeof values !== "object" || !(prop in values)) return values;
|
|
123
|
+
const copy = { ...values };
|
|
124
|
+
delete copy[prop];
|
|
125
|
+
return copy;
|
|
126
|
+
}
|
|
62
127
|
function set(values, path, value) {
|
|
63
128
|
if (!path.length) return value;
|
|
64
129
|
const [prop, ...props] = path;
|
|
@@ -69,6 +134,35 @@
|
|
|
69
134
|
}
|
|
70
135
|
return { ...values, [prop]: set(values && values[prop], props, value) };
|
|
71
136
|
}
|
|
137
|
+
function setOwned(root, path, value, owned) {
|
|
138
|
+
if (!path.length) return value;
|
|
139
|
+
let container = root;
|
|
140
|
+
let parent = null;
|
|
141
|
+
let parentProp = "";
|
|
142
|
+
for (let i = 0; i < path.length; i++) {
|
|
143
|
+
const prop = path[i];
|
|
144
|
+
if (!owned.has(container)) {
|
|
145
|
+
let copy;
|
|
146
|
+
if (typeof prop === "number") {
|
|
147
|
+
copy = Array.isArray(container) ? container.slice() : [];
|
|
148
|
+
} else {
|
|
149
|
+
copy = { ...container };
|
|
150
|
+
}
|
|
151
|
+
owned.add(copy);
|
|
152
|
+
if (i === 0) root = copy;
|
|
153
|
+
else parent[parentProp] = copy;
|
|
154
|
+
container = copy;
|
|
155
|
+
}
|
|
156
|
+
if (i === path.length - 1) {
|
|
157
|
+
container[prop] = value;
|
|
158
|
+
} else {
|
|
159
|
+
parent = container;
|
|
160
|
+
parentProp = prop;
|
|
161
|
+
container = container[prop];
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return root;
|
|
165
|
+
}
|
|
72
166
|
function isPromise(value) {
|
|
73
167
|
return value && typeof value.then === "function";
|
|
74
168
|
}
|
|
@@ -82,7 +176,7 @@
|
|
|
82
176
|
reject();
|
|
83
177
|
return;
|
|
84
178
|
}
|
|
85
|
-
if (isResolve()) return;
|
|
179
|
+
if (!isResolve()) return;
|
|
86
180
|
off();
|
|
87
181
|
resolve();
|
|
88
182
|
});
|
|
@@ -95,85 +189,148 @@
|
|
|
95
189
|
}
|
|
96
190
|
|
|
97
191
|
const emit = emit$1;
|
|
192
|
+
const VALIDATION_OUTCOME = /* @__PURE__ */ Symbol("validation-outcome");
|
|
98
193
|
function create(options) {
|
|
99
194
|
const emitter = create$2();
|
|
100
195
|
return {
|
|
101
196
|
emitter,
|
|
102
|
-
revalidateOnChange: true,
|
|
103
197
|
...options,
|
|
198
|
+
mode: options?.mode ?? "onSubmit",
|
|
199
|
+
reValidateMode: options?.reValidateMode ?? "onChange",
|
|
200
|
+
disabled: options?.disabled ?? false,
|
|
104
201
|
initialValues: options?.initialValues ?? {},
|
|
105
202
|
values: /* @__PURE__ */ new Map(),
|
|
203
|
+
deleted: /* @__PURE__ */ new Set(),
|
|
106
204
|
errors: /* @__PURE__ */ new Map(),
|
|
107
205
|
touched: /* @__PURE__ */ new Set(),
|
|
108
206
|
validators: /* @__PURE__ */ new Map(),
|
|
109
207
|
validating: /* @__PURE__ */ new Set(),
|
|
208
|
+
parsedValues: void 0,
|
|
110
209
|
isSubmitting: false,
|
|
111
210
|
submitCount: 0,
|
|
112
211
|
isSubmitSuccessful: void 0
|
|
113
212
|
};
|
|
114
213
|
}
|
|
115
214
|
function getValues(form) {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
)
|
|
215
|
+
const { initialValues, parsedValues, values, deleted } = form;
|
|
216
|
+
const owned = /* @__PURE__ */ new Set();
|
|
217
|
+
let merged = parsedValues ?? initialValues;
|
|
218
|
+
for (const [key, value] of values) {
|
|
219
|
+
merged = setOwned(merged, JSON.parse(key), value, owned);
|
|
220
|
+
}
|
|
221
|
+
for (const key of deleted) {
|
|
222
|
+
merged = unset(merged, JSON.parse(key));
|
|
223
|
+
}
|
|
224
|
+
return merged;
|
|
120
225
|
}
|
|
121
226
|
function getValue(form, name) {
|
|
122
227
|
return getValueByPath(form, create$1(name));
|
|
123
228
|
}
|
|
124
|
-
function getValueByPath({ initialValues, values }, path) {
|
|
229
|
+
function getValueByPath({ initialValues, parsedValues, values, deleted }, path) {
|
|
125
230
|
if (values.has(path.key)) return values.get(path.key);
|
|
126
|
-
|
|
231
|
+
if (deleted.has(path.key)) return void 0;
|
|
232
|
+
return get(parsedValues ?? initialValues, path.value);
|
|
127
233
|
}
|
|
128
|
-
function setValue(form, name, value) {
|
|
129
|
-
setValueByPath(form, create$1(name), value);
|
|
234
|
+
function setValue(form, name, value, options) {
|
|
235
|
+
setValueByPath(form, create$1(name), value, options);
|
|
130
236
|
}
|
|
131
|
-
function setValueByPath(
|
|
237
|
+
function setValueByPath(form, path, value, options) {
|
|
238
|
+
const { emitter, values, deleted } = form;
|
|
132
239
|
values.set(path.key, value);
|
|
240
|
+
reviveBranch(deleted, path);
|
|
241
|
+
bumpDirtyVersion(form);
|
|
242
|
+
if (options?.shouldTouch) setTouchedByPath(form, path);
|
|
243
|
+
if (options?.shouldValidate) form.validators.get(path.key)?.();
|
|
133
244
|
emit(emitter, "change", path);
|
|
134
245
|
}
|
|
135
246
|
function getError(form, name) {
|
|
136
247
|
return getErrorByPath(form, create$1(name));
|
|
137
248
|
}
|
|
138
249
|
function getErrorByPath({ errors }, path) {
|
|
139
|
-
return errors.get(path.key);
|
|
250
|
+
return errors.get(path.key)?.[0];
|
|
251
|
+
}
|
|
252
|
+
const NO_ERRORS = [];
|
|
253
|
+
function getFieldErrors(form, name) {
|
|
254
|
+
return getFieldErrorsByPath(form, create$1(name));
|
|
255
|
+
}
|
|
256
|
+
function getFieldErrorsByPath({ errors }, path) {
|
|
257
|
+
return errors.get(path.key) ?? NO_ERRORS;
|
|
140
258
|
}
|
|
141
259
|
function getErrors({ errors }) {
|
|
142
|
-
|
|
260
|
+
const entries = [];
|
|
261
|
+
for (const [key, list] of errors) {
|
|
262
|
+
const path = JSON.parse(key).join(".");
|
|
263
|
+
for (const { type, message } of list) entries.push({ path, type, message });
|
|
264
|
+
}
|
|
265
|
+
return entries;
|
|
143
266
|
}
|
|
144
267
|
function getFirstError({ errors }) {
|
|
145
|
-
return errors.values().next().value;
|
|
268
|
+
return errors.values().next().value?.[0]?.message;
|
|
146
269
|
}
|
|
147
|
-
function
|
|
148
|
-
|
|
149
|
-
|
|
270
|
+
function getFieldState(form, name) {
|
|
271
|
+
const path = create$1(name);
|
|
272
|
+
const { initialValues, values, touched, validating } = form;
|
|
273
|
+
const live = values.get(path.key);
|
|
274
|
+
return {
|
|
275
|
+
value: getValueByPath(form, path),
|
|
276
|
+
error: getErrorByPath(form, path),
|
|
277
|
+
errors: getFieldErrorsByPath(form, path),
|
|
278
|
+
isDirty: values.has(path.key) && get(initialValues, path.value) !== live,
|
|
279
|
+
isTouched: touched.has(path.key),
|
|
280
|
+
isValidating: validating.has(path.key)
|
|
281
|
+
};
|
|
150
282
|
}
|
|
151
|
-
function
|
|
152
|
-
validating.
|
|
153
|
-
emit(emitter, "validating");
|
|
283
|
+
function unsetValidatingByPath({ emitter, validating }, path) {
|
|
284
|
+
validating.delete(path.key);
|
|
285
|
+
emit(emitter, "validating", path);
|
|
286
|
+
}
|
|
287
|
+
function setValidatingByPath({ emitter, validating }, path) {
|
|
288
|
+
validating.add(path.key);
|
|
289
|
+
emit(emitter, "validating", path);
|
|
154
290
|
}
|
|
155
291
|
function setError(form, name, error) {
|
|
156
292
|
setErrorByPath(form, create$1(name), error);
|
|
157
293
|
}
|
|
158
294
|
function setErrorByPath({ emitter, errors }, path, error) {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
295
|
+
const list = normalizeErrors(error);
|
|
296
|
+
if (list) errors.set(path.key, list);
|
|
297
|
+
else errors.delete(path.key);
|
|
298
|
+
emit(emitter, "errors", path);
|
|
299
|
+
}
|
|
300
|
+
function normalizeErrors(error) {
|
|
301
|
+
if (typeof error === "string") {
|
|
302
|
+
return error ? [{ type: "custom", message: error }] : void 0;
|
|
163
303
|
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
304
|
+
if (isFieldError(error)) return [error];
|
|
305
|
+
if (!error) return void 0;
|
|
306
|
+
const list = [];
|
|
307
|
+
error.forEach((item) => {
|
|
308
|
+
if (typeof item === "string" && item) {
|
|
309
|
+
list.push({ type: "custom", message: item });
|
|
310
|
+
} else if (isFieldError(item)) {
|
|
311
|
+
list.push(item);
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
return list.length ? list : void 0;
|
|
315
|
+
}
|
|
316
|
+
function clearErrors(form, name) {
|
|
317
|
+
const { emitter, errors } = form;
|
|
318
|
+
if (name === void 0) {
|
|
319
|
+
errors.clear();
|
|
320
|
+
emit(emitter, "errors");
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
const paths = typeof name === "string" || isSegmentsPath(name) ? [create$1(name)] : name.map((one) => create$1(one));
|
|
324
|
+
for (const { key } of paths) errors.delete(key);
|
|
325
|
+
for (const path of paths) emit(emitter, "errors", path);
|
|
169
326
|
}
|
|
170
327
|
function setTouched(form, name) {
|
|
171
328
|
setTouchedByPath(form, create$1(name));
|
|
172
329
|
}
|
|
173
|
-
function setTouchedByPath({ emitter, touched },
|
|
174
|
-
if (touched.has(key)) return;
|
|
175
|
-
touched.add(key);
|
|
176
|
-
emit(emitter, "touched");
|
|
330
|
+
function setTouchedByPath({ emitter, touched }, path) {
|
|
331
|
+
if (touched.has(path.key)) return;
|
|
332
|
+
touched.add(path.key);
|
|
333
|
+
emit(emitter, "touched", path);
|
|
177
334
|
}
|
|
178
335
|
function hasTouched(form, name) {
|
|
179
336
|
return hasTouchedByPath(form, create$1(name));
|
|
@@ -181,12 +338,53 @@
|
|
|
181
338
|
function hasTouchedByPath({ touched }, path) {
|
|
182
339
|
return touched.has(path.key);
|
|
183
340
|
}
|
|
184
|
-
function isDirty(
|
|
341
|
+
function isDirty(form) {
|
|
342
|
+
let dirty = false;
|
|
343
|
+
forEachDirtyField(form, () => {
|
|
344
|
+
dirty = true;
|
|
345
|
+
});
|
|
346
|
+
return dirty;
|
|
347
|
+
}
|
|
348
|
+
function forEachDirtyField({ initialValues, values }, fn) {
|
|
185
349
|
for (const [key, value] of values) {
|
|
186
350
|
const path = JSON.parse(key);
|
|
187
|
-
if (get(initialValues, path) !== value)
|
|
351
|
+
if (get(initialValues, path) !== value) fn(path.join("."));
|
|
188
352
|
}
|
|
189
|
-
|
|
353
|
+
}
|
|
354
|
+
const dirtyFieldsCaches = /* @__PURE__ */ new WeakMap();
|
|
355
|
+
function bumpDirtyVersion(form) {
|
|
356
|
+
const cache = dirtyFieldsCaches.get(form);
|
|
357
|
+
if (cache) cache.version++;
|
|
358
|
+
}
|
|
359
|
+
function computeDirtyFields(form) {
|
|
360
|
+
const dirtyFields = {};
|
|
361
|
+
forEachDirtyField(form, (key) => {
|
|
362
|
+
dirtyFields[key] = true;
|
|
363
|
+
});
|
|
364
|
+
return dirtyFields;
|
|
365
|
+
}
|
|
366
|
+
function sameDirtyKeys(a, b) {
|
|
367
|
+
const aKeys = Object.keys(a);
|
|
368
|
+
if (aKeys.length !== Object.keys(b).length) return false;
|
|
369
|
+
return aKeys.every((key) => b[key] === true);
|
|
370
|
+
}
|
|
371
|
+
function getDirtyFields(form) {
|
|
372
|
+
let cache = dirtyFieldsCaches.get(form);
|
|
373
|
+
if (!cache) {
|
|
374
|
+
cache = { version: 0, result: computeDirtyFields(form) };
|
|
375
|
+
dirtyFieldsCaches.set(form, cache);
|
|
376
|
+
} else if (cache.version > 0) {
|
|
377
|
+
const result = computeDirtyFields(form);
|
|
378
|
+
if (!sameDirtyKeys(cache.result, result)) cache.result = result;
|
|
379
|
+
cache.version = 0;
|
|
380
|
+
}
|
|
381
|
+
return cache.result;
|
|
382
|
+
}
|
|
383
|
+
function getTouchedFields({ touched }) {
|
|
384
|
+
return Array.from(
|
|
385
|
+
touched,
|
|
386
|
+
(key) => JSON.parse(key).join(".")
|
|
387
|
+
);
|
|
190
388
|
}
|
|
191
389
|
function isTouched({ touched }) {
|
|
192
390
|
return touched.size > 0;
|
|
@@ -194,38 +392,154 @@
|
|
|
194
392
|
function removeField(form, name) {
|
|
195
393
|
removeFieldByPath(form, create$1(name));
|
|
196
394
|
}
|
|
197
|
-
function removeFieldByPath(form, { key }) {
|
|
198
|
-
const { emitter, values, touched, errors, validating } = form;
|
|
395
|
+
function removeFieldByPath(form, { key, value: segments }) {
|
|
396
|
+
const { emitter, values, touched, errors, validating, deleted } = form;
|
|
199
397
|
values.delete(key);
|
|
200
398
|
touched.delete(key);
|
|
201
399
|
errors.delete(key);
|
|
202
400
|
validating.delete(key);
|
|
401
|
+
if (!hasLiveBranch(values, segments)) deleted.add(key);
|
|
402
|
+
bumpDirtyVersion(form);
|
|
203
403
|
emit(emitter, "change");
|
|
204
404
|
emit(emitter, "touched");
|
|
205
405
|
emit(emitter, "errors");
|
|
206
406
|
emit(emitter, "validating");
|
|
207
407
|
}
|
|
408
|
+
function hasLiveBranch(values, segments) {
|
|
409
|
+
for (let i = 1; i < segments.length; i++) {
|
|
410
|
+
if (values.has(JSON.stringify(segments.slice(0, i)))) return true;
|
|
411
|
+
}
|
|
412
|
+
const stem = `${JSON.stringify(segments).slice(0, -1)},`;
|
|
413
|
+
for (const key of values.keys()) {
|
|
414
|
+
if (key.startsWith(stem)) return true;
|
|
415
|
+
}
|
|
416
|
+
return false;
|
|
417
|
+
}
|
|
418
|
+
function reviveBranch(deleted, { key }) {
|
|
419
|
+
if (!deleted.size) return;
|
|
420
|
+
for (const tombstone of deleted) {
|
|
421
|
+
if (tombstone === key || tombstone.startsWith(`${key.slice(0, -1)},`) || key.startsWith(`${tombstone.slice(0, -1)},`)) {
|
|
422
|
+
deleted.delete(tombstone);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
}
|
|
208
426
|
function setInitialValues(form, initialValues) {
|
|
209
427
|
if (form.initialValues === initialValues) return;
|
|
210
428
|
form.initialValues = initialValues;
|
|
429
|
+
form.parsedValues = void 0;
|
|
211
430
|
form.values.clear();
|
|
431
|
+
form.deleted.clear();
|
|
432
|
+
bumpDirtyVersion(form);
|
|
212
433
|
emit(form.emitter, "change");
|
|
213
434
|
}
|
|
214
|
-
function reset(form, initialValues) {
|
|
435
|
+
function reset(form, initialValues, options) {
|
|
436
|
+
const dirtyValues = options?.keepDirtyValues ? Object.keys(getDirtyFields(form)).map((key) => ({
|
|
437
|
+
key,
|
|
438
|
+
value: getValue(form, key)
|
|
439
|
+
})) : [];
|
|
215
440
|
form.initialValues = initialValues;
|
|
216
|
-
|
|
217
|
-
|
|
441
|
+
form.parsedValues = void 0;
|
|
442
|
+
if (!options?.keepErrors) clearErrors(form);
|
|
443
|
+
const { emitter, touched, values, deleted, validating } = form;
|
|
218
444
|
values.clear();
|
|
219
|
-
|
|
445
|
+
deleted.clear();
|
|
446
|
+
if (!options?.keepTouched) touched.clear();
|
|
447
|
+
validating.clear();
|
|
448
|
+
if (!options?.keepIsSubmitting) form.isSubmitting = false;
|
|
449
|
+
if (!options?.keepSubmitCount) form.submitCount = 0;
|
|
450
|
+
if (!options?.keepIsSubmitted) form.isSubmitSuccessful = void 0;
|
|
451
|
+
bumpDirtyVersion(form);
|
|
452
|
+
for (const { key, value } of dirtyValues) {
|
|
453
|
+
setValueByPath(form, create$1(key), value);
|
|
454
|
+
}
|
|
220
455
|
emit(emitter, "change");
|
|
221
456
|
emit(emitter, "touched");
|
|
457
|
+
emit(emitter, "validating");
|
|
458
|
+
emit(emitter, "submitting");
|
|
459
|
+
emit(emitter, "submitCount");
|
|
460
|
+
emit(emitter, "submitSuccessful");
|
|
222
461
|
emit(emitter, "reset");
|
|
223
462
|
}
|
|
463
|
+
function resetField(form, name, options) {
|
|
464
|
+
const path = create$1(name);
|
|
465
|
+
const { emitter, values, touched, errors, deleted } = form;
|
|
466
|
+
values.delete(path.key);
|
|
467
|
+
if (form.parsedValues !== void 0) {
|
|
468
|
+
form.parsedValues = unset(form.parsedValues, path.value);
|
|
469
|
+
const initial = get(form.initialValues, path.value);
|
|
470
|
+
if (initial !== void 0) values.set(path.key, initial);
|
|
471
|
+
}
|
|
472
|
+
if (options && "value" in options) {
|
|
473
|
+
values.set(path.key, options.value);
|
|
474
|
+
}
|
|
475
|
+
reviveBranch(deleted, path);
|
|
476
|
+
emit(emitter, "change");
|
|
477
|
+
if (!options?.keepTouched && touched.delete(path.key)) {
|
|
478
|
+
emit(emitter, "touched", path);
|
|
479
|
+
}
|
|
480
|
+
if (!options?.keepErrors && errors.delete(path.key)) {
|
|
481
|
+
emit(emitter, "errors", path);
|
|
482
|
+
}
|
|
483
|
+
bumpDirtyVersion(form);
|
|
484
|
+
}
|
|
224
485
|
function hasErrors({ errors }) {
|
|
225
486
|
return errors.size > 0;
|
|
226
487
|
}
|
|
227
|
-
function trigger(form) {
|
|
228
|
-
|
|
488
|
+
async function trigger(form, name) {
|
|
489
|
+
const settle = () => waitUntil(
|
|
490
|
+
form.emitter,
|
|
491
|
+
"validating",
|
|
492
|
+
() => !form.validating.size,
|
|
493
|
+
() => false
|
|
494
|
+
);
|
|
495
|
+
if (name === void 0) {
|
|
496
|
+
form.validators.forEach((validator) => validator());
|
|
497
|
+
await settle();
|
|
498
|
+
if (form.validate) {
|
|
499
|
+
const result = await form.validate(getValues(form));
|
|
500
|
+
applyValidateResult(form, result);
|
|
501
|
+
}
|
|
502
|
+
return !hasErrors(form);
|
|
503
|
+
}
|
|
504
|
+
const keys = typeof name === "string" || isSegmentsPath(name) ? [create$1(name).key] : name.map((one) => create$1(one).key);
|
|
505
|
+
keys.forEach((key) => form.validators.get(key)?.());
|
|
506
|
+
await settle();
|
|
507
|
+
return keys.every((key) => !form.errors.has(key));
|
|
508
|
+
}
|
|
509
|
+
function isSegmentsPath(name) {
|
|
510
|
+
return name.some((part) => typeof part === "number");
|
|
511
|
+
}
|
|
512
|
+
function isFieldError(value) {
|
|
513
|
+
return !!value && typeof value === "object" && typeof value.type === "string" && typeof value.message === "string";
|
|
514
|
+
}
|
|
515
|
+
function setFormErrors(form, result, segments = []) {
|
|
516
|
+
Object.entries(result).forEach(([key, value]) => {
|
|
517
|
+
const path = [...segments, ...normalizePath(key)];
|
|
518
|
+
if (typeof value === "string") {
|
|
519
|
+
if (value) setError(form, path, value);
|
|
520
|
+
} else if (Array.isArray(value)) {
|
|
521
|
+
setError(form, path, value);
|
|
522
|
+
} else if (isFieldError(value)) {
|
|
523
|
+
setError(form, path, value);
|
|
524
|
+
} else if (value && typeof value === "object") {
|
|
525
|
+
setFormErrors(form, value, path);
|
|
526
|
+
}
|
|
527
|
+
});
|
|
528
|
+
}
|
|
529
|
+
function setParsedValues(form, values) {
|
|
530
|
+
if (values === void 0 || values === form.parsedValues) return;
|
|
531
|
+
form.parsedValues = values;
|
|
532
|
+
emit(form.emitter, "change");
|
|
533
|
+
}
|
|
534
|
+
function applyValidateResult(form, result) {
|
|
535
|
+
if (!result) return;
|
|
536
|
+
if (typeof result === "object" && VALIDATION_OUTCOME in result) {
|
|
537
|
+
const outcome = result;
|
|
538
|
+
if (outcome.errors) setFormErrors(form, outcome.errors);
|
|
539
|
+
setParsedValues(form, outcome.values);
|
|
540
|
+
return;
|
|
541
|
+
}
|
|
542
|
+
setFormErrors(form, result);
|
|
229
543
|
}
|
|
230
544
|
async function ensureValidate(form) {
|
|
231
545
|
form.validators.forEach((validator) => validator());
|
|
@@ -239,13 +553,8 @@
|
|
|
239
553
|
});
|
|
240
554
|
if (form.validate) {
|
|
241
555
|
const result = await form.validate(getValues(form));
|
|
242
|
-
|
|
243
|
-
if (
|
|
244
|
-
entries.forEach(([field, error]) => {
|
|
245
|
-
setError(form, field, error);
|
|
246
|
-
});
|
|
247
|
-
throw new Error(getFirstError(form));
|
|
248
|
-
}
|
|
556
|
+
applyValidateResult(form, result);
|
|
557
|
+
if (hasErrors(form)) throw new Error(getFirstError(form));
|
|
249
558
|
}
|
|
250
559
|
}
|
|
251
560
|
async function validate(form) {
|
|
@@ -263,68 +572,510 @@
|
|
|
263
572
|
form.isSubmitSuccessful = value;
|
|
264
573
|
emit(form.emitter, "submitSuccessful");
|
|
265
574
|
}
|
|
575
|
+
function setDisabled(form, value) {
|
|
576
|
+
form.disabled = value;
|
|
577
|
+
emit(form.emitter, "disabled");
|
|
578
|
+
}
|
|
579
|
+
function nameToPath(name) {
|
|
580
|
+
if (name.startsWith("[")) {
|
|
581
|
+
try {
|
|
582
|
+
const segments = JSON.parse(name);
|
|
583
|
+
if (Array.isArray(segments)) return segments.join(".");
|
|
584
|
+
} catch {
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
return name;
|
|
588
|
+
}
|
|
589
|
+
function getNativeErrors(formEl) {
|
|
590
|
+
const errors = [];
|
|
591
|
+
const { elements } = formEl;
|
|
592
|
+
for (let i = 0; i < elements.length; i++) {
|
|
593
|
+
const el = elements[i];
|
|
594
|
+
if (el.name && typeof el.checkValidity === "function" && !el.checkValidity()) {
|
|
595
|
+
errors.push({
|
|
596
|
+
path: nameToPath(el.name),
|
|
597
|
+
type: "native",
|
|
598
|
+
message: el.validationMessage
|
|
599
|
+
});
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
return errors;
|
|
603
|
+
}
|
|
604
|
+
function handleSubmit(form, options) {
|
|
605
|
+
const {
|
|
606
|
+
onSubmit,
|
|
607
|
+
onValidSubmit,
|
|
608
|
+
onInvalidSubmit,
|
|
609
|
+
shouldFocusError = true
|
|
610
|
+
} = options ?? {};
|
|
611
|
+
return async (e) => {
|
|
612
|
+
if (e && typeof e.preventDefault === "function") {
|
|
613
|
+
e.preventDefault();
|
|
614
|
+
}
|
|
615
|
+
const formEl = e?.currentTarget;
|
|
616
|
+
setIsSubmitting(form, true);
|
|
617
|
+
incrementSubmitCount(form);
|
|
618
|
+
const values = getValues(form);
|
|
619
|
+
if (formEl && typeof formEl.checkValidity === "function" && formEl.checkValidity() === false) {
|
|
620
|
+
formEl.reportValidity();
|
|
621
|
+
if (shouldFocusError && typeof formEl.querySelector === "function") {
|
|
622
|
+
const invalid = formEl.querySelector(":invalid");
|
|
623
|
+
if (invalid && typeof invalid.focus === "function") invalid.focus();
|
|
624
|
+
}
|
|
625
|
+
setIsSubmitting(form, false);
|
|
626
|
+
setSubmitSuccessful(form, false);
|
|
627
|
+
if (onInvalidSubmit) onInvalidSubmit(getNativeErrors(formEl), values);
|
|
628
|
+
return;
|
|
629
|
+
}
|
|
630
|
+
const error = await validate(form);
|
|
631
|
+
if (error) {
|
|
632
|
+
setIsSubmitting(form, false);
|
|
633
|
+
setSubmitSuccessful(form, false);
|
|
634
|
+
if (shouldFocusError) {
|
|
635
|
+
const firstKey = form.errors.keys().next().value;
|
|
636
|
+
if (firstKey !== void 0) emit(form.emitter, "focusError", firstKey);
|
|
637
|
+
}
|
|
638
|
+
if (onInvalidSubmit) onInvalidSubmit(getErrors(form), values);
|
|
639
|
+
return;
|
|
640
|
+
}
|
|
641
|
+
try {
|
|
642
|
+
const submitted = getValues(form);
|
|
643
|
+
if (onSubmit) await onSubmit(submitted, e);
|
|
644
|
+
if (onValidSubmit) await onValidSubmit(submitted, e);
|
|
645
|
+
setSubmitSuccessful(form, true);
|
|
646
|
+
} catch {
|
|
647
|
+
setSubmitSuccessful(form, false);
|
|
648
|
+
} finally {
|
|
649
|
+
setIsSubmitting(form, false);
|
|
650
|
+
}
|
|
651
|
+
};
|
|
652
|
+
}
|
|
653
|
+
function setFocus(form, name, options) {
|
|
654
|
+
const { key } = create$1(name);
|
|
655
|
+
if (options) emit(form.emitter, "focusError", key, options);
|
|
656
|
+
else emit(form.emitter, "focusError", key);
|
|
657
|
+
}
|
|
266
658
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
659
|
+
function defaultMessage(type, bound) {
|
|
660
|
+
switch (type) {
|
|
661
|
+
case "required":
|
|
662
|
+
return "This field is required";
|
|
663
|
+
case "min":
|
|
664
|
+
return `Must be at least ${bound}`;
|
|
665
|
+
case "max":
|
|
666
|
+
return `Must be at most ${bound}`;
|
|
667
|
+
case "minLength":
|
|
668
|
+
return `Must be at least ${bound} characters`;
|
|
669
|
+
case "maxLength":
|
|
670
|
+
return `Must be at most ${bound} characters`;
|
|
671
|
+
case "pattern":
|
|
672
|
+
return "Invalid format";
|
|
673
|
+
default:
|
|
674
|
+
return "Invalid value";
|
|
675
|
+
}
|
|
273
676
|
}
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
677
|
+
function rulesToValidator(rules) {
|
|
678
|
+
return (value) => {
|
|
679
|
+
if (rules.required) {
|
|
680
|
+
if (value === "" || value === void 0 || value === null) {
|
|
681
|
+
return [
|
|
682
|
+
{
|
|
683
|
+
type: "required",
|
|
684
|
+
message: typeof rules.required === "string" ? rules.required : defaultMessage("required")
|
|
685
|
+
}
|
|
686
|
+
];
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
const errors = [];
|
|
690
|
+
const message = (type, bound) => rules.messages?.[type] ?? defaultMessage(type, bound);
|
|
691
|
+
if (rules.min !== void 0) {
|
|
692
|
+
const n = Number(value);
|
|
693
|
+
if (!Number.isNaN(n) && n < rules.min) {
|
|
694
|
+
errors.push({ type: "min", message: message("min", rules.min) });
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
if (rules.max !== void 0) {
|
|
698
|
+
const n = Number(value);
|
|
699
|
+
if (!Number.isNaN(n) && n > rules.max) {
|
|
700
|
+
errors.push({ type: "max", message: message("max", rules.max) });
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
if (rules.minLength !== void 0 && typeof value === "string" && value.length < rules.minLength) {
|
|
704
|
+
errors.push({
|
|
705
|
+
type: "minLength",
|
|
706
|
+
message: message("minLength", rules.minLength)
|
|
707
|
+
});
|
|
708
|
+
}
|
|
709
|
+
if (rules.maxLength !== void 0 && typeof value === "string" && value.length > rules.maxLength) {
|
|
710
|
+
errors.push({
|
|
711
|
+
type: "maxLength",
|
|
712
|
+
message: message("maxLength", rules.maxLength)
|
|
713
|
+
});
|
|
714
|
+
}
|
|
715
|
+
if (rules.pattern && !rules.pattern.value.test(value)) {
|
|
716
|
+
errors.push({
|
|
717
|
+
type: "pattern",
|
|
718
|
+
// pattern.message is type-required but JS consumers may omit it.
|
|
719
|
+
message: rules.messages?.pattern ?? rules.pattern.message ?? defaultMessage("pattern")
|
|
720
|
+
});
|
|
721
|
+
}
|
|
722
|
+
return errors.length ? errors : void 0;
|
|
723
|
+
};
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
var shim = {exports: {}};
|
|
727
|
+
|
|
728
|
+
var useSyncExternalStoreShim_production = {};
|
|
729
|
+
|
|
730
|
+
/**
|
|
731
|
+
* @license React
|
|
732
|
+
* use-sync-external-store-shim.production.js
|
|
733
|
+
*
|
|
734
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
735
|
+
*
|
|
736
|
+
* This source code is licensed under the MIT license found in the
|
|
737
|
+
* LICENSE file in the root directory of this source tree.
|
|
738
|
+
*/
|
|
739
|
+
|
|
740
|
+
var hasRequiredUseSyncExternalStoreShim_production;
|
|
741
|
+
|
|
742
|
+
function requireUseSyncExternalStoreShim_production () {
|
|
743
|
+
if (hasRequiredUseSyncExternalStoreShim_production) return useSyncExternalStoreShim_production;
|
|
744
|
+
hasRequiredUseSyncExternalStoreShim_production = 1;
|
|
745
|
+
var React$1 = React;
|
|
746
|
+
function is(x, y) {
|
|
747
|
+
return (x === y && (0 !== x || 1 / x === 1 / y)) || (x !== x && y !== y);
|
|
748
|
+
}
|
|
749
|
+
var objectIs = "function" === typeof Object.is ? Object.is : is,
|
|
750
|
+
useState = React$1.useState,
|
|
751
|
+
useEffect = React$1.useEffect,
|
|
752
|
+
useLayoutEffect = React$1.useLayoutEffect,
|
|
753
|
+
useDebugValue = React$1.useDebugValue;
|
|
754
|
+
function useSyncExternalStore$2(subscribe, getSnapshot) {
|
|
755
|
+
var value = getSnapshot(),
|
|
756
|
+
_useState = useState({ inst: { value: value, getSnapshot: getSnapshot } }),
|
|
757
|
+
inst = _useState[0].inst,
|
|
758
|
+
forceUpdate = _useState[1];
|
|
759
|
+
useLayoutEffect(
|
|
760
|
+
function () {
|
|
761
|
+
inst.value = value;
|
|
762
|
+
inst.getSnapshot = getSnapshot;
|
|
763
|
+
checkIfSnapshotChanged(inst) && forceUpdate({ inst: inst });
|
|
764
|
+
},
|
|
765
|
+
[subscribe, value, getSnapshot]
|
|
766
|
+
);
|
|
767
|
+
useEffect(
|
|
768
|
+
function () {
|
|
769
|
+
checkIfSnapshotChanged(inst) && forceUpdate({ inst: inst });
|
|
770
|
+
return subscribe(function () {
|
|
771
|
+
checkIfSnapshotChanged(inst) && forceUpdate({ inst: inst });
|
|
772
|
+
});
|
|
773
|
+
},
|
|
774
|
+
[subscribe]
|
|
775
|
+
);
|
|
776
|
+
useDebugValue(value);
|
|
777
|
+
return value;
|
|
778
|
+
}
|
|
779
|
+
function checkIfSnapshotChanged(inst) {
|
|
780
|
+
var latestGetSnapshot = inst.getSnapshot;
|
|
781
|
+
inst = inst.value;
|
|
782
|
+
try {
|
|
783
|
+
var nextValue = latestGetSnapshot();
|
|
784
|
+
return !objectIs(inst, nextValue);
|
|
785
|
+
} catch (error) {
|
|
786
|
+
return !0;
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
function useSyncExternalStore$1(subscribe, getSnapshot) {
|
|
790
|
+
return getSnapshot();
|
|
791
|
+
}
|
|
792
|
+
var shim =
|
|
793
|
+
"undefined" === typeof window ||
|
|
794
|
+
"undefined" === typeof window.document ||
|
|
795
|
+
"undefined" === typeof window.document.createElement
|
|
796
|
+
? useSyncExternalStore$1
|
|
797
|
+
: useSyncExternalStore$2;
|
|
798
|
+
useSyncExternalStoreShim_production.useSyncExternalStore =
|
|
799
|
+
void 0 !== React$1.useSyncExternalStore ? React$1.useSyncExternalStore : shim;
|
|
800
|
+
return useSyncExternalStoreShim_production;
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
var useSyncExternalStoreShim_development = {};
|
|
804
|
+
|
|
805
|
+
/**
|
|
806
|
+
* @license React
|
|
807
|
+
* use-sync-external-store-shim.development.js
|
|
808
|
+
*
|
|
809
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
810
|
+
*
|
|
811
|
+
* This source code is licensed under the MIT license found in the
|
|
812
|
+
* LICENSE file in the root directory of this source tree.
|
|
813
|
+
*/
|
|
814
|
+
|
|
815
|
+
var hasRequiredUseSyncExternalStoreShim_development;
|
|
816
|
+
|
|
817
|
+
function requireUseSyncExternalStoreShim_development () {
|
|
818
|
+
if (hasRequiredUseSyncExternalStoreShim_development) return useSyncExternalStoreShim_development;
|
|
819
|
+
hasRequiredUseSyncExternalStoreShim_development = 1;
|
|
820
|
+
"production" !== process.env.NODE_ENV &&
|
|
821
|
+
(function () {
|
|
822
|
+
function is(x, y) {
|
|
823
|
+
return (x === y && (0 !== x || 1 / x === 1 / y)) || (x !== x && y !== y);
|
|
824
|
+
}
|
|
825
|
+
function useSyncExternalStore$2(subscribe, getSnapshot) {
|
|
826
|
+
didWarnOld18Alpha ||
|
|
827
|
+
void 0 === React$1.startTransition ||
|
|
828
|
+
((didWarnOld18Alpha = !0),
|
|
829
|
+
console.error(
|
|
830
|
+
"You are using an outdated, pre-release alpha of React 18 that does not support useSyncExternalStore. The use-sync-external-store shim will not work correctly. Upgrade to a newer pre-release."
|
|
831
|
+
));
|
|
832
|
+
var value = getSnapshot();
|
|
833
|
+
if (!didWarnUncachedGetSnapshot) {
|
|
834
|
+
var cachedValue = getSnapshot();
|
|
835
|
+
objectIs(value, cachedValue) ||
|
|
836
|
+
(console.error(
|
|
837
|
+
"The result of getSnapshot should be cached to avoid an infinite loop"
|
|
838
|
+
),
|
|
839
|
+
(didWarnUncachedGetSnapshot = !0));
|
|
840
|
+
}
|
|
841
|
+
cachedValue = useState({
|
|
842
|
+
inst: { value: value, getSnapshot: getSnapshot }
|
|
843
|
+
});
|
|
844
|
+
var inst = cachedValue[0].inst,
|
|
845
|
+
forceUpdate = cachedValue[1];
|
|
846
|
+
useLayoutEffect(
|
|
847
|
+
function () {
|
|
848
|
+
inst.value = value;
|
|
849
|
+
inst.getSnapshot = getSnapshot;
|
|
850
|
+
checkIfSnapshotChanged(inst) && forceUpdate({ inst: inst });
|
|
851
|
+
},
|
|
852
|
+
[subscribe, value, getSnapshot]
|
|
853
|
+
);
|
|
854
|
+
useEffect(
|
|
855
|
+
function () {
|
|
856
|
+
checkIfSnapshotChanged(inst) && forceUpdate({ inst: inst });
|
|
857
|
+
return subscribe(function () {
|
|
858
|
+
checkIfSnapshotChanged(inst) && forceUpdate({ inst: inst });
|
|
859
|
+
});
|
|
860
|
+
},
|
|
861
|
+
[subscribe]
|
|
862
|
+
);
|
|
863
|
+
useDebugValue(value);
|
|
864
|
+
return value;
|
|
865
|
+
}
|
|
866
|
+
function checkIfSnapshotChanged(inst) {
|
|
867
|
+
var latestGetSnapshot = inst.getSnapshot;
|
|
868
|
+
inst = inst.value;
|
|
869
|
+
try {
|
|
870
|
+
var nextValue = latestGetSnapshot();
|
|
871
|
+
return !objectIs(inst, nextValue);
|
|
872
|
+
} catch (error) {
|
|
873
|
+
return !0;
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
function useSyncExternalStore$1(subscribe, getSnapshot) {
|
|
877
|
+
return getSnapshot();
|
|
878
|
+
}
|
|
879
|
+
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
|
|
880
|
+
"function" ===
|
|
881
|
+
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart &&
|
|
882
|
+
__REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(Error());
|
|
883
|
+
var React$1 = React,
|
|
884
|
+
objectIs = "function" === typeof Object.is ? Object.is : is,
|
|
885
|
+
useState = React$1.useState,
|
|
886
|
+
useEffect = React$1.useEffect,
|
|
887
|
+
useLayoutEffect = React$1.useLayoutEffect,
|
|
888
|
+
useDebugValue = React$1.useDebugValue,
|
|
889
|
+
didWarnOld18Alpha = !1,
|
|
890
|
+
didWarnUncachedGetSnapshot = !1,
|
|
891
|
+
shim =
|
|
892
|
+
"undefined" === typeof window ||
|
|
893
|
+
"undefined" === typeof window.document ||
|
|
894
|
+
"undefined" === typeof window.document.createElement
|
|
895
|
+
? useSyncExternalStore$1
|
|
896
|
+
: useSyncExternalStore$2;
|
|
897
|
+
useSyncExternalStoreShim_development.useSyncExternalStore =
|
|
898
|
+
void 0 !== React$1.useSyncExternalStore ? React$1.useSyncExternalStore : shim;
|
|
899
|
+
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
|
|
900
|
+
"function" ===
|
|
901
|
+
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&
|
|
902
|
+
__REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(Error());
|
|
903
|
+
})();
|
|
904
|
+
return useSyncExternalStoreShim_development;
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
if (process.env.NODE_ENV === 'production') {
|
|
908
|
+
shim.exports = requireUseSyncExternalStoreShim_production();
|
|
909
|
+
} else {
|
|
910
|
+
shim.exports = requireUseSyncExternalStoreShim_development();
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
var shimExports = shim.exports;
|
|
914
|
+
|
|
915
|
+
function isDescendant(key, ancestorKey) {
|
|
916
|
+
return key.startsWith(`${ancestorKey.slice(0, -1)},`);
|
|
917
|
+
}
|
|
918
|
+
function onPathEvent(emitter, event, path, scope, cb) {
|
|
919
|
+
const { key } = path;
|
|
920
|
+
return on(emitter, event, (changed) => {
|
|
921
|
+
if (changed === void 0 || changed.key === key || isDescendant(key, changed.key) || scope === "branch" && isDescendant(changed.key, key)) {
|
|
922
|
+
cb();
|
|
923
|
+
}
|
|
924
|
+
});
|
|
925
|
+
}
|
|
926
|
+
function onKeyEvent(emitter, event, key, cb) {
|
|
927
|
+
return on(emitter, event, (changed) => {
|
|
928
|
+
if (changed === void 0 || changed.key === key) cb();
|
|
929
|
+
});
|
|
930
|
+
}
|
|
931
|
+
function isNameList(name) {
|
|
932
|
+
return Array.isArray(name) && name.every((part) => typeof part !== "number");
|
|
933
|
+
}
|
|
934
|
+
function subscribe(form, options) {
|
|
935
|
+
const { name, event = "change", scope = "branch", callback } = options;
|
|
936
|
+
if (name === void 0) return on(form.emitter, event, callback);
|
|
937
|
+
const names = isNameList(name) ? name : [name];
|
|
938
|
+
const unsubscribes = names.map((one) => {
|
|
939
|
+
const path = create$1(one);
|
|
940
|
+
return event === "errors" || event === "touched" ? onKeyEvent(form.emitter, event, path.key, callback) : onPathEvent(form.emitter, event, path, scope, callback);
|
|
941
|
+
});
|
|
942
|
+
return unsubscribes.length === 1 ? unsubscribes[0] : () => unsubscribes.forEach((unsubscribe) => unsubscribe());
|
|
280
943
|
}
|
|
281
944
|
|
|
282
945
|
function useForm(options) {
|
|
283
|
-
const
|
|
284
|
-
|
|
946
|
+
const [form] = React.useState(() => {
|
|
947
|
+
const created = create(options);
|
|
948
|
+
if (options && options.values !== void 0) {
|
|
949
|
+
setInitialValues(created, options.values);
|
|
950
|
+
}
|
|
951
|
+
return created;
|
|
952
|
+
});
|
|
285
953
|
const initialValues = options && options.initialValues;
|
|
954
|
+
const values = options && options.values;
|
|
955
|
+
const seededRef = React.useRef(null);
|
|
956
|
+
if (seededRef.current === null)
|
|
957
|
+
seededRef.current = { done: false, source: void 0 };
|
|
286
958
|
React.useEffect(() => {
|
|
959
|
+
const seeded = seededRef.current;
|
|
960
|
+
if (seeded.done && (seeded.source === initialValues || isEqual(seeded.source, initialValues))) {
|
|
961
|
+
return;
|
|
962
|
+
}
|
|
963
|
+
seeded.done = true;
|
|
964
|
+
seeded.source = initialValues;
|
|
287
965
|
setInitialValues(form, initialValues);
|
|
288
|
-
}, [initialValues]);
|
|
966
|
+
}, [form, initialValues]);
|
|
967
|
+
const controlledRef = React.useRef(null);
|
|
968
|
+
if (controlledRef.current === null) {
|
|
969
|
+
controlledRef.current = { done: false, source: void 0 };
|
|
970
|
+
}
|
|
971
|
+
React.useEffect(() => {
|
|
972
|
+
if (values === void 0) return;
|
|
973
|
+
const seeded = controlledRef.current;
|
|
974
|
+
if (seeded.done && (seeded.source === values || isEqual(seeded.source, values))) {
|
|
975
|
+
return;
|
|
976
|
+
}
|
|
977
|
+
seeded.done = true;
|
|
978
|
+
seeded.source = values;
|
|
979
|
+
setInitialValues(form, values);
|
|
980
|
+
}, [form, values]);
|
|
289
981
|
return form;
|
|
290
982
|
}
|
|
983
|
+
function useWatchCore(subscribeFactory, getter) {
|
|
984
|
+
const cacheRef = React.useRef(null);
|
|
985
|
+
if (cacheRef.current === null) cacheRef.current = { hasValue: false };
|
|
986
|
+
const cache = cacheRef.current;
|
|
987
|
+
const getterRef = React.useRef(getter);
|
|
988
|
+
getterRef.current = getter;
|
|
989
|
+
const getSnapshot = React.useCallback(() => {
|
|
990
|
+
if (!cache.hasValue) {
|
|
991
|
+
cache.value = getterRef.current();
|
|
992
|
+
cache.hasValue = true;
|
|
993
|
+
}
|
|
994
|
+
return cache.value;
|
|
995
|
+
}, [cache]);
|
|
996
|
+
const subscribe = React.useCallback(
|
|
997
|
+
(notify) => {
|
|
998
|
+
cache.hasValue = false;
|
|
999
|
+
const invalidate = () => {
|
|
1000
|
+
cache.hasValue = false;
|
|
1001
|
+
notify();
|
|
1002
|
+
};
|
|
1003
|
+
return subscribeFactory(invalidate);
|
|
1004
|
+
},
|
|
1005
|
+
[subscribeFactory, cache]
|
|
1006
|
+
);
|
|
1007
|
+
return shimExports.useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
1008
|
+
}
|
|
291
1009
|
function useWatch(emitter, event, getter) {
|
|
292
|
-
const
|
|
293
|
-
|
|
294
|
-
|
|
1010
|
+
const subscribeFactory = React.useCallback(
|
|
1011
|
+
(invalidate) => on(emitter, event, invalidate),
|
|
1012
|
+
[emitter, event]
|
|
1013
|
+
);
|
|
1014
|
+
return useWatchCore(subscribeFactory, getter);
|
|
295
1015
|
}
|
|
296
1016
|
function useValue(form, name) {
|
|
297
1017
|
return useValueByPath(form, create$1(name));
|
|
298
1018
|
}
|
|
299
1019
|
function useValueByPath(form, path) {
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
1020
|
+
const { emitter } = form;
|
|
1021
|
+
const { key } = path;
|
|
1022
|
+
const subscribeFactory = React.useCallback(
|
|
1023
|
+
(invalidate) => onPathEvent(emitter, "change", path, "leaf", invalidate),
|
|
1024
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps -- deps are `key` on purpose: useValue creates a fresh Path per render, so the object must stay out of the deps while the key string pins the subscription
|
|
1025
|
+
[emitter, key]
|
|
304
1026
|
);
|
|
1027
|
+
return useWatchCore(subscribeFactory, getValueByPath.bind(null, form, path));
|
|
305
1028
|
}
|
|
306
1029
|
function useTouched(form, name) {
|
|
307
1030
|
return useTouchedByPath(form, create$1(name));
|
|
308
1031
|
}
|
|
309
1032
|
function useTouchedByPath(form, path) {
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
1033
|
+
const { emitter } = form;
|
|
1034
|
+
const { key } = path;
|
|
1035
|
+
const subscribeFactory = React.useCallback(
|
|
1036
|
+
(invalidate) => onKeyEvent(emitter, "touched", key, invalidate),
|
|
1037
|
+
[emitter, key]
|
|
1038
|
+
);
|
|
1039
|
+
return useWatchCore(
|
|
1040
|
+
subscribeFactory,
|
|
313
1041
|
hasTouchedByPath.bind(null, form, path)
|
|
314
1042
|
);
|
|
315
1043
|
}
|
|
316
1044
|
function useError(form, name) {
|
|
317
|
-
return useErrorByPath(form, create$1(name));
|
|
1045
|
+
return useErrorByPath(form, create$1(name))?.message;
|
|
318
1046
|
}
|
|
319
1047
|
function useErrorByPath(form, path) {
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
1048
|
+
const { emitter } = form;
|
|
1049
|
+
const { key } = path;
|
|
1050
|
+
const subscribeFactory = React.useCallback(
|
|
1051
|
+
(invalidate) => onKeyEvent(emitter, "errors", key, invalidate),
|
|
1052
|
+
[emitter, key]
|
|
1053
|
+
);
|
|
1054
|
+
return useWatchCore(subscribeFactory, getErrorByPath.bind(null, form, path));
|
|
1055
|
+
}
|
|
1056
|
+
function useFieldErrors(form, name) {
|
|
1057
|
+
return useFieldErrorsByPath(form, create$1(name));
|
|
1058
|
+
}
|
|
1059
|
+
function useFieldErrorsByPath(form, path) {
|
|
1060
|
+
const { emitter } = form;
|
|
1061
|
+
const { key } = path;
|
|
1062
|
+
const subscribeFactory = React.useCallback(
|
|
1063
|
+
(invalidate) => onKeyEvent(emitter, "errors", key, invalidate),
|
|
1064
|
+
[emitter, key]
|
|
1065
|
+
);
|
|
1066
|
+
return useWatchCore(
|
|
1067
|
+
subscribeFactory,
|
|
1068
|
+
getFieldErrorsByPath.bind(null, form, path)
|
|
324
1069
|
);
|
|
325
1070
|
}
|
|
326
1071
|
function useIsDirty(form) {
|
|
327
|
-
return useWatch(form.emitter, "
|
|
1072
|
+
return useWatch(form.emitter, "change", isDirty.bind(null, form));
|
|
1073
|
+
}
|
|
1074
|
+
function useDirtyFields(form) {
|
|
1075
|
+
return useWatch(form.emitter, "change", getDirtyFields.bind(null, form));
|
|
1076
|
+
}
|
|
1077
|
+
function useTouchedFields(form) {
|
|
1078
|
+
return useWatch(form.emitter, "touched", getTouchedFields.bind(null, form));
|
|
328
1079
|
}
|
|
329
1080
|
function useHasErrors(form) {
|
|
330
1081
|
return useWatch(form.emitter, "errors", hasErrors.bind(null, form));
|
|
@@ -335,6 +1086,31 @@
|
|
|
335
1086
|
function useSubmitCount(form) {
|
|
336
1087
|
return useWatch(form.emitter, "submitCount", () => form.submitCount);
|
|
337
1088
|
}
|
|
1089
|
+
function isEqual(a, b) {
|
|
1090
|
+
if (Object.is(a, b)) return true;
|
|
1091
|
+
if (a instanceof Date && b instanceof Date)
|
|
1092
|
+
return a.getTime() === b.getTime();
|
|
1093
|
+
if (!a || !b || typeof a !== "object" || typeof b !== "object") return false;
|
|
1094
|
+
const isArray = Array.isArray(a);
|
|
1095
|
+
if (isArray !== Array.isArray(b)) return false;
|
|
1096
|
+
if (isArray) {
|
|
1097
|
+
if (a.length !== b.length) return false;
|
|
1098
|
+
for (let i = 0; i < a.length; i++) {
|
|
1099
|
+
if (!isEqual(a[i], b[i])) return false;
|
|
1100
|
+
}
|
|
1101
|
+
return true;
|
|
1102
|
+
}
|
|
1103
|
+
const proto = Object.getPrototypeOf(a);
|
|
1104
|
+
if (proto !== Object.prototype && proto !== null) return false;
|
|
1105
|
+
if (Object.getPrototypeOf(b) !== proto) return false;
|
|
1106
|
+
const keysA = Object.keys(a);
|
|
1107
|
+
const keysB = Object.keys(b);
|
|
1108
|
+
if (keysA.length !== keysB.length) return false;
|
|
1109
|
+
for (const key of keysA) {
|
|
1110
|
+
if (!isEqual(a[key], b[key])) return false;
|
|
1111
|
+
}
|
|
1112
|
+
return true;
|
|
1113
|
+
}
|
|
338
1114
|
|
|
339
1115
|
function usePath(name) {
|
|
340
1116
|
const path = React.useMemo(() => create$1(normalizePath(name)), [name]);
|
|
@@ -350,70 +1126,174 @@
|
|
|
350
1126
|
const ref = useStage(fn);
|
|
351
1127
|
return React.useCallback(
|
|
352
1128
|
(...params) => ref.current(...params),
|
|
353
|
-
[]
|
|
1129
|
+
[ref]
|
|
354
1130
|
);
|
|
355
1131
|
}
|
|
356
1132
|
|
|
357
|
-
function useValidate(validate, path) {
|
|
358
|
-
const
|
|
1133
|
+
function useValidate(validate, path, formProp, options) {
|
|
1134
|
+
const contextForm = React.useContext(FormContext);
|
|
1135
|
+
const form = formProp || contextForm;
|
|
1136
|
+
if (!form) throw new Error("no form provided");
|
|
359
1137
|
const lockRef = React.useRef(null);
|
|
360
1138
|
const validateRef = React.useRef(validate);
|
|
361
1139
|
validateRef.current = validate;
|
|
1140
|
+
const debounceRef = React.useRef(options?.debounce ?? 0);
|
|
1141
|
+
debounceRef.current = options?.debounce ?? 0;
|
|
362
1142
|
React.useEffect(() => {
|
|
363
|
-
|
|
1143
|
+
let timer = null;
|
|
1144
|
+
let controller = null;
|
|
1145
|
+
let marked = false;
|
|
1146
|
+
const mark = () => {
|
|
1147
|
+
if (marked) return;
|
|
1148
|
+
marked = true;
|
|
1149
|
+
setValidatingByPath(form, path);
|
|
1150
|
+
};
|
|
1151
|
+
const unmark = () => {
|
|
1152
|
+
if (!marked) return;
|
|
1153
|
+
marked = false;
|
|
1154
|
+
unsetValidatingByPath(form, path);
|
|
1155
|
+
};
|
|
1156
|
+
const run = () => {
|
|
1157
|
+
timer = null;
|
|
364
1158
|
const fn = validateRef.current;
|
|
365
|
-
if (!fn)
|
|
366
|
-
|
|
1159
|
+
if (!fn) {
|
|
1160
|
+
unmark();
|
|
1161
|
+
return;
|
|
1162
|
+
}
|
|
1163
|
+
controller?.abort();
|
|
1164
|
+
controller = new AbortController();
|
|
1165
|
+
const lock = lockRef.current = {};
|
|
1166
|
+
let result;
|
|
1167
|
+
try {
|
|
1168
|
+
result = fn(getValueByPath(form, path), {
|
|
1169
|
+
form,
|
|
1170
|
+
path,
|
|
1171
|
+
signal: controller.signal
|
|
1172
|
+
});
|
|
1173
|
+
} catch (e) {
|
|
1174
|
+
unmark();
|
|
1175
|
+
throw e;
|
|
1176
|
+
}
|
|
367
1177
|
if (!isPromise(result)) {
|
|
368
1178
|
setErrorByPath(form, path, result);
|
|
1179
|
+
unmark();
|
|
369
1180
|
return;
|
|
370
1181
|
}
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
1182
|
+
mark();
|
|
1183
|
+
result.then(
|
|
1184
|
+
(error) => {
|
|
1185
|
+
if (lock === lockRef.current) {
|
|
1186
|
+
setErrorByPath(form, path, error);
|
|
1187
|
+
}
|
|
376
1188
|
}
|
|
1189
|
+
).catch(() => {
|
|
377
1190
|
}).finally(() => {
|
|
378
1191
|
if (lock === lockRef.current) {
|
|
379
|
-
|
|
1192
|
+
unmark();
|
|
380
1193
|
lockRef.current = null;
|
|
381
1194
|
}
|
|
382
1195
|
});
|
|
383
1196
|
};
|
|
1197
|
+
const validator = () => {
|
|
1198
|
+
const debounce = debounceRef.current;
|
|
1199
|
+
if (debounce > 0) {
|
|
1200
|
+
if (timer !== null) clearTimeout(timer);
|
|
1201
|
+
else mark();
|
|
1202
|
+
timer = setTimeout(run, debounce);
|
|
1203
|
+
return;
|
|
1204
|
+
}
|
|
1205
|
+
run();
|
|
1206
|
+
};
|
|
384
1207
|
form.validators.set(path.key, validator);
|
|
385
1208
|
return () => {
|
|
386
1209
|
form.validators.delete(path.key);
|
|
1210
|
+
if (timer !== null) {
|
|
1211
|
+
clearTimeout(timer);
|
|
1212
|
+
timer = null;
|
|
1213
|
+
}
|
|
1214
|
+
unmark();
|
|
1215
|
+
controller?.abort();
|
|
387
1216
|
};
|
|
388
1217
|
}, [form, path.key]);
|
|
389
1218
|
return useStageFn(() => form.validators.get(path.key)?.());
|
|
390
1219
|
}
|
|
391
1220
|
|
|
392
|
-
function
|
|
1221
|
+
function combineRulesAndValidate(rules, validate) {
|
|
1222
|
+
if (!rules) return validate;
|
|
1223
|
+
const ruleValidator = rulesToValidator(rules);
|
|
1224
|
+
if (!validate) return ruleValidator;
|
|
1225
|
+
return (value, meta) => {
|
|
1226
|
+
const ruleErrors = ruleValidator(value, meta);
|
|
1227
|
+
const merge = (other) => {
|
|
1228
|
+
const list = [...ruleErrors ?? []];
|
|
1229
|
+
if (Array.isArray(other)) list.push(...other);
|
|
1230
|
+
else if (other) list.push(other);
|
|
1231
|
+
return list.length ? list : void 0;
|
|
1232
|
+
};
|
|
1233
|
+
const result = validate(value, meta);
|
|
1234
|
+
return isPromise(result) ? result.then(merge) : merge(result);
|
|
1235
|
+
};
|
|
1236
|
+
}
|
|
1237
|
+
function useDelayedErrors(errors, delay) {
|
|
1238
|
+
const [shown, setShown] = React.useState(errors);
|
|
1239
|
+
React.useEffect(() => {
|
|
1240
|
+
if (delay === void 0) return;
|
|
1241
|
+
if (errors.length === 0) {
|
|
1242
|
+
setShown(errors);
|
|
1243
|
+
return;
|
|
1244
|
+
}
|
|
1245
|
+
if (shown.length > 0) {
|
|
1246
|
+
setShown(errors);
|
|
1247
|
+
return;
|
|
1248
|
+
}
|
|
1249
|
+
const timer = setTimeout(() => setShown(errors), delay);
|
|
1250
|
+
return () => clearTimeout(timer);
|
|
1251
|
+
}, [errors, delay, shown]);
|
|
1252
|
+
return delay === void 0 ? errors : shown;
|
|
1253
|
+
}
|
|
1254
|
+
function useFieldCore({
|
|
393
1255
|
form: f1,
|
|
394
1256
|
name,
|
|
395
1257
|
initialValue,
|
|
396
1258
|
shouldUnregister,
|
|
397
1259
|
validate,
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
1260
|
+
rules,
|
|
1261
|
+
validateDebounce,
|
|
1262
|
+
delayError,
|
|
1263
|
+
disabled
|
|
1264
|
+
}, Context) {
|
|
1265
|
+
const contextForm = React.useContext(Context);
|
|
1266
|
+
const form = f1 || contextForm;
|
|
1267
|
+
if (!form) throw new Error("no form provided");
|
|
402
1268
|
const path = usePath(name);
|
|
403
|
-
const validator = useValidate(
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
1269
|
+
const validator = useValidate(
|
|
1270
|
+
combineRulesAndValidate(rules, validate),
|
|
1271
|
+
path,
|
|
1272
|
+
form,
|
|
1273
|
+
{
|
|
1274
|
+
debounce: validateDebounce
|
|
1275
|
+
}
|
|
1276
|
+
);
|
|
1277
|
+
const liveErrors = useFieldErrorsByPath(form, path);
|
|
1278
|
+
const errors = useDelayedErrors(liveErrors, delayError);
|
|
1279
|
+
const errorObject = errors[0];
|
|
1280
|
+
const error = errorObject?.message;
|
|
408
1281
|
const value = useValueByPath(form, path);
|
|
1282
|
+
const formDisabled = useWatch(form.emitter, "disabled", () => form.disabled);
|
|
1283
|
+
React.useEffect(() => {
|
|
1284
|
+
if (initialValue === void 0) return;
|
|
1285
|
+
if (getValueByPath(form, path) === void 0) {
|
|
1286
|
+
setValueByPath(form, path, initialValue);
|
|
1287
|
+
}
|
|
1288
|
+
}, [form, path, initialValue]);
|
|
409
1289
|
const onChange = useStageFn((v) => {
|
|
410
1290
|
setValueByPath(form, path, v);
|
|
411
|
-
if (form.
|
|
1291
|
+
if (form.mode === "onChange" || form.mode === "all" || form.mode === "onTouched" && hasTouchedByPath(form, path) || liveErrors.length > 0 && form.reValidateMode === "onChange")
|
|
412
1292
|
validator();
|
|
413
1293
|
});
|
|
414
1294
|
const onBlur = useStageFn(() => {
|
|
415
1295
|
setTouchedByPath(form, path);
|
|
416
|
-
if (form.
|
|
1296
|
+
if (form.mode === "onBlur" || form.mode === "onTouched" || form.mode === "all" || liveErrors.length > 0 && form.reValidateMode === "onBlur")
|
|
417
1297
|
validator();
|
|
418
1298
|
});
|
|
419
1299
|
React.useEffect(
|
|
@@ -424,16 +1304,30 @@
|
|
|
424
1304
|
},
|
|
425
1305
|
[path, form, shouldUnregister]
|
|
426
1306
|
);
|
|
427
|
-
return {
|
|
1307
|
+
return {
|
|
1308
|
+
form,
|
|
1309
|
+
value,
|
|
1310
|
+
error,
|
|
1311
|
+
errorObject,
|
|
1312
|
+
errors,
|
|
1313
|
+
onChange,
|
|
1314
|
+
onBlur,
|
|
1315
|
+
name: path.key,
|
|
1316
|
+
disabled: formDisabled || !!disabled
|
|
1317
|
+
};
|
|
1318
|
+
}
|
|
1319
|
+
function useField(options) {
|
|
1320
|
+
return useFieldCore(options, FormContext);
|
|
428
1321
|
}
|
|
429
1322
|
|
|
430
1323
|
let idCounter = 0;
|
|
431
1324
|
function generateId() {
|
|
432
1325
|
return `_${++idCounter}`;
|
|
433
1326
|
}
|
|
434
|
-
function
|
|
435
|
-
const
|
|
436
|
-
const form = options.form ||
|
|
1327
|
+
function useFieldArrayCore(options, Context) {
|
|
1328
|
+
const contextForm = React.useContext(Context);
|
|
1329
|
+
const form = options.form || contextForm;
|
|
1330
|
+
if (!form) throw new Error("no form provided");
|
|
437
1331
|
const path = usePath(options.name);
|
|
438
1332
|
const idsRef = React.useRef([]);
|
|
439
1333
|
const getArray = React.useCallback(
|
|
@@ -461,7 +1355,10 @@
|
|
|
461
1355
|
void 0,
|
|
462
1356
|
computeFields
|
|
463
1357
|
);
|
|
464
|
-
React.useEffect(
|
|
1358
|
+
React.useEffect(
|
|
1359
|
+
() => onPathEvent(form.emitter, "change", path, "branch", syncFields),
|
|
1360
|
+
[form.emitter, path]
|
|
1361
|
+
);
|
|
465
1362
|
const append = useStageFn((value) => {
|
|
466
1363
|
const arr = getArray();
|
|
467
1364
|
idsRef.current.push(generateId());
|
|
@@ -503,45 +1400,80 @@
|
|
|
503
1400
|
newArr.splice(to, 0, item);
|
|
504
1401
|
setArray(newArr);
|
|
505
1402
|
});
|
|
506
|
-
|
|
1403
|
+
const replace = useStageFn((values) => {
|
|
1404
|
+
idsRef.current = values.map(() => generateId());
|
|
1405
|
+
setArray([...values]);
|
|
1406
|
+
});
|
|
1407
|
+
const update = useStageFn((index, value) => {
|
|
1408
|
+
const arr = getArray();
|
|
1409
|
+
if (index < 0 || index >= arr.length) return;
|
|
1410
|
+
const newArr = [...arr];
|
|
1411
|
+
newArr[index] = value;
|
|
1412
|
+
setArray(newArr);
|
|
1413
|
+
});
|
|
1414
|
+
return { fields, append, prepend, insert, remove, swap, move, replace, update };
|
|
1415
|
+
}
|
|
1416
|
+
function useFieldArray(options) {
|
|
1417
|
+
return useFieldArrayCore(options, FormContext);
|
|
1418
|
+
}
|
|
1419
|
+
|
|
1420
|
+
const FormContext = React.createContext(null);
|
|
1421
|
+
const FormProvider = FormContext.Provider;
|
|
1422
|
+
function useFormContext() {
|
|
1423
|
+
const form = React.useContext(FormContext);
|
|
1424
|
+
if (!form) throw new Error("no form provided");
|
|
1425
|
+
return form;
|
|
1426
|
+
}
|
|
1427
|
+
function createFormContext() {
|
|
1428
|
+
const Context = React.createContext(null);
|
|
1429
|
+
function FormProvider2({
|
|
1430
|
+
form,
|
|
1431
|
+
children
|
|
1432
|
+
}) {
|
|
1433
|
+
return React.createElement(Context.Provider, { value: form }, children);
|
|
1434
|
+
}
|
|
1435
|
+
function useFormContext2() {
|
|
1436
|
+
const form = React.useContext(Context);
|
|
1437
|
+
if (!form) throw new Error("no form provided");
|
|
1438
|
+
return form;
|
|
1439
|
+
}
|
|
1440
|
+
function useField(options) {
|
|
1441
|
+
return useFieldCore(options, Context);
|
|
1442
|
+
}
|
|
1443
|
+
function useFieldArray(options) {
|
|
1444
|
+
return useFieldArrayCore(options, Context);
|
|
1445
|
+
}
|
|
1446
|
+
return { FormProvider: FormProvider2, useFormContext: useFormContext2, useField, useFieldArray };
|
|
1447
|
+
}
|
|
1448
|
+
const CheckboxGroupContext = React.createContext(null);
|
|
1449
|
+
const CheckboxGroupProvider = CheckboxGroupContext.Provider;
|
|
1450
|
+
function useCheckboxGroupContext() {
|
|
1451
|
+
const group = React.useContext(CheckboxGroupContext);
|
|
1452
|
+
if (!group) throw new Error("no group provided");
|
|
1453
|
+
return group;
|
|
507
1454
|
}
|
|
508
1455
|
|
|
509
1456
|
function Form({
|
|
510
1457
|
form: f1,
|
|
511
1458
|
initialValues,
|
|
1459
|
+
values,
|
|
512
1460
|
onSubmit,
|
|
513
1461
|
onValidSubmit,
|
|
514
1462
|
onInvalidSubmit,
|
|
1463
|
+
shouldFocusError,
|
|
515
1464
|
...props
|
|
516
1465
|
}) {
|
|
517
|
-
const f2 = useForm({ initialValues });
|
|
1466
|
+
const f2 = useForm({ initialValues, values });
|
|
518
1467
|
const form = f1 || f2;
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
setIsSubmitting(form, false);
|
|
527
|
-
setSubmitSuccessful(form, false);
|
|
528
|
-
if (onInvalidSubmit) onInvalidSubmit(getErrors(form), values);
|
|
529
|
-
return;
|
|
530
|
-
}
|
|
531
|
-
try {
|
|
532
|
-
if (onSubmit) await onSubmit(values, e);
|
|
533
|
-
if (onValidSubmit) onValidSubmit(values, e);
|
|
534
|
-
setSubmitSuccessful(form, true);
|
|
535
|
-
} catch {
|
|
536
|
-
setSubmitSuccessful(form, false);
|
|
537
|
-
} finally {
|
|
538
|
-
setIsSubmitting(form, false);
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
return /* @__PURE__ */ React__namespace.createElement(FormProvider, { value: form }, /* @__PURE__ */ React__namespace.createElement("form", { ...props, noValidate: true, onSubmit: handleSubmit }));
|
|
1468
|
+
const submit = handleSubmit(form, {
|
|
1469
|
+
onSubmit,
|
|
1470
|
+
onValidSubmit,
|
|
1471
|
+
onInvalidSubmit,
|
|
1472
|
+
shouldFocusError
|
|
1473
|
+
});
|
|
1474
|
+
return /* @__PURE__ */ React__namespace.createElement(FormProvider, { value: form }, /* @__PURE__ */ React__namespace.createElement("form", { ...props, noValidate: true, onSubmit: submit }));
|
|
542
1475
|
}
|
|
543
1476
|
|
|
544
|
-
const buildInError = /* @__PURE__ */ Symbol("buildInError");
|
|
545
1477
|
function setRef(ref, value) {
|
|
546
1478
|
if (typeof ref === "function") {
|
|
547
1479
|
ref(value);
|
|
@@ -549,9 +1481,30 @@
|
|
|
549
1481
|
ref.current = value;
|
|
550
1482
|
}
|
|
551
1483
|
}
|
|
1484
|
+
function errorIdFromKey(key) {
|
|
1485
|
+
const id = key.replace(/["'[\],\s]+/g, "-").replace(/^-+|-+$/g, "");
|
|
1486
|
+
return id || "field";
|
|
1487
|
+
}
|
|
552
1488
|
const Field = React__namespace.forwardRef(
|
|
553
|
-
({
|
|
1489
|
+
({
|
|
1490
|
+
validate,
|
|
1491
|
+
eventToValue,
|
|
1492
|
+
initialValue,
|
|
1493
|
+
name,
|
|
1494
|
+
asProps,
|
|
1495
|
+
renderError,
|
|
1496
|
+
as,
|
|
1497
|
+
valueToProps,
|
|
1498
|
+
form: formProp,
|
|
1499
|
+
shouldUnregister,
|
|
1500
|
+
rules,
|
|
1501
|
+
validateDebounce,
|
|
1502
|
+
disabled,
|
|
1503
|
+
delayError,
|
|
1504
|
+
...props
|
|
1505
|
+
}, ref) => {
|
|
554
1506
|
const innerRef = React__namespace.useRef(null);
|
|
1507
|
+
const [nativeInvalidCount, setNativeInvalidCount] = React__namespace.useState(0);
|
|
555
1508
|
const mergedRef = React__namespace.useCallback(
|
|
556
1509
|
(node) => {
|
|
557
1510
|
innerRef.current = node;
|
|
@@ -559,57 +1512,187 @@
|
|
|
559
1512
|
},
|
|
560
1513
|
[ref]
|
|
561
1514
|
);
|
|
562
|
-
const {
|
|
563
|
-
|
|
1515
|
+
const {
|
|
1516
|
+
value,
|
|
1517
|
+
onChange,
|
|
1518
|
+
onBlur,
|
|
1519
|
+
error,
|
|
1520
|
+
form,
|
|
1521
|
+
name: fieldKey,
|
|
1522
|
+
disabled: isDisabled
|
|
1523
|
+
} = useField({
|
|
564
1524
|
name,
|
|
1525
|
+
form: formProp,
|
|
565
1526
|
initialValue,
|
|
1527
|
+
shouldUnregister,
|
|
1528
|
+
rules,
|
|
1529
|
+
validateDebounce,
|
|
1530
|
+
delayError,
|
|
1531
|
+
disabled,
|
|
566
1532
|
validate: (...params) => {
|
|
567
|
-
|
|
568
|
-
|
|
1533
|
+
const el = innerRef.current;
|
|
1534
|
+
if (el && typeof el.checkValidity === "function") {
|
|
1535
|
+
el.setCustomValidity("");
|
|
1536
|
+
if (el.checkValidity() === false) {
|
|
1537
|
+
setNativeInvalidCount((count) => count + 1);
|
|
1538
|
+
return void 0;
|
|
1539
|
+
}
|
|
1540
|
+
}
|
|
569
1541
|
if (validate) return validate(...params);
|
|
570
1542
|
}
|
|
571
1543
|
});
|
|
572
1544
|
const Component = as || "input";
|
|
573
1545
|
React__namespace.useEffect(() => {
|
|
574
|
-
|
|
575
|
-
if (
|
|
576
|
-
innerRef.current.setCustomValidity("");
|
|
577
|
-
innerRef.current.reportValidity();
|
|
578
|
-
return;
|
|
579
|
-
}
|
|
1546
|
+
const el = innerRef.current;
|
|
1547
|
+
if (!el || typeof el.setCustomValidity !== "function") return;
|
|
580
1548
|
if (typeof error === "string") {
|
|
581
|
-
|
|
582
|
-
|
|
1549
|
+
el.setCustomValidity(error);
|
|
1550
|
+
el.reportValidity();
|
|
1551
|
+
} else {
|
|
1552
|
+
el.setCustomValidity("");
|
|
583
1553
|
}
|
|
584
1554
|
}, [error]);
|
|
1555
|
+
React__namespace.useEffect(() => {
|
|
1556
|
+
if (nativeInvalidCount > 0) innerRef.current?.reportValidity();
|
|
1557
|
+
}, [nativeInvalidCount]);
|
|
1558
|
+
React__namespace.useEffect(
|
|
1559
|
+
() => on(
|
|
1560
|
+
form.emitter,
|
|
1561
|
+
"focusError",
|
|
1562
|
+
(key, options) => {
|
|
1563
|
+
if (key !== fieldKey) return;
|
|
1564
|
+
const el = innerRef.current;
|
|
1565
|
+
if (!el || typeof el.focus !== "function") return;
|
|
1566
|
+
el.focus();
|
|
1567
|
+
if (options?.shouldSelect && typeof el.select === "function") {
|
|
1568
|
+
el.select();
|
|
1569
|
+
}
|
|
1570
|
+
}
|
|
1571
|
+
),
|
|
1572
|
+
[form, fieldKey]
|
|
1573
|
+
);
|
|
585
1574
|
const toValue = eventToValue ?? ((e) => e.target.value);
|
|
586
|
-
|
|
1575
|
+
const errorId = errorIdFromKey(fieldKey);
|
|
1576
|
+
return /* @__PURE__ */ React__namespace.createElement(React__namespace.Fragment, null, /* @__PURE__ */ React__namespace.createElement(
|
|
587
1577
|
Component,
|
|
588
1578
|
{
|
|
589
|
-
|
|
1579
|
+
"aria-invalid": error ? true : void 0,
|
|
1580
|
+
"aria-describedby": error && renderError ? errorId : void 0,
|
|
1581
|
+
...props,
|
|
1582
|
+
name: fieldKey,
|
|
1583
|
+
onBlur,
|
|
590
1584
|
...asProps,
|
|
591
1585
|
...valueToProps ? valueToProps(value) : { value },
|
|
1586
|
+
disabled: isDisabled,
|
|
592
1587
|
onChange: (e) => onChange(toValue(e)),
|
|
593
1588
|
ref: mergedRef
|
|
594
1589
|
}
|
|
595
|
-
);
|
|
1590
|
+
), error && renderError ? /* @__PURE__ */ React__namespace.createElement("span", { id: errorId, role: "alert" }, renderError(error, errorId)) : null);
|
|
596
1591
|
}
|
|
597
1592
|
);
|
|
598
1593
|
const Checkbox = React__namespace.forwardRef(
|
|
599
|
-
({
|
|
600
|
-
|
|
1594
|
+
({
|
|
1595
|
+
name,
|
|
1596
|
+
form,
|
|
1597
|
+
initialValue,
|
|
1598
|
+
shouldUnregister,
|
|
1599
|
+
validate,
|
|
1600
|
+
rules,
|
|
1601
|
+
validateDebounce,
|
|
1602
|
+
disabled,
|
|
1603
|
+
delayError,
|
|
1604
|
+
...props
|
|
1605
|
+
}, ref) => {
|
|
1606
|
+
const {
|
|
1607
|
+
value,
|
|
1608
|
+
onChange,
|
|
1609
|
+
onBlur,
|
|
1610
|
+
error,
|
|
1611
|
+
name: fieldKey,
|
|
1612
|
+
disabled: isDisabled
|
|
1613
|
+
} = useField({
|
|
1614
|
+
name,
|
|
1615
|
+
form,
|
|
1616
|
+
initialValue,
|
|
1617
|
+
shouldUnregister,
|
|
1618
|
+
validate,
|
|
1619
|
+
rules,
|
|
1620
|
+
validateDebounce,
|
|
1621
|
+
delayError,
|
|
1622
|
+
disabled
|
|
1623
|
+
});
|
|
601
1624
|
return /* @__PURE__ */ React__namespace.createElement(
|
|
602
1625
|
"input",
|
|
603
1626
|
{
|
|
604
|
-
|
|
1627
|
+
"aria-invalid": error ? true : void 0,
|
|
1628
|
+
...props,
|
|
1629
|
+
name: fieldKey,
|
|
1630
|
+
onBlur,
|
|
605
1631
|
type: "checkbox",
|
|
606
1632
|
checked: !!value,
|
|
1633
|
+
disabled: isDisabled,
|
|
607
1634
|
onChange: (e) => onChange(e.target.checked),
|
|
608
1635
|
ref
|
|
609
1636
|
}
|
|
610
1637
|
);
|
|
611
1638
|
}
|
|
612
1639
|
);
|
|
1640
|
+
function toSelectValue(multiple, value) {
|
|
1641
|
+
if (multiple) return Array.isArray(value) ? value : [];
|
|
1642
|
+
return value ?? "";
|
|
1643
|
+
}
|
|
1644
|
+
const Select = React__namespace.forwardRef(
|
|
1645
|
+
({
|
|
1646
|
+
name,
|
|
1647
|
+
multiple,
|
|
1648
|
+
children,
|
|
1649
|
+
form,
|
|
1650
|
+
initialValue,
|
|
1651
|
+
shouldUnregister,
|
|
1652
|
+
validate,
|
|
1653
|
+
rules,
|
|
1654
|
+
validateDebounce,
|
|
1655
|
+
disabled,
|
|
1656
|
+
delayError,
|
|
1657
|
+
...props
|
|
1658
|
+
}, ref) => {
|
|
1659
|
+
const {
|
|
1660
|
+
value,
|
|
1661
|
+
onChange,
|
|
1662
|
+
onBlur,
|
|
1663
|
+
error,
|
|
1664
|
+
name: fieldKey,
|
|
1665
|
+
disabled: isDisabled
|
|
1666
|
+
} = useField({
|
|
1667
|
+
name,
|
|
1668
|
+
form,
|
|
1669
|
+
initialValue,
|
|
1670
|
+
shouldUnregister,
|
|
1671
|
+
validate,
|
|
1672
|
+
rules,
|
|
1673
|
+
validateDebounce,
|
|
1674
|
+
delayError,
|
|
1675
|
+
disabled
|
|
1676
|
+
});
|
|
1677
|
+
return /* @__PURE__ */ React__namespace.createElement(
|
|
1678
|
+
"select",
|
|
1679
|
+
{
|
|
1680
|
+
"aria-invalid": error ? true : void 0,
|
|
1681
|
+
...props,
|
|
1682
|
+
name: fieldKey,
|
|
1683
|
+
onBlur,
|
|
1684
|
+
multiple,
|
|
1685
|
+
value: toSelectValue(multiple, value),
|
|
1686
|
+
disabled: isDisabled,
|
|
1687
|
+
onChange: (e) => onChange(
|
|
1688
|
+
multiple ? Array.from(e.target.selectedOptions, (option) => option.value) : e.target.value
|
|
1689
|
+
),
|
|
1690
|
+
ref
|
|
1691
|
+
},
|
|
1692
|
+
children
|
|
1693
|
+
);
|
|
1694
|
+
}
|
|
1695
|
+
);
|
|
613
1696
|
|
|
614
1697
|
exports.Checkbox = Checkbox;
|
|
615
1698
|
exports.CheckboxGroupContext = CheckboxGroupContext;
|
|
@@ -618,16 +1701,25 @@
|
|
|
618
1701
|
exports.Form = Form;
|
|
619
1702
|
exports.FormContext = FormContext;
|
|
620
1703
|
exports.FormProvider = FormProvider;
|
|
1704
|
+
exports.Select = Select;
|
|
1705
|
+
exports.VALIDATION_OUTCOME = VALIDATION_OUTCOME;
|
|
621
1706
|
exports.clearErrors = clearErrors;
|
|
622
1707
|
exports.createForm = create;
|
|
1708
|
+
exports.createFormContext = createFormContext;
|
|
623
1709
|
exports.ensureValidate = ensureValidate;
|
|
1710
|
+
exports.getDirtyFields = getDirtyFields;
|
|
624
1711
|
exports.getError = getError;
|
|
625
1712
|
exports.getErrorByPath = getErrorByPath;
|
|
626
1713
|
exports.getErrors = getErrors;
|
|
1714
|
+
exports.getFieldErrors = getFieldErrors;
|
|
1715
|
+
exports.getFieldErrorsByPath = getFieldErrorsByPath;
|
|
1716
|
+
exports.getFieldState = getFieldState;
|
|
627
1717
|
exports.getFirstError = getFirstError;
|
|
1718
|
+
exports.getTouchedFields = getTouchedFields;
|
|
628
1719
|
exports.getValue = getValue;
|
|
629
1720
|
exports.getValueByPath = getValueByPath;
|
|
630
1721
|
exports.getValues = getValues;
|
|
1722
|
+
exports.handleSubmit = handleSubmit;
|
|
631
1723
|
exports.hasErrors = hasErrors;
|
|
632
1724
|
exports.hasTouched = hasTouched;
|
|
633
1725
|
exports.hasTouchedByPath = hasTouchedByPath;
|
|
@@ -637,8 +1729,11 @@
|
|
|
637
1729
|
exports.removeField = removeField;
|
|
638
1730
|
exports.removeFieldByPath = removeFieldByPath;
|
|
639
1731
|
exports.reset = reset;
|
|
1732
|
+
exports.resetField = resetField;
|
|
1733
|
+
exports.setDisabled = setDisabled;
|
|
640
1734
|
exports.setError = setError;
|
|
641
1735
|
exports.setErrorByPath = setErrorByPath;
|
|
1736
|
+
exports.setFocus = setFocus;
|
|
642
1737
|
exports.setInitialValues = setInitialValues;
|
|
643
1738
|
exports.setIsSubmitting = setIsSubmitting;
|
|
644
1739
|
exports.setSubmitSuccessful = setSubmitSuccessful;
|
|
@@ -647,13 +1742,17 @@
|
|
|
647
1742
|
exports.setValidatingByPath = setValidatingByPath;
|
|
648
1743
|
exports.setValue = setValue;
|
|
649
1744
|
exports.setValueByPath = setValueByPath;
|
|
1745
|
+
exports.subscribe = subscribe;
|
|
650
1746
|
exports.trigger = trigger;
|
|
651
1747
|
exports.unsetValidatingByPath = unsetValidatingByPath;
|
|
652
1748
|
exports.useCheckboxGroupContext = useCheckboxGroupContext;
|
|
1749
|
+
exports.useDirtyFields = useDirtyFields;
|
|
653
1750
|
exports.useError = useError;
|
|
654
1751
|
exports.useErrorByPath = useErrorByPath;
|
|
655
1752
|
exports.useField = useField;
|
|
656
1753
|
exports.useFieldArray = useFieldArray;
|
|
1754
|
+
exports.useFieldErrors = useFieldErrors;
|
|
1755
|
+
exports.useFieldErrorsByPath = useFieldErrorsByPath;
|
|
657
1756
|
exports.useForm = useForm;
|
|
658
1757
|
exports.useFormContext = useFormContext;
|
|
659
1758
|
exports.useHasErrors = useHasErrors;
|
|
@@ -662,6 +1761,7 @@
|
|
|
662
1761
|
exports.useSubmitCount = useSubmitCount;
|
|
663
1762
|
exports.useTouched = useTouched;
|
|
664
1763
|
exports.useTouchedByPath = useTouchedByPath;
|
|
1764
|
+
exports.useTouchedFields = useTouchedFields;
|
|
665
1765
|
exports.useValue = useValue;
|
|
666
1766
|
exports.useValueByPath = useValueByPath;
|
|
667
1767
|
exports.useWatch = useWatch;
|