Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 83 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,98 @@ should change the heading of the (upcoming) version to include a major version b
-->
# 6.0.0-beta.21

## @rjsf/antd

- Updated `ArrayFieldTemplate`, `ObjectFieldTemplate`, `TitleField` to add support for the new `optionalDataControl` feature
- Added the new `OptionalDataControlTemplate` to the theme, adding it to the `templates` list
- Updated the `ButtonTemplates` classes to fix up the props in `AntdIconButtonProps` and the `IconButton`s associated with them to better support the `OptionalDataControlTemplate`

## @rjsf/chakra-ui

- Updated `ArrayFieldTemplate`, `ObjectFieldTemplate`, `TitleField` to add support for the new `optionalDataControl` feature
- Added the new `OptionalDataControlTemplate` to the theme, adding it to the `templates` list
- Updated the `ButtonTemplates` classes to add `ChakraIconButtonProps` and the `IconButton`s associated with them to better support the `OptionalDataControlTemplate`

## @rjsf/core

- Added `initialDefaultsGenerated` flag to state, which indicates whether the initial generation of defaults has been completed
- Added `ObjectField` tests for additionalProperties with defaults
- Added `ObjectField` tests for additionalProperties with defaults
- Added a new `OptionalDataControlsField` to the `fields` that renders either undefined (when there is data for a readonly/disabled field) or gets the `OptionalDataControlsTemplate` and renders the `label` and potentially an `onAddClick` or `onRemoveClick` function
- Updated `ArrayField` and `ObjectField` to check whether it `shouldRenderOptionalData()` and if true, calls `ObjectDataControlsField` and passes the result to its associated render template as `optionalDataControl`
- Updated `ArrayFieldTemplate`, `ObjectFieldTemplate`, `TitleField` to add support for the new `optionalDataControl` feature
- Added the new `OptionalDataControlTemplate` to the theme, adding it to the `templates` list

## @rjsf/daisyui

- Updated `ArrayFieldTemplate`, `ArrayFieldTitleTemplate`, `ObjectFieldTemplate`, `TitleField` to add support for the new `optionalDataControl` feature
- Added the new `OptionalDataControlTemplate` to the theme, adding it to the `templates` list
- Updated the `ButtonTemplates` classes to better support the `OptionalDataControlTemplate`

## @rjsf/fluentui-rc

- Updated `ArrayFieldTemplate`, `ObjectFieldTemplate`, `TitleField` to add support for the new `optionalDataControl` feature
- Added the new `OptionalDataControlTemplate` to the theme, adding it to the `templates` list
- Updated the `ButtonTemplates` classes to add `FluentIconButtonProps` and the `IconButton`s associated with them to better support the `OptionalDataControlTemplate`

## @rjsf/mantine

- Updated `ArrayFieldTemplate`, `ObjectFieldTemplate`, `TitleField` to add support for the new `optionalDataControl` feature
- Added the new `OptionalDataControlTemplate` to the theme, adding it to the `templates` list

## @rjsf/mui

- Updated `ArrayFieldTemplate`, `ObjectFieldTemplate`, `TitleField` to add support for the new `optionalDataControl` feature
- Added the new `OptionalDataControlTemplate` to the theme, adding it to the `templates` list

## @rjsf/primereact

- Updated `ArrayFieldTemplate`, `ObjectFieldTemplate`, `TitleField` to add support for the new `optionalDataControl` feature
- Added the new `OptionalDataControlTemplate` to the theme, adding it to the `templates` list
- Updated the `ButtonTemplates` classes to add `PrimeIconButtonProps` and the `IconButton`s associated with them to better support the `OptionalDataControlTemplate`

## @rjsf/react-bootstrap

- Updated `ArrayFieldTemplate`, `ObjectFieldTemplate`, `TitleField` to add support for the new `optionalDataControl` feature
- Added the new `OptionalDataControlTemplate` to the theme, adding it to the `templates` list
- Updated the `ButtonTemplates` classes to add `BootstrapIconButtonProps` and the `IconButton`s associated with them to better support the `OptionalDataControlTemplate`

## @rjsf/semantic-ui

