@conform-to/react 0.7.0-pre.0 → 0.7.0-pre.2
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 +3 -3
- package/_virtual/_rollupPluginBabelHelpers.js +8 -1
- package/_virtual/{_rollupPluginBabelHelpers.cjs → _rollupPluginBabelHelpers.mjs} +1 -8
- package/helpers.d.ts +1 -1
- package/helpers.js +19 -7
- package/{helpers.cjs → helpers.mjs} +7 -19
- package/hooks.d.ts +2 -5
- package/hooks.js +121 -102
- package/{hooks.cjs → hooks.mjs} +108 -115
- package/index.d.ts +2 -2
- package/index.js +36 -4
- package/index.mjs +4 -0
- package/package.json +8 -9
- package/index.cjs +0 -36
package/README.md
CHANGED
|
@@ -507,7 +507,7 @@ export default function SignupForm() {
|
|
|
507
507
|
|
|
508
508
|
### list
|
|
509
509
|
|
|
510
|
-
It provides serveral helpers to configure an intent button for [modifying a list](/docs/
|
|
510
|
+
It provides serveral helpers to configure an intent button for [modifying a list](/docs/intent-button.md#modifying-a-list).
|
|
511
511
|
|
|
512
512
|
```tsx
|
|
513
513
|
import { list } from '@conform-to/react';
|
|
@@ -540,7 +540,7 @@ function Example() {
|
|
|
540
540
|
|
|
541
541
|
### validate
|
|
542
542
|
|
|
543
|
-
It returns the properties required to configure an intent button for [validation](/docs/
|
|
543
|
+
It returns the properties required to configure an intent button for [validation](/docs/intent-button.md#validation).
|
|
544
544
|
|
|
545
545
|
```tsx
|
|
546
546
|
import { validate } from '@conform-to/react';
|
|
@@ -562,7 +562,7 @@ function Example() {
|
|
|
562
562
|
|
|
563
563
|
### requestIntent
|
|
564
564
|
|
|
565
|
-
It lets you [trigger an intent](/docs/
|
|
565
|
+
It lets you [trigger an intent](/docs/intent-button.md#triggering-an-intent) without requiring users to click on a button. It supports both [list](#list) and [validate](#validate) intent.
|
|
566
566
|
|
|
567
567
|
```tsx
|
|
568
568
|
import {
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
1
5
|
function ownKeys(object, enumerableOnly) {
|
|
2
6
|
var keys = Object.keys(object);
|
|
3
7
|
if (Object.getOwnPropertySymbols) {
|
|
@@ -48,4 +52,7 @@ function _toPropertyKey(arg) {
|
|
|
48
52
|
return typeof key === "symbol" ? key : String(key);
|
|
49
53
|
}
|
|
50
54
|
|
|
51
|
-
|
|
55
|
+
exports.defineProperty = _defineProperty;
|
|
56
|
+
exports.objectSpread2 = _objectSpread2;
|
|
57
|
+
exports.toPrimitive = _toPrimitive;
|
|
58
|
+
exports.toPropertyKey = _toPropertyKey;
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
-
|
|
5
1
|
function ownKeys(object, enumerableOnly) {
|
|
6
2
|
var keys = Object.keys(object);
|
|
7
3
|
if (Object.getOwnPropertySymbols) {
|
|
@@ -52,7 +48,4 @@ function _toPropertyKey(arg) {
|
|
|
52
48
|
return typeof key === "symbol" ? key : String(key);
|
|
53
49
|
}
|
|
54
50
|
|
|
55
|
-
|
|
56
|
-
exports.objectSpread2 = _objectSpread2;
|
|
57
|
-
exports.toPrimitive = _toPrimitive;
|
|
58
|
-
exports.toPropertyKey = _toPropertyKey;
|
|
51
|
+
export { _defineProperty as defineProperty, _objectSpread2 as objectSpread2, _toPrimitive as toPrimitive, _toPropertyKey as toPropertyKey };
|
package/helpers.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { INTENT } from '@conform-to/dom';
|
|
2
|
-
import { type FieldConfig, type Primitive, VALIDATION_UNDEFINED, VALIDATION_SKIPPED } from './hooks';
|
|
2
|
+
import { type FieldConfig, type Primitive, VALIDATION_UNDEFINED, VALIDATION_SKIPPED } from './hooks.js';
|
|
3
3
|
import type { CSSProperties, HTMLInputTypeAttribute } from 'react';
|
|
4
4
|
interface FormControlProps {
|
|
5
5
|
id?: string;
|
package/helpers.js
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var _rollupPluginBabelHelpers = require('./_virtual/_rollupPluginBabelHelpers.js');
|
|
6
|
+
var dom = require('@conform-to/dom');
|
|
7
|
+
var hooks = require('./hooks.js');
|
|
4
8
|
|
|
5
9
|
/**
|
|
6
10
|
* Style to make the input element visually hidden
|
|
@@ -47,7 +51,7 @@ function getFormControlProps(config, options) {
|
|
|
47
51
|
}
|
|
48
52
|
function input(config) {
|
|
49
53
|
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
50
|
-
var props =
|
|
54
|
+
var props = _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, getFormControlProps(config, options)), {}, {
|
|
51
55
|
type: options.type,
|
|
52
56
|
minLength: config.minLength,
|
|
53
57
|
maxLength: config.maxLength,
|
|
@@ -67,14 +71,14 @@ function input(config) {
|
|
|
67
71
|
return props;
|
|
68
72
|
}
|
|
69
73
|
function select(config, options) {
|
|
70
|
-
var props =
|
|
74
|
+
var props = _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, getFormControlProps(config, options)), {}, {
|
|
71
75
|
defaultValue: config.defaultValue,
|
|
72
76
|
multiple: config.multiple
|
|
73
77
|
});
|
|
74
78
|
return props;
|
|
75
79
|
}
|
|
76
80
|
function textarea(config, options) {
|
|
77
|
-
var props =
|
|
81
|
+
var props = _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, getFormControlProps(config, options)), {}, {
|
|
78
82
|
defaultValue: config.defaultValue,
|
|
79
83
|
minLength: config.minLength,
|
|
80
84
|
maxLength: config.maxLength
|
|
@@ -82,4 +86,12 @@ function textarea(config, options) {
|
|
|
82
86
|
return props;
|
|
83
87
|
}
|
|
84
88
|
|
|
85
|
-
|
|
89
|
+
Object.defineProperty(exports, 'INTENT', {
|
|
90
|
+
enumerable: true,
|
|
91
|
+
get: function () { return dom.INTENT; }
|
|
92
|
+
});
|
|
93
|
+
exports.VALIDATION_SKIPPED = hooks.VALIDATION_SKIPPED;
|
|
94
|
+
exports.VALIDATION_UNDEFINED = hooks.VALIDATION_UNDEFINED;
|
|
95
|
+
exports.input = input;
|
|
96
|
+
exports.select = select;
|
|
97
|
+
exports.textarea = textarea;
|
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
var _rollupPluginBabelHelpers = require('./_virtual/_rollupPluginBabelHelpers.cjs');
|
|
6
|
-
var dom = require('@conform-to/dom');
|
|
7
|
-
var hooks = require('./hooks.cjs');
|
|
1
|
+
import { objectSpread2 as _objectSpread2 } from './_virtual/_rollupPluginBabelHelpers.mjs';
|
|
2
|
+
export { INTENT } from '@conform-to/dom';
|
|
3
|
+
export { VALIDATION_SKIPPED, VALIDATION_UNDEFINED } from './hooks.mjs';
|
|
8
4
|
|
|
9
5
|
/**
|
|
10
6
|
* Style to make the input element visually hidden
|
|
@@ -51,7 +47,7 @@ function getFormControlProps(config, options) {
|
|
|
51
47
|
}
|
|
52
48
|
function input(config) {
|
|
53
49
|
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
54
|
-
var props =
|
|
50
|
+
var props = _objectSpread2(_objectSpread2({}, getFormControlProps(config, options)), {}, {
|
|
55
51
|
type: options.type,
|
|
56
52
|
minLength: config.minLength,
|
|
57
53
|
maxLength: config.maxLength,
|
|
@@ -71,14 +67,14 @@ function input(config) {
|
|
|
71
67
|
return props;
|
|
72
68
|
}
|
|
73
69
|
function select(config, options) {
|
|
74
|
-
var props =
|
|
70
|
+
var props = _objectSpread2(_objectSpread2({}, getFormControlProps(config, options)), {}, {
|
|
75
71
|
defaultValue: config.defaultValue,
|
|
76
72
|
multiple: config.multiple
|
|
77
73
|
});
|
|
78
74
|
return props;
|
|
79
75
|
}
|
|
80
76
|
function textarea(config, options) {
|
|
81
|
-
var props =
|
|
77
|
+
var props = _objectSpread2(_objectSpread2({}, getFormControlProps(config, options)), {}, {
|
|
82
78
|
defaultValue: config.defaultValue,
|
|
83
79
|
minLength: config.minLength,
|
|
84
80
|
maxLength: config.maxLength
|
|
@@ -86,12 +82,4 @@ function textarea(config, options) {
|
|
|
86
82
|
return props;
|
|
87
83
|
}
|
|
88
84
|
|
|
89
|
-
|
|
90
|
-
enumerable: true,
|
|
91
|
-
get: function () { return dom.INTENT; }
|
|
92
|
-
});
|
|
93
|
-
exports.VALIDATION_SKIPPED = hooks.VALIDATION_SKIPPED;
|
|
94
|
-
exports.VALIDATION_UNDEFINED = hooks.VALIDATION_UNDEFINED;
|
|
95
|
-
exports.input = input;
|
|
96
|
-
exports.select = select;
|
|
97
|
-
exports.textarea = textarea;
|
|
85
|
+
export { input, select, textarea };
|
package/hooks.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type FieldConstraint, type FieldElement, type FieldsetConstraint, type Submission, type KeysOf, type ResolveType, getFormEncType, getFormMethod } from '@conform-to/dom';
|
|
1
|
+
import { type FieldConstraint, type FieldElement, type FieldsetConstraint, type Submission, type KeysOf, type ResolveType, getFormEncType, getFormMethod, parseIntent } from '@conform-to/dom';
|
|
2
2
|
import { type FormEvent, type RefObject } from 'react';
|
|
3
3
|
export type Primitive = null | undefined | string | number | boolean | Date;
|
|
4
4
|
export interface FieldConfig<Schema> extends FieldConstraint<Schema> {
|
|
@@ -211,8 +211,5 @@ export declare function validateConstraint(options: {
|
|
|
211
211
|
}) => string[];
|
|
212
212
|
}): Submission;
|
|
213
213
|
export declare function reportSubmission(form: HTMLFormElement, submission: Submission): void;
|
|
214
|
-
|
|
215
|
-
* Check if the current focus is on a intent button.
|
|
216
|
-
*/
|
|
217
|
-
export declare function isFocusedOnIntentButton(form: HTMLFormElement, intent: string): boolean;
|
|
214
|
+
export declare function getScope(intent: ReturnType<typeof parseIntent>): string | null;
|
|
218
215
|
export {};
|
package/hooks.js
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var _rollupPluginBabelHelpers = require('./_virtual/_rollupPluginBabelHelpers.js');
|
|
6
|
+
var dom = require('@conform-to/dom');
|
|
7
|
+
var react = require('react');
|
|
4
8
|
|
|
5
9
|
/**
|
|
6
10
|
* Normalize error to an array of string.
|
|
@@ -13,40 +17,40 @@ function normalizeError(error) {
|
|
|
13
17
|
return [].concat(error);
|
|
14
18
|
}
|
|
15
19
|
function useNoValidate(defaultNoValidate, validateBeforeHydrate) {
|
|
16
|
-
var [noValidate, setNoValidate] = useState(defaultNoValidate || !validateBeforeHydrate);
|
|
17
|
-
useEffect(() => {
|
|
20
|
+
var [noValidate, setNoValidate] = react.useState(defaultNoValidate || !validateBeforeHydrate);
|
|
21
|
+
react.useEffect(() => {
|
|
18
22
|
setNoValidate(true);
|
|
19
23
|
}, []);
|
|
20
24
|
return noValidate;
|
|
21
25
|
}
|
|
22
26
|
function useFormRef(userProvidedRef) {
|
|
23
|
-
var formRef = useRef(null);
|
|
27
|
+
var formRef = react.useRef(null);
|
|
24
28
|
return userProvidedRef !== null && userProvidedRef !== void 0 ? userProvidedRef : formRef;
|
|
25
29
|
}
|
|
26
30
|
function useConfigRef(config) {
|
|
27
|
-
var ref = useRef(config);
|
|
31
|
+
var ref = react.useRef(config);
|
|
28
32
|
useSafeLayoutEffect(() => {
|
|
29
33
|
ref.current = config;
|
|
30
34
|
});
|
|
31
35
|
return ref;
|
|
32
36
|
}
|
|
33
37
|
function useFormReporter(ref, lastSubmission) {
|
|
34
|
-
var [submission, setSubmission] = useState(lastSubmission);
|
|
35
|
-
var report = useCallback((form, submission) => {
|
|
38
|
+
var [submission, setSubmission] = react.useState(lastSubmission);
|
|
39
|
+
var report = react.useCallback((form, submission) => {
|
|
36
40
|
var event = new CustomEvent('conform', {
|
|
37
41
|
detail: submission.intent
|
|
38
42
|
});
|
|
39
43
|
form.dispatchEvent(event);
|
|
40
44
|
setSubmission(submission);
|
|
41
45
|
}, []);
|
|
42
|
-
useEffect(() => {
|
|
46
|
+
react.useEffect(() => {
|
|
43
47
|
var form = ref.current;
|
|
44
48
|
if (!form || !lastSubmission) {
|
|
45
49
|
return;
|
|
46
50
|
}
|
|
47
51
|
report(form, lastSubmission);
|
|
48
52
|
}, [ref, lastSubmission, report]);
|
|
49
|
-
useEffect(() => {
|
|
53
|
+
react.useEffect(() => {
|
|
50
54
|
var form = ref.current;
|
|
51
55
|
if (!form || !submission) {
|
|
52
56
|
return;
|
|
@@ -56,30 +60,30 @@ function useFormReporter(ref, lastSubmission) {
|
|
|
56
60
|
return report;
|
|
57
61
|
}
|
|
58
62
|
function useFormError(ref, config) {
|
|
59
|
-
var [error, setError] = useState(() => {
|
|
63
|
+
var [error, setError] = react.useState(() => {
|
|
60
64
|
if (!config.initialError) {
|
|
61
65
|
return {};
|
|
62
66
|
}
|
|
63
67
|
var result = {};
|
|
64
68
|
for (var [name, message] of Object.entries(config.initialError)) {
|
|
65
|
-
var paths = getPaths(name);
|
|
69
|
+
var paths = dom.getPaths(name);
|
|
66
70
|
if (paths.length === 1) {
|
|
67
71
|
result[paths[0]] = normalizeError(message);
|
|
68
72
|
}
|
|
69
73
|
}
|
|
70
74
|
return result;
|
|
71
75
|
});
|
|
72
|
-
useEffect(() => {
|
|
76
|
+
react.useEffect(() => {
|
|
73
77
|
var handleInvalid = event => {
|
|
74
|
-
var form = getFormElement(ref.current);
|
|
78
|
+
var form = dom.getFormElement(ref.current);
|
|
75
79
|
var element = event.target;
|
|
76
|
-
if (!isFieldElement(element) || element.form !== form || !element.dataset.conformTouched) {
|
|
80
|
+
if (!dom.isFieldElement(element) || element.form !== form || !element.dataset.conformTouched) {
|
|
77
81
|
return;
|
|
78
82
|
}
|
|
79
83
|
var key = element.name;
|
|
80
84
|
if (config.name) {
|
|
81
|
-
var scopePaths = getPaths(config.name);
|
|
82
|
-
var fieldPaths = getPaths(element.name);
|
|
85
|
+
var scopePaths = dom.getPaths(config.name);
|
|
86
|
+
var fieldPaths = dom.getPaths(element.name);
|
|
83
87
|
for (var i = 0; i <= scopePaths.length; i++) {
|
|
84
88
|
var path = fieldPaths[i];
|
|
85
89
|
if (i < scopePaths.length) {
|
|
@@ -93,17 +97,17 @@ function useFormError(ref, config) {
|
|
|
93
97
|
}
|
|
94
98
|
}
|
|
95
99
|
setError(prev => {
|
|
96
|
-
if (element.validationMessage === getValidationMessage(prev[key])) {
|
|
100
|
+
if (element.validationMessage === dom.getValidationMessage(prev[key])) {
|
|
97
101
|
return prev;
|
|
98
102
|
}
|
|
99
|
-
return
|
|
100
|
-
[key]: getErrors(element.validationMessage)
|
|
103
|
+
return _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, prev), {}, {
|
|
104
|
+
[key]: dom.getErrors(element.validationMessage)
|
|
101
105
|
});
|
|
102
106
|
});
|
|
103
107
|
event.preventDefault();
|
|
104
108
|
};
|
|
105
109
|
var handleReset = event => {
|
|
106
|
-
var form = getFormElement(ref.current);
|
|
110
|
+
var form = dom.getFormElement(ref.current);
|
|
107
111
|
if (form && event.target === form) {
|
|
108
112
|
setError({});
|
|
109
113
|
}
|
|
@@ -131,16 +135,17 @@ function useForm() {
|
|
|
131
135
|
var ref = useFormRef(config.ref);
|
|
132
136
|
var noValidate = useNoValidate(config.noValidate, config.fallbackNative);
|
|
133
137
|
var report = useFormReporter(ref, config.lastSubmission);
|
|
134
|
-
var [errors, setErrors] = useState(() => {
|
|
138
|
+
var [errors, setErrors] = react.useState(() => {
|
|
135
139
|
var _config$lastSubmissio;
|
|
136
140
|
return normalizeError((_config$lastSubmissio = config.lastSubmission) === null || _config$lastSubmissio === void 0 ? void 0 : _config$lastSubmissio.error['']);
|
|
137
141
|
});
|
|
138
|
-
var initialError = useMemo(() => {
|
|
142
|
+
var initialError = react.useMemo(() => {
|
|
139
143
|
var submission = config.lastSubmission;
|
|
140
144
|
if (!submission) {
|
|
141
145
|
return {};
|
|
142
146
|
}
|
|
143
|
-
var
|
|
147
|
+
var intent = dom.parseIntent(submission.intent);
|
|
148
|
+
var scope = getScope(intent);
|
|
144
149
|
return scope === null ? submission.error : {
|
|
145
150
|
[scope]: submission.error[scope]
|
|
146
151
|
};
|
|
@@ -151,7 +156,7 @@ function useForm() {
|
|
|
151
156
|
constraint: config.constraint,
|
|
152
157
|
form: config.id
|
|
153
158
|
});
|
|
154
|
-
useEffect(() => {
|
|
159
|
+
react.useEffect(() => {
|
|
155
160
|
// custom validate handler
|
|
156
161
|
var createValidateHandler = name => event => {
|
|
157
162
|
var field = event.target;
|
|
@@ -161,22 +166,22 @@ function useForm() {
|
|
|
161
166
|
shouldValidate = initialReport === 'onChange' ? 'onInput' : initialReport,
|
|
162
167
|
shouldRevalidate = 'onInput'
|
|
163
168
|
} = configRef.current;
|
|
164
|
-
if (!form || !isFocusableFormControl(field) || field.form !== form || !field.name) {
|
|
169
|
+
if (!form || !dom.isFocusableFormControl(field) || field.form !== form || !field.name) {
|
|
165
170
|
return;
|
|
166
171
|
}
|
|
167
172
|
if (field.dataset.conformTouched ? shouldRevalidate === name : shouldValidate === name) {
|
|
168
|
-
requestIntent(form, validate(field.name));
|
|
173
|
+
dom.requestIntent(form, dom.validate(field.name));
|
|
169
174
|
}
|
|
170
175
|
};
|
|
171
176
|
var handleInvalid = event => {
|
|
172
177
|
var form = ref.current;
|
|
173
178
|
var field = event.target;
|
|
174
|
-
if (!form || !isFieldElement(field) || field.form !== form || field.name !== FORM_ERROR_ELEMENT_NAME) {
|
|
179
|
+
if (!form || !dom.isFieldElement(field) || field.form !== form || field.name !== FORM_ERROR_ELEMENT_NAME) {
|
|
175
180
|
return;
|
|
176
181
|
}
|
|
177
182
|
event.preventDefault();
|
|
178
183
|
if (field.dataset.conformTouched) {
|
|
179
|
-
setErrors(getErrors(field.validationMessage));
|
|
184
|
+
setErrors(dom.getErrors(field.validationMessage));
|
|
180
185
|
}
|
|
181
186
|
};
|
|
182
187
|
var handleReset = event => {
|
|
@@ -186,7 +191,7 @@ function useForm() {
|
|
|
186
191
|
}
|
|
187
192
|
|
|
188
193
|
// Reset all field state
|
|
189
|
-
for (var element of getFormControls(form)) {
|
|
194
|
+
for (var element of dom.getFormControls(form)) {
|
|
190
195
|
delete element.dataset.conformTouched;
|
|
191
196
|
element.setCustomValidity('');
|
|
192
197
|
}
|
|
@@ -221,20 +226,35 @@ function useForm() {
|
|
|
221
226
|
}
|
|
222
227
|
try {
|
|
223
228
|
var _config$onValidate, _config$onValidate2;
|
|
224
|
-
var formData = getFormData(form, submitter);
|
|
229
|
+
var formData = dom.getFormData(form, submitter);
|
|
225
230
|
var submission = (_config$onValidate = (_config$onValidate2 = config.onValidate) === null || _config$onValidate2 === void 0 ? void 0 : _config$onValidate2.call(config, {
|
|
226
231
|
form,
|
|
227
232
|
formData
|
|
228
|
-
})) !== null && _config$onValidate !== void 0 ? _config$onValidate : parse(formData);
|
|
229
|
-
var
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
},
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
233
|
+
})) !== null && _config$onValidate !== void 0 ? _config$onValidate : dom.parse(formData);
|
|
234
|
+
var {
|
|
235
|
+
errors: _errors,
|
|
236
|
+
shouldServerValidate
|
|
237
|
+
} = Object.entries(submission.error).reduce((result, _ref2) => {
|
|
238
|
+
var [, error] = _ref2;
|
|
239
|
+
for (var message of normalizeError(error)) {
|
|
240
|
+
if (message === VALIDATION_UNDEFINED) {
|
|
241
|
+
result.shouldServerValidate = true;
|
|
242
|
+
} else if (message !== VALIDATION_SKIPPED) {
|
|
243
|
+
result.errors.push(message);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
return result;
|
|
247
|
+
}, {
|
|
248
|
+
errors: [],
|
|
249
|
+
shouldServerValidate: false
|
|
250
|
+
});
|
|
251
|
+
if (
|
|
252
|
+
// has client validation
|
|
253
|
+
typeof config.onValidate !== 'undefined' &&
|
|
254
|
+
// not necessary to validate on the server
|
|
255
|
+
!shouldServerValidate && (
|
|
256
|
+
// client validation failed or non submit intent
|
|
257
|
+
!config.noValidate && !(submitter !== null && submitter !== void 0 && submitter.formNoValidate) && _errors.length > 0 || dom.parseIntent(submission.intent) !== null)) {
|
|
238
258
|
report(form, submission);
|
|
239
259
|
event.preventDefault();
|
|
240
260
|
} else {
|
|
@@ -242,9 +262,9 @@ function useForm() {
|
|
|
242
262
|
(_config$onSubmit = config.onSubmit) === null || _config$onSubmit === void 0 ? void 0 : _config$onSubmit.call(config, event, {
|
|
243
263
|
formData,
|
|
244
264
|
submission,
|
|
245
|
-
action: getFormAction(nativeEvent),
|
|
246
|
-
encType: getFormEncType(nativeEvent),
|
|
247
|
-
method: getFormMethod(nativeEvent)
|
|
265
|
+
action: dom.getFormAction(nativeEvent),
|
|
266
|
+
encType: dom.getFormEncType(nativeEvent),
|
|
267
|
+
method: dom.getFormMethod(nativeEvent)
|
|
248
268
|
});
|
|
249
269
|
}
|
|
250
270
|
} catch (e) {
|
|
@@ -291,13 +311,13 @@ function useFieldset(ref, config) {
|
|
|
291
311
|
var errors = error === null || error === void 0 ? void 0 : error[key];
|
|
292
312
|
var initialError = Object.entries((_fieldsetConfig$initi = fieldsetConfig.initialError) !== null && _fieldsetConfig$initi !== void 0 ? _fieldsetConfig$initi : {}).reduce((result, _ref3) => {
|
|
293
313
|
var [name, message] = _ref3;
|
|
294
|
-
var [field, ...paths] = getPaths(name);
|
|
314
|
+
var [field, ...paths] = dom.getPaths(name);
|
|
295
315
|
if (field === key) {
|
|
296
|
-
result[getName(paths)] = message;
|
|
316
|
+
result[dom.getName(paths)] = message;
|
|
297
317
|
}
|
|
298
318
|
return result;
|
|
299
319
|
}, {});
|
|
300
|
-
var field =
|
|
320
|
+
var field = _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, constraint), {}, {
|
|
301
321
|
name: fieldsetConfig.name ? "".concat(fieldsetConfig.name, ".").concat(key) : key,
|
|
302
322
|
// @ts-expect-error The FieldValue type might need a rework
|
|
303
323
|
defaultValue: (_fieldsetConfig$defau = fieldsetConfig.defaultValue) === null || _fieldsetConfig$defau === void 0 ? void 0 : _fieldsetConfig$defau[key],
|
|
@@ -327,37 +347,33 @@ function useFieldList(ref, config) {
|
|
|
327
347
|
initialError: config.initialError,
|
|
328
348
|
name: config.name
|
|
329
349
|
});
|
|
330
|
-
var [entries, setEntries] = useState(() => {
|
|
350
|
+
var [entries, setEntries] = react.useState(() => {
|
|
331
351
|
var _config$defaultValue;
|
|
332
352
|
return Object.entries((_config$defaultValue = config.defaultValue) !== null && _config$defaultValue !== void 0 ? _config$defaultValue : [undefined]);
|
|
333
353
|
});
|
|
334
|
-
useEffect(() => {
|
|
354
|
+
react.useEffect(() => {
|
|
335
355
|
var conformHandler = event => {
|
|
336
|
-
var form = getFormElement(ref.current);
|
|
356
|
+
var form = dom.getFormElement(ref.current);
|
|
337
357
|
if (!form || event.target !== form) {
|
|
338
358
|
return;
|
|
339
359
|
}
|
|
340
|
-
var
|
|
341
|
-
if ((
|
|
342
|
-
// Ensure the scope of the listener are limited to specific field name
|
|
360
|
+
var intent = dom.parseIntent(event.detail);
|
|
361
|
+
if ((intent === null || intent === void 0 ? void 0 : intent.type) !== 'list' || (intent === null || intent === void 0 ? void 0 : intent.payload.name) !== configRef.current.name) {
|
|
343
362
|
return;
|
|
344
363
|
}
|
|
345
364
|
setEntries(entries => {
|
|
346
|
-
|
|
365
|
+
var list = [...entries];
|
|
366
|
+
switch (intent.payload.operation) {
|
|
347
367
|
case 'append':
|
|
348
368
|
case 'prepend':
|
|
349
369
|
case 'replace':
|
|
350
|
-
return updateList(
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
command.payload.defaultValue]
|
|
355
|
-
})
|
|
370
|
+
return dom.updateList(list, _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, intent.payload), {}, {
|
|
371
|
+
defaultValue: [
|
|
372
|
+
// Generate a random key to avoid conflicts
|
|
373
|
+
crypto.getRandomValues(new Uint32Array(1))[0].toString(36), intent.payload.defaultValue]
|
|
356
374
|
}));
|
|
357
375
|
default:
|
|
358
|
-
|
|
359
|
-
return updateList([...(entries !== null && entries !== void 0 ? entries : [])], command);
|
|
360
|
-
}
|
|
376
|
+
return dom.updateList(list, intent.payload);
|
|
361
377
|
}
|
|
362
378
|
});
|
|
363
379
|
setError(error => {
|
|
@@ -367,28 +383,24 @@ function useFieldList(ref, config) {
|
|
|
367
383
|
errorList[key] = messages;
|
|
368
384
|
}
|
|
369
385
|
}
|
|
370
|
-
switch (
|
|
386
|
+
switch (intent.payload.operation) {
|
|
371
387
|
case 'append':
|
|
372
388
|
case 'prepend':
|
|
373
389
|
case 'replace':
|
|
374
|
-
errorList = updateList(errorList,
|
|
375
|
-
|
|
376
|
-
defaultValue: undefined
|
|
377
|
-
})
|
|
390
|
+
errorList = dom.updateList(errorList, _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, intent.payload), {}, {
|
|
391
|
+
defaultValue: undefined
|
|
378
392
|
}));
|
|
379
393
|
break;
|
|
380
394
|
default:
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
break;
|
|
384
|
-
}
|
|
395
|
+
errorList = dom.updateList(errorList, intent.payload);
|
|
396
|
+
break;
|
|
385
397
|
}
|
|
386
398
|
return Object.assign({}, errorList);
|
|
387
399
|
});
|
|
388
400
|
};
|
|
389
401
|
var resetHandler = event => {
|
|
390
402
|
var _configRef$current$de;
|
|
391
|
-
var form = getFormElement(ref.current);
|
|
403
|
+
var form = dom.getFormElement(ref.current);
|
|
392
404
|
if (!form || event.target !== form) {
|
|
393
405
|
return;
|
|
394
406
|
}
|
|
@@ -410,9 +422,9 @@ function useFieldList(ref, config) {
|
|
|
410
422
|
var errors = error[index];
|
|
411
423
|
var initialError = Object.entries((_config$initialError = config.initialError) !== null && _config$initialError !== void 0 ? _config$initialError : {}).reduce((result, _ref5) => {
|
|
412
424
|
var [name, message] = _ref5;
|
|
413
|
-
var [field, ...paths] = getPaths(name);
|
|
425
|
+
var [field, ...paths] = dom.getPaths(name);
|
|
414
426
|
if (field === index) {
|
|
415
|
-
result[getName(paths)] = message;
|
|
427
|
+
result[dom.getName(paths)] = message;
|
|
416
428
|
}
|
|
417
429
|
return result;
|
|
418
430
|
}, {});
|
|
@@ -429,7 +441,7 @@ function useFieldList(ref, config) {
|
|
|
429
441
|
fieldConfig.errorId = "".concat(fieldConfig.id, "-error");
|
|
430
442
|
fieldConfig.descriptionId = "".concat(fieldConfig.id, "-description");
|
|
431
443
|
}
|
|
432
|
-
return
|
|
444
|
+
return _rollupPluginBabelHelpers.objectSpread2({
|
|
433
445
|
key
|
|
434
446
|
}, fieldConfig);
|
|
435
447
|
});
|
|
@@ -468,13 +480,13 @@ function setNativeValue(element, value) {
|
|
|
468
480
|
* useLayoutEffect is client-only.
|
|
469
481
|
* This basically makes it a no-op on server
|
|
470
482
|
*/
|
|
471
|
-
var useSafeLayoutEffect = typeof document === 'undefined' ? useEffect : useLayoutEffect;
|
|
483
|
+
var useSafeLayoutEffect = typeof document === 'undefined' ? react.useEffect : react.useLayoutEffect;
|
|
472
484
|
function useInputEvent(options) {
|
|
473
|
-
var ref = useRef(null);
|
|
485
|
+
var ref = react.useRef(null);
|
|
474
486
|
var optionsRef = useConfigRef(options);
|
|
475
|
-
var changeDispatched = useRef(false);
|
|
476
|
-
var focusDispatched = useRef(false);
|
|
477
|
-
var blurDispatched = useRef(false);
|
|
487
|
+
var changeDispatched = react.useRef(false);
|
|
488
|
+
var focusDispatched = react.useRef(false);
|
|
489
|
+
var blurDispatched = react.useRef(false);
|
|
478
490
|
useSafeLayoutEffect(() => {
|
|
479
491
|
var getInputElement = () => {
|
|
480
492
|
var _optionsRef$current$g, _optionsRef$current, _optionsRef$current$g2;
|
|
@@ -525,7 +537,7 @@ function useInputEvent(options) {
|
|
|
525
537
|
document.removeEventListener('reset', resetHandler);
|
|
526
538
|
};
|
|
527
539
|
}, []);
|
|
528
|
-
var control = useMemo(() => {
|
|
540
|
+
var control = react.useMemo(() => {
|
|
529
541
|
var getInputElement = () => {
|
|
530
542
|
var _optionsRef$current$g3, _optionsRef$current4, _optionsRef$current4$;
|
|
531
543
|
return (_optionsRef$current$g3 = (_optionsRef$current4 = optionsRef.current) === null || _optionsRef$current4 === void 0 ? void 0 : (_optionsRef$current4$ = _optionsRef$current4.getElement) === null || _optionsRef$current4$ === void 0 ? void 0 : _optionsRef$current4$.call(_optionsRef$current4, ref.current)) !== null && _optionsRef$current$g3 !== void 0 ? _optionsRef$current$g3 : ref.current;
|
|
@@ -640,12 +652,12 @@ function validateConstraint(options) {
|
|
|
640
652
|
} = _ref6;
|
|
641
653
|
return defaultErrors;
|
|
642
654
|
};
|
|
643
|
-
return parse(formData, {
|
|
655
|
+
return dom.parse(formData, {
|
|
644
656
|
resolve(payload, intent) {
|
|
645
657
|
var error = {};
|
|
646
658
|
var constraintPattern = /^constraint[A-Z][^A-Z]*$/;
|
|
647
659
|
var _loop = function _loop(element) {
|
|
648
|
-
if (isFieldElement(element)) {
|
|
660
|
+
if (dom.isFieldElement(element)) {
|
|
649
661
|
var _options$acceptMultip, _options$acceptMultip2;
|
|
650
662
|
var name = element.name !== FORM_ERROR_ELEMENT_NAME ? element.name : '';
|
|
651
663
|
var constraint = Object.entries(element.dataset).reduce((result, _ref7) => {
|
|
@@ -718,8 +730,9 @@ function reportSubmission(form, submission) {
|
|
|
718
730
|
form.appendChild(button);
|
|
719
731
|
}
|
|
720
732
|
}
|
|
721
|
-
var
|
|
722
|
-
|
|
733
|
+
var intent = dom.parseIntent(submission.intent);
|
|
734
|
+
var scope = getScope(intent);
|
|
735
|
+
for (var element of dom.getFormControls(form)) {
|
|
723
736
|
var _elementName = element.name !== FORM_ERROR_ELEMENT_NAME ? element.name : '';
|
|
724
737
|
var messages = normalizeError(submission.error[_elementName]);
|
|
725
738
|
if (scope === null || scope === _elementName) {
|
|
@@ -729,25 +742,31 @@ function reportSubmission(form, submission) {
|
|
|
729
742
|
var invalidEvent = new Event('invalid', {
|
|
730
743
|
cancelable: true
|
|
731
744
|
});
|
|
732
|
-
element.setCustomValidity(getValidationMessage(messages));
|
|
745
|
+
element.setCustomValidity(dom.getValidationMessage(messages));
|
|
733
746
|
element.dispatchEvent(invalidEvent);
|
|
734
747
|
}
|
|
735
748
|
}
|
|
736
|
-
if (
|
|
737
|
-
|
|
738
|
-
focusFormControl(form, scope);
|
|
739
|
-
} else {
|
|
740
|
-
focusFirstInvalidControl(form);
|
|
741
|
-
}
|
|
749
|
+
if (!intent) {
|
|
750
|
+
dom.focusFirstInvalidControl(form);
|
|
742
751
|
}
|
|
743
752
|
}
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
753
|
+
function getScope(intent) {
|
|
754
|
+
switch (intent === null || intent === void 0 ? void 0 : intent.type) {
|
|
755
|
+
case 'validate':
|
|
756
|
+
return intent.payload;
|
|
757
|
+
case 'list':
|
|
758
|
+
return intent.payload.name;
|
|
759
|
+
}
|
|
760
|
+
return null;
|
|
751
761
|
}
|
|
752
762
|
|
|
753
|
-
|
|
763
|
+
exports.FORM_ERROR_ELEMENT_NAME = FORM_ERROR_ELEMENT_NAME;
|
|
764
|
+
exports.VALIDATION_SKIPPED = VALIDATION_SKIPPED;
|
|
765
|
+
exports.VALIDATION_UNDEFINED = VALIDATION_UNDEFINED;
|
|
766
|
+
exports.getScope = getScope;
|
|
767
|
+
exports.reportSubmission = reportSubmission;
|
|
768
|
+
exports.useFieldList = useFieldList;
|
|
769
|
+
exports.useFieldset = useFieldset;
|
|
770
|
+
exports.useForm = useForm;
|
|
771
|
+
exports.useInputEvent = useInputEvent;
|
|
772
|
+
exports.validateConstraint = validateConstraint;
|
package/{hooks.cjs → hooks.mjs}
RENAMED
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
var _rollupPluginBabelHelpers = require('./_virtual/_rollupPluginBabelHelpers.cjs');
|
|
6
|
-
var dom = require('@conform-to/dom');
|
|
7
|
-
var react = require('react');
|
|
1
|
+
import { objectSpread2 as _objectSpread2 } from './_virtual/_rollupPluginBabelHelpers.mjs';
|
|
2
|
+
import { parseIntent, getFormData, parse, getFormAction, getFormEncType, getFormMethod, getPaths, getName, isFieldElement, getErrors, getFormControls, getFormElement, updateList, getValidationMessage, focusFirstInvalidControl, isFocusableFormControl, requestIntent, validate } from '@conform-to/dom';
|
|
3
|
+
import { useState, useMemo, useEffect, useRef, useCallback, useLayoutEffect } from 'react';
|
|
8
4
|
|
|
9
5
|
/**
|
|
10
6
|
* Normalize error to an array of string.
|
|
@@ -17,40 +13,40 @@ function normalizeError(error) {
|
|
|
17
13
|
return [].concat(error);
|
|
18
14
|
}
|
|
19
15
|
function useNoValidate(defaultNoValidate, validateBeforeHydrate) {
|
|
20
|
-
var [noValidate, setNoValidate] =
|
|
21
|
-
|
|
16
|
+
var [noValidate, setNoValidate] = useState(defaultNoValidate || !validateBeforeHydrate);
|
|
17
|
+
useEffect(() => {
|
|
22
18
|
setNoValidate(true);
|
|
23
19
|
}, []);
|
|
24
20
|
return noValidate;
|
|
25
21
|
}
|
|
26
22
|
function useFormRef(userProvidedRef) {
|
|
27
|
-
var formRef =
|
|
23
|
+
var formRef = useRef(null);
|
|
28
24
|
return userProvidedRef !== null && userProvidedRef !== void 0 ? userProvidedRef : formRef;
|
|
29
25
|
}
|
|
30
26
|
function useConfigRef(config) {
|
|
31
|
-
var ref =
|
|
27
|
+
var ref = useRef(config);
|
|
32
28
|
useSafeLayoutEffect(() => {
|
|
33
29
|
ref.current = config;
|
|
34
30
|
});
|
|
35
31
|
return ref;
|
|
36
32
|
}
|
|
37
33
|
function useFormReporter(ref, lastSubmission) {
|
|
38
|
-
var [submission, setSubmission] =
|
|
39
|
-
var report =
|
|
34
|
+
var [submission, setSubmission] = useState(lastSubmission);
|
|
35
|
+
var report = useCallback((form, submission) => {
|
|
40
36
|
var event = new CustomEvent('conform', {
|
|
41
37
|
detail: submission.intent
|
|
42
38
|
});
|
|
43
39
|
form.dispatchEvent(event);
|
|
44
40
|
setSubmission(submission);
|
|
45
41
|
}, []);
|
|
46
|
-
|
|
42
|
+
useEffect(() => {
|
|
47
43
|
var form = ref.current;
|
|
48
44
|
if (!form || !lastSubmission) {
|
|
49
45
|
return;
|
|
50
46
|
}
|
|
51
47
|
report(form, lastSubmission);
|
|
52
48
|
}, [ref, lastSubmission, report]);
|
|
53
|
-
|
|
49
|
+
useEffect(() => {
|
|
54
50
|
var form = ref.current;
|
|
55
51
|
if (!form || !submission) {
|
|
56
52
|
return;
|
|
@@ -60,30 +56,30 @@ function useFormReporter(ref, lastSubmission) {
|
|
|
60
56
|
return report;
|
|
61
57
|
}
|
|
62
58
|
function useFormError(ref, config) {
|
|
63
|
-
var [error, setError] =
|
|
59
|
+
var [error, setError] = useState(() => {
|
|
64
60
|
if (!config.initialError) {
|
|
65
61
|
return {};
|
|
66
62
|
}
|
|
67
63
|
var result = {};
|
|
68
64
|
for (var [name, message] of Object.entries(config.initialError)) {
|
|
69
|
-
var paths =
|
|
65
|
+
var paths = getPaths(name);
|
|
70
66
|
if (paths.length === 1) {
|
|
71
67
|
result[paths[0]] = normalizeError(message);
|
|
72
68
|
}
|
|
73
69
|
}
|
|
74
70
|
return result;
|
|
75
71
|
});
|
|
76
|
-
|
|
72
|
+
useEffect(() => {
|
|
77
73
|
var handleInvalid = event => {
|
|
78
|
-
var form =
|
|
74
|
+
var form = getFormElement(ref.current);
|
|
79
75
|
var element = event.target;
|
|
80
|
-
if (!
|
|
76
|
+
if (!isFieldElement(element) || element.form !== form || !element.dataset.conformTouched) {
|
|
81
77
|
return;
|
|
82
78
|
}
|
|
83
79
|
var key = element.name;
|
|
84
80
|
if (config.name) {
|
|
85
|
-
var scopePaths =
|
|
86
|
-
var fieldPaths =
|
|
81
|
+
var scopePaths = getPaths(config.name);
|
|
82
|
+
var fieldPaths = getPaths(element.name);
|
|
87
83
|
for (var i = 0; i <= scopePaths.length; i++) {
|
|
88
84
|
var path = fieldPaths[i];
|
|
89
85
|
if (i < scopePaths.length) {
|
|
@@ -97,17 +93,17 @@ function useFormError(ref, config) {
|
|
|
97
93
|
}
|
|
98
94
|
}
|
|
99
95
|
setError(prev => {
|
|
100
|
-
if (element.validationMessage ===
|
|
96
|
+
if (element.validationMessage === getValidationMessage(prev[key])) {
|
|
101
97
|
return prev;
|
|
102
98
|
}
|
|
103
|
-
return
|
|
104
|
-
[key]:
|
|
99
|
+
return _objectSpread2(_objectSpread2({}, prev), {}, {
|
|
100
|
+
[key]: getErrors(element.validationMessage)
|
|
105
101
|
});
|
|
106
102
|
});
|
|
107
103
|
event.preventDefault();
|
|
108
104
|
};
|
|
109
105
|
var handleReset = event => {
|
|
110
|
-
var form =
|
|
106
|
+
var form = getFormElement(ref.current);
|
|
111
107
|
if (form && event.target === form) {
|
|
112
108
|
setError({});
|
|
113
109
|
}
|
|
@@ -135,16 +131,17 @@ function useForm() {
|
|
|
135
131
|
var ref = useFormRef(config.ref);
|
|
136
132
|
var noValidate = useNoValidate(config.noValidate, config.fallbackNative);
|
|
137
133
|
var report = useFormReporter(ref, config.lastSubmission);
|
|
138
|
-
var [errors, setErrors] =
|
|
134
|
+
var [errors, setErrors] = useState(() => {
|
|
139
135
|
var _config$lastSubmissio;
|
|
140
136
|
return normalizeError((_config$lastSubmissio = config.lastSubmission) === null || _config$lastSubmissio === void 0 ? void 0 : _config$lastSubmissio.error['']);
|
|
141
137
|
});
|
|
142
|
-
var initialError =
|
|
138
|
+
var initialError = useMemo(() => {
|
|
143
139
|
var submission = config.lastSubmission;
|
|
144
140
|
if (!submission) {
|
|
145
141
|
return {};
|
|
146
142
|
}
|
|
147
|
-
var
|
|
143
|
+
var intent = parseIntent(submission.intent);
|
|
144
|
+
var scope = getScope(intent);
|
|
148
145
|
return scope === null ? submission.error : {
|
|
149
146
|
[scope]: submission.error[scope]
|
|
150
147
|
};
|
|
@@ -155,7 +152,7 @@ function useForm() {
|
|
|
155
152
|
constraint: config.constraint,
|
|
156
153
|
form: config.id
|
|
157
154
|
});
|
|
158
|
-
|
|
155
|
+
useEffect(() => {
|
|
159
156
|
// custom validate handler
|
|
160
157
|
var createValidateHandler = name => event => {
|
|
161
158
|
var field = event.target;
|
|
@@ -165,22 +162,22 @@ function useForm() {
|
|
|
165
162
|
shouldValidate = initialReport === 'onChange' ? 'onInput' : initialReport,
|
|
166
163
|
shouldRevalidate = 'onInput'
|
|
167
164
|
} = configRef.current;
|
|
168
|
-
if (!form || !
|
|
165
|
+
if (!form || !isFocusableFormControl(field) || field.form !== form || !field.name) {
|
|
169
166
|
return;
|
|
170
167
|
}
|
|
171
168
|
if (field.dataset.conformTouched ? shouldRevalidate === name : shouldValidate === name) {
|
|
172
|
-
|
|
169
|
+
requestIntent(form, validate(field.name));
|
|
173
170
|
}
|
|
174
171
|
};
|
|
175
172
|
var handleInvalid = event => {
|
|
176
173
|
var form = ref.current;
|
|
177
174
|
var field = event.target;
|
|
178
|
-
if (!form || !
|
|
175
|
+
if (!form || !isFieldElement(field) || field.form !== form || field.name !== FORM_ERROR_ELEMENT_NAME) {
|
|
179
176
|
return;
|
|
180
177
|
}
|
|
181
178
|
event.preventDefault();
|
|
182
179
|
if (field.dataset.conformTouched) {
|
|
183
|
-
setErrors(
|
|
180
|
+
setErrors(getErrors(field.validationMessage));
|
|
184
181
|
}
|
|
185
182
|
};
|
|
186
183
|
var handleReset = event => {
|
|
@@ -190,7 +187,7 @@ function useForm() {
|
|
|
190
187
|
}
|
|
191
188
|
|
|
192
189
|
// Reset all field state
|
|
193
|
-
for (var element of
|
|
190
|
+
for (var element of getFormControls(form)) {
|
|
194
191
|
delete element.dataset.conformTouched;
|
|
195
192
|
element.setCustomValidity('');
|
|
196
193
|
}
|
|
@@ -225,20 +222,35 @@ function useForm() {
|
|
|
225
222
|
}
|
|
226
223
|
try {
|
|
227
224
|
var _config$onValidate, _config$onValidate2;
|
|
228
|
-
var formData =
|
|
225
|
+
var formData = getFormData(form, submitter);
|
|
229
226
|
var submission = (_config$onValidate = (_config$onValidate2 = config.onValidate) === null || _config$onValidate2 === void 0 ? void 0 : _config$onValidate2.call(config, {
|
|
230
227
|
form,
|
|
231
228
|
formData
|
|
232
|
-
})) !== null && _config$onValidate !== void 0 ? _config$onValidate :
|
|
233
|
-
var
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
},
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
229
|
+
})) !== null && _config$onValidate !== void 0 ? _config$onValidate : parse(formData);
|
|
230
|
+
var {
|
|
231
|
+
errors: _errors,
|
|
232
|
+
shouldServerValidate
|
|
233
|
+
} = Object.entries(submission.error).reduce((result, _ref2) => {
|
|
234
|
+
var [, error] = _ref2;
|
|
235
|
+
for (var message of normalizeError(error)) {
|
|
236
|
+
if (message === VALIDATION_UNDEFINED) {
|
|
237
|
+
result.shouldServerValidate = true;
|
|
238
|
+
} else if (message !== VALIDATION_SKIPPED) {
|
|
239
|
+
result.errors.push(message);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
return result;
|
|
243
|
+
}, {
|
|
244
|
+
errors: [],
|
|
245
|
+
shouldServerValidate: false
|
|
246
|
+
});
|
|
247
|
+
if (
|
|
248
|
+
// has client validation
|
|
249
|
+
typeof config.onValidate !== 'undefined' &&
|
|
250
|
+
// not necessary to validate on the server
|
|
251
|
+
!shouldServerValidate && (
|
|
252
|
+
// client validation failed or non submit intent
|
|
253
|
+
!config.noValidate && !(submitter !== null && submitter !== void 0 && submitter.formNoValidate) && _errors.length > 0 || parseIntent(submission.intent) !== null)) {
|
|
242
254
|
report(form, submission);
|
|
243
255
|
event.preventDefault();
|
|
244
256
|
} else {
|
|
@@ -246,9 +258,9 @@ function useForm() {
|
|
|
246
258
|
(_config$onSubmit = config.onSubmit) === null || _config$onSubmit === void 0 ? void 0 : _config$onSubmit.call(config, event, {
|
|
247
259
|
formData,
|
|
248
260
|
submission,
|
|
249
|
-
action:
|
|
250
|
-
encType:
|
|
251
|
-
method:
|
|
261
|
+
action: getFormAction(nativeEvent),
|
|
262
|
+
encType: getFormEncType(nativeEvent),
|
|
263
|
+
method: getFormMethod(nativeEvent)
|
|
252
264
|
});
|
|
253
265
|
}
|
|
254
266
|
} catch (e) {
|
|
@@ -295,13 +307,13 @@ function useFieldset(ref, config) {
|
|
|
295
307
|
var errors = error === null || error === void 0 ? void 0 : error[key];
|
|
296
308
|
var initialError = Object.entries((_fieldsetConfig$initi = fieldsetConfig.initialError) !== null && _fieldsetConfig$initi !== void 0 ? _fieldsetConfig$initi : {}).reduce((result, _ref3) => {
|
|
297
309
|
var [name, message] = _ref3;
|
|
298
|
-
var [field, ...paths] =
|
|
310
|
+
var [field, ...paths] = getPaths(name);
|
|
299
311
|
if (field === key) {
|
|
300
|
-
result[
|
|
312
|
+
result[getName(paths)] = message;
|
|
301
313
|
}
|
|
302
314
|
return result;
|
|
303
315
|
}, {});
|
|
304
|
-
var field =
|
|
316
|
+
var field = _objectSpread2(_objectSpread2({}, constraint), {}, {
|
|
305
317
|
name: fieldsetConfig.name ? "".concat(fieldsetConfig.name, ".").concat(key) : key,
|
|
306
318
|
// @ts-expect-error The FieldValue type might need a rework
|
|
307
319
|
defaultValue: (_fieldsetConfig$defau = fieldsetConfig.defaultValue) === null || _fieldsetConfig$defau === void 0 ? void 0 : _fieldsetConfig$defau[key],
|
|
@@ -331,37 +343,33 @@ function useFieldList(ref, config) {
|
|
|
331
343
|
initialError: config.initialError,
|
|
332
344
|
name: config.name
|
|
333
345
|
});
|
|
334
|
-
var [entries, setEntries] =
|
|
346
|
+
var [entries, setEntries] = useState(() => {
|
|
335
347
|
var _config$defaultValue;
|
|
336
348
|
return Object.entries((_config$defaultValue = config.defaultValue) !== null && _config$defaultValue !== void 0 ? _config$defaultValue : [undefined]);
|
|
337
349
|
});
|
|
338
|
-
|
|
350
|
+
useEffect(() => {
|
|
339
351
|
var conformHandler = event => {
|
|
340
|
-
var form =
|
|
352
|
+
var form = getFormElement(ref.current);
|
|
341
353
|
if (!form || event.target !== form) {
|
|
342
354
|
return;
|
|
343
355
|
}
|
|
344
|
-
var
|
|
345
|
-
if ((
|
|
346
|
-
// Ensure the scope of the listener are limited to specific field name
|
|
356
|
+
var intent = parseIntent(event.detail);
|
|
357
|
+
if ((intent === null || intent === void 0 ? void 0 : intent.type) !== 'list' || (intent === null || intent === void 0 ? void 0 : intent.payload.name) !== configRef.current.name) {
|
|
347
358
|
return;
|
|
348
359
|
}
|
|
349
360
|
setEntries(entries => {
|
|
350
|
-
|
|
361
|
+
var list = [...entries];
|
|
362
|
+
switch (intent.payload.operation) {
|
|
351
363
|
case 'append':
|
|
352
364
|
case 'prepend':
|
|
353
365
|
case 'replace':
|
|
354
|
-
return
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
command.payload.defaultValue]
|
|
359
|
-
})
|
|
366
|
+
return updateList(list, _objectSpread2(_objectSpread2({}, intent.payload), {}, {
|
|
367
|
+
defaultValue: [
|
|
368
|
+
// Generate a random key to avoid conflicts
|
|
369
|
+
crypto.getRandomValues(new Uint32Array(1))[0].toString(36), intent.payload.defaultValue]
|
|
360
370
|
}));
|
|
361
371
|
default:
|
|
362
|
-
|
|
363
|
-
return dom.updateList([...(entries !== null && entries !== void 0 ? entries : [])], command);
|
|
364
|
-
}
|
|
372
|
+
return updateList(list, intent.payload);
|
|
365
373
|
}
|
|
366
374
|
});
|
|
367
375
|
setError(error => {
|
|
@@ -371,28 +379,24 @@ function useFieldList(ref, config) {
|
|
|
371
379
|
errorList[key] = messages;
|
|
372
380
|
}
|
|
373
381
|
}
|
|
374
|
-
switch (
|
|
382
|
+
switch (intent.payload.operation) {
|
|
375
383
|
case 'append':
|
|
376
384
|
case 'prepend':
|
|
377
385
|
case 'replace':
|
|
378
|
-
errorList =
|
|
379
|
-
|
|
380
|
-
defaultValue: undefined
|
|
381
|
-
})
|
|
386
|
+
errorList = updateList(errorList, _objectSpread2(_objectSpread2({}, intent.payload), {}, {
|
|
387
|
+
defaultValue: undefined
|
|
382
388
|
}));
|
|
383
389
|
break;
|
|
384
390
|
default:
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
break;
|
|
388
|
-
}
|
|
391
|
+
errorList = updateList(errorList, intent.payload);
|
|
392
|
+
break;
|
|
389
393
|
}
|
|
390
394
|
return Object.assign({}, errorList);
|
|
391
395
|
});
|
|
392
396
|
};
|
|
393
397
|
var resetHandler = event => {
|
|
394
398
|
var _configRef$current$de;
|
|
395
|
-
var form =
|
|
399
|
+
var form = getFormElement(ref.current);
|
|
396
400
|
if (!form || event.target !== form) {
|
|
397
401
|
return;
|
|
398
402
|
}
|
|
@@ -414,9 +418,9 @@ function useFieldList(ref, config) {
|
|
|
414
418
|
var errors = error[index];
|
|
415
419
|
var initialError = Object.entries((_config$initialError = config.initialError) !== null && _config$initialError !== void 0 ? _config$initialError : {}).reduce((result, _ref5) => {
|
|
416
420
|
var [name, message] = _ref5;
|
|
417
|
-
var [field, ...paths] =
|
|
421
|
+
var [field, ...paths] = getPaths(name);
|
|
418
422
|
if (field === index) {
|
|
419
|
-
result[
|
|
423
|
+
result[getName(paths)] = message;
|
|
420
424
|
}
|
|
421
425
|
return result;
|
|
422
426
|
}, {});
|
|
@@ -433,7 +437,7 @@ function useFieldList(ref, config) {
|
|
|
433
437
|
fieldConfig.errorId = "".concat(fieldConfig.id, "-error");
|
|
434
438
|
fieldConfig.descriptionId = "".concat(fieldConfig.id, "-description");
|
|
435
439
|
}
|
|
436
|
-
return
|
|
440
|
+
return _objectSpread2({
|
|
437
441
|
key
|
|
438
442
|
}, fieldConfig);
|
|
439
443
|
});
|
|
@@ -472,13 +476,13 @@ function setNativeValue(element, value) {
|
|
|
472
476
|
* useLayoutEffect is client-only.
|
|
473
477
|
* This basically makes it a no-op on server
|
|
474
478
|
*/
|
|
475
|
-
var useSafeLayoutEffect = typeof document === 'undefined' ?
|
|
479
|
+
var useSafeLayoutEffect = typeof document === 'undefined' ? useEffect : useLayoutEffect;
|
|
476
480
|
function useInputEvent(options) {
|
|
477
|
-
var ref =
|
|
481
|
+
var ref = useRef(null);
|
|
478
482
|
var optionsRef = useConfigRef(options);
|
|
479
|
-
var changeDispatched =
|
|
480
|
-
var focusDispatched =
|
|
481
|
-
var blurDispatched =
|
|
483
|
+
var changeDispatched = useRef(false);
|
|
484
|
+
var focusDispatched = useRef(false);
|
|
485
|
+
var blurDispatched = useRef(false);
|
|
482
486
|
useSafeLayoutEffect(() => {
|
|
483
487
|
var getInputElement = () => {
|
|
484
488
|
var _optionsRef$current$g, _optionsRef$current, _optionsRef$current$g2;
|
|
@@ -529,7 +533,7 @@ function useInputEvent(options) {
|
|
|
529
533
|
document.removeEventListener('reset', resetHandler);
|
|
530
534
|
};
|
|
531
535
|
}, []);
|
|
532
|
-
var control =
|
|
536
|
+
var control = useMemo(() => {
|
|
533
537
|
var getInputElement = () => {
|
|
534
538
|
var _optionsRef$current$g3, _optionsRef$current4, _optionsRef$current4$;
|
|
535
539
|
return (_optionsRef$current$g3 = (_optionsRef$current4 = optionsRef.current) === null || _optionsRef$current4 === void 0 ? void 0 : (_optionsRef$current4$ = _optionsRef$current4.getElement) === null || _optionsRef$current4$ === void 0 ? void 0 : _optionsRef$current4$.call(_optionsRef$current4, ref.current)) !== null && _optionsRef$current$g3 !== void 0 ? _optionsRef$current$g3 : ref.current;
|
|
@@ -644,12 +648,12 @@ function validateConstraint(options) {
|
|
|
644
648
|
} = _ref6;
|
|
645
649
|
return defaultErrors;
|
|
646
650
|
};
|
|
647
|
-
return
|
|
651
|
+
return parse(formData, {
|
|
648
652
|
resolve(payload, intent) {
|
|
649
653
|
var error = {};
|
|
650
654
|
var constraintPattern = /^constraint[A-Z][^A-Z]*$/;
|
|
651
655
|
var _loop = function _loop(element) {
|
|
652
|
-
if (
|
|
656
|
+
if (isFieldElement(element)) {
|
|
653
657
|
var _options$acceptMultip, _options$acceptMultip2;
|
|
654
658
|
var name = element.name !== FORM_ERROR_ELEMENT_NAME ? element.name : '';
|
|
655
659
|
var constraint = Object.entries(element.dataset).reduce((result, _ref7) => {
|
|
@@ -722,8 +726,9 @@ function reportSubmission(form, submission) {
|
|
|
722
726
|
form.appendChild(button);
|
|
723
727
|
}
|
|
724
728
|
}
|
|
725
|
-
var
|
|
726
|
-
|
|
729
|
+
var intent = parseIntent(submission.intent);
|
|
730
|
+
var scope = getScope(intent);
|
|
731
|
+
for (var element of getFormControls(form)) {
|
|
727
732
|
var _elementName = element.name !== FORM_ERROR_ELEMENT_NAME ? element.name : '';
|
|
728
733
|
var messages = normalizeError(submission.error[_elementName]);
|
|
729
734
|
if (scope === null || scope === _elementName) {
|
|
@@ -733,34 +738,22 @@ function reportSubmission(form, submission) {
|
|
|
733
738
|
var invalidEvent = new Event('invalid', {
|
|
734
739
|
cancelable: true
|
|
735
740
|
});
|
|
736
|
-
element.setCustomValidity(
|
|
741
|
+
element.setCustomValidity(getValidationMessage(messages));
|
|
737
742
|
element.dispatchEvent(invalidEvent);
|
|
738
743
|
}
|
|
739
744
|
}
|
|
740
|
-
if (
|
|
741
|
-
|
|
742
|
-
dom.focusFormControl(form, scope);
|
|
743
|
-
} else {
|
|
744
|
-
dom.focusFirstInvalidControl(form);
|
|
745
|
-
}
|
|
745
|
+
if (!intent) {
|
|
746
|
+
focusFirstInvalidControl(form);
|
|
746
747
|
}
|
|
747
748
|
}
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
749
|
+
function getScope(intent) {
|
|
750
|
+
switch (intent === null || intent === void 0 ? void 0 : intent.type) {
|
|
751
|
+
case 'validate':
|
|
752
|
+
return intent.payload;
|
|
753
|
+
case 'list':
|
|
754
|
+
return intent.payload.name;
|
|
755
|
+
}
|
|
756
|
+
return null;
|
|
755
757
|
}
|
|
756
758
|
|
|
757
|
-
|
|
758
|
-
exports.VALIDATION_SKIPPED = VALIDATION_SKIPPED;
|
|
759
|
-
exports.VALIDATION_UNDEFINED = VALIDATION_UNDEFINED;
|
|
760
|
-
exports.isFocusedOnIntentButton = isFocusedOnIntentButton;
|
|
761
|
-
exports.reportSubmission = reportSubmission;
|
|
762
|
-
exports.useFieldList = useFieldList;
|
|
763
|
-
exports.useFieldset = useFieldset;
|
|
764
|
-
exports.useForm = useForm;
|
|
765
|
-
exports.useInputEvent = useInputEvent;
|
|
766
|
-
exports.validateConstraint = validateConstraint;
|
|
759
|
+
export { FORM_ERROR_ELEMENT_NAME, VALIDATION_SKIPPED, VALIDATION_UNDEFINED, getScope, reportSubmission, useFieldList, useFieldset, useForm, useInputEvent, validateConstraint };
|
package/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { type FieldsetConstraint, type Submission, parse, list, validate, requestIntent, isFieldElement, } from '@conform-to/dom';
|
|
2
|
-
export { type Fieldset, type FieldConfig, type FieldsetConfig, type FormConfig, useForm, useFieldset, useFieldList, useInputEvent, validateConstraint, } from './hooks';
|
|
3
|
-
export * as conform from './helpers';
|
|
2
|
+
export { type Fieldset, type FieldConfig, type FieldsetConfig, type FormConfig, useForm, useFieldset, useFieldList, useInputEvent, validateConstraint, } from './hooks.js';
|
|
3
|
+
export * as conform from './helpers.js';
|
package/index.js
CHANGED
|
@@ -1,4 +1,36 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var dom = require('@conform-to/dom');
|
|
6
|
+
var hooks = require('./hooks.js');
|
|
7
|
+
var helpers = require('./helpers.js');
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
Object.defineProperty(exports, 'isFieldElement', {
|
|
12
|
+
enumerable: true,
|
|
13
|
+
get: function () { return dom.isFieldElement; }
|
|
14
|
+
});
|
|
15
|
+
Object.defineProperty(exports, 'list', {
|
|
16
|
+
enumerable: true,
|
|
17
|
+
get: function () { return dom.list; }
|
|
18
|
+
});
|
|
19
|
+
Object.defineProperty(exports, 'parse', {
|
|
20
|
+
enumerable: true,
|
|
21
|
+
get: function () { return dom.parse; }
|
|
22
|
+
});
|
|
23
|
+
Object.defineProperty(exports, 'requestIntent', {
|
|
24
|
+
enumerable: true,
|
|
25
|
+
get: function () { return dom.requestIntent; }
|
|
26
|
+
});
|
|
27
|
+
Object.defineProperty(exports, 'validate', {
|
|
28
|
+
enumerable: true,
|
|
29
|
+
get: function () { return dom.validate; }
|
|
30
|
+
});
|
|
31
|
+
exports.useFieldList = hooks.useFieldList;
|
|
32
|
+
exports.useFieldset = hooks.useFieldset;
|
|
33
|
+
exports.useForm = hooks.useForm;
|
|
34
|
+
exports.useInputEvent = hooks.useInputEvent;
|
|
35
|
+
exports.validateConstraint = hooks.validateConstraint;
|
|
36
|
+
exports.conform = helpers;
|
package/index.mjs
ADDED
package/package.json
CHANGED
|
@@ -3,18 +3,17 @@
|
|
|
3
3
|
"description": "Conform view adapter for react",
|
|
4
4
|
"homepage": "https://conform.guide",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"version": "0.7.0-pre.
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
"module": "index.js",
|
|
6
|
+
"version": "0.7.0-pre.2",
|
|
7
|
+
"main": "index.js",
|
|
8
|
+
"module": "index.mjs",
|
|
10
9
|
"types": "index.d.ts",
|
|
11
10
|
"exports": {
|
|
12
11
|
".": {
|
|
13
12
|
"types": "./index.d.ts",
|
|
14
|
-
"module": "./index.
|
|
15
|
-
"import": "./index.
|
|
16
|
-
"require": "./index.
|
|
17
|
-
"default": "./index.
|
|
13
|
+
"module": "./index.mjs",
|
|
14
|
+
"import": "./index.mjs",
|
|
15
|
+
"require": "./index.js",
|
|
16
|
+
"default": "./index.mjs"
|
|
18
17
|
}
|
|
19
18
|
},
|
|
20
19
|
"repository": {
|
|
@@ -31,7 +30,7 @@
|
|
|
31
30
|
"url": "https://github.com/edmundhung/conform/issues"
|
|
32
31
|
},
|
|
33
32
|
"dependencies": {
|
|
34
|
-
"@conform-to/dom": "0.7.0-pre.
|
|
33
|
+
"@conform-to/dom": "0.7.0-pre.2"
|
|
35
34
|
},
|
|
36
35
|
"peerDependencies": {
|
|
37
36
|
"react": ">=16.8"
|
package/index.cjs
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
-
|
|
5
|
-
var dom = require('@conform-to/dom');
|
|
6
|
-
var hooks = require('./hooks.cjs');
|
|
7
|
-
var helpers = require('./helpers.cjs');
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
Object.defineProperty(exports, 'isFieldElement', {
|
|
12
|
-
enumerable: true,
|
|
13
|
-
get: function () { return dom.isFieldElement; }
|
|
14
|
-
});
|
|
15
|
-
Object.defineProperty(exports, 'list', {
|
|
16
|
-
enumerable: true,
|
|
17
|
-
get: function () { return dom.list; }
|
|
18
|
-
});
|
|
19
|
-
Object.defineProperty(exports, 'parse', {
|
|
20
|
-
enumerable: true,
|
|
21
|
-
get: function () { return dom.parse; }
|
|
22
|
-
});
|
|
23
|
-
Object.defineProperty(exports, 'requestIntent', {
|
|
24
|
-
enumerable: true,
|
|
25
|
-
get: function () { return dom.requestIntent; }
|
|
26
|
-
});
|
|
27
|
-
Object.defineProperty(exports, 'validate', {
|
|
28
|
-
enumerable: true,
|
|
29
|
-
get: function () { return dom.validate; }
|
|
30
|
-
});
|
|
31
|
-
exports.useFieldList = hooks.useFieldList;
|
|
32
|
-
exports.useFieldset = hooks.useFieldset;
|
|
33
|
-
exports.useForm = hooks.useForm;
|
|
34
|
-
exports.useInputEvent = hooks.useInputEvent;
|
|
35
|
-
exports.validateConstraint = hooks.validateConstraint;
|
|
36
|
-
exports.conform = helpers;
|