@conform-to/dom 0.4.0-pre.2 → 0.4.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.
@@ -4,17 +4,14 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  function ownKeys(object, enumerableOnly) {
6
6
  var keys = Object.keys(object);
7
-
8
7
  if (Object.getOwnPropertySymbols) {
9
8
  var symbols = Object.getOwnPropertySymbols(object);
10
9
  enumerableOnly && (symbols = symbols.filter(function (sym) {
11
10
  return Object.getOwnPropertyDescriptor(object, sym).enumerable;
12
11
  })), keys.push.apply(keys, symbols);
13
12
  }
14
-
15
13
  return keys;
16
14
  }
17
-
18
15
  function _objectSpread2(target) {
19
16
  for (var i = 1; i < arguments.length; i++) {
20
17
  var source = null != arguments[i] ? arguments[i] : {};
@@ -24,10 +21,8 @@ function _objectSpread2(target) {
24
21
  Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
25
22
  });
26
23
  }
27
-
28
24
  return target;
29
25
  }
30
-
31
26
  function _defineProperty(obj, key, value) {
32
27
  if (key in obj) {
33
28
  Object.defineProperty(obj, key, {
@@ -39,7 +34,6 @@ function _defineProperty(obj, key, value) {
39
34
  } else {
40
35
  obj[key] = value;
41
36
  }
42
-
43
37
  return obj;
44
38
  }
45
39
 
package/index.d.ts CHANGED
@@ -23,18 +23,18 @@ export declare type FieldsetConstraint<Schema extends Record<string, any>> = {
23
23
  [Key in keyof Schema]?: FieldConstraint;
24
24
  };
25
25
  export declare type Submission<Schema = unknown> = {
26
- context: string;
26
+ type: string;
27
27
  intent?: string;
28
28
  value: FieldValue<Schema>;
29
29
  error: Array<[string, string]>;
30
30
  };
31
31
  export declare function isFieldElement(element: unknown): element is FieldElement;
32
+ export declare function getFormElements(form: HTMLFormElement): FieldElement[];
32
33
  export declare function getPaths(name: string): Array<string | number>;
33
34
  export declare function getFormData(form: HTMLFormElement, submitter?: HTMLInputElement | HTMLButtonElement | null): FormData;
34
35
  export declare function getName(paths: Array<string | number>): string;
35
- export declare function shouldValidate(submission: Submission, name: string): boolean;
36
- export declare function hasError(error: Array<[string, string]>, names?: string[]): boolean;
37
- export declare function getFormError(form: HTMLFormElement, getFieldError?: (field: FieldElement) => Array<[string, string]>): Array<[string, string]>;
36
+ export declare function shouldValidate(submission: Submission, name?: string): boolean;
37
+ export declare function hasError(error: Array<[string, string]>, name?: string): boolean;
38
38
  export declare function setFormError(form: HTMLFormElement, submission: Submission): void;
39
39
  export declare function setValue<T>(target: any, paths: Array<string | number>, valueFn: (prev?: T) => T): void;
40
40
  export declare function requestSubmit(form: HTMLFormElement, submitter?: HTMLButtonElement | HTMLInputElement): void;
package/index.js CHANGED
@@ -7,34 +7,30 @@ var _rollupPluginBabelHelpers = require('./_virtual/_rollupPluginBabelHelpers.js
7
7
  function isFieldElement(element) {
8
8
  return element instanceof Element && (element.tagName === 'INPUT' || element.tagName === 'SELECT' || element.tagName === 'TEXTAREA' || element.tagName === 'BUTTON');
9
9
  }
10
+ function getFormElements(form) {
11
+ return Array.from(form.elements).filter(isFieldElement);
12
+ }
10
13
  function getPaths(name) {
11
14
  var pattern = /(\w*)\[(\d+)\]/;
12
-
13
15
  if (!name) {
14
16
  return [];
15
17
  }
16
-
17
18
  return name.split('.').flatMap(key => {
18
19
  var matches = pattern.exec(key);
19
-
20
20
  if (!matches) {
21
21
  return key;
22
22
  }
23
-
24
23
  if (matches[1] === '') {
25
24
  return Number(matches[2]);
26
25
  }
27
-
28
26
  return [matches[1], Number(matches[2])];
29
27
  });
30
28
  }
31
29
  function getFormData(form, submitter) {
32
30
  var payload = new FormData(form);
33
-
34
31
  if (submitter !== null && submitter !== void 0 && submitter.name) {
35
32
  payload.append(submitter.name, submitter.value);
36
33
  }
37
-
38
34
  return payload;
39
35
  }
40
36
  function getName(paths) {
@@ -42,43 +38,26 @@ function getName(paths) {
42
38
  if (typeof path === 'number') {
43
39
  return "".concat(name, "[").concat(path, "]");
44
40
  }
45
-
46
41
  if (name === '' || path === '') {
47
42
  return [name, path].join('');
48
43
  }
49
-
50
44
  return [name, path].join('.');
51
45
  }, '');
52
46
  }
53
47
  function shouldValidate(submission, name) {
54
- return submission.context === 'submit' || submission.context === 'validate' && submission.intent === name;
48
+ return submission.type === 'submit' || submission.type === 'validate' && (typeof name === 'undefined' || submission.intent === name);
55
49
  }
56
- function hasError(error, names) {
50
+ function hasError(error, name) {
57
51
  return typeof error.find(_ref => {
58
52
  var [fieldName, message] = _ref;
59
- return (typeof names === 'undefined' || names.includes(fieldName)) && message !== '';
53
+ return (typeof name === 'undefined' || name === fieldName) && message !== '';
60
54
  }) !== 'undefined';
61
55
  }
62
- function getFormError(form, getFieldError) {
63
- var error = [];
64
-
65
- for (var element of form.elements) {
66
- if (isFieldElement(element) && element.willValidate) {
67
- var _getFieldError;
68
-
69
- error.push(...((_getFieldError = getFieldError === null || getFieldError === void 0 ? void 0 : getFieldError(element)) !== null && _getFieldError !== void 0 ? _getFieldError : [[element.name, element.validationMessage]]));
70
- }
71
- }
72
-
73
- return error;
74
- }
75
56
  function setFormError(form, submission) {
76
57
  var firstErrorByName = Object.fromEntries([...submission.error].reverse());
77
-
78
58
  for (var element of form.elements) {
79
59
  if (isFieldElement(element)) {
80
60
  var error = firstErrorByName[element.name];
81
-
82
61
  if (typeof error !== 'undefined' || shouldValidate(submission, element.name)) {
83
62
  element.setCustomValidity(error !== null && error !== void 0 ? error : '');
84
63
  }
@@ -90,10 +69,8 @@ function setValue(target, paths, valueFn) {
90
69
  var lastIndex = length - 1;
91
70
  var index = -1;
92
71
  var pointer = target;
93
-
94
72
  while (pointer != null && ++index < length) {
95
73
  var _pointer$key;
96
-
97
74
  var key = paths[index];
98
75
  var next = paths[index + 1];
99
76
  var newValue = index != lastIndex ? (_pointer$key = pointer[key]) !== null && _pointer$key !== void 0 ? _pointer$key : typeof next === 'number' ? [] : {} : valueFn(pointer[key]);
@@ -121,26 +98,21 @@ function requestValidate(form, field) {
121
98
  }
122
99
  function getFormElement(element) {
123
100
  var form = element instanceof HTMLFormElement ? element : element === null || element === void 0 ? void 0 : element.form;
124
-
125
101
  if (!form) {
126
102
  return null;
127
103
  }
128
-
129
104
  return form;
130
105
  }
131
106
  function focusFirstInvalidField(form) {
132
107
  var currentFocus = document.activeElement;
133
-
134
108
  if (!isFieldElement(currentFocus) || currentFocus.tagName !== 'BUTTON' || currentFocus.form !== form) {
135
109
  return;
136
110
  }
137
-
138
- for (var _field of form.elements) {
139
- if (isFieldElement(_field)) {
111
+ for (var field of form.elements) {
112
+ if (isFieldElement(field)) {
140
113
  // Focus on the first non button field
141
- if (!_field.validity.valid && _field.dataset.conformTouched && _field.tagName !== 'BUTTON') {
142
- _field.focus();
143
-
114
+ if (!field.validity.valid && field.dataset.conformTouched && field.tagName !== 'BUTTON') {
115
+ field.focus();
144
116
  break;
145
117
  }
146
118
  }
@@ -148,36 +120,30 @@ function focusFirstInvalidField(form) {
148
120
  }
149
121
  function getSubmissionType(name) {
150
122
  var prefix = 'conform/';
151
-
152
123
  if (!name.startsWith(prefix) || name.length <= prefix.length) {
153
124
  return null;
154
125
  }
155
-
156
126
  return name.slice(prefix.length);
157
127
  }
158
128
  function parse(payload) {
159
129
  var hasCommand = false;
160
130
  var submission = {
161
- context: 'submit',
131
+ type: 'submit',
162
132
  value: {},
163
133
  error: []
164
134
  };
165
-
166
135
  try {
167
136
  var _loop = function _loop(name, value) {
168
137
  var submissionType = getSubmissionType(name);
169
-
170
138
  if (submissionType) {
171
139
  if (typeof value !== 'string') {
172
140
  throw new Error('The conform command could not be used on a file input');
173
141
  }
174
-
175
142
  if (hasCommand) {
176
143
  throw new Error('The conform command could only be set on a button');
177
144
  }
178
-
179
145
  submission = _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, submission), {}, {
180
- context: submissionType,
146
+ type: submissionType,
181
147
  intent: value
182
148
  });
183
149
  hasCommand = true;
@@ -187,17 +153,14 @@ function parse(payload) {
187
153
  if (prev) {
188
154
  throw new Error('Entry with the same name is not supported');
189
155
  }
190
-
191
156
  return value;
192
157
  });
193
158
  }
194
159
  };
195
-
196
160
  for (var [name, value] of payload.entries()) {
197
161
  _loop(name, value);
198
162
  }
199
-
200
- switch (submission.context) {
163
+ switch (submission.type) {
201
164
  case 'list':
202
165
  submission = handleList(submission);
203
166
  break;
@@ -205,17 +168,14 @@ function parse(payload) {
205
168
  } catch (e) {
206
169
  submission.error.push(['', e instanceof Error ? e.message : 'Invalid payload received']);
207
170
  }
208
-
209
171
  return submission;
210
172
  }
211
173
  function parseListCommand(data) {
212
174
  try {
213
175
  var command = JSON.parse(data);
214
-
215
176
  if (typeof command.type !== 'string' || !['prepend', 'append', 'replace', 'remove', 'reorder'].includes(command.type)) {
216
177
  throw new Error('Unsupported list command type');
217
178
  }
218
-
219
179
  return command;
220
180
  } catch (error) {
221
181
  throw new Error("Invalid list command: \"".concat(data, "\"; ").concat(error));
@@ -228,47 +188,38 @@ function updateList(list, command) {
228
188
  list.unshift(command.payload.defaultValue);
229
189
  break;
230
190
  }
231
-
232
191
  case 'append':
233
192
  {
234
193
  list.push(command.payload.defaultValue);
235
194
  break;
236
195
  }
237
-
238
196
  case 'replace':
239
197
  {
240
198
  list.splice(command.payload.index, 1, command.payload.defaultValue);
241
199
  break;
242
200
  }
243
-
244
201
  case 'remove':
245
202
  list.splice(command.payload.index, 1);
246
203
  break;
247
-
248
204
  case 'reorder':
249
205
  list.splice(command.payload.to, 0, ...list.splice(command.payload.from, 1));
250
206
  break;
251
-
252
207
  default:
253
208
  throw new Error('Unknown list command received');
254
209
  }
255
-
256
210
  return list;
257
211
  }
258
212
  function handleList(submission) {
259
213
  var _submission$intent;
260
-
261
- if (submission.context !== 'list') {
214
+ if (submission.type !== 'list') {
262
215
  return submission;
263
216
  }
264
-
265
217
  var command = parseListCommand((_submission$intent = submission.intent) !== null && _submission$intent !== void 0 ? _submission$intent : '');
266
218
  var paths = getPaths(command.scope);
267
219
  setValue(submission.value, paths, list => {
268
220
  if (!Array.isArray(list)) {
269
221
  throw new Error('The list command can only be applied to a list');
270
222
  }
271
-
272
223
  return updateList(list, command);
273
224
  });
274
225
  return submission;
@@ -277,7 +228,7 @@ function handleList(submission) {
277
228
  exports.focusFirstInvalidField = focusFirstInvalidField;
278
229
  exports.getFormData = getFormData;
279
230
  exports.getFormElement = getFormElement;
280
- exports.getFormError = getFormError;
231
+ exports.getFormElements = getFormElements;
281
232
  exports.getName = getName;
282
233
  exports.getPaths = getPaths;
283
234
  exports.getSubmissionType = getSubmissionType;
@@ -1,16 +1,13 @@
1
1
  function ownKeys(object, enumerableOnly) {
2
2
  var keys = Object.keys(object);
3
-
4
3
  if (Object.getOwnPropertySymbols) {
5
4
  var symbols = Object.getOwnPropertySymbols(object);
6
5
  enumerableOnly && (symbols = symbols.filter(function (sym) {
7
6
  return Object.getOwnPropertyDescriptor(object, sym).enumerable;
8
7
  })), keys.push.apply(keys, symbols);
9
8
  }
10
-
11
9
  return keys;
12
10
  }
13
-
14
11
  function _objectSpread2(target) {
15
12
  for (var i = 1; i < arguments.length; i++) {
16
13
  var source = null != arguments[i] ? arguments[i] : {};
@@ -20,10 +17,8 @@ function _objectSpread2(target) {
20
17
  Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
21
18
  });
22
19
  }
23
-
24
20
  return target;
25
21
  }
26
-
27
22
  function _defineProperty(obj, key, value) {
28
23
  if (key in obj) {
29
24
  Object.defineProperty(obj, key, {
@@ -35,7 +30,6 @@ function _defineProperty(obj, key, value) {
35
30
  } else {
36
31
  obj[key] = value;
37
32
  }
38
-
39
33
  return obj;
40
34
  }
41
35
 
package/module/index.js CHANGED
@@ -3,34 +3,30 @@ import { objectSpread2 as _objectSpread2 } from './_virtual/_rollupPluginBabelHe
3
3
  function isFieldElement(element) {
4
4
  return element instanceof Element && (element.tagName === 'INPUT' || element.tagName === 'SELECT' || element.tagName === 'TEXTAREA' || element.tagName === 'BUTTON');
5
5
  }
6
+ function getFormElements(form) {
7
+ return Array.from(form.elements).filter(isFieldElement);
8
+ }
6
9
  function getPaths(name) {
7
10
  var pattern = /(\w*)\[(\d+)\]/;
8
-
9
11
  if (!name) {
10
12
  return [];
11
13
  }
12
-
13
14
  return name.split('.').flatMap(key => {
14
15
  var matches = pattern.exec(key);
15
-
16
16
  if (!matches) {
17
17
  return key;
18
18
  }
19
-
20
19
  if (matches[1] === '') {
21
20
  return Number(matches[2]);
22
21
  }
23
-
24
22
  return [matches[1], Number(matches[2])];
25
23
  });
26
24
  }
27
25
  function getFormData(form, submitter) {
28
26
  var payload = new FormData(form);
29
-
30
27
  if (submitter !== null && submitter !== void 0 && submitter.name) {
31
28
  payload.append(submitter.name, submitter.value);
32
29
  }
33
-
34
30
  return payload;
35
31
  }
36
32
  function getName(paths) {
@@ -38,43 +34,26 @@ function getName(paths) {
38
34
  if (typeof path === 'number') {
39
35
  return "".concat(name, "[").concat(path, "]");
40
36
  }
41
-
42
37
  if (name === '' || path === '') {
43
38
  return [name, path].join('');
44
39
  }
45
-
46
40
  return [name, path].join('.');
47
41
  }, '');
48
42
  }
49
43
  function shouldValidate(submission, name) {
50
- return submission.context === 'submit' || submission.context === 'validate' && submission.intent === name;
44
+ return submission.type === 'submit' || submission.type === 'validate' && (typeof name === 'undefined' || submission.intent === name);
51
45
  }
52
- function hasError(error, names) {
46
+ function hasError(error, name) {
53
47
  return typeof error.find(_ref => {
54
48
  var [fieldName, message] = _ref;
55
- return (typeof names === 'undefined' || names.includes(fieldName)) && message !== '';
49
+ return (typeof name === 'undefined' || name === fieldName) && message !== '';
56
50
  }) !== 'undefined';
57
51
  }
58
- function getFormError(form, getFieldError) {
59
- var error = [];
60
-
61
- for (var element of form.elements) {
62
- if (isFieldElement(element) && element.willValidate) {
63
- var _getFieldError;
64
-
65
- error.push(...((_getFieldError = getFieldError === null || getFieldError === void 0 ? void 0 : getFieldError(element)) !== null && _getFieldError !== void 0 ? _getFieldError : [[element.name, element.validationMessage]]));
66
- }
67
- }
68
-
69
- return error;
70
- }
71
52
  function setFormError(form, submission) {
72
53
  var firstErrorByName = Object.fromEntries([...submission.error].reverse());
73
-
74
54
  for (var element of form.elements) {
75
55
  if (isFieldElement(element)) {
76
56
  var error = firstErrorByName[element.name];
77
-
78
57
  if (typeof error !== 'undefined' || shouldValidate(submission, element.name)) {
79
58
  element.setCustomValidity(error !== null && error !== void 0 ? error : '');
80
59
  }
@@ -86,10 +65,8 @@ function setValue(target, paths, valueFn) {
86
65
  var lastIndex = length - 1;
87
66
  var index = -1;
88
67
  var pointer = target;
89
-
90
68
  while (pointer != null && ++index < length) {
91
69
  var _pointer$key;
92
-
93
70
  var key = paths[index];
94
71
  var next = paths[index + 1];
95
72
  var newValue = index != lastIndex ? (_pointer$key = pointer[key]) !== null && _pointer$key !== void 0 ? _pointer$key : typeof next === 'number' ? [] : {} : valueFn(pointer[key]);
@@ -117,26 +94,21 @@ function requestValidate(form, field) {
117
94
  }
118
95
  function getFormElement(element) {
119
96
  var form = element instanceof HTMLFormElement ? element : element === null || element === void 0 ? void 0 : element.form;
120
-
121
97
  if (!form) {
122
98
  return null;
123
99
  }
124
-
125
100
  return form;
126
101
  }
127
102
  function focusFirstInvalidField(form) {
128
103
  var currentFocus = document.activeElement;
129
-
130
104
  if (!isFieldElement(currentFocus) || currentFocus.tagName !== 'BUTTON' || currentFocus.form !== form) {
131
105
  return;
132
106
  }
133
-
134
- for (var _field of form.elements) {
135
- if (isFieldElement(_field)) {
107
+ for (var field of form.elements) {
108
+ if (isFieldElement(field)) {
136
109
  // Focus on the first non button field
137
- if (!_field.validity.valid && _field.dataset.conformTouched && _field.tagName !== 'BUTTON') {
138
- _field.focus();
139
-
110
+ if (!field.validity.valid && field.dataset.conformTouched && field.tagName !== 'BUTTON') {
111
+ field.focus();
140
112
  break;
141
113
  }
142
114
  }
@@ -144,36 +116,30 @@ function focusFirstInvalidField(form) {
144
116
  }
145
117
  function getSubmissionType(name) {
146
118
  var prefix = 'conform/';
147
-
148
119
  if (!name.startsWith(prefix) || name.length <= prefix.length) {
149
120
  return null;
150
121
  }
151
-
152
122
  return name.slice(prefix.length);
153
123
  }
154
124
  function parse(payload) {
155
125
  var hasCommand = false;
156
126
  var submission = {
157
- context: 'submit',
127
+ type: 'submit',
158
128
  value: {},
159
129
  error: []
160
130
  };
161
-
162
131
  try {
163
132
  var _loop = function _loop(name, value) {
164
133
  var submissionType = getSubmissionType(name);
165
-
166
134
  if (submissionType) {
167
135
  if (typeof value !== 'string') {
168
136
  throw new Error('The conform command could not be used on a file input');
169
137
  }
170
-
171
138
  if (hasCommand) {
172
139
  throw new Error('The conform command could only be set on a button');
173
140
  }
174
-
175
141
  submission = _objectSpread2(_objectSpread2({}, submission), {}, {
176
- context: submissionType,
142
+ type: submissionType,
177
143
  intent: value
178
144
  });
179
145
  hasCommand = true;
@@ -183,17 +149,14 @@ function parse(payload) {
183
149
  if (prev) {
184
150
  throw new Error('Entry with the same name is not supported');
185
151
  }
186
-
187
152
  return value;
188
153
  });
189
154
  }
190
155
  };
191
-
192
156
  for (var [name, value] of payload.entries()) {
193
157
  _loop(name, value);
194
158
  }
195
-
196
- switch (submission.context) {
159
+ switch (submission.type) {
197
160
  case 'list':
198
161
  submission = handleList(submission);
199
162
  break;
@@ -201,17 +164,14 @@ function parse(payload) {
201
164
  } catch (e) {
202
165
  submission.error.push(['', e instanceof Error ? e.message : 'Invalid payload received']);
203
166
  }
204
-
205
167
  return submission;
206
168
  }
207
169
  function parseListCommand(data) {
208
170
  try {
209
171
  var command = JSON.parse(data);
210
-
211
172
  if (typeof command.type !== 'string' || !['prepend', 'append', 'replace', 'remove', 'reorder'].includes(command.type)) {
212
173
  throw new Error('Unsupported list command type');
213
174
  }
214
-
215
175
  return command;
216
176
  } catch (error) {
217
177
  throw new Error("Invalid list command: \"".concat(data, "\"; ").concat(error));
@@ -224,50 +184,41 @@ function updateList(list, command) {
224
184
  list.unshift(command.payload.defaultValue);
225
185
  break;
226
186
  }
227
-
228
187
  case 'append':
229
188
  {
230
189
  list.push(command.payload.defaultValue);
231
190
  break;
232
191
  }
233
-
234
192
  case 'replace':
235
193
  {
236
194
  list.splice(command.payload.index, 1, command.payload.defaultValue);
237
195
  break;
238
196
  }
239
-
240
197
  case 'remove':
241
198
  list.splice(command.payload.index, 1);
242
199
  break;
243
-
244
200
  case 'reorder':
245
201
  list.splice(command.payload.to, 0, ...list.splice(command.payload.from, 1));
246
202
  break;
247
-
248
203
  default:
249
204
  throw new Error('Unknown list command received');
250
205
  }
251
-
252
206
  return list;
253
207
  }
254
208
  function handleList(submission) {
255
209
  var _submission$intent;
256
-
257
- if (submission.context !== 'list') {
210
+ if (submission.type !== 'list') {
258
211
  return submission;
259
212
  }
260
-
261
213
  var command = parseListCommand((_submission$intent = submission.intent) !== null && _submission$intent !== void 0 ? _submission$intent : '');
262
214
  var paths = getPaths(command.scope);
263
215
  setValue(submission.value, paths, list => {
264
216
  if (!Array.isArray(list)) {
265
217
  throw new Error('The list command can only be applied to a list');
266
218
  }
267
-
268
219
  return updateList(list, command);
269
220
  });
270
221
  return submission;
271
222
  }
272
223
 
273
- export { focusFirstInvalidField, getFormData, getFormElement, getFormError, getName, getPaths, getSubmissionType, handleList, hasError, isFieldElement, parse, parseListCommand, requestSubmit, requestValidate, setFormError, setValue, shouldValidate, updateList };
224
+ export { focusFirstInvalidField, getFormData, getFormElement, getFormElements, getName, getPaths, getSubmissionType, handleList, hasError, isFieldElement, parse, parseListCommand, requestSubmit, requestValidate, setFormError, setValue, shouldValidate, updateList };
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@conform-to/dom",
3
3
  "description": "A set of opinionated helpers built on top of the Constraint Validation API",
4
4
  "license": "MIT",
5
- "version": "0.4.0-pre.2",
5
+ "version": "0.4.0",
6
6
  "main": "index.js",
7
7
  "module": "module/index.js",
8
8
  "repository": {