react-f0rm 0.1.0 → 0.2.1
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 +174 -0
- package/dist/index.cjs.js +667 -0
- package/dist/index.cjs.js.map +1 -0
- package/dist/index.esm.js +482 -340
- package/dist/index.esm.js.map +1 -1
- package/dist/index.umd.js +529 -344
- 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/yup.cjs.js +15 -0
- package/dist/resolvers/yup.cjs.js.map +1 -0
- package/dist/resolvers/yup.esm.js +13 -0
- package/dist/resolvers/yup.esm.js.map +1 -0
- package/dist/resolvers/zod.cjs.js +12 -0
- package/dist/resolvers/zod.cjs.js.map +1 -0
- package/dist/resolvers/zod.esm.js +10 -0
- package/dist/resolvers/zod.esm.js.map +1 -0
- package/package.json +82 -45
- package/index.d.ts +0 -22
package/dist/index.esm.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { createContext, useContext, useRef, useEffect, useReducer, useMemo, useCallback } from 'react';
|
|
2
3
|
|
|
3
4
|
function getSet(ee, key) {
|
|
4
5
|
var set = ee.get(key);
|
|
@@ -7,14 +8,13 @@ function getSet(ee, key) {
|
|
|
7
8
|
ee.set(key, newSet);
|
|
8
9
|
return newSet;
|
|
9
10
|
}
|
|
10
|
-
function create() {
|
|
11
|
+
function create$2() {
|
|
11
12
|
return new Map();
|
|
12
13
|
}
|
|
13
|
-
function emit(ee, key) {
|
|
14
|
+
function emit$1(ee, key) {
|
|
14
15
|
for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
|
|
15
16
|
args[_key - 2] = arguments[_key];
|
|
16
17
|
}
|
|
17
|
-
|
|
18
18
|
(ee.get(key) || []).forEach(function (h) {
|
|
19
19
|
return h.apply(void 0, args);
|
|
20
20
|
});
|
|
@@ -27,425 +27,567 @@ function on(ee, key, handler) {
|
|
|
27
27
|
};
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
function
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
} catch (e) {
|
|
34
|
-
return undefined;
|
|
35
|
-
}
|
|
30
|
+
function normalizePath(path) {
|
|
31
|
+
if (Array.isArray(path)) return path;
|
|
32
|
+
return path.split(/\.|\[/).map((prop) => prop.endsWith("]") ? Number.parseInt(prop, 10) : prop);
|
|
36
33
|
}
|
|
37
|
-
function
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
34
|
+
function get(values, path) {
|
|
35
|
+
return path.reduce((current, p) => {
|
|
36
|
+
if (current == null) return void 0;
|
|
37
|
+
return current[p];
|
|
38
|
+
}, values);
|
|
39
|
+
}
|
|
40
|
+
function set(values, path, value) {
|
|
41
|
+
if (!path.length) return value;
|
|
42
|
+
const [prop, ...props] = path;
|
|
43
|
+
if (typeof prop === "number") {
|
|
42
44
|
const arr = Array.isArray(values) ? values.slice() : [];
|
|
43
|
-
arr[
|
|
45
|
+
arr[prop] = set(arr[prop], props, value);
|
|
44
46
|
return arr;
|
|
45
47
|
}
|
|
46
|
-
|
|
47
|
-
return { ...values,
|
|
48
|
-
[paths[0]]: set(values[path], paths.slice(1), value)
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/** @typedef { import('../index').TaskCounter } TaskCounter */
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* @return {TaskCounter}
|
|
56
|
-
*/
|
|
57
|
-
|
|
58
|
-
function create$1() {
|
|
59
|
-
return {
|
|
60
|
-
emitter: create(),
|
|
61
|
-
count: 0
|
|
62
|
-
};
|
|
48
|
+
return { ...values, [prop]: set(values && values[prop], props, value) };
|
|
63
49
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
*/
|
|
67
|
-
|
|
68
|
-
function isRunning(counter) {
|
|
69
|
-
return Boolean(counter.count);
|
|
50
|
+
function isPromise(value) {
|
|
51
|
+
return value && typeof value.then === "function";
|
|
70
52
|
}
|
|
71
|
-
|
|
72
|
-
* @param {TaskCounter} counter
|
|
73
|
-
* @param {() => boolean} ifReject
|
|
74
|
-
*/
|
|
75
|
-
|
|
76
|
-
function waitUntil(counter, ifReject) {
|
|
53
|
+
function waitUntil(emitter, event, isResolve, isReject) {
|
|
77
54
|
return new Promise((resolve, reject) => {
|
|
78
|
-
|
|
79
|
-
|
|
55
|
+
if (isReject()) return void reject();
|
|
56
|
+
if (isResolve()) return void resolve();
|
|
57
|
+
const off = on(emitter, event, () => {
|
|
58
|
+
if (isReject()) {
|
|
80
59
|
off();
|
|
81
60
|
reject();
|
|
82
61
|
return;
|
|
83
62
|
}
|
|
84
|
-
|
|
85
|
-
if (counter.count) return;
|
|
63
|
+
if (isResolve()) return;
|
|
86
64
|
off();
|
|
87
65
|
resolve();
|
|
88
66
|
});
|
|
89
67
|
});
|
|
90
68
|
}
|
|
91
69
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Create form instance
|
|
98
|
-
* @param {Object} [defaultValues] default values
|
|
99
|
-
* @return {Form}
|
|
100
|
-
*/
|
|
70
|
+
function create$1(name) {
|
|
71
|
+
const value = normalizePath(name);
|
|
72
|
+
return { value, key: JSON.stringify(value) };
|
|
73
|
+
}
|
|
101
74
|
|
|
102
|
-
|
|
103
|
-
|
|
75
|
+
const emit = emit$1;
|
|
76
|
+
function create(options) {
|
|
77
|
+
const emitter = create$2();
|
|
104
78
|
return {
|
|
105
79
|
emitter,
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
80
|
+
revalidateOnChange: true,
|
|
81
|
+
...options,
|
|
82
|
+
initialValues: options?.initialValues ?? {},
|
|
83
|
+
values: /* @__PURE__ */ new Map(),
|
|
84
|
+
errors: /* @__PURE__ */ new Map(),
|
|
85
|
+
touched: /* @__PURE__ */ new Set(),
|
|
86
|
+
validators: /* @__PURE__ */ new Map(),
|
|
87
|
+
validating: /* @__PURE__ */ new Set(),
|
|
88
|
+
isSubmitting: false,
|
|
89
|
+
submitCount: 0,
|
|
90
|
+
isSubmitSuccessful: void 0
|
|
111
91
|
};
|
|
112
92
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
function getValues({
|
|
119
|
-
defaultValues,
|
|
120
|
-
values
|
|
121
|
-
}) {
|
|
122
|
-
return values.keys().reduce((k, v) => set(v, JSON.parse(k), values.get(k)), defaultValues);
|
|
93
|
+
function getValues(form) {
|
|
94
|
+
return Array.from(form.values.keys()).reduce(
|
|
95
|
+
(v, k) => set(v, JSON.parse(k), form.values.get(k)),
|
|
96
|
+
form.initialValues
|
|
97
|
+
);
|
|
123
98
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
function setValue({
|
|
146
|
-
emitter,
|
|
147
|
-
values
|
|
148
|
-
}, paths, value) {
|
|
149
|
-
const key = JSON.stringify(paths);
|
|
150
|
-
values.set(key, value);
|
|
151
|
-
emit(emitter, 'change');
|
|
152
|
-
}
|
|
153
|
-
/**
|
|
154
|
-
* Get field error
|
|
155
|
-
* @param {Form} form
|
|
156
|
-
* @param {Paths} paths
|
|
157
|
-
*/
|
|
158
|
-
|
|
159
|
-
function getError({
|
|
160
|
-
errors
|
|
161
|
-
}, paths) {
|
|
162
|
-
return errors.get(JSON.stringify(paths));
|
|
163
|
-
}
|
|
164
|
-
/**
|
|
165
|
-
* Get all errors
|
|
166
|
-
* @param {Form} form
|
|
167
|
-
*/
|
|
168
|
-
|
|
169
|
-
function getErrors({
|
|
170
|
-
errors
|
|
171
|
-
}) {
|
|
99
|
+
function getValue(form, name) {
|
|
100
|
+
return getValueByPath(form, create$1(name));
|
|
101
|
+
}
|
|
102
|
+
function getValueByPath({ initialValues, values }, path) {
|
|
103
|
+
if (values.has(path.key)) return values.get(path.key);
|
|
104
|
+
return get(initialValues, path.value);
|
|
105
|
+
}
|
|
106
|
+
function setValue(form, name, value) {
|
|
107
|
+
setValueByPath(form, create$1(name), value);
|
|
108
|
+
}
|
|
109
|
+
function setValueByPath({ emitter, values }, path, value) {
|
|
110
|
+
values.set(path.key, value);
|
|
111
|
+
emit(emitter, "change", path);
|
|
112
|
+
}
|
|
113
|
+
function getError(form, name) {
|
|
114
|
+
return getErrorByPath(form, create$1(name));
|
|
115
|
+
}
|
|
116
|
+
function getErrorByPath({ errors }, path) {
|
|
117
|
+
return errors.get(path.key);
|
|
118
|
+
}
|
|
119
|
+
function getErrors({ errors }) {
|
|
172
120
|
return Array.from(errors.values());
|
|
173
121
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
function
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
emitter,
|
|
195
|
-
|
|
196
|
-
}) {
|
|
122
|
+
function getFirstError({ errors }) {
|
|
123
|
+
return errors.values().next().value;
|
|
124
|
+
}
|
|
125
|
+
function unsetValidatingByPath({ emitter, validating }, { key }) {
|
|
126
|
+
validating.delete(key);
|
|
127
|
+
emit(emitter, "validating");
|
|
128
|
+
}
|
|
129
|
+
function setValidatingByPath({ emitter, validating }, { key }) {
|
|
130
|
+
validating.add(key);
|
|
131
|
+
emit(emitter, "validating");
|
|
132
|
+
}
|
|
133
|
+
function setError(form, name, error) {
|
|
134
|
+
setErrorByPath(form, create$1(name), error);
|
|
135
|
+
}
|
|
136
|
+
function setErrorByPath({ emitter, errors }, path, error) {
|
|
137
|
+
if (error) {
|
|
138
|
+
errors.set(path.key, error);
|
|
139
|
+
} else {
|
|
140
|
+
errors.delete(path.key);
|
|
141
|
+
}
|
|
142
|
+
emit(emitter, "errors");
|
|
143
|
+
}
|
|
144
|
+
function clearErrors({ emitter, errors }) {
|
|
197
145
|
errors.clear();
|
|
198
|
-
emit(emitter,
|
|
146
|
+
emit(emitter, "errors");
|
|
199
147
|
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
}
|
|
222
|
-
return touched.has(JSON.stringify(paths));
|
|
223
|
-
}
|
|
224
|
-
/**
|
|
225
|
-
* Is dirty
|
|
226
|
-
* @param {Form} form
|
|
227
|
-
*/
|
|
228
|
-
|
|
229
|
-
function isDirty({
|
|
230
|
-
touched
|
|
231
|
-
}) {
|
|
148
|
+
function setTouched(form, name) {
|
|
149
|
+
setTouchedByPath(form, create$1(name));
|
|
150
|
+
}
|
|
151
|
+
function setTouchedByPath({ emitter, touched }, { key }) {
|
|
152
|
+
if (touched.has(key)) return;
|
|
153
|
+
touched.add(key);
|
|
154
|
+
emit(emitter, "touched");
|
|
155
|
+
}
|
|
156
|
+
function hasTouched(form, name) {
|
|
157
|
+
return hasTouchedByPath(form, create$1(name));
|
|
158
|
+
}
|
|
159
|
+
function hasTouchedByPath({ touched }, path) {
|
|
160
|
+
return touched.has(path.key);
|
|
161
|
+
}
|
|
162
|
+
function isDirty({ initialValues, values }) {
|
|
163
|
+
for (const [key, value] of values) {
|
|
164
|
+
const path = JSON.parse(key);
|
|
165
|
+
if (get(initialValues, path) !== value) return true;
|
|
166
|
+
}
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
function isTouched({ touched }) {
|
|
232
170
|
return touched.size > 0;
|
|
233
171
|
}
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
function removeField(form, paths) {
|
|
241
|
-
const key = JSON.stringify(paths);
|
|
242
|
-
const {
|
|
243
|
-
emitter,
|
|
244
|
-
values,
|
|
245
|
-
touched,
|
|
246
|
-
errors
|
|
247
|
-
} = form;
|
|
172
|
+
function removeField(form, name) {
|
|
173
|
+
removeFieldByPath(form, create$1(name));
|
|
174
|
+
}
|
|
175
|
+
function removeFieldByPath(form, { key }) {
|
|
176
|
+
const { emitter, values, touched, errors, validating } = form;
|
|
248
177
|
values.delete(key);
|
|
249
178
|
touched.delete(key);
|
|
250
179
|
errors.delete(key);
|
|
251
|
-
|
|
252
|
-
emit(emitter,
|
|
253
|
-
emit(emitter,
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
180
|
+
validating.delete(key);
|
|
181
|
+
emit(emitter, "change");
|
|
182
|
+
emit(emitter, "touched");
|
|
183
|
+
emit(emitter, "errors");
|
|
184
|
+
emit(emitter, "validating");
|
|
185
|
+
}
|
|
186
|
+
function setInitialValues(form, initialValues) {
|
|
187
|
+
if (form.initialValues === initialValues) return;
|
|
188
|
+
form.initialValues = initialValues;
|
|
189
|
+
form.values.clear();
|
|
190
|
+
emit(form.emitter, "change");
|
|
191
|
+
}
|
|
192
|
+
function reset(form, initialValues) {
|
|
193
|
+
form.initialValues = initialValues;
|
|
263
194
|
clearErrors(form);
|
|
264
|
-
const {
|
|
265
|
-
|
|
266
|
-
touched
|
|
267
|
-
} = form;
|
|
195
|
+
const { emitter, touched, values } = form;
|
|
196
|
+
values.clear();
|
|
268
197
|
touched.clear();
|
|
269
|
-
emit(emitter,
|
|
270
|
-
emit(emitter,
|
|
271
|
-
emit(emitter,
|
|
198
|
+
emit(emitter, "change");
|
|
199
|
+
emit(emitter, "touched");
|
|
200
|
+
emit(emitter, "reset");
|
|
272
201
|
}
|
|
273
|
-
|
|
274
|
-
* @param {Form} form
|
|
275
|
-
*/
|
|
276
|
-
|
|
277
|
-
function hasErrors({
|
|
278
|
-
errors
|
|
279
|
-
}) {
|
|
202
|
+
function hasErrors({ errors }) {
|
|
280
203
|
return errors.size > 0;
|
|
281
204
|
}
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
205
|
+
function trigger(form) {
|
|
206
|
+
form.validators.forEach((validator) => validator());
|
|
207
|
+
}
|
|
208
|
+
async function ensureValidate(form) {
|
|
209
|
+
form.validators.forEach((validator) => validator());
|
|
210
|
+
await waitUntil(
|
|
211
|
+
form.emitter,
|
|
212
|
+
"validating",
|
|
213
|
+
() => !form.validating.size,
|
|
214
|
+
() => hasErrors(form)
|
|
215
|
+
).catch(() => {
|
|
216
|
+
throw new Error(getFirstError(form));
|
|
217
|
+
});
|
|
218
|
+
if (form.validate) {
|
|
219
|
+
const result = await form.validate(getValues(form));
|
|
220
|
+
const entries = result ? Object.entries(result) : [];
|
|
221
|
+
if (entries.length) {
|
|
222
|
+
entries.forEach(([field, error]) => {
|
|
223
|
+
setError(form, field, error);
|
|
224
|
+
});
|
|
225
|
+
throw new Error(getFirstError(form));
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
async function validate(form) {
|
|
230
|
+
return ensureValidate(form).catch((e) => e.message);
|
|
231
|
+
}
|
|
232
|
+
function setIsSubmitting(form, value) {
|
|
233
|
+
form.isSubmitting = value;
|
|
234
|
+
emit(form.emitter, "submitting");
|
|
235
|
+
}
|
|
236
|
+
function incrementSubmitCount(form) {
|
|
237
|
+
form.submitCount++;
|
|
238
|
+
emit(form.emitter, "submitCount");
|
|
239
|
+
}
|
|
240
|
+
function setSubmitSuccessful(form, value) {
|
|
241
|
+
form.isSubmitSuccessful = value;
|
|
242
|
+
emit(form.emitter, "submitSuccessful");
|
|
294
243
|
}
|
|
295
244
|
|
|
296
|
-
const FormContext =
|
|
245
|
+
const FormContext = createContext(null);
|
|
297
246
|
const FormProvider = FormContext.Provider;
|
|
298
247
|
function useFormContext() {
|
|
299
248
|
const form = useContext(FormContext);
|
|
300
|
-
if (!form) throw new Error(
|
|
249
|
+
if (!form) throw new Error("no form provided");
|
|
301
250
|
return form;
|
|
302
251
|
}
|
|
252
|
+
const CheckboxGroupContext = createContext(null);
|
|
253
|
+
const CheckboxGroupProvider = CheckboxGroupContext.Provider;
|
|
254
|
+
function useCheckboxGroupContext() {
|
|
255
|
+
const group = useContext(CheckboxGroupContext);
|
|
256
|
+
if (!group) throw new Error("no group provided");
|
|
257
|
+
return group;
|
|
258
|
+
}
|
|
303
259
|
|
|
304
|
-
function useForm(
|
|
305
|
-
const ref = useRef();
|
|
306
|
-
const form = ref.current = ref.current || create
|
|
260
|
+
function useForm(options) {
|
|
261
|
+
const ref = useRef(null);
|
|
262
|
+
const form = ref.current = ref.current || create(options);
|
|
263
|
+
const initialValues = options && options.initialValues;
|
|
307
264
|
useEffect(() => {
|
|
308
|
-
form
|
|
309
|
-
|
|
310
|
-
}, [defaultValues]);
|
|
265
|
+
setInitialValues(form, initialValues);
|
|
266
|
+
}, [initialValues]);
|
|
311
267
|
return form;
|
|
312
268
|
}
|
|
313
|
-
/**
|
|
314
|
-
* @param {EventEmitter} emitter
|
|
315
|
-
* @param {string} event
|
|
316
|
-
* @param {() => any} getter
|
|
317
|
-
*/
|
|
318
|
-
|
|
319
269
|
function useWatch(emitter, event, getter) {
|
|
320
|
-
const [value, syncValue] = useReducer(getter, getter);
|
|
270
|
+
const [value, syncValue] = useReducer(getter, void 0, getter);
|
|
321
271
|
useEffect(() => on(emitter, event, syncValue), [emitter, event]);
|
|
322
272
|
return value;
|
|
323
273
|
}
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
274
|
+
function useValue(form, name) {
|
|
275
|
+
return useValueByPath(form, create$1(name));
|
|
276
|
+
}
|
|
277
|
+
function useValueByPath(form, path) {
|
|
278
|
+
return useWatch(
|
|
279
|
+
form.emitter,
|
|
280
|
+
"change",
|
|
281
|
+
getValueByPath.bind(null, form, path)
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
function useTouched(form, name) {
|
|
285
|
+
return useTouchedByPath(form, create$1(name));
|
|
286
|
+
}
|
|
287
|
+
function useTouchedByPath(form, path) {
|
|
288
|
+
return useWatch(
|
|
289
|
+
form.emitter,
|
|
290
|
+
"touched",
|
|
291
|
+
hasTouchedByPath.bind(null, form, path)
|
|
292
|
+
);
|
|
332
293
|
}
|
|
333
|
-
function
|
|
334
|
-
return
|
|
294
|
+
function useError(form, name) {
|
|
295
|
+
return useErrorByPath(form, create$1(name));
|
|
335
296
|
}
|
|
336
|
-
function
|
|
337
|
-
return useWatch(
|
|
297
|
+
function useErrorByPath(form, path) {
|
|
298
|
+
return useWatch(
|
|
299
|
+
form.emitter,
|
|
300
|
+
"errors",
|
|
301
|
+
getErrorByPath.bind(null, form, path)
|
|
302
|
+
);
|
|
338
303
|
}
|
|
339
304
|
function useIsDirty(form) {
|
|
340
|
-
return useWatch(form.emitter,
|
|
305
|
+
return useWatch(form.emitter, "touched", isDirty.bind(null, form));
|
|
341
306
|
}
|
|
342
307
|
function useHasErrors(form) {
|
|
343
|
-
return useWatch(form.emitter,
|
|
308
|
+
return useWatch(form.emitter, "errors", hasErrors.bind(null, form));
|
|
309
|
+
}
|
|
310
|
+
function useIsSubmitting(form) {
|
|
311
|
+
return useWatch(form.emitter, "submitting", () => form.isSubmitting);
|
|
312
|
+
}
|
|
313
|
+
function useSubmitCount(form) {
|
|
314
|
+
return useWatch(form.emitter, "submitCount", () => form.submitCount);
|
|
344
315
|
}
|
|
345
316
|
|
|
346
|
-
function
|
|
347
|
-
name,
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
}) {
|
|
351
|
-
const form = useFormContext();
|
|
352
|
-
const lockRef = useRef();
|
|
353
|
-
const validateRef = useRef();
|
|
354
|
-
validateRef.current = validate;
|
|
355
|
-
const nameKey = JSON.stringify(name);
|
|
356
|
-
const handlers = useMemo(() => {
|
|
357
|
-
setValue(form, name, defaultValue);
|
|
358
|
-
|
|
359
|
-
const onChange = v => setValue(form, name, v);
|
|
317
|
+
function usePath(name) {
|
|
318
|
+
const path = useMemo(() => create$1(normalizePath(name)), [name]);
|
|
319
|
+
return useMemo(() => path, [path.key]);
|
|
320
|
+
}
|
|
360
321
|
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
322
|
+
function useStage(value) {
|
|
323
|
+
const ref = useRef(value);
|
|
324
|
+
ref.current = value;
|
|
325
|
+
return ref;
|
|
326
|
+
}
|
|
327
|
+
function useStageFn(fn) {
|
|
328
|
+
const ref = useStage(fn);
|
|
329
|
+
return useCallback(
|
|
330
|
+
(...params) => ref.current(...params),
|
|
331
|
+
[]
|
|
332
|
+
);
|
|
333
|
+
}
|
|
366
334
|
|
|
367
|
-
|
|
368
|
-
|
|
335
|
+
function useValidate(validate, path) {
|
|
336
|
+
const form = useFormContext();
|
|
337
|
+
const lockRef = useRef(null);
|
|
338
|
+
const validateRef = useRef(validate);
|
|
339
|
+
validateRef.current = validate;
|
|
340
|
+
useEffect(() => {
|
|
341
|
+
const validator = () => {
|
|
342
|
+
const fn = validateRef.current;
|
|
343
|
+
if (!fn) return;
|
|
344
|
+
const result = fn(getValueByPath(form, path), { form, path });
|
|
345
|
+
if (!isPromise(result)) {
|
|
346
|
+
setErrorByPath(form, path, result);
|
|
369
347
|
return;
|
|
370
348
|
}
|
|
371
|
-
|
|
372
349
|
const lock = lockRef.current = {};
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
350
|
+
setValidatingByPath(form, path);
|
|
351
|
+
result.then((error) => {
|
|
352
|
+
if (lock === lockRef.current) {
|
|
353
|
+
setErrorByPath(form, path, error);
|
|
354
|
+
}
|
|
355
|
+
}).finally(() => {
|
|
356
|
+
if (lock === lockRef.current) {
|
|
357
|
+
unsetValidatingByPath(form, path);
|
|
358
|
+
lockRef.current = null;
|
|
359
|
+
}
|
|
360
|
+
});
|
|
376
361
|
};
|
|
377
|
-
|
|
378
|
-
return {
|
|
379
|
-
|
|
380
|
-
onBlur
|
|
362
|
+
form.validators.set(path.key, validator);
|
|
363
|
+
return () => {
|
|
364
|
+
form.validators.delete(path.key);
|
|
381
365
|
};
|
|
382
|
-
}, [
|
|
383
|
-
|
|
384
|
-
removeField(form, name);
|
|
385
|
-
}, [nameKey, form]);
|
|
386
|
-
const value = useValue(form, name);
|
|
387
|
-
return {
|
|
388
|
-
value,
|
|
389
|
-
...handlers
|
|
390
|
-
};
|
|
366
|
+
}, [form, path.key]);
|
|
367
|
+
return useStageFn(() => form.validators.get(path.key)?.());
|
|
391
368
|
}
|
|
392
369
|
|
|
393
|
-
function
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
370
|
+
function useField({
|
|
371
|
+
form: f1,
|
|
372
|
+
name,
|
|
373
|
+
initialValue,
|
|
374
|
+
shouldUnregister,
|
|
375
|
+
validate,
|
|
376
|
+
...rest
|
|
377
|
+
}) {
|
|
378
|
+
const f2 = useFormContext();
|
|
379
|
+
const form = f1 || f2;
|
|
380
|
+
const path = usePath(name);
|
|
381
|
+
const validator = useValidate(validate, path);
|
|
382
|
+
useMemo(() => {
|
|
383
|
+
if (initialValue !== void 0) setValueByPath(form, path, initialValue);
|
|
384
|
+
}, [form, path]);
|
|
385
|
+
const error = useErrorByPath(form, path);
|
|
386
|
+
const value = useValueByPath(form, path);
|
|
387
|
+
const onChange = useStageFn((v) => {
|
|
388
|
+
setValueByPath(form, path, v);
|
|
389
|
+
if (form.validateOnChange || form.revalidateOnChange && error && error !== void 0)
|
|
390
|
+
validator();
|
|
391
|
+
});
|
|
392
|
+
const onBlur = useStageFn(() => {
|
|
393
|
+
setTouchedByPath(form, path);
|
|
394
|
+
if (form.validateOnBlur || form.revalidateOnBlur && error !== void 0)
|
|
395
|
+
validator();
|
|
396
|
+
});
|
|
397
|
+
useEffect(
|
|
398
|
+
() => () => {
|
|
399
|
+
if (shouldUnregister !== false) {
|
|
400
|
+
removeFieldByPath(form, path);
|
|
402
401
|
}
|
|
402
|
+
},
|
|
403
|
+
[path, form, shouldUnregister]
|
|
404
|
+
);
|
|
405
|
+
return { ...rest, value, error, onChange, onBlur, name: path.key };
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
let idCounter = 0;
|
|
409
|
+
function generateId() {
|
|
410
|
+
return `_${++idCounter}`;
|
|
411
|
+
}
|
|
412
|
+
function useFieldArray(options) {
|
|
413
|
+
const f2 = useFormContext();
|
|
414
|
+
const form = options.form || f2;
|
|
415
|
+
const path = usePath(options.name);
|
|
416
|
+
const idsRef = useRef([]);
|
|
417
|
+
const getArray = useCallback(
|
|
418
|
+
() => getValueByPath(form, path) || [],
|
|
419
|
+
[form, path]
|
|
420
|
+
);
|
|
421
|
+
const setArray = useCallback(
|
|
422
|
+
(arr) => {
|
|
423
|
+
setValueByPath(form, path, arr);
|
|
424
|
+
},
|
|
425
|
+
[form, path]
|
|
426
|
+
);
|
|
427
|
+
const computeFields = useCallback(() => {
|
|
428
|
+
const arr = getArray();
|
|
429
|
+
while (idsRef.current.length < arr.length) {
|
|
430
|
+
idsRef.current.push(generateId());
|
|
403
431
|
}
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
432
|
+
while (idsRef.current.length > arr.length) {
|
|
433
|
+
idsRef.current.pop();
|
|
434
|
+
}
|
|
435
|
+
return idsRef.current.map((id, index) => ({ id, index }));
|
|
436
|
+
}, [getArray]);
|
|
437
|
+
const [fields, syncFields] = useReducer(
|
|
438
|
+
computeFields,
|
|
439
|
+
void 0,
|
|
440
|
+
computeFields
|
|
441
|
+
);
|
|
442
|
+
useEffect(() => on(form.emitter, "change", syncFields), [form.emitter]);
|
|
443
|
+
const append = useStageFn((value) => {
|
|
444
|
+
const arr = getArray();
|
|
445
|
+
idsRef.current.push(generateId());
|
|
446
|
+
setArray([...arr, value]);
|
|
447
|
+
});
|
|
448
|
+
const prepend = useStageFn((value) => {
|
|
449
|
+
const arr = getArray();
|
|
450
|
+
idsRef.current.unshift(generateId());
|
|
451
|
+
setArray([value, ...arr]);
|
|
452
|
+
});
|
|
453
|
+
const insert = useStageFn((index, value) => {
|
|
454
|
+
const arr = getArray();
|
|
455
|
+
idsRef.current.splice(index, 0, generateId());
|
|
456
|
+
const newArr = [...arr.slice(0, index), value, ...arr.slice(index)];
|
|
457
|
+
setArray(newArr);
|
|
458
|
+
});
|
|
459
|
+
const remove = useStageFn((index) => {
|
|
460
|
+
const arr = getArray();
|
|
461
|
+
idsRef.current.splice(index, 1);
|
|
462
|
+
const newArr = arr.filter((_, i) => i !== index);
|
|
463
|
+
setArray(newArr);
|
|
464
|
+
});
|
|
465
|
+
const swap = useStageFn((from, to) => {
|
|
466
|
+
const arr = getArray();
|
|
467
|
+
[idsRef.current[from], idsRef.current[to]] = [
|
|
468
|
+
idsRef.current[to],
|
|
469
|
+
idsRef.current[from]
|
|
470
|
+
];
|
|
471
|
+
const newArr = [...arr];
|
|
472
|
+
[newArr[from], newArr[to]] = [newArr[to], newArr[from]];
|
|
473
|
+
setArray(newArr);
|
|
474
|
+
});
|
|
475
|
+
const move = useStageFn((from, to) => {
|
|
476
|
+
const arr = getArray();
|
|
477
|
+
const [id] = idsRef.current.splice(from, 1);
|
|
478
|
+
idsRef.current.splice(to, 0, id);
|
|
479
|
+
const newArr = [...arr];
|
|
480
|
+
const [item] = newArr.splice(from, 1);
|
|
481
|
+
newArr.splice(to, 0, item);
|
|
482
|
+
setArray(newArr);
|
|
483
|
+
});
|
|
484
|
+
return { fields, append, prepend, insert, remove, swap, move };
|
|
409
485
|
}
|
|
410
486
|
|
|
411
|
-
/** @typedef { import('../index').FormProps } FormProps */
|
|
412
|
-
|
|
413
|
-
/**
|
|
414
|
-
* Form
|
|
415
|
-
* @param {FormProps} props
|
|
416
|
-
*/
|
|
417
|
-
|
|
418
487
|
function Form({
|
|
419
|
-
form:
|
|
488
|
+
form: f1,
|
|
489
|
+
initialValues,
|
|
420
490
|
onSubmit,
|
|
421
491
|
onValidSubmit,
|
|
422
492
|
onInvalidSubmit,
|
|
423
493
|
...props
|
|
424
494
|
}) {
|
|
425
|
-
const
|
|
426
|
-
|
|
427
|
-
function handleSubmit(e) {
|
|
428
|
-
|
|
429
|
-
|
|
495
|
+
const f2 = useForm({ initialValues });
|
|
496
|
+
const form = f1 || f2;
|
|
497
|
+
async function handleSubmit(e) {
|
|
498
|
+
e.preventDefault();
|
|
499
|
+
setIsSubmitting(form, true);
|
|
500
|
+
incrementSubmitCount(form);
|
|
501
|
+
const error = await validate(form);
|
|
430
502
|
const values = getValues(form);
|
|
431
|
-
if (
|
|
432
|
-
|
|
503
|
+
if (error) {
|
|
504
|
+
setIsSubmitting(form, false);
|
|
505
|
+
setSubmitSuccessful(form, false);
|
|
506
|
+
if (onInvalidSubmit) onInvalidSubmit(getErrors(form), values);
|
|
507
|
+
return;
|
|
508
|
+
}
|
|
509
|
+
try {
|
|
510
|
+
if (onSubmit) await onSubmit(values, e);
|
|
511
|
+
if (onValidSubmit) onValidSubmit(values, e);
|
|
512
|
+
setSubmitSuccessful(form, true);
|
|
513
|
+
} catch {
|
|
514
|
+
setSubmitSuccessful(form, false);
|
|
515
|
+
} finally {
|
|
516
|
+
setIsSubmitting(form, false);
|
|
517
|
+
}
|
|
433
518
|
}
|
|
434
|
-
|
|
435
|
-
return /*#__PURE__*/createElement(FormProvider, {
|
|
436
|
-
value: form
|
|
437
|
-
}, /*#__PURE__*/createElement("form", _extends({}, props, {
|
|
438
|
-
onSubmit: handleSubmit
|
|
439
|
-
})));
|
|
519
|
+
return /* @__PURE__ */ React.createElement(FormProvider, { value: form }, /* @__PURE__ */ React.createElement("form", { ...props, noValidate: true, onSubmit: handleSubmit }));
|
|
440
520
|
}
|
|
441
521
|
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
522
|
+
const buildInError = /* @__PURE__ */ Symbol("buildInError");
|
|
523
|
+
function setRef(ref, value) {
|
|
524
|
+
if (typeof ref === "function") {
|
|
525
|
+
ref(value);
|
|
526
|
+
} else if (ref) {
|
|
527
|
+
ref.current = value;
|
|
528
|
+
}
|
|
448
529
|
}
|
|
530
|
+
const Field = React.forwardRef(
|
|
531
|
+
({ validate, eventToValue, initialValue, name, asProps, ...props }, ref) => {
|
|
532
|
+
const innerRef = React.useRef(null);
|
|
533
|
+
const mergedRef = React.useCallback(
|
|
534
|
+
(node) => {
|
|
535
|
+
innerRef.current = node;
|
|
536
|
+
setRef(ref, node);
|
|
537
|
+
},
|
|
538
|
+
[ref]
|
|
539
|
+
);
|
|
540
|
+
const { as, value, valueToProps, onChange, error, ...rest } = useField({
|
|
541
|
+
...props,
|
|
542
|
+
name,
|
|
543
|
+
initialValue,
|
|
544
|
+
validate: (...params) => {
|
|
545
|
+
if (innerRef.current?.checkValidity() === false)
|
|
546
|
+
return buildInError;
|
|
547
|
+
if (validate) return validate(...params);
|
|
548
|
+
}
|
|
549
|
+
});
|
|
550
|
+
const Component = as || "input";
|
|
551
|
+
React.useEffect(() => {
|
|
552
|
+
if (!innerRef.current) return;
|
|
553
|
+
if (error === buildInError) {
|
|
554
|
+
innerRef.current.setCustomValidity("");
|
|
555
|
+
innerRef.current.reportValidity();
|
|
556
|
+
return;
|
|
557
|
+
}
|
|
558
|
+
if (typeof error === "string") {
|
|
559
|
+
innerRef.current.setCustomValidity(error);
|
|
560
|
+
innerRef.current.reportValidity();
|
|
561
|
+
}
|
|
562
|
+
}, [error]);
|
|
563
|
+
const toValue = eventToValue ?? ((e) => e.target.value);
|
|
564
|
+
return /* @__PURE__ */ React.createElement(
|
|
565
|
+
Component,
|
|
566
|
+
{
|
|
567
|
+
...rest,
|
|
568
|
+
...asProps,
|
|
569
|
+
...valueToProps ? valueToProps(value) : { value },
|
|
570
|
+
onChange: (e) => onChange(toValue(e)),
|
|
571
|
+
ref: mergedRef
|
|
572
|
+
}
|
|
573
|
+
);
|
|
574
|
+
}
|
|
575
|
+
);
|
|
576
|
+
const Checkbox = React.forwardRef(
|
|
577
|
+
({ name, ...props }, ref) => {
|
|
578
|
+
const { value, onChange, error, ...rest } = useField({ ...props, name });
|
|
579
|
+
return /* @__PURE__ */ React.createElement(
|
|
580
|
+
"input",
|
|
581
|
+
{
|
|
582
|
+
...rest,
|
|
583
|
+
type: "checkbox",
|
|
584
|
+
checked: !!value,
|
|
585
|
+
onChange: (e) => onChange(e.target.checked),
|
|
586
|
+
ref
|
|
587
|
+
}
|
|
588
|
+
);
|
|
589
|
+
}
|
|
590
|
+
);
|
|
449
591
|
|
|
450
|
-
export { Field, Form, FormContext, FormProvider, clearErrors, create
|
|
592
|
+
export { Checkbox, CheckboxGroupContext, CheckboxGroupProvider, Field, Form, FormContext, FormProvider, clearErrors, create as createForm, ensureValidate, getError, getErrorByPath, getErrors, getFirstError, getValue, getValueByPath, getValues, hasErrors, hasTouched, hasTouchedByPath, incrementSubmitCount, isDirty, isTouched, removeField, removeFieldByPath, reset, setError, setErrorByPath, setInitialValues, setIsSubmitting, setSubmitSuccessful, setTouched, setTouchedByPath, setValidatingByPath, setValue, setValueByPath, trigger, unsetValidatingByPath, useCheckboxGroupContext, useError, useErrorByPath, useField, useFieldArray, useForm, useFormContext, useHasErrors, useIsDirty, useIsSubmitting, useSubmitCount, useTouched, useTouchedByPath, useValue, useValueByPath, useWatch, validate };
|
|
451
593
|
//# sourceMappingURL=index.esm.js.map
|