import { and , ControlProps , ControlState , EnumCellProps , JsonSchema , RankedTester , rankWith , schemaMatches , uiTypeIs , WithClassname } from '@jsonforms/core' ; import { Control , withJsonFormsControlProps } from '@jsonforms/react' ; import { Input , InputBaseComponentProps } from '@mui/material' ; import merge from 'lodash/merge' ; import React , { useMemo } from 'react' ; import { useDebouncedChange } from '../util' ; import { MaterialInputControl } from './MaterialInputControl' ; const findEnumSchema = ( schemas ) => schemas . find ( s => s . enum !== undefined && ( s . type === 'string' || s . type === undefined ) ) ; const findTextSchema = ( schemas ) => schemas . find ( s => s . type === 'string' && s . enum === undefined ) ; const MuiAutocompleteInputText = ( props ) => { const { data , config , className , id , enabled , uischema , isValid , path , handleChange , schema } = props ; const enumSchema = findEnumSchema ( schema . anyOf ) ; const stringSchema = findTextSchema ( schema . anyOf ) ; const maxLength = stringSchema . maxLength ; const appliedUiSchemaOptions = useMemo ( ( ) => merge ( { } , config , uischema . options ) , [ config , uischema . options ] ) ; const inputProps = useMemo ( ( ) => { let propMemo = { } ; if ( appliedUiSchemaOptions . restrict ) { propMemo = { maxLength : maxLength } ; } if ( appliedUiSchemaOptions . trim && maxLength !== undefined ) { propMemo . size = maxLength ; } propMemo . list = props . id + 'datalist' ; return propMemo ; } , [ appliedUiSchemaOptions , props . id ] ) ; const [ inputText , onChange ] = useDebouncedChange ( handleChange , '' , data , path ) ; const dataList = ( < datalist id = { props . id + 'datalist' } > { enumSchema . enum . map ( optionValue => ( < option value = { optionValue } key = { optionValue } / > ) ) } < /datalist>); return ( < Input type = 'text' value = { inputText } onChange = { onChange } className = { className } id = { id } disabled = { ! enabled } autoFocus = { appliedUiSchemaOptions . focus } fullWidth = { ! appliedUiSchemaOptions . trim || maxLength === undefined } inputProps = { inputProps } error = { ! isValid } endAdornment = { dataList } / > ) ; } ; export class MaterialAnyOfStringOrEnumControl extends Control < ControlProps , ControlState > { render ( ) { return ( < MaterialInputControl { ... this . props } input = { MuiAutocompleteInputText } / > ) ; } } const hasEnumAndText = ( schemas ) => { const enumSchema = findEnumSchema ( schemas ) ; const stringSchema = findTextSchema ( schemas ) ; const remainingSchemas = schemas . filter ( s => s !== enumSchema || s !== stringSchema ) ; const wrongType = remainingSchemas . find ( s => s . type && s . type !== 'string' ) ; return enumSchema && stringSchema && ! wrongType ; } ; const simpleAnyOf = and ( uiTypeIs ( 'Control' ) , schemaMatches ( schema => schema . hasOwnProperty ( 'anyOf' ) && hasEnumAndText ( schema . anyOf ) ) ) ; export const materialAnyOfStringOrEnumControlTester = rankWith ( 5 , simpleAnyOf ) ; export default withJsonFormsControlProps ( MaterialAnyOfStringOrEnumControl ) ;