@conform-to/dom 1.19.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.
package/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
  ╚══════╝ ╚═════╝ ╚═╝ ╚══╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝
8
8
  ```
9
9
 
10
- Version 1.19.0 / License MIT / Copyright (c) 2026 Edmund Hung
10
+ Version 1.19.1 / License MIT / Copyright (c) 2026 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
 
@@ -126,12 +126,12 @@ export declare function parseSubmission(formData: FormData | URLSearchParams, op
126
126
  * The name of the submit button field that indicates the submission intent.
127
127
  * Defaults to `__INTENT__`.
128
128
  */
129
- intentName?: string;
129
+ intentName?: string | undefined;
130
130
  /**
131
131
  * A function to exclude specific form fields from being parsed.
132
132
  * Return `true` to skip the entry.
133
133
  */
134
- skipEntry?: (name: string) => boolean;
134
+ skipEntry?: ((name: string) => boolean) | undefined;
135
135
  /**
136
136
  * Whether to strip empty values (empty strings, empty files, arrays with all empty values)
137
137
  * from the submission payload. Defaults to `false`.
@@ -140,7 +140,7 @@ export declare function parseSubmission(formData: FormData | URLSearchParams, op
140
140
  * If you are using a schema library like Zod or Valibot, our integration
141
141
  * already strips empty values for you. There is no need to use this option.
142
142
  */
143
- stripEmptyValues?: boolean;
143
+ stripEmptyValues?: boolean | undefined;
144
144
  }): Submission;
145
145
  /**
146
146
  * Creates a SubmissionResult object from a submission, adding validation results and target values.
@@ -174,16 +174,30 @@ export declare function parseSubmission(formData: FormData | URLSearchParams, op
174
174
  * })
175
175
  * ```
176
176
  */
177
+ export declare function report(submission: Submission, options?: {
178
+ keepFiles?: false;
179
+ error?: null;
180
+ value?: Record<string, FormValue> | null;
181
+ hideFields?: string[];
182
+ reset?: boolean;
183
+ }): SubmissionResult<never, Exclude<JsonPrimitive | FormDataEntryValue, File>>;
184
+ export declare function report(submission: Submission, options: {
185
+ keepFiles: true;
186
+ error?: null;
187
+ value?: Record<string, FormValue> | null;
188
+ hideFields?: string[];
189
+ reset?: boolean;
190
+ }): SubmissionResult<never>;
177
191
  export declare function report<ErrorShape>(submission: Submission, options: {
178
192
  keepFiles?: false;
179
- error: CustomError<ErrorShape>;
193
+ error: CustomError<ErrorShape> | null;
180
194
  value?: Record<string, FormValue> | null;
181
195
  hideFields?: string[];
182
196
  reset?: boolean;
183
197
  }): SubmissionResult<ErrorShape, Exclude<JsonPrimitive | FormDataEntryValue, File>>;
