@conform-to/dom 1.0.5 → 1.1.0-pre.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 +1 -1
- package/form.d.ts +3 -1
- package/form.js +55 -18
- package/form.mjs +57 -20
- package/formdata.d.ts +5 -1
- package/formdata.js +8 -0
- package/formdata.mjs +8 -1
- package/package.json +1 -1
- package/submission.d.ts +15 -1
- package/submission.js +19 -10
- package/submission.mjs +20 -12
package/README
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
╚══════╝ ╚═════╝ ╚═╝ ╚══╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
Version 1.0.
|
|
11
|
+
Version 1.1.0-pre.0 / 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
|
@@ -33,6 +33,7 @@ export type Constraint = {
|
|
|
33
33
|
pattern?: string;
|
|
34
34
|
};
|
|
35
35
|
export type FormMeta<FormError> = {
|
|
36
|
+
isValueUpdated: boolean;
|
|
36
37
|
submissionStatus?: 'error' | 'success';
|
|
37
38
|
defaultValue: Record<string, unknown>;
|
|
38
39
|
initialValue: Record<string, unknown>;
|
|
@@ -42,7 +43,7 @@ export type FormMeta<FormError> = {
|
|
|
42
43
|
key: Record<string, string | undefined>;
|
|
43
44
|
validated: Record<string, boolean>;
|
|
44
45
|
};
|
|
45
|
-
export type FormState<FormError> = FormMeta<FormError> & {
|
|
46
|
+
export type FormState<FormError> = Omit<FormMeta<FormError>, 'isValueUpdated'> & {
|
|
46
47
|
valid: Record<string, boolean>;
|
|
47
48
|
dirty: Record<string, boolean>;
|
|
48
49
|
};
|
|
@@ -119,6 +120,7 @@ export type FormContext<Schema extends Record<string, any> = any, FormError = st
|
|
|
119
120
|
onInput(event: Event): void;
|
|
120
121
|
onBlur(event: Event): void;
|
|
121
122
|
onUpdate(options: Partial<FormOptions<Schema, FormError, FormValue>>): void;
|
|
123
|
+
observe(): () => void;
|
|
122
124
|
subscribe(callback: () => void, getSubject?: () => SubscriptionSubject | undefined): () => void;
|
|
123
125
|
getState(): FormState<FormError>;
|
|
124
126
|
getSerializedState(): string;
|
package/form.js
CHANGED
|
@@ -14,6 +14,7 @@ function createFormMeta(options, initialized) {
|
|
|
14
14
|
var defaultValue = options.defaultValue ? submission.serialize(options.defaultValue) : {};
|
|
15
15
|
var initialValue = (_lastResult$initialVa = lastResult === null || lastResult === void 0 ? void 0 : lastResult.initialValue) !== null && _lastResult$initialVa !== void 0 ? _lastResult$initialVa : defaultValue;
|
|
16
16
|
var result = {
|
|
17
|
+
isValueUpdated: false,
|
|
17
18
|
submissionStatus: lastResult === null || lastResult === void 0 ? void 0 : lastResult.status,
|
|
18
19
|
defaultValue,
|
|
19
20
|
initialValue,
|
|
@@ -37,7 +38,7 @@ function getDefaultKey(defaultValue, prefix) {
|
|
|
37
38
|
var [key, value] = _ref2;
|
|
38
39
|
if (Array.isArray(value)) {
|
|
39
40
|
for (var i = 0; i < value.length; i++) {
|
|
40
|
-
result[formdata.
|
|
41
|
+
result[formdata.formatName(key, i)] = util.generateId();
|
|
41
42
|
}
|
|
42
43
|
}
|
|
43
44
|
return result;
|
|
@@ -66,10 +67,10 @@ function handleIntent(meta, intent, fields, initialized) {
|
|
|
66
67
|
case 'update':
|
|
67
68
|
{
|
|
68
69
|
var {
|
|
69
|
-
name: _name2,
|
|
70
70
|
validated,
|
|
71
71
|
value
|
|
72
72
|
} = intent.payload;
|
|
73
|
+
var _name2 = formdata.formatName(intent.payload.name, intent.payload.index);
|
|
73
74
|
if (typeof value !== 'undefined') {
|
|
74
75
|
updateValue(meta, _name2 !== null && _name2 !== void 0 ? _name2 : '', submission.serialize(value));
|
|
75
76
|
}
|
|
@@ -98,8 +99,7 @@ function handleIntent(meta, intent, fields, initialized) {
|
|
|
98
99
|
}
|
|
99
100
|
case 'reset':
|
|
100
101
|
{
|
|
101
|
-
var
|
|
102
|
-
var _name3 = (_intent$payload$name = intent.payload.name) !== null && _intent$payload$name !== void 0 ? _intent$payload$name : '';
|
|
102
|
+
var _name3 = formdata.formatName(intent.payload.name, intent.payload.index);
|
|
103
103
|
var _value = formdata.getValue(meta.defaultValue, _name3);
|
|
104
104
|
updateValue(meta, _name3, _value);
|
|
105
105
|
if (_name3) {
|
|
@@ -117,11 +117,13 @@ function handleIntent(meta, intent, fields, initialized) {
|
|
|
117
117
|
if (initialized) {
|
|
118
118
|
meta.initialValue = util.clone(meta.initialValue);
|
|
119
119
|
meta.key = util.clone(meta.key);
|
|
120
|
-
submission.setListState(meta.key, intent,
|
|
120
|
+
submission.setListState(meta.key, intent, defaultValue => {
|
|
121
121
|
if (!Array.isArray(defaultValue) && !formdata.isPlainObject(defaultValue)) {
|
|
122
122
|
return util.generateId();
|
|
123
123
|
}
|
|
124
|
-
return getDefaultKey(defaultValue,
|
|
124
|
+
return Object.assign(getDefaultKey(defaultValue), {
|
|
125
|
+
[submission.root]: util.generateId()
|
|
126
|
+
});
|
|
125
127
|
});
|
|
126
128
|
submission.setListValue(meta.initialValue, intent);
|
|
127
129
|
}
|
|
@@ -355,8 +357,11 @@ function createFormContext(options) {
|
|
|
355
357
|
formData,
|
|
356
358
|
submitter
|
|
357
359
|
});
|
|
358
|
-
if (submission.status
|
|
359
|
-
|
|
360
|
+
if (submission.status === 'success' || submission.error !== null) {
|
|
361
|
+
var _result2 = submission.reply();
|
|
362
|
+
report(_rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, _result2), {}, {
|
|
363
|
+
status: _result2.status !== 'success' ? _result2.status : undefined
|
|
364
|
+
}));
|
|
360
365
|
}
|
|
361
366
|
return _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, result), {}, {
|
|
362
367
|
submission
|
|
@@ -365,7 +370,7 @@ function createFormContext(options) {
|
|
|
365
370
|
function resolveTarget(event) {
|
|
366
371
|
var form = getFormElement();
|
|
367
372
|
var element = event.target;
|
|
368
|
-
if (!form || !dom.isFieldElement(element) || element.form !== form || element.name === '') {
|
|
373
|
+
if (!form || !dom.isFieldElement(element) || element.form !== form || !element.form.isConnected || element.name === '') {
|
|
369
374
|
return null;
|
|
370
375
|
}
|
|
371
376
|
return element;
|
|
@@ -376,7 +381,15 @@ function createFormContext(options) {
|
|
|
376
381
|
shouldRevalidate = shouldValidate
|
|
377
382
|
} = latestOptions;
|
|
378
383
|
var validated = meta.validated[element.name];
|
|
379
|
-
return validated ? shouldRevalidate === eventName : shouldValidate === eventName;
|
|
384
|
+
return validated ? shouldRevalidate === eventName && (eventName === 'onInput' || meta.isValueUpdated) : shouldValidate === eventName;
|
|
385
|
+
}
|
|
386
|
+
function updateFormValue(form) {
|
|
387
|
+
var formData = new FormData(form);
|
|
388
|
+
var result = submission.getSubmissionContext(formData);
|
|
389
|
+
updateFormMeta(_rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, meta), {}, {
|
|
390
|
+
isValueUpdated: true,
|
|
391
|
+
value: result.payload
|
|
392
|
+
}));
|
|
380
393
|
}
|
|
381
394
|
function onInput(event) {
|
|
382
395
|
var element = resolveTarget(event);
|
|
@@ -384,11 +397,7 @@ function createFormContext(options) {
|
|
|
384
397
|
return;
|
|
385
398
|
}
|
|
386
399
|
if (event.defaultPrevented || !willValidate(element, 'onInput')) {
|
|
387
|
-
|
|
388
|
-
var result = submission.getSubmissionContext(formData);
|
|
389
|
-
updateFormMeta(_rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, meta), {}, {
|
|
390
|
-
value: result.payload
|
|
391
|
-
}));
|
|
400
|
+
updateFormValue(element.form);
|
|
392
401
|
} else {
|
|
393
402
|
dispatch({
|
|
394
403
|
type: 'validate',
|
|
@@ -433,6 +442,7 @@ function createFormContext(options) {
|
|
|
433
442
|
return result;
|
|
434
443
|
}, {});
|
|
435
444
|
var update = _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, meta), {}, {
|
|
445
|
+
isValueUpdated: false,
|
|
436
446
|
submissionStatus: result.status,
|
|
437
447
|
value: result.initialValue,
|
|
438
448
|
validated: _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, meta.validated), (_result$state = result.state) === null || _result$state === void 0 ? void 0 : _result$state.validated),
|
|
@@ -456,8 +466,7 @@ function createFormContext(options) {
|
|
|
456
466
|
// Merge new options with the latest options
|
|
457
467
|
Object.assign(latestOptions, options);
|
|
458
468
|
if (latestOptions.formId !== currentFormId) {
|
|
459
|
-
|
|
460
|
-
(_getFormElement = getFormElement()) === null || _getFormElement === void 0 || _getFormElement.reset();
|
|
469
|
+
updateFormMeta(createFormMeta(latestOptions, true));
|
|
461
470
|
} else if (options.lastResult && options.lastResult !== currentResult) {
|
|
462
471
|
report(options.lastResult);
|
|
463
472
|
}
|
|
@@ -513,6 +522,33 @@ function createFormContext(options) {
|
|
|
513
522
|
}
|
|
514
523
|
});
|
|
515
524
|
}
|
|
525
|
+
function observe() {
|
|
526
|
+
var observer = new MutationObserver(mutations => {
|
|
527
|
+
var form = getFormElement();
|
|
528
|
+
if (!form) {
|
|
529
|
+
return;
|
|
530
|
+
}
|
|
531
|
+
for (var mutation of mutations) {
|
|
532
|
+
var nodes = mutation.type === 'childList' ? [...mutation.addedNodes, ...mutation.removedNodes] : [mutation.target];
|
|
533
|
+
for (var node of nodes) {
|
|
534
|
+
var element = dom.isFieldElement(node) ? node : node instanceof HTMLElement ? node.querySelector('input,select,textarea') : null;
|
|
535
|
+
if ((element === null || element === void 0 ? void 0 : element.form) === form) {
|
|
536
|
+
updateFormValue(form);
|
|
537
|
+
return;
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
});
|
|
542
|
+
observer.observe(document, {
|
|
543
|
+
subtree: true,
|
|
544
|
+
childList: true,
|
|
545
|
+
attributes: true,
|
|
546
|
+
attributeFilter: ['form', 'name']
|
|
547
|
+
});
|
|
548
|
+
return () => {
|
|
549
|
+
observer.disconnect();
|
|
550
|
+
};
|
|
551
|
+
}
|
|
516
552
|
return {
|
|
517
553
|
get formId() {
|
|
518
554
|
return latestOptions.formId;
|
|
@@ -530,7 +566,8 @@ function createFormContext(options) {
|
|
|
530
566
|
reorder: createFormControl('reorder'),
|
|
531
567
|
subscribe,
|
|
532
568
|
getState,
|
|
533
|
-
getSerializedState
|
|
569
|
+
getSerializedState,
|
|
570
|
+
observe
|
|
534
571
|
};
|
|
535
572
|
}
|
|
536
573
|
|
package/form.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { objectSpread2 as _objectSpread2 } from './_virtual/_rollupPluginBabelHelpers.mjs';
|
|
2
|
-
import { flatten,
|
|
2
|
+
import { flatten, formatName, getValue, isPlainObject, setValue, normalize, getFormData, getPaths, formatPaths, 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,
|
|
5
|
+
import { serialize, setListState, setListValue, setState, INTENT, serializeIntent, root, getSubmissionContext } from './submission.mjs';
|
|
6
6
|
|
|
7
7
|
function createFormMeta(options, initialized) {
|
|
8
8
|
var _lastResult$initialVa, _options$constraint, _lastResult$state$val, _lastResult$state, _ref;
|
|
@@ -10,6 +10,7 @@ function createFormMeta(options, initialized) {
|
|
|
10
10
|
var defaultValue = options.defaultValue ? serialize(options.defaultValue) : {};
|
|
11
11
|
var initialValue = (_lastResult$initialVa = lastResult === null || lastResult === void 0 ? void 0 : lastResult.initialValue) !== null && _lastResult$initialVa !== void 0 ? _lastResult$initialVa : defaultValue;
|
|
12
12
|
var result = {
|
|
13
|
+
isValueUpdated: false,
|
|
13
14
|
submissionStatus: lastResult === null || lastResult === void 0 ? void 0 : lastResult.status,
|
|
14
15
|
defaultValue,
|
|
15
16
|
initialValue,
|
|
@@ -33,7 +34,7 @@ function getDefaultKey(defaultValue, prefix) {
|
|
|
33
34
|
var [key, value] = _ref2;
|
|
34
35
|
if (Array.isArray(value)) {
|
|
35
36
|
for (var i = 0; i < value.length; i++) {
|
|
36
|
-
result[
|
|
37
|
+
result[formatName(key, i)] = generateId();
|
|
37
38
|
}
|
|
38
39
|
}
|
|
39
40
|
return result;
|
|
@@ -62,10 +63,10 @@ function handleIntent(meta, intent, fields, initialized) {
|
|
|
62
63
|
case 'update':
|
|
63
64
|
{
|
|
64
65
|
var {
|
|
65
|
-
name: _name2,
|
|
66
66
|
validated,
|
|
67
67
|
value
|
|
68
68
|
} = intent.payload;
|
|
69
|
+
var _name2 = formatName(intent.payload.name, intent.payload.index);
|
|
69
70
|
if (typeof value !== 'undefined') {
|
|
70
71
|
updateValue(meta, _name2 !== null && _name2 !== void 0 ? _name2 : '', serialize(value));
|
|
71
72
|
}
|
|
@@ -94,8 +95,7 @@ function handleIntent(meta, intent, fields, initialized) {
|
|
|
94
95
|
}
|
|
95
96
|
case 'reset':
|
|
96
97
|
{
|
|
97
|
-
var
|
|
98
|
-
var _name3 = (_intent$payload$name = intent.payload.name) !== null && _intent$payload$name !== void 0 ? _intent$payload$name : '';
|
|
98
|
+
var _name3 = formatName(intent.payload.name, intent.payload.index);
|
|
99
99
|
var _value = getValue(meta.defaultValue, _name3);
|
|
100
100
|
updateValue(meta, _name3, _value);
|
|
101
101
|
if (_name3) {
|
|
@@ -113,11 +113,13 @@ function handleIntent(meta, intent, fields, initialized) {
|
|
|
113
113
|
if (initialized) {
|
|
114
114
|
meta.initialValue = clone(meta.initialValue);
|
|
115
115
|
meta.key = clone(meta.key);
|
|
116
|
-
setListState(meta.key, intent,
|
|
116
|
+
setListState(meta.key, intent, defaultValue => {
|
|
117
117
|
if (!Array.isArray(defaultValue) && !isPlainObject(defaultValue)) {
|
|
118
118
|
return generateId();
|
|
119
119
|
}
|
|
120
|
-
return getDefaultKey(defaultValue,
|
|
120
|
+
return Object.assign(getDefaultKey(defaultValue), {
|
|
121
|
+
[root]: generateId()
|
|
122
|
+
});
|
|
121
123
|
});
|
|
122
124
|
setListValue(meta.initialValue, intent);
|
|
123
125
|
}
|
|
@@ -351,8 +353,11 @@ function createFormContext(options) {
|
|
|
351
353
|
formData,
|
|
352
354
|
submitter
|
|
353
355
|
});
|
|
354
|
-
if (submission.status
|
|
355
|
-
|
|
356
|
+
if (submission.status === 'success' || submission.error !== null) {
|
|
357
|
+
var _result2 = submission.reply();
|
|
358
|
+
report(_objectSpread2(_objectSpread2({}, _result2), {}, {
|
|
359
|
+
status: _result2.status !== 'success' ? _result2.status : undefined
|
|
360
|
+
}));
|
|
356
361
|
}
|
|
357
362
|
return _objectSpread2(_objectSpread2({}, result), {}, {
|
|
358
363
|
submission
|
|
@@ -361,7 +366,7 @@ function createFormContext(options) {
|
|
|
361
366
|
function resolveTarget(event) {
|
|
362
367
|
var form = getFormElement();
|
|
363
368
|
var element = event.target;
|
|
364
|
-
if (!form || !isFieldElement(element) || element.form !== form || element.name === '') {
|
|
369
|
+
if (!form || !isFieldElement(element) || element.form !== form || !element.form.isConnected || element.name === '') {
|
|
365
370
|
return null;
|
|
366
371
|
}
|
|
367
372
|
return element;
|
|
@@ -372,7 +377,15 @@ function createFormContext(options) {
|
|
|
372
377
|
shouldRevalidate = shouldValidate
|
|
373
378
|
} = latestOptions;
|
|
374
379
|
var validated = meta.validated[element.name];
|
|
375
|
-
return validated ? shouldRevalidate === eventName : shouldValidate === eventName;
|
|
380
|
+
return validated ? shouldRevalidate === eventName && (eventName === 'onInput' || meta.isValueUpdated) : shouldValidate === eventName;
|
|
381
|
+
}
|
|
382
|
+
function updateFormValue(form) {
|
|
383
|
+
var formData = new FormData(form);
|
|
384
|
+
var result = getSubmissionContext(formData);
|
|
385
|
+
updateFormMeta(_objectSpread2(_objectSpread2({}, meta), {}, {
|
|
386
|
+
isValueUpdated: true,
|
|
387
|
+
value: result.payload
|
|
388
|
+
}));
|
|
376
389
|
}
|
|
377
390
|
function onInput(event) {
|
|
378
391
|
var element = resolveTarget(event);
|
|
@@ -380,11 +393,7 @@ function createFormContext(options) {
|
|
|
380
393
|
return;
|
|
381
394
|
}
|
|
382
395
|
if (event.defaultPrevented || !willValidate(element, 'onInput')) {
|
|
383
|
-
|
|
384
|
-
var result = getSubmissionContext(formData);
|
|
385
|
-
updateFormMeta(_objectSpread2(_objectSpread2({}, meta), {}, {
|
|
386
|
-
value: result.payload
|
|
387
|
-
}));
|
|
396
|
+
updateFormValue(element.form);
|
|
388
397
|
} else {
|
|
389
398
|
dispatch({
|
|
390
399
|
type: 'validate',
|
|
@@ -429,6 +438,7 @@ function createFormContext(options) {
|
|
|
429
438
|
return result;
|
|
430
439
|
}, {});
|
|
431
440
|
var update = _objectSpread2(_objectSpread2({}, meta), {}, {
|
|
441
|
+
isValueUpdated: false,
|
|
432
442
|
submissionStatus: result.status,
|
|
433
443
|
value: result.initialValue,
|
|
434
444
|
validated: _objectSpread2(_objectSpread2({}, meta.validated), (_result$state = result.state) === null || _result$state === void 0 ? void 0 : _result$state.validated),
|
|
@@ -452,8 +462,7 @@ function createFormContext(options) {
|
|
|
452
462
|
// Merge new options with the latest options
|
|
453
463
|
Object.assign(latestOptions, options);
|
|
454
464
|
if (latestOptions.formId !== currentFormId) {
|
|
455
|
-
|
|
456
|
-
(_getFormElement = getFormElement()) === null || _getFormElement === void 0 || _getFormElement.reset();
|
|
465
|
+
updateFormMeta(createFormMeta(latestOptions, true));
|
|
457
466
|
} else if (options.lastResult && options.lastResult !== currentResult) {
|
|
458
467
|
report(options.lastResult);
|
|
459
468
|
}
|
|
@@ -509,6 +518,33 @@ function createFormContext(options) {
|
|
|
509
518
|
}
|
|
510
519
|
});
|
|
511
520
|
}
|
|
521
|
+
function observe() {
|
|
522
|
+
var observer = new MutationObserver(mutations => {
|
|
523
|
+
var form = getFormElement();
|
|
524
|
+
if (!form) {
|
|
525
|
+
return;
|
|
526
|
+
}
|
|
527
|
+
for (var mutation of mutations) {
|
|
528
|
+
var nodes = mutation.type === 'childList' ? [...mutation.addedNodes, ...mutation.removedNodes] : [mutation.target];
|
|
529
|
+
for (var node of nodes) {
|
|
530
|
+
var element = isFieldElement(node) ? node : node instanceof HTMLElement ? node.querySelector('input,select,textarea') : null;
|
|
531
|
+
if ((element === null || element === void 0 ? void 0 : element.form) === form) {
|
|
532
|
+
updateFormValue(form);
|
|
533
|
+
return;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
});
|
|
538
|
+
observer.observe(document, {
|
|
539
|
+
subtree: true,
|
|
540
|
+
childList: true,
|
|
541
|
+
attributes: true,
|
|
542
|
+
attributeFilter: ['form', 'name']
|
|
543
|
+
});
|
|
544
|
+
return () => {
|
|
545
|
+
observer.disconnect();
|
|
546
|
+
};
|
|
547
|
+
}
|
|
512
548
|
return {
|
|
513
549
|
get formId() {
|
|
514
550
|
return latestOptions.formId;
|
|
@@ -526,7 +562,8 @@ function createFormContext(options) {
|
|
|
526
562
|
reorder: createFormControl('reorder'),
|
|
527
563
|
subscribe,
|
|
528
564
|
getState,
|
|
529
|
-
getSerializedState
|
|
565
|
+
getSerializedState,
|
|
566
|
+
observe
|
|
530
567
|
};
|
|
531
568
|
}
|
|
532
569
|
|
package/formdata.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ export declare function getFormData(form: HTMLFormElement, submitter?: HTMLInput
|
|
|
13
13
|
* const paths = getPaths('todos[0].content'); // ['todos', 0, 'content']
|
|
14
14
|
* ```
|
|
15
15
|
*/
|
|
16
|
-
export declare function getPaths(name: string): Array<string | number>;
|
|
16
|
+
export declare function getPaths(name: string | undefined): Array<string | number>;
|
|
17
17
|
/**
|
|
18
18
|
* Returns a formatted name from the paths based on the JS syntax convention
|
|
19
19
|
* @example
|
|
@@ -22,6 +22,10 @@ export declare function getPaths(name: string): Array<string | number>;
|
|
|
22
22
|
* ```
|
|
23
23
|
*/
|
|
24
24
|
export declare function formatPaths(paths: Array<string | number>): string;
|
|
25
|
+
/**
|
|
26
|
+
* Format based on a prefix and a path
|
|
27
|
+
*/
|
|
28
|
+
export declare function formatName(prefix: string | undefined, path?: string | number): string;
|
|
25
29
|
/**
|
|
26
30
|
* Check if a name match the prefix paths
|
|
27
31
|
*/
|
package/formdata.js
CHANGED
|
@@ -65,6 +65,13 @@ function formatPaths(paths) {
|
|
|
65
65
|
}, '');
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
/**
|
|
69
|
+
* Format based on a prefix and a path
|
|
70
|
+
*/
|
|
71
|
+
function formatName(prefix, path) {
|
|
72
|
+
return typeof path !== 'undefined' ? formatPaths([...getPaths(prefix), path]) : prefix !== null && prefix !== void 0 ? prefix : '';
|
|
73
|
+
}
|
|
74
|
+
|
|
68
75
|
/**
|
|
69
76
|
* Check if a name match the prefix paths
|
|
70
77
|
*/
|
|
@@ -215,6 +222,7 @@ function flatten(data, options) {
|
|
|
215
222
|
}
|
|
216
223
|
|
|
217
224
|
exports.flatten = flatten;
|
|
225
|
+
exports.formatName = formatName;
|
|
218
226
|
exports.formatPaths = formatPaths;
|
|
219
227
|
exports.getFormData = getFormData;
|
|
220
228
|
exports.getPaths = getPaths;
|
package/formdata.mjs
CHANGED
|
@@ -61,6 +61,13 @@ function formatPaths(paths) {
|
|
|
61
61
|
}, '');
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
+
/**
|
|
65
|
+
* Format based on a prefix and a path
|
|
66
|
+
*/
|
|
67
|
+
function formatName(prefix, path) {
|
|
68
|
+
return typeof path !== 'undefined' ? formatPaths([...getPaths(prefix), path]) : prefix !== null && prefix !== void 0 ? prefix : '';
|
|
69
|
+
}
|
|
70
|
+
|
|
64
71
|
/**
|
|
65
72
|
* Check if a name match the prefix paths
|
|
66
73
|
*/
|
|
@@ -210,4 +217,4 @@ function flatten(data, options) {
|
|
|
210
217
|
return result;
|
|
211
218
|
}
|
|
212
219
|
|
|
213
|
-
export { flatten, formatPaths, getFormData, getPaths, getValue, isFile, isPlainObject, isPrefix, normalize, setValue };
|
|
220
|
+
export { flatten, formatName, formatPaths, getFormData, getPaths, getValue, isFile, isPlainObject, isPrefix, normalize, setValue };
|
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.1.0-pre.0",
|
|
7
7
|
"main": "index.js",
|
|
8
8
|
"module": "index.mjs",
|
|
9
9
|
"types": "index.d.ts",
|
package/submission.d.ts
CHANGED
|
@@ -78,14 +78,24 @@ export type ResetIntent<Schema = any> = {
|
|
|
78
78
|
type: 'reset';
|
|
79
79
|
payload: {
|
|
80
80
|
name?: FieldName<Schema>;
|
|
81
|
+
index?: never;
|
|
82
|
+
} | {
|
|
83
|
+
name: FieldName<Schema>;
|
|
84
|
+
index: Schema extends Array<unknown> ? number : never;
|
|
81
85
|
};
|
|
82
86
|
};
|
|
83
87
|
export type UpdateIntent<Schema = unknown> = {
|
|
84
88
|
type: 'update';
|
|
85
89
|
payload: {
|
|
86
90
|
name?: FieldName<Schema>;
|
|
91
|
+
index?: never;
|
|
87
92
|
value?: NonNullable<DefaultValue<Schema>>;
|
|
88
93
|
validated?: boolean;
|
|
94
|
+
} | {
|
|
95
|
+
name: FieldName<Schema>;
|
|
96
|
+
index: Schema extends Array<unknown> ? number : never;
|
|
97
|
+
value?: NonNullable<DefaultValue<Schema extends Array<infer Item> ? Item : unknown>>;
|
|
98
|
+
validated?: boolean;
|
|
89
99
|
};
|
|
90
100
|
};
|
|
91
101
|
export type RemoveIntent<Schema extends Array<any> = any> = {
|
|
@@ -116,6 +126,10 @@ export declare function getIntent(serializedIntent: string | null | undefined):
|
|
|
116
126
|
export declare function serializeIntent<Schema>(intent: Intent<Schema>): string;
|
|
117
127
|
export declare function updateList(list: unknown, intent: InsertIntent | RemoveIntent | ReorderIntent): void;
|
|
118
128
|
export declare function setListValue(data: Record<string, unknown>, intent: InsertIntent | RemoveIntent | ReorderIntent): void;
|
|
129
|
+
/**
|
|
130
|
+
* A placeholder symbol for the root value of a nested object
|
|
131
|
+
*/
|
|
132
|
+
export declare const root: unique symbol;
|
|
119
133
|
export declare function setState(state: Record<string, unknown>, name: string, valueFn: (value: unknown) => unknown): void;
|
|
120
|
-
export declare function setListState(state: Record<string, unknown>, intent: InsertIntent | RemoveIntent | ReorderIntent, getDefaultValue?: (defaultValue: any
|
|
134
|
+
export declare function setListState(state: Record<string, unknown>, intent: InsertIntent | RemoveIntent | ReorderIntent, getDefaultValue?: (defaultValue: any) => any): void;
|
|
121
135
|
export declare function serialize<Schema>(defaultValue: DefaultValue<Schema>): FormValue<Schema>;
|
package/submission.js
CHANGED
|
@@ -54,9 +54,7 @@ function parse(payload, options) {
|
|
|
54
54
|
switch (intent.type) {
|
|
55
55
|
case 'update':
|
|
56
56
|
{
|
|
57
|
-
var
|
|
58
|
-
name
|
|
59
|
-
} = intent.payload;
|
|
57
|
+
var name = formdata.formatName(intent.payload.name, intent.payload.index);
|
|
60
58
|
var _value = serialize(intent.payload.value);
|
|
61
59
|
if (typeof _value !== 'undefined') {
|
|
62
60
|
if (name) {
|
|
@@ -70,9 +68,7 @@ function parse(payload, options) {
|
|
|
70
68
|
}
|
|
71
69
|
case 'reset':
|
|
72
70
|
{
|
|
73
|
-
var
|
|
74
|
-
name: _name
|
|
75
|
-
} = intent.payload;
|
|
71
|
+
var _name = formdata.formatName(intent.payload.name, intent.payload.index);
|
|
76
72
|
if (_name) {
|
|
77
73
|
formdata.setValue(context.payload, _name, () => undefined);
|
|
78
74
|
} else {
|
|
@@ -81,6 +77,15 @@ function parse(payload, options) {
|
|
|
81
77
|
break;
|
|
82
78
|
}
|
|
83
79
|
case 'insert':
|
|
80
|
+
{
|
|
81
|
+
setListValue(context.payload, {
|
|
82
|
+
type: intent.type,
|
|
83
|
+
payload: _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, intent.payload), {}, {
|
|
84
|
+
defaultValue: serialize(intent.payload.defaultValue)
|
|
85
|
+
})
|
|
86
|
+
});
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
84
89
|
case 'remove':
|
|
85
90
|
case 'reorder':
|
|
86
91
|
{
|
|
@@ -168,7 +173,7 @@ function updateList(list, intent) {
|
|
|
168
173
|
util.invariant(Array.isArray(list), "Failed to update list. The value is not an array.");
|
|
169
174
|
switch (intent.type) {
|
|
170
175
|
case 'insert':
|
|
171
|
-
list.splice((_intent$payload$index = intent.payload.index) !== null && _intent$payload$index !== void 0 ? _intent$payload$index : list.length, 0,
|
|
176
|
+
list.splice((_intent$payload$index = intent.payload.index) !== null && _intent$payload$index !== void 0 ? _intent$payload$index : list.length, 0, intent.payload.defaultValue);
|
|
172
177
|
break;
|
|
173
178
|
case 'remove':
|
|
174
179
|
list.splice(intent.payload.index, 1);
|
|
@@ -187,9 +192,12 @@ function setListValue(data, intent) {
|
|
|
187
192
|
return list;
|
|
188
193
|
});
|
|
189
194
|
}
|
|
190
|
-
function setState(state, name, valueFn) {
|
|
191
|
-
var root = Symbol.for('root');
|
|
192
195
|
|
|
196
|
+
/**
|
|
197
|
+
* A placeholder symbol for the root value of a nested object
|
|
198
|
+
*/
|
|
199
|
+
var root = Symbol.for('root');
|
|
200
|
+
function setState(state, name, valueFn) {
|
|
193
201
|
// The keys are sorted in desc so that the root value is handled last
|
|
194
202
|
var keys = Object.keys(state).sort((prev, next) => next.localeCompare(prev));
|
|
195
203
|
var target = {};
|
|
@@ -239,7 +247,7 @@ function setListState(state, intent, getDefaultValue) {
|
|
|
239
247
|
updateList(list, {
|
|
240
248
|
type: intent.type,
|
|
241
249
|
payload: _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, intent.payload), {}, {
|
|
242
|
-
defaultValue: getDefaultValue === null || getDefaultValue === void 0 ? void 0 : getDefaultValue(intent.payload.defaultValue
|
|
250
|
+
defaultValue: getDefaultValue === null || getDefaultValue === void 0 ? void 0 : getDefaultValue(intent.payload.defaultValue)
|
|
243
251
|
})
|
|
244
252
|
});
|
|
245
253
|
break;
|
|
@@ -286,6 +294,7 @@ exports.getIntent = getIntent;
|
|
|
286
294
|
exports.getSubmissionContext = getSubmissionContext;
|
|
287
295
|
exports.parse = parse;
|
|
288
296
|
exports.replySubmission = replySubmission;
|
|
297
|
+
exports.root = root;
|
|
289
298
|
exports.serialize = serialize;
|
|
290
299
|
exports.serializeIntent = serializeIntent;
|
|
291
300
|
exports.setListState = setListState;
|
package/submission.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { objectSpread2 as _objectSpread2 } from './_virtual/_rollupPluginBabelHelpers.mjs';
|
|
2
|
-
import { setValue, isPlainObject, getValue, normalize, flatten, isPrefix } from './formdata.mjs';
|
|
2
|
+
import { formatName, setValue, isPlainObject, getValue, normalize, flatten, isPrefix } from './formdata.mjs';
|
|
3
3
|
import { invariant } from './util.mjs';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -50,9 +50,7 @@ function parse(payload, options) {
|
|
|
50
50
|
switch (intent.type) {
|
|
51
51
|
case 'update':
|
|
52
52
|
{
|
|
53
|
-
var
|
|
54
|
-
name
|
|
55
|
-
} = intent.payload;
|
|
53
|
+
var name = formatName(intent.payload.name, intent.payload.index);
|
|
56
54
|
var _value = serialize(intent.payload.value);
|
|
57
55
|
if (typeof _value !== 'undefined') {
|
|
58
56
|
if (name) {
|
|
@@ -66,9 +64,7 @@ function parse(payload, options) {
|
|
|
66
64
|
}
|
|
67
65
|
case 'reset':
|
|
68
66
|
{
|
|
69
|
-
var
|
|
70
|
-
name: _name
|
|
71
|
-
} = intent.payload;
|
|
67
|
+
var _name = formatName(intent.payload.name, intent.payload.index);
|
|
72
68
|
if (_name) {
|
|
73
69
|
setValue(context.payload, _name, () => undefined);
|
|
74
70
|
} else {
|
|
@@ -77,6 +73,15 @@ function parse(payload, options) {
|
|
|
77
73
|
break;
|
|
78
74
|
}
|
|
79
75
|
case 'insert':
|
|
76
|
+
{
|
|
77
|
+
setListValue(context.payload, {
|
|
78
|
+
type: intent.type,
|
|
79
|
+
payload: _objectSpread2(_objectSpread2({}, intent.payload), {}, {
|
|
80
|
+
defaultValue: serialize(intent.payload.defaultValue)
|
|
81
|
+
})
|
|
82
|
+
});
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
80
85
|
case 'remove':
|
|
81
86
|
case 'reorder':
|
|
82
87
|
{
|
|
@@ -164,7 +169,7 @@ function updateList(list, intent) {
|
|
|
164
169
|
invariant(Array.isArray(list), "Failed to update list. The value is not an array.");
|
|
165
170
|
switch (intent.type) {
|
|
166
171
|
case 'insert':
|
|
167
|
-
list.splice((_intent$payload$index = intent.payload.index) !== null && _intent$payload$index !== void 0 ? _intent$payload$index : list.length, 0,
|
|
172
|
+
list.splice((_intent$payload$index = intent.payload.index) !== null && _intent$payload$index !== void 0 ? _intent$payload$index : list.length, 0, intent.payload.defaultValue);
|
|
168
173
|
break;
|
|
169
174
|
case 'remove':
|
|
170
175
|
list.splice(intent.payload.index, 1);
|
|
@@ -183,9 +188,12 @@ function setListValue(data, intent) {
|
|
|
183
188
|
return list;
|
|
184
189
|
});
|
|
185
190
|
}
|
|
186
|
-
function setState(state, name, valueFn) {
|
|
187
|
-
var root = Symbol.for('root');
|
|
188
191
|
|
|
192
|
+
/**
|
|
193
|
+
* A placeholder symbol for the root value of a nested object
|
|
194
|
+
*/
|
|
195
|
+
var root = Symbol.for('root');
|
|
196
|
+
function setState(state, name, valueFn) {
|
|
189
197
|
// The keys are sorted in desc so that the root value is handled last
|
|
190
198
|
var keys = Object.keys(state).sort((prev, next) => next.localeCompare(prev));
|
|
191
199
|
var target = {};
|
|
@@ -235,7 +243,7 @@ function setListState(state, intent, getDefaultValue) {
|
|
|
235
243
|
updateList(list, {
|
|
236
244
|
type: intent.type,
|
|
237
245
|
payload: _objectSpread2(_objectSpread2({}, intent.payload), {}, {
|
|
238
|
-
defaultValue: getDefaultValue === null || getDefaultValue === void 0 ? void 0 : getDefaultValue(intent.payload.defaultValue
|
|
246
|
+
defaultValue: getDefaultValue === null || getDefaultValue === void 0 ? void 0 : getDefaultValue(intent.payload.defaultValue)
|
|
239
247
|
})
|
|
240
248
|
});
|
|
241
249
|
break;
|
|
@@ -275,4 +283,4 @@ function serialize(defaultValue) {
|
|
|
275
283
|
}
|
|
276
284
|
}
|
|
277
285
|
|
|
278
|
-
export { INTENT, STATE, createSubmission, getIntent, getSubmissionContext, parse, replySubmission, serialize, serializeIntent, setListState, setListValue, setState, updateList };
|
|
286
|
+
export { INTENT, STATE, createSubmission, getIntent, getSubmissionContext, parse, replySubmission, root, serialize, serializeIntent, setListState, setListValue, setState, updateList };
|