@conform-to/react 1.17.1 → 1.19.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/future/dom.d.ts +4 -17
- package/dist/future/dom.js +81 -124
- package/dist/future/dom.mjs +81 -121
- package/dist/future/forms.d.ts +1157 -26
- package/dist/future/forms.js +154 -25
- package/dist/future/forms.mjs +152 -28
- package/dist/future/hooks.d.ts +61 -186
- package/dist/future/hooks.js +336 -433
- package/dist/future/hooks.mjs +340 -430
- package/dist/future/index.d.ts +3 -3
- package/dist/future/index.js +6 -6
- package/dist/future/index.mjs +2 -2
- package/dist/future/intent.js +47 -35
- package/dist/future/intent.mjs +49 -37
- package/dist/future/memoize.d.ts +1 -1
- package/dist/future/memoize.js +1 -1
- package/dist/future/memoize.mjs +1 -1
- package/dist/future/state.d.ts +10 -14
- package/dist/future/state.js +58 -68
- package/dist/future/state.mjs +59 -70
- package/dist/future/types.d.ts +207 -139
- package/dist/future/util.d.ts +8 -12
- package/dist/future/util.js +27 -30
- package/dist/future/util.mjs +24 -27
- package/dist/helpers.d.ts +14 -10
- package/dist/helpers.js +14 -10
- package/dist/helpers.mjs +14 -10
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
╚══════╝ ╚═════╝ ╚═╝ ╚══╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝
|
|
8
8
|
```
|
|
9
9
|
|
|
10
|
-
Version 1.
|
|
10
|
+
Version 1.19.0 / License MIT / Copyright (c) 2026 Edmund Hung
|
|
11
11
|
|
|
12
12
|
Progressively enhance HTML forms with React. Build resilient, type-safe forms with no hassle using web standards.
|
|
13
13
|
|
package/dist/future/dom.d.ts
CHANGED
|
@@ -1,27 +1,14 @@
|
|
|
1
1
|
import { Serialize } from '@conform-to/dom/future';
|
|
2
|
-
import type { ErrorContext, FormRef,
|
|
2
|
+
import type { ControlOptions, ErrorContext, FormRef, IntentDispatcher } from './types';
|
|
3
3
|
export declare function getFormElement(formRef: FormRef | undefined): HTMLFormElement | null;
|
|
4
4
|
export declare function getSubmitEvent(event: React.FormEvent<HTMLFormElement>): SubmitEvent;
|
|
5
5
|
export declare function initializeField(element: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement, options: {
|
|
6
|
-
defaultValue?:
|
|
6
|
+
defaultValue?: unknown;
|
|
7
7
|
defaultChecked?: boolean | undefined;
|
|
8
8
|
value?: string | undefined;
|
|
9
9
|
} | undefined): void;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
*/
|
|
13
|
-
export declare function makeInputFocusable(element: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement): void;
|
|
14
|
-
export declare function getRadioGroupValue(inputs: Array<HTMLInputElement>): string | undefined;
|
|
15
|
-
export declare function getCheckboxGroupValue(inputs: Array<HTMLInputElement>): string[] | undefined;
|
|
16
|
-
export declare function getInputSnapshot(input: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement): InputSnapshot;
|
|
17
|
-
/**
|
|
18
|
-
* Creates an InputSnapshot based on the provided options:
|
|
19
|
-
* - checkbox/radio: value / defaultChecked
|
|
20
|
-
* - file inputs: defaultValue is File or FileList
|
|
21
|
-
* - select multiple: defaultValue is string array
|
|
22
|
-
* - others: defaultValue is string
|
|
23
|
-
*/
|
|
24
|
-
export declare function createDefaultSnapshot(defaultValue: string | string[] | File | File[] | FileList | null | undefined, defaultChecked: boolean | undefined, value: string | undefined): InputSnapshot;
|
|
10
|
+
export declare function resolveControlPayload(input: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement | HTMLFieldSetElement | Array<HTMLInputElement>): unknown;
|
|
11
|
+
export declare function deriveDefaultPayload(options: ControlOptions): unknown;
|
|
25
12
|
/**
|
|
26
13
|
* Focuses the first field with validation errors on default form submission.
|
|
27
14
|
* Does nothing if the submission was triggered with a specific intent (e.g. validate / insert)
|
package/dist/future/dom.js
CHANGED
|
@@ -4,17 +4,20 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
4
4
|
|
|
5
5
|
var future = require('@conform-to/dom/future');
|
|
6
6
|
var intent = require('./intent.js');
|
|
7
|
+
var state = require('./state.js');
|
|
7
8
|
|
|
8
9
|
function getFormElement(formRef) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
return document.forms.namedItem(formRef);
|
|
10
|
+
if (typeof formRef === 'undefined') {
|
|
11
|
+
return null;
|
|
12
12
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
if (typeof formRef !== 'string') {
|
|
14
|
+
var element = formRef.current;
|
|
15
|
+
if (!element) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
return future.isGlobalInstance(element, 'HTMLFormElement') ? element : element.form;
|
|
16
19
|
}
|
|
17
|
-
return (
|
|
20
|
+
return document.forms.namedItem(formRef);
|
|
18
21
|
}
|
|
19
22
|
function getSubmitEvent(event) {
|
|
20
23
|
if (event.type !== 'submit') {
|
|
@@ -45,125 +48,69 @@ function initializeField(element, options) {
|
|
|
45
48
|
});
|
|
46
49
|
element.dataset.conform = 'initialized';
|
|
47
50
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
element.style.padding = '0';
|
|
62
|
-
element.style.margin = '-1px';
|
|
63
|
-
element.style.overflow = 'hidden';
|
|
64
|
-
element.style.clip = 'rect(0,0,0,0)';
|
|
65
|
-
element.style.whiteSpace = 'nowrap';
|
|
66
|
-
element.style.border = '0';
|
|
67
|
-
|
|
68
|
-
// Hide the element from screen readers
|
|
69
|
-
element.setAttribute('aria-hidden', 'true');
|
|
70
|
-
|
|
71
|
-
// Make sure people won't tab to this element
|
|
72
|
-
element.tabIndex = -1;
|
|
73
|
-
|
|
74
|
-
// Set the element to be visible again so it can be focused
|
|
75
|
-
if (element.hidden) {
|
|
76
|
-
element.hidden = false;
|
|
77
|
-
}
|
|
78
|
-
if (element.type === 'hidden') {
|
|
79
|
-
element.setAttribute('type', 'text');
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
function getRadioGroupValue(inputs) {
|
|
83
|
-
for (var input of inputs) {
|
|
84
|
-
if (input.type === 'radio' && input.checked) {
|
|
85
|
-
return input.value;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
function getCheckboxGroupValue(inputs) {
|
|
90
|
-
var values;
|
|
91
|
-
for (var input of inputs) {
|
|
92
|
-
if (input.type === 'checkbox') {
|
|
93
|
-
var _values;
|
|
94
|
-
(_values = values) !== null && _values !== void 0 ? _values : values = [];
|
|
95
|
-
if (input.checked) {
|
|
96
|
-
values.push(input.value);
|
|
51
|
+
function resolveControlPayload(input) {
|
|
52
|
+
if (Array.isArray(input)) {
|
|
53
|
+
var options;
|
|
54
|
+
for (var element of input) {
|
|
55
|
+
if (element.type === 'radio' && element.checked) {
|
|
56
|
+
return element.value;
|
|
57
|
+
}
|
|
58
|
+
if (element.type === 'checkbox') {
|
|
59
|
+
var _options;
|
|
60
|
+
(_options = options) !== null && _options !== void 0 ? _options : options = [];
|
|
61
|
+
if (element.checked) {
|
|
62
|
+
options.push(element.value);
|
|
63
|
+
}
|
|
97
64
|
}
|
|
98
65
|
}
|
|
66
|
+
return options;
|
|
99
67
|
}
|
|
100
|
-
return values;
|
|
101
|
-
}
|
|
102
|
-
function getInputSnapshot(input) {
|
|
103
68
|
if (input instanceof HTMLInputElement) {
|
|
104
69
|
switch (input.type) {
|
|
105
70
|
case 'file':
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
}
|
|
71
|
+
{
|
|
72
|
+
return input.files ? Array.from(input.files) : [];
|
|
73
|
+
}
|
|
109
74
|
case 'radio':
|
|
110
75
|
case 'checkbox':
|
|
111
|
-
return
|
|
112
|
-
value: input.value,
|
|
113
|
-
checked: input.checked
|
|
114
|
-
};
|
|
76
|
+
return input.checked ? input.value : null;
|
|
115
77
|
}
|
|
116
78
|
} else if (input instanceof HTMLSelectElement && input.multiple) {
|
|
117
|
-
return
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
return {
|
|
122
|
-
value: input.value
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Creates an InputSnapshot based on the provided options:
|
|
128
|
-
* - checkbox/radio: value / defaultChecked
|
|
129
|
-
* - file inputs: defaultValue is File or FileList
|
|
130
|
-
* - select multiple: defaultValue is string array
|
|
131
|
-
* - others: defaultValue is string
|
|
132
|
-
*/
|
|
133
|
-
function createDefaultSnapshot(defaultValue, defaultChecked, value) {
|
|
134
|
-
if (typeof value === 'string' || typeof defaultChecked === 'boolean') {
|
|
135
|
-
return {
|
|
136
|
-
value: value !== null && value !== void 0 ? value : 'on',
|
|
137
|
-
checked: defaultChecked
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
if (typeof defaultValue === 'string') {
|
|
141
|
-
return {
|
|
142
|
-
value: defaultValue
|
|
143
|
-
};
|
|
144
|
-
}
|
|
145
|
-
if (Array.isArray(defaultValue)) {
|
|
146
|
-
if (defaultValue.every(item => typeof item === 'string')) {
|
|
147
|
-
return {
|
|
148
|
-
options: defaultValue
|
|
149
|
-
};
|
|
150
|
-
} else {
|
|
151
|
-
return {
|
|
152
|
-
files: defaultValue
|
|
153
|
-
};
|
|
79
|
+
return Array.from(input.selectedOptions).map(option => option.value);
|
|
80
|
+
} else if (input instanceof HTMLFieldSetElement) {
|
|
81
|
+
if (input.elements.length === 0) {
|
|
82
|
+
return null;
|
|
154
83
|
}
|
|
84
|
+
var result = {};
|
|
85
|
+
var entries = new Map();
|
|
86
|
+
for (var _element of input.elements) {
|
|
87
|
+
if (future.isFieldElement(_element)) {
|
|
88
|
+
var payload = resolveControlPayload(_element);
|
|
89
|
+
var value = entries.get(_element.name);
|
|
90
|
+
if (_element.type === 'checkbox') {
|
|
91
|
+
entries.set(_element.name, value === undefined ? payload : (Array.isArray(value) ? [...value, payload] : [value, payload]).filter(v => v !== null));
|
|
92
|
+
} else if (_element.type === 'radio') {
|
|
93
|
+
entries.set(_element.name, value == null ? payload : payload === null ? value : payload);
|
|
94
|
+
} else {
|
|
95
|
+
entries.set(_element.name, value === undefined ? payload : Array.isArray(value) ? [...value, payload] : [value, payload]);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
for (var [name, _value] of entries) {
|
|
100
|
+
future.setPathValue(result, name, _value);
|
|
101
|
+
}
|
|
102
|
+
return future.getPathValue(result, input.name);
|
|
155
103
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
104
|
+
return input.value;
|
|
105
|
+
}
|
|
106
|
+
function deriveDefaultPayload(options) {
|
|
107
|
+
if ('defaultChecked' in options && typeof options.defaultChecked === 'boolean') {
|
|
108
|
+
var _options$value2;
|
|
109
|
+
return options.defaultChecked ? (_options$value2 = options.value) !== null && _options$value2 !== void 0 ? _options$value2 : 'on' : null;
|
|
160
110
|
}
|
|
161
|
-
if (
|
|
162
|
-
return
|
|
163
|
-
files: Array.from(defaultValue)
|
|
164
|
-
};
|
|
111
|
+
if ('defaultValue' in options) {
|
|
112
|
+
return options.defaultValue;
|
|
165
113
|
}
|
|
166
|
-
return {};
|
|
167
114
|
}
|
|
168
115
|
|
|
169
116
|
/**
|
|
@@ -175,22 +122,33 @@ function focusFirstInvalidField(ctx) {
|
|
|
175
122
|
return;
|
|
176
123
|
}
|
|
177
124
|
for (var element of ctx.formElement.elements) {
|
|
178
|
-
|
|
179
|
-
|
|
125
|
+
if (!(future.isFieldElement(element) || element instanceof HTMLFieldSetElement) || element.name === '' || !state.hasFieldError(ctx.error, element.name)) {
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Treat fieldset as a focusable field only if it is hidden
|
|
130
|
+
if (element.type === 'fieldset' && !element.hidden) {
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
if (element.hidden || element.type === 'hidden' || element.type === 'fieldset') {
|
|
134
|
+
future.focus(element);
|
|
135
|
+
} else {
|
|
180
136
|
element.focus();
|
|
181
|
-
break;
|
|
182
137
|
}
|
|
138
|
+
break;
|
|
183
139
|
}
|
|
184
140
|
}
|
|
185
141
|
function updateFormValue(form, targetValue, serialize) {
|
|
186
142
|
for (var element of form.elements) {
|
|
187
143
|
if (future.isFieldElement(element) && element.name && element.type !== 'hidden') {
|
|
188
|
-
var fieldValue = future.
|
|
144
|
+
var fieldValue = future.getPathValue(targetValue, element.name);
|
|
189
145
|
if (element.type === 'file' && fieldValue === undefined) {
|
|
190
146
|
// Do not update file inputs unless there's a target value
|
|
191
147
|
continue;
|
|
192
148
|
}
|
|
193
|
-
var value = serialize(fieldValue
|
|
149
|
+
var value = serialize(fieldValue, {
|
|
150
|
+
name: element.name
|
|
151
|
+
});
|
|
194
152
|
|
|
195
153
|
// Treat undefined as null to clear the field value
|
|
196
154
|
future.change(element, value !== undefined ? value : null, {
|
|
@@ -202,8 +160,10 @@ function updateFormValue(form, targetValue, serialize) {
|
|
|
202
160
|
function resetFormValue(form, defaultValue, serialize) {
|
|
203
161
|
for (var element of form.elements) {
|
|
204
162
|
if (future.isFieldElement(element) && element.name && element.type !== 'hidden' && element.type !== 'file') {
|
|
205
|
-
var fieldValue = future.
|
|
206
|
-
var value = serialize(fieldValue
|
|
163
|
+
var fieldValue = future.getPathValue(defaultValue, element.name);
|
|
164
|
+
var value = serialize(fieldValue, {
|
|
165
|
+
name: element.name
|
|
166
|
+
});
|
|
207
167
|
future.updateField(element, {
|
|
208
168
|
defaultValue: value !== undefined ? value : null
|
|
209
169
|
});
|
|
@@ -363,16 +323,13 @@ function preserveInputs(inputs, form, name) {
|
|
|
363
323
|
}
|
|
364
324
|
|
|
365
325
|
exports.cleanupPreservedInputs = cleanupPreservedInputs;
|
|
366
|
-
exports.createDefaultSnapshot = createDefaultSnapshot;
|
|
367
326
|
exports.createIntentDispatcher = createIntentDispatcher;
|
|
327
|
+
exports.deriveDefaultPayload = deriveDefaultPayload;
|
|
368
328
|
exports.focusFirstInvalidField = focusFirstInvalidField;
|
|
369
|
-
exports.getCheckboxGroupValue = getCheckboxGroupValue;
|
|
370
329
|
exports.getFormElement = getFormElement;
|
|
371
|
-
exports.getInputSnapshot = getInputSnapshot;
|
|
372
|
-
exports.getRadioGroupValue = getRadioGroupValue;
|
|
373
330
|
exports.getSubmitEvent = getSubmitEvent;
|
|
374
331
|
exports.initializeField = initializeField;
|
|
375
|
-
exports.makeInputFocusable = makeInputFocusable;
|
|
376
332
|
exports.preserveInputs = preserveInputs;
|
|
377
333
|
exports.resetFormValue = resetFormValue;
|
|
334
|
+
exports.resolveControlPayload = resolveControlPayload;
|
|
378
335
|
exports.updateFormValue = updateFormValue;
|
package/dist/future/dom.mjs
CHANGED
|
@@ -1,16 +1,19 @@
|
|
|
1
|
-
import { change, updateField,
|
|
1
|
+
import { isGlobalInstance, change, updateField, isFieldElement, setPathValue, getPathValue, focus, requestIntent } from '@conform-to/dom/future';
|
|
2
2
|
import { serializeIntent } from './intent.mjs';
|
|
3
|
+
import { hasFieldError } from './state.mjs';
|
|
3
4
|
|
|
4
5
|
function getFormElement(formRef) {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
return document.forms.namedItem(formRef);
|
|
6
|
+
if (typeof formRef === 'undefined') {
|
|
7
|
+
return null;
|
|
8
8
|
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
if (typeof formRef !== 'string') {
|
|
10
|
+
var element = formRef.current;
|
|
11
|
+
if (!element) {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
return isGlobalInstance(element, 'HTMLFormElement') ? element : element.form;
|
|
12
15
|
}
|
|
13
|
-
return (
|
|
16
|
+
return document.forms.namedItem(formRef);
|
|
14
17
|
}
|
|
15
18
|
function getSubmitEvent(event) {
|
|
16
19
|
if (event.type !== 'submit') {
|
|
@@ -41,125 +44,69 @@ function initializeField(element, options) {
|
|
|
41
44
|
});
|
|
42
45
|
element.dataset.conform = 'initialized';
|
|
43
46
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
element.style.padding = '0';
|
|
58
|
-
element.style.margin = '-1px';
|
|
59
|
-
element.style.overflow = 'hidden';
|
|
60
|
-
element.style.clip = 'rect(0,0,0,0)';
|
|
61
|
-
element.style.whiteSpace = 'nowrap';
|
|
62
|
-
element.style.border = '0';
|
|
63
|
-
|
|
64
|
-
// Hide the element from screen readers
|
|
65
|
-
element.setAttribute('aria-hidden', 'true');
|
|
66
|
-
|
|
67
|
-
// Make sure people won't tab to this element
|
|
68
|
-
element.tabIndex = -1;
|
|
69
|
-
|
|
70
|
-
// Set the element to be visible again so it can be focused
|
|
71
|
-
if (element.hidden) {
|
|
72
|
-
element.hidden = false;
|
|
73
|
-
}
|
|
74
|
-
if (element.type === 'hidden') {
|
|
75
|
-
element.setAttribute('type', 'text');
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
function getRadioGroupValue(inputs) {
|
|
79
|
-
for (var input of inputs) {
|
|
80
|
-
if (input.type === 'radio' && input.checked) {
|
|
81
|
-
return input.value;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
function getCheckboxGroupValue(inputs) {
|
|
86
|
-
var values;
|
|
87
|
-
for (var input of inputs) {
|
|
88
|
-
if (input.type === 'checkbox') {
|
|
89
|
-
var _values;
|
|
90
|
-
(_values = values) !== null && _values !== void 0 ? _values : values = [];
|
|
91
|
-
if (input.checked) {
|
|
92
|
-
values.push(input.value);
|
|
47
|
+
function resolveControlPayload(input) {
|
|
48
|
+
if (Array.isArray(input)) {
|
|
49
|
+
var options;
|
|
50
|
+
for (var element of input) {
|
|
51
|
+
if (element.type === 'radio' && element.checked) {
|
|
52
|
+
return element.value;
|
|
53
|
+
}
|
|
54
|
+
if (element.type === 'checkbox') {
|
|
55
|
+
var _options;
|
|
56
|
+
(_options = options) !== null && _options !== void 0 ? _options : options = [];
|
|
57
|
+
if (element.checked) {
|
|
58
|
+
options.push(element.value);
|
|
59
|
+
}
|
|
93
60
|
}
|
|
94
61
|
}
|
|
62
|
+
return options;
|
|
95
63
|
}
|
|
96
|
-
return values;
|
|
97
|
-
}
|
|
98
|
-
function getInputSnapshot(input) {
|
|
99
64
|
if (input instanceof HTMLInputElement) {
|
|
100
65
|
switch (input.type) {
|
|
101
66
|
case 'file':
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
67
|
+
{
|
|
68
|
+
return input.files ? Array.from(input.files) : [];
|
|
69
|
+
}
|
|
105
70
|
case 'radio':
|
|
106
71
|
case 'checkbox':
|
|
107
|
-
return
|
|
108
|
-
value: input.value,
|
|
109
|
-
checked: input.checked
|
|
110
|
-
};
|
|
72
|
+
return input.checked ? input.value : null;
|
|
111
73
|
}
|
|
112
74
|
} else if (input instanceof HTMLSelectElement && input.multiple) {
|
|
113
|
-
return
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
return {
|
|
118
|
-
value: input.value
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Creates an InputSnapshot based on the provided options:
|
|
124
|
-
* - checkbox/radio: value / defaultChecked
|
|
125
|
-
* - file inputs: defaultValue is File or FileList
|
|
126
|
-
* - select multiple: defaultValue is string array
|
|
127
|
-
* - others: defaultValue is string
|
|
128
|
-
*/
|
|
129
|
-
function createDefaultSnapshot(defaultValue, defaultChecked, value) {
|
|
130
|
-
if (typeof value === 'string' || typeof defaultChecked === 'boolean') {
|
|
131
|
-
return {
|
|
132
|
-
value: value !== null && value !== void 0 ? value : 'on',
|
|
133
|
-
checked: defaultChecked
|
|
134
|
-
};
|
|
135
|
-
}
|
|
136
|
-
if (typeof defaultValue === 'string') {
|
|
137
|
-
return {
|
|
138
|
-
value: defaultValue
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
if (Array.isArray(defaultValue)) {
|
|
142
|
-
if (defaultValue.every(item => typeof item === 'string')) {
|
|
143
|
-
return {
|
|
144
|
-
options: defaultValue
|
|
145
|
-
};
|
|
146
|
-
} else {
|
|
147
|
-
return {
|
|
148
|
-
files: defaultValue
|
|
149
|
-
};
|
|
75
|
+
return Array.from(input.selectedOptions).map(option => option.value);
|
|
76
|
+
} else if (input instanceof HTMLFieldSetElement) {
|
|
77
|
+
if (input.elements.length === 0) {
|
|
78
|
+
return null;
|
|
150
79
|
}
|
|
80
|
+
var result = {};
|
|
81
|
+
var entries = new Map();
|
|
82
|
+
for (var _element of input.elements) {
|
|
83
|
+
if (isFieldElement(_element)) {
|
|
84
|
+
var payload = resolveControlPayload(_element);
|
|
85
|
+
var value = entries.get(_element.name);
|
|
86
|
+
if (_element.type === 'checkbox') {
|
|
87
|
+
entries.set(_element.name, value === undefined ? payload : (Array.isArray(value) ? [...value, payload] : [value, payload]).filter(v => v !== null));
|
|
88
|
+
} else if (_element.type === 'radio') {
|
|
89
|
+
entries.set(_element.name, value == null ? payload : payload === null ? value : payload);
|
|
90
|
+
} else {
|
|
91
|
+
entries.set(_element.name, value === undefined ? payload : Array.isArray(value) ? [...value, payload] : [value, payload]);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
for (var [name, _value] of entries) {
|
|
96
|
+
setPathValue(result, name, _value);
|
|
97
|
+
}
|
|
98
|
+
return getPathValue(result, input.name);
|
|
151
99
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
100
|
+
return input.value;
|
|
101
|
+
}
|
|
102
|
+
function deriveDefaultPayload(options) {
|
|
103
|
+
if ('defaultChecked' in options && typeof options.defaultChecked === 'boolean') {
|
|
104
|
+
var _options$value2;
|
|
105
|
+
return options.defaultChecked ? (_options$value2 = options.value) !== null && _options$value2 !== void 0 ? _options$value2 : 'on' : null;
|
|
156
106
|
}
|
|
157
|
-
if (
|
|
158
|
-
return
|
|
159
|
-
files: Array.from(defaultValue)
|
|
160
|
-
};
|
|
107
|
+
if ('defaultValue' in options) {
|
|
108
|
+
return options.defaultValue;
|
|
161
109
|
}
|
|
162
|
-
return {};
|
|
163
110
|
}
|
|
164
111
|
|
|
165
112
|
/**
|
|
@@ -171,22 +118,33 @@ function focusFirstInvalidField(ctx) {
|
|
|
171
118
|
return;
|
|
172
119
|
}
|
|
173
120
|
for (var element of ctx.formElement.elements) {
|
|
174
|
-
|
|
175
|
-
|
|
121
|
+
if (!(isFieldElement(element) || element instanceof HTMLFieldSetElement) || element.name === '' || !hasFieldError(ctx.error, element.name)) {
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Treat fieldset as a focusable field only if it is hidden
|
|
126
|
+
if (element.type === 'fieldset' && !element.hidden) {
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
if (element.hidden || element.type === 'hidden' || element.type === 'fieldset') {
|
|
130
|
+
focus(element);
|
|
131
|
+
} else {
|
|
176
132
|
element.focus();
|
|
177
|
-
break;
|
|
178
133
|
}
|
|
134
|
+
break;
|
|
179
135
|
}
|
|
180
136
|
}
|
|
181
137
|
function updateFormValue(form, targetValue, serialize) {
|
|
182
138
|
for (var element of form.elements) {
|
|
183
139
|
if (isFieldElement(element) && element.name && element.type !== 'hidden') {
|
|
184
|
-
var fieldValue =
|
|
140
|
+
var fieldValue = getPathValue(targetValue, element.name);
|
|
185
141
|
if (element.type === 'file' && fieldValue === undefined) {
|
|
186
142
|
// Do not update file inputs unless there's a target value
|
|
187
143
|
continue;
|
|
188
144
|
}
|
|
189
|
-
var value = serialize(fieldValue
|
|
145
|
+
var value = serialize(fieldValue, {
|
|
146
|
+
name: element.name
|
|
147
|
+
});
|
|
190
148
|
|
|
191
149
|
// Treat undefined as null to clear the field value
|
|
192
150
|
change(element, value !== undefined ? value : null, {
|
|
@@ -198,8 +156,10 @@ function updateFormValue(form, targetValue, serialize) {
|
|
|
198
156
|
function resetFormValue(form, defaultValue, serialize) {
|
|
199
157
|
for (var element of form.elements) {
|
|
200
158
|
if (isFieldElement(element) && element.name && element.type !== 'hidden' && element.type !== 'file') {
|
|
201
|
-
var fieldValue =
|
|
202
|
-
var value = serialize(fieldValue
|
|
159
|
+
var fieldValue = getPathValue(defaultValue, element.name);
|
|
160
|
+
var value = serialize(fieldValue, {
|
|
161
|
+
name: element.name
|
|
162
|
+
});
|
|
203
163
|
updateField(element, {
|
|
204
164
|
defaultValue: value !== undefined ? value : null
|
|
205
165
|
});
|
|
@@ -358,4 +318,4 @@ function preserveInputs(inputs, form, name) {
|
|
|
358
318
|
}
|
|
359
319
|
}
|
|
360
320
|
|
|
361
|
-
export { cleanupPreservedInputs,
|
|
321
|
+
export { cleanupPreservedInputs, createIntentDispatcher, deriveDefaultPayload, focusFirstInvalidField, getFormElement, getSubmitEvent, initializeField, preserveInputs, resetFormValue, resolveControlPayload, updateFormValue };
|