@conform-to/react 0.7.3 → 0.8.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 +7 -8
- package/helpers.d.ts +14 -10
- package/helpers.js +38 -26
- package/helpers.mjs +38 -27
- package/hooks.d.ts +9 -9
- package/hooks.js +58 -49
- package/hooks.mjs +57 -50
- package/index.d.ts +1 -1
- package/index.js +1 -0
- package/index.mjs +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -156,7 +156,7 @@ function LoginForm() {
|
|
|
156
156
|
|
|
157
157
|
### useFieldset
|
|
158
158
|
|
|
159
|
-
This hook enables you to work with [nested object](/docs/
|
|
159
|
+
This hook enables you to work with [nested object](/docs/complex-structures.md#nested-object) by monitoring the state of each nested field and prepraing the config required.
|
|
160
160
|
|
|
161
161
|
```tsx
|
|
162
162
|
import { useForm, useFieldset } from '@conform-to/react';
|
|
@@ -238,7 +238,7 @@ function ExampleForm() {
|
|
|
238
238
|
|
|
239
239
|
### useFieldList
|
|
240
240
|
|
|
241
|
-
This hook enables you to work with [array](/docs/
|
|
241
|
+
This hook enables you to work with [array](/docs/complex-structures.md#array) and support the [list](#list) intent button builder to modify a list. It can also be used with [useFieldset](#usefieldset) for [nested list](/docs/complex-structures.md#nested-list) at the same time.
|
|
242
242
|
|
|
243
243
|
```tsx
|
|
244
244
|
import { useForm, useFieldList, list } from '@conform-to/react';
|
|
@@ -373,7 +373,6 @@ function Example() {
|
|
|
373
373
|
<input
|
|
374
374
|
{...conform.input(title, {
|
|
375
375
|
type: 'text',
|
|
376
|
-
ariaAttributes: true,
|
|
377
376
|
})}
|
|
378
377
|
/>
|
|
379
378
|
</form>
|
|
@@ -385,7 +384,7 @@ function Example() {
|
|
|
385
384
|
|
|
386
385
|
### parse
|
|
387
386
|
|
|
388
|
-
It parses the formData based on the [naming convention](/docs/
|
|
387
|
+
It parses the formData based on the [naming convention](/docs/complex-structures.md#naming-convention) with the validation result from the resolver.
|
|
389
388
|
|
|
390
389
|
```tsx
|
|
391
390
|
import { parse } from '@conform-to/react';
|
|
@@ -393,16 +392,16 @@ import { parse } from '@conform-to/react';
|
|
|
393
392
|
const formData = new FormData();
|
|
394
393
|
const submission = parse(formData, {
|
|
395
394
|
resolve({ email, password }) {
|
|
396
|
-
const error: Record<string, string> = {};
|
|
395
|
+
const error: Record<string, string[]> = {};
|
|
397
396
|
|
|
398
397
|
if (typeof email !== 'string') {
|
|
399
|
-
error.email = 'Email is required';
|
|
398
|
+
error.email = ['Email is required'];
|
|
400
399
|
} else if (!/^[^@]+@[^@]+$/.test(email)) {
|
|
401
|
-
error.email = 'Email is invalid';
|
|
400
|
+
error.email = ['Email is invalid'];
|
|
402
401
|
}
|
|
403
402
|
|
|
404
403
|
if (typeof password !== 'string') {
|
|
405
|
-
error.password = 'Password is required';
|
|
404
|
+
error.password = ['Password is required'];
|
|
406
405
|
}
|
|
407
406
|
|
|
408
407
|
if (error.email || error.password) {
|
package/helpers.d.ts
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import { INTENT, VALIDATION_UNDEFINED, VALIDATION_SKIPPED } from '@conform-to/dom';
|
|
2
2
|
import type { FieldConfig, Primitive } from './hooks.js';
|
|
3
3
|
import type { CSSProperties, HTMLInputTypeAttribute } from 'react';
|
|
4
|
-
interface
|
|
4
|
+
interface FormElementProps {
|
|
5
5
|
id?: string;
|
|
6
6
|
name: string;
|
|
7
7
|
form?: string;
|
|
8
|
+
'aria-describedby'?: string;
|
|
9
|
+
'aria-invalid'?: boolean;
|
|
10
|
+
}
|
|
11
|
+
interface FormControlProps extends FormElementProps {
|
|
8
12
|
required?: boolean;
|
|
9
13
|
autoFocus?: boolean;
|
|
10
14
|
tabIndex?: number;
|
|
11
15
|
style?: CSSProperties;
|
|
12
|
-
'aria-describedby'?: string;
|
|
13
|
-
'aria-invalid'?: boolean;
|
|
14
16
|
'aria-hidden'?: boolean;
|
|
15
17
|
}
|
|
16
18
|
interface InputProps<Schema> extends FormControlProps {
|
|
@@ -36,14 +38,15 @@ interface TextareaProps extends FormControlProps {
|
|
|
36
38
|
defaultValue?: string;
|
|
37
39
|
}
|
|
38
40
|
type BaseOptions = {
|
|
39
|
-
ariaAttributes?:
|
|
40
|
-
hidden?: boolean;
|
|
41
|
-
} | {
|
|
42
|
-
ariaAttributes: true;
|
|
41
|
+
ariaAttributes?: true;
|
|
43
42
|
description?: boolean;
|
|
43
|
+
} | {
|
|
44
|
+
ariaAttributes: false;
|
|
45
|
+
};
|
|
46
|
+
type ControlOptions = BaseOptions & {
|
|
44
47
|
hidden?: boolean;
|
|
45
48
|
};
|
|
46
|
-
type InputOptions =
|
|
49
|
+
type InputOptions = ControlOptions & ({
|
|
47
50
|
type: 'checkbox' | 'radio';
|
|
48
51
|
value?: string;
|
|
49
52
|
} | {
|
|
@@ -59,6 +62,7 @@ export declare function input<Schema extends Primitive | unknown>(config: FieldC
|
|
|
59
62
|
export declare function input<Schema extends File | File[]>(config: FieldConfig<Schema>, options: InputOptions & {
|
|
60
63
|
type: 'file';
|
|
61
64
|
}): InputProps<Schema>;
|
|
62
|
-
export declare function select<Schema extends Primitive | Primitive[] | undefined | unknown>(config: FieldConfig<Schema>, options?:
|
|
63
|
-
export declare function textarea<Schema extends Primitive | undefined | unknown>(config: FieldConfig<Schema>, options?:
|
|
65
|
+
export declare function select<Schema extends Primitive | Primitive[] | undefined | unknown>(config: FieldConfig<Schema>, options?: ControlOptions): SelectProps;
|
|
66
|
+
export declare function textarea<Schema extends Primitive | undefined | unknown>(config: FieldConfig<Schema>, options?: ControlOptions): TextareaProps;
|
|
67
|
+
export declare function fieldset<Schema extends Record<string, unknown> | undefined | unknown>(config: FieldConfig<Schema>, options?: BaseOptions): FormControlProps;
|
|
64
68
|
export { INTENT, VALIDATION_UNDEFINED, VALIDATION_SKIPPED };
|
package/helpers.js
CHANGED
|
@@ -5,26 +5,10 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
5
5
|
var _rollupPluginBabelHelpers = require('./_virtual/_rollupPluginBabelHelpers.js');
|
|
6
6
|
var dom = require('@conform-to/dom');
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
form: config.form,
|
|
13
|
-
required: config.required,
|
|
14
|
-
autoFocus: config.initialError && Object.entries(config.initialError).length > 0 ? true : undefined
|
|
15
|
-
};
|
|
16
|
-
if (options !== null && options !== void 0 && options.ariaAttributes) {
|
|
17
|
-
var _config$error;
|
|
18
|
-
if (config.descriptionId && options !== null && options !== void 0 && options.description) {
|
|
19
|
-
props['aria-describedby'] = config.descriptionId;
|
|
20
|
-
}
|
|
21
|
-
if (config.errorId && (_config$error = config.error) !== null && _config$error !== void 0 && _config$error.length) {
|
|
22
|
-
props['aria-invalid'] = true;
|
|
23
|
-
props['aria-describedby'] = config.descriptionId && options !== null && options !== void 0 && options.description ? "".concat(config.errorId, " ").concat(config.descriptionId) : config.errorId;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
return _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, props), options !== null && options !== void 0 && options.hidden ? hiddenProps : {});
|
|
27
|
-
}
|
|
8
|
+
/**
|
|
9
|
+
* Cleanup `undefined` from the dervied props
|
|
10
|
+
* To minimize conflicts when merging with user defined props
|
|
11
|
+
*/
|
|
28
12
|
function cleanup(props) {
|
|
29
13
|
for (var key in props) {
|
|
30
14
|
if (props[key] === undefined) {
|
|
@@ -33,6 +17,32 @@ function cleanup(props) {
|
|
|
33
17
|
}
|
|
34
18
|
return props;
|
|
35
19
|
}
|
|
20
|
+
function getFormElementProps(config) {
|
|
21
|
+
var _options$ariaAttribut, _config$error, _config$error2;
|
|
22
|
+
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
23
|
+
var hasAriaAttributes = (_options$ariaAttribut = options.ariaAttributes) !== null && _options$ariaAttribut !== void 0 ? _options$ariaAttribut : true;
|
|
24
|
+
return cleanup({
|
|
25
|
+
id: config.id,
|
|
26
|
+
name: config.name,
|
|
27
|
+
form: config.form,
|
|
28
|
+
'aria-invalid': hasAriaAttributes && config.errorId && (_config$error = config.error) !== null && _config$error !== void 0 && _config$error.length ? true : undefined,
|
|
29
|
+
'aria-describedby': hasAriaAttributes ? [config.errorId && (_config$error2 = config.error) !== null && _config$error2 !== void 0 && _config$error2.length ? config.errorId : undefined, config.descriptionId && options.ariaAttributes !== false && options.description ? config.descriptionId : undefined].reduce((result, id) => {
|
|
30
|
+
if (!result) {
|
|
31
|
+
return id;
|
|
32
|
+
}
|
|
33
|
+
if (!id) {
|
|
34
|
+
return result;
|
|
35
|
+
}
|
|
36
|
+
return "".concat(result, " ").concat(id);
|
|
37
|
+
}) : undefined
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
function getFormControlProps(config, options) {
|
|
41
|
+
return cleanup(_rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, getFormElementProps(config, options)), {}, {
|
|
42
|
+
required: config.required,
|
|
43
|
+
autoFocus: config.initialError && Object.entries(config.initialError).length > 0 ? true : undefined
|
|
44
|
+
}, options !== null && options !== void 0 && options.hidden ? hiddenProps : undefined));
|
|
45
|
+
}
|
|
36
46
|
var hiddenProps = {
|
|
37
47
|
/**
|
|
38
48
|
* Style to make the input element visually hidden
|
|
@@ -74,19 +84,20 @@ function input(config) {
|
|
|
74
84
|
return cleanup(props);
|
|
75
85
|
}
|
|
76
86
|
function select(config, options) {
|
|
77
|
-
|
|
87
|
+
return cleanup(_rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, getFormControlProps(config, options)), {}, {
|
|
78
88
|
defaultValue: config.defaultValue,
|
|
79
89
|
multiple: config.multiple
|
|
80
|
-
});
|
|
81
|
-
return cleanup(props);
|
|
90
|
+
}));
|
|
82
91
|
}
|
|
83
92
|
function textarea(config, options) {
|
|
84
|
-
|
|
93
|
+
return cleanup(_rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, getFormControlProps(config, options)), {}, {
|
|
85
94
|
defaultValue: config.defaultValue,
|
|
86
95
|
minLength: config.minLength,
|
|
87
96
|
maxLength: config.maxLength
|
|
88
|
-
});
|
|
89
|
-
|
|
97
|
+
}));
|
|
98
|
+
}
|
|
99
|
+
function fieldset(config, options) {
|
|
100
|
+
return getFormElementProps(config, options);
|
|
90
101
|
}
|
|
91
102
|
|
|
92
103
|
Object.defineProperty(exports, 'INTENT', {
|
|
@@ -101,6 +112,7 @@ Object.defineProperty(exports, 'VALIDATION_UNDEFINED', {
|
|
|
101
112
|
enumerable: true,
|
|
102
113
|
get: function () { return dom.VALIDATION_UNDEFINED; }
|
|
103
114
|
});
|
|
115
|
+
exports.fieldset = fieldset;
|
|
104
116
|
exports.hiddenProps = hiddenProps;
|
|
105
117
|
exports.input = input;
|
|
106
118
|
exports.select = select;
|
package/helpers.mjs
CHANGED
|
@@ -1,26 +1,10 @@
|
|
|
1
1
|
import { objectSpread2 as _objectSpread2 } from './_virtual/_rollupPluginBabelHelpers.mjs';
|
|
2
2
|
export { INTENT, VALIDATION_SKIPPED, VALIDATION_UNDEFINED } from '@conform-to/dom';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
form: config.form,
|
|
9
|
-
required: config.required,
|
|
10
|
-
autoFocus: config.initialError && Object.entries(config.initialError).length > 0 ? true : undefined
|
|
11
|
-
};
|
|
12
|
-
if (options !== null && options !== void 0 && options.ariaAttributes) {
|
|
13
|
-
var _config$error;
|
|
14
|
-
if (config.descriptionId && options !== null && options !== void 0 && options.description) {
|
|
15
|
-
props['aria-describedby'] = config.descriptionId;
|
|
16
|
-
}
|
|
17
|
-
if (config.errorId && (_config$error = config.error) !== null && _config$error !== void 0 && _config$error.length) {
|
|
18
|
-
props['aria-invalid'] = true;
|
|
19
|
-
props['aria-describedby'] = config.descriptionId && options !== null && options !== void 0 && options.description ? "".concat(config.errorId, " ").concat(config.descriptionId) : config.errorId;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
return _objectSpread2(_objectSpread2({}, props), options !== null && options !== void 0 && options.hidden ? hiddenProps : {});
|
|
23
|
-
}
|
|
4
|
+
/**
|
|
5
|
+
* Cleanup `undefined` from the dervied props
|
|
6
|
+
* To minimize conflicts when merging with user defined props
|
|
7
|
+
*/
|
|
24
8
|
function cleanup(props) {
|
|
25
9
|
for (var key in props) {
|
|
26
10
|
if (props[key] === undefined) {
|
|
@@ -29,6 +13,32 @@ function cleanup(props) {
|
|
|
29
13
|
}
|
|
30
14
|
return props;
|
|
31
15
|
}
|
|
16
|
+
function getFormElementProps(config) {
|
|
17
|
+
var _options$ariaAttribut, _config$error, _config$error2;
|
|
18
|
+
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
19
|
+
var hasAriaAttributes = (_options$ariaAttribut = options.ariaAttributes) !== null && _options$ariaAttribut !== void 0 ? _options$ariaAttribut : true;
|
|
20
|
+
return cleanup({
|
|
21
|
+
id: config.id,
|
|
22
|
+
name: config.name,
|
|
23
|
+
form: config.form,
|
|
24
|
+
'aria-invalid': hasAriaAttributes && config.errorId && (_config$error = config.error) !== null && _config$error !== void 0 && _config$error.length ? true : undefined,
|
|
25
|
+
'aria-describedby': hasAriaAttributes ? [config.errorId && (_config$error2 = config.error) !== null && _config$error2 !== void 0 && _config$error2.length ? config.errorId : undefined, config.descriptionId && options.ariaAttributes !== false && options.description ? config.descriptionId : undefined].reduce((result, id) => {
|
|
26
|
+
if (!result) {
|
|
27
|
+
return id;
|
|
28
|
+
}
|
|
29
|
+
if (!id) {
|
|
30
|
+
return result;
|
|
31
|
+
}
|
|
32
|
+
return "".concat(result, " ").concat(id);
|
|
33
|
+
}) : undefined
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
function getFormControlProps(config, options) {
|
|
37
|
+
return cleanup(_objectSpread2(_objectSpread2({}, getFormElementProps(config, options)), {}, {
|
|
38
|
+
required: config.required,
|
|
39
|
+
autoFocus: config.initialError && Object.entries(config.initialError).length > 0 ? true : undefined
|
|
40
|
+
}, options !== null && options !== void 0 && options.hidden ? hiddenProps : undefined));
|
|
41
|
+
}
|
|
32
42
|
var hiddenProps = {
|
|
33
43
|
/**
|
|
34
44
|
* Style to make the input element visually hidden
|
|
@@ -70,19 +80,20 @@ function input(config) {
|
|
|
70
80
|
return cleanup(props);
|
|
71
81
|
}
|
|
72
82
|
function select(config, options) {
|
|
73
|
-
|
|
83
|
+
return cleanup(_objectSpread2(_objectSpread2({}, getFormControlProps(config, options)), {}, {
|
|
74
84
|
defaultValue: config.defaultValue,
|
|
75
85
|
multiple: config.multiple
|
|
76
|
-
});
|
|
77
|
-
return cleanup(props);
|
|
86
|
+
}));
|
|
78
87
|
}
|
|
79
88
|
function textarea(config, options) {
|
|
80
|
-
|
|
89
|
+
return cleanup(_objectSpread2(_objectSpread2({}, getFormControlProps(config, options)), {}, {
|
|
81
90
|
defaultValue: config.defaultValue,
|
|
82
91
|
minLength: config.minLength,
|
|
83
92
|
maxLength: config.maxLength
|
|
84
|
-
});
|
|
85
|
-
|
|
93
|
+
}));
|
|
94
|
+
}
|
|
95
|
+
function fieldset(config, options) {
|
|
96
|
+
return getFormElementProps(config, options);
|
|
86
97
|
}
|
|
87
98
|
|
|
88
|
-
export { hiddenProps, input, select, textarea };
|
|
99
|
+
export { fieldset, hiddenProps, input, select, textarea };
|
package/hooks.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export interface FieldConfig<Schema> extends FieldConstraint<Schema> {
|
|
|
5
5
|
id?: string;
|
|
6
6
|
name: string;
|
|
7
7
|
defaultValue?: FieldValue<Schema>;
|
|
8
|
-
initialError?: Record<string, string
|
|
8
|
+
initialError?: Record<string, string[]>;
|
|
9
9
|
form?: string;
|
|
10
10
|
descriptionId?: string;
|
|
11
11
|
errorId?: string;
|
|
@@ -26,6 +26,11 @@ type SubmissionResult = {
|
|
|
26
26
|
payload: Submission['payload'] | null;
|
|
27
27
|
error: Submission['error'];
|
|
28
28
|
};
|
|
29
|
+
interface ReportOptions {
|
|
30
|
+
formError?: string[];
|
|
31
|
+
resetForm?: boolean;
|
|
32
|
+
}
|
|
33
|
+
export declare function report(submission: Submission, options?: ReportOptions): SubmissionResult;
|
|
29
34
|
export interface FormConfig<Output extends Record<string, any>, Input extends Record<string, any> = Output> {
|
|
30
35
|
/**
|
|
31
36
|
* If the form id is provided, Id for label,
|
|
@@ -107,7 +112,7 @@ interface FormProps {
|
|
|
107
112
|
interface Form {
|
|
108
113
|
id?: string;
|
|
109
114
|
errorId?: string;
|
|
110
|
-
error: string;
|
|
115
|
+
error: string | undefined;
|
|
111
116
|
errors: string[];
|
|
112
117
|
ref: RefObject<HTMLFormElement>;
|
|
113
118
|
props: FormProps;
|
|
@@ -137,7 +142,7 @@ export interface FieldsetConfig<Schema extends Record<string, any> | undefined>
|
|
|
137
142
|
/**
|
|
138
143
|
* An object describing the initial error of each field
|
|
139
144
|
*/
|
|
140
|
-
initialError?: Record<string, string
|
|
145
|
+
initialError?: Record<string, string[]>;
|
|
141
146
|
/**
|
|
142
147
|
* An object describing the constraint of each field
|
|
143
148
|
*/
|
|
@@ -171,7 +176,6 @@ interface InputControl {
|
|
|
171
176
|
focus: () => void;
|
|
172
177
|
blur: () => void;
|
|
173
178
|
}
|
|
174
|
-
export declare function useEventListeners(type: string, ref: RefObject<FieldElement>): void;
|
|
175
179
|
/**
|
|
176
180
|
* Returns a ref object and a set of helpers that dispatch corresponding dom event.
|
|
177
181
|
*
|
|
@@ -196,11 +200,6 @@ export declare function validateConstraint(options: {
|
|
|
196
200
|
formData: FormData;
|
|
197
201
|
attributeValue: string;
|
|
198
202
|
}) => boolean>;
|
|
199
|
-
acceptMultipleErrors?: ({ name, intent, payload, }: {
|
|
200
|
-
name: string;
|
|
201
|
-
intent: string;
|
|
202
|
-
payload: Record<string, any>;
|
|
203
|
-
}) => boolean;
|
|
204
203
|
formatMessages?: ({ name, validity, constraint, defaultErrors, }: {
|
|
205
204
|
name: string;
|
|
206
205
|
validity: ValidityState;
|
|
@@ -208,6 +207,7 @@ export declare function validateConstraint(options: {
|
|
|
208
207
|
defaultErrors: string[];
|
|
209
208
|
}) => string[];
|
|
210
209
|
}): Submission;
|
|
210
|
+
export declare function getUniqueKey(): string;
|
|
211
211
|
export declare function reportSubmission(form: HTMLFormElement, submission: SubmissionResult): void;
|
|
212
212
|
export declare function getScope(intent: ReturnType<typeof parseIntent>): string | null;
|
|
213
213
|
export {};
|
package/hooks.js
CHANGED
|
@@ -6,16 +6,21 @@ var _rollupPluginBabelHelpers = require('./_virtual/_rollupPluginBabelHelpers.js
|
|
|
6
6
|
var dom = require('@conform-to/dom');
|
|
7
7
|
var react = require('react');
|
|
8
8
|
|
|
9
|
+
function report(submission, options) {
|
|
10
|
+
var _submission$error$;
|
|
11
|
+
return {
|
|
12
|
+
intent: submission.intent,
|
|
13
|
+
payload: options !== null && options !== void 0 && options.resetForm ? null : submission.payload,
|
|
14
|
+
error: options !== null && options !== void 0 && options.formError ? _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, submission.error), {}, {
|
|
15
|
+
'': options.formError.concat((_submission$error$ = submission.error['']) !== null && _submission$error$ !== void 0 ? _submission$error$ : [])
|
|
16
|
+
}) : submission.error
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
9
20
|
/**
|
|
10
|
-
*
|
|
21
|
+
* Properties to be applied to the form element
|
|
11
22
|
*/
|
|
12
|
-
|
|
13
|
-
if (!error) {
|
|
14
|
-
// This treat both empty string and undefined as no error.
|
|
15
|
-
return [];
|
|
16
|
-
}
|
|
17
|
-
return [].concat(error);
|
|
18
|
-
}
|
|
23
|
+
|
|
19
24
|
function useNoValidate(defaultNoValidate, validateBeforeHydrate) {
|
|
20
25
|
var [noValidate, setNoValidate] = react.useState(defaultNoValidate || !validateBeforeHydrate);
|
|
21
26
|
react.useEffect(() => {
|
|
@@ -74,42 +79,33 @@ function useFormError(ref, config) {
|
|
|
74
79
|
}
|
|
75
80
|
var result = {};
|
|
76
81
|
for (var [name, message] of Object.entries(config.initialError)) {
|
|
77
|
-
var
|
|
78
|
-
if (
|
|
79
|
-
result[
|
|
82
|
+
var [path, ...restPaths] = dom.getPaths(name);
|
|
83
|
+
if (typeof path !== 'undefined' && restPaths.length === 0) {
|
|
84
|
+
result[path] = message;
|
|
80
85
|
}
|
|
81
86
|
}
|
|
82
87
|
return result;
|
|
83
88
|
});
|
|
84
89
|
react.useEffect(() => {
|
|
85
90
|
var handleInvalid = event => {
|
|
91
|
+
var _config$name;
|
|
86
92
|
var form = dom.getFormElement(ref.current);
|
|
87
93
|
var element = event.target;
|
|
88
|
-
|
|
94
|
+
var prefix = (_config$name = config.name) !== null && _config$name !== void 0 ? _config$name : '';
|
|
95
|
+
if (!dom.isFieldElement(element) || element.form !== form || !element.name.startsWith(prefix) || !element.dataset.conformTouched) {
|
|
89
96
|
return;
|
|
90
97
|
}
|
|
91
|
-
var
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
for (var i = 0; i <= scopePaths.length; i++) {
|
|
96
|
-
var path = fieldPaths[i];
|
|
97
|
-
if (i < scopePaths.length) {
|
|
98
|
-
// Skip if the field is not in the scope
|
|
99
|
-
if (path !== scopePaths[i]) {
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
} else {
|
|
103
|
-
key = path;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
98
|
+
var name = element.name.slice(prefix.length);
|
|
99
|
+
var [path, ...restPaths] = dom.getPaths(name);
|
|
100
|
+
if (typeof path === 'undefined' || restPaths.length > 0) {
|
|
101
|
+
return;
|
|
106
102
|
}
|
|
107
103
|
setError(prev => {
|
|
108
|
-
if (element.validationMessage === dom.getValidationMessage(prev[
|
|
104
|
+
if (element.validationMessage === dom.getValidationMessage(prev[path])) {
|
|
109
105
|
return prev;
|
|
110
106
|
}
|
|
111
107
|
return _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, prev), {}, {
|
|
112
|
-
[
|
|
108
|
+
[path]: dom.getErrors(element.validationMessage)
|
|
113
109
|
});
|
|
114
110
|
});
|
|
115
111
|
event.preventDefault();
|
|
@@ -137,31 +133,35 @@ function useFormError(ref, config) {
|
|
|
137
133
|
* @see https://conform.guide/api/react#useform
|
|
138
134
|
*/
|
|
139
135
|
function useForm() {
|
|
140
|
-
var _config$
|
|
136
|
+
var _config$lastSubmissio3, _config$lastSubmissio4;
|
|
141
137
|
var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
142
138
|
var configRef = useConfigRef(config);
|
|
143
139
|
var ref = useFormRef(config.ref);
|
|
144
140
|
var noValidate = useNoValidate(config.noValidate, config.fallbackNative);
|
|
145
141
|
var report = useFormReporter(ref, config.lastSubmission);
|
|
146
142
|
var [errors, setErrors] = react.useState(() => {
|
|
147
|
-
var _config$lastSubmissio;
|
|
148
|
-
return
|
|
143
|
+
var _config$lastSubmissio, _config$lastSubmissio2;
|
|
144
|
+
return (_config$lastSubmissio = (_config$lastSubmissio2 = config.lastSubmission) === null || _config$lastSubmissio2 === void 0 ? void 0 : _config$lastSubmissio2.error['']) !== null && _config$lastSubmissio !== void 0 ? _config$lastSubmissio : [];
|
|
149
145
|
});
|
|
150
146
|
var initialError = react.useMemo(() => {
|
|
147
|
+
var _submission$error$sco;
|
|
151
148
|
var submission = config.lastSubmission;
|
|
152
149
|
if (!submission) {
|
|
153
150
|
return {};
|
|
154
151
|
}
|
|
155
152
|
var intent = dom.parseIntent(submission.intent);
|
|
156
153
|
var scope = getScope(intent);
|
|
157
|
-
|
|
158
|
-
|
|
154
|
+
if (typeof scope !== 'string') {
|
|
155
|
+
return submission.error;
|
|
156
|
+
}
|
|
157
|
+
return {
|
|
158
|
+
[scope]: (_submission$error$sco = submission.error[scope]) !== null && _submission$error$sco !== void 0 ? _submission$error$sco : []
|
|
159
159
|
};
|
|
160
160
|
}, [config.lastSubmission]);
|
|
161
161
|
// This payload from lastSubmission is only useful before hydration
|
|
162
162
|
// After hydration, any new payload on lastSubmission will be ignored
|
|
163
163
|
var [defaultValueFromLastSubmission, setDefaultValueFromLastSubmission] = react.useState( // @ts-expect-error defaultValue is not in Submission type
|
|
164
|
-
(_config$
|
|
164
|
+
(_config$lastSubmissio3 = (_config$lastSubmissio4 = config.lastSubmission) === null || _config$lastSubmissio4 === void 0 ? void 0 : _config$lastSubmissio4.payload) !== null && _config$lastSubmissio3 !== void 0 ? _config$lastSubmissio3 : null);
|
|
165
165
|
var fieldset = useFieldset(ref, {
|
|
166
166
|
defaultValue: defaultValueFromLastSubmission !== null && defaultValueFromLastSubmission !== void 0 ? defaultValueFromLastSubmission : config.defaultValue,
|
|
167
167
|
initialError,
|
|
@@ -248,7 +248,7 @@ function useForm() {
|
|
|
248
248
|
shouldServerValidate
|
|
249
249
|
} = Object.entries(submission.error).reduce((result, _ref) => {
|
|
250
250
|
var [, error] = _ref;
|
|
251
|
-
for (var message of
|
|
251
|
+
for (var message of error) {
|
|
252
252
|
if (message === dom.VALIDATION_UNDEFINED) {
|
|
253
253
|
result.shouldServerValidate = true;
|
|
254
254
|
} else if (message !== dom.VALIDATION_SKIPPED) {
|
|
@@ -302,6 +302,12 @@ function useForm() {
|
|
|
302
302
|
* A set of field configuration
|
|
303
303
|
*/
|
|
304
304
|
|
|
305
|
+
/**
|
|
306
|
+
* Returns all the information about the fieldset.
|
|
307
|
+
*
|
|
308
|
+
* @see https://conform.guide/api/react#usefieldset
|
|
309
|
+
*/
|
|
310
|
+
|
|
305
311
|
function useFieldset(ref, config) {
|
|
306
312
|
var [error] = useFormError(ref, {
|
|
307
313
|
initialError: config.initialError,
|
|
@@ -383,7 +389,7 @@ function useFieldList(ref, config) {
|
|
|
383
389
|
return dom.updateList(list, _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, intent.payload), {}, {
|
|
384
390
|
defaultValue: [
|
|
385
391
|
// Generate a random key to avoid conflicts
|
|
386
|
-
|
|
392
|
+
getUniqueKey(), intent.payload.defaultValue]
|
|
387
393
|
}));
|
|
388
394
|
default:
|
|
389
395
|
return dom.updateList(list, intent.payload);
|
|
@@ -465,7 +471,6 @@ function useFieldList(ref, config) {
|
|
|
465
471
|
* This basically makes it a no-op on server
|
|
466
472
|
*/
|
|
467
473
|
var useSafeLayoutEffect = typeof document === 'undefined' ? react.useEffect : react.useLayoutEffect;
|
|
468
|
-
|
|
469
474
|
/**
|
|
470
475
|
* Returns a ref object and a set of helpers that dispatch corresponding dom event.
|
|
471
476
|
*
|
|
@@ -488,7 +493,7 @@ function useInputEvent(options) {
|
|
|
488
493
|
if (listener !== 'onReset') {
|
|
489
494
|
eventDispatched.current[listener] = true;
|
|
490
495
|
}
|
|
491
|
-
(_optionsRef$current4 = optionsRef.current) === null || _optionsRef$current4 === void 0
|
|
496
|
+
(_optionsRef$current4 = optionsRef.current) === null || _optionsRef$current4 === void 0 || (_optionsRef$current4$ = _optionsRef$current4[listener]) === null || _optionsRef$current4$ === void 0 ? void 0 : _optionsRef$current4$.call(_optionsRef$current4, event);
|
|
492
497
|
}
|
|
493
498
|
};
|
|
494
499
|
};
|
|
@@ -631,12 +636,11 @@ function validateConstraint(options) {
|
|
|
631
636
|
return defaultErrors;
|
|
632
637
|
};
|
|
633
638
|
return dom.parse(formData, {
|
|
634
|
-
resolve(
|
|
639
|
+
resolve() {
|
|
635
640
|
var error = {};
|
|
636
641
|
var constraintPattern = /^constraint[A-Z][^A-Z]*$/;
|
|
637
642
|
var _loop = function _loop(_element3) {
|
|
638
643
|
if (dom.isFieldElement(_element3)) {
|
|
639
|
-
var _options$acceptMultip, _options$acceptMultip2;
|
|
640
644
|
var name = _element3.name !== FORM_ERROR_ELEMENT_NAME ? _element3.name : '';
|
|
641
645
|
var constraint = Object.entries(_element3.dataset).reduce((result, _ref6) => {
|
|
642
646
|
var [name, attributeValue = ''] = _ref6;
|
|
@@ -662,13 +666,8 @@ function validateConstraint(options) {
|
|
|
662
666
|
constraint,
|
|
663
667
|
defaultErrors: getDefaultErrors(_element3.validity, constraint)
|
|
664
668
|
});
|
|
665
|
-
var shouldAcceptMultipleErrors = (_options$acceptMultip = options === null || options === void 0 ? void 0 : (_options$acceptMultip2 = options.acceptMultipleErrors) === null || _options$acceptMultip2 === void 0 ? void 0 : _options$acceptMultip2.call(options, {
|
|
666
|
-
name,
|
|
667
|
-
payload,
|
|
668
|
-
intent
|
|
669
|
-
})) !== null && _options$acceptMultip !== void 0 ? _options$acceptMultip : false;
|
|
670
669
|
if (errors.length > 0) {
|
|
671
|
-
error[name] =
|
|
670
|
+
error[name] = errors;
|
|
672
671
|
}
|
|
673
672
|
}
|
|
674
673
|
};
|
|
@@ -681,10 +680,17 @@ function validateConstraint(options) {
|
|
|
681
680
|
}
|
|
682
681
|
});
|
|
683
682
|
}
|
|
683
|
+
function getUniqueKey() {
|
|
684
|
+
var [value] = crypto.getRandomValues(new Uint32Array(1));
|
|
685
|
+
if (!value) {
|
|
686
|
+
throw new Error('Fail to generate an unique key');
|
|
687
|
+
}
|
|
688
|
+
return value.toString(36);
|
|
689
|
+
}
|
|
684
690
|
function reportSubmission(form, submission) {
|
|
685
691
|
for (var [name, message] of Object.entries(submission.error)) {
|
|
686
692
|
// There is no need to create a placeholder button if all we want is to reset the error
|
|
687
|
-
if (message ===
|
|
693
|
+
if (message.length === 0) {
|
|
688
694
|
continue;
|
|
689
695
|
}
|
|
690
696
|
|
|
@@ -713,8 +719,9 @@ function reportSubmission(form, submission) {
|
|
|
713
719
|
var intent = dom.parseIntent(submission.intent);
|
|
714
720
|
var scope = getScope(intent);
|
|
715
721
|
for (var _element4 of dom.getFormControls(form)) {
|
|
722
|
+
var _submission$error$_el;
|
|
716
723
|
var _elementName = _element4.name !== FORM_ERROR_ELEMENT_NAME ? _element4.name : '';
|
|
717
|
-
var messages =
|
|
724
|
+
var messages = (_submission$error$_el = submission.error[_elementName]) !== null && _submission$error$_el !== void 0 ? _submission$error$_el : [];
|
|
718
725
|
if (scope === null || scope === _elementName) {
|
|
719
726
|
_element4.dataset.conformTouched = 'true';
|
|
720
727
|
}
|
|
@@ -742,6 +749,8 @@ function getScope(intent) {
|
|
|
742
749
|
|
|
743
750
|
exports.FORM_ERROR_ELEMENT_NAME = FORM_ERROR_ELEMENT_NAME;
|
|
744
751
|
exports.getScope = getScope;
|
|
752
|
+
exports.getUniqueKey = getUniqueKey;
|
|
753
|
+
exports.report = report;
|
|
745
754
|
exports.reportSubmission = reportSubmission;
|
|
746
755
|
exports.useFieldList = useFieldList;
|
|
747
756
|
exports.useFieldset = useFieldset;
|
package/hooks.mjs
CHANGED
|
@@ -2,16 +2,21 @@ import { objectSpread2 as _objectSpread2 } from './_virtual/_rollupPluginBabelHe
|
|
|
2
2
|
import { parseIntent, getFormData, parse, VALIDATION_UNDEFINED, VALIDATION_SKIPPED, getFormAction, getFormEncType, getFormMethod, getPaths, getName, isFieldElement, getErrors, getFormControls, getFormElement, updateList, getValidationMessage, focusFirstInvalidControl, isFocusableFormControl, requestIntent, validate } from '@conform-to/dom';
|
|
3
3
|
import { useState, useMemo, useEffect, useRef, useCallback, useLayoutEffect } from 'react';
|
|
4
4
|
|
|
5
|
+
function report(submission, options) {
|
|
6
|
+
var _submission$error$;
|
|
7
|
+
return {
|
|
8
|
+
intent: submission.intent,
|
|
9
|
+
payload: options !== null && options !== void 0 && options.resetForm ? null : submission.payload,
|
|
10
|
+
error: options !== null && options !== void 0 && options.formError ? _objectSpread2(_objectSpread2({}, submission.error), {}, {
|
|
11
|
+
'': options.formError.concat((_submission$error$ = submission.error['']) !== null && _submission$error$ !== void 0 ? _submission$error$ : [])
|
|
12
|
+
}) : submission.error
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
5
16
|
/**
|
|
6
|
-
*
|
|
17
|
+
* Properties to be applied to the form element
|
|
7
18
|
*/
|
|
8
|
-
|
|
9
|
-
if (!error) {
|
|
10
|
-
// This treat both empty string and undefined as no error.
|
|
11
|
-
return [];
|
|
12
|
-
}
|
|
13
|
-
return [].concat(error);
|
|
14
|
-
}
|
|
19
|
+
|
|
15
20
|
function useNoValidate(defaultNoValidate, validateBeforeHydrate) {
|
|
16
21
|
var [noValidate, setNoValidate] = useState(defaultNoValidate || !validateBeforeHydrate);
|
|
17
22
|
useEffect(() => {
|
|
@@ -70,42 +75,33 @@ function useFormError(ref, config) {
|
|
|
70
75
|
}
|
|
71
76
|
var result = {};
|
|
72
77
|
for (var [name, message] of Object.entries(config.initialError)) {
|
|
73
|
-
var
|
|
74
|
-
if (
|
|
75
|
-
result[
|
|
78
|
+
var [path, ...restPaths] = getPaths(name);
|
|
79
|
+
if (typeof path !== 'undefined' && restPaths.length === 0) {
|
|
80
|
+
result[path] = message;
|
|
76
81
|
}
|
|
77
82
|
}
|
|
78
83
|
return result;
|
|
79
84
|
});
|
|
80
85
|
useEffect(() => {
|
|
81
86
|
var handleInvalid = event => {
|
|
87
|
+
var _config$name;
|
|
82
88
|
var form = getFormElement(ref.current);
|
|
83
89
|
var element = event.target;
|
|
84
|
-
|
|
90
|
+
var prefix = (_config$name = config.name) !== null && _config$name !== void 0 ? _config$name : '';
|
|
91
|
+
if (!isFieldElement(element) || element.form !== form || !element.name.startsWith(prefix) || !element.dataset.conformTouched) {
|
|
85
92
|
return;
|
|
86
93
|
}
|
|
87
|
-
var
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
for (var i = 0; i <= scopePaths.length; i++) {
|
|
92
|
-
var path = fieldPaths[i];
|
|
93
|
-
if (i < scopePaths.length) {
|
|
94
|
-
// Skip if the field is not in the scope
|
|
95
|
-
if (path !== scopePaths[i]) {
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
} else {
|
|
99
|
-
key = path;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
94
|
+
var name = element.name.slice(prefix.length);
|
|
95
|
+
var [path, ...restPaths] = getPaths(name);
|
|
96
|
+
if (typeof path === 'undefined' || restPaths.length > 0) {
|
|
97
|
+
return;
|
|
102
98
|
}
|
|
103
99
|
setError(prev => {
|
|
104
|
-
if (element.validationMessage === getValidationMessage(prev[
|
|
100
|
+
if (element.validationMessage === getValidationMessage(prev[path])) {
|
|
105
101
|
return prev;
|
|
106
102
|
}
|
|
107
103
|
return _objectSpread2(_objectSpread2({}, prev), {}, {
|
|
108
|
-
[
|
|
104
|
+
[path]: getErrors(element.validationMessage)
|
|
109
105
|
});
|
|
110
106
|
});
|
|
111
107
|
event.preventDefault();
|
|
@@ -133,31 +129,35 @@ function useFormError(ref, config) {
|
|
|
133
129
|
* @see https://conform.guide/api/react#useform
|
|
134
130
|
*/
|
|
135
131
|
function useForm() {
|
|
136
|
-
var _config$
|
|
132
|
+
var _config$lastSubmissio3, _config$lastSubmissio4;
|
|
137
133
|
var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
138
134
|
var configRef = useConfigRef(config);
|
|
139
135
|
var ref = useFormRef(config.ref);
|
|
140
136
|
var noValidate = useNoValidate(config.noValidate, config.fallbackNative);
|
|
141
137
|
var report = useFormReporter(ref, config.lastSubmission);
|
|
142
138
|
var [errors, setErrors] = useState(() => {
|
|
143
|
-
var _config$lastSubmissio;
|
|
144
|
-
return
|
|
139
|
+
var _config$lastSubmissio, _config$lastSubmissio2;
|
|
140
|
+
return (_config$lastSubmissio = (_config$lastSubmissio2 = config.lastSubmission) === null || _config$lastSubmissio2 === void 0 ? void 0 : _config$lastSubmissio2.error['']) !== null && _config$lastSubmissio !== void 0 ? _config$lastSubmissio : [];
|
|
145
141
|
});
|
|
146
142
|
var initialError = useMemo(() => {
|
|
143
|
+
var _submission$error$sco;
|
|
147
144
|
var submission = config.lastSubmission;
|
|
148
145
|
if (!submission) {
|
|
149
146
|
return {};
|
|
150
147
|
}
|
|
151
148
|
var intent = parseIntent(submission.intent);
|
|
152
149
|
var scope = getScope(intent);
|
|
153
|
-
|
|
154
|
-
|
|
150
|
+
if (typeof scope !== 'string') {
|
|
151
|
+
return submission.error;
|
|
152
|
+
}
|
|
153
|
+
return {
|
|
154
|
+
[scope]: (_submission$error$sco = submission.error[scope]) !== null && _submission$error$sco !== void 0 ? _submission$error$sco : []
|
|
155
155
|
};
|
|
156
156
|
}, [config.lastSubmission]);
|
|
157
157
|
// This payload from lastSubmission is only useful before hydration
|
|
158
158
|
// After hydration, any new payload on lastSubmission will be ignored
|
|
159
159
|
var [defaultValueFromLastSubmission, setDefaultValueFromLastSubmission] = useState( // @ts-expect-error defaultValue is not in Submission type
|
|
160
|
-
(_config$
|
|
160
|
+
(_config$lastSubmissio3 = (_config$lastSubmissio4 = config.lastSubmission) === null || _config$lastSubmissio4 === void 0 ? void 0 : _config$lastSubmissio4.payload) !== null && _config$lastSubmissio3 !== void 0 ? _config$lastSubmissio3 : null);
|
|
161
161
|
var fieldset = useFieldset(ref, {
|
|
162
162
|
defaultValue: defaultValueFromLastSubmission !== null && defaultValueFromLastSubmission !== void 0 ? defaultValueFromLastSubmission : config.defaultValue,
|
|
163
163
|
initialError,
|
|
@@ -244,7 +244,7 @@ function useForm() {
|
|
|
244
244
|
shouldServerValidate
|
|
245
245
|
} = Object.entries(submission.error).reduce((result, _ref) => {
|
|
246
246
|
var [, error] = _ref;
|
|
247
|
-
for (var message of
|
|
247
|
+
for (var message of error) {
|
|
248
248
|
if (message === VALIDATION_UNDEFINED) {
|
|
249
249
|
result.shouldServerValidate = true;
|
|
250
250
|
} else if (message !== VALIDATION_SKIPPED) {
|
|
@@ -298,6 +298,12 @@ function useForm() {
|
|
|
298
298
|
* A set of field configuration
|
|
299
299
|
*/
|
|
300
300
|
|
|
301
|
+
/**
|
|
302
|
+
* Returns all the information about the fieldset.
|
|
303
|
+
*
|
|
304
|
+
* @see https://conform.guide/api/react#usefieldset
|
|
305
|
+
*/
|
|
306
|
+
|
|
301
307
|
function useFieldset(ref, config) {
|
|
302
308
|
var [error] = useFormError(ref, {
|
|
303
309
|
initialError: config.initialError,
|
|
@@ -379,7 +385,7 @@ function useFieldList(ref, config) {
|
|
|
379
385
|
return updateList(list, _objectSpread2(_objectSpread2({}, intent.payload), {}, {
|
|
380
386
|
defaultValue: [
|
|
381
387
|
// Generate a random key to avoid conflicts
|
|
382
|
-
|
|
388
|
+
getUniqueKey(), intent.payload.defaultValue]
|
|
383
389
|
}));
|
|
384
390
|
default:
|
|
385
391
|
return updateList(list, intent.payload);
|
|
@@ -461,7 +467,6 @@ function useFieldList(ref, config) {
|
|
|
461
467
|
* This basically makes it a no-op on server
|
|
462
468
|
*/
|
|
463
469
|
var useSafeLayoutEffect = typeof document === 'undefined' ? useEffect : useLayoutEffect;
|
|
464
|
-
|
|
465
470
|
/**
|
|
466
471
|
* Returns a ref object and a set of helpers that dispatch corresponding dom event.
|
|
467
472
|
*
|
|
@@ -484,7 +489,7 @@ function useInputEvent(options) {
|
|
|
484
489
|
if (listener !== 'onReset') {
|
|
485
490
|
eventDispatched.current[listener] = true;
|
|
486
491
|
}
|
|
487
|
-
(_optionsRef$current4 = optionsRef.current) === null || _optionsRef$current4 === void 0
|
|
492
|
+
(_optionsRef$current4 = optionsRef.current) === null || _optionsRef$current4 === void 0 || (_optionsRef$current4$ = _optionsRef$current4[listener]) === null || _optionsRef$current4$ === void 0 ? void 0 : _optionsRef$current4$.call(_optionsRef$current4, event);
|
|
488
493
|
}
|
|
489
494
|
};
|
|
490
495
|
};
|
|
@@ -627,12 +632,11 @@ function validateConstraint(options) {
|
|
|
627
632
|
return defaultErrors;
|
|
628
633
|
};
|
|
629
634
|
return parse(formData, {
|
|
630
|
-
resolve(
|
|
635
|
+
resolve() {
|
|
631
636
|
var error = {};
|
|
632
637
|
var constraintPattern = /^constraint[A-Z][^A-Z]*$/;
|
|
633
638
|
var _loop = function _loop(_element3) {
|
|
634
639
|
if (isFieldElement(_element3)) {
|
|
635
|
-
var _options$acceptMultip, _options$acceptMultip2;
|
|
636
640
|
var name = _element3.name !== FORM_ERROR_ELEMENT_NAME ? _element3.name : '';
|
|
637
641
|
var constraint = Object.entries(_element3.dataset).reduce((result, _ref6) => {
|
|
638
642
|
var [name, attributeValue = ''] = _ref6;
|
|
@@ -658,13 +662,8 @@ function validateConstraint(options) {
|
|
|
658
662
|
constraint,
|
|
659
663
|
defaultErrors: getDefaultErrors(_element3.validity, constraint)
|
|
660
664
|
});
|
|
661
|
-
var shouldAcceptMultipleErrors = (_options$acceptMultip = options === null || options === void 0 ? void 0 : (_options$acceptMultip2 = options.acceptMultipleErrors) === null || _options$acceptMultip2 === void 0 ? void 0 : _options$acceptMultip2.call(options, {
|
|
662
|
-
name,
|
|
663
|
-
payload,
|
|
664
|
-
intent
|
|
665
|
-
})) !== null && _options$acceptMultip !== void 0 ? _options$acceptMultip : false;
|
|
666
665
|
if (errors.length > 0) {
|
|
667
|
-
error[name] =
|
|
666
|
+
error[name] = errors;
|
|
668
667
|
}
|
|
669
668
|
}
|
|
670
669
|
};
|
|
@@ -677,10 +676,17 @@ function validateConstraint(options) {
|
|
|
677
676
|
}
|
|
678
677
|
});
|
|
679
678
|
}
|
|
679
|
+
function getUniqueKey() {
|
|
680
|
+
var [value] = crypto.getRandomValues(new Uint32Array(1));
|
|
681
|
+
if (!value) {
|
|
682
|
+
throw new Error('Fail to generate an unique key');
|
|
683
|
+
}
|
|
684
|
+
return value.toString(36);
|
|
685
|
+
}
|
|
680
686
|
function reportSubmission(form, submission) {
|
|
681
687
|
for (var [name, message] of Object.entries(submission.error)) {
|
|
682
688
|
// There is no need to create a placeholder button if all we want is to reset the error
|
|
683
|
-
if (message ===
|
|
689
|
+
if (message.length === 0) {
|
|
684
690
|
continue;
|
|
685
691
|
}
|
|
686
692
|
|
|
@@ -709,8 +715,9 @@ function reportSubmission(form, submission) {
|
|
|
709
715
|
var intent = parseIntent(submission.intent);
|
|
710
716
|
var scope = getScope(intent);
|
|
711
717
|
for (var _element4 of getFormControls(form)) {
|
|
718
|
+
var _submission$error$_el;
|
|
712
719
|
var _elementName = _element4.name !== FORM_ERROR_ELEMENT_NAME ? _element4.name : '';
|
|
713
|
-
var messages =
|
|
720
|
+
var messages = (_submission$error$_el = submission.error[_elementName]) !== null && _submission$error$_el !== void 0 ? _submission$error$_el : [];
|
|
714
721
|
if (scope === null || scope === _elementName) {
|
|
715
722
|
_element4.dataset.conformTouched = 'true';
|
|
716
723
|
}
|
|
@@ -736,4 +743,4 @@ function getScope(intent) {
|
|
|
736
743
|
return null;
|
|
737
744
|
}
|
|
738
745
|
|
|
739
|
-
export { FORM_ERROR_ELEMENT_NAME, getScope, reportSubmission, useFieldList, useFieldset, useForm, useInputEvent, validateConstraint };
|
|
746
|
+
export { FORM_ERROR_ELEMENT_NAME, getScope, getUniqueKey, report, 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.js';
|
|
2
|
+
export { type Fieldset, type FieldConfig, type FieldsetConfig, type FormConfig, useForm, useFieldset, useFieldList, useInputEvent, validateConstraint, report, } from './hooks.js';
|
|
3
3
|
export * as conform from './helpers.js';
|
package/index.js
CHANGED
|
@@ -28,6 +28,7 @@ Object.defineProperty(exports, 'validate', {
|
|
|
28
28
|
enumerable: true,
|
|
29
29
|
get: function () { return dom.validate; }
|
|
30
30
|
});
|
|
31
|
+
exports.report = hooks.report;
|
|
31
32
|
exports.useFieldList = hooks.useFieldList;
|
|
32
33
|
exports.useFieldset = hooks.useFieldset;
|
|
33
34
|
exports.useForm = hooks.useForm;
|
package/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { isFieldElement, list, parse, requestIntent, validate } from '@conform-to/dom';
|
|
2
|
-
export { useFieldList, useFieldset, useForm, useInputEvent, validateConstraint } from './hooks.mjs';
|
|
2
|
+
export { report, useFieldList, useFieldset, useForm, useInputEvent, validateConstraint } from './hooks.mjs';
|
|
3
3
|
import * as helpers from './helpers.mjs';
|
|
4
4
|
export { helpers as conform };
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "Conform view adapter for react",
|
|
4
4
|
"homepage": "https://conform.guide",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"version": "0.
|
|
6
|
+
"version": "0.8.0-pre.0",
|
|
7
7
|
"main": "index.js",
|
|
8
8
|
"module": "index.mjs",
|
|
9
9
|
"types": "index.d.ts",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"url": "https://github.com/edmundhung/conform/issues"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@conform-to/dom": "0.
|
|
33
|
+
"@conform-to/dom": "0.8.0-pre.0"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
36
|
"react": ">=16.8"
|