From db140942ee6073cfce8b1afc0987aee605b5a647 Mon Sep 17 00:00:00 2001 From: Nick Grosenbacher Date: Thu, 5 Jan 2023 22:36:54 -0500 Subject: [PATCH] fix: Generic support for Chakra UI (#3327) * Generic support for Chakra UI - Partially fix #3072 - Extract ChakraIconButton to its own file to abstract away React.memo - Refactor AltDateWidget to extract DateElement component * Changes from code review * Update packages/chakra-ui/src/IconButton/index.ts Co-authored-by: Heath C <51679588+heath-freenome@users.noreply.github.com> --- CHANGELOG.md | 1 + .../chakra-ui/src/AddButton/AddButton.tsx | 29 ++++--- .../AltDateTimeWidget/AltDateTimeWidget.tsx | 15 +++- .../src/AltDateWidget/AltDateWidget.tsx | 85 +++++++++++-------- .../ArrayFieldItemTemplate.tsx | 17 ++-- .../ArrayFieldTemplate/ArrayFieldTemplate.tsx | 46 +++++----- .../BaseInputTemplate/BaseInputTemplate.tsx | 20 +++-- .../src/CheckboxWidget/CheckboxWidget.tsx | 20 +++-- .../src/CheckboxesWidget/CheckboxesWidget.tsx | 39 +++------ .../src/DescriptionField/DescriptionField.tsx | 17 ++-- .../chakra-ui/src/ErrorList/ErrorList.tsx | 17 ++-- .../FieldErrorTemplate/FieldErrorTemplate.tsx | 13 ++- .../FieldHelpTemplate/FieldHelpTemplate.tsx | 13 ++- .../src/FieldTemplate/FieldTemplate.tsx | 30 ++++--- packages/chakra-ui/src/Form/Form.tsx | 14 ++- .../src/IconButton/ChakraIconButton.tsx | 28 ++++++ .../chakra-ui/src/IconButton/IconButton.tsx | 68 +++++++++------ packages/chakra-ui/src/IconButton/index.ts | 2 +- .../ObjectFieldTemplate.tsx | 28 +++--- .../chakra-ui/src/RadioWidget/RadioWidget.tsx | 19 +++-- .../chakra-ui/src/RangeWidget/RangeWidget.tsx | 22 +++-- .../src/SelectWidget/SelectWidget.tsx | 26 ++++-- .../src/SubmitButton/SubmitButton.tsx | 17 +++- packages/chakra-ui/src/Templates/Templates.ts | 54 +++++++----- .../src/TextareaWidget/TextareaWidget.tsx | 19 +++-- packages/chakra-ui/src/Theme/Theme.tsx | 21 +++-- .../chakra-ui/src/TitleField/TitleField.tsx | 27 ++++-- .../src/UpDownWidget/UpDownWidget.tsx | 17 ++-- packages/chakra-ui/src/Widgets/Widgets.ts | 36 +++++--- .../WrapIfAdditionalTemplate.tsx | 13 ++- packages/chakra-ui/src/index.ts | 11 +++ packages/chakra-ui/src/index.tsx | 11 --- 32 files changed, 512 insertions(+), 283 deletions(-) create mode 100644 packages/chakra-ui/src/IconButton/ChakraIconButton.tsx create mode 100644 packages/chakra-ui/src/index.ts delete mode 100644 packages/chakra-ui/src/index.tsx diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f98f5d3ec..0c4f19f344 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,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/core - 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/chakra-ui/src/AddButton/AddButton.tsx b/packages/chakra-ui/src/AddButton/AddButton.tsx index 8ff0dd5e89..a3868a2842 100644 --- a/packages/chakra-ui/src/AddButton/AddButton.tsx +++ b/packages/chakra-ui/src/AddButton/AddButton.tsx @@ -1,16 +1,21 @@ import React from "react"; -import { IconButtonProps } from "@rjsf/utils"; +import { + FormContextType, + IconButtonProps, + RJSFSchema, + StrictRJSFSchema, +} from "@rjsf/utils"; import { Button } from "@chakra-ui/react"; import { AddIcon } from "@chakra-ui/icons"; -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/chakra-ui/src/AltDateTimeWidget/AltDateTimeWidget.tsx b/packages/chakra-ui/src/AltDateTimeWidget/AltDateTimeWidget.tsx index 222de81600..eacf8a6c5c 100644 --- a/packages/chakra-ui/src/AltDateTimeWidget/AltDateTimeWidget.tsx +++ b/packages/chakra-ui/src/AltDateTimeWidget/AltDateTimeWidget.tsx @@ -1,12 +1,21 @@ import React from "react"; import _AltDateWidget from "../AltDateWidget"; -import { WidgetProps } from "@rjsf/utils"; +import { + FormContextType, + RJSFSchema, + StrictRJSFSchema, + WidgetProps, +} from "@rjsf/utils"; -const AltDateTimeWidget = (props: WidgetProps) => { +function AltDateTimeWidget< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>(props: WidgetProps) { const { AltDateWidget } = props.registry.widgets; return ; -}; +} AltDateTimeWidget.defaultProps = { ..._AltDateWidget.defaultProps, diff --git a/packages/chakra-ui/src/AltDateWidget/AltDateWidget.tsx b/packages/chakra-ui/src/AltDateWidget/AltDateWidget.tsx index c92231dc2f..b90de98053 100644 --- a/packages/chakra-ui/src/AltDateWidget/AltDateWidget.tsx +++ b/packages/chakra-ui/src/AltDateWidget/AltDateWidget.tsx @@ -1,8 +1,11 @@ import React, { MouseEvent, useEffect, useState } from "react"; import { DateObject, + FormContextType, pad, parseDateString, + RJSFSchema, + StrictRJSFSchema, toDateString, WidgetProps, } from "@rjsf/utils"; @@ -16,6 +19,31 @@ const rangeOptions = (start: number, stop: number) => { return options; }; +function DateElement< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>(props: WidgetProps) { + const { SelectWidget } = props.registry.widgets; + const value = props.value ? props.value : undefined; + return ( + ) => + props.select(props.type, elemValue) + } + options={{ + enumOptions: rangeOptions(props.range[0], props.range[1]), + }} + placeholder={props.type} + schema={{ type: "integer" } as S} + value={value} + /> + ); +} + interface AltDateStateType extends DateObject { [x: string]: number | undefined; } @@ -26,7 +54,11 @@ const readyForChange = (state: AltDateStateType) => { ); }; -const AltDateWidget = (props: any) => { +function AltDateWidget< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>(props: WidgetProps) { const { autofocus, disabled, @@ -40,7 +72,6 @@ const AltDateWidget = (props: any) => { showTime, value, } = props; - const { SelectWidget } = registry.widgets; const [state, setState] = useState(parseDateString(value, showTime)); useEffect(() => { setState(parseDateString(value, showTime)); @@ -96,26 +127,6 @@ const AltDateWidget = (props: any) => { return data; }; - const renderDateElement = (elemProps: WidgetProps) => { - const value = elemProps.value ? elemProps.value : undefined; - return ( - - elemProps.select(elemProps.type, elemValue) - } - options={{ - enumOptions: rangeOptions(elemProps.range[0], elemProps.range[1]), - }} - placeholder={elemProps.type} - schema={{ type: "integer" }} - value={value} - /> - ); - }; - return ( @@ -123,20 +134,20 @@ const AltDateWidget = (props: any) => { const elemId = id + "_" + elemProps.type; return ( - {renderDateElement({ - ...props, - ...elemProps, - autofocus: autofocus && i === 0, - disabled, - id: elemId, - name: id, - onBlur, - onFocus, - readonly, - registry, - select: handleChange, - value: elemProps.value < 0 ? "" : elemProps.value, - })} + + {...props} + {...elemProps} + autofocus={autofocus && i === 0} + disabled={disabled} + id={elemId} + name={id} + onBlur={onBlur} + onFocus={onFocus} + readonly={readonly} + registry={registry} + select={handleChange} + value={elemProps.value < 0 ? "" : elemProps.value} + /> ); })} @@ -160,7 +171,7 @@ const AltDateWidget = (props: any) => { ); -}; +} AltDateWidget.defaultProps = { autofocus: false, diff --git a/packages/chakra-ui/src/ArrayFieldItemTemplate/ArrayFieldItemTemplate.tsx b/packages/chakra-ui/src/ArrayFieldItemTemplate/ArrayFieldItemTemplate.tsx index a386652029..490d699c3a 100644 --- a/packages/chakra-ui/src/ArrayFieldItemTemplate/ArrayFieldItemTemplate.tsx +++ b/packages/chakra-ui/src/ArrayFieldItemTemplate/ArrayFieldItemTemplate.tsx @@ -1,8 +1,17 @@ import React, { useMemo } from "react"; import { Box, ButtonGroup, HStack } from "@chakra-ui/react"; -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, @@ -69,6 +78,4 @@ const ArrayFieldItemTemplate = (props: ArrayFieldTemplateItemType) => { )} ); -}; - -export default ArrayFieldItemTemplate; +} diff --git a/packages/chakra-ui/src/ArrayFieldTemplate/ArrayFieldTemplate.tsx b/packages/chakra-ui/src/ArrayFieldTemplate/ArrayFieldTemplate.tsx index 24f9214956..67d5aca276 100644 --- a/packages/chakra-ui/src/ArrayFieldTemplate/ArrayFieldTemplate.tsx +++ b/packages/chakra-ui/src/ArrayFieldTemplate/ArrayFieldTemplate.tsx @@ -5,9 +5,16 @@ import { getUiOptions, ArrayFieldTemplateItemType, ArrayFieldTemplateProps, + StrictRJSFSchema, + RJSFSchema, + FormContextType, } 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, @@ -21,23 +28,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 }, @@ -62,9 +70,11 @@ const ArrayFieldTemplate = (props: ArrayFieldTemplateProps) => { {items.length > 0 && - items.map(({ key, ...itemProps }: ArrayFieldTemplateItemType) => ( - - ))} + items.map( + ({ key, ...itemProps }: ArrayFieldTemplateItemType) => ( + + ) + )} {canAdd && ( @@ -82,6 +92,4 @@ const ArrayFieldTemplate = (props: ArrayFieldTemplateProps) => { ); -}; - -export default ArrayFieldTemplate; +} diff --git a/packages/chakra-ui/src/BaseInputTemplate/BaseInputTemplate.tsx b/packages/chakra-ui/src/BaseInputTemplate/BaseInputTemplate.tsx index 91bf6f7727..cf87c79947 100644 --- a/packages/chakra-ui/src/BaseInputTemplate/BaseInputTemplate.tsx +++ b/packages/chakra-ui/src/BaseInputTemplate/BaseInputTemplate.tsx @@ -1,9 +1,19 @@ import * as React from "react"; import { FormControl, FormLabel, Input } from "@chakra-ui/react"; -import { getInputProps, WidgetProps } from "@rjsf/utils"; +import { + FormContextType, + getInputProps, + RJSFSchema, + StrictRJSFSchema, + WidgetProps, +} from "@rjsf/utils"; import { getChakra } from "../utils"; -const BaseInputTemplate = (props: WidgetProps) => { +export default function BaseInputTemplate< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>(props: WidgetProps) { const { id, type, @@ -23,7 +33,7 @@ const BaseInputTemplate = (props: WidgetProps) => { disabled, registry, } = props; - const inputProps = getInputProps(schema, type, options); + const inputProps = getInputProps(schema, type, options); const chakraProps = getChakra({ uiSchema }); const { schemaUtils } = registry; @@ -78,6 +88,4 @@ const BaseInputTemplate = (props: WidgetProps) => { ) : null} ); -}; - -export default BaseInputTemplate; +} diff --git a/packages/chakra-ui/src/CheckboxWidget/CheckboxWidget.tsx b/packages/chakra-ui/src/CheckboxWidget/CheckboxWidget.tsx index 56f9eb8cdc..59bb4c115b 100644 --- a/packages/chakra-ui/src/CheckboxWidget/CheckboxWidget.tsx +++ b/packages/chakra-ui/src/CheckboxWidget/CheckboxWidget.tsx @@ -1,9 +1,19 @@ import React from "react"; import { Checkbox, FormControl, Text } from "@chakra-ui/react"; -import { WidgetProps, schemaRequiresTrueValue } from "@rjsf/utils"; +import { + WidgetProps, + schemaRequiresTrueValue, + StrictRJSFSchema, + RJSFSchema, + FormContextType, +} from "@rjsf/utils"; import { getChakra } from "../utils"; -const CheckboxWidget = (props: WidgetProps) => { +export default function CheckboxWidget< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>(props: WidgetProps) { const { id, value, @@ -20,7 +30,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 }, @@ -47,6 +57,4 @@ const CheckboxWidget = (props: WidgetProps) => { ); -}; - -export default CheckboxWidget; +} diff --git a/packages/chakra-ui/src/CheckboxesWidget/CheckboxesWidget.tsx b/packages/chakra-ui/src/CheckboxesWidget/CheckboxesWidget.tsx index c12b6f8eb1..b3b7ab0bed 100644 --- a/packages/chakra-ui/src/CheckboxesWidget/CheckboxesWidget.tsx +++ b/packages/chakra-ui/src/CheckboxesWidget/CheckboxesWidget.tsx @@ -7,23 +7,19 @@ import { Text, Stack, } from "@chakra-ui/react"; -import { WidgetProps } from "@rjsf/utils"; +import { + FormContextType, + RJSFSchema, + StrictRJSFSchema, + WidgetProps, +} from "@rjsf/utils"; import { getChakra } from "../utils"; -// const selectValue = (value, selected, all) => { -// const at = all.indexOf(value); -// const updated = selected.slice(0, at).concat(value, selected.slice(at)); - -// // As inserting values at predefined index positions doesn't work with empty -// // arrays, we need to reorder the updated selection to match the initial order -// return updated.sort((a, b) => all.indexOf(a) > all.indexOf(b)); -// }; - -// const deselectValue = (value, selected) => { -// return selected.filter((v) => v !== value); -// }; - -const CheckboxesWidget = (props: WidgetProps) => { +export default function CheckboxesWidget< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>(props: WidgetProps) { const { id, disabled, @@ -41,15 +37,6 @@ const CheckboxesWidget = (props: WidgetProps) => { } = props; const { enumOptions, enumDisabled } = options; const chakraProps = getChakra({ uiSchema }); - // const _onChange = option => ({ target: { checked } }) => { - // const all = enumOptions.map(({ value }) => value) - - // if (checked) { - // onChange(selectValue(option.value, value, all)) - // } else { - // onChange(deselectValue(option.value, value)) - // } - // } const _onBlur = ({ target: { value }, @@ -102,6 +89,4 @@ const CheckboxesWidget = (props: WidgetProps) => { ); -}; - -export default CheckboxesWidget; +} diff --git a/packages/chakra-ui/src/DescriptionField/DescriptionField.tsx b/packages/chakra-ui/src/DescriptionField/DescriptionField.tsx index 46bf12a445..18a4fed2f6 100644 --- a/packages/chakra-ui/src/DescriptionField/DescriptionField.tsx +++ b/packages/chakra-ui/src/DescriptionField/DescriptionField.tsx @@ -1,8 +1,17 @@ import React from "react"; -import { DescriptionFieldProps } from "@rjsf/utils"; +import { + DescriptionFieldProps, + FormContextType, + RJSFSchema, + StrictRJSFSchema, +} from "@rjsf/utils"; import { Text } from "@chakra-ui/react"; -const DescriptionField = ({ description, id }: DescriptionFieldProps) => { +export default function DescriptionField< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>({ description, id }: DescriptionFieldProps) { if (!description) { return null; } @@ -16,6 +25,4 @@ const DescriptionField = ({ description, id }: DescriptionFieldProps) => { } return <>{description}; -}; - -export default DescriptionField; +} diff --git a/packages/chakra-ui/src/ErrorList/ErrorList.tsx b/packages/chakra-ui/src/ErrorList/ErrorList.tsx index aa91b7e03d..af7a64e35a 100644 --- a/packages/chakra-ui/src/ErrorList/ErrorList.tsx +++ b/packages/chakra-ui/src/ErrorList/ErrorList.tsx @@ -1,9 +1,18 @@ import React from "react"; -import { ErrorListProps } from "@rjsf/utils"; +import { + ErrorListProps, + FormContextType, + RJSFSchema, + StrictRJSFSchema, +} from "@rjsf/utils"; import { List, ListIcon, ListItem, Alert, AlertTitle } from "@chakra-ui/react"; import { WarningIcon } from "@chakra-ui/icons"; -const ErrorList = ({ errors }: ErrorListProps) => { +export default function ErrorList< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>({ errors }: ErrorListProps) { return ( { ); -}; - -export default ErrorList; +} diff --git a/packages/chakra-ui/src/FieldErrorTemplate/FieldErrorTemplate.tsx b/packages/chakra-ui/src/FieldErrorTemplate/FieldErrorTemplate.tsx index 03e7f4adff..7b871f9444 100644 --- a/packages/chakra-ui/src/FieldErrorTemplate/FieldErrorTemplate.tsx +++ b/packages/chakra-ui/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 { FormErrorMessage, List, ListItem } from "@chakra-ui/react"; /** 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/chakra-ui/src/FieldHelpTemplate/FieldHelpTemplate.tsx b/packages/chakra-ui/src/FieldHelpTemplate/FieldHelpTemplate.tsx index dfa5f86df3..50a6a0ad66 100644 --- a/packages/chakra-ui/src/FieldHelpTemplate/FieldHelpTemplate.tsx +++ b/packages/chakra-ui/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 { FormHelperText } from "@chakra-ui/react"; /** 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 } = props; if (!help) { return null; diff --git a/packages/chakra-ui/src/FieldTemplate/FieldTemplate.tsx b/packages/chakra-ui/src/FieldTemplate/FieldTemplate.tsx index 0d99da1f45..8cc0243f68 100644 --- a/packages/chakra-ui/src/FieldTemplate/FieldTemplate.tsx +++ b/packages/chakra-ui/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 { Text, FormControl } from "@chakra-ui/react"; -const FieldTemplate = (props: FieldTemplateProps) => { +export default function FieldTemplate< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>(props: FieldTemplateProps) { const { id, children, @@ -23,12 +34,13 @@ const FieldTemplate = (props: FieldTemplateProps) => { schema, uiSchema, } = props; - 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}
; @@ -61,6 +73,4 @@ const FieldTemplate = (props: FieldTemplateProps) => { ); -}; - -export default FieldTemplate; +} diff --git a/packages/chakra-ui/src/Form/Form.tsx b/packages/chakra-ui/src/Form/Form.tsx index b2f87f1c74..d24c4348a5 100644 --- a/packages/chakra-ui/src/Form/Form.tsx +++ b/packages/chakra-ui/src/Form/Form.tsx @@ -1,8 +1,14 @@ import { ComponentType } from "react"; import { withTheme, FormProps } from "@rjsf/core"; +import { generateTheme } from "../Theme"; +import { FormContextType, RJSFSchema, StrictRJSFSchema } from "@rjsf/utils"; -import Theme from "../Theme"; +export function generateForm< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>(): ComponentType> { + return withTheme(generateTheme()); +} -const Form: ComponentType = withTheme(Theme); - -export default Form; +export default generateForm(); diff --git a/packages/chakra-ui/src/IconButton/ChakraIconButton.tsx b/packages/chakra-ui/src/IconButton/ChakraIconButton.tsx new file mode 100644 index 0000000000..0506da5843 --- /dev/null +++ b/packages/chakra-ui/src/IconButton/ChakraIconButton.tsx @@ -0,0 +1,28 @@ +import React from "react"; +import { IconButton } from "@chakra-ui/react"; +import { IconButtonProps as ChakraIconButtonProps } from "@chakra-ui/button/dist/declarations/src/icon-button"; +import { + FormContextType, + IconButtonProps, + RJSFSchema, + StrictRJSFSchema, +} from "@rjsf/utils"; + +function ChakraIconButton< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>(props: IconButtonProps) { + const { icon, iconType, uiSchema, registry, ...otherProps } = props; + return ( + + ); +} + +ChakraIconButton.displayName = "ChakraIconButton"; + +export default React.memo(ChakraIconButton) as typeof ChakraIconButton; diff --git a/packages/chakra-ui/src/IconButton/IconButton.tsx b/packages/chakra-ui/src/IconButton/IconButton.tsx index abb47f790b..cd243f24c5 100644 --- a/packages/chakra-ui/src/IconButton/IconButton.tsx +++ b/packages/chakra-ui/src/IconButton/IconButton.tsx @@ -1,41 +1,53 @@ -import React, { memo } from "react"; +import React from "react"; + import { - IconButton, - IconButtonProps as ChakraIconButtonProps, -} from "@chakra-ui/react"; -import { IconButtonProps } from "@rjsf/utils"; + FormContextType, + IconButtonProps, + RJSFSchema, + StrictRJSFSchema, +} from "@rjsf/utils"; import { ArrowUpIcon, ArrowDownIcon, DeleteIcon } from "@chakra-ui/icons"; +import ChakraIconButton from "./ChakraIconButton"; -/** - * props used in Template: - * icon, tabIndex, disabled, onClick - */ -const ChakraIconButton = memo((props: IconButtonProps) => { - const { icon, iconType, uiSchema, registry, ...otherProps } = props; +export function MoveDownButton< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>(props: IconButtonProps) { return ( - + title="Move down" + {...props} + icon={} /> ); -}); - -ChakraIconButton.displayName = "ChakraIconButton"; - -export default ChakraIconButton; +} -export function MoveDownButton(props: IconButtonProps) { +export function MoveUpButton< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>(props: IconButtonProps) { return ( - } /> + + title="Move up" + {...props} + icon={} + /> ); } -export function MoveUpButton(props: IconButtonProps) { - return } />; -} - -export function RemoveButton(props: IconButtonProps) { - return } />; +export function RemoveButton< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>(props: IconButtonProps) { + return ( + + title="Remove" + {...props} + icon={} + /> + ); } diff --git a/packages/chakra-ui/src/IconButton/index.ts b/packages/chakra-ui/src/IconButton/index.ts index 55447475bc..8d37bdfc1f 100644 --- a/packages/chakra-ui/src/IconButton/index.ts +++ b/packages/chakra-ui/src/IconButton/index.ts @@ -1,2 +1,2 @@ -export { default } from "./IconButton"; +export { default } from "./ChakraIconButton"; export * from "./IconButton"; diff --git a/packages/chakra-ui/src/ObjectFieldTemplate/ObjectFieldTemplate.tsx b/packages/chakra-ui/src/ObjectFieldTemplate/ObjectFieldTemplate.tsx index 4c0a521fef..278894e404 100644 --- a/packages/chakra-ui/src/ObjectFieldTemplate/ObjectFieldTemplate.tsx +++ b/packages/chakra-ui/src/ObjectFieldTemplate/ObjectFieldTemplate.tsx @@ -2,12 +2,19 @@ import React from "react"; import { Grid, GridItem } from "@chakra-ui/react"; import { canExpand, + FormContextType, getTemplate, getUiOptions, ObjectFieldTemplateProps, + RJSFSchema, + StrictRJSFSchema, } from "@rjsf/utils"; -const ObjectFieldTemplate = (props: ObjectFieldTemplateProps) => { +export default function ObjectFieldTemplate< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>(props: ObjectFieldTemplateProps) { const { description, title, @@ -22,17 +29,18 @@ const ObjectFieldTemplate = (props: ObjectFieldTemplateProps) => { onAddClick, registry, } = props; - const uiOptions = getUiOptions(uiSchema); - const TitleFieldTemplate = getTemplate<"TitleFieldTemplate">( + 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 }, @@ -69,7 +77,7 @@ const ObjectFieldTemplate = (props: ObjectFieldTemplateProps) => { ) )} - {canExpand(schema, uiSchema, formData) && ( + {canExpand(schema, uiSchema, formData) && ( { ); -}; - -export default ObjectFieldTemplate; +} diff --git a/packages/chakra-ui/src/RadioWidget/RadioWidget.tsx b/packages/chakra-ui/src/RadioWidget/RadioWidget.tsx index 60e9d68750..0c7341d969 100644 --- a/packages/chakra-ui/src/RadioWidget/RadioWidget.tsx +++ b/packages/chakra-ui/src/RadioWidget/RadioWidget.tsx @@ -8,10 +8,19 @@ import { Stack, } from "@chakra-ui/react"; -import { WidgetProps } from "@rjsf/utils"; +import { + FormContextType, + RJSFSchema, + StrictRJSFSchema, + WidgetProps, +} from "@rjsf/utils"; import { getChakra } from "../utils"; -const RadioWidget = ({ +export default function RadioWidget< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>({ id, schema, options, @@ -24,7 +33,7 @@ const RadioWidget = ({ onBlur, onFocus, uiSchema, -}: WidgetProps) => { +}: WidgetProps) { const { enumOptions, enumDisabled } = options; const chakraProps = getChakra({ uiSchema }); @@ -76,6 +85,4 @@ const RadioWidget = ({ ); -}; - -export default RadioWidget; +} diff --git a/packages/chakra-ui/src/RangeWidget/RangeWidget.tsx b/packages/chakra-ui/src/RangeWidget/RangeWidget.tsx index 48074c7d80..c11bab8eea 100644 --- a/packages/chakra-ui/src/RangeWidget/RangeWidget.tsx +++ b/packages/chakra-ui/src/RangeWidget/RangeWidget.tsx @@ -7,10 +7,20 @@ import { SliderThumb, SliderTrack, } from "@chakra-ui/react"; -import { rangeSpec, WidgetProps } from "@rjsf/utils"; +import { + FormContextType, + rangeSpec, + RJSFSchema, + StrictRJSFSchema, + WidgetProps, +} from "@rjsf/utils"; import { getChakra } from "../utils"; -const RangeWidget = ({ +export default function RangeWidget< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>({ value, readonly, disabled, @@ -23,11 +33,11 @@ const RangeWidget = ({ label, id, registry, -}: WidgetProps) => { +}: WidgetProps) { const { schemaUtils } = registry; const chakraProps = getChakra({ uiSchema }); - const sliderWidgetProps = { value, label, id, ...rangeSpec(schema) }; + const sliderWidgetProps = { value, label, id, ...rangeSpec(schema) }; const displayLabel = schemaUtils.getDisplayLabel(schema, uiSchema) && @@ -62,6 +72,4 @@ const RangeWidget = ({ ); -}; - -export default RangeWidget; +} diff --git a/packages/chakra-ui/src/SelectWidget/SelectWidget.tsx b/packages/chakra-ui/src/SelectWidget/SelectWidget.tsx index b1268e801b..5eec1dc521 100644 --- a/packages/chakra-ui/src/SelectWidget/SelectWidget.tsx +++ b/packages/chakra-ui/src/SelectWidget/SelectWidget.tsx @@ -1,10 +1,20 @@ import React from "react"; import { FormControl, FormLabel } from "@chakra-ui/react"; -import { processSelectValue, WidgetProps } from "@rjsf/utils"; +import { + FormContextType, + processSelectValue, + RJSFSchema, + StrictRJSFSchema, + WidgetProps, +} from "@rjsf/utils"; import { getChakra } from "../utils"; import { GroupBase, OptionsOrGroups, Select } from "chakra-react-select"; -const SelectWidget = (props: WidgetProps) => { +export default function SelectWidget< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>(props: WidgetProps) { const { schema, id, @@ -28,7 +38,7 @@ const SelectWidget = (props: WidgetProps) => { const _onMultiChange = (e: any) => { return onChange( - processSelectValue( + processSelectValue( schema, e.map((v: { label: any; value: any }) => { return v.value; @@ -39,16 +49,16 @@ const SelectWidget = (props: WidgetProps) => { }; const _onChange = (e: any) => { - return onChange(processSelectValue(schema, e.value, options)); + return onChange(processSelectValue(schema, e.value, options)); }; const _onBlur = ({ target: { value } }: React.FocusEvent) => - onBlur(id, processSelectValue(schema, value, options)); + onBlur(id, processSelectValue(schema, value, options)); const _onFocus = ({ target: { value }, }: React.FocusEvent) => - onFocus(id, processSelectValue(schema, value, options)); + onFocus(id, processSelectValue(schema, value, options)); const _valueLabelMap: any = {}; (enumOptions as any).map((option: any) => { @@ -99,6 +109,4 @@ const SelectWidget = (props: WidgetProps) => { /> ); -}; - -export default SelectWidget; +} diff --git a/packages/chakra-ui/src/SubmitButton/SubmitButton.tsx b/packages/chakra-ui/src/SubmitButton/SubmitButton.tsx index 02929703c2..130e256daf 100644 --- a/packages/chakra-ui/src/SubmitButton/SubmitButton.tsx +++ b/packages/chakra-ui/src/SubmitButton/SubmitButton.tsx @@ -1,8 +1,18 @@ import React from "react"; import { Box, Button } from "@chakra-ui/react"; -import { getSubmitButtonOptions, SubmitButtonProps } from "@rjsf/utils"; +import { + FormContextType, + getSubmitButtonOptions, + RJSFSchema, + StrictRJSFSchema, + SubmitButtonProps, +} from "@rjsf/utils"; -const SubmitButton = ({ uiSchema }: SubmitButtonProps) => { +export default function SubmitButton< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>({ uiSchema }: SubmitButtonProps) { const { submitText, norender, @@ -19,5 +29,4 @@ const SubmitButton = ({ uiSchema }: SubmitButtonProps) => { ); -}; -export default SubmitButton; +} diff --git a/packages/chakra-ui/src/Templates/Templates.ts b/packages/chakra-ui/src/Templates/Templates.ts index e8eef55a09..96f9ad9dbe 100644 --- a/packages/chakra-ui/src/Templates/Templates.ts +++ b/packages/chakra-ui/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/chakra-ui/src/TextareaWidget/TextareaWidget.tsx b/packages/chakra-ui/src/TextareaWidget/TextareaWidget.tsx index 79f9cb0848..38b75647cc 100644 --- a/packages/chakra-ui/src/TextareaWidget/TextareaWidget.tsx +++ b/packages/chakra-ui/src/TextareaWidget/TextareaWidget.tsx @@ -1,9 +1,18 @@ import React from "react"; import { FormControl, FormLabel, Textarea } from "@chakra-ui/react"; -import { WidgetProps } from "@rjsf/utils"; +import { + FormContextType, + RJSFSchema, + StrictRJSFSchema, + WidgetProps, +} from "@rjsf/utils"; import { getChakra } from "../utils"; -const TextareaWidget = ({ +export default function TextareaWidget< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>({ id, placeholder, value, @@ -20,7 +29,7 @@ const TextareaWidget = ({ required, rawErrors, registry, -}: WidgetProps) => { +}: WidgetProps) { const chakraProps = getChakra({ uiSchema }); const { schemaUtils } = registry; const displayLabel = @@ -62,6 +71,4 @@ const TextareaWidget = ({ /> ); -}; - -export default TextareaWidget; +} diff --git a/packages/chakra-ui/src/Theme/Theme.tsx b/packages/chakra-ui/src/Theme/Theme.tsx index ecfcdd5720..ec9d319569 100644 --- a/packages/chakra-ui/src/Theme/Theme.tsx +++ b/packages/chakra-ui/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/chakra-ui/src/TitleField/TitleField.tsx b/packages/chakra-ui/src/TitleField/TitleField.tsx index e9869f0dc6..e3f5a464d8 100644 --- a/packages/chakra-ui/src/TitleField/TitleField.tsx +++ b/packages/chakra-ui/src/TitleField/TitleField.tsx @@ -1,12 +1,21 @@ import React from "react"; -import { TitleFieldProps } from "@rjsf/utils"; +import { + FormContextType, + RJSFSchema, + StrictRJSFSchema, + TitleFieldProps, +} from "@rjsf/utils"; import { Box, Divider, Heading } from "@chakra-ui/react"; -const TitleField = ({ id, title /* , required */ }: TitleFieldProps) => ( - - {title} - - -); - -export default TitleField; +export default function TitleField< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>({ id, title }: TitleFieldProps) { + return ( + + {title} + + + ); +} diff --git a/packages/chakra-ui/src/UpDownWidget/UpDownWidget.tsx b/packages/chakra-ui/src/UpDownWidget/UpDownWidget.tsx index 847ab00f98..408f7c5726 100644 --- a/packages/chakra-ui/src/UpDownWidget/UpDownWidget.tsx +++ b/packages/chakra-ui/src/UpDownWidget/UpDownWidget.tsx @@ -8,10 +8,19 @@ import { FormControl, FormLabel, } from "@chakra-ui/react"; -import { WidgetProps } from "@rjsf/utils"; +import { + FormContextType, + RJSFSchema, + StrictRJSFSchema, + WidgetProps, +} from "@rjsf/utils"; import { getChakra } from "../utils"; -const UpDownWidget = (props: WidgetProps) => { +export default function UpDownWidget< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>(props: WidgetProps) { const { id, schema, @@ -69,6 +78,4 @@ const UpDownWidget = (props: WidgetProps) => { ); -}; - -export default UpDownWidget; +} diff --git a/packages/chakra-ui/src/Widgets/Widgets.ts b/packages/chakra-ui/src/Widgets/Widgets.ts index e8091b11e1..6d3f53d519 100644 --- a/packages/chakra-ui/src/Widgets/Widgets.ts +++ b/packages/chakra-ui/src/Widgets/Widgets.ts @@ -7,17 +7,29 @@ import RangeWidget from "../RangeWidget/RangeWidget"; import SelectWidget from "../SelectWidget/SelectWidget"; import TextareaWidget from "../TextareaWidget/TextareaWidget"; import UpDownWidget from "../UpDownWidget/UpDownWidget"; +import { + FormContextType, + RegistryWidgetsType, + RJSFSchema, + StrictRJSFSchema, +} from "@rjsf/utils"; -const widgets = { - AltDateTimeWidget, - AltDateWidget, - CheckboxWidget, - CheckboxesWidget, - RadioWidget, - RangeWidget, - SelectWidget, - TextareaWidget, - UpDownWidget, -}; +export function generateWidgets< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>(): RegistryWidgetsType { + return { + AltDateTimeWidget, + AltDateWidget, + CheckboxWidget, + CheckboxesWidget, + RadioWidget, + RangeWidget, + SelectWidget, + TextareaWidget, + UpDownWidget, + }; +} -export default widgets; +export default generateWidgets(); diff --git a/packages/chakra-ui/src/WrapIfAdditionalTemplate/WrapIfAdditionalTemplate.tsx b/packages/chakra-ui/src/WrapIfAdditionalTemplate/WrapIfAdditionalTemplate.tsx index dd82dab360..f8bd4e1a13 100644 --- a/packages/chakra-ui/src/WrapIfAdditionalTemplate/WrapIfAdditionalTemplate.tsx +++ b/packages/chakra-ui/src/WrapIfAdditionalTemplate/WrapIfAdditionalTemplate.tsx @@ -1,6 +1,9 @@ import React from "react"; import { ADDITIONAL_PROPERTY_FLAG, + FormContextType, + RJSFSchema, + StrictRJSFSchema, WrapIfAdditionalTemplateProps, } from "@rjsf/utils"; import { @@ -11,7 +14,11 @@ import { Input, } from "@chakra-ui/react"; -const WrapIfAdditionalTemplate = (props: WrapIfAdditionalTemplateProps) => { +export default function WrapIfAdditionalTemplate< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any +>(props: WrapIfAdditionalTemplateProps) { const { children, classNames, @@ -66,6 +73,4 @@ const WrapIfAdditionalTemplate = (props: WrapIfAdditionalTemplateProps) => { ); -}; - -export default WrapIfAdditionalTemplate; +} diff --git a/packages/chakra-ui/src/index.ts b/packages/chakra-ui/src/index.ts new file mode 100644 index 0000000000..a451912b75 --- /dev/null +++ b/packages/chakra-ui/src/index.ts @@ -0,0 +1,11 @@ +import Form from "./Form"; + +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 { __createChakraFrameProvider } from "./ChakraFrameProvider"; + +export type { ChakraUiSchema as UiSchema } from "./utils"; + +export default Form; diff --git a/packages/chakra-ui/src/index.tsx b/packages/chakra-ui/src/index.tsx deleted file mode 100644 index 3c05718180..0000000000 --- a/packages/chakra-ui/src/index.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import Form from "./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 { __createChakraFrameProvider } from "./ChakraFrameProvider"; - -export type { ChakraUiSchema as UiSchema } from "./utils"; - -export default Form;