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