@conform-to/react 1.6.1 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/context.d.ts +3 -0
- package/dist/context.js +23 -0
- package/dist/context.mjs +23 -0
- package/dist/future/hooks.d.ts +90 -0
- package/dist/future/hooks.js +179 -0
- package/dist/future/hooks.mjs +174 -0
- package/dist/future/index.d.ts +2 -0
- package/dist/future/index.js +9 -0
- package/dist/future/index.mjs +1 -0
- package/dist/future/util.d.ts +37 -0
- package/dist/future/util.js +134 -0
- package/dist/future/util.mjs +125 -0
- package/dist/integrations.js +2 -2
- package/dist/integrations.mjs +3 -3
- package/dist/vitest.config.d.ts +3 -0
- package/package.json +11 -3
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
╚══════╝ ╚═════╝ ╚═╝ ╚══╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝
|
|
8
8
|
```
|
|
9
9
|
|
|
10
|
-
Version 1.
|
|
10
|
+
Version 1.7.0 / License MIT / Copyright (c) 2024 Edmund Hung
|
|
11
11
|
|
|
12
12
|
A type-safe form validation library utilizing web fundamentals to progressively enhance HTML Forms with full support for server frameworks like Remix and Next.js.
|
|
13
13
|
|
package/dist/context.d.ts
CHANGED
|
@@ -10,6 +10,9 @@ export type Metadata<Schema, FormSchema extends Record<string, unknown>, FormErr
|
|
|
10
10
|
errorId: string;
|
|
11
11
|
descriptionId: string;
|
|
12
12
|
name: FieldName<Schema, FormSchema, FormError>;
|
|
13
|
+
defaultValue: string | undefined;
|
|
14
|
+
defaultOptions: string[] | undefined;
|
|
15
|
+
defaultChecked: boolean | undefined;
|
|
13
16
|
initialValue: FormValue<Schema>;
|
|
14
17
|
value: FormValue<Schema>;
|
|
15
18
|
errors: FormError | undefined;
|
package/dist/context.js
CHANGED
|
@@ -74,6 +74,29 @@ function getMetadata(context, subjectRef, stateSnapshot) {
|
|
|
74
74
|
name,
|
|
75
75
|
errorId: "".concat(id, "-error"),
|
|
76
76
|
descriptionId: "".concat(id, "-description"),
|
|
77
|
+
get defaultValue() {
|
|
78
|
+
var initialValue = this.initialValue;
|
|
79
|
+
if (typeof initialValue === 'string') {
|
|
80
|
+
return initialValue;
|
|
81
|
+
}
|
|
82
|
+
if (Array.isArray(initialValue)) {
|
|
83
|
+
return initialValue[0];
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
get defaultOptions() {
|
|
87
|
+
var initialValue = this.initialValue;
|
|
88
|
+
if (typeof initialValue === 'string') {
|
|
89
|
+
return [initialValue];
|
|
90
|
+
}
|
|
91
|
+
if (Array.isArray(initialValue) && initialValue.every(item => typeof item === 'string')) {
|
|
92
|
+
return initialValue;
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
get defaultChecked() {
|
|
96
|
+
if (this.initialValue === 'on') {
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
},
|
|
77
100
|
get initialValue() {
|
|
78
101
|
return state.initialValue[name];
|
|
79
102
|
},
|
package/dist/context.mjs
CHANGED
|
@@ -70,6 +70,29 @@ function getMetadata(context, subjectRef, stateSnapshot) {
|
|
|
70
70
|
name,
|
|
71
71
|
errorId: "".concat(id, "-error"),
|
|
72
72
|
descriptionId: "".concat(id, "-description"),
|
|
73
|
+
get defaultValue() {
|
|
74
|
+
var initialValue = this.initialValue;
|
|
75
|
+
if (typeof initialValue === 'string') {
|
|
76
|
+
return initialValue;
|
|
77
|
+
}
|
|
78
|
+
if (Array.isArray(initialValue)) {
|
|
79
|
+
return initialValue[0];
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
get defaultOptions() {
|
|
83
|
+
var initialValue = this.initialValue;
|
|
84
|
+
if (typeof initialValue === 'string') {
|
|
85
|
+
return [initialValue];
|
|
86
|
+
}
|
|
87
|
+
if (Array.isArray(initialValue) && initialValue.every(item => typeof item === 'string')) {
|
|
88
|
+
return initialValue;
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
get defaultChecked() {
|
|
92
|
+
if (this.initialValue === 'on') {
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
},
|
|
73
96
|
get initialValue() {
|
|
74
97
|
return state.initialValue[name];
|
|
75
98
|
},
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
export declare const formObserver: {
|
|
2
|
+
onFieldUpdate(callback: (event: {
|
|
3
|
+
type: "input" | "reset" | "mutation";
|
|
4
|
+
target: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement;
|
|
5
|
+
}) => void): () => void;
|
|
6
|
+
onFormUpdate(callback: (event: {
|
|
7
|
+
type: "submit" | "input" | "reset" | "mutation";
|
|
8
|
+
target: HTMLFormElement;
|
|
9
|
+
submitter?: HTMLInputElement | HTMLButtonElement | null;
|
|
10
|
+
}) => void): () => void;
|
|
11
|
+
dispose(): void;
|
|
12
|
+
};
|
|
13
|
+
export type Control = {
|
|
14
|
+
/**
|
|
15
|
+
* Current value of the base input. Undefined if the registered input
|
|
16
|
+
* is a multi-select, file input, or checkbox group.
|
|
17
|
+
*/
|
|
18
|
+
value: string | undefined;
|
|
19
|
+
/**
|
|
20
|
+
* Selected options of the base input. Defined only when the registered input
|
|
21
|
+
* is a multi-select or checkbox group.
|
|
22
|
+
*/
|
|
23
|
+
checked: boolean | undefined;
|
|
24
|
+
/**
|
|
25
|
+
* Checked state of the base input. Defined only when the registered input
|
|
26
|
+
* is a single checkbox or radio input.
|
|
27
|
+
*/
|
|
28
|
+
options: string[] | undefined;
|
|
29
|
+
/**
|
|
30
|
+
* Selected files of the base input. Defined only when the registered input
|
|
31
|
+
* is a file input.
|
|
32
|
+
*/
|
|
33
|
+
files: File[] | undefined;
|
|
34
|
+
/**
|
|
35
|
+
* Registers the base input element(s). Accepts a single input or an array for groups.
|
|
36
|
+
*/
|
|
37
|
+
register: (element: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement | HTMLCollectionOf<HTMLInputElement> | NodeListOf<HTMLInputElement> | null | undefined) => void;
|
|
38
|
+
/**
|
|
39
|
+
* Programmatically updates the input value and emits
|
|
40
|
+
* both [change](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event) and
|
|
41
|
+
* [input](https://developer.mozilla.org/en-US/docs/Web/API/Element/input_event) events.
|
|
42
|
+
*/
|
|
43
|
+
change(value: string | string[] | boolean | File | File[] | FileList): void;
|
|
44
|
+
/**
|
|
45
|
+
* Emits [blur](https://developer.mozilla.org/en-US/docs/Web/API/Element/blur_event) and
|
|
46
|
+
* [focusout](https://developer.mozilla.org/en-US/docs/Web/API/Element/focusout_event) events.
|
|
47
|
+
* Does not actually move focus.
|
|
48
|
+
*/
|
|
49
|
+
focus(): void;
|
|
50
|
+
/**
|
|
51
|
+
* Emits [focus](https://developer.mozilla.org/en-US/docs/Web/API/Element/focus_event) and
|
|
52
|
+
* [focusin](https://developer.mozilla.org/en-US/docs/Web/API/Element/focusin_event) events.
|
|
53
|
+
* This does not move the actual keyboard focus to the input. Use `element.focus()` instead
|
|
54
|
+
* if you want to move focus to the input.
|
|
55
|
+
*/
|
|
56
|
+
blur(): void;
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* A React hook that lets you sync the state of an input and dispatch native form events from it.
|
|
60
|
+
* This is useful when emulating native input behavior — typically by rendering a hidden base input
|
|
61
|
+
* and syncing it with a custom input.
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```ts
|
|
65
|
+
* const control = useControl(options);
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
export declare function useControl(options?: {
|
|
69
|
+
/**
|
|
70
|
+
* The initial value of the base input. It will be used to set the value
|
|
71
|
+
* when the input is first registered.
|
|
72
|
+
*/
|
|
73
|
+
defaultValue?: string | string[] | File | File[] | null | undefined;
|
|
74
|
+
/**
|
|
75
|
+
* Whether the base input should be checked by default. It will be applied
|
|
76
|
+
* when the input is first registered.
|
|
77
|
+
*/
|
|
78
|
+
defaultChecked?: boolean | undefined;
|
|
79
|
+
/**
|
|
80
|
+
* The value of a checkbox or radio input when checked. This sets the
|
|
81
|
+
* value attribute of the base input.
|
|
82
|
+
*/
|
|
83
|
+
value?: string;
|
|
84
|
+
/**
|
|
85
|
+
* A callback function that is triggered when the base input is focused.
|
|
86
|
+
* Use this to delegate focus to a custom input.
|
|
87
|
+
*/
|
|
88
|
+
onFocus?: () => void;
|
|
89
|
+
}): Control;
|
|
90
|
+
//# sourceMappingURL=hooks.d.ts.map
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var dom = require('@conform-to/dom');
|
|
6
|
+
var react = require('react');
|
|
7
|
+
var util = require('./util.js');
|
|
8
|
+
|
|
9
|
+
var formObserver = dom.unstable_createGlobalFormsObserver();
|
|
10
|
+
/**
|
|
11
|
+
* A React hook that lets you sync the state of an input and dispatch native form events from it.
|
|
12
|
+
* This is useful when emulating native input behavior — typically by rendering a hidden base input
|
|
13
|
+
* and syncing it with a custom input.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* const control = useControl(options);
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
function useControl(options) {
|
|
21
|
+
var inputRef = react.useRef(null);
|
|
22
|
+
var eventDispatched = react.useRef({});
|
|
23
|
+
var defaultSnapshot = util.getDefaultSnapshot(options === null || options === void 0 ? void 0 : options.defaultValue, options === null || options === void 0 ? void 0 : options.defaultChecked, options === null || options === void 0 ? void 0 : options.value);
|
|
24
|
+
var snapshotRef = react.useRef(defaultSnapshot);
|
|
25
|
+
var optionsRef = react.useRef(options);
|
|
26
|
+
react.useEffect(() => {
|
|
27
|
+
optionsRef.current = options;
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// This is necessary to ensure that input is re-registered
|
|
31
|
+
// if the onFocus handler changes
|
|
32
|
+
var shouldHandleFocus = typeof (options === null || options === void 0 ? void 0 : options.onFocus) === 'function';
|
|
33
|
+
var snapshot = react.useSyncExternalStore(react.useCallback(callback => formObserver.onFieldUpdate(event => {
|
|
34
|
+
var input = event.target;
|
|
35
|
+
if (Array.isArray(inputRef.current) ? inputRef.current.some(item => item === input) : inputRef.current === input) {
|
|
36
|
+
callback();
|
|
37
|
+
}
|
|
38
|
+
}), []), () => {
|
|
39
|
+
var input = inputRef.current;
|
|
40
|
+
var prev = snapshotRef.current;
|
|
41
|
+
var next = !input ? defaultSnapshot : Array.isArray(input) ? {
|
|
42
|
+
value: util.getRadioGroupValue(input),
|
|
43
|
+
options: util.getCheckboxGroupValue(input)
|
|
44
|
+
} : util.getInputSnapshot(input);
|
|
45
|
+
if (dom.unstable_deepEqual(prev, next)) {
|
|
46
|
+
return prev;
|
|
47
|
+
}
|
|
48
|
+
snapshotRef.current = next;
|
|
49
|
+
return next;
|
|
50
|
+
}, () => snapshotRef.current);
|
|
51
|
+
react.useEffect(() => {
|
|
52
|
+
var createEventListener = listener => {
|
|
53
|
+
return event => {
|
|
54
|
+
if (Array.isArray(inputRef.current) ? inputRef.current.some(item => item === event.target) : inputRef.current === event.target) {
|
|
55
|
+
var timer = eventDispatched.current[listener];
|
|
56
|
+
if (timer) {
|
|
57
|
+
clearTimeout(timer);
|
|
58
|
+
}
|
|
59
|
+
eventDispatched.current[listener] = window.setTimeout(() => {
|
|
60
|
+
eventDispatched.current[listener] = undefined;
|
|
61
|
+
});
|
|
62
|
+
if (listener === 'focus') {
|
|
63
|
+
var _optionsRef$current, _optionsRef$current$o;
|
|
64
|
+
(_optionsRef$current = optionsRef.current) === null || _optionsRef$current === void 0 || (_optionsRef$current$o = _optionsRef$current.onFocus) === null || _optionsRef$current$o === void 0 || _optionsRef$current$o.call(_optionsRef$current);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
var inputHandler = createEventListener('change');
|
|
70
|
+
var focusHandler = createEventListener('focus');
|
|
71
|
+
var blurHandler = createEventListener('blur');
|
|
72
|
+
document.addEventListener('input', inputHandler, true);
|
|
73
|
+
document.addEventListener('focusin', focusHandler, true);
|
|
74
|
+
document.addEventListener('focusout', blurHandler, true);
|
|
75
|
+
return () => {
|
|
76
|
+
document.removeEventListener('input', inputHandler, true);
|
|
77
|
+
document.removeEventListener('focusin', focusHandler, true);
|
|
78
|
+
document.removeEventListener('focusout', blurHandler, true);
|
|
79
|
+
};
|
|
80
|
+
}, []);
|
|
81
|
+
return {
|
|
82
|
+
value: snapshot.value,
|
|
83
|
+
checked: snapshot.checked,
|
|
84
|
+
options: snapshot.options,
|
|
85
|
+
files: snapshot.files,
|
|
86
|
+
register: react.useCallback(element => {
|
|
87
|
+
if (!element) {
|
|
88
|
+
inputRef.current = null;
|
|
89
|
+
} else if (dom.isFieldElement(element)) {
|
|
90
|
+
inputRef.current = element;
|
|
91
|
+
if (shouldHandleFocus) {
|
|
92
|
+
util.focusable(element);
|
|
93
|
+
}
|
|
94
|
+
if (element.type === 'checkbox' || element.type === 'radio') {
|
|
95
|
+
var _optionsRef$current$v, _optionsRef$current2;
|
|
96
|
+
// React set the value as empty string incorrectly when the value is undefined
|
|
97
|
+
// This make sure the checkbox value falls back to the default value "on" properly
|
|
98
|
+
// @see https://github.com/facebook/react/issues/17590
|
|
99
|
+
element.value = (_optionsRef$current$v = (_optionsRef$current2 = optionsRef.current) === null || _optionsRef$current2 === void 0 ? void 0 : _optionsRef$current2.value) !== null && _optionsRef$current$v !== void 0 ? _optionsRef$current$v : 'on';
|
|
100
|
+
}
|
|
101
|
+
util.initializeField(element, optionsRef.current);
|
|
102
|
+
} else {
|
|
103
|
+
var _inputs$0$name, _inputs$, _inputs$0$type, _inputs$2;
|
|
104
|
+
var inputs = Array.from(element);
|
|
105
|
+
var name = (_inputs$0$name = (_inputs$ = inputs[0]) === null || _inputs$ === void 0 ? void 0 : _inputs$.name) !== null && _inputs$0$name !== void 0 ? _inputs$0$name : '';
|
|
106
|
+
var type = (_inputs$0$type = (_inputs$2 = inputs[0]) === null || _inputs$2 === void 0 ? void 0 : _inputs$2.type) !== null && _inputs$0$type !== void 0 ? _inputs$0$type : '';
|
|
107
|
+
if (!name || !(type === 'checkbox' || type === 'radio') || !inputs.every(input => input.name === name && input.type === type)) {
|
|
108
|
+
throw new Error('You can only register a checkbox or radio group with the same name');
|
|
109
|
+
}
|
|
110
|
+
inputRef.current = inputs;
|
|
111
|
+
for (var input of inputs) {
|
|
112
|
+
var _optionsRef$current3;
|
|
113
|
+
if (shouldHandleFocus) {
|
|
114
|
+
util.focusable(input);
|
|
115
|
+
}
|
|
116
|
+
util.initializeField(input, {
|
|
117
|
+
// We will not be uitlizing defaultChecked / value on checkbox / radio group
|
|
118
|
+
defaultValue: (_optionsRef$current3 = optionsRef.current) === null || _optionsRef$current3 === void 0 ? void 0 : _optionsRef$current3.defaultValue
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}, [shouldHandleFocus]),
|
|
123
|
+
change: react.useCallback(value => {
|
|
124
|
+
if (!eventDispatched.current.change) {
|
|
125
|
+
var _inputRef$current;
|
|
126
|
+
var _element = Array.isArray(inputRef.current) ? (_inputRef$current = inputRef.current) === null || _inputRef$current === void 0 ? void 0 : _inputRef$current.find(input => {
|
|
127
|
+
var wasChecked = input.checked;
|
|
128
|
+
var isChecked = Array.isArray(value) ? value.some(item => item === input.value) : input.value === value;
|
|
129
|
+
switch (input.type) {
|
|
130
|
+
case 'checkbox':
|
|
131
|
+
// We assume that only one checkbox can be checked at a time
|
|
132
|
+
// So we will pick the first element with checked state changed
|
|
133
|
+
return wasChecked !== isChecked;
|
|
134
|
+
case 'radio':
|
|
135
|
+
// We cannot uncheck a radio button
|
|
136
|
+
// So we will pick the first element that should be checked
|
|
137
|
+
return isChecked;
|
|
138
|
+
default:
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
}) : inputRef.current;
|
|
142
|
+
if (_element) {
|
|
143
|
+
dom.unstable_change(_element, typeof value === 'boolean' ? value ? _element.value : null : value);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
if (eventDispatched.current.change) {
|
|
147
|
+
clearTimeout(eventDispatched.current.change);
|
|
148
|
+
}
|
|
149
|
+
eventDispatched.current.change = undefined;
|
|
150
|
+
}, []),
|
|
151
|
+
focus: react.useCallback(() => {
|
|
152
|
+
if (!eventDispatched.current.focus) {
|
|
153
|
+
var _element2 = Array.isArray(inputRef.current) ? inputRef.current[0] : inputRef.current;
|
|
154
|
+
if (_element2) {
|
|
155
|
+
dom.unstable_focus(_element2);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
if (eventDispatched.current.focus) {
|
|
159
|
+
clearTimeout(eventDispatched.current.focus);
|
|
160
|
+
}
|
|
161
|
+
eventDispatched.current.focus = undefined;
|
|
162
|
+
}, []),
|
|
163
|
+
blur: react.useCallback(() => {
|
|
164
|
+
if (!eventDispatched.current.blur) {
|
|
165
|
+
var _element3 = Array.isArray(inputRef.current) ? inputRef.current[0] : inputRef.current;
|
|
166
|
+
if (_element3) {
|
|
167
|
+
dom.unstable_blur(_element3);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
if (eventDispatched.current.blur) {
|
|
171
|
+
clearTimeout(eventDispatched.current.blur);
|
|
172
|
+
}
|
|
173
|
+
eventDispatched.current.blur = undefined;
|
|
174
|
+
}, [])
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
exports.formObserver = formObserver;
|
|
179
|
+
exports.useControl = useControl;
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { unstable_createGlobalFormsObserver, unstable_deepEqual, isFieldElement, unstable_change, unstable_focus, unstable_blur } from '@conform-to/dom';
|
|
2
|
+
import { useRef, useEffect, useSyncExternalStore, useCallback } from 'react';
|
|
3
|
+
import { getDefaultSnapshot, getRadioGroupValue, getCheckboxGroupValue, getInputSnapshot, focusable, initializeField } from './util.mjs';
|
|
4
|
+
|
|
5
|
+
var formObserver = unstable_createGlobalFormsObserver();
|
|
6
|
+
/**
|
|
7
|
+
* A React hook that lets you sync the state of an input and dispatch native form events from it.
|
|
8
|
+
* This is useful when emulating native input behavior — typically by rendering a hidden base input
|
|
9
|
+
* and syncing it with a custom input.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* const control = useControl(options);
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
function useControl(options) {
|
|
17
|
+
var inputRef = useRef(null);
|
|
18
|
+
var eventDispatched = useRef({});
|
|
19
|
+
var defaultSnapshot = getDefaultSnapshot(options === null || options === void 0 ? void 0 : options.defaultValue, options === null || options === void 0 ? void 0 : options.defaultChecked, options === null || options === void 0 ? void 0 : options.value);
|
|
20
|
+
var snapshotRef = useRef(defaultSnapshot);
|
|
21
|
+
var optionsRef = useRef(options);
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
optionsRef.current = options;
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
// This is necessary to ensure that input is re-registered
|
|
27
|
+
// if the onFocus handler changes
|
|
28
|
+
var shouldHandleFocus = typeof (options === null || options === void 0 ? void 0 : options.onFocus) === 'function';
|
|
29
|
+
var snapshot = useSyncExternalStore(useCallback(callback => formObserver.onFieldUpdate(event => {
|
|
30
|
+
var input = event.target;
|
|
31
|
+
if (Array.isArray(inputRef.current) ? inputRef.current.some(item => item === input) : inputRef.current === input) {
|
|
32
|
+
callback();
|
|
33
|
+
}
|
|
34
|
+
}), []), () => {
|
|
35
|
+
var input = inputRef.current;
|
|
36
|
+
var prev = snapshotRef.current;
|
|
37
|
+
var next = !input ? defaultSnapshot : Array.isArray(input) ? {
|
|
38
|
+
value: getRadioGroupValue(input),
|
|
39
|
+
options: getCheckboxGroupValue(input)
|
|
40
|
+
} : getInputSnapshot(input);
|
|
41
|
+
if (unstable_deepEqual(prev, next)) {
|
|
42
|
+
return prev;
|
|
43
|
+
}
|
|
44
|
+
snapshotRef.current = next;
|
|
45
|
+
return next;
|
|
46
|
+
}, () => snapshotRef.current);
|
|
47
|
+
useEffect(() => {
|
|
48
|
+
var createEventListener = listener => {
|
|
49
|
+
return event => {
|
|
50
|
+
if (Array.isArray(inputRef.current) ? inputRef.current.some(item => item === event.target) : inputRef.current === event.target) {
|
|
51
|
+
var timer = eventDispatched.current[listener];
|
|
52
|
+
if (timer) {
|
|
53
|
+
clearTimeout(timer);
|
|
54
|
+
}
|
|
55
|
+
eventDispatched.current[listener] = window.setTimeout(() => {
|
|
56
|
+
eventDispatched.current[listener] = undefined;
|
|
57
|
+
});
|
|
58
|
+
if (listener === 'focus') {
|
|
59
|
+
var _optionsRef$current, _optionsRef$current$o;
|
|
60
|
+
(_optionsRef$current = optionsRef.current) === null || _optionsRef$current === void 0 || (_optionsRef$current$o = _optionsRef$current.onFocus) === null || _optionsRef$current$o === void 0 || _optionsRef$current$o.call(_optionsRef$current);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
var inputHandler = createEventListener('change');
|
|
66
|
+
var focusHandler = createEventListener('focus');
|
|
67
|
+
var blurHandler = createEventListener('blur');
|
|
68
|
+
document.addEventListener('input', inputHandler, true);
|
|
69
|
+
document.addEventListener('focusin', focusHandler, true);
|
|
70
|
+
document.addEventListener('focusout', blurHandler, true);
|
|
71
|
+
return () => {
|
|
72
|
+
document.removeEventListener('input', inputHandler, true);
|
|
73
|
+
document.removeEventListener('focusin', focusHandler, true);
|
|
74
|
+
document.removeEventListener('focusout', blurHandler, true);
|
|
75
|
+
};
|
|
76
|
+
}, []);
|
|
77
|
+
return {
|
|
78
|
+
value: snapshot.value,
|
|
79
|
+
checked: snapshot.checked,
|
|
80
|
+
options: snapshot.options,
|
|
81
|
+
files: snapshot.files,
|
|
82
|
+
register: useCallback(element => {
|
|
83
|
+
if (!element) {
|
|
84
|
+
inputRef.current = null;
|
|
85
|
+
} else if (isFieldElement(element)) {
|
|
86
|
+
inputRef.current = element;
|
|
87
|
+
if (shouldHandleFocus) {
|
|
88
|
+
focusable(element);
|
|
89
|
+
}
|
|
90
|
+
if (element.type === 'checkbox' || element.type === 'radio') {
|
|
91
|
+
var _optionsRef$current$v, _optionsRef$current2;
|
|
92
|
+
// React set the value as empty string incorrectly when the value is undefined
|
|
93
|
+
// This make sure the checkbox value falls back to the default value "on" properly
|
|
94
|
+
// @see https://github.com/facebook/react/issues/17590
|
|
95
|
+
element.value = (_optionsRef$current$v = (_optionsRef$current2 = optionsRef.current) === null || _optionsRef$current2 === void 0 ? void 0 : _optionsRef$current2.value) !== null && _optionsRef$current$v !== void 0 ? _optionsRef$current$v : 'on';
|
|
96
|
+
}
|
|
97
|
+
initializeField(element, optionsRef.current);
|
|
98
|
+
} else {
|
|
99
|
+
var _inputs$0$name, _inputs$, _inputs$0$type, _inputs$2;
|
|
100
|
+
var inputs = Array.from(element);
|
|
101
|
+
var name = (_inputs$0$name = (_inputs$ = inputs[0]) === null || _inputs$ === void 0 ? void 0 : _inputs$.name) !== null && _inputs$0$name !== void 0 ? _inputs$0$name : '';
|
|
102
|
+
var type = (_inputs$0$type = (_inputs$2 = inputs[0]) === null || _inputs$2 === void 0 ? void 0 : _inputs$2.type) !== null && _inputs$0$type !== void 0 ? _inputs$0$type : '';
|
|
103
|
+
if (!name || !(type === 'checkbox' || type === 'radio') || !inputs.every(input => input.name === name && input.type === type)) {
|
|
104
|
+
throw new Error('You can only register a checkbox or radio group with the same name');
|
|
105
|
+
}
|
|
106
|
+
inputRef.current = inputs;
|
|
107
|
+
for (var input of inputs) {
|
|
108
|
+
var _optionsRef$current3;
|
|
109
|
+
if (shouldHandleFocus) {
|
|
110
|
+
focusable(input);
|
|
111
|
+
}
|
|
112
|
+
initializeField(input, {
|
|
113
|
+
// We will not be uitlizing defaultChecked / value on checkbox / radio group
|
|
114
|
+
defaultValue: (_optionsRef$current3 = optionsRef.current) === null || _optionsRef$current3 === void 0 ? void 0 : _optionsRef$current3.defaultValue
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}, [shouldHandleFocus]),
|
|
119
|
+
change: useCallback(value => {
|
|
120
|
+
if (!eventDispatched.current.change) {
|
|
121
|
+
var _inputRef$current;
|
|
122
|
+
var _element = Array.isArray(inputRef.current) ? (_inputRef$current = inputRef.current) === null || _inputRef$current === void 0 ? void 0 : _inputRef$current.find(input => {
|
|
123
|
+
var wasChecked = input.checked;
|
|
124
|
+
var isChecked = Array.isArray(value) ? value.some(item => item === input.value) : input.value === value;
|
|
125
|
+
switch (input.type) {
|
|
126
|
+
case 'checkbox':
|
|
127
|
+
// We assume that only one checkbox can be checked at a time
|
|
128
|
+
// So we will pick the first element with checked state changed
|
|
129
|
+
return wasChecked !== isChecked;
|
|
130
|
+
case 'radio':
|
|
131
|
+
// We cannot uncheck a radio button
|
|
132
|
+
// So we will pick the first element that should be checked
|
|
133
|
+
return isChecked;
|
|
134
|
+
default:
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
}) : inputRef.current;
|
|
138
|
+
if (_element) {
|
|
139
|
+
unstable_change(_element, typeof value === 'boolean' ? value ? _element.value : null : value);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
if (eventDispatched.current.change) {
|
|
143
|
+
clearTimeout(eventDispatched.current.change);
|
|
144
|
+
}
|
|
145
|
+
eventDispatched.current.change = undefined;
|
|
146
|
+
}, []),
|
|
147
|
+
focus: useCallback(() => {
|
|
148
|
+
if (!eventDispatched.current.focus) {
|
|
149
|
+
var _element2 = Array.isArray(inputRef.current) ? inputRef.current[0] : inputRef.current;
|
|
150
|
+
if (_element2) {
|
|
151
|
+
unstable_focus(_element2);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
if (eventDispatched.current.focus) {
|
|
155
|
+
clearTimeout(eventDispatched.current.focus);
|
|
156
|
+
}
|
|
157
|
+
eventDispatched.current.focus = undefined;
|
|
158
|
+
}, []),
|
|
159
|
+
blur: useCallback(() => {
|
|
160
|
+
if (!eventDispatched.current.blur) {
|
|
161
|
+
var _element3 = Array.isArray(inputRef.current) ? inputRef.current[0] : inputRef.current;
|
|
162
|
+
if (_element3) {
|
|
163
|
+
unstable_blur(_element3);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
if (eventDispatched.current.blur) {
|
|
167
|
+
clearTimeout(eventDispatched.current.blur);
|
|
168
|
+
}
|
|
169
|
+
eventDispatched.current.blur = undefined;
|
|
170
|
+
}, [])
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export { formObserver, useControl };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useControl } from './hooks.mjs';
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export declare function focusable(element: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement): void;
|
|
2
|
+
export declare function initializeField(element: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement, options: {
|
|
3
|
+
defaultValue?: string | string[] | File | File[] | null;
|
|
4
|
+
defaultChecked?: boolean;
|
|
5
|
+
value?: string;
|
|
6
|
+
} | undefined): void;
|
|
7
|
+
export declare function getRadioGroupValue(inputs: Array<HTMLInputElement>): string | undefined;
|
|
8
|
+
export declare function getCheckboxGroupValue(inputs: Array<HTMLInputElement>): string[] | undefined;
|
|
9
|
+
export type InputSnapshot = {
|
|
10
|
+
value?: string;
|
|
11
|
+
options?: string[];
|
|
12
|
+
checked?: boolean;
|
|
13
|
+
files?: File[];
|
|
14
|
+
};
|
|
15
|
+
export declare function getInputSnapshot(input: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement): {
|
|
16
|
+
files: File[] | undefined;
|
|
17
|
+
value?: undefined;
|
|
18
|
+
checked?: undefined;
|
|
19
|
+
options?: undefined;
|
|
20
|
+
} | {
|
|
21
|
+
value: string;
|
|
22
|
+
checked: boolean;
|
|
23
|
+
files?: undefined;
|
|
24
|
+
options?: undefined;
|
|
25
|
+
} | {
|
|
26
|
+
options: string[];
|
|
27
|
+
files?: undefined;
|
|
28
|
+
value?: undefined;
|
|
29
|
+
checked?: undefined;
|
|
30
|
+
} | {
|
|
31
|
+
value: string;
|
|
32
|
+
files?: undefined;
|
|
33
|
+
checked?: undefined;
|
|
34
|
+
options?: undefined;
|
|
35
|
+
};
|
|
36
|
+
export declare function getDefaultSnapshot(defaultValue: string | string[] | File | File[] | FileList | null | undefined, defaultChecked: boolean | undefined, value: string | undefined): InputSnapshot;
|
|
37
|
+
//# sourceMappingURL=util.d.ts.map
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var dom = require('@conform-to/dom');
|
|
6
|
+
|
|
7
|
+
function focusable(element) {
|
|
8
|
+
if (!element.hidden && element.type !== 'hidden') {
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// Style the element to be visually hidden
|
|
13
|
+
element.style.position = 'absolute';
|
|
14
|
+
element.style.width = '1px';
|
|
15
|
+
element.style.height = '1px';
|
|
16
|
+
element.style.padding = '0';
|
|
17
|
+
element.style.margin = '-1px';
|
|
18
|
+
element.style.overflow = 'hidden';
|
|
19
|
+
element.style.clip = 'rect(0,0,0,0)';
|
|
20
|
+
element.style.whiteSpace = 'nowrap';
|
|
21
|
+
element.style.border = '0';
|
|
22
|
+
|
|
23
|
+
// Hide the element from screen readers
|
|
24
|
+
element.setAttribute('aria-hidden', 'true');
|
|
25
|
+
|
|
26
|
+
// Make sure people won't tab to this element
|
|
27
|
+
element.tabIndex = -1;
|
|
28
|
+
|
|
29
|
+
// Set the element to be visible again so it can be focused
|
|
30
|
+
if (element.hidden) {
|
|
31
|
+
element.hidden = false;
|
|
32
|
+
}
|
|
33
|
+
if (element.type === 'hidden') {
|
|
34
|
+
element.setAttribute('type', 'text');
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function initializeField(element, options) {
|
|
38
|
+
var _options$value;
|
|
39
|
+
if (element.dataset.conform) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
var defaultValue = typeof (options === null || options === void 0 ? void 0 : options.value) === 'string' || typeof (options === null || options === void 0 ? void 0 : options.defaultChecked) === 'boolean' ? options.defaultChecked ? (_options$value = options.value) !== null && _options$value !== void 0 ? _options$value : 'on' : null : options === null || options === void 0 ? void 0 : options.defaultValue;
|
|
43
|
+
|
|
44
|
+
// Update the value of the element, including the default value
|
|
45
|
+
dom.unstable_updateField(element, {
|
|
46
|
+
value: defaultValue,
|
|
47
|
+
defaultValue
|
|
48
|
+
});
|
|
49
|
+
element.dataset.conform = 'initialized';
|
|
50
|
+
}
|
|
51
|
+
function getRadioGroupValue(inputs) {
|
|
52
|
+
for (var input of inputs) {
|
|
53
|
+
if (input.type === 'radio' && input.checked) {
|
|
54
|
+
return input.value;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function getCheckboxGroupValue(inputs) {
|
|
59
|
+
var values;
|
|
60
|
+
for (var input of inputs) {
|
|
61
|
+
if (input.type === 'checkbox') {
|
|
62
|
+
var _values;
|
|
63
|
+
(_values = values) !== null && _values !== void 0 ? _values : values = [];
|
|
64
|
+
if (input.checked) {
|
|
65
|
+
values.push(input.value);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return values;
|
|
70
|
+
}
|
|
71
|
+
function getInputSnapshot(input) {
|
|
72
|
+
if (input instanceof HTMLInputElement) {
|
|
73
|
+
switch (input.type) {
|
|
74
|
+
case 'file':
|
|
75
|
+
return {
|
|
76
|
+
files: input.files ? Array.from(input.files) : undefined
|
|
77
|
+
};
|
|
78
|
+
case 'radio':
|
|
79
|
+
case 'checkbox':
|
|
80
|
+
return {
|
|
81
|
+
value: input.value,
|
|
82
|
+
checked: input.checked
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
} else if (input instanceof HTMLSelectElement && input.multiple) {
|
|
86
|
+
return {
|
|
87
|
+
options: Array.from(input.selectedOptions).map(option => option.value)
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
value: input.value
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
function getDefaultSnapshot(defaultValue, defaultChecked, value) {
|
|
95
|
+
if (typeof value === 'string' || typeof defaultChecked === 'boolean') {
|
|
96
|
+
return {
|
|
97
|
+
value: value !== null && value !== void 0 ? value : 'on',
|
|
98
|
+
checked: defaultChecked
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
if (typeof defaultValue === 'string') {
|
|
102
|
+
return {
|
|
103
|
+
value: defaultValue
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
if (Array.isArray(defaultValue) && defaultValue.every(item => typeof item === 'string')) {
|
|
107
|
+
return {
|
|
108
|
+
options: defaultValue
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
if (defaultValue instanceof FileList) {
|
|
112
|
+
return {
|
|
113
|
+
files: Array.from(defaultValue)
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
if (Array.isArray(defaultValue)) {
|
|
117
|
+
return {
|
|
118
|
+
files: defaultValue
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
if (defaultValue) {
|
|
122
|
+
return {
|
|
123
|
+
files: [defaultValue]
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
return {};
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
exports.focusable = focusable;
|
|
130
|
+
exports.getCheckboxGroupValue = getCheckboxGroupValue;
|
|
131
|
+
exports.getDefaultSnapshot = getDefaultSnapshot;
|
|
132
|
+
exports.getInputSnapshot = getInputSnapshot;
|
|
133
|
+
exports.getRadioGroupValue = getRadioGroupValue;
|
|
134
|
+
exports.initializeField = initializeField;
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { unstable_updateField } from '@conform-to/dom';
|
|
2
|
+
|
|
3
|
+
function focusable(element) {
|
|
4
|
+
if (!element.hidden && element.type !== 'hidden') {
|
|
5
|
+
return;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
// Style the element to be visually hidden
|
|
9
|
+
element.style.position = 'absolute';
|
|
10
|
+
element.style.width = '1px';
|
|
11
|
+
element.style.height = '1px';
|
|
12
|
+
element.style.padding = '0';
|
|
13
|
+
element.style.margin = '-1px';
|
|
14
|
+
element.style.overflow = 'hidden';
|
|
15
|
+
element.style.clip = 'rect(0,0,0,0)';
|
|
16
|
+
element.style.whiteSpace = 'nowrap';
|
|
17
|
+
element.style.border = '0';
|
|
18
|
+
|
|
19
|
+
// Hide the element from screen readers
|
|
20
|
+
element.setAttribute('aria-hidden', 'true');
|
|
21
|
+
|
|
22
|
+
// Make sure people won't tab to this element
|
|
23
|
+
element.tabIndex = -1;
|
|
24
|
+
|
|
25
|
+
// Set the element to be visible again so it can be focused
|
|
26
|
+
if (element.hidden) {
|
|
27
|
+
element.hidden = false;
|
|
28
|
+
}
|
|
29
|
+
if (element.type === 'hidden') {
|
|
30
|
+
element.setAttribute('type', 'text');
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function initializeField(element, options) {
|
|
34
|
+
var _options$value;
|
|
35
|
+
if (element.dataset.conform) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
var defaultValue = typeof (options === null || options === void 0 ? void 0 : options.value) === 'string' || typeof (options === null || options === void 0 ? void 0 : options.defaultChecked) === 'boolean' ? options.defaultChecked ? (_options$value = options.value) !== null && _options$value !== void 0 ? _options$value : 'on' : null : options === null || options === void 0 ? void 0 : options.defaultValue;
|
|
39
|
+
|
|
40
|
+
// Update the value of the element, including the default value
|
|
41
|
+
unstable_updateField(element, {
|
|
42
|
+
value: defaultValue,
|
|
43
|
+
defaultValue
|
|
44
|
+
});
|
|
45
|
+
element.dataset.conform = 'initialized';
|
|
46
|
+
}
|
|
47
|
+
function getRadioGroupValue(inputs) {
|
|
48
|
+
for (var input of inputs) {
|
|
49
|
+
if (input.type === 'radio' && input.checked) {
|
|
50
|
+
return input.value;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function getCheckboxGroupValue(inputs) {
|
|
55
|
+
var values;
|
|
56
|
+
for (var input of inputs) {
|
|
57
|
+
if (input.type === 'checkbox') {
|
|
58
|
+
var _values;
|
|
59
|
+
(_values = values) !== null && _values !== void 0 ? _values : values = [];
|
|
60
|
+
if (input.checked) {
|
|
61
|
+
values.push(input.value);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return values;
|
|
66
|
+
}
|
|
67
|
+
function getInputSnapshot(input) {
|
|
68
|
+
if (input instanceof HTMLInputElement) {
|
|
69
|
+
switch (input.type) {
|
|
70
|
+
case 'file':
|
|
71
|
+
return {
|
|
72
|
+
files: input.files ? Array.from(input.files) : undefined
|
|
73
|
+
};
|
|
74
|
+
case 'radio':
|
|
75
|
+
case 'checkbox':
|
|
76
|
+
return {
|
|
77
|
+
value: input.value,
|
|
78
|
+
checked: input.checked
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
} else if (input instanceof HTMLSelectElement && input.multiple) {
|
|
82
|
+
return {
|
|
83
|
+
options: Array.from(input.selectedOptions).map(option => option.value)
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
value: input.value
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function getDefaultSnapshot(defaultValue, defaultChecked, value) {
|
|
91
|
+
if (typeof value === 'string' || typeof defaultChecked === 'boolean') {
|
|
92
|
+
return {
|
|
93
|
+
value: value !== null && value !== void 0 ? value : 'on',
|
|
94
|
+
checked: defaultChecked
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
if (typeof defaultValue === 'string') {
|
|
98
|
+
return {
|
|
99
|
+
value: defaultValue
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
if (Array.isArray(defaultValue) && defaultValue.every(item => typeof item === 'string')) {
|
|
103
|
+
return {
|
|
104
|
+
options: defaultValue
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
if (defaultValue instanceof FileList) {
|
|
108
|
+
return {
|
|
109
|
+
files: Array.from(defaultValue)
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
if (Array.isArray(defaultValue)) {
|
|
113
|
+
return {
|
|
114
|
+
files: defaultValue
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
if (defaultValue) {
|
|
118
|
+
return {
|
|
119
|
+
files: [defaultValue]
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
return {};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export { focusable, getCheckboxGroupValue, getDefaultSnapshot, getInputSnapshot, getRadioGroupValue, initializeField };
|
package/dist/integrations.js
CHANGED
|
@@ -102,7 +102,7 @@ function useInputEvent(onUpdate) {
|
|
|
102
102
|
eventDispatched.current.change = true;
|
|
103
103
|
var element = ref.current;
|
|
104
104
|
if (element) {
|
|
105
|
-
dom.
|
|
105
|
+
dom.unstable_updateField(element, {
|
|
106
106
|
value
|
|
107
107
|
});
|
|
108
108
|
|
|
@@ -223,7 +223,7 @@ function useControl(meta) {
|
|
|
223
223
|
// This is now handled mostly by the side effect
|
|
224
224
|
// But we still need to set the initial value for backward compatibility
|
|
225
225
|
if (!element.dataset.conform) {
|
|
226
|
-
dom.
|
|
226
|
+
dom.unstable_updateField(element, {
|
|
227
227
|
value
|
|
228
228
|
});
|
|
229
229
|
}
|
package/dist/integrations.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { unstable_updateField } from '@conform-to/dom';
|
|
2
2
|
import { useRef, useEffect, useMemo, useState } from 'react';
|
|
3
3
|
|
|
4
4
|
function getFormElement(formId) {
|
|
@@ -98,7 +98,7 @@ function useInputEvent(onUpdate) {
|
|
|
98
98
|
eventDispatched.current.change = true;
|
|
99
99
|
var element = ref.current;
|
|
100
100
|
if (element) {
|
|
101
|
-
|
|
101
|
+
unstable_updateField(element, {
|
|
102
102
|
value
|
|
103
103
|
});
|
|
104
104
|
|
|
@@ -219,7 +219,7 @@ function useControl(meta) {
|
|
|
219
219
|
// This is now handled mostly by the side effect
|
|
220
220
|
// But we still need to set the initial value for backward compatibility
|
|
221
221
|
if (!element.dataset.conform) {
|
|
222
|
-
|
|
222
|
+
unstable_updateField(element, {
|
|
223
223
|
value
|
|
224
224
|
});
|
|
225
225
|
}
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "Conform view adapter for react",
|
|
4
4
|
"homepage": "https://conform.guide",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"version": "1.
|
|
6
|
+
"version": "1.7.0",
|
|
7
7
|
"main": "./dist/index.js",
|
|
8
8
|
"module": "./dist/index.mjs",
|
|
9
9
|
"types": "./dist/index.d.ts",
|
|
@@ -14,6 +14,13 @@
|
|
|
14
14
|
"import": "./dist/index.mjs",
|
|
15
15
|
"require": "./dist/index.js",
|
|
16
16
|
"default": "./dist/index.mjs"
|
|
17
|
+
},
|
|
18
|
+
"./future": {
|
|
19
|
+
"types": "./dist/future/index.d.ts",
|
|
20
|
+
"module": "./dist/future/index.mjs",
|
|
21
|
+
"import": "./dist/future/index.mjs",
|
|
22
|
+
"require": "./dist/future/index.js",
|
|
23
|
+
"default": "./dist/future/index.mjs"
|
|
17
24
|
}
|
|
18
25
|
},
|
|
19
26
|
"files": [
|
|
@@ -34,7 +41,7 @@
|
|
|
34
41
|
"url": "https://github.com/edmundhung/conform/issues"
|
|
35
42
|
},
|
|
36
43
|
"dependencies": {
|
|
37
|
-
"@conform-to/dom": "1.
|
|
44
|
+
"@conform-to/dom": "1.7.0"
|
|
38
45
|
},
|
|
39
46
|
"devDependencies": {
|
|
40
47
|
"@babel/core": "^7.17.8",
|
|
@@ -46,7 +53,8 @@
|
|
|
46
53
|
"@types/react": "^18.2.43",
|
|
47
54
|
"react": "^18.2.0",
|
|
48
55
|
"rollup-plugin-copy": "^3.4.0",
|
|
49
|
-
"rollup": "^2.79.1"
|
|
56
|
+
"rollup": "^2.79.1",
|
|
57
|
+
"vitest-browser-react": "^0.1.1"
|
|
50
58
|
},
|
|
51
59
|
"peerDependencies": {
|
|
52
60
|
"react": ">=18"
|