@conform-to/dom 1.14.1 → 1.15.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.
package/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
  ╚══════╝ ╚═════╝ ╚═╝ ╚══╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝
8
8
  ```
9
9
 
10
- Version 1.14.1 / License MIT / Copyright (c) 2025 Edmund Hung
10
+ Version 1.15.1 / 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
 
package/dist/dom.js CHANGED
@@ -410,7 +410,6 @@ function normalizeFileValues(value) {
410
410
  * If the value or defaultValue is undefined, it will keep the current value instead
411
411
  */
412
412
  function updateField(element, options) {
413
- var _value$;
414
413
  var isChanged = false;
415
414
  if (isInputElement(element)) {
416
415
  switch (element.type) {
@@ -498,29 +497,32 @@ function updateField(element, options) {
498
497
  }
499
498
  var value = normalizeStringValues(options.value);
500
499
  var defaultValue = normalizeStringValues(options.defaultValue);
501
- var inputValue = (_value$ = value === null || value === void 0 ? void 0 : value[0]) !== null && _value$ !== void 0 ? _value$ : '';
502
- if (element.value !== inputValue) {
503
- /**
504
- * Triggering react custom change event
505
- * Solution based on dom-testing-library
506
- * @see https://github.com/facebook/react/issues/10135#issuecomment-401496776
507
- * @see https://github.com/testing-library/dom-testing-library/blob/main/src/events.js#L104-L123
508
- */
509
- var {
510
- set: valueSetter
511
- } = Object.getOwnPropertyDescriptor(element, 'value') || {};
512
- var prototype = Object.getPrototypeOf(element);
513
- var {
514
- set: prototypeValueSetter
515
- } = Object.getOwnPropertyDescriptor(prototype, 'value') || {};
516
- if (prototypeValueSetter && valueSetter !== prototypeValueSetter) {
517
- prototypeValueSetter.call(element, inputValue);
518
- } else if (valueSetter) {
519
- valueSetter.call(element, inputValue);
520
- } else {
521
- throw new Error('The given element does not have a value setter');
500
+ if (value) {
501
+ var _value$;
502
+ var inputValue = (_value$ = value[0]) !== null && _value$ !== void 0 ? _value$ : '';
503
+ if (element.value !== inputValue) {
504
+ /**
505
+ * Triggering react custom change event
506
+ * Solution based on dom-testing-library
507
+ * @see https://github.com/facebook/react/issues/10135#issuecomment-401496776
508
+ * @see https://github.com/testing-library/dom-testing-library/blob/main/src/events.js#L104-L123
509
+ */
510
+ var {
511
+ set: valueSetter
512
+ } = Object.getOwnPropertyDescriptor(element, 'value') || {};
513
+ var prototype = Object.getPrototypeOf(element);
514
+ var {
515
+ set: prototypeValueSetter
516
+ } = Object.getOwnPropertyDescriptor(prototype, 'value') || {};
517
+ if (prototypeValueSetter && valueSetter !== prototypeValueSetter) {
518
+ prototypeValueSetter.call(element, inputValue);
519
+ } else if (valueSetter) {
520
+ valueSetter.call(element, inputValue);
521
+ } else {
522
+ throw new Error('The given element does not have a value setter');
523
+ }
524
+ isChanged = true;
522
525
  }
523
- isChanged = true;
524
526
  }
525
527
  if (defaultValue) {
526
528
  var _defaultValue$;
package/dist/dom.mjs CHANGED
@@ -406,7 +406,6 @@ function normalizeFileValues(value) {
406
406
  * If the value or defaultValue is undefined, it will keep the current value instead
407
407
  */
408
408
  function updateField(element, options) {
409
- var _value$;
410
409
  var isChanged = false;
411
410
  if (isInputElement(element)) {
412
411
  switch (element.type) {
@@ -494,29 +493,32 @@ function updateField(element, options) {
494
493
  }
495
494
  var value = normalizeStringValues(options.value);
496
495
  var defaultValue = normalizeStringValues(options.defaultValue);
497
- var inputValue = (_value$ = value === null || value === void 0 ? void 0 : value[0]) !== null && _value$ !== void 0 ? _value$ : '';
498
- if (element.value !== inputValue) {
499
- /**
500
- * Triggering react custom change event
501
- * Solution based on dom-testing-library
502
- * @see https://github.com/facebook/react/issues/10135#issuecomment-401496776
503
- * @see https://github.com/testing-library/dom-testing-library/blob/main/src/events.js#L104-L123
504
- */
505
- var {
506
- set: valueSetter
507
- } = Object.getOwnPropertyDescriptor(element, 'value') || {};
508
- var prototype = Object.getPrototypeOf(element);
509
- var {
510
- set: prototypeValueSetter
511
- } = Object.getOwnPropertyDescriptor(prototype, 'value') || {};
512
- if (prototypeValueSetter && valueSetter !== prototypeValueSetter) {
513
- prototypeValueSetter.call(element, inputValue);
514
- } else if (valueSetter) {
515
- valueSetter.call(element, inputValue);
516
- } else {
517
- throw new Error('The given element does not have a value setter');
496
+ if (value) {
497
+ var _value$;
498
+ var inputValue = (_value$ = value[0]) !== null && _value$ !== void 0 ? _value$ : '';
499
+ if (element.value !== inputValue) {
500
+ /**
501
+ * Triggering react custom change event
502
+ * Solution based on dom-testing-library
503
+ * @see https://github.com/facebook/react/issues/10135#issuecomment-401496776
504
+ * @see https://github.com/testing-library/dom-testing-library/blob/main/src/events.js#L104-L123
505
+ */
506
+ var {
507
+ set: valueSetter
508
+ } = Object.getOwnPropertyDescriptor(element, 'value') || {};
509
+ var prototype = Object.getPrototypeOf(element);
510
+ var {
511
+ set: prototypeValueSetter
512
+ } = Object.getOwnPropertyDescriptor(prototype, 'value') || {};
513
+ if (prototypeValueSetter && valueSetter !== prototypeValueSetter) {
514
+ prototypeValueSetter.call(element, inputValue);
515
+ } else if (valueSetter) {
516
+ valueSetter.call(element, inputValue);
517
+ } else {
518
+ throw new Error('The given element does not have a value setter');
519
+ }
520
+ isChanged = true;
518
521
  }
519
- isChanged = true;
520
522
  }
521
523
  if (defaultValue) {
522
524
  var _defaultValue$;
@@ -1,4 +1,4 @@
1
- import type { FormValue, JsonPrimitive, Serialize, SerializedValue, Submission, SubmissionResult } from './types';
1
+ import type { FormValue, FieldName, JsonPrimitive, Serialize, SerializedValue, Submission, SubmissionResult, UnknownObject } from './types';
2
2
  import type { StandardSchemaIssue } from './standard-schema';
3
3
  export declare const DEFAULT_INTENT_NAME = "__INTENT__";
4
4
  /**
@@ -285,4 +285,81 @@ formData: FormData | URLSearchParams | FormValue | null, options?: {
285
285
  * - anything else -> undefined
286
286
  */
287
287
  export declare function serialize(value: unknown): SerializedValue | null | undefined;
288
+ /**
289
+ * Retrieve a field value from FormData with optional type guards.
290
+ *
291
+ * @example
292
+ * // Basic field access: return `unknown`
293
+ * const email = getFieldValue(formData, 'email');
294
+ * // String type: returns `string`
295
+ * const name = getFieldValue(formData, 'name', { type: 'string' });
296
+ * // File type: returns `File`
297
+ * const avatar = getFieldValue(formData, 'avatar', { type: 'file' });
298
+ * // Object type: returns { city: unknown, ... }
299
+ * const address = getFieldValue<Address>(formData, 'address', { type: 'object' });
300
+ * // Array: returns `unknown[]`
301
+ * const tags = getFieldValue(formData, 'tags', { array: true });
302
+ * // Array with object type: returns `Array<{ name: unknown, ... }>`
303
+ * const items = getFieldValue<Item[]>(formData, 'items', { type: 'object', array: true });
304
+ * // Optional string type: returns `string | undefined`
305
+ * const bio = getFieldValue(formData, 'bio', { type: 'string', optional: true });
306
+ */
307
+ export declare function getFieldValue<FieldShape extends Array<Record<string, unknown>>>(formData: FormData | URLSearchParams, name: FieldName<FieldShape>, options: {
308
+ type: 'object';
309
+ array: true;
310
+ optional: true;
311
+ }): FieldShape extends Array<infer Item extends Record<string, unknown>> ? Array<UnknownObject<Item>> | undefined : never;
312
+ export declare function getFieldValue<FieldShape extends Array<Record<string, unknown>>>(formData: FormData | URLSearchParams, name: FieldName<FieldShape>, options: {
313
+ type: 'object';
314
+ array: true;
315
+ }): FieldShape extends Array<infer Item extends Record<string, unknown>> ? Array<UnknownObject<Item>> : never;
316
+ export declare function getFieldValue<FieldShape extends Record<string, unknown> = Record<string, unknown>>(formData: FormData | URLSearchParams, name: FieldName<FieldShape>, options: {
317
+ type: 'object';
318
+ optional: true;
319
+ }): UnknownObject<FieldShape> | undefined;
320
+ export declare function getFieldValue<FieldShape extends Record<string, unknown> = Record<string, unknown>>(formData: FormData | URLSearchParams, name: FieldName<FieldShape>, options: {
321
+ type: 'object';
322
+ }): UnknownObject<FieldShape>;
323
+ export declare function getFieldValue<FieldShape>(formData: FormData | URLSearchParams, name: FieldName<FieldShape>, options: {
324
+ type: 'string';
325
+ array: true;
326
+ optional: true;
327
+ }): string[] | undefined;
328
+ export declare function getFieldValue<FieldShape>(formData: FormData | URLSearchParams, name: FieldName<FieldShape>, options: {
329
+ type: 'string';
330
+ array: true;
331
+ }): string[];
332
+ export declare function getFieldValue<FieldShape>(formData: FormData | URLSearchParams, name: FieldName<FieldShape>, options: {
333
+ type: 'string';
334
+ optional: true;
335
+ }): string | undefined;
336
+ export declare function getFieldValue<FieldShape>(formData: FormData | URLSearchParams, name: FieldName<FieldShape>, options: {
337
+ type: 'string';
338
+ }): string;
339
+ export declare function getFieldValue<FieldShape>(formData: FormData | URLSearchParams, name: FieldName<FieldShape>, options: {
340
+ type: 'file';
341
+ array: true;
342
+ optional: true;
343
+ }): File[] | undefined;
344
+ export declare function getFieldValue<FieldShape>(formData: FormData | URLSearchParams, name: FieldName<FieldShape>, options: {
345
+ type: 'file';
346
+ array: true;
347
+ }): File[];
348
+ export declare function getFieldValue<FieldShape>(formData: FormData | URLSearchParams, name: FieldName<FieldShape>, options: {
349
+ type: 'file';
350
+ optional: true;
351
+ }): File | undefined;
352
+ export declare function getFieldValue<FieldShape>(formData: FormData | URLSearchParams, name: FieldName<FieldShape>, options: {
353
+ type: 'file';
354
+ }): File;
355
+ export declare function getFieldValue<FieldShape>(formData: FormData | URLSearchParams, name: FieldName<FieldShape>, options: {
356
+ array: true;
357
+ optional: true;
358
+ }): Array<unknown> | undefined;
359
+ export declare function getFieldValue<FieldShape>(formData: FormData | URLSearchParams, name: FieldName<FieldShape>, options: {
360
+ array: true;
361
+ }): Array<unknown>;
362
+ export declare function getFieldValue<FieldShape>(formData: FormData | URLSearchParams, name: FieldName<FieldShape>, options?: {
363
+ optional?: boolean;
364
+ }): unknown;
288
365
  //# sourceMappingURL=formdata.d.ts.map
package/dist/formdata.js CHANGED
@@ -576,9 +576,81 @@ function serialize(value) {
576
576
  return serializePrimitive(value);
577
577
  }
578
578
 
579
+ /**
580
+ * Retrieve a field value from FormData with optional type guards.
581
+ *
582
+ * @example
583
+ * // Basic field access: return `unknown`
584
+ * const email = getFieldValue(formData, 'email');
585
+ * // String type: returns `string`
586
+ * const name = getFieldValue(formData, 'name', { type: 'string' });
587
+ * // File type: returns `File`
588
+ * const avatar = getFieldValue(formData, 'avatar', { type: 'file' });
589
+ * // Object type: returns { city: unknown, ... }
590
+ * const address = getFieldValue<Address>(formData, 'address', { type: 'object' });
591
+ * // Array: returns `unknown[]`
592
+ * const tags = getFieldValue(formData, 'tags', { array: true });
593
+ * // Array with object type: returns `Array<{ name: unknown, ... }>`
594
+ * const items = getFieldValue<Item[]>(formData, 'items', { type: 'object', array: true });
595
+ * // Optional string type: returns `string | undefined`
596
+ * const bio = getFieldValue(formData, 'bio', { type: 'string', optional: true });
597
+ */
598
+
599
+ function getFieldValue(formData, name, options) {
600
+ var {
601
+ type,
602
+ array,
603
+ optional
604
+ } = options !== null && options !== void 0 ? options : {};
605
+ var value;
606
+
607
+ // Check if formData has a direct entry
608
+ if (formData.has(name)) {
609
+ // Get value based on array option
610
+ value = array ? formData.getAll(name) : formData.get(name);
611
+ } else {
612
+ // Parse formData and use getValueAtPath
613
+ var _submission = parseSubmission(formData, {
614
+ stripEmptyValues: false
615
+ });
616
+ value = getValueAtPath(_submission.payload, name);
617
+ }
618
+
619
+ // If optional and value is undefined, skip validation and return early
620
+ if (optional && value === undefined) {
621
+ return;
622
+ }
623
+
624
+ // Type guards - validate the value matches the expected type
625
+ if (array && !Array.isArray(value)) {
626
+ throw new Error("Expected field \"".concat(name, "\" to be an array, but got ").concat(util.getTypeName(value)));
627
+ }
628
+ if (type) {
629
+ var items = array ? value : [value];
630
+ var predicate = {
631
+ string: v => typeof v === 'string',
632
+ file: v => v instanceof File,
633
+ object: util.isPlainObject
634
+ }[type];
635
+ var typeName = {
636
+ string: 'a string',
637
+ file: 'a File',
638
+ object: 'an object'
639
+ }[type];
640
+ for (var i = 0; i < items.length; i++) {
641
+ if (!predicate(items[i])) {
642
+ var field = array ? "".concat(name, "[").concat(i, "]") : name;
643
+ throw new Error("Expected field \"".concat(field, "\" to be ").concat(typeName, ", but got ").concat(util.getTypeName(items[i])));
644
+ }
645
+ }
646
+ }
647
+ return value;
648
+ }
649
+
579
650
  exports.DEFAULT_INTENT_NAME = DEFAULT_INTENT_NAME;
580
651
  exports.appendPathSegment = appendPathSegment;
581
652
  exports.formatPathSegments = formatPathSegments;
653
+ exports.getFieldValue = getFieldValue;
582
654
  exports.getFormData = getFormData;
583
655
  exports.getPathSegments = getPathSegments;
584
656
  exports.getRelativePath = getRelativePath;
package/dist/formdata.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { objectSpread2 as _objectSpread2 } from './_virtual/_rollupPluginBabelHelpers.mjs';
2
2
  import { isSubmitter, isGlobalInstance } from './dom.mjs';
3
- import { isPlainObject, stripFiles, deepEqual } from './util.mjs';
3
+ import { isPlainObject, stripFiles, deepEqual, getTypeName } from './util.mjs';
4
4
  import { formatIssues } from './standard-schema.mjs';
5
5
 
6
6
  var DEFAULT_INTENT_NAME = '__INTENT__';
@@ -572,4 +572,75 @@ function serialize(value) {
572
572
  return serializePrimitive(value);
573
573
  }
574
574
 
575
- export { DEFAULT_INTENT_NAME, appendPathSegment, formatPathSegments, getFormData, getPathSegments, getRelativePath, getValueAtPath, isDirty, isPrefix, parseSubmission, report, serialize, setValueAtPath };
575
+ /**
576
+ * Retrieve a field value from FormData with optional type guards.
577
+ *
578
+ * @example
579
+ * // Basic field access: return `unknown`
580
+ * const email = getFieldValue(formData, 'email');
581
+ * // String type: returns `string`
582
+ * const name = getFieldValue(formData, 'name', { type: 'string' });
583
+ * // File type: returns `File`
584
+ * const avatar = getFieldValue(formData, 'avatar', { type: 'file' });
585
+ * // Object type: returns { city: unknown, ... }
586
+ * const address = getFieldValue<Address>(formData, 'address', { type: 'object' });
587
+ * // Array: returns `unknown[]`
588
+ * const tags = getFieldValue(formData, 'tags', { array: true });
589
+ * // Array with object type: returns `Array<{ name: unknown, ... }>`
590
+ * const items = getFieldValue<Item[]>(formData, 'items', { type: 'object', array: true });
591
+ * // Optional string type: returns `string | undefined`
592
+ * const bio = getFieldValue(formData, 'bio', { type: 'string', optional: true });
593
+ */
594
+
595
+ function getFieldValue(formData, name, options) {
596
+ var {
597
+ type,
598
+ array,
599
+ optional
600
+ } = options !== null && options !== void 0 ? options : {};
601
+ var value;
602
+
603
+ // Check if formData has a direct entry
604
+ if (formData.has(name)) {
605
+ // Get value based on array option
606
+ value = array ? formData.getAll(name) : formData.get(name);
607
+ } else {
608
+ // Parse formData and use getValueAtPath
609
+ var _submission = parseSubmission(formData, {
610
+ stripEmptyValues: false
611
+ });
612
+ value = getValueAtPath(_submission.payload, name);
613
+ }
614
+
615
+ // If optional and value is undefined, skip validation and return early
616
+ if (optional && value === undefined) {
617
+ return;
618
+ }
619
+
620
+ // Type guards - validate the value matches the expected type
621
+ if (array && !Array.isArray(value)) {
622
+ throw new Error("Expected field \"".concat(name, "\" to be an array, but got ").concat(getTypeName(value)));
623
+ }
624
+ if (type) {
625
+ var items = array ? value : [value];
626
+ var predicate = {
627
+ string: v => typeof v === 'string',
628
+ file: v => v instanceof File,
629
+ object: isPlainObject
630
+ }[type];
631
+ var typeName = {
632
+ string: 'a string',
633
+ file: 'a File',
634
+ object: 'an object'
635
+ }[type];
636
+ for (var i = 0; i < items.length; i++) {
637
+ if (!predicate(items[i])) {
638
+ var field = array ? "".concat(name, "[").concat(i, "]") : name;
639
+ throw new Error("Expected field \"".concat(field, "\" to be ").concat(typeName, ", but got ").concat(getTypeName(items[i])));
640
+ }
641
+ }
642
+ }
643
+ return value;
644
+ }
645
+
646
+ export { DEFAULT_INTENT_NAME, appendPathSegment, formatPathSegments, getFieldValue, getFormData, getPathSegments, getRelativePath, getValueAtPath, isDirty, isPrefix, parseSubmission, report, serialize, setValueAtPath };
@@ -1,5 +1,5 @@
1
- export type { Serialize, FormValue, FormError, Submission, SubmissionResult, ValidationAttributes, } from '../types';
2
- export { DEFAULT_INTENT_NAME, getFormData, isDirty, parseSubmission, getPathSegments, formatPathSegments, appendPathSegment, getRelativePath, getValueAtPath, setValueAtPath, report, serialize, } from '../formdata';
1
+ export type { Serialize, FieldName, FormValue, FormError, Submission, SubmissionResult, ValidationAttributes, } from '../types';
2
+ export { DEFAULT_INTENT_NAME, getFormData, isDirty, parseSubmission, getPathSegments, formatPathSegments, appendPathSegment, getRelativePath, getValueAtPath, setValueAtPath, report, serialize, getFieldValue, } from '../formdata';
3
3
  export { isPlainObject, deepEqual } from '../util';
4
4
  export { isFieldElement, isGlobalInstance, updateField, createFileList, createSubmitEvent, createGlobalFormsObserver, focus, change, blur, getFormAction, getFormEncType, getFormMethod, requestSubmit, requestIntent, } from '../dom';
5
5
  export { formatIssues } from '../standard-schema';
@@ -12,6 +12,7 @@ var standardSchema = require('../standard-schema.js');
12
12
  exports.DEFAULT_INTENT_NAME = formdata.DEFAULT_INTENT_NAME;
13
13
  exports.appendPathSegment = formdata.appendPathSegment;
14
14
  exports.formatPathSegments = formdata.formatPathSegments;
15
+ exports.getFieldValue = formdata.getFieldValue;
15
16
  exports.getFormData = formdata.getFormData;
16
17
  exports.getPathSegments = formdata.getPathSegments;
17
18
  exports.getRelativePath = formdata.getRelativePath;
@@ -1,4 +1,4 @@
1
- export { DEFAULT_INTENT_NAME, appendPathSegment, formatPathSegments, getFormData, getPathSegments, getRelativePath, getValueAtPath, isDirty, parseSubmission, report, serialize, setValueAtPath } from '../formdata.mjs';
1
+ export { DEFAULT_INTENT_NAME, appendPathSegment, formatPathSegments, getFieldValue, getFormData, getPathSegments, getRelativePath, getValueAtPath, isDirty, parseSubmission, report, serialize, setValueAtPath } from '../formdata.mjs';
2
2
  export { deepEqual, isPlainObject } from '../util.mjs';
3
3
  export { blur, change, createFileList, createGlobalFormsObserver, createSubmitEvent, focus, getFormAction, getFormEncType, getFormMethod, isFieldElement, isGlobalInstance, requestIntent, requestSubmit, updateField } from '../dom.mjs';
4
4
  export { formatIssues } from '../standard-schema.mjs';
@@ -98,7 +98,7 @@ function parse(payload, options) {
98
98
  return mergeResolveResult(result);
99
99
  }
100
100
  function createSubmission(context) {
101
- if (context.intent || !context.value || context.error) {
101
+ if (context.intent || context.error !== undefined) {
102
102
  return {
103
103
  status: !context.intent ? 'error' : undefined,
104
104
  payload: context.payload,
@@ -94,7 +94,7 @@ function parse(payload, options) {
94
94
  return mergeResolveResult(result);
95
95
  }
96
96
  function createSubmission(context) {
97
- if (context.intent || !context.value || context.error) {
97
+ if (context.intent || context.error !== undefined) {
98
98
  return {
99
99
  status: !context.intent ? 'error' : undefined,
100
100
  payload: context.payload,
package/dist/types.d.ts CHANGED
@@ -76,6 +76,10 @@ export type SubmissionResult<ErrorShape = string, ValueType extends JsonPrimitiv
76
76
  */
77
77
  reset?: boolean;
78
78
  };
79
+ /** The name of an input field with type information for TypeScript inference. */
80
+ export type FieldName<FieldShape> = string & {
81
+ '~shape'?: FieldShape;
82
+ };
79
83
  /**
80
84
  * The input attributes with related to the Constraint Validation API
81
85
  * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Constraint_validation
@@ -115,4 +119,14 @@ export type Serialize = (value: unknown) => SerializedValue | null | undefined;
115
119
  * - Arrays allow representing multi-value fields.
116
120
  */
117
121
  export type SerializedValue = string | string[] | File | File[];
122
+ /**
123
+ * Flatten a discriminated union into a single type with all properties.
124
+ */
125
+ export type Combine<T, K extends PropertyKey = T extends unknown ? keyof T : never> = T extends unknown ? T & Partial<Record<Exclude<K, keyof T>, never>> : never;
126
+ /**
127
+ * Maps all keys of T (including all keys from discriminated unions) to unknown.
128
+ */
129
+ export type UnknownObject<T> = [T] extends [Record<string, any>] ? {
130
+ [K in keyof Combine<T>]-?: unknown;
131
+ } : never;
118
132
  //# sourceMappingURL=types.d.ts.map
package/dist/util.d.ts CHANGED
@@ -12,4 +12,8 @@ export declare function isPlainObject(obj: unknown): obj is Record<string | numb
12
12
  */
13
13
  export declare function deepEqual(left: unknown, right: unknown): boolean;
14
14
  export declare function stripFiles<Type extends string | number | boolean | File | null>(value: Record<string, FormValue<Type>>): Record<string, FormValue<Exclude<Type, File>>>;
15
+ /**
16
+ * Helper to get readable type name for error messages
17
+ */
18
+ export declare function getTypeName(value: unknown): string;
15
19
  //# sourceMappingURL=util.d.ts.map
package/dist/util.js CHANGED
@@ -78,9 +78,23 @@ function stripFiles(value) {
78
78
  return JSON.parse(json);
79
79
  }
80
80
 
81
+ /**
82
+ * Helper to get readable type name for error messages
83
+ */
84
+ function getTypeName(value) {
85
+ if (value === null) return 'null';
86
+ if (Array.isArray(value)) return 'Array';
87
+ if (typeof value === 'object') {
88
+ var _value$constructor$na, _value$constructor;
89
+ return (_value$constructor$na = (_value$constructor = value.constructor) === null || _value$constructor === void 0 ? void 0 : _value$constructor.name) !== null && _value$constructor$na !== void 0 ? _value$constructor$na : 'Object';
90
+ }
91
+ return typeof value;
92
+ }
93
+
81
94
  exports.clone = clone;
82
95
  exports.deepEqual = deepEqual;
83
96
  exports.generateId = generateId;
97
+ exports.getTypeName = getTypeName;
84
98
  exports.invariant = invariant;
85
99
  exports.isPlainObject = isPlainObject;
86
100
  exports.stripFiles = stripFiles;
package/dist/util.mjs CHANGED
@@ -74,4 +74,17 @@ function stripFiles(value) {
74
74
  return JSON.parse(json);
75
75
  }
76
76
 
77
- export { clone, deepEqual, generateId, invariant, isPlainObject, stripFiles };
77
+ /**
78
+ * Helper to get readable type name for error messages
79
+ */
80
+ function getTypeName(value) {
81
+ if (value === null) return 'null';
82
+ if (Array.isArray(value)) return 'Array';
83
+ if (typeof value === 'object') {
84
+ var _value$constructor$na, _value$constructor;
85
+ return (_value$constructor$na = (_value$constructor = value.constructor) === null || _value$constructor === void 0 ? void 0 : _value$constructor.name) !== null && _value$constructor$na !== void 0 ? _value$constructor$na : 'Object';
86
+ }
87
+ return typeof value;
88
+ }
89
+
90
+ export { clone, deepEqual, generateId, getTypeName, invariant, isPlainObject, stripFiles };
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "A set of opinionated helpers built on top of the Constraint Validation API",
4
4
  "homepage": "https://conform.guide",
5
5
  "license": "MIT",
6
- "version": "1.14.1",
6
+ "version": "1.15.1",
7
7
  "main": "./dist/index.js",
8
8
  "module": "./dist/index.mjs",
9
9
  "types": "./dist/index.d.ts",