@@ -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,17 @@ 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 =
688
+ start . x < this . _getViewportMarginStart ( )
689
+ ? viewport . left - scrollPosition . left - start . x
690
+ : 0 ;
686
691
}
687
692
688
693
if ( overlay . height <= viewport . height ) {
689
694
pushY = overflowTop || - overflowBottom ;
690
695
} else {
691
- pushY = start . y < this . _viewportMargin ? viewport . top - scrollPosition . top - start . y : 0 ;
696
+ pushY =
697
+ start . y < this . _getViewportMarginTop ( ) ? viewport . top - scrollPosition . top - start . y : 0 ;
692
698
}
693
699
694
700
this . _previousPushAmount = { x : pushX , y : pushY } ;
@@ -777,13 +783,14 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
777
783
if ( position . overlayY === 'top' ) {
778
784
// Overlay is opening "downward" and thus is bound by the bottom viewport edge.
779
785
top = origin . y ;
780
- height = viewport . height - top + this . _viewportMargin ;
786
+ height = viewport . height - top + this . _getViewportMarginBottom ( ) ;
781
787
} else if ( position . overlayY === 'bottom' ) {
782
788
// Overlay is opening "upward" and thus is bound by the top viewport edge. We need to add
783
789
// the viewport margin back in, because the viewport rect is narrowed down to remove the
784
790
// 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 ;
791
+ bottom =
792
+ viewport . height - origin . y + this . _getViewportMarginTop ( ) + this . _getViewportMarginBottom ( ) ;
793
+ height = viewport . height - bottom + this . _getViewportMarginTop ( ) ;
787
794
} else {
788
795
// If neither top nor bottom, it means that the overlay is vertically centered on the
789
796
// origin point. Note that we want the position relative to the viewport, rather than
@@ -815,11 +822,12 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
815
822
let width : number , left : number , right : number ;
816
823
817
824
if ( isBoundedByLeftViewportEdge ) {
818
- right = viewport . width - origin . x + this . _viewportMargin * 2 ;
819
- width = origin . x - this . _viewportMargin ;
825
+ right =
826
+ viewport . width - origin . x + this . _getViewportMarginStart ( ) + this . _getViewportMarginEnd ( ) ;
827
+ width = origin . x - this . _getViewportMarginStart ( ) ;
820
828
} else if ( isBoundedByRightViewportEdge ) {
821
829
left = origin . x ;
822
- width = viewport . right - origin . x ;
830
+ width = viewport . right - origin . x - this . _getViewportMarginEnd ( ) ;
823
831
} else {
824
832
// If neither start nor end, it means that the overlay is horizontally centered on the
825
833
// origin point. Note that we want the position relative to the viewport, rather than
@@ -1098,12 +1106,12 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
1098
1106
const scrollPosition = this . _viewportRuler . getViewportScrollPosition ( ) ;
1099
1107
1100
1108
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 ,
1109
+ top : scrollPosition . top + this . _getViewportMarginTop ( ) ,
1110
+ left : scrollPosition . left + this . _getViewportMarginStart ( ) ,
1111
+ right : scrollPosition . left + width - this . _getViewportMarginEnd ( ) ,
1112
+ bottom : scrollPosition . top + height - this . _getViewportMarginBottom ( ) ,
1113
+ width : width - this . _getViewportMarginStart ( ) - this . _getViewportMarginEnd ( ) ,
1114
+ height : height - this . _getViewportMarginTop ( ) - this . _getViewportMarginBottom ( ) ,
1107
1115
} ;
1108
1116
}
1109
1117
@@ -1168,6 +1176,42 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
1168
1176
}
1169
1177
}
1170
1178
1179
+ /**
1180
+ * Returns either the _viewportMargin directly (if it is a number) or its 'start' value.
1181
+ * @private
1182
+ */
1183
+ private _getViewportMarginStart ( ) : number {
1184
+ if ( typeof this . _viewportMargin === 'number' ) return this . _viewportMargin ;
1185
+ return this . _viewportMargin ?. start ?? 0 ;
1186
+ }
1187
+
1188
+ /**
1189
+ * Returns either the _viewportMargin directly (if it is a number) or its 'end' value.
1190
+ * @private
1191
+ */
1192
+ private _getViewportMarginEnd ( ) : number {
1193
+ if ( typeof this . _viewportMargin === 'number' ) return this . _viewportMargin ;
1194
+ return this . _viewportMargin ?. end ?? 0 ;
1195
+ }
1196
+
1197
+ /**
1198
+ * Returns either the _viewportMargin directly (if it is a number) or its 'top' value.
1199
+ * @private
1200
+ */
1201
+ private _getViewportMarginTop ( ) : number {
1202
+ if ( typeof this . _viewportMargin === 'number' ) return this . _viewportMargin ;
1203
+ return this . _viewportMargin ?. top ?? 0 ;
1204
+ }
1205
+
1206
+ /**
1207
+ * Returns either the _viewportMargin directly (if it is a number) or its 'bottom' value.
1208
+ * @private
1209
+ */
1210
+ private _getViewportMarginBottom ( ) : number {
1211
+ if ( typeof this . _viewportMargin === 'number' ) return this . _viewportMargin ;
1212
+ return this . _viewportMargin ?. bottom ?? 0 ;
1213
+ }
1214
+
1171
1215
/** Returns the DOMRect of the current origin. */
1172
1216
private _getOriginRect ( ) : Dimensions {
1173
1217
const origin = this . _origin ;
0 commit comments