@conform-to/dom 1.17.0 → 1.18.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 +1 -1
- package/dist/dom.d.ts +13 -9
- package/dist/dom.js +91 -24
- package/dist/dom.mjs +90 -24
- package/dist/form.js +23 -23
- package/dist/form.mjs +24 -24
- package/dist/formdata.d.ts +41 -26
- package/dist/formdata.js +103 -102
- package/dist/formdata.mjs +97 -97
- package/dist/future/index.d.ts +2 -2
- package/dist/future/index.js +7 -6
- package/dist/future/index.mjs +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +4 -3
- package/dist/index.mjs +1 -1
- package/dist/standard-schema.js +1 -1
- package/dist/standard-schema.mjs +2 -2
- package/dist/submission.js +11 -11
- package/dist/submission.mjs +12 -12
- package/package.json +1 -1
package/dist/form.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { objectSpread2 as _objectSpread2 } from './_virtual/_rollupPluginBabelHelpers.mjs';
|
|
2
|
-
import {
|
|
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[
|
|
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 =
|
|
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 =
|
|
105
|
-
var _value =
|
|
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 =>
|
|
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
|
-
|
|
159
|
-
|
|
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 =
|
|
185
|
-
var basename =
|
|
186
|
-
var key =
|
|
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
220
|
+
var segments = parsePath(name);
|
|
221
221
|
if (segments.length === 0) {
|
|
222
222
|
return currentKey;
|
|
223
223
|
}
|
|
224
|
-
var parentKey = proxy[
|
|
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 (
|
|
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 =>
|
|
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 =
|
|
580
|
-
var baseSegments =
|
|
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 =
|
|
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 =
|
|
602
|
+
var prefix = appendPath(intent.payload.name, intent.payload.index);
|
|
603
603
|
for (var _element of formElement.elements) {
|
|
604
|
-
if (isFieldElement(_element) && _element.name &&
|
|
605
|
-
var _value2 =
|
|
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;
|
package/dist/formdata.d.ts
CHANGED
|
@@ -14,23 +14,23 @@ export declare function getFormData(form: HTMLFormElement, submitter?: HTMLEleme
|
|
|
14
14
|
*
|
|
15
15
|
* @example
|
|
16
16
|
* ```js
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
17
|
+
* parsePath("object.key"); // → ['object', 'key']
|
|
18
|
+
* parsePath("array[0].content"); // → ['array', 0, 'content']
|
|
19
|
+
* parsePath("todos[]"); // → ['todos', '']
|
|
20
20
|
* ```
|
|
21
21
|
*/
|
|
22
|
-
export declare function
|
|
22
|
+
export declare function parsePath(path: string | undefined): Array<string | number>;
|
|
23
23
|
/**
|
|
24
24
|
* Returns a formatted name from the path segments based on the dot and bracket notation.
|
|
25
25
|
*
|
|
26
26
|
* @example
|
|
27
27
|
* ```js
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
28
|
+
* formatPath(['object', 'key']); // → "object.key"
|
|
29
|
+
* formatPath(['array', 0, 'content']); // → "array[0].content"
|
|
30
|
+
* formatPath(['todos', '']); // → "todos[]"
|
|
31
31
|
* ```
|
|
32
32
|
*/
|
|
33
|
-
export declare function
|
|
33
|
+
export declare function formatPath(segments: Readonly<Array<string | number>>): string;
|
|
34
34
|
/**
|
|
35
35
|
* Append one more segment onto an existing path string.
|
|
36
36
|
*
|
|
@@ -39,26 +39,26 @@ export declare function formatPathSegments(segments: Readonly<Array<string | num
|
|
|
39
39
|
* - segment = `number` ⇒ bracket notation "[n]"
|
|
40
40
|
* - segment = `string` ⇒ dot-notation ".prop"
|
|
41
41
|
*/
|
|
42
|
-
export declare function
|
|
42
|
+
export declare function appendPath(path: string | undefined, segment: string | number | undefined): string;
|
|
43
43
|
/**
|
|
44
44
|
* Returns true if `prefix` is a valid leading path of `name`.
|
|
45
45
|
*
|
|
46
46
|
* @example
|
|
47
47
|
* ```js
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
48
|
+
* isPathPrefix("foo.bar.baz", "foo.bar") // → true
|
|
49
|
+
* isPathPrefix("foo.bar[3].baz", "foo.bar[3]") // → true
|
|
50
|
+
* isPathPrefix("foo.bar[3].baz", "foo.bar") // → true
|
|
51
|
+
* isPathPrefix("foo.bar[3].baz", "foo.baz") // → false
|
|
52
|
+
* isPathPrefix("foo", "foo.bar") // → false
|
|
53
53
|
* ```
|
|
54
54
|
*/
|
|
55
|
-
export declare function
|
|
55
|
+
export declare function isPathPrefix(name: string, prefix: string): boolean;
|
|
56
56
|
/**
|
|
57
|
-
* Return the segments of `
|
|
57
|
+
* Return the segments of `fullPath` that come after the `basePath` prefix.
|
|
58
58
|
*
|
|
59
|
-
* @param
|
|
60
|
-
* @param basePath
|
|
61
|
-
* @returns The “tail” segments, or `null` if `
|
|
59
|
+
* @param fullPath Full path as a dot/bracket string or array of segments
|
|
60
|
+
* @param basePath Base path as a dot/bracket string or array of segments
|
|
61
|
+
* @returns The “tail” segments, or `null` if `fullPath` isn’t nested under `basePath`
|
|
62
62
|
*
|
|
63
63
|
* @example
|
|
64
64
|
* ```js
|
|
@@ -67,18 +67,18 @@ export declare function isPrefix(name: string, prefix: string): boolean;
|
|
|
67
67
|
* getRelativePath("foo", ["foo","bar"]) // → null
|
|
68
68
|
* ```
|
|
69
69
|
*/
|
|
70
|
-
export declare function getRelativePath(
|
|
70
|
+
export declare function getRelativePath(fullPath: string | Array<string | number>, basePath: string | Array<string | number>): Array<string | number> | null;
|
|
71
71
|
/**
|
|
72
72
|
* Assign a value to a target object by following the path segments.
|
|
73
73
|
*/
|
|
74
|
-
export declare function
|
|
74
|
+
export declare function setPathValue<T extends Record<string, any>>(target: T, pathOrSegments: string | Array<string | number>, valueOrFn: unknown | ((current: unknown) => unknown), options?: {
|
|
75
75
|
clone?: boolean;
|
|
76
76
|
silent?: boolean;
|
|
77
77
|
}): T;
|
|
78
78
|
/**
|
|
79
79
|
* Retrive the value from a target object by following the path segments.
|
|
80
80
|
*/
|
|
81
|
-
export declare function
|
|
81
|
+
export declare function getPathValue(target: unknown, pathOrSegments: string | Array<string | number>): unknown;
|
|
82
82
|
/**
|
|
83
83
|
* Parse `FormData` or `URLSearchParams` into a submission object.
|
|
84
84
|
* This function structures the form values based on the naming convention.
|
|
@@ -122,8 +122,11 @@ export declare function parseSubmission(formData: FormData | URLSearchParams, op
|
|
|
122
122
|
skipEntry?: (name: string) => boolean;
|
|
123
123
|
/**
|
|
124
124
|
* Whether to strip empty values (empty strings, empty files, arrays with all empty values)
|
|
125
|
-
* from the submission payload. Defaults to `
|
|
126
|
-
*
|
|
125
|
+
* from the submission payload. Defaults to `false`.
|
|
126
|
+
*
|
|
127
|
+
* @deprecated This option will be removed in a future minor release.
|
|
128
|
+
* If you are using a schema library like Zod or Valibot, our integration
|
|
129
|
+
* already strips empty values for you. There is no need to use this option.
|
|
127
130
|
*/
|
|
128
131
|
stripEmptyValues?: boolean;
|
|
129
132
|
}): Submission;
|
|
@@ -252,7 +255,7 @@ formData: FormData | URLSearchParams | FormValue | null, options?: {
|
|
|
252
255
|
* - number / bigint:
|
|
253
256
|
* - Converted to string using `.toString()`
|
|
254
257
|
* - Date:
|
|
255
|
-
* - Converted to
|
|
258
|
+
* - Converted to UTC datetime string without trailing `Z` (e.g. `2026-01-01T12:00:00.000`)
|
|
256
259
|
*/
|
|
257
260
|
serialize?: (value: unknown, defaultSerialize: Serialize) => SerializedValue | null | undefined;
|
|
258
261
|
/**
|
|
@@ -278,13 +281,25 @@ formData: FormData | URLSearchParams | FormValue | null, options?: {
|
|
|
278
281
|
* - null -> '' (empty string)
|
|
279
282
|
* - boolean -> 'on' | '' (checked semantics)
|
|
280
283
|
* - number | bigint -> value.toString()
|
|
281
|
-
* - Date -> value.toISOString()
|
|
284
|
+
* - Date -> value.toISOString() without trailing `Z`
|
|
282
285
|
* - File -> File
|
|
283
286
|
* - FileList -> File[]
|
|
284
287
|
* - Array -> string[] or File[] if all items serialize to the same kind; otherwise undefined
|
|
285
288
|
* - anything else -> undefined
|
|
286
289
|
*/
|
|
287
290
|
export declare function serialize(value: unknown): SerializedValue | null | undefined;
|
|
291
|
+
/**
|
|
292
|
+
* Recursively serializes a value using the provided serialize function,
|
|
293
|
+
* collapsing empty leaves (`null`, `''`, empty files) to `undefined`
|
|
294
|
+
* and removing empty containers (objects with no remaining keys, empty arrays).
|
|
295
|
+
*
|
|
296
|
+
* When serialize returns `undefined` for a value (i.e. it can't be represented
|
|
297
|
+
* as form data), the raw value is kept and recursed into if it's an object or array.
|
|
298
|
+
*
|
|
299
|
+
* Single-element arrays where the element is a string or undefined are unwrapped
|
|
300
|
+
* to handle the case where a multi-value field (e.g. checkboxes) has only one value.
|
|
301
|
+
*/
|
|
302
|
+
export declare function normalize(value: unknown, serializeValue?: Serialize): unknown;
|
|
288
303
|
/**
|
|
289
304
|
* Retrieve a field value from FormData with optional type guards.
|
|
290
305
|
*
|
package/dist/formdata.js
CHANGED
|
@@ -39,12 +39,12 @@ function getFormData(form, submitter) {
|
|
|
39
39
|
*
|
|
40
40
|
* @example
|
|
41
41
|
* ```js
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
42
|
+
* parsePath("object.key"); // → ['object', 'key']
|
|
43
|
+
* parsePath("array[0].content"); // → ['array', 0, 'content']
|
|
44
|
+
* parsePath("todos[]"); // → ['todos', '']
|
|
45
45
|
* ```
|
|
46
46
|
*/
|
|
47
|
-
function
|
|
47
|
+
function parsePath(path) {
|
|
48
48
|
if (!path) return [];
|
|
49
49
|
var tokenRegex = /([^.[\]]+)|\[(\d*)\]/g;
|
|
50
50
|
var segments = [];
|
|
@@ -85,13 +85,13 @@ function getPathSegments(path) {
|
|
|
85
85
|
*
|
|
86
86
|
* @example
|
|
87
87
|
* ```js
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
88
|
+
* formatPath(['object', 'key']); // → "object.key"
|
|
89
|
+
* formatPath(['array', 0, 'content']); // → "array[0].content"
|
|
90
|
+
* formatPath(['todos', '']); // → "todos[]"
|
|
91
91
|
* ```
|
|
92
92
|
*/
|
|
93
|
-
function
|
|
94
|
-
return segments.reduce((path, segment) =>
|
|
93
|
+
function formatPath(segments) {
|
|
94
|
+
return segments.reduce((path, segment) => appendPath(path, segment), '');
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
/**
|
|
@@ -102,7 +102,7 @@ function formatPathSegments(segments) {
|
|
|
102
102
|
* - segment = `number` ⇒ bracket notation "[n]"
|
|
103
103
|
* - segment = `string` ⇒ dot-notation ".prop"
|
|
104
104
|
*/
|
|
105
|
-
function
|
|
105
|
+
function appendPath(path, segment) {
|
|
106
106
|
// 1) nothing to append
|
|
107
107
|
if (typeof segment === 'undefined') {
|
|
108
108
|
return path !== null && path !== void 0 ? path : '';
|
|
@@ -128,23 +128,23 @@ function appendPathSegment(path, segment) {
|
|
|
128
128
|
*
|
|
129
129
|
* @example
|
|
130
130
|
* ```js
|
|
131
|
-
*
|
|
132
|
-
*
|
|
133
|
-
*
|
|
134
|
-
*
|
|
135
|
-
*
|
|
131
|
+
* isPathPrefix("foo.bar.baz", "foo.bar") // → true
|
|
132
|
+
* isPathPrefix("foo.bar[3].baz", "foo.bar[3]") // → true
|
|
133
|
+
* isPathPrefix("foo.bar[3].baz", "foo.bar") // → true
|
|
134
|
+
* isPathPrefix("foo.bar[3].baz", "foo.baz") // → false
|
|
135
|
+
* isPathPrefix("foo", "foo.bar") // → false
|
|
136
136
|
* ```
|
|
137
137
|
*/
|
|
138
|
-
function
|
|
139
|
-
return getRelativePath(name,
|
|
138
|
+
function isPathPrefix(name, prefix) {
|
|
139
|
+
return getRelativePath(name, parsePath(prefix)) !== null;
|
|
140
140
|
}
|
|
141
141
|
|
|
142
142
|
/**
|
|
143
|
-
* Return the segments of `
|
|
143
|
+
* Return the segments of `fullPath` that come after the `basePath` prefix.
|
|
144
144
|
*
|
|
145
|
-
* @param
|
|
146
|
-
* @param basePath
|
|
147
|
-
* @returns The “tail” segments, or `null` if `
|
|
145
|
+
* @param fullPath Full path as a dot/bracket string or array of segments
|
|
146
|
+
* @param basePath Base path as a dot/bracket string or array of segments
|
|
147
|
+
* @returns The “tail” segments, or `null` if `fullPath` isn’t nested under `basePath`
|
|
148
148
|
*
|
|
149
149
|
* @example
|
|
150
150
|
* ```js
|
|
@@ -153,12 +153,13 @@ function isPrefix(name, prefix) {
|
|
|
153
153
|
* getRelativePath("foo", ["foo","bar"]) // → null
|
|
154
154
|
* ```
|
|
155
155
|
*/
|
|
156
|
-
function getRelativePath(
|
|
157
|
-
var
|
|
156
|
+
function getRelativePath(fullPath, basePath) {
|
|
157
|
+
var fullPathSegments = typeof fullPath === 'string' ? parsePath(fullPath) : fullPath;
|
|
158
|
+
var basePathSegments = typeof basePath === 'string' ? parsePath(basePath) : basePath;
|
|
158
159
|
|
|
159
160
|
// if full is at least as long *and* starts with the base…
|
|
160
|
-
if (
|
|
161
|
-
return
|
|
161
|
+
if (fullPathSegments.length >= basePathSegments.length && basePathSegments.every((segment, i) => segment === fullPathSegments[i])) {
|
|
162
|
+
return fullPathSegments.slice(basePathSegments.length);
|
|
162
163
|
}
|
|
163
164
|
return null;
|
|
164
165
|
}
|
|
@@ -166,11 +167,11 @@ function getRelativePath(name, basePath) {
|
|
|
166
167
|
/**
|
|
167
168
|
* Assign a value to a target object by following the path segments.
|
|
168
169
|
*/
|
|
169
|
-
function
|
|
170
|
+
function setPathValue(target, pathOrSegments, valueOrFn) {
|
|
170
171
|
var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
|
|
171
172
|
try {
|
|
172
173
|
// 1) normalize + validate path
|
|
173
|
-
var segments = typeof pathOrSegments === 'string' ?
|
|
174
|
+
var segments = typeof pathOrSegments === 'string' ? parsePath(pathOrSegments) : pathOrSegments;
|
|
174
175
|
if (segments.length === 0) {
|
|
175
176
|
throw new Error('Cannot set value at the object root');
|
|
176
177
|
}
|
|
@@ -222,9 +223,9 @@ function setValueAtPath(target, pathOrSegments, valueOrFn) {
|
|
|
222
223
|
/**
|
|
223
224
|
* Retrive the value from a target object by following the path segments.
|
|
224
225
|
*/
|
|
225
|
-
function
|
|
226
|
+
function getPathValue(target, pathOrSegments) {
|
|
226
227
|
var pointer = target;
|
|
227
|
-
var segments = typeof pathOrSegments === 'string' ?
|
|
228
|
+
var segments = typeof pathOrSegments === 'string' ? parsePath(pathOrSegments) : pathOrSegments;
|
|
228
229
|
for (var segment of segments) {
|
|
229
230
|
if (segment === '') {
|
|
230
231
|
throw new Error("Cannot access empty segment \"[]\" in \"".concat(pathOrSegments, "\""));
|
|
@@ -302,7 +303,7 @@ function parseSubmission(formData, options) {
|
|
|
302
303
|
if (_name !== intentName && !(options !== null && options !== void 0 && (_options$skipEntry = options.skipEntry) !== null && _options$skipEntry !== void 0 && _options$skipEntry.call(options, _name))) {
|
|
303
304
|
var _options$stripEmptyVa;
|
|
304
305
|
var _value = formData.getAll(_name);
|
|
305
|
-
var segments =
|
|
306
|
+
var segments = parsePath(_name);
|
|
306
307
|
|
|
307
308
|
// If the name ends with [], remove the empty segment and keep the full array
|
|
308
309
|
// Otherwise, unwrap single values
|
|
@@ -311,9 +312,7 @@ function parseSubmission(formData, options) {
|
|
|
311
312
|
} else {
|
|
312
313
|
_value = _value.length > 1 ? _value : _value[0];
|
|
313
314
|
}
|
|
314
|
-
|
|
315
|
-
// Check if the value is empty and should be skipped (defaults to true)
|
|
316
|
-
var stripEmptyValues = (_options$stripEmptyVa = options === null || options === void 0 ? void 0 : options.stripEmptyValues) !== null && _options$stripEmptyVa !== void 0 ? _options$stripEmptyVa : true;
|
|
315
|
+
var stripEmptyValues = (_options$stripEmptyVa = options === null || options === void 0 ? void 0 : options.stripEmptyValues) !== null && _options$stripEmptyVa !== void 0 ? _options$stripEmptyVa : false;
|
|
317
316
|
if (stripEmptyValues) {
|
|
318
317
|
// For arrays, filter out individual empty items
|
|
319
318
|
if (Array.isArray(_value)) {
|
|
@@ -323,7 +322,7 @@ function parseSubmission(formData, options) {
|
|
|
323
322
|
_value = undefined;
|
|
324
323
|
}
|
|
325
324
|
}
|
|
326
|
-
|
|
325
|
+
setPathValue(submission.payload, segments, _value, {
|
|
327
326
|
silent: true // Avoid errors if the path is invalid
|
|
328
327
|
});
|
|
329
328
|
submission.fields.push(_name);
|
|
@@ -399,10 +398,10 @@ function report(submission) {
|
|
|
399
398
|
var targetValue = typeof options.value === 'undefined' || submission.payload === options.value && !options.reset ? undefined : options.value && !options.keepFiles ? util.stripFiles(options.value) : (_options$value = options.value) !== null && _options$value !== void 0 ? _options$value : {};
|
|
400
399
|
if (options.hideFields) {
|
|
401
400
|
for (var _name3 of options.hideFields) {
|
|
402
|
-
var path =
|
|
403
|
-
|
|
401
|
+
var path = parsePath(_name3);
|
|
402
|
+
setPathValue(submission.payload, path, undefined);
|
|
404
403
|
if (targetValue) {
|
|
405
|
-
|
|
404
|
+
setPathValue(targetValue, path, undefined);
|
|
406
405
|
}
|
|
407
406
|
}
|
|
408
407
|
}
|
|
@@ -452,58 +451,8 @@ formData, options) {
|
|
|
452
451
|
skipEntry: options === null || options === void 0 ? void 0 : options.skipEntry
|
|
453
452
|
}).payload : formData;
|
|
454
453
|
var defaultValue = options === null || options === void 0 ? void 0 : options.defaultValue;
|
|
455
|
-
var
|
|
456
|
-
|
|
457
|
-
return options.serialize(value, serialize);
|
|
458
|
-
}
|
|
459
|
-
return serialize(value);
|
|
460
|
-
};
|
|
461
|
-
function normalize(data) {
|
|
462
|
-
var value = serializeData(data);
|
|
463
|
-
if (typeof value === 'undefined') {
|
|
464
|
-
value = data;
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
// Removes empty strings, so that both empty string, empty file, null and undefined are treated as the same
|
|
468
|
-
if (value === '' || value === null) {
|
|
469
|
-
return undefined;
|
|
470
|
-
}
|
|
471
|
-
if (dom.isGlobalInstance(value, 'File')) {
|
|
472
|
-
// Remove empty File as well, which happens if no File was selected
|
|
473
|
-
if (value.name === '' && value.size === 0) {
|
|
474
|
-
return undefined;
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
// If the value is a File, no need to serialize it
|
|
478
|
-
return value;
|
|
479
|
-
}
|
|
480
|
-
if (Array.isArray(value)) {
|
|
481
|
-
if (value.length === 0) {
|
|
482
|
-
return undefined;
|
|
483
|
-
}
|
|
484
|
-
var array = value.map(normalize);
|
|
485
|
-
if (array.length === 1 && (typeof array[0] === 'string' || array[0] === undefined)) {
|
|
486
|
-
return array[0];
|
|
487
|
-
}
|
|
488
|
-
return array;
|
|
489
|
-
}
|
|
490
|
-
if (util.isPlainObject(value)) {
|
|
491
|
-
var entries = Object.entries(value).reduce((list, _ref) => {
|
|
492
|
-
var [key, value] = _ref;
|
|
493
|
-
var normalizedValue = normalize(value);
|
|
494
|
-
if (typeof normalizedValue !== 'undefined') {
|
|
495
|
-
list.push([key, normalizedValue]);
|
|
496
|
-
}
|
|
497
|
-
return list;
|
|
498
|
-
}, []);
|
|
499
|
-
if (entries.length === 0) {
|
|
500
|
-
return undefined;
|
|
501
|
-
}
|
|
502
|
-
return Object.fromEntries(entries);
|
|
503
|
-
}
|
|
504
|
-
return value;
|
|
505
|
-
}
|
|
506
|
-
return !util.deepEqual(normalize(formValue), normalize(defaultValue));
|
|
454
|
+
var serializeValue = options !== null && options !== void 0 && options.serialize ? value => options.serialize(value, serialize) : serialize;
|
|
455
|
+
return !util.deepEqual(normalize(formValue, serializeValue), normalize(defaultValue, serializeValue));
|
|
507
456
|
}
|
|
508
457
|
|
|
509
458
|
/**
|
|
@@ -515,7 +464,7 @@ formData, options) {
|
|
|
515
464
|
* - null -> '' (empty string)
|
|
516
465
|
* - boolean -> 'on' | '' (checked semantics)
|
|
517
466
|
* - number | bigint -> value.toString()
|
|
518
|
-
* - Date -> value.toISOString()
|
|
467
|
+
* - Date -> value.toISOString() without trailing `Z`
|
|
519
468
|
* - File -> File
|
|
520
469
|
* - FileList -> File[]
|
|
521
470
|
* - Array -> string[] or File[] if all items serialize to the same kind; otherwise undefined
|
|
@@ -533,7 +482,7 @@ function serialize(value) {
|
|
|
533
482
|
return value.toString();
|
|
534
483
|
}
|
|
535
484
|
if (value instanceof Date) {
|
|
536
|
-
return value.toISOString();
|
|
485
|
+
return value.toISOString().slice(0, -1);
|
|
537
486
|
}
|
|
538
487
|
if (dom.isGlobalInstance(value, 'File')) {
|
|
539
488
|
return value;
|
|
@@ -576,6 +525,59 @@ function serialize(value) {
|
|
|
576
525
|
return serializePrimitive(value);
|
|
577
526
|
}
|
|
578
527
|
|
|
528
|
+
/**
|
|
529
|
+
* Recursively serializes a value using the provided serialize function,
|
|
530
|
+
* collapsing empty leaves (`null`, `''`, empty files) to `undefined`
|
|
531
|
+
* and removing empty containers (objects with no remaining keys, empty arrays).
|
|
532
|
+
*
|
|
533
|
+
* When serialize returns `undefined` for a value (i.e. it can't be represented
|
|
534
|
+
* as form data), the raw value is kept and recursed into if it's an object or array.
|
|
535
|
+
*
|
|
536
|
+
* Single-element arrays where the element is a string or undefined are unwrapped
|
|
537
|
+
* to handle the case where a multi-value field (e.g. checkboxes) has only one value.
|
|
538
|
+
*/
|
|
539
|
+
function normalize(value) {
|
|
540
|
+
var serializeValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : serialize;
|
|
541
|
+
var data = serializeValue(value);
|
|
542
|
+
if (typeof data === 'undefined') {
|
|
543
|
+
data = value;
|
|
544
|
+
}
|
|
545
|
+
if (data === '' || data === null) {
|
|
546
|
+
return undefined;
|
|
547
|
+
}
|
|
548
|
+
if (dom.isGlobalInstance(data, 'File')) {
|
|
549
|
+
if (data.name === '' && data.size === 0) {
|
|
550
|
+
return undefined;
|
|
551
|
+
}
|
|
552
|
+
return data;
|
|
553
|
+
}
|
|
554
|
+
if (Array.isArray(data)) {
|
|
555
|
+
if (data.length === 0) {
|
|
556
|
+
return undefined;
|
|
557
|
+
}
|
|
558
|
+
var array = data.map(item => normalize(item, serializeValue));
|
|
559
|
+
if (array.length === 1 && (typeof array[0] === 'string' || array[0] === undefined)) {
|
|
560
|
+
return array[0];
|
|
561
|
+
}
|
|
562
|
+
return array;
|
|
563
|
+
}
|
|
564
|
+
if (util.isPlainObject(data)) {
|
|
565
|
+
var entries = Object.entries(data).reduce((list, _ref) => {
|
|
566
|
+
var [key, value] = _ref;
|
|
567
|
+
var normalizedValue = normalize(value, serializeValue);
|
|
568
|
+
if (typeof normalizedValue !== 'undefined') {
|
|
569
|
+
list.push([key, normalizedValue]);
|
|
570
|
+
}
|
|
571
|
+
return list;
|
|
572
|
+
}, []);
|
|
573
|
+
if (entries.length === 0) {
|
|
574
|
+
return undefined;
|
|
575
|
+
}
|
|
576
|
+
return Object.fromEntries(entries);
|
|
577
|
+
}
|
|
578
|
+
return data;
|
|
579
|
+
}
|
|
580
|
+
|
|
579
581
|
/**
|
|
580
582
|
* Retrieve a field value from FormData with optional type guards.
|
|
581
583
|
*
|
|
@@ -609,11 +611,9 @@ function getFieldValue(formData, name, options) {
|
|
|
609
611
|
// Get value based on array option
|
|
610
612
|
value = array ? formData.getAll(name) : formData.get(name);
|
|
611
613
|
} else {
|
|
612
|
-
// Parse formData and use
|
|
613
|
-
var _submission = parseSubmission(formData
|
|
614
|
-
|
|
615
|
-
});
|
|
616
|
-
value = getValueAtPath(_submission.payload, name);
|
|
614
|
+
// Parse formData and use getPathValue
|
|
615
|
+
var _submission = parseSubmission(formData);
|
|
616
|
+
value = getPathValue(_submission.payload, name);
|
|
617
617
|
}
|
|
618
618
|
|
|
619
619
|
// If optional and value is undefined, skip validation and return early
|
|
@@ -648,16 +648,17 @@ function getFieldValue(formData, name, options) {
|
|
|
648
648
|
}
|
|
649
649
|
|
|
650
650
|
exports.DEFAULT_INTENT_NAME = DEFAULT_INTENT_NAME;
|
|
651
|
-
exports.
|
|
652
|
-
exports.
|
|
651
|
+
exports.appendPath = appendPath;
|
|
652
|
+
exports.formatPath = formatPath;
|
|
653
653
|
exports.getFieldValue = getFieldValue;
|
|
654
654
|
exports.getFormData = getFormData;
|
|
655
|
-
exports.
|
|
655
|
+
exports.getPathValue = getPathValue;
|
|
656
656
|
exports.getRelativePath = getRelativePath;
|
|
657
|
-
exports.getValueAtPath = getValueAtPath;
|
|
658
657
|
exports.isDirty = isDirty;
|
|
659
|
-
exports.
|
|
658
|
+
exports.isPathPrefix = isPathPrefix;
|
|
659
|
+
exports.normalize = normalize;
|
|
660
|
+
exports.parsePath = parsePath;
|
|
660
661
|
exports.parseSubmission = parseSubmission;
|
|
661
662
|
exports.report = report;
|
|
662
663
|
exports.serialize = serialize;
|
|
663
|
-
exports.
|
|
664
|
+
exports.setPathValue = setPathValue;
|