@@ -21,15 +21,12 @@ const wrapperClass = 'cdk-global-overlay-wrapper';
21
21
export class GlobalPositionStrategy implements PositionStrategy {
22
22
/** The overlay to which this strategy is attached. */
23
23
private _overlayRef : OverlayReference ;
24
- private _cssPosition : string = 'static' ;
25
- private _topOffset : string = '' ;
26
- private _bottomOffset : string = '' ;
27
- private _leftOffset : string = '' ;
28
- private _rightOffset : string = '' ;
29
- private _alignItems : string = '' ;
30
- private _justifyContent : string = '' ;
31
24
private _width : string = '' ;
32
25
private _height : string = '' ;
26
+ private _yPosition : 'top' | 'bottom' | 'center' = 'center' ;
27
+ private _yOffset = '' ;
28
+ private _xPosition : 'left' | 'right' | 'start' | 'end' | 'center' = 'center' ;
29
+ private _xOffset = '' ;
33
30
private _isDisposed : boolean ;
34
31
35
32
attach ( overlayRef : OverlayReference ) : void {
@@ -50,46 +47,64 @@ export class GlobalPositionStrategy implements PositionStrategy {
50
47
}
51
48
52
49
/**
53
- * Sets the top position of the overlay. Clears any previously set vertical position .
54
- * @param value New top offset .
50
+ * Positions the overlay to the top of the viewport .
51
+ * @param offset Offset from the top of the viewport .
55
52
*/
56
- top ( value : string = '' ) : this {
57
- this . _bottomOffset = '' ;
58
- this . _topOffset = value ;
59
- this . _alignItems = 'flex-start' ;
53
+ top ( offset : string = '' ) : this {
54
+ this . _yOffset = offset ;
55
+ this . _yPosition = 'top' ;
60
56
return this ;
61
57
}
62
58
63
59
/**
64
- * Sets the left position of the overlay. Clears any previously set horizontal position .
65
- * @param value New left offset .
60
+ * Positions the overlay to the left of the viewport, no matter what layout direction it has .
61
+ * @param offset Offset from the left of the viewport .
66
62
*/
67
- left ( value : string = '' ) : this {
68
- this . _rightOffset = '' ;
69
- this . _leftOffset = value ;
70
- this . _justifyContent = 'flex-start' ;
63
+ left ( offset : string = '' ) : this {
64
+ this . _xOffset = offset ;
65
+ this . _xPosition = 'left' ;
71
66
return this ;
72
67
}
73
68
74
69
/**
75
- * Sets the bottom position of the overlay. Clears any previously set vertical position .
76
- * @param value New bottom offset .
70
+ * Positions the overlay to the bottom of the viewport .
71
+ * @param offset Offset from the bottom of the viewport .
77
72
*/
78
- bottom ( value : string = '' ) : this {
79
- this . _topOffset = '' ;
80
- this . _bottomOffset = value ;
81
- this . _alignItems = 'flex-end' ;
73
+ bottom ( offset : string = '' ) : this {
74
+ this . _yOffset = offset ;
75
+ this . _yPosition = 'bottom' ;
82
76
return this ;
83
77
}
84
78
85
79
/**
86
- * Sets the right position of the overlay. Clears any previously set horizontal position .
87
- * @param value New right offset .
80
+ * Positions the overlay to the right of the viewport, no matter what layout direction it has .
81
+ * @param offset Offset from the right of the viewport .
88
82
*/
89
- right ( value : string = '' ) : this {
90
- this . _leftOffset = '' ;
91
- this . _rightOffset = value ;
92
- this . _justifyContent = 'flex-end' ;
83
+ right ( offset : string = '' ) : this {
84
+ this . _xOffset = offset ;
85
+ this . _xPosition = 'right' ;
86
+ return this ;
87
+ }
88
+
89
+ /**
90
+ * Sets the overlay to the start of the viewport, depending on the overlay direction.
91
+ * This will be to the left in LTR layouts and to the right in RTL.
92
+ * @param offset Offset from the edge of the screen.
93
+ */
94
+ start ( offset : string = '' ) : this {
95
+ this . _xOffset = offset ;
96
+ this . _xPosition = 'start' ;
97
+ return this ;
98
+ }
99
+
100
+ /**
101
+ * Sets the overlay to the end of the viewport, depending on the overlay direction.
102
+ * This will be to the right in LTR layouts and to the left in RTL.
103
+ * @param offset Offset from the edge of the screen.
104
+ */
105
+ end ( offset : string = '' ) : this {
106
+ this . _xOffset = offset ;
107
+ this . _xPosition = 'end' ;
93
108
return this ;
94
109
}
95
110
@@ -126,26 +141,22 @@ export class GlobalPositionStrategy implements PositionStrategy {
126
141
}
127
142
128
143
/**
129
- * Centers the overlay horizontally with an optional offset.
130
- * Clears any previously set horizontal position.
131
- *
132
- * @param offset Overlay offset from the horizontal center.
144
+ * Centers the overlay horizontally in the viewport.
145
+ * @param offset Offset from the center of the viewport.
133
146
*/
134
147
centerHorizontally ( offset : string = '' ) : this {
135
- this . left ( offset ) ;
136
- this . _justifyContent = 'center' ;
148
+ this . _xOffset = offset ;
149
+ this . _xPosition = 'center' ;
137
150
return this ;
138
151
}
139
152
140
153
/**
141
- * Centers the overlay vertically with an optional offset.
142
- * Clears any previously set vertical position.
143
- *
144
- * @param offset Overlay offset from the vertical center.
154
+ * Centers the overlay vertically in the viewport.
155
+ * @param offset Offset from the center of the viewport.
145
156
*/
146
157
centerVertically ( offset : string = '' ) : this {
147
- this . top ( offset ) ;
148
- this . _alignItems = 'center' ;
158
+ this . _yPosition = 'center' ;
159
+ this . _yOffset = offset ;
149
160
return this ;
150
161
}
151
162
@@ -161,35 +172,90 @@ export class GlobalPositionStrategy implements PositionStrategy {
161
172
return ;
162
173
}
163
174
175
+ this . _overlayRef . overlayElement . style . position = 'static' ;
176
+ this . _applyYPosition ( ) ;
177
+ this . _applyXPosition ( ) ;
178
+ }
179
+
180
+ private _applyYPosition ( ) {
164
181
const styles = this . _overlayRef . overlayElement . style ;
165
182
const parentStyles = this . _overlayRef . hostElement . style ;
166
183
const config = this . _overlayRef . getConfig ( ) ;
167
184
168
- styles . position = this . _cssPosition ;
169
- styles . marginLeft = config . width === '100%' ? '0' : this . _leftOffset ;
170
- styles . marginTop = config . height === '100%' ? '0' : this . _topOffset ;
171
- styles . marginBottom = this . _bottomOffset ;
172
- styles . marginRight = this . _rightOffset ;
185
+ if ( config . height === '100%' ) {
186
+ parentStyles . alignItems = 'flex-start' ;
187
+ styles . marginTop = styles . marginBottom = '0' ;
188
+ return ;
189
+ }
190
+
191
+ switch ( this . _yPosition ) {
192
+ case 'top' :
193
+ case 'center' :
194
+ parentStyles . alignItems = this . _yPosition === 'center' ? 'center' : 'flex-start' ;
195
+ styles . marginTop = this . _yOffset ;
196
+ styles . marginBottom = '' ;
197
+ break ;
198
+
199
+ case 'bottom' :
200
+ parentStyles . alignItems = 'flex-end' ;
201
+ styles . marginTop = '' ;
202
+ styles . marginBottom = this . _yOffset ;
203
+ break ;
204
+
205
+ default :
206
+ throw Error ( `Unsupported Y axis position ${ this . _yPosition } .` ) ;
207
+ }
208
+ }
209
+
210
+ private _applyXPosition ( ) {
211
+ const styles = this . _overlayRef . overlayElement . style ;
212
+ const parentStyles = this . _overlayRef . hostElement . style ;
213
+ const config = this . _overlayRef . getConfig ( ) ;
214
+ const isRtl = this . _overlayRef . getConfig ( ) . direction === 'rtl' ;
173
215
174
216
if ( config . width === '100%' ) {
175
217
parentStyles . justifyContent = 'flex-start' ;
176
- } else if ( this . _justifyContent === 'center' ) {
177
- parentStyles . justifyContent = 'center' ;
178
- } else if ( this . _overlayRef . getConfig ( ) . direction === 'rtl' ) {
179
- // In RTL the browser will invert `flex-start` and `flex-end` automatically, but we
180
- // don't want that because our positioning is explicitly `left` and `right`, hence
181
- // why we do another inversion to ensure that the overlay stays in the same position.
182
- // TODO: reconsider this if we add `start` and `end` methods.
183
- if ( this . _justifyContent === 'flex-start' ) {
184
- parentStyles . justifyContent = 'flex-end' ;
185
- } else if ( this . _justifyContent === 'flex-end' ) {
186
- parentStyles . justifyContent = 'flex-start' ;
187
- }
188
- } else {
189
- parentStyles . justifyContent = this . _justifyContent ;
218
+ styles . marginLeft = styles . marginRight = '0' ;
219
+ return ;
190
220
}
191
221
192
- parentStyles . alignItems = config . height === '100%' ? 'flex-start' : this . _alignItems ;
222
+ switch ( this . _xPosition ) {
223
+ // In RTL the browser will invert `flex-start` and `flex-end` automatically, but we don't
224
+ // want that if the positioning is explicitly `left` and `right`, hence why we do another
225
+ // inversion to ensure that the overlay stays in the same position.
226
+ case 'left' :
227
+ parentStyles . justifyContent = isRtl ? 'flex-end' : 'flex-start' ;
228
+ styles . marginLeft = this . _xOffset ;
229
+ styles . marginRight = '' ;
230
+ break ;
231
+
232
+ case 'right' :
233
+ parentStyles . justifyContent = isRtl ? 'flex-start' : 'flex-end' ;
234
+ styles . marginRight = this . _xOffset ;
235
+ styles . marginLeft = '' ;
236
+ break ;
237
+
238
+ case 'center' :
239
+ parentStyles . justifyContent = 'center' ;
240
+ styles . marginLeft = isRtl ? '' : this . _xOffset ;
241
+ styles . marginRight = isRtl ? this . _xOffset : '' ;
242
+ break ;
243
+
244
+ case 'start' :
245
+ parentStyles . justifyContent = 'flex-start' ;
246
+ styles . marginLeft = isRtl ? '' : this . _xOffset ;
247
+ styles . marginRight = isRtl ? this . _xOffset : '' ;
248
+ break ;
249
+
250
+ case 'end' :
251
+ parentStyles . justifyContent = 'flex-end' ;
252
+ styles . marginLeft = isRtl ? this . _xOffset : '' ;
253
+ styles . marginRight = isRtl ? '' : this . _xOffset ;
254
+ break ;
255
+
256
+ default :
257
+ throw Error ( `Unsupported X axis position ${ this . _xPosition } .` ) ;
258
+ }
193
259
}
194
260
195
261
/**
0 commit comments