/** ******************************************************************************************************************* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. * ******************************************************************************************************************** */ import React, { useCallback } from 'react'; import { action } from '@storybook/addon-actions'; import FormRenderer, { componentTypes, validatorTypes } from '.'; import { awsServices } from '../Autosuggest/data/data'; import Box from '../../layouts/Box'; import Text from '../Text'; import Input from '../Input'; import FileUpload from '../FileUpload'; import Container from '../../layouts/Container'; import { ValidatorMapper } from '@data-driven-forms/react-form-renderer/validator-mapper'; import FormRendererMarkdownEditor from '../FormRendererMarkdownEditor'; import FormRendererTable from '../FormRendererTable'; export default { component: FormRenderer, title: 'Components/FormRenderer', }; const treeItems = { id: '1', label: 'Tree Root', children: [ { id: '2', label: 'Node 1.0', children: [ { id: '3', label: 'Node 1.1' }, { id: '4', label: 'Node 1.3' }, ], }, { id: '5', label: 'Node 2.0', children: [ { id: '6', label: 'Node 2.1.0', children: [{ id: '7', label: 'Node 2.1.2' }], }, { id: '8', label: 'Node 2.2' }, ], }, ], }; const baseSchema = { fields: [ { component: componentTypes.TEXT_FIELD, name: 'email', label: 'Email', isRequired: true, validate: [ { type: validatorTypes.REQUIRED, }, { type: validatorTypes.PATTERN, message: 'Invalid email address', // eslint-disable-next-line pattern: /^(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])$/i, }, ], }, { component: componentTypes.TEXT_FIELD, name: 'password', label: 'Password', type: 'password', isRequired: true, validate: [ { type: validatorTypes.REQUIRED, }, { type: validatorTypes.MIN_LENGTH, threshold: 6, }, { type: validatorTypes.MAX_LENGTH, threshold: 10, }, ], }, { component: componentTypes.TEXT_FIELD, name: 'number', label: 'Number', type: 'number', validate: [ { type: validatorTypes.MIN_NUMBER_VALUE, includeThreshold: true, value: 4, }, { type: validatorTypes.MAX_NUMBER_VALUE, includeThreshold: false, value: 20, }, ], }, { component: componentTypes.CHECKBOX, name: 'checkbox', label: 'Checkbox', options: [ { label: 'Option 1', value: '1', }, { label: 'Option 2', value: '2', }, { label: 'Option 3', value: '3', }, ], isRequired: true, validate: [ { type: validatorTypes.REQUIRED, }, ], }, { component: componentTypes.RADIO, name: 'radio', label: 'Radio', options: [ { label: 'Option 1', description: 'Description 1', value: '1', }, { label: 'Option 2', value: '2', }, { label: 'Option 3', value: '3', }, ], isRequired: true, validate: [ { type: validatorTypes.REQUIRED, }, ], }, { component: componentTypes.SELECT, name: 'select', label: 'Select', placeholder: 'Choose an option', options: [ { label: 'Option 1', value: '1', }, { label: 'Option 2', value: '2', }, { label: 'Option 3', value: '3', }, ], isRequired: true, validate: [ { type: validatorTypes.REQUIRED, }, ], renderReload: true, onReloadClick: () => {}, createNewLink: 'Create new option', createNewLinkHref: '/options/create', }, { component: componentTypes.SELECT, name: 'autosugguest', label: 'Autosuggest', placeholder: 'Choose an AWS service', isSearchable: true, options: awsServices, isRequired: true, validate: [ { type: validatorTypes.REQUIRED, }, ], }, { component: componentTypes.SELECT, name: 'multiselect', label: 'Multiselect', placeholder: 'Choose an AWS service', multiSelect: true, options: awsServices, isRequired: true, checkboxes: true, validate: [ { type: validatorTypes.REQUIRED, }, ], }, { component: componentTypes.TEXTAREA, name: 'textarea', label: 'Textarea', helperText: 'This is a help text', isRequired: true, validate: [ { type: validatorTypes.REQUIRED, }, ], }, { component: componentTypes.SWITCH, name: 'switch', label: 'Switch', }, { component: componentTypes.SWITCH, name: 'switch1', label: 'Switch 1', }, { component: componentTypes.SWITCH, name: 'switch2', label: 'Switch 2', }, { component: componentTypes.DATE_PICKER, name: 'datePicker', label: 'Date picker', isRequired: true, validate: [ { type: validatorTypes.REQUIRED, }, ], }, { component: componentTypes.TIME_PICKER, name: 'timePicker', label: 'Time picker', isRequired: true, validate: [ { type: validatorTypes.REQUIRED, }, ], }, { component: componentTypes.TREE_VIEW, label: 'this is a tree', helperText: 'this is a hint', description: 'this is a description', name: 'tree', treeItems: treeItems, multiSelect: true, defaultExpanded: ['1', '2'], validate: [ { type: validatorTypes.REQUIRED, }, ], }, { component: componentTypes.CHECKBOX, name: 'confirm', label: 'I understand the terms and condition', description: 'Term 1.0.0', validate: [ { type: validatorTypes.REQUIRED, message: 'please accept the terms and condition', }, ], }, ], header: 'Data driven form', description: 'Define your form in json format', }; export const Default = () => { return ; }; export const WithInitialValues = () => { const initialValues = { email: 'test@test.com', password: 'password', number: 10, textarea: 'textarea', checkbox: ['1', '2'], switch: true, radio: '3', select: '2', autosugguest: { value: 'Lambda', label: 'Lambda - Amazon Lambda', }, multiselect: [ { value: 'Lambda', label: 'Lambda - Amazon Lambda', }, { value: 'EC2', label: 'EC2 - Amazon Elastic Compute Cloud', }, ], confirm: true, datePicker: new Date(2020, 1, 1), timePicker: '2020-01-01T00:00:00Z', tree: ['3', '5'], }; return ( ); }; export const ResetButton = () => { const initialValues = { email: 'test@test.com', password: 'password', number: 10, textarea: 'textarea', checkbox: ['1', '2'], switch: true, radio: '3', select: '2', autosugguest: { value: 'Lambda', label: 'Lambda - Amazon Lambda', }, multiselect: [ { value: 'Lambda', label: 'Lambda - Amazon Lambda', }, { value: 'EC2', label: 'EC2 - Amazon Elastic Compute Cloud', }, ], confirm: true, datePicker: new Date(2020, 1, 1), timePicker: '2020-01-01T00:00:00Z', tree: ['3', '5'], }; const resetableSchema = { ...baseSchema, canReset: true, }; return ( ); }; export const SubForms = () => { const schema = { fields: [ { component: componentTypes.SUB_FORM, title: 'Subform 1', description: 'This is a subform', name: 'subform1', fields: [ { component: componentTypes.TEXT_FIELD, name: 'name1', label: 'Name', validate: [ { type: validatorTypes.REQUIRED, }, ], }, { component: componentTypes.EXPANDABLE_SECTION, title: 'Additional information', description: 'This is for additional information', name: 'additionalInfo', fields: [ { component: componentTypes.TEXT_FIELD, name: 'username', label: 'Username', validate: [ { type: validatorTypes.REQUIRED, }, ], }, ], }, ], }, { component: componentTypes.EXPANDABLE_SECTION, title: 'Subform 2', description: 'This is a expandable subform', name: 'subform2', variant: 'container', fields: [ { component: componentTypes.TEXT_FIELD, name: 'name2', label: 'First name', validate: [ { type: validatorTypes.REQUIRED, }, ], }, { component: componentTypes.TEXT_FIELD, name: 'name3', label: 'Last name', validate: [ { type: validatorTypes.REQUIRED, }, ], }, ], }, { component: componentTypes.EXPANDABLE_SECTION, title: 'Subform 3', description: 'This is a expanded expandable subform', name: 'subform3', expandable: true, expanded: true, variant: 'container', fields: [ { component: componentTypes.SELECT, name: 'select', label: 'Select', placeholder: 'Choose an option', options: [ { label: 'Option 1', value: '1', }, { label: 'Option 2', value: '2', }, { label: 'Option 3', value: '3', }, ], isRequired: true, validate: [ { type: validatorTypes.REQUIRED, }, ], }, ], }, ], header: 'Data driven form with subforms', description: 'Define your form in json format', }; return ; }; export const FieldArray = () => { const schema = { fields: [ { component: componentTypes.FIELD_ARRAY, label: 'Attribute Editor - layout=default', description: 'This is a form array', name: 'fieldArray1', helperText: 'You can add up to 6 more items.', minItems: 4, maxItems: 6, noItemsMessage: 'Please add new item', defaultItem: { key: 'key', value: 'value', type: 'type1', }, validate: [ { type: validatorTypes.MIN_ITEMS, threshold: 4, }, { type: validatorTypes.REQUIRED, }, ], fields: [ { component: componentTypes.TEXT_FIELD, name: 'key', label: 'Key', validate: [ { type: validatorTypes.REQUIRED, }, ], }, { component: componentTypes.TEXT_FIELD, name: 'value', label: 'Value', validate: [ { type: validatorTypes.REQUIRED, }, ], }, { component: componentTypes.SELECT, name: 'type', label: 'Type', placeholder: 'Choose the type', options: [ { label: 'Type 1', value: 'type1' }, { label: 'Type 2', value: 'type2' }, { label: 'Type 3', value: 'type3' }, ], validate: [ { type: validatorTypes.REQUIRED, }, ], }, ], }, { component: componentTypes.FIELD_ARRAY, label: 'Attribute Editor', description: 'This is a form array - layout=stack', name: 'fieldArray2', helperText: 'You can add up to 6 more items.', minItems: 3, maxItems: 6, layout: 'stack', noItemsMessage: 'Please add new item', defaultItem: { key: 'key', value: 'value', type: { label: 'Type 1', value: 'type1', }, }, validate: [ { type: validatorTypes.MIN_ITEMS, threshold: 3, }, { type: validatorTypes.REQUIRED, }, ], fields: [ { component: componentTypes.TEXT_FIELD, name: 'key', label: 'Key', validate: [ { type: validatorTypes.REQUIRED, }, ], }, { component: componentTypes.TEXT_FIELD, name: 'value', label: 'Value', validate: [ { type: validatorTypes.REQUIRED, }, ], }, { component: componentTypes.SELECT, name: 'type', label: 'Type', placeholder: 'Choose the type', isSearchable: true, options: [ { label: 'Type 1', value: 'type1' }, { label: 'Type 2', value: 'type2' }, { label: 'Type 3', value: 'type3' }, ], validate: [ { type: validatorTypes.REQUIRED, }, ], }, ], }, { component: componentTypes.FIELD_ARRAY, label: 'Attribute Editor - readonly - layout=grid', description: 'This is a readonly form array', name: 'readonlyFieldArray', layout: 'grid', isReadOnly: true, fields: [ { component: componentTypes.TEXT_FIELD, name: 'key', label: 'Key', isReadOnly: true, column: 3, validate: [ { type: validatorTypes.REQUIRED, }, ], }, { component: componentTypes.TEXT_FIELD, name: 'value', label: 'Value', isReadOnly: true, column: 4, validate: [ { type: validatorTypes.REQUIRED, }, ], }, { component: componentTypes.SELECT, name: 'type', label: 'Type', placeholder: 'Choose the type', isReadOnly: true, column: 5, options: [ { label: 'Type 1', value: 'type1' }, { label: 'Type 2', value: 'type2' }, { label: 'Type 3', value: 'type3' }, ], validate: [ { type: validatorTypes.REQUIRED, }, ], }, ], }, ], header: 'Data driven form with field arrays', description: 'Define your form in json format', }; const initialValues = { fieldArray1: [ { key: 'key1', value: 'value1', type: 'type1' }, { key: 'key2', value: 'value2', type: 'type2' }, { key: 'key3', value: 'value3', type: 'type3' }, ], readonlyFieldArray: [ { key: 'key1', value: 'value1', type: 'type1' }, { key: 'key2', value: 'value2', type: 'type2' }, { key: 'key3', value: 'value3', type: 'type3' }, { key: 'key4', value: 'value4', type: 'type1' }, ], }; return ( ); }; export const ComplexFieldArray = () => { const schema = { fields: [ { component: componentTypes.FIELD_ARRAY, label: 'Sales Order', description: 'Enter sales order detail', name: 'salesOrder', displayLablePerItem: true, renderContainer: true, layout: 'grid', noItemsMessage: 'Please add new sales order', buttonLabels: { add: 'Add a new sales order', }, fields: [ { component: componentTypes.TEXT_FIELD, name: 'id', label: 'Id', column: 5, validate: [ { type: validatorTypes.REQUIRED, }, ], }, { component: componentTypes.TEXT_FIELD, name: 'description', label: 'Description', column: 5, validate: [ { type: validatorTypes.REQUIRED, }, ], }, { component: componentTypes.FIELD_ARRAY, label: 'Sales Order Items', description: 'Enter sales order items', name: 'items', helperText: 'You can add up to 6 more items.', column: 10, minItems: 1, maxItems: 6, buttonLabels: { add: 'Add a new sales order item', }, noItemsMessage: 'Please add new sales order item', defaultItem: { id: 'item1', count: '1', status: 'Ready', }, validate: [ { type: validatorTypes.MIN_ITEMS, threshold: 1, }, { type: validatorTypes.REQUIRED, }, ], fields: [ { component: componentTypes.TEXT_FIELD, name: 'id', label: 'Id', validate: [ { type: validatorTypes.REQUIRED, }, ], }, { component: componentTypes.TEXT_FIELD, name: 'count', label: 'Count', validate: [ { type: validatorTypes.REQUIRED, }, ], }, { component: componentTypes.SELECT, name: 'status', label: 'Status', placeholder: 'Choose the type', options: [ { label: 'Picking', value: 'Picking' }, { label: 'Packing', value: 'Packing' }, { label: 'Ready', value: 'Ready' }, ], validate: [ { type: validatorTypes.REQUIRED, }, ], }, ], }, ], }, ], header: 'Sales Order Form', description: 'Enter sales orders', }; const initialValues = { salesOrder: [ { id: 'orderId', description: 'value1', items: [ { id: 'item1', count: '1', status: 'Picking' }, { id: 'item2', count: '2', status: 'Packing' }, ], }, ], }; return ( ); }; const ReviewTemplate = (data: any) => { return {JSON.stringify(data)}; }; const wizardSchema = { fields: [ { component: componentTypes.WIZARD, name: 'wizzard', submitButtonText: 'Custom Submit Label', fields: [ { name: 'step-1', title: 'Step 1', description: 'Descrirption for Step 1', fields: [ { component: componentTypes.TEXTAREA, name: 'textarea', label: 'Textarea', validate: [ { type: validatorTypes.REQUIRED, }, ], }, { component: componentTypes.SELECT, name: 'type', label: 'Type', placeholder: 'Choose the type', options: [ { label: 'Type 1', value: 'type1' }, { label: 'Type 2', value: 'type2' }, { label: 'Type 3', value: 'type3' }, ], validate: [ { type: validatorTypes.REQUIRED, }, ], }, { component: componentTypes.EXPANDABLE_SECTION, title: 'Additional information', description: 'This is for additional information', name: 'additionalInfo', variant: 'default', fields: [ { component: componentTypes.TEXT_FIELD, name: 'username', label: 'Username', expandable: true, validate: [ { type: validatorTypes.REQUIRED, }, ], }, ], }, ], }, { name: 'step-2', title: 'Step 2', fields: [ { component: componentTypes.CHECKBOX, name: 'checkbox', label: 'Checkbox', options: [ { label: 'Option 1', value: '1', }, { label: 'Option 2', value: '2', }, { label: 'Option 3', value: '3', }, ], isRequired: true, validate: [ { type: validatorTypes.REQUIRED, }, ], }, { component: componentTypes.RADIO, name: 'radio', label: 'Radio', options: [ { label: 'Option 1', value: '1', }, { label: 'Option 2', value: '2', }, { label: 'Option 3', value: '3', }, ], isRequired: true, validate: [ { type: validatorTypes.REQUIRED, }, ], }, { component: componentTypes.FIELD_ARRAY, label: 'Attribute Editor', description: 'This is a form array', name: 'fieldArray', helperText: 'You can add up to 6 more items.', minItems: 4, maxItems: 6, noItemsMessage: 'Please add new item', defaultItem: { key: 'key', value: 'value', type: 'type1', }, validate: [ { type: validatorTypes.MIN_ITEMS, threshold: 4, }, { type: validatorTypes.REQUIRED, }, ], fields: [ { component: componentTypes.TEXT_FIELD, name: 'key', label: 'Key', validate: [ { type: validatorTypes.REQUIRED, }, ], }, { component: componentTypes.TEXT_FIELD, name: 'value', label: 'Value', validate: [ { type: validatorTypes.REQUIRED, }, ], }, { component: componentTypes.SELECT, name: 'type', label: 'Type', placeholder: 'Choose the type', options: [ { label: 'Type 1', value: 'type1' }, { label: 'Type 2', value: 'type2' }, { label: 'Type 3', value: 'type3' }, ], validate: [ { type: validatorTypes.REQUIRED, }, ], }, ], }, ], }, { name: 'step-3', title: 'Step 3', fields: [ { component: componentTypes.TEXT_FIELD, name: 'name1', label: 'Name', validate: [ { type: validatorTypes.REQUIRED, }, ], }, { component: componentTypes.SWITCH, name: 'switch', label: 'Switch', }, { component: componentTypes.DATE_PICKER, name: 'datePicker', label: 'Date picker', isRequired: true, validate: [ { type: validatorTypes.REQUIRED, }, ], }, { component: componentTypes.TIME_PICKER, name: 'timePicker', label: 'Time picker', isRequired: true, validate: [ { type: validatorTypes.REQUIRED, }, ], }, { component: componentTypes.TREE_VIEW, label: 'this is a tree', helperText: 'this is a hint', description: 'this is a description', name: 'tree', treeItems: treeItems, multiSelect: true, defaultExpanded: ['1', '2'], validate: [ { type: validatorTypes.REQUIRED, }, ], }, { component: componentTypes.CHECKBOX, name: 'confirm', label: 'I understand the terms and condition', description: 'Term 1.0.0', validate: [ { type: validatorTypes.REQUIRED, message: 'please accept the terms and condition', }, ], }, ], }, { name: 'step-4', title: 'Step 4', fields: [ { component: 'TABLE', name: 'table', label: 'Table', description: 'This is a table', getRowId: (data: any) => data.id, items: [ { id: 'id0000011', name: 'Engagement 11', createdDate: '2019-10-12', }, { id: 'id0000012', name: 'Engagement 12', createdDate: '2019-11-12', }, { id: 'id0000013', name: 'Engagement 13', createdDate: '2020-01-01', }, ], columnDefinitions: [ { id: 'id', width: 200, Header: 'Id', accessor: 'id', }, { id: 'name', width: 200, Header: 'Name', accessor: 'name', }, { id: 'createdDate', width: 200, Header: 'Created date', accessor: 'createdDate', }, ], validate: [ { type: validatorTypes.REQUIRED, }, ], }, ], }, { name: 'step-5', title: 'Review', fields: [ { component: componentTypes.REVIEW, name: 'review', Template: ReviewTemplate, }, ], }, ], }, ], header: 'Data driven form with wizard', description: 'Define your form in json format', }; export const Wizard = () => { const customComponentMapping = { TABLE: FormRendererTable, }; return ( ); }; export const WizardWithInitialValues = () => { const customComponentMapping = { TABLE: FormRendererTable, }; const initialValues = { textarea: 'textarea', type: 'type1', additionalInfo: { username: 'username' }, checkbox: ['1'], radio: '1', fieldArray: [ { key: 'key1', value: 'value1', type: 'type1' }, { key: 'key2', value: 'value2', type: 'type2' }, { key: 'key3', value: 'value3', type: 'type3' }, { key: 'key4', value: 'value4', type: 'type1' }, ], name1: 'name', switch: true, datePicker: '2020-06-11T14:00:00.000Z', timePicker: '2020-06-11T14:00:00.000Z', tree: ['3'], confirm: true, table: [ { id: 'id0000012', name: 'Engagement 12', createdDate: '2019-11-12' }, { id: 'id0000013', name: 'Engagement 13', createdDate: '2020-01-01' }, ], }; return ( ); }; const CustomComponentSimple = ({ label }) => {label}; const CustomComponentComplex = ({ input }) => ; export const Custom = () => { const schema = { fields: [ { component: componentTypes.CUSTOM, name: 'text', label: 'This is the content of custom component', CustomComponent: CustomComponentSimple, }, { component: componentTypes.CUSTOM, name: 'input', CustomComponent: CustomComponentComplex, }, ], header: 'Data driven form with Custom Component', description: 'Custom Component is an extension of Review Component which allows users to include custom business logic', }; return ( ); }; const FileUploadComponent = ({ name, input, onChange }) => { const handleOnChange = useCallback( (files) => { if (files && files.length > 0) { if (onChange) { onChange(files); } input.onChange(files.map((f) => f.name)); } }, [input, onChange] ); return ; }; export const FileUploader = () => { const schema = { fields: [ { component: componentTypes.CUSTOM, name: 'file', CustomComponent: FileUploadComponent, onChange: action('File selection change'), }, ], header: 'Data driven form using FileUpload', description: 'File upload logic can be implemented outside FormRenderer', }; return ; }; export const Submitting = () => { const schema = { fields: [ { component: componentTypes.TEXT_FIELD, name: 'input', isDisabled: true, }, ], header: 'Spinner while submitting', }; return ; }; export const SimpleMarkdownEditor = () => { const customComponentMapping = { MARKDOWN_EDITOR: FormRendererMarkdownEditor, }; const schema = { submitLabel: 'Save', cancelLabel: 'Back', fields: [ { component: 'MARKDOWN_EDITOR', name: 'markdownOne', label: 'This is a markdown editor', helperText: 'Helper text provides users some guidance.', initialValue: '# I am a Markdown editor.\n\rHave a play.', onChange: action('Markdown content change'), validate: [ { type: validatorTypes.REQUIRED, }, ], }, { component: 'MARKDOWN_EDITOR', name: 'markdownTwo', label: 'This is a read only markdown editor', isReadOnly: true, initialValue: '# I should be read only\n\rAnd you should not be able to edit me', }, ], header: 'Markdown Editor', description: 'This component allows a user to enter markdown and renders it in real-time.', }; return ( ); }; const controlInteractionSchema = { fields: [ { component: componentTypes.SELECT, name: 'select1', label: 'Select 1', placeholder: 'Choose an option', options: [ { label: 'Option 1', value: '1', }, { label: 'Option 2', value: '2', }, { label: 'Option 3', value: '3', }, ], isRequired: true, validate: [ { type: validatorTypes.REQUIRED, }, ], }, { component: componentTypes.SELECT, name: 'select2', label: 'Select 2', helperText: 'Enabled only when the value of Select 1 is 2', placeholder: 'Choose an option', options: [ { label: 'Option 21', value: '21', }, { label: 'Option 22', value: '22', }, { label: 'Option 23', value: '23', }, ], isRequired: true, validate: [ { type: validatorTypes.REQUIRED, }, ], resolveProps: (_props, _field, formOptions) => { const values = formOptions.getState().values; return values.select1 === '2' ? { isDisabled: false, } : { isDisabled: true, }; }, condition: { when: 'select1', is: '2', then: { visible: true, set: { select2: '22' } }, else: { visible: true, set: { select2: '21' } }, }, }, { component: componentTypes.SELECT, name: 'select3', label: 'Select 3', helperText: 'Options changes with the value of Select 1 and only visible when Select 1 is set', placeholder: 'Choose an option', isRequired: true, validate: [ { type: validatorTypes.REQUIRED, }, ], resolveProps: (_props, _field, formOptions) => { const values = formOptions.getState().values; return { options: [ { label: `Option 3${values.select1}1`, value: `3${values.select1}1`, }, { label: `Option 3${values.select1}2`, value: `3${values.select1}2`, }, { label: `Option 3${values.select1}3`, value: `3${values.select1}3`, }, ], }; }, condition: { when: 'select1', isNotEmpty: true, }, }, ], header: 'Data driven form', description: 'Define your form in json format', }; export const ControlInteraction = () => { return ( ); }; export const CustomValidator = () => { const validatorMapping: ValidatorMapper = { custom: ({ threshold }: any) => (value: number) => !value ? 'this is a required field' : value > threshold ? `${value} must be <= ${threshold}` : undefined, }; const schema = { submitLabel: 'Save', cancelLabel: 'Back', fields: [ { component: componentTypes.TEXT_FIELD, name: 'number', label: 'Number', type: 'number', validate: [ { type: 'custom', threshold: 6, }, ], }, ], header: 'Custom Validator', description: 'This component allows a user to provide a custom validator.', }; return ( ); };