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