@conform-to/dom 1.8.1 → 1.9.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 +32 -2
- package/dist/dom.js +111 -24
- package/dist/dom.mjs +104 -22
- package/dist/form.js +51 -40
- package/dist/form.mjs +49 -38
- package/dist/formdata.d.ts +122 -75
- package/dist/formdata.js +341 -241
- package/dist/formdata.mjs +328 -225
- package/dist/future/index.d.ts +5 -0
- package/dist/future/index.js +38 -0
- package/dist/future/index.mjs +3 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +3 -9
- package/dist/index.mjs +2 -2
- package/dist/submission.d.ts +13 -0
- package/dist/submission.js +81 -15
- package/dist/submission.mjs +77 -13
- package/dist/types.d.ts +99 -0
- package/dist/util.d.ts +11 -0
- package/dist/util.js +67 -0
- package/dist/util.mjs +65 -1
- package/package.json +8 -1
|
@@ -0,0 +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';
|
|
3
|
+
export { isPlainObject, deepEqual } from '../util';
|
|
4
|
+
export { isFieldElement, isGlobalInstance, updateField, createFileList, createSubmitEvent, createGlobalFormsObserver, focus, change, blur, getFormAction, getFormEncType, getFormMethod, requestSubmit, requestIntent, } from '../dom';
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var formdata = require('../formdata.js');
|
|
6
|
+
var util = require('../util.js');
|
|
7
|
+
var dom = require('../dom.js');
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
exports.DEFAULT_INTENT_NAME = formdata.DEFAULT_INTENT_NAME;
|
|
12
|
+
exports.appendPathSegment = formdata.appendPathSegment;
|
|
13
|
+
exports.formatPathSegments = formdata.formatPathSegments;
|
|
14
|
+
exports.getFormData = formdata.getFormData;
|
|
15
|
+
exports.getPathSegments = formdata.getPathSegments;
|
|
16
|
+
exports.getRelativePath = formdata.getRelativePath;
|
|
17
|
+
exports.getValueAtPath = formdata.getValueAtPath;
|
|
18
|
+
exports.isDirty = formdata.isDirty;
|
|
19
|
+
exports.parseSubmission = formdata.parseSubmission;
|
|
20
|
+
exports.report = formdata.report;
|
|
21
|
+
exports.serialize = formdata.serialize;
|
|
22
|
+
exports.setValueAtPath = formdata.setValueAtPath;
|
|
23
|
+
exports.deepEqual = util.deepEqual;
|
|
24
|
+
exports.isPlainObject = util.isPlainObject;
|
|
25
|
+
exports.blur = dom.blur;
|
|
26
|
+
exports.change = dom.change;
|
|
27
|
+
exports.createFileList = dom.createFileList;
|
|
28
|
+
exports.createGlobalFormsObserver = dom.createGlobalFormsObserver;
|
|
29
|
+
exports.createSubmitEvent = dom.createSubmitEvent;
|
|
30
|
+
exports.focus = dom.focus;
|
|
31
|
+
exports.getFormAction = dom.getFormAction;
|
|
32
|
+
exports.getFormEncType = dom.getFormEncType;
|
|
33
|
+
exports.getFormMethod = dom.getFormMethod;
|
|
34
|
+
exports.isFieldElement = dom.isFieldElement;
|
|
35
|
+
exports.isGlobalInstance = dom.isGlobalInstance;
|
|
36
|
+
exports.requestIntent = dom.requestIntent;
|
|
37
|
+
exports.requestSubmit = dom.requestSubmit;
|
|
38
|
+
exports.updateField = dom.updateField;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { DEFAULT_INTENT_NAME, appendPathSegment, formatPathSegments, getFormData, getPathSegments, getRelativePath, getValueAtPath, isDirty, parseSubmission, report, serialize, setValueAtPath } from '../formdata.mjs';
|
|
2
|
+
export { deepEqual, isPlainObject } from '../util.mjs';
|
|
3
|
+
export { blur, change, createFileList, createGlobalFormsObserver, createSubmitEvent, focus, getFormAction, getFormEncType, getFormMethod, isFieldElement, isGlobalInstance, requestIntent, requestSubmit, updateField } from '../dom.mjs';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { type Combine, type Constraint, type ControlButtonProps, type FormId, type FieldName, type DefaultValue, type FormValue, type FormOptions, type FormState, type FormContext, type SubscriptionSubject, type SubscriptionScope, createFormContext as unstable_createFormContext, } from './form';
|
|
2
|
-
export { type FieldElement, isFieldElement, updateField as unstable_updateField, createFileList,
|
|
2
|
+
export { type FieldElement, isFieldElement, isGlobalInstance, updateField as unstable_updateField, createFileList, } from './dom';
|
|
3
3
|
export { type Submission, type SubmissionResult, type Intent, INTENT, STATE, serializeIntent, parse, } from './submission';
|
|
4
|
-
export { getFormData,
|
|
4
|
+
export { getFormData, getPathSegments as getPaths, formatPathSegments as formatPaths, isPrefix, } from './formdata';
|
|
5
5
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -12,19 +12,13 @@ var formdata = require('./formdata.js');
|
|
|
12
12
|
exports.unstable_createFormContext = form.createFormContext;
|
|
13
13
|
exports.createFileList = dom.createFileList;
|
|
14
14
|
exports.isFieldElement = dom.isFieldElement;
|
|
15
|
-
exports.
|
|
16
|
-
exports.unstable_change = dom.change;
|
|
17
|
-
exports.unstable_createGlobalFormsObserver = dom.createGlobalFormsObserver;
|
|
18
|
-
exports.unstable_focus = dom.focus;
|
|
15
|
+
exports.isGlobalInstance = dom.isGlobalInstance;
|
|
19
16
|
exports.unstable_updateField = dom.updateField;
|
|
20
17
|
exports.INTENT = submission.INTENT;
|
|
21
18
|
exports.STATE = submission.STATE;
|
|
22
19
|
exports.parse = submission.parse;
|
|
23
20
|
exports.serializeIntent = submission.serializeIntent;
|
|
24
|
-
exports.formatPaths = formdata.
|
|
21
|
+
exports.formatPaths = formdata.formatPathSegments;
|
|
25
22
|
exports.getFormData = formdata.getFormData;
|
|
26
|
-
exports.getPaths = formdata.
|
|
27
|
-
exports.isGlobalInstance = formdata.isGlobalInstance;
|
|
23
|
+
exports.getPaths = formdata.getPathSegments;
|
|
28
24
|
exports.isPrefix = formdata.isPrefix;
|
|
29
|
-
exports.unstable_deepEqual = formdata.deepEqual;
|
|
30
|
-
exports.unstable_isDirty = formdata.isDirty;
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { createFormContext as unstable_createFormContext } from './form.mjs';
|
|
2
|
-
export { createFileList, isFieldElement,
|
|
2
|
+
export { createFileList, isFieldElement, isGlobalInstance, updateField as unstable_updateField } from './dom.mjs';
|
|
3
3
|
export { INTENT, STATE, parse, serializeIntent } from './submission.mjs';
|
|
4
|
-
export { formatPaths, getFormData,
|
|
4
|
+
export { formatPathSegments as formatPaths, getFormData, getPathSegments as getPaths, isPrefix } from './formdata.mjs';
|
package/dist/submission.d.ts
CHANGED
|
@@ -136,4 +136,17 @@ export declare const root: unique symbol;
|
|
|
136
136
|
export declare function setState(state: Record<string, unknown>, name: string, valueFn: (value: unknown) => unknown): void;
|
|
137
137
|
export declare function setListState(state: Record<string, unknown>, intent: InsertIntent | RemoveIntent | ReorderIntent, getDefaultValue?: (defaultValue: any) => any): void;
|
|
138
138
|
export declare function serialize<Schema>(defaultValue: Schema): FormValue<Schema>;
|
|
139
|
+
/**
|
|
140
|
+
* Normalize value by removing empty object or array, empty string and null values
|
|
141
|
+
*/
|
|
142
|
+
export declare function normalize<Type extends Record<string, unknown>>(value: Type, acceptFile?: boolean): Type | undefined;
|
|
143
|
+
export declare function normalize<Type extends Array<unknown>>(value: Type, acceptFile?: boolean): Type | undefined;
|
|
144
|
+
export declare function normalize(value: unknown, acceptFile?: boolean): unknown | undefined;
|
|
145
|
+
/**
|
|
146
|
+
* Flatten a tree into a dictionary
|
|
147
|
+
*/
|
|
148
|
+
export declare function flatten(data: unknown, options?: {
|
|
149
|
+
resolve?: (data: unknown) => unknown;
|
|
150
|
+
prefix?: string;
|
|
151
|
+
}): Record<string, unknown>;
|
|
139
152
|
//# sourceMappingURL=submission.d.ts.map
|
package/dist/submission.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
var _rollupPluginBabelHelpers = require('./_virtual/_rollupPluginBabelHelpers.js');
|
|
6
|
+
var dom = require('./dom.js');
|
|
6
7
|
var formdata = require('./formdata.js');
|
|
7
8
|
var util = require('./util.js');
|
|
8
9
|
|
|
@@ -32,7 +33,7 @@ function getSubmissionContext(body) {
|
|
|
32
33
|
return 1; // continue
|
|
33
34
|
}
|
|
34
35
|
context.fields.add(name);
|
|
35
|
-
formdata.
|
|
36
|
+
formdata.setValueAtPath(context.payload, name, prev => {
|
|
36
37
|
if (!prev) {
|
|
37
38
|
return next;
|
|
38
39
|
} else if (Array.isArray(prev)) {
|
|
@@ -40,6 +41,8 @@ function getSubmissionContext(body) {
|
|
|
40
41
|
} else {
|
|
41
42
|
return [prev, next];
|
|
42
43
|
}
|
|
44
|
+
}, {
|
|
45
|
+
silent: true
|
|
43
46
|
});
|
|
44
47
|
};
|
|
45
48
|
for (var [name, next] of body.entries()) {
|
|
@@ -54,11 +57,11 @@ function parse(payload, options) {
|
|
|
54
57
|
switch (intent.type) {
|
|
55
58
|
case 'update':
|
|
56
59
|
{
|
|
57
|
-
var name = formdata.
|
|
60
|
+
var name = formdata.appendPathSegment(intent.payload.name, intent.payload.index);
|
|
58
61
|
var _value = intent.payload.value;
|
|
59
62
|
if (typeof intent.payload.value !== 'undefined') {
|
|
60
63
|
if (name) {
|
|
61
|
-
formdata.
|
|
64
|
+
formdata.setValueAtPath(context.payload, name, () => _value);
|
|
62
65
|
} else {
|
|
63
66
|
context.payload = _value;
|
|
64
67
|
}
|
|
@@ -67,9 +70,9 @@ function parse(payload, options) {
|
|
|
67
70
|
}
|
|
68
71
|
case 'reset':
|
|
69
72
|
{
|
|
70
|
-
var _name = formdata.
|
|
73
|
+
var _name = formdata.appendPathSegment(intent.payload.name, intent.payload.index);
|
|
71
74
|
if (_name) {
|
|
72
|
-
formdata.
|
|
75
|
+
formdata.setValueAtPath(context.payload, _name, () => undefined);
|
|
73
76
|
} else {
|
|
74
77
|
context.payload = {};
|
|
75
78
|
}
|
|
@@ -124,17 +127,17 @@ function replySubmission(context) {
|
|
|
124
127
|
}
|
|
125
128
|
if ('hideFields' in options && options.hideFields) {
|
|
126
129
|
for (var name of options.hideFields) {
|
|
127
|
-
var _value2 = formdata.
|
|
130
|
+
var _value2 = formdata.getValueAtPath(context.payload, name);
|
|
128
131
|
if (typeof _value2 !== 'undefined') {
|
|
129
|
-
formdata.
|
|
132
|
+
formdata.setValueAtPath(context.payload, name, () => undefined);
|
|
130
133
|
}
|
|
131
134
|
}
|
|
132
135
|
}
|
|
133
|
-
var extraError = 'formErrors' in options || 'fieldErrors' in options ?
|
|
136
|
+
var extraError = 'formErrors' in options || 'fieldErrors' in options ? normalize(_rollupPluginBabelHelpers.objectSpread2({
|
|
134
137
|
'': (_options$formErrors = options.formErrors) !== null && _options$formErrors !== void 0 ? _options$formErrors : null
|
|
135
138
|
}, options.fieldErrors)) : null;
|
|
136
139
|
var error = context.error || extraError ? _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, context.error), extraError) : undefined;
|
|
137
|
-
var initialValue = (_ref =
|
|
140
|
+
var initialValue = (_ref = normalize(context.payload,
|
|
138
141
|
// We can't serialize the file and send it back from the server, but we can preserve it in the client
|
|
139
142
|
typeof document !== 'undefined'
|
|
140
143
|
// We need the file on the client because it's treated as the form value
|
|
@@ -198,7 +201,7 @@ function updateList(list, intent) {
|
|
|
198
201
|
}
|
|
199
202
|
}
|
|
200
203
|
function setListValue(data, intent) {
|
|
201
|
-
formdata.
|
|
204
|
+
formdata.setValueAtPath(data, intent.payload.name, value => {
|
|
202
205
|
var list = value !== null && value !== void 0 ? value : [];
|
|
203
206
|
updateList(list, intent);
|
|
204
207
|
return list;
|
|
@@ -216,7 +219,7 @@ function setState(state, name, valueFn) {
|
|
|
216
219
|
var _loop2 = function _loop2() {
|
|
217
220
|
var value = state[_key];
|
|
218
221
|
if (formdata.isPrefix(_key, name) && _key !== name) {
|
|
219
|
-
formdata.
|
|
222
|
+
formdata.setValueAtPath(target, _key, currentValue => {
|
|
220
223
|
if (typeof currentValue === 'undefined') {
|
|
221
224
|
return value;
|
|
222
225
|
}
|
|
@@ -236,10 +239,10 @@ function setState(state, name, valueFn) {
|
|
|
236
239
|
for (var _key of keys) {
|
|
237
240
|
_loop2();
|
|
238
241
|
}
|
|
239
|
-
var result = valueFn(formdata.
|
|
240
|
-
Object.assign(state,
|
|
242
|
+
var result = valueFn(formdata.getValueAtPath(target, name));
|
|
243
|
+
Object.assign(state, flatten(result, {
|
|
241
244
|
resolve(data) {
|
|
242
|
-
if (
|
|
245
|
+
if (util.isPlainObject(data) || Array.isArray(data)) {
|
|
243
246
|
var _data$root;
|
|
244
247
|
// @ts-expect-error
|
|
245
248
|
return (_data$root = data[root]) !== null && _data$root !== void 0 ? _data$root : null;
|
|
@@ -269,7 +272,7 @@ function setListState(state, intent, getDefaultValue) {
|
|
|
269
272
|
});
|
|
270
273
|
}
|
|
271
274
|
function serialize(defaultValue) {
|
|
272
|
-
if (
|
|
275
|
+
if (util.isPlainObject(defaultValue)) {
|
|
273
276
|
// @ts-expect-error FIXME
|
|
274
277
|
return Object.entries(defaultValue).reduce((result, _ref2) => {
|
|
275
278
|
var [key, value] = _ref2;
|
|
@@ -294,11 +297,74 @@ function serialize(defaultValue) {
|
|
|
294
297
|
}
|
|
295
298
|
}
|
|
296
299
|
|
|
300
|
+
/**
|
|
301
|
+
* Normalize value by removing empty object or array, empty string and null values
|
|
302
|
+
*/
|
|
303
|
+
|
|
304
|
+
function normalize(value) {
|
|
305
|
+
var acceptFile = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
|
|
306
|
+
if (util.isPlainObject(value)) {
|
|
307
|
+
var obj = Object.keys(value).sort().reduce((result, key) => {
|
|
308
|
+
var data = normalize(value[key], acceptFile);
|
|
309
|
+
if (typeof data !== 'undefined') {
|
|
310
|
+
result[key] = data;
|
|
311
|
+
}
|
|
312
|
+
return result;
|
|
313
|
+
}, {});
|
|
314
|
+
if (Object.keys(obj).length === 0) {
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
return obj;
|
|
318
|
+
}
|
|
319
|
+
if (Array.isArray(value)) {
|
|
320
|
+
if (value.length === 0) {
|
|
321
|
+
return undefined;
|
|
322
|
+
}
|
|
323
|
+
return value.map(item => normalize(item, acceptFile));
|
|
324
|
+
}
|
|
325
|
+
if (typeof value === 'string' && value === '' || value === null || dom.isGlobalInstance(value, 'File') && (!acceptFile || value.size === 0)) {
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
return value;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Flatten a tree into a dictionary
|
|
333
|
+
*/
|
|
334
|
+
function flatten(data) {
|
|
335
|
+
var _options$resolve;
|
|
336
|
+
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
337
|
+
var result = {};
|
|
338
|
+
var resolve = (_options$resolve = options.resolve) !== null && _options$resolve !== void 0 ? _options$resolve : data => data;
|
|
339
|
+
function process(data, prefix) {
|
|
340
|
+
var value = normalize(resolve(data));
|
|
341
|
+
if (typeof value !== 'undefined') {
|
|
342
|
+
result[prefix] = value;
|
|
343
|
+
}
|
|
344
|
+
if (Array.isArray(data)) {
|
|
345
|
+
for (var i = 0; i < data.length; i++) {
|
|
346
|
+
process(data[i], "".concat(prefix, "[").concat(i, "]"));
|
|
347
|
+
}
|
|
348
|
+
} else if (util.isPlainObject(data)) {
|
|
349
|
+
for (var [_key2, _value3] of Object.entries(data)) {
|
|
350
|
+
process(_value3, prefix ? "".concat(prefix, ".").concat(_key2) : _key2);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
if (data) {
|
|
355
|
+
var _options$prefix;
|
|
356
|
+
process(data, (_options$prefix = options.prefix) !== null && _options$prefix !== void 0 ? _options$prefix : '');
|
|
357
|
+
}
|
|
358
|
+
return result;
|
|
359
|
+
}
|
|
360
|
+
|
|
297
361
|
exports.INTENT = INTENT;
|
|
298
362
|
exports.STATE = STATE;
|
|
299
363
|
exports.createSubmission = createSubmission;
|
|
364
|
+
exports.flatten = flatten;
|
|
300
365
|
exports.getIntent = getIntent;
|
|
301
366
|
exports.getSubmissionContext = getSubmissionContext;
|
|
367
|
+
exports.normalize = normalize;
|
|
302
368
|
exports.parse = parse;
|
|
303
369
|
exports.replySubmission = replySubmission;
|
|
304
370
|
exports.root = root;
|
package/dist/submission.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { objectSpread2 as _objectSpread2 } from './_virtual/_rollupPluginBabelHelpers.mjs';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { isGlobalInstance } from './dom.mjs';
|
|
3
|
+
import { appendPathSegment, setValueAtPath, getValueAtPath, isPrefix } from './formdata.mjs';
|
|
4
|
+
import { isPlainObject, invariant } from './util.mjs';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* The name to be used when submitting a form control
|
|
@@ -28,7 +29,7 @@ function getSubmissionContext(body) {
|
|
|
28
29
|
return 1; // continue
|
|
29
30
|
}
|
|
30
31
|
context.fields.add(name);
|
|
31
|
-
|
|
32
|
+
setValueAtPath(context.payload, name, prev => {
|
|
32
33
|
if (!prev) {
|
|
33
34
|
return next;
|
|
34
35
|
} else if (Array.isArray(prev)) {
|
|
@@ -36,6 +37,8 @@ function getSubmissionContext(body) {
|
|
|
36
37
|
} else {
|
|
37
38
|
return [prev, next];
|
|
38
39
|
}
|
|
40
|
+
}, {
|
|
41
|
+
silent: true
|
|
39
42
|
});
|
|
40
43
|
};
|
|
41
44
|
for (var [name, next] of body.entries()) {
|
|
@@ -50,11 +53,11 @@ function parse(payload, options) {
|
|
|
50
53
|
switch (intent.type) {
|
|
51
54
|
case 'update':
|
|
52
55
|
{
|
|
53
|
-
var name =
|
|
56
|
+
var name = appendPathSegment(intent.payload.name, intent.payload.index);
|
|
54
57
|
var _value = intent.payload.value;
|
|
55
58
|
if (typeof intent.payload.value !== 'undefined') {
|
|
56
59
|
if (name) {
|
|
57
|
-
|
|
60
|
+
setValueAtPath(context.payload, name, () => _value);
|
|
58
61
|
} else {
|
|
59
62
|
context.payload = _value;
|
|
60
63
|
}
|
|
@@ -63,9 +66,9 @@ function parse(payload, options) {
|
|
|
63
66
|
}
|
|
64
67
|
case 'reset':
|
|
65
68
|
{
|
|
66
|
-
var _name =
|
|
69
|
+
var _name = appendPathSegment(intent.payload.name, intent.payload.index);
|
|
67
70
|
if (_name) {
|
|
68
|
-
|
|
71
|
+
setValueAtPath(context.payload, _name, () => undefined);
|
|
69
72
|
} else {
|
|
70
73
|
context.payload = {};
|
|
71
74
|
}
|
|
@@ -120,9 +123,9 @@ function replySubmission(context) {
|
|
|
120
123
|
}
|
|
121
124
|
if ('hideFields' in options && options.hideFields) {
|
|
122
125
|
for (var name of options.hideFields) {
|
|
123
|
-
var _value2 =
|
|
126
|
+
var _value2 = getValueAtPath(context.payload, name);
|
|
124
127
|
if (typeof _value2 !== 'undefined') {
|
|
125
|
-
|
|
128
|
+
setValueAtPath(context.payload, name, () => undefined);
|
|
126
129
|
}
|
|
127
130
|
}
|
|
128
131
|
}
|
|
@@ -194,7 +197,7 @@ function updateList(list, intent) {
|
|
|
194
197
|
}
|
|
195
198
|
}
|
|
196
199
|
function setListValue(data, intent) {
|
|
197
|
-
|
|
200
|
+
setValueAtPath(data, intent.payload.name, value => {
|
|
198
201
|
var list = value !== null && value !== void 0 ? value : [];
|
|
199
202
|
updateList(list, intent);
|
|
200
203
|
return list;
|
|
@@ -212,7 +215,7 @@ function setState(state, name, valueFn) {
|
|
|
212
215
|
var _loop2 = function _loop2() {
|
|
213
216
|
var value = state[_key];
|
|
214
217
|
if (isPrefix(_key, name) && _key !== name) {
|
|
215
|
-
|
|
218
|
+
setValueAtPath(target, _key, currentValue => {
|
|
216
219
|
if (typeof currentValue === 'undefined') {
|
|
217
220
|
return value;
|
|
218
221
|
}
|
|
@@ -232,7 +235,7 @@ function setState(state, name, valueFn) {
|
|
|
232
235
|
for (var _key of keys) {
|
|
233
236
|
_loop2();
|
|
234
237
|
}
|
|
235
|
-
var result = valueFn(
|
|
238
|
+
var result = valueFn(getValueAtPath(target, name));
|
|
236
239
|
Object.assign(state, flatten(result, {
|
|
237
240
|
resolve(data) {
|
|
238
241
|
if (isPlainObject(data) || Array.isArray(data)) {
|
|
@@ -290,4 +293,65 @@ function serialize(defaultValue) {
|
|
|
290
293
|
}
|
|
291
294
|
}
|
|
292
295
|
|
|
293
|
-
|
|
296
|
+
/**
|
|
297
|
+
* Normalize value by removing empty object or array, empty string and null values
|
|
298
|
+
*/
|
|
299
|
+
|
|
300
|
+
function normalize(value) {
|
|
301
|
+
var acceptFile = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
|
|
302
|
+
if (isPlainObject(value)) {
|
|
303
|
+
var obj = Object.keys(value).sort().reduce((result, key) => {
|
|
304
|
+
var data = normalize(value[key], acceptFile);
|
|
305
|
+
if (typeof data !== 'undefined') {
|
|
306
|
+
result[key] = data;
|
|
307
|
+
}
|
|
308
|
+
return result;
|
|
309
|
+
}, {});
|
|
310
|
+
if (Object.keys(obj).length === 0) {
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
return obj;
|
|
314
|
+
}
|
|
315
|
+
if (Array.isArray(value)) {
|
|
316
|
+
if (value.length === 0) {
|
|
317
|
+
return undefined;
|
|
318
|
+
}
|
|
319
|
+
return value.map(item => normalize(item, acceptFile));
|
|
320
|
+
}
|
|
321
|
+
if (typeof value === 'string' && value === '' || value === null || isGlobalInstance(value, 'File') && (!acceptFile || value.size === 0)) {
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
return value;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Flatten a tree into a dictionary
|
|
329
|
+
*/
|
|
330
|
+
function flatten(data) {
|
|
331
|
+
var _options$resolve;
|
|
332
|
+
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
333
|
+
var result = {};
|
|
334
|
+
var resolve = (_options$resolve = options.resolve) !== null && _options$resolve !== void 0 ? _options$resolve : data => data;
|
|
335
|
+
function process(data, prefix) {
|
|
336
|
+
var value = normalize(resolve(data));
|
|
337
|
+
if (typeof value !== 'undefined') {
|
|
338
|
+
result[prefix] = value;
|
|
339
|
+
}
|
|
340
|
+
if (Array.isArray(data)) {
|
|
341
|
+
for (var i = 0; i < data.length; i++) {
|
|
342
|
+
process(data[i], "".concat(prefix, "[").concat(i, "]"));
|
|
343
|
+
}
|
|
344
|
+
} else if (isPlainObject(data)) {
|
|
345
|
+
for (var [_key2, _value3] of Object.entries(data)) {
|
|
346
|
+
process(_value3, prefix ? "".concat(prefix, ".").concat(_key2) : _key2);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
if (data) {
|
|
351
|
+
var _options$prefix;
|
|
352
|
+
process(data, (_options$prefix = options.prefix) !== null && _options$prefix !== void 0 ? _options$prefix : '');
|
|
353
|
+
}
|
|
354
|
+
return result;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
export { INTENT, STATE, createSubmission, flatten, getIntent, getSubmissionContext, normalize, parse, replySubmission, root, serialize, serializeIntent, setListState, setListValue, setState, updateList };
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Valid JSON primitive types.
|
|
3
|
+
*/
|
|
4
|
+
export type JsonPrimitive = string | number | boolean | null;
|
|
5
|
+
/**
|
|
6
|
+
* The form value of a submission. This is usually constructed from a FormData or URLSearchParams.
|
|
7
|
+
* It may contains JSON primitives if the value is updated based on a form intent.
|
|
8
|
+
*/
|
|
9
|
+
export type FormValue<Type extends JsonPrimitive | FormDataEntryValue = JsonPrimitive | FormDataEntryValue> = Type | FormValue<Type | null>[] | {
|
|
10
|
+
[key: string]: FormValue<Type>;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Form error object that contains both form errors and field errors.
|
|
14
|
+
*/
|
|
15
|
+
export type FormError<ErrorShape = string> = {
|
|
16
|
+
/**
|
|
17
|
+
* The error of the form.
|
|
18
|
+
*/
|
|
19
|
+
formErrors: ErrorShape[];
|
|
20
|
+
/**
|
|
21
|
+
* The field errors based on the field name.
|
|
22
|
+
*/
|
|
23
|
+
fieldErrors: Record<string, ErrorShape[]>;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Structured data parsed from a form submission.
|
|
27
|
+
*/
|
|
28
|
+
export type Submission<ValueType extends JsonPrimitive | FormDataEntryValue = JsonPrimitive | FormDataEntryValue> = {
|
|
29
|
+
/**
|
|
30
|
+
* The submitted values mapped by field name.
|
|
31
|
+
* Supports nested names like `user.email` or indexed names like `items[0].id`.
|
|
32
|
+
*/
|
|
33
|
+
payload: Record<string, FormValue<ValueType>>;
|
|
34
|
+
/**
|
|
35
|
+
* The list of field names present in the FormData or URLSearchParams.
|
|
36
|
+
*/
|
|
37
|
+
fields: string[];
|
|
38
|
+
/**
|
|
39
|
+
* The submission intent, usually set by the name/value of the button that triggered the submission.
|
|
40
|
+
*/
|
|
41
|
+
intent: string | null;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* The result of a submission.
|
|
45
|
+
*/
|
|
46
|
+
export type SubmissionResult<ErrorShape = string, ValueType extends JsonPrimitive | FormDataEntryValue = JsonPrimitive | FormDataEntryValue> = {
|
|
47
|
+
/**
|
|
48
|
+
* The original submission data.
|
|
49
|
+
*/
|
|
50
|
+
submission: Submission<ValueType>;
|
|
51
|
+
/**
|
|
52
|
+
* The intended value of the submission. Defined only when the intended value is different from the submitted value.
|
|
53
|
+
*/
|
|
54
|
+
intendedValue?: Record<string, FormValue<ValueType>> | null;
|
|
55
|
+
/**
|
|
56
|
+
* Validation errors for `intendedValue` when present, otherwise for the original payload.
|
|
57
|
+
*/
|
|
58
|
+
error?: FormError<ErrorShape> | null;
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* The input attributes with related to the Constraint Validation API
|
|
62
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Constraint_validation
|
|
63
|
+
*/
|
|
64
|
+
export type ValidationAttributes = {
|
|
65
|
+
required?: boolean;
|
|
66
|
+
minLength?: number;
|
|
67
|
+
maxLength?: number;
|
|
68
|
+
min?: string | number;
|
|
69
|
+
max?: string | number;
|
|
70
|
+
step?: string | number;
|
|
71
|
+
multiple?: boolean;
|
|
72
|
+
pattern?: string;
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* A type helper that makes sure the FormError type is serializable.
|
|
76
|
+
* Used only to strip `File` type from the Form Shape at the moment.
|
|
77
|
+
*/
|
|
78
|
+
export type Serializable<T> = T extends File ? undefined : T extends Array<infer U> ? Serializable<U>[] : T extends object ? {
|
|
79
|
+
[K in keyof T]: Serializable<T[K]>;
|
|
80
|
+
} : T;
|
|
81
|
+
/**
|
|
82
|
+
* Converts an arbitrary value into a {@link SerializedValue}.
|
|
83
|
+
*
|
|
84
|
+
* This function is used to prepare field values for submission,
|
|
85
|
+
* ensuring they are compatible with the browser's `FormData` API.
|
|
86
|
+
*
|
|
87
|
+
* @param value - The original value to serialize.
|
|
88
|
+
* @returns A `SerializedValue` if the input can be represented in `FormData`,
|
|
89
|
+
* or `undefined` if it cannot be serialized.
|
|
90
|
+
*/
|
|
91
|
+
export type Serialize = (value: unknown) => SerializedValue | undefined;
|
|
92
|
+
/**
|
|
93
|
+
* A value that can be serialized into `FormData`.
|
|
94
|
+
*
|
|
95
|
+
* - `string` and `File` are supported natively by `FormData`.
|
|
96
|
+
* - Arrays allow representing multi-value fields.
|
|
97
|
+
*/
|
|
98
|
+
export type SerializedValue = string | string[] | File | File[];
|
|
99
|
+
//# sourceMappingURL=types.d.ts.map
|
package/dist/util.d.ts
CHANGED
|
@@ -1,4 +1,15 @@
|
|
|
1
|
+
import type { FormValue } from './types';
|
|
1
2
|
export declare function invariant(expectedCondition: boolean, message: string): asserts expectedCondition;
|
|
2
3
|
export declare function generateId(): string;
|
|
3
4
|
export declare function clone<Data>(data: Data): Data;
|
|
5
|
+
/**
|
|
6
|
+
* Check if the value is a plain object
|
|
7
|
+
*/
|
|
8
|
+
export declare function isPlainObject(obj: unknown): obj is Record<string | number | symbol, unknown>;
|
|
9
|
+
/**
|
|
10
|
+
* A utility function that performs a deep equality check between two values.
|
|
11
|
+
* It handles plain objects, arrays, and primitive values only.
|
|
12
|
+
*/
|
|
13
|
+
export declare function deepEqual(left: unknown, right: unknown): boolean;
|
|
14
|
+
export declare function stripFiles<Type extends string | number | boolean | File | null>(value: Record<string, FormValue<Type>>): Record<string, FormValue<Exclude<Type, File>>>;
|
|
4
15
|
//# sourceMappingURL=util.d.ts.map
|
package/dist/util.js
CHANGED
|
@@ -14,6 +14,73 @@ function clone(data) {
|
|
|
14
14
|
return JSON.parse(JSON.stringify(data));
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Check if the value is a plain object
|
|
19
|
+
*/
|
|
20
|
+
function isPlainObject(obj) {
|
|
21
|
+
return !!obj && obj.constructor === Object && Object.getPrototypeOf(obj) === Object.prototype;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* A utility function that performs a deep equality check between two values.
|
|
26
|
+
* It handles plain objects, arrays, and primitive values only.
|
|
27
|
+
*/
|
|
28
|
+
function deepEqual(left, right) {
|
|
29
|
+
if (Object.is(left, right)) {
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
if (left == null || right == null) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Compare plain objects
|
|
37
|
+
if (isPlainObject(left) && isPlainObject(right)) {
|
|
38
|
+
var prevKeys = Object.keys(left);
|
|
39
|
+
var nextKeys = Object.keys(right);
|
|
40
|
+
if (prevKeys.length !== nextKeys.length) {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
for (var key of prevKeys) {
|
|
44
|
+
if (!Object.prototype.hasOwnProperty.call(right, key) || !deepEqual(left[key], right[key])) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Compare arrays
|
|
52
|
+
if (Array.isArray(left) && Array.isArray(right)) {
|
|
53
|
+
if (left.length !== right.length) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
for (var i = 0; i < left.length; i++) {
|
|
57
|
+
if (!deepEqual(left[i], right[i])) {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/*
|
|
67
|
+
* Removes File object from the FormValue.
|
|
68
|
+
* Used to avoid serialzing/sending File object back to the client.
|
|
69
|
+
*/
|
|
70
|
+
function stripFiles(value) {
|
|
71
|
+
var json = JSON.stringify(value, (_, value) => {
|
|
72
|
+
// If the current value is a File, return undefined to omit it
|
|
73
|
+
if (typeof File !== 'undefined' && value instanceof File) {
|
|
74
|
+
return undefined;
|
|
75
|
+
}
|
|
76
|
+
return value;
|
|
77
|
+
});
|
|
78
|
+
return JSON.parse(json);
|
|
79
|
+
}
|
|
80
|
+
|
|
17
81
|
exports.clone = clone;
|
|
82
|
+
exports.deepEqual = deepEqual;
|
|
18
83
|
exports.generateId = generateId;
|
|
19
84
|
exports.invariant = invariant;
|
|
85
|
+
exports.isPlainObject = isPlainObject;
|
|
86
|
+
exports.stripFiles = stripFiles;
|