@conform-to/react 0.4.0-pre.2 → 0.4.0-pre.3
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 +56 -120
- package/hooks.d.ts +23 -26
- package/hooks.js +44 -35
- package/index.d.ts +1 -1
- package/index.js +2 -6
- package/module/hooks.js +45 -36
- package/module/index.js +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -11,10 +11,9 @@
|
|
|
11
11
|
- [useFieldList](#usefieldlist)
|
|
12
12
|
- [useControlledInput](#usecontrolledinput)
|
|
13
13
|
- [conform](#conform)
|
|
14
|
+
- [getFormElements](#getformelements)
|
|
14
15
|
- [hasError](#haserror)
|
|
15
|
-
- [isFieldElement](#isfieldelement)
|
|
16
16
|
- [parse](#parse)
|
|
17
|
-
- [setFormError](#setformerror)
|
|
18
17
|
- [shouldValidate](#shouldvalidate)
|
|
19
18
|
|
|
20
19
|
<!-- /aside -->
|
|
@@ -295,33 +294,6 @@ function Fieldset() {
|
|
|
295
294
|
}
|
|
296
295
|
```
|
|
297
296
|
|
|
298
|
-
<details>
|
|
299
|
-
<summary>Is it required to provide the FieldsetConfig to `useFieldset`?</summary>
|
|
300
|
-
|
|
301
|
-
No. The only thing required is the ref object. All the config is optional. You can always pass them to each fields manually.
|
|
302
|
-
|
|
303
|
-
```tsx
|
|
304
|
-
import { useForm, useFieldset } from '@conform-to/react';
|
|
305
|
-
|
|
306
|
-
function SubscriptionForm() {
|
|
307
|
-
const formProps = useForm();
|
|
308
|
-
const { email } = useFieldset(formProps.ref);
|
|
309
|
-
|
|
310
|
-
return (
|
|
311
|
-
<form {...formProps}>
|
|
312
|
-
<input
|
|
313
|
-
type="email"
|
|
314
|
-
name={email.config.name}
|
|
315
|
-
defaultValue="support@conform.dev"
|
|
316
|
-
required
|
|
317
|
-
/>
|
|
318
|
-
</form>
|
|
319
|
-
);
|
|
320
|
-
}
|
|
321
|
-
```
|
|
322
|
-
|
|
323
|
-
</details>
|
|
324
|
-
|
|
325
297
|
<details>
|
|
326
298
|
<summary>Why does `useFieldset` require a ref object of the form or fieldset?</summary>
|
|
327
299
|
|
|
@@ -352,7 +324,7 @@ function ExampleForm() {
|
|
|
352
324
|
|
|
353
325
|
### useFieldList
|
|
354
326
|
|
|
355
|
-
It returns a list of key and config, with
|
|
327
|
+
It returns a list of key and config, with helpers to configure command buttons with [list command](/docs/submission.md#list-command).
|
|
356
328
|
|
|
357
329
|
```tsx
|
|
358
330
|
import { useFieldset, useFieldList } from '@conform-to/react';
|
|
@@ -373,7 +345,7 @@ type Collection = {
|
|
|
373
345
|
function CollectionFieldset() {
|
|
374
346
|
const ref = useRef();
|
|
375
347
|
const { books } = useFieldset<Collection>(ref);
|
|
376
|
-
const [bookList,
|
|
348
|
+
const [bookList, command] = useFieldList(ref, books.config);
|
|
377
349
|
|
|
378
350
|
return (
|
|
379
351
|
<fieldset ref={ref}>
|
|
@@ -390,12 +362,12 @@ function CollectionFieldset() {
|
|
|
390
362
|
/>
|
|
391
363
|
|
|
392
364
|
{/* To setup a delete button */}
|
|
393
|
-
<button {...
|
|
365
|
+
<button {...command.remove({ index })}>Delete</button>
|
|
394
366
|
</div>
|
|
395
367
|
))}
|
|
396
368
|
|
|
397
369
|
{/* To setup a button that can append a new row with optional default value */}
|
|
398
|
-
<button {...
|
|
370
|
+
<button {...command.append({ defaultValue: { name: '', isbn: '' } })}>
|
|
399
371
|
add
|
|
400
372
|
</button>
|
|
401
373
|
</fieldset>
|
|
@@ -412,7 +384,7 @@ import { useRef } from 'react';
|
|
|
412
384
|
function CollectionFieldset() {
|
|
413
385
|
const ref = useRef();
|
|
414
386
|
const { books } = useFieldset<Collection>(ref);
|
|
415
|
-
const [bookList,
|
|
387
|
+
const [bookList, command] = useFieldList(ref, books.config);
|
|
416
388
|
|
|
417
389
|
return (
|
|
418
390
|
<fieldset ref={ref}>
|
|
@@ -422,12 +394,12 @@ function CollectionFieldset() {
|
|
|
422
394
|
<BookFieldset {...book.config} />
|
|
423
395
|
|
|
424
396
|
{/* To setup a delete button */}
|
|
425
|
-
<button {...
|
|
397
|
+
<button {...command.remove({ index })}>Delete</button>
|
|
426
398
|
</div>
|
|
427
399
|
))}
|
|
428
400
|
|
|
429
401
|
{/* To setup a button that can append a new row */}
|
|
430
|
-
<button {...
|
|
402
|
+
<button {...command.append()}>add</button>
|
|
431
403
|
</fieldset>
|
|
432
404
|
);
|
|
433
405
|
}
|
|
@@ -582,74 +554,43 @@ function RandomForm() {
|
|
|
582
554
|
}
|
|
583
555
|
```
|
|
584
556
|
|
|
585
|
-
### hasError
|
|
586
|
-
|
|
587
|
-
This helper checks if there is any message defined in error array with the provided name.
|
|
588
|
-
|
|
589
|
-
```ts
|
|
590
|
-
import { hasError } from '@conform-to/react';
|
|
591
|
-
|
|
592
|
-
/**
|
|
593
|
-
* Assume the error looks like this:
|
|
594
|
-
*/
|
|
595
|
-
const error = [['email', 'Email is required']];
|
|
596
|
-
|
|
597
|
-
// This will log `true`
|
|
598
|
-
console.log(hasError(error, 'email'));
|
|
599
|
-
|
|
600
|
-
// This will log `false`
|
|
601
|
-
console.log(hasError(error, 'password'));
|
|
602
|
-
```
|
|
603
|
-
|
|
604
557
|
---
|
|
605
558
|
|
|
606
|
-
###
|
|
559
|
+
### getFormElements
|
|
607
560
|
|
|
608
|
-
|
|
561
|
+
It returns all _input_ / _select_ / _textarea_ or _button_ in the forms. Useful when looping through the form elements to validate each field.
|
|
609
562
|
|
|
610
563
|
```tsx
|
|
611
|
-
import {
|
|
564
|
+
import { useForm, parse, getFormElements } from '@conform-to/react';
|
|
612
565
|
|
|
613
|
-
export default function
|
|
566
|
+
export default function LoginForm() {
|
|
614
567
|
const form = useForm({
|
|
615
|
-
onValidate({ form }) {
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
} else if (field.validity.tooShort) {
|
|
632
|
-
field.setCustomValidity(
|
|
633
|
-
'The password should be at least 10 characters long',
|
|
634
|
-
);
|
|
635
|
-
} else {
|
|
636
|
-
field.setCustomValidity('');
|
|
637
|
-
}
|
|
638
|
-
break;
|
|
639
|
-
case 'confirm-password': {
|
|
640
|
-
if (field.validity.valueMissing) {
|
|
641
|
-
field.setCustomValidity('Confirm Password is required');
|
|
642
|
-
} else if (field.value !== formData.get('password')) {
|
|
643
|
-
field.setCustomValidity('The password does not match');
|
|
644
|
-
} else {
|
|
645
|
-
field.setCustomValidity('');
|
|
646
|
-
}
|
|
647
|
-
break;
|
|
568
|
+
onValidate({ form, formData }) {
|
|
569
|
+
const submission = parse(formData);
|
|
570
|
+
|
|
571
|
+
for (const element of getFormElements(form)) {
|
|
572
|
+
switch (element.name) {
|
|
573
|
+
case 'email': {
|
|
574
|
+
if (element.validity.valueMissing) {
|
|
575
|
+
submission.error.push([element.name, 'Email is required']);
|
|
576
|
+
} else if (element.validity.typeMismatch) {
|
|
577
|
+
submission.error.push([element.name, 'Email is invalid']);
|
|
578
|
+
}
|
|
579
|
+
break;
|
|
580
|
+
}
|
|
581
|
+
case 'password': {
|
|
582
|
+
if (element.validity.valueMissing) {
|
|
583
|
+
submission.error.push([element.name, 'Password is required']);
|
|
648
584
|
}
|
|
585
|
+
break;
|
|
649
586
|
}
|
|
650
587
|
}
|
|
651
588
|
}
|
|
589
|
+
|
|
590
|
+
return submission;
|
|
652
591
|
},
|
|
592
|
+
|
|
593
|
+
// ....
|
|
653
594
|
});
|
|
654
595
|
|
|
655
596
|
// ...
|
|
@@ -658,42 +599,38 @@ export default function SignupForm() {
|
|
|
658
599
|
|
|
659
600
|
---
|
|
660
601
|
|
|
661
|
-
###
|
|
602
|
+
### hasError
|
|
662
603
|
|
|
663
|
-
|
|
604
|
+
This helper checks if there is any message defined in error array with the provided name.
|
|
664
605
|
|
|
665
|
-
```
|
|
666
|
-
import {
|
|
606
|
+
```ts
|
|
607
|
+
import { hasError } from '@conform-to/react';
|
|
667
608
|
|
|
668
|
-
|
|
669
|
-
|
|
609
|
+
/**
|
|
610
|
+
* Assume the error looks like this:
|
|
611
|
+
*/
|
|
612
|
+
const error = [['email', 'Email is required']];
|
|
670
613
|
|
|
671
|
-
|
|
614
|
+
// This will log `true`
|
|
615
|
+
console.log(hasError(error, 'email'));
|
|
616
|
+
|
|
617
|
+
// This will log `false`
|
|
618
|
+
console.log(hasError(error, 'password'));
|
|
672
619
|
```
|
|
673
620
|
|
|
674
621
|
---
|
|
675
622
|
|
|
676
|
-
###
|
|
623
|
+
### parse
|
|
677
624
|
|
|
678
|
-
|
|
625
|
+
It parses the formData based on the [naming convention](/docs/submission).
|
|
679
626
|
|
|
680
627
|
```tsx
|
|
681
|
-
import {
|
|
682
|
-
|
|
683
|
-
function ExampleForm() {
|
|
684
|
-
const form = useForm({
|
|
685
|
-
onValidate({ form, submission }) {
|
|
686
|
-
const error = validate(submission);
|
|
628
|
+
import { parse } from '@conform-to/react';
|
|
687
629
|
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
error,
|
|
691
|
-
});
|
|
692
|
-
},
|
|
693
|
-
});
|
|
630
|
+
const formData = new FormData();
|
|
631
|
+
const submission = parse(formData);
|
|
694
632
|
|
|
695
|
-
|
|
696
|
-
}
|
|
633
|
+
console.log(submission);
|
|
697
634
|
```
|
|
698
635
|
|
|
699
636
|
---
|
|
@@ -706,14 +643,13 @@ This helper checks if the scope of validation includes a specific field by check
|
|
|
706
643
|
import { shouldValidate } from '@conform-to/react';
|
|
707
644
|
|
|
708
645
|
/**
|
|
709
|
-
* The submission type and
|
|
646
|
+
* The submission type and intent give us hint on what should be valdiated.
|
|
710
647
|
* If the type is 'validate', only the field with name matching the metadata must be validated.
|
|
711
|
-
*
|
|
712
|
-
* However, if the type is `undefined`, both will log true (Default submission)
|
|
648
|
+
* If the type is 'submit', everything should be validated (Default submission)
|
|
713
649
|
*/
|
|
714
650
|
const submission = {
|
|
715
|
-
|
|
716
|
-
|
|
651
|
+
context: 'validate',
|
|
652
|
+
intent: 'email',
|
|
717
653
|
value: {},
|
|
718
654
|
error: [],
|
|
719
655
|
};
|
package/hooks.d.ts
CHANGED
|
@@ -1,10 +1,5 @@
|
|
|
1
1
|
import { type FieldConfig, type FieldElement, type FieldValue, type FieldsetConstraint, type ListCommand, type Primitive, type Submission } from '@conform-to/dom';
|
|
2
2
|
import { type InputHTMLAttributes, type FormEvent, type RefObject } from 'react';
|
|
3
|
-
interface FormContext<Schema extends Record<string, any>> {
|
|
4
|
-
form: HTMLFormElement;
|
|
5
|
-
formData: FormData;
|
|
6
|
-
submission: Submission<Schema>;
|
|
7
|
-
}
|
|
8
3
|
export interface FormConfig<Schema extends Record<string, any>> {
|
|
9
4
|
/**
|
|
10
5
|
* Validation mode. Default to `client-only`.
|
|
@@ -40,12 +35,18 @@ export interface FormConfig<Schema extends Record<string, any>> {
|
|
|
40
35
|
/**
|
|
41
36
|
* A function to be called when the form should be (re)validated.
|
|
42
37
|
*/
|
|
43
|
-
onValidate?: (
|
|
38
|
+
onValidate?: ({ form, formData, }: {
|
|
39
|
+
form: HTMLFormElement;
|
|
40
|
+
formData: FormData;
|
|
41
|
+
}) => Submission<Schema>;
|
|
44
42
|
/**
|
|
45
43
|
* The submit event handler of the form. It will be called
|
|
46
44
|
* only when the form is considered valid.
|
|
47
45
|
*/
|
|
48
|
-
onSubmit?: (event: FormEvent<HTMLFormElement>, context:
|
|
46
|
+
onSubmit?: (event: FormEvent<HTMLFormElement>, context: {
|
|
47
|
+
formData: FormData;
|
|
48
|
+
submission: Submission<Schema>;
|
|
49
|
+
}) => void;
|
|
49
50
|
}
|
|
50
51
|
/**
|
|
51
52
|
* Properties to be applied to the form element
|
|
@@ -65,7 +66,7 @@ interface Form<Schema extends Record<string, any>> {
|
|
|
65
66
|
* Returns properties required to hook into form events.
|
|
66
67
|
* Applied custom validation and define when error should be reported.
|
|
67
68
|
*
|
|
68
|
-
* @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.
|
|
69
|
+
* @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.3/packages/conform-react/README.md#useform
|
|
69
70
|
*/
|
|
70
71
|
export declare function useForm<Schema extends Record<string, any>>(config?: FormConfig<Schema>): Form<Schema>;
|
|
71
72
|
/**
|
|
@@ -106,41 +107,37 @@ export interface FieldsetConfig<Schema extends Record<string, any>> {
|
|
|
106
107
|
/**
|
|
107
108
|
* Returns all the information about the fieldset.
|
|
108
109
|
*
|
|
109
|
-
* @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.
|
|
110
|
+
* @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.3/packages/conform-react/README.md#usefieldset
|
|
110
111
|
*/
|
|
111
|
-
export declare function useFieldset<Schema extends Record<string, any>>(ref: RefObject<HTMLFormElement | HTMLFieldSetElement>, config
|
|
112
|
-
export declare function useFieldset<Schema extends Record<string, any>>(ref: RefObject<HTMLFormElement | HTMLFieldSetElement>, config
|
|
113
|
-
interface
|
|
112
|
+
export declare function useFieldset<Schema extends Record<string, any>>(ref: RefObject<HTMLFormElement | HTMLFieldSetElement>, config: FieldsetConfig<Schema>): Fieldset<Schema>;
|
|
113
|
+
export declare function useFieldset<Schema extends Record<string, any>>(ref: RefObject<HTMLFormElement | HTMLFieldSetElement>, config: FieldConfig<Schema>): Fieldset<Schema>;
|
|
114
|
+
interface CommandButtonProps {
|
|
114
115
|
name?: string;
|
|
115
116
|
value?: string;
|
|
116
117
|
form?: string;
|
|
117
118
|
formNoValidate: true;
|
|
118
119
|
}
|
|
119
|
-
declare type
|
|
120
|
+
declare type ListCommandPayload<Schema, Type extends ListCommand<FieldValue<Schema>>['type']> = Extract<ListCommand<FieldValue<Schema>>, {
|
|
120
121
|
type: Type;
|
|
121
122
|
}>['payload'];
|
|
122
|
-
/**
|
|
123
|
-
* A group of helpers for configuring a list control button
|
|
124
|
-
*/
|
|
125
|
-
interface ListControl<Schema> {
|
|
126
|
-
prepend(payload?: CommandPayload<Schema, 'prepend'>): ControlButtonProps;
|
|
127
|
-
append(payload?: CommandPayload<Schema, 'append'>): ControlButtonProps;
|
|
128
|
-
replace(payload: CommandPayload<Schema, 'replace'>): ControlButtonProps;
|
|
129
|
-
remove(payload: CommandPayload<Schema, 'remove'>): ControlButtonProps;
|
|
130
|
-
reorder(payload: CommandPayload<Schema, 'reorder'>): ControlButtonProps;
|
|
131
|
-
}
|
|
132
123
|
/**
|
|
133
124
|
* Returns a list of key and config, with a group of helpers
|
|
134
125
|
* configuring buttons for list manipulation
|
|
135
126
|
*
|
|
136
|
-
* @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.
|
|
127
|
+
* @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.3/packages/conform-react/README.md#usefieldlist
|
|
137
128
|
*/
|
|
138
129
|
export declare function useFieldList<Payload = any>(ref: RefObject<HTMLFormElement | HTMLFieldSetElement>, config: FieldConfig<Array<Payload>>): [
|
|
139
130
|
Array<{
|
|
140
131
|
key: string;
|
|
141
132
|
config: FieldConfig<Payload>;
|
|
142
133
|
}>,
|
|
143
|
-
|
|
134
|
+
{
|
|
135
|
+
prepend(payload?: ListCommandPayload<Payload, 'prepend'>): CommandButtonProps;
|
|
136
|
+
append(payload?: ListCommandPayload<Payload, 'append'>): CommandButtonProps;
|
|
137
|
+
replace(payload: ListCommandPayload<Payload, 'replace'>): CommandButtonProps;
|
|
138
|
+
remove(payload: ListCommandPayload<Payload, 'remove'>): CommandButtonProps;
|
|
139
|
+
reorder(payload: ListCommandPayload<Payload, 'reorder'>): CommandButtonProps;
|
|
140
|
+
}
|
|
144
141
|
];
|
|
145
142
|
interface ShadowInputProps extends InputHTMLAttributes<HTMLInputElement> {
|
|
146
143
|
ref: RefObject<HTMLInputElement>;
|
|
@@ -163,7 +160,7 @@ interface InputControl<Element extends {
|
|
|
163
160
|
* This is particular useful when integrating dropdown and datepicker whichs
|
|
164
161
|
* introduces custom input mode.
|
|
165
162
|
*
|
|
166
|
-
* @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.
|
|
163
|
+
* @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.3/packages/conform-react/README.md#usecontrolledinput
|
|
167
164
|
*/
|
|
168
165
|
export declare function useControlledInput<Element extends {
|
|
169
166
|
focus: () => void;
|
package/hooks.js
CHANGED
|
@@ -11,7 +11,7 @@ var helpers = require('./helpers.js');
|
|
|
11
11
|
* Returns properties required to hook into form events.
|
|
12
12
|
* Applied custom validation and define when error should be reported.
|
|
13
13
|
*
|
|
14
|
-
* @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.
|
|
14
|
+
* @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.3/packages/conform-react/README.md#useform
|
|
15
15
|
*/
|
|
16
16
|
function useForm() {
|
|
17
17
|
var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
@@ -183,50 +183,58 @@ function useForm() {
|
|
|
183
183
|
}
|
|
184
184
|
|
|
185
185
|
try {
|
|
186
|
+
var submission;
|
|
186
187
|
var formData = dom.getFormData(form, submitter);
|
|
187
|
-
var submission = dom.parse(formData);
|
|
188
|
-
var _context = {
|
|
189
|
-
form,
|
|
190
|
-
formData,
|
|
191
|
-
submission
|
|
192
|
-
}; // Touch all fields only if the submitter is not a command button
|
|
193
|
-
|
|
194
|
-
if (submission.context === 'submit') {
|
|
195
|
-
for (var field of form.elements) {
|
|
196
|
-
if (dom.isFieldElement(field)) {
|
|
197
|
-
// Mark the field as touched
|
|
198
|
-
field.dataset.conformTouched = 'true';
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
var _error;
|
|
204
188
|
|
|
205
189
|
if (typeof config.onValidate === 'function') {
|
|
206
|
-
|
|
190
|
+
submission = config.onValidate({
|
|
191
|
+
form,
|
|
192
|
+
formData
|
|
193
|
+
});
|
|
207
194
|
} else {
|
|
195
|
+
submission = dom.parse(formData);
|
|
196
|
+
|
|
208
197
|
if (config.mode !== 'server-validation') {
|
|
209
|
-
|
|
198
|
+
/**
|
|
199
|
+
* As there is no custom logic defined,
|
|
200
|
+
* removing the custom validity state will allow us
|
|
201
|
+
* finding the latest validation message.
|
|
202
|
+
*
|
|
203
|
+
* This is mainly used to showcase the constraint validation API.
|
|
204
|
+
*/
|
|
210
205
|
dom.setFormError(form, {
|
|
211
|
-
|
|
206
|
+
type: 'submit',
|
|
212
207
|
value: {},
|
|
213
208
|
error: []
|
|
214
209
|
});
|
|
210
|
+
|
|
211
|
+
for (var _element of form.elements) {
|
|
212
|
+
if (dom.isFieldElement(_element) && _element.willValidate) {
|
|
213
|
+
submission.error.push([_element.name, _element.validationMessage]);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
215
216
|
}
|
|
217
|
+
} // Touch all fields only if the submitter is not a command button
|
|
216
218
|
|
|
217
|
-
_error = dom.getFormError(form);
|
|
218
|
-
}
|
|
219
219
|
|
|
220
|
-
if (
|
|
221
|
-
|
|
220
|
+
if (submission.type === 'submit') {
|
|
221
|
+
for (var field of form.elements) {
|
|
222
|
+
if (dom.isFieldElement(field)) {
|
|
223
|
+
// Mark the field as touched
|
|
224
|
+
field.dataset.conformTouched = 'true';
|
|
225
|
+
}
|
|
226
|
+
}
|
|
222
227
|
}
|
|
223
228
|
|
|
224
|
-
if (!config.noValidate && !submitter.formNoValidate && dom.hasError(submission.error) || submission.
|
|
229
|
+
if (!config.noValidate && !submitter.formNoValidate && dom.hasError(submission.error) || submission.type === 'validate' && config.mode !== 'server-validation') {
|
|
225
230
|
event.preventDefault();
|
|
226
231
|
} else {
|
|
227
232
|
var _config$onSubmit;
|
|
228
233
|
|
|
229
|
-
(_config$onSubmit = config.onSubmit) === null || _config$onSubmit === void 0 ? void 0 : _config$onSubmit.call(config, event,
|
|
234
|
+
(_config$onSubmit = config.onSubmit) === null || _config$onSubmit === void 0 ? void 0 : _config$onSubmit.call(config, event, {
|
|
235
|
+
formData,
|
|
236
|
+
submission
|
|
237
|
+
});
|
|
230
238
|
}
|
|
231
239
|
|
|
232
240
|
if (event.defaultPrevented) {
|
|
@@ -301,11 +309,11 @@ function useFieldset(ref, config) {
|
|
|
301
309
|
});
|
|
302
310
|
react.useEffect(() => {
|
|
303
311
|
var invalidHandler = event => {
|
|
304
|
-
var _configRef$current$na
|
|
312
|
+
var _configRef$current$na;
|
|
305
313
|
|
|
306
314
|
var form = dom.getFormElement(ref.current);
|
|
307
315
|
var field = event.target;
|
|
308
|
-
var fieldsetName = (_configRef$current$na =
|
|
316
|
+
var fieldsetName = (_configRef$current$na = configRef.current.name) !== null && _configRef$current$na !== void 0 ? _configRef$current$na : '';
|
|
309
317
|
|
|
310
318
|
if (!form || !dom.isFieldElement(field) || field.form !== form || !field.name.startsWith(fieldsetName)) {
|
|
311
319
|
return;
|
|
@@ -349,10 +357,10 @@ function useFieldset(ref, config) {
|
|
|
349
357
|
|
|
350
358
|
|
|
351
359
|
setError(prev => {
|
|
352
|
-
var _configRef$current$na2
|
|
360
|
+
var _configRef$current$na2;
|
|
353
361
|
|
|
354
362
|
var next = prev;
|
|
355
|
-
var fieldsetName = (_configRef$current$na2 =
|
|
363
|
+
var fieldsetName = (_configRef$current$na2 = configRef.current.name) !== null && _configRef$current$na2 !== void 0 ? _configRef$current$na2 : '';
|
|
356
364
|
|
|
357
365
|
for (var field of form.elements) {
|
|
358
366
|
if (dom.isFieldElement(field) && field.name.startsWith(fieldsetName)) {
|
|
@@ -437,7 +445,7 @@ function useFieldset(ref, config) {
|
|
|
437
445
|
* Returns a list of key and config, with a group of helpers
|
|
438
446
|
* configuring buttons for list manipulation
|
|
439
447
|
*
|
|
440
|
-
* @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.
|
|
448
|
+
* @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.3/packages/conform-react/README.md#usefieldlist
|
|
441
449
|
*/
|
|
442
450
|
function useFieldList(ref, config) {
|
|
443
451
|
var configRef = react.useRef(config);
|
|
@@ -493,7 +501,7 @@ function useFieldList(ref, config) {
|
|
|
493
501
|
* have it encoded in the value.
|
|
494
502
|
*/
|
|
495
503
|
|
|
496
|
-
var
|
|
504
|
+
var command = new Proxy({}, {
|
|
497
505
|
get(_target, type) {
|
|
498
506
|
return function () {
|
|
499
507
|
var payload = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
@@ -573,7 +581,8 @@ function useFieldList(ref, config) {
|
|
|
573
581
|
document.removeEventListener('reset', resetHandler);
|
|
574
582
|
};
|
|
575
583
|
}, [ref]);
|
|
576
|
-
return [list,
|
|
584
|
+
return [list, // @ts-expect-error proxy type
|
|
585
|
+
command];
|
|
577
586
|
}
|
|
578
587
|
|
|
579
588
|
/**
|
|
@@ -581,7 +590,7 @@ function useFieldList(ref, config) {
|
|
|
581
590
|
* This is particular useful when integrating dropdown and datepicker whichs
|
|
582
591
|
* introduces custom input mode.
|
|
583
592
|
*
|
|
584
|
-
* @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.
|
|
593
|
+
* @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.3/packages/conform-react/README.md#usecontrolledinput
|
|
585
594
|
*/
|
|
586
595
|
function useControlledInput(config) {
|
|
587
596
|
var _config$defaultValue4;
|
package/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { type FieldsetConstraint, type Submission,
|
|
1
|
+
export { type FieldsetConstraint, type Submission, getFormElements, hasError, parse, shouldValidate, } from '@conform-to/dom';
|
|
2
2
|
export * from './hooks';
|
|
3
3
|
export * as conform from './helpers';
|
package/index.js
CHANGED
|
@@ -8,18 +8,14 @@ var helpers = require('./helpers.js');
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
Object.defineProperty(exports, '
|
|
11
|
+
Object.defineProperty(exports, 'getFormElements', {
|
|
12
12
|
enumerable: true,
|
|
13
|
-
get: function () { return dom.
|
|
13
|
+
get: function () { return dom.getFormElements; }
|
|
14
14
|
});
|
|
15
15
|
Object.defineProperty(exports, 'hasError', {
|
|
16
16
|
enumerable: true,
|
|
17
17
|
get: function () { return dom.hasError; }
|
|
18
18
|
});
|
|
19
|
-
Object.defineProperty(exports, 'isFieldElement', {
|
|
20
|
-
enumerable: true,
|
|
21
|
-
get: function () { return dom.isFieldElement; }
|
|
22
|
-
});
|
|
23
19
|
Object.defineProperty(exports, 'parse', {
|
|
24
20
|
enumerable: true,
|
|
25
21
|
get: function () { return dom.parse; }
|
package/module/hooks.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { objectSpread2 as _objectSpread2 } from './_virtual/_rollupPluginBabelHelpers.js';
|
|
2
|
-
import { getSubmissionType, setFormError, focusFirstInvalidField, requestSubmit, isFieldElement, getFormData, parse,
|
|
2
|
+
import { getSubmissionType, setFormError, focusFirstInvalidField, requestSubmit, isFieldElement, getFormData, parse, hasError, getPaths, getName, requestValidate, getFormElement, parseListCommand, updateList } from '@conform-to/dom';
|
|
3
3
|
import { useRef, useState, useEffect } from 'react';
|
|
4
4
|
import { input } from './helpers.js';
|
|
5
5
|
|
|
@@ -7,7 +7,7 @@ import { input } from './helpers.js';
|
|
|
7
7
|
* Returns properties required to hook into form events.
|
|
8
8
|
* Applied custom validation and define when error should be reported.
|
|
9
9
|
*
|
|
10
|
-
* @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.
|
|
10
|
+
* @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.3/packages/conform-react/README.md#useform
|
|
11
11
|
*/
|
|
12
12
|
function useForm() {
|
|
13
13
|
var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
@@ -179,50 +179,58 @@ function useForm() {
|
|
|
179
179
|
}
|
|
180
180
|
|
|
181
181
|
try {
|
|
182
|
+
var submission;
|
|
182
183
|
var formData = getFormData(form, submitter);
|
|
183
|
-
var submission = parse(formData);
|
|
184
|
-
var _context = {
|
|
185
|
-
form,
|
|
186
|
-
formData,
|
|
187
|
-
submission
|
|
188
|
-
}; // Touch all fields only if the submitter is not a command button
|
|
189
|
-
|
|
190
|
-
if (submission.context === 'submit') {
|
|
191
|
-
for (var field of form.elements) {
|
|
192
|
-
if (isFieldElement(field)) {
|
|
193
|
-
// Mark the field as touched
|
|
194
|
-
field.dataset.conformTouched = 'true';
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
var _error;
|
|
200
184
|
|
|
201
185
|
if (typeof config.onValidate === 'function') {
|
|
202
|
-
|
|
186
|
+
submission = config.onValidate({
|
|
187
|
+
form,
|
|
188
|
+
formData
|
|
189
|
+
});
|
|
203
190
|
} else {
|
|
191
|
+
submission = parse(formData);
|
|
192
|
+
|
|
204
193
|
if (config.mode !== 'server-validation') {
|
|
205
|
-
|
|
194
|
+
/**
|
|
195
|
+
* As there is no custom logic defined,
|
|
196
|
+
* removing the custom validity state will allow us
|
|
197
|
+
* finding the latest validation message.
|
|
198
|
+
*
|
|
199
|
+
* This is mainly used to showcase the constraint validation API.
|
|
200
|
+
*/
|
|
206
201
|
setFormError(form, {
|
|
207
|
-
|
|
202
|
+
type: 'submit',
|
|
208
203
|
value: {},
|
|
209
204
|
error: []
|
|
210
205
|
});
|
|
206
|
+
|
|
207
|
+
for (var _element of form.elements) {
|
|
208
|
+
if (isFieldElement(_element) && _element.willValidate) {
|
|
209
|
+
submission.error.push([_element.name, _element.validationMessage]);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
211
212
|
}
|
|
213
|
+
} // Touch all fields only if the submitter is not a command button
|
|
212
214
|
|
|
213
|
-
_error = getFormError(form);
|
|
214
|
-
}
|
|
215
215
|
|
|
216
|
-
if (
|
|
217
|
-
|
|
216
|
+
if (submission.type === 'submit') {
|
|
217
|
+
for (var field of form.elements) {
|
|
218
|
+
if (isFieldElement(field)) {
|
|
219
|
+
// Mark the field as touched
|
|
220
|
+
field.dataset.conformTouched = 'true';
|
|
221
|
+
}
|
|
222
|
+
}
|
|
218
223
|
}
|
|
219
224
|
|
|
220
|
-
if (!config.noValidate && !submitter.formNoValidate && hasError(submission.error) || submission.
|
|
225
|
+
if (!config.noValidate && !submitter.formNoValidate && hasError(submission.error) || submission.type === 'validate' && config.mode !== 'server-validation') {
|
|
221
226
|
event.preventDefault();
|
|
222
227
|
} else {
|
|
223
228
|
var _config$onSubmit;
|
|
224
229
|
|
|
225
|
-
(_config$onSubmit = config.onSubmit) === null || _config$onSubmit === void 0 ? void 0 : _config$onSubmit.call(config, event,
|
|
230
|
+
(_config$onSubmit = config.onSubmit) === null || _config$onSubmit === void 0 ? void 0 : _config$onSubmit.call(config, event, {
|
|
231
|
+
formData,
|
|
232
|
+
submission
|
|
233
|
+
});
|
|
226
234
|
}
|
|
227
235
|
|
|
228
236
|
if (event.defaultPrevented) {
|
|
@@ -297,11 +305,11 @@ function useFieldset(ref, config) {
|
|
|
297
305
|
});
|
|
298
306
|
useEffect(() => {
|
|
299
307
|
var invalidHandler = event => {
|
|
300
|
-
var _configRef$current$na
|
|
308
|
+
var _configRef$current$na;
|
|
301
309
|
|
|
302
310
|
var form = getFormElement(ref.current);
|
|
303
311
|
var field = event.target;
|
|
304
|
-
var fieldsetName = (_configRef$current$na =
|
|
312
|
+
var fieldsetName = (_configRef$current$na = configRef.current.name) !== null && _configRef$current$na !== void 0 ? _configRef$current$na : '';
|
|
305
313
|
|
|
306
314
|
if (!form || !isFieldElement(field) || field.form !== form || !field.name.startsWith(fieldsetName)) {
|
|
307
315
|
return;
|
|
@@ -345,10 +353,10 @@ function useFieldset(ref, config) {
|
|
|
345
353
|
|
|
346
354
|
|
|
347
355
|
setError(prev => {
|
|
348
|
-
var _configRef$current$na2
|
|
356
|
+
var _configRef$current$na2;
|
|
349
357
|
|
|
350
358
|
var next = prev;
|
|
351
|
-
var fieldsetName = (_configRef$current$na2 =
|
|
359
|
+
var fieldsetName = (_configRef$current$na2 = configRef.current.name) !== null && _configRef$current$na2 !== void 0 ? _configRef$current$na2 : '';
|
|
352
360
|
|
|
353
361
|
for (var field of form.elements) {
|
|
354
362
|
if (isFieldElement(field) && field.name.startsWith(fieldsetName)) {
|
|
@@ -433,7 +441,7 @@ function useFieldset(ref, config) {
|
|
|
433
441
|
* Returns a list of key and config, with a group of helpers
|
|
434
442
|
* configuring buttons for list manipulation
|
|
435
443
|
*
|
|
436
|
-
* @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.
|
|
444
|
+
* @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.3/packages/conform-react/README.md#usefieldlist
|
|
437
445
|
*/
|
|
438
446
|
function useFieldList(ref, config) {
|
|
439
447
|
var configRef = useRef(config);
|
|
@@ -489,7 +497,7 @@ function useFieldList(ref, config) {
|
|
|
489
497
|
* have it encoded in the value.
|
|
490
498
|
*/
|
|
491
499
|
|
|
492
|
-
var
|
|
500
|
+
var command = new Proxy({}, {
|
|
493
501
|
get(_target, type) {
|
|
494
502
|
return function () {
|
|
495
503
|
var payload = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
@@ -569,7 +577,8 @@ function useFieldList(ref, config) {
|
|
|
569
577
|
document.removeEventListener('reset', resetHandler);
|
|
570
578
|
};
|
|
571
579
|
}, [ref]);
|
|
572
|
-
return [list,
|
|
580
|
+
return [list, // @ts-expect-error proxy type
|
|
581
|
+
command];
|
|
573
582
|
}
|
|
574
583
|
|
|
575
584
|
/**
|
|
@@ -577,7 +586,7 @@ function useFieldList(ref, config) {
|
|
|
577
586
|
* This is particular useful when integrating dropdown and datepicker whichs
|
|
578
587
|
* introduces custom input mode.
|
|
579
588
|
*
|
|
580
|
-
* @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.
|
|
589
|
+
* @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.3/packages/conform-react/README.md#usecontrolledinput
|
|
581
590
|
*/
|
|
582
591
|
function useControlledInput(config) {
|
|
583
592
|
var _config$defaultValue4;
|
package/module/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { getFormElements, hasError, parse, shouldValidate } from '@conform-to/dom';
|
|
2
2
|
export { useControlledInput, useFieldList, useFieldset, useForm } from './hooks.js';
|
|
3
3
|
import * as helpers from './helpers.js';
|
|
4
4
|
export { helpers as conform };
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@conform-to/react",
|
|
3
3
|
"description": "Conform view adapter for react",
|
|
4
4
|
"license": "MIT",
|
|
5
|
-
"version": "0.4.0-pre.
|
|
5
|
+
"version": "0.4.0-pre.3",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"module": "module/index.js",
|
|
8
8
|
"repository": {
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"url": "https://github.com/edmundhung/conform/issues"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@conform-to/dom": "0.4.0-pre.
|
|
22
|
+
"@conform-to/dom": "0.4.0-pre.3"
|
|
23
23
|
},
|
|
24
24
|
"peerDependencies": {
|
|
25
25
|
"react": ">=16.8"
|