UNPKG

@rjsf/core

Version:

A simple React component capable of building HTML forms out of a JSON schema.

400 lines (399 loc) 19.9 kB
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