@@ -6,12 +6,11 @@ import {
66 FlexibleConnectedPositionStrategy ,
77 Overlay ,
88 OverlayOutsideClickDispatcher ,
9- OverlayRef ,
10- PositionStrategy
9+ OverlayRef
1110} from '@angular/cdk/overlay' ;
1211import { ComponentPortal } from '@angular/cdk/portal' ;
13- import { ElementRef , inject , Injectable , Injector , signal , DOCUMENT } from '@angular/core' ;
14- import { makeOverlay , makePositionStrategy } from '@siemens/element-ng/common' ;
12+ import { DOCUMENT , ElementRef , inject , Injectable , Injector , signal } from '@angular/core' ;
13+ import { isRTL } from '@siemens/element-ng/common' ;
1514import { ResizeObserverService } from '@siemens/element-ng/resize-observer' ;
1615import { map , merge , Subject , Subscription , tap , throttleTime } from 'rxjs' ;
1716
@@ -145,7 +144,11 @@ export class SiTourService {
145144 ? new ElementRef ( anchorElement ! )
146145 : undefined ;
147146
148- this . makeOverlay ( anchorElementRef ) ;
147+ if ( anchorElementRef ) {
148+ this . attachOverlay ( anchorElementRef ) ;
149+ } else {
150+ this . centerOverlay ( ) ;
151+ }
149152 this . handleResizeSubscription ( anchorElementRef ) ;
150153
151154 this . tourToken . currentStep . next ( {
@@ -179,12 +182,57 @@ export class SiTourService {
179182 }
180183 }
181184
182- private makeOverlay ( anchorElement : ElementRef < HTMLElement > | undefined ) : void {
183- const strategy = makePositionStrategy ( anchorElement , this . overlay , 'auto' ) ;
184- this . handlePositionChangeSubscription ( strategy , anchorElement ) ;
185+ private centerOverlay ( ) : void {
186+ this . positionChangeSub ?. unsubscribe ( ) ;
187+ this . createOverlays ( ) ;
188+
189+ const positionStrategy = this . overlayRef ! . getConfig ( ) . positionStrategy ;
190+ if ( ! positionStrategy || positionStrategy instanceof FlexibleConnectedPositionStrategy ) {
191+ this . overlayRef ! . updatePositionStrategy (
192+ this . overlay . position ( ) . global ( ) . centerHorizontally ( ) . centerVertically ( )
193+ ) ;
194+ }
195+ this . tourToken . positionChange . next ( undefined ) ;
196+ }
197+
198+ private attachOverlay ( anchor : ElementRef < HTMLElement > ) : void {
199+ this . createOverlays ( ) ;
200+
201+ const positionStrategy = this . overlayRef ! . getConfig ( ) . positionStrategy ;
202+ if ( positionStrategy && positionStrategy instanceof FlexibleConnectedPositionStrategy ) {
203+ positionStrategy . setOrigin ( anchor ) ;
204+ } else {
205+ this . createFlexiblePositionStrategy ( anchor ) ;
206+ }
207+ }
185208
209+ private createFlexiblePositionStrategy ( anchor : ElementRef < HTMLElement > ) : void {
210+ const positionStrategy = this . overlay
211+ . position ( )
212+ . flexibleConnectedTo ( anchor )
213+ . withGrowAfterOpen ( true )
214+ . withPositions ( [
215+ // On top
216+ { originX : 'center' , overlayX : 'center' , originY : 'top' , overlayY : 'bottom' } ,
217+ { originX : 'start' , overlayX : 'start' , originY : 'top' , overlayY : 'bottom' } ,
218+ { originX : 'end' , overlayX : 'end' , originY : 'top' , overlayY : 'bottom' } ,
219+ // On bottom
220+ { originX : 'center' , overlayX : 'center' , originY : 'bottom' , overlayY : 'top' } ,
221+ { originX : 'start' , overlayX : 'start' , originY : 'bottom' , overlayY : 'top' } ,
222+ { originX : 'end' , overlayX : 'end' , originY : 'bottom' , overlayY : 'top' } ,
223+ // Left and right
224+ { originX : 'start' , overlayX : 'end' , originY : 'center' , overlayY : 'center' } ,
225+ { originX : 'end' , overlayX : 'start' , originY : 'center' , overlayY : 'center' }
226+ ] ) ;
227+ this . overlayRef ! . updatePositionStrategy ( positionStrategy ) ;
228+ this . positionChangeSub = positionStrategy . positionChanges
229+ . pipe ( map ( change => ( { change, anchor } ) ) )
230+ // We only want to forward the next channel, as the positionChanges completes when setting a new origin.
231+ . subscribe ( value => this . tourToken . positionChange . next ( value ) ) ;
232+ }
233+
234+ private createOverlays ( ) : void {
186235 if ( this . overlayRef ) {
187- this . overlayRef . updatePositionStrategy ( strategy ) ;
188236 // This moves the dispatcher to the top, allowing it to catch other open overlays.
189237 // Much lighter than to detach and re-attach the portal, not re-creating the si-tour
190238 // component for each step
@@ -207,10 +255,13 @@ export class SiTourService {
207255
208256 // then the dialog
209257 this . portal = new ComponentPortal ( SiTourComponent , undefined , componentInjector ) ;
210- this . overlayRef = makeOverlay ( strategy , this . overlay , true ) ;
258+ this . overlayRef = this . overlay . create ( {
259+ scrollStrategy : this . overlay . scrollStrategies . reposition ( ) ,
260+ direction : isRTL ( ) ? 'rtl' : 'ltr'
261+ } ) ;
262+ this . overlayRef . attach ( this . portal ) ;
211263 // needs a subscriber, otherwise events will be ignored and the .backdrop CSS hack doesn't help
212264 this . overlayRef . outsidePointerEvents ( ) . subscribe ( ) ;
213- this . overlayRef . attach ( this . portal ) ;
214265 }
215266
216267 private handleResizeSubscription ( anchorElement : ElementRef < HTMLElement > | undefined ) : void {
@@ -228,7 +279,7 @@ export class SiTourService {
228279 tap ( ( ) => {
229280 if ( ! this . isElementVisible ( anchorElement ?. nativeElement ) ) {
230281 // repositions to center if anchor disappears
231- this . makeOverlay ( undefined ) ;
282+ this . centerOverlay ( ) ;
232283 } else {
233284 this . overlayRef ?. updatePosition ( ) ;
234285 }
@@ -243,20 +294,6 @@ export class SiTourService {
243294 return ! ! rect ?. width && ! ! rect . height ;
244295 }
245296
246- private handlePositionChangeSubscription (
247- strategy : PositionStrategy ,
248- anchor ?: ElementRef < HTMLElement >
249- ) : void {
250- this . positionChangeSub ?. unsubscribe ( ) ;
251- if ( anchor && strategy instanceof FlexibleConnectedPositionStrategy ) {
252- this . positionChangeSub = strategy . positionChanges
253- . pipe ( map ( change => ( { change, anchor } ) ) )
254- . subscribe ( this . tourToken . positionChange ) ;
255- } else {
256- this . tourToken . positionChange . next ( undefined ) ;
257- }
258- }
259-
260297 private getElement (
261298 selectorOrElement ?: string | HTMLElement | ( ( ) => string | HTMLElement )
262299 ) : HTMLElement | undefined {
0 commit comments