@conform-to/react 1.10.1 → 1.11.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
@@ -7,7 +7,7 @@
7
7
  ╚══════╝ ╚═════╝ ╚═╝ ╚══╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝
8
8
  ```
9
9
 
10
- Version 1.10.1 / License MIT / Copyright (c) 2025 Edmund Hung
10
+ Version 1.11.0 / License MIT / Copyright (c) 2025 Edmund Hung
11
11
 
12
12
  Progressively enhance HTML forms with React. Build resilient, type-safe forms with no hassle using web standards.
13
13
 
@@ -1,6 +1,6 @@
1
1
  import { type Serialize, type SubmissionResult, serialize } from '@conform-to/dom/future';
2
2
  import { useEffect } from 'react';
3
- import type { FormContext, DefaultMetadata, IntentDispatcher, FormMetadata, Fieldset, FormOptions, FieldName, FieldMetadata, Control, Selector, UseFormDataOptions, ValidateHandler, ErrorHandler, SubmitHandler, FormState, FormRef } from './types';
3
+ import type { FormContext, IntentDispatcher, FormMetadata, Fieldset, FormOptions, FieldName, FieldMetadata, Control, Selector, UseFormDataOptions, ValidateHandler, ErrorHandler, SubmitHandler, FormState, FormRef } from './types';
4
4
  export declare const INITIAL_KEY = "INITIAL_KEY";
5
5
  export declare const FormConfig: import("react").Context<{
6
6
  intentName: string;
@@ -67,7 +67,7 @@ export declare function useConform<ErrorShape, Value = undefined>(formRef: FormR
67
67
  */
68
68
  export declare function useForm<FormShape extends Record<string, any> = Record<string, any>, ErrorShape = string, Value = undefined>(options: FormOptions<FormShape, ErrorShape, Value>): {
69
69
  form: FormMetadata<ErrorShape>;
70
- fields: Fieldset<FormShape, DefaultMetadata<ErrorShape>>;
70
+ fields: Fieldset<FormShape, ErrorShape>;
71
71
  intent: IntentDispatcher;
72
72
  };
73
73
  /**
@@ -111,9 +111,9 @@ export declare function useFormMetadata<ErrorShape = string[]>(options?: {
111
111
  * }
112
112
  * ```
113
113
  */
114
- export declare function useField<FieldShape = any>(name: FieldName<FieldShape>, options?: {
114
+ export declare function useField<FieldShape = any, ErrorShape = string>(name: FieldName<FieldShape>, options?: {
115
115
  formId?: string;
116
- }): FieldMetadata<FieldShape>;
116
+ }): FieldMetadata<FieldShape, ErrorShape>;
117
117
  /**
118
118
  * A React hook that provides an intent dispatcher for programmatic form actions.
119
119
  * Intent dispatchers allow you to trigger form operations like validation, field updates,
@@ -195,7 +195,8 @@ function useConform(formRef, options) {
195
195
  intent: submission.intent ? intent.deserializeIntent(submission.intent) : null,
196
196
  formElement,
197
197
  submitter: submitEvent.submitter,
198
- formData
198
+ formData,
199
+ schemaValue: undefined
199
200
  }) : {
200
201
  error: null
201
202
  };
@@ -339,6 +340,7 @@ function useForm(options) {
339
340
  if (resolvedResult.error) {
340
341
  ctx.error = resolvedResult.error;
341
342
  }
343
+ ctx.schemaValue = resolvedResult.value;
342
344
  var validateResult = util.resolveValidateResult(options.onValidate(ctx));
343
345
  if (validateResult.syncResult) {
344
346
  var _validateResult$syncR, _validateResult$syncR2;
@@ -191,7 +191,8 @@ function useConform(formRef, options) {
191
191
  intent: submission.intent ? deserializeIntent(submission.intent) : null,
192
192
  formElement,
193
193
  submitter: submitEvent.submitter,
194
- formData
194
+ formData,
195
+ schemaValue: undefined
195
196
  }) : {
196
197
  error: null
197
198
  };
@@ -335,6 +336,7 @@ function useForm(options) {
335
336
  if (resolvedResult.error) {
336
337
  ctx.error = resolvedResult.error;
337
338
  }
339
+ ctx.schemaValue = resolvedResult.value;
338
340
  var validateResult = resolveValidateResult(options.onValidate(ctx));
339
341
  if (validateResult.syncResult) {
340
342
  var _validateResult$syncR, _validateResult$syncR2;
@@ -1,5 +1,5 @@
1
1
  import { type ValidationAttributes, type Serialize } from '@conform-to/dom/future';
2
- import type { DefaultMetadata, FieldMetadata, FieldName, Fieldset, FormContext, FormMetadata, FormState, FormAction, UnknownIntent, ActionHandler } from './types';
2
+ import type { FieldMetadata, FieldName, Fieldset, FormContext, FormMetadata, FormState, FormAction, UnknownIntent, ActionHandler } from './types';
3
3
  export declare function initializeState<ErrorShape>(resetKey?: string): FormState<ErrorShape>;
4
4
  /**
5
5
  * Updates form state based on action type:
@@ -33,19 +33,19 @@ export declare function isValid(state: FormState<any>, name?: string): boolean;
33
33
  export declare function getConstraint(context: FormContext<any>, name: string): ValidationAttributes | undefined;
34
34
  export declare function getFormMetadata<ErrorShape>(context: FormContext<ErrorShape>, options: {
35
35
  serialize: Serialize;
36
- }): FormMetadata<ErrorShape, DefaultMetadata<ErrorShape>>;
36
+ }): FormMetadata<ErrorShape>;
37
37
  export declare function getField<FieldShape, ErrorShape = string>(context: FormContext<ErrorShape>, options: {
38
38
  name: FieldName<FieldShape>;
39
39
  serialize: Serialize;
40
40
  key?: string;
41
- }): FieldMetadata<FieldShape, DefaultMetadata<ErrorShape>>;
41
+ }): FieldMetadata<FieldShape, ErrorShape>;
42
42
  /**
43
43
  * Creates a proxy that dynamically generates field objects when properties are accessed.
44
44
  */
