import clamp from 'lodash.clamp' ; export class MovableRange < T > { public endPosition : number ; public visibleLength : number ; constructor ( public data , length ) { this . endPosition = this . data . length ; this . visibleLength = length ; } public setData ( data ) { const minPosition = this . visibleLength > data . length ? data . length : this . visibleLength ; this . endPosition = clamp ( data . length - ( this . data . length - this . endPosition ) , minPosition , data . length ) ; this . data = data ; } public setVisibleLength ( length ) { this . visibleLength = length ; const minPosition = length > this . data . length ? this . data . length : length ; this . endPosition = clamp ( this . endPosition , minPosition , this . data . length ) ; } public visible ( ) { return this . data . slice ( this . visibleStartIndex ( ) , this . endPosition ) ; } public visibleStartIndex ( ) { return clamp ( this . endPosition - this . visibleLength , 0 , this . data . length ) ; } param step returns public move ( step ) { const minPosition = this . visibleLength > this . data . length ? this . data . length : this . visibleLength ; const pos = clamp ( this . endPosition + step , minPosition , this . data . length ) ; const moved = this . endPosition !== pos ; this . endPosition = pos ; return moved ; } public recenter ( visibleIndex , length ) { const i = clamp ( this . visibleStartIndex ( ) + visibleIndex , 0 , this . data . length ) ; this . endPosition = i + Math . floor ( length / 2 ) + 1 ; this . setVisibleLength ( length ) ; } }