diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e23f72906..5f98f5d3ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ should change the heading of the (upcoming) version to include a major version b - Updated the usage of the `ButtonTemplates` to pass the new required `registry` prop, filtering it out in the actual implementations before spreading props, fixing - [#3314](https://github.com/rjsf-team/react-jsonschema-form/issues/3314) - Updated `CheckboxWidget` to get the `required` state of the checkbox from the `schemaRequiresTrueValue()` utility function rather than the `required` prop, fixing [#3317](https://github.com/rjsf-team/react-jsonschema-form/issues/3317) - Updated the test for the `CheckboxWidget` validating that the `schema.title` is passed as the label, fixing [#3302](https://github.com/rjsf-team/react-jsonschema-form/issues/3302) +- Updated the theme to accept generic types, exporting `generateXXX` functions for `Form`, `Theme`, `Templates` and `Widgets` to support using the theme with user-specified type generics, partially fixing [#3072](https://github.com/rjsf-team/react-jsonschema-form/issues/3072) ## @rjsf/chakra-ui - Updated the usage of the `ButtonTemplates` to pass the new required `registry` prop, filtering it out in the actual implementations before spreading props, fixing - [#3314](https://github.com/rjsf-team/react-jsonschema-form/issues/3314) diff --git a/packages/bootstrap-4/src/AddButton/AddButton.tsx b/packages/bootstrap-4/src/AddButton/AddButton.tsx index 0b11e23ff7..d643dbb6eb 100644 --- a/packages/bootstrap-4/src/AddButton/AddButton.tsx +++ b/packages/bootstrap-4/src/AddButton/AddButton.tsx @@ -1,21 +1,26 @@ import React from "react"; -import { IconButtonProps } from "@rjsf/utils"; +import { + FormContextType, + IconButtonProps, + RJSFSchema, + StrictRJSFSchema, +} from "@rjsf/utils"; import Button from "react-bootstrap/Button"; import { BsPlus } from "@react-icons/all-files/bs/BsPlus"; -const AddButton: React.ComponentType = ({ - uiSchema, - registry, - ...props -}) => ( - -); - -export default AddButton; +export default function AddButton< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>({ uiSchema, registry, ...props }: IconButtonProps) { + return ( + + ); +} diff --git a/packages/bootstrap-4/src/ArrayFieldItemTemplate/ArrayFieldItemTemplate.tsx b/packages/bootstrap-4/src/ArrayFieldItemTemplate/ArrayFieldItemTemplate.tsx index e4f62d8c68..2747d3605f 100644 --- a/packages/bootstrap-4/src/ArrayFieldItemTemplate/ArrayFieldItemTemplate.tsx +++ b/packages/bootstrap-4/src/ArrayFieldItemTemplate/ArrayFieldItemTemplate.tsx @@ -1,9 +1,18 @@ import React, { CSSProperties } from "react"; import Row from "react-bootstrap/Row"; import Col from "react-bootstrap/Col"; -import { ArrayFieldTemplateItemType } from "@rjsf/utils"; +import { + ArrayFieldTemplateItemType, + FormContextType, + RJSFSchema, + StrictRJSFSchema, +} from "@rjsf/utils"; -const ArrayFieldItemTemplate = (props: ArrayFieldTemplateItemType) => { +export default function ArrayFieldItemTemplate< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>(props: ArrayFieldTemplateItemType) { const { children, disabled, @@ -75,6 +84,4 @@ const ArrayFieldItemTemplate = (props: ArrayFieldTemplateItemType) => { ); -}; - -export default ArrayFieldItemTemplate; +} diff --git a/packages/bootstrap-4/src/ArrayFieldTemplate/ArrayFieldTemplate.tsx b/packages/bootstrap-4/src/ArrayFieldTemplate/ArrayFieldTemplate.tsx index 439298f8ab..6dcf85740a 100644 --- a/packages/bootstrap-4/src/ArrayFieldTemplate/ArrayFieldTemplate.tsx +++ b/packages/bootstrap-4/src/ArrayFieldTemplate/ArrayFieldTemplate.tsx @@ -5,11 +5,18 @@ import Container from "react-bootstrap/Container"; import { ArrayFieldTemplateItemType, ArrayFieldTemplateProps, + FormContextType, getTemplate, getUiOptions, + RJSFSchema, + StrictRJSFSchema, } from "@rjsf/utils"; -const ArrayFieldTemplate = (props: ArrayFieldTemplateProps) => { +export default function ArrayFieldTemplate< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>(props: ArrayFieldTemplateProps) { const { canAdd, disabled, @@ -23,23 +30,24 @@ const ArrayFieldTemplate = (props: ArrayFieldTemplateProps) => { schema, title, } = props; - const uiOptions = getUiOptions(uiSchema); - const ArrayFieldDescriptionTemplate = - getTemplate<"ArrayFieldDescriptionTemplate">( - "ArrayFieldDescriptionTemplate", - registry, - uiOptions - ); - const ArrayFieldItemTemplate = getTemplate<"ArrayFieldItemTemplate">( + const uiOptions = getUiOptions(uiSchema); + const ArrayFieldDescriptionTemplate = getTemplate< + "ArrayFieldDescriptionTemplate", + T, + S, + F + >("ArrayFieldDescriptionTemplate", registry, uiOptions); + const ArrayFieldItemTemplate = getTemplate<"ArrayFieldItemTemplate", T, S, F>( "ArrayFieldItemTemplate", registry, uiOptions ); - const ArrayFieldTitleTemplate = getTemplate<"ArrayFieldTitleTemplate">( + const ArrayFieldTitleTemplate = getTemplate< "ArrayFieldTitleTemplate", - registry, - uiOptions - ); + T, + S, + F + >("ArrayFieldTitleTemplate", registry, uiOptions); // Button templates are not overridden in the uiSchema const { ButtonTemplates: { AddButton }, @@ -69,9 +77,14 @@ const ArrayFieldTemplate = (props: ArrayFieldTemplateProps) => { className="p-0 m-0" > {items && - items.map(({ key, ...itemProps }: ArrayFieldTemplateItemType) => ( - - ))} + items.map( + ({ + key, + ...itemProps + }: ArrayFieldTemplateItemType) => ( + + ) + )} {canAdd && ( @@ -93,6 +106,4 @@ const ArrayFieldTemplate = (props: ArrayFieldTemplateProps) => { ); -}; - -export default ArrayFieldTemplate; +} diff --git a/packages/bootstrap-4/src/BaseInputTemplate/BaseInputTemplate.tsx b/packages/bootstrap-4/src/BaseInputTemplate/BaseInputTemplate.tsx index 68699d050f..56d7ecbdef 100644 --- a/packages/bootstrap-4/src/BaseInputTemplate/BaseInputTemplate.tsx +++ b/packages/bootstrap-4/src/BaseInputTemplate/BaseInputTemplate.tsx @@ -1,8 +1,18 @@ import React from "react"; import Form from "react-bootstrap/Form"; -import { getInputProps, WidgetProps } from "@rjsf/utils"; +import { + FormContextType, + getInputProps, + RJSFSchema, + StrictRJSFSchema, + WidgetProps, +} from "@rjsf/utils"; -const BaseInputTemplate = ({ +export default function BaseInputTemplate< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>({ id, placeholder, required, @@ -19,8 +29,11 @@ const BaseInputTemplate = ({ rawErrors = [], children, extraProps, -}: WidgetProps) => { - const inputProps = { ...extraProps, ...getInputProps(schema, type, options) }; +}: WidgetProps) { + const inputProps = { + ...extraProps, + ...getInputProps(schema, type, options), + }; const _onChange = ({ target: { value }, }: React.ChangeEvent) => @@ -62,6 +75,4 @@ const BaseInputTemplate = ({ ) : null} ); -}; - -export default BaseInputTemplate; +} diff --git a/packages/bootstrap-4/src/CheckboxWidget/CheckboxWidget.tsx b/packages/bootstrap-4/src/CheckboxWidget/CheckboxWidget.tsx index 4be1594787..74fec64cce 100644 --- a/packages/bootstrap-4/src/CheckboxWidget/CheckboxWidget.tsx +++ b/packages/bootstrap-4/src/CheckboxWidget/CheckboxWidget.tsx @@ -1,9 +1,18 @@ import React from "react"; - -import { WidgetProps, schemaRequiresTrueValue } from "@rjsf/utils"; +import { + WidgetProps, + schemaRequiresTrueValue, + StrictRJSFSchema, + RJSFSchema, + FormContextType, +} from "@rjsf/utils"; import Form from "react-bootstrap/Form"; -const CheckboxWidget = (props: WidgetProps) => { +export default function CheckboxWidget< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>(props: WidgetProps) { const { id, value, @@ -19,7 +28,7 @@ const CheckboxWidget = (props: WidgetProps) => { // Because an unchecked checkbox will cause html5 validation to fail, only add // the "required" attribute if the field value must be "true", due to the // "const" or "enum" keywords - const required = schemaRequiresTrueValue(schema); + const required = schemaRequiresTrueValue(schema); const _onChange = ({ target: { checked }, @@ -51,6 +60,4 @@ const CheckboxWidget = (props: WidgetProps) => { /> ); -}; - -export default CheckboxWidget; +} diff --git a/packages/bootstrap-4/src/CheckboxesWidget/CheckboxesWidget.tsx b/packages/bootstrap-4/src/CheckboxesWidget/CheckboxesWidget.tsx index 71646084ed..38db6f7e02 100644 --- a/packages/bootstrap-4/src/CheckboxesWidget/CheckboxesWidget.tsx +++ b/packages/bootstrap-4/src/CheckboxesWidget/CheckboxesWidget.tsx @@ -1,6 +1,11 @@ import React from "react"; import Form from "react-bootstrap/Form"; -import { WidgetProps } from "@rjsf/utils"; +import { + FormContextType, + RJSFSchema, + StrictRJSFSchema, + WidgetProps, +} from "@rjsf/utils"; const selectValue = (value: any, selected: any, all: any) => { const at = all.indexOf(value); @@ -15,7 +20,11 @@ const deselectValue = (value: any, selected: any) => { return selected.filter((v: any) => v !== value); }; -const CheckboxesWidget = ({ +export default function CheckboxesWidget< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>({ id, disabled, options, @@ -26,7 +35,7 @@ const CheckboxesWidget = ({ onChange, onBlur, onFocus, -}: WidgetProps) => { +}: WidgetProps) { const { enumOptions, enumDisabled, inline } = options; const _onChange = @@ -78,6 +87,4 @@ const CheckboxesWidget = ({ })} ); -}; - -export default CheckboxesWidget; +} diff --git a/packages/bootstrap-4/src/DescriptionField/DescriptionField.tsx b/packages/bootstrap-4/src/DescriptionField/DescriptionField.tsx index 1e6e0eccba..bb58a3bad1 100644 --- a/packages/bootstrap-4/src/DescriptionField/DescriptionField.tsx +++ b/packages/bootstrap-4/src/DescriptionField/DescriptionField.tsx @@ -1,7 +1,16 @@ import React from "react"; -import { DescriptionFieldProps } from "@rjsf/utils"; +import { + DescriptionFieldProps, + FormContextType, + RJSFSchema, + StrictRJSFSchema, +} from "@rjsf/utils"; -const DescriptionField = ({ id, description }: DescriptionFieldProps) => { +export default function DescriptionField< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>({ id, description }: DescriptionFieldProps) { if (description) { return (
@@ -13,6 +22,4 @@ const DescriptionField = ({ id, description }: DescriptionFieldProps) => { } return null; -}; - -export default DescriptionField; +} diff --git a/packages/bootstrap-4/src/ErrorList/ErrorList.tsx b/packages/bootstrap-4/src/ErrorList/ErrorList.tsx index 61dd663125..5c87b90221 100644 --- a/packages/bootstrap-4/src/ErrorList/ErrorList.tsx +++ b/packages/bootstrap-4/src/ErrorList/ErrorList.tsx @@ -3,23 +3,32 @@ import React from "react"; import Card from "react-bootstrap/Card"; import ListGroup from "react-bootstrap/ListGroup"; -import { ErrorListProps } from "@rjsf/utils"; +import { + ErrorListProps, + FormContextType, + RJSFSchema, + StrictRJSFSchema, +} from "@rjsf/utils"; -const ErrorList = ({ errors }: ErrorListProps) => ( - - Errors - - - {errors.map((error, i: number) => { - return ( - - {error.stack} - - ); - })} - - - -); - -export default ErrorList; +export default function ErrorList< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>({ errors }: ErrorListProps) { + return ( + + Errors + + + {errors.map((error, i: number) => { + return ( + + {error.stack} + + ); + })} + + + + ); +} diff --git a/packages/bootstrap-4/src/FieldErrorTemplate/FieldErrorTemplate.tsx b/packages/bootstrap-4/src/FieldErrorTemplate/FieldErrorTemplate.tsx index f1709ddaf5..5e088f5737 100644 --- a/packages/bootstrap-4/src/FieldErrorTemplate/FieldErrorTemplate.tsx +++ b/packages/bootstrap-4/src/FieldErrorTemplate/FieldErrorTemplate.tsx @@ -1,12 +1,21 @@ import React from "react"; -import { FieldErrorProps } from "@rjsf/utils"; +import { + FieldErrorProps, + FormContextType, + RJSFSchema, + StrictRJSFSchema, +} from "@rjsf/utils"; import ListGroup from "react-bootstrap/ListGroup"; /** The `FieldErrorTemplate` component renders the errors local to the particular field * * @param props - The `FieldErrorProps` for the errors being rendered */ -export default function FieldErrorTemplate(props: FieldErrorProps) { +export default function FieldErrorTemplate< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>(props: FieldErrorProps) { const { errors = [], idSchema } = props; if (errors.length === 0) { return null; diff --git a/packages/bootstrap-4/src/FieldHelpTemplate/FieldHelpTemplate.tsx b/packages/bootstrap-4/src/FieldHelpTemplate/FieldHelpTemplate.tsx index 2719231888..a67e836218 100644 --- a/packages/bootstrap-4/src/FieldHelpTemplate/FieldHelpTemplate.tsx +++ b/packages/bootstrap-4/src/FieldHelpTemplate/FieldHelpTemplate.tsx @@ -1,12 +1,21 @@ import React from "react"; -import { FieldHelpProps } from "@rjsf/utils"; +import { + FieldHelpProps, + FormContextType, + RJSFSchema, + StrictRJSFSchema, +} from "@rjsf/utils"; import Form from "react-bootstrap/Form"; /** The `FieldHelpTemplate` component renders any help desired for a field * * @param props - The `FieldHelpProps` to be rendered */ -export default function FieldHelpTemplate(props: FieldHelpProps) { +export default function FieldHelpTemplate< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>(props: FieldHelpProps) { const { idSchema, help, hasErrors } = props; if (!help) { return null; diff --git a/packages/bootstrap-4/src/FieldTemplate/FieldTemplate.tsx b/packages/bootstrap-4/src/FieldTemplate/FieldTemplate.tsx index ace72557d1..8af007dfbf 100644 --- a/packages/bootstrap-4/src/FieldTemplate/FieldTemplate.tsx +++ b/packages/bootstrap-4/src/FieldTemplate/FieldTemplate.tsx @@ -1,8 +1,19 @@ import React from "react"; -import { FieldTemplateProps, getTemplate, getUiOptions } from "@rjsf/utils"; +import { + FieldTemplateProps, + FormContextType, + getTemplate, + getUiOptions, + RJSFSchema, + StrictRJSFSchema, +} from "@rjsf/utils"; import Form from "react-bootstrap/Form"; -const FieldTemplate = ({ +export default function FieldTemplate< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>({ id, children, displayLabel, @@ -21,13 +32,14 @@ const FieldTemplate = ({ schema, uiSchema, registry, -}: FieldTemplateProps) => { +}: FieldTemplateProps) { const uiOptions = getUiOptions(uiSchema); - const WrapIfAdditionalTemplate = getTemplate<"WrapIfAdditionalTemplate">( + const WrapIfAdditionalTemplate = getTemplate< "WrapIfAdditionalTemplate", - registry, - uiOptions - ); + T, + S, + F + >("WrapIfAdditionalTemplate", registry, uiOptions); if (hidden) { return
{children}
; } @@ -68,6 +80,4 @@ const FieldTemplate = ({ ); -}; - -export default FieldTemplate; +} diff --git a/packages/bootstrap-4/src/FileWidget/FileWidget.tsx b/packages/bootstrap-4/src/FileWidget/FileWidget.tsx index 4bd934b4bb..cdedf3891e 100644 --- a/packages/bootstrap-4/src/FileWidget/FileWidget.tsx +++ b/packages/bootstrap-4/src/FileWidget/FileWidget.tsx @@ -1,14 +1,22 @@ import React from "react"; -import { getTemplate, WidgetProps } from "@rjsf/utils"; +import { + FormContextType, + getTemplate, + RJSFSchema, + StrictRJSFSchema, + WidgetProps, +} from "@rjsf/utils"; -const FileWidget = (props: WidgetProps) => { +export default function FileWidget< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>(props: WidgetProps) { const { options, registry } = props; - const BaseInputTemplate = getTemplate<"BaseInputTemplate">( + const BaseInputTemplate = getTemplate<"BaseInputTemplate", T, S, F>( "BaseInputTemplate", registry, options ); return ; -}; - -export default FileWidget; +} diff --git a/packages/bootstrap-4/src/Form/Form.tsx b/packages/bootstrap-4/src/Form/Form.tsx index e193619249..81d8f92be4 100644 --- a/packages/bootstrap-4/src/Form/Form.tsx +++ b/packages/bootstrap-4/src/Form/Form.tsx @@ -1,7 +1,15 @@ -import { withTheme, FormProps } from "@rjsf/core"; +import { ComponentType } from "react"; -import Theme from "../Theme"; +import { withTheme, FormProps } from "@rjsf/core"; +import { generateTheme } from "../Theme"; +import { FormContextType, RJSFSchema, StrictRJSFSchema } from "@rjsf/utils"; -const Form: React.ComponentType = withTheme(Theme); +export function generateForm< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>(): ComponentType> { + return withTheme(generateTheme()); +} -export default Form; +export default generateForm(); diff --git a/packages/bootstrap-4/src/IconButton/IconButton.tsx b/packages/bootstrap-4/src/IconButton/IconButton.tsx index e76a07b7a0..07dec2fde9 100644 --- a/packages/bootstrap-4/src/IconButton/IconButton.tsx +++ b/packages/bootstrap-4/src/IconButton/IconButton.tsx @@ -1,11 +1,20 @@ import React from "react"; -import { IconButtonProps } from "@rjsf/utils"; +import { + FormContextType, + IconButtonProps, + RJSFSchema, + StrictRJSFSchema, +} from "@rjsf/utils"; import Button, { ButtonProps } from "react-bootstrap/Button"; import { IoIosRemove } from "@react-icons/all-files/io/IoIosRemove"; import { AiOutlineArrowUp } from "@react-icons/all-files/ai/AiOutlineArrowUp"; import { AiOutlineArrowDown } from "@react-icons/all-files/ai/AiOutlineArrowDown"; -const IconButton = (props: IconButtonProps & ButtonProps) => { +export default function IconButton< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>(props: IconButtonProps & ButtonProps) { const { icon, iconType, className, uiSchema, registry, ...otherProps } = props; return ( @@ -18,21 +27,31 @@ const IconButton = (props: IconButtonProps & ButtonProps) => { {icon} ); -}; - -export default IconButton; +} -export function MoveDownButton(props: IconButtonProps) { +export function MoveDownButton< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>(props: IconButtonProps) { return ( } /> ); } -export function MoveUpButton(props: IconButtonProps) { +export function MoveUpButton< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>(props: IconButtonProps) { return } />; } -export function RemoveButton(props: IconButtonProps) { +export function RemoveButton< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>(props: IconButtonProps) { return ( ({ description, title, properties, @@ -24,18 +31,19 @@ const ObjectFieldTemplate = ({ disabled, readonly, registry, -}: ObjectFieldTemplateProps) => { - const uiOptions = getUiOptions(uiSchema); - const TitleFieldTemplate = getTemplate<"TitleFieldTemplate">( +}: ObjectFieldTemplateProps) { + const uiOptions = getUiOptions(uiSchema); + const TitleFieldTemplate = getTemplate<"TitleFieldTemplate", T, S, F>( "TitleFieldTemplate", registry, uiOptions ); - const DescriptionFieldTemplate = getTemplate<"DescriptionFieldTemplate">( + const DescriptionFieldTemplate = getTemplate< "DescriptionFieldTemplate", - registry, - uiOptions - ); + T, + S, + F + >("DescriptionFieldTemplate", registry, uiOptions); // Button templates are not overridden in the uiSchema const { ButtonTemplates: { AddButton }, @@ -87,6 +95,4 @@ const ObjectFieldTemplate = ({ ); -}; - -export default ObjectFieldTemplate; +} diff --git a/packages/bootstrap-4/src/RadioWidget/RadioWidget.tsx b/packages/bootstrap-4/src/RadioWidget/RadioWidget.tsx index 715a66e1d1..ba4b259ab0 100644 --- a/packages/bootstrap-4/src/RadioWidget/RadioWidget.tsx +++ b/packages/bootstrap-4/src/RadioWidget/RadioWidget.tsx @@ -2,9 +2,18 @@ import React from "react"; import Form from "react-bootstrap/Form"; -import { WidgetProps } from "@rjsf/utils"; +import { + FormContextType, + RJSFSchema, + StrictRJSFSchema, + WidgetProps, +} from "@rjsf/utils"; -const RadioWidget = ({ +export default function RadioWidget< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>({ id, schema, options, @@ -15,7 +24,7 @@ const RadioWidget = ({ onChange, onBlur, onFocus, -}: WidgetProps) => { +}: WidgetProps) { const { enumOptions, enumDisabled } = options; const _onChange = ({ @@ -60,6 +69,4 @@ const RadioWidget = ({ })} ); -}; - -export default RadioWidget; +} diff --git a/packages/bootstrap-4/src/RangeWidget/RangeWidget.tsx b/packages/bootstrap-4/src/RangeWidget/RangeWidget.tsx index f75d3756c9..3611a38b7d 100644 --- a/packages/bootstrap-4/src/RangeWidget/RangeWidget.tsx +++ b/packages/bootstrap-4/src/RangeWidget/RangeWidget.tsx @@ -1,9 +1,19 @@ import React from "react"; -import { getTemplate, WidgetProps } from "@rjsf/utils"; +import { + FormContextType, + getTemplate, + RJSFSchema, + StrictRJSFSchema, + WidgetProps, +} from "@rjsf/utils"; -const RangeWidget = (props: WidgetProps) => { +export default function RangeWidget< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>(props: WidgetProps) { const { value, label, options, registry } = props; - const BaseInputTemplate = getTemplate<"BaseInputTemplate">( + const BaseInputTemplate = getTemplate<"BaseInputTemplate", T, S, F>( "BaseInputTemplate", registry, options @@ -13,6 +23,4 @@ const RangeWidget = (props: WidgetProps) => { {value} ); -}; - -export default RangeWidget; +} diff --git a/packages/bootstrap-4/src/SelectWidget/SelectWidget.tsx b/packages/bootstrap-4/src/SelectWidget/SelectWidget.tsx index 07864f0e6d..0bd033e3cb 100644 --- a/packages/bootstrap-4/src/SelectWidget/SelectWidget.tsx +++ b/packages/bootstrap-4/src/SelectWidget/SelectWidget.tsx @@ -2,9 +2,19 @@ import React from "react"; import Form from "react-bootstrap/Form"; -import { processSelectValue, WidgetProps } from "@rjsf/utils"; +import { + FormContextType, + processSelectValue, + RJSFSchema, + StrictRJSFSchema, + WidgetProps, +} from "@rjsf/utils"; -const SelectWidget = ({ +export default function SelectWidget< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>({ schema, id, options, @@ -19,7 +29,7 @@ const SelectWidget = ({ onFocus, placeholder, rawErrors = [], -}: WidgetProps) => { +}: WidgetProps) { const { enumOptions, enumDisabled } = options; const emptyValue = multiple ? [] : ""; @@ -54,19 +64,19 @@ const SelectWidget = ({ onBlur && ((event: React.FocusEvent) => { const newValue = getValue(event, multiple); - onBlur(id, processSelectValue(schema, newValue, options)); + onBlur(id, processSelectValue(schema, newValue, options)); }) } onFocus={ onFocus && ((event: React.FocusEvent) => { const newValue = getValue(event, multiple); - onFocus(id, processSelectValue(schema, newValue, options)); + onFocus(id, processSelectValue(schema, newValue, options)); }) } onChange={(event: React.ChangeEvent) => { const newValue = getValue(event, multiple); - onChange(processSelectValue(schema, newValue, options)); + onChange(processSelectValue(schema, newValue, options)); }} > {!multiple && schema.default === undefined && ( @@ -84,6 +94,4 @@ const SelectWidget = ({ })} ); -}; - -export default SelectWidget; +} diff --git a/packages/bootstrap-4/src/SubmitButton/SubmitButton.tsx b/packages/bootstrap-4/src/SubmitButton/SubmitButton.tsx index fc88cc93f0..d08034c814 100644 --- a/packages/bootstrap-4/src/SubmitButton/SubmitButton.tsx +++ b/packages/bootstrap-4/src/SubmitButton/SubmitButton.tsx @@ -1,13 +1,23 @@ import React from "react"; import Button from "react-bootstrap/Button"; -import { getSubmitButtonOptions, SubmitButtonProps } from "@rjsf/utils"; +import { + FormContextType, + getSubmitButtonOptions, + RJSFSchema, + StrictRJSFSchema, + SubmitButtonProps, +} from "@rjsf/utils"; -const SubmitButton: React.ComponentType = (props) => { +export default function SubmitButton< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>(props: SubmitButtonProps) { const { submitText, norender, props: submitButtonProps, - } = getSubmitButtonOptions(props.uiSchema); + } = getSubmitButtonOptions(props.uiSchema); if (norender) { return null; } @@ -18,6 +28,4 @@ const SubmitButton: React.ComponentType = (props) => {
); -}; - -export default SubmitButton; +} diff --git a/packages/bootstrap-4/src/Templates/Templates.ts b/packages/bootstrap-4/src/Templates/Templates.ts index e8eef55a09..96f9ad9dbe 100644 --- a/packages/bootstrap-4/src/Templates/Templates.ts +++ b/packages/bootstrap-4/src/Templates/Templates.ts @@ -12,24 +12,38 @@ import ObjectFieldTemplate from "../ObjectFieldTemplate"; import SubmitButton from "../SubmitButton"; import TitleField from "../TitleField"; import WrapIfAdditionalTemplate from "../WrapIfAdditionalTemplate"; +import { + FormContextType, + RJSFSchema, + StrictRJSFSchema, + TemplatesType, +} from "@rjsf/utils"; -export default { - ArrayFieldItemTemplate, - ArrayFieldTemplate, - BaseInputTemplate, - ButtonTemplates: { - AddButton, - MoveDownButton, - MoveUpButton, - RemoveButton, - SubmitButton, - }, - DescriptionFieldTemplate: DescriptionField, - ErrorListTemplate: ErrorList, - FieldErrorTemplate, - FieldHelpTemplate, - FieldTemplate, - ObjectFieldTemplate, - TitleFieldTemplate: TitleField, - WrapIfAdditionalTemplate, -}; +export function generateTemplates< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>(): Partial> { + return { + ArrayFieldItemTemplate, + ArrayFieldTemplate, + BaseInputTemplate, + ButtonTemplates: { + AddButton, + MoveDownButton, + MoveUpButton, + RemoveButton, + SubmitButton, + }, + DescriptionFieldTemplate: DescriptionField, + ErrorListTemplate: ErrorList, + FieldErrorTemplate, + FieldHelpTemplate, + FieldTemplate, + ObjectFieldTemplate, + TitleFieldTemplate: TitleField, + WrapIfAdditionalTemplate, + }; +} + +export default generateTemplates(); diff --git a/packages/bootstrap-4/src/TextareaWidget/TextareaWidget.tsx b/packages/bootstrap-4/src/TextareaWidget/TextareaWidget.tsx index afb2c98daf..891879efd5 100644 --- a/packages/bootstrap-4/src/TextareaWidget/TextareaWidget.tsx +++ b/packages/bootstrap-4/src/TextareaWidget/TextareaWidget.tsx @@ -1,14 +1,27 @@ import React from "react"; -import { WidgetProps } from "@rjsf/utils"; +import { + FormContextType, + RJSFSchema, + StrictRJSFSchema, + WidgetProps, +} from "@rjsf/utils"; import FormControl from "react-bootstrap/FormControl"; import InputGroup from "react-bootstrap/InputGroup"; -type CustomWidgetProps = WidgetProps & { +type CustomWidgetProps< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +> = WidgetProps & { options: any; }; -const TextareaWidget = ({ +export default function TextareaWidget< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>({ id, placeholder, value, @@ -20,7 +33,7 @@ const TextareaWidget = ({ onFocus, onChange, options, -}: CustomWidgetProps) => { +}: CustomWidgetProps) { const _onChange = ({ target: { value }, }: React.ChangeEvent) => @@ -51,6 +64,4 @@ const TextareaWidget = ({ /> ); -}; - -export default TextareaWidget; +} diff --git a/packages/bootstrap-4/src/Theme/Theme.tsx b/packages/bootstrap-4/src/Theme/Theme.tsx index ecfcdd5720..ec9d319569 100644 --- a/packages/bootstrap-4/src/Theme/Theme.tsx +++ b/packages/bootstrap-4/src/Theme/Theme.tsx @@ -1,11 +1,18 @@ import { ThemeProps } from "@rjsf/core"; -import Templates from "../Templates"; -import Widgets from "../Widgets"; +import { generateTemplates } from "../Templates"; +import { generateWidgets } from "../Widgets"; +import { FormContextType, RJSFSchema, StrictRJSFSchema } from "@rjsf/utils"; -const Theme: ThemeProps = { - templates: Templates, - widgets: Widgets, -}; +export function generateTheme< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>(): ThemeProps { + return { + templates: generateTemplates(), + widgets: generateWidgets(), + }; +} -export default Theme; +export default generateTheme(); diff --git a/packages/bootstrap-4/src/TitleField/TitleField.tsx b/packages/bootstrap-4/src/TitleField/TitleField.tsx index 4606e0d155..fdbbd742e6 100644 --- a/packages/bootstrap-4/src/TitleField/TitleField.tsx +++ b/packages/bootstrap-4/src/TitleField/TitleField.tsx @@ -1,13 +1,22 @@ import React from "react"; -import { TitleFieldProps } from "@rjsf/utils"; +import { + FormContextType, + getUiOptions, + RJSFSchema, + StrictRJSFSchema, + TitleFieldProps, +} from "@rjsf/utils"; -const TitleField = ({ id, title, uiSchema }: TitleFieldProps) => ( - <> +export default function TitleField< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>({ id, title, uiSchema }: TitleFieldProps) { + const uiOptions = getUiOptions(uiSchema); + return (
-
{(uiSchema && uiSchema["ui:title"]) || title}
+
{uiOptions.title || title}

- -); - -export default TitleField; + ); +} diff --git a/packages/bootstrap-4/src/Widgets/Widgets.ts b/packages/bootstrap-4/src/Widgets/Widgets.ts index 543a05ec34..35003fb41d 100644 --- a/packages/bootstrap-4/src/Widgets/Widgets.ts +++ b/packages/bootstrap-4/src/Widgets/Widgets.ts @@ -5,13 +5,27 @@ import RangeWidget from "../RangeWidget/RangeWidget"; import SelectWidget from "../SelectWidget/SelectWidget"; import TextareaWidget from "../TextareaWidget/TextareaWidget"; import FileWidget from "../FileWidget/FileWidget"; +import { + FormContextType, + RegistryWidgetsType, + RJSFSchema, + StrictRJSFSchema, +} from "@rjsf/utils"; -export default { - CheckboxWidget, - CheckboxesWidget, - RadioWidget, - RangeWidget, - SelectWidget, - TextareaWidget, - FileWidget, -}; +export function generateWidgets< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>(): RegistryWidgetsType { + return { + CheckboxWidget, + CheckboxesWidget, + RadioWidget, + RangeWidget, + SelectWidget, + TextareaWidget, + FileWidget, + }; +} + +export default generateWidgets(); diff --git a/packages/bootstrap-4/src/WrapIfAdditionalTemplate/WrapIfAdditionalTemplate.tsx b/packages/bootstrap-4/src/WrapIfAdditionalTemplate/WrapIfAdditionalTemplate.tsx index 3c9dff0bbc..910f9600b1 100644 --- a/packages/bootstrap-4/src/WrapIfAdditionalTemplate/WrapIfAdditionalTemplate.tsx +++ b/packages/bootstrap-4/src/WrapIfAdditionalTemplate/WrapIfAdditionalTemplate.tsx @@ -2,6 +2,9 @@ import React from "react"; import { ADDITIONAL_PROPERTY_FLAG, + FormContextType, + RJSFSchema, + StrictRJSFSchema, WrapIfAdditionalTemplateProps, } from "@rjsf/utils"; @@ -9,7 +12,11 @@ import Row from "react-bootstrap/Row"; import Col from "react-bootstrap/Col"; import Form from "react-bootstrap/Form"; -const WrapIfAdditionalTemplate = ({ +export default function WrapIfAdditionalTemplate< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>({ classNames, children, disabled, @@ -22,7 +29,7 @@ const WrapIfAdditionalTemplate = ({ schema, uiSchema, registry, -}: WrapIfAdditionalTemplateProps) => { +}: WrapIfAdditionalTemplateProps) { // Button templates are not overridden in the uiSchema const { RemoveButton } = registry.templates.ButtonTemplates; const keyLabel = `${label} Key`; // i18n ? @@ -65,6 +72,4 @@ const WrapIfAdditionalTemplate = ({ ); -}; - -export default WrapIfAdditionalTemplate; +} diff --git a/packages/bootstrap-4/src/index.ts b/packages/bootstrap-4/src/index.ts index d537d73876..5d0c9a57b8 100644 --- a/packages/bootstrap-4/src/index.ts +++ b/packages/bootstrap-4/src/index.ts @@ -1,8 +1,8 @@ import Form from "./Form/Form"; -export { default as Form } from "./Form"; -export { default as Templates } from "./Templates"; -export { default as Theme } from "./Theme"; -export { default as Widgets } from "./Widgets"; +export { default as Form, generateForm } from "./Form"; +export { default as Templates, generateTemplates } from "./Templates"; +export { default as Theme, generateTheme } from "./Theme"; +export { default as Widgets, generateWidgets } from "./Widgets"; export default Form;