From bfd48ed56e0c1e28cf786445938544b91dae3097 Mon Sep 17 00:00:00 2001 From: Heath Chiavettone Date: Sat, 4 Oct 2025 13:26:24 -0700 Subject: [PATCH 1/6] Feature - Optional Data Controls Added new `Optional Data Controls` feature as follows: - In `@rjsf/utils`: - Updated existing tests where `getDefaultFormState` is used to reflect addition of `initialDefaultsGenerated` - 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>` - 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 three new utility functions: `isFormDataAvailable()`, `isRootSchema()` and `shouldRenderOptionalField()` - Added or updated tests to verify all of the new behaviors - In `@rjsf/core`: - 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 - In the rest of the themes: - 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` - In the doc directory: - 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 - Updated the `CHANGELOG.md` file accordingly --- CHANGELOG.md | 88 +++- .../templates/ArrayFieldTemplate/index.tsx | 12 +- .../antd/src/templates/IconButton/index.tsx | 18 +- .../templates/ObjectFieldTemplate/index.tsx | 5 +- .../OptionalDataControlsTemplate/index.tsx | 45 +++ .../antd/src/templates/TitleField/index.tsx | 21 +- packages/antd/src/templates/index.ts | 2 + .../test/__snapshots__/Array.test.tsx.snap | 381 +++++++++++++++--- .../test/__snapshots__/Form.test.tsx.snap | 9 + .../test/__snapshots__/GridSnap.test.tsx.snap | 54 +++ .../test/__snapshots__/Object.test.tsx.snap | 180 ++++++++- .../ArrayFieldTemplate/ArrayFieldTemplate.tsx | 28 +- .../src/IconButton/ChakraIconButton.tsx | 12 +- .../chakra-ui/src/IconButton/IconButton.tsx | 14 +- .../ObjectFieldTemplate.tsx | 6 +- .../OptionalDataControlsTemplate.tsx | 45 +++ .../src/OptionalDataControlsTemplate/index.ts | 2 + packages/chakra-ui/src/Templates/Templates.ts | 2 + .../chakra-ui/src/TitleField/TitleField.tsx | 15 +- .../test/__snapshots__/Array.test.tsx.snap | 6 +- .../test/__snapshots__/Form.test.tsx.snap | 12 +- .../test/__snapshots__/Object.test.tsx.snap | 12 +- packages/core/src/components/Form.tsx | 1 - .../core/src/components/fields/ArrayField.tsx | 45 ++- .../src/components/fields/ObjectField.tsx | 45 ++- .../fields/OptionalDataControlsField.tsx | 78 ++++ packages/core/src/components/fields/index.ts | 2 + .../templates/ArrayFieldTemplate.tsx | 4 + .../templates/ArrayFieldTitleTemplate.tsx | 3 +- .../templates/ObjectFieldTemplate.tsx | 7 +- .../OptionalDataControlsTemplate.tsx | 41 ++ .../src/components/templates/TitleField.tsx | 7 +- .../core/src/components/templates/index.ts | 2 + packages/core/test/ArrayField.test.jsx | 1 + .../ArrayFieldTemplate/ArrayFieldTemplate.tsx | 11 +- .../ArrayFieldTitleTemplate.tsx | 14 +- .../templates/ButtonTemplates/AddButton.tsx | 2 +- .../templates/ButtonTemplates/IconButton.tsx | 8 +- .../ObjectFieldTemplate.tsx | 4 + .../OptionalDataControlsTemplate.tsx | 39 ++ .../OptionalDataControlsTemplate/index.ts | 2 + packages/daisyui/src/templates/Templates.tsx | 2 + .../src/templates/TitleField/TitleField.tsx | 15 +- .../test/__snapshots__/Array.test.tsx.snap | 18 +- .../test/__snapshots__/Form.test.tsx.snap | 2 +- .../test/__snapshots__/Object.test.tsx.snap | 16 +- .../fluentui-rc/src/AddButton/AddButton.tsx | 2 +- .../ArrayFieldTemplate/ArrayFieldTemplate.tsx | 26 +- .../fluentui-rc/src/IconButton/IconButton.tsx | 18 +- .../ObjectFieldTemplate.tsx | 4 + .../OptionalDataControlsTemplate.tsx | 46 +++ .../src/OptionalDataControlsTemplate/index.ts | 2 + .../fluentui-rc/src/Templates/Templates.ts | 2 + .../fluentui-rc/src/TitleField/TitleField.tsx | 19 +- .../test/__snapshots__/Array.test.tsx.snap | 45 +++ .../test/__snapshots__/Form.test.tsx.snap | 5 + .../test/__snapshots__/GridSnap.test.tsx.snap | 30 ++ .../test/__snapshots__/Object.test.tsx.snap | 40 ++ .../src/templates/ArrayFieldTemplate.tsx | 13 +- .../src/templates/ObjectFieldTemplate.tsx | 5 +- .../OptionalDataControlsTemplate.tsx | 42 ++ packages/mantine/src/templates/TitleField.tsx | 15 +- packages/mantine/src/templates/index.ts | 2 + .../ArrayFieldTemplate/ArrayFieldTemplate.tsx | 26 +- .../ObjectFieldTemplate.tsx | 4 + .../OptionalDataControlsTemplate.tsx | 36 ++ .../src/OptionalDataControlsTemplate/index.ts | 2 + packages/mui/src/Templates/Templates.ts | 2 + packages/mui/src/TitleField/TitleField.tsx | 13 +- packages/playground/src/app.tsx | 8 +- packages/playground/src/samples/index.ts | 2 + .../src/samples/optionalDataControls.ts | 142 +++++++ .../ArrayFieldTemplate/ArrayFieldTemplate.tsx | 23 +- .../ArrayFieldTitleTemplate.tsx | 13 +- .../primereact/src/IconButton/IconButton.tsx | 22 +- .../ObjectFieldTemplate.tsx | 4 + .../OptionalDataControlsTemplate.tsx | 42 ++ .../src/OptionalDataControlsTemplate/index.ts | 2 + .../primereact/src/Templates/Templates.ts | 2 + .../primereact/src/TitleField/TitleField.tsx | 18 +- .../src/AddButton/AddButton.tsx | 2 +- .../ArrayFieldTemplate/ArrayFieldTemplate.tsx | 26 +- .../src/IconButton/IconButton.tsx | 18 +- .../ObjectFieldTemplate.tsx | 4 + .../OptionalDataControlsTemplate.tsx | 45 +++ .../src/OptionalDataControlsTemplate/index.ts | 2 + .../src/Templates/Templates.ts | 2 + .../src/TitleField/TitleField.tsx | 21 +- .../test/__snapshots__/Array.test.tsx.snap | 18 +- .../test/__snapshots__/Form.test.tsx.snap | 2 +- .../test/__snapshots__/GridSnap.test.tsx.snap | 12 +- .../test/__snapshots__/Object.test.tsx.snap | 16 +- .../semantic-ui/src/AddButton/AddButton.tsx | 8 +- .../ArrayFieldTemplate/ArrayFieldTemplate.tsx | 27 +- .../semantic-ui/src/IconButton/IconButton.tsx | 20 +- .../ObjectFieldTemplate.tsx | 4 + .../OptionalDataControlsTemplate.tsx | 42 ++ .../src/OptionalDataControlsTemplate/index.ts | 2 + .../semantic-ui/src/Templates/Templates.ts | 2 + .../semantic-ui/src/TitleField/TitleField.tsx | 22 +- .../ArrayFieldTemplate/ArrayFieldTemplate.tsx | 26 +- packages/shadcn/src/IconButton/IconButton.tsx | 16 +- .../ObjectFieldTemplate.tsx | 6 +- .../OptionalDataControlsTemplate.tsx | 43 ++ .../src/OptionalDataControlsTemplate/index.ts | 2 + packages/shadcn/src/Templates/Templates.ts | 2 + packages/shadcn/src/TitleField/TitleField.tsx | 12 +- packages/shadcn/src/components/ui/button.tsx | 1 + .../test/__snapshots__/Array.test.tsx.snap | 3 - .../test/__snapshots__/Form.test.tsx.snap | 6 - .../test/__snapshots__/Object.test.tsx.snap | 19 - packages/utils/src/createSchemaUtils.ts | 4 +- packages/utils/src/enums.ts | 6 + packages/utils/src/index.ts | 10 +- packages/utils/src/isFormDataAvailable.ts | 13 + packages/utils/src/isRootSchema.ts | 30 ++ .../utils/src/schema/getDefaultFormState.ts | 7 +- packages/utils/src/schema/retrieveSchema.ts | 44 +- .../utils/src/shouldRenderOptionalField.ts | 56 +++ packages/utils/src/types.ts | 61 ++- packages/utils/test/getTemplate.test.ts | 7 +- .../utils/test/isFormDataAvailable.test.ts | 19 + packages/utils/test/isRootSchema.test.ts | 84 ++++ .../test/schema/getDefaultFormStateTest.ts | 154 ++++++- .../utils/test/schema/retrieveSchemaTest.ts | 47 +++ .../test/shouldRenderOptionalField.test.ts | 124 ++++++ packages/utils/test/testUtils/testData.ts | 4 + 127 files changed, 2711 insertions(+), 405 deletions(-) create mode 100644 packages/antd/src/templates/OptionalDataControlsTemplate/index.tsx create mode 100644 packages/chakra-ui/src/OptionalDataControlsTemplate/OptionalDataControlsTemplate.tsx create mode 100644 packages/chakra-ui/src/OptionalDataControlsTemplate/index.ts create mode 100644 packages/core/src/components/fields/OptionalDataControlsField.tsx create mode 100644 packages/core/src/components/templates/OptionalDataControlsTemplate.tsx create mode 100644 packages/daisyui/src/templates/OptionalDataControlsTemplate/OptionalDataControlsTemplate.tsx create mode 100644 packages/daisyui/src/templates/OptionalDataControlsTemplate/index.ts create mode 100644 packages/fluentui-rc/src/OptionalDataControlsTemplate/OptionalDataControlsTemplate.tsx create mode 100644 packages/fluentui-rc/src/OptionalDataControlsTemplate/index.ts create mode 100644 packages/mantine/src/templates/OptionalDataControlsTemplate.tsx create mode 100644 packages/mui/src/OptionalDataControlsTemplate/OptionalDataControlsTemplate.tsx create mode 100644 packages/mui/src/OptionalDataControlsTemplate/index.ts create mode 100644 packages/playground/src/samples/optionalDataControls.ts create mode 100644 packages/primereact/src/OptionalDataControlsTemplate/OptionalDataControlsTemplate.tsx create mode 100644 packages/primereact/src/OptionalDataControlsTemplate/index.ts create mode 100644 packages/react-bootstrap/src/OptionalDataControlsTemplate/OptionalDataControlsTemplate.tsx create mode 100644 packages/react-bootstrap/src/OptionalDataControlsTemplate/index.ts create mode 100644 packages/semantic-ui/src/OptionalDataControlsTemplate/OptionalDataControlsTemplate.tsx create mode 100644 packages/semantic-ui/src/OptionalDataControlsTemplate/index.ts create mode 100644 packages/shadcn/src/OptionalDataControlsTemplate/OptionalDataControlsTemplate.tsx create mode 100644 packages/shadcn/src/OptionalDataControlsTemplate/index.ts create mode 100644 packages/utils/src/isFormDataAvailable.ts create mode 100644 packages/utils/src/isRootSchema.ts create mode 100644 packages/utils/src/shouldRenderOptionalField.ts create mode 100644 packages/utils/test/isFormDataAvailable.test.ts create mode 100644 packages/utils/test/isRootSchema.test.ts create mode 100644 packages/utils/test/shouldRenderOptionalField.test.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 22131cadb1..9287a30304 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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>` +- 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 three new utility functions: `isFormDataAvailable()`, `isRootSchema()` 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 diff --git a/packages/antd/src/templates/ArrayFieldTemplate/index.tsx b/packages/antd/src/templates/ArrayFieldTemplate/index.tsx index 213660f390..fe9f670c23 100644 --- a/packages/antd/src/templates/ArrayFieldTemplate/index.tsx +++ b/packages/antd/src/templates/ArrayFieldTemplate/index.tsx @@ -32,6 +32,7 @@ export default function ArrayFieldTemplate< disabled, fieldPathId, items, + optionalDataControl, onAddClick, readonly, registry, @@ -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 { @@ -84,6 +86,7 @@ export default function ArrayFieldTemplate< schema={schema} uiSchema={uiSchema} registry={registry} + optionalDataControl={showOptionalDataControlInTitle ? optionalDataControl : undefined} /> )} @@ -99,12 +102,11 @@ export default function ArrayFieldTemplate< )} - {items && - items.map(({ key, ...itemProps }: ArrayFieldItemTemplateType) => ( - - ))} + {!showOptionalDataControlInTitle ? optionalDataControl : undefined} + {items.map(({ key, ...itemProps }: ArrayFieldItemTemplateType) => ( + + ))} - {canAdd && ( diff --git a/packages/antd/src/templates/IconButton/index.tsx b/packages/antd/src/templates/IconButton/index.tsx index 82586117da..c7308e1a61 100644 --- a/packages/antd/src/templates/IconButton/index.tsx +++ b/packages/antd/src/templates/IconButton/index.tsx @@ -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, 'type' | 'color'>; +> = IconButtonProps & Pick; export default function IconButton( - props: AntdIconButtonProps & Omit, + props: AntdIconButtonProps, ) { - const { iconType = 'default', icon, onClick, uiSchema, registry, ...otherProps } = props; + const { iconType = 'default', icon, onClick, uiSchema, registry, color, ...otherProps } = props; return ( diff --git a/packages/react-bootstrap/src/ArrayFieldTemplate/ArrayFieldTemplate.tsx b/packages/react-bootstrap/src/ArrayFieldTemplate/ArrayFieldTemplate.tsx index cf110fe302..6bf9b76aab 100644 --- a/packages/react-bootstrap/src/ArrayFieldTemplate/ArrayFieldTemplate.tsx +++ b/packages/react-bootstrap/src/ArrayFieldTemplate/ArrayFieldTemplate.tsx @@ -17,8 +17,20 @@ export default function ArrayFieldTemplate< S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any, >(props: ArrayFieldTemplateProps) { - const { canAdd, disabled, fieldPathId, uiSchema, items, onAddClick, readonly, registry, required, schema, title } = - props; + const { + canAdd, + disabled, + fieldPathId, + uiSchema, + items, + optionalDataControl, + onAddClick, + readonly, + registry, + required, + schema, + title, + } = props; const uiOptions = getUiOptions(uiSchema); const ArrayFieldDescriptionTemplate = getTemplate<'ArrayFieldDescriptionTemplate', T, S, F>( 'ArrayFieldDescriptionTemplate', @@ -35,6 +47,7 @@ export default function ArrayFieldTemplate< registry, uiOptions, ); + const showOptionalDataControlInTitle = !readonly && !disabled; // Button templates are not overridden in the uiSchema const { ButtonTemplates: { AddButton }, @@ -50,6 +63,7 @@ export default function ArrayFieldTemplate< uiSchema={uiSchema} required={required} registry={registry} + optionalDataControl={showOptionalDataControlInTitle ? optionalDataControl : undefined} /> - {items && - items.map(({ key, ...itemProps }: ArrayFieldItemTemplateType) => ( - - ))} + {!showOptionalDataControlInTitle ? optionalDataControl : undefined} + {items.map(({ key, ...itemProps }: ArrayFieldItemTemplateType) => ( + + ))} {canAdd && ( diff --git a/packages/react-bootstrap/src/IconButton/IconButton.tsx b/packages/react-bootstrap/src/IconButton/IconButton.tsx index 9cb323e021..2685fe7b48 100644 --- a/packages/react-bootstrap/src/IconButton/IconButton.tsx +++ b/packages/react-bootstrap/src/IconButton/IconButton.tsx @@ -5,8 +5,14 @@ import { IoIosRemove } from '@react-icons/all-files/io/IoIosRemove'; import { AiOutlineArrowUp } from '@react-icons/all-files/ai/AiOutlineArrowUp'; import { AiOutlineArrowDown } from '@react-icons/all-files/ai/AiOutlineArrowDown'; +export type BootstrapIconButtonProps< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any, +> = IconButtonProps & ButtonProps; + export default function IconButton( - props: IconButtonProps & ButtonProps, + props: BootstrapIconButtonProps, ) { const { icon, iconType, className, uiSchema, registry, ...otherProps } = props; return ( @@ -17,7 +23,7 @@ export default function IconButton( - props: IconButtonProps, + props: BootstrapIconButtonProps, ) { const { registry: { translateString }, @@ -26,7 +32,7 @@ export function CopyButton( - props: IconButtonProps, + props: BootstrapIconButtonProps, ) { const { registry: { translateString }, @@ -37,7 +43,7 @@ export function MoveDownButton( - props: IconButtonProps, + props: BootstrapIconButtonProps, ) { const { registry: { translateString }, @@ -46,7 +52,7 @@ export function MoveUpButton( - props: IconButtonProps, + props: BootstrapIconButtonProps, ) { const { registry: { translateString }, @@ -54,8 +60,8 @@ export function RemoveButton} /> ); diff --git a/packages/react-bootstrap/src/ObjectFieldTemplate/ObjectFieldTemplate.tsx b/packages/react-bootstrap/src/ObjectFieldTemplate/ObjectFieldTemplate.tsx index 5bc9486ec1..b7cffed2b8 100644 --- a/packages/react-bootstrap/src/ObjectFieldTemplate/ObjectFieldTemplate.tsx +++ b/packages/react-bootstrap/src/ObjectFieldTemplate/ObjectFieldTemplate.tsx @@ -28,6 +28,7 @@ export default function ObjectFieldTemplate< fieldPathId, schema, formData, + optionalDataControl, onAddClick, disabled, readonly, @@ -40,6 +41,7 @@ export default function ObjectFieldTemplate< registry, uiOptions, ); + const showOptionalDataControlInTitle = !readonly && !disabled; // Button templates are not overridden in the uiSchema const { ButtonTemplates: { AddButton }, @@ -54,6 +56,7 @@ export default function ObjectFieldTemplate< schema={schema} uiSchema={uiSchema} registry={registry} + optionalDataControl={showOptionalDataControlInTitle ? optionalDataControl : undefined} /> )} {description && ( @@ -66,6 +69,7 @@ export default function ObjectFieldTemplate< /> )} + {!showOptionalDataControlInTitle ? optionalDataControl : undefined} {properties.map((element: any, index: number) => ( {element.content} diff --git a/packages/react-bootstrap/src/OptionalDataControlsTemplate/OptionalDataControlsTemplate.tsx b/packages/react-bootstrap/src/OptionalDataControlsTemplate/OptionalDataControlsTemplate.tsx new file mode 100644 index 0000000000..c81622de3c --- /dev/null +++ b/packages/react-bootstrap/src/OptionalDataControlsTemplate/OptionalDataControlsTemplate.tsx @@ -0,0 +1,45 @@ +import { FormContextType, OptionalDataControlsTemplateProps, RJSFSchema, StrictRJSFSchema } from '@rjsf/utils'; +import { BsPlus } from '@react-icons/all-files/bs/BsPlus'; + +import IconButton, { 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) { + const { registry, label, onAddClick, onRemoveClick } = props; + if (onAddClick) { + return ( + } + onClick={onAddClick} + title={label} + size='sm' + variant='secondary' + /> + ); + } else if (onRemoveClick) { + return ( + + ); + } + return {label}; +} diff --git a/packages/react-bootstrap/src/OptionalDataControlsTemplate/index.ts b/packages/react-bootstrap/src/OptionalDataControlsTemplate/index.ts new file mode 100644 index 0000000000..cf4d5a78ee --- /dev/null +++ b/packages/react-bootstrap/src/OptionalDataControlsTemplate/index.ts @@ -0,0 +1,2 @@ +export { default } from './OptionalDataControlsTemplate'; +export * from './OptionalDataControlsTemplate'; diff --git a/packages/react-bootstrap/src/Templates/Templates.ts b/packages/react-bootstrap/src/Templates/Templates.ts index 009dd99e57..f8df4df231 100644 --- a/packages/react-bootstrap/src/Templates/Templates.ts +++ b/packages/react-bootstrap/src/Templates/Templates.ts @@ -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'; @@ -41,6 +42,7 @@ export function generateTemplates< GridTemplate, MultiSchemaFieldTemplate, ObjectFieldTemplate, + OptionalDataControlsTemplate, TitleFieldTemplate: TitleField, WrapIfAdditionalTemplate, }; diff --git a/packages/react-bootstrap/src/TitleField/TitleField.tsx b/packages/react-bootstrap/src/TitleField/TitleField.tsx index 6aa9e8ed1b..9f93814cc9 100644 --- a/packages/react-bootstrap/src/TitleField/TitleField.tsx +++ b/packages/react-bootstrap/src/TitleField/TitleField.tsx @@ -1,15 +1,32 @@ import { FormContextType, getUiOptions, RJSFSchema, StrictRJSFSchema, TitleFieldProps } from '@rjsf/utils'; +import Row from 'react-bootstrap/Row'; +import Col from 'react-bootstrap/Col'; +import Container from 'react-bootstrap/Container'; export default function TitleField({ id, title, uiSchema, + optionalDataControl, }: TitleFieldProps) { const uiOptions = getUiOptions(uiSchema); + let heading =
{uiOptions.title || title}
; + if (optionalDataControl) { + heading = ( + + + {heading} + + {optionalDataControl} + + + + ); + } return (
-
{uiOptions.title || title}
-
+ {heading} +
); } diff --git a/packages/react-bootstrap/test/__snapshots__/Array.test.tsx.snap b/packages/react-bootstrap/test/__snapshots__/Array.test.tsx.snap index 1e0f62e92d..a0ee4521b7 100644 --- a/packages/react-bootstrap/test/__snapshots__/Array.test.tsx.snap +++ b/packages/react-bootstrap/test/__snapshots__/Array.test.tsx.snap @@ -968,7 +968,7 @@ exports[`with title and description array 1`] = ` Test field























) { +}: SemanticIconButtonProps) { const { translateString } = registry; return ( diff --git a/packages/semantic-ui/src/ArrayFieldTemplate/ArrayFieldTemplate.tsx b/packages/semantic-ui/src/ArrayFieldTemplate/ArrayFieldTemplate.tsx index 8a2ccaa3d3..7abe998320 100644 --- a/packages/semantic-ui/src/ArrayFieldTemplate/ArrayFieldTemplate.tsx +++ b/packages/semantic-ui/src/ArrayFieldTemplate/ArrayFieldTemplate.tsx @@ -30,6 +30,7 @@ export default function ArrayFieldTemplate< // classNames, This is not part of the type, so it is likely never passed in disabled, items, + optionalDataControl, onAddClick, // options, This is not part of the type, so it is likely never passed in readonly, @@ -61,6 +62,7 @@ export default function ArrayFieldTemplate< registry, uiOptions, ); + const showOptionalDataControlInTitle = !readonly && !disabled; // Button templates are not overridden in the uiSchema const { ButtonTemplates: { AddButton }, @@ -74,6 +76,7 @@ export default function ArrayFieldTemplate< uiSchema={uiSchema} required={required} registry={registry} + optionalDataControl={showOptionalDataControlInTitle ? optionalDataControl : undefined} />
- {items && - items.map(({ key, uiSchema: itemUiSchema = {}, ...props }: ArrayFieldItemTemplateType) => { - // Merge in the semantic props from the ArrayFieldTemplate into each of the items - const mergedUiSchema = { - ...itemUiSchema, - [UI_OPTIONS_KEY]: { - ...itemUiSchema[UI_OPTIONS_KEY], - semantic, - }, - }; - return ; - })} + {!showOptionalDataControlInTitle ? optionalDataControl : undefined} + {items.map(({ key, uiSchema: itemUiSchema = {}, ...props }: ArrayFieldItemTemplateType) => { + // Merge in the semantic props from the ArrayFieldTemplate into each of the items + const mergedUiSchema = { + ...itemUiSchema, + [UI_OPTIONS_KEY]: { + ...itemUiSchema[UI_OPTIONS_KEY], + semantic, + }, + }; + return ; + })}
{canAdd && (
( - props: IconButtonProps, +export type SemanticIconButtonProps< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any, +> = IconButtonProps & Omit; + +export default function IconButton( + props: SemanticIconButtonProps, ) { const { icon, iconType, color, className, uiSchema, registry, ...otherProps } = props; return ( @@ -16,10 +22,8 @@ function IconButton( - props: IconButtonProps, + props: SemanticIconButtonProps, ) { const { registry: { translateString }, @@ -28,7 +32,7 @@ export function CopyButton( - props: IconButtonProps, + props: SemanticIconButtonProps, ) { const { registry: { translateString }, @@ -37,7 +41,7 @@ export function MoveDownButton( - props: IconButtonProps, + props: SemanticIconButtonProps, ) { const { registry: { translateString }, @@ -46,7 +50,7 @@ export function MoveUpButton( - props: IconButtonProps, + props: SemanticIconButtonProps, ) { const { registry: { translateString }, diff --git a/packages/semantic-ui/src/ObjectFieldTemplate/ObjectFieldTemplate.tsx b/packages/semantic-ui/src/ObjectFieldTemplate/ObjectFieldTemplate.tsx index df0faeb1d8..7c24783f30 100644 --- a/packages/semantic-ui/src/ObjectFieldTemplate/ObjectFieldTemplate.tsx +++ b/packages/semantic-ui/src/ObjectFieldTemplate/ObjectFieldTemplate.tsx @@ -25,6 +25,7 @@ export default function ObjectFieldTemplate< >(props: ObjectFieldTemplateProps) { const { description, + optionalDataControl, onAddClick, title, properties, @@ -44,6 +45,7 @@ export default function ObjectFieldTemplate< registry, uiOptions, ); + const showOptionalDataControlInTitle = !readonly && !disabled; // Button templates are not overridden in the uiSchema const { ButtonTemplates: { AddButton }, @@ -58,6 +60,7 @@ export default function ObjectFieldTemplate< schema={schema} uiSchema={uiSchema} registry={registry} + optionalDataControl={showOptionalDataControlInTitle ? optionalDataControl : undefined} /> )} {description && ( @@ -69,6 +72,7 @@ export default function ObjectFieldTemplate< registry={registry} /> )} + {!showOptionalDataControlInTitle ? optionalDataControl : undefined} {properties.map((prop) => prop.content)} {canExpand(schema, uiSchema, formData) && ( diff --git a/packages/semantic-ui/src/OptionalDataControlsTemplate/OptionalDataControlsTemplate.tsx b/packages/semantic-ui/src/OptionalDataControlsTemplate/OptionalDataControlsTemplate.tsx new file mode 100644 index 0000000000..0ec72e258b --- /dev/null +++ b/packages/semantic-ui/src/OptionalDataControlsTemplate/OptionalDataControlsTemplate.tsx @@ -0,0 +1,42 @@ +import { FormContextType, OptionalDataControlsTemplateProps, RJSFSchema, StrictRJSFSchema } from '@rjsf/utils'; + +import { RemoveButton } from '../IconButton'; +import AddButton from '../AddButton'; + +/** 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) { + const { registry, label, onAddClick, onRemoveClick } = props; + if (onAddClick) { + return ( + + ); + } else if (onRemoveClick) { + return ( + + ); + } + return {label}; +} diff --git a/packages/semantic-ui/src/OptionalDataControlsTemplate/index.ts b/packages/semantic-ui/src/OptionalDataControlsTemplate/index.ts new file mode 100644 index 0000000000..cf4d5a78ee --- /dev/null +++ b/packages/semantic-ui/src/OptionalDataControlsTemplate/index.ts @@ -0,0 +1,2 @@ +export { default } from './OptionalDataControlsTemplate'; +export * from './OptionalDataControlsTemplate'; diff --git a/packages/semantic-ui/src/Templates/Templates.ts b/packages/semantic-ui/src/Templates/Templates.ts index ccc1a290f4..83037717ad 100644 --- a/packages/semantic-ui/src/Templates/Templates.ts +++ b/packages/semantic-ui/src/Templates/Templates.ts @@ -13,6 +13,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'; @@ -42,6 +43,7 @@ export function generateTemplates< GridTemplate, MultiSchemaFieldTemplate, ObjectFieldTemplate, + OptionalDataControlsTemplate, TitleFieldTemplate: TitleField, WrapIfAdditionalTemplate, }; diff --git a/packages/semantic-ui/src/TitleField/TitleField.tsx b/packages/semantic-ui/src/TitleField/TitleField.tsx index 0c37a6d5cc..2380a816e8 100644 --- a/packages/semantic-ui/src/TitleField/TitleField.tsx +++ b/packages/semantic-ui/src/TitleField/TitleField.tsx @@ -1,5 +1,5 @@ import { FormContextType, TitleFieldProps, RJSFSchema, StrictRJSFSchema } from '@rjsf/utils'; -import { Header } from 'semantic-ui-react'; +import { Grid, Header } from 'semantic-ui-react'; import { getSemanticProps } from '../util'; @@ -16,17 +16,27 @@ export default function TitleField) { const semanticProps = getSemanticProps({ uiSchema, defaultSchemaProps: DEFAULT_OPTIONS, }); - if (!title) { - return null; - } - return ( + let heading = title ? (
{title}
- ); + ) : null; + if (optionalDataControl) { + heading = ( + + + {heading} + + {optionalDataControl} + + ); + } + + return heading; } diff --git a/packages/shadcn/src/ArrayFieldTemplate/ArrayFieldTemplate.tsx b/packages/shadcn/src/ArrayFieldTemplate/ArrayFieldTemplate.tsx index ae181695bb..bbc14d03fe 100644 --- a/packages/shadcn/src/ArrayFieldTemplate/ArrayFieldTemplate.tsx +++ b/packages/shadcn/src/ArrayFieldTemplate/ArrayFieldTemplate.tsx @@ -18,8 +18,20 @@ export default function ArrayFieldTemplate< S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any, >(props: ArrayFieldTemplateProps) { - const { canAdd, disabled, fieldPathId, uiSchema, items, onAddClick, readonly, registry, required, schema, title } = - props; + const { + canAdd, + disabled, + fieldPathId, + uiSchema, + items, + optionalDataControl, + onAddClick, + readonly, + registry, + required, + schema, + title, + } = props; const uiOptions = getUiOptions(uiSchema); const ArrayFieldDescriptionTemplate = getTemplate<'ArrayFieldDescriptionTemplate', T, S, F>( 'ArrayFieldDescriptionTemplate', @@ -36,6 +48,7 @@ export default function ArrayFieldTemplate< registry, uiOptions, ); + const showOptionalDataControlInTitle = !readonly && !disabled; // Button templates are not overridden in the uiSchema const { ButtonTemplates: { AddButton }, @@ -51,6 +64,7 @@ export default function ArrayFieldTemplate< uiSchema={uiSchema} required={required} registry={registry} + optionalDataControl={showOptionalDataControlInTitle ? optionalDataControl : undefined} />
- {items && - items.map(({ key, ...itemProps }: ArrayFieldItemTemplateType) => ( - - ))} + {!showOptionalDataControlInTitle ? optionalDataControl : undefined} + {items.map(({ key, ...itemProps }: ArrayFieldItemTemplateType) => ( + + ))} {canAdd && (
= IconButtonProps & VariantProps; + /** Base button component that renders a Shadcn button with an icon for RJSF form actions. * This component serves as the foundation for other specialized buttons used in array operations. * It combines RJSF's IconButtonProps with Shadcn's ButtonProps to provide a consistent styling @@ -12,7 +18,7 @@ import { Button, buttonVariants } from '../components/ui/button'; * @param props - The combined props from RJSF IconButtonProps and Shadcn ButtonProps, including icon and event handlers */ export default function IconButton( - props: IconButtonProps & VariantProps, + props: ShadIconButtonProps, ) { const { icon, iconType, className, uiSchema, registry, ...otherProps } = props; return ( @@ -29,7 +35,7 @@ export default function IconButton( - props: IconButtonProps, + props: ShadIconButtonProps, ) { const { registry: { translateString }, @@ -46,7 +52,7 @@ export function CopyButton( - props: IconButtonProps, + props: ShadIconButtonProps, ) { const { registry: { translateString }, @@ -67,7 +73,7 @@ export function MoveDownButton( - props: IconButtonProps, + props: ShadIconButtonProps, ) { const { registry: { translateString }, @@ -89,7 +95,7 @@ export function MoveUpButton( - props: IconButtonProps, + props: ShadIconButtonProps, ) { const { registry: { translateString }, diff --git a/packages/shadcn/src/ObjectFieldTemplate/ObjectFieldTemplate.tsx b/packages/shadcn/src/ObjectFieldTemplate/ObjectFieldTemplate.tsx index e62e0aa12f..5a6977ea3d 100644 --- a/packages/shadcn/src/ObjectFieldTemplate/ObjectFieldTemplate.tsx +++ b/packages/shadcn/src/ObjectFieldTemplate/ObjectFieldTemplate.tsx @@ -30,6 +30,7 @@ export default function ObjectFieldTemplate< fieldPathId, schema, formData, + optionalDataControl, onAddClick, disabled, readonly, @@ -42,6 +43,7 @@ export default function ObjectFieldTemplate< registry, uiOptions, ); + const showOptionalDataControlInTitle = !readonly && !disabled; // Button templates are not overridden in the uiSchema const { ButtonTemplates: { AddButton }, @@ -56,6 +58,7 @@ export default function ObjectFieldTemplate< schema={schema} uiSchema={uiSchema} registry={registry} + optionalDataControl={showOptionalDataControlInTitle ? optionalDataControl : undefined} /> )} {description && ( @@ -68,9 +71,10 @@ export default function ObjectFieldTemplate< /> )}
+ {!showOptionalDataControlInTitle ? optionalDataControl : undefined} {properties.map((element: any, index: number) => (
-
{element.content}
+
{element.content}
))} {canExpand(schema, uiSchema, formData) ? ( diff --git a/packages/shadcn/src/OptionalDataControlsTemplate/OptionalDataControlsTemplate.tsx b/packages/shadcn/src/OptionalDataControlsTemplate/OptionalDataControlsTemplate.tsx new file mode 100644 index 0000000000..71861a6617 --- /dev/null +++ b/packages/shadcn/src/OptionalDataControlsTemplate/OptionalDataControlsTemplate.tsx @@ -0,0 +1,43 @@ +import { FormContextType, OptionalDataControlsTemplateProps, RJSFSchema, StrictRJSFSchema } from '@rjsf/utils'; +import { PlusCircle } from 'lucide-react'; + +import IconButton, { 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) { + const { registry, label, onAddClick, onRemoveClick } = props; + if (onAddClick) { + return ( + } + size='xs' + /> + ); + } else if (onRemoveClick) { + return ( + + ); + } + return {label}; +} diff --git a/packages/shadcn/src/OptionalDataControlsTemplate/index.ts b/packages/shadcn/src/OptionalDataControlsTemplate/index.ts new file mode 100644 index 0000000000..cf4d5a78ee --- /dev/null +++ b/packages/shadcn/src/OptionalDataControlsTemplate/index.ts @@ -0,0 +1,2 @@ +export { default } from './OptionalDataControlsTemplate'; +export * from './OptionalDataControlsTemplate'; diff --git a/packages/shadcn/src/Templates/Templates.ts b/packages/shadcn/src/Templates/Templates.ts index 27f0554ef4..da3079760e 100644 --- a/packages/shadcn/src/Templates/Templates.ts +++ b/packages/shadcn/src/Templates/Templates.ts @@ -12,6 +12,7 @@ import GridTemplate from '../GridTemplate'; import { CopyButton, MoveDownButton, MoveUpButton, RemoveButton } from '../IconButton'; import MultiSchemaFieldTemplate from '../MultiSchemaFieldTemplate'; import ObjectFieldTemplate from '../ObjectFieldTemplate'; +import OptionalDataControlsTemplate from '../OptionalDataControlsTemplate'; import SubmitButton from '../SubmitButton'; import TitleField from '../TitleField'; import WrapIfAdditionalTemplate from '../WrapIfAdditionalTemplate'; @@ -41,6 +42,7 @@ export function generateTemplates< GridTemplate, MultiSchemaFieldTemplate, ObjectFieldTemplate, + OptionalDataControlsTemplate, TitleFieldTemplate: TitleField, WrapIfAdditionalTemplate, }; diff --git a/packages/shadcn/src/TitleField/TitleField.tsx b/packages/shadcn/src/TitleField/TitleField.tsx index ea2b609bb3..60c26ee304 100644 --- a/packages/shadcn/src/TitleField/TitleField.tsx +++ b/packages/shadcn/src/TitleField/TitleField.tsx @@ -10,11 +10,21 @@ export default function TitleField) { const uiOptions = getUiOptions(uiSchema); + let heading =
{uiOptions.title || title}
; + if (optionalDataControl) { + heading = ( +
+
{heading}
+
{optionalDataControl}
+
+ ); + } return (
-
{uiOptions.title || title}
+ {heading}
); diff --git a/packages/shadcn/src/components/ui/button.tsx b/packages/shadcn/src/components/ui/button.tsx index 8ffe139756..9c973585d7 100644 --- a/packages/shadcn/src/components/ui/button.tsx +++ b/packages/shadcn/src/components/ui/button.tsx @@ -26,6 +26,7 @@ const buttonVariants = cva( default: 'h-9 px-4 py-2 has-[>svg]:px-3', sm: 'h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5', lg: 'h-10 rounded-md px-6 has-[>svg]:px-4', + xs: 'h-6 rounded-md gap-1 px-2 has-[>svg]:px-2', icon: 'size-9', }, }, diff --git a/packages/shadcn/test/__snapshots__/Array.test.tsx.snap b/packages/shadcn/test/__snapshots__/Array.test.tsx.snap index 0053238313..ce67c1cc6c 100644 --- a/packages/shadcn/test/__snapshots__/Array.test.tsx.snap +++ b/packages/shadcn/test/__snapshots__/Array.test.tsx.snap @@ -646,7 +646,6 @@ exports[`array fields empty errors array 1`] = `
-
@@ -911,7 +910,6 @@ exports[`array fields has errors 1`] = `
-
@@ -996,7 +994,6 @@ exports[`array fields no errors 1`] = `
-
diff --git a/packages/shadcn/test/__snapshots__/Form.test.tsx.snap b/packages/shadcn/test/__snapshots__/Form.test.tsx.snap index 2be3718a8f..0b609c583f 100644 --- a/packages/shadcn/test/__snapshots__/Form.test.tsx.snap +++ b/packages/shadcn/test/__snapshots__/Form.test.tsx.snap @@ -596,7 +596,6 @@ exports[`single fields field with description 1`] = `
-
@@ -683,7 +682,6 @@ exports[`single fields field with description in uiSchema 1`] = `
-
@@ -770,7 +768,6 @@ exports[`single fields field with markdown description 1`] = `
-
@@ -863,7 +860,6 @@ exports[`single fields field with markdown description in uiSchema 1`] = `
-
@@ -1275,7 +1271,6 @@ exports[`single fields hidden field 1`] = `
-
@@ -3628,7 +3623,6 @@ exports[`single fields title field 1`] = `
-
diff --git a/packages/shadcn/test/__snapshots__/Object.test.tsx.snap b/packages/shadcn/test/__snapshots__/Object.test.tsx.snap index 1f93e35a76..dbb83c2dd9 100644 --- a/packages/shadcn/test/__snapshots__/Object.test.tsx.snap +++ b/packages/shadcn/test/__snapshots__/Object.test.tsx.snap @@ -21,7 +21,6 @@ exports[`object fields additionalProperties 1`] = `
-
@@ -215,7 +214,6 @@ exports[`object fields object 1`] = `
-
@@ -259,7 +257,6 @@ exports[`object fields object 1`] = `
-
@@ -335,7 +332,6 @@ exports[`object fields show add button and fields if additionalProperties is tru
-
@@ -557,7 +553,6 @@ exports[`object fields with title and description additionalProperties 1`] = `
-
@@ -779,7 +774,6 @@ exports[`object fields with title and description from both additionalProperties
-
@@ -1001,7 +995,6 @@ exports[`object fields with title and description from both object 1`] = `
-
@@ -1057,7 +1050,6 @@ exports[`object fields with title and description from both object 1`] = `
-
@@ -1173,7 +1165,6 @@ exports[`object fields with title and description from uiSchema additionalProper
-
@@ -1395,7 +1386,6 @@ exports[`object fields with title and description from uiSchema object 1`] = `
-
@@ -1451,7 +1441,6 @@ exports[`object fields with title and description from uiSchema object 1`] = `
-
@@ -1567,7 +1556,6 @@ exports[`object fields with title and description from uiSchema show add button
-
@@ -1789,7 +1777,6 @@ exports[`object fields with title and description object 1`] = `
-
@@ -1845,7 +1832,6 @@ exports[`object fields with title and description object 1`] = `
-
@@ -1961,7 +1947,6 @@ exports[`object fields with title and description show add button and fields if
-
@@ -2155,7 +2140,6 @@ exports[`object fields with title and description with global label off addition
-
@@ -2343,7 +2327,6 @@ exports[`object fields with title and description with global label off object 1
-
@@ -2381,7 +2364,6 @@ exports[`object fields with title and description with global label off object 1
-
@@ -2451,7 +2433,6 @@ exports[`object fields with title and description with global label off show add
-
diff --git a/packages/utils/src/createSchemaUtils.ts b/packages/utils/src/createSchemaUtils.ts index 3cf181ee1c..6e0524e6cf 100644 --- a/packages/utils/src/createSchemaUtils.ts +++ b/packages/utils/src/createSchemaUtils.ts @@ -304,15 +304,17 @@ class SchemaUtils( this.validator, schema, this.rootSchema, rawFormData, this.experimental_customMergeAllOf, + resolveAnyOfOrOneOfRefs, ); } diff --git a/packages/utils/src/enums.ts b/packages/utils/src/enums.ts index 88a101c2fd..c9d0478904 100644 --- a/packages/utils/src/enums.ts +++ b/packages/utils/src/enums.ts @@ -45,6 +45,12 @@ export enum TranslatableString { DecrementAriaLabel = 'Decrease value by 1', /** Increment button aria label, used by UpDownWidget */ IncrementAriaLabel = 'Increase value by 1', + /** The label for the Add button in for an optional object field */ + OptionalObjectAdd = 'Add data for optional field', + /** The label for the Remove button in for an optional object field */ + OptionalObjectRemove = 'Remove data for optional field', + /** The label for when displaying a non-editable form with missing optional field data */ + OptionalObjectEmptyMsg = 'No data for optional field', // Strings with replaceable parameters /** Unknown field type reason, where %1 will be replaced with the type as provided by SchemaField */ UnknownFieldType = 'Unknown field type %1', diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index 832c29c82b..4a63464b95 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -15,9 +15,11 @@ import enumOptionsSelectValue from './enumOptionsSelectValue'; import enumOptionsValueForIndex from './enumOptionsValueForIndex'; import ErrorSchemaBuilder from './ErrorSchemaBuilder'; import findSchemaDefinition from './findSchemaDefinition'; +import getChangedFields from './getChangedFields'; import getDateElementProps, { type DateElementFormat } from './getDateElementProps'; import getDiscriminatorFieldFromSchema from './getDiscriminatorFieldFromSchema'; import getInputProps from './getInputProps'; +import getOptionMatchingSimpleDiscriminator from './getOptionMatchingSimpleDiscriminator'; import getSchemaType from './getSchemaType'; import getSubmitButtonOptions from './getSubmitButtonOptions'; import getTemplate from './getTemplate'; @@ -40,7 +42,9 @@ import { import isConstant from './isConstant'; import isCustomWidget from './isCustomWidget'; import isFixedItems from './isFixedItems'; +import isFormDataAvailable from './isFormDataAvailable'; import isObject from './isObject'; +import isRootSchema from './isRootSchema'; import labelValue from './labelValue'; import localToUTC from './localToUTC'; import lookupFromFormContext from './lookupFromFormContext'; @@ -55,6 +59,7 @@ import rangeSpec from './rangeSpec'; import replaceStringParameters from './replaceStringParameters'; import schemaRequiresTrueValue from './schemaRequiresTrueValue'; import shouldRender from './shouldRender'; +import shouldRenderOptionalField from './shouldRenderOptionalField'; import toConstant from './toConstant'; import toDateString from './toDateString'; import toErrorList from './toErrorList'; @@ -64,8 +69,6 @@ import unwrapErrorHandler from './unwrapErrorHandler'; import utcToLocal from './utcToLocal'; import validationDataMerge from './validationDataMerge'; import withIdRefPrefix from './withIdRefPrefix'; -import getOptionMatchingSimpleDiscriminator from './getOptionMatchingSimpleDiscriminator'; -import getChangedFields from './getChangedFields'; export * from './types'; export * from './enums'; @@ -117,7 +120,9 @@ export { isConstant, isCustomWidget, isFixedItems, + isFormDataAvailable, isObject, + isRootSchema, labelValue, localToUTC, lookupFromFormContext, @@ -134,6 +139,7 @@ export { schemaRequiresTrueValue, shallowEquals, shouldRender, + shouldRenderOptionalField, sortedJSONStringify, titleId, toConstant, diff --git a/packages/utils/src/isFormDataAvailable.ts b/packages/utils/src/isFormDataAvailable.ts new file mode 100644 index 0000000000..1a89d0dbf6 --- /dev/null +++ b/packages/utils/src/isFormDataAvailable.ts @@ -0,0 +1,13 @@ +import isNil from 'lodash/isNil'; +import isEmpty from 'lodash/isEmpty'; +import isObject from 'lodash/isObject'; + +/** Determines whether the given `formData` represents valid form data, such as a primitive type, or a non-empty object + * or array. + * + * @param formData - The data to check + * @returns - true if `formData` is not undefined, null, a primitive type or an empty object/array + */ +export default function isFormDataAvailable(formData?: T) { + return !isNil(formData) && (!isObject(formData) || Array.isArray(formData) || !isEmpty(formData)); +} diff --git a/packages/utils/src/isRootSchema.ts b/packages/utils/src/isRootSchema.ts new file mode 100644 index 0000000000..b95969cdc7 --- /dev/null +++ b/packages/utils/src/isRootSchema.ts @@ -0,0 +1,30 @@ +import isEqual from 'lodash/isEqual'; + +import { FormContextType, Registry, RJSFSchema, StrictRJSFSchema } from './types'; +import { REF_KEY } from './constants'; + +/** Helper to check whether a JSON schema object is the root schema. The schema is a root schema with root `properties` + * key or a root `$ref` key. If the `schemaToCompare` has a root `oneOf` property, the function will + * return false. Else if `schemaToCompare` and `rootSchema` are the same object or equal, the function will return + * `true`. Else if the `rootSchema` has a $ref, it will be resolved using `schemaUtils.resolveSchema` utility. If the + * resolved schema matches the `schemaToCompare` the function will return `true`. Otherwise, it will return false. + * + * @param registry - The `Registry` used to get the `rootSchema` and `schemaUtils` + * @param schemaToCompare - The JSON schema object to check. If `schemaToCompare` is an root schema, the + * function will return true. + * @returns - Flag indicating whether the `schemaToCompare` is the root schema + */ +export default function isRootSchema( + registry: Registry, + schemaToCompare: S, +): boolean { + const { rootSchema, schemaUtils } = registry; + if (isEqual(schemaToCompare, rootSchema)) { + return true; + } + if (REF_KEY in rootSchema) { + const resolvedSchema = schemaUtils.retrieveSchema(rootSchema); + return isEqual(schemaToCompare, resolvedSchema); + } + return false; +} diff --git a/packages/utils/src/schema/getDefaultFormState.ts b/packages/utils/src/schema/getDefaultFormState.ts index 25d73e1a94..5f26dfce15 100644 --- a/packages/utils/src/schema/getDefaultFormState.ts +++ b/packages/utils/src/schema/getDefaultFormState.ts @@ -200,6 +200,8 @@ interface ComputeDefaultsProps experimental_customMergeAllOf?: Experimental_CustomMergeAllOf; /** Optional flag, if true, indicates this schema was required in the parent schema. */ required?: boolean; + /** Optional flag, if true, indicates this schema was required because it is the root. */ + requiredAsRoot?: boolean; /** Optional flag, if true, It will merge defaults into formData. * The formData should take precedence unless it's not valid. This is useful when for example the value from formData does not exist in the schema 'enum' property, in such cases we take the value from the defaults because the value from the formData is not valid. */ @@ -586,6 +588,7 @@ export function getArrayDefaults = {}, @@ -671,7 +674,8 @@ export function getArrayDefaults(validator, schema, rootSchema) || schema.minItems <= defaultsLength ) { - arrayDefault = defaults ? defaults : emptyDefault; + // we don't want undefined defaults unless it is both not required or not required as root + arrayDefault = defaults || (!required && !requiredAsRoot) ? defaults : emptyDefault; } else { const defaultEntries: T[] = (defaults || []) as T[]; const fillerSchema: S = getInnerSchemaForArrayItem(schema, AdditionalItemsHandling.Invert); @@ -770,6 +774,7 @@ export default function getDefaultFormState< rawFormData: formData, shouldMergeDefaultsIntoFormData: true, initialDefaultsGenerated, + requiredAsRoot: true, }); if (schema.type !== 'object' && isObject(schema.default)) { diff --git a/packages/utils/src/schema/retrieveSchema.ts b/packages/utils/src/schema/retrieveSchema.ts index fbb5423658..f46d7b4a80 100644 --- a/packages/utils/src/schema/retrieveSchema.ts +++ b/packages/utils/src/schema/retrieveSchema.ts @@ -47,6 +47,7 @@ import isEmpty from 'lodash/isEmpty'; * @param [rootSchema={}] - The root schema that will be forwarded to all the APIs * @param [rawFormData] - The current formData, if any, to assist retrieving a schema * @param [experimental_customMergeAllOf] - Optional function that allows for custom merging of `allOf` schemas + * @param [resolveAnyOfOrOneOfRefs = false] - Optional flag indicating whether to resolved refs in anyOf/oneOf lists * @returns - The schema having its conditions, additional properties, references and dependencies resolved */ export default function retrieveSchema< @@ -59,6 +60,7 @@ export default function retrieveSchema< rootSchema: S = {} as S, rawFormData?: T, experimental_customMergeAllOf?: Experimental_CustomMergeAllOf, + resolveAnyOfOrOneOfRefs = false, ): S { return retrieveSchemaInternal( validator, @@ -68,6 +70,7 @@ export default function retrieveSchema< undefined, undefined, experimental_customMergeAllOf, + resolveAnyOfOrOneOfRefs, )[0]; } @@ -223,6 +226,7 @@ export function getMatchingPatternProperties( @@ -233,6 +237,7 @@ export function resolveSchema, + resolveAnyOfOrOneOfRefs?: boolean, ): S[] { const updatedSchemas = resolveReference( validator, @@ -242,6 +247,7 @@ export function resolveSchema 1 || updatedSchemas[0] !== schema) { // return the updatedSchemas array if it has either multiple schemas within it @@ -270,7 +276,7 @@ export function resolveSchema retrieveSchemaInternal( validator, @@ -304,6 +310,7 @@ export function resolveSchema( @@ -314,8 +321,9 @@ export function resolveReference, + resolveAnyOfOrOneOfRefs?: boolean, ): S[] { - const updatedSchema = resolveAllReferences(schema, rootSchema, recurseList); + const updatedSchema = resolveAllReferences(schema, rootSchema, recurseList, undefined, resolveAnyOfOrOneOfRefs); if (updatedSchema !== schema) { // Only call this if the schema was actually changed by the `resolveAllReferences()` function return retrieveSchemaInternal( @@ -326,6 +334,7 @@ export function resolveReference( @@ -344,6 +354,7 @@ export function resolveAllReferences( rootSchema: S, recurseList: string[], baseURI?: string, + resolveAnyOfOrOneOfRefs?: boolean, ): S { if (!isObject(schema)) { return schema; @@ -371,7 +382,7 @@ export function resolveAllReferences( resolvedSchema[PROPERTIES_KEY]!, (result, value, key: string) => { const childList: string[] = [...recurseList]; - result[key] = resolveAllReferences(value as S, rootSchema, childList, baseURI); + result[key] = resolveAllReferences(value as S, rootSchema, childList, baseURI, resolveAnyOfOrOneOfRefs); childrenLists.push(childList); }, {} as RJSFSchema, @@ -387,10 +398,30 @@ export function resolveAllReferences( ) { resolvedSchema = { ...resolvedSchema, - items: resolveAllReferences(resolvedSchema.items as S, rootSchema, recurseList, baseURI), + items: resolveAllReferences(resolvedSchema.items as S, rootSchema, recurseList, baseURI, resolveAnyOfOrOneOfRefs), }; } + if (resolveAnyOfOrOneOfRefs) { + let key: 'anyOf' | 'oneOf' | undefined; + let schemas: S[] | undefined; + if (ANY_OF_KEY in schema && Array.isArray(schema[ANY_OF_KEY])) { + key = ANY_OF_KEY; + schemas = resolvedSchema[ANY_OF_KEY] as S[]; + } else if (ONE_OF_KEY in schema && Array.isArray(schema[ONE_OF_KEY])) { + key = ONE_OF_KEY; + schemas = resolvedSchema[ONE_OF_KEY] as S[]; + } + if (key && schemas) { + resolvedSchema = { + ...resolvedSchema, + [key]: schemas.map((s: S) => + resolveAllReferences(s, rootSchema, recurseList, baseURI, resolveAnyOfOrOneOfRefs), + ), + }; + } + } + return deepEquals(schema, resolvedSchema) ? schema : resolvedSchema; } @@ -442,7 +473,7 @@ export function stubExistingAdditionalProperties< } } if (ADDITIONAL_PROPERTIES_KEY in schema && schema.additionalProperties !== false) { - let additionalProperties: S['additionalProperties'] = {}; + let additionalProperties: S['additionalProperties']; if (typeof schema.additionalProperties !== 'boolean') { if (REF_KEY in schema.additionalProperties!) { additionalProperties = retrieveSchema( @@ -494,6 +525,7 @@ export function stubExistingAdditionalProperties< * dependencies as a list of schemas * @param [recurseList=[]] - The optional, list of recursive references already processed * @param [experimental_customMergeAllOf] - Optional function that allows for custom merging of `allOf` schemas + * @param [resolveAnyOfOrOneOfRefs] - Optional flag indicating whether to resolved refs in anyOf/oneOf lists * @returns - The schema(s) resulting from having its conditions, additional properties, references and dependencies * resolved. Multiple schemas may be returned if `expandAllBranches` is true. */ @@ -509,6 +541,7 @@ export function retrieveSchemaInternal< expandAllBranches = false, recurseList: string[] = [], experimental_customMergeAllOf?: Experimental_CustomMergeAllOf, + resolveAnyOfOrOneOfRefs?: boolean, ): S[] { if (!isObject(schema)) { return [{} as S]; @@ -521,6 +554,7 @@ export function retrieveSchemaInternal< recurseList, rawFormData, experimental_customMergeAllOf, + resolveAnyOfOrOneOfRefs, ); return resolvedSchemas.flatMap((s: S) => { let resolvedSchema = s; diff --git a/packages/utils/src/shouldRenderOptionalField.ts b/packages/utils/src/shouldRenderOptionalField.ts new file mode 100644 index 0000000000..b7ee55dfda --- /dev/null +++ b/packages/utils/src/shouldRenderOptionalField.ts @@ -0,0 +1,56 @@ +import isObject from 'lodash/isObject'; +import uniq from 'lodash/uniq'; + +import { FormContextType, Registry, RJSFSchema, StrictRJSFSchema, UiSchema } from './types'; +import getSchemaType from './getSchemaType'; +import getUiOptions from './getUiOptions'; +import isRootSchema from './isRootSchema'; +import { ANY_OF_KEY, ONE_OF_KEY } from './constants'; + +/** Returns the unique list of schema types for all of the options in a anyOf/oneOf + * + * @param schemas - The list of schemas representing the XxxOf options + * @returns - All of the unique types contained within the oneOf list + */ +export function getSchemaTypesForXxxOf(schemas: S[]): string | string[] { + const allTypes: string[] = uniq( + schemas + .map((s) => (isObject(s) ? getSchemaType(s) : undefined)) + .flat() + .filter((t) => t !== undefined), + ); + return allTypes.length === 1 ? allTypes[0] : allTypes; +} + +/** Determines whether the field information from the combination of `schema` and `required` along with the + * `enableOptionalDataFieldForType` settings from the global UI options in the `registry` all indicate that this field + * should rendered with the optional field UI. + * + * @param registry - The `registry` object + * @param schema - The schema for the field + * @param required - Flag indicating whether the field is required + * @param [uiSchema] - The uiSchema for the field + * @return - true if the field should be rendered with the optional field UI, otherwise false + */ +export default function shouldRenderOptionalField< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any, +>(registry: Registry, schema: S, required: boolean, uiSchema?: UiSchema) { + const { enableOptionalDataFieldForType = [] } = getUiOptions(uiSchema, registry.globalUiOptions); + let schemaType: ReturnType>; + if (ANY_OF_KEY in schema && Array.isArray(schema[ANY_OF_KEY])) { + schemaType = getSchemaTypesForXxxOf(schema[ANY_OF_KEY] as S[]); + } else if (ONE_OF_KEY in schema && Array.isArray(schema[ONE_OF_KEY])) { + schemaType = getSchemaTypesForXxxOf(schema[ONE_OF_KEY] as S[]); + } else { + schemaType = getSchemaType(schema); + } + return ( + !isRootSchema(registry, schema) && + !required && + !!schemaType && + !Array.isArray(schemaType) && + !!enableOptionalDataFieldForType.find((val) => val === schemaType) + ); +} diff --git a/packages/utils/src/types.ts b/packages/utils/src/types.ts index ce368b5bcb..ca8464fd67 100644 --- a/packages/utils/src/types.ts +++ b/packages/utils/src/types.ts @@ -350,6 +350,8 @@ export type TemplatesType>; /** The template to use while rendering an object */ ObjectFieldTemplate: ComponentType>; + /** The template to use while rendering the Optional Data field controls */ + OptionalDataControlsTemplate: ComponentType>; /** The template to use for rendering the title of a field */ TitleFieldTemplate: ComponentType>; /** The template to use for rendering information about an unsupported field type in the schema */ @@ -398,6 +400,10 @@ export type GlobalUISchemaOptions = GenericObjectType & { /** Enables the displaying of description text that contains markdown */ enableMarkdownInDescription?: boolean; + /** Enables the rendering of the Optional Data Field UI for specific types of schemas, either `object`, `array` or + * both. To disable the Optional Data Field UI for a specific field, provide an empty array within the UI schema. + */ + enableOptionalDataFieldForType?: ('object' | 'array')[]; }; /** The set of options from the `Form` that will be available on the `Registry` for use in everywhere the `registry` is @@ -571,6 +577,8 @@ export type TitleFieldProps< title: string; /** A boolean value stating if the field is required */ required?: boolean; + /** Add optional data control */ + optionalDataControl?: ReactNode; }; /** The properties that are passed to a `DescriptionFieldTemplate` implementation */ @@ -595,6 +603,8 @@ export type ArrayFieldTitleProps< title?: string; /** The FieldPathId of the field in the hierarchy */ fieldPathId: FieldPathId; + /** Add optional data control */ + optionalDataControl?: ReactNode; }; /** The properties that are passed to a `ArrayFieldDescriptionTemplate` implementation */ @@ -684,24 +694,18 @@ export type ArrayFieldTemplateItemType< F extends FormContextType = any, > = ArrayFieldItemTemplateType; -/** The properties that are passed to an `ArrayFieldTemplate` implementation */ -export type ArrayFieldTemplateProps< +/** The common properties of the two container templates: `ArrayFieldTemplateProps` and `ObjectFieldTemplateProps` */ +export type ContainerFieldTemplateProps< T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any, > = RJSFBaseProps & { - /** A boolean value stating whether new elements can be added to the array */ - canAdd?: boolean; /** The className string */ className?: string; /** A boolean value stating if the array is disabled */ disabled?: boolean; /** The FieldPathId of the field in the hierarchy */ fieldPathId: FieldPathId; - /** An array of objects representing the items in the array */ - items: ArrayFieldItemTemplateType[]; - /** A function that adds a new item to the array */ - onAddClick: (event?: any) => void; /** A boolean value stating if the array is read-only */ readonly?: boolean; /** A boolean value stating if the array is required */ @@ -712,8 +716,24 @@ export type ArrayFieldTemplateProps< title: string; /** The formData for this array */ formData?: T; - /** The tree of errors for this field and its children */ + /** The optional validation errors in the form of an `ErrorSchema` */ errorSchema?: ErrorSchema; + /** The optional data control node to render within the ObjectFieldTemplate that controls */ + optionalDataControl?: ReactNode; +}; + +/** The properties that are passed to an `ArrayFieldTemplate` implementation */ +export type ArrayFieldTemplateProps< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any, +> = ContainerFieldTemplateProps & { + /** A boolean value stating whether new elements can be added to the array */ + canAdd?: boolean; + /** An array of objects representing the items in the array */ + items: ArrayFieldItemTemplateType[]; + /** A function that adds a new item to the array */ + onAddClick: (event?: any) => void; /** An array of strings listing all generated error messages from encountered errors for this widget */ rawErrors?: string[]; }; @@ -737,13 +757,9 @@ export type ObjectFieldTemplateProps< T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any, -> = RJSFBaseProps & { - /** A string value containing the title for the object */ - title: string; +> = ContainerFieldTemplateProps & { /** A string value containing the description for the object */ description?: string | ReactElement; - /** A boolean value stating if the object is disabled */ - disabled?: boolean; /** An array of objects representing the properties in the object */ properties: ObjectFieldTemplatePropertyType[]; /** Returns a function that adds a new property to the object (to be used with additionalProperties) */ @@ -762,6 +778,20 @@ export type ObjectFieldTemplateProps< formData?: T; }; +/** The properties that are passed to a OptionalDataControlsTemplate implementation */ +export type OptionalDataControlsTemplateProps< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any, +> = RJSFBaseProps & { + /** The label to use for the control */ + label: string; + /** Optional callback to call when clicking on the optional data control to add data */ + onAddClick?: () => void; + /** Optional callback to call when clicking on the optional data control to add data */ + onRemoveClick?: () => void; +}; + /** The properties that are passed to a WrapIfAdditionalTemplate implementation */ export type WrapIfAdditionalTemplateProps< T = any, @@ -1277,9 +1307,10 @@ export interface SchemaUtilsType null; @@ -44,13 +43,14 @@ const registry: Registry = { GridTemplate: FakeTemplate, MultiSchemaFieldTemplate: FakeTemplate, ObjectFieldTemplate: FakeTemplate, + OptionalDataControlsTemplate: FakeTemplate, TitleFieldTemplate: FakeTemplate, UnsupportedFieldTemplate: FakeTemplate, WrapIfAdditionalTemplate: FakeTemplate, }, fields: {}, widgets: {}, - globalFormOptions: { idPrefix: DEFAULT_ID_PREFIX, idSeparator: DEFAULT_ID_SEPARATOR }, + globalFormOptions: GLOBAL_FORM_OPTIONS, }; const uiOptions: UIOptionsType = { @@ -68,6 +68,7 @@ const uiOptions: UIOptionsType = { GridTemplate: CustomTemplate as unknown as UIOptionsType['GridTemplate'], MultiSchemaFieldTemplate: CustomTemplate as unknown as UIOptionsType['MultiSchemaFieldTemplate'], ObjectFieldTemplate: CustomTemplate as unknown as UIOptionsType['ObjectFieldTemplate'], + OptionalDataControlsTemplate: CustomTemplate as unknown as UIOptionsType['OptionalDataControlsTemplate'], TitleFieldTemplate: CustomTemplate as unknown as UIOptionsType['TitleFieldTemplate'], UnsupportedFieldTemplate: CustomTemplate as unknown as UIOptionsType['UnsupportedFieldTemplate'], WrapIfAdditionalTemplate: CustomTemplate as unknown as UIOptionsType['WrapIfAdditionalTemplate'], diff --git a/packages/utils/test/isFormDataAvailable.test.ts b/packages/utils/test/isFormDataAvailable.test.ts new file mode 100644 index 0000000000..57e1c24ab7 --- /dev/null +++ b/packages/utils/test/isFormDataAvailable.test.ts @@ -0,0 +1,19 @@ +import { isFormDataAvailable } from '../src'; + +const TEST_CASES = [ + { value: undefined, result: false }, + { value: null, result: false }, + { value: [], result: true }, + { value: {}, result: false }, + { value: true, result: true }, + { value: 1, result: true }, + { value: 'string', result: true }, + { value: [1], result: true }, + { value: { foo: true }, result: true }, +]; + +describe.each(TEST_CASES)('hasFormData(%s)', ({ value, result }) => { + test(`hasFormData(value) returns ${result}`, () => { + expect(isFormDataAvailable(value)).toEqual(result); + }); +}); diff --git a/packages/utils/test/isRootSchema.test.ts b/packages/utils/test/isRootSchema.test.ts new file mode 100644 index 0000000000..43bf707029 --- /dev/null +++ b/packages/utils/test/isRootSchema.test.ts @@ -0,0 +1,84 @@ +import { createSchemaUtils, englishStringTranslator, isRootSchema, Registry, RJSFSchema, TemplatesType } from '../src'; +import getTestValidator from './testUtils/getTestValidator'; +import { GLOBAL_FORM_OPTIONS } from './testUtils/testData'; + +const TEST_SCHEMA_TO_COMPARE: RJSFSchema = { + title: 'Sample Schema', + type: 'object', + definitions: { + root_ref_def: { + type: 'object', + properties: { + string_property: { type: 'string', default: 'merge_bams_settings' }, + }, + }, + }, + properties: { + string_property: { type: 'string', default: 'merge_bams_settings' }, + }, +}; +const TEST_ROOT_REF_SCHEMA: RJSFSchema = { + title: 'Sample Schema', + type: 'object', + definitions: { + root_ref_def: { + type: 'object', + properties: { + string_property: { type: 'string', default: 'merge_bams_settings' }, + }, + }, + }, + $ref: '#/definitions/root_ref_def', +}; + +function getRegistry(rootSchema: RJSFSchema): Registry { + return { + formContext: {}, + rootSchema, + schemaUtils: createSchemaUtils(getTestValidator({}), rootSchema), + translateString: englishStringTranslator, + fields: {}, + widgets: {}, + templates: {} as TemplatesType, + globalFormOptions: GLOBAL_FORM_OPTIONS, + }; +} + +describe('isRootSchema', () => { + it('returns true when passed the same schema objects', () => { + const registry = getRegistry(TEST_ROOT_REF_SCHEMA); + expect(isRootSchema(registry, TEST_ROOT_REF_SCHEMA)).toBe(true); + }); + it('returns true when passed a copy of the root schema object', () => { + const registry = getRegistry(TEST_ROOT_REF_SCHEMA); + expect(isRootSchema(registry, { ...TEST_ROOT_REF_SCHEMA })).toBe(true); + }); + it('returns false when passed different schemas, with ref in rootSchema', () => { + const registry = getRegistry(TEST_ROOT_REF_SCHEMA); + expect(isRootSchema(registry, { title: 'will not match' })).toBe(false); + }); + it('returns false when passed different schemas, without ref in rootSchema', () => { + const registry = getRegistry(TEST_SCHEMA_TO_COMPARE); + expect(isRootSchema(registry, { title: 'will not match' })).toBe(false); + }); + describe('root schema with root $ref', () => { + let retrieveSchemaSpy: jest.SpyInstance; + let registry: Registry; + beforeAll(() => { + registry = getRegistry(TEST_ROOT_REF_SCHEMA); + retrieveSchemaSpy = jest.spyOn(registry.schemaUtils, 'retrieveSchema'); + }); + it('returns true when passed the same schema but with a $ref property', () => { + expect(isRootSchema(registry, TEST_SCHEMA_TO_COMPARE)).toBe(true); + }); + it('calls resolveSchema with the root schema that was passed', () => { + expect(retrieveSchemaSpy).toHaveBeenCalledWith(TEST_ROOT_REF_SCHEMA); + }); + it('returns false when passed a different schema with a $ref property', () => { + expect(isRootSchema(registry, { ...TEST_SCHEMA_TO_COMPARE, title: 'different' })).toBe(false); + }); + it('calls resolveSchema again with the root schema that was passed', () => { + expect(retrieveSchemaSpy).toHaveBeenNthCalledWith(2, TEST_ROOT_REF_SCHEMA); + }); + }); +}); diff --git a/packages/utils/test/schema/getDefaultFormStateTest.ts b/packages/utils/test/schema/getDefaultFormStateTest.ts index 4d6f2ced8e..3e19c61e17 100644 --- a/packages/utils/test/schema/getDefaultFormStateTest.ts +++ b/packages/utils/test/schema/getDefaultFormStateTest.ts @@ -1837,25 +1837,55 @@ export default function getDefaultFormStateTest(testValidator: TestValidatorType ); }); - test('computeDefaults', () => { + test('computeDefaults, requiredAsRoot = true', () => { expect( computeDefaults(testValidator, schema, { rootSchema: schema, includeUndefinedValues, + requiredAsRoot: true, }), ).toEqual(expected); }); - test('getDefaultBasedOnSchemaType', () => { + test('computeDefaults, requiredAsRoot = false', () => { + expect( + computeDefaults(testValidator, schema, { + rootSchema: schema, + includeUndefinedValues, + }), + ).toBeUndefined(); + }); + + test('getDefaultBasedOnSchemaType, requiredAsRoot = true', () => { + expect( + getDefaultBasedOnSchemaType(testValidator, schema, { + rootSchema: schema, + includeUndefinedValues, + requiredAsRoot: true, + }), + ).toEqual(expected); + }); + + test('getDefaultBasedOnSchemaType, requiredAsRoot = false', () => { expect( getDefaultBasedOnSchemaType(testValidator, schema, { rootSchema: schema, includeUndefinedValues }), + ).toBeUndefined(); + }); + + test('getArrayDefaults, requiredAsRoot = true', () => { + expect( + getArrayDefaults(testValidator, schema, { + rootSchema: schema, + includeUndefinedValues, + requiredAsRoot: true, + }), ).toEqual(expected); }); - test('getArrayDefaults', () => { - expect(getArrayDefaults(testValidator, schema, { rootSchema: schema, includeUndefinedValues })).toEqual( - expected, - ); + test('getArrayDefaults, requiredAsRoot = false', () => { + expect( + getArrayDefaults(testValidator, schema, { rootSchema: schema, includeUndefinedValues }), + ).toBeUndefined(); }); }); @@ -1867,16 +1897,28 @@ export default function getDefaultFormStateTest(testValidator: TestValidatorType expect(getDefaultFormState(testValidator, schema)).toEqual(expected); }); - test('computeDefaults', () => { - expect(computeDefaults(testValidator, schema)).toEqual(expected); + test('computeDefaults, requiredAsRoot = true', () => { + expect(computeDefaults(testValidator, schema, { requiredAsRoot: true })).toEqual(expected); }); - test('getDefaultBasedOnSchemaType', () => { - expect(getDefaultBasedOnSchemaType(testValidator, schema)).toEqual(expected); + test('computeDefaults, requiredAsRoot = false', () => { + expect(computeDefaults(testValidator, schema)).toBeUndefined(); }); - test('getArrayDefaults', () => { - expect(getArrayDefaults(testValidator, schema)).toEqual(expected); + test('getDefaultBasedOnSchemaType, requiredAsRoot = true', () => { + expect(getDefaultBasedOnSchemaType(testValidator, schema, { requiredAsRoot: true })).toEqual(expected); + }); + + test('getDefaultBasedOnSchemaType, requiredAsRoot = false', () => { + expect(getDefaultBasedOnSchemaType(testValidator, schema)).toBeUndefined(); + }); + + test('getArrayDefaults, requiredAsRoot = true', () => { + expect(getArrayDefaults(testValidator, schema, { requiredAsRoot: true })).toEqual(expected); + }); + + test('getArrayDefaults, requiredAsRoot = false', () => { + expect(getArrayDefaults(testValidator, schema)).toBeUndefined(); }); }); }); @@ -2124,7 +2166,7 @@ export default function getDefaultFormStateTest(testValidator: TestValidatorType }); describe('AJV $data reference in const property in schema should not be treated as default/const value', () => { let schema: RJSFSchema; - it('test nested object with $data in the schema', () => { + it('test nested object with $data in the schema, optional array', () => { schema = { type: 'object', properties: { @@ -2185,6 +2227,70 @@ export default function getDefaultFormStateTest(testValidator: TestValidatorType }, }, }; + expect(computeDefaults(testValidator, schema, { rootSchema: schema })).toEqual({}); + }); + it('test nested object with $data in the schema, required array', () => { + schema = { + type: 'object', + properties: { + email: { + type: 'string', + title: 'E-mail', + format: 'email', + }, + emailConfirm: { + type: 'string', + const: { + $data: '/email', + }, + title: 'Confirm e-mail', + format: 'email', + }, + nestedObject: { + type: 'object', + properties: { + nestedEmail: { + type: 'string', + title: 'E-mail', + format: 'email', + }, + nestedEmailConfirm: { + type: 'string', + title: 'Confirm e-mail', + const: { + $data: '/nestedObject/nestedEmail', + }, + format: 'email', + }, + }, + }, + nestedObjectConfirm: { + type: 'object', + properties: { + nestedEmailConfirm: { + type: 'string', + title: 'Confirm e-mail', + const: { + $data: '/nestedObject/nestedEmail', + }, + format: 'email', + }, + }, + }, + arrayConfirm: { + type: 'array', + items: { + type: 'string', + title: 'Confirm e-mail', + const: { + $data: '/nestedObject/nestedEmail', + }, + format: 'email', + }, + }, + }, + required: ['arrayConfirm'], + }; expect( computeDefaults(testValidator, schema, { rootSchema: schema, @@ -2199,7 +2305,7 @@ export default function getDefaultFormStateTest(testValidator: TestValidatorType rootSchema: schema, experimental_defaultFormStateBehavior: { emptyObjectFields: 'populateRequiredDefaults' }, }), - ).toEqual({}); + ).toEqual({ arrayConfirm: [] }); }); it('test nested object with $data in the schema and emptyObjectFields set to skipEmptyDefaults', () => { expect( @@ -3874,7 +3980,7 @@ export default function getDefaultFormStateTest(testValidator: TestValidatorType array: ['foo', 'qux'], }); }); - it('returns empty defaults when no item defaults are defined', () => { + it('returns empty defaults when no item defaults are defined for required array', () => { const schema: RJSFSchema = { type: 'object', properties: { @@ -3888,11 +3994,29 @@ export default function getDefaultFormStateTest(testValidator: TestValidatorType }, }, }, + required: ['array'], }; expect(getDefaultFormState(testValidator, schema, {})).toEqual({ array: [], }); }); + it('returns undefined defaults when no item defaults are defined for optional array', () => { + const schema: RJSFSchema = { + type: 'object', + properties: { + array: { + type: 'array', + minItems: 1, + uniqueItems: true, + items: { + type: 'string', + enum: ['foo', 'bar', 'fuzz', 'qux'], + }, + }, + }, + }; + expect(getDefaultFormState(testValidator, schema, {})).toEqual({}); + }); it('returns explicit defaults along with auto-fill when provided', () => { const schema: RJSFSchema = { type: 'object', diff --git a/packages/utils/test/schema/retrieveSchemaTest.ts b/packages/utils/test/schema/retrieveSchemaTest.ts index a2a87a7f97..705ada8146 100644 --- a/packages/utils/test/schema/retrieveSchemaTest.ts +++ b/packages/utils/test/schema/retrieveSchemaTest.ts @@ -2270,5 +2270,52 @@ export default function retrieveSchemaTest(testValidator: TestValidatorType) { }); }); }); + describe('retrieveSchema() with resolveAnyOfOrOneOfRefs', () => { + it('resolves simple ref with no anyOf or oneOfs when false', () => { + const priceSchema: RJSFSchema = SUPER_SCHEMA.properties?.price as RJSFSchema; + expect(retrieveSchema(testValidator, priceSchema, SUPER_SCHEMA, {}, undefined)).toEqual({ + ...(SUPER_SCHEMA.definitions?.price as RJSFSchema), + }); + }); + it('resolves simple ref with no anyOf or oneOfs when true', () => { + const priceSchema: RJSFSchema = SUPER_SCHEMA.properties?.price as RJSFSchema; + expect(retrieveSchema(testValidator, priceSchema, SUPER_SCHEMA, {}, undefined, true)).toEqual({ + ...(SUPER_SCHEMA.definitions?.price as RJSFSchema), + }); + }); + it('does not resolves the references inside of anyOfs when false', () => { + const anyOfSchema: RJSFSchema = SUPER_SCHEMA.properties?.multi as RJSFSchema; + expect(retrieveSchema(testValidator, anyOfSchema, SUPER_SCHEMA, {}, undefined)).toEqual(anyOfSchema); + }); + it('resolves the references inside of anyOfs when true', () => { + const anyOfSchema: RJSFSchema = SUPER_SCHEMA.properties?.multi as RJSFSchema; + expect(retrieveSchema(testValidator, anyOfSchema, SUPER_SCHEMA, {}, undefined, true)).toEqual({ + ...anyOfSchema, + anyOf: [ + { + ...(SUPER_SCHEMA.definitions?.foo as RJSFSchema), + }, + ], + }); + }); + it('does not resolves the references inside of oneOfs when false', () => { + const oneOfSchema: RJSFSchema = SUPER_SCHEMA.properties?.single as RJSFSchema; + expect(retrieveSchema(testValidator, oneOfSchema, SUPER_SCHEMA, {}, undefined, false)).toEqual(oneOfSchema); + }); + it('resolves the references inside of oneOfs when true', () => { + const oneOfSchema: RJSFSchema = SUPER_SCHEMA.properties?.single as RJSFSchema; + expect(retrieveSchema(testValidator, oneOfSchema, SUPER_SCHEMA, {}, undefined, true)).toEqual({ + ...oneOfSchema, + oneOf: [ + { + ...(SUPER_SCHEMA.definitions?.choice1 as RJSFSchema), + }, + { + ...(SUPER_SCHEMA.definitions?.choice2 as RJSFSchema), + }, + ], + }); + }); + }); }); } diff --git a/packages/utils/test/shouldRenderOptionalField.test.ts b/packages/utils/test/shouldRenderOptionalField.test.ts new file mode 100644 index 0000000000..12751b9f47 --- /dev/null +++ b/packages/utils/test/shouldRenderOptionalField.test.ts @@ -0,0 +1,124 @@ +import { + createSchemaUtils, + englishStringTranslator, + shouldRenderOptionalField, + Registry, + RJSFSchema, + TemplatesType, +} from '../src'; +import { getSchemaTypesForXxxOf } from '../src/shouldRenderOptionalField'; +import getTestValidator from './testUtils/getTestValidator'; +import { GlobalUISchemaOptions } from '../lib'; +import { GLOBAL_FORM_OPTIONS } from './testUtils/testData'; + +const TEST_ROOT_SCHEMA: RJSFSchema = { + type: 'object', + properties: { + foo: { + type: 'string', + }, + }, +}; +const ONE_OF_SCHEMA_OBJECT: RJSFSchema = { + oneOf: [ + TEST_ROOT_SCHEMA, + { + type: 'object', + properties: { + bar: { + type: 'string', + }, + }, + }, + ], +}; +const ONE_OF_SCHEMA_ARRAY: RJSFSchema = { + oneOf: [ + { + type: 'array', + items: { type: 'string' }, + }, + { + type: 'array', + items: { type: 'number' }, + }, + ], +}; +const ONE_OF_SCHEMA_MIXED: RJSFSchema = { + oneOf: [ + TEST_ROOT_SCHEMA, + { + type: 'array', + items: { type: 'string' }, + }, + false, + { type: 'string' }, + ], +}; +const ANY_OF_SCHEMA_ARRAY: RJSFSchema = { + anyOf: ONE_OF_SCHEMA_ARRAY.oneOf, +}; + +const registry: Registry = { + formContext: {}, + rootSchema: TEST_ROOT_SCHEMA, + schemaUtils: createSchemaUtils(getTestValidator({}), TEST_ROOT_SCHEMA), + translateString: englishStringTranslator, + fields: {}, + widgets: {}, + templates: {} as TemplatesType, + globalFormOptions: GLOBAL_FORM_OPTIONS, +}; + +describe('getSchemaTypesForXxxOf', () => { + test('empty list', () => { + expect(getSchemaTypesForXxxOf([])).toEqual([]); + }); + test('all objects', () => { + expect(getSchemaTypesForXxxOf(ONE_OF_SCHEMA_OBJECT.oneOf as RJSFSchema[])).toEqual('object'); + }); + test('all arrays', () => { + expect(getSchemaTypesForXxxOf(ONE_OF_SCHEMA_ARRAY.oneOf as RJSFSchema[])).toEqual('array'); + }); + test('mixed', () => { + expect(getSchemaTypesForXxxOf(ONE_OF_SCHEMA_MIXED.oneOf as RJSFSchema[])).toEqual(['object', 'array', 'string']); + }); +}); + +describe('shouldRenderOptionalField()', () => { + test('is root schema returns false', () => { + expect(shouldRenderOptionalField(registry, TEST_ROOT_SCHEMA, false)).toBe(false); + }); + test('required returns false', () => { + expect(shouldRenderOptionalField(registry, {}, true)).toBe(false); + }); + test('schemaType undefined returns false', () => { + expect(shouldRenderOptionalField(registry, {}, false)).toBe(false); + }); + test('schemaType array returns false', () => { + expect(shouldRenderOptionalField(registry, { type: ['boolean', 'array'] }, false)).toBe(false); + }); + test('schemaType is not in enableOptionalDataFieldForType returns false', () => { + expect(shouldRenderOptionalField(registry, { type: 'array' }, false)).toBe(false); + }); + test('schemaType is NOT in enableOptionalDataFieldForType returns false', () => { + const globalUiOptions: GlobalUISchemaOptions = { enableOptionalDataFieldForType: ['object'] }; + expect(shouldRenderOptionalField({ ...registry, globalUiOptions }, { type: 'array' }, false)).toBe(false); + }); + test('schemaType IS in enableOptionalDataFieldForType returns true', () => { + const globalUiOptions: GlobalUISchemaOptions = { enableOptionalDataFieldForType: ['object'] }; + expect(shouldRenderOptionalField({ ...registry, globalUiOptions }, { type: 'object' }, false)).toBe(true); + }); + test('schemaType for single-type oneOf IS in enableOptionalDataFieldForType returns true', () => { + const globalUiOptions: GlobalUISchemaOptions = { enableOptionalDataFieldForType: ['object'] }; + expect(shouldRenderOptionalField({ ...registry, globalUiOptions }, ONE_OF_SCHEMA_OBJECT, false)).toBe(true); + }); + test('schemaType for single-type anyOf IS in enableOptionalDataFieldForType returns true', () => { + const globalUiOptions: GlobalUISchemaOptions = { enableOptionalDataFieldForType: ['array'] }; + expect(shouldRenderOptionalField({ ...registry, globalUiOptions }, ANY_OF_SCHEMA_ARRAY, false)).toBe(true); + }); + test('schemaType for mixed-type oneOf IS in enableOptionalDataFieldForType returns true', () => { + const globalUiOptions: GlobalUISchemaOptions = { enableOptionalDataFieldForType: ['array'] }; + expect(shouldRenderOptionalField({ ...registry, globalUiOptions }, ONE_OF_SCHEMA_MIXED, false)).toBe(false); + }); +}); diff --git a/packages/utils/test/testUtils/testData.ts b/packages/utils/test/testUtils/testData.ts index 52d3b85918..8df9d2d46a 100644 --- a/packages/utils/test/testUtils/testData.ts +++ b/packages/utils/test/testUtils/testData.ts @@ -3,6 +3,8 @@ import deepFreeze from 'deep-freeze-es6'; import { ANY_OF_KEY, + DEFAULT_ID_PREFIX, + DEFAULT_ID_SEPARATOR, EnumOptionsType, ErrorSchema, ErrorSchemaBuilder, @@ -12,6 +14,8 @@ import { RJSFValidationError, } from '../../src'; +export const GLOBAL_FORM_OPTIONS = { idPrefix: DEFAULT_ID_PREFIX, idSeparator: DEFAULT_ID_SEPARATOR }; + export const oneOfData = { name: 'second_option', flag: true, From 533132d1d11b54d993a0e5aa89e5c62434cadbd7 Mon Sep 17 00:00:00 2001 From: Heath Chiavettone Date: Sat, 4 Oct 2025 20:32:52 -0700 Subject: [PATCH 2/6] - Added the snapsnot test for `FormTest.tsx` and ran it on all the themes --- .../test/__snapshots__/Form.test.tsx.snap | 9876 ++++++++++++ .../test/__snapshots__/Form.test.tsx.snap | 10904 +++++++++++++ .../test/__snapshots__/FormSnap.test.tsx.snap | 2560 +++ .../test/__snapshots__/Form.test.tsx.snap | 6112 ++++++++ .../test/__snapshots__/Form.test.tsx.snap | 4833 ++++++ .../test/__snapshots__/Form.test.tsx.snap | 13067 ++++++++++++++++ .../mui/test/__snapshots__/Form.test.tsx.snap | 11822 ++++++++++++++ .../test/__snapshots__/Form.test.tsx.snap | 5534 +++++++ .../test/__snapshots__/Form.test.tsx.snap | 5352 +++++++ .../test/__snapshots__/Form.test.tsx.snap | 3373 ++++ .../test/__snapshots__/Form.test.tsx.snap | 5366 +++++++ packages/snapshot-tests/src/formTests.tsx | 217 +- 12 files changed, 79015 insertions(+), 1 deletion(-) diff --git a/packages/antd/test/__snapshots__/Form.test.tsx.snap b/packages/antd/test/__snapshots__/Form.test.tsx.snap index e3eea0e792..f8e5668fe4 100644 --- a/packages/antd/test/__snapshots__/Form.test.tsx.snap +++ b/packages/antd/test/__snapshots__/Form.test.tsx.snap @@ -2449,6 +2449,9882 @@ exports[`single fields number field 1`] = ` `; +exports[`single fields optional data controls does not show optional controls when not turned on in uiSchema and no formData 1`] = ` +
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+ +
+
+
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+ +
+
+
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+ +
+
+
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+ +
+
+
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+ + + + + + Option 1 + + +
+ + + + + +
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+ +
+
+
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+`; + +exports[`single fields optional data controls does not show optional controls when not turned on in uiSchema, readonly and no formData 1`] = ` +
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+ +
+
+
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+ +
+
+
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+ +
+
+
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+ +
+
+
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+ + + + + + Option 1 + + +
+ + + + + +
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+ +
+
+
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+`; + +exports[`single fields optional data controls shows "add" and "remove" optional controls when turned on in uiSchema and formData 1`] = ` +
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+ +
+
+
+
+
+
+
+
+
+ +
+
+
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+ +
+
+
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+ +
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+ + + + +
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+ +
+
+
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+ + + + + + Option 1 + + +
+ + + + + +
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+ +
+
+
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+`; + +exports[`single fields optional data controls shows "add" and "remove" optional controls when turned on in uiSchema, readonly and formData 1`] = ` +
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+ +
+
+
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+ + No data for optional field + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+ +
+
+
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+ + No data for optional field + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+ +
+
+
+
+ + + + +
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+ +
+
+
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+ + + + + + Option 1 + + +
+ + + + + +
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+ +
+
+
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+`; + +exports[`single fields optional data controls shows "add" optional controls when turned on in uiSchema and no formData 1`] = ` +
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+ +
+
+
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+ + + + + + Option 1 + + +
+ + + + + +
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+ +
+
+
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+`; + +exports[`single fields optional data controls shows "add" optional controls when turned on in uiSchema, disabled and no formData 1`] = ` +
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+ + No data for optional field + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+ + No data for optional field + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+ +
+
+
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+ + + + + + Option 1 + + +
+ + + + + +
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+ +
+
+
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+`; + exports[`single fields password field 1`] = `
`; +exports[`single fields optional data controls does not show optional controls when not turned on in uiSchema and no formData 1`] = ` +@layer recipes { + .emotion-0 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + width: var(--chakra-sizes-full); + } + + .emotion-0>:not(style, [hidden])~:not(style, [hidden]) { + --space-y-reverse: 0; + margin-top: calc(var(--chakra-spacing-4) * calc(1 - var(--space-y-reverse))); + margin-bottom: calc(var(--chakra-spacing-4) * var(--space-y-reverse)); + } +} + +@layer recipes { + .emotion-1 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + width: var(--chakra-sizes-full); + gap: var(--chakra-spacing-4); + } +} + +.emotion-2 { + margin-top: var(--chakra-spacing-1); + margin-bottom: var(--chakra-spacing-4); +} + +@layer recipes { + .emotion-3 { + font-family: var(--chakra-fonts-heading); + font-weight: var(--chakra-font-weights-semibold); + font-size: var(--chakra-font-sizes-xl); + line-height: 1.875rem; + } +} + +@layer recipes { + .emotion-4 { + display: block; + border-color: var(--chakra-colors-border); + --separator-thickness: 1px; + border-style: solid; + border-top-width: var(--separator-thickness); + } +} + +.emotion-5 { + display: grid; + gap: var(--chakra-spacing-4); + margin-bottom: var(--chakra-spacing-4); +} + +.emotion-14 { + margin-bottom: var(--chakra-spacing-1); +} + +@layer recipes { + .emotion-14 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + width: 100%; + position: relative; + gap: var(--chakra-spacing-1\\.5); + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + -webkit-align-items: flex-start; + -webkit-box-align: flex-start; + -ms-flex-align: flex-start; + align-items: flex-start; + } +} + +@layer recipes { + .emotion-15 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + text-align: start; + font-size: var(--chakra-font-sizes-sm); + line-height: 1.25rem; + font-weight: var(--chakra-font-weights-medium); + gap: var(--chakra-spacing-1); + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + } + + .emotion-15:is(:disabled, [disabled], [data-disabled], [aria-disabled=true]) { + opacity: 0.5; + } +} + +@layer recipes { + .emotion-16 { + width: 100%; + min-width: var(--input-height); + outline: 0; + position: relative; + -webkit-appearance: none; + -moz-appearance: none; + -ms-appearance: none; + appearance: none; + text-align: start; + border-radius: var(--chakra-radii-l2); + height: var(--input-height); + --focus-color: var(--chakra-colors-color-palette-focus-ring); + --error-color: var(--chakra-colors-border-error); + font-size: var(--chakra-font-sizes-sm); + line-height: 1.25rem; + padding-inline: var(--chakra-spacing-3); + --input-height: var(--chakra-sizes-10); + background: var(--chakra-colors-transparent); + --bg-currentcolor: var(--chakra-colors-transparent); + border-width: 1px; + border-color: var(--chakra-colors-border); + --focus-ring-color: var(--focus-color); + } + + .emotion-16:is(:disabled, [disabled], [data-disabled], [aria-disabled=true]) { + opacity: 0.5; + cursor: not-allowed; + } + + .emotion-16:is([data-invalid], [aria-invalid=true], [data-state=invalid]) { + --focus-ring-color: var(--error-color); + border-color: var(--error-color); + } + + .emotion-16:is(:focus-visible, [data-focus-visible]) { + outline-offset: 0px; + outline-width: var(--focus-ring-width, 1px); + outline-color: var(--focus-ring-color); + outline-style: var(--focus-ring-style, solid); + border-color: var(--focus-ring-color); + } +} + +.emotion-44 { + display: grid; +} + +.emotion-45 { + justify-self: flex-end; +} + +.emotion-46 { + margin-top: var(--chakra-spacing-2); +} + +@layer recipes { + .emotion-47 { + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + -webkit-appearance: none; + -moz-appearance: none; + -ms-appearance: none; + appearance: none; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + -webkit-justify-content: center; + justify-content: center; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + position: relative; + border-radius: var(--chakra-radii-l2); + white-space: nowrap; + vertical-align: middle; + border-width: 1px; + border-color: var(--chakra-colors-transparent); + cursor: var(--chakra-cursor-button); + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; + outline: 0; + line-height: 1.25rem; + isolation: isolate; + font-weight: var(--chakra-font-weights-medium); + transition-property: background-color,border-color,color,fill,stroke,opacity,box-shadow,translate,transform; + transition-duration: var(--chakra-durations-moderate); + --focus-ring-color: var(--chakra-colors-color-palette-focus-ring); + height: var(--chakra-sizes-10); + min-width: var(--chakra-sizes-10); + font-size: var(--chakra-font-sizes-sm); + padding-inline: var(--chakra-spacing-4); + gap: var(--chakra-spacing-2); + background: var(--chakra-colors-color-palette-solid); + --bg-currentcolor: var(--chakra-colors-color-palette-solid); + color: var(--chakra-colors-color-palette-contrast); + } + + .emotion-47:is(:focus-visible, [data-focus-visible]) { + outline-width: var(--focus-ring-width, 2px); + outline-offset: var(--focus-ring-offset, 2px); + outline-style: var(--focus-ring-style, solid); + outline-color: var(--focus-ring-color); + } + + .emotion-47:is(:disabled, [disabled], [data-disabled], [aria-disabled=true]) { + opacity: 0.5; + cursor: not-allowed; + } + + .emotion-47 :where(svg) { + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; + width: var(--chakra-sizes-5); + height: var(--chakra-sizes-5); + } + + .emotion-47:is([aria-expanded=true], [data-expanded], [data-state=expanded]) { + --mix-background: color-mix(in srgb, var(--chakra-colors-color-palette-solid) 90%, transparent); + background: var(--mix-background, var(--chakra-colors-color-palette-solid)); + --bg-currentcolor: var(--mix-background, var(--chakra-colors-color-palette-solid)); + } + + @media (hover: hover) { + .emotion-47:is(:hover, [data-hover]):not(:disabled, [data-disabled]) { + --mix-background: color-mix(in srgb, var(--chakra-colors-color-palette-solid) 90%, transparent); + background: var(--mix-background, var(--chakra-colors-color-palette-solid)); + --bg-currentcolor: var(--mix-background, var(--chakra-colors-color-palette-solid)); + } + } +} + +.emotion-97 { + margin-bottom: var(--chakra-spacing-2); +} + +@layer recipes { + .emotion-97 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + position: relative; + min-width: 0; + word-wrap: break-word; + border-radius: var(--chakra-radii-l3); + color: var(--chakra-colors-fg); + text-align: start; + background: var(--chakra-colors-bg-panel); + --bg-currentcolor: var(--chakra-colors-bg-panel); + border-width: 1px; + border-color: var(--chakra-colors-border); + --card-padding: var(--chakra-spacing-6); + } +} + +.emotion-98 { + padding-bottom: var(--chakra-spacing-2); +} + +@layer recipes { + .emotion-98 { + padding: var(--card-padding); + -webkit-flex: 1; + -ms-flex: 1; + flex: 1; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + } +} + +.emotion-99 { + margin-bottom: var(--chakra-spacing-4); +} + +.emotion-100 { + margin-bottom: var(--chakra-spacing-1); + position: relative; +} + +@layer recipes { + .emotion-100 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + width: 100%; + position: relative; + gap: var(--chakra-spacing-1\\.5); + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + -webkit-align-items: flex-start; + -webkit-box-align: flex-start; + -ms-flex-align: flex-start; + align-items: flex-start; + } +} + +@layer recipes { + .emotion-102 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + gap: var(--chakra-spacing-1\\.5); + width: var(--chakra-sizes-full); + --select-trigger-height: var(--chakra-sizes-10); + --select-trigger-padding-x: var(--chakra-spacing-3); + } +} + +@layer recipes { + .emotion-103 { + position: relative; + } +} + +@layer recipes { + .emotion-105 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: justify; + -webkit-justify-content: space-between; + justify-content: space-between; + width: var(--chakra-sizes-full); + min-height: var(--select-trigger-height); + --input-height: var(--select-trigger-height); + padding-inline: var(--select-trigger-padding-x); + border-radius: var(--chakra-radii-l2); + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + text-align: start; + --focus-ring-color: var(--chakra-colors-color-palette-focus-ring); + font-size: var(--chakra-font-sizes-sm); + line-height: 1.25rem; + gap: var(--chakra-spacing-2); + background: var(--chakra-colors-transparent); + --bg-currentcolor: var(--chakra-colors-transparent); + border-width: 1px; + border-color: var(--chakra-colors-border); + } + + .emotion-105:is(:focus-visible, [data-focus-visible]) { + outline-offset: 0px; + outline-width: var(--focus-ring-width, 1px); + outline-color: var(--focus-ring-color); + outline-style: var(--focus-ring-style, solid); + border-color: var(--focus-ring-color); + } + + .emotion-105:is(:placeholder-shown, [data-placeholder-shown]) { + --mix-color: color-mix(in srgb, var(--chakra-colors-fg-muted) 80%, transparent); + color: var(--mix-color, var(--chakra-colors-fg-muted)); + } + + .emotion-105:is(:disabled, [disabled], [data-disabled], [aria-disabled=true]) { + opacity: 0.5; + cursor: not-allowed; + } + + .emotion-105:is([data-invalid], [aria-invalid=true], [data-state=invalid]) { + border-color: var(--chakra-colors-border-error); + } + + .emotion-105:is([aria-expanded=true], [data-expanded], [data-state=expanded]) { + border-color: var(--chakra-colors-border-emphasized); + } +} + +@layer recipes { + .emotion-106 { + overflow: hidden; + display: -webkit-box; + -webkit-line-clamp: 1; + -webkit-box-orient: vertical; + text-wrap: wrap; + max-width: 80%; + } +} + +@layer recipes { + .emotion-107 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + gap: var(--chakra-spacing-1); + position: absolute; + inset-inline-end: 0; + top: 0; + bottom: 0; + padding-inline: var(--select-trigger-padding-x); + pointer-events: none; + } +} + +@layer recipes { + .emotion-108 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + -webkit-justify-content: center; + justify-content: center; + color: var(--chakra-colors-fg-muted); + } + + .emotion-108:is(:disabled, [disabled], [data-disabled], [aria-disabled=true]) { + color: var(--chakra-colors-fg-subtle); + } + + .emotion-108:is([data-invalid], [aria-invalid=true], [data-state=invalid]) { + color: var(--chakra-colors-fg-error); + } + + .emotion-108 :where(svg) { + width: var(--chakra-sizes-4); + height: var(--chakra-sizes-4); + } +} + +.emotion-109 { + fill: none; + stroke: currentColor; + stroke-width: 2; + stroke-linecap: round; + stroke-linejoin: round; +} + +.emotion-110 { + min-width: 100%!important; + z-index: 2!important; + top: calc(100% + 5px)!important; +} + +@layer recipes { + .emotion-111 { + background: var(--chakra-colors-bg-panel); + --bg-currentcolor: var(--chakra-colors-bg-panel); + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + z-index: var(--chakra-z-index-dropdown); + border-radius: var(--chakra-radii-l2); + outline: 0; + max-height: var(--chakra-sizes-96); + overflow-y: auto; + box-shadow: var(--chakra-shadows-md); + padding: var(--chakra-spacing-1); + font-size: var(--chakra-font-sizes-sm); + line-height: 1.25rem; + } + + .emotion-111:is([open], [data-open], [data-state=open]) { + transform-origin: var(--transform-origin); + -webkit-animation-duration: var(--chakra-durations-fast); + animation-duration: var(--chakra-durations-fast); + } + + .emotion-111:is([open], [data-open], [data-state=open])[data-placement^=top] { + -webkit-animation-name: slide-from-bottom,fade-in; + animation-name: slide-from-bottom,fade-in; + } + + .emotion-111:is([open], [data-open], [data-state=open])[data-placement^=bottom] { + -webkit-animation-name: slide-from-top,fade-in; + animation-name: slide-from-top,fade-in; + } + + .emotion-111:is([open], [data-open], [data-state=open])[data-placement^=left] { + -webkit-animation-name: slide-from-right,fade-in; + animation-name: slide-from-right,fade-in; + } + + .emotion-111:is([open], [data-open], [data-state=open])[data-placement^=right] { + -webkit-animation-name: slide-from-left,fade-in; + animation-name: slide-from-left,fade-in; + } + + .emotion-111:is([closed], [data-closed], [data-state=closed]) { + transform-origin: var(--transform-origin); + -webkit-animation-duration: var(--chakra-durations-fastest); + animation-duration: var(--chakra-durations-fastest); + } + + .emotion-111:is([closed], [data-closed], [data-state=closed])[data-placement^=top] { + -webkit-animation-name: slide-to-bottom,fade-out; + animation-name: slide-to-bottom,fade-out; + } + + .emotion-111:is([closed], [data-closed], [data-state=closed])[data-placement^=bottom] { + -webkit-animation-name: slide-to-top,fade-out; + animation-name: slide-to-top,fade-out; + } + + .emotion-111:is([closed], [data-closed], [data-state=closed])[data-placement^=left] { + -webkit-animation-name: slide-to-right,fade-out; + animation-name: slide-to-right,fade-out; + } + + .emotion-111:is([closed], [data-closed], [data-state=closed])[data-placement^=right] { + -webkit-animation-name: slide-to-left,fade-out; + animation-name: slide-to-left,fade-out; + } +} + +@layer recipes { + .emotion-112 { + position: relative; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + gap: var(--chakra-spacing-2); + cursor: var(--chakra-cursor-option); + -webkit-box-pack: justify; + -webkit-justify-content: space-between; + justify-content: space-between; + -webkit-flex: 1; + -ms-flex: 1; + flex: 1; + text-align: start; + border-radius: var(--chakra-radii-l1); + padding-block: var(--chakra-spacing-1\\.5); + padding-inline: var(--chakra-spacing-2); + } + + .emotion-112[data-highlighted] { + --mix-background: color-mix(in srgb, var(--chakra-colors-bg-emphasized) 60%, transparent); + background: var(--mix-background, var(--chakra-colors-bg-emphasized)); + --bg-currentcolor: var(--mix-background, var(--chakra-colors-bg-emphasized)); + } + + .emotion-112:is(:disabled, [disabled], [data-disabled], [aria-disabled=true]) { + pointer-events: none; + opacity: 0.5; + } + + .emotion-112 :where(svg) { + width: var(--chakra-sizes-4); + height: var(--chakra-sizes-4); + } +} + +@layer recipes { + .emotion-113 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + -webkit-justify-content: center; + justify-content: center; + } +} + +.emotion-132 { + margin-top: var(--chakra-spacing-3); +} + + +
+
+
+
+
+ test +
+ +
+
+
+
+
+
+
+
+ nestedObjectOptional +
+ +
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+
+ deepObjectOptional +
+ +
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ deepObject +
+ +
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ deepArrayOptional +
+ +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ deepArrayOptional2 +
+ +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ deepArray +
+ +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ nestedArrayOptional +
+ +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+ nestedObject +
+ +
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ nestedArray +
+ +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+
+ +
+
+ + + +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+ optionalObjectWithOneofs +
+ +
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+`; + +exports[`single fields optional data controls does not show optional controls when not turned on in uiSchema, readonly and no formData 1`] = ` +@layer recipes { + .emotion-0 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + width: var(--chakra-sizes-full); + } + + .emotion-0>:not(style, [hidden])~:not(style, [hidden]) { + --space-y-reverse: 0; + margin-top: calc(var(--chakra-spacing-4) * calc(1 - var(--space-y-reverse))); + margin-bottom: calc(var(--chakra-spacing-4) * var(--space-y-reverse)); + } +} + +@layer recipes { + .emotion-1 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + width: var(--chakra-sizes-full); + gap: var(--chakra-spacing-4); + } +} + +.emotion-2 { + margin-top: var(--chakra-spacing-1); + margin-bottom: var(--chakra-spacing-4); +} + +@layer recipes { + .emotion-3 { + font-family: var(--chakra-fonts-heading); + font-weight: var(--chakra-font-weights-semibold); + font-size: var(--chakra-font-sizes-xl); + line-height: 1.875rem; + } +} + +@layer recipes { + .emotion-4 { + display: block; + border-color: var(--chakra-colors-border); + --separator-thickness: 1px; + border-style: solid; + border-top-width: var(--separator-thickness); + } +} + +.emotion-5 { + display: grid; + gap: var(--chakra-spacing-4); + margin-bottom: var(--chakra-spacing-4); +} + +.emotion-14 { + margin-bottom: var(--chakra-spacing-1); +} + +@layer recipes { + .emotion-14 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + width: 100%; + position: relative; + gap: var(--chakra-spacing-1\\.5); + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + -webkit-align-items: flex-start; + -webkit-box-align: flex-start; + -ms-flex-align: flex-start; + align-items: flex-start; + } +} + +@layer recipes { + .emotion-15 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + text-align: start; + font-size: var(--chakra-font-sizes-sm); + line-height: 1.25rem; + font-weight: var(--chakra-font-weights-medium); + gap: var(--chakra-spacing-1); + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + } + + .emotion-15:is(:disabled, [disabled], [data-disabled], [aria-disabled=true]) { + opacity: 0.5; + } +} + +@layer recipes { + .emotion-16 { + width: 100%; + min-width: var(--input-height); + outline: 0; + position: relative; + -webkit-appearance: none; + -moz-appearance: none; + -ms-appearance: none; + appearance: none; + text-align: start; + border-radius: var(--chakra-radii-l2); + height: var(--input-height); + --focus-color: var(--chakra-colors-color-palette-focus-ring); + --error-color: var(--chakra-colors-border-error); + font-size: var(--chakra-font-sizes-sm); + line-height: 1.25rem; + padding-inline: var(--chakra-spacing-3); + --input-height: var(--chakra-sizes-10); + background: var(--chakra-colors-transparent); + --bg-currentcolor: var(--chakra-colors-transparent); + border-width: 1px; + border-color: var(--chakra-colors-border); + --focus-ring-color: var(--focus-color); + } + + .emotion-16:is(:disabled, [disabled], [data-disabled], [aria-disabled=true]) { + opacity: 0.5; + cursor: not-allowed; + } + + .emotion-16:is([data-invalid], [aria-invalid=true], [data-state=invalid]) { + --focus-ring-color: var(--error-color); + border-color: var(--error-color); + } + + .emotion-16:is(:focus-visible, [data-focus-visible]) { + outline-offset: 0px; + outline-width: var(--focus-ring-width, 1px); + outline-color: var(--focus-ring-color); + outline-style: var(--focus-ring-style, solid); + border-color: var(--focus-ring-color); + } +} + +.emotion-44 { + display: grid; +} + +.emotion-45 { + justify-self: flex-end; +} + +.emotion-46 { + margin-top: var(--chakra-spacing-2); +} + +@layer recipes { + .emotion-47 { + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + -webkit-appearance: none; + -moz-appearance: none; + -ms-appearance: none; + appearance: none; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + -webkit-justify-content: center; + justify-content: center; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + position: relative; + border-radius: var(--chakra-radii-l2); + white-space: nowrap; + vertical-align: middle; + border-width: 1px; + border-color: var(--chakra-colors-transparent); + cursor: var(--chakra-cursor-button); + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; + outline: 0; + line-height: 1.25rem; + isolation: isolate; + font-weight: var(--chakra-font-weights-medium); + transition-property: background-color,border-color,color,fill,stroke,opacity,box-shadow,translate,transform; + transition-duration: var(--chakra-durations-moderate); + --focus-ring-color: var(--chakra-colors-color-palette-focus-ring); + height: var(--chakra-sizes-10); + min-width: var(--chakra-sizes-10); + font-size: var(--chakra-font-sizes-sm); + padding-inline: var(--chakra-spacing-4); + gap: var(--chakra-spacing-2); + background: var(--chakra-colors-color-palette-solid); + --bg-currentcolor: var(--chakra-colors-color-palette-solid); + color: var(--chakra-colors-color-palette-contrast); + } + + .emotion-47:is(:focus-visible, [data-focus-visible]) { + outline-width: var(--focus-ring-width, 2px); + outline-offset: var(--focus-ring-offset, 2px); + outline-style: var(--focus-ring-style, solid); + outline-color: var(--focus-ring-color); + } + + .emotion-47:is(:disabled, [disabled], [data-disabled], [aria-disabled=true]) { + opacity: 0.5; + cursor: not-allowed; + } + + .emotion-47 :where(svg) { + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; + width: var(--chakra-sizes-5); + height: var(--chakra-sizes-5); + } + + .emotion-47:is([aria-expanded=true], [data-expanded], [data-state=expanded]) { + --mix-background: color-mix(in srgb, var(--chakra-colors-color-palette-solid) 90%, transparent); + background: var(--mix-background, var(--chakra-colors-color-palette-solid)); + --bg-currentcolor: var(--mix-background, var(--chakra-colors-color-palette-solid)); + } + + @media (hover: hover) { + .emotion-47:is(:hover, [data-hover]):not(:disabled, [data-disabled]) { + --mix-background: color-mix(in srgb, var(--chakra-colors-color-palette-solid) 90%, transparent); + background: var(--mix-background, var(--chakra-colors-color-palette-solid)); + --bg-currentcolor: var(--mix-background, var(--chakra-colors-color-palette-solid)); + } + } +} + +.emotion-97 { + margin-bottom: var(--chakra-spacing-2); +} + +@layer recipes { + .emotion-97 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + position: relative; + min-width: 0; + word-wrap: break-word; + border-radius: var(--chakra-radii-l3); + color: var(--chakra-colors-fg); + text-align: start; + background: var(--chakra-colors-bg-panel); + --bg-currentcolor: var(--chakra-colors-bg-panel); + border-width: 1px; + border-color: var(--chakra-colors-border); + --card-padding: var(--chakra-spacing-6); + } +} + +.emotion-98 { + padding-bottom: var(--chakra-spacing-2); +} + +@layer recipes { + .emotion-98 { + padding: var(--card-padding); + -webkit-flex: 1; + -ms-flex: 1; + flex: 1; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + } +} + +.emotion-99 { + margin-bottom: var(--chakra-spacing-4); +} + +.emotion-100 { + margin-bottom: var(--chakra-spacing-1); + position: relative; +} + +@layer recipes { + .emotion-100 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + width: 100%; + position: relative; + gap: var(--chakra-spacing-1\\.5); + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + -webkit-align-items: flex-start; + -webkit-box-align: flex-start; + -ms-flex-align: flex-start; + align-items: flex-start; + } +} + +@layer recipes { + .emotion-102 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + gap: var(--chakra-spacing-1\\.5); + width: var(--chakra-sizes-full); + --select-trigger-height: var(--chakra-sizes-10); + --select-trigger-padding-x: var(--chakra-spacing-3); + } +} + +@layer recipes { + .emotion-103 { + position: relative; + } +} + +@layer recipes { + .emotion-105 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: justify; + -webkit-justify-content: space-between; + justify-content: space-between; + width: var(--chakra-sizes-full); + min-height: var(--select-trigger-height); + --input-height: var(--select-trigger-height); + padding-inline: var(--select-trigger-padding-x); + border-radius: var(--chakra-radii-l2); + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + text-align: start; + --focus-ring-color: var(--chakra-colors-color-palette-focus-ring); + font-size: var(--chakra-font-sizes-sm); + line-height: 1.25rem; + gap: var(--chakra-spacing-2); + background: var(--chakra-colors-transparent); + --bg-currentcolor: var(--chakra-colors-transparent); + border-width: 1px; + border-color: var(--chakra-colors-border); + } + + .emotion-105:is(:focus-visible, [data-focus-visible]) { + outline-offset: 0px; + outline-width: var(--focus-ring-width, 1px); + outline-color: var(--focus-ring-color); + outline-style: var(--focus-ring-style, solid); + border-color: var(--focus-ring-color); + } + + .emotion-105:is(:placeholder-shown, [data-placeholder-shown]) { + --mix-color: color-mix(in srgb, var(--chakra-colors-fg-muted) 80%, transparent); + color: var(--mix-color, var(--chakra-colors-fg-muted)); + } + + .emotion-105:is(:disabled, [disabled], [data-disabled], [aria-disabled=true]) { + opacity: 0.5; + cursor: not-allowed; + } + + .emotion-105:is([data-invalid], [aria-invalid=true], [data-state=invalid]) { + border-color: var(--chakra-colors-border-error); + } + + .emotion-105:is([aria-expanded=true], [data-expanded], [data-state=expanded]) { + border-color: var(--chakra-colors-border-emphasized); + } +} + +@layer recipes { + .emotion-106 { + overflow: hidden; + display: -webkit-box; + -webkit-line-clamp: 1; + -webkit-box-orient: vertical; + text-wrap: wrap; + max-width: 80%; + } +} + +@layer recipes { + .emotion-107 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + gap: var(--chakra-spacing-1); + position: absolute; + inset-inline-end: 0; + top: 0; + bottom: 0; + padding-inline: var(--select-trigger-padding-x); + pointer-events: none; + } +} + +@layer recipes { + .emotion-108 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + -webkit-justify-content: center; + justify-content: center; + color: var(--chakra-colors-fg-muted); + } + + .emotion-108:is(:disabled, [disabled], [data-disabled], [aria-disabled=true]) { + color: var(--chakra-colors-fg-subtle); + } + + .emotion-108:is([data-invalid], [aria-invalid=true], [data-state=invalid]) { + color: var(--chakra-colors-fg-error); + } + + .emotion-108 :where(svg) { + width: var(--chakra-sizes-4); + height: var(--chakra-sizes-4); + } +} + +.emotion-109 { + fill: none; + stroke: currentColor; + stroke-width: 2; + stroke-linecap: round; + stroke-linejoin: round; +} + +.emotion-110 { + min-width: 100%!important; + z-index: 2!important; + top: calc(100% + 5px)!important; +} + +@layer recipes { + .emotion-111 { + background: var(--chakra-colors-bg-panel); + --bg-currentcolor: var(--chakra-colors-bg-panel); + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + z-index: var(--chakra-z-index-dropdown); + border-radius: var(--chakra-radii-l2); + outline: 0; + max-height: var(--chakra-sizes-96); + overflow-y: auto; + box-shadow: var(--chakra-shadows-md); + padding: var(--chakra-spacing-1); + font-size: var(--chakra-font-sizes-sm); + line-height: 1.25rem; + } + + .emotion-111:is([open], [data-open], [data-state=open]) { + transform-origin: var(--transform-origin); + -webkit-animation-duration: var(--chakra-durations-fast); + animation-duration: var(--chakra-durations-fast); + } + + .emotion-111:is([open], [data-open], [data-state=open])[data-placement^=top] { + -webkit-animation-name: slide-from-bottom,fade-in; + animation-name: slide-from-bottom,fade-in; + } + + .emotion-111:is([open], [data-open], [data-state=open])[data-placement^=bottom] { + -webkit-animation-name: slide-from-top,fade-in; + animation-name: slide-from-top,fade-in; + } + + .emotion-111:is([open], [data-open], [data-state=open])[data-placement^=left] { + -webkit-animation-name: slide-from-right,fade-in; + animation-name: slide-from-right,fade-in; + } + + .emotion-111:is([open], [data-open], [data-state=open])[data-placement^=right] { + -webkit-animation-name: slide-from-left,fade-in; + animation-name: slide-from-left,fade-in; + } + + .emotion-111:is([closed], [data-closed], [data-state=closed]) { + transform-origin: var(--transform-origin); + -webkit-animation-duration: var(--chakra-durations-fastest); + animation-duration: var(--chakra-durations-fastest); + } + + .emotion-111:is([closed], [data-closed], [data-state=closed])[data-placement^=top] { + -webkit-animation-name: slide-to-bottom,fade-out; + animation-name: slide-to-bottom,fade-out; + } + + .emotion-111:is([closed], [data-closed], [data-state=closed])[data-placement^=bottom] { + -webkit-animation-name: slide-to-top,fade-out; + animation-name: slide-to-top,fade-out; + } + + .emotion-111:is([closed], [data-closed], [data-state=closed])[data-placement^=left] { + -webkit-animation-name: slide-to-right,fade-out; + animation-name: slide-to-right,fade-out; + } + + .emotion-111:is([closed], [data-closed], [data-state=closed])[data-placement^=right] { + -webkit-animation-name: slide-to-left,fade-out; + animation-name: slide-to-left,fade-out; + } +} + +@layer recipes { + .emotion-112 { + position: relative; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + gap: var(--chakra-spacing-2); + cursor: var(--chakra-cursor-option); + -webkit-box-pack: justify; + -webkit-justify-content: space-between; + justify-content: space-between; + -webkit-flex: 1; + -ms-flex: 1; + flex: 1; + text-align: start; + border-radius: var(--chakra-radii-l1); + padding-block: var(--chakra-spacing-1\\.5); + padding-inline: var(--chakra-spacing-2); + } + + .emotion-112[data-highlighted] { + --mix-background: color-mix(in srgb, var(--chakra-colors-bg-emphasized) 60%, transparent); + background: var(--mix-background, var(--chakra-colors-bg-emphasized)); + --bg-currentcolor: var(--mix-background, var(--chakra-colors-bg-emphasized)); + } + + .emotion-112:is(:disabled, [disabled], [data-disabled], [aria-disabled=true]) { + pointer-events: none; + opacity: 0.5; + } + + .emotion-112 :where(svg) { + width: var(--chakra-sizes-4); + height: var(--chakra-sizes-4); + } +} + +@layer recipes { + .emotion-113 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + -webkit-justify-content: center; + justify-content: center; + } +} + +.emotion-132 { + margin-top: var(--chakra-spacing-3); +} + +
+
+
+
+
+
+ test +
+ +
+
+
+
+
+
+
+
+
+ nestedObjectOptional +
+ +
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+
+ deepObjectOptional +
+ +
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ deepObject +
+ +
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ deepArrayOptional +
+ +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ deepArrayOptional2 +
+ +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ deepArray +
+ +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ nestedArrayOptional +
+ +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+ nestedObject +
+ +
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ nestedArray +
+ +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+
+ +
+
+ + + +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+ optionalObjectWithOneofs +
+ +
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+`; + +exports[`single fields optional data controls shows "add" and "remove" optional controls when turned on in uiSchema and formData 1`] = ` +@layer recipes { + .emotion-0 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + width: var(--chakra-sizes-full); + } + + .emotion-0>:not(style, [hidden])~:not(style, [hidden]) { + --space-y-reverse: 0; + margin-top: calc(var(--chakra-spacing-4) * calc(1 - var(--space-y-reverse))); + margin-bottom: calc(var(--chakra-spacing-4) * var(--space-y-reverse)); + } +} + +@layer recipes { + .emotion-1 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + width: var(--chakra-sizes-full); + gap: var(--chakra-spacing-4); + } +} + +.emotion-2 { + margin-top: var(--chakra-spacing-1); + margin-bottom: var(--chakra-spacing-4); +} + +@layer recipes { + .emotion-3 { + font-family: var(--chakra-fonts-heading); + font-weight: var(--chakra-font-weights-semibold); + font-size: var(--chakra-font-sizes-xl); + line-height: 1.875rem; + } +} + +@layer recipes { + .emotion-4 { + display: block; + border-color: var(--chakra-colors-border); + --separator-thickness: 1px; + border-style: solid; + border-top-width: var(--separator-thickness); + } +} + +.emotion-5 { + display: grid; + gap: var(--chakra-spacing-4); + margin-bottom: var(--chakra-spacing-4); +} + +.emotion-9 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; +} + +@layer recipes { + .emotion-11 { + -webkit-flex: 1; + -ms-flex: 1; + flex: 1; + justify-self: stretch; + -webkit-align-self: stretch; + -ms-flex-item-align: stretch; + align-self: stretch; + } +} + +.emotion-12 { + padding-inline: 0; + padding-block: 0; +} + +@layer recipes { + .emotion-12 { + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + -webkit-appearance: none; + -moz-appearance: none; + -ms-appearance: none; + appearance: none; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + -webkit-justify-content: center; + justify-content: center; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + position: relative; + border-radius: var(--chakra-radii-l2); + white-space: nowrap; + vertical-align: middle; + border-width: 1px; + border-color: var(--chakra-colors-transparent); + cursor: var(--chakra-cursor-button); + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; + outline: 0; + line-height: 1rem; + isolation: isolate; + font-weight: var(--chakra-font-weights-medium); + transition-property: background-color,border-color,color,fill,stroke,opacity,box-shadow,translate,transform; + transition-duration: var(--chakra-durations-moderate); + --focus-ring-color: var(--chakra-colors-color-palette-focus-ring); + height: var(--chakra-sizes-8); + min-width: var(--chakra-sizes-8); + font-size: var(--chakra-font-sizes-xs); + padding-inline: var(--chakra-spacing-2\\.5); + gap: var(--chakra-spacing-1); + background: var(--chakra-colors-color-palette-subtle); + --bg-currentcolor: var(--chakra-colors-color-palette-subtle); + color: var(--chakra-colors-color-palette-fg); + } + + .emotion-12:is(:focus-visible, [data-focus-visible]) { + outline-width: var(--focus-ring-width, 2px); + outline-offset: var(--focus-ring-offset, 2px); + outline-style: var(--focus-ring-style, solid); + outline-color: var(--focus-ring-color); + } + + .emotion-12:is(:disabled, [disabled], [data-disabled], [aria-disabled=true]) { + opacity: 0.5; + cursor: not-allowed; + } + + .emotion-12 :where(svg) { + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; + width: var(--chakra-sizes-4); + height: var(--chakra-sizes-4); + } + + .emotion-12:is([aria-expanded=true], [data-expanded], [data-state=expanded]) { + background: var(--chakra-colors-color-palette-muted); + --bg-currentcolor: var(--chakra-colors-color-palette-muted); + } + + @media (hover: hover) { + .emotion-12:is(:hover, [data-hover]):not(:disabled, [data-disabled]) { + background: var(--chakra-colors-color-palette-muted); + --bg-currentcolor: var(--chakra-colors-color-palette-muted); + } + } +} + +.emotion-12 :where(svg) { + font-size: 1.2em; +} + +.emotion-17 { + margin-bottom: var(--chakra-spacing-1); +} + +@layer recipes { + .emotion-17 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + width: 100%; + position: relative; + gap: var(--chakra-spacing-1\\.5); + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + -webkit-align-items: flex-start; + -webkit-box-align: flex-start; + -ms-flex-align: flex-start; + align-items: flex-start; + } +} + +@layer recipes { + .emotion-18 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + text-align: start; + font-size: var(--chakra-font-sizes-sm); + line-height: 1.25rem; + font-weight: var(--chakra-font-weights-medium); + gap: var(--chakra-spacing-1); + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + } + + .emotion-18:is(:disabled, [disabled], [data-disabled], [aria-disabled=true]) { + opacity: 0.5; + } +} + +@layer recipes { + .emotion-19 { + width: 100%; + min-width: var(--input-height); + outline: 0; + position: relative; + -webkit-appearance: none; + -moz-appearance: none; + -ms-appearance: none; + appearance: none; + text-align: start; + border-radius: var(--chakra-radii-l2); + height: var(--input-height); + --focus-color: var(--chakra-colors-color-palette-focus-ring); + --error-color: var(--chakra-colors-border-error); + font-size: var(--chakra-font-sizes-sm); + line-height: 1.25rem; + padding-inline: var(--chakra-spacing-3); + --input-height: var(--chakra-sizes-10); + background: var(--chakra-colors-transparent); + --bg-currentcolor: var(--chakra-colors-transparent); + border-width: 1px; + border-color: var(--chakra-colors-border); + --focus-ring-color: var(--focus-color); + } + + .emotion-19:is(:disabled, [disabled], [data-disabled], [aria-disabled=true]) { + opacity: 0.5; + cursor: not-allowed; + } + + .emotion-19:is([data-invalid], [aria-invalid=true], [data-state=invalid]) { + --focus-ring-color: var(--error-color); + border-color: var(--error-color); + } + + .emotion-19:is(:focus-visible, [data-focus-visible]) { + outline-offset: 0px; + outline-width: var(--focus-ring-width, 1px); + outline-color: var(--focus-ring-color); + outline-style: var(--focus-ring-style, solid); + border-color: var(--focus-ring-color); + } +} + +.emotion-45 { + display: grid; +} + +.emotion-46 { + justify-self: flex-end; +} + +.emotion-47 { + margin-top: var(--chakra-spacing-2); +} + +@layer recipes { + .emotion-48 { + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + -webkit-appearance: none; + -moz-appearance: none; + -ms-appearance: none; + appearance: none; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + -webkit-justify-content: center; + justify-content: center; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + position: relative; + border-radius: var(--chakra-radii-l2); + white-space: nowrap; + vertical-align: middle; + border-width: 1px; + border-color: var(--chakra-colors-transparent); + cursor: var(--chakra-cursor-button); + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; + outline: 0; + line-height: 1.25rem; + isolation: isolate; + font-weight: var(--chakra-font-weights-medium); + transition-property: background-color,border-color,color,fill,stroke,opacity,box-shadow,translate,transform; + transition-duration: var(--chakra-durations-moderate); + --focus-ring-color: var(--chakra-colors-color-palette-focus-ring); + height: var(--chakra-sizes-10); + min-width: var(--chakra-sizes-10); + font-size: var(--chakra-font-sizes-sm); + padding-inline: var(--chakra-spacing-4); + gap: var(--chakra-spacing-2); + background: var(--chakra-colors-color-palette-solid); + --bg-currentcolor: var(--chakra-colors-color-palette-solid); + color: var(--chakra-colors-color-palette-contrast); + } + + .emotion-48:is(:focus-visible, [data-focus-visible]) { + outline-width: var(--focus-ring-width, 2px); + outline-offset: var(--focus-ring-offset, 2px); + outline-style: var(--focus-ring-style, solid); + outline-color: var(--focus-ring-color); + } + + .emotion-48:is(:disabled, [disabled], [data-disabled], [aria-disabled=true]) { + opacity: 0.5; + cursor: not-allowed; + } + + .emotion-48 :where(svg) { + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; + width: var(--chakra-sizes-5); + height: var(--chakra-sizes-5); + } + + .emotion-48:is([aria-expanded=true], [data-expanded], [data-state=expanded]) { + --mix-background: color-mix(in srgb, var(--chakra-colors-color-palette-solid) 90%, transparent); + background: var(--mix-background, var(--chakra-colors-color-palette-solid)); + --bg-currentcolor: var(--mix-background, var(--chakra-colors-color-palette-solid)); + } + + @media (hover: hover) { + .emotion-48:is(:hover, [data-hover]):not(:disabled, [data-disabled]) { + --mix-background: color-mix(in srgb, var(--chakra-colors-color-palette-solid) 90%, transparent); + background: var(--mix-background, var(--chakra-colors-color-palette-solid)); + --bg-currentcolor: var(--mix-background, var(--chakra-colors-color-palette-solid)); + } + } +} + +.emotion-76 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: flex-end; + -webkit-box-align: flex-end; + -ms-flex-align: flex-end; + align-items: flex-end; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + gap: 0.5rem; + padding-block: var(--chakra-spacing-1); +} + +.emotion-77 { + width: 100%; +} + +@layer recipes { + .emotion-82 { + color: var(--chakra-colors-fg-error); + line-height: 1; + } +} + +.emotion-84 { + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: start; + -ms-flex-pack: start; + -webkit-justify-content: flex-start; + justify-content: flex-start; + margin-bottom: var(--chakra-spacing-1); +} + +@layer recipes { + .emotion-84 { + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + gap: 0!important; + isolation: isolate; + position: relative; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + } + + .emotion-84 [data-group-item]:is(:focus-visible, [data-focus-visible]) { + z-index: 1; + } + + .emotion-84>*[data-first] { + border-start-end-radius: 0!important; + border-end-end-radius: 0!important; + -webkit-margin-end: -1px; + margin-inline-end: -1px; + } + + .emotion-84>*[data-between] { + border-radius: 0!important; + -webkit-margin-end: -1px; + margin-inline-end: -1px; + } + + .emotion-84>*[data-last] { + border-start-start-radius: 0!important; + border-end-start-radius: 0!important; + } +} + +.emotion-85 { + padding-inline: 0; + padding-block: 0; +} + +@layer recipes { + .emotion-85 { + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + -webkit-appearance: none; + -moz-appearance: none; + -ms-appearance: none; + appearance: none; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + -webkit-justify-content: center; + justify-content: center; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + position: relative; + border-radius: var(--chakra-radii-l2); + white-space: nowrap; + vertical-align: middle; + border-width: 1px; + border-color: var(--chakra-colors-transparent); + cursor: var(--chakra-cursor-button); + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; + outline: 0; + line-height: 1.25rem; + isolation: isolate; + font-weight: var(--chakra-font-weights-medium); + transition-property: background-color,border-color,color,fill,stroke,opacity,box-shadow,translate,transform; + transition-duration: var(--chakra-durations-moderate); + --focus-ring-color: var(--chakra-colors-color-palette-focus-ring); + height: var(--chakra-sizes-10); + min-width: var(--chakra-sizes-10); + font-size: var(--chakra-font-sizes-sm); + padding-inline: var(--chakra-spacing-4); + gap: var(--chakra-spacing-2); + background: var(--chakra-colors-color-palette-solid); + --bg-currentcolor: var(--chakra-colors-color-palette-solid); + color: var(--chakra-colors-color-palette-contrast); + } + + .emotion-85:is(:focus-visible, [data-focus-visible]) { + outline-width: var(--focus-ring-width, 2px); + outline-offset: var(--focus-ring-offset, 2px); + outline-style: var(--focus-ring-style, solid); + outline-color: var(--focus-ring-color); + } + + .emotion-85:is(:disabled, [disabled], [data-disabled], [aria-disabled=true]) { + opacity: 0.5; + cursor: not-allowed; + } + + .emotion-85 :where(svg) { + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; + width: var(--chakra-sizes-5); + height: var(--chakra-sizes-5); + } + + .emotion-85:is([aria-expanded=true], [data-expanded], [data-state=expanded]) { + --mix-background: color-mix(in srgb, var(--chakra-colors-color-palette-solid) 90%, transparent); + background: var(--mix-background, var(--chakra-colors-color-palette-solid)); + --bg-currentcolor: var(--mix-background, var(--chakra-colors-color-palette-solid)); + } + + @media (hover: hover) { + .emotion-85:is(:hover, [data-hover]):not(:disabled, [data-disabled]) { + --mix-background: color-mix(in srgb, var(--chakra-colors-color-palette-solid) 90%, transparent); + background: var(--mix-background, var(--chakra-colors-color-palette-solid)); + --bg-currentcolor: var(--mix-background, var(--chakra-colors-color-palette-solid)); + } + } +} + +.emotion-85 :where(svg) { + font-size: 1.2em; +} + +.emotion-111 { + margin-bottom: var(--chakra-spacing-2); +} + +@layer recipes { + .emotion-111 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + position: relative; + min-width: 0; + word-wrap: break-word; + border-radius: var(--chakra-radii-l3); + color: var(--chakra-colors-fg); + text-align: start; + background: var(--chakra-colors-bg-panel); + --bg-currentcolor: var(--chakra-colors-bg-panel); + border-width: 1px; + border-color: var(--chakra-colors-border); + --card-padding: var(--chakra-spacing-6); + } +} + +.emotion-112 { + padding-bottom: var(--chakra-spacing-2); +} + +@layer recipes { + .emotion-112 { + padding: var(--card-padding); + -webkit-flex: 1; + -ms-flex: 1; + flex: 1; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + } +} + +.emotion-113 { + margin-bottom: var(--chakra-spacing-4); +} + +.emotion-114 { + margin-bottom: var(--chakra-spacing-1); + position: relative; +} + +@layer recipes { + .emotion-114 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + width: 100%; + position: relative; + gap: var(--chakra-spacing-1\\.5); + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + -webkit-align-items: flex-start; + -webkit-box-align: flex-start; + -ms-flex-align: flex-start; + align-items: flex-start; + } +} + +@layer recipes { + .emotion-116 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + gap: var(--chakra-spacing-1\\.5); + width: var(--chakra-sizes-full); + --select-trigger-height: var(--chakra-sizes-10); + --select-trigger-padding-x: var(--chakra-spacing-3); + } +} + +@layer recipes { + .emotion-117 { + position: relative; + } +} + +@layer recipes { + .emotion-119 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: justify; + -webkit-justify-content: space-between; + justify-content: space-between; + width: var(--chakra-sizes-full); + min-height: var(--select-trigger-height); + --input-height: var(--select-trigger-height); + padding-inline: var(--select-trigger-padding-x); + border-radius: var(--chakra-radii-l2); + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + text-align: start; + --focus-ring-color: var(--chakra-colors-color-palette-focus-ring); + font-size: var(--chakra-font-sizes-sm); + line-height: 1.25rem; + gap: var(--chakra-spacing-2); + background: var(--chakra-colors-transparent); + --bg-currentcolor: var(--chakra-colors-transparent); + border-width: 1px; + border-color: var(--chakra-colors-border); + } + + .emotion-119:is(:focus-visible, [data-focus-visible]) { + outline-offset: 0px; + outline-width: var(--focus-ring-width, 1px); + outline-color: var(--focus-ring-color); + outline-style: var(--focus-ring-style, solid); + border-color: var(--focus-ring-color); + } + + .emotion-119:is(:placeholder-shown, [data-placeholder-shown]) { + --mix-color: color-mix(in srgb, var(--chakra-colors-fg-muted) 80%, transparent); + color: var(--mix-color, var(--chakra-colors-fg-muted)); + } + + .emotion-119:is(:disabled, [disabled], [data-disabled], [aria-disabled=true]) { + opacity: 0.5; + cursor: not-allowed; + } + + .emotion-119:is([data-invalid], [aria-invalid=true], [data-state=invalid]) { + border-color: var(--chakra-colors-border-error); + } + + .emotion-119:is([aria-expanded=true], [data-expanded], [data-state=expanded]) { + border-color: var(--chakra-colors-border-emphasized); + } +} + +@layer recipes { + .emotion-120 { + overflow: hidden; + display: -webkit-box; + -webkit-line-clamp: 1; + -webkit-box-orient: vertical; + text-wrap: wrap; + max-width: 80%; + } +} + +@layer recipes { + .emotion-121 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + gap: var(--chakra-spacing-1); + position: absolute; + inset-inline-end: 0; + top: 0; + bottom: 0; + padding-inline: var(--select-trigger-padding-x); + pointer-events: none; + } +} + +@layer recipes { + .emotion-122 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + -webkit-justify-content: center; + justify-content: center; + color: var(--chakra-colors-fg-muted); + } + + .emotion-122:is(:disabled, [disabled], [data-disabled], [aria-disabled=true]) { + color: var(--chakra-colors-fg-subtle); + } + + .emotion-122:is([data-invalid], [aria-invalid=true], [data-state=invalid]) { + color: var(--chakra-colors-fg-error); + } + + .emotion-122 :where(svg) { + width: var(--chakra-sizes-4); + height: var(--chakra-sizes-4); + } +} + +.emotion-123 { + fill: none; + stroke: currentColor; + stroke-width: 2; + stroke-linecap: round; + stroke-linejoin: round; +} + +.emotion-124 { + min-width: 100%!important; + z-index: 2!important; + top: calc(100% + 5px)!important; +} + +@layer recipes { + .emotion-125 { + background: var(--chakra-colors-bg-panel); + --bg-currentcolor: var(--chakra-colors-bg-panel); + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + z-index: var(--chakra-z-index-dropdown); + border-radius: var(--chakra-radii-l2); + outline: 0; + max-height: var(--chakra-sizes-96); + overflow-y: auto; + box-shadow: var(--chakra-shadows-md); + padding: var(--chakra-spacing-1); + font-size: var(--chakra-font-sizes-sm); + line-height: 1.25rem; + } + + .emotion-125:is([open], [data-open], [data-state=open]) { + transform-origin: var(--transform-origin); + -webkit-animation-duration: var(--chakra-durations-fast); + animation-duration: var(--chakra-durations-fast); + } + + .emotion-125:is([open], [data-open], [data-state=open])[data-placement^=top] { + -webkit-animation-name: slide-from-bottom,fade-in; + animation-name: slide-from-bottom,fade-in; + } + + .emotion-125:is([open], [data-open], [data-state=open])[data-placement^=bottom] { + -webkit-animation-name: slide-from-top,fade-in; + animation-name: slide-from-top,fade-in; + } + + .emotion-125:is([open], [data-open], [data-state=open])[data-placement^=left] { + -webkit-animation-name: slide-from-right,fade-in; + animation-name: slide-from-right,fade-in; + } + + .emotion-125:is([open], [data-open], [data-state=open])[data-placement^=right] { + -webkit-animation-name: slide-from-left,fade-in; + animation-name: slide-from-left,fade-in; + } + + .emotion-125:is([closed], [data-closed], [data-state=closed]) { + transform-origin: var(--transform-origin); + -webkit-animation-duration: var(--chakra-durations-fastest); + animation-duration: var(--chakra-durations-fastest); + } + + .emotion-125:is([closed], [data-closed], [data-state=closed])[data-placement^=top] { + -webkit-animation-name: slide-to-bottom,fade-out; + animation-name: slide-to-bottom,fade-out; + } + + .emotion-125:is([closed], [data-closed], [data-state=closed])[data-placement^=bottom] { + -webkit-animation-name: slide-to-top,fade-out; + animation-name: slide-to-top,fade-out; + } + + .emotion-125:is([closed], [data-closed], [data-state=closed])[data-placement^=left] { + -webkit-animation-name: slide-to-right,fade-out; + animation-name: slide-to-right,fade-out; + } + + .emotion-125:is([closed], [data-closed], [data-state=closed])[data-placement^=right] { + -webkit-animation-name: slide-to-left,fade-out; + animation-name: slide-to-left,fade-out; + } +} + +@layer recipes { + .emotion-126 { + position: relative; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + gap: var(--chakra-spacing-2); + cursor: var(--chakra-cursor-option); + -webkit-box-pack: justify; + -webkit-justify-content: space-between; + justify-content: space-between; + -webkit-flex: 1; + -ms-flex: 1; + flex: 1; + text-align: start; + border-radius: var(--chakra-radii-l1); + padding-block: var(--chakra-spacing-1\\.5); + padding-inline: var(--chakra-spacing-2); + } + + .emotion-126[data-highlighted] { + --mix-background: color-mix(in srgb, var(--chakra-colors-bg-emphasized) 60%, transparent); + background: var(--mix-background, var(--chakra-colors-bg-emphasized)); + --bg-currentcolor: var(--mix-background, var(--chakra-colors-bg-emphasized)); + } + + .emotion-126:is(:disabled, [disabled], [data-disabled], [aria-disabled=true]) { + pointer-events: none; + opacity: 0.5; + } + + .emotion-126 :where(svg) { + width: var(--chakra-sizes-4); + height: var(--chakra-sizes-4); + } +} + +@layer recipes { + .emotion-127 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + -webkit-justify-content: center; + justify-content: center; + } +} + +.emotion-146 { + margin-top: var(--chakra-spacing-3); +} + +
+
+
+
+
+
+ test +
+ +
+
+
+
+
+
+
+
+
+ nestedObjectOptional +
+
+ +
+ +
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+
+
+ deepObjectOptional +
+
+ +
+ +
+
+
+
+
+
+
+
+
+
+
+
+ deepObject +
+ +
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ deepArrayOptional +
+ +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ deepArrayOptional2 +
+
+ +
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ deepArray +
+ +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ nestedArrayOptional +
+
+ +
+ +
+
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+ nestedObject +
+ +
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ nestedArray +
+ +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+
+ +
+
+ + + +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+ optionalObjectWithOneofs +
+ +
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+`; + +exports[`single fields optional data controls shows "add" and "remove" optional controls when turned on in uiSchema, readonly and formData 1`] = ` +@layer recipes { + .emotion-0 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + width: var(--chakra-sizes-full); + } + + .emotion-0>:not(style, [hidden])~:not(style, [hidden]) { + --space-y-reverse: 0; + margin-top: calc(var(--chakra-spacing-4) * calc(1 - var(--space-y-reverse))); + margin-bottom: calc(var(--chakra-spacing-4) * var(--space-y-reverse)); + } +} + +@layer recipes { + .emotion-1 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + width: var(--chakra-sizes-full); + gap: var(--chakra-spacing-4); + } +} + +.emotion-2 { + margin-top: var(--chakra-spacing-1); + margin-bottom: var(--chakra-spacing-4); +} + +@layer recipes { + .emotion-3 { + font-family: var(--chakra-fonts-heading); + font-weight: var(--chakra-font-weights-semibold); + font-size: var(--chakra-font-sizes-xl); + line-height: 1.875rem; + } +} + +@layer recipes { + .emotion-4 { + display: block; + border-color: var(--chakra-colors-border); + --separator-thickness: 1px; + border-style: solid; + border-top-width: var(--separator-thickness); + } +} + +.emotion-5 { + display: grid; + gap: var(--chakra-spacing-4); + margin-bottom: var(--chakra-spacing-4); +} + +.emotion-14 { + margin-bottom: var(--chakra-spacing-1); +} + +@layer recipes { + .emotion-14 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + width: 100%; + position: relative; + gap: var(--chakra-spacing-1\\.5); + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + -webkit-align-items: flex-start; + -webkit-box-align: flex-start; + -ms-flex-align: flex-start; + align-items: flex-start; + } +} + +@layer recipes { + .emotion-15 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + text-align: start; + font-size: var(--chakra-font-sizes-sm); + line-height: 1.25rem; + font-weight: var(--chakra-font-weights-medium); + gap: var(--chakra-spacing-1); + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + } + + .emotion-15:is(:disabled, [disabled], [data-disabled], [aria-disabled=true]) { + opacity: 0.5; + } +} + +@layer recipes { + .emotion-16 { + width: 100%; + min-width: var(--input-height); + outline: 0; + position: relative; + -webkit-appearance: none; + -moz-appearance: none; + -ms-appearance: none; + appearance: none; + text-align: start; + border-radius: var(--chakra-radii-l2); + height: var(--input-height); + --focus-color: var(--chakra-colors-color-palette-focus-ring); + --error-color: var(--chakra-colors-border-error); + font-size: var(--chakra-font-sizes-sm); + line-height: 1.25rem; + padding-inline: var(--chakra-spacing-3); + --input-height: var(--chakra-sizes-10); + background: var(--chakra-colors-transparent); + --bg-currentcolor: var(--chakra-colors-transparent); + border-width: 1px; + border-color: var(--chakra-colors-border); + --focus-ring-color: var(--focus-color); + } + + .emotion-16:is(:disabled, [disabled], [data-disabled], [aria-disabled=true]) { + opacity: 0.5; + cursor: not-allowed; + } + + .emotion-16:is([data-invalid], [aria-invalid=true], [data-state=invalid]) { + --focus-ring-color: var(--error-color); + border-color: var(--error-color); + } + + .emotion-16:is(:focus-visible, [data-focus-visible]) { + outline-offset: 0px; + outline-width: var(--focus-ring-width, 1px); + outline-color: var(--focus-ring-color); + outline-style: var(--focus-ring-style, solid); + border-color: var(--focus-ring-color); + } +} + +.emotion-39 { + display: grid; +} + +.emotion-40 { + justify-self: flex-end; +} + +.emotion-41 { + margin-top: var(--chakra-spacing-2); +} + +@layer recipes { + .emotion-42 { + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + -webkit-appearance: none; + -moz-appearance: none; + -ms-appearance: none; + appearance: none; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + -webkit-justify-content: center; + justify-content: center; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + position: relative; + border-radius: var(--chakra-radii-l2); + white-space: nowrap; + vertical-align: middle; + border-width: 1px; + border-color: var(--chakra-colors-transparent); + cursor: var(--chakra-cursor-button); + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; + outline: 0; + line-height: 1.25rem; + isolation: isolate; + font-weight: var(--chakra-font-weights-medium); + transition-property: background-color,border-color,color,fill,stroke,opacity,box-shadow,translate,transform; + transition-duration: var(--chakra-durations-moderate); + --focus-ring-color: var(--chakra-colors-color-palette-focus-ring); + height: var(--chakra-sizes-10); + min-width: var(--chakra-sizes-10); + font-size: var(--chakra-font-sizes-sm); + padding-inline: var(--chakra-spacing-4); + gap: var(--chakra-spacing-2); + background: var(--chakra-colors-color-palette-solid); + --bg-currentcolor: var(--chakra-colors-color-palette-solid); + color: var(--chakra-colors-color-palette-contrast); + } + + .emotion-42:is(:focus-visible, [data-focus-visible]) { + outline-width: var(--focus-ring-width, 2px); + outline-offset: var(--focus-ring-offset, 2px); + outline-style: var(--focus-ring-style, solid); + outline-color: var(--focus-ring-color); + } + + .emotion-42:is(:disabled, [disabled], [data-disabled], [aria-disabled=true]) { + opacity: 0.5; + cursor: not-allowed; + } + + .emotion-42 :where(svg) { + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; + width: var(--chakra-sizes-5); + height: var(--chakra-sizes-5); + } + + .emotion-42:is([aria-expanded=true], [data-expanded], [data-state=expanded]) { + --mix-background: color-mix(in srgb, var(--chakra-colors-color-palette-solid) 90%, transparent); + background: var(--mix-background, var(--chakra-colors-color-palette-solid)); + --bg-currentcolor: var(--mix-background, var(--chakra-colors-color-palette-solid)); + } + + @media (hover: hover) { + .emotion-42:is(:hover, [data-hover]):not(:disabled, [data-disabled]) { + --mix-background: color-mix(in srgb, var(--chakra-colors-color-palette-solid) 90%, transparent); + background: var(--mix-background, var(--chakra-colors-color-palette-solid)); + --bg-currentcolor: var(--mix-background, var(--chakra-colors-color-palette-solid)); + } + } +} + +.emotion-64 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: flex-end; + -webkit-box-align: flex-end; + -ms-flex-align: flex-end; + align-items: flex-end; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + gap: 0.5rem; + padding-block: var(--chakra-spacing-1); +} + +.emotion-65 { + width: 100%; +} + +@layer recipes { + .emotion-70 { + color: var(--chakra-colors-fg-error); + line-height: 1; + } +} + +.emotion-72 { + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: start; + -ms-flex-pack: start; + -webkit-justify-content: flex-start; + justify-content: flex-start; + margin-bottom: var(--chakra-spacing-1); +} + +@layer recipes { + .emotion-72 { + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + gap: 0!important; + isolation: isolate; + position: relative; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + } + + .emotion-72 [data-group-item]:is(:focus-visible, [data-focus-visible]) { + z-index: 1; + } + + .emotion-72>*[data-first] { + border-start-end-radius: 0!important; + border-end-end-radius: 0!important; + -webkit-margin-end: -1px; + margin-inline-end: -1px; + } + + .emotion-72>*[data-between] { + border-radius: 0!important; + -webkit-margin-end: -1px; + margin-inline-end: -1px; + } + + .emotion-72>*[data-last] { + border-start-start-radius: 0!important; + border-end-start-radius: 0!important; + } +} + +.emotion-73 { + padding-inline: 0; + padding-block: 0; +} + +@layer recipes { + .emotion-73 { + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + -webkit-appearance: none; + -moz-appearance: none; + -ms-appearance: none; + appearance: none; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + -webkit-justify-content: center; + justify-content: center; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + position: relative; + border-radius: var(--chakra-radii-l2); + white-space: nowrap; + vertical-align: middle; + border-width: 1px; + border-color: var(--chakra-colors-transparent); + cursor: var(--chakra-cursor-button); + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; + outline: 0; + line-height: 1.25rem; + isolation: isolate; + font-weight: var(--chakra-font-weights-medium); + transition-property: background-color,border-color,color,fill,stroke,opacity,box-shadow,translate,transform; + transition-duration: var(--chakra-durations-moderate); + --focus-ring-color: var(--chakra-colors-color-palette-focus-ring); + height: var(--chakra-sizes-10); + min-width: var(--chakra-sizes-10); + font-size: var(--chakra-font-sizes-sm); + padding-inline: var(--chakra-spacing-4); + gap: var(--chakra-spacing-2); + background: var(--chakra-colors-color-palette-solid); + --bg-currentcolor: var(--chakra-colors-color-palette-solid); + color: var(--chakra-colors-color-palette-contrast); + } + + .emotion-73:is(:focus-visible, [data-focus-visible]) { + outline-width: var(--focus-ring-width, 2px); + outline-offset: var(--focus-ring-offset, 2px); + outline-style: var(--focus-ring-style, solid); + outline-color: var(--focus-ring-color); + } + + .emotion-73:is(:disabled, [disabled], [data-disabled], [aria-disabled=true]) { + opacity: 0.5; + cursor: not-allowed; + } + + .emotion-73 :where(svg) { + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; + width: var(--chakra-sizes-5); + height: var(--chakra-sizes-5); + } + + .emotion-73:is([aria-expanded=true], [data-expanded], [data-state=expanded]) { + --mix-background: color-mix(in srgb, var(--chakra-colors-color-palette-solid) 90%, transparent); + background: var(--mix-background, var(--chakra-colors-color-palette-solid)); + --bg-currentcolor: var(--mix-background, var(--chakra-colors-color-palette-solid)); + } + + @media (hover: hover) { + .emotion-73:is(:hover, [data-hover]):not(:disabled, [data-disabled]) { + --mix-background: color-mix(in srgb, var(--chakra-colors-color-palette-solid) 90%, transparent); + background: var(--mix-background, var(--chakra-colors-color-palette-solid)); + --bg-currentcolor: var(--mix-background, var(--chakra-colors-color-palette-solid)); + } + } +} + +.emotion-73 :where(svg) { + font-size: 1.2em; +} + +.emotion-99 { + margin-bottom: var(--chakra-spacing-2); +} + +@layer recipes { + .emotion-99 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + position: relative; + min-width: 0; + word-wrap: break-word; + border-radius: var(--chakra-radii-l3); + color: var(--chakra-colors-fg); + text-align: start; + background: var(--chakra-colors-bg-panel); + --bg-currentcolor: var(--chakra-colors-bg-panel); + border-width: 1px; + border-color: var(--chakra-colors-border); + --card-padding: var(--chakra-spacing-6); + } +} + +.emotion-100 { + padding-bottom: var(--chakra-spacing-2); +} + +@layer recipes { + .emotion-100 { + padding: var(--card-padding); + -webkit-flex: 1; + -ms-flex: 1; + flex: 1; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + } +} + +.emotion-101 { + margin-bottom: var(--chakra-spacing-4); +} + +.emotion-102 { + margin-bottom: var(--chakra-spacing-1); + position: relative; +} + +@layer recipes { + .emotion-102 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + width: 100%; + position: relative; + gap: var(--chakra-spacing-1\\.5); + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + -webkit-align-items: flex-start; + -webkit-box-align: flex-start; + -ms-flex-align: flex-start; + align-items: flex-start; + } +} + +@layer recipes { + .emotion-104 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + gap: var(--chakra-spacing-1\\.5); + width: var(--chakra-sizes-full); + --select-trigger-height: var(--chakra-sizes-10); + --select-trigger-padding-x: var(--chakra-spacing-3); + } +} + +@layer recipes { + .emotion-105 { + position: relative; + } +} + +@layer recipes { + .emotion-107 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: justify; + -webkit-justify-content: space-between; + justify-content: space-between; + width: var(--chakra-sizes-full); + min-height: var(--select-trigger-height); + --input-height: var(--select-trigger-height); + padding-inline: var(--select-trigger-padding-x); + border-radius: var(--chakra-radii-l2); + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + text-align: start; + --focus-ring-color: var(--chakra-colors-color-palette-focus-ring); + font-size: var(--chakra-font-sizes-sm); + line-height: 1.25rem; + gap: var(--chakra-spacing-2); + background: var(--chakra-colors-transparent); + --bg-currentcolor: var(--chakra-colors-transparent); + border-width: 1px; + border-color: var(--chakra-colors-border); + } + + .emotion-107:is(:focus-visible, [data-focus-visible]) { + outline-offset: 0px; + outline-width: var(--focus-ring-width, 1px); + outline-color: var(--focus-ring-color); + outline-style: var(--focus-ring-style, solid); + border-color: var(--focus-ring-color); + } + + .emotion-107:is(:placeholder-shown, [data-placeholder-shown]) { + --mix-color: color-mix(in srgb, var(--chakra-colors-fg-muted) 80%, transparent); + color: var(--mix-color, var(--chakra-colors-fg-muted)); + } + + .emotion-107:is(:disabled, [disabled], [data-disabled], [aria-disabled=true]) { + opacity: 0.5; + cursor: not-allowed; + } + + .emotion-107:is([data-invalid], [aria-invalid=true], [data-state=invalid]) { + border-color: var(--chakra-colors-border-error); + } + + .emotion-107:is([aria-expanded=true], [data-expanded], [data-state=expanded]) { + border-color: var(--chakra-colors-border-emphasized); + } +} + +@layer recipes { + .emotion-108 { + overflow: hidden; + display: -webkit-box; + -webkit-line-clamp: 1; + -webkit-box-orient: vertical; + text-wrap: wrap; + max-width: 80%; + } +} + +@layer recipes { + .emotion-109 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + gap: var(--chakra-spacing-1); + position: absolute; + inset-inline-end: 0; + top: 0; + bottom: 0; + padding-inline: var(--select-trigger-padding-x); + pointer-events: none; + } +} + +@layer recipes { + .emotion-110 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + -webkit-justify-content: center; + justify-content: center; + color: var(--chakra-colors-fg-muted); + } + + .emotion-110:is(:disabled, [disabled], [data-disabled], [aria-disabled=true]) { + color: var(--chakra-colors-fg-subtle); + } + + .emotion-110:is([data-invalid], [aria-invalid=true], [data-state=invalid]) { + color: var(--chakra-colors-fg-error); + } + + .emotion-110 :where(svg) { + width: var(--chakra-sizes-4); + height: var(--chakra-sizes-4); + } +} + +.emotion-111 { + fill: none; + stroke: currentColor; + stroke-width: 2; + stroke-linecap: round; + stroke-linejoin: round; +} + +.emotion-112 { + min-width: 100%!important; + z-index: 2!important; + top: calc(100% + 5px)!important; +} + +@layer recipes { + .emotion-113 { + background: var(--chakra-colors-bg-panel); + --bg-currentcolor: var(--chakra-colors-bg-panel); + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + z-index: var(--chakra-z-index-dropdown); + border-radius: var(--chakra-radii-l2); + outline: 0; + max-height: var(--chakra-sizes-96); + overflow-y: auto; + box-shadow: var(--chakra-shadows-md); + padding: var(--chakra-spacing-1); + font-size: var(--chakra-font-sizes-sm); + line-height: 1.25rem; + } + + .emotion-113:is([open], [data-open], [data-state=open]) { + transform-origin: var(--transform-origin); + -webkit-animation-duration: var(--chakra-durations-fast); + animation-duration: var(--chakra-durations-fast); + } + + .emotion-113:is([open], [data-open], [data-state=open])[data-placement^=top] { + -webkit-animation-name: slide-from-bottom,fade-in; + animation-name: slide-from-bottom,fade-in; + } + + .emotion-113:is([open], [data-open], [data-state=open])[data-placement^=bottom] { + -webkit-animation-name: slide-from-top,fade-in; + animation-name: slide-from-top,fade-in; + } + + .emotion-113:is([open], [data-open], [data-state=open])[data-placement^=left] { + -webkit-animation-name: slide-from-right,fade-in; + animation-name: slide-from-right,fade-in; + } + + .emotion-113:is([open], [data-open], [data-state=open])[data-placement^=right] { + -webkit-animation-name: slide-from-left,fade-in; + animation-name: slide-from-left,fade-in; + } + + .emotion-113:is([closed], [data-closed], [data-state=closed]) { + transform-origin: var(--transform-origin); + -webkit-animation-duration: var(--chakra-durations-fastest); + animation-duration: var(--chakra-durations-fastest); + } + + .emotion-113:is([closed], [data-closed], [data-state=closed])[data-placement^=top] { + -webkit-animation-name: slide-to-bottom,fade-out; + animation-name: slide-to-bottom,fade-out; + } + + .emotion-113:is([closed], [data-closed], [data-state=closed])[data-placement^=bottom] { + -webkit-animation-name: slide-to-top,fade-out; + animation-name: slide-to-top,fade-out; + } + + .emotion-113:is([closed], [data-closed], [data-state=closed])[data-placement^=left] { + -webkit-animation-name: slide-to-right,fade-out; + animation-name: slide-to-right,fade-out; + } + + .emotion-113:is([closed], [data-closed], [data-state=closed])[data-placement^=right] { + -webkit-animation-name: slide-to-left,fade-out; + animation-name: slide-to-left,fade-out; + } +} + +@layer recipes { + .emotion-114 { + position: relative; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + gap: var(--chakra-spacing-2); + cursor: var(--chakra-cursor-option); + -webkit-box-pack: justify; + -webkit-justify-content: space-between; + justify-content: space-between; + -webkit-flex: 1; + -ms-flex: 1; + flex: 1; + text-align: start; + border-radius: var(--chakra-radii-l1); + padding-block: var(--chakra-spacing-1\\.5); + padding-inline: var(--chakra-spacing-2); + } + + .emotion-114[data-highlighted] { + --mix-background: color-mix(in srgb, var(--chakra-colors-bg-emphasized) 60%, transparent); + background: var(--mix-background, var(--chakra-colors-bg-emphasized)); + --bg-currentcolor: var(--mix-background, var(--chakra-colors-bg-emphasized)); + } + + .emotion-114:is(:disabled, [disabled], [data-disabled], [aria-disabled=true]) { + pointer-events: none; + opacity: 0.5; + } + + .emotion-114 :where(svg) { + width: var(--chakra-sizes-4); + height: var(--chakra-sizes-4); + } +} + +@layer recipes { + .emotion-115 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + -webkit-justify-content: center; + justify-content: center; + } +} + +.emotion-134 { + margin-top: var(--chakra-spacing-3); +} + +
+
+
+
+
+
+ test +
+ +
+
+
+
+
+
+
+
+
+ nestedObjectOptional +
+ +
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+
+ deepObjectOptional +
+ +
+
+
+ + No data for optional field + +
+
+
+
+
+
+
+
+
+
+
+
+ deepObject +
+ +
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ deepArrayOptional +
+ +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ deepArrayOptional2 +
+ +
+
+
+ + No data for optional field + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+ deepArray +
+ +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ nestedArrayOptional +
+ +
+
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+ nestedObject +
+ +
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ nestedArray +
+ +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+
+ +
+
+ + + +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+ optionalObjectWithOneofs +
+ +
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+`; + +exports[`single fields optional data controls shows "add" optional controls when turned on in uiSchema and no formData 1`] = ` +@layer recipes { + .emotion-0 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + width: var(--chakra-sizes-full); + } + + .emotion-0>:not(style, [hidden])~:not(style, [hidden]) { + --space-y-reverse: 0; + margin-top: calc(var(--chakra-spacing-4) * calc(1 - var(--space-y-reverse))); + margin-bottom: calc(var(--chakra-spacing-4) * var(--space-y-reverse)); + } +} + +@layer recipes { + .emotion-1 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + width: var(--chakra-sizes-full); + gap: var(--chakra-spacing-4); + } +} + +.emotion-2 { + margin-top: var(--chakra-spacing-1); + margin-bottom: var(--chakra-spacing-4); +} + +@layer recipes { + .emotion-3 { + font-family: var(--chakra-fonts-heading); + font-weight: var(--chakra-font-weights-semibold); + font-size: var(--chakra-font-sizes-xl); + line-height: 1.875rem; + } +} + +@layer recipes { + .emotion-4 { + display: block; + border-color: var(--chakra-colors-border); + --separator-thickness: 1px; + border-style: solid; + border-top-width: var(--separator-thickness); + } +} + +.emotion-5 { + display: grid; + gap: var(--chakra-spacing-4); + margin-bottom: var(--chakra-spacing-4); +} + +.emotion-9 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; +} + +@layer recipes { + .emotion-11 { + -webkit-flex: 1; + -ms-flex: 1; + flex: 1; + justify-self: stretch; + -webkit-align-self: stretch; + -ms-flex-item-align: stretch; + align-self: stretch; + } +} + +.emotion-12 { + padding-inline: 0; + padding-block: 0; +} + +@layer recipes { + .emotion-12 { + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + -webkit-appearance: none; + -moz-appearance: none; + -ms-appearance: none; + appearance: none; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + -webkit-justify-content: center; + justify-content: center; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + position: relative; + border-radius: var(--chakra-radii-l2); + white-space: nowrap; + vertical-align: middle; + border-width: 1px; + border-color: var(--chakra-colors-transparent); + cursor: var(--chakra-cursor-button); + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; + outline: 0; + line-height: 1rem; + isolation: isolate; + font-weight: var(--chakra-font-weights-medium); + transition-property: background-color,border-color,color,fill,stroke,opacity,box-shadow,translate,transform; + transition-duration: var(--chakra-durations-moderate); + --focus-ring-color: var(--chakra-colors-color-palette-focus-ring); + height: var(--chakra-sizes-8); + min-width: var(--chakra-sizes-8); + font-size: var(--chakra-font-sizes-xs); + padding-inline: var(--chakra-spacing-2\\.5); + gap: var(--chakra-spacing-1); + background: var(--chakra-colors-color-palette-subtle); + --bg-currentcolor: var(--chakra-colors-color-palette-subtle); + color: var(--chakra-colors-color-palette-fg); + } + + .emotion-12:is(:focus-visible, [data-focus-visible]) { + outline-width: var(--focus-ring-width, 2px); + outline-offset: var(--focus-ring-offset, 2px); + outline-style: var(--focus-ring-style, solid); + outline-color: var(--focus-ring-color); + } + + .emotion-12:is(:disabled, [disabled], [data-disabled], [aria-disabled=true]) { + opacity: 0.5; + cursor: not-allowed; + } + + .emotion-12 :where(svg) { + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; + width: var(--chakra-sizes-4); + height: var(--chakra-sizes-4); + } + + .emotion-12:is([aria-expanded=true], [data-expanded], [data-state=expanded]) { + background: var(--chakra-colors-color-palette-muted); + --bg-currentcolor: var(--chakra-colors-color-palette-muted); + } + + @media (hover: hover) { + .emotion-12:is(:hover, [data-hover]):not(:disabled, [data-disabled]) { + background: var(--chakra-colors-color-palette-muted); + --bg-currentcolor: var(--chakra-colors-color-palette-muted); + } + } +} + +.emotion-12 :where(svg) { + font-size: 1.2em; +} + +.emotion-23 { + display: grid; +} + +.emotion-32 { + margin-bottom: var(--chakra-spacing-1); +} + +@layer recipes { + .emotion-32 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + width: 100%; + position: relative; + gap: var(--chakra-spacing-1\\.5); + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + -webkit-align-items: flex-start; + -webkit-box-align: flex-start; + -ms-flex-align: flex-start; + align-items: flex-start; + } +} + +@layer recipes { + .emotion-33 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + text-align: start; + font-size: var(--chakra-font-sizes-sm); + line-height: 1.25rem; + font-weight: var(--chakra-font-weights-medium); + gap: var(--chakra-spacing-1); + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + } + + .emotion-33:is(:disabled, [disabled], [data-disabled], [aria-disabled=true]) { + opacity: 0.5; + } +} + +@layer recipes { + .emotion-34 { + width: 100%; + min-width: var(--input-height); + outline: 0; + position: relative; + -webkit-appearance: none; + -moz-appearance: none; + -ms-appearance: none; + appearance: none; + text-align: start; + border-radius: var(--chakra-radii-l2); + height: var(--input-height); + --focus-color: var(--chakra-colors-color-palette-focus-ring); + --error-color: var(--chakra-colors-border-error); + font-size: var(--chakra-font-sizes-sm); + line-height: 1.25rem; + padding-inline: var(--chakra-spacing-3); + --input-height: var(--chakra-sizes-10); + background: var(--chakra-colors-transparent); + --bg-currentcolor: var(--chakra-colors-transparent); + border-width: 1px; + border-color: var(--chakra-colors-border); + --focus-ring-color: var(--focus-color); + } + + .emotion-34:is(:disabled, [disabled], [data-disabled], [aria-disabled=true]) { + opacity: 0.5; + cursor: not-allowed; + } + + .emotion-34:is([data-invalid], [aria-invalid=true], [data-state=invalid]) { + --focus-ring-color: var(--error-color); + border-color: var(--error-color); + } + + .emotion-34:is(:focus-visible, [data-focus-visible]) { + outline-offset: 0px; + outline-width: var(--focus-ring-width, 1px); + outline-color: var(--focus-ring-color); + outline-style: var(--focus-ring-style, solid); + border-color: var(--focus-ring-color); + } +} + +.emotion-41 { + justify-self: flex-end; +} + +.emotion-42 { + margin-top: var(--chakra-spacing-2); +} + +@layer recipes { + .emotion-43 { + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + -webkit-appearance: none; + -moz-appearance: none; + -ms-appearance: none; + appearance: none; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + -webkit-justify-content: center; + justify-content: center; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + position: relative; + border-radius: var(--chakra-radii-l2); + white-space: nowrap; + vertical-align: middle; + border-width: 1px; + border-color: var(--chakra-colors-transparent); + cursor: var(--chakra-cursor-button); + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; + outline: 0; + line-height: 1.25rem; + isolation: isolate; + font-weight: var(--chakra-font-weights-medium); + transition-property: background-color,border-color,color,fill,stroke,opacity,box-shadow,translate,transform; + transition-duration: var(--chakra-durations-moderate); + --focus-ring-color: var(--chakra-colors-color-palette-focus-ring); + height: var(--chakra-sizes-10); + min-width: var(--chakra-sizes-10); + font-size: var(--chakra-font-sizes-sm); + padding-inline: var(--chakra-spacing-4); + gap: var(--chakra-spacing-2); + background: var(--chakra-colors-color-palette-solid); + --bg-currentcolor: var(--chakra-colors-color-palette-solid); + color: var(--chakra-colors-color-palette-contrast); + } + + .emotion-43:is(:focus-visible, [data-focus-visible]) { + outline-width: var(--focus-ring-width, 2px); + outline-offset: var(--focus-ring-offset, 2px); + outline-style: var(--focus-ring-style, solid); + outline-color: var(--focus-ring-color); + } + + .emotion-43:is(:disabled, [disabled], [data-disabled], [aria-disabled=true]) { + opacity: 0.5; + cursor: not-allowed; + } + + .emotion-43 :where(svg) { + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; + width: var(--chakra-sizes-5); + height: var(--chakra-sizes-5); + } + + .emotion-43:is([aria-expanded=true], [data-expanded], [data-state=expanded]) { + --mix-background: color-mix(in srgb, var(--chakra-colors-color-palette-solid) 90%, transparent); + background: var(--mix-background, var(--chakra-colors-color-palette-solid)); + --bg-currentcolor: var(--mix-background, var(--chakra-colors-color-palette-solid)); + } + + @media (hover: hover) { + .emotion-43:is(:hover, [data-hover]):not(:disabled, [data-disabled]) { + --mix-background: color-mix(in srgb, var(--chakra-colors-color-palette-solid) 90%, transparent); + background: var(--mix-background, var(--chakra-colors-color-palette-solid)); + --bg-currentcolor: var(--mix-background, var(--chakra-colors-color-palette-solid)); + } + } +} + +.emotion-46 { + margin-bottom: var(--chakra-spacing-2); +} + +@layer recipes { + .emotion-46 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + position: relative; + min-width: 0; + word-wrap: break-word; + border-radius: var(--chakra-radii-l3); + color: var(--chakra-colors-fg); + text-align: start; + background: var(--chakra-colors-bg-panel); + --bg-currentcolor: var(--chakra-colors-bg-panel); + border-width: 1px; + border-color: var(--chakra-colors-border); + --card-padding: var(--chakra-spacing-6); + } +} + +.emotion-47 { + padding-bottom: var(--chakra-spacing-2); +} + +@layer recipes { + .emotion-47 { + padding: var(--card-padding); + -webkit-flex: 1; + -ms-flex: 1; + flex: 1; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + } +} + +.emotion-48 { + margin-bottom: var(--chakra-spacing-4); +} + +.emotion-49 { + margin-bottom: var(--chakra-spacing-1); + position: relative; +} + +@layer recipes { + .emotion-49 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + width: 100%; + position: relative; + gap: var(--chakra-spacing-1\\.5); + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + -webkit-align-items: flex-start; + -webkit-box-align: flex-start; + -ms-flex-align: flex-start; + align-items: flex-start; + } +} + +@layer recipes { + .emotion-51 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + gap: var(--chakra-spacing-1\\.5); + width: var(--chakra-sizes-full); + --select-trigger-height: var(--chakra-sizes-10); + --select-trigger-padding-x: var(--chakra-spacing-3); + } +} + +@layer recipes { + .emotion-52 { + position: relative; + } +} + +@layer recipes { + .emotion-54 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: justify; + -webkit-justify-content: space-between; + justify-content: space-between; + width: var(--chakra-sizes-full); + min-height: var(--select-trigger-height); + --input-height: var(--select-trigger-height); + padding-inline: var(--select-trigger-padding-x); + border-radius: var(--chakra-radii-l2); + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + text-align: start; + --focus-ring-color: var(--chakra-colors-color-palette-focus-ring); + font-size: var(--chakra-font-sizes-sm); + line-height: 1.25rem; + gap: var(--chakra-spacing-2); + background: var(--chakra-colors-transparent); + --bg-currentcolor: var(--chakra-colors-transparent); + border-width: 1px; + border-color: var(--chakra-colors-border); + } + + .emotion-54:is(:focus-visible, [data-focus-visible]) { + outline-offset: 0px; + outline-width: var(--focus-ring-width, 1px); + outline-color: var(--focus-ring-color); + outline-style: var(--focus-ring-style, solid); + border-color: var(--focus-ring-color); + } + + .emotion-54:is(:placeholder-shown, [data-placeholder-shown]) { + --mix-color: color-mix(in srgb, var(--chakra-colors-fg-muted) 80%, transparent); + color: var(--mix-color, var(--chakra-colors-fg-muted)); + } + + .emotion-54:is(:disabled, [disabled], [data-disabled], [aria-disabled=true]) { + opacity: 0.5; + cursor: not-allowed; + } + + .emotion-54:is([data-invalid], [aria-invalid=true], [data-state=invalid]) { + border-color: var(--chakra-colors-border-error); + } + + .emotion-54:is([aria-expanded=true], [data-expanded], [data-state=expanded]) { + border-color: var(--chakra-colors-border-emphasized); + } +} + +@layer recipes { + .emotion-55 { + overflow: hidden; + display: -webkit-box; + -webkit-line-clamp: 1; + -webkit-box-orient: vertical; + text-wrap: wrap; + max-width: 80%; + } +} + +@layer recipes { + .emotion-56 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + gap: var(--chakra-spacing-1); + position: absolute; + inset-inline-end: 0; + top: 0; + bottom: 0; + padding-inline: var(--select-trigger-padding-x); + pointer-events: none; + } +} + +@layer recipes { + .emotion-57 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + -webkit-justify-content: center; + justify-content: center; + color: var(--chakra-colors-fg-muted); + } + + .emotion-57:is(:disabled, [disabled], [data-disabled], [aria-disabled=true]) { + color: var(--chakra-colors-fg-subtle); + } + + .emotion-57:is([data-invalid], [aria-invalid=true], [data-state=invalid]) { + color: var(--chakra-colors-fg-error); + } + + .emotion-57 :where(svg) { + width: var(--chakra-sizes-4); + height: var(--chakra-sizes-4); + } +} + +.emotion-58 { + fill: none; + stroke: currentColor; + stroke-width: 2; + stroke-linecap: round; + stroke-linejoin: round; +} + +.emotion-59 { + min-width: 100%!important; + z-index: 2!important; + top: calc(100% + 5px)!important; +} + +@layer recipes { + .emotion-60 { + background: var(--chakra-colors-bg-panel); + --bg-currentcolor: var(--chakra-colors-bg-panel); + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + z-index: var(--chakra-z-index-dropdown); + border-radius: var(--chakra-radii-l2); + outline: 0; + max-height: var(--chakra-sizes-96); + overflow-y: auto; + box-shadow: var(--chakra-shadows-md); + padding: var(--chakra-spacing-1); + font-size: var(--chakra-font-sizes-sm); + line-height: 1.25rem; + } + + .emotion-60:is([open], [data-open], [data-state=open]) { + transform-origin: var(--transform-origin); + -webkit-animation-duration: var(--chakra-durations-fast); + animation-duration: var(--chakra-durations-fast); + } + + .emotion-60:is([open], [data-open], [data-state=open])[data-placement^=top] { + -webkit-animation-name: slide-from-bottom,fade-in; + animation-name: slide-from-bottom,fade-in; + } + + .emotion-60:is([open], [data-open], [data-state=open])[data-placement^=bottom] { + -webkit-animation-name: slide-from-top,fade-in; + animation-name: slide-from-top,fade-in; + } + + .emotion-60:is([open], [data-open], [data-state=open])[data-placement^=left] { + -webkit-animation-name: slide-from-right,fade-in; + animation-name: slide-from-right,fade-in; + } + + .emotion-60:is([open], [data-open], [data-state=open])[data-placement^=right] { + -webkit-animation-name: slide-from-left,fade-in; + animation-name: slide-from-left,fade-in; + } + + .emotion-60:is([closed], [data-closed], [data-state=closed]) { + transform-origin: var(--transform-origin); + -webkit-animation-duration: var(--chakra-durations-fastest); + animation-duration: var(--chakra-durations-fastest); + } + + .emotion-60:is([closed], [data-closed], [data-state=closed])[data-placement^=top] { + -webkit-animation-name: slide-to-bottom,fade-out; + animation-name: slide-to-bottom,fade-out; + } + + .emotion-60:is([closed], [data-closed], [data-state=closed])[data-placement^=bottom] { + -webkit-animation-name: slide-to-top,fade-out; + animation-name: slide-to-top,fade-out; + } + + .emotion-60:is([closed], [data-closed], [data-state=closed])[data-placement^=left] { + -webkit-animation-name: slide-to-right,fade-out; + animation-name: slide-to-right,fade-out; + } + + .emotion-60:is([closed], [data-closed], [data-state=closed])[data-placement^=right] { + -webkit-animation-name: slide-to-left,fade-out; + animation-name: slide-to-left,fade-out; + } +} + +@layer recipes { + .emotion-61 { + position: relative; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + gap: var(--chakra-spacing-2); + cursor: var(--chakra-cursor-option); + -webkit-box-pack: justify; + -webkit-justify-content: space-between; + justify-content: space-between; + -webkit-flex: 1; + -ms-flex: 1; + flex: 1; + text-align: start; + border-radius: var(--chakra-radii-l1); + padding-block: var(--chakra-spacing-1\\.5); + padding-inline: var(--chakra-spacing-2); + } + + .emotion-61[data-highlighted] { + --mix-background: color-mix(in srgb, var(--chakra-colors-bg-emphasized) 60%, transparent); + background: var(--mix-background, var(--chakra-colors-bg-emphasized)); + --bg-currentcolor: var(--mix-background, var(--chakra-colors-bg-emphasized)); + } + + .emotion-61:is(:disabled, [disabled], [data-disabled], [aria-disabled=true]) { + pointer-events: none; + opacity: 0.5; + } + + .emotion-61 :where(svg) { + width: var(--chakra-sizes-4); + height: var(--chakra-sizes-4); + } +} + +@layer recipes { + .emotion-62 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + -webkit-justify-content: center; + justify-content: center; + } +} + +.emotion-81 { + margin-top: var(--chakra-spacing-3); +} + +
+
+
+
+
+
+ test +
+ +
+
+
+
+
+
+
+
+
+ nestedObjectOptional +
+
+ +
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+ nestedArrayOptional +
+
+ +
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ nestedObject +
+ +
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ nestedArray +
+ +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+
+ +
+
+ + + +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+ optionalObjectWithOneofs +
+ +
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+`; + +exports[`single fields optional data controls shows "add" optional controls when turned on in uiSchema, disabled and no formData 1`] = ` +@layer recipes { + .emotion-0 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + width: var(--chakra-sizes-full); + } + + .emotion-0>:not(style, [hidden])~:not(style, [hidden]) { + --space-y-reverse: 0; + margin-top: calc(var(--chakra-spacing-4) * calc(1 - var(--space-y-reverse))); + margin-bottom: calc(var(--chakra-spacing-4) * var(--space-y-reverse)); + } +} + +@layer recipes { + .emotion-1 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + width: var(--chakra-sizes-full); + gap: var(--chakra-spacing-4); + } +} + +.emotion-2 { + margin-top: var(--chakra-spacing-1); + margin-bottom: var(--chakra-spacing-4); +} + +@layer recipes { + .emotion-3 { + font-family: var(--chakra-fonts-heading); + font-weight: var(--chakra-font-weights-semibold); + font-size: var(--chakra-font-sizes-xl); + line-height: 1.875rem; + } +} + +@layer recipes { + .emotion-4 { + display: block; + border-color: var(--chakra-colors-border); + --separator-thickness: 1px; + border-style: solid; + border-top-width: var(--separator-thickness); + } +} + +.emotion-5 { + display: grid; + gap: var(--chakra-spacing-4); + margin-bottom: var(--chakra-spacing-4); +} + +.emotion-17 { + display: grid; +} + +.emotion-26 { + margin-bottom: var(--chakra-spacing-1); +} + +@layer recipes { + .emotion-26 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + width: 100%; + position: relative; + gap: var(--chakra-spacing-1\\.5); + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + -webkit-align-items: flex-start; + -webkit-box-align: flex-start; + -ms-flex-align: flex-start; + align-items: flex-start; + } +} + +@layer recipes { + .emotion-27 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + text-align: start; + font-size: var(--chakra-font-sizes-sm); + line-height: 1.25rem; + font-weight: var(--chakra-font-weights-medium); + gap: var(--chakra-spacing-1); + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + } + + .emotion-27:is(:disabled, [disabled], [data-disabled], [aria-disabled=true]) { + opacity: 0.5; + } +} + +@layer recipes { + .emotion-28 { + width: 100%; + min-width: var(--input-height); + outline: 0; + position: relative; + -webkit-appearance: none; + -moz-appearance: none; + -ms-appearance: none; + appearance: none; + text-align: start; + border-radius: var(--chakra-radii-l2); + height: var(--input-height); + --focus-color: var(--chakra-colors-color-palette-focus-ring); + --error-color: var(--chakra-colors-border-error); + font-size: var(--chakra-font-sizes-sm); + line-height: 1.25rem; + padding-inline: var(--chakra-spacing-3); + --input-height: var(--chakra-sizes-10); + background: var(--chakra-colors-transparent); + --bg-currentcolor: var(--chakra-colors-transparent); + border-width: 1px; + border-color: var(--chakra-colors-border); + --focus-ring-color: var(--focus-color); + } + + .emotion-28:is(:disabled, [disabled], [data-disabled], [aria-disabled=true]) { + opacity: 0.5; + cursor: not-allowed; + } + + .emotion-28:is([data-invalid], [aria-invalid=true], [data-state=invalid]) { + --focus-ring-color: var(--error-color); + border-color: var(--error-color); + } + + .emotion-28:is(:focus-visible, [data-focus-visible]) { + outline-offset: 0px; + outline-width: var(--focus-ring-width, 1px); + outline-color: var(--focus-ring-color); + outline-style: var(--focus-ring-style, solid); + border-color: var(--focus-ring-color); + } +} + +.emotion-35 { + justify-self: flex-end; +} + +.emotion-36 { + margin-top: var(--chakra-spacing-2); +} + +@layer recipes { + .emotion-37 { + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + -webkit-appearance: none; + -moz-appearance: none; + -ms-appearance: none; + appearance: none; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + -webkit-justify-content: center; + justify-content: center; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + position: relative; + border-radius: var(--chakra-radii-l2); + white-space: nowrap; + vertical-align: middle; + border-width: 1px; + border-color: var(--chakra-colors-transparent); + cursor: var(--chakra-cursor-button); + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; + outline: 0; + line-height: 1.25rem; + isolation: isolate; + font-weight: var(--chakra-font-weights-medium); + transition-property: background-color,border-color,color,fill,stroke,opacity,box-shadow,translate,transform; + transition-duration: var(--chakra-durations-moderate); + --focus-ring-color: var(--chakra-colors-color-palette-focus-ring); + height: var(--chakra-sizes-10); + min-width: var(--chakra-sizes-10); + font-size: var(--chakra-font-sizes-sm); + padding-inline: var(--chakra-spacing-4); + gap: var(--chakra-spacing-2); + background: var(--chakra-colors-color-palette-solid); + --bg-currentcolor: var(--chakra-colors-color-palette-solid); + color: var(--chakra-colors-color-palette-contrast); + } + + .emotion-37:is(:focus-visible, [data-focus-visible]) { + outline-width: var(--focus-ring-width, 2px); + outline-offset: var(--focus-ring-offset, 2px); + outline-style: var(--focus-ring-style, solid); + outline-color: var(--focus-ring-color); + } + + .emotion-37:is(:disabled, [disabled], [data-disabled], [aria-disabled=true]) { + opacity: 0.5; + cursor: not-allowed; + } + + .emotion-37 :where(svg) { + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; + width: var(--chakra-sizes-5); + height: var(--chakra-sizes-5); + } + + .emotion-37:is([aria-expanded=true], [data-expanded], [data-state=expanded]) { + --mix-background: color-mix(in srgb, var(--chakra-colors-color-palette-solid) 90%, transparent); + background: var(--mix-background, var(--chakra-colors-color-palette-solid)); + --bg-currentcolor: var(--mix-background, var(--chakra-colors-color-palette-solid)); + } + + @media (hover: hover) { + .emotion-37:is(:hover, [data-hover]):not(:disabled, [data-disabled]) { + --mix-background: color-mix(in srgb, var(--chakra-colors-color-palette-solid) 90%, transparent); + background: var(--mix-background, var(--chakra-colors-color-palette-solid)); + --bg-currentcolor: var(--mix-background, var(--chakra-colors-color-palette-solid)); + } + } +} + +.emotion-40 { + margin-bottom: var(--chakra-spacing-2); +} + +@layer recipes { + .emotion-40 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + position: relative; + min-width: 0; + word-wrap: break-word; + border-radius: var(--chakra-radii-l3); + color: var(--chakra-colors-fg); + text-align: start; + background: var(--chakra-colors-bg-panel); + --bg-currentcolor: var(--chakra-colors-bg-panel); + border-width: 1px; + border-color: var(--chakra-colors-border); + --card-padding: var(--chakra-spacing-6); + } +} + +.emotion-41 { + padding-bottom: var(--chakra-spacing-2); +} + +@layer recipes { + .emotion-41 { + padding: var(--card-padding); + -webkit-flex: 1; + -ms-flex: 1; + flex: 1; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + } +} + +.emotion-42 { + margin-bottom: var(--chakra-spacing-4); +} + +.emotion-43 { + margin-bottom: var(--chakra-spacing-1); + position: relative; +} + +@layer recipes { + .emotion-43 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + width: 100%; + position: relative; + gap: var(--chakra-spacing-1\\.5); + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + -webkit-align-items: flex-start; + -webkit-box-align: flex-start; + -ms-flex-align: flex-start; + align-items: flex-start; + } +} + +@layer recipes { + .emotion-45 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + gap: var(--chakra-spacing-1\\.5); + width: var(--chakra-sizes-full); + --select-trigger-height: var(--chakra-sizes-10); + --select-trigger-padding-x: var(--chakra-spacing-3); + } +} + +@layer recipes { + .emotion-46 { + position: relative; + } +} + +@layer recipes { + .emotion-48 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: justify; + -webkit-justify-content: space-between; + justify-content: space-between; + width: var(--chakra-sizes-full); + min-height: var(--select-trigger-height); + --input-height: var(--select-trigger-height); + padding-inline: var(--select-trigger-padding-x); + border-radius: var(--chakra-radii-l2); + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + text-align: start; + --focus-ring-color: var(--chakra-colors-color-palette-focus-ring); + font-size: var(--chakra-font-sizes-sm); + line-height: 1.25rem; + gap: var(--chakra-spacing-2); + background: var(--chakra-colors-transparent); + --bg-currentcolor: var(--chakra-colors-transparent); + border-width: 1px; + border-color: var(--chakra-colors-border); + } + + .emotion-48:is(:focus-visible, [data-focus-visible]) { + outline-offset: 0px; + outline-width: var(--focus-ring-width, 1px); + outline-color: var(--focus-ring-color); + outline-style: var(--focus-ring-style, solid); + border-color: var(--focus-ring-color); + } + + .emotion-48:is(:placeholder-shown, [data-placeholder-shown]) { + --mix-color: color-mix(in srgb, var(--chakra-colors-fg-muted) 80%, transparent); + color: var(--mix-color, var(--chakra-colors-fg-muted)); + } + + .emotion-48:is(:disabled, [disabled], [data-disabled], [aria-disabled=true]) { + opacity: 0.5; + cursor: not-allowed; + } + + .emotion-48:is([data-invalid], [aria-invalid=true], [data-state=invalid]) { + border-color: var(--chakra-colors-border-error); + } + + .emotion-48:is([aria-expanded=true], [data-expanded], [data-state=expanded]) { + border-color: var(--chakra-colors-border-emphasized); + } +} + +@layer recipes { + .emotion-49 { + overflow: hidden; + display: -webkit-box; + -webkit-line-clamp: 1; + -webkit-box-orient: vertical; + text-wrap: wrap; + max-width: 80%; + } +} + +@layer recipes { + .emotion-50 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + gap: var(--chakra-spacing-1); + position: absolute; + inset-inline-end: 0; + top: 0; + bottom: 0; + padding-inline: var(--select-trigger-padding-x); + pointer-events: none; + } +} + +@layer recipes { + .emotion-51 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + -webkit-justify-content: center; + justify-content: center; + color: var(--chakra-colors-fg-muted); + } + + .emotion-51:is(:disabled, [disabled], [data-disabled], [aria-disabled=true]) { + color: var(--chakra-colors-fg-subtle); + } + + .emotion-51:is([data-invalid], [aria-invalid=true], [data-state=invalid]) { + color: var(--chakra-colors-fg-error); + } + + .emotion-51 :where(svg) { + width: var(--chakra-sizes-4); + height: var(--chakra-sizes-4); + } +} + +.emotion-52 { + fill: none; + stroke: currentColor; + stroke-width: 2; + stroke-linecap: round; + stroke-linejoin: round; +} + +.emotion-53 { + min-width: 100%!important; + z-index: 2!important; + top: calc(100% + 5px)!important; +} + +@layer recipes { + .emotion-54 { + background: var(--chakra-colors-bg-panel); + --bg-currentcolor: var(--chakra-colors-bg-panel); + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + z-index: var(--chakra-z-index-dropdown); + border-radius: var(--chakra-radii-l2); + outline: 0; + max-height: var(--chakra-sizes-96); + overflow-y: auto; + box-shadow: var(--chakra-shadows-md); + padding: var(--chakra-spacing-1); + font-size: var(--chakra-font-sizes-sm); + line-height: 1.25rem; + } + + .emotion-54:is([open], [data-open], [data-state=open]) { + transform-origin: var(--transform-origin); + -webkit-animation-duration: var(--chakra-durations-fast); + animation-duration: var(--chakra-durations-fast); + } + + .emotion-54:is([open], [data-open], [data-state=open])[data-placement^=top] { + -webkit-animation-name: slide-from-bottom,fade-in; + animation-name: slide-from-bottom,fade-in; + } + + .emotion-54:is([open], [data-open], [data-state=open])[data-placement^=bottom] { + -webkit-animation-name: slide-from-top,fade-in; + animation-name: slide-from-top,fade-in; + } + + .emotion-54:is([open], [data-open], [data-state=open])[data-placement^=left] { + -webkit-animation-name: slide-from-right,fade-in; + animation-name: slide-from-right,fade-in; + } + + .emotion-54:is([open], [data-open], [data-state=open])[data-placement^=right] { + -webkit-animation-name: slide-from-left,fade-in; + animation-name: slide-from-left,fade-in; + } + + .emotion-54:is([closed], [data-closed], [data-state=closed]) { + transform-origin: var(--transform-origin); + -webkit-animation-duration: var(--chakra-durations-fastest); + animation-duration: var(--chakra-durations-fastest); + } + + .emotion-54:is([closed], [data-closed], [data-state=closed])[data-placement^=top] { + -webkit-animation-name: slide-to-bottom,fade-out; + animation-name: slide-to-bottom,fade-out; + } + + .emotion-54:is([closed], [data-closed], [data-state=closed])[data-placement^=bottom] { + -webkit-animation-name: slide-to-top,fade-out; + animation-name: slide-to-top,fade-out; + } + + .emotion-54:is([closed], [data-closed], [data-state=closed])[data-placement^=left] { + -webkit-animation-name: slide-to-right,fade-out; + animation-name: slide-to-right,fade-out; + } + + .emotion-54:is([closed], [data-closed], [data-state=closed])[data-placement^=right] { + -webkit-animation-name: slide-to-left,fade-out; + animation-name: slide-to-left,fade-out; + } +} + +@layer recipes { + .emotion-55 { + position: relative; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + gap: var(--chakra-spacing-2); + cursor: var(--chakra-cursor-option); + -webkit-box-pack: justify; + -webkit-justify-content: space-between; + justify-content: space-between; + -webkit-flex: 1; + -ms-flex: 1; + flex: 1; + text-align: start; + border-radius: var(--chakra-radii-l1); + padding-block: var(--chakra-spacing-1\\.5); + padding-inline: var(--chakra-spacing-2); + } + + .emotion-55[data-highlighted] { + --mix-background: color-mix(in srgb, var(--chakra-colors-bg-emphasized) 60%, transparent); + background: var(--mix-background, var(--chakra-colors-bg-emphasized)); + --bg-currentcolor: var(--mix-background, var(--chakra-colors-bg-emphasized)); + } + + .emotion-55:is(:disabled, [disabled], [data-disabled], [aria-disabled=true]) { + pointer-events: none; + opacity: 0.5; + } + + .emotion-55 :where(svg) { + width: var(--chakra-sizes-4); + height: var(--chakra-sizes-4); + } +} + +@layer recipes { + .emotion-56 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -ms-flex-pack: center; + -webkit-justify-content: center; + justify-content: center; + } +} + +.emotion-75 { + margin-top: var(--chakra-spacing-3); +} + +
+
+
+
+
+
+ test +
+ +
+
+
+
+
+
+
+
+
+ nestedObjectOptional +
+ +
+
+
+ + No data for optional field + +
+
+
+
+
+
+
+
+
+
+
+
+
+ nestedArrayOptional +
+ +
+
+
+ + No data for optional field + +
+
+
+
+
+
+
+
+
+
+
+
+
+ nestedObject +
+ +
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ nestedArray +
+ +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+
+ +
+
+ + + +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+ optionalObjectWithOneofs +
+ +
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+`; + exports[`single fields password field 1`] = ` @layer recipes { .emotion-0 { diff --git a/packages/core/test/__snapshots__/FormSnap.test.tsx.snap b/packages/core/test/__snapshots__/FormSnap.test.tsx.snap index 4676709dab..36c6712ae2 100644 --- a/packages/core/test/__snapshots__/FormSnap.test.tsx.snap +++ b/packages/core/test/__snapshots__/FormSnap.test.tsx.snap @@ -970,6 +970,2566 @@ exports[`single fields number field 1`] = ` `; +exports[`single fields optional data controls does not show optional controls when not turned on in uiSchema and no formData 1`] = ` +
+
+
+ + test + +
+
+ + nestedObjectOptional + +
+ + +
+
+
+ + deepObjectOptional + +
+ + +
+
+
+
+
+ + deepObject + + * + + +
+ + +
+
+
+
+
+ + deepArrayOptional + +
+
+

+ +

+
+
+
+
+
+ + deepArrayOptional2 + +
+
+

+ +

+
+
+
+
+
+ + deepArray + + * + + +
+
+

+ +

+
+
+
+
+
+
+
+ + nestedArrayOptional + +
+
+

+ +

+
+
+
+
+
+ + nestedObject + + * + + +
+ + +
+
+
+
+
+ + nestedArray + + * + + +
+
+

+ +

+
+
+
+
+ +
+
+ +
+
+
+ + optionalObjectWithOneofs + +
+ + +
+
+
+
+
+
+
+
+ +
+ +`; + +exports[`single fields optional data controls does not show optional controls when not turned on in uiSchema, readonly and no formData 1`] = ` +
+
+
+ + test + +
+
+ + nestedObjectOptional + +
+ + +
+
+
+ + deepObjectOptional + +
+ + +
+
+
+
+
+ + deepObject + + * + + +
+ + +
+
+
+
+
+ + deepArrayOptional + +
+
+

+ +

+
+
+
+
+
+ + deepArrayOptional2 + +
+
+

+ +

+
+
+
+
+
+ + deepArray + + * + + +
+
+

+ +

+
+
+
+
+
+
+
+ + nestedArrayOptional + +
+
+

+ +

+
+
+
+
+
+ + nestedObject + + * + + +
+ + +
+
+
+
+
+ + nestedArray + + * + + +
+
+

+ +

+
+
+
+
+ +
+
+ +
+
+
+ + optionalObjectWithOneofs + +
+ + +
+
+
+
+
+
+
+
+ +
+ +`; + +exports[`single fields optional data controls shows "add" and "remove" optional controls when turned on in uiSchema and formData 1`] = ` +
+
+
+ + test + +
+
+ + nestedObjectOptional + + + + +
+ + +
+
+
+ + deepObjectOptional + + + + +
+
+
+
+ + deepObject + + * + + +
+ + +
+
+
+
+
+ + deepArrayOptional + +
+
+

+ +

+
+
+
+
+
+ + deepArrayOptional2 + + + + +
+
+
+
+
+ + deepArray + + * + + +
+
+

+ +

+
+
+
+
+
+
+
+ + nestedArrayOptional + + + + +
+
+
+
+ + +
+
+
+
+ +
+
+
+
+
+

+ +

+
+
+
+
+
+ + nestedObject + + * + + +
+ + +
+
+
+
+
+ + nestedArray + + * + + +
+
+

+ +

+
+
+
+
+ +
+
+ +
+
+
+ + optionalObjectWithOneofs + +
+ + +
+
+
+
+
+
+
+
+ +
+ +`; + +exports[`single fields optional data controls shows "add" and "remove" optional controls when turned on in uiSchema, readonly and formData 1`] = ` +
+
+
+ + test + +
+
+ + nestedObjectOptional + +
+ + +
+
+
+ + deepObjectOptional + + + No data for optional field + +
+
+
+
+ + deepObject + + * + + +
+ + +
+
+
+
+
+ + deepArrayOptional + +
+
+

+ +

+
+
+
+
+
+ + deepArrayOptional2 + + + No data for optional field + +
+
+
+
+
+ + deepArray + + * + + +
+
+

+ +

+
+
+
+
+
+
+
+ + nestedArrayOptional + +
+
+
+
+ + +
+
+
+
+ +
+
+
+
+
+

+ +

+
+
+
+
+
+ + nestedObject + + * + + +
+ + +
+
+
+
+
+ + nestedArray + + * + + +
+
+

+ +

+
+
+
+
+ +
+
+ +
+
+
+ + optionalObjectWithOneofs + +
+ + +
+
+
+
+
+
+
+
+ +
+ +`; + +exports[`single fields optional data controls shows "add" optional controls when turned on in uiSchema and no formData 1`] = ` +
+
+
+ + test + +
+
+ + nestedObjectOptional + + + + +
+
+
+
+ + nestedArrayOptional + + + + +
+
+
+
+
+ + nestedObject + + * + + +
+ + +
+
+
+
+
+ + nestedArray + + * + + +
+
+

+ +

+
+
+
+
+ +
+
+ +
+
+
+ + optionalObjectWithOneofs + +
+ + +
+
+
+
+
+
+
+
+ +
+ +`; + +exports[`single fields optional data controls shows "add" optional controls when turned on in uiSchema, disabled and no formData 1`] = ` +
+
+
+ + test + +
+
+ + nestedObjectOptional + + + No data for optional field + +
+
+
+
+ + nestedArrayOptional + + + No data for optional field + +
+
+
+
+
+ + nestedObject + + * + + +
+ + +
+
+
+
+
+ + nestedArray + + * + + +
+
+

+ +

+
+
+
+
+ +
+
+ +
+
+
+ + optionalObjectWithOneofs + +
+ + +
+
+
+
+
+
+
+
+ +
+ +`; + exports[`single fields password field 1`] = `
`; +exports[`single fields optional data controls does not show optional controls when not turned on in uiSchema and no formData 1`] = ` + +
+
+
+
+

+ test +

+
+
+
+
+
+
+
+
+

+ nestedObjectOptional +

+
+
+
+
+
+
+ +
+ + +
+
+
    +
+
+
+
+
+
+
+
+
+
+
+
+

+ deepObjectOptional +

+
+
+
+
+
+
+ +
+ + +
+
+
    +
+
+
+
+
+
+
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+
+
+

+ deepObject +

+
+
+
+
+
+
+ +
+ + +
+
+
    +
+
+
+
+
+
+
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+
+
+

+ deepArrayOptional +

+
+
+
+
+
+ No items yet. Use the button below to add some. +
+
+
+
+

+ +

+
+
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+
+
+

+ deepArrayOptional2 +

+
+
+
+
+
+ No items yet. Use the button below to add some. +
+
+
+
+

+ +

+
+
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+
+
+

+ deepArray +

+
+
+
+
+
+ No items yet. Use the button below to add some. +
+
+
+
+

+ +

+
+
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+
+
+

+ nestedArrayOptional +

+
+
+
+
+
+ No items yet. Use the button below to add some. +
+
+
+
+

+ +

+
+
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+
+
+

+ nestedObject +

+
+
+
+
+
+
+ +
+ + +
+
+
    +
+
+
+
+
+
+
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+
+
+

+ nestedArray +

+
+
+
+
+
+ No items yet. Use the button below to add some. +
+
+
+
+

+ +

+
+
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+ + Option 1 + + + â–¼ + +
+
    +
  • +
    + + Option 1 + +
    +
  • +
  • +
    + + Option 2 + +
    +
  • +
  • +
    + + Option 3 + +
    +
  • +
+
+
+
+
+
+
+
+

+ optionalObjectWithOneofs +

+
+
+
+
+
+
+ +
+ + +
+
+
    +
+
+
+
+
+
+
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
    +
+
+
+
+
+
+
+ +
+ +`; + +exports[`single fields optional data controls does not show optional controls when not turned on in uiSchema, readonly and no formData 1`] = ` +
+
+
+
+
+

+ test +

+
+
+
+
+
+
+
+
+

+ nestedObjectOptional +

+
+
+
+
+
+
+ +
+ + +
+
+
    +
+
+
+
+
+
+
+
+
+
+
+
+

+ deepObjectOptional +

+
+
+
+
+
+
+ +
+ + +
+
+
    +
+
+
+
+
+
+
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+
+
+

+ deepObject +

+
+
+
+
+
+
+ +
+ + +
+
+
    +
+
+
+
+
+
+
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+
+
+

+ deepArrayOptional +

+
+
+
+
+
+ No items yet. Use the button below to add some. +
+
+
+
+

+ +

+
+
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+
+
+

+ deepArrayOptional2 +

+
+
+
+
+
+ No items yet. Use the button below to add some. +
+
+
+
+

+ +

+
+
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+
+
+

+ deepArray +

+
+
+
+
+
+ No items yet. Use the button below to add some. +
+
+
+
+

+ +

+
+
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+
+
+

+ nestedArrayOptional +

+
+
+
+
+
+ No items yet. Use the button below to add some. +
+
+
+
+

+ +

+
+
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+
+
+

+ nestedObject +

+
+
+
+
+
+
+ +
+ + +
+
+
    +
+
+
+
+
+
+
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+
+
+

+ nestedArray +

+
+
+
+
+
+ No items yet. Use the button below to add some. +
+
+
+
+

+ +

+
+
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+ + Option 1 + + + â–¼ + +
+
    +
  • +
    + + Option 1 + +
    +
  • +
  • +
    + + Option 2 + +
    +
  • +
  • +
    + + Option 3 + +
    +
  • +
+
+
+
+
+
+
+
+

+ optionalObjectWithOneofs +

+
+
+
+
+
+
+ +
+ + +
+
+
    +
+
+
+
+
+
+
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
    +
+
+
+
+
+
+
+ +
+ +`; + +exports[`single fields optional data controls shows "add" and "remove" optional controls when turned on in uiSchema and formData 1`] = ` +
+
+
+
+
+

+ test +

+
+
+
+
+
+
+
+
+
+
+

+ nestedObjectOptional +

+
+
+ +
+
+
+
+
+
+
+
+ +
+ + +
+
+
    +
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ deepObjectOptional +

+
+
+ +
+
+
+
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+
+
+

+ deepObject +

+
+
+
+
+
+
+ +
+ + +
+
+
    +
+
+
+
+
+
+
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+
+
+

+ deepArrayOptional +

+
+
+
+
+
+ No items yet. Use the button below to add some. +
+
+
+
+

+ +

+
+
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ deepArrayOptional2 +

+
+
+ +
+
+
+
+
+
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+
+
+

+ deepArray +

+
+
+
+
+
+ No items yet. Use the button below to add some. +
+
+
+
+

+ +

+
+
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ nestedArrayOptional +

+
+
+ +
+
+
+
+
+
+
+
+
+ +
+ + +
+
+
    +
+
+
+
+
+
+
+ +
+
+
+
+
+

+ +

+
+
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+
+
+

+ nestedObject +

+
+
+
+
+
+
+ +
+ + +
+
+
    +
+
+
+
+
+
+
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+
+
+

+ nestedArray +

+
+
+
+
+
+ No items yet. Use the button below to add some. +
+
+
+
+

+ +

+
+
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+ + Option 1 + + + â–¼ + +
+
    +
  • +
    + + Option 1 + +
    +
  • +
  • +
    + + Option 2 + +
    +
  • +
  • +
    + + Option 3 + +
    +
  • +
+
+
+
+
+
+
+
+

+ optionalObjectWithOneofs +

+
+
+
+
+
+
+ +
+ + +
+
+
    +
+
+
+
+
+
+
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
    +
+
+
+
+
+
+
+ +
+ +`; + +exports[`single fields optional data controls shows "add" and "remove" optional controls when turned on in uiSchema, readonly and formData 1`] = ` +
+
+
+
+
+

+ test +

+
+
+
+
+
+
+
+
+

+ nestedObjectOptional +

+
+
+
+
+
+
+ +
+ + +
+
+
    +
+
+
+
+
+
+
+
+
+
+
+
+

+ deepObjectOptional +

+
+
+
+ + No data for optional field + +
+
+
+
    +
+
+
+
+
+
+
+
+
+
+
+
+

+ deepObject +

+
+
+
+
+
+
+ +
+ + +
+
+
    +
+
+
+
+
+
+
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+
+
+

+ deepArrayOptional +

+
+
+
+
+
+ No items yet. Use the button below to add some. +
+
+
+
+

+ +

+
+
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+
+
+

+ deepArrayOptional2 +

+
+
+
+ + No data for optional field + +
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+
+
+

+ deepArray +

+
+
+
+
+
+ No items yet. Use the button below to add some. +
+
+
+
+

+ +

+
+
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+
+
+

+ nestedArrayOptional +

+
+
+
+
+
+
+
+ +
+ + +
+
+
    +
+
+
+
+
+
+
+ +
+
+
+
+
+

+ +

+
+
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+
+
+

+ nestedObject +

+
+
+
+
+
+
+ +
+ + +
+
+
    +
+
+
+
+
+
+
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+
+
+

+ nestedArray +

+
+
+
+
+
+ No items yet. Use the button below to add some. +
+
+
+
+

+ +

+
+
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+ + Option 1 + + + â–¼ + +
+
    +
  • +
    + + Option 1 + +
    +
  • +
  • +
    + + Option 2 + +
    +
  • +
  • +
    + + Option 3 + +
    +
  • +
+
+
+
+
+
+
+
+

+ optionalObjectWithOneofs +

+
+
+
+
+
+
+ +
+ + +
+
+
    +
+
+
+
+
+
+
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
    +
+
+
+
+
+
+
+ +
+ +`; + +exports[`single fields optional data controls shows "add" optional controls when turned on in uiSchema and no formData 1`] = ` +
+
+
+
+
+

+ test +

+
+
+
+
+
+
+
+
+
+
+

+ nestedObjectOptional +

+
+
+ +
+
+
+
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ nestedArrayOptional +

+
+
+ +
+
+
+
+
+
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+
+
+

+ nestedObject +

+
+
+
+
+
+
+ +
+ + +
+
+
    +
+
+
+
+
+
+
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+
+
+

+ nestedArray +

+
+
+
+
+
+ No items yet. Use the button below to add some. +
+
+
+
+

+ +

+
+
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+ + Option 1 + + + â–¼ + +
+
    +
  • +
    + + Option 1 + +
    +
  • +
  • +
    + + Option 2 + +
    +
  • +
  • +
    + + Option 3 + +
    +
  • +
+
+
+
+
+
+
+
+

+ optionalObjectWithOneofs +

+
+
+
+
+
+
+ +
+ + +
+
+
    +
+
+
+
+
+
+
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
    +
+
+
+
+
+
+
+ +
+ +`; + +exports[`single fields optional data controls shows "add" optional controls when turned on in uiSchema, disabled and no formData 1`] = ` +
+
+
+
+
+

+ test +

+
+
+
+
+
+
+
+
+

+ nestedObjectOptional +

+
+
+
+ + No data for optional field + +
+
+
+
    +
+
+
+
+
+
+
+
+
+
+
+
+

+ nestedArrayOptional +

+
+
+
+ + No data for optional field + +
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+
+
+

+ nestedObject +

+
+
+
+
+
+
+ +
+ + +
+
+
    +
+
+
+
+
+
+
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+
+
+

+ nestedArray +

+
+
+
+
+
+ No items yet. Use the button below to add some. +
+
+
+
+

+ +

+
+
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+ + Option 1 + + + â–¼ + +
+
    +
  • +
    + + Option 1 + +
    +
  • +
  • +
    + + Option 2 + +
    +
  • +
  • +
    + + Option 3 + +
    +
  • +
+
+
+
+
+
+
+
+

+ optionalObjectWithOneofs +

+
+
+
+
+
+
+ +
+ + +
+
+
    +
+
+
+
+
+
+
+
+
+
+
    +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
    +
+
+
+
+
+
+
+ +
+ +`; + exports[`single fields password field 1`] = `
`; +exports[`single fields optional data controls does not show optional controls when not turned on in uiSchema and no formData 1`] = ` + +
+
+
+
+ test +
+
+
+
+
+
+
+
+
+ nestedObjectOptional +
+
+
+
+
+
+
+ + + + +
+
+
+
+
+
+
+
+ deepObjectOptional +
+
+
+
+
+
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+ deepObject +
+
+
+
+
+
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+ deepArrayOptional +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+ deepArrayOptional2 +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+ deepArray +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+ nestedArrayOptional +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+ nestedObject +
+
+
+
+
+
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+ nestedArray +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+ +
+ + +
+
+
+
+
+
+
+ optionalObjectWithOneofs +
+
+
+
+
+
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+ +`; + +exports[`single fields optional data controls does not show optional controls when not turned on in uiSchema, readonly and no formData 1`] = ` +
+
+
+
+
+ test +
+
+
+
+
+
+
+
+
+ nestedObjectOptional +
+
+
+
+
+
+
+ + + + +
+
+
+
+
+
+
+
+ deepObjectOptional +
+
+
+
+
+
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+ deepObject +
+
+
+
+
+
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+ deepArrayOptional +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+ deepArrayOptional2 +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+ deepArray +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+ nestedArrayOptional +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+ nestedObject +
+
+
+
+
+
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+ nestedArray +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+ +
+ + +
+
+
+
+
+
+
+ optionalObjectWithOneofs +
+
+
+
+
+
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+ +`; + +exports[`single fields optional data controls shows "add" and "remove" optional controls when turned on in uiSchema and formData 1`] = ` +
+
+
+
+
+ test +
+
+
+
+
+
+
+
+
+
+
+ nestedObjectOptional +
+
+
+ +
+
+
+
+
+
+
+
+ + + + +
+
+
+
+
+
+
+
+
+
+ deepObjectOptional +
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+ deepObject +
+
+
+
+
+
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+ deepArrayOptional +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+ deepArrayOptional2 +
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+ deepArray +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ nestedArrayOptional +
+
+
+ +
+
+
+
+
+
+
+
+
+ + + + +
+
+
+
+ +
+
+
+ +
+
+
+
+
+
+
+
+
+
+ nestedObject +
+
+
+
+
+
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+ nestedArray +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+ +
+ + +
+
+
+
+
+
+
+ optionalObjectWithOneofs +
+
+
+
+
+
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+ +`; + +exports[`single fields optional data controls shows "add" and "remove" optional controls when turned on in uiSchema, readonly and formData 1`] = ` +
+
+
+
+
+ test +
+
+
+
+
+
+
+
+
+ nestedObjectOptional +
+
+
+
+
+
+
+ + + + +
+
+
+
+
+
+
+
+ deepObjectOptional +
+
+
+
+ + No data for optional field + +
+
+
+
+
+
+
+
+
+ deepObject +
+
+
+
+
+
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+ deepArrayOptional +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+ deepArrayOptional2 +
+
+
+
+ + No data for optional field + +
+
+
+
+
+
+
+
+
+ deepArray +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+ nestedArrayOptional +
+
+
+
+
+
+
+
+ + + + +
+
+
+
+ +
+
+
+ +
+
+
+
+
+
+
+
+
+
+ nestedObject +
+
+
+
+
+
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+ nestedArray +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+ +
+ + +
+
+
+
+
+
+
+ optionalObjectWithOneofs +
+
+
+
+
+
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+ +`; + +exports[`single fields optional data controls shows "add" optional controls when turned on in uiSchema and no formData 1`] = ` +
+
+
+
+
+ test +
+
+
+
+
+
+
+
+
+
+
+ nestedObjectOptional +
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ nestedArrayOptional +
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+ nestedObject +
+
+
+
+
+
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+ nestedArray +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+ +
+ + +
+
+
+
+
+
+
+ optionalObjectWithOneofs +
+
+
+
+
+
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+ +`; + +exports[`single fields optional data controls shows "add" optional controls when turned on in uiSchema, disabled and no formData 1`] = ` +
+
+
+
+
+ test +
+
+
+
+
+
+
+
+
+ nestedObjectOptional +
+
+
+
+ + No data for optional field + +
+
+
+
+
+
+
+
+
+ nestedArrayOptional +
+
+
+
+ + No data for optional field + +
+
+
+
+
+
+
+
+
+ nestedObject +
+
+
+
+
+
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+ nestedArray +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+ +
+ + +
+
+
+
+
+
+
+ optionalObjectWithOneofs +
+
+
+
+
+
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+ +`; + exports[`single fields password field 1`] = `
, +