@@ -5,7 +5,9 @@ import {applyCssTransform} from '../../style/apply-transform';
5
5
import {
6
6
ConnectionPositionPair ,
7
7
OriginConnectionPosition ,
8
- OverlayConnectionPosition
8
+ OverlayConnectionPosition ,
9
+ PreferredPosition ,
10
+ TransformOrigin
9
11
} from './connected-position' ;
10
12
11
13
@@ -25,13 +27,16 @@ export class ConnectedPositionStrategy implements PositionStrategy {
25
27
/** The offset in pixels for the overlay connection point on the y-axis */
26
28
private _offsetY : number = 0 ;
27
29
30
+ /** The selector for the overlay descendant that controls the animation. */
31
+ private _animationRootSelector : string ;
32
+
28
33
/** Whether the we're dealing with an RTL context */
29
34
get _isRtl ( ) {
30
35
return this . _dir === 'rtl' ;
31
36
}
32
37
33
38
/** Ordered list of preferred positions, from most to least desirable. */
34
- _preferredPositions : ConnectionPositionPair [ ] = [ ] ;
39
+ _preferredPositions : PreferredPosition [ ] = [ ] ;
35
40
36
41
/** The origin element against which the overlay will be positioned. */
37
42
private _origin : HTMLElement ;
@@ -70,13 +75,16 @@ export class ConnectedPositionStrategy implements PositionStrategy {
70
75
for ( let pos of this . _preferredPositions ) {
71
76
// Get the (x, y) point of connection on the origin, and then use that to get the
72
77
// (top, left) coordinate for the overlay at `pos`.
73
- let originPoint = this . _getOriginConnectionPoint ( originRect , pos ) ;
74
- let overlayPoint = this . _getOverlayPoint ( originPoint , overlayRect , pos ) ;
78
+ let originPoint = this . _getOriginConnectionPoint ( originRect , pos . position ) ;
79
+ let overlayPoint = this . _getOverlayPoint ( originPoint , overlayRect , pos . position ) ;
75
80
firstOverlayPoint = firstOverlayPoint || overlayPoint ;
76
81
77
82
// If the overlay in the calculated position fits on-screen, put it there and we're done.
78
83
if ( this . _willOverlayFitWithinViewport ( overlayPoint , overlayRect , viewportRect ) ) {
79
84
this . _setElementPosition ( element , overlayPoint ) ;
85
+ if ( pos . transformOrigin ) {
86
+ this . _setElementTransformOrigin ( element , pos . transformOrigin ) ;
87
+ }
80
88
return Promise . resolve ( null ) ;
81
89
}
82
90
}
@@ -89,8 +97,11 @@ export class ConnectedPositionStrategy implements PositionStrategy {
89
97
90
98
withFallbackPosition (
91
99
originPos : OriginConnectionPosition ,
92
- overlayPos : OverlayConnectionPosition ) : this {
93
- this . _preferredPositions . push ( new ConnectionPositionPair ( originPos , overlayPos ) ) ;
100
+ overlayPos : OverlayConnectionPosition , transformOrigin ?: TransformOrigin ) : this {
101
+ this . _preferredPositions . push ( {
102
+ position : new ConnectionPositionPair ( originPos , overlayPos ) ,
103
+ transformOrigin : transformOrigin
104
+ } ) ;
94
105
return this ;
95
106
}
96
107
@@ -112,6 +123,13 @@ export class ConnectedPositionStrategy implements PositionStrategy {
112
123
return this ;
113
124
}
114
125
126
+ /** Sets a custom transform origin on the element that matches the given selector. */
127
+ withTransformOrigin ( animationRootSelector : string , transformOrigin : TransformOrigin ) : this {
128
+ this . _animationRootSelector = animationRootSelector ;
129
+ this . _preferredPositions [ 0 ] . transformOrigin = transformOrigin ;
130
+ return this ;
131
+ }
132
+
115
133
/**
116
134
* Gets the horizontal (x) "start" dimension based on whether the overlay is in an RTL context.
117
135
* @param rect
@@ -224,10 +242,21 @@ export class ConnectedPositionStrategy implements PositionStrategy {
224
242
// because it will need to be used for animations.
225
243
applyCssTransform ( element , `translateX(${ x } px) translateY(${ y } px)` ) ;
226
244
}
245
+
246
+ /**
247
+ * Sets the transform-origin property on the animation root of the overlay.
248
+ * If the transform-origin provided includes 'start' or 'end', it will be converted to
249
+ * 'left' or 'right' depending on the current text direction.
250
+ */
251
+ private _setElementTransformOrigin ( element : HTMLElement ,
252
+ transformOrigin : TransformOrigin ) : void {
253
+ const animationRoot = element . querySelector ( this . _animationRootSelector ) as HTMLElement ;
254
+ const [ start , end ] = this . _isRtl ? [ 'right' , 'left' ] : [ 'left' , 'right' ] ;
255
+ animationRoot . style . transformOrigin = ( transformOrigin as string ) . replace ( 'start' , start )
256
+ . replace ( 'end' , end ) ;
257
+ }
227
258
}
228
259
229
260
230
261
/** A simple (x, y) coordinate. */
231
262
type Point = { x : number , y : number } ;
232
-
233
-
0 commit comments