import type { GridStyleManager } from 'lineupengine' ; import type { ILineUpOptions } from '../../config' ; import { debounce , AEventDispatcher , IEventListener , suffix } from '../../internal' ; import { IGroupData , IGroupItem , isGroup , Ranking , IGroup } from '../../model' ; import { DataProvider } from '../../provider' ; import type { IRenderContext } from '../../renderer' ; import type { IEngineRankingContext } from '../EngineRanking' ; import EngineRenderer from '../EngineRenderer' ; import type { IRankingHeaderContext , IRankingHeaderContextContainer } from '../interfaces' ; import type { IRule } from './rules' ; import type { ADialog } from '../dialogs' ; asMemberOf param dataIndex event export declare function highlightChanged ( dataIndex ) ; asMemberOf param dialog event export declare function dialogOpened ( dialog ) ; asMemberOf param dialog param action event export declare function dialogClosed ( dialog , action ) ; export interface ITaggleOptions { violationChanged ( rule , violation ) : void ; rowPadding : number ; } export default class TaggleRenderer extends AEventDispatcher { static readonly EVENT_HIGHLIGHT_CHANGED = EngineRenderer . EVENT_HIGHLIGHT_CHANGED ; static readonly EVENT_DIALOG_OPENED = EngineRenderer . EVENT_DIALOG_OPENED ; static readonly EVENT_DIALOG_CLOSED = EngineRenderer . EVENT_DIALOG_CLOSED ; private isDynamicLeafHeight = false ; private rule : IRule | null = null ; private levelOfDetail : ( ( rowIndex : number ) => 'high' | 'low' ) | null = null ; private readonly resizeListener = ( ) => debounce ( ( ) => this . update ( ) , 100 ) ; private readonly renderer : EngineRenderer ; private readonly options : Readonly < ITaggleOptions > = { violationChanged : ( ) => undefined , rowPadding : 2 , } ; constructor ( public data , parent , options ) { super ( ) ; Object . assign ( this . options , options ) ; this . renderer = new EngineRenderer ( data , parent , Object . assign ( { } , options , { dynamicHeight : ( data , ranking ) => { const r = this . dynamicHeight ( data , ranking ) ; if ( r ) { return r ; } return options . dynamicHeight ? options . dynamicHeight ( data , ranking ) : null ; } , levelOfDetail : ( rowIndex ) => ( this . levelOfDetail ? this . levelOfDetail ( rowIndex ) : 'high' ) , } ) ) ; this . data . on ( `${ DataProvider . EVENT_SELECTION_CHANGED }.rule` , ( ) => { if ( this . isDynamicLeafHeight ) { this . update ( ) ; } } ) ; this . forward ( this . renderer , ... suffix ( '.main' , EngineRenderer . EVENT_HIGHLIGHT_CHANGED , EngineRenderer . EVENT_DIALOG_OPENED , EngineRenderer . EVENT_DIALOG_CLOSED ) ) ; window . addEventListener ( 'resize' , this . resizeListener , { passive : true , } ) ; } get style ( ) : GridStyleManager { return this . renderer . style ; } get ctx ( ) : IRankingHeaderContextContainer & IRenderContext & IEngineRankingContext { return this . renderer . ctx ; } pushUpdateAble ( updateAble ) { this . renderer . pushUpdateAble ( updateAble ) ; } private dynamicHeight ( data , ranking ) { if ( ! this . rule ) { this . levelOfDetail = null ; this . options . violationChanged ( null , '' ) ; return null ; } const availableHeight = this . renderer ? this . renderer . node . querySelector ( 'main' ) ! . clientHeight : 100 ; const topNGetter = ( group ) => this . data . getTopNAggregated ( ranking , group ) ; const instance = this . rule . apply ( data , availableHeight , new Set ( this . data . getSelection ( ) ) , topNGetter ) ; this . isDynamicLeafHeight = typeof instance . item === 'function' ; this . options . violationChanged ( this . rule , instance . violation || '' ) ; const height = ( item ) => { if ( isGroup ( item ) ) { return typeof instance . group === 'number' ? instance . group : instance . group ( item ) ; } return typeof instance . item === 'number' ? instance . item : instance . item ( item ) ; } ; this . levelOfDetail = ( rowIndex ) => { const item = data [ rowIndex ] ; return this . rule ? this . rule . levelOfDetail ( item , height ( item ) ) : 'high' ; } ; return { defaultHeight : typeof instance . item === 'number' ? instance . item : NaN , height , padding : 0 , } ; } protected createEventList ( ) { return super . createEventList ( ) . concat ( [ TaggleRenderer . EVENT_HIGHLIGHT_CHANGED , TaggleRenderer . EVENT_DIALOG_OPENED , TaggleRenderer . EVENT_DIALOG_CLOSED , ] ) ; } on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) ; on ( type , listener ) { return super . on ( type , listener ) ; } zoomOut ( ) { this . renderer . zoomOut ( ) ; } zoomIn ( ) { this . renderer . zoomIn ( ) ; } switchRule ( rule ) { if ( this . rule === rule ) { return ; } this . rule = rule ; this . update ( ) ; } destroy ( ) { this . renderer . destroy ( ) ; window . removeEventListener ( 'resize' , this . resizeListener ) ; } update ( ) { this . renderer . update ( ) ; } setDataProvider ( data ) { if ( this . data ) { this . data . on ( `${ DataProvider . EVENT_SELECTION_CHANGED }.rule` , null ) ; } this . data = data ; this . data . on ( `${ DataProvider . EVENT_SELECTION_CHANGED }.rule` , ( ) => { if ( this . isDynamicLeafHeight ) { this . update ( ) ; } } ) ; this . renderer . setDataProvider ( data ) ; this . update ( ) ; } setHighlight ( dataIndex , scrollIntoView ) { return this . renderer . setHighlight ( dataIndex , scrollIntoView ) ; } getHighlight ( ) { return this . renderer . getHighlight ( ) ; } enableHighlightListening ( enable ) { this . renderer . enableHighlightListening ( enable ) ; } }