@conform-to/react 0.3.1 → 0.4.0-pre.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/helpers.js +4 -5
- package/hooks.d.ts +30 -11
- package/hooks.js +320 -164
- package/index.d.ts +1 -1
- package/index.js +12 -4
- package/module/helpers.js +4 -5
- package/module/hooks.js +321 -165
- package/module/index.js +1 -1
- package/package.json +2 -2
package/module/hooks.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { objectSpread2 as _objectSpread2 } from './_virtual/_rollupPluginBabelHelpers.js';
|
|
2
|
-
import { isFieldElement,
|
|
2
|
+
import { getSubmissionType, reportValidity, focusFirstInvalidField, requestSubmit, isFieldElement, getFormData, parse, getPaths, getName, requestValidate, getFormElement, parseListCommand, updateList } from '@conform-to/dom';
|
|
3
3
|
import { useRef, useState, useEffect } from 'react';
|
|
4
4
|
import { input } from './helpers.js';
|
|
5
5
|
|
|
@@ -7,64 +7,107 @@ import { input } from './helpers.js';
|
|
|
7
7
|
* Returns properties required to hook into form events.
|
|
8
8
|
* Applied custom validation and define when error should be reported.
|
|
9
9
|
*
|
|
10
|
-
* @see https://github.com/edmundhung/conform/tree/v0.
|
|
10
|
+
* @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.0/packages/conform-react/README.md#useform
|
|
11
11
|
*/
|
|
12
12
|
function useForm() {
|
|
13
13
|
var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
14
|
-
var
|
|
15
|
-
validate
|
|
16
|
-
} = config;
|
|
14
|
+
var configRef = useRef(config);
|
|
17
15
|
var ref = useRef(null);
|
|
16
|
+
var [error, setError] = useState(() => {
|
|
17
|
+
var _config$state$error$f, _config$state, _config$state$error;
|
|
18
|
+
|
|
19
|
+
var [, message] = (_config$state$error$f = (_config$state = config.state) === null || _config$state === void 0 ? void 0 : (_config$state$error = _config$state.error) === null || _config$state$error === void 0 ? void 0 : _config$state$error.find(_ref => {
|
|
20
|
+
var [key] = _ref;
|
|
21
|
+
return key === '';
|
|
22
|
+
})) !== null && _config$state$error$f !== void 0 ? _config$state$error$f : [];
|
|
23
|
+
return message !== null && message !== void 0 ? message : '';
|
|
24
|
+
});
|
|
25
|
+
var [fieldsetConfig, setFieldsetConfig] = useState(() => {
|
|
26
|
+
var _config$state$error2, _config$state2, _config$state3, _config$state$value, _config$state4;
|
|
27
|
+
|
|
28
|
+
var error = (_config$state$error2 = (_config$state2 = config.state) === null || _config$state2 === void 0 ? void 0 : _config$state2.error) !== null && _config$state$error2 !== void 0 ? _config$state$error2 : [];
|
|
29
|
+
var scope = (_config$state3 = config.state) === null || _config$state3 === void 0 ? void 0 : _config$state3.scope;
|
|
30
|
+
return {
|
|
31
|
+
defaultValue: (_config$state$value = (_config$state4 = config.state) === null || _config$state4 === void 0 ? void 0 : _config$state4.value) !== null && _config$state$value !== void 0 ? _config$state$value : config.defaultValue,
|
|
32
|
+
initialError: error.filter(_ref2 => {
|
|
33
|
+
var [name] = _ref2;
|
|
34
|
+
return name !== '' && getSubmissionType(name) === null && (!scope || scope.includes(name));
|
|
35
|
+
})
|
|
36
|
+
};
|
|
37
|
+
});
|
|
18
38
|
var [noValidate, setNoValidate] = useState(config.noValidate || !config.fallbackNative);
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
configRef.current = config;
|
|
41
|
+
});
|
|
19
42
|
useEffect(() => {
|
|
20
43
|
setNoValidate(true);
|
|
21
44
|
}, []);
|
|
22
45
|
useEffect(() => {
|
|
23
|
-
|
|
24
|
-
if (ref.current) {
|
|
25
|
-
validate === null || validate === void 0 ? void 0 : validate(ref.current);
|
|
26
|
-
} // Revalidate the form when input value is changed
|
|
46
|
+
var form = ref.current;
|
|
27
47
|
|
|
48
|
+
if (!form || !config.state) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (!reportValidity(form, config.state)) {
|
|
53
|
+
focusFirstInvalidField(form, config.state.scope);
|
|
54
|
+
}
|
|
28
55
|
|
|
56
|
+
requestSubmit(form);
|
|
57
|
+
}, [config.state]);
|
|
58
|
+
useEffect(() => {
|
|
59
|
+
// Revalidate the form when input value is changed
|
|
29
60
|
var handleInput = event => {
|
|
30
61
|
var field = event.target;
|
|
31
62
|
var form = ref.current;
|
|
63
|
+
var formConfig = configRef.current;
|
|
32
64
|
|
|
33
65
|
if (!form || !isFieldElement(field) || field.form !== form) {
|
|
34
66
|
return;
|
|
35
67
|
}
|
|
36
68
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
if (config.initialReport === 'onChange') {
|
|
41
|
-
field.dataset.conformTouched = 'true';
|
|
42
|
-
} // Field validity might be changed due to cross reference
|
|
43
|
-
|
|
69
|
+
if (formConfig.initialReport === 'onChange') {
|
|
70
|
+
field.dataset.conformTouched = 'true';
|
|
71
|
+
}
|
|
44
72
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
// Report latest error for all touched fields
|
|
48
|
-
_field.checkValidity();
|
|
49
|
-
}
|
|
50
|
-
}
|
|
73
|
+
if (field.dataset.conformTouched) {
|
|
74
|
+
requestValidate(form, field.name);
|
|
51
75
|
}
|
|
52
76
|
};
|
|
53
77
|
|
|
54
78
|
var handleBlur = event => {
|
|
55
79
|
var field = event.target;
|
|
56
80
|
var form = ref.current;
|
|
81
|
+
var formConfig = configRef.current;
|
|
82
|
+
|
|
83
|
+
if (!form || !isFieldElement(field) || field.form !== form) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (formConfig.initialReport === 'onBlur' && !field.dataset.conformTouched) {
|
|
88
|
+
field.dataset.conformTouched = 'true';
|
|
89
|
+
requestValidate(form, field.name);
|
|
90
|
+
}
|
|
91
|
+
};
|
|
57
92
|
|
|
58
|
-
|
|
93
|
+
var handleInvalid = event => {
|
|
94
|
+
var form = getFormElement(ref.current);
|
|
95
|
+
var field = event.target;
|
|
96
|
+
|
|
97
|
+
if (!form || !isFieldElement(field) || field.form !== form || field.name !== '') {
|
|
59
98
|
return;
|
|
60
99
|
}
|
|
61
100
|
|
|
62
|
-
|
|
63
|
-
|
|
101
|
+
event.preventDefault();
|
|
102
|
+
|
|
103
|
+
if (field.dataset.conformTouched) {
|
|
104
|
+
setError(field.validationMessage);
|
|
105
|
+
}
|
|
64
106
|
};
|
|
65
107
|
|
|
66
108
|
var handleReset = event => {
|
|
67
109
|
var form = ref.current;
|
|
110
|
+
var formConfig = configRef.current;
|
|
68
111
|
|
|
69
112
|
if (!form || event.target !== form) {
|
|
70
113
|
return;
|
|
@@ -74,17 +117,15 @@ function useForm() {
|
|
|
74
117
|
for (var field of form.elements) {
|
|
75
118
|
if (isFieldElement(field)) {
|
|
76
119
|
delete field.dataset.conformTouched;
|
|
120
|
+
field.setCustomValidity('');
|
|
77
121
|
}
|
|
78
122
|
}
|
|
79
|
-
/**
|
|
80
|
-
* The reset event is triggered before form reset happens.
|
|
81
|
-
* This make sure the form to be revalidated with initial values.
|
|
82
|
-
*/
|
|
83
|
-
|
|
84
123
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
124
|
+
setError('');
|
|
125
|
+
setFieldsetConfig({
|
|
126
|
+
defaultValue: formConfig.defaultValue,
|
|
127
|
+
initialError: []
|
|
128
|
+
});
|
|
88
129
|
};
|
|
89
130
|
/**
|
|
90
131
|
* The input event handler will be triggered in capturing phase in order to
|
|
@@ -96,58 +137,83 @@ function useForm() {
|
|
|
96
137
|
|
|
97
138
|
document.addEventListener('input', handleInput, true);
|
|
98
139
|
document.addEventListener('blur', handleBlur, true);
|
|
140
|
+
document.addEventListener('invalid', handleInvalid, true);
|
|
99
141
|
document.addEventListener('reset', handleReset);
|
|
100
142
|
return () => {
|
|
101
143
|
document.removeEventListener('input', handleInput, true);
|
|
102
144
|
document.removeEventListener('blur', handleBlur, true);
|
|
145
|
+
document.removeEventListener('invalid', handleInvalid, true);
|
|
103
146
|
document.removeEventListener('reset', handleReset);
|
|
104
147
|
};
|
|
105
|
-
}, [
|
|
148
|
+
}, []);
|
|
106
149
|
return {
|
|
107
150
|
ref,
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
151
|
+
error,
|
|
152
|
+
props: {
|
|
153
|
+
ref,
|
|
154
|
+
noValidate,
|
|
155
|
+
|
|
156
|
+
onSubmit(event) {
|
|
157
|
+
var form = event.currentTarget;
|
|
158
|
+
var nativeEvent = event.nativeEvent;
|
|
159
|
+
var submitter = nativeEvent.submitter;
|
|
160
|
+
|
|
161
|
+
for (var element of form.elements) {
|
|
162
|
+
if (isFieldElement(element) && element.name === '') {
|
|
163
|
+
setError(element.validationMessage);
|
|
164
|
+
break;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* It checks defaultPrevented to confirm if the submission is intentional
|
|
169
|
+
* This is utilized by `useFieldList` to modify the list state when the submit
|
|
170
|
+
* event is captured and revalidate the form with new fields without triggering
|
|
171
|
+
* a form submission at the same time.
|
|
172
|
+
*/
|
|
122
173
|
|
|
123
|
-
if (!config.noValidate && !(submitter !== null && submitter !== void 0 && submitter.formNoValidate) && !event.defaultPrevented) {
|
|
124
|
-
var focused = false;
|
|
125
174
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
175
|
+
if (!submitter || event.defaultPrevented) {
|
|
176
|
+
event.preventDefault();
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
130
179
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
180
|
+
var formData = getFormData(form, submitter);
|
|
181
|
+
var submission = parse(formData);
|
|
182
|
+
var context = {
|
|
183
|
+
form,
|
|
184
|
+
formData,
|
|
185
|
+
submission
|
|
186
|
+
}; // Touch all fields only if the submitter is not a command button
|
|
187
|
+
|
|
188
|
+
if (!submission.type) {
|
|
189
|
+
for (var field of form.elements) {
|
|
190
|
+
if (isFieldElement(field)) {
|
|
191
|
+
// Mark the field as touched
|
|
192
|
+
field.dataset.conformTouched = 'true';
|
|
134
193
|
}
|
|
135
194
|
}
|
|
136
|
-
}
|
|
137
|
-
|
|
195
|
+
}
|
|
138
196
|
|
|
139
|
-
if (!
|
|
140
|
-
|
|
197
|
+
if (typeof config.onValidate === 'function' && !config.noValidate && !submitter.formNoValidate) {
|
|
198
|
+
try {
|
|
199
|
+
if (!config.onValidate(context)) {
|
|
200
|
+
focusFirstInvalidField(form);
|
|
201
|
+
event.preventDefault();
|
|
202
|
+
}
|
|
203
|
+
} catch (e) {
|
|
204
|
+
console.warn(e);
|
|
205
|
+
}
|
|
141
206
|
}
|
|
142
|
-
}
|
|
143
207
|
|
|
144
|
-
|
|
145
|
-
|
|
208
|
+
if (!event.defaultPrevented) {
|
|
209
|
+
var _config$onSubmit;
|
|
146
210
|
|
|
147
|
-
|
|
211
|
+
(_config$onSubmit = config.onSubmit) === null || _config$onSubmit === void 0 ? void 0 : _config$onSubmit.call(config, event, context);
|
|
212
|
+
}
|
|
148
213
|
}
|
|
149
|
-
}
|
|
150
214
|
|
|
215
|
+
},
|
|
216
|
+
config: fieldsetConfig
|
|
151
217
|
};
|
|
152
218
|
}
|
|
153
219
|
/**
|
|
@@ -155,19 +221,55 @@ function useForm() {
|
|
|
155
221
|
*/
|
|
156
222
|
|
|
157
223
|
function useFieldset(ref, config) {
|
|
224
|
+
var configRef = useRef(config);
|
|
225
|
+
var [uncontrolledState, setUncontrolledState] = useState( // @ts-expect-error
|
|
226
|
+
() => {
|
|
227
|
+
var _config$defaultValue;
|
|
228
|
+
|
|
229
|
+
var initialError = {};
|
|
230
|
+
|
|
231
|
+
for (var [name, message] of (_config$initialError = config === null || config === void 0 ? void 0 : config.initialError) !== null && _config$initialError !== void 0 ? _config$initialError : []) {
|
|
232
|
+
var _config$initialError;
|
|
233
|
+
|
|
234
|
+
var [key, ...paths] = getPaths(name);
|
|
235
|
+
|
|
236
|
+
if (typeof key === 'string') {
|
|
237
|
+
var _initialError$key;
|
|
238
|
+
|
|
239
|
+
var scopedName = getName(paths);
|
|
240
|
+
var entries = (_initialError$key = initialError[key]) !== null && _initialError$key !== void 0 ? _initialError$key : [];
|
|
241
|
+
|
|
242
|
+
if (scopedName === '' && entries.length > 0 && entries[0][0] !== '') {
|
|
243
|
+
initialError[key] = [[scopedName, message], ...entries];
|
|
244
|
+
} else {
|
|
245
|
+
initialError[key] = [...entries, [scopedName, message]];
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
return {
|
|
251
|
+
defaultValue: (_config$defaultValue = config === null || config === void 0 ? void 0 : config.defaultValue) !== null && _config$defaultValue !== void 0 ? _config$defaultValue : {},
|
|
252
|
+
initialError
|
|
253
|
+
};
|
|
254
|
+
});
|
|
158
255
|
var [error, setError] = useState(() => {
|
|
159
256
|
var result = {};
|
|
160
257
|
|
|
161
|
-
for (var [key,
|
|
162
|
-
var
|
|
258
|
+
for (var [key, entries] of Object.entries(uncontrolledState.initialError)) {
|
|
259
|
+
var _entries$;
|
|
163
260
|
|
|
164
|
-
|
|
165
|
-
|
|
261
|
+
var [name, message] = (_entries$ = entries === null || entries === void 0 ? void 0 : entries[0]) !== null && _entries$ !== void 0 ? _entries$ : [];
|
|
262
|
+
|
|
263
|
+
if (name === '') {
|
|
264
|
+
result[key] = message !== null && message !== void 0 ? message : '';
|
|
166
265
|
}
|
|
167
266
|
}
|
|
168
267
|
|
|
169
268
|
return result;
|
|
170
269
|
});
|
|
270
|
+
useEffect(() => {
|
|
271
|
+
configRef.current = config;
|
|
272
|
+
});
|
|
171
273
|
useEffect(() => {
|
|
172
274
|
/**
|
|
173
275
|
* Reset the error state of each field if its validity is changed.
|
|
@@ -177,13 +279,16 @@ function useFieldset(ref, config) {
|
|
|
177
279
|
*/
|
|
178
280
|
var resetError = form => {
|
|
179
281
|
setError(prev => {
|
|
282
|
+
var _configRef$current$na, _configRef$current;
|
|
283
|
+
|
|
180
284
|
var next = prev;
|
|
285
|
+
var fieldsetName = (_configRef$current$na = (_configRef$current = configRef.current) === null || _configRef$current === void 0 ? void 0 : _configRef$current.name) !== null && _configRef$current$na !== void 0 ? _configRef$current$na : '';
|
|
181
286
|
|
|
182
287
|
for (var field of form.elements) {
|
|
183
|
-
if (isFieldElement(field)) {
|
|
184
|
-
var key =
|
|
288
|
+
if (isFieldElement(field) && field.name.startsWith(fieldsetName)) {
|
|
289
|
+
var [key, ...paths] = getPaths(fieldsetName.length > 0 ? field.name.slice(fieldsetName.length + 1) : field.name);
|
|
185
290
|
|
|
186
|
-
if (key) {
|
|
291
|
+
if (typeof key === 'string' && paths.length === 0) {
|
|
187
292
|
var _next$key, _next;
|
|
188
293
|
|
|
189
294
|
var prevMessage = (_next$key = (_next = next) === null || _next === void 0 ? void 0 : _next[key]) !== null && _next$key !== void 0 ? _next$key : '';
|
|
@@ -219,29 +324,35 @@ function useFieldset(ref, config) {
|
|
|
219
324
|
};
|
|
220
325
|
|
|
221
326
|
var invalidHandler = event => {
|
|
327
|
+
var _configRef$current$na2, _configRef$current2;
|
|
328
|
+
|
|
222
329
|
var form = getFormElement(ref.current);
|
|
223
330
|
var field = event.target;
|
|
331
|
+
var fieldsetName = (_configRef$current$na2 = (_configRef$current2 = configRef.current) === null || _configRef$current2 === void 0 ? void 0 : _configRef$current2.name) !== null && _configRef$current$na2 !== void 0 ? _configRef$current$na2 : '';
|
|
224
332
|
|
|
225
|
-
if (!form || !isFieldElement(field) || field.form !== form) {
|
|
333
|
+
if (!form || !isFieldElement(field) || field.form !== form || !field.name.startsWith(fieldsetName)) {
|
|
226
334
|
return;
|
|
227
335
|
}
|
|
228
336
|
|
|
229
|
-
var key =
|
|
337
|
+
var [key, ...paths] = getPaths(fieldsetName.length > 0 ? field.name.slice(fieldsetName.length + 1) : field.name); // Update the error only if the field belongs to the fieldset
|
|
230
338
|
|
|
231
|
-
if (key) {
|
|
232
|
-
|
|
233
|
-
|
|
339
|
+
if (typeof key === 'string' && paths.length === 0) {
|
|
340
|
+
if (field.dataset.conformTouched) {
|
|
341
|
+
setError(prev => {
|
|
342
|
+
var _prev$key;
|
|
234
343
|
|
|
235
|
-
|
|
344
|
+
var prevMessage = (_prev$key = prev === null || prev === void 0 ? void 0 : prev[key]) !== null && _prev$key !== void 0 ? _prev$key : '';
|
|
236
345
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
346
|
+
if (prevMessage === field.validationMessage) {
|
|
347
|
+
return prev;
|
|
348
|
+
}
|
|
240
349
|
|
|
241
|
-
|
|
242
|
-
|
|
350
|
+
return _objectSpread2(_objectSpread2({}, prev), {}, {
|
|
351
|
+
[key]: field.validationMessage
|
|
352
|
+
});
|
|
243
353
|
});
|
|
244
|
-
}
|
|
354
|
+
}
|
|
355
|
+
|
|
245
356
|
event.preventDefault();
|
|
246
357
|
}
|
|
247
358
|
};
|
|
@@ -258,12 +369,20 @@ function useFieldset(ref, config) {
|
|
|
258
369
|
};
|
|
259
370
|
|
|
260
371
|
var resetHandler = event => {
|
|
372
|
+
var _fieldsetConfig$defau;
|
|
373
|
+
|
|
261
374
|
var form = getFormElement(ref.current);
|
|
262
375
|
|
|
263
376
|
if (!form || event.target !== form) {
|
|
264
377
|
return;
|
|
265
378
|
}
|
|
266
379
|
|
|
380
|
+
var fieldsetConfig = configRef.current;
|
|
381
|
+
setUncontrolledState({
|
|
382
|
+
// @ts-expect-error
|
|
383
|
+
defaultValue: (_fieldsetConfig$defau = fieldsetConfig === null || fieldsetConfig === void 0 ? void 0 : fieldsetConfig.defaultValue) !== null && _fieldsetConfig$defau !== void 0 ? _fieldsetConfig$defau : {},
|
|
384
|
+
initialError: {}
|
|
385
|
+
});
|
|
267
386
|
setError({});
|
|
268
387
|
};
|
|
269
388
|
|
|
@@ -278,26 +397,7 @@ function useFieldset(ref, config) {
|
|
|
278
397
|
document.removeEventListener('submit', submitHandler);
|
|
279
398
|
document.removeEventListener('reset', resetHandler);
|
|
280
399
|
};
|
|
281
|
-
}, [ref
|
|
282
|
-
useEffect(() => {
|
|
283
|
-
setError(prev => {
|
|
284
|
-
var next = prev;
|
|
285
|
-
|
|
286
|
-
for (var [key, _error2] of Object.entries((_config$initialError2 = config === null || config === void 0 ? void 0 : config.initialError) !== null && _config$initialError2 !== void 0 ? _config$initialError2 : {})) {
|
|
287
|
-
var _config$initialError2;
|
|
288
|
-
|
|
289
|
-
if (next[key] !== (_error2 === null || _error2 === void 0 ? void 0 : _error2.message)) {
|
|
290
|
-
var _error2$message;
|
|
291
|
-
|
|
292
|
-
next = _objectSpread2(_objectSpread2({}, next), {}, {
|
|
293
|
-
[key]: (_error2$message = _error2 === null || _error2 === void 0 ? void 0 : _error2.message) !== null && _error2$message !== void 0 ? _error2$message : ''
|
|
294
|
-
});
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
return next;
|
|
299
|
-
});
|
|
300
|
-
}, [config === null || config === void 0 ? void 0 : config.name, config === null || config === void 0 ? void 0 : config.initialError]);
|
|
400
|
+
}, [ref]);
|
|
301
401
|
/**
|
|
302
402
|
* This allows us constructing the field at runtime as we have no information
|
|
303
403
|
* about which fields would be available. The proxy will also help tracking
|
|
@@ -306,19 +406,20 @@ function useFieldset(ref, config) {
|
|
|
306
406
|
|
|
307
407
|
return new Proxy({}, {
|
|
308
408
|
get(_target, key) {
|
|
309
|
-
var
|
|
409
|
+
var _fieldsetConfig$const, _error$key;
|
|
310
410
|
|
|
311
411
|
if (typeof key !== 'string') {
|
|
312
412
|
return;
|
|
313
413
|
}
|
|
314
414
|
|
|
315
|
-
var
|
|
415
|
+
var fieldsetConfig = config !== null && config !== void 0 ? config : {};
|
|
416
|
+
var constraint = (_fieldsetConfig$const = fieldsetConfig.constraint) === null || _fieldsetConfig$const === void 0 ? void 0 : _fieldsetConfig$const[key];
|
|
316
417
|
var field = {
|
|
317
418
|
config: _objectSpread2({
|
|
318
|
-
name:
|
|
319
|
-
form:
|
|
320
|
-
defaultValue:
|
|
321
|
-
initialError:
|
|
419
|
+
name: fieldsetConfig.name ? "".concat(fieldsetConfig.name, ".").concat(key) : key,
|
|
420
|
+
form: fieldsetConfig.form,
|
|
421
|
+
defaultValue: uncontrolledState.defaultValue[key],
|
|
422
|
+
initialError: uncontrolledState.initialError[key]
|
|
322
423
|
}, constraint),
|
|
323
424
|
error: (_error$key = error === null || error === void 0 ? void 0 : error[key]) !== null && _error$key !== void 0 ? _error$key : ''
|
|
324
425
|
};
|
|
@@ -332,25 +433,55 @@ function useFieldset(ref, config) {
|
|
|
332
433
|
* Returns a list of key and config, with a group of helpers
|
|
333
434
|
* configuring buttons for list manipulation
|
|
334
435
|
*
|
|
335
|
-
* @see https://github.com/edmundhung/conform/tree/v0.
|
|
436
|
+
* @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.0/packages/conform-react/README.md#usefieldlist
|
|
336
437
|
*/
|
|
337
438
|
function useFieldList(ref, config) {
|
|
338
|
-
var
|
|
439
|
+
var configRef = useRef(config);
|
|
440
|
+
var [uncontrolledState, setUncontrolledState] = useState(() => {
|
|
339
441
|
var _config$defaultValue2;
|
|
340
442
|
|
|
341
|
-
|
|
443
|
+
var initialError = [];
|
|
444
|
+
|
|
445
|
+
for (var [name, message] of (_config$initialError2 = config === null || config === void 0 ? void 0 : config.initialError) !== null && _config$initialError2 !== void 0 ? _config$initialError2 : []) {
|
|
446
|
+
var _config$initialError2;
|
|
447
|
+
|
|
448
|
+
var [index, ...paths] = getPaths(name);
|
|
449
|
+
|
|
450
|
+
if (typeof index === 'number') {
|
|
451
|
+
var _initialError$index;
|
|
452
|
+
|
|
453
|
+
var scopedName = getName(paths);
|
|
454
|
+
|
|
455
|
+
var _entries = (_initialError$index = initialError[index]) !== null && _initialError$index !== void 0 ? _initialError$index : [];
|
|
456
|
+
|
|
457
|
+
if (scopedName === '' && _entries.length > 0 && _entries[0][0] !== '') {
|
|
458
|
+
initialError[index] = [[scopedName, message], ..._entries];
|
|
459
|
+
} else {
|
|
460
|
+
initialError[index] = [..._entries, [scopedName, message]];
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
return {
|
|
466
|
+
defaultValue: (_config$defaultValue2 = config.defaultValue) !== null && _config$defaultValue2 !== void 0 ? _config$defaultValue2 : [],
|
|
467
|
+
initialError
|
|
468
|
+
};
|
|
342
469
|
});
|
|
343
|
-
var
|
|
344
|
-
var _config$defaultValue3
|
|
470
|
+
var [entries, setEntries] = useState(() => {
|
|
471
|
+
var _config$defaultValue3;
|
|
345
472
|
|
|
346
|
-
|
|
473
|
+
return Object.entries((_config$defaultValue3 = config.defaultValue) !== null && _config$defaultValue3 !== void 0 ? _config$defaultValue3 : [undefined]);
|
|
474
|
+
});
|
|
475
|
+
var list = entries.map((_ref3, index) => {
|
|
476
|
+
var [key, defaultValue] = _ref3;
|
|
347
477
|
return {
|
|
348
478
|
key,
|
|
349
|
-
config:
|
|
479
|
+
config: {
|
|
350
480
|
name: "".concat(config.name, "[").concat(index, "]"),
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
481
|
+
form: config.form,
|
|
482
|
+
defaultValue: defaultValue !== null && defaultValue !== void 0 ? defaultValue : uncontrolledState.defaultValue[index],
|
|
483
|
+
initialError: uncontrolledState.initialError[index]
|
|
484
|
+
}
|
|
354
485
|
};
|
|
355
486
|
});
|
|
356
487
|
/***
|
|
@@ -363,9 +494,10 @@ function useFieldList(ref, config) {
|
|
|
363
494
|
return function () {
|
|
364
495
|
var payload = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
365
496
|
return {
|
|
366
|
-
name:
|
|
367
|
-
value:
|
|
497
|
+
name: 'conform/list',
|
|
498
|
+
value: JSON.stringify({
|
|
368
499
|
type,
|
|
500
|
+
scope: config.name,
|
|
369
501
|
payload
|
|
370
502
|
}),
|
|
371
503
|
form: config.form,
|
|
@@ -376,56 +508,45 @@ function useFieldList(ref, config) {
|
|
|
376
508
|
|
|
377
509
|
});
|
|
378
510
|
useEffect(() => {
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
var nextEntries = Object.entries((_config$defaultValue4 = config.defaultValue) !== null && _config$defaultValue4 !== void 0 ? _config$defaultValue4 : [undefined]);
|
|
383
|
-
|
|
384
|
-
if (prevEntries.length !== nextEntries.length) {
|
|
385
|
-
return nextEntries;
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
for (var i = 0; i < prevEntries.length; i++) {
|
|
389
|
-
var [prevKey, prevValue] = prevEntries[i];
|
|
390
|
-
var [nextKey, nextValue] = nextEntries[i];
|
|
391
|
-
|
|
392
|
-
if (prevKey !== nextKey || prevValue !== nextValue) {
|
|
393
|
-
return nextEntries;
|
|
394
|
-
}
|
|
395
|
-
} // No need to rerender in this case
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
return prevEntries;
|
|
399
|
-
});
|
|
400
|
-
|
|
511
|
+
configRef.current = config;
|
|
512
|
+
});
|
|
513
|
+
useEffect(() => {
|
|
401
514
|
var submitHandler = event => {
|
|
402
515
|
var form = getFormElement(ref.current);
|
|
403
516
|
|
|
404
|
-
if (!form || event.target !== form || !(event.submitter instanceof HTMLButtonElement) || event.submitter.name !==
|
|
517
|
+
if (!form || event.target !== form || !(event.submitter instanceof HTMLButtonElement) || event.submitter.name !== 'conform/list') {
|
|
405
518
|
return;
|
|
406
519
|
}
|
|
407
520
|
|
|
408
|
-
var
|
|
521
|
+
var command = parseListCommand(event.submitter.value);
|
|
409
522
|
|
|
410
|
-
if (
|
|
523
|
+
if (command.scope !== configRef.current.name) {
|
|
411
524
|
// Ensure the scope of the listener are limited to specific field name
|
|
412
525
|
return;
|
|
413
526
|
}
|
|
414
527
|
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
528
|
+
setEntries(entries => {
|
|
529
|
+
switch (command.type) {
|
|
530
|
+
case 'append':
|
|
531
|
+
case 'prepend':
|
|
532
|
+
case 'replace':
|
|
533
|
+
return updateList([...(entries !== null && entries !== void 0 ? entries : [])], _objectSpread2(_objectSpread2({}, command), {}, {
|
|
534
|
+
payload: _objectSpread2(_objectSpread2({}, command.payload), {}, {
|
|
535
|
+
defaultValue: ["".concat(Date.now()), command.payload.defaultValue]
|
|
536
|
+
})
|
|
537
|
+
}));
|
|
538
|
+
|
|
539
|
+
default:
|
|
540
|
+
{
|
|
541
|
+
return updateList([...(entries !== null && entries !== void 0 ? entries : [])], command);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
});
|
|
424
545
|
event.preventDefault();
|
|
425
546
|
};
|
|
426
547
|
|
|
427
548
|
var resetHandler = event => {
|
|
428
|
-
var
|
|
549
|
+
var _fieldConfig$defaultV, _fieldConfig$defaultV2;
|
|
429
550
|
|
|
430
551
|
var form = getFormElement(ref.current);
|
|
431
552
|
|
|
@@ -433,7 +554,12 @@ function useFieldList(ref, config) {
|
|
|
433
554
|
return;
|
|
434
555
|
}
|
|
435
556
|
|
|
436
|
-
|
|
557
|
+
var fieldConfig = configRef.current;
|
|
558
|
+
setUncontrolledState({
|
|
559
|
+
defaultValue: (_fieldConfig$defaultV = fieldConfig.defaultValue) !== null && _fieldConfig$defaultV !== void 0 ? _fieldConfig$defaultV : [],
|
|
560
|
+
initialError: []
|
|
561
|
+
});
|
|
562
|
+
setEntries(Object.entries((_fieldConfig$defaultV2 = fieldConfig.defaultValue) !== null && _fieldConfig$defaultV2 !== void 0 ? _fieldConfig$defaultV2 : [undefined]));
|
|
437
563
|
};
|
|
438
564
|
|
|
439
565
|
document.addEventListener('submit', submitHandler, true);
|
|
@@ -442,7 +568,7 @@ function useFieldList(ref, config) {
|
|
|
442
568
|
document.removeEventListener('submit', submitHandler, true);
|
|
443
569
|
document.removeEventListener('reset', resetHandler);
|
|
444
570
|
};
|
|
445
|
-
}, [ref
|
|
571
|
+
}, [ref]);
|
|
446
572
|
return [list, control];
|
|
447
573
|
}
|
|
448
574
|
|
|
@@ -451,14 +577,19 @@ function useFieldList(ref, config) {
|
|
|
451
577
|
* This is particular useful when integrating dropdown and datepicker whichs
|
|
452
578
|
* introduces custom input mode.
|
|
453
579
|
*
|
|
454
|
-
* @see https://github.com/edmundhung/conform/tree/v0.
|
|
580
|
+
* @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.0/packages/conform-react/README.md#usecontrolledinput
|
|
455
581
|
*/
|
|
456
|
-
function useControlledInput(
|
|
457
|
-
var
|
|
582
|
+
function useControlledInput(config) {
|
|
583
|
+
var _config$defaultValue4;
|
|
458
584
|
|
|
459
585
|
var ref = useRef(null);
|
|
460
586
|
var inputRef = useRef(null);
|
|
461
|
-
var
|
|
587
|
+
var configRef = useRef(config);
|
|
588
|
+
var [uncontrolledState, setUncontrolledState] = useState({
|
|
589
|
+
defaultValue: config.defaultValue,
|
|
590
|
+
initialError: config.initialError
|
|
591
|
+
});
|
|
592
|
+
var [value, setValue] = useState("".concat((_config$defaultValue4 = config.defaultValue) !== null && _config$defaultValue4 !== void 0 ? _config$defaultValue4 : ''));
|
|
462
593
|
|
|
463
594
|
var handleChange = eventOrValue => {
|
|
464
595
|
if (!ref.current) {
|
|
@@ -485,6 +616,31 @@ function useControlledInput(field) {
|
|
|
485
616
|
event.preventDefault();
|
|
486
617
|
};
|
|
487
618
|
|
|
619
|
+
useEffect(() => {
|
|
620
|
+
configRef.current = config;
|
|
621
|
+
});
|
|
622
|
+
useEffect(() => {
|
|
623
|
+
var resetHandler = event => {
|
|
624
|
+
var _configRef$current$de;
|
|
625
|
+
|
|
626
|
+
var form = getFormElement(ref.current);
|
|
627
|
+
|
|
628
|
+
if (!form || event.target !== form) {
|
|
629
|
+
return;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
setUncontrolledState({
|
|
633
|
+
defaultValue: configRef.current.defaultValue,
|
|
634
|
+
initialError: configRef.current.initialError
|
|
635
|
+
});
|
|
636
|
+
setValue("".concat((_configRef$current$de = configRef.current.defaultValue) !== null && _configRef$current$de !== void 0 ? _configRef$current$de : ''));
|
|
637
|
+
};
|
|
638
|
+
|
|
639
|
+
document.addEventListener('reset', resetHandler);
|
|
640
|
+
return () => {
|
|
641
|
+
document.removeEventListener('reset', resetHandler);
|
|
642
|
+
};
|
|
643
|
+
}, []);
|
|
488
644
|
return [_objectSpread2({
|
|
489
645
|
ref,
|
|
490
646
|
style: {
|
|
@@ -505,7 +661,7 @@ function useControlledInput(field) {
|
|
|
505
661
|
(_inputRef$current = inputRef.current) === null || _inputRef$current === void 0 ? void 0 : _inputRef$current.focus();
|
|
506
662
|
}
|
|
507
663
|
|
|
508
|
-
}, input(
|
|
664
|
+
}, input(_objectSpread2(_objectSpread2({}, config), uncontrolledState), {
|
|
509
665
|
type: 'text'
|
|
510
666
|
})), {
|
|
511
667
|
ref: inputRef,
|