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