import { dispatch , Dispatch } from 'd3-dispatch' ; internal export function suffix ( suffix , ... prefix ) { return prefix . map ( ( p ) => `${ p }${ suffix }` ) ; } export interface IEventContext { /**
     * who is sending this event
     */ readonly source : AEventDispatcher ; /**
     * who was sending this event in case of forwarding
     */ readonly origin : AEventDispatcher ; /**
     * the event type
     */ readonly type : string ; /**
     * in case of multi propagation the 'main' event type, aka the first one
     */ readonly primaryType : string ; /**
     * the arguments to the listener
     */ readonly args : any [ ] ; } export interface IEventListener { ( this , ... args ) : any ; } export interface IEventHandler { on ( type , listener ) : this ; } const __DEBUG = false ; /**
 * base class for event dispatching using d3 event mechanism, thus .suffix is supported for multiple registrations
 */ export default class AEventDispatcher implements IEventHandler { private readonly listeners : Dispatch < any > ; private readonly listenerEvents : Set < string > ; private readonly forwarder : ( ... args : any [ ] ) => void ; constructor ( ) { const events = this . createEventList ( ) ; this . listenerEvents = new Set ( events ) ; this . listeners = dispatch ( ... events ) ; const that = this ; this . forwarder = function ( this , ... args ) { that . fireImpl ( this . type , this . primaryType , this . origin , ... args ) ; } ; } on ( type , listener ) { if ( Array . isArray ( type ) ) { type . forEach ( ( d ) => { if ( this . listenerEvents . has ( d . split ( '.' ) [ 0 ] ) ) { this . listenersChanged ( d , Boolean ( listener ! ) ) ; this . listeners . on ( d , listener ! ) ; } else if ( __DEBUG && ! d . includes ( '.' ) ) { console . warn ( this , 'invalid event type' , d ) ; } } ) ; } else if ( this . listenerEvents . has ( ( type as string ) . split ( '.' ) [ 0 ] ) ) { this . listenersChanged ( type as string , Boolean ( listener ! ) ) ; this . listeners . on ( type as string , listener ! ) ; } else if ( __DEBUG && ! type . includes ( '.' ) ) { console . warn ( this , 'invalid event type' , type ) ; } return this ; } param _type param _active protected listenersChanged ( _type , _active ) { } return { Array } protected createEventList ( ) { return [ ] ; } protected fire ( type , ... args ) { const primaryType = Array . isArray ( type ) ? type [ 0 ] : type ; this . fireImpl ( type , primaryType , this , ... args ) ; } private fireImpl ( type , primaryType , origin , ... args ) { const fireImpl = ( t ) => { if ( ! this . listenerEvents . has ( t ) ) { if ( __DEBUG ) { console . warn ( this , 'invalid event type' , t ) ; } return ; } const context = { source : this , origin , type : t , primaryType , args , } ; this . listeners . apply ( t , context , args ) ; } ; if ( Array . isArray ( type ) ) { type . forEach ( fireImpl ) ; } else { fireImpl ( type as string ) ; } } param { IEventHandler } from param { string [ ] } types protected forward ( from , ... types ) { from . on ( types , this . forwarder ) ; } param { IEventHandler } from param { string [ ] } types protected unforward ( from , ... types ) { from . on ( types , null ) ; } }