@conform-to/react 1.0.0-pre.5 → 1.0.0-pre.7
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 +32 -0
- package/_virtual/_rollupPluginBabelHelpers.js +29 -0
- package/_virtual/_rollupPluginBabelHelpers.mjs +28 -1
- package/context.d.ts +22 -20
- package/context.js +24 -25
- package/context.mjs +24 -26
- package/helpers.d.ts +9 -13
- package/helpers.js +5 -8
- package/helpers.mjs +5 -8
- package/hooks.d.ts +4 -4
- package/hooks.js +15 -20
- package/hooks.mjs +18 -23
- package/index.d.ts +1 -2
- package/index.js +2 -12
- package/index.mjs +1 -2
- package/integrations.d.ts +3 -3
- package/integrations.js +12 -12
- package/integrations.mjs +12 -12
- package/package.json +2 -2
- package/README.md +0 -606
- package/validitystate.d.ts +0 -12
- package/validitystate.js +0 -38
- package/validitystate.mjs +0 -34
package/README
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
███████╗ ██████╗ ███╗ ██╗ ████████╗ ██████╗ ███████╗ ███╗ ███╗
|
|
4
|
+
██╔═════╝ ██╔═══██╗ ████╗ ██║ ██╔═════╝ ██╔═══██╗ ██╔═══██╗ ████████║
|
|
5
|
+
██║ ██║ ██║ ██╔██╗██║ ███████╗ ██║ ██║ ███████╔╝ ██╔██╔██║
|
|
6
|
+
██║ ██║ ██║ ██║╚████║ ██╔════╝ ██║ ██║ ██╔═══██╗ ██║╚═╝██║
|
|
7
|
+
╚███████╗ ╚██████╔╝ ██║ ╚███║ ██║ ╚██████╔╝ ██║ ██║ ██║ ██║
|
|
8
|
+
╚══════╝ ╚═════╝ ╚═╝ ╚══╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
Version 1.0.0-pre.7 / License MIT / Copyright (c) 2024 Edmund Hung
|
|
12
|
+
|
|
13
|
+
A type-safe form validation library utilizing web fundamentals to progressively enhance HTML Forms with full support for server frameworks like Remix route action and Next.js server actions.
|
|
14
|
+
|
|
15
|
+
> Getting Started
|
|
16
|
+
|
|
17
|
+
Check out the overview and tutorial at our website https://conform.guide
|
|
18
|
+
|
|
19
|
+
> Documentation
|
|
20
|
+
|
|
21
|
+
The documentation is divided into several sections:
|
|
22
|
+
|
|
23
|
+
* Overview: https://conform.guide/overview
|
|
24
|
+
* Example Usages: https://conform.guide/examples
|
|
25
|
+
* Complex structures: https://conform.guide/complex-structures
|
|
26
|
+
* UI Integrations: https://conform.guide/integrations
|
|
27
|
+
* Accessibility Guide: https://conform.guide/accessibility
|
|
28
|
+
* API Reference: https://conform.guide/references
|
|
29
|
+
|
|
30
|
+
> Support
|
|
31
|
+
|
|
32
|
+
To report a bug, please open an issue on the repository at https://github.com/edmundhung/conform. For feature requests and questions, you can post them in the Discussions section.
|
|
@@ -37,6 +37,33 @@ function _defineProperty(obj, key, value) {
|
|
|
37
37
|
}
|
|
38
38
|
return obj;
|
|
39
39
|
}
|
|
40
|
+
function _objectWithoutPropertiesLoose(source, excluded) {
|
|
41
|
+
if (source == null) return {};
|
|
42
|
+
var target = {};
|
|
43
|
+
var sourceKeys = Object.keys(source);
|
|
44
|
+
var key, i;
|
|
45
|
+
for (i = 0; i < sourceKeys.length; i++) {
|
|
46
|
+
key = sourceKeys[i];
|
|
47
|
+
if (excluded.indexOf(key) >= 0) continue;
|
|
48
|
+
target[key] = source[key];
|
|
49
|
+
}
|
|
50
|
+
return target;
|
|
51
|
+
}
|
|
52
|
+
function _objectWithoutProperties(source, excluded) {
|
|
53
|
+
if (source == null) return {};
|
|
54
|
+
var target = _objectWithoutPropertiesLoose(source, excluded);
|
|
55
|
+
var key, i;
|
|
56
|
+
if (Object.getOwnPropertySymbols) {
|
|
57
|
+
var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
|
|
58
|
+
for (i = 0; i < sourceSymbolKeys.length; i++) {
|
|
59
|
+
key = sourceSymbolKeys[i];
|
|
60
|
+
if (excluded.indexOf(key) >= 0) continue;
|
|
61
|
+
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
|
|
62
|
+
target[key] = source[key];
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return target;
|
|
66
|
+
}
|
|
40
67
|
function _toPrimitive(input, hint) {
|
|
41
68
|
if (typeof input !== "object" || input === null) return input;
|
|
42
69
|
var prim = input[Symbol.toPrimitive];
|
|
@@ -54,5 +81,7 @@ function _toPropertyKey(arg) {
|
|
|
54
81
|
|
|
55
82
|
exports.defineProperty = _defineProperty;
|
|
56
83
|
exports.objectSpread2 = _objectSpread2;
|
|
84
|
+
exports.objectWithoutProperties = _objectWithoutProperties;
|
|
85
|
+
exports.objectWithoutPropertiesLoose = _objectWithoutPropertiesLoose;
|
|
57
86
|
exports.toPrimitive = _toPrimitive;
|
|
58
87
|
exports.toPropertyKey = _toPropertyKey;
|
|
@@ -33,6 +33,33 @@ function _defineProperty(obj, key, value) {
|
|
|
33
33
|
}
|
|
34
34
|
return obj;
|
|
35
35
|
}
|
|
36
|
+
function _objectWithoutPropertiesLoose(source, excluded) {
|
|
37
|
+
if (source == null) return {};
|
|
38
|
+
var target = {};
|
|
39
|
+
var sourceKeys = Object.keys(source);
|
|
40
|
+
var key, i;
|
|
41
|
+
for (i = 0; i < sourceKeys.length; i++) {
|
|
42
|
+
key = sourceKeys[i];
|
|
43
|
+
if (excluded.indexOf(key) >= 0) continue;
|
|
44
|
+
target[key] = source[key];
|
|
45
|
+
}
|
|
46
|
+
return target;
|
|
47
|
+
}
|
|
48
|
+
function _objectWithoutProperties(source, excluded) {
|
|
49
|
+
if (source == null) return {};
|
|
50
|
+
var target = _objectWithoutPropertiesLoose(source, excluded);
|
|
51
|
+
var key, i;
|
|
52
|
+
if (Object.getOwnPropertySymbols) {
|
|
53
|
+
var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
|
|
54
|
+
for (i = 0; i < sourceSymbolKeys.length; i++) {
|
|
55
|
+
key = sourceSymbolKeys[i];
|
|
56
|
+
if (excluded.indexOf(key) >= 0) continue;
|
|
57
|
+
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
|
|
58
|
+
target[key] = source[key];
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return target;
|
|
62
|
+
}
|
|
36
63
|
function _toPrimitive(input, hint) {
|
|
37
64
|
if (typeof input !== "object" || input === null) return input;
|
|
38
65
|
var prim = input[Symbol.toPrimitive];
|
|
@@ -48,4 +75,4 @@ function _toPropertyKey(arg) {
|
|
|
48
75
|
return typeof key === "symbol" ? key : String(key);
|
|
49
76
|
}
|
|
50
77
|
|
|
51
|
-
export { _defineProperty as defineProperty, _objectSpread2 as objectSpread2, _toPrimitive as toPrimitive, _toPropertyKey as toPropertyKey };
|
|
78
|
+
export { _defineProperty as defineProperty, _objectSpread2 as objectSpread2, _objectWithoutProperties as objectWithoutProperties, _objectWithoutPropertiesLoose as objectWithoutPropertiesLoose, _toPrimitive as toPrimitive, _toPropertyKey as toPropertyKey };
|
package/context.d.ts
CHANGED
|
@@ -1,49 +1,50 @@
|
|
|
1
|
-
import { type Constraint, type
|
|
1
|
+
import { type Constraint, type FormId, type FieldName, type FormContext, type FormValue, type FormState, type Intent, type SubscriptionScope, type SubscriptionSubject, type UnionKeyof, type UnionKeyType } from '@conform-to/dom';
|
|
2
2
|
import { type ReactElement, type ReactNode, type MutableRefObject } from 'react';
|
|
3
3
|
export type Pretty<T> = {
|
|
4
4
|
[K in keyof T]: T[K];
|
|
5
5
|
} & {};
|
|
6
6
|
export type Primitive = string | number | boolean | Date | File | null | undefined;
|
|
7
|
-
export type Metadata<Schema,
|
|
7
|
+
export type Metadata<Schema, FormSchema extends Record<string, unknown>, FormError = string[]> = {
|
|
8
8
|
key: string | undefined;
|
|
9
9
|
id: string;
|
|
10
10
|
errorId: string;
|
|
11
11
|
descriptionId: string;
|
|
12
|
-
name: FieldName<Schema,
|
|
12
|
+
name: FieldName<Schema, FormSchema, FormError>;
|
|
13
13
|
initialValue: FormValue<Schema>;
|
|
14
14
|
value: FormValue<Schema>;
|
|
15
15
|
errors: FormError | undefined;
|
|
16
16
|
allErrors: Record<string, FormError>;
|
|
17
|
-
allValid: boolean;
|
|
18
17
|
valid: boolean;
|
|
19
18
|
dirty: boolean;
|
|
20
19
|
};
|
|
21
|
-
export type FormMetadata<Schema extends Record<string, unknown> = Record<string, unknown>, FormError = string[]> = Omit<Metadata<Schema,
|
|
20
|
+
export type FormMetadata<Schema extends Record<string, unknown> = Record<string, unknown>, FormError = string[]> = Omit<Metadata<Schema, Schema, FormError>, 'id'> & Pick<FormContext<Schema, FormError>, Intent['type']> & {
|
|
22
21
|
id: FormId<Schema, FormError>;
|
|
23
|
-
context: FormContext<Schema, FormError
|
|
22
|
+
context: Wrapped<FormContext<Schema, FormError>>;
|
|
24
23
|
status?: 'success' | 'error';
|
|
25
|
-
dispatch(control: FormControl): void;
|
|
26
|
-
getControlButtonProps(control: FormControl): ControlButtonProps;
|
|
27
24
|
getFieldset: () => {
|
|
28
|
-
[Key in UnionKeyof<Schema>]: FieldMetadata<UnionKeyType<Schema, Key>,
|
|
25
|
+
[Key in UnionKeyof<Schema>]: FieldMetadata<UnionKeyType<Schema, Key>, Schema, FormError>;
|
|
29
26
|
};
|
|
30
|
-
onSubmit: (event: React.FormEvent<HTMLFormElement>) =>
|
|
31
|
-
onReset: (event: React.FormEvent<HTMLFormElement>) => void;
|
|
27
|
+
onSubmit: (event: React.FormEvent<HTMLFormElement>) => void;
|
|
32
28
|
noValidate: boolean;
|
|
33
29
|
};
|
|
34
|
-
export type FieldMetadata<Schema = unknown,
|
|
30
|
+
export type FieldMetadata<Schema = unknown, FormSchema extends Record<string, any> = Record<string, unknown>, FormError = string[]> = Metadata<Schema, FormSchema, FormError> & {
|
|
35
31
|
formId: FormId<FormSchema, FormError>;
|
|
36
32
|
constraint?: Constraint;
|
|
37
33
|
getFieldset: unknown extends Schema ? () => unknown : Schema extends Primitive | Array<any> ? never : () => {
|
|
38
|
-
[Key in UnionKeyof<Schema>]: FieldMetadata<UnionKeyType<Schema, Key>, FormError>;
|
|
34
|
+
[Key in UnionKeyof<Schema>]: FieldMetadata<UnionKeyType<Schema, Key>, FormSchema, FormError>;
|
|
39
35
|
};
|
|
40
|
-
getFieldList: unknown extends Schema ? () => unknown : Schema extends Array<infer Item> ? () => Array<FieldMetadata<Item, FormError>> : never;
|
|
36
|
+
getFieldList: unknown extends Schema ? () => unknown : Schema extends Array<infer Item> ? () => Array<FieldMetadata<Item, FormSchema, FormError>> : never;
|
|
41
37
|
};
|
|
42
38
|
export declare const Form: import("react").Context<FormContext[]>;
|
|
43
|
-
|
|
44
|
-
export
|
|
39
|
+
declare const wrappedSymbol: unique symbol;
|
|
40
|
+
export type Wrapped<Type> = {
|
|
41
|
+
[wrappedSymbol]: Type;
|
|
42
|
+
};
|
|
43
|
+
export declare function getWrappedFormContext(context: Wrapped<FormContext>): FormContext;
|
|
44
|
+
export declare function useFormContext<Schema extends Record<string, any>, FormError>(formId?: FormId<Schema, FormError>): FormContext<Schema, unknown, FormError>;
|
|
45
|
+
export declare function useFormState<FormError>(form: FormContext<any, any, FormError>, subjectRef?: MutableRefObject<SubscriptionSubject>): FormState<FormError>;
|
|
45
46
|
export declare function FormProvider(props: {
|
|
46
|
-
context: FormContext<any, any, any
|
|
47
|
+
context: Wrapped<FormContext<any, any, any>>;
|
|
47
48
|
children: ReactNode;
|
|
48
49
|
}): ReactElement;
|
|
49
50
|
export declare function FormStateInput(props: {
|
|
@@ -51,6 +52,7 @@ export declare function FormStateInput(props: {
|
|
|
51
52
|
}): React.ReactElement;
|
|
52
53
|
export declare function useSubjectRef(initialSubject?: SubscriptionSubject): MutableRefObject<SubscriptionSubject>;
|
|
53
54
|
export declare function updateSubjectRef(ref: MutableRefObject<SubscriptionSubject>, name: string, subject: keyof SubscriptionSubject, scope: keyof SubscriptionScope): void;
|
|
54
|
-
export declare function getMetadata<Schema, FormError, FormSchema extends Record<string, any>>(formId: FormId<FormSchema, FormError>, state: FormState<FormError>, subjectRef: MutableRefObject<SubscriptionSubject>, name?: FieldName<Schema,
|
|
55
|
-
export declare function getFieldMetadata<Schema,
|
|
56
|
-
export declare function getFormMetadata<Schema extends Record<string, any>, FormError = string[]>(formId: FormId<Schema, FormError>, state: FormState<FormError>, subjectRef: MutableRefObject<SubscriptionSubject>, context: FormContext<Schema,
|
|
55
|
+
export declare function getMetadata<Schema, FormError, FormSchema extends Record<string, any>>(formId: FormId<FormSchema, FormError>, state: FormState<FormError>, subjectRef: MutableRefObject<SubscriptionSubject>, name?: FieldName<Schema, FormSchema, FormError>): Metadata<Schema, FormSchema, FormError>;
|
|
56
|
+
export declare function getFieldMetadata<Schema, FormSchema extends Record<string, any>, FormError>(formId: FormId<FormSchema, FormError>, state: FormState<FormError>, subjectRef: MutableRefObject<SubscriptionSubject>, prefix?: string, key?: string | number): FieldMetadata<Schema, FormSchema, FormError>;
|
|
57
|
+
export declare function getFormMetadata<Schema extends Record<string, any>, FormValue = Schema, FormError = string[]>(formId: FormId<Schema, FormError>, state: FormState<FormError>, subjectRef: MutableRefObject<SubscriptionSubject>, context: FormContext<Schema, FormValue, FormError>, noValidate: boolean): FormMetadata<Schema, FormError>;
|
|
58
|
+
export {};
|
package/context.js
CHANGED
|
@@ -8,6 +8,12 @@ var react = require('react');
|
|
|
8
8
|
var jsxRuntime = require('react/jsx-runtime');
|
|
9
9
|
|
|
10
10
|
var Form = /*#__PURE__*/react.createContext([]);
|
|
11
|
+
|
|
12
|
+
// To hide the FormContext type from the public API
|
|
13
|
+
var wrappedSymbol = Symbol('wrapped');
|
|
14
|
+
function getWrappedFormContext(context) {
|
|
15
|
+
return context[wrappedSymbol];
|
|
16
|
+
}
|
|
11
17
|
function useFormContext(formId) {
|
|
12
18
|
var contexts = react.useContext(Form);
|
|
13
19
|
var form = formId ? contexts.find(context => context.formId === formId) : contexts[0];
|
|
@@ -22,9 +28,10 @@ function useFormState(form, subjectRef) {
|
|
|
22
28
|
}
|
|
23
29
|
function FormProvider(props) {
|
|
24
30
|
var forms = react.useContext(Form);
|
|
25
|
-
var
|
|
31
|
+
var context = getWrappedFormContext(props.context);
|
|
32
|
+
var value = react.useMemo(() => [context].concat(forms),
|
|
26
33
|
// Put the latest form context first
|
|
27
|
-
[forms,
|
|
34
|
+
[forms, context]);
|
|
28
35
|
return /*#__PURE__*/jsxRuntime.jsx(Form.Provider, {
|
|
29
36
|
value: value,
|
|
30
37
|
children: props.children
|
|
@@ -78,18 +85,6 @@ function getMetadata(formId, state, subjectRef) {
|
|
|
78
85
|
get dirty() {
|
|
79
86
|
return state.dirty[name];
|
|
80
87
|
},
|
|
81
|
-
get allValid() {
|
|
82
|
-
var keys = Object.keys(state.error);
|
|
83
|
-
if (name === '') {
|
|
84
|
-
return keys.length === 0;
|
|
85
|
-
}
|
|
86
|
-
for (var key of Object.keys(state.error)) {
|
|
87
|
-
if (dom.isPrefix(key, name) && !state.valid[key]) {
|
|
88
|
-
return false;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
return true;
|
|
92
|
-
},
|
|
93
88
|
get allErrors() {
|
|
94
89
|
if (name === '') {
|
|
95
90
|
return state.error;
|
|
@@ -116,18 +111,15 @@ function getMetadata(formId, state, subjectRef) {
|
|
|
116
111
|
get(target, key, receiver) {
|
|
117
112
|
switch (key) {
|
|
118
113
|
case 'key':
|
|
119
|
-
case 'errors':
|
|
120
114
|
case 'initialValue':
|
|
121
115
|
case 'value':
|
|
122
116
|
case 'valid':
|
|
123
117
|
case 'dirty':
|
|
124
|
-
updateSubjectRef(subjectRef, name, key
|
|
118
|
+
updateSubjectRef(subjectRef, name, key, 'name');
|
|
125
119
|
break;
|
|
120
|
+
case 'errors':
|
|
126
121
|
case 'allErrors':
|
|
127
|
-
updateSubjectRef(subjectRef, name, 'error', 'prefix');
|
|
128
|
-
break;
|
|
129
|
-
case 'allValid':
|
|
130
|
-
updateSubjectRef(subjectRef, name, 'valid', 'prefix');
|
|
122
|
+
updateSubjectRef(subjectRef, name, 'error', key === 'errors' ? 'name' : 'prefix');
|
|
131
123
|
break;
|
|
132
124
|
}
|
|
133
125
|
return Reflect.get(target, key, receiver);
|
|
@@ -169,17 +161,23 @@ function getFormMetadata(formId, state, subjectRef, context, noValidate) {
|
|
|
169
161
|
get(_, key, receiver) {
|
|
170
162
|
switch (key) {
|
|
171
163
|
case 'context':
|
|
172
|
-
return
|
|
164
|
+
return {
|
|
165
|
+
[wrappedSymbol]: context
|
|
166
|
+
};
|
|
173
167
|
case 'status':
|
|
174
168
|
return state.submissionStatus;
|
|
175
|
-
case '
|
|
176
|
-
case '
|
|
169
|
+
case 'validate':
|
|
170
|
+
case 'update':
|
|
171
|
+
case 'reset':
|
|
172
|
+
case 'insert':
|
|
173
|
+
case 'remove':
|
|
174
|
+
case 'reorder':
|
|
177
175
|
return context[key];
|
|
178
176
|
case 'onSubmit':
|
|
179
177
|
return event => {
|
|
180
178
|
var submitEvent = event.nativeEvent;
|
|
181
|
-
context.submit(submitEvent);
|
|
182
|
-
if (
|
|
179
|
+
var submission = context.submit(submitEvent);
|
|
180
|
+
if (submission && submission.status !== 'success' && submission.error !== null) {
|
|
183
181
|
event.preventDefault();
|
|
184
182
|
}
|
|
185
183
|
};
|
|
@@ -197,6 +195,7 @@ exports.FormStateInput = FormStateInput;
|
|
|
197
195
|
exports.getFieldMetadata = getFieldMetadata;
|
|
198
196
|
exports.getFormMetadata = getFormMetadata;
|
|
199
197
|
exports.getMetadata = getMetadata;
|
|
198
|
+
exports.getWrappedFormContext = getWrappedFormContext;
|
|
200
199
|
exports.updateSubjectRef = updateSubjectRef;
|
|
201
200
|
exports.useFormContext = useFormContext;
|
|
202
201
|
exports.useFormState = useFormState;
|
package/context.mjs
CHANGED
|
@@ -4,6 +4,12 @@ import { useContext, useMemo, createContext, useCallback, useSyncExternalStore,
|
|
|
4
4
|
import { jsx } from 'react/jsx-runtime';
|
|
5
5
|
|
|
6
6
|
var Form = /*#__PURE__*/createContext([]);
|
|
7
|
+
|
|
8
|
+
// To hide the FormContext type from the public API
|
|
9
|
+
var wrappedSymbol = Symbol('wrapped');
|
|
10
|
+
function getWrappedFormContext(context) {
|
|
11
|
+
return context[wrappedSymbol];
|
|
12
|
+
}
|
|
7
13
|
function useFormContext(formId) {
|
|
8
14
|
var contexts = useContext(Form);
|
|
9
15
|
var form = formId ? contexts.find(context => context.formId === formId) : contexts[0];
|
|
@@ -18,9 +24,10 @@ function useFormState(form, subjectRef) {
|
|
|
18
24
|
}
|
|
19
25
|
function FormProvider(props) {
|
|
20
26
|
var forms = useContext(Form);
|
|
21
|
-
var
|
|
27
|
+
var context = getWrappedFormContext(props.context);
|
|
28
|
+
var value = useMemo(() => [context].concat(forms),
|
|
22
29
|
// Put the latest form context first
|
|
23
|
-
[forms,
|
|
30
|
+
[forms, context]);
|
|
24
31
|
return /*#__PURE__*/jsx(Form.Provider, {
|
|
25
32
|
value: value,
|
|
26
33
|
children: props.children
|
|
@@ -74,18 +81,6 @@ function getMetadata(formId, state, subjectRef) {
|
|
|
74
81
|
get dirty() {
|
|
75
82
|
return state.dirty[name];
|
|
76
83
|
},
|
|
77
|
-
get allValid() {
|
|
78
|
-
var keys = Object.keys(state.error);
|
|
79
|
-
if (name === '') {
|
|
80
|
-
return keys.length === 0;
|
|
81
|
-
}
|
|
82
|
-
for (var key of Object.keys(state.error)) {
|
|
83
|
-
if (isPrefix(key, name) && !state.valid[key]) {
|
|
84
|
-
return false;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
return true;
|
|
88
|
-
},
|
|
89
84
|
get allErrors() {
|
|
90
85
|
if (name === '') {
|
|
91
86
|
return state.error;
|
|
@@ -112,18 +107,15 @@ function getMetadata(formId, state, subjectRef) {
|
|
|
112
107
|
get(target, key, receiver) {
|
|
113
108
|
switch (key) {
|
|
114
109
|
case 'key':
|
|
115
|
-
case 'errors':
|
|
116
110
|
case 'initialValue':
|
|
117
111
|
case 'value':
|
|
118
112
|
case 'valid':
|
|
119
113
|
case 'dirty':
|
|
120
|
-
updateSubjectRef(subjectRef, name, key
|
|
114
|
+
updateSubjectRef(subjectRef, name, key, 'name');
|
|
121
115
|
break;
|
|
116
|
+
case 'errors':
|
|
122
117
|
case 'allErrors':
|
|
123
|
-
updateSubjectRef(subjectRef, name, 'error', 'prefix');
|
|
124
|
-
break;
|
|
125
|
-
case 'allValid':
|
|
126
|
-
updateSubjectRef(subjectRef, name, 'valid', 'prefix');
|
|
118
|
+
updateSubjectRef(subjectRef, name, 'error', key === 'errors' ? 'name' : 'prefix');
|
|
127
119
|
break;
|
|
128
120
|
}
|
|
129
121
|
return Reflect.get(target, key, receiver);
|
|
@@ -165,17 +157,23 @@ function getFormMetadata(formId, state, subjectRef, context, noValidate) {
|
|
|
165
157
|
get(_, key, receiver) {
|
|
166
158
|
switch (key) {
|
|
167
159
|
case 'context':
|
|
168
|
-
return
|
|
160
|
+
return {
|
|
161
|
+
[wrappedSymbol]: context
|
|
162
|
+
};
|
|
169
163
|
case 'status':
|
|
170
164
|
return state.submissionStatus;
|
|
171
|
-
case '
|
|
172
|
-
case '
|
|
165
|
+
case 'validate':
|
|
166
|
+
case 'update':
|
|
167
|
+
case 'reset':
|
|
168
|
+
case 'insert':
|
|
169
|
+
case 'remove':
|
|
170
|
+
case 'reorder':
|
|
173
171
|
return context[key];
|
|
174
172
|
case 'onSubmit':
|
|
175
173
|
return event => {
|
|
176
174
|
var submitEvent = event.nativeEvent;
|
|
177
|
-
context.submit(submitEvent);
|
|
178
|
-
if (
|
|
175
|
+
var submission = context.submit(submitEvent);
|
|
176
|
+
if (submission && submission.status !== 'success' && submission.error !== null) {
|
|
179
177
|
event.preventDefault();
|
|
180
178
|
}
|
|
181
179
|
};
|
|
@@ -187,4 +185,4 @@ function getFormMetadata(formId, state, subjectRef, context, noValidate) {
|
|
|
187
185
|
});
|
|
188
186
|
}
|
|
189
187
|
|
|
190
|
-
export { Form, FormProvider, FormStateInput, getFieldMetadata, getFormMetadata, getMetadata, updateSubjectRef, useFormContext, useFormState, useSubjectRef };
|
|
188
|
+
export { Form, FormProvider, FormStateInput, getFieldMetadata, getFormMetadata, getMetadata, getWrappedFormContext, updateSubjectRef, useFormContext, useFormState, useSubjectRef };
|
package/helpers.d.ts
CHANGED
|
@@ -6,7 +6,6 @@ type FormControlProps = {
|
|
|
6
6
|
name: string;
|
|
7
7
|
form: string;
|
|
8
8
|
required?: boolean;
|
|
9
|
-
autoFocus?: boolean;
|
|
10
9
|
'aria-describedby'?: string;
|
|
11
10
|
'aria-invalid'?: boolean;
|
|
12
11
|
};
|
|
@@ -16,19 +15,19 @@ type FormControlOptions = {
|
|
|
16
15
|
*/
|
|
17
16
|
ariaAttributes?: true;
|
|
18
17
|
/**
|
|
19
|
-
* Decide whether the aria attributes should be based on `
|
|
20
|
-
* @default '
|
|
18
|
+
* Decide whether the aria-invalid attributes should be based on `meta.errors` or `meta.allErrors`.
|
|
19
|
+
* @default 'errors'
|
|
21
20
|
*/
|
|
22
|
-
ariaInvalid?: '
|
|
21
|
+
ariaInvalid?: 'errors' | 'allErrors';
|
|
23
22
|
/**
|
|
24
|
-
* Assign additional `id` to the `aria-describedby` attribute.
|
|
23
|
+
* Assign additional `id` to the `aria-describedby` attribute.
|
|
25
24
|
*/
|
|
26
|
-
ariaDescribedBy?:
|
|
25
|
+
ariaDescribedBy?: string;
|
|
27
26
|
} | {
|
|
28
27
|
ariaAttributes: false;
|
|
29
28
|
};
|
|
30
29
|
type InputProps = Pretty<FormControlProps & {
|
|
31
|
-
type
|
|
30
|
+
type: 'checkbox' | 'color' | 'date' | 'datetime-local' | 'email' | 'file' | 'hidden' | 'image' | 'month' | 'number' | 'password' | 'radio' | 'range' | 'search' | 'tel' | 'text' | 'time' | 'url' | 'week';
|
|
32
31
|
minLength?: number;
|
|
33
32
|
maxLength?: number;
|
|
34
33
|
min?: string | number;
|
|
@@ -48,7 +47,7 @@ type InputOptions = Pretty<FormControlOptions & ({
|
|
|
48
47
|
*/
|
|
49
48
|
value?: string | boolean;
|
|
50
49
|
} | {
|
|
51
|
-
type
|
|
50
|
+
type: Exclude<InputProps['type'], 'checkbox' | 'radio'>;
|
|
52
51
|
/**
|
|
53
52
|
* Decide whether defaultValue should be returned. Pass `false` if you want to mange the value yourself.
|
|
54
53
|
*/
|
|
@@ -130,7 +129,7 @@ export declare function getFormControlProps<Schema>(metadata: FieldMetadata<Sche
|
|
|
130
129
|
* @example
|
|
131
130
|
* ```tsx
|
|
132
131
|
* // To setup an uncontrolled input
|
|
133
|
-
* <input {...getInputProps(metadata)} />
|
|
132
|
+
* <input {...getInputProps(metadata, { type: 'text' })} />
|
|
134
133
|
* // To setup an uncontrolled checkbox
|
|
135
134
|
* <input {...getInputProps(metadata, { type: 'checkbox' })} />
|
|
136
135
|
* // To setup an input without defaultValue
|
|
@@ -139,10 +138,7 @@ export declare function getFormControlProps<Schema>(metadata: FieldMetadata<Sche
|
|
|
139
138
|
* <input {...getInputProps(metadata, { type: 'radio', value: false })} />
|
|
140
139
|
* ```
|
|
141
140
|
*/
|
|
142
|
-
export declare function getInputProps<Schema extends
|
|
143
|
-
export declare function getInputProps<Schema extends File | File[] | null | undefined>(metadata: FieldMetadata<Schema, any, any>, options: InputOptions & {
|
|
144
|
-
type: 'file';
|
|
145
|
-
}): InputProps;
|
|
141
|
+
export declare function getInputProps<Schema extends Primitive | File[]>(metadata: FieldMetadata<Schema, any, any>, options: InputOptions): InputProps;
|
|
146
142
|
/**
|
|
147
143
|
* Derives the properties of a select element based on the field metadata,
|
|
148
144
|
* including common form control attributes like `key`, `id`, `name`, `form`, `autoFocus`, `aria-invalid`, `aria-describedby`
|
package/helpers.js
CHANGED
|
@@ -25,8 +25,8 @@ function getAriaAttributes(metadata) {
|
|
|
25
25
|
if (typeof options.ariaAttributes !== 'undefined' && !options.ariaAttributes) {
|
|
26
26
|
return {};
|
|
27
27
|
}
|
|
28
|
-
var invalid = options.ariaInvalid === '
|
|
29
|
-
var ariaDescribedBy =
|
|
28
|
+
var invalid = options.ariaInvalid === 'allErrors' ? !metadata.valid : typeof metadata.errors !== 'undefined';
|
|
29
|
+
var ariaDescribedBy = options.ariaDescribedBy;
|
|
30
30
|
return simplify({
|
|
31
31
|
'aria-invalid': invalid || undefined,
|
|
32
32
|
'aria-describedby': invalid ? "".concat(metadata.errorId, " ").concat(ariaDescribedBy !== null && ariaDescribedBy !== void 0 ? ariaDescribedBy : '').trim() : ariaDescribedBy
|
|
@@ -75,8 +75,7 @@ function getFormControlProps(metadata, options) {
|
|
|
75
75
|
var _metadata$constraint;
|
|
76
76
|
return simplify(_rollupPluginBabelHelpers.objectSpread2({
|
|
77
77
|
key: metadata.key,
|
|
78
|
-
required: ((_metadata$constraint = metadata.constraint) === null || _metadata$constraint === void 0 ? void 0 : _metadata$constraint.required) || undefined
|
|
79
|
-
autoFocus: !metadata.valid || undefined
|
|
78
|
+
required: ((_metadata$constraint = metadata.constraint) === null || _metadata$constraint === void 0 ? void 0 : _metadata$constraint.required) || undefined
|
|
80
79
|
}, getFieldsetProps(metadata, options)));
|
|
81
80
|
}
|
|
82
81
|
|
|
@@ -91,7 +90,7 @@ function getFormControlProps(metadata, options) {
|
|
|
91
90
|
* @example
|
|
92
91
|
* ```tsx
|
|
93
92
|
* // To setup an uncontrolled input
|
|
94
|
-
* <input {...getInputProps(metadata)} />
|
|
93
|
+
* <input {...getInputProps(metadata, { type: 'text' })} />
|
|
95
94
|
* // To setup an uncontrolled checkbox
|
|
96
95
|
* <input {...getInputProps(metadata, { type: 'checkbox' })} />
|
|
97
96
|
* // To setup an input without defaultValue
|
|
@@ -100,10 +99,8 @@ function getFormControlProps(metadata, options) {
|
|
|
100
99
|
* <input {...getInputProps(metadata, { type: 'radio', value: false })} />
|
|
101
100
|
* ```
|
|
102
101
|
*/
|
|
103
|
-
|
|
104
|
-
function getInputProps(metadata) {
|
|
102
|
+
function getInputProps(metadata, options) {
|
|
105
103
|
var _metadata$constraint2, _metadata$constraint3, _metadata$constraint4, _metadata$constraint5, _metadata$constraint6, _metadata$constraint7, _metadata$constraint8;
|
|
106
|
-
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
107
104
|
var props = _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, getFormControlProps(metadata, options)), {}, {
|
|
108
105
|
type: options.type,
|
|
109
106
|
minLength: (_metadata$constraint2 = metadata.constraint) === null || _metadata$constraint2 === void 0 ? void 0 : _metadata$constraint2.minLength,
|
package/helpers.mjs
CHANGED
|
@@ -21,8 +21,8 @@ function getAriaAttributes(metadata) {
|
|
|
21
21
|
if (typeof options.ariaAttributes !== 'undefined' && !options.ariaAttributes) {
|
|
22
22
|
return {};
|
|
23
23
|
}
|
|
24
|
-
var invalid = options.ariaInvalid === '
|
|
25
|
-
var ariaDescribedBy =
|
|
24
|
+
var invalid = options.ariaInvalid === 'allErrors' ? !metadata.valid : typeof metadata.errors !== 'undefined';
|
|
25
|
+
var ariaDescribedBy = options.ariaDescribedBy;
|
|
26
26
|
return simplify({
|
|
27
27
|
'aria-invalid': invalid || undefined,
|
|
28
28
|
'aria-describedby': invalid ? "".concat(metadata.errorId, " ").concat(ariaDescribedBy !== null && ariaDescribedBy !== void 0 ? ariaDescribedBy : '').trim() : ariaDescribedBy
|
|
@@ -71,8 +71,7 @@ function getFormControlProps(metadata, options) {
|
|
|
71
71
|
var _metadata$constraint;
|
|
72
72
|
return simplify(_objectSpread2({
|
|
73
73
|
key: metadata.key,
|
|
74
|
-
required: ((_metadata$constraint = metadata.constraint) === null || _metadata$constraint === void 0 ? void 0 : _metadata$constraint.required) || undefined
|
|
75
|
-
autoFocus: !metadata.valid || undefined
|
|
74
|
+
required: ((_metadata$constraint = metadata.constraint) === null || _metadata$constraint === void 0 ? void 0 : _metadata$constraint.required) || undefined
|
|
76
75
|
}, getFieldsetProps(metadata, options)));
|
|
77
76
|
}
|
|
78
77
|
|
|
@@ -87,7 +86,7 @@ function getFormControlProps(metadata, options) {
|
|
|
87
86
|
* @example
|
|
88
87
|
* ```tsx
|
|
89
88
|
* // To setup an uncontrolled input
|
|
90
|
-
* <input {...getInputProps(metadata)} />
|
|
89
|
+
* <input {...getInputProps(metadata, { type: 'text' })} />
|
|
91
90
|
* // To setup an uncontrolled checkbox
|
|
92
91
|
* <input {...getInputProps(metadata, { type: 'checkbox' })} />
|
|
93
92
|
* // To setup an input without defaultValue
|
|
@@ -96,10 +95,8 @@ function getFormControlProps(metadata, options) {
|
|
|
96
95
|
* <input {...getInputProps(metadata, { type: 'radio', value: false })} />
|
|
97
96
|
* ```
|
|
98
97
|
*/
|
|
99
|
-
|
|
100
|
-
function getInputProps(metadata) {
|
|
98
|
+
function getInputProps(metadata, options) {
|
|
101
99
|
var _metadata$constraint2, _metadata$constraint3, _metadata$constraint4, _metadata$constraint5, _metadata$constraint6, _metadata$constraint7, _metadata$constraint8;
|
|
102
|
-
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
103
100
|
var props = _objectSpread2(_objectSpread2({}, getFormControlProps(metadata, options)), {}, {
|
|
104
101
|
type: options.type,
|
|
105
102
|
minLength: (_metadata$constraint2 = metadata.constraint) === null || _metadata$constraint2 === void 0 ? void 0 : _metadata$constraint2.minLength,
|
package/hooks.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ import { type FormMetadata, type FieldMetadata, type Pretty } from './context';
|
|
|
8
8
|
export declare const useSafeLayoutEffect: typeof useEffect;
|
|
9
9
|
export declare function useFormId<Schema extends Record<string, unknown>, FormError>(preferredId?: string): FormId<Schema, FormError>;
|
|
10
10
|
export declare function useNoValidate(defaultNoValidate?: boolean): boolean;
|
|
11
|
-
export declare function useForm<Schema extends Record<string, any>,
|
|
11
|
+
export declare function useForm<Schema extends Record<string, any>, FormValue = Schema, FormError = string[]>(options: Pretty<Omit<FormOptions<Schema, FormError, FormValue>, 'formId'> & {
|
|
12
12
|
/**
|
|
13
13
|
* The form id. If not provided, a random id will be generated.
|
|
14
14
|
*/
|
|
@@ -23,12 +23,12 @@ export declare function useForm<Schema extends Record<string, any>, FormError =
|
|
|
23
23
|
FormMetadata<Schema, FormError>,
|
|
24
24
|
ReturnType<FormMetadata<Schema, FormError>['getFieldset']>
|
|
25
25
|
];
|
|
26
|
-
export declare function useFormMetadata<Schema extends Record<string, any>, FormError>(formId: FormId<Schema, FormError>, options?: {
|
|
26
|
+
export declare function useFormMetadata<Schema extends Record<string, any>, FormError = string[]>(formId: FormId<Schema, FormError>, options?: {
|
|
27
27
|
defaultNoValidate?: boolean;
|
|
28
28
|
}): FormMetadata<Schema, FormError>;
|
|
29
|
-
export declare function useField<FieldSchema,
|
|
29
|
+
export declare function useField<FieldSchema, FormSchema extends Record<string, unknown> = Record<string, unknown>, FormError = string[]>(name: FieldName<FieldSchema, FormSchema, FormError>, options?: {
|
|
30
30
|
formId?: FormId<FormSchema, FormError>;
|
|
31
31
|
}): [
|
|
32
|
-
FieldMetadata<FieldSchema,
|
|
32
|
+
FieldMetadata<FieldSchema, FormSchema, FormError>,
|
|
33
33
|
FormMetadata<FormSchema, FormError>
|
|
34
34
|
];
|
package/hooks.js
CHANGED
|
@@ -7,6 +7,8 @@ var dom = require('@conform-to/dom');
|
|
|
7
7
|
var react = require('react');
|
|
8
8
|
var context = require('./context.js');
|
|
9
9
|
|
|
10
|
+
var _excluded = ["id"];
|
|
11
|
+
|
|
10
12
|
/**
|
|
11
13
|
* useLayoutEffect is client-only.
|
|
12
14
|
* This basically makes it a no-op on server
|
|
@@ -30,33 +32,26 @@ function useNoValidate() {
|
|
|
30
32
|
return noValidate;
|
|
31
33
|
}
|
|
32
34
|
function useForm(options) {
|
|
33
|
-
var
|
|
34
|
-
|
|
35
|
+
var {
|
|
36
|
+
id
|
|
37
|
+
} = options,
|
|
38
|
+
formConfig = _rollupPluginBabelHelpers.objectWithoutProperties(options, _excluded);
|
|
39
|
+
var formId = useFormId(id);
|
|
40
|
+
var [context$1] = react.useState(() => dom.unstable_createFormContext(_rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, formConfig), {}, {
|
|
35
41
|
formId
|
|
36
42
|
})));
|
|
37
|
-
var optionsRef = react.useRef(options);
|
|
38
43
|
useSafeLayoutEffect(() => {
|
|
39
|
-
document.addEventListener('input', context$1.
|
|
40
|
-
document.addEventListener('focusout', context$1.
|
|
41
|
-
document.addEventListener('reset', context$1.
|
|
44
|
+
document.addEventListener('input', context$1.onInput);
|
|
45
|
+
document.addEventListener('focusout', context$1.onBlur);
|
|
46
|
+
document.addEventListener('reset', context$1.onReset);
|
|
42
47
|
return () => {
|
|
43
|
-
document.removeEventListener('input', context$1.
|
|
44
|
-
document.removeEventListener('focusout', context$1.
|
|
45
|
-
document.removeEventListener('reset', context$1.
|
|
48
|
+
document.removeEventListener('input', context$1.onInput);
|
|
49
|
+
document.removeEventListener('focusout', context$1.onBlur);
|
|
50
|
+
document.removeEventListener('reset', context$1.onReset);
|
|
46
51
|
};
|
|
47
52
|
}, [context$1]);
|
|
48
53
|
useSafeLayoutEffect(() => {
|
|
49
|
-
|
|
50
|
-
// If there is no change, do nothing
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
if (options.lastResult) {
|
|
54
|
-
context$1.report(options.lastResult);
|
|
55
|
-
}
|
|
56
|
-
}, [context$1, options.lastResult]);
|
|
57
|
-
useSafeLayoutEffect(() => {
|
|
58
|
-
optionsRef.current = options;
|
|
59
|
-
context$1.update(_rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, options), {}, {
|
|
54
|
+
context$1.onUpdate(_rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, formConfig), {}, {
|
|
60
55
|
formId
|
|
61
56
|
}));
|
|
62
57
|
});
|