remix-validated-form 4.1.9 → 4.3.1-beta.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/.turbo/turbo-build.log +15 -9
- package/README.md +8 -5
- package/browser/ValidatedForm.js +6 -2
- package/browser/hooks.d.ts +2 -0
- package/browser/hooks.js +10 -0
- package/browser/internal/MultiValueMap.d.ts +2 -0
- package/browser/internal/MultiValueMap.js +4 -0
- package/browser/internal/getInputProps.js +2 -1
- package/browser/internal/logic/getRadioChecked.js +10 -0
- package/browser/internal/reset.d.ts +28 -0
- package/browser/internal/reset.js +13 -0
- package/browser/internal/state/controlledFields.d.ts +62 -5
- package/browser/internal/state/controlledFields.js +37 -21
- package/browser/internal/state.d.ts +0 -27
- package/browser/internal/state.js +0 -5
- package/browser/server.d.ts +1 -1
- package/browser/server.js +2 -2
- package/browser/unreleased/formStateHooks.d.ts +0 -0
- package/browser/unreleased/formStateHooks.js +0 -0
- package/dist/remix-validated-form.cjs.js +1 -0
- package/dist/remix-validated-form.es.js +3535 -0
- package/dist/remix-validated-form.umd.js +1 -0
- package/{build → dist/types}/ValidatedForm.d.ts +0 -0
- package/{build → dist/types}/hooks.d.ts +2 -0
- package/{build → dist/types}/index.d.ts +0 -0
- package/{build → dist/types}/internal/MultiValueMap.d.ts +2 -0
- package/{build → dist/types}/internal/constants.d.ts +0 -0
- package/{build → dist/types}/internal/flatten.d.ts +0 -0
- package/{build → dist/types}/internal/formContext.d.ts +0 -0
- package/{build → dist/types}/internal/getInputProps.d.ts +0 -0
- package/{build → dist/types}/internal/hooks.d.ts +0 -0
- package/{build → dist/types}/internal/hydratable.d.ts +0 -0
- package/{build → dist/types}/internal/logic/getCheckboxChecked.d.ts +0 -0
- package/{build → dist/types}/internal/logic/getRadioChecked.d.ts +0 -0
- package/dist/types/internal/reset.d.ts +28 -0
- package/{build → dist/types}/internal/state/atomUtils.d.ts +0 -0
- package/dist/types/internal/state/controlledFields.d.ts +119 -0
- package/{build → dist/types}/internal/state.d.ts +0 -27
- package/{build → dist/types}/internal/submissionCallbacks.d.ts +0 -0
- package/{build → dist/types}/internal/util.d.ts +0 -0
- package/{build → dist/types}/server.d.ts +1 -1
- package/{build → dist/types}/unreleased/formStateHooks.d.ts +0 -0
- package/{build → dist/types}/userFacingFormContext.d.ts +0 -0
- package/{build → dist/types}/validation/createValidator.d.ts +0 -0
- package/{build → dist/types}/validation/types.d.ts +0 -0
- package/package.json +8 -7
- package/src/ValidatedForm.tsx +6 -2
- package/src/hooks.ts +15 -0
- package/src/internal/MultiValueMap.ts +6 -0
- package/src/internal/getInputProps.test.ts +251 -0
- package/src/internal/getInputProps.ts +2 -1
- package/src/internal/logic/getRadioChecked.ts +11 -0
- package/src/internal/reset.ts +26 -0
- package/src/internal/state/controlledFields.ts +170 -0
- package/src/internal/state.ts +0 -8
- package/src/server.ts +3 -2
- package/src/validation/validation.test.ts +304 -0
- package/tsconfig.json +4 -1
- package/vite.config.ts +7 -0
- package/.turbo/turbo-test.log +0 -11
- package/browser/components.d.ts +0 -7
- package/browser/components.js +0 -10
- package/browser/internal/SingleTypeMultiValueMap.d.ts +0 -9
- package/browser/internal/SingleTypeMultiValueMap.js +0 -41
- package/browser/internal/customState.d.ts +0 -105
- package/browser/internal/customState.js +0 -46
- package/browser/internal/hooks-valtio.d.ts +0 -18
- package/browser/internal/hooks-valtio.js +0 -110
- package/browser/internal/hooks-zustand.d.ts +0 -16
- package/browser/internal/hooks-zustand.js +0 -100
- package/browser/internal/immerMiddleware.d.ts +0 -6
- package/browser/internal/immerMiddleware.js +0 -7
- package/browser/internal/logic/elementUtils.d.ts +0 -3
- package/browser/internal/logic/elementUtils.js +0 -3
- package/browser/internal/logic/getCheckboxChecked copy.d.ts +0 -1
- package/browser/internal/logic/getCheckboxChecked copy.js +0 -9
- package/browser/internal/logic/setFieldValue.d.ts +0 -1
- package/browser/internal/logic/setFieldValue.js +0 -40
- package/browser/internal/logic/setInputValueInForm.d.ts +0 -1
- package/browser/internal/logic/setInputValueInForm.js +0 -77
- package/browser/internal/setFieldValue.d.ts +0 -20
- package/browser/internal/setFieldValue.js +0 -83
- package/browser/internal/setFormValues.d.ts +0 -2
- package/browser/internal/setFormValues.js +0 -26
- package/browser/internal/state/setFieldValue.d.ts +0 -0
- package/browser/internal/state/setFieldValue.js +0 -1
- package/browser/internal/state-valtio.d.ts +0 -62
- package/browser/internal/state-valtio.js +0 -69
- package/browser/internal/state-zustand.d.ts +0 -47
- package/browser/internal/state-zustand.js +0 -85
- package/browser/internal/test.d.ts +0 -0
- package/browser/internal/test.js +0 -15
- package/browser/internal/useMultiValueMap.d.ts +0 -1
- package/browser/internal/useMultiValueMap.js +0 -11
- package/browser/internal/watch.d.ts +0 -18
- package/browser/internal/watch.js +0 -122
- package/browser/lowLevelHooks.d.ts +0 -0
- package/browser/lowLevelHooks.js +0 -1
- package/browser/test-data/testFormData.d.ts +0 -15
- package/browser/test-data/testFormData.js +0 -46
- package/browser/types.d.ts +0 -1
- package/browser/types.js +0 -1
- package/browser/validation/validation.test.d.ts +0 -1
- package/browser/validation/validation.test.js +0 -274
- package/browser/validation/withYup.d.ts +0 -6
- package/browser/validation/withYup.js +0 -40
- package/browser/validation/withZod.d.ts +0 -6
- package/browser/validation/withZod.js +0 -50
- package/build/ValidatedForm.js +0 -257
- package/build/hooks.js +0 -79
- package/build/index.js +0 -18
- package/build/internal/MultiValueMap.js +0 -44
- package/build/internal/SingleTypeMultiValueMap.d.ts +0 -8
- package/build/internal/SingleTypeMultiValueMap.js +0 -45
- package/build/internal/constants.js +0 -7
- package/build/internal/flatten.js +0 -14
- package/build/internal/formContext.js +0 -5
- package/build/internal/getInputProps.js +0 -57
- package/build/internal/hooks-valtio.d.ts +0 -18
- package/build/internal/hooks-valtio.js +0 -128
- package/build/internal/hooks-zustand.d.ts +0 -16
- package/build/internal/hooks-zustand.js +0 -117
- package/build/internal/hooks.js +0 -128
- package/build/internal/hydratable.js +0 -17
- package/build/internal/immerMiddleware.d.ts +0 -6
- package/build/internal/immerMiddleware.js +0 -14
- package/build/internal/logic/elementUtils.d.ts +0 -3
- package/build/internal/logic/elementUtils.js +0 -9
- package/build/internal/logic/getCheckboxChecked.js +0 -13
- package/build/internal/logic/getRadioChecked.js +0 -9
- package/build/internal/logic/setFieldValue.d.ts +0 -1
- package/build/internal/logic/setFieldValue.js +0 -47
- package/build/internal/logic/setInputValueInForm.d.ts +0 -1
- package/build/internal/logic/setInputValueInForm.js +0 -84
- package/build/internal/setFormValues.d.ts +0 -2
- package/build/internal/setFormValues.js +0 -33
- package/build/internal/state/atomUtils.js +0 -13
- package/build/internal/state/controlledFields.d.ts +0 -62
- package/build/internal/state/controlledFields.js +0 -85
- package/build/internal/state-valtio.d.ts +0 -62
- package/build/internal/state-valtio.js +0 -83
- package/build/internal/state-zustand.d.ts +0 -47
- package/build/internal/state-zustand.js +0 -91
- package/build/internal/state.js +0 -76
- package/build/internal/submissionCallbacks.js +0 -17
- package/build/internal/test.d.ts +0 -1
- package/build/internal/test.js +0 -12
- package/build/internal/util.js +0 -41
- package/build/internal/watch.d.ts +0 -20
- package/build/internal/watch.js +0 -126
- package/build/server.js +0 -32
- package/build/types.d.ts +0 -1
- package/build/types.js +0 -2
- package/build/unreleased/formStateHooks.js +0 -59
- package/build/userFacingFormContext.js +0 -30
- package/build/validation/createValidator.js +0 -45
- package/build/validation/types.js +0 -2
@@ -1,69 +0,0 @@
|
|
1
|
-
import { proxy, useSnapshot } from "valtio";
|
2
|
-
export const state = proxy({ forms: {} });
|
3
|
-
export const registerFormSlice = (formId, { registerReceiveFocus, setFieldValueForForm, validateField, action, defaultValues, subaction, }) => {
|
4
|
-
state.forms[formId] = {
|
5
|
-
hydrated: true,
|
6
|
-
defaultValues: defaultValues !== null && defaultValues !== void 0 ? defaultValues : {},
|
7
|
-
fieldErrors: {},
|
8
|
-
hasBeenSubmitted: false,
|
9
|
-
isSubmitting: false,
|
10
|
-
touchedFields: {},
|
11
|
-
registerReceiveFocus,
|
12
|
-
setFieldValue: setFieldValueForForm,
|
13
|
-
validateField,
|
14
|
-
action,
|
15
|
-
subaction,
|
16
|
-
};
|
17
|
-
};
|
18
|
-
export const unregisterFormSlice = (formId) => {
|
19
|
-
delete state.forms[formId];
|
20
|
-
};
|
21
|
-
const unhydratedFormState = {
|
22
|
-
hydrated: false,
|
23
|
-
fieldErrors: {},
|
24
|
-
isSubmitting: false,
|
25
|
-
hasBeenSubmitted: false,
|
26
|
-
touchedFields: {},
|
27
|
-
defaultValues: {},
|
28
|
-
validateField: () => Promise.resolve(null),
|
29
|
-
registerReceiveFocus: () => () => { },
|
30
|
-
setFieldValue: () => { },
|
31
|
-
};
|
32
|
-
export const useFormData = (formId) => {
|
33
|
-
var _a;
|
34
|
-
const snapshot = useSnapshot(state);
|
35
|
-
return (_a = snapshot.forms[formId]) !== null && _a !== void 0 ? _a : unhydratedFormState;
|
36
|
-
};
|
37
|
-
export const startSubmit = (formId) => {
|
38
|
-
state.forms[formId].isSubmitting = true;
|
39
|
-
state.forms[formId].hasBeenSubmitted = true;
|
40
|
-
};
|
41
|
-
export const endSubmit = (formId) => {
|
42
|
-
state.forms[formId].isSubmitting = false;
|
43
|
-
};
|
44
|
-
export const sync = (formId, { defaultValues, action, subaction, registerReceiveFocus, validateField, setFieldValueForForm, }) => {
|
45
|
-
state.forms[formId].defaultValues = defaultValues !== null && defaultValues !== void 0 ? defaultValues : {};
|
46
|
-
state.forms[formId].action = action;
|
47
|
-
state.forms[formId].subaction = subaction;
|
48
|
-
state.forms[formId].registerReceiveFocus = registerReceiveFocus;
|
49
|
-
state.forms[formId].validateField = validateField;
|
50
|
-
state.forms[formId].hydrated = true;
|
51
|
-
state.forms[formId].setFieldValue = setFieldValueForForm;
|
52
|
-
};
|
53
|
-
export const clearError = (formId, fieldName) => {
|
54
|
-
delete state.forms[formId].fieldErrors[fieldName];
|
55
|
-
};
|
56
|
-
export const addError = (formId, fieldName, error) => {
|
57
|
-
state.forms[formId].fieldErrors[fieldName] = error;
|
58
|
-
};
|
59
|
-
export const setTouched = (formId, fieldName, touched) => {
|
60
|
-
state.forms[formId].touchedFields[fieldName] = touched;
|
61
|
-
};
|
62
|
-
export const reset = (formId) => {
|
63
|
-
state.forms[formId].fieldErrors = {};
|
64
|
-
state.forms[formId].touchedFields = {};
|
65
|
-
state.forms[formId].hasBeenSubmitted = false;
|
66
|
-
};
|
67
|
-
export const setFieldErrors = (formId, fieldErrors) => {
|
68
|
-
state.forms[formId].fieldErrors = fieldErrors;
|
69
|
-
};
|
@@ -1,47 +0,0 @@
|
|
1
|
-
import { FieldErrors, TouchedFields } from "..";
|
2
|
-
export declare type InternalFormState = {
|
3
|
-
hydrated: boolean;
|
4
|
-
fieldErrors: FieldErrors;
|
5
|
-
isSubmitting: boolean;
|
6
|
-
hasBeenSubmitted: boolean;
|
7
|
-
touchedFields: TouchedFields;
|
8
|
-
action?: string;
|
9
|
-
subaction?: string;
|
10
|
-
defaultValues: {
|
11
|
-
[fieldName: string]: any;
|
12
|
-
};
|
13
|
-
validateField: (fieldName: string) => Promise<string | null>;
|
14
|
-
registerReceiveFocus: (fieldName: string, handler: () => void) => () => void;
|
15
|
-
setFieldValue: (fieldName: string, value: unknown) => void;
|
16
|
-
};
|
17
|
-
declare type Helpers = {
|
18
|
-
startSubmit: () => void;
|
19
|
-
endSubmit: () => void;
|
20
|
-
sync: (args: SyncFormArgs) => void;
|
21
|
-
clearError: (name: string) => void;
|
22
|
-
addError: (name: string, error: string) => void;
|
23
|
-
setTouched: (name: string, touched: boolean) => void;
|
24
|
-
reset: () => void;
|
25
|
-
setFieldErrors: (fieldErrors: FieldErrors) => void;
|
26
|
-
register: (init: SyncFormArgs) => void;
|
27
|
-
unregister: () => void;
|
28
|
-
};
|
29
|
-
declare type SyncFormArgs = {
|
30
|
-
defaultValues?: {
|
31
|
-
[fieldName: string]: any;
|
32
|
-
};
|
33
|
-
action?: string;
|
34
|
-
subaction?: string;
|
35
|
-
validateField: InternalFormState["validateField"];
|
36
|
-
registerReceiveFocus: InternalFormState["registerReceiveFocus"];
|
37
|
-
setFieldValueForForm: InternalFormState["setFieldValue"];
|
38
|
-
};
|
39
|
-
declare type StoreState = {
|
40
|
-
forms: {
|
41
|
-
[formId: string | symbol]: InternalFormState;
|
42
|
-
};
|
43
|
-
form: (formId: string | symbol) => InternalFormState;
|
44
|
-
helpers: (formId: string | symbol) => Helpers;
|
45
|
-
};
|
46
|
-
export declare const useStore: import("zustand").UseBoundStore<StoreState, import("zustand").StoreApi<StoreState>>;
|
47
|
-
export {};
|
@@ -1,85 +0,0 @@
|
|
1
|
-
import create from "zustand";
|
2
|
-
import { immer } from "./immerMiddleware";
|
3
|
-
const unhydratedFormState = {
|
4
|
-
hydrated: false,
|
5
|
-
fieldErrors: {},
|
6
|
-
isSubmitting: false,
|
7
|
-
hasBeenSubmitted: false,
|
8
|
-
touchedFields: {},
|
9
|
-
defaultValues: {},
|
10
|
-
validateField: () => Promise.resolve(null),
|
11
|
-
registerReceiveFocus: () => () => { },
|
12
|
-
setFieldValue: () => { },
|
13
|
-
// clearError: () => {},
|
14
|
-
// addError: () => {},
|
15
|
-
// setTouched: () => {},
|
16
|
-
// reset: () => {},
|
17
|
-
// startSubmit: () => {},
|
18
|
-
// endSubmit: () => {},
|
19
|
-
// sync: () => {},
|
20
|
-
// setFieldErrors: () => {},
|
21
|
-
};
|
22
|
-
export const useStore = create(immer((set, get) => ({
|
23
|
-
forms: {},
|
24
|
-
form: (formId) => { var _a; return (_a = get().forms[formId]) !== null && _a !== void 0 ? _a : unhydratedFormState; },
|
25
|
-
helpers: (formId) => ({
|
26
|
-
clearError: (name) => set((state) => {
|
27
|
-
delete state.forms[formId].fieldErrors[name];
|
28
|
-
}),
|
29
|
-
addError: (name, error) => set((state) => {
|
30
|
-
state.forms[formId].fieldErrors[name] = error;
|
31
|
-
}),
|
32
|
-
setTouched: (name, touched) => set((state) => {
|
33
|
-
state.forms[formId].touchedFields[name] = touched;
|
34
|
-
}),
|
35
|
-
reset: () => set((state) => {
|
36
|
-
state.forms[formId].fieldErrors = {};
|
37
|
-
state.forms[formId].touchedFields = {};
|
38
|
-
state.forms[formId].hasBeenSubmitted = false;
|
39
|
-
}),
|
40
|
-
startSubmit: () => set((state) => {
|
41
|
-
state.forms[formId].hasBeenSubmitted = true;
|
42
|
-
state.forms[formId].isSubmitting = true;
|
43
|
-
}),
|
44
|
-
endSubmit: () => set((state) => {
|
45
|
-
state.forms[formId].isSubmitting = false;
|
46
|
-
}),
|
47
|
-
setFieldErrors: (fieldErrors) => {
|
48
|
-
set((state) => {
|
49
|
-
state.forms[formId].fieldErrors = fieldErrors;
|
50
|
-
});
|
51
|
-
},
|
52
|
-
sync: ({ defaultValues, action, subaction, validateField, registerReceiveFocus, setFieldValueForForm, }) => set((state) => {
|
53
|
-
state.forms[formId].defaultValues = defaultValues !== null && defaultValues !== void 0 ? defaultValues : {};
|
54
|
-
state.forms[formId].action = action;
|
55
|
-
state.forms[formId].subaction = subaction;
|
56
|
-
state.forms[formId].registerReceiveFocus = registerReceiveFocus;
|
57
|
-
state.forms[formId].validateField = validateField;
|
58
|
-
state.forms[formId].hydrated = true;
|
59
|
-
state.forms[formId].setFieldValue = setFieldValueForForm;
|
60
|
-
}),
|
61
|
-
unregister: () => {
|
62
|
-
set((state) => {
|
63
|
-
delete state.forms[formId];
|
64
|
-
});
|
65
|
-
},
|
66
|
-
register: ({ defaultValues, action, subaction, validateField, registerReceiveFocus, setFieldValueForForm, }) => {
|
67
|
-
set((state) => {
|
68
|
-
state.forms[formId] = {
|
69
|
-
defaultValues: defaultValues !== null && defaultValues !== void 0 ? defaultValues : {},
|
70
|
-
setFieldValue: setFieldValueForForm,
|
71
|
-
registerReceiveFocus,
|
72
|
-
validateField,
|
73
|
-
action,
|
74
|
-
subaction,
|
75
|
-
hydrated: true,
|
76
|
-
fieldErrors: {},
|
77
|
-
isSubmitting: false,
|
78
|
-
hasBeenSubmitted: false,
|
79
|
-
touchedFields: {},
|
80
|
-
// helpers
|
81
|
-
};
|
82
|
-
});
|
83
|
-
},
|
84
|
-
}),
|
85
|
-
})));
|
File without changes
|
package/browser/internal/test.js
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
"use strict";
|
2
|
-
z.preprocess((val) => {
|
3
|
-
// Somewhat awkward -- this gets processed per item in the form,
|
4
|
-
// but as a whole array in the backend
|
5
|
-
if (Array.isArray(val)) {
|
6
|
-
return val;
|
7
|
-
}
|
8
|
-
else {
|
9
|
-
return [val];
|
10
|
-
}
|
11
|
-
}, z.array(z.preprocess((val) => {
|
12
|
-
return typeof val !== "string" || val === ""
|
13
|
-
? undefined
|
14
|
-
: Number.parseInt(val);
|
15
|
-
}, z.number())));
|
@@ -1 +0,0 @@
|
|
1
|
-
export declare const useMultiValueMap: <Key, Value>() => () => any;
|
@@ -1,11 +0,0 @@
|
|
1
|
-
import { MultiValueMap } from "multi-value-map";
|
2
|
-
import { useRef } from "react";
|
3
|
-
export const useMultiValueMap = () => {
|
4
|
-
const ref = useRef(null);
|
5
|
-
return () => {
|
6
|
-
if (ref.current)
|
7
|
-
return ref.current;
|
8
|
-
ref.current = new MultiValueMap();
|
9
|
-
return ref.current;
|
10
|
-
};
|
11
|
-
};
|
@@ -1,18 +0,0 @@
|
|
1
|
-
declare type ParseInfo = {
|
2
|
-
value: unknown;
|
3
|
-
type: string;
|
4
|
-
isRepeated: boolean;
|
5
|
-
checked?: boolean;
|
6
|
-
};
|
7
|
-
declare type BaseWatchOptions<T> = {
|
8
|
-
formId?: string;
|
9
|
-
parse?: (info: ParseInfo) => T;
|
10
|
-
};
|
11
|
-
declare type UseWatchType = {
|
12
|
-
<T, U extends boolean | undefined>(name: string, options?: BaseWatchOptions<T> & {
|
13
|
-
repeatable: U | undefined;
|
14
|
-
}): U extends true ? T[] : T;
|
15
|
-
<T>(name: string, options?: BaseWatchOptions<T>): T;
|
16
|
-
};
|
17
|
-
export declare const useWatch: UseWatchType;
|
18
|
-
export {};
|
@@ -1,122 +0,0 @@
|
|
1
|
-
import { atom } from "jotai";
|
2
|
-
import { selectAtom } from "jotai/utils";
|
3
|
-
import isNaN from "lodash/isNaN";
|
4
|
-
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
5
|
-
import invariant from "tiny-invariant";
|
6
|
-
import { useInternalFormContext, useFieldDefaultValue, useFormAtomValue, } from "./hooks";
|
7
|
-
import { isCheckbox, isMultiselect, isRadio } from "./logic/elementUtils";
|
8
|
-
import { formElementAtom } from "./state";
|
9
|
-
import { fieldAtomFamily } from "./state/atomUtils";
|
10
|
-
import { controlledFieldsAtom } from "./state/controlledFields";
|
11
|
-
const emptyAtom = atom(undefined); // Always empty -- just used as a default value
|
12
|
-
const watchControlledFieldAtom = fieldAtomFamily(({ field, formId }) => selectAtom(controlledFieldsAtom(formId), (fields) => {
|
13
|
-
var _a;
|
14
|
-
return ({
|
15
|
-
present: field in fields,
|
16
|
-
valueAtom: (_a = fields[field]) !== null && _a !== void 0 ? _a : emptyAtom,
|
17
|
-
});
|
18
|
-
}, (a, b) => a.present === b.present && a.valueAtom === b.valueAtom));
|
19
|
-
const defaultParse = ({ value, type, isRepeated, checked, }) => {
|
20
|
-
if (type === "number") {
|
21
|
-
if (value === "")
|
22
|
-
return undefined;
|
23
|
-
const result = Number(value);
|
24
|
-
if (isNaN(result))
|
25
|
-
throw new Error("Value is not a number");
|
26
|
-
return result;
|
27
|
-
}
|
28
|
-
if (type === "checkbox" && !isRepeated) {
|
29
|
-
return checked;
|
30
|
-
}
|
31
|
-
return value;
|
32
|
-
};
|
33
|
-
const getInputValues = (node, multipleInputs = false) => {
|
34
|
-
if (!node)
|
35
|
-
return [];
|
36
|
-
if (node instanceof RadioNodeList) {
|
37
|
-
return [...node].flatMap((el) => getInputValues(el, true));
|
38
|
-
}
|
39
|
-
if (isMultiselect(node)) {
|
40
|
-
return [
|
41
|
-
{
|
42
|
-
type: "select",
|
43
|
-
value: [...node.options]
|
44
|
-
.filter((opt) => opt.selected)
|
45
|
-
.map((opt) => opt.value),
|
46
|
-
},
|
47
|
-
];
|
48
|
-
}
|
49
|
-
if (isCheckbox(node)) {
|
50
|
-
if (node.checked || !multipleInputs)
|
51
|
-
return [{ type: "checkbox", value: node.value, checked: node.checked }];
|
52
|
-
return [];
|
53
|
-
}
|
54
|
-
if (isRadio(node)) {
|
55
|
-
if (node.checked)
|
56
|
-
return [{ type: "radio", value: node.value, checked: node.checked }];
|
57
|
-
return [];
|
58
|
-
}
|
59
|
-
const input = node;
|
60
|
-
return [{ type: input.type, value: input.value, checked: input.checked }];
|
61
|
-
};
|
62
|
-
export const useWatch = (field, options) => {
|
63
|
-
const { formId, parse = defaultParse, repeatable = false, } = options !== null && options !== void 0 ? options : {};
|
64
|
-
const context = useInternalFormContext(formId, "useWatch");
|
65
|
-
const defaultValue = useFieldDefaultValue(field, context);
|
66
|
-
const hasSynced = useRef(false);
|
67
|
-
const [inputValues, setValue] = useState([]);
|
68
|
-
const formElement = useFormAtomValue(formElementAtom(context.formId));
|
69
|
-
const controlledField = useFormAtomValue(watchControlledFieldAtom({ formId: context.formId, field }));
|
70
|
-
const controlledValue = useFormAtomValue(controlledField.valueAtom);
|
71
|
-
const shouldSyncNativeInputValue = !controlledField.present && formElement;
|
72
|
-
const syncFieldValue = useCallback(() => {
|
73
|
-
invariant(formElement, `Unable to find form element for form. Watching field ${field}`);
|
74
|
-
hasSynced.current = true;
|
75
|
-
// We pull the values out using `form.elements` instead of `FormData`
|
76
|
-
// so that we can access the `type` of the input.
|
77
|
-
setValue(getInputValues(formElement.elements.namedItem(field)));
|
78
|
-
}, [field, formElement]);
|
79
|
-
// Should set the field values after the initial render
|
80
|
-
useEffect(() => {
|
81
|
-
if (shouldSyncNativeInputValue)
|
82
|
-
syncFieldValue();
|
83
|
-
}, [
|
84
|
-
controlledField.present,
|
85
|
-
formElement,
|
86
|
-
shouldSyncNativeInputValue,
|
87
|
-
syncFieldValue,
|
88
|
-
]);
|
89
|
-
useEffect(() => {
|
90
|
-
if (shouldSyncNativeInputValue) {
|
91
|
-
const listener = async (event) => {
|
92
|
-
if (!(event.target instanceof HTMLElement))
|
93
|
-
return;
|
94
|
-
const target = event.target;
|
95
|
-
const { form: targetForm, name: targetName } = target;
|
96
|
-
if (targetForm === formElement && targetName === field) {
|
97
|
-
syncFieldValue();
|
98
|
-
}
|
99
|
-
};
|
100
|
-
window.addEventListener("change", listener);
|
101
|
-
window.addEventListener("input", listener);
|
102
|
-
return () => {
|
103
|
-
window.removeEventListener("change", listener);
|
104
|
-
window.removeEventListener("input", listener);
|
105
|
-
};
|
106
|
-
}
|
107
|
-
}, [field, formElement, shouldSyncNativeInputValue, syncFieldValue]);
|
108
|
-
const parsedValue = useMemo(() => {
|
109
|
-
const parsed = inputValues.map(({ type, value, checked }) => parse({
|
110
|
-
value,
|
111
|
-
type,
|
112
|
-
isRepeated: inputValues.length > 1 || repeatable,
|
113
|
-
checked,
|
114
|
-
}));
|
115
|
-
return parsed.length > 1 || repeatable ? parsed : parsed[0];
|
116
|
-
}, [parse, repeatable, inputValues]);
|
117
|
-
if (controlledField.present)
|
118
|
-
return controlledValue;
|
119
|
-
if (!hasSynced.current)
|
120
|
-
return defaultValue !== null && defaultValue !== void 0 ? defaultValue : (repeatable ? [] : undefined);
|
121
|
-
return parsedValue;
|
122
|
-
};
|
File without changes
|
package/browser/lowLevelHooks.js
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
"use strict";
|
@@ -1,15 +0,0 @@
|
|
1
|
-
export declare class TestFormData implements FormData {
|
2
|
-
private _params;
|
3
|
-
constructor(body?: string);
|
4
|
-
append(name: string, value: string | Blob, fileName?: string): void;
|
5
|
-
delete(name: string): void;
|
6
|
-
get(name: string): FormDataEntryValue | null;
|
7
|
-
getAll(name: string): FormDataEntryValue[];
|
8
|
-
has(name: string): boolean;
|
9
|
-
set(name: string, value: string | Blob, fileName?: string): void;
|
10
|
-
forEach(callbackfn: (value: FormDataEntryValue, key: string, parent: FormData) => void, thisArg?: any): void;
|
11
|
-
entries(): IterableIterator<[string, FormDataEntryValue]>;
|
12
|
-
keys(): IterableIterator<string>;
|
13
|
-
values(): IterableIterator<FormDataEntryValue>;
|
14
|
-
[Symbol.iterator](): IterableIterator<[string, FormDataEntryValue]>;
|
15
|
-
}
|
@@ -1,46 +0,0 @@
|
|
1
|
-
// Copied from remix to use in tests
|
2
|
-
// https://github.com/remix-run/remix/blob/a69a631cb5add72d5fb24211ab2a0be367b6f2fd/packages/remix-node/form-data.ts
|
3
|
-
export class TestFormData {
|
4
|
-
constructor(body) {
|
5
|
-
this._params = new URLSearchParams(body);
|
6
|
-
}
|
7
|
-
append(name, value, fileName) {
|
8
|
-
if (typeof value !== "string") {
|
9
|
-
throw new Error("formData.append can only accept a string");
|
10
|
-
}
|
11
|
-
this._params.append(name, value);
|
12
|
-
}
|
13
|
-
delete(name) {
|
14
|
-
this._params.delete(name);
|
15
|
-
}
|
16
|
-
get(name) {
|
17
|
-
return this._params.get(name);
|
18
|
-
}
|
19
|
-
getAll(name) {
|
20
|
-
return this._params.getAll(name);
|
21
|
-
}
|
22
|
-
has(name) {
|
23
|
-
return this._params.has(name);
|
24
|
-
}
|
25
|
-
set(name, value, fileName) {
|
26
|
-
if (typeof value !== "string") {
|
27
|
-
throw new Error("formData.set can only accept a string");
|
28
|
-
}
|
29
|
-
this._params.set(name, value);
|
30
|
-
}
|
31
|
-
forEach(callbackfn, thisArg) {
|
32
|
-
this._params.forEach(callbackfn, thisArg);
|
33
|
-
}
|
34
|
-
entries() {
|
35
|
-
return this._params.entries();
|
36
|
-
}
|
37
|
-
keys() {
|
38
|
-
return this._params.keys();
|
39
|
-
}
|
40
|
-
values() {
|
41
|
-
return this._params.values();
|
42
|
-
}
|
43
|
-
*[Symbol.iterator]() {
|
44
|
-
yield* this._params;
|
45
|
-
}
|
46
|
-
}
|
package/browser/types.d.ts
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
export declare type ValidationState = "idle" | "validating" | "valid" | "invalid";
|
package/browser/types.js
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
export {};
|
@@ -1 +0,0 @@
|
|
1
|
-
export {};
|