@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 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 a group of helpers configuring buttons for list manipulation
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, control] = useFieldList(ref, books.config);
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 {...control.remove({ index })}>Delete</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 {...control.append({ defaultValue: { name: '', isbn: '' } })}>
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, control] = useFieldList(ref, books.config);
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 {...control.remove({ index })}>Delete</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 {...control.append()}>add</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
- ### isFieldElement
559
+ ### getFormElements
607
560
 
608
- This checks if the provided element is an `input` / `select` / `textarea` or `button` HTML element with type guard. Useful when you need to access the validityState of the fields and modify the validation message manually.
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 { isFieldElement } from '@conform-to/react';
564
+ import { useForm, parse, getFormElements } from '@conform-to/react';
612
565
 
613
- export default function SignupForm() {
566
+ export default function LoginForm() {
614
567
  const form = useForm({
615
- onValidate({ form }) {
616
- for (const element of form.elements) {
617
- if (isFieldElement(element)) {
618
- switch (field.name) {
619
- case 'email':
620
- if (field.validity.valueMissing) {
621
- field.setCustomValidity('Email is required');
622
- } else if (field.validity.typeMismatch) {
623
- field.setCustomValidity('Please enter a valid email');
624
- } else {
625
- field.setCustomValidity('');
626
- }
627
- break;
628
- case 'password':
629
- if (field.validity.valueMissing) {
630
- field.setCustomValidity('Password is required');
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
- ### parse
602
+ ### hasError
662
603
 
663
- It parses the formData based on the [naming convention](/docs/submission).
604
+ This helper checks if there is any message defined in error array with the provided name.
664
605
 
665
- ```tsx
666
- import { parse } from '@conform-to/react';
606
+ ```ts
607
+ import { hasError } from '@conform-to/react';
667
608
 
668
- const formData = new FormData(formElement);
669
- const submission = parse(formData);
609
+ /**
610
+ * Assume the error looks like this:
611
+ */
612
+ const error = [['email', 'Email is required']];
670
613
 
671
- console.log(submission);
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
- ### setFormError
623
+ ### parse
677
624
 
678
- This helpers updates the form error based on the submission result by looping through all elements in the form and update the error with the [setCustomValidity](https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/setCustomValidity) API.
625
+ It parses the formData based on the [naming convention](/docs/submission).
679
626
 
680
627
  ```tsx
681
- import { setFormError } from '@conform-to/react';
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
- setFormError(form, {
689
- ...submission,
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 metadata give us hint on what should be valdiated.
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
- type: 'validate',
716
- metadata: 'email',
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?: (context: FormContext<Schema>) => Array<[string, string]>;
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: FormContext<Schema>) => void;
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.2/packages/conform-react/README.md#useform
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.2/packages/conform-react/README.md#usefieldset
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?: FieldsetConfig<Schema>): Fieldset<Schema>;
112
- export declare function useFieldset<Schema extends Record<string, any>>(ref: RefObject<HTMLFormElement | HTMLFieldSetElement>, config?: FieldConfig<Schema>): Fieldset<Schema>;
113
- interface ControlButtonProps {
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 CommandPayload<Schema, Type extends ListCommand<FieldValue<Schema>>['type']> = Extract<ListCommand<FieldValue<Schema>>, {
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.2/packages/conform-react/README.md#usefieldlist
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
- ListControl<Payload>
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.2/packages/conform-react/README.md#usecontrolledinput
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.2/packages/conform-react/README.md#useform
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
- _error = config.onValidate(_context);
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
- // Clear previous result
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
- context: 'submit',
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 (_error.length > 0) {
221
- submission.error.push(..._error);
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.context === 'validate' && config.mode !== 'server-validation') {
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, _context);
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, _configRef$current;
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 = (_configRef$current = configRef.current) === null || _configRef$current === void 0 ? void 0 : _configRef$current.name) !== null && _configRef$current$na !== void 0 ? _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, _configRef$current2;
360
+ var _configRef$current$na2;
353
361
 
354
362
  var next = prev;
355
- var fieldsetName = (_configRef$current$na2 = (_configRef$current2 = configRef.current) === null || _configRef$current2 === void 0 ? void 0 : _configRef$current2.name) !== null && _configRef$current$na2 !== void 0 ? _configRef$current$na2 : '';
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.2/packages/conform-react/README.md#usefieldlist
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 control = new Proxy({}, {
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, control];
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.2/packages/conform-react/README.md#usecontrolledinput
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, getFormError, hasError, isFieldElement, parse, shouldValidate, } from '@conform-to/dom';
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, 'getFormError', {
11
+ Object.defineProperty(exports, 'getFormElements', {
12
12
  enumerable: true,
13
- get: function () { return dom.getFormError; }
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, getFormError, hasError, getPaths, getName, requestValidate, getFormElement, parseListCommand, updateList } from '@conform-to/dom';
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.2/packages/conform-react/README.md#useform
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
- _error = config.onValidate(_context);
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
- // Clear previous result
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
- context: 'submit',
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 (_error.length > 0) {
217
- submission.error.push(..._error);
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.context === 'validate' && config.mode !== 'server-validation') {
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, _context);
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, _configRef$current;
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 = (_configRef$current = configRef.current) === null || _configRef$current === void 0 ? void 0 : _configRef$current.name) !== null && _configRef$current$na !== void 0 ? _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, _configRef$current2;
356
+ var _configRef$current$na2;
349
357
 
350
358
  var next = prev;
351
- var fieldsetName = (_configRef$current$na2 = (_configRef$current2 = configRef.current) === null || _configRef$current2 === void 0 ? void 0 : _configRef$current2.name) !== null && _configRef$current$na2 !== void 0 ? _configRef$current$na2 : '';
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.2/packages/conform-react/README.md#usefieldlist
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 control = new Proxy({}, {
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, control];
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.2/packages/conform-react/README.md#usecontrolledinput
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 { getFormError, hasError, isFieldElement, parse, shouldValidate } from '@conform-to/dom';
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.2",
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.2"
22
+ "@conform-to/dom": "0.4.0-pre.3"
23
23
  },
24
24
  "peerDependencies": {
25
25
  "react": ">=16.8"