- Updated `ArrayFieldTemplate`, `ObjectFieldTemplate`, `TitleField` to add support for the new `optionalDataControl` feature
- Added the new `OptionalDataControlTemplate` to the theme, adding it to the `templates` list
- Updated the `ButtonTemplates` classes to add `SemanticIconButtonProps` and the `IconButton`s associated with them to better support the `OptionalDataControlTemplate`

## @rjsf/shadcn

- Updated `ArrayFieldTemplate`, `ObjectFieldTemplate`, `TitleField` to add support for the new `optionalDataControl` feature
- Added the new `OptionalDataControlTemplate` to the theme, adding it to the `templates` list
- Updated the `ButtonTemplates` classes to add `ShadIconButtonProps` and the `IconButton`s associated with them to better support the `OptionalDataControlTemplate`

## @rjsf/utils

- Updated `getDefaultFormState` to add a new `initialDefaultsGenerated` prop flag, along with type definitions, fixing uneditable & permanent defaults with additional properties [3759](https://github.com/rjsf-team/react-jsonschema-form/issues/3759)
- Updated `createSchemaUtils` definition to reflect addition of `initialDefaultsGenerated`
- Updated existing tests where `getDefaultFormState` is used to reflect addition of `initialDefaultsGenerated`

## @rjsf/docs

- Updated docs for `getDefaultFormState` to reflect addition of `initialDefaultsGenerated` prop
- Updated `types.ts` to support the new `Optional Data Controls` feature as follows:
- Added new `OptionalDataControlsTemplateProps` and refactored the common props from `ArrayFieldTemplateProps` and `ObjectFieldTemplateProps` into a new super type, `ContainerFieldTemplateProps`
- Added new `optionalDataControl?: ReactNode` to the `ArrayFieldTitleProps`, `TitleFieldProps` and `ContainerFieldTemplateProps`
- Updated `GlobalFormOptions` to add new `enableOptionalDataFieldForType?: ('object' | 'array')[]` prop
- Updated `SchemaUtilsType`'s `retrieveSchema()` function to add an additional, property `resolveAnyOfOrOneOfRefs?: boolean`
- Updated the `Templates` interface to add a new required template `OptionalDataControlsTemplate: ComponentType<OptionalDataControlsTemplateProps<T, S, F>>`
- Updated `retrieveSchema()` to add an additional property `resolveAnyOfOrOneOfRefs?: boolean` which causes `resolveAllSchemas()` to resolve `$ref`s inside of the options of `anyOf`/`oneOf` schemas
- Updated `getDefaultFormState` to fix an issue where optional array props had their default set to an empty array when they shouldn't be
- Updated the `TranslatableString` enum to add three new strings in support of the new feature: `OptionalObjectAdd`, `OptionalObjectRemove` and `OptionalObjectEmptyMsg`
- Added four new utility functions: `isFormDataAvailable()`, `isRootSchema()`, `optionalControlsId()`, and `shouldRenderOptionalField()`

## Dev / docs / playground

- Updated docs for `getDefaultFormState` to reflect addition of the `initialDefaultsGenerated` prop
- Updated `utility-function.me` docs to add documentation for the new functions
- Also updated docs for `retrieveSchema` and `SchemaUtilsType` for the new prop
- Updated `uiSchema.md` to add documentation for the new `enableOptionalDataFieldForType` prop
- Updated the `v6x upgrade guide.md` to document the new feature and utility functions and changes to `retrieveSchema`
- Updated the playground to add a new `Optional Data Controls` example
- Updated the snapshot and jest tests for `Form` to test the new `Optional Data Controls` feature

# 6.0.0-beta-20

Expand Down
12 changes: 7 additions & 5 deletions packages/antd/src/templates/ArrayFieldTemplate/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export default function ArrayFieldTemplate<
disabled,
fieldPathId,
items,
optionalDataControl,
onAddClick,
readonly,
registry,
Expand All @@ -56,6 +57,7 @@ export default function ArrayFieldTemplate<
registry,
uiOptions,
);
const showOptionalDataControlInTitle = !readonly && !disabled;
const { formContext } = registry;
// Button templates are not overridden in the uiSchema
const {
Expand Down Expand Up @@ -84,6 +86,7 @@ export default function ArrayFieldTemplate<
schema={schema}
uiSchema={uiSchema}
registry={registry}
optionalDataControl={showOptionalDataControlInTitle ? optionalDataControl : undefined}
/>
</Col>
)}
Expand All @@ -99,12 +102,11 @@ export default function ArrayFieldTemplate<
</Col>
)}
<Col className='row array-item-list' span={24}>
{items &&
items.map(({ key, ...itemProps }: ArrayFieldItemTemplateType<T, S, F>) => (
<ArrayFieldItemTemplate key={key} {...itemProps} />
))}
{!showOptionalDataControlInTitle ? optionalDataControl : undefined}
{items.map(({ key, ...itemProps }: ArrayFieldItemTemplateType<T, S, F>) => (
<ArrayFieldItemTemplate key={key} {...itemProps} />
))}
</Col>

