import { CreateElement , VueConstructor , VNode } from 'vue' ; import { Vue , Component , Inject , Prop } from 'vue-property-decorator' ; import logger from '../logger' ; import DraggablePolicyCtor , { Instruction , instructionNames as draggableEvents } from './draggable-policy' ; import VirtualScrollListPolicy , { DragStartEvent } from './virtual-scroll-list-policy' ; export interface IDraggable < T > extends VueConstructor { props : { value : Array < T > ; clone : ( x : T ) => T ; } ; $emit ( event , e ) : void ; $emit ( event , e ) : void ; } export interface IVirtualList extends VueConstructor { options : { methods : { getRenderSlots ( h ) : Array < VNode > ; } ; } ; } export enum SortableEvents { start , add , remove , update , end , choose , unchoose , sort , filter , clone } type DraggableEvent < T > = Instruction < T > & Event ; const sortableEvents = Object . values ( SortableEvents ) . filter ( x => typeof x === 'string' ) ; export default function createBroker ( VirtualList ) { @ Component class Broker < T > extends VirtualList { @ Prop ( ) size ? : number ; @ Prop ( ) keeps ! : number ; @ Prop ( ) dataKey ! : keyof T ; @ Prop ( ) dataSources ! : Array < T > ; @ Prop ( ) dataComponent ! : Vue ; @ Inject ( ) Draggable ! : IDraggable < T > ; @ Inject ( ) DraggablePolicy ! : typeof DraggablePolicyCtor ; private range : { start : number ; } ; private vlsPolicy = new VirtualScrollListPolicy ( ) ; getRenderSlots ( h ) { const { Draggable , DraggablePolicy } = this ; const slots = VirtualList . options . methods . getRenderSlots . call ( this , h ) ; const draggablePolicy = new DraggablePolicy ( this . dataKey , this . dataSources , this . range ) ; if ( this . vlsPolicy . draggingVNode ) { slots . splice ( this . vlsPolicy . draggingIndex , 1 , this . vlsPolicy . draggingVNode ) ; } return [ h ( Draggable , { props : { value : this . dataSources , clone : ( x ) => draggablePolicy . findRealItem ( x ) , } , on : { change : ( e ) => { if ( draggableEvents . some ( n => n in e ) ) { this . $emit ( 'input' , draggablePolicy . updatedSources ( e , this . vlsPolicy . draggingRealIndex ) ) ; } } , ... sortableEventHandlers ( this ) , start : ( e ) => { this . vlsPolicy . onDragStart ( e , this . range , slots ) ; this . $emit ( 'start' , e ) ; } , end : ( e ) => { this . vlsPolicy . onDragEnd ( ) ; this . $emit ( 'end' , e ) ; } } , attrs : this . $attrs , } , slots ) , ] ; } } return Broker ; } export function sortableEventHandlers ( context ) { return sortableEvents . reduce ( ( acc , eventName ) => ( { ... acc , [ eventName ] : context . $emit . bind ( context , eventName ) , } ) , { } ) ; }