import { computed , reactive , toRefs , defineComponent , Ref , PropType , Component , ComputedRef } from 'vue' ; import { Filter , LayoutConfig , ShowSelect } from '../types' ; import { useExtensions } from './use-system' ; const NAME_SUFFIX = 'wrapper' ; const WRITABLE_PROPS = [ 'selection' , 'layoutOptions' , 'layoutQuery' ] as const ; type WritableProp = typeof WRITABLE_PROPS [ number ] ; function isWritableProp ( prop ) { return ( WRITABLE_PROPS as readonly string [ ] ) . includes ( prop ) ; } function createLayoutWrapper < Options , Query > ( layout ) { return defineComponent ( { name : `${ layout . id }-${ NAME_SUFFIX }` , props : { collection : { type : String , required : true , } , selection : { type : Array as PropType < ( number | string ) [ ] > , default : ( ) => [ ] , } , layoutOptions : { type : Object as PropType < Options > , default : ( ) => ( { } ) , } , layoutQuery : { type : Object as PropType < Query > , default : ( ) => ( { } ) , } , filter : { type : Object as PropType < Filter > , default : null , } , filterUser : { type : Object as PropType < Filter > , default : null , } , filterSystem : { type : Object as PropType < Filter > , default : null , } , search : { type : String as PropType < string | null > , default : null , } , showSelect : { type : String as PropType < ShowSelect > , default : 'multiple' , } , selectMode : { type : Boolean , default : false , } , readonly : { type : Boolean , default : false , } , resetPreset : { type : Function as PropType < ( ) => Promise < void > > , default : null , } , clearFilters : { type : Function as PropType < ( ) => void > , default : null , } , } , emits : WRITABLE_PROPS . map ( ( prop ) => `update:${ prop }` as const ) , setup ( props , { emit } ) { const state = reactive ( { ... layout . setup ( props , { emit } ) , ... toRefs ( props ) } ) ; for ( const key in state ) { state [ `onUpdate:${ key }` ] = ( value ) => { if ( isWritableProp ( key ) ) { emit ( `update:${ key }` , value ) ; } else if ( ! Object . keys ( props ) . includes ( key ) ) { state [ key ] = value ; } } ; } return { state } ; } , render ( ctx ) { return ctx . $slots . default !== undefined ? ctx . $slots . default ( { layoutState : ctx . state } ) : null ; } , } ) ; } export function useLayout < Options = any , Query = any > ( layoutId ) { const { layouts } = useExtensions ( ) ; const layoutWrappers = computed ( ( ) => layouts . value . map ( ( layout ) => createLayoutWrapper < Options , Query > ( layout ) ) ) ; const layoutWrapper = computed ( ( ) => { const layout = layoutWrappers . value . find ( ( layout ) => layout . name === `${ layoutId . value }-${ NAME_SUFFIX }` ) ; if ( layout === undefined ) { return layoutWrappers . value . find ( ( layout ) => layout . name === `tabular-${ NAME_SUFFIX }` ) ! ; } return layout ; } ) ; return { layoutWrapper } ; }