{canAdd && (
<Col span={24}>
<Row gutter={rowGutter} justify='end'>
Expand Down
18 changes: 10 additions & 8 deletions packages/antd/src/templates/IconButton/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,24 @@ import {
} from '@rjsf/utils';
import { MouseEventHandler } from 'react';

// The `type` and `color` for IconButtonProps collides with props of `ButtonProps` so omit it to avoid Typescript issue
export type AntdIconButtonProps<
T = any,
S extends StrictRJSFSchema = RJSFSchema,
F extends FormContextType = any,
> = Omit<IconButtonProps<T, S, F>, 'type' | 'color'>;
> = IconButtonProps<T, S, F> & Pick<ButtonProps, 'block' | 'danger' | 'size'>;

export default function IconButton<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(
props: AntdIconButtonProps<T, S, F> & Omit<ButtonProps, 'onClick'>,
props: AntdIconButtonProps<T, S, F>,
) {
const { iconType = 'default', icon, onClick, uiSchema, registry, ...otherProps } = props;
const { iconType = 'default', icon, onClick, uiSchema, registry, color, ...otherProps } = props;
return (
<Button
onClick={onClick as MouseEventHandler<HTMLAnchorElement> & MouseEventHandler<HTMLButtonElement>}
type={iconType as ButtonProps['type']}
// @ts-expect-error TS2322, Because even casting as `ButtonProps['type']` has issues
type={iconType}
icon={icon}
color={color as ButtonProps['color']}
style={{ paddingTop: '4px' /* Center the button */ }}
{...otherProps}
/>
);
Expand All @@ -44,9 +46,9 @@ export function AddButton<T = any, S extends StrictRJSFSchema = RJSFSchema, F ex
return (
<IconButton
title={translateString(TranslatableString.AddItemButton)}
{...props}
block
iconType='primary'
block
{...props}
icon={<PlusCircleOutlined />}
/>
);
Expand Down Expand Up @@ -92,10 +94,10 @@ export function RemoveButton<T = any, S extends StrictRJSFSchema = RJSFSchema, F
return (
<IconButton
title={translateString(TranslatableString.RemoveButton)}
{...props}
danger
block={!!options.block}
iconType='primary'
{...props}
icon={<DeleteOutlined />}
/>
);
Expand Down
5 changes: 4 additions & 1 deletion packages/antd/src/templates/ObjectFieldTemplate/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export default function ObjectFieldTemplate<
formData,
fieldPathId,
onAddClick,
optionalDataControl,
properties,
readonly,
required,
Expand All @@ -57,6 +58,7 @@ export default function ObjectFieldTemplate<
uiOptions,
);
const { formContext } = registry;
const showOptionalDataControlInTitle = !readonly && !disabled;
// Button templates are not overridden in the uiSchema
const {
ButtonTemplates: { AddButton },
Expand Down Expand Up @@ -126,6 +128,7 @@ export default function ObjectFieldTemplate<
schema={schema}
uiSchema={uiSchema}
registry={registry}
optionalDataControl={showOptionalDataControlInTitle ? optionalDataControl : undefined}
/>
</Col>
)}
Expand All @@ -140,6 +143,7 @@ export default function ObjectFieldTemplate<
/>
</Col>
)}
{!showOptionalDataControlInTitle ? <Col span={24}>{optionalDataControl}</Col> : undefined}
{properties
.filter((e) => !e.hidden)
.map((element: ObjectFieldTemplatePropertyType) => (
Expand All @@ -148,7 +152,6 @@ export default function ObjectFieldTemplate<
</Col>
))}
</Row>

