import { TimelineLite } from 'gsap' ; export interface ICompanionElement extends HTMLElement { show ( ) : TimelineLite ; hide ( ) : TimelineLite ; } export interface IInterruptMixin extends Polymer . Element { companionElement : ICompanionElement | ICompanionElement [ ] | null ; timeline : TimelineLite ; bindToMessage : string ; itemDisplayDuration : number ; canExtend : boolean ; playItem ( item ) : TimelineLite ; _createEntranceAnim ( item ) : TimelineLite ; _createChangeAnim ( item ) : TimelineLite ; _createExitAnim ( ) : TimelineLite ; _addReset ( ) : void ; } const { property } = Polymer . decorators ; const EMPTY_OBJ = { } ; mixinFunction polymer export default Polymer . dedupingMixin ( ( base ) => { mixinClass polymer abstract class InterruptMixin extends base implements IInterruptMixin { @ property ( { type : Object } ) companionElement : ICompanionElement | ICompanionElement [ ] | null ; @ property ( { type : Object } ) timeline : TimelineLite = new TimelineLite ( { autoRemoveChildren : true } ) ; /**
         * The message name to bind to.
         */ @ property ( { type : String } ) bindToMessage : string ; /**
         * How long, in seconds, to hold items for after they have finished entering.
         */ @ property ( { type : Number } ) itemDisplayDuration = 9 ; /**
         * If true, it means that we're currently showing an item,
         * and are at a point in the animation where we can show another one
         * without performing a full exit/enter cycle again.
         */ @ property ( { type : Boolean , notify : true , observer : InterruptMixin . prototype . _canExtendChanged , readOnly : true } ) canExtend = false ; abstract _createEntranceAnim ( item ) ; abstract _createChangeAnim ( item ) ; abstract _createExitAnim ( ) ; abstract _addReset ( ) ; ready ( ) { super . ready ( ) ; if ( this . bindToMessage && this . bindToMessage . length > 0 && this . bindToMessage !== 'false' ) { nodecg . listenFor ( this . bindToMessage , this . playItem . bind ( this ) ) ; } } param item returns playItem ( item ) { const tl = this . timeline ; if ( ! item ) { return tl ; } let companionElementsArray ; if ( Array . isArray ( this . companionElement ) ) { companionElementsArray = this . companionElement ; } else { companionElementsArray = [ this . companionElement as ICompanionElement ] ; } companionElementsArray = companionElementsArray . filter ( companionElement => { return companionElement && typeof ( companionElement as any ) . hide === 'function' ; } ) ; if ( this . canExtend ) { const newAnim = new TimelineLite ( ) ; newAnim . add ( this . _createChangeAnim ( item ) ) ; newAnim . add ( this . _createHold ( ) ) ; tl . add ( newAnim , 'exit-=0.01' ) ; tl . shiftChildren ( newAnim . duration ( ) , true , tl . getLabelTime ( 'exit' ) ) ; } else { this . _addReset ( ) ; tl . call ( ( ) => { ( this as any ) . _setCanExtend ( true ) ; if ( companionElementsArray . length <= 0 ) { return ; } tl . pause ( null , false ) ; const companionExitTl = new TimelineLite ( ) ; companionElementsArray . forEach ( companionElement => { companionExitTl . add ( companionElement . hide ( ) , 0 ) ; } ) ; companionExitTl . call ( ( ) => { tl . resume ( null , false ) ; } ) ; } , undefined , null , '+=0.03' ) ; if ( companionElementsArray . length > 0 ) { tl . addPause ( ) ; } tl . add ( this . _createEntranceAnim ( item ) , '+=0.03' ) ; if ( ( window as any ) . __SCREENSHOT_TESTING__ ) { return tl ; } tl . add ( this . _createHold ( ) ) ; tl . addLabel ( 'exit' , '+=0' ) ; const exitAnim = new TimelineLite ( { onStart : ( ) => { ( this as any ) . _setCanExtend ( false ) ; } } ) ; exitAnim . add ( this . _createExitAnim ( ) ) ; tl . add ( exitAnim ) ; if ( companionElementsArray . length > 0 ) { tl . addLabel ( 'companionEnter' , '+=0' ) ; companionElementsArray . forEach ( companionElement => { tl . add ( companionElement . show ( ) , 'companionEnter' ) ; } ) ; } tl . to ( EMPTY_OBJ , 0.1 , EMPTY_OBJ ) ; } return tl ; } returns _createHold ( ) { const tl = new TimelineLite ( ) ; tl . to ( EMPTY_OBJ , this . itemDisplayDuration , EMPTY_OBJ ) ; return tl ; } _canExtendChanged ( newVal ) { if ( newVal ) { this . dispatchEvent ( new CustomEvent ( 'can-extend' ) ) ; } } } return InterruptMixin ; } ) ;