@conform-to/react 1.18.0 → 1.19.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.
@@ -1,49 +1,27 @@
1
1
  'use client';
2
2
  import { objectSpread2 as _objectSpread2, objectWithoutProperties as _objectWithoutProperties } from '../_virtual/_rollupPluginBabelHelpers.mjs';
3
- import { DEFAULT_INTENT_NAME, createGlobalFormsObserver, serialize, isFieldElement, isGlobalInstance, deepEqual, change, focus, blur, getFormData, dispatchInternalUpdateEvent, parseSubmission, report, requestSubmit, isPlainObject } from '@conform-to/dom/future';
4
- import { createContext, useContext, useMemo, useRef, useId, useState, useEffect, useSyncExternalStore, useCallback, useLayoutEffect, forwardRef } from 'react';
5
- import { resolveStandardSchemaResult, resolveValidateResult, appendUniqueItem } from './util.mjs';
6
- import { isTouched, getFormMetadata, getFieldset, getField, initializeState, updateState } from './state.mjs';
3
+ import { createGlobalFormsObserver, isGlobalInstance, deepEqual, isFieldElement, change, focus, blur, getFormData, defaultSerialize, isPlainObject, normalizeFormError, dispatchInternalUpdateEvent, parseSubmission, report, requestSubmit } from '@conform-to/dom/future';
4
+ import { createContext, useRef, useContext, useMemo, useState, useEffect, useSyncExternalStore, useCallback, useLayoutEffect, forwardRef } from 'react';
5
+ import { appendUniqueItem, resolveValidateResult } from './util.mjs';
6
+ import { initializeState, updateState } from './state.mjs';
7
7
  import { deserializeIntent, applyIntent, intentHandlers, resolveIntent } from './intent.mjs';
8
- import { cleanupPreservedInputs, preserveInputs, focusFirstInvalidField, getFormElement, createIntentDispatcher, deriveDefaultPayload, resolveControlPayload, initializeField, resetFormValue, updateFormValue, getSubmitEvent } from './dom.mjs';
8
+ import { cleanupPreservedInputs, preserveInputs, deriveDefaultPayload, resolveControlPayload, initializeField, getFormElement, resetFormValue, updateFormValue, getSubmitEvent } from './dom.mjs';
9
9
  import { flushSync } from 'react-dom';
10
10
  import { jsx } from 'react/jsx-runtime';
11
11
 
12
- var _excluded = ["children"],
13
- _excluded2 = ["name", "form", "defaultValue", "hidden"],
14
- _excluded3 = ["defaultValue", "multiple", "hidden"],
15
- _excluded4 = ["defaultValue", "hidden"],
16
- _excluded5 = ["defaultValue", "value", "hidden"],
17
- _excluded6 = ["defaultValue", "hidden"];
12
+ var _excluded = ["name", "form", "defaultValue", "hidden"],
13
+ _excluded2 = ["defaultValue", "multiple", "hidden"],
14
+ _excluded3 = ["defaultValue", "hidden"],
15
+ _excluded4 = ["defaultValue", "value", "hidden"],
16
+ _excluded5 = ["defaultValue", "hidden"];
18
17
  var INITIAL_KEY = 'INITIAL_KEY';
19
- var GlobalFormOptionsContext = /*#__PURE__*/createContext({
20
- intentName: DEFAULT_INTENT_NAME,
21
- observer: createGlobalFormsObserver(),
22
- serialize,
23
- shouldValidate: 'onSubmit'
24
- });
25
- var FormContextContext = /*#__PURE__*/createContext([]);
26
-
27
- /**
28
- * Provides form context to child components.
29
- * Stacks contexts to support nested forms, with latest context taking priority.
30
- */
31
- function FormProvider(props) {
32
- var stack = useContext(FormContextContext);
33
- var value = useMemo(
34
- // Put the latest form context first to ensure that to be the first one found
35
- () => [props.context].concat(stack), [stack, props.context]);
36
- return /*#__PURE__*/jsx(FormContextContext.Provider, {
37
- value: value,
38
- children: props.children
39
- });
40
- }
18
+ var GlobalFormsObserverContext = /*#__PURE__*/createContext(createGlobalFormsObserver());
41
19
 
42
20
  /**
43
21
  * Preserves form field values when its contents are unmounted.
44
22
  * Useful for multi-step forms and virtualized lists.
45
23
  *
46
- * @see https://conform.guide/api/react/future/PreserveBoundary
24
+ * See https://conform.guide/api/react/future/PreserveBoundary
47
25
  */
48
26
  function PreserveBoundary(props) {
49
27
  // name is used as key so React properly unmounts/remounts when switching
@@ -80,30 +58,6 @@ function PreserveBoundaryImpl(props) {
80
58
  });
