@conform-to/react 0.5.0 → 0.6.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.md +33 -58
- package/_virtual/_rollupPluginBabelHelpers.js +17 -0
- package/helpers.d.ts +17 -10
- package/helpers.js +47 -5
- package/hooks.d.ts +30 -32
- package/hooks.js +254 -169
- package/index.d.ts +1 -1
- package/index.js +7 -11
- package/module/_virtual/_rollupPluginBabelHelpers.js +16 -1
- package/module/helpers.js +39 -6
- package/module/hooks.js +256 -171
- package/module/index.js +2 -2
- package/package.json +2 -2
package/hooks.js
CHANGED
|
@@ -5,7 +5,6 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
5
5
|
var _rollupPluginBabelHelpers = require('./_virtual/_rollupPluginBabelHelpers.js');
|
|
6
6
|
var dom = require('@conform-to/dom');
|
|
7
7
|
var react = require('react');
|
|
8
|
-
var helpers = require('./helpers.js');
|
|
9
8
|
|
|
10
9
|
/**
|
|
11
10
|
* Returns properties required to hook into form events.
|
|
@@ -14,16 +13,17 @@ var helpers = require('./helpers.js');
|
|
|
14
13
|
* @see https://conform.guide/api/react#useform
|
|
15
14
|
*/
|
|
16
15
|
function useForm() {
|
|
16
|
+
var _config$state;
|
|
17
17
|
var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
18
18
|
var configRef = react.useRef(config);
|
|
19
19
|
var ref = react.useRef(null);
|
|
20
|
+
var [lastSubmission, setLastSubmission] = react.useState((_config$state = config.state) !== null && _config$state !== void 0 ? _config$state : null);
|
|
20
21
|
var [error, setError] = react.useState(() => {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
return message !== null && message !== void 0 ? message : '';
|
|
22
|
+
if (!config.state) {
|
|
23
|
+
return '';
|
|
24
|
+
}
|
|
25
|
+
var message = config.state.error[''];
|
|
26
|
+
return dom.getValidationMessage(message);
|
|
27
27
|
});
|
|
28
28
|
var [uncontrolledState, setUncontrolledState] = react.useState(() => {
|
|
29
29
|
var submission = config.state;
|
|
@@ -33,11 +33,14 @@ function useForm() {
|
|
|
33
33
|
};
|
|
34
34
|
}
|
|
35
35
|
return {
|
|
36
|
-
defaultValue: submission.
|
|
37
|
-
initialError: submission.error.
|
|
38
|
-
var [name] =
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
defaultValue: submission.payload,
|
|
37
|
+
initialError: Object.entries(submission.error).reduce((result, _ref) => {
|
|
38
|
+
var [name, message] = _ref;
|
|
39
|
+
if (name !== '' && dom.shouldValidate(submission.intent, name)) {
|
|
40
|
+
result[name] = message;
|
|
41
|
+
}
|
|
42
|
+
return result;
|
|
43
|
+
}, {})
|
|
41
44
|
};
|
|
42
45
|
});
|
|
43
46
|
var fieldsetConfig = _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, uncontrolledState), {}, {
|
|
@@ -54,11 +57,25 @@ function useForm() {
|
|
|
54
57
|
}, []);
|
|
55
58
|
react.useEffect(() => {
|
|
56
59
|
var form = ref.current;
|
|
57
|
-
|
|
60
|
+
var submission = config.state;
|
|
61
|
+
if (!form || !submission) {
|
|
58
62
|
return;
|
|
59
63
|
}
|
|
60
|
-
dom.
|
|
64
|
+
var listCommand = dom.parseListCommand(submission.intent);
|
|
65
|
+
if (listCommand) {
|
|
66
|
+
form.dispatchEvent(new CustomEvent('conform/list', {
|
|
67
|
+
detail: submission.intent
|
|
68
|
+
}));
|
|
69
|
+
}
|
|
70
|
+
setLastSubmission(submission);
|
|
61
71
|
}, [config.state]);
|
|
72
|
+
react.useEffect(() => {
|
|
73
|
+
var form = ref.current;
|
|
74
|
+
if (!form || !lastSubmission) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
dom.reportSubmission(ref.current, lastSubmission);
|
|
78
|
+
}, [lastSubmission]);
|
|
62
79
|
react.useEffect(() => {
|
|
63
80
|
// Revalidate the form when input value is changed
|
|
64
81
|
var handleInput = event => {
|
|
@@ -69,7 +86,7 @@ function useForm() {
|
|
|
69
86
|
return;
|
|
70
87
|
}
|
|
71
88
|
if (field.dataset.conformTouched || formConfig.initialReport === 'onChange') {
|
|
72
|
-
dom.
|
|
89
|
+
dom.requestIntent(form, dom.validate(field.name));
|
|
73
90
|
}
|
|
74
91
|
};
|
|
75
92
|
var handleBlur = event => {
|
|
@@ -80,7 +97,7 @@ function useForm() {
|
|
|
80
97
|
return;
|
|
81
98
|
}
|
|
82
99
|
if (formConfig.initialReport === 'onBlur' && !field.dataset.conformTouched) {
|
|
83
|
-
dom.
|
|
100
|
+
dom.requestIntent(form, dom.validate(field.name));
|
|
84
101
|
}
|
|
85
102
|
};
|
|
86
103
|
var handleInvalid = event => {
|
|
@@ -111,8 +128,7 @@ function useForm() {
|
|
|
111
128
|
}
|
|
112
129
|
setError('');
|
|
113
130
|
setUncontrolledState({
|
|
114
|
-
defaultValue: formConfig.defaultValue
|
|
115
|
-
initialError: []
|
|
131
|
+
defaultValue: formConfig.defaultValue
|
|
116
132
|
});
|
|
117
133
|
};
|
|
118
134
|
|
|
@@ -145,53 +161,38 @@ function useForm() {
|
|
|
145
161
|
var form = event.currentTarget;
|
|
146
162
|
var nativeEvent = event.nativeEvent;
|
|
147
163
|
var submitter = nativeEvent.submitter;
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* It checks defaultPrevented to confirm if the submission is intentional
|
|
151
|
-
* This is utilized by `useFieldList` to modify the list state when the submit
|
|
152
|
-
* event is captured and revalidate the form with new fields without triggering
|
|
153
|
-
* a form submission at the same time.
|
|
154
|
-
*/
|
|
155
164
|
if (event.defaultPrevented) {
|
|
156
165
|
return;
|
|
157
166
|
}
|
|
158
167
|
try {
|
|
159
|
-
var
|
|
168
|
+
var _config$onValidate;
|
|
160
169
|
var formData = dom.getFormData(form, submitter);
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
element.setCustomValidity('');
|
|
179
|
-
submission.error.push([element.name, element.validationMessage]);
|
|
180
|
-
}
|
|
181
|
-
}
|
|
170
|
+
var getSubmission = (_config$onValidate = config.onValidate) !== null && _config$onValidate !== void 0 ? _config$onValidate : context => dom.parse(context.formData);
|
|
171
|
+
var submission = getSubmission({
|
|
172
|
+
form,
|
|
173
|
+
formData
|
|
174
|
+
});
|
|
175
|
+
if (!config.noValidate && !(submitter !== null && submitter !== void 0 && submitter.formNoValidate) && Object.entries(submission.error).some(_ref2 => {
|
|
176
|
+
var [, message] = _ref2;
|
|
177
|
+
return message !== '' && ![].concat(message).includes(dom.VALIDATION_UNDEFINED);
|
|
178
|
+
}) || typeof config.onValidate !== 'undefined' && (submission.intent.startsWith('validate') || submission.intent.startsWith('list')) && Object.entries(submission.error).every(_ref3 => {
|
|
179
|
+
var [, message] = _ref3;
|
|
180
|
+
return ![].concat(message).includes(dom.VALIDATION_UNDEFINED);
|
|
181
|
+
})) {
|
|
182
|
+
var listCommand = dom.parseListCommand(submission.intent);
|
|
183
|
+
if (listCommand) {
|
|
184
|
+
form.dispatchEvent(new CustomEvent('conform/list', {
|
|
185
|
+
detail: submission.intent
|
|
186
|
+
}));
|
|
182
187
|
}
|
|
183
|
-
|
|
184
|
-
if (!config.noValidate && !(submitter !== null && submitter !== void 0 && submitter.formNoValidate) && dom.hasError(submission.error) || submission.type === 'validate' && config.mode !== 'server-validation') {
|
|
188
|
+
setLastSubmission(submission);
|
|
185
189
|
event.preventDefault();
|
|
186
190
|
} else {
|
|
187
191
|
var _config$onSubmit;
|
|
188
|
-
(_config$onSubmit = config.onSubmit) === null || _config$onSubmit === void 0 ? void 0 : _config$onSubmit.call(config, event, {
|
|
192
|
+
(_config$onSubmit = config.onSubmit) === null || _config$onSubmit === void 0 ? void 0 : _config$onSubmit.call(config, event, _rollupPluginBabelHelpers.objectSpread2({
|
|
189
193
|
formData,
|
|
190
194
|
submission
|
|
191
|
-
});
|
|
192
|
-
}
|
|
193
|
-
if (event.defaultPrevented) {
|
|
194
|
-
dom.reportSubmission(form, submission);
|
|
195
|
+
}, dom.getFormAttributes(form, submitter)));
|
|
195
196
|
}
|
|
196
197
|
} catch (e) {
|
|
197
198
|
console.warn(e);
|
|
@@ -214,18 +215,14 @@ function useFieldset(ref, config) {
|
|
|
214
215
|
() => {
|
|
215
216
|
var _config$defaultValue;
|
|
216
217
|
var initialError = {};
|
|
217
|
-
for (var [name, message] of (_config$initialError = config === null || config === void 0 ? void 0 : config.initialError) !== null && _config$initialError !== void 0 ? _config$initialError :
|
|
218
|
+
for (var [name, message] of Object.entries((_config$initialError = config === null || config === void 0 ? void 0 : config.initialError) !== null && _config$initialError !== void 0 ? _config$initialError : {})) {
|
|
218
219
|
var _config$initialError;
|
|
219
220
|
var [key, ...paths] = dom.getPaths(name);
|
|
220
221
|
if (typeof key === 'string') {
|
|
221
|
-
var _initialError$key;
|
|
222
222
|
var scopedName = dom.getName(paths);
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
} else {
|
|
227
|
-
initialError[key] = [...entries, [scopedName, message]];
|
|
228
|
-
}
|
|
223
|
+
initialError[key] = _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, initialError[key]), {}, {
|
|
224
|
+
[scopedName]: message
|
|
225
|
+
});
|
|
229
226
|
}
|
|
230
227
|
}
|
|
231
228
|
return {
|
|
@@ -235,12 +232,8 @@ function useFieldset(ref, config) {
|
|
|
235
232
|
});
|
|
236
233
|
var [error, setError] = react.useState(() => {
|
|
237
234
|
var result = {};
|
|
238
|
-
for (var [key,
|
|
239
|
-
|
|
240
|
-
var [name, message] = (_entries$ = entries === null || entries === void 0 ? void 0 : entries[0]) !== null && _entries$ !== void 0 ? _entries$ : [];
|
|
241
|
-
if (name === '') {
|
|
242
|
-
result[key] = message !== null && message !== void 0 ? message : '';
|
|
243
|
-
}
|
|
235
|
+
for (var [key, _error] of Object.entries(uncontrolledState.initialError)) {
|
|
236
|
+
result[key] = dom.getErrors(dom.getValidationMessage(_error === null || _error === void 0 ? void 0 : _error['']));
|
|
244
237
|
}
|
|
245
238
|
return result;
|
|
246
239
|
});
|
|
@@ -266,13 +259,12 @@ function useFieldset(ref, config) {
|
|
|
266
259
|
field.setAttribute('aria-invalid', field.validationMessage !== '' ? 'true' : 'false');
|
|
267
260
|
}
|
|
268
261
|
setError(prev => {
|
|
269
|
-
var
|
|
270
|
-
var prevMessage = (_prev$key = prev === null || prev === void 0 ? void 0 : prev[key]) !== null && _prev$key !== void 0 ? _prev$key : '';
|
|
262
|
+
var prevMessage = dom.getValidationMessage(prev === null || prev === void 0 ? void 0 : prev[key]);
|
|
271
263
|
if (prevMessage === field.validationMessage) {
|
|
272
264
|
return prev;
|
|
273
265
|
}
|
|
274
266
|
return _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, prev), {}, {
|
|
275
|
-
[key]: field.validationMessage
|
|
267
|
+
[key]: dom.getErrors(field.validationMessage)
|
|
276
268
|
});
|
|
277
269
|
});
|
|
278
270
|
}
|
|
@@ -310,19 +302,21 @@ function useFieldset(ref, config) {
|
|
|
310
302
|
*/
|
|
311
303
|
return new Proxy({}, {
|
|
312
304
|
get(_target, key) {
|
|
313
|
-
var _fieldsetConfig$const
|
|
305
|
+
var _fieldsetConfig$const;
|
|
314
306
|
if (typeof key !== 'string') {
|
|
315
307
|
return;
|
|
316
308
|
}
|
|
317
309
|
var fieldsetConfig = config !== null && config !== void 0 ? config : {};
|
|
318
310
|
var constraint = (_fieldsetConfig$const = fieldsetConfig.constraint) === null || _fieldsetConfig$const === void 0 ? void 0 : _fieldsetConfig$const[key];
|
|
311
|
+
var errors = error === null || error === void 0 ? void 0 : error[key];
|
|
319
312
|
var field = {
|
|
320
313
|
config: _rollupPluginBabelHelpers.objectSpread2({
|
|
321
314
|
name: fieldsetConfig.name ? "".concat(fieldsetConfig.name, ".").concat(key) : key,
|
|
322
315
|
defaultValue: uncontrolledState.defaultValue[key],
|
|
323
316
|
initialError: uncontrolledState.initialError[key]
|
|
324
317
|
}, constraint),
|
|
325
|
-
error:
|
|
318
|
+
error: errors === null || errors === void 0 ? void 0 : errors[0],
|
|
319
|
+
errors
|
|
326
320
|
};
|
|
327
321
|
if (fieldsetConfig.form) {
|
|
328
322
|
field.config.form = fieldsetConfig.form;
|
|
@@ -345,18 +339,14 @@ function useFieldList(ref, config) {
|
|
|
345
339
|
var [uncontrolledState, setUncontrolledState] = react.useState(() => {
|
|
346
340
|
var _config$defaultValue2;
|
|
347
341
|
var initialError = [];
|
|
348
|
-
for (var [name, message] of (_config$initialError2 = config === null || config === void 0 ? void 0 : config.initialError) !== null && _config$initialError2 !== void 0 ? _config$initialError2 :
|
|
342
|
+
for (var [name, message] of Object.entries((_config$initialError2 = config === null || config === void 0 ? void 0 : config.initialError) !== null && _config$initialError2 !== void 0 ? _config$initialError2 : {})) {
|
|
349
343
|
var _config$initialError2;
|
|
350
344
|
var [index, ...paths] = dom.getPaths(name);
|
|
351
345
|
if (typeof index === 'number') {
|
|
352
|
-
var _initialError$index;
|
|
353
346
|
var scopedName = dom.getName(paths);
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
} else {
|
|
358
|
-
initialError[index] = [..._entries, [scopedName, message]];
|
|
359
|
-
}
|
|
347
|
+
initialError[index] = _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, initialError[index]), {}, {
|
|
348
|
+
[scopedName]: message
|
|
349
|
+
});
|
|
360
350
|
}
|
|
361
351
|
}
|
|
362
352
|
return {
|
|
@@ -364,7 +354,7 @@ function useFieldList(ref, config) {
|
|
|
364
354
|
initialError
|
|
365
355
|
};
|
|
366
356
|
});
|
|
367
|
-
var [error, setError] = react.useState(() => uncontrolledState.initialError.map(error => error === null || error === void 0 ? void 0 : error[
|
|
357
|
+
var [error, setError] = react.useState(() => uncontrolledState.initialError.map(error => dom.getErrors(dom.getValidationMessage(error === null || error === void 0 ? void 0 : error['']))));
|
|
368
358
|
var [entries, setEntries] = react.useState(() => {
|
|
369
359
|
var _config$defaultValue3;
|
|
370
360
|
return Object.entries((_config$defaultValue3 = config.defaultValue) !== null && _config$defaultValue3 !== void 0 ? _config$defaultValue3 : [undefined]);
|
|
@@ -387,24 +377,23 @@ function useFieldList(ref, config) {
|
|
|
387
377
|
if (typeof index === 'number' && paths.length === 0) {
|
|
388
378
|
if (field.dataset.conformTouched) {
|
|
389
379
|
setError(prev => {
|
|
390
|
-
var
|
|
391
|
-
var prevMessage = (_prev$index = prev === null || prev === void 0 ? void 0 : prev[index]) !== null && _prev$index !== void 0 ? _prev$index : '';
|
|
380
|
+
var prevMessage = dom.getValidationMessage(prev === null || prev === void 0 ? void 0 : prev[index]);
|
|
392
381
|
if (prevMessage === field.validationMessage) {
|
|
393
382
|
return prev;
|
|
394
383
|
}
|
|
395
|
-
return [...prev.slice(0, index), field.validationMessage, ...prev.slice(index + 1)];
|
|
384
|
+
return [...prev.slice(0, index), dom.getErrors(field.validationMessage), ...prev.slice(index + 1)];
|
|
396
385
|
});
|
|
397
386
|
}
|
|
398
387
|
event.preventDefault();
|
|
399
388
|
}
|
|
400
389
|
};
|
|
401
|
-
var
|
|
390
|
+
var listHandler = event => {
|
|
402
391
|
var form = dom.getFormElement(ref.current);
|
|
403
|
-
if (!form || event.target !== form
|
|
392
|
+
if (!form || event.target !== form) {
|
|
404
393
|
return;
|
|
405
394
|
}
|
|
406
|
-
var command = dom.parseListCommand(event.
|
|
407
|
-
if (command.scope !== configRef.current.name) {
|
|
395
|
+
var command = dom.parseListCommand(event.detail);
|
|
396
|
+
if ((command === null || command === void 0 ? void 0 : command.scope) !== configRef.current.name) {
|
|
408
397
|
// Ensure the scope of the listener are limited to specific field name
|
|
409
398
|
return;
|
|
410
399
|
}
|
|
@@ -415,7 +404,9 @@ function useFieldList(ref, config) {
|
|
|
415
404
|
case 'replace':
|
|
416
405
|
return dom.updateList([...(entries !== null && entries !== void 0 ? entries : [])], _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, command), {}, {
|
|
417
406
|
payload: _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, command.payload), {}, {
|
|
418
|
-
defaultValue: ["".concat(Date.now()),
|
|
407
|
+
defaultValue: ["".concat(Date.now()),
|
|
408
|
+
// @ts-expect-error unknown type as it is sent through network
|
|
409
|
+
command.payload.defaultValue]
|
|
419
410
|
})
|
|
420
411
|
}));
|
|
421
412
|
default:
|
|
@@ -440,7 +431,6 @@ function useFieldList(ref, config) {
|
|
|
440
431
|
}
|
|
441
432
|
}
|
|
442
433
|
});
|
|
443
|
-
event.preventDefault();
|
|
444
434
|
};
|
|
445
435
|
var resetHandler = event => {
|
|
446
436
|
var _fieldConfig$defaultV, _fieldConfig$defaultV2;
|
|
@@ -456,17 +446,21 @@ function useFieldList(ref, config) {
|
|
|
456
446
|
setEntries(Object.entries((_fieldConfig$defaultV2 = fieldConfig.defaultValue) !== null && _fieldConfig$defaultV2 !== void 0 ? _fieldConfig$defaultV2 : [undefined]));
|
|
457
447
|
setError([]);
|
|
458
448
|
};
|
|
459
|
-
|
|
449
|
+
|
|
450
|
+
// @ts-expect-error Custom event: conform/list
|
|
451
|
+
document.addEventListener('conform/list', listHandler, true);
|
|
460
452
|
document.addEventListener('invalid', invalidHandler, true);
|
|
461
453
|
document.addEventListener('reset', resetHandler);
|
|
462
454
|
return () => {
|
|
463
|
-
|
|
455
|
+
// @ts-expect-error Custom event: conform/list
|
|
456
|
+
document.removeEventListener('conform/list', listHandler, true);
|
|
464
457
|
document.removeEventListener('invalid', invalidHandler, true);
|
|
465
458
|
document.removeEventListener('reset', resetHandler);
|
|
466
459
|
};
|
|
467
460
|
}, [ref]);
|
|
468
|
-
return entries.map((
|
|
469
|
-
var [key, defaultValue] =
|
|
461
|
+
return entries.map((_ref4, index) => {
|
|
462
|
+
var [key, defaultValue] = _ref4;
|
|
463
|
+
var errors = error[index];
|
|
470
464
|
var fieldConfig = {
|
|
471
465
|
name: "".concat(config.name, "[").concat(index, "]"),
|
|
472
466
|
defaultValue: defaultValue !== null && defaultValue !== void 0 ? defaultValue : uncontrolledState.defaultValue[index],
|
|
@@ -479,98 +473,189 @@ function useFieldList(ref, config) {
|
|
|
479
473
|
}
|
|
480
474
|
return {
|
|
481
475
|
key,
|
|
482
|
-
error:
|
|
476
|
+
error: errors === null || errors === void 0 ? void 0 : errors[0],
|
|
477
|
+
errors,
|
|
483
478
|
config: fieldConfig
|
|
484
479
|
};
|
|
485
480
|
});
|
|
486
481
|
}
|
|
482
|
+
|
|
487
483
|
/**
|
|
488
|
-
*
|
|
489
|
-
*
|
|
490
|
-
*
|
|
491
|
-
*
|
|
492
|
-
* @see https://conform.guide/api/react#usecontrolledinput
|
|
484
|
+
* Triggering react custom change event
|
|
485
|
+
* Solution based on dom-testing-library
|
|
486
|
+
* @see https://github.com/facebook/react/issues/10135#issuecomment-401496776
|
|
487
|
+
* @see https://github.com/testing-library/dom-testing-library/blob/main/src/events.js#L104-L123
|
|
493
488
|
*/
|
|
494
|
-
function
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
var
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
var
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
489
|
+
function setNativeValue(element, value) {
|
|
490
|
+
if (element.value === value) {
|
|
491
|
+
// It will not trigger a change event if `element.value` is the same as the set value
|
|
492
|
+
return;
|
|
493
|
+
}
|
|
494
|
+
var {
|
|
495
|
+
set: valueSetter
|
|
496
|
+
} = Object.getOwnPropertyDescriptor(element, 'value') || {};
|
|
497
|
+
var prototype = Object.getPrototypeOf(element);
|
|
498
|
+
var {
|
|
499
|
+
set: prototypeValueSetter
|
|
500
|
+
} = Object.getOwnPropertyDescriptor(prototype, 'value') || {};
|
|
501
|
+
if (prototypeValueSetter && valueSetter !== prototypeValueSetter) {
|
|
502
|
+
prototypeValueSetter.call(element, value);
|
|
503
|
+
} else {
|
|
504
|
+
if (valueSetter) {
|
|
505
|
+
valueSetter.call(element, value);
|
|
506
|
+
} else {
|
|
507
|
+
throw new Error('The given element does not have a value setter');
|
|
507
508
|
}
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
var
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
react.useEffect(() => {
|
|
525
|
-
configRef.current = config;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
/**
|
|
513
|
+
* useLayoutEffect is client-only.
|
|
514
|
+
* This basically makes it a no-op on server
|
|
515
|
+
*/
|
|
516
|
+
var useSafeLayoutEffect = typeof document === 'undefined' ? react.useEffect : react.useLayoutEffect;
|
|
517
|
+
function useInputEvent(options) {
|
|
518
|
+
var ref = react.useRef(null);
|
|
519
|
+
var optionsRef = react.useRef(options);
|
|
520
|
+
var changeDispatched = react.useRef(false);
|
|
521
|
+
var focusDispatched = react.useRef(false);
|
|
522
|
+
var blurDispatched = react.useRef(false);
|
|
523
|
+
useSafeLayoutEffect(() => {
|
|
524
|
+
optionsRef.current = options;
|
|
526
525
|
});
|
|
527
|
-
|
|
526
|
+
useSafeLayoutEffect(() => {
|
|
527
|
+
var getInputElement = () => {
|
|
528
|
+
var _optionsRef$current$g, _optionsRef$current, _optionsRef$current$g2;
|
|
529
|
+
return (_optionsRef$current$g = (_optionsRef$current = optionsRef.current) === null || _optionsRef$current === void 0 ? void 0 : (_optionsRef$current$g2 = _optionsRef$current.getElement) === null || _optionsRef$current$g2 === void 0 ? void 0 : _optionsRef$current$g2.call(_optionsRef$current, ref.current)) !== null && _optionsRef$current$g !== void 0 ? _optionsRef$current$g : ref.current;
|
|
530
|
+
};
|
|
531
|
+
var inputHandler = event => {
|
|
532
|
+
var input = getInputElement();
|
|
533
|
+
if (input && event.target === input) {
|
|
534
|
+
changeDispatched.current = true;
|
|
535
|
+
}
|
|
536
|
+
};
|
|
537
|
+
var focusHandler = event => {
|
|
538
|
+
var input = getInputElement();
|
|
539
|
+
if (input && event.target === input) {
|
|
540
|
+
focusDispatched.current = true;
|
|
541
|
+
}
|
|
542
|
+
};
|
|
543
|
+
var blurHandler = event => {
|
|
544
|
+
var input = getInputElement();
|
|
545
|
+
if (input && event.target === input) {
|
|
546
|
+
blurDispatched.current = true;
|
|
547
|
+
}
|
|
548
|
+
};
|
|
549
|
+
var submitHandler = event => {
|
|
550
|
+
var input = getInputElement();
|
|
551
|
+
if (input !== null && input !== void 0 && input.form && event.target === input.form) {
|
|
552
|
+
var _optionsRef$current2, _optionsRef$current2$;
|
|
553
|
+
(_optionsRef$current2 = optionsRef.current) === null || _optionsRef$current2 === void 0 ? void 0 : (_optionsRef$current2$ = _optionsRef$current2.onSubmit) === null || _optionsRef$current2$ === void 0 ? void 0 : _optionsRef$current2$.call(_optionsRef$current2, event);
|
|
554
|
+
}
|
|
555
|
+
};
|
|
528
556
|
var resetHandler = event => {
|
|
529
|
-
var
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
557
|
+
var input = getInputElement();
|
|
558
|
+
if (input !== null && input !== void 0 && input.form && event.target === input.form) {
|
|
559
|
+
var _optionsRef$current3, _optionsRef$current3$;
|
|
560
|
+
(_optionsRef$current3 = optionsRef.current) === null || _optionsRef$current3 === void 0 ? void 0 : (_optionsRef$current3$ = _optionsRef$current3.onReset) === null || _optionsRef$current3$ === void 0 ? void 0 : _optionsRef$current3$.call(_optionsRef$current3, event);
|
|
533
561
|
}
|
|
534
|
-
setUncontrolledState({
|
|
535
|
-
defaultValue: configRef.current.defaultValue,
|
|
536
|
-
initialError: configRef.current.initialError
|
|
537
|
-
});
|
|
538
|
-
setValue("".concat((_configRef$current$de = configRef.current.defaultValue) !== null && _configRef$current$de !== void 0 ? _configRef$current$de : ''));
|
|
539
562
|
};
|
|
563
|
+
document.addEventListener('input', inputHandler, true);
|
|
564
|
+
document.addEventListener('focus', focusHandler, true);
|
|
565
|
+
document.addEventListener('blur', blurHandler, true);
|
|
566
|
+
document.addEventListener('submit', submitHandler);
|
|
540
567
|
document.addEventListener('reset', resetHandler);
|
|
541
568
|
return () => {
|
|
569
|
+
document.removeEventListener('input', inputHandler, true);
|
|
570
|
+
document.removeEventListener('focus', focusHandler, true);
|
|
571
|
+
document.removeEventListener('blur', blurHandler, true);
|
|
572
|
+
document.removeEventListener('submit', submitHandler);
|
|
542
573
|
document.removeEventListener('reset', resetHandler);
|
|
543
574
|
};
|
|
544
575
|
}, []);
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
576
|
+
var control = react.useMemo(() => {
|
|
577
|
+
var getInputElement = () => {
|
|
578
|
+
var _optionsRef$current$g3, _optionsRef$current4, _optionsRef$current4$;
|
|
579
|
+
return (_optionsRef$current$g3 = (_optionsRef$current4 = optionsRef.current) === null || _optionsRef$current4 === void 0 ? void 0 : (_optionsRef$current4$ = _optionsRef$current4.getElement) === null || _optionsRef$current4$ === void 0 ? void 0 : _optionsRef$current4$.call(_optionsRef$current4, ref.current)) !== null && _optionsRef$current$g3 !== void 0 ? _optionsRef$current$g3 : ref.current;
|
|
580
|
+
};
|
|
581
|
+
return {
|
|
582
|
+
change(eventOrValue) {
|
|
583
|
+
var input = getInputElement();
|
|
584
|
+
if (!input) {
|
|
585
|
+
console.warn('Missing input ref; No change-related events will be dispatched');
|
|
586
|
+
return;
|
|
587
|
+
}
|
|
588
|
+
if (changeDispatched.current) {
|
|
589
|
+
changeDispatched.current = false;
|
|
590
|
+
return;
|
|
591
|
+
}
|
|
592
|
+
var previousValue = input.value;
|
|
593
|
+
var nextValue = typeof eventOrValue === 'string' ? eventOrValue : eventOrValue.target.value;
|
|
594
|
+
|
|
595
|
+
// This make sure no event is dispatched on the first effect run
|
|
596
|
+
if (nextValue === previousValue) {
|
|
597
|
+
return;
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
// Dispatch beforeinput event before updating the input value
|
|
601
|
+
input.dispatchEvent(new Event('beforeinput', {
|
|
602
|
+
bubbles: true
|
|
603
|
+
}));
|
|
604
|
+
// Update the input value to trigger a change event
|
|
605
|
+
setNativeValue(input, nextValue);
|
|
606
|
+
// Dispatch input event with the updated input value
|
|
607
|
+
input.dispatchEvent(new InputEvent('input', {
|
|
608
|
+
bubbles: true
|
|
609
|
+
}));
|
|
610
|
+
// Reset the dispatched flag
|
|
611
|
+
changeDispatched.current = false;
|
|
612
|
+
},
|
|
613
|
+
focus() {
|
|
614
|
+
var input = getInputElement();
|
|
615
|
+
if (!input) {
|
|
616
|
+
console.warn('Missing input ref; No focus-related events will be dispatched');
|
|
617
|
+
return;
|
|
618
|
+
}
|
|
619
|
+
if (focusDispatched.current) {
|
|
620
|
+
focusDispatched.current = false;
|
|
621
|
+
return;
|
|
622
|
+
}
|
|
623
|
+
var focusinEvent = new FocusEvent('focusin', {
|
|
624
|
+
bubbles: true
|
|
625
|
+
});
|
|
626
|
+
var focusEvent = new FocusEvent('focus');
|
|
627
|
+
input.dispatchEvent(focusinEvent);
|
|
628
|
+
input.dispatchEvent(focusEvent);
|
|
629
|
+
|
|
630
|
+
// Reset the dispatched flag
|
|
631
|
+
focusDispatched.current = false;
|
|
632
|
+
},
|
|
633
|
+
blur() {
|
|
634
|
+
var input = getInputElement();
|
|
635
|
+
if (!input) {
|
|
636
|
+
console.warn('Missing input ref; No blur-related events will be dispatched');
|
|
637
|
+
return;
|
|
638
|
+
}
|
|
639
|
+
if (blurDispatched.current) {
|
|
640
|
+
blurDispatched.current = false;
|
|
641
|
+
return;
|
|
642
|
+
}
|
|
643
|
+
var focusoutEvent = new FocusEvent('focusout', {
|
|
644
|
+
bubbles: true
|
|
645
|
+
});
|
|
646
|
+
var blurEvent = new FocusEvent('blur');
|
|
647
|
+
input.dispatchEvent(focusoutEvent);
|
|
648
|
+
input.dispatchEvent(blurEvent);
|
|
649
|
+
|
|
650
|
+
// Reset the dispatched flag
|
|
651
|
+
blurDispatched.current = false;
|
|
652
|
+
}
|
|
653
|
+
};
|
|
654
|
+
}, []);
|
|
655
|
+
return [ref, control];
|
|
571
656
|
}
|
|
572
657
|
|
|
573
|
-
exports.useControlledInput = useControlledInput;
|
|
574
658
|
exports.useFieldList = useFieldList;
|
|
575
659
|
exports.useFieldset = useFieldset;
|
|
576
660
|
exports.useForm = useForm;
|
|
661
|
+
exports.useInputEvent = useInputEvent;
|
package/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { type FieldConfig, type FieldsetConstraint, type Submission, getFormElements,
|
|
1
|
+
export { type FieldConfig, type FieldsetConstraint, type Submission, getFormElements, list, validate, requestIntent, requestSubmit, parse, validateConstraint, } from '@conform-to/dom';
|
|
2
2
|
export * from './hooks';
|
|
3
3
|
export * as conform from './helpers';
|