@conform-to/react 1.0.0-rc.0 → 1.0.0-rc.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 CHANGED
@@ -10,7 +10,7 @@
10
10
 
11
11
  Version 1.0.0-rc.0 / License MIT / Copyright (c) 2024 Edmund Hung
12
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.
13
+ 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.
14
14
 
15
15
  > Getting Started
16
16
 
@@ -21,7 +21,7 @@ Check out the overview and tutorial at our website https://conform.guide
21
21
  The documentation is divided into several sections:
22
22
 
23
23
  * Overview: https://conform.guide/overview
24
- * Example Usages: https://conform.guide/examples
24
+ * Examples: https://conform.guide/examples
25
25
  * Complex structures: https://conform.guide/complex-structures
26
26
  * UI Integrations: https://conform.guide/integrations
27
27
  * Accessibility Guide: https://conform.guide/accessibility
package/context.d.ts CHANGED
@@ -1,5 +1,5 @@
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
- import { type ReactElement, type ReactNode, type MutableRefObject } from 'react';
1
+ import { type Constraint, type FormId, type FieldName, type FormContext as BaseFormContext, type FormValue, type FormState, type Intent, type SubscriptionScope, type SubscriptionSubject, type UnionKeyof, type UnionKeyType, type FormOptions as BaseFormOptions } from '@conform-to/dom';
2
+ import { type FormEvent, type ReactElement, type ReactNode, type MutableRefObject } from 'react';
3
3
  export type Pretty<T> = {
4
4
  [K in keyof T]: T[K];
5
5
  } & {};
@@ -35,16 +35,16 @@ export type FieldMetadata<Schema = unknown, FormSchema extends Record<string, an
35
35
  };
36
36
  getFieldList: unknown extends Schema ? () => unknown : Schema extends Array<infer Item> ? () => Array<FieldMetadata<Item, FormSchema, FormError>> : never;
37
37
  };
38
- export declare const Form: import("react").Context<FormContext[]>;
38
+ export declare const Form: import("react").Context<FormContext<any, string[], any>[]>;
39
39
  declare const wrappedSymbol: unique symbol;
40
40
  export type Wrapped<Type> = {
41
41
  [wrappedSymbol]: Type;
42
42
  };
43
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>;
44
+ export declare function useFormContext<Schema extends Record<string, any>, FormError>(formId?: FormId<Schema, FormError>): FormContext<Schema, FormError, unknown>;
45
+ export declare function useFormState<FormError>(form: FormContext<any, FormError>, subjectRef?: MutableRefObject<SubscriptionSubject>): FormState<FormError>;
46
46
  export declare function FormProvider(props: {
47
- context: Wrapped<FormContext<any, any, any>>;
47
+ context: Wrapped<FormContext<any, any>>;
48
48
  children: ReactNode;
49
49
  }): ReactElement;
50
50
  export declare function FormStateInput(props: {
@@ -54,5 +54,16 @@ export declare function useSubjectRef(initialSubject?: SubscriptionSubject): Mut
54
54
  export declare function updateSubjectRef(ref: MutableRefObject<SubscriptionSubject>, name: string, subject: keyof SubscriptionSubject, scope: keyof SubscriptionScope): void;
55
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
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>;
57
+ export declare function getFormMetadata<Schema extends Record<string, any>, FormError = string[], FormValue = Schema>(formId: FormId<Schema, FormError>, state: FormState<FormError>, subjectRef: MutableRefObject<SubscriptionSubject>, context: FormContext<Schema, FormError, FormValue>, noValidate: boolean): FormMetadata<Schema, FormError>;
58
+ export type FormOptions<Schema extends Record<string, any> = any, FormError = string[], FormValue = Schema> = BaseFormOptions<Schema, FormError, FormValue> & {
59
+ /**
60
+ * A function to be called before the form is submitted.
61
+ */
62
+ onSubmit?: (event: FormEvent<HTMLFormElement>, context: ReturnType<BaseFormContext<Schema, FormError, FormValue>['submit']>) => void;
63
+ };
64
+ export type FormContext<Schema extends Record<string, any> = any, FormError = string[], FormValue = Schema> = Omit<BaseFormContext<Schema, FormError, FormValue>, 'submit' | 'onUpdate'> & {
65
+ submit: (event: FormEvent<HTMLFormElement>) => void;
66
+ onUpdate: (options: Partial<FormOptions<Schema, FormError, FormValue>>) => void;
67
+ };
68
+ export declare function createFormContext<Schema extends Record<string, any> = any, FormError = string[], FormValue = Schema>(options: FormOptions<Schema, FormError, FormValue>): FormContext<Schema, FormError, FormValue>;
58
69
  export {};
package/context.js CHANGED
@@ -7,6 +7,7 @@ var dom = require('@conform-to/dom');
7
7
  var react = require('react');
8
8
  var jsxRuntime = require('react/jsx-runtime');
9
9
 
10
+ var _excluded = ["onSubmit"];
10
11
  var Form = /*#__PURE__*/react.createContext([]);
11
12
 
12
13
  // To hide the FormContext type from the public API
@@ -174,13 +175,7 @@ function getFormMetadata(formId, state, subjectRef, context, noValidate) {
174
175
  case 'reorder':
175
176
  return context[key];
176
177
  case 'onSubmit':
177
- return event => {
178
- var submitEvent = event.nativeEvent;
179
- var submission = context.submit(submitEvent);
180
- if (submission && submission.status !== 'success' && submission.error !== null) {
181
- event.preventDefault();
182
- }
183
- };
178
+ return context.submit;
184
179
  case 'noValidate':
185
180
  return noValidate;
186
181
  }
@@ -188,10 +183,34 @@ function getFormMetadata(formId, state, subjectRef, context, noValidate) {
188
183
  }
189
184
  });