81
59
  }
82
60
 
83
- /**
84
- * @deprecated Replaced by the `configureForms` factory API. This will be removed in the next minor version. If you are not ready to migrate, please pin to `v1.16.0`.
85
- */
86
- function FormOptionsProvider(props) {
87
- var {
88
- children
89
- } = props,
90
- providedOptions = _objectWithoutProperties(props, _excluded);
91
- var defaultOptions = useContext(GlobalFormOptionsContext);
92
- var options = useMemo(() => _objectSpread2(_objectSpread2({}, defaultOptions), providedOptions), [defaultOptions, providedOptions]);
93
- return /*#__PURE__*/jsx(GlobalFormOptionsContext.Provider, {
94
- value: options,
95
- children: children
96
- });
97
- }
98
- function useFormContext(formId) {
99
- var contexts = useContext(FormContextContext);
100
- var context = formId ? contexts.find(context => formId === context.formId) : contexts[0];
101
- if (!context) {
102
- throw new Error('No form context found; Have you render a <FormProvider /> with the corresponding form context?');
103
- }
104
- return context;
105
- }
106
-
107
61
  /**
108
62
  * Core form hook that manages form state, validation, and submission.
109
63
  * Handles both sync and async validation, intent dispatching, and DOM updates.
@@ -146,8 +100,11 @@ function useConform(formRef, options) {
146
100
  var abortControllerRef = useRef(null);
147
101
  var handleSubmission = useCallback(function (type, result) {
148
102
  var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : optionsRef.current;
103
+ var normalizedResult = !result.error ? result : _objectSpread2(_objectSpread2({}, result), {}, {
104
+ error: normalizeFormError(result.error)
105
+ });
149
106
  var intent = result.submission.intent ? deserializeIntent(result.submission.intent) : null;
150
- var finalResult = applyIntent(result, intent, {
107
+ var finalResult = applyIntent(normalizedResult, intent, {
151
108
  handlers: intentHandlers
152
109
  });
153
110
  var formElement = getFormElement(formRef);
@@ -159,7 +116,7 @@ function useConform(formRef, options) {
159
116
  intent,
160
117
  ctx: {
161
118
  handlers: intentHandlers,
162
- cancelled: finalResult !== result,
119
+ cancelled: finalResult !== normalizedResult,
163
120
  reset(defaultValue) {
164
121
  return initializeState({
165
122
  defaultValue: defaultValue !== null && defaultValue !== void 0 ? defaultValue : options.defaultValue
@@ -169,11 +126,11 @@ function useConform(formRef, options) {
169
126
  })));
170
127
 
171
128
  // TODO: move on error handler to a new effect
172
- if (formElement && result.error) {
129
+ if (formElement && finalResult.error) {
173
130
  var _optionsRef$current$o, _optionsRef$current;
174
131
  (_optionsRef$current$o = (_optionsRef$current = optionsRef.current).onError) === null || _optionsRef$current$o === void 0 || _optionsRef$current$o.call(_optionsRef$current, {
175
132
  formElement,
176
- error: result.error,
133
+ error: finalResult.error,
177
134
  intent
178
135
  });
179
136
  }
@@ -271,7 +228,7 @@ function useConform(formRef, options) {
271
228
  value !== undefined ? (_optionsRef$current$o2 = (_optionsRef$current2 = optionsRef.current).onValidate) === null || _optionsRef$current$o2 === void 0 ? void 0 : _optionsRef$current$o2.call(_optionsRef$current2, {
272
229
  payload: value,
273
230
  error: {
274
- formErrors: [],
231
+ formErrors: null,
275
232
  fieldErrors: {}
276
233
  },
277
234
  intent: submission.intent ? deserializeIntent(submission.intent) : null,
@@ -364,279 +321,12 @@ function useConform(formRef, options) {
364
321
  return [state, handleSubmit];
365
322
  }
366
323
 
367
- /**
368
- * The main React hook for form management. Handles form state, validation, and submission
369
- * while providing access to form metadata, field objects, and form actions.
370
- *
371
- * It can be called in two ways:
372
- * - **Schema first**: Pass a schema as the first argument for automatic validation with type inference
373
- * - **Manual configuration**: Pass options with custom `onValidate` handler for manual validation
374
- *
375
- * @see https://conform.guide/api/react/future/useForm
376
- * @example Schema first setup with zod:
377
- *
378
- * ```tsx
379
- * const { form, fields } = useForm(zodSchema, {
380
- * lastResult,
381
- * shouldValidate: 'onBlur',
382
- * });
383
- *
384
- * return (
385
- * <form {...form.props}>
386
- * <input name={fields.email.name} defaultValue={fields.email.defaultValue} />
387
- * <div>{fields.email.errors}</div>
388
- * </form>
389
- * );
390
- * ```
391
- *
392
- * @example Manual configuration setup with custom validation:
393
- *
394
- * ```tsx
395
- * const { form, fields } = useForm({
396
- * onValidate({ payload, error }) {
397
- * if (!payload.email) {
398
- * error.fieldErrors.email = ['Required'];
399
- * }
400
- * return error;
401
- * }
402
- * });
403
- *
404
- * return (
405
- * <form {...form.props}>
406
- * <input name={fields.email.name} defaultValue={fields.email.defaultValue} />
407
- * <div>{fields.email.errors}</div>
408
- * </form>
409
- * );
410
- * ```
411
- */
412
-
413
- /**
414
- * @deprecated Use `useForm(schema, options)` instead for better type inference.
415
- */
416
-
417
- function useForm(schemaOrOptions, maybeOptions) {
418
- var _options$onError;
419
- var schema;
420
- var options;
421
- if (maybeOptions) {
422
- schema = schemaOrOptions;
423
- options = maybeOptions;
424
- } else {
425
- var fullOptions = schemaOrOptions;
426
- options = fullOptions;
427
- schema = fullOptions.schema;
428
- }
429
- var {
430
- id,
431
- constraint
432
- } = options;
433
- var globalOptions = useContext(GlobalFormOptionsContext);
434
- var optionsRef = useLatest(options);
435
- var globalOptionsRef = useLatest(globalOptions);
436
- var fallbackId = useId();
437
- var formId = id !== null && id !== void 0 ? id : "form-".concat(fallbackId);
438
- var [state, handleSubmit] = useConform(formId, _objectSpread2(_objectSpread2({}, options), {}, {
439
- serialize: globalOptions.serialize,
440
- intentName: globalOptions.intentName,
441
- onError: (_options$onError = options.onError) !== null && _options$onError !== void 0 ? _options$onError : focusFirstInvalidField,
442
- onValidate(ctx) {
443
- var _options$onValidate, _options$onValidate2, _options;
444
- if (schema) {
445
- var standardResult = schema['~standard'].validate(ctx.payload);
446
- if (standardResult instanceof Promise) {
447
- return standardResult.then(actualStandardResult => {
448
- if (typeof options.onValidate === 'function') {
449
- throw new Error('The "onValidate" handler is not supported when used with asynchronous schema validation.');
450
- }
451
- return resolveStandardSchemaResult(actualStandardResult);
452
- });
453
- }
454
- var resolvedResult = resolveStandardSchemaResult(standardResult);
455
- if (!options.onValidate) {
456
- return resolvedResult;
457
- }
458
-
459
- // Update the schema error in the context
460
- if (resolvedResult.error) {
461
- ctx.error = resolvedResult.error;
462
- }
463
- ctx.schemaValue = resolvedResult.value;
464
- var validateResult = resolveValidateResult(options.onValidate(ctx));
465
- if (validateResult.syncResult) {
466
- var _validateResult$syncR, _validateResult$syncR2;
467
- (_validateResult$syncR2 = (_validateResult$syncR = validateResult.syncResult).value) !== null && _validateResult$syncR2 !== void 0 ? _validateResult$syncR2 : _validateResult$syncR.value = resolvedResult.value;
468
- }
469
- if (validateResult.asyncResult) {
470
- validateResult.asyncResult = validateResult.asyncResult.then(result => {
471
- var _result$value;
472
- (_result$value = result.value) !== null && _result$value !== void 0 ? _result$value : result.value = resolvedResult.value;
473
- return result;
474
- });
475
- }
476
- return [validateResult.syncResult, validateResult.asyncResult];
477
- }
478
- return (_options$onValidate = (_options$onValidate2 = (_options = options).onValidate) === null || _options$onValidate2 === void 0 ? void 0 : _options$onValidate2.call(_options, ctx)) !== null && _options$onValidate !== void 0 ? _options$onValidate : {
479
- // To avoid conform falling back to server validation,
480
- // if neither schema nor validation handler is provided,
481
- // we just treat it as a valid client submission
482
- error: null
483
- };
484
- }
485
- }));
486
- var intent = useIntent(formId);
487
- var context = useMemo(() => ({
488
- formId,
489
- state,
490
- constraint: constraint !== null && constraint !== void 0 ? constraint : null,
491
- handleSubmit,
492
- handleInput(event) {
493
- var _optionsRef$current$o4, _optionsRef$current4, _globalOptionsRef$cur;
494
- if (!isFieldElement(event.target) || event.target.name === '' || event.target.form === null || event.target.form !== getFormElement(formId)) {
495
- return;
496
- }
497
- (_optionsRef$current$o4 = (_optionsRef$current4 = optionsRef.current).onInput) === null || _optionsRef$current$o4 === void 0 || _optionsRef$current$o4.call(_optionsRef$current4, _objectSpread2(_objectSpread2({}, event), {}, {
498
- target: event.target,
499
- currentTarget: event.target.form
500
- }));
501
- if (event.defaultPrevented) {
502
- return;
503
- }
504
- var {
505
- shouldValidate = globalOptionsRef.current.shouldValidate,
506
- shouldRevalidate = (_globalOptionsRef$cur = globalOptionsRef.current.shouldRevalidate) !== null && _globalOptionsRef$cur !== void 0 ? _globalOptionsRef$cur : shouldValidate
507
- } = optionsRef.current;
508
- if (isTouched(state, event.target.name) ? shouldRevalidate === 'onInput' : shouldValidate === 'onInput') {
509
- intent.validate(event.target.name);
510
- }
511
- },
512
- handleBlur(event) {
513
- var _optionsRef$current$o5, _optionsRef$current5, _globalOptionsRef$cur2;
514
- if (!isFieldElement(event.target) || event.target.name === '' || event.target.form === null || event.target.form !== getFormElement(formId)) {
515
- return;
516
- }
517
- (_optionsRef$current$o5 = (_optionsRef$current5 = optionsRef.current).onBlur) === null || _optionsRef$current$o5 === void 0 || _optionsRef$current$o5.call(_optionsRef$current5, _objectSpread2(_objectSpread2({}, event), {}, {
518
- target: event.target,
519
- currentTarget: event.target.form
520
- }));
521
- if (event.defaultPrevented) {
522
- return;
523
- }
524
- var {
525
- shouldValidate = globalOptionsRef.current.shouldValidate,
526
- shouldRevalidate = (_globalOptionsRef$cur2 = globalOptionsRef.current.shouldRevalidate) !== null && _globalOptionsRef$cur2 !== void 0 ? _globalOptionsRef$cur2 : shouldValidate
527
- } = optionsRef.current;
528
- if (isTouched(state, event.target.name) ? shouldRevalidate === 'onBlur' : shouldValidate === 'onBlur') {
529
- intent.validate(event.target.name);
530
- }
531
- }
532
- }), [formId, state, constraint, handleSubmit, intent, optionsRef, globalOptionsRef]);
533
- var form = useMemo(() => getFormMetadata(context, {
534
- serialize: globalOptions.serialize,
535
- extendFieldMetadata: globalOptions.defineCustomMetadata
536
- }), [context, globalOptions.serialize, globalOptions.defineCustomMetadata]);
537
- var fields = useMemo(() => getFieldset(context, {
538
- serialize: globalOptions.serialize,
539
- extendFieldMetadata: globalOptions.defineCustomMetadata
540
- }), [context, globalOptions.serialize, globalOptions.defineCustomMetadata]);
541
- return {
542
- form,
543
- fields,
544
- intent
545
- };
546
- }
547
-
548
- /**
549
- * A React hook that provides access to form-level metadata and state.
550
- * Requires `FormProvider` context when used in child components.
551
- *
552
- * @see https://conform.guide/api/react/future/useFormMetadata
553
- * @example
554
- * ```tsx
555
- * function ErrorSummary() {
556
- * const form = useFormMetadata();
557
- *
558
- * if (form.valid) return null;
559
- *
560
- * return (
561
- * <div>Please fix {Object.keys(form.fieldErrors).length} errors</div>
562
- * );
563
- * }
564
- * ```
565
- */
566
- function useFormMetadata() {
567
- var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
568
- var globalOptions = useContext(GlobalFormOptionsContext);
569
- var context = useFormContext(options.formId);
570
- var formMetadata = useMemo(() => getFormMetadata(context, {
571
- serialize: globalOptions.serialize,
572
- extendFieldMetadata: globalOptions.defineCustomMetadata
573
- }), [context, globalOptions.serialize, globalOptions.defineCustomMetadata]);
574
- return formMetadata;
575
- }
576
-
577
- /**
578
- * A React hook that provides access to a specific field's metadata and state.
579
- * Requires `FormProvider` context when used in child components.
580
- *
581
- * @see https://conform.guide/api/react/future/useField
582
- * @example
583
- * ```tsx
584
- * function FormField({ name, label }) {
585
- * const field = useField(name);
586
- *
587
- * return (
588
- * <div>
589
- * <label htmlFor={field.id}>{label}</label>
590
- * <input id={field.id} name={field.name} defaultValue={field.defaultValue} />
591
- * {field.errors && <div>{field.errors.join(', ')}</div>}
592
- * </div>
593
- * );
594
- * }
595
- * ```
596
- */
597
- function useField(name) {
598
- var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
599
- var globalOptions = useContext(GlobalFormOptionsContext);
600
- var context = useFormContext(options.formId);
601
- var field = useMemo(() => getField(context, {
602
- name,
603
- serialize: globalOptions.serialize,
604
- extendFieldMetadata: globalOptions.defineCustomMetadata
605
- }), [context, name, globalOptions.serialize, globalOptions.defineCustomMetadata]);
606
- return field;
607
- }
608
-
609
- /**
610
- * A React hook that provides an intent dispatcher for programmatic form actions.
611
- * Intent dispatchers allow you to trigger form operations like validation, field updates,
612
- * and array manipulations without manual form submission.
613
- *
614
- * @see https://conform.guide/api/react/future/useIntent
615
- * @example
616
- * ```tsx
617
- * function ResetButton() {
618
- * const buttonRef = useRef<HTMLButtonElement>(null);
619
- * const intent = useIntent(buttonRef);
620
- *
621
- * return (
622
- * <button type="button" ref={buttonRef} onClick={() => intent.reset()}>
623
- * Reset Form
624
- * </button>
625
- * );
626
- * }
627
- * ```
628
- */
629
- function useIntent(formRef) {
630
- var globalOptions = useContext(GlobalFormOptionsContext);
631
- return useMemo(() => createIntentDispatcher(() => getFormElement(formRef), globalOptions.intentName), [formRef, globalOptions.intentName]);
632
- }
633
-
634
324
  /**
635
325
  * A React hook that lets you sync the state of an input and dispatch native form events from it.
636
326
  * This is useful when emulating native input behavior — typically by rendering a hidden base control
637
327
  * and syncing it with a custom input.
638
328
  *
639
- * @example
329
+ * **Example:**
640
330
  * ```ts
641
331
  * const control = useControl(options);
642
332
  * ```
@@ -644,9 +334,7 @@ function useIntent(formRef) {
644
334
 
645
335
  function useControl() {
646
336
  var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
647
- var {
648
- observer
649
- } = useContext(GlobalFormOptionsContext);
337
+ var observer = useContext(GlobalFormsObserverContext);
650
338
  var inputRef = useRef(null);
651
339
  var formRef = useMemo(() => ({
652
340
  get current() {
@@ -711,8 +399,8 @@ function useControl() {
711
399
  eventDispatched.current[listener] = undefined;
712
400
  });
713
401
  if (listener === 'focus') {
714
- var _optionsRef$current6, _optionsRef$current6$;
715
- (_optionsRef$current6 = optionsRef.current) === null || _optionsRef$current6 === void 0 || (_optionsRef$current6$ = _optionsRef$current6.onFocus) === null || _optionsRef$current6$ === void 0 || _optionsRef$current6$.call(_optionsRef$current6);
402
+ var _optionsRef$current4, _optionsRef$current4$;
403
+ (_optionsRef$current4 = optionsRef.current) === null || _optionsRef$current4 === void 0 || (_optionsRef$current4$ = _optionsRef$current4.onFocus) === null || _optionsRef$current4$ === void 0 || _optionsRef$current4$.call(_optionsRef$current4);
716
404
  }
717
405
  }
718
406
  };
@@ -802,7 +490,7 @@ function useControl() {
802
490
  if (element.type === 'checkbox' || element.type === 'radio') {
803
491
  // React set the value as empty string incorrectly when the value is undefined
804
492
  // This make sure the checkbox value falls back to the default value "on" properly
805
- // @see https://github.com/facebook/react/issues/17590
493
+ // See https://github.com/facebook/react/issues/17590
806
494
  var value = 'value' in optionsRef.current && optionsRef.current.value ? optionsRef.current.value : 'on';
807
495
  element.value = value;
808
496
  }
@@ -820,10 +508,10 @@ function useControl() {
820
508
  inputRef.current = inputs;
821
509
  if ('defaultValue' in optionsRef.current) {
822
510
  for (var input of inputs) {
823
- var _optionsRef$current7;
511
+ var _optionsRef$current5;
824
512
  initializeField(input, {
825
513
  // We will not be uitlizing defaultChecked / value on checkbox / radio group
826
- defaultValue: (_optionsRef$current7 = optionsRef.current) === null || _optionsRef$current7 === void 0 ? void 0 : _optionsRef$current7.defaultValue
514
+ defaultValue: (_optionsRef$current5 = optionsRef.current) === null || _optionsRef$current5 === void 0 ? void 0 : _optionsRef$current5.defaultValue
827
515
  });
828
516
  }
829
517
  }
@@ -889,8 +577,9 @@ function useControl() {
889
577
  * Returns `undefined` when the form element is not available (e.g., on SSR or initial client render),
890
578
  * unless a `fallback` is provided.
891
579
  *
892
- * @see https://conform.guide/api/react/future/useFormData
893
- * @example
580
+ * See https://conform.guide/api/react/future/useFormData
581
+ *
582
+ * **Example:**
894
583
  * ```ts
895
584
  * const value = useFormData(
896
585
  * formRef,
@@ -900,9 +589,7 @@ function useControl() {
900
589
  */
