license import { PlacementOptions , PopoverPlacement , PopoverPlacements , } from './type' ; import { Frame } from '../../devsupport' ; const PLACEMENT_FAMILIES = [ PopoverPlacements . BOTTOM . rawValue , PopoverPlacements . TOP . rawValue , PopoverPlacements . LEFT . rawValue , PopoverPlacements . RIGHT . rawValue , ] ; export class PopoverPlacementService { public find ( preferredValue , options ) { const placement = this . findRecursive ( preferredValue , PLACEMENT_FAMILIES , options ) ; return placement || preferredValue ; } private findRecursive ( placement , families , options ) { const oneOfCurrentFamily = this . findFromFamily ( placement , options ) ; if ( oneOfCurrentFamily ) { return oneOfCurrentFamily ; } const oneOfReversedFamily = this . findFromFamily ( placement . reverse ( ) , options ) ; if ( oneOfReversedFamily ) { return oneOfReversedFamily ; } delete families [ families . indexOf ( placement . parent ( ) . rawValue ) ] ; delete families [ families . indexOf ( placement . reverse ( ) . parent ( ) . rawValue ) ] ; const firstTruthy = families . filter ( Boolean ) [ 0 ] ; if ( firstTruthy ) { const nextPlacement = PopoverPlacements . parse ( firstTruthy ) ; return this . findRecursive ( nextPlacement , families , options ) ; } return null ; } private findFromFamily ( placement , options ) { const preferredFrame = placement . frame ( options ) ; if ( placement . fits ( preferredFrame , options . bounds ) ) { return placement ; } return placement . family ( ) . find ( ( familyValue ) : boolean => { const familyFrame = familyValue . frame ( options ) ; return familyValue . fits ( familyFrame , options . bounds ) ; } ) ; } }