react-f0rm 0.2.2 → 0.4.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 +573 -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 +1265 -157
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +419 -59
- package/dist/index.mjs +1684 -0
- package/dist/index.mjs.map +1 -0
- package/dist/index.umd.js +1265 -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,88 @@ 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 {
|
|
1445
|
+
context: Context,
|
|
1446
|
+
FormProvider: FormProvider2,
|
|
1447
|
+
useFormContext: useFormContext2,
|
|
1448
|
+
useField,
|
|
1449
|
+
useFieldArray
|
|
1450
|
+
};
|
|
1451
|
+
}
|
|
1452
|
+
const CheckboxGroupContext = React.createContext(null);
|
|
1453
|
+
const CheckboxGroupProvider = CheckboxGroupContext.Provider;
|
|
1454
|
+
function useCheckboxGroupContext() {
|
|
1455
|
+
const group = React.useContext(CheckboxGroupContext);
|
|
1456
|
+
if (!group) throw new Error("no group provided");
|
|
1457
|
+
return group;
|
|
505
1458
|
}
|
|
506
1459
|
|
|
507
1460
|
function Form({
|
|
508
1461
|
form: f1,
|
|
1462
|
+
context,
|
|
509
1463
|
initialValues,
|
|
1464
|
+
values,
|
|
510
1465
|
onSubmit,
|
|
511
1466
|
onValidSubmit,
|
|
512
1467
|
onInvalidSubmit,
|
|
1468
|
+
shouldFocusError,
|
|
513
1469
|
...props
|
|
514
1470
|
}) {
|
|
515
|
-
const f2 = useForm({ initialValues });
|
|
1471
|
+
const f2 = useForm({ initialValues, values });
|
|
516
1472
|
const form = f1 || f2;
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
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 }));
|
|
1473
|
+
const submit = handleSubmit(form, {
|
|
1474
|
+
onSubmit,
|
|
1475
|
+
onValidSubmit,
|
|
1476
|
+
onInvalidSubmit,
|
|
1477
|
+
shouldFocusError
|
|
1478
|
+
});
|
|
1479
|
+
const { Provider } = context ?? FormContext;
|
|
1480
|
+
return /* @__PURE__ */ React__namespace.createElement(Provider, { value: form }, /* @__PURE__ */ React__namespace.createElement("form", { ...props, noValidate: true, onSubmit: submit }));
|
|
540
1481
|
}
|
|
541
1482
|
|
|
542
|
-
const buildInError = /* @__PURE__ */ Symbol("buildInError");
|
|
543
1483
|
function setRef(ref, value) {
|
|
544
1484
|
if (typeof ref === "function") {
|
|
545
1485
|
ref(value);
|
|
@@ -547,9 +1487,30 @@ function setRef(ref, value) {
|
|
|
547
1487
|
ref.current = value;
|
|
548
1488
|
}
|
|
549
1489
|
}
|
|
1490
|
+
function errorIdFromKey(key) {
|
|
1491
|
+
const id = key.replace(/["'[\],\s]+/g, "-").replace(/^-+|-+$/g, "");
|
|
1492
|
+
return id || "field";
|
|
1493
|
+
}
|
|
550
1494
|
const Field = React__namespace.forwardRef(
|
|
551
|
-
({
|
|
1495
|
+
({
|
|
1496
|
+
validate,
|
|
1497
|
+
eventToValue,
|
|
1498
|
+
initialValue,
|
|
1499
|
+
name,
|
|
1500
|
+
asProps,
|
|
1501
|
+
renderError,
|
|
1502
|
+
as,
|
|
1503
|
+
valueToProps,
|
|
1504
|
+
form: formProp,
|
|
1505
|
+
shouldUnregister,
|
|
1506
|
+
rules,
|
|
1507
|
+
validateDebounce,
|
|
1508
|
+
disabled,
|
|
1509
|
+
delayError,
|
|
1510
|
+
...props
|
|
1511
|
+
}, ref) => {
|
|
552
1512
|
const innerRef = React__namespace.useRef(null);
|
|
1513
|
+
const [nativeInvalidCount, setNativeInvalidCount] = React__namespace.useState(0);
|
|
553
1514
|
const mergedRef = React__namespace.useCallback(
|
|
554
1515
|
(node) => {
|
|
555
1516
|
innerRef.current = node;
|
|
@@ -557,57 +1518,187 @@ const Field = React__namespace.forwardRef(
|
|
|
557
1518
|
},
|
|
558
1519
|
[ref]
|
|
559
1520
|
);
|
|
560
|
-
const {
|
|
561
|
-
|
|
1521
|
+
const {
|
|
1522
|
+
value,
|
|
1523
|
+
onChange,
|
|
1524
|
+
onBlur,
|
|
1525
|
+
error,
|
|
1526
|
+
form,
|
|
1527
|
+
name: fieldKey,
|
|
1528
|
+
disabled: isDisabled
|
|
1529
|
+
} = useField({
|
|
562
1530
|
name,
|
|
1531
|
+
form: formProp,
|
|
563
1532
|
initialValue,
|
|
1533
|
+
shouldUnregister,
|
|
1534
|
+
rules,
|
|
1535
|
+
validateDebounce,
|
|
1536
|
+
delayError,
|
|
1537
|
+
disabled,
|
|
564
1538
|
validate: (...params) => {
|
|
565
|
-
|
|
566
|
-
|
|
1539
|
+
const el = innerRef.current;
|
|
1540
|
+
if (el && typeof el.checkValidity === "function") {
|
|
1541
|
+
el.setCustomValidity("");
|
|
1542
|
+
if (el.checkValidity() === false) {
|
|
1543
|
+
setNativeInvalidCount((count) => count + 1);
|
|
1544
|
+
return void 0;
|
|
1545
|
+
}
|
|
1546
|
+
}
|
|
567
1547
|
if (validate) return validate(...params);
|
|
568
1548
|
}
|
|
569
1549
|
});
|
|
570
1550
|
const Component = as || "input";
|
|
571
1551
|
React__namespace.useEffect(() => {
|
|
572
|
-
|
|
573
|
-
if (
|
|
574
|
-
innerRef.current.setCustomValidity("");
|
|
575
|
-
innerRef.current.reportValidity();
|
|
576
|
-
return;
|
|
577
|
-
}
|
|
1552
|
+
const el = innerRef.current;
|
|
1553
|
+
if (!el || typeof el.setCustomValidity !== "function") return;
|
|
578
1554
|
if (typeof error === "string") {
|
|
579
|
-
|
|
580
|
-
|
|
1555
|
+
el.setCustomValidity(error);
|
|
1556
|
+
el.reportValidity();
|
|
1557
|
+
} else {
|
|
1558
|
+
el.setCustomValidity("");
|
|
581
1559
|
}
|
|
582
1560
|
}, [error]);
|
|
1561
|
+
React__namespace.useEffect(() => {
|
|
1562
|
+
if (nativeInvalidCount > 0) innerRef.current?.reportValidity();
|
|
1563
|
+
}, [nativeInvalidCount]);
|
|
1564
|
+
React__namespace.useEffect(
|
|
1565
|
+
() => on(
|
|
1566
|
+
form.emitter,
|
|
1567
|
+
"focusError",
|
|
1568
|
+
(key, options) => {
|
|
1569
|
+
if (key !== fieldKey) return;
|
|
1570
|
+
const el = innerRef.current;
|
|
1571
|
+
if (!el || typeof el.focus !== "function") return;
|
|
1572
|
+
el.focus();
|
|
1573
|
+
if (options?.shouldSelect && typeof el.select === "function") {
|
|
1574
|
+
el.select();
|
|
1575
|
+
}
|
|
1576
|
+
}
|
|
1577
|
+
),
|
|
1578
|
+
[form, fieldKey]
|
|
1579
|
+
);
|
|
583
1580
|
const toValue = eventToValue ?? ((e) => e.target.value);
|
|
584
|
-
|
|
1581
|
+
const errorId = errorIdFromKey(fieldKey);
|
|
1582
|
+
return /* @__PURE__ */ React__namespace.createElement(React__namespace.Fragment, null, /* @__PURE__ */ React__namespace.createElement(
|
|
585
1583
|
Component,
|
|
586
1584
|
{
|
|
587
|
-
|
|
1585
|
+
"aria-invalid": error ? true : void 0,
|
|
1586
|
+
"aria-describedby": error && renderError ? errorId : void 0,
|
|
1587
|
+
...props,
|
|
1588
|
+
name: fieldKey,
|
|
1589
|
+
onBlur,
|
|
588
1590
|
...asProps,
|
|
589
1591
|
...valueToProps ? valueToProps(value) : { value },
|
|
1592
|
+
disabled: isDisabled,
|
|
590
1593
|
onChange: (e) => onChange(toValue(e)),
|
|
591
1594
|
ref: mergedRef
|
|
592
1595
|
}
|
|
593
|
-
);
|
|
1596
|
+
), error && renderError ? /* @__PURE__ */ React__namespace.createElement("span", { id: errorId, role: "alert" }, renderError(error, errorId)) : null);
|
|
594
1597
|
}
|
|
595
1598
|
);
|
|
596
1599
|
const Checkbox = React__namespace.forwardRef(
|
|
597
|
-
({
|
|
598
|
-
|
|
1600
|
+
({
|
|
1601
|
+
name,
|
|
1602
|
+
form,
|
|
1603
|
+
initialValue,
|
|
1604
|
+
shouldUnregister,
|
|
1605
|
+
validate,
|
|
1606
|
+
rules,
|
|
1607
|
+
validateDebounce,
|
|
1608
|
+
disabled,
|
|
1609
|
+
delayError,
|
|
1610
|
+
...props
|
|
1611
|
+
}, ref) => {
|
|
1612
|
+
const {
|
|
1613
|
+
value,
|
|
1614
|
+
onChange,
|
|
1615
|
+
onBlur,
|
|
1616
|
+
error,
|
|
1617
|
+
name: fieldKey,
|
|
1618
|
+
disabled: isDisabled
|
|
1619
|
+
} = useField({
|
|
1620
|
+
name,
|
|
1621
|
+
form,
|
|
1622
|
+
initialValue,
|
|
1623
|
+
shouldUnregister,
|
|
1624
|
+
validate,
|
|
1625
|
+
rules,
|
|
1626
|
+
validateDebounce,
|
|
1627
|
+
delayError,
|
|
1628
|
+
disabled
|
|
1629
|
+
});
|
|
599
1630
|
return /* @__PURE__ */ React__namespace.createElement(
|
|
600
1631
|
"input",
|
|
601
1632
|
{
|
|
602
|
-
|
|
1633
|
+
"aria-invalid": error ? true : void 0,
|
|
1634
|
+
...props,
|
|
1635
|
+
name: fieldKey,
|
|
1636
|
+
onBlur,
|
|
603
1637
|
type: "checkbox",
|
|
604
1638
|
checked: !!value,
|
|
1639
|
+
disabled: isDisabled,
|
|
605
1640
|
onChange: (e) => onChange(e.target.checked),
|
|
606
1641
|
ref
|
|
607
1642
|
}
|
|
608
1643
|
);
|
|
609
1644
|
}
|
|
610
1645
|
);
|
|
1646
|
+
function toSelectValue(multiple, value) {
|
|
1647
|
+
if (multiple) return Array.isArray(value) ? value : [];
|
|
1648
|
+
return value ?? "";
|
|
1649
|
+
}
|
|
1650
|
+
const Select = React__namespace.forwardRef(
|
|
1651
|
+
({
|
|
1652
|
+
name,
|
|
1653
|
+
multiple,
|
|
1654
|
+
children,
|
|
1655
|
+
form,
|
|
1656
|
+
initialValue,
|
|
1657
|
+
shouldUnregister,
|
|
1658
|
+
validate,
|
|
1659
|
+
rules,
|
|
1660
|
+
validateDebounce,
|
|
1661
|
+
disabled,
|
|
1662
|
+
delayError,
|
|
1663
|
+
...props
|
|
1664
|
+
}, ref) => {
|
|
1665
|
+
const {
|
|
1666
|
+
value,
|
|
1667
|
+
onChange,
|
|
1668
|
+
onBlur,
|
|
1669
|
+
error,
|
|
1670
|
+
name: fieldKey,
|
|
1671
|
+
disabled: isDisabled
|
|
1672
|
+
} = useField({
|
|
1673
|
+
name,
|
|
1674
|
+
form,
|
|
1675
|
+
initialValue,
|
|
1676
|
+
shouldUnregister,
|
|
1677
|
+
validate,
|
|
1678
|
+
rules,
|
|
1679
|
+
validateDebounce,
|
|
1680
|
+
delayError,
|
|
1681
|
+
disabled
|
|
1682
|
+
});
|
|
1683
|
+
return /* @__PURE__ */ React__namespace.createElement(
|
|
1684
|
+
"select",
|
|
1685
|
+
{
|
|
1686
|
+
"aria-invalid": error ? true : void 0,
|
|
1687
|
+
...props,
|
|
1688
|
+
name: fieldKey,
|
|
1689
|
+
onBlur,
|
|
1690
|
+
multiple,
|
|
1691
|
+
value: toSelectValue(multiple, value),
|
|
1692
|
+
disabled: isDisabled,
|
|
1693
|
+
onChange: (e) => onChange(
|
|
1694
|
+
multiple ? Array.from(e.target.selectedOptions, (option) => option.value) : e.target.value
|
|
1695
|
+
),
|
|
1696
|
+
ref
|
|
1697
|
+
},
|
|
1698
|
+
children
|
|
1699
|
+
);
|
|
1700
|
+
}
|
|
1701
|
+
);
|
|
611
1702
|
|
|
612
1703
|
exports.Checkbox = Checkbox;
|
|
613
1704
|
exports.CheckboxGroupContext = CheckboxGroupContext;
|
|
@@ -616,16 +1707,25 @@ exports.Field = Field;
|
|
|
616
1707
|
exports.Form = Form;
|
|
617
1708
|
exports.FormContext = FormContext;
|
|
618
1709
|
exports.FormProvider = FormProvider;
|
|
1710
|
+
exports.Select = Select;
|
|
1711
|
+
exports.VALIDATION_OUTCOME = VALIDATION_OUTCOME;
|
|
619
1712
|
exports.clearErrors = clearErrors;
|
|
620
1713
|
exports.createForm = create;
|
|
1714
|
+
exports.createFormContext = createFormContext;
|
|
621
1715
|
exports.ensureValidate = ensureValidate;
|
|
1716
|
+
exports.getDirtyFields = getDirtyFields;
|
|
622
1717
|
exports.getError = getError;
|
|
623
1718
|
exports.getErrorByPath = getErrorByPath;
|
|
624
1719
|
exports.getErrors = getErrors;
|
|
1720
|
+
exports.getFieldErrors = getFieldErrors;
|
|
1721
|
+
exports.getFieldErrorsByPath = getFieldErrorsByPath;
|
|
1722
|
+
exports.getFieldState = getFieldState;
|
|
625
1723
|
exports.getFirstError = getFirstError;
|
|
1724
|
+
exports.getTouchedFields = getTouchedFields;
|
|
626
1725
|
exports.getValue = getValue;
|
|
627
1726
|
exports.getValueByPath = getValueByPath;
|
|
628
1727
|
exports.getValues = getValues;
|
|
1728
|
+
exports.handleSubmit = handleSubmit;
|
|
629
1729
|
exports.hasErrors = hasErrors;
|
|
630
1730
|
exports.hasTouched = hasTouched;
|
|
631
1731
|
exports.hasTouchedByPath = hasTouchedByPath;
|
|
@@ -635,8 +1735,11 @@ exports.isTouched = isTouched;
|
|
|
635
1735
|
exports.removeField = removeField;
|
|
636
1736
|
exports.removeFieldByPath = removeFieldByPath;
|
|
637
1737
|
exports.reset = reset;
|
|
1738
|
+
exports.resetField = resetField;
|
|
1739
|
+
exports.setDisabled = setDisabled;
|
|
638
1740
|
exports.setError = setError;
|
|
639
1741
|
exports.setErrorByPath = setErrorByPath;
|
|
1742
|
+
exports.setFocus = setFocus;
|
|
640
1743
|
exports.setInitialValues = setInitialValues;
|
|
641
1744
|
exports.setIsSubmitting = setIsSubmitting;
|
|
642
1745
|
exports.setSubmitSuccessful = setSubmitSuccessful;
|
|
@@ -645,13 +1748,17 @@ exports.setTouchedByPath = setTouchedByPath;
|
|
|
645
1748
|
exports.setValidatingByPath = setValidatingByPath;
|
|
646
1749
|
exports.setValue = setValue;
|
|
647
1750
|
exports.setValueByPath = setValueByPath;
|
|
1751
|
+
exports.subscribe = subscribe;
|
|
648
1752
|
exports.trigger = trigger;
|
|
649
1753
|
exports.unsetValidatingByPath = unsetValidatingByPath;
|
|
650
1754
|
exports.useCheckboxGroupContext = useCheckboxGroupContext;
|
|
1755
|
+
exports.useDirtyFields = useDirtyFields;
|
|
651
1756
|
exports.useError = useError;
|
|
652
1757
|
exports.useErrorByPath = useErrorByPath;
|
|
653
1758
|
exports.useField = useField;
|
|
654
1759
|
exports.useFieldArray = useFieldArray;
|
|
1760
|
+
exports.useFieldErrors = useFieldErrors;
|
|
1761
|
+
exports.useFieldErrorsByPath = useFieldErrorsByPath;
|
|
655
1762
|
exports.useForm = useForm;
|
|
656
1763
|
exports.useFormContext = useFormContext;
|
|
657
1764
|
exports.useHasErrors = useHasErrors;
|
|
@@ -660,6 +1767,7 @@ exports.useIsSubmitting = useIsSubmitting;
|
|
|
660
1767
|
exports.useSubmitCount = useSubmitCount;
|
|
661
1768
|
exports.useTouched = useTouched;
|
|
662
1769
|
exports.useTouchedByPath = useTouchedByPath;
|
|
1770
|
+
exports.useTouchedFields = useTouchedFields;
|
|
663
1771
|
exports.useValue = useValue;
|
|
664
1772
|
exports.useValueByPath = useValueByPath;
|
|
665
1773
|
exports.useWatch = useWatch;
|