react-f0rm 0.3.0 → 0.4.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/dist/index.d.ts CHANGED
@@ -151,9 +151,11 @@ declare function useFormContext<T extends Record<string, any> = any>(): Form$1<T
151
151
  * (`Ctx.useField({name: 'user.name'})` gets its `name` constrained by
152
152
  * `FieldPath<Values>` and its `value` typed accordingly), so call sites stop
153
153
  * hand-writing generics, and each instance's Provider scopes a strictly
154
- * separate form.
154
+ * separate form. The bundle also carries its raw React context
155
+ * (`Ctx.context`) so `<Form context={Ctx.context}>` can provide into it.
155
156
  */
156
157
  declare function createFormContext<TValues extends Record<string, any> = any>(): {
158
+ context: React.Context<Form$1<TValues> | null>;
157
159
  FormProvider: ({ form, children }: {
158
160
  form: Form$1<TValues>;
159
161
  children: ReactNode;
@@ -316,6 +318,16 @@ declare function subscribe(form: Form$1, options: SubscribeOptions): () => void;
316
318
  */
317
319
  interface FormProps<T extends Record<string, any> = any> extends Omit<React.FormHTMLAttributes<HTMLFormElement>, 'onSubmit'> {
318
320
  form?: Form<T>;
321
+ /**
322
+ * Provide into an isolated context from `createFormContext()` instead of
323
+ * the module-level one — `<Form context={ProfileForm.context}>` keeps the
324
+ * component's full submit machinery while the factory's bound hooks
325
+ * (`ProfileForm.useField`, `ProfileForm.useFormContext`, ...) resolve this
326
+ * form from their private context. The module-level `useFormContext()` /
327
+ * `useField` do not see it; that is the point of the isolation. Omitted,
328
+ * the form lands in the module-level FormContext as before.
329
+ */
330
+ context?: React.Context<Form<any> | null>;
319
331
  initialValues?: T;
320
332
  /**
321
333
  * Controlled external values. When the `values` reference changes, the
@@ -349,14 +361,34 @@ interface FormProps<T extends Record<string, any> = any> extends Omit<React.Form
349
361
  */
350
362
  shouldFocusError?: boolean;
351
363
  }
352
- declare function Form<T extends Record<string, any> = any>({ form: f1, initialValues, values, onSubmit, onValidSubmit, onInvalidSubmit, shouldFocusError, ...props }: FormProps<T>): React.JSX.Element;
364
+ declare function Form<T extends Record<string, any> = any>({ form: f1, context, initialValues, values, onSubmit, onValidSubmit, onInvalidSubmit, shouldFocusError, ...props }: FormProps<T>): React.JSX.Element;
353
365
 
354
- interface UseFieldOptions {
355
- form?: any;
356
- name?: Name;
366
+ /**
367
+ * Props shared by Field/Checkbox/Select. Generic so a typed form flows into
368
+ * the `validate` callback: with `form` (a `Form<Values>`) and `name`
369
+ * (a `FieldPath<Values>`) provided, `validate` receives the value at that
370
+ * path — `PathValueOf<Values, P>` — instead of `any`. The defaults keep the
371
+ * bare `<Field name="x" />` (context-resolved, untyped) call sites exactly
372
+ * as permissive as before.
373
+ */
374
+ interface UseFieldOptions<TValues extends Record<string, any> = any, TPath extends FieldPath<TValues> | Name = Name> {
375
+ form?: Form$1<TValues>;
376
+ name?: TPath;
357
377
  initialValue?: any;
358
378
  shouldUnregister?: boolean;
359
- validate?: Validator;
379
+ /**
380
+ * Field-level validator. The value argument is typed when the field is
381
+ * tied to a typed form (via the `form` prop); the return shape mirrors
382
+ * {@link Validator} — an error (string / FieldError / mixed array) or
383
+ * undefined when valid, possibly a Promise for async validation. The
384
+ * second argument carries the validation context (`meta.signal` aborts
385
+ * when the round is superseded).
386
+ */
387
+ validate?: (value: PathValueOf<TValues, TPath>, meta: {
388
+ form: Form$1;
389
+ path: Path;
390
+ signal: AbortSignal;
391
+ }) => ReturnType<Validator>;
360
392
  /**
361
393
  * Declarative rules (required/min/max/minLength/maxLength/pattern),
362
394
  * compiled into a validator that runs before `validate`; failures land
@@ -388,7 +420,7 @@ interface UseFieldOptions {
388
420
  delayError?: number;
389
421
  [key: string]: any;
390
422
  }
391
- interface FieldProps extends UseFieldOptions {
423
+ interface FieldProps<TValues extends Record<string, any> = any, TPath extends FieldPath<TValues> | Name = Name> extends UseFieldOptions<TValues, TPath> {
392
424
  as?: React.ComponentType<any>;
393
425
  asProps?: Record<string, any>;
394
426
  eventToValue?: (e: any) => any;
@@ -402,15 +434,39 @@ interface FieldProps extends UseFieldOptions {
402
434
  */
403
435
  renderError?: (error: string, id: string) => React.ReactNode;
404
436
  }
405
- declare const Field: React.ForwardRefExoticComponent<Omit<FieldProps, "ref"> & React.RefAttributes<HTMLInputElement>>;
406
- interface CheckboxProps extends UseFieldOptions {
437
+ /**
438
+ * The callable shape of {@link Field}: `form` + `name` flow their generics
439
+ * into `validate`'s value argument (`PathValueOf<TValues, TPath>`). A named
440
+ * interface rather than an inline `as <TValues, ...>() => ...` signature —
441
+ * same types, and the inline form trips no-use-before-define on the type
442
+ * parameters.
443
+ */
444
+ interface FieldComponent {
445
+ <TValues extends Record<string, any> = any, TPath extends FieldPath<TValues> | Name = Name>(props: FieldProps<TValues, TPath> & React.RefAttributes<HTMLInputElement>): React.ReactElement | null;
446
+ }
447
+ declare const Field: FieldComponent;
448
+ interface CheckboxProps<TValues extends Record<string, any> = any, TPath extends FieldPath<TValues> | Name = Name> extends UseFieldOptions<TValues, TPath> {
449
+ }
450
+ /**
451
+ * Callable shape of {@link Checkbox}: the same form-typed `validate`
452
+ * inference contract as {@link FieldComponent}.
453
+ */
454
+ interface CheckboxComponent {
455
+ <TValues extends Record<string, any> = any, TPath extends FieldPath<TValues> | Name = Name>(props: CheckboxProps<TValues, TPath> & React.RefAttributes<HTMLInputElement>): React.ReactElement | null;
407
456
  }
408
- declare const Checkbox: React.ForwardRefExoticComponent<Omit<CheckboxProps, "ref"> & React.RefAttributes<HTMLInputElement>>;
409
- interface SelectProps extends UseFieldOptions {
457
+ declare const Checkbox: CheckboxComponent;
458
+ interface SelectProps<TValues extends Record<string, any> = any, TPath extends FieldPath<TValues> | Name = Name> extends UseFieldOptions<TValues, TPath> {
410
459
  multiple?: boolean;
411
460
  children?: React.ReactNode;
412
461
  }
413
- declare const Select: React.ForwardRefExoticComponent<Omit<SelectProps, "ref"> & React.RefAttributes<HTMLSelectElement>>;
462
+ /**
463
+ * Callable shape of {@link Select}: the same form-typed `validate`
464
+ * inference contract as {@link FieldComponent}.
465
+ */
466
+ interface SelectComponent {
467
+ <TValues extends Record<string, any> = any, TPath extends FieldPath<TValues> | Name = Name>(props: SelectProps<TValues, TPath> & React.RefAttributes<HTMLSelectElement>): React.ReactElement | null;
468
+ }
469
+ declare const Select: SelectComponent;
414
470
 
415
471
  export { Checkbox, CheckboxGroupContext, CheckboxGroupProvider, Field, FieldError, FieldPath, Form, FormContext, Form$1 as FormInstance, FormProvider, Name, Options, PathValueOf, Select, createFormContext, subscribe, useCheckboxGroupContext, useDirtyFields, useError, useErrorByPath, useField, useFieldArray, useFieldErrors, useFieldErrorsByPath, useForm, useFormContext, useHasErrors, useIsDirty, useIsSubmitting, useSubmitCount, useTouched, useTouchedByPath, useTouchedFields, useValue, useValueByPath, useWatch };
416
472
  export type { FieldRules, SubscribeEvent, SubscribeOptions, WatchScope };
package/dist/index.mjs CHANGED
@@ -1421,7 +1421,13 @@ function createFormContext() {
1421
1421
  function useFieldArray(options) {
1422
1422
  return useFieldArrayCore(options, Context);
1423
1423
  }
1424
- return { FormProvider: FormProvider2, useFormContext: useFormContext2, useField, useFieldArray };
1424
+ return {
1425
+ context: Context,
1426
+ FormProvider: FormProvider2,
1427
+ useFormContext: useFormContext2,
1428
+ useField,
1429
+ useFieldArray
1430
+ };
1425
1431
  }
1426
1432
  const CheckboxGroupContext = createContext(null);
1427
1433
  const CheckboxGroupProvider = CheckboxGroupContext.Provider;
@@ -1433,6 +1439,7 @@ function useCheckboxGroupContext() {
1433
1439
 
1434
1440
  function Form({
1435
1441
  form: f1,
1442
+ context,
1436
1443
  initialValues,
1437
1444
  values,
1438
1445
  onSubmit,
@@ -1449,7 +1456,8 @@ function Form({
1449
1456
  onInvalidSubmit,
1450
1457
  shouldFocusError
1451
1458
  });
1452
- return /* @__PURE__ */ React.createElement(FormProvider, { value: form }, /* @__PURE__ */ React.createElement("form", { ...props, noValidate: true, onSubmit: submit }));
1459
+ const { Provider } = context ?? FormContext;
1460
+ return /* @__PURE__ */ React.createElement(Provider, { value: form }, /* @__PURE__ */ React.createElement("form", { ...props, noValidate: true, onSubmit: submit }));
1453
1461
  }
1454
1462
 
1455
1463
  function setRef(ref, value) {