@conform-to/dom 1.17.1 → 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.
package/dist/form.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { objectSpread2 as _objectSpread2 } from './_virtual/_rollupPluginBabelHelpers.mjs';
2
- import { appendPathSegment, getValueAtPath, isPrefix, setValueAtPath, getFormData, getPathSegments, getRelativePath, formatPathSegments } from './formdata.mjs';
2
+ import { appendPath, getPathValue, isPathPrefix, setPathValue, getFormData, parsePath, getRelativePath, formatPath } from './formdata.mjs';
3
3
  import { getFormAction, getFormEncType, getFormMethod, isFieldElement, requestSubmit, isDirtyInput, updateField } from './dom.mjs';
4
4
  import { generateId, clone, isPlainObject, invariant } from './util.mjs';
5
5
  import { serialize, flatten, setListState, setListValue, setState, normalize, INTENT, serializeIntent, root, getSubmissionContext } from './submission.mjs';
@@ -39,7 +39,7 @@ function getDefaultKey(defaultValue, prefix) {
39
39
  var [key, value] = _ref2;
40
40
  if (Array.isArray(value)) {
41
41
  for (var i = 0; i < value.length; i++) {
42
- result[appendPathSegment(key, i)] = generateId();
42
+ result[appendPath(key, i)] = generateId();
43
43
  }
44
44
  }
45
45
  return result;
@@ -72,7 +72,7 @@ function handleIntent(meta, intent, fields, initialized) {
72
72
  validated,
73
73
  value
74
74
  } = intent.payload;
75
- var _name2 = appendPathSegment(intent.payload.name, intent.payload.index);
75
+ var _name2 = appendPath(intent.payload.name, intent.payload.index);
76
76
  if (typeof value !== 'undefined') {
77
77
  updateValue(meta, _name2 !== null && _name2 !== void 0 ? _name2 : '', value);
78
78
  }
@@ -101,8 +101,8 @@ function handleIntent(meta, intent, fields, initialized) {
101
101
  }
102
102
  case 'reset':
103
103
  {
104
- var _name3 = appendPathSegment(intent.payload.name, intent.payload.index);
105
- var _value = getValueAtPath(meta.defaultValue, _name3);
104
+ var _name3 = appendPath(intent.payload.name, intent.payload.index);
105
+ var _value = getPathValue(meta.defaultValue, _name3);
106
106
  updateValue(meta, _name3, _value);
107
107
  if (_name3) {
108
108
  setState(meta.validated, _name3, () => undefined);
@@ -137,7 +137,7 @@ function handleIntent(meta, intent, fields, initialized) {
137
137
  var validatedFields = (_fields$filter = fields === null || fields === void 0 ? void 0 : fields.filter(name => meta.validated[name])) !== null && _fields$filter !== void 0 ? _fields$filter : [];
138
138
  meta.error = Object.entries(meta.error).reduce((result, _ref3) => {
139
139
  var [name, error] = _ref3;
140
- if (meta.validated[name] || validatedFields.some(field => isPrefix(name, field))) {
140
+ if (meta.validated[name] || validatedFields.some(field => isPathPrefix(name, field))) {
141
141
  result[name] = error;
142
142
  }
143
143
  return result;
@@ -155,8 +155,8 @@ function updateValue(meta, name, value) {
155
155
  meta.initialValue = clone(meta.initialValue);
156
156
  meta.value = clone(meta.value);
157
157
  meta.key = clone(meta.key);
158
- setValueAtPath(meta.initialValue, name, () => value);
159
- setValueAtPath(meta.value, name, () => value);
158
+ setPathValue(meta.initialValue, name, () => value);
159
+ setPathValue(meta.value, name, () => value);
160
160
  if (isPlainObject(value) || Array.isArray(value)) {
161
161
  setState(meta.key, name, () => undefined);
162
162
  Object.assign(meta.key, getDefaultKey(value, name));
@@ -181,11 +181,11 @@ function createValueProxy(value) {
181
181
  if (name === '') {
182
182
  return val;
183
183
  }
184
- var path = getPathSegments(name);
185
- var basename = formatPathSegments(path.slice(0, -1));
186
- var key = formatPathSegments(path.slice(-1));
184
+ var path = parsePath(name);
185
+ var basename = formatPath(path.slice(0, -1));
186
+ var key = formatPath(path.slice(-1));
187
187
  var parentValue = proxy[basename];
188
- return getValueAtPath(parentValue, key);
188
+ return getPathValue(parentValue, key);
189
189
  });
190
190
  }
191
191
  function createConstraintProxy(constraint) {
@@ -193,7 +193,7 @@ function createConstraintProxy(constraint) {
193
193
  var _result;
194
194
  var result = constraint[name];
195
195
  if (!result) {
196
- var path = getPathSegments(name);
196
+ var path = parsePath(name);
197
197
  for (var i = path.length - 1; i >= 0; i--) {
198
198
  var segment = path[i];
199
199
 
@@ -206,7 +206,7 @@ function createConstraintProxy(constraint) {
206
206
  break;
207
207
  }
208
208
  }
209
- var alternative = formatPathSegments(path);
209
+ var alternative = formatPath(path);
210
210
  if (name !== alternative) {
211
211
  result = proxy[alternative];
212
212
  }
@@ -217,11 +217,11 @@ function createConstraintProxy(constraint) {
217
217
  function createKeyProxy(key) {
218
218
  return createStateProxy((name, proxy) => {
219
219
  var currentKey = key[name];
220
- var segments = getPathSegments(name);
220
+ var segments = parsePath(name);
221
221
  if (segments.length === 0) {
222
222
  return currentKey;
223
223
  }
224
- var parentKey = proxy[formatPathSegments(segments.slice(0, -1))];
224
+ var parentKey = proxy[formatPath(segments.slice(0, -1))];
225
225
  if (typeof parentKey === 'undefined') {
226
226
  return currentKey;
227
227
  }
@@ -235,7 +235,7 @@ function createValidProxy(error) {
235
235
  return keys.length === 0;
236
236
  }
237
237
  for (var key of keys) {
238
- if (isPrefix(key, name) && typeof error[key] !== 'undefined') {
238
+ if (isPathPrefix(key, name) && typeof error[key] !== 'undefined') {
239
239
  return false;
240
240
  }
241
241
  }
@@ -266,7 +266,7 @@ function shouldNotify(prev, next, cache, scope) {
266
266
  var names = (_scope$name = scope.name) !== null && _scope$name !== void 0 ? _scope$name : [];
267
267
  var list = prefixes.length === 0 ? names : Array.from(new Set([...Object.keys(prev), ...Object.keys(next)]));
268
268
  var _loop = function _loop(_name4) {
269
- if (prefixes.length === 0 || names.includes(_name4) || prefixes.some(prefix => isPrefix(_name4, prefix))) {
269
+ if (prefixes.length === 0 || names.includes(_name4) || prefixes.some(prefix => isPathPrefix(_name4, prefix))) {
270
270
  var _cache$_name;
271
271
  (_cache$_name = cache[_name4]) !== null && _cache$_name !== void 0 ? _cache$_name : cache[_name4] = compareFn(prev[_name4], next[_name4]);
272
272
  if (cache[_name4]) {
@@ -576,13 +576,13 @@ function createFormContext(options) {
576
576
  switch (intent.type) {
577
577
  case 'update':
578
578
  {
579
- var _name5 = appendPathSegment(intent.payload.name, intent.payload.index);
580
- var baseSegments = getPathSegments(_name5);
579
+ var _name5 = appendPath(intent.payload.name, intent.payload.index);
580
+ var baseSegments = parsePath(_name5);
581
581
  for (var element of formElement.elements) {
582
582
  if (isFieldElement(element)) {
583
583
  var paths = getRelativePath(element.name, baseSegments);
584
584
  if (paths) {
585
- var value = getValueAtPath(intent.payload.value, paths);
585
+ var value = getPathValue(intent.payload.value, paths);
586
586
  var inputValue = typeof value === 'string' || Array.isArray(value) && value.every(item => typeof item === 'string') ? value : undefined;
587
587
  if (typeof inputValue !== 'undefined' || _name5 === '' && paths.length > 1) {
588
588
  updateField(element, {
@@ -599,10 +599,10 @@ function createFormContext(options) {
599
599
  }
600
600
  case 'reset':
601
601
  {
602
- var prefix = appendPathSegment(intent.payload.name, intent.payload.index);
602
+ var prefix = appendPath(intent.payload.name, intent.payload.index);
603
603
  for (var _element of formElement.elements) {
604
- if (isFieldElement(_element) && _element.name && isPrefix(_element.name, prefix)) {
605
- var _value2 = getValueAtPath(meta.defaultValue, _element.name);
604
+ if (isFieldElement(_element) && _element.name && isPathPrefix(_element.name, prefix)) {
605
+ var _value2 = getPathValue(meta.defaultValue, _element.name);
606
606
  var defaultValue = typeof _value2 === 'string' || Array.isArray(_value2) && _value2.every(item => typeof item === 'string') ? _value2 : undefined;
607
607
  if (typeof defaultValue === 'undefined' && !_element.dataset.conform && 'defaultValue' in _element && !isDirtyInput(_element)) {
608
608
  continue;
@@ -1,36 +1,47 @@
1
- import type { FormValue, FieldName, JsonPrimitive, Serialize, SerializedValue, Submission, SubmissionResult, UnknownObject } from './types';
2
- import type { StandardSchemaIssue } from './standard-schema';
1
+ import type { FormError, FormValue, FieldName, JsonPrimitive, CustomSerialize, Submission, SubmissionResult, UnknownObject, Serialize, StandardSchemaError, CustomError } from './types';
3
2
  export declare const DEFAULT_INTENT_NAME = "__INTENT__";
3
+ /**
4
+ * Returns whether an error payload contains a meaningful value.
5
+ * Empty strings and empty arrays are treated as no error.
6
+ */
7
+ export declare function hasError<ErrorShape>(error: ErrorShape | null | undefined): error is ErrorShape;
8
+ /**
9
+ * Normalizes a form error object by removing empty error payloads such as
10
+ * empty strings and empty arrays.
11
+ *
12
+ * Returns `null` when no form-level or field-level errors remain.
13
+ */
14
+ export declare function normalizeFormError<ErrorShape>(error: CustomError<ErrorShape> | null): FormError<ErrorShape> | null;
4
15
  /**
5
16
  * Construct a form data with the submitter value.
6
17
  * It utilizes the submitter argument on the FormData constructor from modern browsers
7
18
  * with fallback to append the submitter value in case it is not unsupported.
8
19
  *
9
- * @see https://developer.mozilla.org/en-US/docs/Web/API/FormData/FormData#parameters
20
+ * See https://developer.mozilla.org/en-US/docs/Web/API/FormData/FormData#parameters
10
21
  */
11
22
  export declare function getFormData(form: HTMLFormElement, submitter?: HTMLElement | null): FormData;
12
23
  /**
13
24
  * Convert a string path into an array of segments.
14
25
  *
15
- * @example
26
+ * **Example:**
16
27
  * ```js
17
- * getPathSegments("object.key"); // → ['object', 'key']
18
- * getPathSegments("array[0].content"); // → ['array', 0, 'content']
19
- * getPathSegments("todos[]"); // → ['todos', '']
28
+ * parsePath("object.key"); // → ['object', 'key']
29
+ * parsePath("array[0].content"); // → ['array', 0, 'content']
30
+ * parsePath("todos[]"); // → ['todos', '']
20
31
  * ```
21
32
  */
22
- export declare function getPathSegments(path: string | undefined): Array<string | number>;
33
+ export declare function parsePath(path: string | undefined): Array<string | number>;
23
34
  /**
24
35
  * Returns a formatted name from the path segments based on the dot and bracket notation.
25
36
  *
26
- * @example
37
+ * **Example:**
27
38
  * ```js
28
- * formatPathSegments(['object', 'key']); // → "object.key"
29
- * formatPathSegments(['array', 0, 'content']); // → "array[0].content"
30
- * formatPathSegments(['todos', '']); // → "todos[]"
39
+ * formatPath(['object', 'key']); // → "object.key"
40
+ * formatPath(['array', 0, 'content']); // → "array[0].content"
41
+ * formatPath(['todos', '']); // → "todos[]"
31
42
  * ```
32
43
  */
33
- export declare function formatPathSegments(segments: Readonly<Array<string | number>>): string;
44
+ export declare function formatPath(segments: Readonly<Array<string | number>>): string;
34
45
  /**
35
46
  * Append one more segment onto an existing path string.
36
47
  *
@@ -39,53 +50,54 @@ export declare function formatPathSegments(segments: Readonly<Array<string | num
39
50
  * - segment = `number` ⇒ bracket notation "[n]"
40
51
  * - segment = `string` ⇒ dot-notation ".prop"
41
52
  */
42
- export declare function appendPathSegment(path: string | undefined, segment: string | number | undefined): string;
53
+ export declare function appendPath(path: string | undefined, segment: string | number | undefined): string;
43
54
  /**
44
55
  * Returns true if `prefix` is a valid leading path of `name`.
45
56
  *
46
- * @example
57
+ * **Example:**
47
58
  * ```js
48
- * isPrefix("foo.bar.baz", "foo.bar") // → true
49
- * isPrefix("foo.bar[3].baz", "foo.bar[3]") // → true
50
- * isPrefix("foo.bar[3].baz", "foo.bar") // → true
51
- * isPrefix("foo.bar[3].baz", "foo.baz") // → false
52
- * isPrefix("foo", "foo.bar") // → false
59
+ * isPathPrefix("foo.bar.baz", "foo.bar") // → true
60
+ * isPathPrefix("foo.bar[3].baz", "foo.bar[3]") // → true
61
+ * isPathPrefix("foo.bar[3].baz", "foo.bar") // → true
62
+ * isPathPrefix("foo.bar[3].baz", "foo.baz") // → false
63
+ * isPathPrefix("foo", "foo.bar") // → false
53
64
  * ```
54
65
  */
55
- export declare function isPrefix(name: string, prefix: string): boolean;
66
+ export declare function isPathPrefix(name: string, prefix: string): boolean;
56
67
  /**
57
- * Return the segments of `fullPathStr` that come after the `baseSegments` prefix.
68
+ * Return the segments of `fullPath` that come after the `basePath` prefix.
58
69
  *
59
- * @param fullPathStr Full path as a dot/bracket string
60
- * @param basePath Base path, already parsed into segments
61
- * @returns The “tail” segments, or `null` if `fullPathStr` isn’t nested under `baseSegments`
70
+ * @param fullPath Full path as a dot/bracket string or array of segments
71
+ * @param basePath Base path as a dot/bracket string or array of segments
72
+ * @returns The “tail” segments, or `null` if `fullPath` isn’t nested under `basePath`
62
73
  *
63
- * @example
74
+ * **Example:**
64
75
  * ```js
65
76
  * getRelativePath("foo.bar[0].qux", ["foo","bar"]) // → [0, "qux"]
66
77
  * getRelativePath("a.b.c.d", ["a","b"]) // → ["c","d"]
67
78
  * getRelativePath("foo", ["foo","bar"]) // → null
68
79
  * ```
69
80
  */
70
- export declare function getRelativePath(name: string, basePath: Array<string | number>): Array<string | number> | null;
81
+ export declare function getRelativePath(fullPath: string | Array<string | number>, basePath: string | Array<string | number>): Array<string | number> | null;
71
82
  /**
72
83
  * Assign a value to a target object by following the path segments.
73
84
  */
74
- export declare function setValueAtPath<T extends Record<string, any>>(target: T, pathOrSegments: string | Array<string | number>, valueOrFn: unknown | ((current: unknown) => unknown), options?: {
85
+ export declare function setPathValue<T extends Record<string, any>>(target: T, pathOrSegments: string | Array<string | number>, valueOrFn: unknown | ((current: unknown) => unknown), options?: {
75
86
  clone?: boolean;
76
87
  silent?: boolean;
77
88
  }): T;
78
89
  /**
79
90
  * Retrive the value from a target object by following the path segments.
80
91
  */
81
- export declare function getValueAtPath(target: unknown, pathOrSegments: string | Array<string | number>): unknown;
92
+ export declare function getPathValue(target: unknown, pathOrSegments: string | Array<string | number>): unknown;
82
93
  /**
83
94
  * Parse `FormData` or `URLSearchParams` into a submission object.
84
95
  * This function structures the form values based on the naming convention.
85
96
  * It also includes all the field names and extracts the intent from the submission.
86
97
  *
87
- * @see https://conform.guide/api/react/future/parseSubmission
88
- * @example
98
+ * See https://conform.guide/api/react/future/parseSubmission
99
+ *
100
+ * **Example:**
89
101
  * ```ts
90
102
  * const formData = new FormData();
91
103
  *
@@ -122,8 +134,11 @@ export declare function parseSubmission(formData: FormData | URLSearchParams, op
122
134
  skipEntry?: (name: string) => boolean;
123
135
  /**
124
136
  * Whether to strip empty values (empty strings, empty files, arrays with all empty values)
125
- * from the submission payload. Defaults to `true`.
126
- * Set to `false` to preserve empty values in the payload.
137
+ * from the submission payload. Defaults to `false`.
138
+ *
139
+ * @deprecated This option will be removed in a future minor release.
140
+ * If you are using a schema library like Zod or Valibot, our integration
141
+ * already strips empty values for you. There is no need to use this option.
127
142
  */
128
143
  stripEmptyValues?: boolean;
129
144
  }): Submission;
@@ -133,8 +148,9 @@ export declare function parseSubmission(formData: FormData | URLSearchParams, op
133
148
  * file inputs cannot be initialized with files.
134
149
  * You can specify `keepFiles: true` to keep the files if needed.
135
150
  *
136
- * @see https://conform.guide/api/react/future/report
137
- * @example
151
+ * See https://conform.guide/api/react/future/report
152
+ *
153
+ * **Example:**
138
154
  * ```ts
139
155
  * // Report the submission with the field errors
140
156
  * report(submission, {
@@ -158,55 +174,61 @@ export declare function parseSubmission(formData: FormData | URLSearchParams, op
158
174
  * })
159
175
  * ```
160
176
  */
161
- export declare function report<ErrorShape = string>(submission: Submission, options?: {
177
+ export declare function report<ErrorShape>(submission: Submission, options: {
162
178
  keepFiles?: false;
163
- error?: {
164
- issues?: undefined;
165
- formErrors?: ErrorShape[];
166
- fieldErrors?: Record<string, ErrorShape[]>;
167
- } | null;
179
+ error: CustomError<ErrorShape>;
168
180
  value?: Record<string, FormValue> | null;
169
181
  hideFields?: string[];
170
182
  reset?: boolean;
171
183
  }): SubmissionResult<ErrorShape, Exclude<JsonPrimitive | FormDataEntryValue, File>>;
172
- export declare function report<ErrorShape = string>(submission: Submission, options: {
184
+ export declare function report<ErrorShape>(submission: Submission, options: {
173
185
  keepFiles: true;
174
- error?: {
175
- issues?: undefined;
176
- formErrors?: ErrorShape[];
177
- fieldErrors?: Record<string, ErrorShape[]>;
178
- } | null;
186
+ error: CustomError<ErrorShape>;
179
187
  value?: Record<string, FormValue> | null;
180
188
  hideFields?: string[];
181
189
  reset?: boolean;
182
190
  }): SubmissionResult<ErrorShape>;
183
- export declare function report(submission: Submission, options?: {
191
+ export declare function report(submission: Submission, options: {
184
192
  keepFiles?: false;
185
- error?: {
186
- issues: ReadonlyArray<StandardSchemaIssue>;
187
- formErrors?: string[];
188
- fieldErrors?: Record<string, string[]>;
189
- };
193
+ error: StandardSchemaError;
190
194
  value?: Record<string, FormValue> | null;
191
195
  hideFields?: string[];
192
196
  reset?: boolean;
193
- }): SubmissionResult<string, Exclude<JsonPrimitive | FormDataEntryValue, File>>;
197
+ }): SubmissionResult<string[], Exclude<JsonPrimitive | FormDataEntryValue, File>>;
198
+ export declare function report(submission: Submission, options: {
199
+ keepFiles: true;
200
+ error: StandardSchemaError;
201
+ value?: Record<string, FormValue> | null;
202
+ hideFields?: string[];
203
+ reset?: boolean;
204
+ }): SubmissionResult<string[]>;
194
205
  export declare function report(submission: Submission, options?: {
206
+ keepFiles?: false;
207
+ error?: null;
208
+ value?: Record<string, FormValue> | null;
209
+ hideFields?: string[];
210
+ reset?: boolean;
211
+ }): SubmissionResult<never, Exclude<JsonPrimitive | FormDataEntryValue, File>>;
212
+ export declare function report(submission: Submission, options: {
195
213
  keepFiles: true;
196
- error?: {
197
- issues: ReadonlyArray<StandardSchemaIssue>;
198
- formErrors?: string[];
199
- fieldErrors?: Record<string, string[]>;
200
- };
214
+ error?: null;
201
215
  value?: Record<string, FormValue> | null;
202
216
  hideFields?: string[];
203
217
  reset?: boolean;
204
- }): SubmissionResult<string>;
218
+ }): SubmissionResult<never>;
219
+ export declare function report<ErrorShape>(submission: Submission, options?: {
220
+ keepFiles?: boolean;
221
+ error?: CustomError<ErrorShape> | null;
222
+ value?: Record<string, FormValue> | null;
223
+ hideFields?: string[];
224
+ reset?: boolean;
225
+ }): SubmissionResult<ErrorShape>;
205
226
  /**
206
227
  * A utility function that checks whether the current form data differs from the default values.
207
228
  *
208
- * @see https://conform.guide/api/react/future/isDirty
209
- * @example Enable a submit button only if the form is dirty
229
+ * See https://conform.guide/api/react/future/isDirty
230
+ *
231
+ * **Example: Enable a submit button only if the form is dirty**
210
232
  *
211
233
  * ```tsx
212
234
  * const dirty = useFormData(
@@ -248,19 +270,19 @@ formData: FormData | URLSearchParams | FormValue | null, options?: {
248
270
  * - Returned as-is
249
271
  * - boolean:
250
272
  * - true → 'on'
251
- * - false → undefined
273
+ * - false → null
252
274
  * - number / bigint:
253
275
  * - Converted to string using `.toString()`
254
276
  * - Date:
255
- * - Converted to ISO string using `.toISOString()`
277
+ * - Converted to UTC datetime string without trailing `Z` (e.g. `2026-01-01T12:00:00.000`)
256
278
  */
257
- serialize?: (value: unknown, defaultSerialize: Serialize) => SerializedValue | null | undefined;
279
+ serialize?: CustomSerialize;
258
280
  /**
259
281
  * A function to exclude specific fields from the comparison.
260
282
  * Useful for ignoring hidden inputs like CSRF tokens or internal fields added by frameworks
261
283
  * (e.g. Next.js uses hidden inputs to support server actions).
262
284
  *
263
- * @example
285
+ * **Example:**
264
286
  * ```ts
265
287
  * isDirty(formData, {
266
288
  * skipEntry: (name) => name === 'csrf-token',
@@ -278,17 +300,31 @@ formData: FormData | URLSearchParams | FormValue | null, options?: {
278
300
  * - null -> '' (empty string)
279
301
  * - boolean -> 'on' | '' (checked semantics)
280
302
  * - number | bigint -> value.toString()
281
- * - Date -> value.toISOString()
303
+ * - Date -> value.toISOString() without trailing `Z`
282
304
  * - File -> File
283
305
  * - FileList -> File[]
284
306
  * - Array -> string[] or File[] if all items serialize to the same kind; otherwise undefined
285
307
  * - anything else -> undefined
286
308
  */
287
- export declare function serialize(value: unknown): SerializedValue | null | undefined;
309
+ export declare function defaultSerialize(value: unknown): ReturnType<Serialize>;
310
+ /**
311
+ * Recursively serializes a value using the provided serialize function,
312
+ * collapsing empty leaves (`null`, `''`, empty files) to `undefined`
313
+ * and removing empty containers (objects with no remaining keys, empty arrays).
314
+ *
315
+ * When serialize returns `undefined` for a value (i.e. it can't be represented
316
+ * as form data), the raw value is kept and recursed into if it's an object or array.
317
+ *
318
+ * Single-element arrays where the element is a string or undefined are unwrapped
319
+ * to handle the case where a multi-value field (e.g. checkboxes) has only one value.
320
+ */
321
+ export declare function normalize(value: unknown, serialize?: Serialize, name?: string): unknown;
288
322
  /**
289
323
  * Retrieve a field value from FormData with optional type guards.
290
324
  *
291
- * @example
325
+ * **Example:**
326
+ *
327
+ * ```ts
292
328
  * // Basic field access: return `unknown`
293
329
  * const email = getFieldValue(formData, 'email');
294
330
  * // String type: returns `string`
@@ -303,6 +339,7 @@ export declare function serialize(value: unknown): SerializedValue | null | unde
303
339
  * const items = getFieldValue<Item[]>(formData, 'items', { type: 'object', array: true });
304
340
  * // Optional string type: returns `string | undefined`
305
341
  * const bio = getFieldValue(formData, 'bio', { type: 'string', optional: true });
342
+ * ```
306
343
  */
307
344
  export declare function getFieldValue<FieldShape extends Array<Record<string, unknown>>>(formData: FormData | URLSearchParams, name: FieldName<FieldShape>, options: {
308
345
  type: 'object';