import { VNode } from 'vue' ; import { CreateElement } from 'vue/types/umd' ; import { UniqueId as UniqueIdLib } from '@/lib/UniqueId' ; import { Objects as ObjectsLib } from '@/lib/Objects' ; import { Components as ComponentsLib } from '@/lib/Components' ; import { Fieldset as FieldsetLib } from '@/lib/Fieldset' ; import { Parser as ParserLib } from '@/parsers/Parser' ; import { NativeElements as NativeElementsLib } from '@/lib/NativeElements' ; import { NativeComponents as NativeComponentsLib } from '@/lib/NativeComponents' ; import { UIDescriptor as UIDescriptorLib } from '@/descriptors/UIDescriptor' ; import '@/parsers' ; import '@/descriptors' ; import { ComponentOptions , RenderContext , WatchOptions , ComputedOptions } from 'vue/types/options' ; import { SubmitEvent , ParserOptions , UnknowField , DescriptorInstance , Dict , IComponents , IParser , IUIDescriptor , ValidatorFunction } from '../../types' ; import { JsonSchema } from '../../types/jsonschema' ; /**
 * FormSchema API
 */ interface FormSchemaVue extends Vue { schema : JsonSchema ; value ? : unknown ; id : string ; name ? : string ; bracketedObjectInputName : boolean ; search : boolean ; disabled : boolean ; components : IComponents ; descriptor : DescriptorInstance | IUIDescriptor ; validator : ValidatorFunction ; key : string ; ref : string ; initialModel : unknown ; ready : boolean ; parser : IParser < any , UnknowField > | null ; fieldId : string ; listeners : Record < string , Function | Function [ ] > ; clone ( value ) : unknown ; form ( ) : HTMLFormElement | VNode | undefined ; emitInputEvent ( value , field ) : void ; update ( updatedFields ) : void ; } interface FormSchemaComponent < V extends FormSchemaVue = FormSchemaVue > extends ComponentOptions < V > { computed : Accessors < Dict , V > ; watch ? : Record < string , WatchOptionsWithHandler < V , any > | WatchHandler < V , any > | string > ; render ? ( this , createElement , hack ) : VNode ; renderError ? ( this , createElement , err ) : VNode ; staticRenderFns ? : ( ( this : V , createElement : CreateElement ) => VNode ) [ ] ; beforeCreate ? ( this ) : void ; created ? ( this ) : void ; beforeDestroy ? ( this ) : void ; destroyed ? ( this ) : void ; beforeMount ? ( this ) : void ; mounted ? ( this ) : void ; beforeUpdate ? ( this ) : void ; updated ? ( this ) : void ; activated ? ( this ) : void ; deactivated ? ( this ) : void ; errorCaptured ? ( err , vm , info ) : boolean | void ; serverPrefetch ? ( this ) : Promise < void > ; } type Accessors < T , V > = { [ K in keyof T ] : ( ( this : V ) => T [ K ] ) | ComputedOptions < T [ K ] > ; } ; type Props = Record < string , any > ; type WatchHandler < V extends Vue , T > = ( this : V , val : T , oldVal : T ) => void ; interface WatchOptionsWithHandler < V extends Vue , T > extends WatchOptions { handler : WatchHandler < V , T > ; } export const GLOBAL = { Elements : Object . freeze ( NativeElementsLib ) } ; export const Objects = ObjectsLib ; export const UniqueId = UniqueIdLib ; export const Components = ComponentsLib ; export const Fieldset = FieldsetLib ; export const Parser = ParserLib ; export const UIDescriptor = UIDescriptorLib ; export const NativeComponents = NativeComponentsLib ; slot const FormSchema = { name : 'FormSchema' , model : { prop : 'value' , event : 'input' } , props : { /**
         * The input JSON Schema object.
         */ schema : { type : Object , required : true } , type any value : { type : [ Number , String , Array , Object , Boolean ] , default : undefined } , default id : { type : String , default : UniqueId . get ( 'form' ) } , /**
         * The name of the form. It must be unique among the forms in a document.
         */ name : { type : String , default : undefined } , /**
         * When set to `true` (default), checkbox inputs and nested object inputs
         * will * automatically include brackets at the end of their names
         * (e.g. `name="grouped-checkbox-fields[]"`).
         * Setting this property to `false`, disables this behaviour.
         */ bracketedObjectInputName : { type : Boolean , default : true } , /**
         * Use this prop to enable `search` landmark role to identify a section
         * of the page used to search the page, site, or collection of sites.
         */ search : { type : Boolean , default : false } , /**
         * Indicates whether the form elements are disabled or not.
         */ disabled : { type : Boolean , default : false } , default components : { type : Components , default : ( ) : Readonly < NativeComponentsLib > => GLOBAL . Elements } , type DescriptorInstance typeref default descriptor : { type : Object , default : ( ) : object => ( { } ) } , see kind param { GenericField } field param { string } field . id param { string } field . name param { any } field . value param { JsonSchema } field . schema param { boolean } field . required param { boolean } field . hasChildren param { any } field . initialValue param { Message [ ] } field . messages returns { Promise < boolean > } validator : { type : Function , default : null } } , data : ( ) => ( { key : undefined , ref : UniqueId . get ( 'formschema' ) , initialModel : undefined , ready : false , parser : null } ) , computed : { fieldId ( ) { return `${ this . id }-field` ; } , options ( ) { return { schema : this . schema , model : this . initialModel , name : this . name , id : this . fieldId , required : true , descriptor : this . descriptor , components : this . components , bracketedObjectInputName : this . bracketedObjectInputName , onChange : this . emitInputEvent , validator : this . validator , requestRender : this . update } ; } , listeners ( ) { const on = { ... this . $listeners } ; on . reset = on . reset ? [ on . reset ] : [ ] ; on . reset . unshift ( ( ) => { if ( this . parser ) { this . parser . field . reset ( ) ; } } ) ; if ( on . submit ) { const onsubmit = on . submit ; on . submit = ( event ) => { if ( this . parser ) { event . field = this . parser . field ; } return onsubmit ( event ) ; } ; } delete on . input ; return on ; } } , watch : { schema : { immediate : true , handler ( ) { this . ready = false ; this . initialModel = Objects . clone ( this . value as any ) ; } } , options : { immediate : true , handler ( options ) { this . parser = Parser . get ( options ) ; } } } , render ( createElement ) { if ( this . parser === null || this . ready === false ) { return null as any ; } const attrs = { disabled : this . disabled } ; const props = { field : this . parser . field } ; const element = createElement ( props . field . descriptor . component , { attrs , props } ) ; const nodes = [ element ] ; if ( this . $slots . default ) { nodes . push ( ... this . $slots . default ) ; } return createElement ( this . components . get ( 'form' ) , { ref : this . ref , key : this . key , attrs : { id : this . id , name : this . name , role : this . search ? 'search' : undefined } , props : props , on : this . listeners } , nodes ) ; } , methods : { returns { HTMLFormElement | VNode | undefined } form ( ) { return this . $refs [ this . ref ] as any ; } , private emitInputEvent ( value , field ) { if ( this . ready && this . validator ) { this . validator ( field ) . then ( ( result ) => { if ( result ) { this . ready = true ; } } ) ; } /**
             * Fired synchronously when the value of an element is changed.
             */ this . $emit ( 'input' , value ) ; this . $nextTick ( ( ) => { this . ready = true ; } ) ; } , private update ( [ field ] ) { this . key = field . key ; } } } ; export default FormSchema ;