45
45
  export declare function getFieldset<FieldShape = Record<string, any>, ErrorShape = string>(context: FormContext<ErrorShape>, options: {
46
46
  name?: FieldName<FieldShape>;
47
47
  serialize: Serialize;
48
- }): Fieldset<FieldShape, DefaultMetadata<ErrorShape>>;
48
+ }): Fieldset<FieldShape, ErrorShape>;
49
49
  /**
50
50
  * Creates an array of field objects for list/array inputs
51
51
  */
@@ -54,5 +54,5 @@ export declare function getFieldList<FieldShape = Array<any>, ErrorShape = strin
54
54
  serialize: Serialize;
55
55
  }): FieldMetadata<[
56
56
  FieldShape
57
- ] extends [Array<infer ItemShape> | null | undefined] ? ItemShape : unknown, DefaultMetadata<ErrorShape>>[];
57
+ ] extends [Array<infer ItemShape> | null | undefined] ? ItemShape : unknown, ErrorShape>[];
58
58
  //# sourceMappingURL=state.d.ts.map
@@ -241,7 +241,7 @@ export type Combine<T> = {
241
241
  [K in keyof BaseCombine<T>]: BaseCombine<T>[K];
242
242
  };
243
243
  /** Field metadata object containing field state, validation attributes, and nested field access methods. */
244
- export type FieldMetadata<FieldShape, Metadata extends Record<string, unknown> = DefaultMetadata<unknown>> = Readonly<Metadata & {
244
+ export type FieldMetadata<FieldShape, ErrorShape = string> = Readonly<DefaultMetadata<ErrorShape> & {
245
245
  /** Unique key for React list rendering (for array fields). */
246
246
  key: string | undefined;
247
247
  /** The field name path exactly as provided. */
@@ -249,19 +249,18 @@ export type FieldMetadata<FieldShape, Metadata extends Record<string, unknown> =
249
249
  /** Method to get nested fieldset for object fields under this field. */
250
250
  getFieldset(): Fieldset<[
251
251
  FieldShape
252
- ] extends [Record<string, unknown> | null | undefined] ? FieldShape : unknown, Metadata>;
252
+ ] extends [Record<string, unknown> | null | undefined] ? FieldShape : unknown, ErrorShape>;
253
253
  /** Method to get array of fields for list/array fields under this field. */
254
254
  getFieldList(): Array<FieldMetadata<[
255
255
  FieldShape
256
- ] extends [Array<infer ItemShape> | null | undefined] ? ItemShape : unknown, Metadata>>;
256
+ ] extends [Array<infer ItemShape> | null | undefined] ? ItemShape : unknown, ErrorShape>>;
257
257
  }>;