190
185
  }
186
+ function createFormContext(options) {
187
+ var {
188
+ onSubmit
189
+ } = options,
190
+ rest = _rollupPluginBabelHelpers.objectWithoutProperties(options, _excluded);
191
+ var context = dom.unstable_createFormContext(rest);
192
+ return _rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, context), {}, {
193
+ submit(event) {
194
+ var submitEvent = event.nativeEvent;
195
+ var result = context.submit(submitEvent);
196
+ if (result.submission && result.submission.status !== 'success' && result.submission.error !== null) {
197
+ event.preventDefault();
198
+ } else {
199
+ var _onSubmit;
200
+ (_onSubmit = onSubmit) === null || _onSubmit === void 0 || _onSubmit(event, result);
201
+ }
202
+ },
203
+ onUpdate(options) {
204
+ onSubmit = options.onSubmit;
205
+ context.onUpdate(options);
206
+ }
207
+ });
208
+ }
191
209
 
192
210
  exports.Form = Form;
193
211
  exports.FormProvider = FormProvider;
194
212
  exports.FormStateInput = FormStateInput;
213
+ exports.createFormContext = createFormContext;
195
214
  exports.getFieldMetadata = getFieldMetadata;
196
215
  exports.getFormMetadata = getFormMetadata;
197
216
  exports.getMetadata = getMetadata;
package/context.mjs CHANGED
@@ -1,8 +1,9 @@
1
- import { objectSpread2 as _objectSpread2 } from './_virtual/_rollupPluginBabelHelpers.mjs';
2
- import { STATE, formatPaths, getPaths, isPrefix } from '@conform-to/dom';
1
+ import { objectWithoutProperties as _objectWithoutProperties, objectSpread2 as _objectSpread2 } from './_virtual/_rollupPluginBabelHelpers.mjs';
2
+ import { STATE, formatPaths, getPaths, unstable_createFormContext, isPrefix } from '@conform-to/dom';
3
3
  import { useContext, useMemo, createContext, useCallback, useSyncExternalStore, useRef } from 'react';
4
4
  import { jsx } from 'react/jsx-runtime';
5
5
 
6
+ var _excluded = ["onSubmit"];
6
7
  var Form = /*#__PURE__*/createContext([]);
7
8
 
8
9
  // To hide the FormContext type from the public API
@@ -170,13 +171,7 @@ function getFormMetadata(formId, state, subjectRef, context, noValidate) {
170
171
  case 'reorder':
171
172
  return context[key];
172
173
  case 'onSubmit':
173
- return event => {
174
- var submitEvent = event.nativeEvent;
175
- var submission = context.submit(submitEvent);
176
- if (submission && submission.status !== 'success' && submission.error !== null) {
177
- event.preventDefault();
178
- }
179
- };
174
+ return context.submit;
180
175
  case 'noValidate':
181
176
  return noValidate;
182
177
  }
@@ -184,5 +179,28 @@ function getFormMetadata(formId, state, subjectRef, context, noValidate) {
184
179
  }
185
180
  });
186
181
  }
182
+ function createFormContext(options) {
183
+ var {
184
+ onSubmit
185
+ } = options,
186
+ rest = _objectWithoutProperties(options, _excluded);
187
+ var context = unstable_createFormContext(rest);
188
+ return _objectSpread2(_objectSpread2({}, context), {}, {
189
+ submit(event) {
190
+ var submitEvent = event.nativeEvent;
191
+ var result = context.submit(submitEvent);
192
+ if (result.submission && result.submission.status !== 'success' && result.submission.error !== null) {
193
+ event.preventDefault();
194
+ } else {
195
+ var _onSubmit;
196
+ (_onSubmit = onSubmit) === null || _onSubmit === void 0 || _onSubmit(event, result);
197
+ }
198
+ },
199
+ onUpdate(options) {
200
+ onSubmit = options.onSubmit;
201
+ context.onUpdate(options);
202
+ }
203
+ });
204
+ }
187
205
 
