import { TimelineLite } from 'gsap' ; const { property } = Polymer . decorators ; export interface IGDQBreakLoopMixin < ItemType > extends Polymer . Element { availableItems : ItemType [ ] ; currentItem : ItemType | null ; noAutoLoop : boolean ; maxNoMoreItemsRetries : number ; itemIdField : keyof ItemType ; _showItem ( item ) : TimelineLite ; _resetState ? ( ) : void ; } mixinFunction polymer export default Polymer . dedupingMixin ( ( base ) => { mixinClass polymer abstract class GDQBreakLoopMixin < ItemType > extends base implements IGDQBreakLoopMixin < ItemType > { @ property ( { type : Array } ) availableItems : ItemType [ ] ; @ property ( { type : Object } ) currentItem : ItemType | null ; @ property ( { type : Boolean } ) noAutoLoop = false ; @ property ( { type : Number } ) maxNoMoreItemsRetries = Infinity ; @ property ( { type : String } ) itemIdField : keyof ItemType = 'id' as keyof ItemType ; @ property ( { type : Number } ) _noMoreItemsRetries = 0 ; _loopRetryTimeout : number | undefined ; _currentLoopIterationTimeline ? : TimelineLite ; abstract _showItem ( item ) ; _resetState ? ( ) ; ready ( ) { super . ready ( ) ; if ( ! this . noAutoLoop ) { this . _loop ( ) ; } } _loop ( ) { if ( ( window as any ) . __SCREENSHOT_TESTING__ ) { return ; } if ( ! this . availableItems || this . availableItems . length <= 0 ) { clearTimeout ( this . _loopRetryTimeout ) ; this . _loopRetryTimeout = window . setTimeout ( ( ) => { this . _loop ( ) ; } , 1000 ) ; return ; } const availableItems = this . availableItems ; let nextIdx = 0 ; if ( this . currentItem && this . currentItem [ this . itemIdField ] ) { let currentIdx = - 1 ; availableItems . some ( ( item , index ) => { if ( item [ this . itemIdField ] === this . currentItem ! [ this . itemIdField ] ) { currentIdx = index ; return true ; } return false ; } ) ; nextIdx = currentIdx + 1 ; } if ( nextIdx >= availableItems . length ) { nextIdx = 0 ; } const nextItem = availableItems [ nextIdx ] ; if ( this . currentItem && nextItem [ this . itemIdField ] === this . currentItem [ this . itemIdField ] && this . _noMoreItemsRetries < this . maxNoMoreItemsRetries ) { this . _noMoreItemsRetries ++ ; clearTimeout ( this . _loopRetryTimeout ) ; this . _loopRetryTimeout = window . setTimeout ( ( ) => { this . _loop ( ) ; } , 1000 ) ; return ; } this . _killLoop ( ) ; this . currentItem = nextItem ; const tl = this . _showItem ( nextItem ) ; tl . call ( ( ) => { this . _loop ( ) ; } ) ; this . _currentLoopIterationTimeline = tl ; } _killLoop ( ) { if ( this . _currentLoopIterationTimeline ) { this . _currentLoopIterationTimeline . clear ( ) ; this . _currentLoopIterationTimeline . kill ( ) ; this . _currentLoopIterationTimeline = undefined ; } clearTimeout ( this . _loopRetryTimeout ) ; this . _noMoreItemsRetries = 0 ; if ( this . _resetState ) { this . _resetState ( ) ; } } } return GDQBreakLoopMixin ; } ) ;