@conform-to/react 0.4.0 → 0.5.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 CHANGED
@@ -324,7 +324,7 @@ function ExampleForm() {
324
324
 
325
325
  ### useFieldList
326
326
 
327
- It returns a list of key and config, with helpers to configure command buttons with [list command](/docs/submission.md#list-command).
327
+ It returns a list of key, config and error, with helpers to configure [list command](/docs/submission.md#list-command) button.
328
328
 
329
329
  ```tsx
330
330
  import { useFieldset, useFieldList } from '@conform-to/react';
@@ -333,33 +333,24 @@ import { useRef } from 'react';
333
333
  /**
334
334
  * Consider the schema as follow:
335
335
  */
336
- type Book = {
337
- name: string;
338
- isbn: string;
339
- };
340
-
341
- type Collection = {
342
- books: Book[];
336
+ type Schema = {
337
+ list: string[];
343
338
  };
344
339
 
345
340
  function CollectionFieldset() {
346
- const ref = useRef();
347
- const { books } = useFieldset<Collection>(ref);
348
- const [bookList, command] = useFieldList(ref, books.config);
341
+ const ref = useRef<HTMLFieldsetElement>(null);
342
+ const fieldset = useFieldset<Collection>(ref);
343
+ const [list, command] = useFieldList(ref, fieldset.list.config);
349
344
 
350
345
  return (
351
346
  <fieldset ref={ref}>
352
- {bookList.map((book, index) => (
353
- <div key={book.key}>
354
- {/* To setup the fields */}
355
- <input
356
- name={`${book.config.name}.name`}
357
- defaultValue={book.config.defaultValue.name}
358
- />
359
- <input
360
- name={`${book.config.name}.isbn`}
361
- defaultValue={book.config.defaultValue.isbn}
362
- />
347
+ {list.map((item, index) => (
348
+ <div key={item.key}>
349
+ {/* Setup an input per item */}
350
+ <input {...conform.input(item.config)} />
351
+
352
+ {/* Error of each book */}
353
+ <span>{item.error}</span>
363
354
 
364
355
  {/* To setup a delete button */}
365
356
  <button {...command.remove({ index })}>Delete</button>
@@ -367,79 +358,86 @@ function CollectionFieldset() {
367
358
  ))}
368
359
 
369
360
  {/* To setup a button that can append a new row with optional default value */}
370
- <button {...command.append({ defaultValue: { name: '', isbn: '' } })}>
371
- add
372
- </button>
361
+ <button {...command.append({ defaultValue: '' })}>add</button>
373
362
  </fieldset>
374
363
  );
375
364
  }
376
365
  ```
377
366
 
378
- This hook can also be used in combination with `useFieldset` to distribute the config:
367
+ This hook can also be used in combination with `useFieldset` for nested list:
379
368
 
380
369
  ```tsx
381
- import { useForm, useFieldset, useFieldList } from '@conform-to/react';
370
+ import {
371
+ type FieldConfig,
372
+ useForm,
373
+ useFieldset,
374
+ useFieldList,
375
+ } from '@conform-to/react';
382
376
  import { useRef } from 'react';
383
377
 
378
+ /**
379
+ * Consider the schema as follow:
380
+ */
381
+ type Schema = {
382
+ list: Array<Item>;
383
+ };
384
+
385
+ type Item = {
386
+ title: string;
387
+ description: string;
388
+ };
389
+
384
390
  function CollectionFieldset() {
385
- const ref = useRef();
386
- const { books } = useFieldset<Collection>(ref);
387
- const [bookList, command] = useFieldList(ref, books.config);
391
+ const ref = useRef<HTMLFieldsetElement>(null);
392
+ const fieldset = useFieldset<Collection>(ref);
393
+ const [list, command] = useFieldList(ref, fieldset.list.config);
388
394
 
389
395
  return (
390
396
  <fieldset ref={ref}>
391
- {bookList.map((book, index) => (
392
- <div key={book.key}>
393
- {/* `book.config` is a FieldConfig object similar to `books` */}
394
- <BookFieldset {...book.config} />
395
-
396
- {/* To setup a delete button */}
397
- <button {...command.remove({ index })}>Delete</button>
397
+ {list.map((item, index) => (
398
+ <div key={item.key}>
399
+ {/* Pass the item config to another fieldset*/}
400
+ <ItemFieldset {...item.config} />
398
401
  </div>
399
402
  ))}
400
-
401
- {/* To setup a button that can append a new row */}
402
- <button {...command.append()}>add</button>
403
403
  </fieldset>
404
404
  );
405
405
  }
406
406
 
407
- /**
408
- * This is basically the BookFieldset component from
409
- * the `useFieldset` example, but setting all the
410
- * options with the component props instead
411
- */
412
- function BookFieldset({ name, form, defaultValue, error }) {
413
- const ref = useRef();
414
- const { name, isbn } = useFieldset(ref, {
415
- name,
416
- form,
417
- defaultValue,
418
- error,
419
- });
407
+ function ItemFieldset(config: FieldConfig<Item>) {
408
+ const ref = useRef<HTMLFieldsetElement>(null);
409
+ const { title, description } = useFieldset(ref, config);
420
410
 
421
- return <fieldset ref={ref}>{/* ... */}</fieldset>;
411
+ return (
412
+ <fieldset ref={ref}>
413
+ <input {...conform.input(title.config)} />
414
+ <span>{title.error}</span>
415
+
416
+ <input {...conform.input(description.config)} />
417
+ <span>{description.error}</span>
418
+ </fieldset>
419
+ );
422
420
  }
423
421
  ```
424
422
 
425
423
  <details>
426
- <summary>What can I do with `controls`?</summary>
424
+ <summary>What can I do with `command`?</summary>
427
425
 
428
426
  ```tsx
429
427
  // To append a new row with optional defaultValue
430
- <button {...controls.append({ defaultValue })}>Append</button>;
428
+ <button {...command.append({ defaultValue })}>Append</button>;
431
429
 
432
430
  // To prepend a new row with optional defaultValue
433
- <button {...controls.prepend({ defaultValue })}>Prepend</button>;
431
+ <button {...command.prepend({ defaultValue })}>Prepend</button>;
434
432
 
435
433
  // To remove a row by index
436
- <button {...controls.remove({ index })}>Remove</button>;
434
+ <button {...command.remove({ index })}>Remove</button>;
437
435
 
438
436
  // To replace a row with another defaultValue
439
- <button {...controls.replace({ index, defaultValue })}>Replace</button>;
437
+ <button {...command.replace({ index, defaultValue })}>Replace</button>;
440
438
 
441
439
  // To reorder a particular row to an another index
442
- <button {...controls.reorder({ from, to })}>Reorder</button>;
440
+ <button {...command.reorder({ from, to })}>Reorder</button>;
443
441
  ```
444
442
 
445
443
  </details>
package/base.d.ts ADDED
@@ -0,0 +1,17 @@
1
+ import { type InputHTMLAttributes, type RefObject } from 'react';
2
+ declare type EventLikeOrString = {
3
+ target: {
4
+ value: string;
5
+ };
6
+ } | string;
7
+ declare type InputControl = {
8
+ onChange: (eventLikeOrString: EventLikeOrString) => void;
9
+ onInput: (eventLikeOrString: EventLikeOrString) => void;
10
+ onFocus: () => void;
11
+ onBlur: () => void;
12
+ };
13
+ export declare function useInputControl(ref: RefObject<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>): InputControl;
14
+ export declare const BaseInput: import("react").ForwardRefExoticComponent<{
15
+ name: string;
16
+ } & Omit<InputHTMLAttributes<HTMLInputElement>, "name" | "type" | "value" | "defaultValue"> & import("react").RefAttributes<HTMLInputElement>>;
17
+ export {};
package/base.js ADDED
@@ -0,0 +1,112 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var _rollupPluginBabelHelpers = require('./_virtual/_rollupPluginBabelHelpers.js');
6
+ var react = require('react');
7
+
8
+ var _excluded = ["hidden", "className", "style"];
9
+ /**
10
+ * Triggering react custom change event
11
+ * Solution based on dom-testing-library
12
+ * @see https://github.com/facebook/react/issues/10135#issuecomment-401496776
13
+ * @see https://github.com/testing-library/dom-testing-library/blob/main/src/events.js#L104-L123
14
+ */
15
+ function setNativeValue(element, value) {
16
+ var {
17
+ set: valueSetter
18
+ } = Object.getOwnPropertyDescriptor(element, 'value') || {};
19
+ var prototype = Object.getPrototypeOf(element);
20
+ var {
21
+ set: prototypeValueSetter
22
+ } = Object.getOwnPropertyDescriptor(prototype, 'value') || {};
23
+ if (prototypeValueSetter && valueSetter !== prototypeValueSetter) {
24
+ prototypeValueSetter.call(element, value);
25
+ } else {
26
+ if (valueSetter) {
27
+ valueSetter.call(element, value);
28
+ } else {
29
+ throw new Error('The given element does not have a value setter');
30
+ }
31
+ }
32
+ }
33
+ function useInputControl(ref) {
34
+ function getInputElement() {
35
+ var $input = ref.current;
36
+ if (!$input) {
37
+ console.warn('input ref is not available; Maybe you forget to setup the ref?');
38
+ }
39
+ return $input;
40
+ }
41
+ return {
42
+ onChange(eventLikeOrString) {
43
+ var $input = getInputElement();
44
+ var value = typeof eventLikeOrString === 'string' ? eventLikeOrString : eventLikeOrString.target.value;
45
+ if ($input && $input.value !== value) {
46
+ $input.dispatchEvent(new InputEvent('beforeinput', {
47
+ bubbles: true,
48
+ cancelable: true
49
+ }));
50
+ setNativeValue($input, value);
51
+ $input.dispatchEvent(new InputEvent('input', {
52
+ bubbles: true,
53
+ cancelable: true
54
+ }));
55
+ }
56
+ },
57
+ onInput(eventLikeOrString) {
58
+ this.onChange(eventLikeOrString);
59
+ },
60
+ onFocus() {
61
+ var $input = getInputElement();
62
+ if ($input) {
63
+ $input.dispatchEvent(new FocusEvent('focusin', {
64
+ bubbles: true,
65
+ cancelable: true
66
+ }));
67
+ $input.dispatchEvent(new FocusEvent('focus', {
68
+ cancelable: true
69
+ }));
70
+ }
71
+ },
72
+ onBlur() {
73
+ var $input = getInputElement();
74
+ if ($input) {
75
+ $input.dispatchEvent(new FocusEvent('focusout', {
76
+ bubbles: true,
77
+ cancelable: true
78
+ }));
79
+ $input.dispatchEvent(new FocusEvent('blur', {
80
+ cancelable: true
81
+ }));
82
+ }
83
+ }
84
+ };
85
+ }
86
+ function BaseInputImpl(_ref, ref) {
87
+ var {
88
+ hidden = true,
89
+ className,
90
+ style
91
+ } = _ref,
92
+ props = _rollupPluginBabelHelpers.objectWithoutProperties(_ref, _excluded);
93
+ return /*#__PURE__*/react.createElement('input', _rollupPluginBabelHelpers.objectSpread2({
94
+ ref,
95
+ className: hidden ? '' : className,
96
+ style: hidden ? {
97
+ position: 'absolute',
98
+ width: '1px',
99
+ height: '1px',
100
+ padding: 0,
101
+ margin: '-1px',
102
+ overflow: 'hidden',
103
+ clip: 'rect(0,0,0,0)',
104
+ whiteSpace: 'nowrap',
105
+ borderWidth: 0
106
+ } : style
107
+ }, props));
108
+ }
109
+ var BaseInput = /*#__PURE__*/react.forwardRef(BaseInputImpl);
110
+
111
+ exports.BaseInput = BaseInput;
112
+ exports.useInputControl = useInputControl;
package/helpers.d.ts CHANGED
@@ -1,8 +1,47 @@
1
- import { type FieldConfig, type Primitive } from '@conform-to/dom';
2
- import { type InputHTMLAttributes, type SelectHTMLAttributes, type TextareaHTMLAttributes } from 'react';
3
- export declare function input<Schema extends Primitive>(config: FieldConfig<Schema>, { type, value }?: {
4
- type?: string;
1
+ import type { FieldConfig } from '@conform-to/dom';
2
+ import type { HTMLInputTypeAttribute } from 'react';
3
+ interface FieldProps {
4
+ name: string;
5
+ form?: string;
6
+ required?: boolean;
7
+ autoFocus?: boolean;
8
+ }
9
+ interface InputProps<Schema> extends FieldProps {
10
+ type?: HTMLInputTypeAttribute;
11
+ minLength?: number;
12
+ maxLength?: number;
13
+ min?: Schema extends number ? number : string | number;
14
+ max?: Schema extends number ? number : string | number;
15
+ step?: Schema extends number ? number : string | number;
16
+ pattern?: string;
17
+ multiple?: boolean;
5
18
  value?: string;
6
- }): InputHTMLAttributes<HTMLInputElement>;
7
- export declare function select<Schema extends Primitive | Array<Primitive>>(config: FieldConfig<Schema>): SelectHTMLAttributes<HTMLSelectElement>;
8
- export declare function textarea<Schema extends Primitive>(config: FieldConfig<Schema>): TextareaHTMLAttributes<HTMLTextAreaElement>;
19
+ defaultChecked?: boolean;
20
+ defaultValue?: string;
21
+ }
22
+ interface SelectProps extends FieldProps {
23
+ defaultValue?: string | number | readonly string[] | undefined;
24
+ multiple?: boolean;
25
+ }
26
+ interface TextareaProps extends FieldProps {
27
+ minLength?: number;
28
+ maxLength?: number;
29
+ defaultValue?: string;
30
+ }
31
+ declare type InputOptions = {
32
+ type: 'checkbox' | 'radio';
33
+ value?: string;
34
+ } | {
35
+ type: 'file';
36
+ value?: never;
37
+ } | {
38
+ type?: Exclude<HTMLInputTypeAttribute, 'button' | 'submit' | 'hidden' | 'file'>;
39
+ value?: never;
40
+ };
41
+ export declare function input<Schema extends File | File[]>(config: FieldConfig<Schema>, options: {
42
+ type: 'file';
43
+ }): InputProps<Schema>;
44
+ export declare function input<Schema extends any>(config: FieldConfig<Schema>, options?: InputOptions): InputProps<Schema>;
45
+ export declare function select<Schema>(config: FieldConfig<Schema>): SelectProps;
46
+ export declare function textarea<Schema>(config: FieldConfig<Schema>): TextareaProps;
47
+ export {};
package/helpers.js CHANGED
@@ -3,13 +3,9 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  function input(config) {
6
- var {
7
- type,
8
- value
9
- } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
10
- var isCheckboxOrRadio = type === 'checkbox' || type === 'radio';
6
+ var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
11
7
  var attributes = {
12
- type,
8
+ type: options.type,
13
9
  name: config.name,
14
10
  form: config.form,
15
11
  required: config.required,
@@ -24,10 +20,11 @@ function input(config) {
24
20
  if (config.initialError && config.initialError.length > 0) {
25
21
  attributes.autoFocus = true;
26
22
  }
27
- if (isCheckboxOrRadio) {
28
- attributes.value = value !== null && value !== void 0 ? value : 'on';
23
+ if (options.type === 'checkbox' || options.type === 'radio') {
24
+ var _options$value;
25
+ attributes.value = (_options$value = options.value) !== null && _options$value !== void 0 ? _options$value : 'on';
29
26
  attributes.defaultChecked = config.defaultValue === attributes.value;
30
- } else {
27
+ } else if (options.type !== 'file') {
31
28
  attributes.defaultValue = config.defaultValue;
32
29
  }
33
30
  return attributes;
package/hooks.d.ts CHANGED
@@ -66,7 +66,7 @@ interface Form<Schema extends Record<string, any>> {
66
66
  * Returns properties required to hook into form events.
67
67
  * Applied custom validation and define when error should be reported.
68
68
  *
69
- * @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.3/packages/conform-react/README.md#useform
69
+ * @see https://github.com/edmundhung/conform/tree/v0.4.1/packages/conform-react/README.md#useform
70
70
  */
71
71
  export declare function useForm<Schema extends Record<string, any>>(config?: FormConfig<Schema>): Form<Schema>;
72
72
  /**
@@ -107,7 +107,7 @@ export interface FieldsetConfig<Schema extends Record<string, any>> {
107
107
  /**
108
108
  * Returns all the information about the fieldset.
109
109
  *
110
- * @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.3/packages/conform-react/README.md#usefieldset
110
+ * @see https://github.com/edmundhung/conform/tree/v0.4.1/packages/conform-react/README.md#usefieldset
111
111
  */
112
112
  export declare function useFieldset<Schema extends Record<string, any>>(ref: RefObject<HTMLFormElement | HTMLFieldSetElement>, config: FieldsetConfig<Schema>): Fieldset<Schema>;
113
113
  export declare function useFieldset<Schema extends Record<string, any>>(ref: RefObject<HTMLFormElement | HTMLFieldSetElement>, config: FieldConfig<Schema>): Fieldset<Schema>;
@@ -124,11 +124,12 @@ declare type ListCommandPayload<Schema, Type extends ListCommand<FieldValue<Sche
124
124
  * Returns a list of key and config, with a group of helpers
125
125
  * configuring buttons for list manipulation
126
126
  *
127
- * @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.3/packages/conform-react/README.md#usefieldlist
127
+ * @see https://github.com/edmundhung/conform/tree/v0.4.1/packages/conform-react/README.md#usefieldlist
128
128
  */
129
129
  export declare function useFieldList<Payload = any>(ref: RefObject<HTMLFormElement | HTMLFieldSetElement>, config: FieldConfig<Array<Payload>>): [
130
130
  Array<{
131
131
  key: string;
132
+ error: string | undefined;
132
133
  config: FieldConfig<Payload>;
133
134
  }>,
134
135
  {
@@ -160,7 +161,7 @@ interface InputControl<Element extends {
160
161
  * This is particular useful when integrating dropdown and datepicker whichs
161
162
  * introduces custom input mode.
162
163
  *
163
- * @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.3/packages/conform-react/README.md#usecontrolledinput
164
+ * @see https://github.com/edmundhung/conform/tree/v0.4.1/packages/conform-react/README.md#usecontrolledinput
164
165
  */
165
166
  export declare function useControlledInput<Element extends {
166
167
  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.3/packages/conform-react/README.md#useform
14
+ * @see https://github.com/edmundhung/conform/tree/v0.4.1/packages/conform-react/README.md#useform
15
15
  */
16
16
  function useForm() {
17
17
  var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
@@ -48,11 +48,7 @@ function useForm() {
48
48
  if (!form || !config.state) {
49
49
  return;
50
50
  }
51
- dom.setFormError(form, config.state);
52
- if (!form.reportValidity()) {
53
- dom.focusFirstInvalidField(form);
54
- }
55
- dom.requestSubmit(form);
51
+ dom.reportSubmission(form, config.state);
56
52
  }, [config.state]);
57
53
  react.useEffect(() => {
58
54
  // Revalidate the form when input value is changed
@@ -85,7 +81,7 @@ function useForm() {
85
81
  var handleInvalid = event => {
86
82
  var form = dom.getFormElement(ref.current);
87
83
  var field = event.target;
88
- if (!form || !dom.isFieldElement(field) || field.form !== form || field.name !== '') {
84
+ if (!form || !dom.isFieldElement(field) || field.form !== form || field.name !== '__form__') {
89
85
  return;
90
86
  }
91
87
  event.preventDefault();
@@ -141,12 +137,6 @@ function useForm() {
141
137
  var form = event.currentTarget;
142
138
  var nativeEvent = event.nativeEvent;
143
139
  var submitter = nativeEvent.submitter;
144
- for (var element of form.elements) {
145
- if (dom.isFieldElement(element) && element.name === '') {
146
- setError(element.validationMessage);
147
- break;
148
- }
149
- }
150
140
 
151
141
  /**
152
142
  * It checks defaultPrevented to confirm if the submission is intentional
@@ -154,8 +144,7 @@ function useForm() {
154
144
  * event is captured and revalidate the form with new fields without triggering
155
145
  * a form submission at the same time.
156
146
  */
157
- if (!submitter || event.defaultPrevented) {
158
- event.preventDefault();
147
+ if (event.defaultPrevented) {
159
148
  return;
160
149
  }
161
150
  try {
@@ -176,14 +165,10 @@ function useForm() {
176
165
  *
177
166
  * This is mainly used to showcase the constraint validation API.
178
167
  */
179
- dom.setFormError(form, {
180
- type: 'submit',
181
- value: {},
182
- error: []
183
- });
184
- for (var _element of form.elements) {
185
- if (dom.isFieldElement(_element) && _element.willValidate) {
186
- submission.error.push([_element.name, _element.validationMessage]);
168
+ for (var element of form.elements) {
169
+ if (dom.isFieldElement(element) && element.willValidate) {
170
+ element.setCustomValidity('');
171
+ submission.error.push([element.name, element.validationMessage]);
187
172
  }
188
173
  }
189
174
  }
@@ -198,7 +183,7 @@ function useForm() {
198
183
  }
199
184
  }
200
185
  }
201
- if (!config.noValidate && !submitter.formNoValidate && dom.hasError(submission.error) || submission.type === 'validate' && config.mode !== 'server-validation') {
186
+ if (!config.noValidate && !(submitter !== null && submitter !== void 0 && submitter.formNoValidate) && dom.hasError(submission.error) || submission.type === 'validate' && config.mode !== 'server-validation') {
202
187
  event.preventDefault();
203
188
  } else {
204
189
  var _config$onSubmit;
@@ -208,10 +193,7 @@ function useForm() {
208
193
  });
209
194
  }
210
195
  if (event.defaultPrevented) {
211
- dom.setFormError(form, submission);
212
- if (!form.reportValidity()) {
213
- dom.focusFirstInvalidField(form);
214
- }
196
+ dom.reportSubmission(form, submission);
215
197
  }
216
198
  } catch (e) {
217
199
  console.warn(e);
@@ -294,38 +276,6 @@ function useFieldset(ref, config) {
294
276
  event.preventDefault();
295
277
  }
296
278
  };
297
- var submitHandler = event => {
298
- var form = dom.getFormElement(ref.current);
299
- if (!form || event.target !== form) {
300
- return;
301
- }
302
-
303
- /**
304
- * Reset the error state of each field if its validity is changed.
305
- *
306
- * This is a workaround as no official way is provided to notify
307
- * when the validity of the field is changed from `invalid` to `valid`.
308
- */
309
- setError(prev => {
310
- var _configRef$current$na2;
311
- var next = prev;
312
- var fieldsetName = (_configRef$current$na2 = configRef.current.name) !== null && _configRef$current$na2 !== void 0 ? _configRef$current$na2 : '';
313
- for (var field of form.elements) {
314
- if (dom.isFieldElement(field) && field.name.startsWith(fieldsetName)) {
315
- var _next$key, _next;
316
- var key = fieldsetName ? field.name.slice(fieldsetName.length + 1) : field.name;
317
- var prevMessage = (_next$key = (_next = next) === null || _next === void 0 ? void 0 : _next[key]) !== null && _next$key !== void 0 ? _next$key : '';
318
- var nextMessage = field.validationMessage;
319
- if (prevMessage !== '' && nextMessage === '') {
320
- next = _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, next), {}, {
321
- [key]: ''
322
- });
323
- }
324
- }
325
- }
326
- return next;
327
- });
328
- };
329
279
  var resetHandler = event => {
330
280
  var _fieldsetConfig$defau;
331
281
  var form = dom.getFormElement(ref.current);
@@ -343,11 +293,9 @@ function useFieldset(ref, config) {
343
293
 
344
294
  // The invalid event does not bubble and so listening on the capturing pharse is needed
345
295
  document.addEventListener('invalid', invalidHandler, true);
346
- document.addEventListener('submit', submitHandler);
347
296
  document.addEventListener('reset', resetHandler);
348
297
  return () => {
349
298
  document.removeEventListener('invalid', invalidHandler, true);
350
- document.removeEventListener('submit', submitHandler);
351
299
  document.removeEventListener('reset', resetHandler);
352
300
  };
353
301
  }, [ref]);
@@ -382,7 +330,7 @@ function useFieldset(ref, config) {
382
330
  * Returns a list of key and config, with a group of helpers
383
331
  * configuring buttons for list manipulation
384
332
  *
385
- * @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.3/packages/conform-react/README.md#usefieldlist
333
+ * @see https://github.com/edmundhung/conform/tree/v0.4.1/packages/conform-react/README.md#usefieldlist
386
334
  */
387
335
  function useFieldList(ref, config) {
388
336
  var configRef = react.useRef(config);
@@ -408,6 +356,7 @@ function useFieldList(ref, config) {
408
356
  initialError
409
357
  };
410
358
  });
359
+ var [error, setError] = react.useState(() => uncontrolledState.initialError.map(error => error === null || error === void 0 ? void 0 : error[0][1]));
411
360
  var [entries, setEntries] = react.useState(() => {
412
361
  var _config$defaultValue3;
413
362
  return Object.entries((_config$defaultValue3 = config.defaultValue) !== null && _config$defaultValue3 !== void 0 ? _config$defaultValue3 : [undefined]);
@@ -416,6 +365,7 @@ function useFieldList(ref, config) {
416
365
  var [key, defaultValue] = _ref3;
417
366
  return {
418
367
  key,
368
+ error: error[index],
419
369
  config: {
420
370
  name: "".concat(config.name, "[").concat(index, "]"),
421
371
  form: config.form,
@@ -450,6 +400,31 @@ function useFieldList(ref, config) {
450
400
  configRef.current = config;
451
401
  });
452
402
  react.useEffect(() => {
403
+ var invalidHandler = event => {
404
+ var _configRef$current$na2;
405
+ var form = dom.getFormElement(ref.current);
406
+ var field = event.target;
407
+ var prefix = (_configRef$current$na2 = configRef.current.name) !== null && _configRef$current$na2 !== void 0 ? _configRef$current$na2 : '';
408
+ if (!form || !dom.isFieldElement(field) || field.form !== form || !field.name.startsWith(prefix)) {
409
+ return;
410
+ }
411
+ var [index, ...paths] = dom.getPaths(prefix.length > 0 ? field.name.slice(prefix.length) : field.name);
412
+
413
+ // Update the error only if the field belongs to the fieldset
414
+ if (typeof index === 'number' && paths.length === 0) {
415
+ if (field.dataset.conformTouched) {
416
+ setError(prev => {
417
+ var _prev$index;
418
+ var prevMessage = (_prev$index = prev === null || prev === void 0 ? void 0 : prev[index]) !== null && _prev$index !== void 0 ? _prev$index : '';
419
+ if (prevMessage === field.validationMessage) {
420
+ return prev;
421
+ }
422
+ return [...prev.slice(0, index), field.validationMessage, ...prev.slice(index + 1)];
423
+ });
424
+ }
425
+ event.preventDefault();
426
+ }
427
+ };
453
428
  var submitHandler = event => {
454
429
  var form = dom.getFormElement(ref.current);
455
430
  if (!form || event.target !== form || !(event.submitter instanceof HTMLButtonElement) || event.submitter.name !== 'conform/list') {
@@ -476,6 +451,22 @@ function useFieldList(ref, config) {
476
451
  }
477
452
  }
478
453
  });
454
+ setError(error => {
455
+ switch (command.type) {
456
+ case 'append':
457
+ case 'prepend':
458
+ case 'replace':
459
+ return dom.updateList([...error], _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, command), {}, {
460
+ payload: _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, command.payload), {}, {
461
+ defaultValue: undefined
462
+ })
463
+ }));
464
+ default:
465
+ {
466
+ return dom.updateList([...error], command);
467
+ }
468
+ }
469
+ });
479
470
  event.preventDefault();
480
471
  };
481
472
  var resetHandler = event => {
@@ -490,11 +481,14 @@ function useFieldList(ref, config) {
490
481
  initialError: []
491
482
  });
492
483
  setEntries(Object.entries((_fieldConfig$defaultV2 = fieldConfig.defaultValue) !== null && _fieldConfig$defaultV2 !== void 0 ? _fieldConfig$defaultV2 : [undefined]));
484
+ setError([]);
493
485
  };
494
486
  document.addEventListener('submit', submitHandler, true);
487
+ document.addEventListener('invalid', invalidHandler, true);
495
488
  document.addEventListener('reset', resetHandler);
496
489
  return () => {
497
490
  document.removeEventListener('submit', submitHandler, true);
491
+ document.removeEventListener('invalid', invalidHandler, true);
498
492
  document.removeEventListener('reset', resetHandler);
499
493
  };
500
494
  }, [ref]);
@@ -507,7 +501,7 @@ function useFieldList(ref, config) {
507
501
  * This is particular useful when integrating dropdown and datepicker whichs
508
502
  * introduces custom input mode.
509
503
  *
510
- * @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.3/packages/conform-react/README.md#usecontrolledinput
504
+ * @see https://github.com/edmundhung/conform/tree/v0.4.1/packages/conform-react/README.md#usecontrolledinput
511
505
  */
512
506
  function useControlledInput(config) {
513
507
  var _config$defaultValue4;
@@ -573,13 +567,13 @@ function useControlledInput(config) {
573
567
  whiteSpace: 'nowrap',
574
568
  borderWidth: 0
575
569
  },
570
+ tabIndex: -1,
571
+ 'aria-hidden': true,
576
572
  onFocus() {
577
573
  var _inputRef$current;
578
574
  (_inputRef$current = inputRef.current) === null || _inputRef$current === void 0 ? void 0 : _inputRef$current.focus();
579
575
  }
580
- }, helpers.input(_rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, config), uncontrolledState), {
581
- type: 'text'
582
- })), {
576
+ }, helpers.input(_rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, config), uncontrolledState))), {
583
577
  ref: inputRef,
584
578
  value,
585
579
  onChange: handleChange,
package/index.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- export { type FieldsetConstraint, type Submission, getFormElements, hasError, parse, shouldValidate, } from '@conform-to/dom';
1
+ export { type FieldConfig, 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/module/base.js ADDED
@@ -0,0 +1,107 @@
1
+ import { objectWithoutProperties as _objectWithoutProperties, objectSpread2 as _objectSpread2 } from './_virtual/_rollupPluginBabelHelpers.js';
2
+ import { forwardRef, createElement } from 'react';
3
+
4
+ var _excluded = ["hidden", "className", "style"];
5
+ /**
6
+ * Triggering react custom change event
7
+ * Solution based on dom-testing-library
8
+ * @see https://github.com/facebook/react/issues/10135#issuecomment-401496776
9
+ * @see https://github.com/testing-library/dom-testing-library/blob/main/src/events.js#L104-L123
10
+ */
11
+ function setNativeValue(element, value) {
12
+ var {
13
+ set: valueSetter
14
+ } = Object.getOwnPropertyDescriptor(element, 'value') || {};
15
+ var prototype = Object.getPrototypeOf(element);
16
+ var {
17
+ set: prototypeValueSetter
18
+ } = Object.getOwnPropertyDescriptor(prototype, 'value') || {};
19
+ if (prototypeValueSetter && valueSetter !== prototypeValueSetter) {
20
+ prototypeValueSetter.call(element, value);
21
+ } else {
22
+ if (valueSetter) {
23
+ valueSetter.call(element, value);
24
+ } else {
25
+ throw new Error('The given element does not have a value setter');
26
+ }
27
+ }
28
+ }
29
+ function useInputControl(ref) {
30
+ function getInputElement() {
31
+ var $input = ref.current;
32
+ if (!$input) {
33
+ console.warn('input ref is not available; Maybe you forget to setup the ref?');
34
+ }
35
+ return $input;
36
+ }
37
+ return {
38
+ onChange(eventLikeOrString) {
39
+ var $input = getInputElement();
40
+ var value = typeof eventLikeOrString === 'string' ? eventLikeOrString : eventLikeOrString.target.value;
41
+ if ($input && $input.value !== value) {
42
+ $input.dispatchEvent(new InputEvent('beforeinput', {
43
+ bubbles: true,
44
+ cancelable: true
45
+ }));
46
+ setNativeValue($input, value);
47
+ $input.dispatchEvent(new InputEvent('input', {
48
+ bubbles: true,
49
+ cancelable: true
50
+ }));
51
+ }
52
+ },
53
+ onInput(eventLikeOrString) {
54
+ this.onChange(eventLikeOrString);
55
+ },
56
+ onFocus() {
57
+ var $input = getInputElement();
58
+ if ($input) {
59
+ $input.dispatchEvent(new FocusEvent('focusin', {
60
+ bubbles: true,
61
+ cancelable: true
62
+ }));
63
+ $input.dispatchEvent(new FocusEvent('focus', {
64
+ cancelable: true
65
+ }));
66
+ }
67
+ },
68
+ onBlur() {
69
+ var $input = getInputElement();
70
+ if ($input) {
71
+ $input.dispatchEvent(new FocusEvent('focusout', {
72
+ bubbles: true,
73
+ cancelable: true
74
+ }));
75
+ $input.dispatchEvent(new FocusEvent('blur', {
76
+ cancelable: true
77
+ }));
78
+ }
79
+ }
80
+ };
81
+ }
82
+ function BaseInputImpl(_ref, ref) {
83
+ var {
84
+ hidden = true,
85
+ className,
86
+ style
87
+ } = _ref,
88
+ props = _objectWithoutProperties(_ref, _excluded);
89
+ return /*#__PURE__*/createElement('input', _objectSpread2({
90
+ ref,
91
+ className: hidden ? '' : className,
92
+ style: hidden ? {
93
+ position: 'absolute',
94
+ width: '1px',
95
+ height: '1px',
96
+ padding: 0,
97
+ margin: '-1px',
98
+ overflow: 'hidden',
99
+ clip: 'rect(0,0,0,0)',
100
+ whiteSpace: 'nowrap',
101
+ borderWidth: 0
102
+ } : style
103
+ }, props));
104
+ }
105
+ var BaseInput = /*#__PURE__*/forwardRef(BaseInputImpl);
106
+
107
+ export { BaseInput, useInputControl };
package/module/helpers.js CHANGED
@@ -1,11 +1,7 @@
1
1
  function input(config) {
2
- var {
3
- type,
4
- value
5
- } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
6
- var isCheckboxOrRadio = type === 'checkbox' || type === 'radio';
2
+ var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
7
3
  var attributes = {
8
- type,
4
+ type: options.type,
9
5
  name: config.name,
10
6
  form: config.form,
11
7
  required: config.required,
@@ -20,10 +16,11 @@ function input(config) {
20
16
  if (config.initialError && config.initialError.length > 0) {
21
17
  attributes.autoFocus = true;
22
18
  }
23
- if (isCheckboxOrRadio) {
24
- attributes.value = value !== null && value !== void 0 ? value : 'on';
19
+ if (options.type === 'checkbox' || options.type === 'radio') {
20
+ var _options$value;
21
+ attributes.value = (_options$value = options.value) !== null && _options$value !== void 0 ? _options$value : 'on';
25
22
  attributes.defaultChecked = config.defaultValue === attributes.value;
26
- } else {
23
+ } else if (options.type !== 'file') {
27
24
  attributes.defaultValue = config.defaultValue;
28
25
  }
29
26
  return attributes;
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, hasError, getPaths, getName, requestValidate, getFormElement, parseListCommand, updateList } from '@conform-to/dom';
2
+ import { getSubmissionType, reportSubmission, getFormData, parse, isFieldElement, 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.3/packages/conform-react/README.md#useform
10
+ * @see https://github.com/edmundhung/conform/tree/v0.4.1/packages/conform-react/README.md#useform
11
11
  */
12
12
  function useForm() {
13
13
  var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
@@ -44,11 +44,7 @@ function useForm() {
44
44
  if (!form || !config.state) {
45
45
  return;
46
46
  }
47
- setFormError(form, config.state);
48
- if (!form.reportValidity()) {
49
- focusFirstInvalidField(form);
50
- }
51
- requestSubmit(form);
47
+ reportSubmission(form, config.state);
52
48
  }, [config.state]);
53
49
  useEffect(() => {
54
50
  // Revalidate the form when input value is changed
@@ -81,7 +77,7 @@ function useForm() {
81
77
  var handleInvalid = event => {
82
78
  var form = getFormElement(ref.current);
83
79
  var field = event.target;
84
- if (!form || !isFieldElement(field) || field.form !== form || field.name !== '') {
80
+ if (!form || !isFieldElement(field) || field.form !== form || field.name !== '__form__') {
85
81
  return;
86
82
  }
87
83
  event.preventDefault();
@@ -137,12 +133,6 @@ function useForm() {
137
133
  var form = event.currentTarget;
138
134
  var nativeEvent = event.nativeEvent;
139
135
  var submitter = nativeEvent.submitter;
140
- for (var element of form.elements) {
141
- if (isFieldElement(element) && element.name === '') {
142
- setError(element.validationMessage);
143
- break;
144
- }
145
- }
146
136
 
147
137
  /**
148
138
  * It checks defaultPrevented to confirm if the submission is intentional
@@ -150,8 +140,7 @@ function useForm() {
150
140
  * event is captured and revalidate the form with new fields without triggering
151
141
  * a form submission at the same time.
152
142
  */
153
- if (!submitter || event.defaultPrevented) {
154
- event.preventDefault();
143
+ if (event.defaultPrevented) {
155
144
  return;
156
145
  }
157
146
  try {
@@ -172,14 +161,10 @@ function useForm() {
172
161
  *
173
162
  * This is mainly used to showcase the constraint validation API.
174
163
  */
175
- setFormError(form, {
176
- type: 'submit',
177
- value: {},
178
- error: []
179
- });
180
- for (var _element of form.elements) {
181
- if (isFieldElement(_element) && _element.willValidate) {
182
- submission.error.push([_element.name, _element.validationMessage]);
164
+ for (var element of form.elements) {
165
+ if (isFieldElement(element) && element.willValidate) {
166
+ element.setCustomValidity('');
167
+ submission.error.push([element.name, element.validationMessage]);
183
168
  }
184
169
  }
185
170
  }
@@ -194,7 +179,7 @@ function useForm() {
194
179
  }
195
180
  }
196
181
  }
197
- if (!config.noValidate && !submitter.formNoValidate && hasError(submission.error) || submission.type === 'validate' && config.mode !== 'server-validation') {
182
+ if (!config.noValidate && !(submitter !== null && submitter !== void 0 && submitter.formNoValidate) && hasError(submission.error) || submission.type === 'validate' && config.mode !== 'server-validation') {
198
183
  event.preventDefault();
199
184
  } else {
200
185
  var _config$onSubmit;
@@ -204,10 +189,7 @@ function useForm() {
204
189
  });
205
190
  }
206
191
  if (event.defaultPrevented) {
207
- setFormError(form, submission);
208
- if (!form.reportValidity()) {
209
- focusFirstInvalidField(form);
210
- }
192
+ reportSubmission(form, submission);
211
193
  }
212
194
  } catch (e) {
213
195
  console.warn(e);
@@ -290,38 +272,6 @@ function useFieldset(ref, config) {
290
272
  event.preventDefault();
291
273
  }
292
274
  };
293
- var submitHandler = event => {
294
- var form = getFormElement(ref.current);
295
- if (!form || event.target !== form) {
296
- return;
297
- }
298
-
299
- /**
300
- * Reset the error state of each field if its validity is changed.
301
- *
302
- * This is a workaround as no official way is provided to notify
303
- * when the validity of the field is changed from `invalid` to `valid`.
304
- */
305
- setError(prev => {
306
- var _configRef$current$na2;
307
- var next = prev;
308
- var fieldsetName = (_configRef$current$na2 = configRef.current.name) !== null && _configRef$current$na2 !== void 0 ? _configRef$current$na2 : '';
309
- for (var field of form.elements) {
310
- if (isFieldElement(field) && field.name.startsWith(fieldsetName)) {
311
- var _next$key, _next;
312
- var key = fieldsetName ? field.name.slice(fieldsetName.length + 1) : field.name;
313
- var prevMessage = (_next$key = (_next = next) === null || _next === void 0 ? void 0 : _next[key]) !== null && _next$key !== void 0 ? _next$key : '';
314
- var nextMessage = field.validationMessage;
315
- if (prevMessage !== '' && nextMessage === '') {
316
- next = _objectSpread2(_objectSpread2({}, next), {}, {
317
- [key]: ''
318
- });
319
- }
320
- }
321
- }
322
- return next;
323
- });
324
- };
325
275
  var resetHandler = event => {
326
276
  var _fieldsetConfig$defau;
327
277
  var form = getFormElement(ref.current);
@@ -339,11 +289,9 @@ function useFieldset(ref, config) {
339
289
 
340
290
  // The invalid event does not bubble and so listening on the capturing pharse is needed
341
291
  document.addEventListener('invalid', invalidHandler, true);
342
- document.addEventListener('submit', submitHandler);
343
292
  document.addEventListener('reset', resetHandler);
344
293
  return () => {
345
294
  document.removeEventListener('invalid', invalidHandler, true);
346
- document.removeEventListener('submit', submitHandler);
347
295
  document.removeEventListener('reset', resetHandler);
348
296
  };
349
297
  }, [ref]);
@@ -378,7 +326,7 @@ function useFieldset(ref, config) {
378
326
  * Returns a list of key and config, with a group of helpers
379
327
  * configuring buttons for list manipulation
380
328
  *
381
- * @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.3/packages/conform-react/README.md#usefieldlist
329
+ * @see https://github.com/edmundhung/conform/tree/v0.4.1/packages/conform-react/README.md#usefieldlist
382
330
  */
383
331
  function useFieldList(ref, config) {
384
332
  var configRef = useRef(config);
@@ -404,6 +352,7 @@ function useFieldList(ref, config) {
404
352
  initialError
405
353
  };
406
354
  });
355
+ var [error, setError] = useState(() => uncontrolledState.initialError.map(error => error === null || error === void 0 ? void 0 : error[0][1]));
407
356
  var [entries, setEntries] = useState(() => {
408
357
  var _config$defaultValue3;
409
358
  return Object.entries((_config$defaultValue3 = config.defaultValue) !== null && _config$defaultValue3 !== void 0 ? _config$defaultValue3 : [undefined]);
@@ -412,6 +361,7 @@ function useFieldList(ref, config) {
412
361
  var [key, defaultValue] = _ref3;
413
362
  return {
414
363
  key,
364
+ error: error[index],
415
365
  config: {
416
366
  name: "".concat(config.name, "[").concat(index, "]"),
417
367
  form: config.form,
@@ -446,6 +396,31 @@ function useFieldList(ref, config) {
446
396
  configRef.current = config;
447
397
  });
448
398
  useEffect(() => {
399
+ var invalidHandler = event => {
400
+ var _configRef$current$na2;
401
+ var form = getFormElement(ref.current);
402
+ var field = event.target;
403
+ var prefix = (_configRef$current$na2 = configRef.current.name) !== null && _configRef$current$na2 !== void 0 ? _configRef$current$na2 : '';
404
+ if (!form || !isFieldElement(field) || field.form !== form || !field.name.startsWith(prefix)) {
405
+ return;
406
+ }
407
+ var [index, ...paths] = getPaths(prefix.length > 0 ? field.name.slice(prefix.length) : field.name);
408
+
409
+ // Update the error only if the field belongs to the fieldset
410
+ if (typeof index === 'number' && paths.length === 0) {
411
+ if (field.dataset.conformTouched) {
412
+ setError(prev => {
413
+ var _prev$index;
414
+ var prevMessage = (_prev$index = prev === null || prev === void 0 ? void 0 : prev[index]) !== null && _prev$index !== void 0 ? _prev$index : '';
415
+ if (prevMessage === field.validationMessage) {
416
+ return prev;
417
+ }
418
+ return [...prev.slice(0, index), field.validationMessage, ...prev.slice(index + 1)];
419
+ });
420
+ }
421
+ event.preventDefault();
422
+ }
423
+ };
449
424
  var submitHandler = event => {
450
425
  var form = getFormElement(ref.current);
451
426
  if (!form || event.target !== form || !(event.submitter instanceof HTMLButtonElement) || event.submitter.name !== 'conform/list') {
@@ -472,6 +447,22 @@ function useFieldList(ref, config) {
472
447
  }
473
448
  }
474
449
  });
450
+ setError(error => {
451
+ switch (command.type) {
452
+ case 'append':
453
+ case 'prepend':
454
+ case 'replace':
455
+ return updateList([...error], _objectSpread2(_objectSpread2({}, command), {}, {
456
+ payload: _objectSpread2(_objectSpread2({}, command.payload), {}, {
457
+ defaultValue: undefined
458
+ })
459
+ }));
460
+ default:
461
+ {
462
+ return updateList([...error], command);
463
+ }
464
+ }
465
+ });
475
466
  event.preventDefault();
476
467
  };
477
468
  var resetHandler = event => {
@@ -486,11 +477,14 @@ function useFieldList(ref, config) {
486
477
  initialError: []
487
478
  });
488
479
  setEntries(Object.entries((_fieldConfig$defaultV2 = fieldConfig.defaultValue) !== null && _fieldConfig$defaultV2 !== void 0 ? _fieldConfig$defaultV2 : [undefined]));
480
+ setError([]);
489
481
  };
490
482
  document.addEventListener('submit', submitHandler, true);
483
+ document.addEventListener('invalid', invalidHandler, true);
491
484
  document.addEventListener('reset', resetHandler);
492
485
  return () => {
493
486
  document.removeEventListener('submit', submitHandler, true);
487
+ document.removeEventListener('invalid', invalidHandler, true);
494
488
  document.removeEventListener('reset', resetHandler);
495
489
  };
496
490
  }, [ref]);
@@ -503,7 +497,7 @@ function useFieldList(ref, config) {
503
497
  * This is particular useful when integrating dropdown and datepicker whichs
504
498
  * introduces custom input mode.
505
499
  *
506
- * @see https://github.com/edmundhung/conform/tree/v0.4.0-pre.3/packages/conform-react/README.md#usecontrolledinput
500
+ * @see https://github.com/edmundhung/conform/tree/v0.4.1/packages/conform-react/README.md#usecontrolledinput
507
501
  */
508
502
  function useControlledInput(config) {
509
503
  var _config$defaultValue4;
@@ -569,13 +563,13 @@ function useControlledInput(config) {
569
563
  whiteSpace: 'nowrap',
570
564
  borderWidth: 0
571
565
  },
566
+ tabIndex: -1,
567
+ 'aria-hidden': true,
572
568
  onFocus() {
573
569
  var _inputRef$current;
574
570
  (_inputRef$current = inputRef.current) === null || _inputRef$current === void 0 ? void 0 : _inputRef$current.focus();
575
571
  }
576
- }, input(_objectSpread2(_objectSpread2({}, config), uncontrolledState), {
577
- type: 'text'
578
- })), {
572
+ }, input(_objectSpread2(_objectSpread2({}, config), uncontrolledState))), {
579
573
  ref: inputRef,
580
574
  value,
581
575
  onChange: handleChange,
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",
5
+ "version": "0.5.0-pre.0",
6
6
  "main": "index.js",
7
7
  "module": "module/index.js",
8
8
  "repository": {
@@ -19,7 +19,7 @@
19
19
  "url": "https://github.com/edmundhung/conform/issues"
20
20
  },
21
21
  "dependencies": {
22
- "@conform-to/dom": "0.4.0"
22
+ "@conform-to/dom": "0.5.0-pre.0"
23
23
  },
24
24
  "peerDependencies": {
25
25
  "react": ">=16.8"