@conform-to/react 1.18.0 → 1.19.1

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() {
@@ -699,27 +387,25 @@ function useControl() {
699
387
  return next;
700
388
  }, () => snapshotRef.current);
701
389
  useEffect(() => {
702
- var createEventListener = listener => {
703
- return event => {
704
- var _inputRef$current2;
705
- if (Array.isArray(inputRef.current) ? inputRef.current.some(item => item === event.target) : event.target instanceof Node && ((_inputRef$current2 = inputRef.current) === null || _inputRef$current2 === void 0 ? void 0 : _inputRef$current2.contains(event.target))) {
706
- var timer = eventDispatched.current[listener];
707
- if (timer) {
708
- clearTimeout(timer);
709
- }
710
- eventDispatched.current[listener] = window.setTimeout(() => {
711
- eventDispatched.current[listener] = undefined;
712
- });
713
- 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);
716
- }
390
+ var createEventListener = (listener, event) => {
391
+ var _inputRef$current2;
392
+ if (Array.isArray(inputRef.current) ? inputRef.current.some(item => item === event.target) : event.target instanceof Node && ((_inputRef$current2 = inputRef.current) === null || _inputRef$current2 === void 0 ? void 0 : _inputRef$current2.contains(event.target))) {
393
+ var timer = eventDispatched.current[listener];
394
+ if (timer) {
395
+ clearTimeout(timer);
717
396
  }
718
- };
397
+ eventDispatched.current[listener] = window.setTimeout(() => {
398
+ eventDispatched.current[listener] = undefined;
399
+ });
400
+ if (listener === 'focus') {
401
+ var _optionsRef$current4, _optionsRef$current4$;
402
+ (_optionsRef$current4 = optionsRef.current) === null || _optionsRef$current4 === void 0 || (_optionsRef$current4$ = _optionsRef$current4.onFocus) === null || _optionsRef$current4$ === void 0 || _optionsRef$current4$.call(_optionsRef$current4);
403
+ }
404
+ }
719
405
  };
720
- var inputHandler = createEventListener('change');
721
- var focusHandler = createEventListener('focus');
722
- var blurHandler = createEventListener('blur');
406
+ var inputHandler = createEventListener.bind(null, 'change');
407
+ var focusHandler = createEventListener.bind(null, 'focus');
408
+ var blurHandler = createEventListener.bind(null, 'blur');
723
409
  document.addEventListener('input', inputHandler, true);
724
410
  document.addEventListener('focusin', focusHandler, true);
725
411
  document.addEventListener('focusout', blurHandler, true);
@@ -802,7 +488,7 @@ function useControl() {
802
488
  if (element.type === 'checkbox' || element.type === 'radio') {
803
489
  // React set the value as empty string incorrectly when the value is undefined
804
490
  // This make sure the checkbox value falls back to the default value "on" properly
805
- // @see https://github.com/facebook/react/issues/17590
491
+ // See https://github.com/facebook/react/issues/17590
806
492
  var value = 'value' in optionsRef.current && optionsRef.current.value ? optionsRef.current.value : 'on';
807
493
  element.value = value;
808
494
  }
@@ -820,10 +506,10 @@ function useControl() {
820
506
  inputRef.current = inputs;
821
507
  if ('defaultValue' in optionsRef.current) {
822
508
  for (var input of inputs) {
823
- var _optionsRef$current7;
509
+ var _optionsRef$current5;
824
510
  initializeField(input, {
825
511
  // 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
512
+ defaultValue: (_optionsRef$current5 = optionsRef.current) === null || _optionsRef$current5 === void 0 ? void 0 : _optionsRef$current5.defaultValue
827
513
  });
828
514
  }
829
515
  }
@@ -889,8 +575,9 @@ function useControl() {
889
575
  * Returns `undefined` when the form element is not available (e.g., on SSR or initial client render),
890
576
  * unless a `fallback` is provided.
891
577
  *
892
- * @see https://conform.guide/api/react/future/useFormData
893
- * @example
578
+ * See https://conform.guide/api/react/future/useFormData
579
+ *
580
+ * **Example:**
894
581
  * ```ts
895
582
  * const value = useFormData(
896
583
  * formRef,
@@ -900,9 +587,7 @@ function useControl() {
900
587
  */
901
588
 
902
589
  function useFormData(formRef, select, options) {
903
- var {
904
- observer
905
- } = useContext(GlobalFormOptionsContext);
590
+ var observer = useContext(GlobalFormsObserverContext);
906
591
  var valueRef = useRef();
907
592
  var formDataRef = useRef();
908
593
  var value = useSyncExternalStore(useCallback(callback => {
@@ -962,7 +647,7 @@ function useLatest(value) {
962
647
  * A component that renders hidden base control(s) based on the shape of defaultValue.
963
648
  * Used with useControl to sync complex values with form data.
964
649
  *
965
- * @example
650
+ * **Example:**
966
651
  * ```tsx
967
652
  * const control = useControl<{ street: string; city: string }>({
968
653
  * defaultValue: { street: '123 Main St', city: 'Anytown' },
@@ -992,7 +677,7 @@ function useLatest(value) {
992
677
  */
993
678
  var BaseControl = /*#__PURE__*/forwardRef(function BaseControl(props, ref) {
994
679
  function formatValue(value) {
995
- var serialized = serialize(value);
680
+ var serialized = defaultSerialize(value);
996
681
  if (typeof serialized === 'string') {
997
682
  return serialized;
998
683
  }
@@ -1023,7 +708,7 @@ var BaseControl = /*#__PURE__*/forwardRef(function BaseControl(props, ref) {
1023
708
  defaultValue: _defaultValue,
1024
709
  hidden: _hidden = true
1025
710
  } = props,
1026
- fieldsetProps = _objectWithoutProperties(props, _excluded2);
711
+ fieldsetProps = _objectWithoutProperties(props, _excluded);
1027
712
  return /*#__PURE__*/jsx("fieldset", _objectSpread2(_objectSpread2({}, fieldsetProps), {}, {
1028
713
  ref: ref,
1029
714
  name: name,
@@ -1038,7 +723,7 @@ var BaseControl = /*#__PURE__*/forwardRef(function BaseControl(props, ref) {
1038
723
  multiple = Array.isArray(_defaultValue2),
1039
724
  hidden: _hidden2 = true
1040
725
  } = props,
1041
- selectProps = _objectWithoutProperties(props, _excluded3);
726
+ selectProps = _objectWithoutProperties(props, _excluded2);
1042
727
  if (multiple) {
1043
728
  var defaultOptions = Array.isArray(_defaultValue2) ? _defaultValue2.map(formatValue) : [formatValue(_defaultValue2)];
1044
729
  return /*#__PURE__*/jsx("select", _objectSpread2(_objectSpread2({}, selectProps), {}, {
@@ -1068,7 +753,7 @@ var BaseControl = /*#__PURE__*/forwardRef(function BaseControl(props, ref) {
1068
753
  defaultValue: _defaultValue3,
1069
754
  hidden: _hidden3 = true
1070
755
  } = props,
1071
- textareaProps = _objectWithoutProperties(props, _excluded4);
756
+ textareaProps = _objectWithoutProperties(props, _excluded3);
1072
757
  return /*#__PURE__*/jsx("textarea", _objectSpread2(_objectSpread2({}, textareaProps), {}, {
1073
758
  defaultValue: formatValue(_defaultValue3),
1074
759
  ref: ref,
@@ -1081,7 +766,7 @@ var BaseControl = /*#__PURE__*/forwardRef(function BaseControl(props, ref) {
1081
766
  value = _defaultValue4,
1082
767
  hidden: _hidden4 = true
1083
768
  } = props,
1084
- _inputProps = _objectWithoutProperties(props, _excluded5);
769
+ _inputProps = _objectWithoutProperties(props, _excluded4);
1085
770
  return /*#__PURE__*/jsx("input", _objectSpread2(_objectSpread2({}, _inputProps), {}, {
1086
771
  ref: ref,
1087
772
  value: value,
@@ -1092,7 +777,7 @@ var BaseControl = /*#__PURE__*/forwardRef(function BaseControl(props, ref) {
1092
777
  defaultValue,
1093
778
  hidden = true
1094
779
  } = props,
1095
- inputProps = _objectWithoutProperties(props, _excluded6);
780
+ inputProps = _objectWithoutProperties(props, _excluded5);
1096
781
  return /*#__PURE__*/jsx("input", _objectSpread2(_objectSpread2({}, inputProps), {}, {
1097
782
  ref: ref,
1098
783
  defaultValue: defaultValue !== undefined ? formatValue(defaultValue) : undefined,
@@ -1100,4 +785,4 @@ var BaseControl = /*#__PURE__*/forwardRef(function BaseControl(props, ref) {
1100
785
  }));
1101
786
  });
1102
787
 
1103
- export { BaseControl, FormContextContext, FormOptionsProvider, FormProvider, GlobalFormOptionsContext, INITIAL_KEY, PreserveBoundary, useConform, useControl, useField, useForm, useFormContext, useFormData, useFormMetadata, useIntent, useLatest, useSafeLayoutEffect };
788
+ 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';