@conform-to/dom 0.1.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/LICENSE +21 -0
- package/README.md +42 -0
- package/index.d.ts +84 -0
- package/index.js +253 -0
- package/module/index.js +238 -0
- package/package.json +29 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022 Edmund Hung
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# @conform-to/dom
|
|
2
|
+
|
|
3
|
+
> A set of opinionated helpers interacting with the DOM elements
|
|
4
|
+
|
|
5
|
+
## API Reference
|
|
6
|
+
|
|
7
|
+
- [createControlButton](#createControlButton)
|
|
8
|
+
- [createFieldConfig](#createFieldConfig)
|
|
9
|
+
- [getFieldElements](#getFieldElements)
|
|
10
|
+
- [getName](#getName)
|
|
11
|
+
- [getPaths](#getPaths)
|
|
12
|
+
- [isFieldElement](#isFieldElement)
|
|
13
|
+
- [parse](#parse)
|
|
14
|
+
- [reportValidity](#reportValidity)
|
|
15
|
+
- [setFieldState](#setFieldState)
|
|
16
|
+
- [shouldSkipValidate](#shouldSkipValidate)
|
|
17
|
+
- [setFieldState](#setFieldState)
|
|
18
|
+
- [transform](#transform)
|
|
19
|
+
|
|
20
|
+
### createControlButton
|
|
21
|
+
|
|
22
|
+
### createFieldConfig
|
|
23
|
+
|
|
24
|
+
### getFieldElements
|
|
25
|
+
|
|
26
|
+
### getName
|
|
27
|
+
|
|
28
|
+
### getPaths
|
|
29
|
+
|
|
30
|
+
### isFieldElement
|
|
31
|
+
|
|
32
|
+
### isFieldsetElement
|
|
33
|
+
|
|
34
|
+
### parse
|
|
35
|
+
|
|
36
|
+
### reportValidity
|
|
37
|
+
|
|
38
|
+
### setFieldState
|
|
39
|
+
|
|
40
|
+
### shouldSkipValidate
|
|
41
|
+
|
|
42
|
+
### transform
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
export declare type Constraint<Type> = (Type extends string | number | Date | undefined ? {
|
|
2
|
+
required?: boolean;
|
|
3
|
+
minLength?: number;
|
|
4
|
+
maxLength?: number;
|
|
5
|
+
min?: string;
|
|
6
|
+
max?: string;
|
|
7
|
+
step?: string;
|
|
8
|
+
multiple?: boolean;
|
|
9
|
+
pattern?: string;
|
|
10
|
+
} : {}) & (undefined extends Type ? {
|
|
11
|
+
required?: false;
|
|
12
|
+
} : {
|
|
13
|
+
required: true;
|
|
14
|
+
}) & (Type extends Array<any> ? {
|
|
15
|
+
multiple: true;
|
|
16
|
+
} : {
|
|
17
|
+
multiple?: false;
|
|
18
|
+
});
|
|
19
|
+
export interface FieldConfig<Type = any> {
|
|
20
|
+
name: string;
|
|
21
|
+
initialValue?: FieldsetData<Type, string>;
|
|
22
|
+
error?: FieldsetData<Type, string>;
|
|
23
|
+
form?: string;
|
|
24
|
+
constraint?: Constraint<Type>;
|
|
25
|
+
}
|
|
26
|
+
export declare type Schema<Type extends Record<string, any>> = {
|
|
27
|
+
fields: {
|
|
28
|
+
[Key in keyof Type]-?: Constraint<Type[Key]>;
|
|
29
|
+
};
|
|
30
|
+
validate?: (element: FieldsetElement) => void;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Data structure of the form value
|
|
34
|
+
*/
|
|
35
|
+
export declare type FieldsetData<Type, Value> = Type extends string | number | Date | undefined ? Value : Type extends Array<infer InnerType> ? Array<FieldsetData<InnerType, Value>> : Type extends Object ? {
|
|
36
|
+
[Key in keyof Type]?: FieldsetData<Type[Key], Value>;
|
|
37
|
+
} : unknown;
|
|
38
|
+
/**
|
|
39
|
+
* Element that maintains a list of fields
|
|
40
|
+
* i.e. fieldset.elements
|
|
41
|
+
*/
|
|
42
|
+
export declare type FieldsetElement = HTMLFormElement | HTMLFieldSetElement;
|
|
43
|
+
/**
|
|
44
|
+
* Element type that might be a candiate of Constraint Validation
|
|
45
|
+
*/
|
|
46
|
+
export declare type FieldElement = HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement | HTMLButtonElement;
|
|
47
|
+
export declare type FormResult<T> = {
|
|
48
|
+
state: 'processed';
|
|
49
|
+
value: FieldsetData<T, string> | null;
|
|
50
|
+
error: FieldsetData<T, string> | null;
|
|
51
|
+
} | {
|
|
52
|
+
state: 'rejected';
|
|
53
|
+
value: FieldsetData<T, string> | null;
|
|
54
|
+
error: FieldsetData<T, string>;
|
|
55
|
+
} | {
|
|
56
|
+
state: 'accepted';
|
|
57
|
+
value: T;
|
|
58
|
+
};
|
|
59
|
+
export declare function isFieldsetElement(element: unknown): element is FieldsetElement;
|
|
60
|
+
export declare function isFieldElement(element: unknown): element is FieldElement;
|
|
61
|
+
export declare function setFieldState(field: unknown, state: {
|
|
62
|
+
touched: boolean;
|
|
63
|
+
}): void;
|
|
64
|
+
export declare function reportValidity(fieldset: FieldsetElement): boolean;
|
|
65
|
+
export declare function createFieldConfig<Type extends Record<string, any>>(schema: Schema<Type>, options: {
|
|
66
|
+
name?: string;
|
|
67
|
+
form?: string;
|
|
68
|
+
initialValue?: FieldsetData<Type, string>;
|
|
69
|
+
error?: FieldsetData<Type, string>;
|
|
70
|
+
}): {
|
|
71
|
+
[Key in keyof Type]-?: FieldConfig<Type[Key]>;
|
|
72
|
+
};
|
|
73
|
+
export declare function shouldSkipValidate(event: SubmitEvent): boolean;
|
|
74
|
+
export declare function getPaths(name?: string): Array<string | number>;
|
|
75
|
+
export declare function getName(paths: Array<string | number>): string;
|
|
76
|
+
export declare function transform(entries: Array<[string, FormDataEntryValue]> | Iterable<[string, FormDataEntryValue]>): unknown;
|
|
77
|
+
export declare function createControlButton(name: string, action: 'prepend' | 'append' | 'remove', data: any): {
|
|
78
|
+
type: 'submit';
|
|
79
|
+
name: string;
|
|
80
|
+
value: string;
|
|
81
|
+
formNoValidate: boolean;
|
|
82
|
+
};
|
|
83
|
+
export declare function parse(payload: FormData | URLSearchParams): FormResult<unknown>;
|
|
84
|
+
export declare function getFieldElements(fieldset: FieldsetElement, key: string): FieldElement[];
|
package/index.js
ADDED
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Data structure of the form value
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Element that maintains a list of fields
|
|
11
|
+
* i.e. fieldset.elements
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Element type that might be a candiate of Constraint Validation
|
|
16
|
+
*/
|
|
17
|
+
function isFieldsetElement(element) {
|
|
18
|
+
return element instanceof Element && (element.tagName === 'FORM' || element.tagName === 'FIELDSET');
|
|
19
|
+
}
|
|
20
|
+
function isFieldElement(element) {
|
|
21
|
+
return element instanceof Element && (element.tagName === 'INPUT' || element.tagName === 'SELECT' || element.tagName === 'TEXTAREA' || element.tagName === 'BUTTON');
|
|
22
|
+
}
|
|
23
|
+
function setFieldState(field, state) {
|
|
24
|
+
if (isFieldsetElement(field)) {
|
|
25
|
+
for (var _element of field.elements) {
|
|
26
|
+
setFieldState(_element, state);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (!isFieldElement(field)) {
|
|
33
|
+
console.warn('Only input/select/textarea/button element can be touched');
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (state.touched) {
|
|
38
|
+
field.dataset.touched = 'true';
|
|
39
|
+
} else {
|
|
40
|
+
delete field.dataset.touched;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function reportValidity(fieldset) {
|
|
44
|
+
var isValid = true;
|
|
45
|
+
|
|
46
|
+
for (var field of fieldset.elements) {
|
|
47
|
+
if (isFieldElement(field) && field.dataset.touched && !field.checkValidity()) {
|
|
48
|
+
isValid = false;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return isValid;
|
|
53
|
+
}
|
|
54
|
+
function createFieldConfig(schema, options) {
|
|
55
|
+
var result = {};
|
|
56
|
+
|
|
57
|
+
for (var key of Object.keys(schema.fields)) {
|
|
58
|
+
var _options$initialValue, _options$error;
|
|
59
|
+
|
|
60
|
+
var constraint = schema.fields[key];
|
|
61
|
+
var config = {
|
|
62
|
+
name: options.name ? "".concat(options.name, ".").concat(key) : key,
|
|
63
|
+
form: options.form,
|
|
64
|
+
initialValue: (_options$initialValue = options.initialValue) === null || _options$initialValue === void 0 ? void 0 : _options$initialValue[key],
|
|
65
|
+
error: (_options$error = options.error) === null || _options$error === void 0 ? void 0 : _options$error[key],
|
|
66
|
+
// @ts-expect-error
|
|
67
|
+
constraint
|
|
68
|
+
};
|
|
69
|
+
result[key] = config;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return result;
|
|
73
|
+
}
|
|
74
|
+
function shouldSkipValidate(event) {
|
|
75
|
+
var _event$submitter, _event$submitter2;
|
|
76
|
+
|
|
77
|
+
if (((_event$submitter = event.submitter) === null || _event$submitter === void 0 ? void 0 : _event$submitter.tagName) === 'BUTTON' || ((_event$submitter2 = event.submitter) === null || _event$submitter2 === void 0 ? void 0 : _event$submitter2.tagName) === 'INPUT') {
|
|
78
|
+
return event.submitter.formNoValidate;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
function getPaths(name) {
|
|
84
|
+
var pattern = /(\w+)\[(\d+)\]/;
|
|
85
|
+
|
|
86
|
+
if (!name) {
|
|
87
|
+
return [];
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return name.split('.').flatMap(key => {
|
|
91
|
+
var matches = pattern.exec(key);
|
|
92
|
+
|
|
93
|
+
if (!matches) {
|
|
94
|
+
return key;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return [matches[1], Number(matches[2])];
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
function getName(paths) {
|
|
101
|
+
return paths.reduce((name, path) => {
|
|
102
|
+
if (name === '' || path === '') {
|
|
103
|
+
return [name, path].join('');
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (typeof path === 'number') {
|
|
107
|
+
return "".concat(name, "[").concat(path, "]");
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return [name, path].join('.');
|
|
111
|
+
}, '');
|
|
112
|
+
}
|
|
113
|
+
function transform(entries) {
|
|
114
|
+
var result = {};
|
|
115
|
+
|
|
116
|
+
for (var [key, value] of entries) {
|
|
117
|
+
var paths = getPaths(key);
|
|
118
|
+
var length = paths.length;
|
|
119
|
+
var lastIndex = length - 1;
|
|
120
|
+
var index = -1;
|
|
121
|
+
var pointer = result;
|
|
122
|
+
|
|
123
|
+
while (pointer != null && ++index < length) {
|
|
124
|
+
var _key = paths[index];
|
|
125
|
+
var next = paths[index + 1];
|
|
126
|
+
var newValue = value;
|
|
127
|
+
|
|
128
|
+
if (index != lastIndex) {
|
|
129
|
+
var _pointer$_key;
|
|
130
|
+
|
|
131
|
+
newValue = (_pointer$_key = pointer[_key]) !== null && _pointer$_key !== void 0 ? _pointer$_key : typeof next === 'number' ? [] : {};
|
|
132
|
+
} // if (typeof pointer[key] !== 'undefined') {
|
|
133
|
+
// pointer[key] = Array.isArray(pointer[key])
|
|
134
|
+
// ? pointer[key].concat(newValue)
|
|
135
|
+
// : [pointer[key], newValue];
|
|
136
|
+
// } else {
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
pointer[_key] = newValue; // }
|
|
140
|
+
|
|
141
|
+
pointer = pointer[_key];
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return result;
|
|
146
|
+
}
|
|
147
|
+
function createControlButton(name, action, data) {
|
|
148
|
+
return {
|
|
149
|
+
type: 'submit',
|
|
150
|
+
name: '__conform__',
|
|
151
|
+
value: [name, action, JSON.stringify(data)].join('::'),
|
|
152
|
+
formNoValidate: true
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
function parse(payload) {
|
|
156
|
+
var command = payload.get('__conform__');
|
|
157
|
+
|
|
158
|
+
if (command) {
|
|
159
|
+
payload.delete('__conform__');
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
var value = transform(payload.entries());
|
|
163
|
+
|
|
164
|
+
if (command) {
|
|
165
|
+
try {
|
|
166
|
+
if (command instanceof File) {
|
|
167
|
+
throw new Error('The __conform__ key is reserved for special command and could not be used for file upload.');
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
var [name, action, json] = command.split('::');
|
|
171
|
+
var list = value;
|
|
172
|
+
|
|
173
|
+
for (var path of getPaths(name)) {
|
|
174
|
+
list = list[path];
|
|
175
|
+
|
|
176
|
+
if (typeof list === 'undefined') {
|
|
177
|
+
break;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (!Array.isArray(list)) {
|
|
182
|
+
throw new Error('');
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
switch (action) {
|
|
186
|
+
case 'prepend':
|
|
187
|
+
{
|
|
188
|
+
var initialValue = JSON.parse(json);
|
|
189
|
+
list.unshift(initialValue);
|
|
190
|
+
break;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
case 'append':
|
|
194
|
+
{
|
|
195
|
+
var _initialValue = JSON.parse(json);
|
|
196
|
+
|
|
197
|
+
list.push(_initialValue);
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
case 'remove':
|
|
202
|
+
var {
|
|
203
|
+
index
|
|
204
|
+
} = JSON.parse(json);
|
|
205
|
+
list.splice(index, 1);
|
|
206
|
+
break;
|
|
207
|
+
|
|
208
|
+
default:
|
|
209
|
+
throw new Error('Invalid action found; Only `prepend`, `append` and `remove` is accepted');
|
|
210
|
+
}
|
|
211
|
+
} catch (e) {
|
|
212
|
+
return {
|
|
213
|
+
state: 'rejected',
|
|
214
|
+
value,
|
|
215
|
+
error: {
|
|
216
|
+
__conform__: e instanceof Error ? e.message : 'Something went wrong'
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
return {
|
|
222
|
+
state: 'processed',
|
|
223
|
+
value,
|
|
224
|
+
error: null
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return {
|
|
229
|
+
state: 'accepted',
|
|
230
|
+
value
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
function getFieldElements(fieldset, key) {
|
|
234
|
+
var _fieldset$name;
|
|
235
|
+
|
|
236
|
+
var name = getName([(_fieldset$name = fieldset.name) !== null && _fieldset$name !== void 0 ? _fieldset$name : '', key]);
|
|
237
|
+
var item = fieldset.elements.namedItem(name);
|
|
238
|
+
var nodes = item instanceof RadioNodeList ? Array.from(item) : item !== null ? [item] : [];
|
|
239
|
+
return nodes.filter(isFieldElement);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
exports.createControlButton = createControlButton;
|
|
243
|
+
exports.createFieldConfig = createFieldConfig;
|
|
244
|
+
exports.getFieldElements = getFieldElements;
|
|
245
|
+
exports.getName = getName;
|
|
246
|
+
exports.getPaths = getPaths;
|
|
247
|
+
exports.isFieldElement = isFieldElement;
|
|
248
|
+
exports.isFieldsetElement = isFieldsetElement;
|
|
249
|
+
exports.parse = parse;
|
|
250
|
+
exports.reportValidity = reportValidity;
|
|
251
|
+
exports.setFieldState = setFieldState;
|
|
252
|
+
exports.shouldSkipValidate = shouldSkipValidate;
|
|
253
|
+
exports.transform = transform;
|
package/module/index.js
ADDED
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Data structure of the form value
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Element that maintains a list of fields
|
|
7
|
+
* i.e. fieldset.elements
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Element type that might be a candiate of Constraint Validation
|
|
12
|
+
*/
|
|
13
|
+
function isFieldsetElement(element) {
|
|
14
|
+
return element instanceof Element && (element.tagName === 'FORM' || element.tagName === 'FIELDSET');
|
|
15
|
+
}
|
|
16
|
+
function isFieldElement(element) {
|
|
17
|
+
return element instanceof Element && (element.tagName === 'INPUT' || element.tagName === 'SELECT' || element.tagName === 'TEXTAREA' || element.tagName === 'BUTTON');
|
|
18
|
+
}
|
|
19
|
+
function setFieldState(field, state) {
|
|
20
|
+
if (isFieldsetElement(field)) {
|
|
21
|
+
for (var _element of field.elements) {
|
|
22
|
+
setFieldState(_element, state);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (!isFieldElement(field)) {
|
|
29
|
+
console.warn('Only input/select/textarea/button element can be touched');
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (state.touched) {
|
|
34
|
+
field.dataset.touched = 'true';
|
|
35
|
+
} else {
|
|
36
|
+
delete field.dataset.touched;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function reportValidity(fieldset) {
|
|
40
|
+
var isValid = true;
|
|
41
|
+
|
|
42
|
+
for (var field of fieldset.elements) {
|
|
43
|
+
if (isFieldElement(field) && field.dataset.touched && !field.checkValidity()) {
|
|
44
|
+
isValid = false;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return isValid;
|
|
49
|
+
}
|
|
50
|
+
function createFieldConfig(schema, options) {
|
|
51
|
+
var result = {};
|
|
52
|
+
|
|
53
|
+
for (var key of Object.keys(schema.fields)) {
|
|
54
|
+
var _options$initialValue, _options$error;
|
|
55
|
+
|
|
56
|
+
var constraint = schema.fields[key];
|
|
57
|
+
var config = {
|
|
58
|
+
name: options.name ? "".concat(options.name, ".").concat(key) : key,
|
|
59
|
+
form: options.form,
|
|
60
|
+
initialValue: (_options$initialValue = options.initialValue) === null || _options$initialValue === void 0 ? void 0 : _options$initialValue[key],
|
|
61
|
+
error: (_options$error = options.error) === null || _options$error === void 0 ? void 0 : _options$error[key],
|
|
62
|
+
// @ts-expect-error
|
|
63
|
+
constraint
|
|
64
|
+
};
|
|
65
|
+
result[key] = config;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return result;
|
|
69
|
+
}
|
|
70
|
+
function shouldSkipValidate(event) {
|
|
71
|
+
var _event$submitter, _event$submitter2;
|
|
72
|
+
|
|
73
|
+
if (((_event$submitter = event.submitter) === null || _event$submitter === void 0 ? void 0 : _event$submitter.tagName) === 'BUTTON' || ((_event$submitter2 = event.submitter) === null || _event$submitter2 === void 0 ? void 0 : _event$submitter2.tagName) === 'INPUT') {
|
|
74
|
+
return event.submitter.formNoValidate;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
function getPaths(name) {
|
|
80
|
+
var pattern = /(\w+)\[(\d+)\]/;
|
|
81
|
+
|
|
82
|
+
if (!name) {
|
|
83
|
+
return [];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return name.split('.').flatMap(key => {
|
|
87
|
+
var matches = pattern.exec(key);
|
|
88
|
+
|
|
89
|
+
if (!matches) {
|
|
90
|
+
return key;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return [matches[1], Number(matches[2])];
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
function getName(paths) {
|
|
97
|
+
return paths.reduce((name, path) => {
|
|
98
|
+
if (name === '' || path === '') {
|
|
99
|
+
return [name, path].join('');
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (typeof path === 'number') {
|
|
103
|
+
return "".concat(name, "[").concat(path, "]");
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return [name, path].join('.');
|
|
107
|
+
}, '');
|
|
108
|
+
}
|
|
109
|
+
function transform(entries) {
|
|
110
|
+
var result = {};
|
|
111
|
+
|
|
112
|
+
for (var [key, value] of entries) {
|
|
113
|
+
var paths = getPaths(key);
|
|
114
|
+
var length = paths.length;
|
|
115
|
+
var lastIndex = length - 1;
|
|
116
|
+
var index = -1;
|
|
117
|
+
var pointer = result;
|
|
118
|
+
|
|
119
|
+
while (pointer != null && ++index < length) {
|
|
120
|
+
var _key = paths[index];
|
|
121
|
+
var next = paths[index + 1];
|
|
122
|
+
var newValue = value;
|
|
123
|
+
|
|
124
|
+
if (index != lastIndex) {
|
|
125
|
+
var _pointer$_key;
|
|
126
|
+
|
|
127
|
+
newValue = (_pointer$_key = pointer[_key]) !== null && _pointer$_key !== void 0 ? _pointer$_key : typeof next === 'number' ? [] : {};
|
|
128
|
+
} // if (typeof pointer[key] !== 'undefined') {
|
|
129
|
+
// pointer[key] = Array.isArray(pointer[key])
|
|
130
|
+
// ? pointer[key].concat(newValue)
|
|
131
|
+
// : [pointer[key], newValue];
|
|
132
|
+
// } else {
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
pointer[_key] = newValue; // }
|
|
136
|
+
|
|
137
|
+
pointer = pointer[_key];
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return result;
|
|
142
|
+
}
|
|
143
|
+
function createControlButton(name, action, data) {
|
|
144
|
+
return {
|
|
145
|
+
type: 'submit',
|
|
146
|
+
name: '__conform__',
|
|
147
|
+
value: [name, action, JSON.stringify(data)].join('::'),
|
|
148
|
+
formNoValidate: true
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
function parse(payload) {
|
|
152
|
+
var command = payload.get('__conform__');
|
|
153
|
+
|
|
154
|
+
if (command) {
|
|
155
|
+
payload.delete('__conform__');
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
var value = transform(payload.entries());
|
|
159
|
+
|
|
160
|
+
if (command) {
|
|
161
|
+
try {
|
|
162
|
+
if (command instanceof File) {
|
|
163
|
+
throw new Error('The __conform__ key is reserved for special command and could not be used for file upload.');
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
var [name, action, json] = command.split('::');
|
|
167
|
+
var list = value;
|
|
168
|
+
|
|
169
|
+
for (var path of getPaths(name)) {
|
|
170
|
+
list = list[path];
|
|
171
|
+
|
|
172
|
+
if (typeof list === 'undefined') {
|
|
173
|
+
break;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (!Array.isArray(list)) {
|
|
178
|
+
throw new Error('');
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
switch (action) {
|
|
182
|
+
case 'prepend':
|
|
183
|
+
{
|
|
184
|
+
var initialValue = JSON.parse(json);
|
|
185
|
+
list.unshift(initialValue);
|
|
186
|
+
break;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
case 'append':
|
|
190
|
+
{
|
|
191
|
+
var _initialValue = JSON.parse(json);
|
|
192
|
+
|
|
193
|
+
list.push(_initialValue);
|
|
194
|
+
break;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
case 'remove':
|
|
198
|
+
var {
|
|
199
|
+
index
|
|
200
|
+
} = JSON.parse(json);
|
|
201
|
+
list.splice(index, 1);
|
|
202
|
+
break;
|
|
203
|
+
|
|
204
|
+
default:
|
|
205
|
+
throw new Error('Invalid action found; Only `prepend`, `append` and `remove` is accepted');
|
|
206
|
+
}
|
|
207
|
+
} catch (e) {
|
|
208
|
+
return {
|
|
209
|
+
state: 'rejected',
|
|
210
|
+
value,
|
|
211
|
+
error: {
|
|
212
|
+
__conform__: e instanceof Error ? e.message : 'Something went wrong'
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
return {
|
|
218
|
+
state: 'processed',
|
|
219
|
+
value,
|
|
220
|
+
error: null
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return {
|
|
225
|
+
state: 'accepted',
|
|
226
|
+
value
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
function getFieldElements(fieldset, key) {
|
|
230
|
+
var _fieldset$name;
|
|
231
|
+
|
|
232
|
+
var name = getName([(_fieldset$name = fieldset.name) !== null && _fieldset$name !== void 0 ? _fieldset$name : '', key]);
|
|
233
|
+
var item = fieldset.elements.namedItem(name);
|
|
234
|
+
var nodes = item instanceof RadioNodeList ? Array.from(item) : item !== null ? [item] : [];
|
|
235
|
+
return nodes.filter(isFieldElement);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
export { createControlButton, createFieldConfig, getFieldElements, getName, getPaths, isFieldElement, isFieldsetElement, parse, reportValidity, setFieldState, shouldSkipValidate, transform };
|
package/package.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@conform-to/dom",
|
|
3
|
+
"description": "A set of opinionated helpers built on top of the Constraint Validation API",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"version": "0.1.0",
|
|
6
|
+
"main": "index.js",
|
|
7
|
+
"module": "module/index.js",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/edmundhung/conform",
|
|
11
|
+
"directory": "packages/conform-dom"
|
|
12
|
+
},
|
|
13
|
+
"author": {
|
|
14
|
+
"name": "Edmund Hung",
|
|
15
|
+
"email": "me@edmund.dev",
|
|
16
|
+
"url": "https://edmund.dev"
|
|
17
|
+
},
|
|
18
|
+
"bugs": {
|
|
19
|
+
"url": "https://github.com/edmundhung/conform/issues"
|
|
20
|
+
},
|
|
21
|
+
"keywords": [
|
|
22
|
+
"constraint-validation",
|
|
23
|
+
"form",
|
|
24
|
+
"form-validation",
|
|
25
|
+
"validation",
|
|
26
|
+
"dom"
|
|
27
|
+
],
|
|
28
|
+
"sideEffects": false
|
|
29
|
+
}
|