184
198
  export declare function report<ErrorShape>(submission: Submission, options: {
185
199
  keepFiles: true;
186
- error: CustomError<ErrorShape>;
200
+ error: CustomError<ErrorShape> | null;
187
201
  value?: Record<string, FormValue> | null;
188
202
  hideFields?: string[];
189
203
  reset?: boolean;
@@ -202,20 +216,6 @@ export declare function report(submission: Submission, options: {
202
216
  hideFields?: string[];
203
217
  reset?: boolean;
204
218
  }): SubmissionResult<string[]>;
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: {
213
- keepFiles: true;
214
- error?: null;
215
- value?: Record<string, FormValue> | null;
216
- hideFields?: string[];
217
- reset?: boolean;
218
- }): SubmissionResult<never>;
219
219
  export declare function report<ErrorShape>(submission: Submission, options?: {
220
220
  keepFiles?: boolean;
221
221
  error?: CustomError<ErrorShape> | null;
@@ -256,12 +256,12 @@ formData: FormData | URLSearchParams | FormValue | null, options?: {
256
256
  * An object representing the default values of the form to compare against.
257
257
  * Defaults to an empty object if not provided.
258
258
  */
259
- defaultValue?: unknown;
259
+ defaultValue?: unknown | undefined;
260
260
  /**
261
261
  * The name of the submit button that triggered the submission.
262
262
  * It will be excluded from the dirty comparison.
263
263
  */
264
- intentName?: string;
264
+ intentName?: string | undefined;
265
265
  /**
266
266
  * A function to serialize values in defaultValue before comparing them to the form data.
267
267
  * If not provided, a default serializer is used that behaves as follows:
@@ -276,7 +276,7 @@ formData: FormData | URLSearchParams | FormValue | null, options?: {
276
276
  * - Date:
277
277
  * - Converted to UTC datetime string without trailing `Z` (e.g. `2026-01-01T12:00:00.000`)
278
278
  */
279
- serialize?: CustomSerialize;
279
+ serialize?: CustomSerialize | undefined;
280
280
  /**
281
281
  * A function to exclude specific fields from the comparison.
282
282
  * Useful for ignoring hidden inputs like CSRF tokens or internal fields added by frameworks
@@ -289,7 +289,7 @@ formData: FormData | URLSearchParams | FormValue | null, options?: {
289
289
  * });
290
290
  * ```
291
291
  */
292
- skipEntry?: (name: string) => boolean;
292
+ skipEntry?: ((name: string) => boolean) | undefined;
293
293
  }): boolean | undefined;
294
294
  /**
295
295
  * Convert an unknown value into something acceptable for HTML form submission.
package/dist/formdata.js CHANGED
@@ -292,8 +292,8 @@ function isEmptyValue(value) {
292
292
  return value.size === 0 && value.name === '';
293
293
  }
294
294
  if (Array.isArray(value)) {
295
- // If array is empty or all items are empty, consider it empty
296
- return value.length === 0 || value.every(item => isEmptyValue(item));
295
+ // If all items are empty, consider it empty
296
+ return value.every(item => isEmptyValue(item));
297
297
  }
298
298
  return false;
299
299
  }
package/dist/formdata.mjs CHANGED
@@ -288,8 +288,8 @@ function isEmptyValue(value) {
288
288
  return value.size === 0 && value.name === '';
289
289
  }
290
290
  if (Array.isArray(value)) {
291
- // If array is empty or all items are empty, consider it empty
292
- return value.length === 0 || value.every(item => isEmptyValue(item));
291
+ // If all items are empty, consider it empty
292
+ return value.every(item => isEmptyValue(item));
293
293
  }
294
294
  return false;
295
295
  }
@@ -1,6 +1,6 @@
1
1
  export type { Serialize, CustomSerialize, FieldName, FormValue, FormError, Submission, SubmissionResult, ValidationAttributes, } from '../types';
2
2
  export { DEFAULT_INTENT_NAME, getFormData, isDirty, normalize, parseSubmission, parsePath, formatPath, appendPath, getRelativePath, getPathValue, setPathValue, report, defaultSerialize, getFieldValue, normalizeFormError, } from '../formdata';
3
- export { isPlainObject, deepEqual } from '../util';
3
+ export { isPlainObject, deepEqual, serializeHtmlPattern } from '../util';
4
4
  export { isFieldElement, isGlobalInstance, updateField, createFileList, createGlobalFormsObserver, dispatchInternalUpdateEvent, focus, change, blur, getFormAction, getFormEncType, getFormMethod, requestSubmit, requestIntent, } from '../dom';
5
5
  export { formatIssues } from '../standard-schema';
6
6
  //# sourceMappingURL=index.d.ts.map
@@ -26,6 +26,7 @@ exports.report = formdata.report;
26
26
  exports.setPathValue = formdata.setPathValue;
27
27
  exports.deepEqual = util.deepEqual;
28
28
  exports.isPlainObject = util.isPlainObject;
29
+ exports.serializeHtmlPattern = util.serializeHtmlPattern;
29
30
  exports.blur = dom.blur;
30
31
  exports.change = dom.change;
31
32
  exports.createFileList = dom.createFileList;
@@ -1,4 +1,4 @@
1
1
  export { DEFAULT_INTENT_NAME, appendPath, defaultSerialize, formatPath, getFieldValue, getFormData, getPathValue, getRelativePath, isDirty, normalize, normalizeFormError, parsePath, parseSubmission, report, setPathValue } from '../formdata.mjs';
2
- export { deepEqual, isPlainObject } from '../util.mjs';
2
+ export { deepEqual, isPlainObject, serializeHtmlPattern } from '../util.mjs';
3
3
  export { blur, change, createFileList, createGlobalFormsObserver, dispatchInternalUpdateEvent, focus, getFormAction, getFormEncType, getFormMethod, isFieldElement, isGlobalInstance, requestIntent, requestSubmit, updateField } from '../dom.mjs';
4
4
  export { formatIssues } from '../standard-schema.mjs';
package/dist/types.d.ts CHANGED
@@ -86,15 +86,15 @@ export type SubmissionResult<ErrorShape = string[], ValueType extends JsonPrimit
86
86
  /**
87
87
  * The target value of the submission. Defined only when the target value is different from the submitted value.
88
88
  */
89
- targetValue?: Record<string, FormValue<ValueType>>;
89
+ targetValue?: Record<string, FormValue<ValueType>> | undefined;
90
90
  /**
91
91
  * Validation errors for `targetValue` when present, otherwise for the original payload.
92
92
  */
93
- error?: FormError<ErrorShape> | null;
93
+ error?: FormError<ErrorShape> | null | undefined;
94
94
  /**
95
95
  * Indicates whether the form should be reset to its initial state.
96
96
  */
97
- reset?: boolean;
97
+ reset?: boolean | undefined;
98
98
  };
99
99
  /** The name of an input field with type information for TypeScript inference. */
100
100
  export type FieldName<FieldShape> = string & {
package/dist/util.d.ts CHANGED
@@ -16,4 +16,16 @@ export declare function stripFiles<Type extends string | number | boolean | File
16
16
  * Helper to get readable type name for error messages
17
17
  */
18
18
  export declare function getTypeName(value: unknown): string;
19
+ /**
20
+ * Combines multiple regex patterns into a single HTML pattern attribute.
21
+ *
22
+ * This is done by putting each input pattern into a lookahead assertion
23
+ * and stripping all flags.
24
+ *
25
+ * Returns undefined if any pattern is case-insensitive, since transforming
26
+ * it to a case-sensitive pattern is a non-trivial operation.
27
+ *
28
+ * Example: [/[A-Z]/, /[0-9]/] -> '^(?=.*(?:[A-Z]))(?=.*(?:[0-9])).*$'
29
+ */
30
+ export declare function serializeHtmlPattern(pattern: RegExp | RegExp[]): string | undefined;
19
31
  //# sourceMappingURL=util.d.ts.map
package/dist/util.js CHANGED
@@ -91,10 +91,36 @@ function getTypeName(value) {
91
91
  return typeof value;
92
92
  }
93
93
 
94
+ /**
95
+ * Combines multiple regex patterns into a single HTML pattern attribute.
96
+ *
97
+ * This is done by putting each input pattern into a lookahead assertion
98
+ * and stripping all flags.
99
+ *
100
+ * Returns undefined if any pattern is case-insensitive, since transforming
101
+ * it to a case-sensitive pattern is a non-trivial operation.
102
+ *
103
+ * Example: [/[A-Z]/, /[0-9]/] -> '^(?=.*(?:[A-Z]))(?=.*(?:[0-9])).*$'
104
+ */
105
+ function serializeHtmlPattern(pattern) {
106
+ var patterns = Array.isArray(pattern) ? pattern : [pattern];
107
+ if (patterns.length === 0 || patterns.some(p => p.flags.includes('i'))) {
108
+ return undefined;
109
+ }
110
+ var serializedPattern = "^".concat(patterns.map(p => "(?=.*(?:".concat(p.source, "))")).join(''), ".*$");
111
+ try {
112
+ new RegExp(serializedPattern, 'v');
113
+ } catch (_unused) {
114
+ return undefined;
115
+ }
116
+ return serializedPattern;
117
+ }
118
+
94
119
  exports.clone = clone;
95
120
  exports.deepEqual = deepEqual;
96
121
  exports.generateId = generateId;
97
122
  exports.getTypeName = getTypeName;
98
123
  exports.invariant = invariant;
99
124
  exports.isPlainObject = isPlainObject;
125
+ exports.serializeHtmlPattern = serializeHtmlPattern;
100
126
  exports.stripFiles = stripFiles;
package/dist/util.mjs CHANGED
@@ -87,4 +87,29 @@ function getTypeName(value) {
87
87
  return typeof value;
88
88
  }
89
89
 
90
- export { clone, deepEqual, generateId, getTypeName, invariant, isPlainObject, stripFiles };
90
+ /**
91
+ * Combines multiple regex patterns into a single HTML pattern attribute.
92
+ *
93
+ * This is done by putting each input pattern into a lookahead assertion
94
+ * and stripping all flags.
95
+ *
96
+ * Returns undefined if any pattern is case-insensitive, since transforming
97
+ * it to a case-sensitive pattern is a non-trivial operation.
98
+ *
99
+ * Example: [/[A-Z]/, /[0-9]/] -> '^(?=.*(?:[A-Z]))(?=.*(?:[0-9])).*$'
100
+ */
101
+ function serializeHtmlPattern(pattern) {
102
+ var patterns = Array.isArray(pattern) ? pattern : [pattern];
103
+ if (patterns.length === 0 || patterns.some(p => p.flags.includes('i'))) {
104
+ return undefined;
105
+ }
106
+ var serializedPattern = "^".concat(patterns.map(p => "(?=.*(?:".concat(p.source, "))")).join(''), ".*$");
107
+ try {
108
+ new RegExp(serializedPattern, 'v');
109
+ } catch (_unused) {
110
+ return undefined;
111
+ }
112
+ return serializedPattern;
113
+ }
114
+
115
+ export { clone, deepEqual, generateId, getTypeName, invariant, isPlainObject, serializeHtmlPattern, 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.19.0",
6
+ "version": "1.19.1",
7
7
  "main": "./dist/index.js",
8
8
  "module": "./dist/index.mjs",
9
9
  "types": "./dist/index.d.ts",