From fdc29415de87cf0d5e5204a7a5e9a034869106c3 Mon Sep 17 00:00:00 2001
From: Heath C <51679588+heath-freenome@users.noreply.github.com>
Date: Wed, 4 Jan 2023 10:36:34 -0800
Subject: [PATCH] fix: Add generic type support to the antd theme (#3338)
partially fix: #3072 by adding generic type support to the `antd` theme as follows:
- In `@rjsf/antd` added generic type support as follows:
- Updated all of the template and widget components to add the `T = any`, `S extends StrictRJSFSchema = RJSFSchema` and `F extends FormContextType = any` generics on the function definitions, types and utility function calls
- Converted the three components that used the `withConfigConsumer()` HOC to instead use the `` component to generate the prefixCls
- Added a `generateForm()` function to main `index.ts`, exporting it and exporting the default `Form` as a call to `generateForm()`
- Added a `generateTemplates()` function to the `Templates.tsx`, exporting it and exporting the default `Templates` as a call to `generateTemplates()`
- Added a `generateTheme()` function to the main `index.ts`, exporting it and exporting the default `Theme` as a call to `generateTheme()`
- Added a `generateWidgets()` function to the `Widgets.tsx`, exporting it and exporting the default `Widgets` as a call to `generateWidgets()`
- Updated the main `index.ts` for the theme to also export the `generateTemplates()` and `generateWidgets()` functions
- Updated the `CHANGELOG.md` accordingly
---
CHANGELOG.md | 2 +
packages/antd/src/index.ts | 34 ++-
.../ArrayFieldItemTemplate/index.tsx | 48 ++--
.../templates/ArrayFieldTemplate/index.tsx | 207 +++++++++--------
.../src/templates/BaseInputTemplate/index.tsx | 56 +++--
.../src/templates/DescriptionField/index.tsx | 22 +-
.../antd/src/templates/ErrorList/index.tsx | 22 +-
.../templates/FieldErrorTemplate/index.tsx | 13 +-
.../src/templates/FieldTemplate/index.tsx | 85 ++++---
.../antd/src/templates/IconButton/index.tsx | 46 +++-
.../templates/ObjectFieldTemplate/index.tsx | 211 ++++++++++--------
.../antd/src/templates/SubmitButton/index.tsx | 18 +-
.../antd/src/templates/TitleField/index.tsx | 81 +++----
.../WrapIfAdditionalTemplate/index.tsx | 53 +++--
packages/antd/src/templates/index.ts | 55 +++--
.../src/widgets/AltDateTimeWidget/index.tsx | 17 +-
.../antd/src/widgets/AltDateWidget/index.tsx | 62 ++---
.../antd/src/widgets/CheckboxWidget/index.tsx | 48 ++--
.../src/widgets/CheckboxesWidget/index.tsx | 27 ++-
.../antd/src/widgets/DateTimeWidget/index.tsx | 46 ++--
.../antd/src/widgets/DateWidget/index.tsx | 46 ++--
.../antd/src/widgets/PasswordWidget/index.tsx | 47 ++--
.../antd/src/widgets/RadioWidget/index.tsx | 27 ++-
.../antd/src/widgets/RangeWidget/index.tsx | 53 +++--
.../antd/src/widgets/SelectWidget/index.tsx | 40 ++--
.../antd/src/widgets/TextareaWidget/index.tsx | 26 ++-
packages/antd/src/widgets/index.ts | 41 ++--
27 files changed, 893 insertions(+), 540 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6f1f079b77..1e23f72906 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -20,6 +20,8 @@ should change the heading of the (upcoming) version to include a major version b
## @rjsf/antd
- 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 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)
+- Updated the use of the deprecated `withConfigConsumer` with the `ConfigConsumer` component instead, fixing [#3336](https://github.com/rjsf-team/react-jsonschema-form/issues/3336)
## @rjsf/bootstrap-4
- 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/antd/src/index.ts b/packages/antd/src/index.ts
index 1fc501f1c7..f5e5953104 100644
--- a/packages/antd/src/index.ts
+++ b/packages/antd/src/index.ts
@@ -1,15 +1,33 @@
+import { ComponentType } from "react";
+import { FormContextType, RJSFSchema, StrictRJSFSchema } from "@rjsf/utils";
import { FormProps, ThemeProps, withTheme } from "@rjsf/core";
-import Templates from "./templates";
-import Widgets from "./widgets";
+import Templates, { generateTemplates } from "./templates";
+import Widgets, { generateWidgets } from "./widgets";
-export { Templates, Widgets };
+export function generateTheme<
+ T = any,
+ S extends StrictRJSFSchema = RJSFSchema,
+ F extends FormContextType = any
+>(): ThemeProps {
+ return {
+ templates: generateTemplates(),
+ widgets: generateWidgets(),
+ };
+}
-export const Theme: ThemeProps = {
- templates: Templates,
- widgets: Widgets,
-};
+const Theme = generateTheme();
-export const Form: React.ComponentType = withTheme(Theme);
+export function generateForm<
+ T = any,
+ S extends StrictRJSFSchema = RJSFSchema,
+ F extends FormContextType = any
+>(): ComponentType> {
+ return withTheme(generateTheme());
+}
+
+const Form = generateForm();
+
+export { Form, Templates, Theme, Widgets, generateTemplates, generateWidgets };
export default Form;
diff --git a/packages/antd/src/templates/ArrayFieldItemTemplate/index.tsx b/packages/antd/src/templates/ArrayFieldItemTemplate/index.tsx
index 0f5dbe4aec..7f920acacd 100644
--- a/packages/antd/src/templates/ArrayFieldItemTemplate/index.tsx
+++ b/packages/antd/src/templates/ArrayFieldItemTemplate/index.tsx
@@ -1,8 +1,13 @@
import React from "react";
-import { ArrayFieldTemplateItemType } from "@rjsf/utils";
import Button from "antd/lib/button";
import Col from "antd/lib/col";
import Row from "antd/lib/row";
+import {
+ ArrayFieldTemplateItemType,
+ FormContextType,
+ RJSFSchema,
+ StrictRJSFSchema,
+} from "@rjsf/utils";
const BTN_GRP_STYLE = {
width: "100%",
@@ -12,20 +17,29 @@ const BTN_STYLE = {
width: "calc(100% / 3)",
};
-const ArrayFieldItemTemplate = ({
- children,
- disabled,
- hasMoveDown,
- hasMoveUp,
- hasRemove,
- hasToolbar,
- index,
- onDropIndexClick,
- onReorderClick,
- readonly,
- registry,
- uiSchema,
-}: ArrayFieldTemplateItemType) => {
+/** The `ArrayFieldItemTemplate` component is the template used to render an items of an array.
+ *
+ * @param props - The `ArrayFieldTemplateItemType` props for the component
+ */
+export default function ArrayFieldItemTemplate<
+ T = any,
+ S extends StrictRJSFSchema = RJSFSchema,
+ F extends FormContextType = any
+>(props: ArrayFieldTemplateItemType) {
+ const {
+ children,
+ disabled,
+ hasMoveDown,
+ hasMoveUp,
+ hasRemove,
+ hasToolbar,
+ index,
+ onDropIndexClick,
+ onReorderClick,
+ readonly,
+ registry,
+ uiSchema,
+ } = props;
const { MoveDownButton, MoveUpButton, RemoveButton } =
registry.templates.ButtonTemplates;
const { rowGutter = 24, toolbarAlign = "top" } = registry.formContext;
@@ -69,6 +83,4 @@ const ArrayFieldItemTemplate = ({
)}
);
-};
-
-export default ArrayFieldItemTemplate;
+}
diff --git a/packages/antd/src/templates/ArrayFieldTemplate/index.tsx b/packages/antd/src/templates/ArrayFieldTemplate/index.tsx
index 39793e20fa..18f77ecbb7 100644
--- a/packages/antd/src/templates/ArrayFieldTemplate/index.tsx
+++ b/packages/antd/src/templates/ArrayFieldTemplate/index.tsx
@@ -3,119 +3,144 @@ import {
getTemplate,
getUiOptions,
ArrayFieldTemplateProps,
+ ArrayFieldTemplateItemType,
+ FormContextType,
+ GenericObjectType,
+ RJSFSchema,
+ StrictRJSFSchema,
} from "@rjsf/utils";
import classNames from "classnames";
import Col from "antd/lib/col";
import Row from "antd/lib/row";
-import { withConfigConsumer } from "antd/lib/config-provider/context";
+import {
+ ConfigConsumer,
+ ConfigConsumerProps,
+} from "antd/lib/config-provider/context";
const DESCRIPTION_COL_STYLE = {
paddingBottom: "8px",
};
-// Add in the `prefixCls` element needed by the `withConfigConsumer` HOC
-export type AntdArrayFieldTemplateProps = ArrayFieldTemplateProps & {
- prefixCls: string;
-};
-
-const ArrayFieldTemplate = ({
- canAdd,
- className,
- disabled,
- formContext,
- idSchema,
- items,
- onAddClick,
- prefixCls,
- readonly,
- registry,
- required,
- schema,
- title,
- uiSchema,
-}: AntdArrayFieldTemplateProps) => {
- const uiOptions = getUiOptions(uiSchema);
- const ArrayFieldDescriptionTemplate = getTemplate(
- "ArrayFieldDescriptionTemplate",
+/** The `ArrayFieldTemplate` component is the template used to render all items in an array.
+ *
+ * @param props - The `ArrayFieldTemplateItemType` props for the component
+ */
+export default function ArrayFieldTemplate<
+ T = any,
+ S extends StrictRJSFSchema = RJSFSchema,
+ F extends FormContextType = any
+>(props: ArrayFieldTemplateProps) {
+ const {
+ canAdd,
+ className,
+ disabled,
+ formContext,
+ idSchema,
+ items,
+ onAddClick,
+ readonly,
registry,
- uiOptions
- );
- const ArrayFieldItemTemplate = getTemplate<"ArrayFieldItemTemplate">(
+ required,
+ schema,
+ title,
+ uiSchema,
+ } = props;
+ 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 },
} = registry.templates;
- const { labelAlign = "right", rowGutter = 24 } = formContext;
-
- const labelClsBasic = `${prefixCls}-item-label`;
- const labelColClassName = classNames(
- labelClsBasic,
- labelAlign === "left" && `${labelClsBasic}-left`
- // labelCol.className,
- );
+ const { labelAlign = "right", rowGutter = 24 } =
+ formContext as GenericObjectType;
return (
-
+
+ );
+ }}
+
);
-};
-
-export default withConfigConsumer({
- prefixCls: "form",
-})(ArrayFieldTemplate);
+}
diff --git a/packages/antd/src/templates/BaseInputTemplate/index.tsx b/packages/antd/src/templates/BaseInputTemplate/index.tsx
index a2f5453236..b4a686525c 100644
--- a/packages/antd/src/templates/BaseInputTemplate/index.tsx
+++ b/packages/antd/src/templates/BaseInputTemplate/index.tsx
@@ -1,28 +1,46 @@
import React from "react";
-import { getInputProps, WidgetProps } from "@rjsf/utils";
import Input from "antd/lib/input";
import InputNumber from "antd/lib/input-number";
+import {
+ getInputProps,
+ FormContextType,
+ RJSFSchema,
+ StrictRJSFSchema,
+ WidgetProps,
+ GenericObjectType,
+} from "@rjsf/utils";
const INPUT_STYLE = {
width: "100%",
};
-const BaseInputTemplate = ({
- disabled,
- formContext,
- id,
- onBlur,
- onChange,
- onFocus,
- options,
- placeholder,
- readonly,
- schema,
- value,
- type,
-}: WidgetProps) => {
- const inputProps = getInputProps(schema, type, options, false);
- const { readonlyAsDisabled = true } = formContext;
+/** The `BaseInputTemplate` is the template to use to render the basic `` component for the `core` theme.
+ * It is used as the template for rendering many of the based widgets that differ by `type` and callbacks only.
+ * It can be customized/overridden for other themes or individual implementations as needed.
+ *
+ * @param props - The `WidgetProps` for this template
+ */
+export default function BaseInputTemplate<
+ T = any,
+ S extends StrictRJSFSchema = RJSFSchema,
+ F extends FormContextType = any
+>(props: WidgetProps) {
+ const {
+ disabled,
+ formContext,
+ id,
+ onBlur,
+ onChange,
+ onFocus,
+ options,
+ placeholder,
+ readonly,
+ schema,
+ value,
+ type,
+ } = props;
+ const inputProps = getInputProps(schema, type, options, false);
+ const { readonlyAsDisabled = true } = formContext as GenericObjectType;
const handleNumberChange = (nextValue: number | null) => onChange(nextValue);
@@ -80,6 +98,4 @@ const BaseInputTemplate = ({
)}
>
);
-};
-
-export default BaseInputTemplate;
+}
diff --git a/packages/antd/src/templates/DescriptionField/index.tsx b/packages/antd/src/templates/DescriptionField/index.tsx
index 809adf3bea..601c4981f8 100644
--- a/packages/antd/src/templates/DescriptionField/index.tsx
+++ b/packages/antd/src/templates/DescriptionField/index.tsx
@@ -1,11 +1,23 @@
import React from "react";
-import { DescriptionFieldProps } from "@rjsf/utils";
+import {
+ DescriptionFieldProps,
+ FormContextType,
+ RJSFSchema,
+ StrictRJSFSchema,
+} from "@rjsf/utils";
-const DescriptionField = ({ description, id }: DescriptionFieldProps) => {
+/** The `DescriptionField` is the template to use to render the description of a field
+ *
+ * @param props - The `DescriptionFieldProps` for this component
+ */
+export default function DescriptionField<
+ T = any,
+ S extends StrictRJSFSchema = RJSFSchema,
+ F extends FormContextType = any
+>(props: DescriptionFieldProps) {
+ const { id, description } = props;
if (!description) {
return null;
}
return {description};
-};
-
-export default DescriptionField;
+}
diff --git a/packages/antd/src/templates/ErrorList/index.tsx b/packages/antd/src/templates/ErrorList/index.tsx
index 5cd62dc686..27d19c1334 100644
--- a/packages/antd/src/templates/ErrorList/index.tsx
+++ b/packages/antd/src/templates/ErrorList/index.tsx
@@ -1,12 +1,24 @@
import React from "react";
-import { ErrorListProps } from "@rjsf/utils";
-
import Alert from "antd/lib/alert";
import List from "antd/lib/list";
import Space from "antd/lib/space";
import ExclamationCircleOutlined from "@ant-design/icons/ExclamationCircleOutlined";
+import {
+ ErrorListProps,
+ FormContextType,
+ RJSFSchema,
+ StrictRJSFSchema,
+} from "@rjsf/utils";
-const ErrorList = ({ errors }: ErrorListProps) => {
+/** The `ErrorList` component is the template that renders the all the errors associated with the fields in the `Form`
+ *
+ * @param props - The `ErrorListProps` for this component
+ */
+export default function ErrorList<
+ T = any,
+ S extends StrictRJSFSchema = RJSFSchema,
+ F extends FormContextType = any
+>({ errors }: ErrorListProps) {
const renderErrors = () => (
{errors.map((error, index) => (
@@ -28,6 +40,4 @@ const ErrorList = ({ errors }: ErrorListProps) => {
type="error"
/>
);
-};
-
-export default ErrorList;
+}
diff --git a/packages/antd/src/templates/FieldErrorTemplate/index.tsx b/packages/antd/src/templates/FieldErrorTemplate/index.tsx
index e0854a7e26..a9d4904ea3 100644
--- a/packages/antd/src/templates/FieldErrorTemplate/index.tsx
+++ b/packages/antd/src/templates/FieldErrorTemplate/index.tsx
@@ -1,11 +1,20 @@
import React from "react";
-import { FieldErrorProps } from "@rjsf/utils";
+import {
+ FieldErrorProps,
+ FormContextType,
+ RJSFSchema,
+ StrictRJSFSchema,
+} from "@rjsf/utils";
/** 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/antd/src/templates/FieldTemplate/index.tsx b/packages/antd/src/templates/FieldTemplate/index.tsx
index 3d2d98fb92..b672734784 100644
--- a/packages/antd/src/templates/FieldTemplate/index.tsx
+++ b/packages/antd/src/templates/FieldTemplate/index.tsx
@@ -1,48 +1,65 @@
import React from "react";
-import { FieldTemplateProps } from "@rjsf/utils";
import Form from "antd/lib/form";
-
-import { getUiOptions, getTemplate } from "@rjsf/utils";
+import {
+ FieldTemplateProps,
+ FormContextType,
+ RJSFSchema,
+ StrictRJSFSchema,
+ getTemplate,
+ getUiOptions,
+ GenericObjectType,
+} from "@rjsf/utils";
const VERTICAL_LABEL_COL = { span: 24 };
const VERTICAL_WRAPPER_COL = { span: 24 };
-const FieldTemplate = ({
- children,
- classNames,
- description,
- disabled,
- displayLabel,
- errors,
- formContext,
- help,
- hidden,
- id,
- label,
- onDropPropertyClick,
- onKeyChange,
- rawErrors,
- rawDescription,
- rawHelp,
- readonly,
- registry,
- required,
- schema,
- uiSchema,
-}: FieldTemplateProps) => {
+/** The `FieldTemplate` component is the template used by `SchemaField` to render any field. It renders the field
+ * content, (label, description, children, errors and help) inside of a `WrapIfAdditional` component.
+ *
+ * @param props - The `FieldTemplateProps` for this component
+ */
+export default function FieldTemplate<
+ T = any,
+ S extends StrictRJSFSchema = RJSFSchema,
+ F extends FormContextType = any
+>(props: FieldTemplateProps) {
+ const {
+ children,
+ classNames,
+ description,
+ disabled,
+ displayLabel,
+ errors,
+ formContext,
+ help,
+ hidden,
+ id,
+ label,
+ onDropPropertyClick,
+ onKeyChange,
+ rawErrors,
+ rawDescription,
+ rawHelp,
+ readonly,
+ registry,
+ required,
+ schema,
+ uiSchema,
+ } = props;
const {
colon,
labelCol = VERTICAL_LABEL_COL,
wrapperCol = VERTICAL_WRAPPER_COL,
wrapperStyle,
- } = formContext;
+ } = formContext as GenericObjectType;
- const uiOptions = getUiOptions(uiSchema);
- const WrapIfAdditionalTemplate = getTemplate<"WrapIfAdditionalTemplate">(
+ const uiOptions = getUiOptions(uiSchema);
+ const WrapIfAdditionalTemplate = getTemplate<
"WrapIfAdditionalTemplate",
- registry,
- uiOptions
- );
+ T,
+ S,
+ F
+ >("WrapIfAdditionalTemplate", registry, uiOptions);
if (hidden) {
return {children}
;
@@ -83,6 +100,4 @@ const FieldTemplate = ({
)}
);
-};
-
-export default FieldTemplate;
+}
diff --git a/packages/antd/src/templates/IconButton/index.tsx b/packages/antd/src/templates/IconButton/index.tsx
index ec3d8a58b3..e3343ea642 100644
--- a/packages/antd/src/templates/IconButton/index.tsx
+++ b/packages/antd/src/templates/IconButton/index.tsx
@@ -1,15 +1,29 @@
import React from "react";
-import { IconButtonProps, getUiOptions } from "@rjsf/utils";
import Button, { ButtonProps, ButtonType } from "antd/lib/button";
import ArrowDownOutlined from "@ant-design/icons/ArrowDownOutlined";
import ArrowUpOutlined from "@ant-design/icons/ArrowUpOutlined";
import DeleteOutlined from "@ant-design/icons/DeleteOutlined";
import PlusCircleOutlined from "@ant-design/icons/PlusCircleOutlined";
+import {
+ getUiOptions,
+ FormContextType,
+ IconButtonProps,
+ RJSFSchema,
+ StrictRJSFSchema,
+} from "@rjsf/utils";
// The `type` for IconButtonProps collides with the `type` for `ButtonProps` so omit it to avoid Typescript issue
-export type AntdIconButtonProps = Omit;
+export type AntdIconButtonProps<
+ T = any,
+ S extends StrictRJSFSchema = RJSFSchema,
+ F extends FormContextType = any
+> = Omit, "type">;
-export default function IconButton(props: AntdIconButtonProps & ButtonProps) {
+export default function IconButton<
+ T = any,
+ S extends StrictRJSFSchema = RJSFSchema,
+ F extends FormContextType = any
+>(props: AntdIconButtonProps & ButtonProps) {
const {
iconType = "default",
icon,
@@ -20,7 +34,11 @@ export default function IconButton(props: AntdIconButtonProps & ButtonProps) {
return ;
}
-export function AddButton(props: AntdIconButtonProps) {
+export function AddButton<
+ T = any,
+ S extends StrictRJSFSchema = RJSFSchema,
+ F extends FormContextType = any
+>(props: AntdIconButtonProps) {
return (
(props: AntdIconButtonProps) {
return (
} />
);
}
-export function MoveUpButton(props: AntdIconButtonProps) {
+export function MoveUpButton<
+ T = any,
+ S extends StrictRJSFSchema = RJSFSchema,
+ F extends FormContextType = any
+>(props: AntdIconButtonProps) {
return } />;
}
-export function RemoveButton(props: AntdIconButtonProps) {
+export function RemoveButton<
+ T = any,
+ S extends StrictRJSFSchema = RJSFSchema,
+ F extends FormContextType = any
+>(props: AntdIconButtonProps) {
// The `block` prop is not part of the `IconButtonProps` defined in the template, so get it from the uiSchema instead
- const options = getUiOptions(props.uiSchema);
+ const options = getUiOptions(props.uiSchema);
return (
{
- const uiOptions = getUiOptions(uiSchema);
- const TitleFieldTemplate = getTemplate<"TitleFieldTemplate">(
+/** The `ObjectFieldTemplate` is the template to use to render all the inner properties of an object along with the
+ * title and description if available. If the object is expandable, then an `AddButton` is also rendered after all
+ * the properties.
+ *
+ * @param props - The `ObjectFieldTemplateProps` for this component
+ */
+export default function ObjectFieldTemplate<
+ T = any,
+ S extends StrictRJSFSchema = RJSFSchema,
+ F extends FormContextType = any
+>(props: ObjectFieldTemplateProps) {
+ const {
+ description,
+ disabled,
+ formContext,
+ formData,
+ idSchema,
+ onAddClick,
+ properties,
+ readonly,
+ required,
+ registry,
+ schema,
+ title,
+ uiSchema,
+ } = props;
+ 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 },
} = registry.templates;
- const { colSpan = 24, labelAlign = "right", rowGutter = 24 } = formContext;
-
- const labelClsBasic = `${prefixCls}-item-label`;
- const labelColClassName = classNames(
- labelClsBasic,
- labelAlign === "left" && `${labelClsBasic}-left`
- // labelCol.className,
- );
+ const {
+ colSpan = 24,
+ labelAlign = "right",
+ rowGutter = 24,
+ } = formContext as GenericObjectType;
- const findSchema = (element: ObjectFieldTemplatePropertyType): RJSFSchema =>
+ const findSchema = (element: ObjectFieldTemplatePropertyType): S =>
element.content.props.schema;
const findSchemaType = (element: ObjectFieldTemplatePropertyType) =>
@@ -74,7 +82,7 @@ const ObjectFieldTemplate = ({
const findUiSchema = (
element: ObjectFieldTemplatePropertyType
- ): UiSchema | undefined => element.content.props.uiSchema;
+ ): UiSchema | undefined => element.content.props.uiSchema;
const findUiSchemaField = (element: ObjectFieldTemplatePropertyType) =>
getUiOptions(findUiSchema(element)).field;
@@ -114,59 +122,70 @@ const ObjectFieldTemplate = ({
};
return (
-
-
- {(uiOptions.title || title) && (
-
-
-
- )}
- {(uiOptions.description || description) && (
-
-
-
- )}
- {properties
- .filter((e) => !e.hidden)
- .map((element: ObjectFieldTemplatePropertyType) => (
-
- {element.content}
-
- ))}
-
+
+ {(configProps: ConfigConsumerProps) => {
+ const { getPrefixCls } = configProps;
+ const prefixCls = getPrefixCls("form");
+ const labelClsBasic = `${prefixCls}-item-label`;
+ const labelColClassName = classNames(
+ labelClsBasic,
+ labelAlign === "left" && `${labelClsBasic}-left`
+ // labelCol.className,
+ );
- {canExpand(schema, uiSchema, formData) && (
-
-
-
-
-
-
-
- )}
-
- );
-};
+ return (
+
+
+ {(uiOptions.title || title) && (
+
+
+
+ )}
+ {(uiOptions.description || description) && (
+
+
+
+ )}
+ {properties
+ .filter((e) => !e.hidden)
+ .map((element: ObjectFieldTemplatePropertyType) => (
+
+ {element.content}
+
+ ))}
+
-export default withConfigConsumer({
- prefixCls: "form",
-})(ObjectFieldTemplate);
+ {canExpand(schema, uiSchema, formData) && (
+
+
+
+
+
+
+
+ )}
+
+ );
+ }}
+
+ );
+}
diff --git a/packages/antd/src/templates/SubmitButton/index.tsx b/packages/antd/src/templates/SubmitButton/index.tsx
index 3703882810..a34937befa 100644
--- a/packages/antd/src/templates/SubmitButton/index.tsx
+++ b/packages/antd/src/templates/SubmitButton/index.tsx
@@ -1,8 +1,20 @@
-import { getSubmitButtonOptions, SubmitButtonProps } from "@rjsf/utils";
import React from "react";
import Button, { ButtonType } from "antd/lib/button";
+import {
+ getSubmitButtonOptions,
+ FormContextType,
+ RJSFSchema,
+ StrictRJSFSchema,
+ SubmitButtonProps,
+} from "@rjsf/utils";
-export default ({ uiSchema }: SubmitButtonProps) => {
+/** The `SubmitButton` renders a button that represent the `Submit` action on a form
+ */
+export default function SubmitButton<
+ T = any,
+ S extends StrictRJSFSchema = RJSFSchema,
+ F extends FormContextType = any
+>({ uiSchema }: SubmitButtonProps) {
const {
submitText,
norender,
@@ -20,4 +32,4 @@ export default ({ uiSchema }: SubmitButtonProps) => {
{submitText}
);
-};
+}
diff --git a/packages/antd/src/templates/TitleField/index.tsx b/packages/antd/src/templates/TitleField/index.tsx
index 0891ca611e..1cae16ea46 100644
--- a/packages/antd/src/templates/TitleField/index.tsx
+++ b/packages/antd/src/templates/TitleField/index.tsx
@@ -1,35 +1,33 @@
import React from "react";
import classNames from "classnames";
-import { TitleFieldProps } from "@rjsf/utils";
-import { withConfigConsumer } from "antd/lib/config-provider/context";
+import {
+ ConfigConsumer,
+ ConfigConsumerProps,
+} from "antd/lib/config-provider/context";
+import {
+ FormContextType,
+ TitleFieldProps,
+ RJSFSchema,
+ StrictRJSFSchema,
+} from "@rjsf/utils";
-// Add in the `prefixCls` element needed by the `withConfigConsumer` HOC
-export type AntdTitleFieldProps = TitleFieldProps & {
- prefixCls: string;
- formContext: object;
-};
-
-const TitleField = ({
- id,
- prefixCls,
- required,
- registry,
- formContext: formContext1,
- title,
-}: AntdTitleFieldProps) => {
+/** The `TitleField` is the template to use to render the title of a field
+ *
+ * @param props - The `TitleFieldProps` for this component
+ */
+export default function TitleField<
+ T = any,
+ S extends StrictRJSFSchema = RJSFSchema,
+ F extends FormContextType = any
+>({ id, required, registry, title }: TitleFieldProps) {
const { formContext } = registry;
- const { colon = true } = { ...formContext1, ...formContext };
+ const { colon = true } = formContext;
let labelChildren = title;
if (colon && typeof title === "string" && title.trim() !== "") {
labelChildren = title.replace(/[::]\s*$/, "");
}
- const labelClassName = classNames({
- [`${prefixCls}-item-required`]: required,
- [`${prefixCls}-item-no-colon`]: !colon,
- });
-
const handleLabelClick = () => {
if (!id) {
return;
@@ -44,21 +42,26 @@ const TitleField = ({
};
return title ? (
-
- ) : null;
-};
+
+ {(configProps: ConfigConsumerProps) => {
+ const { getPrefixCls } = configProps;
+ const prefixCls = getPrefixCls("form");
+ const labelClassName = classNames({
+ [`${prefixCls}-item-required`]: required,
+ [`${prefixCls}-item-no-colon`]: !colon,
+ });
-TitleField.defaultProps = {
- formContext: {},
-};
-
-export default withConfigConsumer({ prefixCls: "form" })(
- TitleField
-);
+ return (
+
+ );
+ }}
+
+ ) : null;
+}
diff --git a/packages/antd/src/templates/WrapIfAdditionalTemplate/index.tsx b/packages/antd/src/templates/WrapIfAdditionalTemplate/index.tsx
index 8fe2dee0fe..fc1e92f7d3 100644
--- a/packages/antd/src/templates/WrapIfAdditionalTemplate/index.tsx
+++ b/packages/antd/src/templates/WrapIfAdditionalTemplate/index.tsx
@@ -1,13 +1,16 @@
import React from "react";
+import Col from "antd/lib/col";
+import Form from "antd/lib/form";
+import Input from "antd/lib/input";
+import Row from "antd/lib/row";
import {
ADDITIONAL_PROPERTY_FLAG,
UI_OPTIONS_KEY,
+ FormContextType,
+ RJSFSchema,
+ StrictRJSFSchema,
WrapIfAdditionalTemplateProps,
} from "@rjsf/utils";
-import Col from "antd/lib/col";
-import Form from "antd/lib/form";
-import Input from "antd/lib/input";
-import Row from "antd/lib/row";
const VERTICAL_LABEL_COL = { span: 24 };
const VERTICAL_WRAPPER_COL = { span: 24 };
@@ -16,20 +19,30 @@ const INPUT_STYLE = {
width: "100%",
};
-const WrapIfAdditionalTemplate = ({
- children,
- classNames,
- disabled,
- id,
- label,
- onDropPropertyClick,
- onKeyChange,
- readonly,
- required,
- registry,
- schema,
- uiSchema,
-}: WrapIfAdditionalTemplateProps) => {
+/** The `WrapIfAdditional` component is used by the `FieldTemplate` to rename, or remove properties that are
+ * part of an `additionalProperties` part of a schema.
+ *
+ * @param props - The `WrapIfAdditionalProps` for this component
+ */
+export default function WrapIfAdditionalTemplate<
+ T = any,
+ S extends StrictRJSFSchema = RJSFSchema,
+ F extends FormContextType = any
+>(props: WrapIfAdditionalTemplateProps) {
+ const {
+ children,
+ classNames,
+ disabled,
+ id,
+ label,
+ onDropPropertyClick,
+ onKeyChange,
+ readonly,
+ required,
+ registry,
+ schema,
+ uiSchema,
+ } = props;
const {
colon,
labelCol = VERTICAL_LABEL_COL,
@@ -103,6 +116,4 @@ const WrapIfAdditionalTemplate = ({
);
-};
-
-export default WrapIfAdditionalTemplate;
+}
diff --git a/packages/antd/src/templates/index.ts b/packages/antd/src/templates/index.ts
index 09297916d1..506f7d7b37 100644
--- a/packages/antd/src/templates/index.ts
+++ b/packages/antd/src/templates/index.ts
@@ -1,3 +1,10 @@
+import {
+ FormContextType,
+ RJSFSchema,
+ StrictRJSFSchema,
+ TemplatesType,
+} from "@rjsf/utils";
+
import ArrayFieldItemTemplate from "./ArrayFieldItemTemplate";
import ArrayFieldTemplate from "./ArrayFieldTemplate";
import BaseInputTemplate from "./BaseInputTemplate";
@@ -15,27 +22,31 @@ import ObjectFieldTemplate from "./ObjectFieldTemplate";
import SubmitButton from "./SubmitButton";
import TitleField from "./TitleField";
import WrapIfAdditionalTemplate from "./WrapIfAdditionalTemplate";
-import { TemplatesType } from "@rjsf/utils";
-const Index: Partial = {
- ArrayFieldItemTemplate,
- ArrayFieldTemplate: ArrayFieldTemplate as TemplatesType["ArrayFieldTemplate"],
- BaseInputTemplate,
- ButtonTemplates: {
- AddButton,
- MoveDownButton,
- MoveUpButton,
- RemoveButton,
- SubmitButton,
- },
- DescriptionFieldTemplate: DescriptionField,
- ErrorListTemplate: ErrorList,
- FieldErrorTemplate,
- FieldTemplate,
- ObjectFieldTemplate:
- ObjectFieldTemplate as TemplatesType["ObjectFieldTemplate"],
- TitleFieldTemplate: TitleField as TemplatesType["TitleFieldTemplate"],
- 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,
+ FieldTemplate,
+ ObjectFieldTemplate,
+ TitleFieldTemplate: TitleField,
+ WrapIfAdditionalTemplate,
+ };
+}
-export default Index;
+export default generateTemplates();
diff --git a/packages/antd/src/widgets/AltDateTimeWidget/index.tsx b/packages/antd/src/widgets/AltDateTimeWidget/index.tsx
index 92a0891a2f..0bd07ff403 100644
--- a/packages/antd/src/widgets/AltDateTimeWidget/index.tsx
+++ b/packages/antd/src/widgets/AltDateTimeWidget/index.tsx
@@ -1,16 +1,23 @@
import React from "react";
-import { WidgetProps } from "@rjsf/utils";
+import {
+ FormContextType,
+ RJSFSchema,
+ StrictRJSFSchema,
+ WidgetProps,
+} from "@rjsf/utils";
import _AltDateWidget from "../AltDateWidget";
-const AltDateTimeWidget = (props: WidgetProps) => {
+export default function AltDateTimeWidget<
+ T = any,
+ S extends StrictRJSFSchema = RJSFSchema,
+ F extends FormContextType = any
+>(props: WidgetProps) {
const { AltDateWidget } = props.registry.widgets;
return ;
-};
+}
AltDateTimeWidget.defaultProps = {
..._AltDateWidget.defaultProps,
showTime: true,
};
-
-export default AltDateTimeWidget;
diff --git a/packages/antd/src/widgets/AltDateWidget/index.tsx b/packages/antd/src/widgets/AltDateWidget/index.tsx
index 732336c7e2..83b7a6d51f 100644
--- a/packages/antd/src/widgets/AltDateWidget/index.tsx
+++ b/packages/antd/src/widgets/AltDateWidget/index.tsx
@@ -1,18 +1,25 @@
import React, { useEffect, useState } from "react";
-
+import Button from "antd/lib/button";
+import Col from "antd/lib/col";
+import Row from "antd/lib/row";
import {
pad,
parseDateString,
toDateString,
DateObject,
+ FormContextType,
+ RJSFSchema,
+ StrictRJSFSchema,
WidgetProps,
+ GenericObjectType,
} from "@rjsf/utils";
-import Button from "antd/lib/button";
-import Col from "antd/lib/col";
-import Row from "antd/lib/row";
-type DateElementProps = Pick<
- WidgetProps,
+type DateElementProps<
+ T = any,
+ S extends StrictRJSFSchema = RJSFSchema,
+ F extends FormContextType = any
+> = Pick<
+ WidgetProps,
| "id"
| "name"
| "value"
@@ -65,22 +72,27 @@ function dateElementProps(
return data;
}
-const AltDateWidget = ({
- autofocus,
- disabled,
- formContext,
- id,
- onBlur,
- onChange,
- onFocus,
- options,
- readonly,
- registry,
- showTime,
- value,
-}: WidgetProps) => {
+export default function AltDateWidget<
+ T = any,
+ S extends StrictRJSFSchema = RJSFSchema,
+ F extends FormContextType = any
+>(props: WidgetProps) {
+ const {
+ autofocus,
+ disabled,
+ formContext,
+ id,
+ onBlur,
+ onChange,
+ onFocus,
+ options,
+ readonly,
+ registry,
+ showTime,
+ value,
+ } = props;
const { SelectWidget } = registry.widgets;
- const { rowGutter = 24 } = formContext;
+ const { rowGutter = 24 } = formContext as GenericObjectType;
const [state, setState] = useState(parseDateString(value, showTime));
@@ -118,7 +130,7 @@ const AltDateWidget = ({
onChange(undefined);
};
- const renderDateElement = (elemProps: DateElementProps) => (
+ const renderDateElement = (elemProps: DateElementProps) => (
);
-};
+}
AltDateWidget.defaultProps = {
autofocus: false,
@@ -203,5 +215,3 @@ AltDateWidget.defaultProps = {
readonly: false,
showTime: false,
};
-
-export default AltDateWidget;
diff --git a/packages/antd/src/widgets/CheckboxWidget/index.tsx b/packages/antd/src/widgets/CheckboxWidget/index.tsx
index a9dab4bc64..8a52c8f1d3 100644
--- a/packages/antd/src/widgets/CheckboxWidget/index.tsx
+++ b/packages/antd/src/widgets/CheckboxWidget/index.tsx
@@ -1,20 +1,36 @@
import React from "react";
-import { WidgetProps } from "@rjsf/utils";
import Checkbox, { CheckboxChangeEvent } from "antd/lib/checkbox";
+import {
+ FormContextType,
+ RJSFSchema,
+ StrictRJSFSchema,
+ WidgetProps,
+ GenericObjectType,
+} from "@rjsf/utils";
-const CheckboxWidget = ({
- autofocus,
- disabled,
- formContext,
- id,
- label,
- onBlur,
- onChange,
- onFocus,
- readonly,
- value,
-}: WidgetProps) => {
- const { readonlyAsDisabled = true } = formContext;
+/** The `CheckBoxWidget` is a widget for rendering boolean properties.
+ * It is typically used to represent a boolean.
+ *
+ * @param props - The `WidgetProps` for this component
+ */
+export default function CheckboxWidget<
+ T = any,
+ S extends StrictRJSFSchema = RJSFSchema,
+ F extends FormContextType = any
+>(props: WidgetProps) {
+ const {
+ autofocus,
+ disabled,
+ formContext,
+ id,
+ label,
+ onBlur,
+ onChange,
+ onFocus,
+ readonly,
+ value,
+ } = props;
+ const { readonlyAsDisabled = true } = formContext as GenericObjectType;
const handleChange = ({ target }: CheckboxChangeEvent) =>
onChange(target.checked);
@@ -45,6 +61,4 @@ const CheckboxWidget = ({
{label}
);
-};
-
-export default CheckboxWidget;
+}
diff --git a/packages/antd/src/widgets/CheckboxesWidget/index.tsx b/packages/antd/src/widgets/CheckboxesWidget/index.tsx
index e12f87635e..925fb901d8 100644
--- a/packages/antd/src/widgets/CheckboxesWidget/index.tsx
+++ b/packages/antd/src/widgets/CheckboxesWidget/index.tsx
@@ -1,8 +1,23 @@
import React from "react";
-import { WidgetProps } from "@rjsf/utils";
import Checkbox from "antd/lib/checkbox";
+import {
+ FormContextType,
+ WidgetProps,
+ RJSFSchema,
+ StrictRJSFSchema,
+ GenericObjectType,
+} from "@rjsf/utils";
-const CheckboxesWidget = ({
+/** The `CheckboxesWidget` is a widget for rendering checkbox groups.
+ * It is typically used to represent an array of enums.
+ *
+ * @param props - The `WidgetProps` for this component
+ */
+export default function CheckboxesWidget<
+ T = any,
+ S extends StrictRJSFSchema = RJSFSchema,
+ F extends FormContextType = any
+>({
autofocus,
disabled,
formContext,
@@ -13,8 +28,8 @@ const CheckboxesWidget = ({
options,
readonly,
value,
-}: WidgetProps) => {
- const { readonlyAsDisabled = true } = formContext;
+}: WidgetProps) {
+ const { readonlyAsDisabled = true } = formContext as GenericObjectType;
const { enumOptions, enumDisabled, inline } = options;
@@ -62,6 +77,4 @@ const CheckboxesWidget = ({
))}
) : null;
-};
-
-export default CheckboxesWidget;
+}
diff --git a/packages/antd/src/widgets/DateTimeWidget/index.tsx b/packages/antd/src/widgets/DateTimeWidget/index.tsx
index 85b6b23a78..b1a42743de 100644
--- a/packages/antd/src/widgets/DateTimeWidget/index.tsx
+++ b/packages/antd/src/widgets/DateTimeWidget/index.tsx
@@ -1,6 +1,12 @@
import React from "react";
import dayjs from "dayjs";
-import { WidgetProps } from "@rjsf/utils";
+import {
+ FormContextType,
+ GenericObjectType,
+ RJSFSchema,
+ StrictRJSFSchema,
+ WidgetProps,
+} from "@rjsf/utils";
import DatePicker from "../../components/DatePicker";
@@ -8,18 +14,28 @@ const DATE_PICKER_STYLE = {
width: "100%",
};
-const DateTimeWidget = ({
- disabled,
- formContext,
- id,
- onBlur,
- onChange,
- onFocus,
- placeholder,
- readonly,
- value,
-}: WidgetProps) => {
- const { readonlyAsDisabled = true } = formContext;
+/** The `DateTimeWidget` component uses the `BaseInputTemplate` changing the type to `datetime-local` and transforms
+ * the value to/from utc using the appropriate utility functions.
+ *
+ * @param props - The `WidgetProps` for this component
+ */
+export default function DateTimeWidget<
+ T = any,
+ S extends StrictRJSFSchema = RJSFSchema,
+ F extends FormContextType = any
+>(props: WidgetProps) {
+ const {
+ disabled,
+ formContext,
+ id,
+ onBlur,
+ onChange,
+ onFocus,
+ placeholder,
+ readonly,
+ value,
+ } = props;
+ const { readonlyAsDisabled = true } = formContext as GenericObjectType;
const handleChange = (nextValue: any) =>
onChange(nextValue && nextValue.toISOString());
@@ -45,6 +61,4 @@ const DateTimeWidget = ({
value={value && dayjs(value)}
/>
);
-};
-
-export default DateTimeWidget;
+}
diff --git a/packages/antd/src/widgets/DateWidget/index.tsx b/packages/antd/src/widgets/DateWidget/index.tsx
index 9e6833493e..7ad1db1be0 100644
--- a/packages/antd/src/widgets/DateWidget/index.tsx
+++ b/packages/antd/src/widgets/DateWidget/index.tsx
@@ -1,6 +1,12 @@
import React from "react";
import dayjs from "dayjs";
-import { WidgetProps } from "@rjsf/utils";
+import {
+ FormContextType,
+ RJSFSchema,
+ StrictRJSFSchema,
+ WidgetProps,
+ GenericObjectType,
+} from "@rjsf/utils";
import DatePicker from "../../components/DatePicker";
@@ -8,18 +14,28 @@ const DATE_PICKER_STYLE = {
width: "100%",
};
-const DateWidget = ({
- disabled,
- formContext,
- id,
- onBlur,
- onChange,
- onFocus,
- placeholder,
- readonly,
- value,
-}: WidgetProps) => {
- const { readonlyAsDisabled = true } = formContext;
+/** The `DateWidget` component uses the `BaseInputTemplate` changing the type to `date` and transforms
+ * the value to undefined when it is falsy during the `onChange` handling.
+ *
+ * @param props - The `WidgetProps` for this component
+ */
+export default function DateWidget<
+ T = any,
+ S extends StrictRJSFSchema = RJSFSchema,
+ F extends FormContextType = any
+>(props: WidgetProps) {
+ const {
+ disabled,
+ formContext,
+ id,
+ onBlur,
+ onChange,
+ onFocus,
+ placeholder,
+ readonly,
+ value,
+ } = props;
+ const { readonlyAsDisabled = true } = formContext as GenericObjectType;
const handleChange = (nextValue: any) =>
onChange(nextValue && nextValue.format("YYYY-MM-DD"));
@@ -45,6 +61,4 @@ const DateWidget = ({
value={value && dayjs(value)}
/>
);
-};
-
-export default DateWidget;
+}
diff --git a/packages/antd/src/widgets/PasswordWidget/index.tsx b/packages/antd/src/widgets/PasswordWidget/index.tsx
index 79da9ad323..960f6ea5e7 100644
--- a/packages/antd/src/widgets/PasswordWidget/index.tsx
+++ b/packages/antd/src/widgets/PasswordWidget/index.tsx
@@ -1,20 +1,35 @@
import React from "react";
-import { WidgetProps } from "@rjsf/utils";
import Input from "antd/lib/input";
+import {
+ FormContextType,
+ RJSFSchema,
+ StrictRJSFSchema,
+ WidgetProps,
+ GenericObjectType,
+} from "@rjsf/utils";
-const PasswordWidget = ({
- disabled,
- formContext,
- id,
- onBlur,
- onChange,
- onFocus,
- options,
- placeholder,
- readonly,
- value,
-}: WidgetProps) => {
- const { readonlyAsDisabled = true } = formContext;
+/** The `PasswordWidget` component uses the `BaseInputTemplate` changing the type to `password`.
+ *
+ * @param props - The `WidgetProps` for this component
+ */
+export default function PasswordWidget<
+ T = any,
+ S extends StrictRJSFSchema = RJSFSchema,
+ F extends FormContextType = any
+>(props: WidgetProps) {
+ const {
+ disabled,
+ formContext,
+ id,
+ onBlur,
+ onChange,
+ onFocus,
+ options,
+ placeholder,
+ readonly,
+ value,
+ } = props;
+ const { readonlyAsDisabled = true } = formContext as GenericObjectType;
const emptyValue = options.emptyValue || "";
@@ -39,6 +54,4 @@ const PasswordWidget = ({
value={value || ""}
/>
);
-};
-
-export default PasswordWidget;
+}
diff --git a/packages/antd/src/widgets/RadioWidget/index.tsx b/packages/antd/src/widgets/RadioWidget/index.tsx
index 3865ec6ed0..638062d6e1 100644
--- a/packages/antd/src/widgets/RadioWidget/index.tsx
+++ b/packages/antd/src/widgets/RadioWidget/index.tsx
@@ -1,8 +1,23 @@
import React from "react";
-import { WidgetProps } from "@rjsf/utils";
import Radio, { RadioChangeEvent } from "antd/lib/radio";
+import {
+ FormContextType,
+ GenericObjectType,
+ RJSFSchema,
+ StrictRJSFSchema,
+ WidgetProps,
+} from "@rjsf/utils";
-const RadioWidget = ({
+/** The `RadioWidget` is a widget for rendering a radio group.
+ * It is typically used with a string property constrained with enum options.
+ *
+ * @param props - The `WidgetProps` for this component
+ */
+export default function RadioWidget<
+ T = any,
+ S extends StrictRJSFSchema = RJSFSchema,
+ F extends FormContextType = any
+>({
autofocus,
disabled,
formContext,
@@ -14,8 +29,8 @@ const RadioWidget = ({
readonly,
schema,
value,
-}: WidgetProps) => {
- const { readonlyAsDisabled = true } = formContext;
+}: WidgetProps) {
+ const { readonlyAsDisabled = true } = formContext as GenericObjectType;
const { enumOptions, enumDisabled } = options;
@@ -55,6 +70,4 @@ const RadioWidget = ({
))}
);
-};
-
-export default RadioWidget;
+}
diff --git a/packages/antd/src/widgets/RangeWidget/index.tsx b/packages/antd/src/widgets/RangeWidget/index.tsx
index acca3a4460..f3bc8e2aea 100644
--- a/packages/antd/src/widgets/RangeWidget/index.tsx
+++ b/packages/antd/src/widgets/RangeWidget/index.tsx
@@ -1,22 +1,39 @@
import React from "react";
-import { rangeSpec, WidgetProps } from "@rjsf/utils";
import Slider from "antd/lib/slider";
+import {
+ rangeSpec,
+ FormContextType,
+ RJSFSchema,
+ StrictRJSFSchema,
+ WidgetProps,
+ GenericObjectType,
+} from "@rjsf/utils";
-const RangeWidget = ({
- autofocus,
- disabled,
- formContext,
- id,
- onBlur,
- onChange,
- onFocus,
- options,
- placeholder,
- readonly,
- schema,
- value,
-}: WidgetProps) => {
- const { readonlyAsDisabled = true } = formContext;
+/** The `RangeWidget` component uses the `BaseInputTemplate` changing the type to `range` and wrapping the result
+ * in a div, with the value along side it.
+ *
+ * @param props - The `WidgetProps` for this component
+ */
+export default function RangeWidget<
+ T = any,
+ S extends StrictRJSFSchema = RJSFSchema,
+ F extends FormContextType = any
+>(props: WidgetProps) {
+ const {
+ autofocus,
+ disabled,
+ formContext,
+ id,
+ onBlur,
+ onChange,
+ onFocus,
+ options,
+ placeholder,
+ readonly,
+ schema,
+ value,
+ } = props;
+ const { readonlyAsDisabled = true } = formContext as GenericObjectType;
const { min, max, step } = rangeSpec(schema);
@@ -51,6 +68,4 @@ const RangeWidget = ({
{...extraProps}
/>
);
-};
-
-export default RangeWidget;
+}
diff --git a/packages/antd/src/widgets/SelectWidget/index.tsx b/packages/antd/src/widgets/SelectWidget/index.tsx
index 617fd9026e..909a892d60 100644
--- a/packages/antd/src/widgets/SelectWidget/index.tsx
+++ b/packages/antd/src/widgets/SelectWidget/index.tsx
@@ -1,15 +1,31 @@
import React from "react";
-import { processSelectValue, WidgetProps } from "@rjsf/utils";
import Select from "antd/lib/select";
+import {
+ processSelectValue,
+ FormContextType,
+ GenericObjectType,
+ RJSFSchema,
+ StrictRJSFSchema,
+ WidgetProps,
+} from "@rjsf/utils";
const SELECT_STYLE = {
width: "100%",
};
-const SelectWidget = ({
+/** The `SelectWidget` is a widget for rendering dropdowns.
+ * It is typically used with string properties constrained with enum options.
+ *
+ * @param props - The `WidgetProps` for this component
+ */
+export default function SelectWidget<
+ T = any,
+ S extends StrictRJSFSchema = RJSFSchema,
+ F extends FormContextType = any
+>({
autofocus,
disabled,
- formContext,
+ formContext = {} as F,
id,
multiple,
onBlur,
@@ -20,19 +36,19 @@ const SelectWidget = ({
readonly,
schema,
value,
-}: WidgetProps) => {
- const { readonlyAsDisabled = true } = formContext;
+}: WidgetProps) {
+ const { readonlyAsDisabled = true } = formContext as GenericObjectType;
const { enumOptions, enumDisabled } = options;
const handleChange = (nextValue: any) =>
- onChange(processSelectValue(schema, nextValue, options));
+ onChange(processSelectValue(schema, nextValue, options));
const handleBlur = () =>
- onBlur(id, processSelectValue(schema, value, options));
+ onBlur(id, processSelectValue(schema, value, options));
const handleFocus = () =>
- onFocus(id, processSelectValue(schema, value, options));
+ onFocus(id, processSelectValue(schema, value, options));
const getPopupContainer = (node: any) => node.parentNode;
@@ -74,10 +90,4 @@ const SelectWidget = ({
))}
);
-};
-
-SelectWidget.defaultProps = {
- formContext: {},
-};
-
-export default SelectWidget;
+}
diff --git a/packages/antd/src/widgets/TextareaWidget/index.tsx b/packages/antd/src/widgets/TextareaWidget/index.tsx
index b752a77060..b44fa64d3c 100644
--- a/packages/antd/src/widgets/TextareaWidget/index.tsx
+++ b/packages/antd/src/widgets/TextareaWidget/index.tsx
@@ -1,12 +1,26 @@
import React from "react";
-import { WidgetProps } from "@rjsf/utils";
import Input from "antd/lib/input";
+import {
+ FormContextType,
+ GenericObjectType,
+ RJSFSchema,
+ StrictRJSFSchema,
+ WidgetProps,
+} from "@rjsf/utils";
const INPUT_STYLE = {
width: "100%",
};
-const TextareaWidget = ({
+/** The `TextareaWidget` is a widget for rendering input fields as textarea.
+ *
+ * @param props - The `WidgetProps` for this component
+ */
+export default function TextareaWidget<
+ T = any,
+ S extends StrictRJSFSchema = RJSFSchema,
+ F extends FormContextType = any
+>({
disabled,
formContext,
id,
@@ -17,8 +31,8 @@ const TextareaWidget = ({
placeholder,
readonly,
value,
-}: WidgetProps) => {
- const { readonlyAsDisabled = true } = formContext;
+}: WidgetProps) {
+ const { readonlyAsDisabled = true } = formContext as GenericObjectType;
const handleChange = ({ target }: React.ChangeEvent) =>
onChange(target.value === "" ? options.emptyValue : target.value);
@@ -50,6 +64,4 @@ const TextareaWidget = ({
{...extraProps}
/>
);
-};
-
-export default TextareaWidget;
+}
diff --git a/packages/antd/src/widgets/index.ts b/packages/antd/src/widgets/index.ts
index 34c927c032..b9cd29276f 100644
--- a/packages/antd/src/widgets/index.ts
+++ b/packages/antd/src/widgets/index.ts
@@ -1,3 +1,10 @@
+import {
+ FormContextType,
+ RegistryWidgetsType,
+ RJSFSchema,
+ StrictRJSFSchema,
+} from "@rjsf/utils";
+
import AltDateTimeWidget from "./AltDateTimeWidget";
import AltDateWidget from "./AltDateWidget";
import CheckboxesWidget from "./CheckboxesWidget";
@@ -10,18 +17,24 @@ import RangeWidget from "./RangeWidget";
import SelectWidget from "./SelectWidget";
import TextareaWidget from "./TextareaWidget";
-const Widgets = {
- AltDateTimeWidget,
- AltDateWidget,
- CheckboxesWidget,
- CheckboxWidget,
- DateTimeWidget,
- DateWidget,
- PasswordWidget,
- RadioWidget,
- RangeWidget,
- SelectWidget,
- TextareaWidget,
-};
+export function generateWidgets<
+ T = any,
+ S extends StrictRJSFSchema = RJSFSchema,
+ F extends FormContextType = any
+>(): RegistryWidgetsType {
+ return {
+ AltDateTimeWidget,
+ AltDateWidget,
+ CheckboxesWidget,
+ CheckboxWidget,
+ DateTimeWidget,
+ DateWidget,
+ PasswordWidget,
+ RadioWidget,
+ RangeWidget,
+ SelectWidget,
+ TextareaWidget,
+ };
+}
-export default Widgets;
+export default generateWidgets();