258
258
  /** Fieldset object containing all form fields as properties with their respective field metadata. */
259
- export type Fieldset<FieldShape, // extends Record<string, unknown>,
260
- Metadata extends Record<string, unknown>> = {
261
- [Key in keyof Combine<FieldShape>]-?: FieldMetadata<Combine<FieldShape>[Key], Metadata>;
259
+ export type Fieldset<FieldShape, ErrorShape = string> = {
260
+ [Key in keyof Combine<FieldShape>]-?: FieldMetadata<Combine<FieldShape>[Key], ErrorShape>;
262
261
  };
263
262
  /** Form-level metadata and state object containing validation status, errors, and field access methods. */
264
- export type FormMetadata<ErrorShape, Metadata extends Record<string, unknown> = DefaultMetadata<ErrorShape>> = Readonly<{
263
+ export type FormMetadata<ErrorShape = string> = Readonly<{
265
264
  /** Unique identifier that changes on form reset */
266
265
  key: string;
267
266
  /** The form's unique identifier. */
@@ -291,15 +290,15 @@ export type FormMetadata<ErrorShape, Metadata extends Record<string, unknown> =
291
290
  /** The current state of the form */
292
291
  context: FormContext<ErrorShape>;
293
292
  /** Method to get metadata for a specific field by name. */
294
- getField<FieldShape>(name: FieldName<FieldShape>): FieldMetadata<FieldShape, Metadata>;
293
+ getField<FieldShape>(name: FieldName<FieldShape>): FieldMetadata<FieldShape, ErrorShape>;
295
294
  /** Method to get a fieldset object for nested object fields. */
296
295
  getFieldset<FieldShape>(name?: FieldName<FieldShape>): Fieldset<[
297
296
  FieldShape
298
- ] extends [Record<string, unknown> | null | undefined] ? FieldShape : unknown, Metadata>;
297
+ ] extends [Record<string, unknown> | null | undefined] ? FieldShape : unknown, ErrorShape>;
299
298
  /** Method to get an array of field objects for array fields. */
300
299
  getFieldList<FieldShape>(name: FieldName<FieldShape>): Array<FieldMetadata<[
301
300
  FieldShape
302
- ] extends [Array<infer ItemShape> | null | undefined] ? ItemShape : unknown, Metadata>>;
301
+ ] extends [Array<infer ItemShape> | null | undefined] ? ItemShape : unknown, ErrorShape>>;
303
302
  }>;
304
303
  /** Default field metadata object containing field state, validation attributes, and accessibility IDs. */
