@@ -15,6 +15,7 @@ import {
1515  ScrollingVisibility , 
1616  validateHorizontalPosition , 
1717  validateVerticalPosition , 
18+   ViewportMargin , 
1819}  from  './connected-position' ; 
1920import  { Observable ,  Subscription ,  Subject }  from  'rxjs' ; 
2021import  { isElementScrolledOutsideView ,  isElementClippedByScrolling }  from  './scroll-clip' ; 
@@ -106,8 +107,8 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
106107  /** Cached container dimensions */ 
107108  private  _containerRect : Dimensions ; 
108109
109-   /** Amount of space that must be maintained between the overlay and the edge of the viewport. */ 
110-   private  _viewportMargin  =  0 ; 
110+   /** Amount of space that must be maintained between the overlay and the right  edge of the viewport. */ 
111+   private  _viewportMargin :  ViewportMargin  =  0 ; 
111112
112113  /** The Scrollable containers used to check scrollable view properties on position change. */ 
113114  private  _scrollables : CdkScrollable [ ]  =  [ ] ; 
@@ -429,10 +430,11 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
429430  } 
430431
431432  /** 
432-    * Sets a minimum distance the overlay may be positioned to the edge of the viewport. 
433-    * @param  margin Required margin between the overlay and the viewport edge in pixels. 
433+    * Sets a minimum distance the overlay may be positioned from the bottom edge of the viewport. 
434+    * @param  margin Required margin between the overlay and the viewport. 
435+    * It can be a number to be applied to all directions, or an object to supply different values for each direction. 
434436   */ 
435-   withViewportMargin ( margin : number ) : this { 
437+   withViewportMargin ( margin : ViewportMargin ) : this { 
436438    this . _viewportMargin  =  margin ; 
437439    return  this ; 
438440  } 
@@ -700,13 +702,17 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
700702    if  ( overlay . width  <=  viewport . width )  { 
701703      pushX  =  overflowLeft  ||  - overflowRight ; 
702704    }  else  { 
703-       pushX  =  start . x  <  this . _viewportMargin  ? viewport . left  -  scrollPosition . left  -  start . x  : 0 ; 
705+       pushX  = 
706+         start . x  <  this . _getViewportMarginStart ( ) 
707+           ? viewport . left  -  scrollPosition . left  -  start . x 
708+           : 0 ; 
704709    } 
705710
706711    if  ( overlay . height  <=  viewport . height )  { 
707712      pushY  =  overflowTop  ||  - overflowBottom ; 
708713    }  else  { 
709-       pushY  =  start . y  <  this . _viewportMargin  ? viewport . top  -  scrollPosition . top  -  start . y  : 0 ; 
714+       pushY  = 
715+         start . y  <  this . _getViewportMarginTop ( )  ? viewport . top  -  scrollPosition . top  -  start . y  : 0 ; 
710716    } 
711717
712718    this . _previousPushAmount  =  { x : pushX ,  y : pushY } ; 
@@ -795,13 +801,14 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
795801    if  ( position . overlayY  ===  'top' )  { 
796802      // Overlay is opening "downward" and thus is bound by the bottom viewport edge. 
797803      top  =  origin . y ; 
798-       height  =  viewport . height  -  top  +  this . _viewportMargin ; 
804+       height  =  viewport . height  -  top  +  this . _getViewportMarginBottom ( ) ; 
799805    }  else  if  ( position . overlayY  ===  'bottom' )  { 
800806      // Overlay is opening "upward" and thus is bound by the top viewport edge. We need to add 
801807      // the viewport margin back in, because the viewport rect is narrowed down to remove the 
802808      // margin, whereas the `origin` position is calculated based on its `DOMRect`. 
803-       bottom  =  viewport . height  -  origin . y  +  this . _viewportMargin  *  2 ; 
804-       height  =  viewport . height  -  bottom  +  this . _viewportMargin ; 
809+       bottom  = 
810+         viewport . height  -  origin . y  +  this . _getViewportMarginTop ( )  +  this . _getViewportMarginBottom ( ) ; 
811+       height  =  viewport . height  -  bottom  +  this . _getViewportMarginTop ( ) ; 
805812    }  else  { 
806813      // If neither top nor bottom, it means that the overlay is vertically centered on the 
807814      // origin point. Note that we want the position relative to the viewport, rather than 
@@ -833,11 +840,12 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
833840    let  width : number ,  left : number ,  right : number ; 
834841
835842    if  ( isBoundedByLeftViewportEdge )  { 
836-       right  =  viewport . width  -  origin . x  +  this . _viewportMargin  *  2 ; 
837-       width  =  origin . x  -  this . _viewportMargin ; 
843+       right  = 
844+         viewport . width  -  origin . x  +  this . _getViewportMarginStart ( )  +  this . _getViewportMarginEnd ( ) ; 
845+       width  =  origin . x  -  this . _getViewportMarginStart ( ) ; 
838846    }  else  if  ( isBoundedByRightViewportEdge )  { 
839847      left  =  origin . x ; 
840-       width  =  viewport . right  -  origin . x ; 
848+       width  =  viewport . right  -  origin . x   -   this . _getViewportMarginEnd ( ) ; 
841849    }  else  { 
842850      // If neither start nor end, it means that the overlay is horizontally centered on the 
843851      // origin point. Note that we want the position relative to the viewport, rather than 
@@ -1116,12 +1124,12 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
11161124    const  scrollPosition  =  this . _viewportRuler . getViewportScrollPosition ( ) ; 
11171125
11181126    return  { 
1119-       top : scrollPosition . top  +  this . _viewportMargin , 
1120-       left : scrollPosition . left  +  this . _viewportMargin , 
1121-       right : scrollPosition . left  +  width  -  this . _viewportMargin , 
1122-       bottom : scrollPosition . top  +  height  -  this . _viewportMargin , 
1123-       width : width  -  2   *  this . _viewportMargin , 
1124-       height : height  -  2   *  this . _viewportMargin , 
1127+       top : scrollPosition . top  +  this . _getViewportMarginTop ( ) , 
1128+       left : scrollPosition . left  +  this . _getViewportMarginStart ( ) , 
1129+       right : scrollPosition . left  +  width  -  this . _getViewportMarginEnd ( ) , 
1130+       bottom : scrollPosition . top  +  height  -  this . _getViewportMarginBottom ( ) , 
1131+       width : width  -  this . _getViewportMarginStart ( )   -  this . _getViewportMarginEnd ( ) , 
1132+       height : height  -  this . _getViewportMarginTop ( )   -  this . _getViewportMarginBottom ( ) , 
11251133    } ; 
11261134  } 
11271135
@@ -1186,6 +1194,42 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
11861194    } 
11871195  } 
11881196
1197+   /** 
1198+    * Returns either the _viewportMargin directly (if it is a number) or its 'start' value. 
1199+    * @private  
1200+    */ 
1201+   private  _getViewportMarginStart ( ) : number  { 
1202+     if  ( typeof  this . _viewportMargin  ===  'number' )  return  this . _viewportMargin ; 
1203+     return  this . _viewportMargin ?. start  ??  0 ; 
1204+   } 
1205+ 
1206+   /** 
1207+    * Returns either the _viewportMargin directly (if it is a number) or its 'end' value. 
1208+    * @private  
1209+    */ 
1210+   private  _getViewportMarginEnd ( ) : number  { 
1211+     if  ( typeof  this . _viewportMargin  ===  'number' )  return  this . _viewportMargin ; 
1212+     return  this . _viewportMargin ?. end  ??  0 ; 
1213+   } 
1214+ 
1215+   /** 
1216+    * Returns either the _viewportMargin directly (if it is a number) or its 'top' value. 
1217+    * @private  
1218+    */ 
1219+   private  _getViewportMarginTop ( ) : number  { 
1220+     if  ( typeof  this . _viewportMargin  ===  'number' )  return  this . _viewportMargin ; 
1221+     return  this . _viewportMargin ?. top  ??  0 ; 
1222+   } 
1223+ 
1224+   /** 
1225+    * Returns either the _viewportMargin directly (if it is a number) or its 'bottom' value. 
1226+    * @private  
1227+    */ 
1228+   private  _getViewportMarginBottom ( ) : number  { 
1229+     if  ( typeof  this . _viewportMargin  ===  'number' )  return  this . _viewportMargin ; 
1230+     return  this . _viewportMargin ?. bottom  ??  0 ; 
1231+   } 
1232+ 
11891233  /** Returns the DOMRect of the current origin. */ 
11901234  private  _getOriginRect ( ) : Dimensions  { 
11911235    const  origin  =  this . _origin ; 
0 commit comments