@rjsf/core
Version:
A simple React component capable of building HTML forms out of a JSON schema.
400 lines (399 loc) • 19.9 kB
TypeScript
import { ComponentType, ReactNode } from 'react';
import { FieldProps, FieldPathId, FormContextType, GenericObjectType, RJSFSchema, Registry, StrictRJSFSchema, UiSchema } from '@rjsf/utils';
/** The enumeration of the three different Layout GridTemplate type values
*/
export declare enum GridType {
ROW = "ui:row",
COLUMN = "ui:col",
COLUMNS = "ui:columns",
CONDITION = "ui:condition"
}
/** The enumeration of the different operators within a condition
*/
export declare enum Operators {
ALL = "all",
SOME = "some",
NONE = "none"
}
/** Type used to represent an object that contains anything */
type ConfigObject = Record<string, any>;
export interface GridProps extends GenericObjectType {
/** The optional operator to use when comparing a field's value with the expected value for `GridType.CONDITION`
*/
operator?: Operators;
/** The optional name of the field from which to get the value for `GridType.CONDITION`
*/
field?: string;
/** The optional expected value against which to compare the field's value using the `operator`
*/
value?: unknown;
}
export type GridSchemaType = {
[gridType in GridType]?: object;
};
/** The types which comprise the possibilities for the `layoutGridSchema` prop
*/
export type LayoutGridSchemaType = GridSchemaType | ConfigObject | string;
export interface LayoutGridFieldProps<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any> extends FieldProps<T, S, F> {
/** Optional string or object used to describe the current level of the `LayoutGridField`
*/
layoutGridSchema?: LayoutGridSchemaType;
}
/** The regular expression that is used to detect whether a string contains a lookup key
*/
export declare const LOOKUP_REGEX: RegExp;
/** The constant representing the main layout grid schema option name in the `uiSchema`
*/
export declare const LAYOUT_GRID_UI_OPTION = "layoutGrid";
/** The constant representing the main layout grid schema option name in the `uiSchema`
*/
export declare const LAYOUT_GRID_OPTION = "ui:layoutGrid";
/** Type used to return options list and whether it has a discriminator */
type OneOfOptionsInfoType<S extends StrictRJSFSchema = RJSFSchema> = {
options: S[];
hasDiscriminator: boolean;
};
/** Type used to represent a React-based rendering component */
type RenderComponent = ComponentType<any>;
/** Type used to determine what are the UIComponent and props from the grid schema */
type UIComponentPropsType = {
/** The name of the component */
name: string;
/** The render component if specified */
UIComponent: RenderComponent | null;
/** Any uiProps associated with the render component */
uiProps: ConfigObject;
/** The special case where the component is immediately rendered */
rendered: ReactNode;
};
/** Computes the uiSchema for the field with `name` from the `uiProps` and `uiSchema` provided. The field UI Schema
* will always contain a copy of the global options from the `uiSchema` (so they can be passed down) as well as
* copying them into the local ui options. When the `forceReadonly` flag is true, then the field UI Schema is
* updated to make "readonly" be true. When the `schemaReadonly` flag is true AND the field UI Schema does NOT have
* the flag already provided, then we also make "readonly" true. We always make sure to return the final value of the
* field UI Schema's "readonly" flag as `uiReadonly` along with the `fieldUiSchema` in the return value.
*
* @param field - The name of the field to pull the existing UI Schema for
* @param uiProps - Any props that should be put into the field's uiSchema
* @param [uiSchema] - The optional UI Schema from which to get the UI schema for the field
* @param [schemaReadonly] - Optional flag indicating whether the schema indicates the field is readonly
* @param [forceReadonly] - Optional flag indicating whether the Form itself is in readonly mode
*/
export declare function computeFieldUiSchema<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(field: string, uiProps: ConfigObject, uiSchema?: UiSchema<T, S, F>, schemaReadonly?: boolean, forceReadonly?: boolean): {
fieldUiSchema: any;
uiReadonly: boolean | undefined;
};
/** Given an `operator`, `datum` and `value` determines whether this condition is considered matching. Matching
* depends on the `operator`. The `datum` and `value` are converted into arrays if they aren't already and then the
* contents of the two arrays are compared using the `operator`. When `operator` is All, then the two arrays must be
* equal to match. When `operator` is SOME then the intersection of the two arrays must have at least one value in
* common to match. When `operator` is NONE then the intersection of the two arrays must not have any values in common
* to match.
*
* @param [operator] - The optional operator for the condition
* @param [datum] - The optional datum for the condition, this can be an item or a list of items of type unknown
* @param [value='$0m3tH1nG Un3xP3cT3d'] The optional value for the condition, defaulting to a highly unlikely value
* to avoid comparing two undefined elements when `value` was forgotten in the condition definition.
* This can be an item or a list of items of type unknown
* @returns - True if the condition matches, false otherwise
*/
export declare function conditionMatches(operator?: Operators, datum?: unknown, value?: unknown): boolean;
/** From within the `layoutGridSchema` finds the `children` and any extra `gridProps` from the object keyed by
* `schemaKey`. If the `children` contains extra `gridProps` and those props contain a `className` string, try to
* lookup whether that `className` has a replacement value in the `registry` using the `FORM_CONTEXT_LOOKUP_BASE`.
* When the `className` value contains multiple classNames separated by a space, the lookup will look for a
* replacement value for each `className` and combine them into one.
*
* @param layoutGridSchema - The GridSchemaType instance from which to obtain the `schemaKey` children and extra props
* @param schemaKey - A `GridType` value, used to get the children and extra props from within the `layoutGridSchema`
* @param registry - The `@rjsf` Registry from which to look up `classNames` if they are present in the extra props
* @returns - An object containing the list of `LayoutGridSchemaType` `children` and any extra `gridProps`
* @throws - A `TypeError` when the `children` is not an array
*/
export declare function findChildrenAndProps<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(layoutGridSchema: GridSchemaType, schemaKey: GridType, registry: Registry<T, S, F>): {
children: LayoutGridSchemaType[];
gridProps: GridProps;
};
/** Computes the `rawSchema` and `fieldPathId` for a `schema` and a `potentialIndex`. If the `schema` is of type array,
* has an `ITEMS_KEY` element and `potentialIndex` represents a numeric value, the element at `ITEMS_KEY` is checked
* to see if it is an array. If it is AND the `potentialIndex`th element is available, it is used as the `rawSchema`,
* otherwise the last value of the element is used. If it is not, then the element is used as the `rawSchema`. In
* either case, an `fieldPathId` is computed for the array index. If the `schema` does not represent an array or the
* `potentialIndex` is not a numeric value, then `rawSchema` is returned as undefined and given `fieldPathId` is returned
* as is.
*
* @param schema - The schema to generate the fieldPathId for
* @param fieldPathId - The FieldPathId for the schema
* @param potentialIndex - A string containing a potential index
* @returns - An object containing the `rawSchema` and `fieldPathId` of an array item, otherwise an undefined `rawSchema`
*/
export declare function computeArraySchemasIfPresent<S extends StrictRJSFSchema = RJSFSchema>(schema: S | undefined, fieldPathId: FieldPathId, potentialIndex: string): {
rawSchema?: S;
fieldPathId: FieldPathId;
};
/** Given a `dottedPath` to a field in the `initialSchema`, iterate through each individual path in the schema until
* the leaf path is found and returned (along with whether that leaf path `isRequired`) OR no schema exists for an
* element in the path. If the leaf schema element happens to be a oneOf/anyOf then also return the oneOf/anyOf as
* `options`.
*
* @param registry - The registry
* @param dottedPath - The dotted-path to the field for which to get the schema
* @param initialSchema - The initial schema to start the search from
* @param formData - The formData, useful for resolving a oneOf/anyOf selection in the path hierarchy
* @param initialFieldIdPath - The initial fieldPathId to start the search from
* @returns - An object containing the destination schema, isRequired and isReadonly flags for the field and options
* info if a oneOf/anyOf
*/
export declare function getSchemaDetailsForField<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(registry: Registry<T, S, F>, dottedPath: string, initialSchema: S, formData: FieldProps<T, S, F>['formData'], initialFieldIdPath: FieldPathId): {
schema?: S;
isRequired: boolean;
isReadonly?: boolean;
optionsInfo?: OneOfOptionsInfoType<S>;
fieldPathId: FieldPathId;
};
/** Gets the custom render component from the `render`, by either determining that it is either already a function or
* it is a non-function value that can be used to look up the function in the registry. If no function can be found,
* null is returned.
*
* @param render - The potential render function or lookup name to one
* @param registry - The `@rjsf` Registry from which to look up `classNames` if they are present in the extra props
* @returns - Either a render function if available, or null if not
*/
export declare function getCustomRenderComponent<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(render: string | RenderComponent, registry: Registry<T, S, F>): RenderComponent | null;
/** Extract the `name`, and optional `render` and all other props from the `gridSchema`. We look up the `render` to
* see if can be resolved to a UIComponent. If `name` does not exist and there is an optional `render` UIComponent, we
* set the `rendered` component with only specified props for that component in the object.
*
* @param registry - The `@rjsf` Registry from which to look up `classNames` if they are present in the extra props
* @param gridSchema - The string or object that represents the configuration for the grid field
* @returns - The UIComponentPropsType computed from the gridSchema
*/
export declare function computeUIComponentPropsFromGridSchema<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(registry: Registry<T, S, F>, gridSchema?: string | ConfigObject): UIComponentPropsType;
/** The `LayoutGridField` will render a schema, uiSchema and formData combination out into a GridTemplate in the shape
* described in the uiSchema. To define the grid to use to render the elements within a field in the schema, provide in
* the uiSchema for that field the object contained under a `ui:layoutGrid` element. E.g. (as a JSON object):
*
* ```
* {
* "field1" : {
* "ui:field": "LayoutGridField",
* "ui:layoutGrid": {
* "ui:row": { ... }
* }
* }
* }
* ```
*
* The outermost level of a `LayoutGridField` is the `ui:row` that defines the nested rows, columns, and/or condition
* elements (i.e. "grid elements") in the grid. This definition is either a simple "grid elements" OR an object with
* native `GridTemplate` implementation specific props and a `children` array of "grid elements". E.g. (as JSON objects):
*
* Simple `ui:row` definition, without additional `GridTemplate` props:
* ```
* "ui:row": [
* { "ui:row"|"ui:col"|"ui:columns"|"ui:condition": ... },
* ...
* ]
* ```
*
* Complex `ui:row` definition, with additional `GridTemplate` (this example uses @mui/material/Grid2 native props):
* ```
* "ui:row": {
* "spacing": 2,
* "size": { md": 4 },
* "alignContent": "flex-start",
* "className": "GridRow",
* "children": [
* { "ui:row"|"ui:col"|"ui:columns"|"ui:condition": ... },
* ...
* ]
* }
* ```
*
* NOTE: Special note about the native `className` prop values. All className values will automatically be looked up in
* the `formContext.lookupMap` in case they have been defined using a CSS-in-JS approach. In other words, from the
* example above, if the `Form` was constructed with a `lookupMap` set to `{ GridRow: cssInJs.GridRowClass }`
* then when rendered, the native `GridTemplate` will get the `className` with the value from
* `cssInJs.GridRowClass`. This automatic lookup will happen for any of the "grid elements" when rendering with
* `GridTemplate` props. If multiple className values are present, for example:
* `{ className: 'GridRow GridColumn' }`, the classNames are split apart, looked up individually, and joined
* together to form one className with the values from `cssInJs.GridRowClass` and `cssInJs.GridColumnClass`.
*
* The `ui:col` grid element is used to specify the list of columns within a grid row. A `ui:col` element can take on
* several forms: 1) a simple list of dotted-path field names within the root field; 2) a list of objects containing the
* dotted-path field `name` any other props that are gathered into `ui:options` for the field; 3) a list with a one-off
* `render` functional component with or without a non-field `name` identifier and any other to-be-spread props; and
* 4) an object with native `GridTemplate` implementation specific props and a `children` array with 1) or 2) or even a
* nested `ui:row` or a `ui:condition` containing a `ui:row` (although this should be used carefully). E.g.
* (as JSON objects):
*
* Simple `ui:col` definition, without additional `GridTemplate` props and form 1 only children:
* ```
* "ui:col": ["innerField", "inner.grandChild", ...]
* ```
*
* Complicated `ui:col` definition, without additional `GridTemplate` props and form 2 only children:
* ```
* "ui:col": [
* { "name": "innerField", "fullWidth": true },
* { "name": "inner.grandChild", "convertOther": true },
* ...
* ]
* ```
*
* More complicated `ui:col` definition, without additional `GridTemplate` props and form 2 children, one being a
* one-off `render` functional component without a non-field `name` identifier
* ```
* "ui:col": [
* "innerField",
* {
* "render": "WizardNavButton",
* "isNext": true,
* "size": "large"
* }
* ]
* ```
*
* Most complicated `ui:col` definition, additional `GridTemplate` props and form 1, 2 and 3 children (this example
* uses @mui/material/Grid2 native props):
* ```
* "ui:col": {
* "size": { "md": 4 },
* "className": "GridColumn",
* "children": [
* "innerField",
* { "name": "inner.grandChild", "convertOther": true },
* { "name": "customRender", "render": "CustomRender", toSpread: "prop-value" }
* { "ui:row|ui:condition": ... }
* ...
* ]
* }
* ```
*
* NOTE: If a `name` prop does not exist or its value does not match any field in a schema, then it is assumed to be a
* custom `render` component. If the `render` prop does not exist, a null render will occur. If `render` is a
* string, its value will be looked up in the `formContext.lookupMap` first before defaulting to a null render.
*
* The `ui:columns` grid element is syntactic sugar to specify a set of `ui:col` columns that all share the same set of
* native `GridTemplate` props. In other words rather than writing the following configuration that renders a
* `<GridTemplate>` element with 3 `<GridTemplate column className="GridColumn col-md-4">` nodes and 2
* `<GridTemplate column className="col-md-6">` nodes within it (one for each of the fields contained in the `children`
* list):
*
* ```
* "ui:row": {
* "children": [
* {
* "ui:col": {
* "className": "GridColumn col-md-4",
* "children": ["innerField"],
* }
* },
* {
* "ui:col": {
* "className": "GridColumn col-md-4",
* "children": ["inner.grandChild"],
* }
* },
* {
* "ui:col": {
* "className": "GridColumn col-md-4",
* "children": [{ "name": "inner.grandChild2" }],
* }
* },
* {
* "ui:col": {
* "className": "col-md-6",
* "children": ["innerField2"],
* }
* },
* {
* "ui:col": {
* "className": "col-md-6",
* "children": ["inner.grandChild3"],
* }
* },
* ]
* }
* ```
*
* One can write this instead:
* ```
* "ui:row": {
* "children": [
* {
* "ui:columns": {
* "className": "GridColumn col-md-4",
* "children": ["innerField", "inner.grandChild", { "name": "inner.grandChild2", "convertOther": true }],
* }
* },
* {
* "ui:columns": {
* "className": "col-md-6",
* "children": ["innerField2", "inner.grandChild3"],
* }
* }
* ]
* }
* ```
*
* NOTE: This syntax differs from
* `"ui:col": { "className": "col-md-6", "children": ["innerField2", "inner.grandChild3"] }` in that
* the `ui:col` will render the two children fields inside a single `<GridTemplate "className": "col-md-6",>`
* element.
*
* The final grid element, `ui:condition`, allows for conditionally displaying "grid elements" within a row based on the
* current value of a field as it relates to a (list of) hard-coded value(s). There are four elements that make up a
* `ui:condition`: 1) the dotted-path `field` name within the root field that makes up the left-side of the condition;
* 2) the hard-coded `value` (single or list) that makes up the right-side of the condition; 3) the `operator` that
* controls how the left and right sides of the condition are compared; and 4) the `children` array that defines the
* "grid elements" to display if the condition passes.
*
* A `ui:condition` uses one of three `operators` when deciding if a condition passes: 1) The `all` operator will pass
* when the right-side and left-side contains all the same value(s); 2) the `some` operator will pass when the
* right-side and left-side contain as least one value in common; 3) the `none` operator will pass when the right-side
* and left-side do not contain any values in common. E.g. (as JSON objects):
*
* Here is how to render an if-then-else for `field2` which is an enum that has 3 known values and supports allowing
* any other value:
* ```
* "ui:row": [
* {
* "ui:condition": {
* "field": "field2",
* "operator": "all",
* "value": "value1",
* "children": [
* { "ui:row": [...] },
* ],
* }
* },
* {
* "ui:condition": {
* "field": "field2",
* "operator": "some",
* "value": ["value2", "value3"],
* "children": [
* { "ui:row": [...] },
* ],
* }
* },
* {
* "ui:condition": {
* "field": "field2",
* "operator": "none",
* "value": ["value1", "value2", "value3"],
* "children": [
* { "ui:row": [...] },
* ],
* }
* }
* ]
* ```
*/
declare function LayoutGridField<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(props: LayoutGridFieldProps<T, S, F>): import("react/jsx-runtime").JSX.Element;
declare namespace LayoutGridField {
var TEST_IDS: import("@rjsf/utils").TestIdShape;
}
export default LayoutGridField;
//# sourceMappingURL=LayoutGridField.d.ts.map