@conform-to/react 0.3.0 → 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/README.md +99 -48
- package/helpers.js +20 -3
- package/hooks.d.ts +36 -12
- package/hooks.js +342 -160
- package/index.d.ts +1 -1
- package/index.js +12 -4
- package/module/helpers.js +20 -3
- package/module/hooks.js +343 -161
- 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;
|
|
61
86
|
|
|
62
|
-
if (!form || !dom.isFieldElement(field) || field.form !== form
|
|
87
|
+
if (!form || !dom.isFieldElement(field) || field.form !== form) {
|
|
63
88
|
return;
|
|
64
89
|
}
|
|
65
90
|
|
|
66
|
-
field.dataset.conformTouched
|
|
67
|
-
|
|
91
|
+
if (formConfig.initialReport === 'onBlur' && !field.dataset.conformTouched) {
|
|
92
|
+
field.dataset.conformTouched = 'true';
|
|
93
|
+
dom.requestValidate(form, field.name);
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
|
|
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 !== '') {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
|
|
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
127
|
|
|
88
|
-
|
|
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,51 +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
|
-
|
|
126
|
-
|
|
127
|
-
if (!config.noValidate && !(submitter !== null && submitter !== void 0 && submitter.formNoValidate) && !event.defaultPrevented) {
|
|
128
|
-
// Mark all fields as touched
|
|
129
|
-
for (var field of form.elements) {
|
|
130
|
-
if (dom.isFieldElement(field)) {
|
|
131
|
-
field.dataset.conformTouched = 'true';
|
|
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;
|
|
132
169
|
}
|
|
133
|
-
}
|
|
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
|
+
*/
|
|
134
177
|
|
|
135
178
|
|
|
136
|
-
if (!event.
|
|
179
|
+
if (!submitter || event.defaultPrevented) {
|
|
137
180
|
event.preventDefault();
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
|
|
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';
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
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
|
+
}
|
|
138
210
|
}
|
|
139
|
-
}
|
|
140
211
|
|
|
141
|
-
|
|
142
|
-
|
|
212
|
+
if (!event.defaultPrevented) {
|
|
213
|
+
var _config$onSubmit;
|
|
143
214
|
|
|
144
|
-
|
|
215
|
+
(_config$onSubmit = config.onSubmit) === null || _config$onSubmit === void 0 ? void 0 : _config$onSubmit.call(config, event, context);
|
|
216
|
+
}
|
|
145
217
|
}
|
|
146
|
-
}
|
|
147
218
|
|
|
219
|
+
},
|
|
220
|
+
config: fieldsetConfig
|
|
148
221
|
};
|
|
149
222
|
}
|
|
150
223
|
/**
|
|
@@ -152,19 +225,55 @@ function useForm() {
|
|
|
152
225
|
*/
|
|
153
226
|
|
|
154
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
|
+
});
|
|
155
259
|
var [error, setError] = react.useState(() => {
|
|
156
260
|
var result = {};
|
|
157
261
|
|
|
158
|
-
for (var [key,
|
|
159
|
-
var
|
|
262
|
+
for (var [key, entries] of Object.entries(uncontrolledState.initialError)) {
|
|
263
|
+
var _entries$;
|
|
160
264
|
|
|
161
|
-
|
|
162
|
-
|
|
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 : '';
|
|
163
269
|
}
|
|
164
270
|
}
|
|
165
271
|
|
|
166
272
|
return result;
|
|
167
273
|
});
|
|
274
|
+
react.useEffect(() => {
|
|
275
|
+
configRef.current = config;
|
|
276
|
+
});
|
|
168
277
|
react.useEffect(() => {
|
|
169
278
|
/**
|
|
170
279
|
* Reset the error state of each field if its validity is changed.
|
|
@@ -174,13 +283,16 @@ function useFieldset(ref, config) {
|
|
|
174
283
|
*/
|
|
175
284
|
var resetError = form => {
|
|
176
285
|
setError(prev => {
|
|
286
|
+
var _configRef$current$na, _configRef$current;
|
|
287
|
+
|
|
177
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 : '';
|
|
178
290
|
|
|
179
291
|
for (var field of form.elements) {
|
|
180
|
-
if (dom.isFieldElement(field)) {
|
|
181
|
-
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);
|
|
182
294
|
|
|
183
|
-
if (key) {
|
|
295
|
+
if (typeof key === 'string' && paths.length === 0) {
|
|
184
296
|
var _next$key, _next;
|
|
185
297
|
|
|
186
298
|
var prevMessage = (_next$key = (_next = next) === null || _next === void 0 ? void 0 : _next[key]) !== null && _next$key !== void 0 ? _next$key : '';
|
|
@@ -216,29 +328,35 @@ function useFieldset(ref, config) {
|
|
|
216
328
|
};
|
|
217
329
|
|
|
218
330
|
var invalidHandler = event => {
|
|
331
|
+
var _configRef$current$na2, _configRef$current2;
|
|
332
|
+
|
|
219
333
|
var form = dom.getFormElement(ref.current);
|
|
220
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 : '';
|
|
221
336
|
|
|
222
|
-
if (!form || !dom.isFieldElement(field) || field.form !== form) {
|
|
337
|
+
if (!form || !dom.isFieldElement(field) || field.form !== form || !field.name.startsWith(fieldsetName)) {
|
|
223
338
|
return;
|
|
224
339
|
}
|
|
225
340
|
|
|
226
|
-
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
|
|
227
342
|
|
|
228
|
-
if (key) {
|
|
229
|
-
|
|
230
|
-
|
|
343
|
+
if (typeof key === 'string' && paths.length === 0) {
|
|
344
|
+
if (field.dataset.conformTouched) {
|
|
345
|
+
setError(prev => {
|
|
346
|
+
var _prev$key;
|
|
231
347
|
|
|
232
|
-
|
|
348
|
+
var prevMessage = (_prev$key = prev === null || prev === void 0 ? void 0 : prev[key]) !== null && _prev$key !== void 0 ? _prev$key : '';
|
|
233
349
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
350
|
+
if (prevMessage === field.validationMessage) {
|
|
351
|
+
return prev;
|
|
352
|
+
}
|
|
237
353
|
|
|
238
|
-
|
|
239
|
-
|
|
354
|
+
return _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, prev), {}, {
|
|
355
|
+
[key]: field.validationMessage
|
|
356
|
+
});
|
|
240
357
|
});
|
|
241
|
-
}
|
|
358
|
+
}
|
|
359
|
+
|
|
242
360
|
event.preventDefault();
|
|
243
361
|
}
|
|
244
362
|
};
|
|
@@ -255,12 +373,20 @@ function useFieldset(ref, config) {
|
|
|
255
373
|
};
|
|
256
374
|
|
|
257
375
|
var resetHandler = event => {
|
|
376
|
+
var _fieldsetConfig$defau;
|
|
377
|
+
|
|
258
378
|
var form = dom.getFormElement(ref.current);
|
|
259
379
|
|
|
260
380
|
if (!form || event.target !== form) {
|
|
261
381
|
return;
|
|
262
382
|
}
|
|
263
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
|
+
});
|
|
264
390
|
setError({});
|
|
265
391
|
};
|
|
266
392
|
|
|
@@ -275,26 +401,7 @@ function useFieldset(ref, config) {
|
|
|
275
401
|
document.removeEventListener('submit', submitHandler);
|
|
276
402
|
document.removeEventListener('reset', resetHandler);
|
|
277
403
|
};
|
|
278
|
-
}, [ref
|
|
279
|
-
react.useEffect(() => {
|
|
280
|
-
setError(prev => {
|
|
281
|
-
var next = prev;
|
|
282
|
-
|
|
283
|
-
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 : {})) {
|
|
284
|
-
var _config$initialError2;
|
|
285
|
-
|
|
286
|
-
if (next[key] !== (_error2 === null || _error2 === void 0 ? void 0 : _error2.message)) {
|
|
287
|
-
var _error2$message;
|
|
288
|
-
|
|
289
|
-
next = _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, next), {}, {
|
|
290
|
-
[key]: (_error2$message = _error2 === null || _error2 === void 0 ? void 0 : _error2.message) !== null && _error2$message !== void 0 ? _error2$message : ''
|
|
291
|
-
});
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
return next;
|
|
296
|
-
});
|
|
297
|
-
}, [config === null || config === void 0 ? void 0 : config.name, config === null || config === void 0 ? void 0 : config.initialError]);
|
|
404
|
+
}, [ref]);
|
|
298
405
|
/**
|
|
299
406
|
* This allows us constructing the field at runtime as we have no information
|
|
300
407
|
* about which fields would be available. The proxy will also help tracking
|
|
@@ -303,19 +410,20 @@ function useFieldset(ref, config) {
|
|
|
303
410
|
|
|
304
411
|
return new Proxy({}, {
|
|
305
412
|
get(_target, key) {
|
|
306
|
-
var
|
|
413
|
+
var _fieldsetConfig$const, _error$key;
|
|
307
414
|
|
|
308
415
|
if (typeof key !== 'string') {
|
|
309
416
|
return;
|
|
310
417
|
}
|
|
311
418
|
|
|
312
|
-
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];
|
|
313
421
|
var field = {
|
|
314
422
|
config: _rollupPluginBabelHelpers.objectSpread2({
|
|
315
|
-
name:
|
|
316
|
-
form:
|
|
317
|
-
defaultValue:
|
|
318
|
-
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]
|
|
319
427
|
}, constraint),
|
|
320
428
|
error: (_error$key = error === null || error === void 0 ? void 0 : error[key]) !== null && _error$key !== void 0 ? _error$key : ''
|
|
321
429
|
};
|
|
@@ -329,25 +437,55 @@ function useFieldset(ref, config) {
|
|
|
329
437
|
* Returns a list of key and config, with a group of helpers
|
|
330
438
|
* configuring buttons for list manipulation
|
|
331
439
|
*
|
|
332
|
-
* @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
|
|
333
441
|
*/
|
|
334
442
|
function useFieldList(ref, config) {
|
|
335
|
-
var
|
|
443
|
+
var configRef = react.useRef(config);
|
|
444
|
+
var [uncontrolledState, setUncontrolledState] = react.useState(() => {
|
|
336
445
|
var _config$defaultValue2;
|
|
337
446
|
|
|
338
|
-
|
|
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
|
+
};
|
|
339
473
|
});
|
|
340
|
-
var
|
|
341
|
-
var _config$defaultValue3
|
|
474
|
+
var [entries, setEntries] = react.useState(() => {
|
|
475
|
+
var _config$defaultValue3;
|
|
342
476
|
|
|
343
|
-
|
|
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;
|
|
344
481
|
return {
|
|
345
482
|
key,
|
|
346
|
-
config:
|
|
483
|
+
config: {
|
|
347
484
|
name: "".concat(config.name, "[").concat(index, "]"),
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
485
|
+
form: config.form,
|
|
486
|
+
defaultValue: defaultValue !== null && defaultValue !== void 0 ? defaultValue : uncontrolledState.defaultValue[index],
|
|
487
|
+
initialError: uncontrolledState.initialError[index]
|
|
488
|
+
}
|
|
351
489
|
};
|
|
352
490
|
});
|
|
353
491
|
/***
|
|
@@ -360,9 +498,10 @@ function useFieldList(ref, config) {
|
|
|
360
498
|
return function () {
|
|
361
499
|
var payload = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
362
500
|
return {
|
|
363
|
-
name:
|
|
364
|
-
value:
|
|
501
|
+
name: 'conform/list',
|
|
502
|
+
value: JSON.stringify({
|
|
365
503
|
type,
|
|
504
|
+
scope: config.name,
|
|
366
505
|
payload
|
|
367
506
|
}),
|
|
368
507
|
form: config.form,
|
|
@@ -373,56 +512,45 @@ function useFieldList(ref, config) {
|
|
|
373
512
|
|
|
374
513
|
});
|
|
375
514
|
react.useEffect(() => {
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
var nextEntries = Object.entries((_config$defaultValue4 = config.defaultValue) !== null && _config$defaultValue4 !== void 0 ? _config$defaultValue4 : [undefined]);
|
|
380
|
-
|
|
381
|
-
if (prevEntries.length !== nextEntries.length) {
|
|
382
|
-
return nextEntries;
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
for (var i = 0; i < prevEntries.length; i++) {
|
|
386
|
-
var [prevKey, prevValue] = prevEntries[i];
|
|
387
|
-
var [nextKey, nextValue] = nextEntries[i];
|
|
388
|
-
|
|
389
|
-
if (prevKey !== nextKey || prevValue !== nextValue) {
|
|
390
|
-
return nextEntries;
|
|
391
|
-
}
|
|
392
|
-
} // No need to rerender in this case
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
return prevEntries;
|
|
396
|
-
});
|
|
397
|
-
|
|
515
|
+
configRef.current = config;
|
|
516
|
+
});
|
|
517
|
+
react.useEffect(() => {
|
|
398
518
|
var submitHandler = event => {
|
|
399
519
|
var form = dom.getFormElement(ref.current);
|
|
400
520
|
|
|
401
|
-
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') {
|
|
402
522
|
return;
|
|
403
523
|
}
|
|
404
524
|
|
|
405
|
-
var
|
|
525
|
+
var command = dom.parseListCommand(event.submitter.value);
|
|
406
526
|
|
|
407
|
-
if (
|
|
527
|
+
if (command.scope !== configRef.current.name) {
|
|
408
528
|
// Ensure the scope of the listener are limited to specific field name
|
|
409
529
|
return;
|
|
410
530
|
}
|
|
411
531
|
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
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
|
+
});
|
|
421
549
|
event.preventDefault();
|
|
422
550
|
};
|
|
423
551
|
|
|
424
552
|
var resetHandler = event => {
|
|
425
|
-
var
|
|
553
|
+
var _fieldConfig$defaultV, _fieldConfig$defaultV2;
|
|
426
554
|
|
|
427
555
|
var form = dom.getFormElement(ref.current);
|
|
428
556
|
|
|
@@ -430,7 +558,12 @@ function useFieldList(ref, config) {
|
|
|
430
558
|
return;
|
|
431
559
|
}
|
|
432
560
|
|
|
433
|
-
|
|
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]));
|
|
434
567
|
};
|
|
435
568
|
|
|
436
569
|
document.addEventListener('submit', submitHandler, true);
|
|
@@ -439,7 +572,7 @@ function useFieldList(ref, config) {
|
|
|
439
572
|
document.removeEventListener('submit', submitHandler, true);
|
|
440
573
|
document.removeEventListener('reset', resetHandler);
|
|
441
574
|
};
|
|
442
|
-
}, [ref
|
|
575
|
+
}, [ref]);
|
|
443
576
|
return [list, control];
|
|
444
577
|
}
|
|
445
578
|
|
|
@@ -448,13 +581,19 @@ function useFieldList(ref, config) {
|
|
|
448
581
|
* This is particular useful when integrating dropdown and datepicker whichs
|
|
449
582
|
* introduces custom input mode.
|
|
450
583
|
*
|
|
451
|
-
* @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
|
|
452
585
|
*/
|
|
453
|
-
function useControlledInput(
|
|
454
|
-
var
|
|
586
|
+
function useControlledInput(config) {
|
|
587
|
+
var _config$defaultValue4;
|
|
455
588
|
|
|
456
589
|
var ref = react.useRef(null);
|
|
457
|
-
var
|
|
590
|
+
var inputRef = react.useRef(null);
|
|
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 : ''));
|
|
458
597
|
|
|
459
598
|
var handleChange = eventOrValue => {
|
|
460
599
|
if (!ref.current) {
|
|
@@ -481,12 +620,55 @@ function useControlledInput(field) {
|
|
|
481
620
|
event.preventDefault();
|
|
482
621
|
};
|
|
483
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
|
+
}, []);
|
|
484
648
|
return [_rollupPluginBabelHelpers.objectSpread2({
|
|
485
649
|
ref,
|
|
486
|
-
|
|
487
|
-
|
|
650
|
+
style: {
|
|
651
|
+
position: 'absolute',
|
|
652
|
+
width: '1px',
|
|
653
|
+
height: '1px',
|
|
654
|
+
padding: 0,
|
|
655
|
+
margin: '-1px',
|
|
656
|
+
overflow: 'hidden',
|
|
657
|
+
clip: 'rect(0,0,0,0)',
|
|
658
|
+
whiteSpace: 'nowrap',
|
|
659
|
+
borderWidth: 0
|
|
660
|
+
},
|
|
661
|
+
|
|
662
|
+
onFocus() {
|
|
663
|
+
var _inputRef$current;
|
|
664
|
+
|
|
665
|
+
(_inputRef$current = inputRef.current) === null || _inputRef$current === void 0 ? void 0 : _inputRef$current.focus();
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
}, helpers.input(_rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, config), uncontrolledState), {
|
|
488
669
|
type: 'text'
|
|
489
670
|
})), {
|
|
671
|
+
ref: inputRef,
|
|
490
672
|
value,
|
|
491
673
|
onChange: handleChange,
|
|
492
674
|
onBlur: handleBlur,
|