@conform-to/react 1.7.2 → 1.8.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 +1 -1
- package/dist/future/context.d.ts +15 -0
- package/dist/future/context.js +12 -0
- package/dist/future/context.mjs +8 -0
- package/dist/future/hooks.d.ts +27 -13
- package/dist/future/hooks.js +56 -4
- package/dist/future/hooks.mjs +59 -7
- package/dist/future/index.d.ts +3 -1
- package/dist/future/index.js +6 -0
- package/dist/future/index.mjs +2 -1
- package/dist/future/util.d.ts +2 -0
- package/dist/future/util.js +12 -0
- package/dist/future/util.mjs +12 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
╚══════╝ ╚═════╝ ╚═╝ ╚══╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝
|
|
8
8
|
```
|
|
9
9
|
|
|
10
|
-
Version 1.
|
|
10
|
+
Version 1.8.1 / 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
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare const FormContext: import("react").Context<{
|
|
2
|
+
observer: {
|
|
3
|
+
onFieldUpdate(callback: (event: {
|
|
4
|
+
type: "input" | "reset" | "mutation";
|
|
5
|
+
target: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement;
|
|
6
|
+
}) => void): () => void;
|
|
7
|
+
onFormUpdate(callback: (event: {
|
|
8
|
+
type: "submit" | "input" | "reset" | "mutation";
|
|
9
|
+
target: HTMLFormElement;
|
|
10
|
+
submitter?: HTMLInputElement | HTMLButtonElement | null;
|
|
11
|
+
}) => void): () => void;
|
|
12
|
+
dispose(): void;
|
|
13
|
+
};
|
|
14
|
+
}>;
|
|
15
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var react = require('react');
|
|
6
|
+
var dom = require('@conform-to/dom');
|
|
7
|
+
|
|
8
|
+
var FormContext = /*#__PURE__*/react.createContext({
|
|
9
|
+
observer: dom.unstable_createGlobalFormsObserver()
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
exports.FormContext = FormContext;
|
package/dist/future/hooks.d.ts
CHANGED
|
@@ -1,15 +1,4 @@
|
|
|
1
|
-
|
|
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
|
-
};
|
|
1
|
+
import { type FormRef } from './util';
|
|
13
2
|
export type Control = {
|
|
14
3
|
/**
|
|
15
4
|
* Current value of the base input. Undefined if the registered input
|
|
@@ -40,7 +29,7 @@ export type Control = {
|
|
|
40
29
|
* both [change](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event) and
|
|
41
30
|
* [input](https://developer.mozilla.org/en-US/docs/Web/API/Element/input_event) events.
|
|
42
31
|
*/
|
|
43
|
-
change(value: string | string[] | boolean | File | File[] | FileList): void;
|
|
32
|
+
change(value: string | string[] | boolean | File | File[] | FileList | null): void;
|
|
44
33
|
/**
|
|
45
34
|
* Emits [blur](https://developer.mozilla.org/en-US/docs/Web/API/Element/blur_event) and
|
|
46
35
|
* [focusout](https://developer.mozilla.org/en-US/docs/Web/API/Element/focusout_event) events.
|
|
@@ -87,4 +76,29 @@ export declare function useControl(options?: {
|
|
|
87
76
|
*/
|
|
88
77
|
onFocus?: () => void;
|
|
89
78
|
}): Control;
|
|
79
|
+
type Selector<FormValue, Result> = (formData: FormValue | null, lastResult: Result | undefined) => Result;
|
|
80
|
+
type UseFormDataOptions = {
|
|
81
|
+
/**
|
|
82
|
+
* Set to `true` to preserve file inputs and receive a `FormData` object in the selector.
|
|
83
|
+
* If omitted or `false`, the selector receives a `URLSearchParams` object, where all values are coerced to strings.
|
|
84
|
+
*/
|
|
85
|
+
acceptFiles?: boolean;
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* A React hook that lets you subscribe to the current `FormData` of a form and derive a custom value from it.
|
|
89
|
+
* The selector runs whenever the form's structure or data changes, and the hook re-renders only when the result is deeply different.
|
|
90
|
+
*
|
|
91
|
+
* @see https://conform.guide/api/react/future/useFormData
|
|
92
|
+
* @example
|
|
93
|
+
* ```ts
|
|
94
|
+
* const value = useFormData(formRef, formData => formData?.get('fieldName').toString() ?? '');
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
97
|
+
export declare function useFormData<Value = any>(formRef: FormRef, select: Selector<FormData, Value>, options: UseFormDataOptions & {
|
|
98
|
+
acceptFiles: true;
|
|
99
|
+
}): Value;
|
|
100
|
+
export declare function useFormData<Value = any>(formRef: FormRef, select: Selector<URLSearchParams, Value>, options?: UseFormDataOptions & {
|
|
101
|
+
acceptFiles?: boolean;
|
|
102
|
+
}): Value;
|
|
103
|
+
export {};
|
|
90
104
|
//# sourceMappingURL=hooks.d.ts.map
|
package/dist/future/hooks.js
CHANGED
|
@@ -5,8 +5,8 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
5
5
|
var dom = require('@conform-to/dom');
|
|
6
6
|
var react = require('react');
|
|
7
7
|
var util = require('./util.js');
|
|
8
|
+
var context = require('./context.js');
|
|
8
9
|
|
|
9
|
-
var formObserver = dom.unstable_createGlobalFormsObserver();
|
|
10
10
|
/**
|
|
11
11
|
* A React hook that lets you sync the state of an input and dispatch native form events from it.
|
|
12
12
|
* This is useful when emulating native input behavior — typically by rendering a hidden base input
|
|
@@ -18,6 +18,9 @@ var formObserver = dom.unstable_createGlobalFormsObserver();
|
|
|
18
18
|
* ```
|
|
19
19
|
*/
|
|
20
20
|
function useControl(options) {
|
|
21
|
+
var {
|
|
22
|
+
observer
|
|
23
|
+
} = react.useContext(context.FormContext);
|
|
21
24
|
var inputRef = react.useRef(null);
|
|
22
25
|
var eventDispatched = react.useRef({});
|
|
23
26
|
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);
|
|
@@ -30,12 +33,12 @@ function useControl(options) {
|
|
|
30
33
|
// This is necessary to ensure that input is re-registered
|
|
31
34
|
// if the onFocus handler changes
|
|
32
35
|
var shouldHandleFocus = typeof (options === null || options === void 0 ? void 0 : options.onFocus) === 'function';
|
|
33
|
-
var snapshot = react.useSyncExternalStore(react.useCallback(callback =>
|
|
36
|
+
var snapshot = react.useSyncExternalStore(react.useCallback(callback => observer.onFieldUpdate(event => {
|
|
34
37
|
var input = event.target;
|
|
35
38
|
if (Array.isArray(inputRef.current) ? inputRef.current.some(item => item === input) : inputRef.current === input) {
|
|
36
39
|
callback();
|
|
37
40
|
}
|
|
38
|
-
}), []), () => {
|
|
41
|
+
}), [observer]), () => {
|
|
39
42
|
var input = inputRef.current;
|
|
40
43
|
var prev = snapshotRef.current;
|
|
41
44
|
var next = !input ? defaultSnapshot : Array.isArray(input) ? {
|
|
@@ -175,5 +178,54 @@ function useControl(options) {
|
|
|
175
178
|
};
|
|
176
179
|
}
|
|
177
180
|
|
|
178
|
-
|
|
181
|
+
/**
|
|
182
|
+
* A React hook that lets you subscribe to the current `FormData` of a form and derive a custom value from it.
|
|
183
|
+
* The selector runs whenever the form's structure or data changes, and the hook re-renders only when the result is deeply different.
|
|
184
|
+
*
|
|
185
|
+
* @see https://conform.guide/api/react/future/useFormData
|
|
186
|
+
* @example
|
|
187
|
+
* ```ts
|
|
188
|
+
* const value = useFormData(formRef, formData => formData?.get('fieldName').toString() ?? '');
|
|
189
|
+
* ```
|
|
190
|
+
*/
|
|
191
|
+
|
|
192
|
+
function useFormData(formRef, select, options) {
|
|
193
|
+
var {
|
|
194
|
+
observer
|
|
195
|
+
} = react.useContext(context.FormContext);
|
|
196
|
+
var valueRef = react.useRef();
|
|
197
|
+
var formDataRef = react.useRef(null);
|
|
198
|
+
var value = react.useSyncExternalStore(react.useCallback(callback => {
|
|
199
|
+
var formElement = util.getFormElement(formRef);
|
|
200
|
+
if (formElement) {
|
|
201
|
+
var _formData = dom.getFormData(formElement);
|
|
202
|
+
formDataRef.current = options !== null && options !== void 0 && options.acceptFiles ? _formData : new URLSearchParams(Array.from(_formData).map(_ref => {
|
|
203
|
+
var [key, value] = _ref;
|
|
204
|
+
return [key, value.toString()];
|
|
205
|
+
}));
|
|
206
|
+
}
|
|
207
|
+
var unsubscribe = observer.onFormUpdate(event => {
|
|
208
|
+
if (event.target === util.getFormElement(formRef)) {
|
|
209
|
+
var _formData2 = dom.getFormData(event.target, event.submitter);
|
|
210
|
+
formDataRef.current = options !== null && options !== void 0 && options.acceptFiles ? _formData2 : new URLSearchParams(Array.from(_formData2).map(_ref2 => {
|
|
211
|
+
var [key, value] = _ref2;
|
|
212
|
+
return [key, value.toString()];
|
|
213
|
+
}));
|
|
214
|
+
callback();
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
return unsubscribe;
|
|
218
|
+
}, [observer, formRef, options === null || options === void 0 ? void 0 : options.acceptFiles]), () => {
|
|
219
|
+
// @ts-expect-error FIXME
|
|
220
|
+
var result = select(formDataRef.current, valueRef.current);
|
|
221
|
+
if (typeof valueRef.current !== 'undefined' && dom.unstable_deepEqual(result, valueRef.current)) {
|
|
222
|
+
return valueRef.current;
|
|
223
|
+
}
|
|
224
|
+
valueRef.current = result;
|
|
225
|
+
return result;
|
|
226
|
+
}, () => select(null, undefined));
|
|
227
|
+
return value;
|
|
228
|
+
}
|
|
229
|
+
|
|
179
230
|
exports.useControl = useControl;
|
|
231
|
+
exports.useFormData = useFormData;
|
package/dist/future/hooks.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { useRef, useEffect, useSyncExternalStore, useCallback } from 'react';
|
|
3
|
-
import { getDefaultSnapshot, getRadioGroupValue, getCheckboxGroupValue, getInputSnapshot, focusable, initializeField } from './util.mjs';
|
|
1
|
+
import { unstable_deepEqual, isFieldElement, unstable_change, unstable_focus, unstable_blur, getFormData } from '@conform-to/dom';
|
|
2
|
+
import { useContext, useRef, useEffect, useSyncExternalStore, useCallback } from 'react';
|
|
3
|
+
import { getDefaultSnapshot, getRadioGroupValue, getCheckboxGroupValue, getInputSnapshot, focusable, initializeField, getFormElement } from './util.mjs';
|
|
4
|
+
import { FormContext } from './context.mjs';
|
|
4
5
|
|
|
5
|
-
var formObserver = unstable_createGlobalFormsObserver();
|
|
6
6
|
/**
|
|
7
7
|
* A React hook that lets you sync the state of an input and dispatch native form events from it.
|
|
8
8
|
* This is useful when emulating native input behavior — typically by rendering a hidden base input
|
|
@@ -14,6 +14,9 @@ var formObserver = unstable_createGlobalFormsObserver();
|
|
|
14
14
|
* ```
|
|
15
15
|
*/
|
|
16
16
|
function useControl(options) {
|
|
17
|
+
var {
|
|
18
|
+
observer
|
|
19
|
+
} = useContext(FormContext);
|
|
17
20
|
var inputRef = useRef(null);
|
|
18
21
|
var eventDispatched = useRef({});
|
|
19
22
|
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);
|
|
@@ -26,12 +29,12 @@ function useControl(options) {
|
|
|
26
29
|
// This is necessary to ensure that input is re-registered
|
|
27
30
|
// if the onFocus handler changes
|
|
28
31
|
var shouldHandleFocus = typeof (options === null || options === void 0 ? void 0 : options.onFocus) === 'function';
|
|
29
|
-
var snapshot = useSyncExternalStore(useCallback(callback =>
|
|
32
|
+
var snapshot = useSyncExternalStore(useCallback(callback => observer.onFieldUpdate(event => {
|
|
30
33
|
var input = event.target;
|
|
31
34
|
if (Array.isArray(inputRef.current) ? inputRef.current.some(item => item === input) : inputRef.current === input) {
|
|
32
35
|
callback();
|
|
33
36
|
}
|
|
34
|
-
}), []), () => {
|
|
37
|
+
}), [observer]), () => {
|
|
35
38
|
var input = inputRef.current;
|
|
36
39
|
var prev = snapshotRef.current;
|
|
37
40
|
var next = !input ? defaultSnapshot : Array.isArray(input) ? {
|
|
@@ -171,4 +174,53 @@ function useControl(options) {
|
|
|
171
174
|
};
|
|
172
175
|
}
|
|
173
176
|
|
|
174
|
-
|
|
177
|
+
/**
|
|
178
|
+
* A React hook that lets you subscribe to the current `FormData` of a form and derive a custom value from it.
|
|
179
|
+
* The selector runs whenever the form's structure or data changes, and the hook re-renders only when the result is deeply different.
|
|
180
|
+
*
|
|
181
|
+
* @see https://conform.guide/api/react/future/useFormData
|
|
182
|
+
* @example
|
|
183
|
+
* ```ts
|
|
184
|
+
* const value = useFormData(formRef, formData => formData?.get('fieldName').toString() ?? '');
|
|
185
|
+
* ```
|
|
186
|
+
*/
|
|
187
|
+
|
|
188
|
+
function useFormData(formRef, select, options) {
|
|
189
|
+
var {
|
|
190
|
+
observer
|
|
191
|
+
} = useContext(FormContext);
|
|
192
|
+
var valueRef = useRef();
|
|
193
|
+
var formDataRef = useRef(null);
|
|
194
|
+
var value = useSyncExternalStore(useCallback(callback => {
|
|
195
|
+
var formElement = getFormElement(formRef);
|
|
196
|
+
if (formElement) {
|
|
197
|
+
var _formData = getFormData(formElement);
|
|
198
|
+
formDataRef.current = options !== null && options !== void 0 && options.acceptFiles ? _formData : new URLSearchParams(Array.from(_formData).map(_ref => {
|
|
199
|
+
var [key, value] = _ref;
|
|
200
|
+
return [key, value.toString()];
|
|
201
|
+
}));
|
|
202
|
+
}
|
|
203
|
+
var unsubscribe = observer.onFormUpdate(event => {
|
|
204
|
+
if (event.target === getFormElement(formRef)) {
|
|
205
|
+
var _formData2 = getFormData(event.target, event.submitter);
|
|
206
|
+
formDataRef.current = options !== null && options !== void 0 && options.acceptFiles ? _formData2 : new URLSearchParams(Array.from(_formData2).map(_ref2 => {
|
|
207
|
+
var [key, value] = _ref2;
|
|
208
|
+
return [key, value.toString()];
|
|
209
|
+
}));
|
|
210
|
+
callback();
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
return unsubscribe;
|
|
214
|
+
}, [observer, formRef, options === null || options === void 0 ? void 0 : options.acceptFiles]), () => {
|
|
215
|
+
// @ts-expect-error FIXME
|
|
216
|
+
var result = select(formDataRef.current, valueRef.current);
|
|
217
|
+
if (typeof valueRef.current !== 'undefined' && unstable_deepEqual(result, valueRef.current)) {
|
|
218
|
+
return valueRef.current;
|
|
219
|
+
}
|
|
220
|
+
valueRef.current = result;
|
|
221
|
+
return result;
|
|
222
|
+
}, () => select(null, undefined));
|
|
223
|
+
return value;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
export { useControl, useFormData };
|
package/dist/future/index.d.ts
CHANGED
package/dist/future/index.js
CHANGED
|
@@ -2,8 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
+
var dom = require('@conform-to/dom');
|
|
5
6
|
var hooks = require('./hooks.js');
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
|
|
10
|
+
Object.defineProperty(exports, 'isDirty', {
|
|
11
|
+
enumerable: true,
|
|
12
|
+
get: function () { return dom.unstable_isDirty; }
|
|
13
|
+
});
|
|
9
14
|
exports.useControl = hooks.useControl;
|
|
15
|
+
exports.useFormData = hooks.useFormData;
|
package/dist/future/index.mjs
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { unstable_isDirty as isDirty } from '@conform-to/dom';
|
|
2
|
+
export { useControl, useFormData } from './hooks.mjs';
|
package/dist/future/util.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
export type FormRef = React.RefObject<HTMLFormElement | HTMLFieldSetElement | HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement | HTMLButtonElement | null> | string;
|
|
2
|
+
export declare function getFormElement(formRef: FormRef | undefined): HTMLFormElement | null;
|
|
1
3
|
export declare function focusable(element: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement): void;
|
|
2
4
|
export declare function initializeField(element: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement, options: {
|
|
3
5
|
defaultValue?: string | string[] | File | File[] | null;
|
package/dist/future/util.js
CHANGED
|
@@ -4,6 +4,17 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
4
4
|
|
|
5
5
|
var dom = require('@conform-to/dom');
|
|
6
6
|
|
|
7
|
+
function getFormElement(formRef) {
|
|
8
|
+
var _element$form;
|
|
9
|
+
if (typeof formRef === 'string') {
|
|
10
|
+
return document.forms.namedItem(formRef);
|
|
11
|
+
}
|
|
12
|
+
var element = formRef === null || formRef === void 0 ? void 0 : formRef.current;
|
|
13
|
+
if (element instanceof HTMLFormElement) {
|
|
14
|
+
return element;
|
|
15
|
+
}
|
|
16
|
+
return (_element$form = element === null || element === void 0 ? void 0 : element.form) !== null && _element$form !== void 0 ? _element$form : null;
|
|
17
|
+
}
|
|
7
18
|
function focusable(element) {
|
|
8
19
|
if (!element.hidden && element.type !== 'hidden') {
|
|
9
20
|
return;
|
|
@@ -130,6 +141,7 @@ function getDefaultSnapshot(defaultValue, defaultChecked, value) {
|
|
|
130
141
|
exports.focusable = focusable;
|
|
131
142
|
exports.getCheckboxGroupValue = getCheckboxGroupValue;
|
|
132
143
|
exports.getDefaultSnapshot = getDefaultSnapshot;
|
|
144
|
+
exports.getFormElement = getFormElement;
|
|
133
145
|
exports.getInputSnapshot = getInputSnapshot;
|
|
134
146
|
exports.getRadioGroupValue = getRadioGroupValue;
|
|
135
147
|
exports.initializeField = initializeField;
|
package/dist/future/util.mjs
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
import { unstable_updateField, isGlobalInstance } from '@conform-to/dom';
|
|
2
2
|
|
|
3
|
+
function getFormElement(formRef) {
|
|
4
|
+
var _element$form;
|
|
5
|
+
if (typeof formRef === 'string') {
|
|
6
|
+
return document.forms.namedItem(formRef);
|
|
7
|
+
}
|
|
8
|
+
var element = formRef === null || formRef === void 0 ? void 0 : formRef.current;
|
|
9
|
+
if (element instanceof HTMLFormElement) {
|
|
10
|
+
return element;
|
|
11
|
+
}
|
|
12
|
+
return (_element$form = element === null || element === void 0 ? void 0 : element.form) !== null && _element$form !== void 0 ? _element$form : null;
|
|
13
|
+
}
|
|
3
14
|
function focusable(element) {
|
|
4
15
|
if (!element.hidden && element.type !== 'hidden') {
|
|
5
16
|
return;
|
|
@@ -123,4 +134,4 @@ function getDefaultSnapshot(defaultValue, defaultChecked, value) {
|
|
|
123
134
|
return {};
|
|
124
135
|
}
|
|
125
136
|
|
|
126
|
-
export { focusable, getCheckboxGroupValue, getDefaultSnapshot, getInputSnapshot, getRadioGroupValue, initializeField };
|
|
137
|
+
export { focusable, getCheckboxGroupValue, getDefaultSnapshot, getFormElement, getInputSnapshot, getRadioGroupValue, initializeField };
|
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.8.1",
|
|
7
7
|
"main": "./dist/index.js",
|
|
8
8
|
"module": "./dist/index.mjs",
|
|
9
9
|
"types": "./dist/index.d.ts",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"url": "https://github.com/edmundhung/conform/issues"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@conform-to/dom": "1.
|
|
44
|
+
"@conform-to/dom": "1.8.1"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@babel/core": "^7.17.8",
|