901
590
 
902
591
  function useFormData(formRef, select, options) {
903
- var {
904
- observer
905
- } = useContext(GlobalFormOptionsContext);
592
+ var observer = useContext(GlobalFormsObserverContext);
906
593
  var valueRef = useRef();
907
594
  var formDataRef = useRef();
908
595
  var value = useSyncExternalStore(useCallback(callback => {
@@ -962,7 +649,7 @@ function useLatest(value) {
962
649
  * A component that renders hidden base control(s) based on the shape of defaultValue.
963
650
  * Used with useControl to sync complex values with form data.
964
651
  *
965
- * @example
652
+ * **Example:**
966
653
  * ```tsx
967
654
  * const control = useControl<{ street: string; city: string }>({
968
655
  * defaultValue: { street: '123 Main St', city: 'Anytown' },
@@ -992,7 +679,7 @@ function useLatest(value) {
992
679
  */
993
680
  var BaseControl = /*#__PURE__*/forwardRef(function BaseControl(props, ref) {
994
681
  function formatValue(value) {
995
- var serialized = serialize(value);
682
+ var serialized = defaultSerialize(value);
996
683
  if (typeof serialized === 'string') {
997
684
  return serialized;
998
685
  }
@@ -1023,7 +710,7 @@ var BaseControl = /*#__PURE__*/forwardRef(function BaseControl(props, ref) {
1023
710
  defaultValue: _defaultValue,
1024
711
  hidden: _hidden = true
1025
712
  } = props,
1026
- fieldsetProps = _objectWithoutProperties(props, _excluded2);
713
+ fieldsetProps = _objectWithoutProperties(props, _excluded);
1027
714
  return /*#__PURE__*/jsx("fieldset", _objectSpread2(_objectSpread2({}, fieldsetProps), {}, {
1028
715
  ref: ref,
1029
716
  name: name,
@@ -1038,7 +725,7 @@ var BaseControl = /*#__PURE__*/forwardRef(function BaseControl(props, ref) {
1038
725
  multiple = Array.isArray(_defaultValue2),
1039
726
  hidden: _hidden2 = true
1040
727
  } = props,
1041
- selectProps = _objectWithoutProperties(props, _excluded3);
728
+ selectProps = _objectWithoutProperties(props, _excluded2);
1042
729
  if (multiple) {
1043
730
  var defaultOptions = Array.isArray(_defaultValue2) ? _defaultValue2.map(formatValue) : [formatValue(_defaultValue2)];
1044
731
  return /*#__PURE__*/jsx("select", _objectSpread2(_objectSpread2({}, selectProps), {}, {
@@ -1068,7 +755,7 @@ var BaseControl = /*#__PURE__*/forwardRef(function BaseControl(props, ref) {
1068
755
  defaultValue: _defaultValue3,
1069
756
  hidden: _hidden3 = true
1070
757
  } = props,
1071
- textareaProps = _objectWithoutProperties(props, _excluded4);
758
+ textareaProps = _objectWithoutProperties(props, _excluded3);
1072
759
  return /*#__PURE__*/jsx("textarea", _objectSpread2(_objectSpread2({}, textareaProps), {}, {
1073
760
  defaultValue: formatValue(_defaultValue3),
1074
761
  ref: ref,
@@ -1081,7 +768,7 @@ var BaseControl = /*#__PURE__*/forwardRef(function BaseControl(props, ref) {
1081
768
  value = _defaultValue4,
1082
769
  hidden: _hidden4 = true
1083
770
  } = props,
1084
- _inputProps = _objectWithoutProperties(props, _excluded5);
771
+ _inputProps = _objectWithoutProperties(props, _excluded4);
1085
772
  return /*#__PURE__*/jsx("input", _objectSpread2(_objectSpread2({}, _inputProps), {}, {
1086
773
  ref: ref,
1087
774
  value: value,
@@ -1092,7 +779,7 @@ var BaseControl = /*#__PURE__*/forwardRef(function BaseControl(props, ref) {
1092
779
  defaultValue,
1093
780
  hidden = true
1094
781
  } = props,
1095
- inputProps = _objectWithoutProperties(props, _excluded6);
782
+ inputProps = _objectWithoutProperties(props, _excluded5);
1096
783
  return /*#__PURE__*/jsx("input", _objectSpread2(_objectSpread2({}, inputProps), {}, {
1097
784
  ref: ref,
1098
785
  defaultValue: defaultValue !== undefined ? formatValue(defaultValue) : undefined,
@@ -1100,4 +787,4 @@ var BaseControl = /*#__PURE__*/forwardRef(function BaseControl(props, ref) {
1100
787
  }));
1101
788
  });
1102
789
 
1103
- export { BaseControl, FormContextContext, FormOptionsProvider, FormProvider, GlobalFormOptionsContext, INITIAL_KEY, PreserveBoundary, useConform, useControl, useField, useForm, useFormContext, useFormData, useFormMetadata, useIntent, useLatest, useSafeLayoutEffect };
790
+ export { BaseControl, GlobalFormsObserverContext, INITIAL_KEY, PreserveBoundary, useConform, useControl, useFormData, useLatest, useSafeLayoutEffect };
@@ -1,8 +1,8 @@
1
1
  export type { FieldName, FormError, FormValue, Submission, SubmissionResult, } from '@conform-to/dom/future';
2
2
  export { getFieldValue, parseSubmission, report, isDirty, } from '@conform-to/dom/future';
3
- export type { Control, ControlOptions, BaseControlProps, DefaultValue, BaseMetadata, BaseFieldMetadata, CustomMetadata, CustomMetadataDefinition, BaseErrorShape, CustomTypes, CustomSchemaTypes, FormsConfig, FormContext, FormMetadata, FormOptions, FormRef, FieldMetadata, Fieldset, IntentDispatcher, InferBaseErrorShape, InferCustomFormMetadata, InferCustomFieldMetadata, } from './types';
4
- export { configureForms } from './forms';
5
- export { BaseControl, PreserveBoundary, FormProvider, FormOptionsProvider, useControl, useField, useForm, useFormData, useFormMetadata, useIntent, } from './hooks';
3
+ export type { Control, ControlOptions, BaseControlProps, DefaultValue, BaseFieldMetadata, CustomSchemaTypes, FormsConfig, FormContext, FormMetadata, FormOptions, FormRef, FieldMetadata, Fieldset, IntentDispatcher, InferBaseErrorShape, InferCustomFormMetadata, InferCustomFieldMetadata, } from './types';
4
+ export { configureForms, FormProvider, useForm, useFormMetadata, useField, useIntent, } from './forms';
5
+ export { BaseControl, PreserveBoundary, useControl, useFormData, } from './hooks';
6
6
  export { shape } from './util';
7
7
  export { memoize } from './memoize';
8
8
  //# sourceMappingURL=index.d.ts.map
@@ -26,16 +26,15 @@ Object.defineProperty(exports, 'report', {
26
26
  enumerable: true,
27
27
  get: function () { return future.report; }
28
28
  });
29
+ exports.FormProvider = forms.FormProvider;
29
30
  exports.configureForms = forms.configureForms;
31
+ exports.useField = forms.useField;
32
+ exports.useForm = forms.useForm;
33
+ exports.useFormMetadata = forms.useFormMetadata;
34
+ exports.useIntent = forms.useIntent;
30
35
  exports.BaseControl = hooks.BaseControl;
31
- exports.FormOptionsProvider = hooks.FormOptionsProvider;
32
- exports.FormProvider = hooks.FormProvider;
33
36
  exports.PreserveBoundary = hooks.PreserveBoundary;
34
37
  exports.useControl = hooks.useControl;
35
- exports.useField = hooks.useField;
36
- exports.useForm = hooks.useForm;
37
38
  exports.useFormData = hooks.useFormData;
38
- exports.useFormMetadata = hooks.useFormMetadata;
39
- exports.useIntent = hooks.useIntent;
40
39
  exports.shape = util.shape;
41
40
  exports.memoize = memoize.memoize;
@@ -1,5 +1,5 @@
1
1
  export { getFieldValue, isDirty, parseSubmission, report } from '@conform-to/dom/future';
2
- export { configureForms } from './forms.mjs';
3
- export { BaseControl, FormOptionsProvider, FormProvider, PreserveBoundary, useControl, useField, useForm, useFormData, useFormMetadata, useIntent } from './hooks.mjs';
2
+ export { FormProvider, configureForms, useField, useForm, useFormMetadata, useIntent } from './forms.mjs';
3
+ export { BaseControl, PreserveBoundary, useControl, useFormData } from './hooks.mjs';
4
4
  export { shape } from './util.mjs';
5
5
  export { memoize } from './memoize.mjs';
@@ -215,27 +215,39 @@ var intentHandlers = {
215
215
  console.warn('intent.insert() with `onInvalid` or `from` requires the validation result to be available synchronously. ' + 'These options are ignored because the error is not yet known.');
216
216
  return result;
217
217
  }
218
- var arrayErrors = (_result$error = result.error) === null || _result$error === void 0 ? void 0 : _result$error.fieldErrors[options.name];
219
- if (options.onInvalid === 'revert' && arrayErrors !== null && arrayErrors !== void 0 && arrayErrors.length) {
218
+ var listError = (_result$error = result.error) === null || _result$error === void 0 ? void 0 : _result$error.fieldErrors[options.name];
219
+ if (options.onInvalid === 'revert' && listError != null) {
220
220
  return _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, result), {}, {
221
221
  targetValue: undefined
222
222
  });
223
223
  }
224
224
  if (options.from !== undefined) {
225
- var _options$index2, _result$error2;
225
+ var _options$index2, _result$error2, _result$error3;
226
226
  var index = (_options$index2 = options.index) !== null && _options$index2 !== void 0 ? _options$index2 : util.getPathArray(result.submission.payload, options.name).length;
227
227
  var insertedItemPath = future.appendPath(options.name, index);
228
- var insertedItemErrors = (_result$error2 = result.error) === null || _result$error2 === void 0 ? void 0 : _result$error2.fieldErrors[insertedItemPath];
229
- if (insertedItemErrors !== null && insertedItemErrors !== void 0 && insertedItemErrors.length) {
230
- var _result$error$fieldEr, _result$error3, _result$error$formErr, _result$error4, _result$error5;
231
- var fromErrors = (_result$error$fieldEr = (_result$error3 = result.error) === null || _result$error3 === void 0 ? void 0 : _result$error3.fieldErrors[options.from]) !== null && _result$error$fieldEr !== void 0 ? _result$error$fieldEr : [];
228
+ var insertedItemError = (_result$error2 = result.error) === null || _result$error2 === void 0 ? void 0 : _result$error2.fieldErrors[insertedItemPath];
229
+ var fromFieldError = (_result$error3 = result.error) === null || _result$error3 === void 0 ? void 0 : _result$error3.fieldErrors[options.from];
230
+ if (fromFieldError != null) {
231
+ var _result$error$formErr, _result$error4, _result$error5;
232
232
  return _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, result), {}, {
233
233
  targetValue: undefined,
234
234
  error: {
235
- formErrors: (_result$error$formErr = (_result$error4 = result.error) === null || _result$error4 === void 0 ? void 0 : _result$error4.formErrors) !== null && _result$error$formErr !== void 0 ? _result$error$formErr : [],
235
+ formErrors: (_result$error$formErr = (_result$error4 = result.error) === null || _result$error4 === void 0 ? void 0 : _result$error4.formErrors) !== null && _result$error$formErr !== void 0 ? _result$error$formErr : null,
236
236
  fieldErrors: _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, (_result$error5 = result.error) === null || _result$error5 === void 0 ? void 0 : _result$error5.fieldErrors), {}, {
237
- [options.from]: [...fromErrors, ...insertedItemErrors],
238
- [insertedItemPath]: []
237
+ [insertedItemPath]: null
238
+ })
239
+ }
240
+ });
241
+ }
242
+ if (insertedItemError != null) {
243
+ var _result$error$formErr2, _result$error6, _result$error7;
244
+ return _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, result), {}, {
245
+ targetValue: undefined,
246
+ error: {
247
+ formErrors: (_result$error$formErr2 = (_result$error6 = result.error) === null || _result$error6 === void 0 ? void 0 : _result$error6.formErrors) !== null && _result$error$formErr2 !== void 0 ? _result$error$formErr2 : null,
248
+ fieldErrors: _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, (_result$error7 = result.error) === null || _result$error7 === void 0 ? void 0 : _result$error7.fieldErrors), {}, {
249
+ [options.from]: insertedItemError,
250
+ [insertedItemPath]: null
239
251
  })
240
252
  }
241
253
  });
@@ -293,7 +305,7 @@ var intentHandlers = {
293
305
  return util.updatePathValue(value, options.name, list);
294
306
  },
295
307
  apply(result, options) {
296
- var _result$error6;
308
+ var _result$error8;
297
309
  // Warn if validation result is not yet available
298
310
  if (typeof result.error === 'undefined' && options.onInvalid) {
299
311
  if (process.env.NODE_ENV !== 'production') {
@@ -302,7 +314,7 @@ var intentHandlers = {
302
314
  }
303
315
  return result;
304
316
  }
305
- if (result.targetValue && (_result$error6 = result.error) !== null && _result$error6 !== void 0 && _result$error6.fieldErrors[options.name]) {
317
+ if (result.targetValue && (_result$error8 = result.error) !== null && _result$error8 !== void 0 && _result$error8.fieldErrors[options.name]) {
306
318
  switch (options.onInvalid) {
307
319
  case 'revert':
308
320
  return _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, result), {}, {