From 5cd65ca2c47d2ee3573d0178d755b6448cd8e6fc Mon Sep 17 00:00:00 2001
From: Volodymyr Zakhovaiko
Date: Fri, 17 Jan 2025 13:24:02 +0100
Subject: [PATCH 1/4] Added API reference docs
---
website/docs/api-reference/_category_.json | 5 +
website/docs/api-reference/bridges.mdx | 288 ++++++++
website/docs/api-reference/context-data.mdx | 132 ++++
website/docs/api-reference/fields.mdx | 687 ++++++++++++++++++++
website/docs/api-reference/forms.mdx | 462 +++++++++++++
website/docs/api-reference/helpers.mdx | 217 +++++++
6 files changed, 1791 insertions(+)
create mode 100644 website/docs/api-reference/_category_.json
create mode 100644 website/docs/api-reference/bridges.mdx
create mode 100644 website/docs/api-reference/context-data.mdx
create mode 100644 website/docs/api-reference/fields.mdx
create mode 100644 website/docs/api-reference/forms.mdx
create mode 100644 website/docs/api-reference/helpers.mdx
diff --git a/website/docs/api-reference/_category_.json b/website/docs/api-reference/_category_.json
new file mode 100644
index 000000000..12c1a64c1
--- /dev/null
+++ b/website/docs/api-reference/_category_.json
@@ -0,0 +1,5 @@
+{
+ "position": 4,
+ "label": "API Reference",
+ "collapsible": false
+}
diff --git a/website/docs/api-reference/bridges.mdx b/website/docs/api-reference/bridges.mdx
new file mode 100644
index 000000000..b76ef3a28
--- /dev/null
+++ b/website/docs/api-reference/bridges.mdx
@@ -0,0 +1,288 @@
+---
+id: bridges
+title: 'Bridges'
+sidebar_position: 3
+---
+
+To make use of any schema, uniforms have to create a _bridge_ of it - a unified schema mapper.
+
+
+
+
+
+Currently available bridges:
+
+- `JSONSchemaBridge` in `uniforms-bridge-json-schema` ([schema documentation](https://json-schema.org/))
+- `SimpleSchema2Bridge` in `uniforms-bridge-simple-schema-2` ([schema documentation](https://github.com/longshotlabs/simpl-schema#readme))
+- `ZodBridge` in `uniforms-bridge-zod` ([schema documentation](https://zod.dev/))
+
+Deprecated bridges:
+
+- `SimpleSchemaBridge` in `uniforms-bridge-simple-schema` ([schema documentation](https://github.com/Meteor-Community-Packages/meteor-simple-schema/blob/master/DOCS.md))
+- `GraphQLBridge` in `uniforms-bridge-graphql` ([schema documentation](https://graphql.org/))
+
+If you see a lot of [`Warning: Unknown props...`](https://fb.me/react-unknown-prop) logs, check if your schema or theme doesn't provide extra props. If so, consider [registering it with `filterDOMProps`](/docs/api-helpers#filterdomprops).
+
+## `JSONSchemaBridge`
+
+```tsx
+import Ajv from 'ajv';
+import { JSONSchemaBridge } from 'uniforms-bridge-json-schema';
+
+const ajv = new Ajv({ allErrors: true, useDefaults: true });
+
+const schema = {
+ title: 'Person',
+ type: 'object',
+ properties: {
+ firstName: { type: 'string' },
+ lastName: { type: 'string' },
+ age: {
+ description: 'Age in years',
+ type: 'integer',
+ minimum: 0,
+ },
+ },
+ required: ['firstName', 'lastName'],
+};
+
+function createValidator(schema: object) {
+ const validator = ajv.compile(schema);
+
+ return (model: object) => {
+ validator(model);
+ return validator.errors?.length ? { details: validator.errors } : null;
+ };
+}
+
+const validator = createValidator(schema);
+
+const bridge = new JSONSchemaBridge({ schema, validator });
+```
+
+### Note on `allOf`/`anyOf`/`oneOf`
+
+The current handling of `allOf`/`anyOf`/`oneOf` is not complete and does not work with all possible cases. For an in-detail discussion, see [\#863](https://github.com/vazco/uniforms/issues/863). How it works, is that only a few properties are being used:
+
+- `properties`, where all subfields are merged (last definition wins),
+- `required`, where all properties are accumulated, and
+- `type`, where the first one is being used.
+
+Below is an example of these implications:
+
+```ts
+{
+ "type": "object",
+ "properties": {
+ // This will render `NumField` WITHOUT `min` nor `max` properties.
+ // It will be properly validated, but without any UI guidelines.
+ "foo": {
+ "type": "number",
+ "allOf": [{ "minimum": 0 }, { "maximum": 10 }]
+ },
+ // This will render as `TextField`.
+ "bar": {
+ "oneOf": [{ "type": "string" }, { "type": "number" }]
+ }
+ }
+}
+```
+
+### Note on Bluebird
+
+If you're using the [`bluebird`](https://www.npmjs.com/package/bluebird) package, you may have seen the following warning ([docs](http://bluebirdjs.com/docs/warning-explanations.html#warning-a-promise-was-rejected-with-a-non-error)):
+
+> Warning: a promise was rejected with a non-error [object Object]
+
+There could be multiple causes of this error. One of it is not returning a proper error object.
+
+In order to fix it, your `validator` function should return a `Error`-like object instead of an object with a single `details` property. The cleanest would be to create a custom `ValidationError` class:
+
+```ts
+import { ErrorObject } from 'ajv';
+
+class ValidationError extends Error {
+ name = 'ValidationError';
+
+ constructor(public details: ErrorObject[]) {
+ super('ValidationError');
+ }
+}
+
+// Usage.
+return validator.errors?.length ? new ValidationError(validator.errors) : null;
+```
+
+Another cause of this error may be two different implementations of the `Promise` object when using an asynchronous validate function.
+Ensure that you are returning the same `Promise` object implementation that Bluebird is expecting.
+The simplest way to do that should be to avoid using the `async` keyword and instead make the function return a `Promise` instead.
+
+See [#1047](https://github.com/vazco/uniforms/discussions/1047) for more details.
+
+## `SimpleSchema2Bridge`
+
+```tsx
+import SimpleSchema from 'simpl-schema';
+import SimpleSchema2Bridge from 'uniforms-bridge-simple-schema-2';
+
+const schema = new SimpleSchema({
+ // ...
+
+ aboutMe: {
+ type: String,
+ uniforms: MyText, // Component...
+ uniforms: {
+ // ...or object...
+ component: MyText, // ...with component...
+ propA: 1, // ...and/or extra props.
+ },
+ },
+});
+
+const bridge = new SimpleSchema2Bridge({ schema });
+```
+
+## `ZodBridge`
+
+```tsx
+import ZodBridge from 'uniforms-bridge-zod';
+import z from 'zod';
+
+const schema = z.object({ aboutMe: z.string() });
+
+const bridge = new ZodBridge({ schema });
+```
+
+## `SimpleSchemaBridge`
+
+:::caution
+
+SimpleSchemaBridge is deprecated since uniforms v4.
+
+:::
+
+```tsx
+import SimpleSchemaBridge from 'uniforms-bridge-simple-schema';
+import { SimpleSchema } from 'aldeed:simple-schema';
+
+const schema = new SimpleSchema({
+ // ...
+
+ aboutMe: {
+ type: String,
+ uniforms: MyText, // Component...
+ uniforms: {
+ // ...or object...
+ component: MyText, // ...with component...
+ propA: 1, // ...and/or extra props.
+ },
+ },
+});
+
+const bridge = new SimpleSchemaBridge({ schema });
+```
+
+## `ZodBridge`
+
+```tsx
+import ZodBridge from 'uniforms-bridge-zod';
+import z from 'zod';
+
+const schema = z.object({ aboutMe: z.string() });
+
+const bridge = new ZodBridge({ schema });
+```
+
+## `GraphQLBridge`
+
+:::caution
+
+GraphQLBridge is deprecated since uniforms v4.
+
+:::
+
+This bridge enables using GraphQL schema types as uniforms forms.
+This saves you from not having to rewrite the form schema in your code.
+As a trade-off, you have to write the validator from scratch. In some cases, it might be easier to rewrite the schema and use, for example, [`JSONSchemaBridge` with `ajv`](/docs/api-bridges#jsonschemabridge).
+If only a simple or no validation is needed, this bridge is perfectly suited to work with GraphQL schemas.
+
+The constructor accepts these arguments:
+
+- `schema: GraphQLType` can be any type parsed and extracted from a GraphQL schema.
+- `validator: (model: Record) => any` a custom validator function that should return a falsy value if no errors are present or information about errors in the model as described in the [custom bridge section](/docs/examples-custom-bridge#validator-definition).
+- `extras: Record = {}` used to extend the schema generated from GraphQL type with extra field configuration.
+- `provideDefaultLabelFromFieldName = true` if set to `true`, the bridge will use the field name as a label if no label is provided in the schema.
+
+### Code example
+
+```tsx
+import { GraphQLBridge } from 'uniforms-bridge-graphql';
+import { buildASTSchema, parse } from 'graphql';
+
+const schema = `
+ type Author {
+ id: String!
+ firstName: String
+ lastName: String
+ }
+
+ type Post {
+ id: Int!
+ author: Author!
+ title: String
+ votes: Int
+ }
+
+ # This is required by buildASTSchema
+ type Query { anything: ID }
+`;
+
+const schemaType = buildASTSchema(parse(schema)).getType('Post');
+const schemaExtras = {
+ id: {
+ options: [
+ { label: 1, value: 1 },
+ { label: 2, value: 2 },
+ { label: 3, value: 3 },
+ ],
+ },
+ title: {
+ options: [
+ { label: 1, value: 'a' },
+ { label: 2, value: 'b' },
+ ],
+ },
+ 'author.firstName': {
+ placeholder: 'John',
+ },
+};
+
+const schemaValidator = (model: object) => {
+ const details = [];
+
+ if (!model.id) {
+ details.push({ name: 'id', message: 'ID is required!' });
+ }
+
+ if (!model.author.id) {
+ details.push({ name: 'author.id', message: 'Author ID is required!' });
+ }
+
+ if (model.votes < 0) {
+ details.push({
+ name: 'votes',
+ message: 'Votes must be a non-negative number!',
+ });
+ }
+
+ // ...
+
+ return details.length ? { details } : null;
+};
+
+const bridge = new GraphQLBridge({
+ schema: schemaType,
+ validator: schemaValidator,
+ extras: schemaExtras,
+});
+```
diff --git a/website/docs/api-reference/context-data.mdx b/website/docs/api-reference/context-data.mdx
new file mode 100644
index 000000000..6fcfd7029
--- /dev/null
+++ b/website/docs/api-reference/context-data.mdx
@@ -0,0 +1,132 @@
+---
+id: context-data
+title: 'Context data'
+sidebar_position: 4
+---
+
+Some components might need to know a current form state, which is passed as [React context](https://reactjs.org/docs/context.html).
+Properties stored in the context relates either to the form values or the form instance itself.
+That means, besides current form state, you can access form methods or encounter some metadata, e.g. about the used schema.
+Some of them were designed for internal use, but you can still take advantage of them.
+
+## Accessing context data
+
+A direct way of accessing the context data is to use the [`useForm`](/docs/api-helpers/#useform) hook:
+
+```tsx
+import { useForm } from 'uniforms';
+
+function Example() {
+ const context = useForm();
+}
+```
+
+For convenience, it's also accessible through the [`useField`](/docs/api-helpers/#usefield) hook:
+
+```tsx
+import { useField } from 'uniforms';
+
+function Example(rawProps) {
+ const [props, context] = useField(rawProps.name, rawProps);
+}
+```
+
+## Available context data
+
+### `changed`
+
+Indicates whether there was a change on form.
+
+### `changedMap`
+
+A map of changed fields. Rather internal one, used for checking if _other_ fields has changed.
+
+### `error`
+
+An object with a `details` field, which is an array of any validation errors.
+
+### `formRef`
+
+Contains reference to the form component that gives access to [the form methods](/docs/api-forms#methods).
+
+### `model`
+
+An object with current form fields values structured `{field: value}`.
+
+### `name`
+
+It is an array of the parent fields names:
+
+```tsx
+
+ // name = []
+
+ // name = ['x']
+ // name = ['x', 'y', 'z']
+
+
+```
+
+For example if we define a `CompositeField`:
+
+```tsx
+const Composite = () => (
+
+
+
+
+);
+```
+
+And use it like that:
+
+```tsx
+
+
+
+
+```
+
+The `name` array of the nested `AutoFields` will store a `personA` value.
+
+### `onChange`
+
+You can directly access to the `onChange` method. E.g. `onChange(field, value)`.
+
+### `onSubmit`
+
+Access to `onSubmit` method.
+
+### `randomId`
+
+Access to `randomId` method, created using the [`randomIds()`](/docs/api-helpers#randomids) helper.
+
+### `schema`
+
+A bridge class instance with `schema` and `validator` properties.
+
+The `schema` is simply your schema object and `validator` is your validating function.
+
+### `state`
+
+The `state` is an object representing your current form status.
+
+The state properties are:
+
+| Name | Description |
+| :---------------: | :--------------------------------------------------: |
+| `disabled` | Indicates whether the form is disabled. |
+| `readOnly` | Indicates whether the form is read-only. |
+| `showInlineError` | Indicates whether the inline errors should be shown. |
+
+### `submitted`
+
+Indicates whether the form was submitted.
+
+### `submitting`
+
+Indicates whether the form is in the `submitting` state. Helpful when handling asynchronous submission.
+
+### `validating`
+
+Indicates whether the form is in the `validating` state. Helpful when handling asynchronous validation.
diff --git a/website/docs/api-reference/fields.mdx b/website/docs/api-reference/fields.mdx
new file mode 100644
index 000000000..0a62c0155
--- /dev/null
+++ b/website/docs/api-reference/fields.mdx
@@ -0,0 +1,687 @@
+---
+id: fields
+title: 'Fields'
+sidebar_position: 2
+---
+
+uniforms provide a set of predefined components that can be used as form fields.
+
+The list below contains a guaranteed set of fields, implemented in every theme package:
+
+| Component | Description |
+| :-------------: | :-----------------------------------------------: |
+| `AutoField` | Automatically renders a given field. |
+| `AutoFields` | Automatically renders given fields. |
+| `BoolField` | Checkbox. |
+| `DateField` | HTML5 `date` or `datetime-local` input. |
+| `ErrorField` | Error message for a given field. |
+| `ErrorsField` | Error message with a list of validation errors. |
+| `HiddenField` | Hidden field (with a possibility to omit in DOM). |
+| `ListAddField` | An icon with action to add a list item. |
+| `ListDelField` | An icon with action to remove a list item. |
+| `ListField` | List of nested fields. |
+| `ListItemField` | Single list item wrapper. |
+| `LongTextField` | Textarea. |
+| `NestField` | Block of nested fields. |
+| `NumField` | Numeric input. |
+| `RadioField` | Radio checkbox. |
+| `SelectField` | Select (or set of radio checkboxes). |
+| `SubmitField` | Submit button. |
+| `TextField` | Text (or any HTML5 compatible) input. |
+
+## Fields
+
+### `AutoField`
+
+`AutoField` is basically a field renderer - it will render a field of a type adequate to the one defined in the schema,
+according to the [`AutoField` algorithm](/docs/uth-autofield-algorithm).
+You can also directly pass a component to it (by a `component` prop).
+All additional props will be passed to the result field component.
+
+##### Props:
+
+| Name | Default | Description |
+| :---------: | :------------------------------------------: | :-----------------------------: |
+| `component` | Field according to the `AutoField` algorithm | Component to render |
+| `name` | - | Name of the field in the schema |
+
+##### Props usage:
+
+```tsx
+import { AutoField } from 'uniforms-unstyled';
+
+;
+```
+
+### `AutoFields`
+
+`AutoFields` is basically a set of rendered `AutoField`s.
+By default, the rendered fields will be `AutoField` in a chosen theme.
+However, you can replace the standard `AutoField` with [`AutoField.componentDetectorContext`](/docs/uth-autofield-algorithm#overriding-autofield).
+
+The `element` property defines a wrapping component.
+E.g. you want to group your fields inside a section, just do `element="section"`. The default one is `div`.
+
+##### Props:
+
+| Name | Default | Description |
+| :----------: | :---------------: | :----------------------: |
+| `element` | `div` | Fields wrapper |
+| `fields` | All schema fields | List of fields to render |
+| `omitFields` | `[]` | List of fields to omit |
+
+##### Props usage:
+
+```tsx
+import { AutoFields } from 'uniforms-unstyled';
+
+;
+```
+
+### `BoolField`
+
+A checkbox.
+
+##### Props:
+
+| Name | Description | Available in |
+| :---------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------: |
+| `appearance` | Field appearance. Set to "toggle" to appear as a Material Toggle or to "checkbox" (or leave it undefined) to use a Checkbox appearance. | material, mui |
+| `extra` | Extra feedback text. In the antd theme, this renders additional help text below any validation messages. | antd |
+| `grid` | Field layout. Bootstrap grid layout style. Number is an equivalent of n. Object is a size object. Complete string is simply passed through. | bootstrap4, bootstrap5 |
+| `help` | Help text. _Some description would be great, huh?_ | antd, bootstrap4, bootstrap5 |
+| `helpClassName` | Help block className. _Some description would be great, huh?_ | bootstrap4, bootstrap5 |
+| `inline` | Checkbox inline state. In bootstrap themes, a label is rendered as a text but in inline mode, it's treated as a field label. | bootstrap4, bootstrap5 |
+| `inputClassName` | Input wrapper class name. In bootstrap themes, passed className is used on field block. This is used on direct field wrapper. | bootstrap4, bootstrap5 |
+| `inputRef` | Setting ref prop to a field won't work as desired, because you'll receive a field component rather than an HTML input. If you need an input ref, use this prop instead. | All |
+| `labelBefore` | Left label. In bootstrap themes, label is rendered on the right side of a checkbox. This label is rendered above the field. | bootstrap4, bootstrap5 |
+| `labelClassName` | Label className. A custom className for the field's label. | bootstrap4, bootstrap5 |
+| `labelCol` | Field layout. The layout of label. You can set span and/or offset. | antd |
+| `showInlineError` | Field inline error. _Some description would be great, huh?_ | antd, bootstrap4, bootstrap5, semantic |
+| `wrapClassName` | Field and surroundings wrap className. _Some description would be great, huh?_ | bootstrap4, bootstrap5 |
+| `wrapperCol` | Field layout. The layout for input controls. Same as labelCol. | antd |
+
+##### Props usage:
+
+```tsx
+import { BoolField } from 'uniforms-unstyled';
+import { useRef } from 'react'
+
+const inputRef = useRef();
+
+;
+```
+
+### `DateField`
+
+##### Props:
+
+| Name | Description | Available in |
+| :---------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------: |
+| `extra` | Extra feedback text. In the antd theme, this renders additional help text below any validation messages. | antd |
+| `grid` | Field layout. Bootstrap grid layout style. Number is an equivalent of n. Object is a size object. Complete string is simply passed through. | bootstrap4, bootstrap5 |
+| `help` | Help text. _Some description would be great, huh?_ | antd, bootstrap4, bootstrap5 |
+| `helpClassName` | Help block className. _Some description would be great, huh?_ | bootstrap4, bootstrap5 |
+| `icon` | Input icon. Semantic inputs can have an icon. By default, it's placed on the right side - to place it on the left, use `iconLeft` prop instead. | semantic |
+| `iconLeft` | Semantic inputs can have an icon. With this prop, it's placed on the left side - to place it on the right, use icon prop instead. | semantic |
+| `iconProps` | Input icon props. Semantic inputs can have an icon. These props are passed directly to the icon element. | semantic |
+| `inputClassName` | Input wrapper class name. In bootstrap themes, passed className is used on field block. This is used on direct field wrapper. | bootstrap4, bootstrap5 |
+| `inputRef` | Setting ref prop to a field won't work as desired, because you'll receive a field component rather than an HTML input. If you need an input ref, use this prop instead. | All |
+| `labelClassName` | Label className. A custom className for the field's label. | bootstrap4, bootstrap5 |
+| `labelCol` | Field layout. The layout of label. You can set span and/or offset. | antd |
+| `labelProps` | Props for the InputLabel | material, mui |
+| `max` | Maximum value. Date object. | All |
+| `min` | Minimal value. Date object. | All |
+| `showInlineError` | Field inline error. _Some description would be great, huh?_ | antd, bootstrap4, bootstrap5, semantic |
+| `timeFormat` | Display time picker in ampm (12hr) format or 24hr format. | material, mui |
+| `type` | Display date and time or date only picker. Format value according to its type | All except antd |
+| `wrapClassName` | Field and surroundings wrap className. In SemanticUI theme, this class name is used on ui input wrapper, so you can pass classes like small, huge, inverted, transparent etc. | bootstrap4, bootstrap5, semantic |
+| `wrapperCol` | Field layout. The layout for input controls. Same as labelCol. | antd |
+
+##### Props usage:
+
+```tsx
+import { DateField } from 'uniforms-unstyled';
+import { useRef } from 'react'
+
+const inputRef = useRef();
+
+;
+```
+
+### `ErrorField`
+
+Error message renderer.
+
+##### Props:
+
+| Name | Description |
+| :--------: | :--------------------------------------------------------------------------------------------------------------------: |
+| `children` | Custom content. By default, it will render a block with the error message (if any), but you can customize the content. |
+| `name` | Target field. This field error should be used. |
+
+##### Props usage:
+
+```tsx
+import { ErrorField } from 'uniforms-unstyled';
+
+;
+```
+
+### `ErrorsField`
+
+Error messages renderer.
+
+##### Props:
+
+| Name | Description |
+| :--------: | :---------------------------------------------------------------------------------------------------------------------: |
+| `children` | Custom content. By default, it will render a block with the error messages (if any), but you can customize the content. |
+
+##### Props usage:
+
+```tsx
+import { ErrorsField } from 'uniforms-unstyled';
+
+;
+```
+
+### `HiddenField`
+
+##### Props:
+
+| Name | Description |
+| :-----: | :-------------------------------------------------------------------------------------------------------------------------------------------------------: |
+| `name` | Field name. Used for identification. It should match your schema - if not, it will throw an error. |
+| `value` | Field value. This field has completely different semantics. When a value is set, then it's updating a current model instead of being passed to the field. |
+
+##### Props usage:
+
+```tsx
+import { HiddenField } from 'uniforms-unstyled';
+
+;
+```
+
+### `ListAddField`
+
+##### Props:
+
+| Name | Description | Available in |
+| :-------: | :----------------------------------: | :--------------------------------: |
+| `addIcon` | Icon. By default, glyphicon is used. | bootstrap4, bootstrap5 |
+
+**Note:** This is one of _internal_ components of `ListField`.
+
+##### Props usage:
+
+```tsx
+import { ListAddField } from 'uniforms-unstyled';
+
+} />;
+```
+
+### `ListDelField`
+
+##### Props:
+
+| Name | Description | Available in |
+| :----------: | :----------------------------------: | :--------------------------------: |
+| `removeIcon` | Icon. By default, glyphicon is used. | bootstrap4, bootstrap5 |
+
+**Note:** This is one of _internal_ components of `ListField`.
+
+##### Props usage:
+
+```tsx
+import { ListDelField } from 'uniforms-unstyled';
+
+} />;
+```
+
+### `ListField`
+
+##### Props:
+
+| Name | Default | Description | Available in |
+| :---------------: | :-------: | :------------------------------------------------------------------------------------: | :------------------------------------------: |
+| `addIcon` | glyphicon | Icon. It's passed to the ListAddField. | bootstrap4, bootstrap5 |
+| `initialCount` | - | Initial items count. At least this amount of fields will be rendered at the beginning. | All |
+| `itemProps` | - | ListItemField props. These props are passed to the ListItemField. | All |
+| `removeIcon` | glyphicon | Icon. It's passed to the ListDelField. | bootstrap4, bootstrap5 |
+| `showInlineError` | | Field inline error. _Some description would be great, huh?_ | bootstrap4, bootstrap5, semantic |
+
+##### Props usage:
+
+```tsx
+import { ListField } from 'uniforms-unstyled';
+
+}
+ initialCount={5}
+ itemProps={
+ {
+ /* ... */
+ }
+ }
+ removeIcon={}
+ showInlineError
+/>;
+```
+
+### `ListItemField`
+
+| Name | Default | Description | Available in |
+| :----------: | :-------: | :------------------------------------: | :--------------------------------: |
+| `removeIcon` | glyphicon | Icon. It's passed to the ListDelField. | bootstrap4, bootstrap5 |
+
+**Note:** This is one of _internal_ components of `ListField`.
+
+##### Props usage:
+
+```tsx
+import { ListItemField } from 'uniforms-unstyled';
+
+} />;
+```
+
+### `LongTextField`
+
+A textarea.
+
+##### Props:
+
+| Name | Description | Available in |
+| :---------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------: |
+| `extra` | Extra feedback text. In the antd theme, this renders additional help text below any validation messages. | antd |
+| `grid` | Field layout. Bootstrap grid layout style. Number is an equivalent of n. Object is a size object. Complete string is simply passed through. | bootstrap4, bootstrap5 |
+| `help` | Help text. _Some description would be great, huh?_ | antd, bootstrap4, bootstrap5 |
+| `helpClassName` | Help block className. _Some description would be great, huh?_ | bootstrap4, bootstrap5 |
+| `icon` | Input icon. Semantic inputs can have an icon. By default, it's placed on the right side - to place it on the left, use `iconLeft` prop instead. | semantic |
+| `iconLeft` | Semantic inputs can have an icon. With this prop, it's placed on the left side - to place it on the right, use icon prop instead. | semantic |
+| `iconProps` | Input icon props. Semantic inputs can have an icon. These props are passed directly to the icon element. | semantic |
+| `inputClassName` | Input wrapper class name. In bootstrap themes, passed className is used on field block. This is used on direct field wrapper. | bootstrap4, bootstrap5 |
+| `inline` | Checkbox inline state. In bootstrap themes, a label is rendered as a text but in inline mode, it's treated as a field label. | bootstrap4 |
+| `inputRef` | Setting ref prop to a field won't work as desired, because you'll receive a field component rather than an HTML input. If you need an input ref, use this prop instead. | All |
+| `labelBefore` | Left label. In bootstrap themes, label is rendered on the right side of a checkbox. This label is rendered above the field. | bootstrap4, bootstrap5 |
+| `labelClassName` | Label className. A custom className for the field's label. | bootstrap4, bootstrap5 |
+| `labelCol` | Field layout. The layout of label. You can set span and/or offset. | antd |
+| `showInlineError` | Field inline error. _Some description would be great, huh?_ | antd, bootstrap4, bootstrap5, semantic |
+| `wrapperCol` | Field layout. The layout for input controls. Same as labelCol. | antd |
+| `wrapClassName` | Field and surroundings wrap className. _Some description would be great, huh?_ | bootstrap4, bootstrap5 |
+
+##### Props usage:
+
+```tsx
+import { LongTextField } from 'uniforms-unstyled';
+import { useRef } from 'react'
+
+const inputRef = useRef();
+
+;
+```
+
+### `NestField`
+
+##### Props:
+
+| Name | Description | Available in |
+| :---------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------: |
+| `fields` | Array of rendered fields. If no custom content provided, only those fields are rendered. By default, All of nested fields are rendered. | All |
+| `grouped` | Add / remove "grouped" class from the field. In Semantic, fields can be grouped using this class. By default, this class is added to the NestField. | semantic |
+| `showInlineError` | Field inline error. _Some description would be great, huh?_ | antd, bootstrap4, bootstrap5, semantic |
+
+##### Props usage:
+
+```tsx
+import { NestField } from 'uniforms-unstyled';
+
+;
+```
+
+### `NumField`
+
+A numeric input field.
+
+##### Props:
+
+| Name | Description | Available in |
+| :---------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------: |
+| `decimal` | Decimal mode. This will change value step from 1 to 0.01. | All |
+| `extra` | Extra feedback text. In the antd theme, this renders additional help text below any validation messages. | antd |
+| `grid` | Field layout. Bootstrap grid layout style. Number is an equivalent of n. Object is a size object. Complete string is simply passed through. | bootstrap4, bootstrap5 |
+| `help` | Help text. _Some description would be great, huh?_ | antd, bootstrap4, bootstrap5 |
+| `helpClassName` | Help block className. _Some description would be great, huh?_ | bootstrap4, bootstrap5 |
+| `icon` | Input icon. Semantic inputs can have an icon. By default, it's placed on the right side - to place it on the left, use `iconLeft` prop instead. | semantic |
+| `iconLeft` | Semantic inputs can have an icon. With this prop, it's placed on the left side - to place it on the right, use icon prop instead. | semantic |
+| `iconProps` | Input icon props. Semantic inputs can have an icon. These props are passed directly to the icon element. | semantic |
+| `inputClassName` | Input wrapper class name. In bootstrap themes, passed className is used on field block. This is used on direct field wrapper. | bootstrap4, bootstrap5 |
+| `inline` | Checkbox inline state. In bootstrap themes, a label is rendered as a text but in inline mode, it's treated as a field label. | bootstrap4 |
+| `inputRef` | Setting ref prop to a field won't work as desired, because you'll receive a field component rather than an HTML input. If you need an input ref, use this prop instead. | All |
+| `labelBefore` | Left label. In bootstrap themes, label is rendered on the right side of a checkbox. This label is rendered above the field. | bootstrap4 |
+| `labelClassName` | Label className. A custom className for the field's label. | bootstrap4, bootstrap5 |
+| `labelCol` | Field layout. The layout of label. You can set span and/or offset. | antd |
+| `max` | Maximum value. Date object. | All |
+| `min` | Minimal value. Date object. | All |
+| `showInlineError` | Field inline error. _Some description would be great, huh?_ | antd, bootstrap4, bootstrap5, semantic |
+| `step` | Input step. | All |
+| `wrapperCol` | Field layout. The layout for input controls. Same as labelCol. | antd |
+| `wrapClassName` | Field and surroundings wrap className. _Some description would be great, huh?_ | bootstrap4, bootstrap5 |
+
+##### Props usage:
+
+```tsx
+import { NumField } from 'uniforms-unstyled';
+import { useRef } from 'react'
+
+const inputRef = useRef();
+
+;
+```
+
+### `RadioField`
+
+##### Props:
+
+| Name | Description | Available in |
+| :---------------: | :---------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------: |
+| `inline` | Checkbox inline state. In bootstrap themes, a label is rendered as a text but in inline mode, it's treated as a field label. | bootstrap4, bootstrap5 |
+| `options` | Options. It can be either an object or an array (or a function, that returns it). | All |
+| `labelCol` | Field layout. The layout of label. You can set span and/or offset. | antd |
+| `wrapperCol` | Field layout. The layout for input controls. Same as labelCol. | antd |
+| `inputClassName` | Input wrapper class name. In bootstrap themes, passed className is used on field block. This is used on direct field wrapper. | bootstrap4, bootstrap5 |
+| `labelClassName` | Label className. A custom className for the field's label. | bootstrap4, bootstrap5 |
+| `showInlineError` | Field inline error. _Some description would be great, huh?_ | antd, bootstrap4, bootstrap5, semantic |
+
+##### Props usage:
+
+```tsx
+import { RadioField } from 'uniforms-unstyled';
+
+;
+```
+
+### `SelectField`
+
+##### Props:
+
+| Name | Description | Available in |
+| :---------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------: |
+| `appearance` | Field appearance. Set to "toggle" to appear as a Material Toggle or to "checkbox" (or leave it undefined) to use a Checkbox appearance. | material, mui |
+| `checkboxes` | Turn on checkbox/radio mode. It's always true in multiple (i.e. fieldType === Array) mode. | All |
+| `disableItem` | Disable items (options) based on a given predicate. | All |
+| `extra` | Extra feedback text. In the antd theme, this renders additional help text below any validation messages. | antd |
+| `help` | Help text. _Some description would be great, huh?_ | antd, bootstrap4, bootstrap5 |
+| `helpClassName` | Help block className. _Some description would be great, huh?_ | bootstrap4, bootstrap5 |
+| `inline` | Checkbox inline state. In bootstrap themes, a label is rendered as a text but in inline mode, it's treated as a field label. | bootstrap4, bootstrap5 |
+| `inputClassName` | Input wrapper class name. In bootstrap themes, passed className is used on field block. This is used on direct field wrapper. | bootstrap4, bootstrap5 |
+| `inputRef` | Setting ref prop to a field won't work as desired, because you'll receive a field component rather than an HTML input. If you need an input ref, use this prop instead. | All |
+| `labelClassName` | Label className. A custom className for the field's label. | bootstrap4, bootstrap5 |
+| `labelCol` | Field layout. The layout of label. You can set span and/or offset. | antd |
+| `labelProps` | Props for the InputLabel | material, mui |
+| `options` | Options. It can be either an object or an array (or a function, that returns it). | All |
+| `showInlineError` | Field inline error. _Some description would be great, huh?_ | antd, bootstrap4, bootstrap5, semantic |
+| `wrapperCol` | Field layout. The layout for input controls. Same as labelCol. | antd |
+| `wrapClassName` | Field and surroundings wrap className. _Some description would be great, huh?_ | bootstrap4, bootstrap5 |
+| `textFieldProps` | Props injected directly to `TextField` ( valid only for non-checkbox `SelectField` ). | material, mui |
+
+##### Props usage:
+
+```tsx
+import { SelectField } from 'uniforms-unstyled';
+import { useRef } from 'react'
+
+const inputRef = useRef();
+
+ value % 2}
+ extra="Extra Feedback or Help"
+ help="Need help?"
+ helpClassName="a b c"
+ inline
+ inputClassName="a b c"
+ inputRef={inputRef}
+ labelClassName="a b c" // You can either specify them as a single string
+ labelClassName={[ 'a', 'b', 'c' ]} // or as an array of strings
+ labelCol={{offset: 2}} // 'ant-col-offset-2' on label
+ labelCol={{span: 4}} // 'ant-col-4' on label
+ labelProps={{shrink: true, disableAnimation: true}}
+ options={[{ label: 'A', value: 'a' }, { label: 'B', value: 'b' }, /* ... */]}
+ showInlineError
+ wrapperCol={{offset: 2}} // 'ant-col-offset-2' on field
+ wrapperCol={{span: 4}} // 'ant-col-4' on field
+/>;
+```
+
+### `SubmitField`
+
+##### Props:
+
+| Name | Description | Available in |
+| :--------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------: |
+| `inputClassName` | Input wrapper class name. In bootstrap themes, passed className is used on field block. This is used on direct field wrapper. | bootstrap4, bootstrap5 |
+| `inputRef` | Setting ref prop to a field won't work as desired, because you'll receive a field component rather than an HTML input. If you need an input ref, use this prop instead. | All |
+
+##### Props usage:
+
+```tsx
+import { SubmitField } from 'uniforms-unstyled';
+import { useRef } from 'react';
+
+const inputRef = useRef();
+
+;
+```
+
+### `TextField`
+
+##### Props:
+
+| Name | Description | Available in |
+| :---------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------: |
+| `extra` | Extra feedback text. In the antd theme, this renders additional help text below any validation messages. | antd |
+| `grid` | Field layout. Bootstrap grid layout style. Number is an equivalent of n. Object is a size object. Complete string is simply passed through. | bootstrap4, bootstrap5 |
+| `help` | Help text. _Some description would be great, huh?_ | antd, bootstrap4, bootstrap5 |
+| `helpClassName` | Help block className. _Some description would be great, huh?_ | bootstrap4, bootstrap5 |
+| `icon` | Input icon. Semantic inputs can have an icon. By default, it's placed on the right side - to place it on the left, use `iconLeft` prop instead. | semantic |
+| `iconLeft` | Semantic inputs can have an icon. With this prop, it's placed on the left side - to place it on the right, use icon prop instead. | semantic |
+| `iconProps` | Input icon props. Semantic inputs can have an icon. These props are passed directly to the icon element. | semantic |
+| `inputClassName` | Input wrapper class name. In bootstrap themes, passed className is used on field block. This is used on direct field wrapper. | bootstrap4, bootstrap5 |
+| `inputRef` | Setting ref prop to a field won't work as desired, because you'll receive a field component rather than an HTML input. If you need an input ref, use this prop instead. | All |
+| `labelClassName` | Label className. A custom className for the field's label. | bootstrap4, bootstrap5 |
+| `labelCol` | Field layout. The layout of label. You can set span and/or offset. | antd |
+| `showInlineError` | Field inline error. _Some description would be great, huh?_ | antd, bootstrap4, bootstrap5, semantic |
+| `type` | Input type. HTML compatible input type like password. Default is text. | All |
+| `wrapperCol` | Field layout. The layout for input controls. Same as labelCol. | antd |
+| `wrapClassName` | Field and surroundings wrap className. _Some description would be great, huh?_ | bootstrap4, bootstrap5 |
+
+##### Props usage:
+
+```tsx
+import { TextField } from 'uniforms-unstyled';
+import { useRef } from 'react'
+
+const inputRef = useRef();
+
+;
+```
+
+## Common props
+
+| Name | Default | Description |
+| :-----------: | :-----: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
+| `disabled` | `false` | Field disabled state. It's passed directly to the field, but it propagates same as the label. |
+| `label` | `true` | Field label. This prop has three modes. If you pass a string, then it will be used as a label. If you pass a null, then it won't have a label, but nested fields will have default labels. If you pass a non-null falsy value, it won't have a label and nested fields won't have labels too. |
+| `name` | - | Field name. Used for identification. It should match your schema - if not, it will throw an error. |
+| `placeholder` | `false` | Field placeholder. If set to true, then a label will be used. Otherwise, it's handled like a label (including propagation). |
+| `readOnly` | `false` | Field read-only state. It's passed directly to the field, but it propagates same as the label. |
+
+##### Props usage:
+
+```tsx
+
+```
+
+## Props propagation
+
+Few props propagate in a very special way. These are `disabled`, `label`, `placeholder`, and `readOnly`.
+
+**Example:**
+
+```tsx
+ // default label | no placeholder
+ // custom label | no placeholder
+ // no label | no placeholder
+ // default label | default placeholder
+ // default label | custom placeholder
+
+ // null = no label but the children have their labels
+
+
+
+ // false = no label and the children have no labels
+
+
+
+ // Additions are disabled...
+ // ...deletion too
+ // ...but editing is not.
+
+
+
+
+
+```
+
+**Note:** `disabled`, `label`, `placeholder`, and `readOnly` are casted to `Boolean` before being passed to nested fields.
diff --git a/website/docs/api-reference/forms.mdx b/website/docs/api-reference/forms.mdx
new file mode 100644
index 000000000..aaf646bc8
--- /dev/null
+++ b/website/docs/api-reference/forms.mdx
@@ -0,0 +1,462 @@
+---
+id: forms
+title: 'Forms'
+sidebar_position: 1
+---
+
+## Forms components
+
+Most of the time you'll be using either `AutoForm` or `ValidatedForm`, but there are also other form components (rather low-level ones) with different capabilities.
+
+| Component | Self-generated? | Self-managed? | Self-validated? |
+| :------------------: | :----------------------: | :----------------------: | :----------------------: |
+| `AutoForm` | ✅ | ✅ | ✅ |
+| `ValidatedQuickForm` | ✅ | ❌ | ✅ |
+| `ValidatedForm` | ❌ | ❌ | ✅ |
+| `QuickForm` | ✅ | ❌ | ❌ |
+| `BaseForm` | ❌ | ❌ | ❌ |
+
+### `AutoForm`
+
+`AutoForm` extends `ValidatedQuickForm` with state management.
+It is the most user-friendly and commonly used form.
+It's self-generated so if you provide a schema, the fields will be automatically rendered.
+These fields will be also validated.
+By default, the validation will take place `onSubmit`, and `onChange` **after the first submission**.
+
+##### Props:
+
+| Name | Description |
+| :-------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
+| `onChangeModel` | Like `onChange` but for the whole model. Triggered just after `onChange` with the next model and information what `{ key, value, previousValue }` caused the change. `previousValue` will be `undefined` if there was no value before. |
+
+**Note:** All `ValidatedQuickForm` props are also accepted and all methods are available.
+In other words, that means that `AutoForm` receives all props listed on this page.
+
+##### Props usage:
+
+```tsx
+import { AutoForm } from 'uniforms'; // Or from the theme package.
+
+ console.log(model)} />;
+```
+
+### `ValidatedQuickForm`
+
+This form combines both `QuickForm` and `ValidatedForm` features.
+It is not self-managed, however, it will automatically generate fields based on the provided schema and validate them.
+
+**Note:** All `QuickForm` props are also accepted and all methods are available.
+**Note:** All `ValidatedForm` props are also accepted and all methods are available.
+
+### `ValidatedForm`
+
+(_It's rather an internal form, but it's still exported._)
+
+It's based on `BaseForm` and extends its functionality by enabling automatic form validation.
+Its purpose is providing validation functions.
+It's not autogenerated, so if you want to see any fields rendered, you have to manually add them.
+`ValidatedForm` is not self-managed, so you won't be able to type anything until there is no `onChange` handler,
+however, there will be validation checks.
+
+##### Props:
+
+| Name | Description |
+| :----------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
+| `onValidate` | Additional asynchronous validation. Schema validation has to be sync, so this is the only way to achieve async validation. |
+| `validate` | Validation mode. By default, the form will start to validate from the time of the first submit and then revalidate on every change. It's `onChangeAfterSubmit`. There are also `onChange` and `onSubmit` modes, but those are quite self-explanatory. |
+| `validator` | Validator options. It's passed to `getValidator` of your schema bridge. It really depends on your schema. |
+
+**Note:** All `BaseForm` props are also accepted and all methods are available.
+
+##### Props usage:
+
+```tsx
+import { ValidatedForm } from 'uniforms'; // Or from the theme package.
+import { useRef } from 'react';
+
+const formRef = useRef();
+
+const formAction = () => {
+ // Reset form.
+ // It will reset changed state, model state in AutoForm, validation
+ // state in ValidatedForm and rerender.
+ formRef.reset();
+
+ // Trigger form change.
+ // It's a programmatic equivalent of a change event.
+ formRef.change(key, value);
+
+ // Submit form.
+ // It's a programmatic equivalent of a submit event. Returns a promise,
+ // which will either resolve with submitted form or reject with
+ // validation error in ValidatedForm.
+ formRef.submit();
+};
+
+ {
+ // You can either ignore validation error...
+ if (omitValidation(model)) {
+ return null;
+ }
+
+ // ...or any additional validation if an error is already there...
+ if (isSomeSpecialCase(error)) {
+ return MyAPI.checkOtherCondition(model);
+ }
+
+ // ...or feed it with another error.
+ return MyAPI.validate(model);
+ }}
+ validate="onChangeAfterSubmit"
+ validator={{ clean: true }}
+ ref={formRef}
+/>;
+```
+
+### `QuickForm`
+
+(_It's rather an internal form, but it's still exported._)
+
+It's based on `BaseForm` and extends its functionality by enabling automatic form generation.
+If you provide a schema, the fields will be automatically rendered.
+However, `QuickForm` is not self-managed, so you won't be able to type anything until there is no `onChange` handler.
+You can customize which `AutoField` should be used with [`AutoField.componentDetectorContext`](/docs/uth-autofield-algorithm#overriding-autofield).
+
+##### Props:
+
+| Name | Description |
+| :-----------: | :---------------------------------------------------------------------------------------: |
+| `errorsField` | Custom `ErrorsField`. It should be anything that will pass through `React.createElement`. |
+| `submitField` | Custom `SubmitField`. It should be anything that will pass through `React.createElement`. |
+
+**Note:** All `BaseForm` props are also accepted and all methods are available.
+
+##### Props usage:
+
+```tsx
+import { QuickForm } from 'uniforms'; // Or from the theme package.
+
+;
+```
+
+### `BaseForm`
+
+(_It's rather an internal form, but it's still exported._)
+
+It's the very basic form & foundation for the other forms.
+It's not autogenerated, so if you want to see any fields rendered, you have to manually add them.
+However, `BaseForm` is not self-managed, so you won't be able to type anything until there is no `onChange` handler.
+
+##### Props:
+
+| Name | Description |
+| :---------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
+| `autosaveDelay` | Autosave delay. Set 0 for an instant autosave. |
+| `autosave` | Enable autosave. Every change triggers `onSubmit`. |
+| `disabled` | Default `disabled` prop for all fields. By default it's `false` - set it to `true` to disable the whole form. |
+| `error` | Validation error. Current validation state. It should be either compatible with your schema or an `Error` object. |
+| `grid` | Bootstrap grid layout style. Passing a number is an equivalent of `{sm: n}`. Object is a `{mode: size}` object. Complete string is simply passed through. Available in: bootstrap4. |
+| `model` | Form model. An object with `{field: value}` structure. It doesn't matter if it has a prototype or not, but keep in mind that in `onSubmit` or in `onChangeModel` you'll receive a plain object. If you treat form as an input, then this is a value. |
+| `modelTransform` | Model transform. Function transforming one model into another. It's used in a few situations (modes) described below. Do not mutate a given model! |
+| `onChange` | Field change action. It receives two arguments: key and value, where the key is a dot-separated path to the changed field and value is a requested value. |
+| `onSubmit` | Submit action. When the form is submitted manually or by an HTML5 event, then it's called with the current model. **Note:** use `Promise` to return values and errors - synchronous `return` and `throw` are disallowed. |
+| `readOnly` | Default `readOnly` prop for all fields. By default it's `false` - set it to `true` to make the whole form read-only. |
+| `schema` | Form schema. It's used for form generation in QuickForm and validation in ValidatedForm. |
+| `showInlineError` | Default `showInlineError` prop for all fields. By default it's `false` - set it to `true` to enable inline errors for the whole form. Available in: antd, bootstrap4, semantic. |
+
+##### Props usage:
+
+```tsx
+import { BaseForm } from 'uniforms'; // Or from the theme package.
+import { useRef } from 'react';
+
+const formRef = useRef();
+
+const formAction = () => {
+ // Reset form.
+ // It will reset changed state, model state in AutoForm, validation
+ // state in ValidatedForm and rerender.
+ formRef.reset();
+
+ // Trigger form change.
+ // It's a programmatic equivalent of a change event.
+ formRef.change(key, value);
+
+ // Submit form.
+ // It's a programmatic equivalent of a submit event. Returns a promise,
+ // which will either resolve with submitted form or reject with
+ // validation error in ValidatedForm.
+ formRef.submit();
+};
+
+ {
+ // This model will be passed to the fields.
+ if (mode === 'form') {
+ /* ... */
+ }
+
+ // This model will be submitted.
+ if (mode === 'submit') {
+ /* ... */
+ }
+
+ // This model will be validated.
+ if (mode === 'validate') {
+ /* ... */
+ }
+
+ // Otherwise, return unaltered model.
+ return model;
+ }}
+ onChange={(key, value) => console.log(key, value)}
+ onSubmit={model => db.saveThatReturnsPromiseOrNothing(model)}
+ readOnly={false}
+ schema={myFormSchema}
+ showInlineError
+ ref={formRef}
+/>;
+```
+
+## Form features
+
+### Asynchronous validation
+
+`AutoForm` and `ValidatedForm` both accept an `onValidate` prop. It can be used to create an asynchronous validation:
+
+The `onValidate` should return `null` if the `model` is valid, otherwise return any error value. The error can be either `Promise` for asynchronous validation or any other value for synchronous validation (https://github.com/vazco/uniforms/blob/d557f90e6807e34c1ebb9803d44fd799174175f8/packages/uniforms/src/ValidatedForm.tsx#L118-L142).
+
+```tsx
+const MyAPI = {
+ checkOtherCondition(model): Error | null {
+ if (model.age < 18) {
+ return new Error('Too young')
+ }
+ return null
+ }
+
+ async validate(model): Error | null {
+ const result = await fetch('...', { body: JSON.stringify(model) })
+ const { error } = await result.json()
+ return error
+ }
+}
+
+const onValidate = async (model, error) => {
+ // You can either ignore validation error...
+ if (omitValidation(model)) {
+ return null;
+ }
+
+ // ...or any additional validation if an error is already there...
+ if (isSomeSpecialCase(error)) {
+ return MyAPI.checkOtherCondition(model);
+ }
+
+ // ...or feed it with another error.
+ return MyAPI.validate(model);
+};
+
+// Later...
+
+;
+```
+
+### Autosave
+
+Every form has autosave functionality. If you set an `autosave` prop, then every change will trigger a submit. There's also an `autosaveDelay` prop - a minimum time between saves in milliseconds (default: `0`).
+
+**Example:**
+
+```tsx
+
+```
+
+### Methods
+
+You can use [React `ref` prop](https://facebook.github.io/react/docs/more-about-refs.html) to manually access form methods. Example usage:
+
+```tsx
+import { useRef } from 'react';
+
+const MyForm = ({ schema, onSubmit }) => {
+ const formRef = useRef();
+
+ return (
+
+
+ formRef.reset()}>Reset
+ formRef.submit()}>Submit
+
+ );
+};
+```
+
+You can do the same by using the [`useForm`](/docs/api-context-data#accessing-context-data) hook and the [`formRef`](/docs/api-context-data#formref) property.
+
+```tsx
+function FormControls() {
+ const { formRef } = useForm();
+
+ return (
+ <>
+
+
+ >
+ );
+}
+
+function App() {
+ return (
+
+
+
+ );
+}
+```
+
+All available methods:
+
+#### `change(key, value)`
+
+Triggers a form change. It's a programmatic equivalent of a change event.
+
+#### `reset()`
+
+Resets a form. It will also reset changed state, model state (only in AutoForm), validation state (only in ValidatedForm) and trigger a rerender.
+
+#### `submit()`
+
+Submits a form. It's a programmatic equivalent of a submit event. Returns a promise, which will either resolve with a submitted model or reject with validation error in ValidatedForm.
+
+#### `validate()`
+
+_(added in `ValidatedForm`)_
+
+Validates a form with the current model. Returns a Promise, which rejects with a validation error or resolves without any value. Note, that it resolves/rejects **after** the component is rerendered.
+
+#### `validate(key, value)`
+
+_(added in `ValidatedForm`)_
+
+Validates a form with key set to value. You can use it to check, if a given value will pass the validation or not. Returns validation Promise, as described above.
+
+#### `validateModel(model)`
+
+_(added in `ValidatedForm`)_
+
+Validates a form with the given model. Returns validation Promise, as described above.
+
+### Change reactions
+
+If you want to make one field to influence others, simply extend `AutoForm` and override `onChange` method.
+
+**Example:**
+
+```tsx
+class ChainForm extends AutoForm {
+ onChange(key, value) {
+ if (key === 'key_to_intercept') return;
+ if (key === 'key_to_translate') return super.onChange('another_key', value);
+ if (key === 'key_to_mutate') {
+ super.onChange('another_key1', value * 2);
+ super.onChange('another_key2', value / 2);
+ return;
+ }
+
+ super.onChange(key, value);
+ }
+}
+```
+
+It can be easily applied multiple times to make your forms even more reusable.
+
+**Example:**
+
+```tsx
+const withMultipliedField = (fieldA, fieldB, Form) =>
+ class withMultipliedFieldForm extends Form {
+ onChange(key, value) {
+ // Multiply fieldA
+ if (key === fieldA) super.onChange(fieldB, value + value);
+
+ // Pass every change
+ super.onChange(key, value);
+ }
+ };
+```
+
+### Model transformations
+
+If you need to transform model before it will be validated, submitted or passed down to the fields, there's a `modelTransform` prop, which should be used in those use cases.
+
+**Example:**
+
+```tsx
+ {
+ // This model will be passed to the fields.
+ if (mode === 'form') {
+ /* ... */
+ }
+
+ // This model will be submitted.
+ if (mode === 'submit') {
+ /* ... */
+ }
+
+ // This model will be validated.
+ if (mode === 'validate') {
+ /* ... */
+ }
+
+ // Otherwise, return unaltered model.
+ return model;
+ }}
+ onSubmit={onSubmit}
+ schema={schema}
+/>
+```
+
+### Validation options and modes
+
+Any form can be validated in one those three styles:
+
+- `onChange`
+ Validate on every change.
+
+- `onChangeAfterSubmit` _(default)_
+ Validate on every change, but only after first submit.
+
+- `onSubmit`
+ Validate on every submit.
+
+If your schema validator accepts any options, those can be passed in `validator` prop.
+
+**Example:**
+
+```tsx
+
+```
diff --git a/website/docs/api-reference/helpers.mdx b/website/docs/api-reference/helpers.mdx
new file mode 100644
index 000000000..ceffa3cef
--- /dev/null
+++ b/website/docs/api-reference/helpers.mdx
@@ -0,0 +1,217 @@
+---
+id: helpers
+title: Helpers
+sidebar_position: 5
+---
+
+## `connectField`
+
+Provides form management related props. The `connectField` helper is a component wrapper (higher order component, HOC), that provides various props related to the form management. It also adds the `Field` suffix to the name of the wrapped component.
+
+The table below lists all of the **guaranteed** props that will be passed to the wrapped component:
+
+| Name | Type | Description |
+| :---------------: | :-------------------: | :------------------------------------: |
+| `changed` | `boolean` | Has field changed? |
+| `disabled` | `boolean` | Is field disabled? |
+| `error` | `object` | Field scoped part of validation error. |
+| `errorMessage` | `string` | Field scoped validation error message. |
+| `field` | `object` | Field definition from schema. |
+| `fields` | `arrayOf(string)` | Subfields names. |
+| `fieldType` | `func` | Field type. |
+| `id` | `string` | Field id - given or random. |
+| `label` | `string` | Field label. |
+| `name` | `string` | Field name. |
+| `onChange` | `func(value, [name])` | Change field value. |
+| `placeholder` | `string` | Field placeholder. |
+| `readOnly` | `boolean` | Is field read-only? |
+| `showInlineError` | `boolean` | Show inline error? |
+| `value` | `any` | Field value. |
+
+The `connectField` function accepts two arguments: the first one is a component and the second one is an `options` object.
+
+```tsx
+function Example(props) {
+ /* ... */
+}
+
+const ExampleField = connectField(Example, options);
+```
+
+The table below lists all available options:
+
+| Name | Type | Description |
+| :------------: | :------------------: | :----------------------------------------------------------------------------------------------------------------------------------: |
+| `initialValue` | `boolean` | Initial value check. If `true`, then after the first render the default value is set as value if no value is provided (`undefined`). |
+| `kind` | `'leaf'` or `'node'` | See [Field kinds](#field-kinds). |
+
+### Field kinds
+
+Every field is either a _leaf_ or _node_ field. In the future, we could introduce new kinds to enable even more optimizations.
+
+- _Leaf_ fields cannot have subfields. This allows us to perform some optimizations, like skipping the extra `Provider` from `connectField`, effectively reducing the overhead down to a single `useField` call.
+ - It includes all input fields, like `NumField`, `SelectField` or `TextField`.
+- _Node_ fields can have subfields. Fields of the _leaf_ kind cannot have subfields.
+ - It includes all combined and layout fields, like `ListField` or `NestField`.
+
+If you are not sure which one to use, do not use the `kind` option at all - it'll default to the safest option (right now it's `node`).
+
+### Props merging order
+
+The resulting props of a field are a merge of the props that uniforms provide, the ones coming from the bridge (schema) and finally the actual field props. For the exact ordering, please refer to the [source of `useField` hook](https://github.com/vazco/uniforms/blob/master/packages/uniforms/src/useField.tsx). Overall, it looks as follows:
+
+1. uniforms props (e.g., `changed`, `onChange`, `value`).
+2. uniforms state (as defined in [context data](/docs/api-context-data/#state)).
+3. bridge props (depending on the schema)
+4. field props (only when rendered directly)
+
+That's important, as using empty values in the schema or field props, like `undefined`, will be merged as well. See [#1094](https://github.com/vazco/uniforms/issues/1094) for more context as well as an example of a potential pitfall.
+
+## `changedKeys`
+
+Returns an array of changed keys between `valueA` and `valueB`, where `root` is the root key. For examples see [`changedKeys` tests](https://github.com/vazco/uniforms/blob/master/packages/uniforms/__tests__/changedKeys.ts).
+
+```tsx
+import { changedKeys } from 'uniforms';
+
+changedKeys('a', { b: 1, c: 2 }, { b: 1 }); // ['a', 'a.c']
+```
+
+## `filterDOMProps`
+
+Removes all uniforms-related props, registered with `filterDOMProps.register`. Use it in all places where you'd like to pass all unrelated props down and `useField` or `connectField` provide you with the props.
+
+```tsx
+import { filterDOMProps } from 'uniforms';
+
+const filteredProps = filterDOMProps(props);
+```
+
+### Custom props registration
+
+It's often the case that your custom components will have a bunch of known properties, like `locale` or `userType`. To ease the process of using them across the project, you can register them to make `filterDOMProps` remove them as well. For example, [`SimpleSchemaBridge`](https://github.com/vazco/uniforms/blob/master/packages/uniforms-bridge-simple-schema/src/register.ts) registers all of the SimpleSchema-specific options.
+
+```tsx
+import { filterDOMProps } from 'uniforms';
+
+filterDOMProps({ example: 42 }); // { example: 42 }
+filterDOMProps.registered.includes('example'); // false
+filterDOMProps.register('example');
+filterDOMProps.registered.includes('example'); // true
+filterDOMProps({ example: 42 }); // {}
+```
+
+As `filterDOMProps` is fully typed, if you'd like to make it work with TypeScript, you have to extend the `FilterDOMProps` interface as well.
+
+```tsx
+declare module 'uniforms' {
+ interface FilterDOMProps {
+ propA: never;
+ propB: never;
+ }
+}
+
+filterDOMProps.register('propA', 'propB');
+```
+
+## `joinName`
+
+Safely joins partial field names.
+If you create a custom field with subfields, do use `joinName` instead of manually concatenating them.
+It ensures that the name will be correctly escaped if needed.
+
+```tsx
+import { joinName } from 'uniforms';
+
+joinName('array', 1, 'field'); // 'array.1.field'
+joinName('object', 'nested.property'); // 'object.nested.property'
+```
+
+If the first argument is `null`, then it returns an array of escaped parts.
+
+```tsx
+import { joinName } from 'uniforms';
+
+joinName(null, 'array', 1, 'field'); // ['array', '1', 'field']
+joinName(null, 'object', 'nested.property'); // ['object', 'nested', 'property']
+```
+
+If the field name contains a dot (`.`) or a bracket (`[` or `]`), it has to be escaped with `["..."]`.
+If any of these characters is not escaped, `joinName` will **not** throw an error but its behavior is not specified.
+The escape of any other name part will be stripped.
+
+```tsx
+joinName(null, 'object["with.dot"].field'); // ['object', '["with.dot"]', 'field']
+joinName('object["with.dot"].field'); // 'object["with.dot"].field'
+
+joinName(null, 'this["is"].safe'); // ['this', 'is', 'safe']
+joinName('this["is"].safe'); // 'this.is.safe'
+```
+
+For more examples check [`joinName` tests](https://github.com/vazco/uniforms/blob/master/packages/uniforms/__tests__/joinName.ts).
+
+## `randomIds`
+
+Generates random ID, based on given prefix. Use it, if you want to have random but deterministic strings. If no prefix is provided, a unique `uniforms-X` prefix will be used generated.
+
+```tsx
+import { randomIds } from 'uniforms';
+
+const randomId1 = randomIds();
+randomId1(); // uniforms-0000-0000
+randomId1(); // uniforms-0000-0001
+randomId1(); // uniforms-0000-0002
+
+const randomId2 = randomIds();
+randomId2(); // uniforms-0001-0000
+randomId2(); // uniforms-0001-0001
+randomId2(); // uniforms-0001-0002
+
+const randomId3 = randomIds('prefix');
+randomId3(); // prefix-0000
+randomId3(); // prefix-0001
+randomId3(); // prefix-0002
+```
+
+## `useForm`
+
+A direct way of accessing the [context data](/docs/api-context-data/#state):
+
+```tsx
+import { useForm } from 'uniforms';
+
+function Example() {
+ const context = useForm();
+}
+```
+
+## `useField`
+
+A hook version of [`connectField`](#connectfield). It receives three arguments: field name (`string`), field props (`object`), and optional options.
+
+```tsx
+function Example(props) {
+ const [fieldProps, context] = useField(props.name, props, options);
+ return ;
+}
+```
+
+The table below lists all available options:
+
+| Name | Type | Default | Description |
+| :------------: | :-------: | :-----: | :----------------------------------------------------------------------------------------------------------------------------------: |
+| `absoluteName` | `boolean` | `false` | Whether the field name should be treated as a top-level one, ignoring parent fields. |
+| `initialValue` | `boolean` | `true` | Initial value check. If `true`, then after the first render the default value is set as value if no value is provided (`undefined`). |
+
+Using `useField` allows you to create components that combine values of multiple fields:
+
+```tsx
+import { useField } from 'uniforms';
+
+function ArePasswordsEqual() {
+ const [{ value: passwordA }] = useField('passwordA', {});
+ const [{ value: passwordB }] = useField('passwordB', {});
+ const areEqual = passwordA === passwordB;
+ return
- API |
+ API |
Contribute |
Quick Start |
Playground |
diff --git a/website/docs/api-reference/bridges.mdx b/website/docs/api-reference/bridges.mdx
index c13586400..62f1f0dc4 100644
--- a/website/docs/api-reference/bridges.mdx
+++ b/website/docs/api-reference/bridges.mdx
@@ -21,7 +21,7 @@ Deprecated bridges:
- `SimpleSchemaBridge` in `uniforms-bridge-simple-schema` ([schema documentation](https://github.com/Meteor-Community-Packages/meteor-simple-schema/blob/master/DOCS.md))
- `GraphQLBridge` in `uniforms-bridge-graphql` ([schema documentation](https://graphql.org/))
-If you see a lot of [`Warning: Unknown props...`](https://fb.me/react-unknown-prop) logs, check if your schema or theme doesn't provide extra props. If so, consider [registering it with `filterDOMProps`](/docs/api-helpers#filterdomprops).
+If you see a lot of [`Warning: Unknown props...`](https://fb.me/react-unknown-prop) logs, check if your schema or theme doesn't provide extra props. If so, consider [registering it with `filterDOMProps`](/docs/api-reference/helpers#filterdomprops).
## `JSONSchemaBridge`
diff --git a/website/docs/api-reference/context-data.mdx b/website/docs/api-reference/context-data.mdx
index 6fcfd7029..74cb48b7c 100644
--- a/website/docs/api-reference/context-data.mdx
+++ b/website/docs/api-reference/context-data.mdx
@@ -11,7 +11,7 @@ Some of them were designed for internal use, but you can still take advantage of
## Accessing context data
-A direct way of accessing the context data is to use the [`useForm`](/docs/api-helpers/#useform) hook:
+A direct way of accessing the context data is to use the [`useForm`](/docs/api-reference/helpers#useform) hook:
```tsx
import { useForm } from 'uniforms';
@@ -21,7 +21,7 @@ function Example() {
}
```
-For convenience, it's also accessible through the [`useField`](/docs/api-helpers/#usefield) hook:
+For convenience, it's also accessible through the [`useField`](/docs/api-reference/helpers#usefield) hook:
```tsx
import { useField } from 'uniforms';
@@ -47,7 +47,7 @@ An object with a `details` field, which is an array of any validation errors.
### `formRef`
-Contains reference to the form component that gives access to [the form methods](/docs/api-forms#methods).
+Contains reference to the form component that gives access to [the form methods](/docs/api-reference/forms#methods).
### `model`
@@ -99,7 +99,7 @@ Access to `onSubmit` method.
### `randomId`
-Access to `randomId` method, created using the [`randomIds()`](/docs/api-helpers#randomids) helper.
+Access to `randomId` method, created using the [`randomIds()`](/docs/api-reference/helpers#randomids) helper.
### `schema`
diff --git a/website/docs/api-reference/forms.mdx b/website/docs/api-reference/forms.mdx
index e97ccc0e4..c9fc787f6 100644
--- a/website/docs/api-reference/forms.mdx
+++ b/website/docs/api-reference/forms.mdx
@@ -307,7 +307,7 @@ const MyForm = ({ schema, onSubmit }) => {
};
```
-You can do the same by using the [`useForm`](/docs/api-context-data#accessing-context-data) hook and the [`formRef`](/docs/api-context-data#formref) property.
+You can do the same by using the [`useForm`](/docs/api-reference/context-data#accessing-context-data) hook and the [`formRef`](/docs/api-reference/context-data#formref) property.
```tsx
function FormControls() {
diff --git a/website/docs/api-reference/helpers.mdx b/website/docs/api-reference/helpers.mdx
index ceffa3cef..6f6c51928 100644
--- a/website/docs/api-reference/helpers.mdx
+++ b/website/docs/api-reference/helpers.mdx
@@ -61,7 +61,7 @@ If you are not sure which one to use, do not use the `kind` option at all - it'l
The resulting props of a field are a merge of the props that uniforms provide, the ones coming from the bridge (schema) and finally the actual field props. For the exact ordering, please refer to the [source of `useField` hook](https://github.com/vazco/uniforms/blob/master/packages/uniforms/src/useField.tsx). Overall, it looks as follows:
1. uniforms props (e.g., `changed`, `onChange`, `value`).
-2. uniforms state (as defined in [context data](/docs/api-context-data/#state)).
+2. uniforms state (as defined in [context data](/docs/api-reference/context-data/#state)).
3. bridge props (depending on the schema)
4. field props (only when rendered directly)
@@ -175,7 +175,7 @@ randomId3(); // prefix-0002
## `useForm`
-A direct way of accessing the [context data](/docs/api-context-data/#state):
+A direct way of accessing the [context data](/docs/api-reference/context-data/#state):
```tsx
import { useForm } from 'uniforms';
diff --git a/website/src/pages-parts/LandingPage/Footer.tsx b/website/src/pages-parts/LandingPage/Footer.tsx
index b37b45553..25c14f8f0 100644
--- a/website/src/pages-parts/LandingPage/Footer.tsx
+++ b/website/src/pages-parts/LandingPage/Footer.tsx
@@ -32,7 +32,7 @@ export function Footer() {