@@ -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,40 +172,96 @@ 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
- const { width, height, maxWidth, maxHeight} = config ;
168
- const shouldBeFlushHorizontally = ( width === '100%' || width === '100vw' ) &&
169
- ( ! maxWidth || maxWidth === '100%' || maxWidth === '100vw' ) ;
184
+ const { height, maxHeight} = config ;
170
185
const shouldBeFlushVertically = ( height === '100%' || height === '100vh' ) &&
171
186
( ! maxHeight || maxHeight === '100%' || maxHeight === '100vh' ) ;
172
187
173
- styles . position = this . _cssPosition ;
174
- styles . marginLeft = shouldBeFlushHorizontally ? '0' : this . _leftOffset ;
175
- styles . marginTop = shouldBeFlushVertically ? '0' : this . _topOffset ;
176
- styles . marginBottom = this . _bottomOffset ;
177
- styles . marginRight = this . _rightOffset ;
188
+ if ( shouldBeFlushVertically ) {
189
+ parentStyles . alignItems = 'flex-start' ;
190
+ styles . marginTop = styles . marginBottom = '0' ;
191
+ return ;
192
+ }
193
+
194
+ switch ( this . _yPosition ) {
195
+ case 'top' :
196
+ case 'center' :
197
+ parentStyles . alignItems = this . _yPosition === 'center' ? 'center' : 'flex-start' ;
198
+ styles . marginTop = shouldBeFlushVertically ? '0' : this . _yOffset ;
199
+ styles . marginBottom = '' ;
200
+ break ;
201
+
202
+ case 'bottom' :
203
+ parentStyles . alignItems = 'flex-end' ;
204
+ styles . marginTop = '' ;
205
+ styles . marginBottom = shouldBeFlushVertically ? '0' : this . _yOffset ;
206
+ break ;
207
+
208
+ default :
209
+ throw Error ( `Unsupported Y axis position ${ this . _yPosition } .` ) ;
210
+ }
211
+ }
212
+
213
+ private _applyXPosition ( ) {
214
+ const styles = this . _overlayRef . overlayElement . style ;
215
+ const parentStyles = this . _overlayRef . hostElement . style ;
216
+ const config = this . _overlayRef . getConfig ( ) ;
217
+ const { width, maxWidth} = config ;
218
+ const isRtl = this . _overlayRef . getConfig ( ) . direction === 'rtl' ;
219
+ const shouldBeFlushHorizontally = ( width === '100%' || width === '100vw' ) &&
220
+ ( ! maxWidth || maxWidth === '100%' || maxWidth === '100vw' ) ;
178
221
179
222
if ( shouldBeFlushHorizontally ) {
180
223
parentStyles . justifyContent = 'flex-start' ;
181
- } else if ( this . _justifyContent === 'center' ) {
182
- parentStyles . justifyContent = 'center' ;
183
- } else if ( this . _overlayRef . getConfig ( ) . direction === 'rtl' ) {
184
- // In RTL the browser will invert `flex-start` and `flex-end` automatically, but we
185
- // don't want that because our positioning is explicitly `left` and `right`, hence
186
- // why we do another inversion to ensure that the overlay stays in the same position.
187
- // TODO: reconsider this if we add `start` and `end` methods.
188
- if ( this . _justifyContent === 'flex-start' ) {
189
- parentStyles . justifyContent = 'flex-end' ;
190
- } else if ( this . _justifyContent === 'flex-end' ) {
191
- parentStyles . justifyContent = 'flex-start' ;
192
- }
193
- } else {
194
- parentStyles . justifyContent = this . _justifyContent ;
224
+ styles . marginLeft = styles . marginRight = '0' ;
225
+ return ;
195
226
}
196
227
197
- parentStyles . alignItems = shouldBeFlushVertically ? 'flex-start' : this . _alignItems ;
228
+ switch ( this . _xPosition ) {
229
+ // In RTL the browser will invert `flex-start` and `flex-end` automatically, but we don't
230
+ // want that if the positioning is explicitly `left` and `right`, hence why we do another
231
+ // inversion to ensure that the overlay stays in the same position.
232
+ case 'left' :
233
+ parentStyles . justifyContent = isRtl ? 'flex-end' : 'flex-start' ;
234
+ styles . marginLeft = this . _xOffset ;
235
+ styles . marginRight = '' ;
236
+ break ;
237
+
238
+ case 'right' :
239
+ parentStyles . justifyContent = isRtl ? 'flex-start' : 'flex-end' ;
240
+ styles . marginRight = this . _xOffset ;
241
+ styles . marginLeft = '' ;
242
+ break ;
243
+
244
+ case 'center' :
245
+ parentStyles . justifyContent = 'center' ;
246
+ styles . marginLeft = isRtl ? '' : this . _xOffset ;
247
+ styles . marginRight = isRtl ? this . _xOffset : '' ;
248
+ break ;
249
+
250
+ case 'start' :
251
+ parentStyles . justifyContent = 'flex-start' ;
252
+ styles . marginLeft = isRtl ? '' : this . _xOffset ;
253
+ styles . marginRight = isRtl ? this . _xOffset : '' ;
254
+ break ;
255
+
256
+ case 'end' :
257
+ parentStyles . justifyContent = 'flex-end' ;
258
+ styles . marginLeft = isRtl ? this . _xOffset : '' ;
259
+ styles . marginRight = isRtl ? '' : this . _xOffset ;
260
+ break ;
261
+
262
+ default :
263
+ throw Error ( `Unsupported X axis position ${ this . _xPosition } .` ) ;
264
+ }
198
265
}
199
266
200
267
/**
0 commit comments