@rjsf/utils
Version:
Utility functions for @rjsf/core
1,090 lines (1,027 loc) • 70.4 kB
text/typescript
import type {
ButtonHTMLAttributes,
ChangeEvent,
ComponentType,
FocusEvent,
HTMLAttributes,
ReactElement,
ReactNode,
StyleHTMLAttributes,
} from 'react';
import { JSONSchema7 } from 'json-schema';
import { TranslatableString } from './enums';
/** The representation of any generic object type, usually used as an intersection on other types to make them more
* flexible in the properties they support (i.e. anything else)
*/
export type GenericObjectType = {
[name: string]: any;
};
/** Map the JSONSchema7 to our own type so that we can easily bump to a more recent version at some future date and only
* have to update this one type.
*/
export type StrictRJSFSchema = JSONSchema7;
/** Allow for more flexible schemas (i.e. draft-2019) than the strict JSONSchema7
*/
export type RJSFSchema = StrictRJSFSchema & GenericObjectType;
/** Alias GenericObjectType as FormContextType to allow us to remap this at some future date
*/
export type FormContextType = GenericObjectType;
/** The interface for the test ID proxy objects that are returned by the `getTestId` utility function.
*/
export type TestIdShape = Record<string, string>;
/** Function to generate HTML name attributes from path segments */
export type NameGeneratorFunction = (path: FieldPathList, idPrefix: string, isMultiValue?: boolean) => string;
/** Experimental feature that specifies the Array `minItems` default form state behavior
*/
export type Experimental_ArrayMinItems = {
/** Optional enumerated flag controlling how array minItems are populated, defaulting to `all`:
* - `all`: Legacy behavior, populate minItems entries with default values initially and include an empty array when
* no values have been defined.
* - `requiredOnly`: Ignore `minItems` on a field when calculating defaults unless the field is required.
* - `never`: Ignore `minItems` on a field even the field is required.
*/
populate?: 'all' | 'requiredOnly' | 'never';
/** A function that determines whether to skip populating the array with default values based on the provided validator,
* schema, and root schema.
* If the function returns true, the array will not be populated with default values.
* If the function returns false, the array will be populated with default values according to the `populate` option.
* @param validator - An implementation of the `ValidatorType` interface that is used to detect valid schema conditions
* @param schema - The schema for which resolving a condition is desired
* @param [rootSchema] - The root schema that will be forwarded to all the APIs
* @returns A boolean indicating whether to skip populating the array with default values.
*/
computeSkipPopulate?: <T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(
validator: ValidatorType<T, S, F>,
schema: S,
rootSchema?: S,
) => boolean;
/** When `formData` is provided and does not contain `minItems` worth of data, this flag (`false` by default) controls
* whether the extra data provided by the defaults is appended onto the existing `formData` items to ensure the
* `minItems` condition is met. When false (legacy behavior), only the `formData` provided is merged into the default
* form state, even if there are fewer than the `minItems`. When true, the defaults are appended onto the end of the
* `formData` until the `minItems` condition is met.
*/
mergeExtraDefaults?: boolean;
};
/** Experimental features to specify different default form state behaviors. Currently, this affects the
* handling of optional array fields where `minItems` is set and handling of setting defaults based on the
* value of `emptyObjectFields`. It also affects how `allOf` fields are handled and how to handle merging defaults into
* the formData in relation to explicit `undefined` values via `mergeDefaultsIntoFormData`.
*/
export type Experimental_DefaultFormStateBehavior = {
/** Optional object, that controls how the default form state for arrays with `minItems` is handled. When not provided
* it defaults to `{ populate: 'all' }`.
*/
arrayMinItems?: Experimental_ArrayMinItems;
/** Optional enumerated flag controlling how empty object fields are populated, defaulting to `populateAllDefaults`:
* - `populateAllDefaults`: Legacy behavior - set default when there is a primitive value, an non-empty object field,
* or the field itself is required |
* - `populateRequiredDefaults`: Only sets default when a value is an object and its parent field is required, or it
* is a primitive value and it is required |
* - `skipDefaults`: Does not set defaults |
* - `skipEmptyDefaults`: Does not set an empty default. It will still apply the default value if a default property is defined in your schema. |
*/
emptyObjectFields?: 'populateAllDefaults' | 'populateRequiredDefaults' | 'skipDefaults' | 'skipEmptyDefaults';
/**
* Optional flag to compute the default form state using allOf and if/then/else schemas. Defaults to `skipDefaults'.
*/
allOf?: 'populateDefaults' | 'skipDefaults';
/** Optional enumerated flag controlling how the defaults are merged into the form data when dealing with undefined
* values, defaulting to `useFormDataIfPresent`.
* NOTE: If there is a default for a field and the `formData` is unspecified, the default ALWAYS merges.
* - `useFormDataIfPresent`: Legacy behavior - Do not merge defaults if there is a value for a field in `formData`,
* even if that value is explicitly set to `undefined`
* - `useDefaultIfFormDataUndefined`: - If the value of a field within the `formData` is `undefined`, then use the
* default value instead
*/
mergeDefaultsIntoFormData?: 'useFormDataIfPresent' | 'useDefaultIfFormDataUndefined';
/** Optional enumerated flag controlling how const values are merged into the form data as defaults when dealing with
* undefined values, defaulting to `always`. The defaulting behavior for this flag will always be controlled by the
* `emptyObjectField` flag value. For instance, if `populateRequiredDefaults` is set and the const value is not
* required, it will not be set.
* - `always`: A const value will always be merged into the form as a default. If there is are const values in a
* `oneOf` (for instance to create an enumeration with title different from the values), the first const value
* will be defaulted
* - `skipOneOf`: If const is in a `oneOf` it will NOT pick the first value as a default
* - `never`: A const value will never be used as a default
*
*/
constAsDefaults?: 'always' | 'skipOneOf' | 'never';
};
/** Optional function that allows for custom merging of `allOf` schemas
* @param schema - Schema with `allOf` that needs to be merged
* @returns The merged schema
*/
export type Experimental_CustomMergeAllOf<S extends StrictRJSFSchema = RJSFSchema> = (schema: S) => S;
/** The interface representing a Date object that contains an optional time */
export interface DateObject {
/** The year of the Date */
year: number;
/** The month of the Date */
month: number;
/** The day of the Date */
day: number;
/** The optional hours for the time of a Date */
hour?: number;
/** The optional minutes for the time of a Date */
minute?: number;
/** The optional seconds for the time of a Date */
second?: number;
}
/** Properties describing a Range specification in terms of attribute that can be added to the `HTML` `<input>` */
export type RangeSpecType = {
/** Specifies the interval between legal numbers in an input field */
step?: number;
/** Specifies a minimum value for an <input> element */
min?: number;
/** Specifies the maximum value for an <input> element */
max?: number;
};
/** Properties describing a Range specification in terms of attribute that can be added to the `HTML` `<input>` */
export type InputPropsType = Omit<RangeSpecType, 'step'> & {
/** Specifies the type of the <input> element */
type: string;
/** Specifies the interval between legal numbers in an input field or "any" */
step?: number | 'any';
/** Specifies the `autoComplete` value for an <input> element */
autoComplete?: HTMLInputElement['autocomplete'];
/** Specifies a filter for what file types the user can upload. */
accept?: HTMLInputElement['accept'];
};
/** The list of path elements that represents where in the schema a field is located. When the item in the field list is
* a string, then it represents the name of the property within an object. When it is a number, then it represents the
* index within an array.
*
* For example:
* `[]` represents the root object of the schema
* `['foo', 'bar']` represents the `bar` element contained within the `foo` element of the schema
* `['baz', 1]` represents the second element in the list `baz` of the schema
*/
export type FieldPathList = (string | number)[];
/** Type describing an id and path used for a field */
export type FieldPathId = {
/** The id for a field */
$id: string;
/** The path for a field */
path: FieldPathList;
/** The optional HTML name attribute for a field, generated by nameGenerator if provided */
name?: string;
};
/** Type describing a name used for a field in the `PathSchema` */
export type FieldPath = {
/** The name of a field */
$name: string;
};
/** Type describing a recursive structure of `FieldPath`s for an object with a non-empty set of keys */
export type PathSchema<T = any> =
T extends Array<infer U>
? FieldPath & {
[i: number]: PathSchema<U>;
}
: T extends GenericObjectType
? FieldPath & {
/** The set of names for fields in the recursive object structure */
[key in keyof T]?: PathSchema<T[key]>;
}
: FieldPath;
/** The type for error produced by RJSF schema validation */
export type RJSFValidationError = {
/** Name of the error, for example, "required" or "minLength" */
name?: string;
/** Message, for example, "is a required property" or "should NOT be shorter than 3 characters" */
message?: string;
/** An object with the error params returned by ajv
* ([see doc](https://github.com/ajv-validator/ajv/tree/6a671057ea6aae690b5967ee26a0ddf8452c6297#error-parameters)
* for more info)
*/
params?: any;
/** A string in Javascript property accessor notation to the data path of the field with the error. For example,
* `.name` or `['first-name']`
*/
property?: string;
/** JSON pointer to the schema of the keyword that failed validation. For example, `#/fields/firstName/required`.
* (Note: this may sometimes be wrong due to a [bug in ajv](https://github.com/ajv-validator/ajv/issues/512))
*/
schemaPath?: string;
/** Full error name, for example ".name is a required property" */
stack: string;
/** The title property for the failing field*/
title?: string;
};
/** The type that describes an error in a field */
export type FieldError = string;
/** The type that describes the list of errors for a field */
export type FieldErrors = {
/** The list of errors for the field */
__errors?: FieldError[];
};
/** Type describing a recursive structure of `FieldErrors`s for an object with a non-empty set of keys */
export type ErrorSchema<T = any> = FieldErrors & {
/** The set of errors for fields in the recursive object structure */
[key in keyof T]?: ErrorSchema<T[key]>;
};
/** Type that describes the list of errors for a field being actively validated by a custom validator */
export type FieldValidation = FieldErrors & {
/** Function that will add a new `message` to the list of errors */
addError: (message: string) => void;
};
/** Type describing a recursive structure of `FieldValidation`s for an object with a non-empty set of keys */
export type FormValidation<T = any> = FieldValidation & {
/** The set of validation objects for fields in the recursive object structure */
[key in keyof T]?: FormValidation<T[key]>;
};
/** The base properties passed to various RJSF components. */
export type RJSFBaseProps<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any> = {
/** The schema object for the field being described */
schema: S;
/** The uiSchema object for this base component */
uiSchema?: UiSchema<T, S, F>;
/** The `registry` object */
registry: Registry<T, S, F>;
};
/** The properties that are passed to an `ErrorListTemplate` implementation */
export type ErrorListProps<
T = any,
S extends StrictRJSFSchema = RJSFSchema,
F extends FormContextType = any,
> = RJSFBaseProps<T, S, F> & {
/** The errorSchema constructed by `Form` */
errorSchema: ErrorSchema<T>;
/** An array of the errors */
errors: RJSFValidationError[];
};
/** The properties that are passed to an `FieldErrorTemplate` implementation */
export type FieldErrorProps<
T = any,
S extends StrictRJSFSchema = RJSFSchema,
F extends FormContextType = any,
> = RJSFBaseProps<T, S, F> & {
/** The errorSchema constructed by `Form` */
errorSchema?: ErrorSchema<T>;
/** An array of the errors */
errors?: Array<string | ReactElement>;
/** The FieldPathId of the field in the hierarchy */
fieldPathId: FieldPathId;
};
/** The properties that are passed to an `FieldHelpTemplate` implementation */
export type FieldHelpProps<
T = any,
S extends StrictRJSFSchema = RJSFSchema,
F extends FormContextType = any,
> = RJSFBaseProps<T, S, F> & {
/** The help information to be rendered */
help?: string | ReactElement;
/** The FieldPathId of the field in the hierarchy */
fieldPathId: FieldPathId;
/** Flag indicating whether there are errors associated with this field */
hasErrors?: boolean;
};
/** The properties that are passed to a `GridTemplate` */
export interface GridTemplateProps extends GenericObjectType {
/** The contents of the grid template */
children?: ReactNode;
/** Optional flag indicating whether the grid element represents a column, necessary for themes which have components
* for Rows vs Columns. NOTE: This is falsy by default when not specified
*/
column?: boolean;
}
/** The set of `Fields` stored in the `Registry` */
export type RegistryFieldsType<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any> = {
/** A `Field` indexed by `name` */
[name: string]: Field<T, S, F>;
};
/** The set of `Widgets` stored in the `Registry` */
export type RegistryWidgetsType<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any> = {
/** A `Widget` indexed by `name` */
[name: string]: Widget<T, S, F>;
};
/** The set of RJSF templates that can be overridden by themes or users */
export type TemplatesType<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any> = {
/** The template to use while rendering normal or fixed array fields */
ArrayFieldTemplate: ComponentType<ArrayFieldTemplateProps<T, S, F>>;
/** The template to use while rendering the description for an array field */
ArrayFieldDescriptionTemplate: ComponentType<ArrayFieldDescriptionProps<T, S, F>>;
/** The template to use while rendering the buttons for an item in an array field */
ArrayFieldItemButtonsTemplate: ComponentType<ArrayFieldItemButtonsTemplateProps<T, S, F>>;
/** The template to use while rendering an item in an array field */
ArrayFieldItemTemplate: ComponentType<ArrayFieldItemTemplateProps<T, S, F>>;
/** The template to use while rendering the title for an array field */
ArrayFieldTitleTemplate: ComponentType<ArrayFieldTitleProps<T, S, F>>;
/** The template to use while rendering the standard html input */
BaseInputTemplate: ComponentType<BaseInputTemplateProps<T, S, F>>;
/** The template to use for rendering the description of a field */
DescriptionFieldTemplate: ComponentType<DescriptionFieldProps<T, S, F>>;
/** The template to use while rendering the errors for the whole form */
ErrorListTemplate: ComponentType<ErrorListProps<T, S, F>>;
/** The template to use while rendering a fallback field for schemas that have an empty or unknown 'type' */
FallbackFieldTemplate: ComponentType<FallbackFieldTemplateProps<T, S, F>>;
/** The template to use while rendering the errors for a single field */
FieldErrorTemplate: ComponentType<FieldErrorProps<T, S, F>>;
/** The template to use while rendering the errors for a single field */
FieldHelpTemplate: ComponentType<FieldHelpProps<T, S, F>>;
/** The template to use while rendering a field */
FieldTemplate: ComponentType<FieldTemplateProps<T, S, F>>;
/** The template to use to render a Grid element */
GridTemplate: ComponentType<GridTemplateProps>;
/** The template to use while rendering a multi-schema field (i.e. anyOf, oneOf) */
MultiSchemaFieldTemplate: ComponentType<MultiSchemaFieldTemplateProps<T, S, F>>;
/** The template to use while rendering an object */
ObjectFieldTemplate: ComponentType<ObjectFieldTemplateProps<T, S, F>>;
/** The template to use while rendering the Optional Data field controls */
OptionalDataControlsTemplate: ComponentType<OptionalDataControlsTemplateProps<T, S, F>>;
/** The template to use for rendering the title of a field */
TitleFieldTemplate: ComponentType<TitleFieldProps<T, S, F>>;
/** The template to use for rendering information about an unsupported field type in the schema */
UnsupportedFieldTemplate: ComponentType<UnsupportedFieldProps<T, S, F>>;
/** The template to use for rendering a field that allows a user to add additional properties */
WrapIfAdditionalTemplate: ComponentType<WrapIfAdditionalTemplateProps<T, S, F>>;
/** The set of templates associated with buttons in the form */
ButtonTemplates: {
/** The template to use for the main `Submit` button */
SubmitButton: ComponentType<SubmitButtonProps<T, S, F>>;
/** The template to use for the Add button used for AdditionalProperties and Array items */
AddButton: ComponentType<IconButtonProps<T, S, F>>;
/** The template to use for the Copy button used for Array items */
CopyButton: ComponentType<IconButtonProps<T, S, F>>;
/** The template to use for the Move Down button used for Array items */
MoveDownButton: ComponentType<IconButtonProps<T, S, F>>;
/** The template to use for the Move Up button used for Array items */
MoveUpButton: ComponentType<IconButtonProps<T, S, F>>;
/** The template to use for the Remove button used for AdditionalProperties and Array items */
RemoveButton: ComponentType<IconButtonProps<T, S, F>>;
/** The template to use for the Clear button used for input fields */
ClearButton: ComponentType<IconButtonProps<T, S, F>>;
};
} & {
/** Allow this to support any named `ComponentType` or an object of named `ComponentType`s */
[key: string]: ComponentType<any> | { [key: string]: ComponentType<any> } | undefined;
};
/** The set of UiSchema options that can be set globally and used as fallbacks at an individual template, field or
* widget level when no field-level value of the option is provided. Extends GenericObjectType to support allowing users
* to provide any value they need for their customizations.
*/
export type GlobalUISchemaOptions = GenericObjectType & {
/** Flag, if set to `false`, new items cannot be added to array fields, unless overridden (defaults to true) */
addable?: boolean;
/** Flag, if set to `true`, array items can be copied (defaults to false) */
copyable?: boolean;
/** Flag, if set to `false`, array items cannot be ordered (defaults to true) */
orderable?: boolean;
/** Flag, if set to `false`, array items will not be removable (defaults to true) */
removable?: boolean;
/** Field labels are rendered by default. Labels may be omitted by setting the `label` option to `false` */
label?: boolean;
/** Flag, if set to `true`, will allow the text input fields to be cleared
*/
allowClearTextInputs?: boolean;
/** When using `additionalProperties`, key collision is prevented by appending a unique integer to the duplicate key.
* This option allows you to change the separator between the original key name and the integer. Default is "-"
*/
duplicateKeySuffixSeparator?: string;
/** Enables the displaying of description text that contains markdown
*/
enableMarkdownInDescription?: boolean;
/** Enables the displaying of help text that contains markdown
*/
enableMarkdownInHelp?: boolean;
/** Enables the rendering of the Optional Data Field UI for specific types of schemas, either `object`, `array` or
* both. To disable the Optional Data Field UI for a specific field, provide an empty array within the UI schema.
*/
enableOptionalDataFieldForType?: ('object' | 'array')[];
};
/** The set of options from the `Form` that will be available on the `Registry` for use in everywhere the `registry` is
* available.
*/
export type GlobalFormOptions = {
/** To avoid collisions with existing ids in the DOM, it is possible to change the prefix used for ids;
* Default is `root`. This prop is passed to the `toFilePathId()` function within the RJSF field implementations.
*/
readonly idPrefix: string;
/** To avoid using a path separator that is present in field names, it is possible to change the separator used for
* ids; Default is `_`. This prop is passed to the `toFilePathId()` function within the RJSF field implementations.
*/
readonly idSeparator: string;
/** The component update strategy used by the Form and its fields for performance optimization */
readonly experimental_componentUpdateStrategy?: 'customDeep' | 'shallow' | 'always';
/** Optional function to generate custom HTML name attributes for form elements. Receives the field path segments
* and element type (object or array), and returns a custom name string. This allows backends like PHP/Rails
* (`root[tasks][0][title]`) or Django (`root__tasks-0__title`) to receive form data in their expected format.
*/
readonly nameGenerator?: NameGeneratorFunction;
/**
* Boolean flag that, when set to true, will cause the form to use a fallback UI when encountering a schema type that
* is not supported by RJSF or a custom field. When false, the UnsupportedField error component will be shown instead.
*/
readonly useFallbackUiForUnsupportedType?: boolean;
};
/** The object containing the registered core, theme and custom fields and widgets as well as the root schema, form
* context, schema utils and templates.
*/
export interface Registry<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any> {
/** The set of all fields used by the `Form`. Includes fields from `core`, theme-specific fields and any custom
* registered fields
*/
fields: RegistryFieldsType<T, S, F>;
/** The set of templates used by the `Form`. Includes templates from `core`, theme-specific templates and any custom
* registered templates
*/
templates: TemplatesType<T, S, F>;
/** The set of all widgets used by the `Form`. Includes widgets from `core`, theme-specific widgets and any custom
* registered widgets
*/
widgets: RegistryWidgetsType<T, S, F>;
/** The `formContext` object that was passed to `Form` */
formContext: F;
/** The root schema, as passed to the `Form`, which can contain referenced definitions */
rootSchema: S;
/** The current implementation of the `SchemaUtilsType` (from `@rjsf/utils`) in use by the `Form`. Used to call any
* of the validation-schema-based utility functions
*/
schemaUtils: SchemaUtilsType<T, S>;
/** The string translation function to use when displaying any of the RJSF strings in templates, fields or widgets */
translateString: (stringKey: TranslatableString, params?: string[]) => string;
/** The global Form Options that are available for all templates, fields and widgets to access */
readonly globalFormOptions: GlobalFormOptions;
/** The optional global UI Options that are available for all templates, fields and widgets to access */
globalUiOptions?: GlobalUISchemaOptions;
/** The optional uiSchema definitions extracted from the root uiSchema, keyed by `$ref` paths.
* Used to automatically apply uiSchema when a schema with a matching `$ref` is resolved.
*/
uiSchemaDefinitions?: UiSchemaDefinitions<T, S, F>;
}
/** The properties that are passed to a `Field` implementation */
export interface FieldProps<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>
extends
GenericObjectType,
RJSFBaseProps<T, S, F>,
Pick<HTMLAttributes<HTMLElement>, Exclude<keyof HTMLAttributes<HTMLElement>, 'onBlur' | 'onFocus' | 'onChange'>> {
/** The FieldPathId of the field in the hierarchy */
fieldPathId: FieldPathId;
/** The data for this field */
formData?: T;
/** The tree of errors for this field and its children */
errorSchema?: ErrorSchema<T>;
/** The field change event handler; called with the updated field value, the change path for the value
* (defaults to an empty array), an optional ErrorSchema and the optional id of the field being changed
*/
onChange: (newValue: T | undefined, path: FieldPathList, es?: ErrorSchema<T>, id?: string) => void;
/** The input blur event handler; call it with the field id and value */
onBlur: (id: string, value: any) => void;
/** The input focus event handler; call it with the field id and value */
onFocus: (id: string, value: any) => void;
/** A boolean value stating if the field should autofocus */
autofocus?: boolean;
/** A boolean value stating if the field is disabled */
disabled?: boolean;
/** A boolean value stating if the field is hiding its errors */
hideError?: boolean;
/** A boolean value stating if the field is read-only */
readonly?: boolean;
/** The required status of this field */
required?: boolean;
/** The unique name of the field, usually derived from the name of the property in the JSONSchema */
name: string;
/** An array of strings listing all generated error messages from encountered errors for this field */
rawErrors?: string[];
}
/** The definition of a React-based Field component */
export type Field<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any> = ComponentType<
FieldProps<T, S, F>
> & {
/** The optional TEST_IDS block that some fields contain, exported for testing purposes */
TEST_IDS?: TestIdShape;
};
/** The properties that are passed to a `FieldTemplate` implementation */
export type FieldTemplateProps<
T = any,
S extends StrictRJSFSchema = RJSFSchema,
F extends FormContextType = any,
> = RJSFBaseProps<T, S, F> & {
/** The FieldPathId containing the id and path for this field */
fieldPathId: FieldPathId;
/** The id of the field in the hierarchy. You can use it to render a label targeting the wrapped widget */
id: string;
/** A string containing the base CSS classes, merged with any custom ones defined in your uiSchema */
classNames?: string;
/** An object containing the style as defined in the `uiSchema` */
style?: StyleHTMLAttributes<any>;
/** The computed label for this field, as a string */
label: string;
/** A component instance rendering the field description, if one is defined (this will use any custom
* `DescriptionField` defined)
*/
description?: ReactElement;
/** A string containing any `ui:description` uiSchema directive defined */
rawDescription?: string;
/** The field or widget component instance for this field row */
children: ReactElement;
/** A component instance listing any encountered errors for this field */
errors?: ReactElement;
/** An array of strings listing all generated error messages from encountered errors for this field */
rawErrors?: string[];
/** A component instance rendering any `ui:help` uiSchema directive defined */
help?: ReactElement;
/** A string containing any `ui:help` uiSchema directive defined. **NOTE:** `rawHelp` will be `undefined` if passed
* `ui:help` is a React component instead of a string
*/
rawHelp?: string;
/** A boolean value stating if the field should be hidden */
hidden?: boolean;
/** A boolean value stating if the field is required */
required?: boolean;
/** A boolean value stating if the field is read-only */
readonly: boolean;
/** A boolean value stating if the field is hiding its errors */
hideError?: boolean;
/** A boolean value stating if the field is disabled */
disabled: boolean;
/** A boolean value stating if the label should be rendered or not. This is useful for nested fields in arrays where
* you don't want to clutter the UI
*/
displayLabel?: boolean;
/** The formData for this field */
formData?: T;
/** The value change event handler; Can be called with a new value to change the value for this field */
onChange: FieldProps<T, S, F>['onChange'];
/** Callback used to handle the changing of an additional property key's name with the new value
*/
onKeyRename: (newKey: string) => void;
/** Callback used to handle the changing of an additional property key's name when the input is blurred. The event's
* target's value will be used as the new value. Its a wrapper callback around `onKeyRename`
*/
onKeyRenameBlur: (event: FocusEvent<HTMLInputElement>) => void;
/** Callback used to handle the removal of the additionalProperty */
onRemoveProperty: () => void;
};
/**
* The properties that are passed to a `FallbackField` implementation
*/
export type FallbackFieldProps<
T = any,
S extends StrictRJSFSchema = RJSFSchema,
F extends FormContextType = any,
> = FieldProps<T, S, F>;
/**
* The properties that are passed to a `FallbackFieldTemplate` implementation
*/
export type FallbackFieldTemplateProps<
T = any,
S extends StrictRJSFSchema = RJSFSchema,
F extends FormContextType = any,
> = RJSFBaseProps<T, S, F> & {
/** A ReactNode that allows the selecting a different type for the field */
typeSelector: ReactNode;
/** A ReactNode that renders the field with the present formData and matches the selected type */
schemaField: ReactNode;
};
/** The properties that are passed to the `UnsupportedFieldTemplate` implementation */
export type UnsupportedFieldProps<
T = any,
S extends StrictRJSFSchema = RJSFSchema,
F extends FormContextType = any,
> = RJSFBaseProps<T, S, F> & {
/** The FieldPathId of the field in the hierarchy */
fieldPathId: FieldPathId;
/** The reason why the schema field has an unsupported type */
reason: string;
};
/** The properties that are passed to a `TitleFieldTemplate` implementation */
export type TitleFieldProps<
T = any,
S extends StrictRJSFSchema = RJSFSchema,
F extends FormContextType = any,
> = RJSFBaseProps<T, S, F> & {
/** The id of the field title in the hierarchy */
id: string;
/** The title for the field being rendered */
title: string;
/** A boolean value stating if the field is required */
required?: boolean;
/** Add optional data control */
optionalDataControl?: ReactNode;
};
/** The properties that are passed to a `DescriptionFieldTemplate` implementation */
export type DescriptionFieldProps<
T = any,
S extends StrictRJSFSchema = RJSFSchema,
F extends FormContextType = any,
> = RJSFBaseProps<T, S, F> & {
/** The id of the field description in the hierarchy */
id: string;
/** The description of the field being rendered */
description: string | ReactElement;
};
/** The properties that are passed to a `ArrayFieldTitleTemplate` implementation */
export type ArrayFieldTitleProps<
T = any,
S extends StrictRJSFSchema = RJSFSchema,
F extends FormContextType = any,
> = Omit<TitleFieldProps<T, S, F>, 'id' | 'title'> & {
/** The title for the field being rendered */
title?: string;
/** The FieldPathId of the field in the hierarchy */
fieldPathId: FieldPathId;
/** Add optional data control */
optionalDataControl?: ReactNode;
};
/** The properties that are passed to a `ArrayFieldDescriptionTemplate` implementation */
export type ArrayFieldDescriptionProps<
T = any,
S extends StrictRJSFSchema = RJSFSchema,
F extends FormContextType = any,
> = Omit<DescriptionFieldProps<T, S, F>, 'id' | 'description'> & {
/** The description of the field being rendered */
description?: string | ReactElement;
/** An object containing the id and path for this field */
fieldPathId: FieldPathId;
};
/** The properties of the buttons to render for each element in the ArrayFieldTemplateProps.items array */
export type ArrayFieldItemButtonsTemplateProps<
T = any,
S extends StrictRJSFSchema = RJSFSchema,
F extends FormContextType = any,
> = RJSFBaseProps<T, S, F> & {
/** The FieldPathId of the item for which buttons are being rendered */
fieldPathId: FieldPathId;
/** The className string */
className?: string;
/** Any optional style attributes */
style?: ButtonHTMLAttributes<HTMLButtonElement>['style'];
/** A boolean value stating if the array item is disabled */
disabled?: boolean;
/** A boolean value stating whether new items can be added to the array */
canAdd: boolean;
/** A boolean value stating whether the array item can be copied, assumed false if missing */
hasCopy: boolean;
/** A boolean value stating whether the array item can be moved down */
hasMoveDown: boolean;
/** A boolean value stating whether the array item can be moved up */
hasMoveUp: boolean;
/** A boolean value stating whether the array item can be removed */
hasRemove: boolean;
/** A number stating the index the array item occurs in `items` */
index: number;
/** A number stating the total number `items` in the array */
totalItems: number;
/** Callback function that adds a new item below this item */
onAddItem: (event?: any) => void;
/** Callback function that copies this item below itself */
onCopyItem: (event?: any) => void;
/** Callback function that moves the item up one spot in the list */
onMoveUpItem: (event?: any) => void;
/** Callback function that moves the item down one spot in the list */
onMoveDownItem: (event?: any) => void;
/** Callback function that removes the item from the list */
onRemoveItem: (event?: any) => void;
/** A boolean value stating if the array item is read-only */
readonly?: boolean;
};
/** The properties used to render the ArrayFieldItemTemplate */
export type ArrayFieldItemTemplateProps<
T = any,
S extends StrictRJSFSchema = RJSFSchema,
F extends FormContextType = any,
> = RJSFBaseProps<T, S, F> & {
/** The html for the item's content */
children: ReactNode;
/** The props to pass to the `ArrayFieldItemButtonTemplate` */
buttonsProps: ArrayFieldItemButtonsTemplateProps<T, S, F>;
/** The className string */
className: string;
/** A boolean value stating if the array item is disabled */
disabled?: boolean;
/** A boolean value stating whether the array item has a toolbar */
hasToolbar: boolean;
/** A number stating the index the array item occurs in `items` */
index: number;
/** A number stating the total number `items` in the array */
totalItems: number;
/** A boolean value stating if the array item is read-only */
readonly?: boolean;
/** A stable, unique key for the array item */
itemKey: string;
/** The UI schema of the array item's parent array field used for
* customization in some themes
*/
parentUiSchema?: UiSchema<T, S, F>;
/** A boolean flag indicating whether the label for the field is being shown, used to assist buttons placement */
displayLabel?: boolean;
/** A boolean flag indicating whether there is a description for the field, used to assist buttons placement */
hasDescription?: boolean;
};
/** The common properties of the two container templates: `ArrayFieldTemplateProps` and `ObjectFieldTemplateProps` */
export type ContainerFieldTemplateProps<
T = any,
S extends StrictRJSFSchema = RJSFSchema,
F extends FormContextType = any,
> = RJSFBaseProps<T, S, F> & {
/** The className string */
className?: string;
/** A boolean value stating if the array is disabled */
disabled?: boolean;
/** The FieldPathId of the field in the hierarchy */
fieldPathId: FieldPathId;
/** A boolean value stating if the array is read-only */
readonly?: boolean;
/** A boolean value stating if the array is required */
required?: boolean;
/** A boolean value stating if the field is hiding its errors */
hideError?: boolean;
/** A string value containing the title for the array */
title: string;
/** The formData for this array */
formData?: T;
/** The optional validation errors in the form of an `ErrorSchema` */
errorSchema?: ErrorSchema<T>;
/** The optional data control node to render within the ObjectFieldTemplate that controls */
optionalDataControl?: ReactNode;
};
/** The properties that are passed to an `ArrayFieldTemplate` implementation */
export type ArrayFieldTemplateProps<
T = any,
S extends StrictRJSFSchema = RJSFSchema,
F extends FormContextType = any,
> = ContainerFieldTemplateProps<T, S, F> & {
/** A boolean value stating whether new elements can be added to the array */
canAdd?: boolean;
/** An array of React elements representing the items in the array */
items: ReactElement[];
/** A function that adds a new item to the end of the array */
onAddClick: (event?: any) => void;
/** An array of strings listing all generated error messages from encountered errors for this widget */
rawErrors?: string[];
};
/** The properties of each element in the ObjectFieldTemplateProps.properties array */
export type ObjectFieldTemplatePropertyType = {
/** The html for the property's content */
content: ReactElement;
/** A string representing the property name */
name: string;
/** A boolean value stating if the object property is disabled */
disabled?: boolean;
/** A boolean value stating if the property is read-only */
readonly?: boolean;
/** A boolean value stating if the property should be hidden */
hidden: boolean;
};
/** The properties that are passed to an ObjectFieldTemplate implementation */
export type ObjectFieldTemplateProps<
T = any,
S extends StrictRJSFSchema = RJSFSchema,
F extends FormContextType = any,
> = ContainerFieldTemplateProps<T, S, F> & {
/** A string value containing the description for the object */
description?: string | ReactElement;
/** An array of objects representing the properties in the object */
properties: ObjectFieldTemplatePropertyType[];
/** Callback to use in order to add an new additionalProperty to the object field (to be used with
* additionalProperties and patternProperties)
*/
onAddProperty: () => void;
/** A boolean value stating if the object is read-only */
readonly?: boolean;
/** A boolean value stating if the object is required */
required?: boolean;
/** A boolean value stating if the field is hiding its errors */
hideError?: boolean;
/** The FieldPathId of the field in the hierarchy */
fieldPathId: FieldPathId;
/** The optional validation errors in the form of an `ErrorSchema` */
errorSchema?: ErrorSchema<T>;
/** The form data for the object */
formData?: T;
};
/** The properties that are passed to a OptionalDataControlsTemplate implementation */
export type OptionalDataControlsTemplateProps<
T = any,
S extends StrictRJSFSchema = RJSFSchema,
F extends FormContextType = any,
> = RJSFBaseProps<T, S, F> & {
/** The generated id for this Optional Data Control instance */
id: string;
/** The label to use for the Optional Data Control */
label: string;
/** Optional callback to call when clicking on the Optional Data Control to add data */
onRemoveClick?: () => void;
/** Optional callback to call when clicking on the Optional Data Control to remove data */
onAddClick?: () => void;
};
/** The properties that are passed to a WrapIfAdditionalTemplate implementation */
export type WrapIfAdditionalTemplateProps<
T = any,
S extends StrictRJSFSchema = RJSFSchema,
F extends FormContextType = any,
> = RJSFBaseProps<T, S, F> & {
/** The field or widget component instance for this field row */
children: ReactNode;
} & Pick<
FieldTemplateProps<T, S, F>,
| 'id'
| 'classNames'
| 'hideError'
| 'rawDescription'
| 'rawErrors'
| 'style'
| 'displayLabel'
| 'label'
| 'required'
| 'readonly'
| 'disabled'
| 'schema'
| 'uiSchema'
| 'onKeyRename'
| 'onKeyRenameBlur'
| 'onRemoveProperty'
| 'registry'
>;
/** The properties that are passed to a MultiSchemaFieldTemplate implementation */
export interface MultiSchemaFieldTemplateProps<
T = any,
S extends StrictRJSFSchema = RJSFSchema,
F extends FormContextType = any,
> extends RJSFBaseProps<T, S, F> {
/** The rendered widget used to select a schema option */
selector: ReactNode;
/** The rendered SchemaField for the selected schema option */
optionSchemaField: ReactNode;
}
/** The properties that are passed to a `Widget` implementation */
export interface WidgetProps<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>
extends
GenericObjectType,
RJSFBaseProps<T, S, F>,
Pick<HTMLAttributes<HTMLElement>, Exclude<keyof HTMLAttributes<HTMLElement>, 'onBlur' | 'onFocus' | 'onChange'>> {
/** The generated id for this widget, used to provide unique `name`s and `id`s for the HTML field elements rendered by
* widgets
*/
id: string;
/** The unique name of the field, usually derived from the name of the property in the JSONSchema; Provided in support
* of custom widgets.
*/
name: string;
/** The current value for this widget */
value: any;
/** The required status of this widget */
required?: boolean;
/** A boolean value stating if the widget is disabled */
disabled?: boolean;
/** A boolean value stating if the widget is read-only */
readonly?: boolean;
/** A boolean value stating if the widget is hiding its errors */
hideError?: boolean;
/** A boolean value stating if the widget should autofocus */
autofocus?: boolean;
/** The placeholder for the widget, if any */
placeholder?: string;
/** A map of UI Options passed as a prop to the component, including the optional `enumOptions`
* which is a special case on top of `UIOptionsType` needed only by widgets
*/
options: NonNullable<UIOptionsType<T, S, F>> & {
/** The enum options list for a type that supports them */
enumOptions?: EnumOptionsType<S>[];
};
/** The input blur event handler; call it with the widget id and value */
onBlur: (id: string, value: any) => void;
/** The value change event handler; call it with the new value every time it changes */
onChange: (value: any, es?: ErrorSchema<T>, id?: string) => void;
/** The input focus event handler; call it with the widget id and value */
onFocus: (id: string, value: any) => void;
/** The computed label for this widget, as a string */
label: string;
/** A boolean value, if true, will cause the label to be hidden. This is useful for nested fields where you don't want
* to clutter the UI. Customized via `label` in the `UiSchema`
*/
hideLabel?: boolean;
/** A boolean value stating if the widget can accept multiple values */
multiple?: boolean;
/** An array of strings listing all generated error messages from encountered errors for this widget */
rawErrors?: string[];
/** The optional custom HTML name attribute generated by the nameGenerator function, if provided */
htmlName?: string;
}
/** The definition of a React-based Widget component */
export type Widget<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any> = ComponentType<
WidgetProps<T, S, F>
>;
/** The properties that are passed to the BaseInputTemplate */
export interface BaseInputTemplateProps<
T = any,
S extends StrictRJSFSchema = RJSFSchema,
F extends FormContextType = any,
> extends WidgetProps<T, S, F> {
/** A `BaseInputTemplate` implements a default `onChange` handler that it passes to the HTML input component to handle
* the `ChangeEvent`. Sometimes a widget may need to handle the `ChangeEvent` using custom logic. If that is the case,
* that widget should provide its own handler via this prop.
*/
onChangeOverride?: (event: ChangeEvent<HTMLInputElement>) => void;
}
/** The type that defines the props used by the Submit button */
export type SubmitButtonProps<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any> = {
/** The uiSchema for this widget */
uiSchema?: UiSchema<T, S, F>;
/** The `registry` object */
registry: Registry<T, S, F>;
};
/** The type that defines the props for an Icon button, extending from a basic HTML button attributes */
export type IconButtonProps<
T = any,
S extends StrictRJSFSchema = RJSFSchema,
F extends FormContextType = any,
> = ButtonHTMLAttributes<HTMLButtonElement> &
Omit<RJSFBaseProps<T, S, F>, 'schema'> & {
/** An alternative specification for the type of the icon button */
iconType?: string;
/** The name representation or actual react element implementation for the icon */
icon?: string | ReactElement;
};
/** The type that defines how to change the behavior of the submit button for the form */
export type UISchemaSubmitButtonOptions = {
/** The text of the submit button. Set to "Submit" by default */
submitText?: string;
/** Flag, if `true`, removes the submit button completely from the form */
norender?: boolean;
/** Any other props to be passed to the submit button itself */
props?: GenericObjectType & {
/** A boolean value stating if the submit button is disabled */
disabled?: boolean;
/** The class name for the submit button */
className?: string;
};
};
/** Represents a primitive JSON Schema enum value */
export type EnumValue = string | number | boolean;
/** This type represents an element used to render an enum option */
export type EnumOptionsType<S extends StrictRJSFSchema = RJSFSchema> = {
/** The value for the enum option */
value: any;
/** The label for the enum options */
label: string;
/** The schema associated with the enum option when the option represents a `oneOf` or `anyOf` choice */
schema?: S;
};
/** This type remaps the keys of `Type` to prepend `ui:` onto them. As a result it does not need to be exported */
type MakeUIType<Type> = {
[Property in keyof Type as `ui:${string & Property}`]: Type[Property];
};
/** This type represents all the known supported options in the `ui:options` property, kept separate in order to
* remap the keys. It also contains all the properties, optionally, of `TemplatesType` except "ButtonTemplates"
*/
type UIOptionsBaseType<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any> = Partial<
Pick<
TemplatesType<T, S, F>,
| 'ArrayFieldDescriptionTemplate'
| 'ArrayFieldItemTemplate'
| 'ArrayFieldTemplate'
| 'ArrayFieldTitleTemplate'
| 'BaseInputTemplate'
| 'DescriptionFieldTemplate'
| 'ErrorListTemplate'
| 'FieldErrorTemplate'
| 'FieldHelpTemplate'
| 'FieldTemplate'
| 'ObjectFieldTemplate'
| 'TitleFieldTemplate'
| 'UnsupportedFieldTemplate'
| 'WrapIfAdditionalTemplate'
>
> &
GlobalUISchemaOptions & {
/** Allows RJSF to override the default field implementation by specifying either the name of a field that is used
* to look up an implementation from the `fields` list or an actual one-off `Field` component implementation itself
*/
field?: Field<T, S, F> | string;
/** Any classnames that the user wants to be applied to a field in the ui */
classNames?: string;
/** Any custom style that the user wants to apply to a field in the ui, applied on the same element as classNames */
style?: StyleHTMLAttributes<any>;
/** We know that for title, it will be a string, if it is provided */
title?: string;
/** We know that for description, it will be a string, if it is provided */
description?: string;
/** We know that for placeholder, it will be a string, if it is provided */
placeholder?: string;
/** Used to add text next to a field to guide the end user in filling it in */
help?: string;
/** Flag, if set to `true`, will mark the field as automatically focused on a text input or textarea input */
autofocus?: boolean;
/** Use to mark the field as supporting auto complete on a text input or textarea input */
autocomplete?: HTMLInputElement['autocomplete'];
/** Flag, if set to `true`, will mark all child widgets from a given field as disabled */
disabled?: boolean;
/** The default value to use when an input for a field is empty */
emptyValue?: any;
/** Will disable any of the enum options specified in the array (by value) */
enumDisabled?: EnumValue[];
/** Allows a user to provide a list of labels for enum values in the schema.
* Can be an array (positional, matched by index) or a Record mapping enum values to labels (matched by value).
*/
enumNames?: string[] | Record<string | number, string>;
/** Controls the display order of enum options, following the same pattern as `ui:order` for object properties.
* Supports a `'*'` wildcard to represent all remaining values in their original schema order.
*/
enumOrder?: EnumValue[];
/** Provides an optional field within a schema to be used as the oneOf/anyOf selector when there isn't a
* discriminator
*/
optionsSchemaSelector?: string;
/** Flag, if set to `true`, will hide the default error display for the g