@conform-to/react 0.5.0-pre.0 → 0.5.1
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 +260 -277
- package/helpers.d.ts +16 -7
- package/helpers.js +47 -7
- package/hooks.d.ts +48 -31
- package/hooks.js +235 -81
- package/index.d.ts +1 -1
- package/index.js +17 -0
- package/module/helpers.js +47 -7
- package/module/hooks.js +237 -84
- package/module/index.js +2 -2
- package/package.json +2 -2
package/module/hooks.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { objectSpread2 as _objectSpread2 } from './_virtual/_rollupPluginBabelHelpers.js';
|
|
2
|
-
import {
|
|
3
|
-
import { useRef, useState, useEffect } from 'react';
|
|
2
|
+
import { shouldValidate, reportSubmission, getFormData, parse, isFieldElement, hasError, getPaths, getName, requestCommand, validate, getFormElement, parseListCommand, updateList } from '@conform-to/dom';
|
|
3
|
+
import { useRef, useState, useEffect, useMemo, useLayoutEffect } from 'react';
|
|
4
4
|
import { input } from './helpers.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Returns properties required to hook into form events.
|
|
8
8
|
* Applied custom validation and define when error should be reported.
|
|
9
9
|
*
|
|
10
|
-
* @see https://
|
|
10
|
+
* @see https://conform.guide/api/react#useform
|
|
11
11
|
*/
|
|
12
12
|
function useForm() {
|
|
13
13
|
var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
@@ -21,17 +21,26 @@ function useForm() {
|
|
|
21
21
|
})) !== null && _config$state$error$f !== void 0 ? _config$state$error$f : [];
|
|
22
22
|
return message !== null && message !== void 0 ? message : '';
|
|
23
23
|
});
|
|
24
|
-
var [
|
|
25
|
-
var
|
|
26
|
-
|
|
24
|
+
var [uncontrolledState, setUncontrolledState] = useState(() => {
|
|
25
|
+
var submission = config.state;
|
|
26
|
+
if (!submission) {
|
|
27
|
+
return {
|
|
28
|
+
defaultValue: config.defaultValue
|
|
29
|
+
};
|
|
30
|
+
}
|
|
27
31
|
return {
|
|
28
|
-
defaultValue:
|
|
29
|
-
initialError: error.filter(_ref2 => {
|
|
32
|
+
defaultValue: submission.value,
|
|
33
|
+
initialError: submission.error.filter(_ref2 => {
|
|
30
34
|
var [name] = _ref2;
|
|
31
|
-
return name !== '' &&
|
|
35
|
+
return name !== '' && shouldValidate(submission, name);
|
|
32
36
|
})
|
|
33
37
|
};
|
|
34
38
|
});
|
|
39
|
+
var fieldsetConfig = _objectSpread2(_objectSpread2({}, uncontrolledState), {}, {
|
|
40
|
+
constraint: config.constraint,
|
|
41
|
+
form: config.id
|
|
42
|
+
});
|
|
43
|
+
var fieldset = useFieldset(ref, fieldsetConfig);
|
|
35
44
|
var [noValidate, setNoValidate] = useState(config.noValidate || !config.fallbackNative);
|
|
36
45
|
useEffect(() => {
|
|
37
46
|
configRef.current = config;
|
|
@@ -55,11 +64,8 @@ function useForm() {
|
|
|
55
64
|
if (!form || !isFieldElement(field) || field.form !== form) {
|
|
56
65
|
return;
|
|
57
66
|
}
|
|
58
|
-
if (formConfig.initialReport === 'onChange') {
|
|
59
|
-
field.
|
|
60
|
-
}
|
|
61
|
-
if (field.dataset.conformTouched) {
|
|
62
|
-
requestValidate(form, field.name);
|
|
67
|
+
if (field.dataset.conformTouched || formConfig.initialReport === 'onChange') {
|
|
68
|
+
requestCommand(form, validate(field.name));
|
|
63
69
|
}
|
|
64
70
|
};
|
|
65
71
|
var handleBlur = event => {
|
|
@@ -70,8 +76,7 @@ function useForm() {
|
|
|
70
76
|
return;
|
|
71
77
|
}
|
|
72
78
|
if (formConfig.initialReport === 'onBlur' && !field.dataset.conformTouched) {
|
|
73
|
-
field.
|
|
74
|
-
requestValidate(form, field.name);
|
|
79
|
+
requestCommand(form, validate(field.name));
|
|
75
80
|
}
|
|
76
81
|
};
|
|
77
82
|
var handleInvalid = event => {
|
|
@@ -96,11 +101,12 @@ function useForm() {
|
|
|
96
101
|
for (var field of form.elements) {
|
|
97
102
|
if (isFieldElement(field)) {
|
|
98
103
|
delete field.dataset.conformTouched;
|
|
104
|
+
field.setAttribute('aria-invalid', 'false');
|
|
99
105
|
field.setCustomValidity('');
|
|
100
106
|
}
|
|
101
107
|
}
|
|
102
108
|
setError('');
|
|
103
|
-
|
|
109
|
+
setUncontrolledState({
|
|
104
110
|
defaultValue: formConfig.defaultValue,
|
|
105
111
|
initialError: []
|
|
106
112
|
});
|
|
@@ -123,11 +129,13 @@ function useForm() {
|
|
|
123
129
|
document.removeEventListener('reset', handleReset);
|
|
124
130
|
};
|
|
125
131
|
}, []);
|
|
126
|
-
|
|
132
|
+
var form = {
|
|
133
|
+
id: config.id,
|
|
127
134
|
ref,
|
|
128
135
|
error,
|
|
129
136
|
props: {
|
|
130
137
|
ref,
|
|
138
|
+
id: config.id,
|
|
131
139
|
noValidate,
|
|
132
140
|
onSubmit(event) {
|
|
133
141
|
var form = event.currentTarget;
|
|
@@ -169,16 +177,6 @@ function useForm() {
|
|
|
169
177
|
}
|
|
170
178
|
}
|
|
171
179
|
}
|
|
172
|
-
|
|
173
|
-
// Touch all fields only if the submitter is not a command button
|
|
174
|
-
if (submission.type === 'submit') {
|
|
175
|
-
for (var field of form.elements) {
|
|
176
|
-
if (isFieldElement(field)) {
|
|
177
|
-
// Mark the field as touched
|
|
178
|
-
field.dataset.conformTouched = 'true';
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
180
|
if (!config.noValidate && !(submitter !== null && submitter !== void 0 && submitter.formNoValidate) && hasError(submission.error) || submission.type === 'validate' && config.mode !== 'server-validation') {
|
|
183
181
|
event.preventDefault();
|
|
184
182
|
} else {
|
|
@@ -198,6 +196,7 @@ function useForm() {
|
|
|
198
196
|
},
|
|
199
197
|
config: fieldsetConfig
|
|
200
198
|
};
|
|
199
|
+
return [form, fieldset];
|
|
201
200
|
}
|
|
202
201
|
|
|
203
202
|
/**
|
|
@@ -258,6 +257,10 @@ function useFieldset(ref, config) {
|
|
|
258
257
|
// Update the error only if the field belongs to the fieldset
|
|
259
258
|
if (typeof key === 'string' && paths.length === 0) {
|
|
260
259
|
if (field.dataset.conformTouched) {
|
|
260
|
+
// Update the aria attribute only if it is set
|
|
261
|
+
if (field.getAttribute('aria-invalid')) {
|
|
262
|
+
field.setAttribute('aria-invalid', field.validationMessage !== '' ? 'true' : 'false');
|
|
263
|
+
}
|
|
261
264
|
setError(prev => {
|
|
262
265
|
var _prev$key;
|
|
263
266
|
var prevMessage = (_prev$key = prev === null || prev === void 0 ? void 0 : prev[key]) !== null && _prev$key !== void 0 ? _prev$key : '';
|
|
@@ -312,21 +315,26 @@ function useFieldset(ref, config) {
|
|
|
312
315
|
var field = {
|
|
313
316
|
config: _objectSpread2({
|
|
314
317
|
name: fieldsetConfig.name ? "".concat(fieldsetConfig.name, ".").concat(key) : key,
|
|
315
|
-
form: fieldsetConfig.form,
|
|
316
318
|
defaultValue: uncontrolledState.defaultValue[key],
|
|
317
319
|
initialError: uncontrolledState.initialError[key]
|
|
318
320
|
}, constraint),
|
|
319
321
|
error: (_error$key = error === null || error === void 0 ? void 0 : error[key]) !== null && _error$key !== void 0 ? _error$key : ''
|
|
320
322
|
};
|
|
323
|
+
if (fieldsetConfig.form) {
|
|
324
|
+
field.config.form = fieldsetConfig.form;
|
|
325
|
+
field.config.id = "".concat(fieldsetConfig.form, "-").concat(field.config.name);
|
|
326
|
+
field.config.errorId = "".concat(field.config.id, "-error");
|
|
327
|
+
}
|
|
321
328
|
return field;
|
|
322
329
|
}
|
|
323
330
|
});
|
|
324
331
|
}
|
|
332
|
+
|
|
325
333
|
/**
|
|
326
334
|
* Returns a list of key and config, with a group of helpers
|
|
327
335
|
* configuring buttons for list manipulation
|
|
328
336
|
*
|
|
329
|
-
* @see https://
|
|
337
|
+
* @see https://conform.guide/api/react#usefieldlist
|
|
330
338
|
*/
|
|
331
339
|
function useFieldList(ref, config) {
|
|
332
340
|
var configRef = useRef(config);
|
|
@@ -357,41 +365,6 @@ function useFieldList(ref, config) {
|
|
|
357
365
|
var _config$defaultValue3;
|
|
358
366
|
return Object.entries((_config$defaultValue3 = config.defaultValue) !== null && _config$defaultValue3 !== void 0 ? _config$defaultValue3 : [undefined]);
|
|
359
367
|
});
|
|
360
|
-
var list = entries.map((_ref3, index) => {
|
|
361
|
-
var [key, defaultValue] = _ref3;
|
|
362
|
-
return {
|
|
363
|
-
key,
|
|
364
|
-
error: error[index],
|
|
365
|
-
config: {
|
|
366
|
-
name: "".concat(config.name, "[").concat(index, "]"),
|
|
367
|
-
form: config.form,
|
|
368
|
-
defaultValue: defaultValue !== null && defaultValue !== void 0 ? defaultValue : uncontrolledState.defaultValue[index],
|
|
369
|
-
initialError: uncontrolledState.initialError[index]
|
|
370
|
-
}
|
|
371
|
-
};
|
|
372
|
-
});
|
|
373
|
-
|
|
374
|
-
/***
|
|
375
|
-
* This use proxy to capture all information about the command and
|
|
376
|
-
* have it encoded in the value.
|
|
377
|
-
*/
|
|
378
|
-
var command = new Proxy({}, {
|
|
379
|
-
get(_target, type) {
|
|
380
|
-
return function () {
|
|
381
|
-
var payload = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
382
|
-
return {
|
|
383
|
-
name: 'conform/list',
|
|
384
|
-
value: JSON.stringify({
|
|
385
|
-
type,
|
|
386
|
-
scope: config.name,
|
|
387
|
-
payload
|
|
388
|
-
}),
|
|
389
|
-
form: config.form,
|
|
390
|
-
formNoValidate: true
|
|
391
|
-
};
|
|
392
|
-
};
|
|
393
|
-
}
|
|
394
|
-
});
|
|
395
368
|
useEffect(() => {
|
|
396
369
|
configRef.current = config;
|
|
397
370
|
});
|
|
@@ -488,16 +461,32 @@ function useFieldList(ref, config) {
|
|
|
488
461
|
document.removeEventListener('reset', resetHandler);
|
|
489
462
|
};
|
|
490
463
|
}, [ref]);
|
|
491
|
-
return
|
|
492
|
-
|
|
493
|
-
|
|
464
|
+
return entries.map((_ref3, index) => {
|
|
465
|
+
var [key, defaultValue] = _ref3;
|
|
466
|
+
var fieldConfig = {
|
|
467
|
+
name: "".concat(config.name, "[").concat(index, "]"),
|
|
468
|
+
defaultValue: defaultValue !== null && defaultValue !== void 0 ? defaultValue : uncontrolledState.defaultValue[index],
|
|
469
|
+
initialError: uncontrolledState.initialError[index]
|
|
470
|
+
};
|
|
471
|
+
if (config.form) {
|
|
472
|
+
fieldConfig.form = config.form;
|
|
473
|
+
fieldConfig.id = "".concat(config.form, "-").concat(config.name);
|
|
474
|
+
fieldConfig.errorId = "".concat(fieldConfig.id, "-error");
|
|
475
|
+
}
|
|
476
|
+
return {
|
|
477
|
+
key,
|
|
478
|
+
error: error[index],
|
|
479
|
+
config: fieldConfig
|
|
480
|
+
};
|
|
481
|
+
});
|
|
494
482
|
}
|
|
495
483
|
/**
|
|
496
484
|
* Returns the properties required to configure a shadow input for validation.
|
|
497
485
|
* This is particular useful when integrating dropdown and datepicker whichs
|
|
498
486
|
* introduces custom input mode.
|
|
499
487
|
*
|
|
500
|
-
* @
|
|
488
|
+
* @deprecated Please use the `useInputEvent` hook instead
|
|
489
|
+
* @see https://conform.guide/api/react#usecontrolledinput
|
|
501
490
|
*/
|
|
502
491
|
function useControlledInput(config) {
|
|
503
492
|
var _config$defaultValue4;
|
|
@@ -552,24 +541,13 @@ function useControlledInput(config) {
|
|
|
552
541
|
}, []);
|
|
553
542
|
return [_objectSpread2({
|
|
554
543
|
ref,
|
|
555
|
-
style: {
|
|
556
|
-
position: 'absolute',
|
|
557
|
-
width: '1px',
|
|
558
|
-
height: '1px',
|
|
559
|
-
padding: 0,
|
|
560
|
-
margin: '-1px',
|
|
561
|
-
overflow: 'hidden',
|
|
562
|
-
clip: 'rect(0,0,0,0)',
|
|
563
|
-
whiteSpace: 'nowrap',
|
|
564
|
-
borderWidth: 0
|
|
565
|
-
},
|
|
566
|
-
tabIndex: -1,
|
|
567
|
-
'aria-hidden': true,
|
|
568
544
|
onFocus() {
|
|
569
545
|
var _inputRef$current;
|
|
570
546
|
(_inputRef$current = inputRef.current) === null || _inputRef$current === void 0 ? void 0 : _inputRef$current.focus();
|
|
571
547
|
}
|
|
572
|
-
}, input(_objectSpread2(_objectSpread2({}, config), uncontrolledState)
|
|
548
|
+
}, input(_objectSpread2(_objectSpread2({}, config), uncontrolledState), {
|
|
549
|
+
hidden: true
|
|
550
|
+
})), {
|
|
573
551
|
ref: inputRef,
|
|
574
552
|
value,
|
|
575
553
|
onChange: handleChange,
|
|
@@ -578,4 +556,179 @@ function useControlledInput(config) {
|
|
|
578
556
|
}];
|
|
579
557
|
}
|
|
580
558
|
|
|
581
|
-
|
|
559
|
+
/**
|
|
560
|
+
* Triggering react custom change event
|
|
561
|
+
* Solution based on dom-testing-library
|
|
562
|
+
* @see https://github.com/facebook/react/issues/10135#issuecomment-401496776
|
|
563
|
+
* @see https://github.com/testing-library/dom-testing-library/blob/main/src/events.js#L104-L123
|
|
564
|
+
*/
|
|
565
|
+
function setNativeValue(element, value) {
|
|
566
|
+
if (element.value === value) {
|
|
567
|
+
// It will not trigger a change event if `element.value` is the same as the set value
|
|
568
|
+
return;
|
|
569
|
+
}
|
|
570
|
+
var {
|
|
571
|
+
set: valueSetter
|
|
572
|
+
} = Object.getOwnPropertyDescriptor(element, 'value') || {};
|
|
573
|
+
var prototype = Object.getPrototypeOf(element);
|
|
574
|
+
var {
|
|
575
|
+
set: prototypeValueSetter
|
|
576
|
+
} = Object.getOwnPropertyDescriptor(prototype, 'value') || {};
|
|
577
|
+
if (prototypeValueSetter && valueSetter !== prototypeValueSetter) {
|
|
578
|
+
prototypeValueSetter.call(element, value);
|
|
579
|
+
} else {
|
|
580
|
+
if (valueSetter) {
|
|
581
|
+
valueSetter.call(element, value);
|
|
582
|
+
} else {
|
|
583
|
+
throw new Error('The given element does not have a value setter');
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
/**
|
|
589
|
+
* useLayoutEffect is client-only.
|
|
590
|
+
* This basically makes it a no-op on server
|
|
591
|
+
*/
|
|
592
|
+
var useSafeLayoutEffect = typeof document === 'undefined' ? useEffect : useLayoutEffect;
|
|
593
|
+
function useInputEvent(options) {
|
|
594
|
+
var ref = useRef(null);
|
|
595
|
+
var optionsRef = useRef(options);
|
|
596
|
+
var changeDispatched = useRef(false);
|
|
597
|
+
var focusDispatched = useRef(false);
|
|
598
|
+
var blurDispatched = useRef(false);
|
|
599
|
+
useSafeLayoutEffect(() => {
|
|
600
|
+
optionsRef.current = options;
|
|
601
|
+
});
|
|
602
|
+
useSafeLayoutEffect(() => {
|
|
603
|
+
var getInputElement = () => {
|
|
604
|
+
var _optionsRef$current$g, _optionsRef$current, _optionsRef$current$g2;
|
|
605
|
+
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;
|
|
606
|
+
};
|
|
607
|
+
var inputHandler = event => {
|
|
608
|
+
var input = getInputElement();
|
|
609
|
+
if (input && event.target === input) {
|
|
610
|
+
changeDispatched.current = true;
|
|
611
|
+
}
|
|
612
|
+
};
|
|
613
|
+
var focusHandler = event => {
|
|
614
|
+
var input = getInputElement();
|
|
615
|
+
if (input && event.target === input) {
|
|
616
|
+
focusDispatched.current = true;
|
|
617
|
+
}
|
|
618
|
+
};
|
|
619
|
+
var blurHandler = event => {
|
|
620
|
+
var input = getInputElement();
|
|
621
|
+
if (input && event.target === input) {
|
|
622
|
+
blurDispatched.current = true;
|
|
623
|
+
}
|
|
624
|
+
};
|
|
625
|
+
var submitHandler = event => {
|
|
626
|
+
var input = getInputElement();
|
|
627
|
+
if (input !== null && input !== void 0 && input.form && event.target === input.form) {
|
|
628
|
+
var _optionsRef$current2, _optionsRef$current2$;
|
|
629
|
+
(_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);
|
|
630
|
+
}
|
|
631
|
+
};
|
|
632
|
+
var resetHandler = event => {
|
|
633
|
+
var input = getInputElement();
|
|
634
|
+
if (input !== null && input !== void 0 && input.form && event.target === input.form) {
|
|
635
|
+
var _optionsRef$current3, _optionsRef$current3$;
|
|
636
|
+
(_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);
|
|
637
|
+
}
|
|
638
|
+
};
|
|
639
|
+
document.addEventListener('input', inputHandler, true);
|
|
640
|
+
document.addEventListener('focus', focusHandler, true);
|
|
641
|
+
document.addEventListener('blur', blurHandler, true);
|
|
642
|
+
document.addEventListener('submit', submitHandler);
|
|
643
|
+
document.addEventListener('reset', resetHandler);
|
|
644
|
+
return () => {
|
|
645
|
+
document.removeEventListener('input', inputHandler, true);
|
|
646
|
+
document.removeEventListener('focus', focusHandler, true);
|
|
647
|
+
document.removeEventListener('blur', blurHandler, true);
|
|
648
|
+
document.removeEventListener('submit', submitHandler);
|
|
649
|
+
document.removeEventListener('reset', resetHandler);
|
|
650
|
+
};
|
|
651
|
+
}, []);
|
|
652
|
+
var control = useMemo(() => {
|
|
653
|
+
var getInputElement = () => {
|
|
654
|
+
var _optionsRef$current$g3, _optionsRef$current4, _optionsRef$current4$;
|
|
655
|
+
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;
|
|
656
|
+
};
|
|
657
|
+
return {
|
|
658
|
+
change(eventOrValue) {
|
|
659
|
+
var input = getInputElement();
|
|
660
|
+
if (!input) {
|
|
661
|
+
console.warn('Missing input ref; No change-related events will be dispatched');
|
|
662
|
+
return;
|
|
663
|
+
}
|
|
664
|
+
if (changeDispatched.current) {
|
|
665
|
+
changeDispatched.current = false;
|
|
666
|
+
return;
|
|
667
|
+
}
|
|
668
|
+
var previousValue = input.value;
|
|
669
|
+
var nextValue = typeof eventOrValue === 'string' ? eventOrValue : eventOrValue.target.value;
|
|
670
|
+
|
|
671
|
+
// This make sure no event is dispatched on the first effect run
|
|
672
|
+
if (nextValue === previousValue) {
|
|
673
|
+
return;
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
// Dispatch beforeinput event before updating the input value
|
|
677
|
+
input.dispatchEvent(new Event('beforeinput', {
|
|
678
|
+
bubbles: true
|
|
679
|
+
}));
|
|
680
|
+
// Update the input value to trigger a change event
|
|
681
|
+
setNativeValue(input, nextValue);
|
|
682
|
+
// Dispatch input event with the updated input value
|
|
683
|
+
input.dispatchEvent(new InputEvent('input', {
|
|
684
|
+
bubbles: true
|
|
685
|
+
}));
|
|
686
|
+
// Reset the dispatched flag
|
|
687
|
+
changeDispatched.current = false;
|
|
688
|
+
},
|
|
689
|
+
focus() {
|
|
690
|
+
var input = getInputElement();
|
|
691
|
+
if (!input) {
|
|
692
|
+
console.warn('Missing input ref; No focus-related events will be dispatched');
|
|
693
|
+
return;
|
|
694
|
+
}
|
|
695
|
+
if (focusDispatched.current) {
|
|
696
|
+
focusDispatched.current = false;
|
|
697
|
+
return;
|
|
698
|
+
}
|
|
699
|
+
var focusinEvent = new FocusEvent('focusin', {
|
|
700
|
+
bubbles: true
|
|
701
|
+
});
|
|
702
|
+
var focusEvent = new FocusEvent('focus');
|
|
703
|
+
input.dispatchEvent(focusinEvent);
|
|
704
|
+
input.dispatchEvent(focusEvent);
|
|
705
|
+
|
|
706
|
+
// Reset the dispatched flag
|
|
707
|
+
focusDispatched.current = false;
|
|
708
|
+
},
|
|
709
|
+
blur() {
|
|
710
|
+
var input = getInputElement();
|
|
711
|
+
if (!input) {
|
|
712
|
+
console.warn('Missing input ref; No blur-related events will be dispatched');
|
|
713
|
+
return;
|
|
714
|
+
}
|
|
715
|
+
if (blurDispatched.current) {
|
|
716
|
+
blurDispatched.current = false;
|
|
717
|
+
return;
|
|
718
|
+
}
|
|
719
|
+
var focusoutEvent = new FocusEvent('focusout', {
|
|
720
|
+
bubbles: true
|
|
721
|
+
});
|
|
722
|
+
var blurEvent = new FocusEvent('blur');
|
|
723
|
+
input.dispatchEvent(focusoutEvent);
|
|
724
|
+
input.dispatchEvent(blurEvent);
|
|
725
|
+
|
|
726
|
+
// Reset the dispatched flag
|
|
727
|
+
blurDispatched.current = false;
|
|
728
|
+
}
|
|
729
|
+
};
|
|
730
|
+
}, []);
|
|
731
|
+
return [ref, control];
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
export { useControlledInput, useFieldList, useFieldset, useForm, useInputEvent };
|
package/module/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { getFormElements, hasError, parse, shouldValidate } from '@conform-to/dom';
|
|
2
|
-
export { useControlledInput, useFieldList, useFieldset, useForm } from './hooks.js';
|
|
1
|
+
export { getFormElements, hasError, list, parse, requestCommand, requestSubmit, shouldValidate, validate } from '@conform-to/dom';
|
|
2
|
+
export { useControlledInput, useFieldList, useFieldset, useForm, useInputEvent } from './hooks.js';
|
|
3
3
|
import * as helpers from './helpers.js';
|
|
4
4
|
export { helpers as conform };
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@conform-to/react",
|
|
3
3
|
"description": "Conform view adapter for react",
|
|
4
4
|
"license": "MIT",
|
|
5
|
-
"version": "0.5.
|
|
5
|
+
"version": "0.5.1",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"module": "module/index.js",
|
|
8
8
|
"repository": {
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"url": "https://github.com/edmundhung/conform/issues"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@conform-to/dom": "0.5.
|
|
22
|
+
"@conform-to/dom": "0.5.1"
|
|
23
23
|
},
|
|
24
24
|
"peerDependencies": {
|
|
25
25
|
"react": ">=16.8"
|