@conform-to/react 0.5.0-pre.0 → 0.5.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 +217 -287
- package/helpers.d.ts +3 -0
- package/helpers.js +15 -5
- package/hooks.d.ts +22 -29
- package/hooks.js +55 -67
- package/index.d.ts +1 -1
- package/index.js +16 -0
- package/module/helpers.js +15 -5
- package/module/hooks.js +56 -68
- 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 {
|
|
2
|
+
import { shouldValidate, reportSubmission, getFormData, parse, isFieldElement, hasError, getPaths, getName, requestCommand, validate, 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,7 +7,7 @@ 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://
|
|
10
|
+
* @see https://conform.guide/api/react#useform
|
|
11
11
|
*/
|
|
12
12
|
function useForm() {
|
|
13
13
|
var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
@@ -21,17 +21,26 @@ function useForm() {
|
|
|
21
21
|
})) !== null && _config$state$error$f !== void 0 ? _config$state$error$f : [];
|
|
22
22
|
return message !== null && message !== void 0 ? message : '';
|
|
23
23
|
});
|
|
24
|
-
var [
|
|
25
|
-
var
|
|
26
|
-
|
|
24
|
+
var [uncontrolledState, setUncontrolledState] = useState(() => {
|
|
25
|
+
var submission = config.state;
|
|
26
|
+
if (!submission) {
|
|
27
|
+
return {
|
|
28
|
+
defaultValue: config.defaultValue
|
|
29
|
+
};
|
|
30
|
+
}
|
|
27
31
|
return {
|
|
28
|
-
defaultValue:
|
|
29
|
-
initialError: error.filter(_ref2 => {
|
|
32
|
+
defaultValue: submission.value,
|
|
33
|
+
initialError: submission.error.filter(_ref2 => {
|
|
30
34
|
var [name] = _ref2;
|
|
31
|
-
return name !== '' &&
|
|
35
|
+
return name !== '' && shouldValidate(submission, name);
|
|
32
36
|
})
|
|
33
37
|
};
|
|
34
38
|
});
|
|
39
|
+
var fieldsetConfig = _objectSpread2(_objectSpread2({}, uncontrolledState), {}, {
|
|
40
|
+
constraint: config.constraint,
|
|
41
|
+
form: config.id
|
|
42
|
+
});
|
|
43
|
+
var fieldset = useFieldset(ref, fieldsetConfig);
|
|
35
44
|
var [noValidate, setNoValidate] = useState(config.noValidate || !config.fallbackNative);
|
|
36
45
|
useEffect(() => {
|
|
37
46
|
configRef.current = config;
|
|
@@ -55,11 +64,8 @@ function useForm() {
|
|
|
55
64
|
if (!form || !isFieldElement(field) || field.form !== form) {
|
|
56
65
|
return;
|
|
57
66
|
}
|
|
58
|
-
if (formConfig.initialReport === 'onChange') {
|
|
59
|
-
field.
|
|
60
|
-
}
|
|
61
|
-
if (field.dataset.conformTouched) {
|
|
62
|
-
requestValidate(form, field.name);
|
|
67
|
+
if (field.dataset.conformTouched || formConfig.initialReport === 'onChange') {
|
|
68
|
+
requestCommand(form, validate(field.name));
|
|
63
69
|
}
|
|
64
70
|
};
|
|
65
71
|
var handleBlur = event => {
|
|
@@ -70,8 +76,7 @@ function useForm() {
|
|
|
70
76
|
return;
|
|
71
77
|
}
|
|
72
78
|
if (formConfig.initialReport === 'onBlur' && !field.dataset.conformTouched) {
|
|
73
|
-
field.
|
|
74
|
-
requestValidate(form, field.name);
|
|
79
|
+
requestCommand(form, validate(field.name));
|
|
75
80
|
}
|
|
76
81
|
};
|
|
77
82
|
var handleInvalid = event => {
|
|
@@ -96,11 +101,12 @@ function useForm() {
|
|
|
96
101
|
for (var field of form.elements) {
|
|
97
102
|
if (isFieldElement(field)) {
|
|
98
103
|
delete field.dataset.conformTouched;
|
|
104
|
+
field.setAttribute('aria-invalid', 'false');
|
|
99
105
|
field.setCustomValidity('');
|
|
100
106
|
}
|
|
101
107
|
}
|
|
102
108
|
setError('');
|
|
103
|
-
|
|
109
|
+
setUncontrolledState({
|
|
104
110
|
defaultValue: formConfig.defaultValue,
|
|
105
111
|
initialError: []
|
|
106
112
|
});
|
|
@@ -123,11 +129,13 @@ function useForm() {
|
|
|
123
129
|
document.removeEventListener('reset', handleReset);
|
|
124
130
|
};
|
|
125
131
|
}, []);
|
|
126
|
-
|
|
132
|
+
var form = {
|
|
133
|
+
id: config.id,
|
|
127
134
|
ref,
|
|
128
135
|
error,
|
|
129
136
|
props: {
|
|
130
137
|
ref,
|
|
138
|
+
id: config.id,
|
|
131
139
|
noValidate,
|
|
132
140
|
onSubmit(event) {
|
|
133
141
|
var form = event.currentTarget;
|
|
@@ -169,16 +177,6 @@ function useForm() {
|
|
|
169
177
|
}
|
|
170
178
|
}
|
|
171
179
|
}
|
|
172
|
-
|
|
173
|
-
// Touch all fields only if the submitter is not a command button
|
|
174
|
-
if (submission.type === 'submit') {
|
|
175
|
-
for (var field of form.elements) {
|
|
176
|
-
if (isFieldElement(field)) {
|
|
177
|
-
// Mark the field as touched
|
|
178
|
-
field.dataset.conformTouched = 'true';
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
180
|
if (!config.noValidate && !(submitter !== null && submitter !== void 0 && submitter.formNoValidate) && hasError(submission.error) || submission.type === 'validate' && config.mode !== 'server-validation') {
|
|
183
181
|
event.preventDefault();
|
|
184
182
|
} else {
|
|
@@ -198,6 +196,7 @@ function useForm() {
|
|
|
198
196
|
},
|
|
199
197
|
config: fieldsetConfig
|
|
200
198
|
};
|
|
199
|
+
return [form, fieldset];
|
|
201
200
|
}
|
|
202
201
|
|
|
203
202
|
/**
|
|
@@ -258,6 +257,10 @@ function useFieldset(ref, config) {
|
|
|
258
257
|
// Update the error only if the field belongs to the fieldset
|
|
259
258
|
if (typeof key === 'string' && paths.length === 0) {
|
|
260
259
|
if (field.dataset.conformTouched) {
|
|
260
|
+
// Update the aria attribute only if it is set
|
|
261
|
+
if (field.getAttribute('aria-invalid')) {
|
|
262
|
+
field.setAttribute('aria-invalid', field.validationMessage !== '' ? 'true' : 'false');
|
|
263
|
+
}
|
|
261
264
|
setError(prev => {
|
|
262
265
|
var _prev$key;
|
|
263
266
|
var prevMessage = (_prev$key = prev === null || prev === void 0 ? void 0 : prev[key]) !== null && _prev$key !== void 0 ? _prev$key : '';
|
|
@@ -312,21 +315,26 @@ function useFieldset(ref, config) {
|
|
|
312
315
|
var field = {
|
|
313
316
|
config: _objectSpread2({
|
|
314
317
|
name: fieldsetConfig.name ? "".concat(fieldsetConfig.name, ".").concat(key) : key,
|
|
315
|
-
form: fieldsetConfig.form,
|
|
316
318
|
defaultValue: uncontrolledState.defaultValue[key],
|
|
317
319
|
initialError: uncontrolledState.initialError[key]
|
|
318
320
|
}, constraint),
|
|
319
321
|
error: (_error$key = error === null || error === void 0 ? void 0 : error[key]) !== null && _error$key !== void 0 ? _error$key : ''
|
|
320
322
|
};
|
|
323
|
+
if (fieldsetConfig.form) {
|
|
324
|
+
field.config.form = fieldsetConfig.form;
|
|
325
|
+
field.config.id = "".concat(fieldsetConfig.form, "-").concat(field.config.name);
|
|
326
|
+
field.config.errorId = "".concat(field.config.id, "-error");
|
|
327
|
+
}
|
|
321
328
|
return field;
|
|
322
329
|
}
|
|
323
330
|
});
|
|
324
331
|
}
|
|
332
|
+
|
|
325
333
|
/**
|
|
326
334
|
* Returns a list of key and config, with a group of helpers
|
|
327
335
|
* configuring buttons for list manipulation
|
|
328
336
|
*
|
|
329
|
-
* @see https://
|
|
337
|
+
* @see https://conform.guide/api/react#usefieldlist
|
|
330
338
|
*/
|
|
331
339
|
function useFieldList(ref, config) {
|
|
332
340
|
var configRef = useRef(config);
|
|
@@ -357,41 +365,6 @@ function useFieldList(ref, config) {
|
|
|
357
365
|
var _config$defaultValue3;
|
|
358
366
|
return Object.entries((_config$defaultValue3 = config.defaultValue) !== null && _config$defaultValue3 !== void 0 ? _config$defaultValue3 : [undefined]);
|
|
359
367
|
});
|
|
360
|
-
var list = entries.map((_ref3, index) => {
|
|
361
|
-
var [key, defaultValue] = _ref3;
|
|
362
|
-
return {
|
|
363
|
-
key,
|
|
364
|
-
error: error[index],
|
|
365
|
-
config: {
|
|
366
|
-
name: "".concat(config.name, "[").concat(index, "]"),
|
|
367
|
-
form: config.form,
|
|
368
|
-
defaultValue: defaultValue !== null && defaultValue !== void 0 ? defaultValue : uncontrolledState.defaultValue[index],
|
|
369
|
-
initialError: uncontrolledState.initialError[index]
|
|
370
|
-
}
|
|
371
|
-
};
|
|
372
|
-
});
|
|
373
|
-
|
|
374
|
-
/***
|
|
375
|
-
* This use proxy to capture all information about the command and
|
|
376
|
-
* have it encoded in the value.
|
|
377
|
-
*/
|
|
378
|
-
var command = new Proxy({}, {
|
|
379
|
-
get(_target, type) {
|
|
380
|
-
return function () {
|
|
381
|
-
var payload = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
382
|
-
return {
|
|
383
|
-
name: 'conform/list',
|
|
384
|
-
value: JSON.stringify({
|
|
385
|
-
type,
|
|
386
|
-
scope: config.name,
|
|
387
|
-
payload
|
|
388
|
-
}),
|
|
389
|
-
form: config.form,
|
|
390
|
-
formNoValidate: true
|
|
391
|
-
};
|
|
392
|
-
};
|
|
393
|
-
}
|
|
394
|
-
});
|
|
395
368
|
useEffect(() => {
|
|
396
369
|
configRef.current = config;
|
|
397
370
|
});
|
|
@@ -488,16 +461,31 @@ function useFieldList(ref, config) {
|
|
|
488
461
|
document.removeEventListener('reset', resetHandler);
|
|
489
462
|
};
|
|
490
463
|
}, [ref]);
|
|
491
|
-
return
|
|
492
|
-
|
|
493
|
-
|
|
464
|
+
return entries.map((_ref3, index) => {
|
|
465
|
+
var [key, defaultValue] = _ref3;
|
|
466
|
+
var fieldConfig = {
|
|
467
|
+
name: "".concat(config.name, "[").concat(index, "]"),
|
|
468
|
+
defaultValue: defaultValue !== null && defaultValue !== void 0 ? defaultValue : uncontrolledState.defaultValue[index],
|
|
469
|
+
initialError: uncontrolledState.initialError[index]
|
|
470
|
+
};
|
|
471
|
+
if (config.form) {
|
|
472
|
+
fieldConfig.form = config.form;
|
|
473
|
+
fieldConfig.id = "".concat(config.form, "-").concat(config.name);
|
|
474
|
+
fieldConfig.errorId = "".concat(fieldConfig.id, "-error");
|
|
475
|
+
}
|
|
476
|
+
return {
|
|
477
|
+
key,
|
|
478
|
+
error: error[index],
|
|
479
|
+
config: fieldConfig
|
|
480
|
+
};
|
|
481
|
+
});
|
|
494
482
|
}
|
|
495
483
|
/**
|
|
496
484
|
* Returns the properties required to configure a shadow input for validation.
|
|
497
485
|
* This is particular useful when integrating dropdown and datepicker whichs
|
|
498
486
|
* introduces custom input mode.
|
|
499
487
|
*
|
|
500
|
-
* @see https://
|
|
488
|
+
* @see https://conform.guide/api/react#usecontrolledinput
|
|
501
489
|
*/
|
|
502
490
|
function useControlledInput(config) {
|
|
503
491
|
var _config$defaultValue4;
|
package/module/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { getFormElements, hasError, parse, shouldValidate } from '@conform-to/dom';
|
|
1
|
+
export { getFormElements, hasError, list, parse, requestCommand, requestSubmit, shouldValidate, validate } from '@conform-to/dom';
|
|
2
2
|
export { useControlledInput, useFieldList, useFieldset, useForm } from './hooks.js';
|
|
3
3
|
import * as helpers from './helpers.js';
|
|
4
4
|
export { helpers as conform };
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@conform-to/react",
|
|
3
3
|
"description": "Conform view adapter for react",
|
|
4
4
|
"license": "MIT",
|
|
5
|
-
"version": "0.5.0
|
|
5
|
+
"version": "0.5.0",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"module": "module/index.js",
|
|
8
8
|
"repository": {
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"url": "https://github.com/edmundhung/conform/issues"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@conform-to/dom": "0.5.0
|
|
22
|
+
"@conform-to/dom": "0.5.0"
|
|
23
23
|
},
|
|
24
24
|
"peerDependencies": {
|
|
25
25
|
"react": ">=16.8"
|