import { defineComponent , PropType , computed , reactive , watchEffect } from 'vue' ; import { JSONSchema6Definition , JSONSchema7Definition } from 'json-schema' ; import { CommonFieldPropsDefine , Schema , SchemaTypes } from '../types' ; import { useVJSFContext } from '../Context' ; import { getMatchingOption , guessType , getDefaultFormState , retrieveSchema , } from '../utils' ; import { ThemeLayoutsNames , useWidget } from '../theme' ; export default defineComponent ( { name : 'MultiSchemaField' , props : { ... CommonFieldPropsDefine , options : { type : Array as PropType < JSONSchema6Definition [ ] | JSONSchema7Definition [ ] > , required : true , } , baseType : { type : String as PropType < SchemaTypes > , required : true , } , } , setup ( props ) { const state = reactive ( { selectedOption : 0 , } ) ; const formContextRef = useVJSFContext ( ) ; const isValidRef = computed ( ( ) => { const { validate } = formContextRef . value ; return ( schema , data ) => validate ( schema , data ) . valid ; } ) ; function getMatchingOptionLocal ( data , options ) { let option = getMatchingOption ( data , options , isValidRef . value ) ; if ( option !== 0 ) { return option ; } return state . selectedOption || 0 ; } const onOptionChange = ( option ) => { const selectedOption = parseInt ( option , 10 ) ; const { value , onChange , options } = props ; const { rootSchema } = props ; const newOption = retrieveSchema ( options [ selectedOption ] , rootSchema , value ) ; let newFormData = undefined ; if ( guessType ( value ) === 'object' && ( newOption . type === 'object' || newOption . properties ) ) { newFormData = Object . assign ( { } , value ) ; const optionsToDiscard = options . slice ( ) ; optionsToDiscard . splice ( selectedOption , 1 ) ; for ( const option of optionsToDiscard ) { if ( typeof option !== 'boolean' && option . properties ) { for ( const key in option . properties ) { if ( newFormData . hasOwnProperty ( key ) ) { delete newFormData [ key ] ; } } } } } onChange ( getDefaultFormState ( options [ selectedOption ] as Schema , newFormData ) ) ; state . selectedOption = selectedOption ; } ; const WidgetRef = computed ( ( ) => { const { uiSchema } = props ; const { widget = 'select' } = uiSchema ; return useWidget ( { type : 'number' } , widget as ThemeLayoutsNames ) . value ; } ) ; watchEffect ( ( ) => { state . selectedOption = getMatchingOptionLocal ( props . value , props . options as Schema [ ] ) ; } ) ; return ( ) => { const { options , baseType , id , schema , uiSchema , value , onChange , ... rest } = props ; const SchemaItem = formContextRef . value . SchemaItem ; const { selectedOption } = state ; const Widget = WidgetRef . value ; const option = options [ selectedOption ] || null ; let optionSchema ; if ( option && typeof option !== 'boolean' ) { optionSchema = option . type ? option : Object . assign ( { } , option , { type : baseType } ) ; } const enumOptions = ( options as any ) . map ( ( option , index ) => ( { key : option . title || `Option ${ index + 1 }` , value : index , } ) ) ; return ( < > < Widget { ... rest } title = "test" uiSchema = { { } } id = { `${ id }${ schema . oneOf ? '__oneof_select' : '__anyof_select' }` } schema = { { type : 'number' , default : 0 } } onChange = { onOptionChange } value = { selectedOption } options = { { ... uiSchema , enumOptions } } /> { option !== null && ( < SchemaItem id = { id } schema = { optionSchema as Schema } uiSchema = { uiSchema } value = { value } onChange = { onChange } { ... rest } / > ) } < />); } ; } , } ) ;