188
- export { Form, FormProvider, FormStateInput, getFieldMetadata, getFormMetadata, getMetadata, getWrappedFormContext, updateSubjectRef, useFormContext, useFormState, useSubjectRef };
206
+ export { Form, FormProvider, FormStateInput, createFormContext, getFieldMetadata, getFormMetadata, getMetadata, getWrappedFormContext, updateSubjectRef, useFormContext, useFormState, useSubjectRef };
package/helpers.d.ts CHANGED
@@ -27,7 +27,7 @@ type FormControlOptions = {
27
27
  ariaAttributes: false;
28
28
  };
29
29
  type InputProps = Pretty<FormControlProps & {
30
- type: 'checkbox' | 'color' | 'date' | 'datetime-local' | 'email' | 'file' | 'hidden' | 'image' | 'month' | 'number' | 'password' | 'radio' | 'range' | 'search' | 'tel' | 'text' | 'time' | 'url' | 'week';
30
+ type: 'checkbox' | 'color' | 'date' | 'datetime-local' | 'email' | 'file' | 'hidden' | 'month' | 'number' | 'password' | 'radio' | 'range' | 'search' | 'tel' | 'text' | 'time' | 'url' | 'week';
31
31
  minLength?: number;
32
32
  maxLength?: number;
33
33
  min?: string | number;
package/hooks.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { type FormId, type FieldName, type FormOptions } from '@conform-to/dom';
1
+ import { type FormId, type FieldName } from '@conform-to/dom';
2
2
  import { useEffect } from 'react';
3
- import { type FormMetadata, type FieldMetadata, type Pretty } from './context';
3
+ import { type FormMetadata, type FieldMetadata, type Pretty, type FormOptions } from './context';
4
4
  /**
5
5
  * useLayoutEffect is client-only.
6
6
  * This basically makes it a no-op on server
package/hooks.js CHANGED
@@ -3,7 +3,6 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var _rollupPluginBabelHelpers = require('./_virtual/_rollupPluginBabelHelpers.js');
6
- var dom = require('@conform-to/dom');
7
6
  var react = require('react');
8
7
  var context = require('./context.js');
9
8
 
@@ -37,7 +36,7 @@ function useForm(options) {
37
36
  } = options,
38
37
  formConfig = _rollupPluginBabelHelpers.objectWithoutProperties(options, _excluded);
39
38
  var formId = useFormId(id);
40
- var [context$1] = react.useState(() => dom.unstable_createFormContext(_rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, formConfig), {}, {
39
+ var [context$1] = react.useState(() => context.createFormContext(_rollupPluginBabelHelpers.objectSpread2(_rollupPluginBabelHelpers.objectSpread2({}, formConfig), {}, {
41
40
  formId
42
41
  })));
43
42
  useSafeLayoutEffect(() => {
package/hooks.mjs CHANGED
@@ -1,7 +1,6 @@
1
1
  import { objectWithoutProperties as _objectWithoutProperties, objectSpread2 as _objectSpread2 } from './_virtual/_rollupPluginBabelHelpers.mjs';
2
- import { unstable_createFormContext } from '@conform-to/dom';
3
2
  import { useState, useEffect, useLayoutEffect, useId } from 'react';
4
- import { useSubjectRef, useFormState, getFormMetadata, useFormContext, getFieldMetadata } from './context.mjs';
3
+ import { createFormContext, useSubjectRef, useFormState, getFormMetadata, useFormContext, getFieldMetadata } from './context.mjs';
5
4
 
6
5
  var _excluded = ["id"];
7
6
 
@@ -33,7 +32,7 @@ function useForm(options) {
33
32
  } = options,
34
33
  formConfig = _objectWithoutProperties(options, _excluded);
35
34
  var formId = useFormId(id);
36
- var [context] = useState(() => unstable_createFormContext(_objectSpread2(_objectSpread2({}, formConfig), {}, {
35
+ var [context] = useState(() => createFormContext(_objectSpread2(_objectSpread2({}, formConfig), {}, {
37
36
  formId
38
37
  })));
39
38
  useSafeLayoutEffect(() => {
package/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export { type Submission, type SubmissionResult, type DefaultValue, type Intent, type FormId, type FieldName, parse, } from '@conform-to/dom';
2
2
  export { type FieldMetadata, type FormMetadata, FormProvider, FormStateInput, } from './context';
3
3
  export { useForm, useFormMetadata, useField } from './hooks';
4
- export { type InputControlOptions, useInputControl } from './integrations';
4
+ export { useInputControl } from './integrations';
5
5
  export { getFormProps, getFieldsetProps, getInputProps, getSelectProps, getTextareaProps, getCollectionProps, } from './helpers';
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.0.0-rc.0",
6
+ "version": "1.0.0-rc.1",
7
7
  "main": "index.js",
8
8
  "module": "index.mjs",
9
9
  "types": "index.d.ts",
@@ -30,7 +30,7 @@
30
30
  "url": "https://github.com/edmundhung/conform/issues"
31
31
  },
32
32
  "dependencies": {
33
- "@conform-to/dom": "1.0.0-rc.0"
33
+ "@conform-to/dom": "1.0.0-rc.1"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@types/react": "^18.2.43",