{canExpand(schema, uiSchema, formData) && (
<Col span={24}>
<Row gutter={rowGutter} justify='end'>
Expand Down
47 changes: 47 additions & 0 deletions packages/antd/src/templates/OptionalDataControlsTemplate/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { FormContextType, OptionalDataControlsTemplateProps, RJSFSchema, StrictRJSFSchema } from '@rjsf/utils';

import { AddButton, RemoveButton } from '../IconButton';

/** The OptionalDataControlsTemplate renders one of three different states. If
* there is an `onAddClick()` function, it renders the "Add" button. If there is
* an `onRemoveClick()` function, it renders the "Remove" button. Otherwise it
* renders the "No data found" section. All of them use the `label` as either
* the `title` of buttons or simply outputting it.
*
* @param props - The `OptionalDataControlsTemplateProps` for the template
*/
export default function OptionalDataControlsTemplate<
T = any,
S extends StrictRJSFSchema = RJSFSchema,
F extends FormContextType = any,
>(props: OptionalDataControlsTemplateProps<T, S, F>) {
const { id, registry, label, onAddClick, onRemoveClick } = props;
if (onAddClick) {
return (
<AddButton
id={id}
registry={registry}
className='rjsf-add-optional-data'
onClick={onAddClick}
title={label}
size='small'
iconType='default'
block={false}
/>
);
} else if (onRemoveClick) {
return (
<RemoveButton
id={id}
registry={registry}
className='rjsf-remove-optional-data'
onClick={onRemoveClick}
title={label}
size='small'
iconType='default'
block={false}
/>
);
}
return <em id={id}>{label}</em>;
}
21 changes: 18 additions & 3 deletions packages/antd/src/templates/TitleField/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import classNames from 'classnames';
import { FormContextType, TitleFieldProps, RJSFSchema, StrictRJSFSchema } from '@rjsf/utils';
import { ConfigProvider } from 'antd';
import { Col, Divider, Row, ConfigProvider } from 'antd';
import { useContext } from 'react';

/** The `TitleField` is the template to use to render the title of a field
Expand All @@ -12,6 +12,7 @@ export default function TitleField<T = any, S extends StrictRJSFSchema = RJSFSch
required,
registry,
title,
optionalDataControl,
}: TitleFieldProps<T, S, F>) {
const { formContext } = registry;
const { colon = true } = formContext;
Expand All @@ -38,8 +39,7 @@ export default function TitleField<T = any, S extends StrictRJSFSchema = RJSFSch
[`${prefixCls}-item-required`]: required,
[`${prefixCls}-item-no-colon`]: !colon,
});

return title ? (
let heading = title ? (
<label
className={labelClassName}
htmlFor={id}
Expand All @@ -49,4 +49,19 @@ export default function TitleField<T = any, S extends StrictRJSFSchema = RJSFSch
{labelChildren}
</label>
) : null;
if (optionalDataControl) {
heading = (
<Row>
<Col flex='auto'>{heading}</Col>
<Col flex='none'>{optionalDataControl}</Col>
</Row>
);
}

return (
<>
{heading}
<Divider size='small' style={{ marginBlock: '1px' /* pull the margin right up against the label */ }} />
</>
);
}
2 changes: 2 additions & 0 deletions packages/antd/src/templates/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import FieldTemplate from './FieldTemplate';
import GridTemplate from './GridTemplate';
import MultiSchemaFieldTemplate from './MultiSchemaFieldTemplate';
import ObjectFieldTemplate from './ObjectFieldTemplate';
import OptionalDataControlsTemplate from './OptionalDataControlsTemplate';
import SubmitButton from './SubmitButton';
import TitleField from './TitleField';
import WrapIfAdditionalTemplate from './WrapIfAdditionalTemplate';
Expand Down Expand Up @@ -39,6 +40,7 @@ export function generateTemplates<
GridTemplate,
MultiSchemaFieldTemplate,
ObjectFieldTemplate,
OptionalDataControlsTemplate,
TitleFieldTemplate: TitleField,
WrapIfAdditionalTemplate,
};
Expand Down
Loading