@@ -22,6 +22,7 @@ import {coerceCssPixelValue, coerceArray} from '@angular/cdk/coercion';
22
22
import { Platform } from '@angular/cdk/platform' ;
23
23
import { OverlayContainer } from '../overlay-container' ;
24
24
import { OverlayRef } from '../overlay-ref' ;
25
+ import { ViewportMargin } from './viewport-margin' ;
25
26
26
27
// TODO: refactor clipping detection into a separate thing (part of scrolling module)
27
28
// TODO: doesn't handle both flexible width and height when it has to scroll along both axis.
@@ -88,8 +89,8 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
88
89
/** Cached container dimensions */
89
90
private _containerRect : Dimensions ;
90
91
91
- /** Amount of space that must be maintained between the overlay and the edge of the viewport. */
92
- private _viewportMargin = 0 ;
92
+ /** Amount of space that must be maintained between the overlay and the right edge of the viewport. */
93
+ private _viewportMargin : ViewportMargin = 0 ;
93
94
94
95
/** The Scrollable containers used to check scrollable view properties on position change. */
95
96
private _scrollables : CdkScrollable [ ] = [ ] ;
@@ -411,10 +412,11 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
411
412
}
412
413
413
414
/**
414
- * Sets a minimum distance the overlay may be positioned to the edge of the viewport.
415
- * @param margin Required margin between the overlay and the viewport edge in pixels.
415
+ * Sets a minimum distance the overlay may be positioned from the bottom edge of the viewport.
416
+ * @param margin Required margin between the overlay and the viewport.
417
+ * It can be a number to be applied to all directions, or an object to supply different values for each direction.
416
418
*/
417
- withViewportMargin ( margin : number ) : this {
419
+ withViewportMargin ( margin : ViewportMargin ) : this {
418
420
this . _viewportMargin = margin ;
419
421
return this ;
420
422
}
@@ -682,13 +684,13 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
682
684
if ( overlay . width <= viewport . width ) {
683
685
pushX = overflowLeft || - overflowRight ;
684
686
} else {
685
- pushX = start . x < this . _viewportMargin ? viewport . left - scrollPosition . left - start . x : 0 ;
687
+ pushX = start . x < this . _getViewportMarginStart ( ) ? viewport . left - scrollPosition . left - start . x : 0 ;
686
688
}
687
689
688
690
if ( overlay . height <= viewport . height ) {
689
691
pushY = overflowTop || - overflowBottom ;
690
692
} else {
691
- pushY = start . y < this . _viewportMargin ? viewport . top - scrollPosition . top - start . y : 0 ;
693
+ pushY = start . y < this . _getViewportMarginTop ( ) ? viewport . top - scrollPosition . top - start . y : 0 ;
692
694
}
693
695
694
696
this . _previousPushAmount = { x : pushX , y : pushY } ;
@@ -777,13 +779,13 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
777
779
if ( position . overlayY === 'top' ) {
778
780
// Overlay is opening "downward" and thus is bound by the bottom viewport edge.
779
781
top = origin . y ;
780
- height = viewport . height - top + this . _viewportMargin ;
782
+ height = viewport . height - top + this . _getViewportMarginBottom ( ) ;
781
783
} else if ( position . overlayY === 'bottom' ) {
782
784
// Overlay is opening "upward" and thus is bound by the top viewport edge. We need to add
783
785
// the viewport margin back in, because the viewport rect is narrowed down to remove the
784
786
// margin, whereas the `origin` position is calculated based on its `DOMRect`.
785
- bottom = viewport . height - origin . y + this . _viewportMargin * 2 ;
786
- height = viewport . height - bottom + this . _viewportMargin ;
787
+ bottom = viewport . height - origin . y + this . _getViewportMarginTop ( ) + this . _getViewportMarginBottom ( ) ;
788
+ height = viewport . height - bottom + this . _getViewportMarginTop ( ) ;
787
789
} else {
788
790
// If neither top nor bottom, it means that the overlay is vertically centered on the
789
791
// origin point. Note that we want the position relative to the viewport, rather than
@@ -815,11 +817,11 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
815
817
let width : number , left : number , right : number ;
816
818
817
819
if ( isBoundedByLeftViewportEdge ) {
818
- right = viewport . width - origin . x + this . _viewportMargin * 2 ;
819
- width = origin . x - this . _viewportMargin ;
820
+ right = viewport . width - origin . x + this . _getViewportMarginStart ( ) + this . _getViewportMarginEnd ( ) ;
821
+ width = origin . x - this . _getViewportMarginStart ( ) ;
820
822
} else if ( isBoundedByRightViewportEdge ) {
821
823
left = origin . x ;
822
- width = viewport . right - origin . x ;
824
+ width = viewport . right - origin . x - this . _getViewportMarginEnd ( ) ;
823
825
} else {
824
826
// If neither start nor end, it means that the overlay is horizontally centered on the
825
827
// origin point. Note that we want the position relative to the viewport, rather than
@@ -1098,12 +1100,12 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
1098
1100
const scrollPosition = this . _viewportRuler . getViewportScrollPosition ( ) ;
1099
1101
1100
1102
return {
1101
- top : scrollPosition . top + this . _viewportMargin ,
1102
- left : scrollPosition . left + this . _viewportMargin ,
1103
- right : scrollPosition . left + width - this . _viewportMargin ,
1104
- bottom : scrollPosition . top + height - this . _viewportMargin ,
1105
- width : width - 2 * this . _viewportMargin ,
1106
- height : height - 2 * this . _viewportMargin ,
1103
+ top : scrollPosition . top + this . _getViewportMarginTop ( ) ,
1104
+ left : scrollPosition . left + this . _getViewportMarginStart ( ) ,
1105
+ right : scrollPosition . left + width - this . _getViewportMarginEnd ( ) ,
1106
+ bottom : scrollPosition . top + height - this . _getViewportMarginBottom ( ) ,
1107
+ width : width - this . _getViewportMarginStart ( ) - this . _getViewportMarginEnd ( ) ,
1108
+ height : height - this . _getViewportMarginTop ( ) - this . _getViewportMarginBottom ( ) ,
1107
1109
} ;
1108
1110
}
1109
1111
@@ -1168,6 +1170,42 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
1168
1170
}
1169
1171
}
1170
1172
1173
+ /**
1174
+ * Returns either the _viewportMargin directly (if it is a number) or its 'start' value.
1175
+ * @private
1176
+ */
1177
+ private _getViewportMarginStart ( ) : number {
1178
+ if ( typeof this . _viewportMargin === 'number' ) return this . _viewportMargin ;
1179
+ return this . _viewportMargin . start ?? 0
1180
+ }
1181
+
1182
+ /**
1183
+ * Returns either the _viewportMargin directly (if it is a number) or its 'end' value.
1184
+ * @private
1185
+ */
1186
+ private _getViewportMarginEnd ( ) : number {
1187
+ if ( typeof this . _viewportMargin === 'number' ) return this . _viewportMargin ;
1188
+ return this . _viewportMargin . end ?? 0 ;
1189
+ }
1190
+
1191
+ /**
1192
+ * Returns either the _viewportMargin directly (if it is a number) or its 'top' value.
1193
+ * @private
1194
+ */
1195
+ private _getViewportMarginTop ( ) : number {
1196
+ if ( typeof this . _viewportMargin === 'number' ) return this . _viewportMargin ;
1197
+ return this . _viewportMargin . top ?? 0 ;
1198
+ }
1199
+
1200
+ /**
1201
+ * Returns either the _viewportMargin directly (if it is a number) or its 'bottom' value.
1202
+ * @private
1203
+ */
1204
+ private _getViewportMarginBottom ( ) : number {
1205
+ if ( typeof this . _viewportMargin === 'number' ) return this . _viewportMargin ;
1206
+ return this . _viewportMargin . bottom ?? 0 ;
1207
+ }
1208
+
1171
1209
/** Returns the DOMRect of the current origin. */
1172
1210
private _getOriginRect ( ) : Dimensions {
1173
1211
const origin = this . _origin ;
0 commit comments