@conform-to/dom 1.0.1 → 1.0.3
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 +1 -1
- package/form.d.ts +12 -8
- package/form.js +89 -49
- package/form.mjs +91 -51
- package/formdata.d.ts +3 -3
- package/formdata.js +4 -3
- package/formdata.mjs +4 -3
- package/index.d.ts +1 -1
- package/package.json +1 -1
- package/submission.d.ts +3 -2
- package/submission.js +29 -86
- package/submission.mjs +30 -87
package/README
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
╚══════╝ ╚═════╝ ╚═╝ ╚══╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
Version 1.0.
|
|
11
|
+
Version 1.0.3 / License MIT / Copyright (c) 2024 Edmund Hung
|
|
12
12
|
|
|
13
13
|
A type-safe form validation library utilizing web fundamentals to progressively enhance HTML Forms with full support for server frameworks like Remix and Next.js.
|
|
14
14
|
|
package/form.d.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { getFormAction, getFormEncType, getFormMethod } from './dom';
|
|
2
2
|
import { type Intent, type Submission, type SubmissionResult } from './submission';
|
|
3
|
-
|
|
4
|
-
export type
|
|
5
|
-
[
|
|
6
|
-
}
|
|
3
|
+
type BaseCombine<T, K extends PropertyKey = T extends unknown ? keyof T : never> = T extends unknown ? T & Partial<Record<Exclude<K, keyof T>, never>> : never;
|
|
4
|
+
export type Combine<T> = {
|
|
5
|
+
[K in keyof BaseCombine<T>]: BaseCombine<T>[K];
|
|
6
|
+
};
|
|
7
7
|
export type DefaultValue<Schema> = Schema extends string | number | boolean | Date | bigint | null | undefined ? Schema | string | null | undefined : Schema extends File ? null | undefined : Schema extends Array<infer Item> ? Array<DefaultValue<Item>> | null | undefined : Schema extends Record<string, any> ? {
|
|
8
|
-
[Key in
|
|
8
|
+
[Key in keyof Schema]?: DefaultValue<Schema[Key]>;
|
|
9
9
|
} | null | undefined : string | null | undefined;
|
|
10
|
-
export type FormValue<Schema> = Schema extends string | number | boolean | Date | bigint | null | undefined ? string | undefined : Schema extends File ? File | undefined : Schema extends Array<infer Item> ? string | Array<FormValue<Item>> | undefined : Schema extends Record<string, any> ? {
|
|
11
|
-
[Key in
|
|
12
|
-
} | undefined : unknown;
|
|
10
|
+
export type FormValue<Schema> = Schema extends string | number | boolean | Date | bigint | null | undefined ? string | undefined : Schema extends File ? File | undefined : Schema extends File[] ? File | Array<File> | undefined : Schema extends Array<infer Item> ? string | Array<FormValue<Item>> | undefined : Schema extends Record<string, any> ? {
|
|
11
|
+
[Key in keyof Schema]?: FormValue<Schema[Key]>;
|
|
12
|
+
} | null | undefined : unknown;
|
|
13
13
|
declare const error: unique symbol;
|
|
14
14
|
declare const field: unique symbol;
|
|
15
15
|
declare const form: unique symbol;
|
|
@@ -90,6 +90,10 @@ export type FormOptions<Schema, FormError = string[], FormValue = Schema> = {
|
|
|
90
90
|
submitter: HTMLInputElement | HTMLButtonElement | null;
|
|
91
91
|
formData: FormData;
|
|
92
92
|
}) => Submission<Schema, FormError, FormValue>;
|
|
93
|
+
/**
|
|
94
|
+
* To schedule when an intent should be dispatched.
|
|
95
|
+
*/
|
|
96
|
+
onSchedule?: (callback: () => void) => void;
|
|
93
97
|
};
|
|
94
98
|
export type SubscriptionSubject = {
|
|
95
99
|
[key in 'error' | 'initialValue' | 'value' | 'key' | 'valid' | 'dirty']?: SubscriptionScope;
|
package/form.js
CHANGED
|
@@ -27,9 +27,7 @@ function createFormMeta(options, initialized) {
|
|
|
27
27
|
// We can consider adding a warning if it happens
|
|
28
28
|
error: (_ref = lastResult === null || lastResult === void 0 ? void 0 : lastResult.error) !== null && _ref !== void 0 ? _ref : {}
|
|
29
29
|
};
|
|
30
|
-
|
|
31
|
-
handleIntent(result, lastResult.intent);
|
|
32
|
-
}
|
|
30
|
+
handleIntent(result, lastResult === null || lastResult === void 0 ? void 0 : lastResult.intent, lastResult === null || lastResult === void 0 ? void 0 : lastResult.fields);
|
|
33
31
|
return result;
|
|
34
32
|
}
|
|
35
33
|
function getDefaultKey(defaultValue, prefix) {
|
|
@@ -45,24 +43,71 @@ function getDefaultKey(defaultValue, prefix) {
|
|
|
45
43
|
return result;
|
|
46
44
|
}, {});
|
|
47
45
|
}
|
|
48
|
-
function
|
|
46
|
+
function setFieldsValidated(meta, fields) {
|
|
47
|
+
for (var _name of Object.keys(meta.error).concat(fields !== null && fields !== void 0 ? fields : [])) {
|
|
48
|
+
meta.validated[_name] = true;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function handleIntent(meta, intent, fields, initialized) {
|
|
52
|
+
if (!intent) {
|
|
53
|
+
setFieldsValidated(meta, fields);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
49
56
|
switch (intent.type) {
|
|
57
|
+
case 'validate':
|
|
58
|
+
{
|
|
59
|
+
if (intent.payload.name) {
|
|
60
|
+
meta.validated[intent.payload.name] = true;
|
|
61
|
+
} else {
|
|
62
|
+
setFieldsValidated(meta, fields);
|
|
63
|
+
}
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
50
66
|
case 'update':
|
|
51
67
|
{
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
68
|
+
var {
|
|
69
|
+
name: _name2,
|
|
70
|
+
validated,
|
|
71
|
+
value
|
|
72
|
+
} = intent.payload;
|
|
73
|
+
if (typeof value !== 'undefined') {
|
|
74
|
+
updateValue(meta, _name2 !== null && _name2 !== void 0 ? _name2 : '', submission.serialize(value));
|
|
75
|
+
}
|
|
76
|
+
if (typeof validated !== 'undefined') {
|
|
77
|
+
// Clean up previous validated state
|
|
78
|
+
if (_name2) {
|
|
79
|
+
submission.setState(meta.validated, _name2, () => undefined);
|
|
80
|
+
} else {
|
|
81
|
+
meta.validated = {};
|
|
82
|
+
}
|
|
83
|
+
if (validated) {
|
|
84
|
+
if (formdata.isPlainObject(value) || Array.isArray(value)) {
|
|
85
|
+
Object.assign(meta.validated, formdata.flatten(value, {
|
|
86
|
+
resolve() {
|
|
87
|
+
return true;
|
|
88
|
+
},
|
|
89
|
+
prefix: _name2
|
|
90
|
+
}));
|
|
91
|
+
}
|
|
92
|
+
meta.validated[_name2 !== null && _name2 !== void 0 ? _name2 : ''] = true;
|
|
93
|
+
} else if (_name2) {
|
|
94
|
+
delete meta.validated[_name2];
|
|
95
|
+
}
|
|
57
96
|
}
|
|
58
97
|
break;
|
|
59
98
|
}
|
|
60
99
|
case 'reset':
|
|
61
100
|
{
|
|
62
|
-
var _intent$payload$
|
|
63
|
-
var
|
|
64
|
-
var _value = formdata.getValue(meta.defaultValue,
|
|
65
|
-
updateValue(meta,
|
|
101
|
+
var _intent$payload$name;
|
|
102
|
+
var _name3 = (_intent$payload$name = intent.payload.name) !== null && _intent$payload$name !== void 0 ? _intent$payload$name : '';
|
|
103
|
+
var _value = formdata.getValue(meta.defaultValue, _name3);
|
|
104
|
+
updateValue(meta, _name3, _value);
|
|
105
|
+
if (_name3) {
|
|
106
|
+
submission.setState(meta.validated, _name3, () => undefined);
|
|
107
|
+
delete meta.validated[_name3];
|
|
108
|
+
} else {
|
|
109
|
+
meta.validated = {};
|
|
110
|
+
}
|
|
66
111
|
break;
|
|
67
112
|
}
|
|
68
113
|
case 'insert':
|
|
@@ -75,9 +120,18 @@ function handleIntent(meta, intent, initialized) {
|
|
|
75
120
|
submission.setListState(meta.key, intent, util.generateId);
|
|
76
121
|
submission.setListValue(meta.initialValue, intent);
|
|
77
122
|
}
|
|
123
|
+
submission.setListState(meta.validated, intent);
|
|
124
|
+
meta.validated[intent.payload.name] = true;
|
|
78
125
|
break;
|
|
79
126
|
}
|
|
80
127
|
}
|
|
128
|
+
meta.error = Object.entries(meta.error).reduce((result, _ref3) => {
|
|
129
|
+
var [name, error] = _ref3;
|
|
130
|
+
if (meta.validated[name]) {
|
|
131
|
+
result[name] = error;
|
|
132
|
+
}
|
|
133
|
+
return result;
|
|
134
|
+
}, {});
|
|
81
135
|
}
|
|
82
136
|
function updateValue(meta, name, value) {
|
|
83
137
|
meta.initialValue = util.clone(meta.initialValue);
|
|
@@ -96,6 +150,9 @@ function createStateProxy(fn) {
|
|
|
96
150
|
return new Proxy(cache, {
|
|
97
151
|
get(_, name, receiver) {
|
|
98
152
|
var _cache$name;
|
|
153
|
+
if (typeof name !== 'string') {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
99
156
|
return (_cache$name = cache[name]) !== null && _cache$name !== void 0 ? _cache$name : cache[name] = fn(name, receiver);
|
|
100
157
|
}
|
|
101
158
|
});
|
|
@@ -165,8 +222,8 @@ function createValidProxy(error) {
|
|
|
165
222
|
function createDirtyProxy(defaultValue, value, shouldDirtyConsider) {
|
|
166
223
|
return createStateProxy(name => JSON.stringify(defaultValue[name]) !== JSON.stringify(value[name], (key, value) => {
|
|
167
224
|
if (name === '' && key === '' && value) {
|
|
168
|
-
return Object.entries(value).reduce((result,
|
|
169
|
-
var [name, value] =
|
|
225
|
+
return Object.entries(value).reduce((result, _ref4) => {
|
|
226
|
+
var [name, value] = _ref4;
|
|
170
227
|
if (!shouldDirtyConsider(name)) {
|
|
171
228
|
return result;
|
|
172
229
|
}
|
|
@@ -185,11 +242,11 @@ function shouldNotify(prev, next, cache, scope) {
|
|
|
185
242
|
var prefixes = (_scope$prefix = scope.prefix) !== null && _scope$prefix !== void 0 ? _scope$prefix : [];
|
|
186
243
|
var names = (_scope$name = scope.name) !== null && _scope$name !== void 0 ? _scope$name : [];
|
|
187
244
|
var list = prefixes.length === 0 ? names : Array.from(new Set([...Object.keys(prev), ...Object.keys(next)]));
|
|
188
|
-
var _loop = function _loop(
|
|
189
|
-
if (prefixes.length === 0 || names.includes(
|
|
245
|
+
var _loop = function _loop(_name4) {
|
|
246
|
+
if (prefixes.length === 0 || names.includes(_name4) || prefixes.some(prefix => formdata.isPrefix(_name4, prefix))) {
|
|
190
247
|
var _cache$_name;
|
|
191
|
-
(_cache$_name = cache[
|
|
192
|
-
if (cache[
|
|
248
|
+
(_cache$_name = cache[_name4]) !== null && _cache$_name !== void 0 ? _cache$_name : cache[_name4] = compareFn(prev[_name4], next[_name4]);
|
|
249
|
+
if (cache[_name4]) {
|
|
193
250
|
return {
|
|
194
251
|
v: true
|
|
195
252
|
};
|
|
@@ -197,8 +254,8 @@ function shouldNotify(prev, next, cache, scope) {
|
|
|
197
254
|
}
|
|
198
255
|
},
|
|
199
256
|
_ret;
|
|
200
|
-
for (var
|
|
201
|
-
_ret = _loop(
|
|
257
|
+
for (var _name4 of list) {
|
|
258
|
+
_ret = _loop(_name4);
|
|
202
259
|
if (_ret) return _ret.v;
|
|
203
260
|
}
|
|
204
261
|
}
|
|
@@ -263,19 +320,6 @@ function createFormContext(options) {
|
|
|
263
320
|
var next = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
264
321
|
return prev !== next;
|
|
265
322
|
}
|
|
266
|
-
function getStateInput(form) {
|
|
267
|
-
var element = form.elements.namedItem(submission.STATE);
|
|
268
|
-
util.invariant(element === null || dom.isFieldElement(element), "The input name \"".concat(submission.STATE, "\" is reserved by Conform. Please use another name."));
|
|
269
|
-
if (!element) {
|
|
270
|
-
var input = document.createElement('input');
|
|
271
|
-
input.type = 'hidden';
|
|
272
|
-
input.name = submission.STATE;
|
|
273
|
-
input.value = '';
|
|
274
|
-
form.append(input);
|
|
275
|
-
return input;
|
|
276
|
-
}
|
|
277
|
-
return element;
|
|
278
|
-
}
|
|
279
323
|
function getSerializedState() {
|
|
280
324
|
return JSON.stringify({
|
|
281
325
|
validated: meta.validated
|
|
@@ -285,10 +329,6 @@ function createFormContext(options) {
|
|
|
285
329
|
var form = event.target;
|
|
286
330
|
var submitter = event.submitter;
|
|
287
331
|
util.invariant(form === getFormElement(), "The submit event is dispatched by form#".concat(form.id, " instead of form#").concat(latestOptions.formId));
|
|
288
|
-
var input = getStateInput(form);
|
|
289
|
-
|
|
290
|
-
// To ensure it capturing latest state before parsing
|
|
291
|
-
input.value = getSerializedState();
|
|
292
332
|
var formData = formdata.getFormData(form, submitter);
|
|
293
333
|
var result = {
|
|
294
334
|
formData,
|
|
@@ -367,14 +407,14 @@ function createFormContext(options) {
|
|
|
367
407
|
updateFormMeta(createFormMeta(latestOptions, true));
|
|
368
408
|
}
|
|
369
409
|
function report(result) {
|
|
370
|
-
var _result$error, _result$state
|
|
410
|
+
var _result$error, _result$state;
|
|
371
411
|
var formElement = getFormElement();
|
|
372
412
|
if (!result.initialValue) {
|
|
373
413
|
formElement === null || formElement === void 0 || formElement.reset();
|
|
374
414
|
return;
|
|
375
415
|
}
|
|
376
|
-
var error = Object.entries((_result$error = result.error) !== null && _result$error !== void 0 ? _result$error : {}).reduce((result,
|
|
377
|
-
var [name, newError] =
|
|
416
|
+
var error = Object.entries((_result$error = result.error) !== null && _result$error !== void 0 ? _result$error : {}).reduce((result, _ref5) => {
|
|
417
|
+
var [name, newError] = _ref5;
|
|
378
418
|
var error = newError === null ? meta.error[name] : newError;
|
|
379
419
|
if (error) {
|
|
380
420
|
result[name] = error;
|
|
@@ -384,16 +424,14 @@ function createFormContext(options) {
|
|
|
384
424
|
var update = _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, meta), {}, {
|
|
385
425
|
submissionStatus: result.status,
|
|
386
426
|
value: result.initialValue,
|
|
387
|
-
|
|
388
|
-
|
|
427
|
+
validated: _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, meta.validated), (_result$state = result.state) === null || _result$state === void 0 ? void 0 : _result$state.validated),
|
|
428
|
+
error
|
|
389
429
|
});
|
|
390
|
-
|
|
391
|
-
handleIntent(update, result.intent, true);
|
|
392
|
-
}
|
|
430
|
+
handleIntent(update, result.intent, result.fields, true);
|
|
393
431
|
updateFormMeta(update);
|
|
394
432
|
if (formElement && result.status === 'error') {
|
|
395
433
|
for (var element of formElement.elements) {
|
|
396
|
-
if (dom.isFieldElement(element) && error[element.name]) {
|
|
434
|
+
if (dom.isFieldElement(element) && meta.error[element.name]) {
|
|
397
435
|
element.focus();
|
|
398
436
|
break;
|
|
399
437
|
}
|
|
@@ -447,12 +485,14 @@ function createFormContext(options) {
|
|
|
447
485
|
};
|
|
448
486
|
}
|
|
449
487
|
function createFormControl(type) {
|
|
488
|
+
var _latestOptions$onSche;
|
|
489
|
+
var schedule = (_latestOptions$onSche = latestOptions.onSchedule) !== null && _latestOptions$onSche !== void 0 ? _latestOptions$onSche : callback => callback();
|
|
450
490
|
var control = function control() {
|
|
451
491
|
var payload = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
452
|
-
return dispatch({
|
|
492
|
+
return schedule(() => dispatch({
|
|
453
493
|
type,
|
|
454
494
|
payload
|
|
455
|
-
});
|
|
495
|
+
}));
|
|
456
496
|
};
|
|
457
497
|
return Object.assign(control, {
|
|
458
498
|
getButtonProps() {
|
package/form.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { objectSpread2 as _objectSpread2 } from './_virtual/_rollupPluginBabelHelpers.mjs';
|
|
2
|
-
import { flatten, formatPaths, getPaths, getValue,
|
|
2
|
+
import { flatten, formatPaths, getPaths, getValue, isPlainObject, setValue, normalize, getFormData, isPrefix } from './formdata.mjs';
|
|
3
3
|
import { getFormAction, getFormEncType, getFormMethod, isFieldElement, requestSubmit } from './dom.mjs';
|
|
4
4
|
import { generateId, clone, invariant } from './util.mjs';
|
|
5
|
-
import { serialize, setListState, setListValue, setState, getSubmissionContext, INTENT, serializeIntent
|
|
5
|
+
import { serialize, setListState, setListValue, setState, getSubmissionContext, INTENT, serializeIntent } from './submission.mjs';
|
|
6
6
|
|
|
7
7
|
function createFormMeta(options, initialized) {
|
|
8
8
|
var _lastResult$initialVa, _options$constraint, _lastResult$state$val, _lastResult$state, _ref;
|
|
@@ -23,9 +23,7 @@ function createFormMeta(options, initialized) {
|
|
|
23
23
|
// We can consider adding a warning if it happens
|
|
24
24
|
error: (_ref = lastResult === null || lastResult === void 0 ? void 0 : lastResult.error) !== null && _ref !== void 0 ? _ref : {}
|
|
25
25
|
};
|
|
26
|
-
|
|
27
|
-
handleIntent(result, lastResult.intent);
|
|
28
|
-
}
|
|
26
|
+
handleIntent(result, lastResult === null || lastResult === void 0 ? void 0 : lastResult.intent, lastResult === null || lastResult === void 0 ? void 0 : lastResult.fields);
|
|
29
27
|
return result;
|
|
30
28
|
}
|
|
31
29
|
function getDefaultKey(defaultValue, prefix) {
|
|
@@ -41,24 +39,71 @@ function getDefaultKey(defaultValue, prefix) {
|
|
|
41
39
|
return result;
|
|
42
40
|
}, {});
|
|
43
41
|
}
|
|
44
|
-
function
|
|
42
|
+
function setFieldsValidated(meta, fields) {
|
|
43
|
+
for (var _name of Object.keys(meta.error).concat(fields !== null && fields !== void 0 ? fields : [])) {
|
|
44
|
+
meta.validated[_name] = true;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function handleIntent(meta, intent, fields, initialized) {
|
|
48
|
+
if (!intent) {
|
|
49
|
+
setFieldsValidated(meta, fields);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
45
52
|
switch (intent.type) {
|
|
53
|
+
case 'validate':
|
|
54
|
+
{
|
|
55
|
+
if (intent.payload.name) {
|
|
56
|
+
meta.validated[intent.payload.name] = true;
|
|
57
|
+
} else {
|
|
58
|
+
setFieldsValidated(meta, fields);
|
|
59
|
+
}
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
46
62
|
case 'update':
|
|
47
63
|
{
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
64
|
+
var {
|
|
65
|
+
name: _name2,
|
|
66
|
+
validated,
|
|
67
|
+
value
|
|
68
|
+
} = intent.payload;
|
|
69
|
+
if (typeof value !== 'undefined') {
|
|
70
|
+
updateValue(meta, _name2 !== null && _name2 !== void 0 ? _name2 : '', serialize(value));
|
|
71
|
+
}
|
|
72
|
+
if (typeof validated !== 'undefined') {
|
|
73
|
+
// Clean up previous validated state
|
|
74
|
+
if (_name2) {
|
|
75
|
+
setState(meta.validated, _name2, () => undefined);
|
|
76
|
+
} else {
|
|
77
|
+
meta.validated = {};
|
|
78
|
+
}
|
|
79
|
+
if (validated) {
|
|
80
|
+
if (isPlainObject(value) || Array.isArray(value)) {
|
|
81
|
+
Object.assign(meta.validated, flatten(value, {
|
|
82
|
+
resolve() {
|
|
83
|
+
return true;
|
|
84
|
+
},
|
|
85
|
+
prefix: _name2
|
|
86
|
+
}));
|
|
87
|
+
}
|
|
88
|
+
meta.validated[_name2 !== null && _name2 !== void 0 ? _name2 : ''] = true;
|
|
89
|
+
} else if (_name2) {
|
|
90
|
+
delete meta.validated[_name2];
|
|
91
|
+
}
|
|
53
92
|
}
|
|
54
93
|
break;
|
|
55
94
|
}
|
|
56
95
|
case 'reset':
|
|
57
96
|
{
|
|
58
|
-
var _intent$payload$
|
|
59
|
-
var
|
|
60
|
-
var _value = getValue(meta.defaultValue,
|
|
61
|
-
updateValue(meta,
|
|
97
|
+
var _intent$payload$name;
|
|
98
|
+
var _name3 = (_intent$payload$name = intent.payload.name) !== null && _intent$payload$name !== void 0 ? _intent$payload$name : '';
|
|
99
|
+
var _value = getValue(meta.defaultValue, _name3);
|
|
100
|
+
updateValue(meta, _name3, _value);
|
|
101
|
+
if (_name3) {
|
|
102
|
+
setState(meta.validated, _name3, () => undefined);
|
|
103
|
+
delete meta.validated[_name3];
|
|
104
|
+
} else {
|
|
105
|
+
meta.validated = {};
|
|
106
|
+
}
|
|
62
107
|
break;
|
|
63
108
|
}
|
|
64
109
|
case 'insert':
|
|
@@ -71,9 +116,18 @@ function handleIntent(meta, intent, initialized) {
|
|
|
71
116
|
setListState(meta.key, intent, generateId);
|
|
72
117
|
setListValue(meta.initialValue, intent);
|
|
73
118
|
}
|
|
119
|
+
setListState(meta.validated, intent);
|
|
120
|
+
meta.validated[intent.payload.name] = true;
|
|
74
121
|
break;
|
|
75
122
|
}
|
|
76
123
|
}
|
|
124
|
+
meta.error = Object.entries(meta.error).reduce((result, _ref3) => {
|
|
125
|
+
var [name, error] = _ref3;
|
|
126
|
+
if (meta.validated[name]) {
|
|
127
|
+
result[name] = error;
|
|
128
|
+
}
|
|
129
|
+
return result;
|
|
130
|
+
}, {});
|
|
77
131
|
}
|
|
78
132
|
function updateValue(meta, name, value) {
|
|
79
133
|
meta.initialValue = clone(meta.initialValue);
|
|
@@ -92,6 +146,9 @@ function createStateProxy(fn) {
|
|
|
92
146
|
return new Proxy(cache, {
|
|
93
147
|
get(_, name, receiver) {
|
|
94
148
|
var _cache$name;
|
|
149
|
+
if (typeof name !== 'string') {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
95
152
|
return (_cache$name = cache[name]) !== null && _cache$name !== void 0 ? _cache$name : cache[name] = fn(name, receiver);
|
|
96
153
|
}
|
|
97
154
|
});
|
|
@@ -161,8 +218,8 @@ function createValidProxy(error) {
|
|
|
161
218
|
function createDirtyProxy(defaultValue, value, shouldDirtyConsider) {
|
|
162
219
|
return createStateProxy(name => JSON.stringify(defaultValue[name]) !== JSON.stringify(value[name], (key, value) => {
|
|
163
220
|
if (name === '' && key === '' && value) {
|
|
164
|
-
return Object.entries(value).reduce((result,
|
|
165
|
-
var [name, value] =
|
|
221
|
+
return Object.entries(value).reduce((result, _ref4) => {
|
|
222
|
+
var [name, value] = _ref4;
|
|
166
223
|
if (!shouldDirtyConsider(name)) {
|
|
167
224
|
return result;
|
|
168
225
|
}
|
|
@@ -181,11 +238,11 @@ function shouldNotify(prev, next, cache, scope) {
|
|
|
181
238
|
var prefixes = (_scope$prefix = scope.prefix) !== null && _scope$prefix !== void 0 ? _scope$prefix : [];
|
|
182
239
|
var names = (_scope$name = scope.name) !== null && _scope$name !== void 0 ? _scope$name : [];
|
|
183
240
|
var list = prefixes.length === 0 ? names : Array.from(new Set([...Object.keys(prev), ...Object.keys(next)]));
|
|
184
|
-
var _loop = function _loop(
|
|
185
|
-
if (prefixes.length === 0 || names.includes(
|
|
241
|
+
var _loop = function _loop(_name4) {
|
|
242
|
+
if (prefixes.length === 0 || names.includes(_name4) || prefixes.some(prefix => isPrefix(_name4, prefix))) {
|
|
186
243
|
var _cache$_name;
|
|
187
|
-
(_cache$_name = cache[
|
|
188
|
-
if (cache[
|
|
244
|
+
(_cache$_name = cache[_name4]) !== null && _cache$_name !== void 0 ? _cache$_name : cache[_name4] = compareFn(prev[_name4], next[_name4]);
|
|
245
|
+
if (cache[_name4]) {
|
|
189
246
|
return {
|
|
190
247
|
v: true
|
|
191
248
|
};
|
|
@@ -193,8 +250,8 @@ function shouldNotify(prev, next, cache, scope) {
|
|
|
193
250
|
}
|
|
194
251
|
},
|
|
195
252
|
_ret;
|
|
196
|
-
for (var
|
|
197
|
-
_ret = _loop(
|
|
253
|
+
for (var _name4 of list) {
|
|
254
|
+
_ret = _loop(_name4);
|
|
198
255
|
if (_ret) return _ret.v;
|
|
199
256
|
}
|
|
200
257
|
}
|
|
@@ -259,19 +316,6 @@ function createFormContext(options) {
|
|
|
259
316
|
var next = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
260
317
|
return prev !== next;
|
|
261
318
|
}
|
|
262
|
-
function getStateInput(form) {
|
|
263
|
-
var element = form.elements.namedItem(STATE);
|
|
264
|
-
invariant(element === null || isFieldElement(element), "The input name \"".concat(STATE, "\" is reserved by Conform. Please use another name."));
|
|
265
|
-
if (!element) {
|
|
266
|
-
var input = document.createElement('input');
|
|
267
|
-
input.type = 'hidden';
|
|
268
|
-
input.name = STATE;
|
|
269
|
-
input.value = '';
|
|
270
|
-
form.append(input);
|
|
271
|
-
return input;
|
|
272
|
-
}
|
|
273
|
-
return element;
|
|
274
|
-
}
|
|
275
319
|
function getSerializedState() {
|
|
276
320
|
return JSON.stringify({
|
|
277
321
|
validated: meta.validated
|
|
@@ -281,10 +325,6 @@ function createFormContext(options) {
|
|
|
281
325
|
var form = event.target;
|
|
282
326
|
var submitter = event.submitter;
|
|
283
327
|
invariant(form === getFormElement(), "The submit event is dispatched by form#".concat(form.id, " instead of form#").concat(latestOptions.formId));
|
|
284
|
-
var input = getStateInput(form);
|
|
285
|
-
|
|
286
|
-
// To ensure it capturing latest state before parsing
|
|
287
|
-
input.value = getSerializedState();
|
|
288
328
|
var formData = getFormData(form, submitter);
|
|
289
329
|
var result = {
|
|
290
330
|
formData,
|
|
@@ -363,14 +403,14 @@ function createFormContext(options) {
|
|
|
363
403
|
updateFormMeta(createFormMeta(latestOptions, true));
|
|
364
404
|
}
|
|
365
405
|
function report(result) {
|
|
366
|
-
var _result$error, _result$state
|
|
406
|
+
var _result$error, _result$state;
|
|
367
407
|
var formElement = getFormElement();
|
|
368
408
|
if (!result.initialValue) {
|
|
369
409
|
formElement === null || formElement === void 0 || formElement.reset();
|
|
370
410
|
return;
|
|
371
411
|
}
|
|
372
|
-
var error = Object.entries((_result$error = result.error) !== null && _result$error !== void 0 ? _result$error : {}).reduce((result,
|
|
373
|
-
var [name, newError] =
|
|
412
|
+
var error = Object.entries((_result$error = result.error) !== null && _result$error !== void 0 ? _result$error : {}).reduce((result, _ref5) => {
|
|
413
|
+
var [name, newError] = _ref5;
|
|
374
414
|
var error = newError === null ? meta.error[name] : newError;
|
|
375
415
|
if (error) {
|
|
376
416
|
result[name] = error;
|
|
@@ -380,16 +420,14 @@ function createFormContext(options) {
|
|
|
380
420
|
var update = _objectSpread2(_objectSpread2({}, meta), {}, {
|
|
381
421
|
submissionStatus: result.status,
|
|
382
422
|
value: result.initialValue,
|
|
383
|
-
|
|
384
|
-
|
|
423
|
+
validated: _objectSpread2(_objectSpread2({}, meta.validated), (_result$state = result.state) === null || _result$state === void 0 ? void 0 : _result$state.validated),
|
|
424
|
+
error
|
|
385
425
|
});
|
|
386
|
-
|
|
387
|
-
handleIntent(update, result.intent, true);
|
|
388
|
-
}
|
|
426
|
+
handleIntent(update, result.intent, result.fields, true);
|
|
389
427
|
updateFormMeta(update);
|
|
390
428
|
if (formElement && result.status === 'error') {
|
|
391
429
|
for (var element of formElement.elements) {
|
|
392
|
-
if (isFieldElement(element) && error[element.name]) {
|
|
430
|
+
if (isFieldElement(element) && meta.error[element.name]) {
|
|
393
431
|
element.focus();
|
|
394
432
|
break;
|
|
395
433
|
}
|
|
@@ -443,12 +481,14 @@ function createFormContext(options) {
|
|
|
443
481
|
};
|
|
444
482
|
}
|
|
445
483
|
function createFormControl(type) {
|
|
484
|
+
var _latestOptions$onSche;
|
|
485
|
+
var schedule = (_latestOptions$onSche = latestOptions.onSchedule) !== null && _latestOptions$onSche !== void 0 ? _latestOptions$onSche : callback => callback();
|
|
446
486
|
var control = function control() {
|
|
447
487
|
var payload = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
448
|
-
return dispatch({
|
|
488
|
+
return schedule(() => dispatch({
|
|
449
489
|
type,
|
|
450
490
|
payload
|
|
451
|
-
});
|
|
491
|
+
}));
|
|
452
492
|
};
|
|
453
493
|
return Object.assign(control, {
|
|
454
494
|
getButtonProps() {
|
package/formdata.d.ts
CHANGED
|
@@ -45,9 +45,9 @@ export declare function isFile(obj: unknown): obj is File;
|
|
|
45
45
|
/**
|
|
46
46
|
* Normalize value by removing empty object or array, empty string and null values
|
|
47
47
|
*/
|
|
48
|
-
export declare function normalize<Type extends Record<string, unknown>>(value: Type
|
|
49
|
-
export declare function normalize<Type extends Array<unknown>>(value: Type
|
|
50
|
-
export declare function normalize(value: unknown): unknown | undefined;
|
|
48
|
+
export declare function normalize<Type extends Record<string, unknown>>(value: Type, acceptFile?: boolean): Type | undefined;
|
|
49
|
+
export declare function normalize<Type extends Array<unknown>>(value: Type, acceptFile?: boolean): Type | undefined;
|
|
50
|
+
export declare function normalize(value: unknown, acceptFile?: boolean): unknown | undefined;
|
|
51
51
|
/**
|
|
52
52
|
* Flatten a tree into a dictionary
|
|
53
53
|
*/
|
package/formdata.js
CHANGED
|
@@ -136,9 +136,10 @@ function isFile(obj) {
|
|
|
136
136
|
*/
|
|
137
137
|
|
|
138
138
|
function normalize(value) {
|
|
139
|
+
var acceptFile = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
|
|
139
140
|
if (isPlainObject(value)) {
|
|
140
141
|
var obj = Object.keys(value).sort().reduce((result, key) => {
|
|
141
|
-
var data = normalize(value[key]);
|
|
142
|
+
var data = normalize(value[key], acceptFile);
|
|
142
143
|
if (typeof data !== 'undefined') {
|
|
143
144
|
result[key] = data;
|
|
144
145
|
}
|
|
@@ -153,9 +154,9 @@ function normalize(value) {
|
|
|
153
154
|
if (value.length === 0) {
|
|
154
155
|
return undefined;
|
|
155
156
|
}
|
|
156
|
-
return value.map(normalize);
|
|
157
|
+
return value.map(item => normalize(item, acceptFile));
|
|
157
158
|
}
|
|
158
|
-
if (typeof value === 'string' && value === '' || value === null || isFile(value)) {
|
|
159
|
+
if (typeof value === 'string' && value === '' || value === null || isFile(value) && (!acceptFile || value.size === 0)) {
|
|
159
160
|
return;
|
|
160
161
|
}
|
|
161
162
|
return value;
|
package/formdata.mjs
CHANGED
|
@@ -132,9 +132,10 @@ function isFile(obj) {
|
|
|
132
132
|
*/
|
|
133
133
|
|
|
134
134
|
function normalize(value) {
|
|
135
|
+
var acceptFile = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
|
|
135
136
|
if (isPlainObject(value)) {
|
|
136
137
|
var obj = Object.keys(value).sort().reduce((result, key) => {
|
|
137
|
-
var data = normalize(value[key]);
|
|
138
|
+
var data = normalize(value[key], acceptFile);
|
|
138
139
|
if (typeof data !== 'undefined') {
|
|
139
140
|
result[key] = data;
|
|
140
141
|
}
|
|
@@ -149,9 +150,9 @@ function normalize(value) {
|
|
|
149
150
|
if (value.length === 0) {
|
|
150
151
|
return undefined;
|
|
151
152
|
}
|
|
152
|
-
return value.map(normalize);
|
|
153
|
+
return value.map(item => normalize(item, acceptFile));
|
|
153
154
|
}
|
|
154
|
-
if (typeof value === 'string' && value === '' || value === null || isFile(value)) {
|
|
155
|
+
if (typeof value === 'string' && value === '' || value === null || isFile(value) && (!acceptFile || value.size === 0)) {
|
|
155
156
|
return;
|
|
156
157
|
}
|
|
157
158
|
return value;
|
package/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { type
|
|
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
2
|
export { type FieldElement, isFieldElement } from './dom';
|
|
3
3
|
export { type Submission, type SubmissionResult, type Intent, INTENT, STATE, serializeIntent, parse, } from './submission';
|
|
4
4
|
export { getPaths, formatPaths, isPrefix } from './formdata';
|
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.0.
|
|
6
|
+
"version": "1.0.3",
|
|
7
7
|
"main": "index.js",
|
|
8
8
|
"module": "index.mjs",
|
|
9
9
|
"types": "index.d.ts",
|
package/submission.d.ts
CHANGED
|
@@ -5,10 +5,10 @@ export type SubmissionState = {
|
|
|
5
5
|
export type SubmissionContext<Value = null, FormError = string[]> = {
|
|
6
6
|
intent: Intent | null;
|
|
7
7
|
payload: Record<string, unknown>;
|
|
8
|
-
fields: string
|
|
8
|
+
fields: Set<string>;
|
|
9
9
|
value?: Value;
|
|
10
10
|
error?: Record<string, FormError | null> | null;
|
|
11
|
-
state
|
|
11
|
+
state?: SubmissionState;
|
|
12
12
|
};
|
|
13
13
|
export type Submission<Schema, FormError = string[], FormValue = Schema> = {
|
|
14
14
|
status: 'success';
|
|
@@ -25,6 +25,7 @@ export type SubmissionResult<FormError = string[]> = {
|
|
|
25
25
|
status?: 'error' | 'success';
|
|
26
26
|
intent?: Intent;
|
|
27
27
|
initialValue?: Record<string, unknown> | null;
|
|
28
|
+
fields?: string[];
|
|
28
29
|
error?: Record<string, FormError | null>;
|
|
29
30
|
state?: SubmissionState;
|
|
30
31
|
};
|
package/submission.js
CHANGED
|
@@ -18,15 +18,21 @@ var STATE = '__state__';
|
|
|
18
18
|
function getSubmissionContext(body) {
|
|
19
19
|
var intent = body.get(INTENT);
|
|
20
20
|
var state = body.get(STATE);
|
|
21
|
-
var payload = {};
|
|
22
|
-
var fields = [];
|
|
23
21
|
util.invariant((typeof intent === 'string' || intent === null) && (typeof state === 'string' || state === null), "The input name \"".concat(INTENT, "\" and \"").concat(STATE, "\" are reserved by Conform. Please use another name for your input."));
|
|
22
|
+
var context = {
|
|
23
|
+
payload: {},
|
|
24
|
+
fields: new Set(),
|
|
25
|
+
intent: getIntent(intent)
|
|
26
|
+
};
|
|
27
|
+
if (state) {
|
|
28
|
+
context.state = JSON.parse(state);
|
|
29
|
+
}
|
|
24
30
|
var _loop = function _loop(next) {
|
|
25
31
|
if (name === INTENT || name === STATE) {
|
|
26
32
|
return 1; // continue
|
|
27
33
|
}
|
|
28
|
-
fields.
|
|
29
|
-
formdata.setValue(payload, name, prev => {
|
|
34
|
+
context.fields.add(name);
|
|
35
|
+
formdata.setValue(context.payload, name, prev => {
|
|
30
36
|
if (!prev) {
|
|
31
37
|
return next;
|
|
32
38
|
} else if (Array.isArray(prev)) {
|
|
@@ -39,30 +45,17 @@ function getSubmissionContext(body) {
|
|
|
39
45
|
for (var [name, next] of body.entries()) {
|
|
40
46
|
if (_loop(next)) continue;
|
|
41
47
|
}
|
|
42
|
-
return
|
|
43
|
-
payload,
|
|
44
|
-
intent: getIntent(intent),
|
|
45
|
-
state: state ? JSON.parse(state) : {
|
|
46
|
-
validated: {}
|
|
47
|
-
},
|
|
48
|
-
fields
|
|
49
|
-
};
|
|
48
|
+
return context;
|
|
50
49
|
}
|
|
51
50
|
function parse(payload, options) {
|
|
52
51
|
var context = getSubmissionContext(payload);
|
|
53
52
|
var intent = context.intent;
|
|
54
53
|
if (intent) {
|
|
55
54
|
switch (intent.type) {
|
|
56
|
-
case 'validate':
|
|
57
|
-
if (intent.payload.name) {
|
|
58
|
-
context.state.validated[intent.payload.name] = true;
|
|
59
|
-
}
|
|
60
|
-
break;
|
|
61
55
|
case 'update':
|
|
62
56
|
{
|
|
63
57
|
var {
|
|
64
|
-
name
|
|
65
|
-
validated
|
|
58
|
+
name
|
|
66
59
|
} = intent.payload;
|
|
67
60
|
var _value = serialize(intent.payload.value);
|
|
68
61
|
if (typeof _value !== 'undefined') {
|
|
@@ -73,27 +66,6 @@ function parse(payload, options) {
|
|
|
73
66
|
context.payload = _value;
|
|
74
67
|
}
|
|
75
68
|
}
|
|
76
|
-
if (typeof validated !== 'undefined') {
|
|
77
|
-
// Clean up previous validated state
|
|
78
|
-
if (name) {
|
|
79
|
-
setState(context.state.validated, name, () => undefined);
|
|
80
|
-
} else {
|
|
81
|
-
context.state.validated = {};
|
|
82
|
-
}
|
|
83
|
-
if (validated) {
|
|
84
|
-
if (formdata.isPlainObject(_value) || Array.isArray(_value)) {
|
|
85
|
-
Object.assign(context.state.validated, formdata.flatten(_value, {
|
|
86
|
-
resolve() {
|
|
87
|
-
return true;
|
|
88
|
-
},
|
|
89
|
-
prefix: name
|
|
90
|
-
}));
|
|
91
|
-
}
|
|
92
|
-
context.state.validated[name !== null && name !== void 0 ? name : ''] = true;
|
|
93
|
-
} else if (name) {
|
|
94
|
-
delete context.state.validated[name];
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
69
|
break;
|
|
98
70
|
}
|
|
99
71
|
case 'reset':
|
|
@@ -103,11 +75,8 @@ function parse(payload, options) {
|
|
|
103
75
|
} = intent.payload;
|
|
104
76
|
if (_name) {
|
|
105
77
|
formdata.setValue(context.payload, _name, () => undefined);
|
|
106
|
-
setState(context.state.validated, _name, () => undefined);
|
|
107
|
-
delete context.state.validated[_name];
|
|
108
78
|
} else {
|
|
109
79
|
context.payload = {};
|
|
110
|
-
context.state.validated = {};
|
|
111
80
|
}
|
|
112
81
|
break;
|
|
113
82
|
}
|
|
@@ -116,25 +85,15 @@ function parse(payload, options) {
|
|
|
116
85
|
case 'reorder':
|
|
117
86
|
{
|
|
118
87
|
setListValue(context.payload, intent);
|
|
119
|
-
setListState(context.state.validated, intent);
|
|
120
|
-
context.state.validated[intent.payload.name] = true;
|
|
121
88
|
break;
|
|
122
89
|
}
|
|
123
90
|
}
|
|
124
91
|
}
|
|
125
92
|
var result = options.resolve(context.payload, intent);
|
|
126
|
-
var mergeResolveResult = resolved => {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
context.state.validated[_name2] = true;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
return createSubmission(_rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, context), {}, {
|
|
134
|
-
value: resolved.value,
|
|
135
|
-
error: resolved.error
|
|
136
|
-
}));
|
|
137
|
-
};
|
|
93
|
+
var mergeResolveResult = resolved => createSubmission(_rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, context), {}, {
|
|
94
|
+
value: resolved.value,
|
|
95
|
+
error: resolved.error
|
|
96
|
+
}));
|
|
138
97
|
if (result instanceof Promise) {
|
|
139
98
|
return result.then(mergeResolveResult);
|
|
140
99
|
}
|
|
@@ -161,50 +120,34 @@ function createSubmission(context) {
|
|
|
161
120
|
};
|
|
162
121
|
}
|
|
163
122
|
function replySubmission(context) {
|
|
164
|
-
var _context$intent, _options$formErrors, _normalize;
|
|
123
|
+
var _context$intent, _context$intent$paylo, _options$formErrors, _normalize;
|
|
165
124
|
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
166
|
-
|
|
167
|
-
case 'reset':
|
|
168
|
-
{
|
|
169
|
-
var _context$intent$paylo;
|
|
170
|
-
var name = (_context$intent$paylo = context.intent.payload.name) !== null && _context$intent$paylo !== void 0 ? _context$intent$paylo : '';
|
|
171
|
-
if (name === '') {
|
|
172
|
-
return {
|
|
173
|
-
initialValue: null
|
|
174
|
-
};
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
if ('resetForm' in options && options.resetForm) {
|
|
125
|
+
if ('resetForm' in options && options.resetForm || ((_context$intent = context.intent) === null || _context$intent === void 0 ? void 0 : _context$intent.type) === 'reset' && ((_context$intent$paylo = context.intent.payload.name) !== null && _context$intent$paylo !== void 0 ? _context$intent$paylo : '') === '') {
|
|
179
126
|
return {
|
|
180
127
|
initialValue: null
|
|
181
128
|
};
|
|
182
129
|
}
|
|
183
130
|
if ('hideFields' in options && options.hideFields) {
|
|
184
|
-
for (var
|
|
185
|
-
var _value2 = formdata.getValue(context.payload,
|
|
131
|
+
for (var name of options.hideFields) {
|
|
132
|
+
var _value2 = formdata.getValue(context.payload, name);
|
|
186
133
|
if (typeof _value2 !== 'undefined') {
|
|
187
|
-
formdata.setValue(context.payload,
|
|
134
|
+
formdata.setValue(context.payload, name, () => undefined);
|
|
188
135
|
}
|
|
189
136
|
}
|
|
190
137
|
}
|
|
191
|
-
var submissionError = context.error ? Object.entries(context.error).reduce((result, _ref) => {
|
|
192
|
-
var [name, error] = _ref;
|
|
193
|
-
if (context.state.validated[name]) {
|
|
194
|
-
result[name] = error;
|
|
195
|
-
}
|
|
196
|
-
return result;
|
|
197
|
-
}, {}) : undefined;
|
|
198
138
|
var extraError = 'formErrors' in options || 'fieldErrors' in options ? formdata.normalize(_rollupPluginBabelHelpers.objectSpread2({
|
|
199
139
|
'': (_options$formErrors = options.formErrors) !== null && _options$formErrors !== void 0 ? _options$formErrors : null
|
|
200
140
|
}, options.fieldErrors)) : null;
|
|
201
|
-
var error =
|
|
141
|
+
var error = context.error || extraError ? _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, context.error), extraError) : undefined;
|
|
202
142
|
return {
|
|
203
143
|
status: context.intent ? undefined : error ? 'error' : 'success',
|
|
204
144
|
intent: context.intent ? context.intent : undefined,
|
|
205
|
-
initialValue: (_normalize = formdata.normalize(context.payload
|
|
145
|
+
initialValue: (_normalize = formdata.normalize(context.payload,
|
|
146
|
+
// We can't serialize the file and send it back from the server, but we can preserve it in the client
|
|
147
|
+
typeof document !== 'undefined')) !== null && _normalize !== void 0 ? _normalize : {},
|
|
206
148
|
error,
|
|
207
|
-
state: context.state
|
|
149
|
+
state: context.state,
|
|
150
|
+
fields: Array.from(context.fields)
|
|
208
151
|
};
|
|
209
152
|
}
|
|
210
153
|
function getIntent(serializedIntent) {
|
|
@@ -310,8 +253,8 @@ function setListState(state, intent, getDefaultValue) {
|
|
|
310
253
|
function serialize(defaultValue) {
|
|
311
254
|
if (formdata.isPlainObject(defaultValue)) {
|
|
312
255
|
// @ts-expect-error FIXME
|
|
313
|
-
return Object.entries(defaultValue).reduce((result,
|
|
314
|
-
var [key, value] =
|
|
256
|
+
return Object.entries(defaultValue).reduce((result, _ref) => {
|
|
257
|
+
var [key, value] = _ref;
|
|
315
258
|
// @ts-ignore-error FIXME
|
|
316
259
|
result[key] = serialize(value);
|
|
317
260
|
return result;
|
package/submission.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { objectSpread2 as _objectSpread2 } from './_virtual/_rollupPluginBabelHelpers.mjs';
|
|
2
|
-
import { setValue, isPlainObject,
|
|
2
|
+
import { setValue, isPlainObject, getValue, normalize, flatten, isPrefix } from './formdata.mjs';
|
|
3
3
|
import { invariant } from './util.mjs';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -14,15 +14,21 @@ var STATE = '__state__';
|
|
|
14
14
|
function getSubmissionContext(body) {
|
|
15
15
|
var intent = body.get(INTENT);
|
|
16
16
|
var state = body.get(STATE);
|
|
17
|
-
var payload = {};
|
|
18
|
-
var fields = [];
|
|
19
17
|
invariant((typeof intent === 'string' || intent === null) && (typeof state === 'string' || state === null), "The input name \"".concat(INTENT, "\" and \"").concat(STATE, "\" are reserved by Conform. Please use another name for your input."));
|
|
18
|
+
var context = {
|
|
19
|
+
payload: {},
|
|
20
|
+
fields: new Set(),
|
|
21
|
+
intent: getIntent(intent)
|
|
22
|
+
};
|
|
23
|
+
if (state) {
|
|
24
|
+
context.state = JSON.parse(state);
|
|
25
|
+
}
|
|
20
26
|
var _loop = function _loop(next) {
|
|
21
27
|
if (name === INTENT || name === STATE) {
|
|
22
28
|
return 1; // continue
|
|
23
29
|
}
|
|
24
|
-
fields.
|
|
25
|
-
setValue(payload, name, prev => {
|
|
30
|
+
context.fields.add(name);
|
|
31
|
+
setValue(context.payload, name, prev => {
|
|
26
32
|
if (!prev) {
|
|
27
33
|
return next;
|
|
28
34
|
} else if (Array.isArray(prev)) {
|
|
@@ -35,30 +41,17 @@ function getSubmissionContext(body) {
|
|
|
35
41
|
for (var [name, next] of body.entries()) {
|
|
36
42
|
if (_loop(next)) continue;
|
|
37
43
|
}
|
|
38
|
-
return
|
|
39
|
-
payload,
|
|
40
|
-
intent: getIntent(intent),
|
|
41
|
-
state: state ? JSON.parse(state) : {
|
|
42
|
-
validated: {}
|
|
43
|
-
},
|
|
44
|
-
fields
|
|
45
|
-
};
|
|
44
|
+
return context;
|
|
46
45
|
}
|
|
47
46
|
function parse(payload, options) {
|
|
48
47
|
var context = getSubmissionContext(payload);
|
|
49
48
|
var intent = context.intent;
|
|
50
49
|
if (intent) {
|
|
51
50
|
switch (intent.type) {
|
|
52
|
-
case 'validate':
|
|
53
|
-
if (intent.payload.name) {
|
|
54
|
-
context.state.validated[intent.payload.name] = true;
|
|
55
|
-
}
|
|
56
|
-
break;
|
|
57
51
|
case 'update':
|
|
58
52
|
{
|
|
59
53
|
var {
|
|
60
|
-
name
|
|
61
|
-
validated
|
|
54
|
+
name
|
|
62
55
|
} = intent.payload;
|
|
63
56
|
var _value = serialize(intent.payload.value);
|
|
64
57
|
if (typeof _value !== 'undefined') {
|
|
@@ -69,27 +62,6 @@ function parse(payload, options) {
|
|
|
69
62
|
context.payload = _value;
|
|
70
63
|
}
|
|
71
64
|
}
|
|
72
|
-
if (typeof validated !== 'undefined') {
|
|
73
|
-
// Clean up previous validated state
|
|
74
|
-
if (name) {
|
|
75
|
-
setState(context.state.validated, name, () => undefined);
|
|
76
|
-
} else {
|
|
77
|
-
context.state.validated = {};
|
|
78
|
-
}
|
|
79
|
-
if (validated) {
|
|
80
|
-
if (isPlainObject(_value) || Array.isArray(_value)) {
|
|
81
|
-
Object.assign(context.state.validated, flatten(_value, {
|
|
82
|
-
resolve() {
|
|
83
|
-
return true;
|
|
84
|
-
},
|
|
85
|
-
prefix: name
|
|
86
|
-
}));
|
|
87
|
-
}
|
|
88
|
-
context.state.validated[name !== null && name !== void 0 ? name : ''] = true;
|
|
89
|
-
} else if (name) {
|
|
90
|
-
delete context.state.validated[name];
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
65
|
break;
|
|
94
66
|
}
|
|
95
67
|
case 'reset':
|
|
@@ -99,11 +71,8 @@ function parse(payload, options) {
|
|
|
99
71
|
} = intent.payload;
|
|
100
72
|
if (_name) {
|
|
101
73
|
setValue(context.payload, _name, () => undefined);
|
|
102
|
-
setState(context.state.validated, _name, () => undefined);
|
|
103
|
-
delete context.state.validated[_name];
|
|
104
74
|
} else {
|
|
105
75
|
context.payload = {};
|
|
106
|
-
context.state.validated = {};
|
|
107
76
|
}
|
|
108
77
|
break;
|
|
109
78
|
}
|
|
@@ -112,25 +81,15 @@ function parse(payload, options) {
|
|
|
112
81
|
case 'reorder':
|
|
113
82
|
{
|
|
114
83
|
setListValue(context.payload, intent);
|
|
115
|
-
setListState(context.state.validated, intent);
|
|
116
|
-
context.state.validated[intent.payload.name] = true;
|
|
117
84
|
break;
|
|
118
85
|
}
|
|
119
86
|
}
|
|
120
87
|
}
|
|
121
88
|
var result = options.resolve(context.payload, intent);
|
|
122
|
-
var mergeResolveResult = resolved => {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
context.state.validated[_name2] = true;
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
return createSubmission(_objectSpread2(_objectSpread2({}, context), {}, {
|
|
130
|
-
value: resolved.value,
|
|
131
|
-
error: resolved.error
|
|
132
|
-
}));
|
|
133
|
-
};
|
|
89
|
+
var mergeResolveResult = resolved => createSubmission(_objectSpread2(_objectSpread2({}, context), {}, {
|
|
90
|
+
value: resolved.value,
|
|
91
|
+
error: resolved.error
|
|
92
|
+
}));
|
|
134
93
|
if (result instanceof Promise) {
|
|
135
94
|
return result.then(mergeResolveResult);
|
|
136
95
|
}
|
|
@@ -157,50 +116,34 @@ function createSubmission(context) {
|
|
|
157
116
|
};
|
|
158
117
|
}
|
|
159
118
|
function replySubmission(context) {
|
|
160
|
-
var _context$intent, _options$formErrors, _normalize;
|
|
119
|
+
var _context$intent, _context$intent$paylo, _options$formErrors, _normalize;
|
|
161
120
|
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
162
|
-
|
|
163
|
-
case 'reset':
|
|
164
|
-
{
|
|
165
|
-
var _context$intent$paylo;
|
|
166
|
-
var name = (_context$intent$paylo = context.intent.payload.name) !== null && _context$intent$paylo !== void 0 ? _context$intent$paylo : '';
|
|
167
|
-
if (name === '') {
|
|
168
|
-
return {
|
|
169
|
-
initialValue: null
|
|
170
|
-
};
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
if ('resetForm' in options && options.resetForm) {
|
|
121
|
+
if ('resetForm' in options && options.resetForm || ((_context$intent = context.intent) === null || _context$intent === void 0 ? void 0 : _context$intent.type) === 'reset' && ((_context$intent$paylo = context.intent.payload.name) !== null && _context$intent$paylo !== void 0 ? _context$intent$paylo : '') === '') {
|
|
175
122
|
return {
|
|
176
123
|
initialValue: null
|
|
177
124
|
};
|
|
178
125
|
}
|
|
179
126
|
if ('hideFields' in options && options.hideFields) {
|
|
180
|
-
for (var
|
|
181
|
-
var _value2 = getValue(context.payload,
|
|
127
|
+
for (var name of options.hideFields) {
|
|
128
|
+
var _value2 = getValue(context.payload, name);
|
|
182
129
|
if (typeof _value2 !== 'undefined') {
|
|
183
|
-
setValue(context.payload,
|
|
130
|
+
setValue(context.payload, name, () => undefined);
|
|
184
131
|
}
|
|
185
132
|
}
|
|
186
133
|
}
|
|
187
|
-
var submissionError = context.error ? Object.entries(context.error).reduce((result, _ref) => {
|
|
188
|
-
var [name, error] = _ref;
|
|
189
|
-
if (context.state.validated[name]) {
|
|
190
|
-
result[name] = error;
|
|
191
|
-
}
|
|
192
|
-
return result;
|
|
193
|
-
}, {}) : undefined;
|
|
194
134
|
var extraError = 'formErrors' in options || 'fieldErrors' in options ? normalize(_objectSpread2({
|
|
195
135
|
'': (_options$formErrors = options.formErrors) !== null && _options$formErrors !== void 0 ? _options$formErrors : null
|
|
196
136
|
}, options.fieldErrors)) : null;
|
|
197
|
-
var error =
|
|
137
|
+
var error = context.error || extraError ? _objectSpread2(_objectSpread2({}, context.error), extraError) : undefined;
|
|
198
138
|
return {
|
|
199
139
|
status: context.intent ? undefined : error ? 'error' : 'success',
|
|
200
140
|
intent: context.intent ? context.intent : undefined,
|
|
201
|
-
initialValue: (_normalize = normalize(context.payload
|
|
141
|
+
initialValue: (_normalize = normalize(context.payload,
|
|
142
|
+
// We can't serialize the file and send it back from the server, but we can preserve it in the client
|
|
143
|
+
typeof document !== 'undefined')) !== null && _normalize !== void 0 ? _normalize : {},
|
|
202
144
|
error,
|
|
203
|
-
state: context.state
|
|
145
|
+
state: context.state,
|
|
146
|
+
fields: Array.from(context.fields)
|
|
204
147
|
};
|
|
205
148
|
}
|
|
206
149
|
function getIntent(serializedIntent) {
|
|
@@ -306,8 +249,8 @@ function setListState(state, intent, getDefaultValue) {
|
|
|
306
249
|
function serialize(defaultValue) {
|
|
307
250
|
if (isPlainObject(defaultValue)) {
|
|
308
251
|
// @ts-expect-error FIXME
|
|
309
|
-
return Object.entries(defaultValue).reduce((result,
|
|
310
|
-
var [key, value] =
|
|
252
|
+
return Object.entries(defaultValue).reduce((result, _ref) => {
|
|
253
|
+
var [key, value] = _ref;
|
|
311
254
|
// @ts-ignore-error FIXME
|
|
312
255
|
result[key] = serialize(value);
|
|
313
256
|
return result;
|