305
304
  export type DefaultMetadata<ErrorShape> = Readonly<ValidationAttributes & {
@@ -332,15 +331,40 @@ export type ValidateResult<ErrorShape, Value> = FormError<ErrorShape> | null | {
332
331
  error: FormError<ErrorShape> | null;
333
332
  value?: Value;
334
333
  };
335
- export type ValidateContext = {
334
+ export type ValidateContext<Value> = {
335
+ /**
336
+ * The submitted values mapped by field name.
337
+ * Supports nested names like `user.email` and indexed names like `items[0].id`.
338
+ */
336
339
  payload: Record<string, FormValue>;
340
+ /**
341
+ * Form error object. Initially empty, but populated with schema validation
342
+ * errors when a schema is provided and validation fails.
343
+ */
337
344
  error: FormError<string>;
345
+ /**
346
+ * The submission intent derived from the button that triggered the form submission.
347
+ */
338
348
  intent: UnknownIntent | null;
349
+ /**
350
+ * The raw FormData object of the submission.
351
+ */
339
352
  formData: FormData;
353
+ /**
354
+ * Reference to the HTML form element that triggered the submission.
355
+ */
340
356
  formElement: HTMLFormElement;
357
+ /**
358
+ * The specific element (button/input) that triggered the form submission.
359
+ */
341
360
  submitter: HTMLElement | null;
361
+ /**
362
+ * The validated value from schema validation. Only defined when a schema is provided
363
+ * and the validation succeeds. Undefined if no schema is provided or validation fails.
364
+ */
365
+ schemaValue: Value | undefined;
342
366
  };
343
- export type ValidateHandler<ErrorShape, Value> = (ctx: ValidateContext) => ValidateResult<ErrorShape, Value> | Promise<ValidateResult<ErrorShape, Value>> | [
367
+ export type ValidateHandler<ErrorShape, Value> = (ctx: ValidateContext<Value>) => ValidateResult<ErrorShape, Value> | Promise<ValidateResult<ErrorShape, Value>> | [
344
368
  ValidateResult<ErrorShape, Value> | undefined,
345
369
  Promise<ValidateResult<ErrorShape, Value>> | undefined
346
370
  ] | undefined;
@@ -41,7 +41,6 @@ export declare function resolveValidateResult<ErrorShape, Value>(result: ReturnT
41
41
  value?: Value | undefined;
42
42
  }> | undefined;
43
43
  };
44
- export declare function resolveStandardSchemaPath(issue: StandardSchemaV1.Issue): Array<string | number>;
45
44
  export declare function resolveStandardSchemaResult<Value>(result: StandardSchemaV1.Result<Value>): {
46
45
  error: FormError<string> | null;
47
46
  value?: Value;
@@ -2,10 +2,8 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var _rollupPluginBabelHelpers = require('../_virtual/_rollupPluginBabelHelpers.js');
6
5
  var future = require('@conform-to/dom/future');
7
6
 
8
- var _excluded = [""];
9
7
  function isUndefined(value) {
10
8
  return value === undefined;
11
9
  }
@@ -117,16 +115,6 @@ function resolveValidateResult(result) {
117
115
  asyncResult: asyncResult ? asyncResult.then(normalizeValidateResult) : undefined
118
116
  };
119
117
  }
120
- function resolveStandardSchemaPath(issue) {
121
- if (!issue.path) {
122
- return [];
123
- }
124
- var segments = issue.path.map(segment => typeof segment === 'object' && 'key' in segment ? segment.key : segment);
125
- if (!segments.every(segment => typeof segment !== 'symbol')) {
126
- throw new Error('Path segments must not contain symbols. Use strings or numbers instead.');
127
- }
128
- return segments;
129
- }
130
118
  function resolveStandardSchemaResult(result) {
131
119
  if (!result.issues) {
132
120
  return {
@@ -134,23 +122,8 @@ function resolveStandardSchemaResult(result) {
134
122
  value: result.value
135
123
  };
136
124
  }
137
- var errorByName = {};
138
- for (var issue of result.issues) {
139
- var _errorByName$_name;
140
- var path = resolveStandardSchemaPath(issue);
141
- var _name = future.formatPathSegments(path);
142
- (_errorByName$_name = errorByName[_name]) !== null && _errorByName$_name !== void 0 ? _errorByName$_name : errorByName[_name] = [];
143
- errorByName[_name].push(issue.message);
144
- }
145
- var {
146
- '': formErrors = []
147
- } = errorByName,
148
- fieldErrors = _rollupPluginBabelHelpers.objectWithoutProperties(errorByName, _excluded);
149
125
  return {
150
- error: {
151
- formErrors,
152
- fieldErrors
153
- }
126
+ error: future.formatIssues(result.issues)
154
127
  };
155
128
  }
156
129
 
@@ -174,9 +147,9 @@ function merge(obj, update) {
174
147
  function transformKeys(obj, fn) {
175
148
  var result = {};
176
149
  for (var [_key, _value] of Object.entries(obj)) {
177
- var _name2 = fn(_key);
178
- if (_name2 !== null) {
179
- result[_name2] = _value;
150
+ var _name = fn(_key);
151
+ if (_name !== null) {
152
+ result[_name] = _value;
180
153
  }
181
154
  }
182
155
  return result;
@@ -222,7 +195,6 @@ exports.isUndefined = isUndefined;
222
195
  exports.merge = merge;
223
196
  exports.normalizeFormError = normalizeFormError;
224
197
  exports.normalizeValidateResult = normalizeValidateResult;
225
- exports.resolveStandardSchemaPath = resolveStandardSchemaPath;
226
198
  exports.resolveStandardSchemaResult = resolveStandardSchemaResult;
227
199
  exports.resolveValidateResult = resolveValidateResult;
228
200
  exports.transformKeys = transformKeys;
@@ -1,7 +1,5 @@
1
- import { objectWithoutProperties as _objectWithoutProperties } from '../_virtual/_rollupPluginBabelHelpers.mjs';
2
- import { formatPathSegments, getValueAtPath, isPlainObject, setValueAtPath, getPathSegments } from '@conform-to/dom/future';
1
+ import { formatIssues, getValueAtPath, isPlainObject, setValueAtPath, getPathSegments, formatPathSegments } from '@conform-to/dom/future';
3
2
 
4
- var _excluded = [""];
5
3
  function isUndefined(value) {
6
4
  return value === undefined;
7
5
  }
@@ -113,16 +111,6 @@ function resolveValidateResult(result) {
113
111
  asyncResult: asyncResult ? asyncResult.then(normalizeValidateResult) : undefined
114
112
  };
115
113
  }
116
- function resolveStandardSchemaPath(issue) {
117
- if (!issue.path) {
118
- return [];
119
- }
120
- var segments = issue.path.map(segment => typeof segment === 'object' && 'key' in segment ? segment.key : segment);
121
- if (!segments.every(segment => typeof segment !== 'symbol')) {
122
- throw new Error('Path segments must not contain symbols. Use strings or numbers instead.');
123
- }
124
- return segments;
125
- }
126
114
  function resolveStandardSchemaResult(result) {
127
115
  if (!result.issues) {
128
116
  return {
@@ -130,23 +118,8 @@ function resolveStandardSchemaResult(result) {
130
118
  value: result.value
131
119
  };
132
120
  }
133
- var errorByName = {};
134
- for (var issue of result.issues) {
135
- var _errorByName$_name;
136
- var path = resolveStandardSchemaPath(issue);
137
- var _name = formatPathSegments(path);
138
- (_errorByName$_name = errorByName[_name]) !== null && _errorByName$_name !== void 0 ? _errorByName$_name : errorByName[_name] = [];
139
- errorByName[_name].push(issue.message);
140
- }
141
- var {
142
- '': formErrors = []
143
- } = errorByName,
144
- fieldErrors = _objectWithoutProperties(errorByName, _excluded);
145
121
  return {
146
- error: {
147
- formErrors,
148
- fieldErrors
149
- }
122
+ error: formatIssues(result.issues)
150
123
  };
151
124
  }
152
125
 
@@ -170,9 +143,9 @@ function merge(obj, update) {
170
143
  function transformKeys(obj, fn) {
171
144
  var result = {};
172
145
  for (var [_key, _value] of Object.entries(obj)) {
173
- var _name2 = fn(_key);
174
- if (_name2 !== null) {
175
- result[_name2] = _value;
146
+ var _name = fn(_key);
147
+ if (_name !== null) {
148
+ result[_name] = _value;
176
149
  }
177
150
  }
178
151
  return result;
@@ -206,4 +179,4 @@ function generateUniqueKey() {
206
179
  return Math.trunc(Date.now() * Math.random()).toString(36);
207
180
  }
208
181
 
209
- export { appendUniqueItem, compactMap, createPathIndexUpdater, generateUniqueKey, getArrayAtPath, isNumber, isOptional, isString, isUndefined, merge, normalizeFormError, normalizeValidateResult, resolveStandardSchemaPath, resolveStandardSchemaResult, resolveValidateResult, transformKeys, updateValueAtPath };
182
+ export { appendUniqueItem, compactMap, createPathIndexUpdater, generateUniqueKey, getArrayAtPath, isNumber, isOptional, isString, isUndefined, merge, normalizeFormError, normalizeValidateResult, resolveStandardSchemaResult, resolveValidateResult, transformKeys, updateValueAtPath };
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "Conform view adapter for react",
4
4
  "homepage": "https://conform.guide",
5
5
  "license": "MIT",
6
- "version": "1.10.1",
6
+ "version": "1.11.0",
7
7
  "main": "./dist/index.js",
8
8
  "module": "./dist/index.mjs",
9
9
  "types": "./dist/index.d.ts",
@@ -41,7 +41,7 @@
41
41
  "url": "https://github.com/edmundhung/conform/issues"
42
42
  },
43
43
  "dependencies": {
44
- "@conform-to/dom": "1.10.1"
44
+ "@conform-to/dom": "1.11.0"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@babel/core": "^7.17.8",