@@ -57,10 +57,13 @@ export class ContextMenuTracker {
57
57
/** Configuration options passed to the context menu. */
58
58
export type ContextMenuOptions = {
59
59
/** The opened menus X coordinate offset from the triggering position. */
60
- offsetX : number ;
60
+ offsetX ? : number ;
61
61
62
62
/** The opened menus Y coordinate offset from the triggering position. */
63
- offsetY : number ;
63
+ offsetY ?: number ;
64
+
65
+ /** Ordered list of preferred positions, from most to least desirable. */
66
+ preferredPositions ?: ConnectedPosition [ ] ;
64
67
} ;
65
68
66
69
/** Injection token for the ContextMenu options object. */
@@ -83,9 +86,6 @@ export type ContextMenuCoordinates = {x: number; y: number};
83
86
'(contextmenu)' : '_openOnContextMenu($event)' ,
84
87
} ,
85
88
providers : [
86
- // In cases where the first menu item in the context menu is a trigger the submenu opens on a
87
- // hover event. Offsetting the opened context menu by 2px prevents this from occurring.
88
- { provide : CDK_CONTEXT_MENU_DEFAULT_OPTIONS , useValue : { offsetX : 2 , offsetY : 2 } } ,
89
89
{ provide : MENU_TRIGGER , useExisting : CdkContextMenuTrigger } ,
90
90
{ provide : MENU_STACK , useClass : MenuStack } ,
91
91
] ,
@@ -129,7 +129,9 @@ export class CdkContextMenuTrigger extends MenuTrigger implements OnDestroy {
129
129
private readonly _overlay : Overlay ,
130
130
private readonly _contextMenuTracker : ContextMenuTracker ,
131
131
@Inject ( MENU_STACK ) menuStack : MenuStack ,
132
- @Inject ( CDK_CONTEXT_MENU_DEFAULT_OPTIONS ) private readonly _options : ContextMenuOptions ,
132
+ @Optional ( )
133
+ @Inject ( CDK_CONTEXT_MENU_DEFAULT_OPTIONS )
134
+ private readonly _options ?: ContextMenuOptions ,
133
135
@Optional ( ) private readonly _directionality ?: Directionality ,
134
136
) {
135
137
super ( injector , menuStack ) ;
@@ -230,25 +232,21 @@ export class CdkContextMenuTrigger extends MenuTrigger implements OnDestroy {
230
232
private _getOverlayPositionStrategy (
231
233
coordinates : ContextMenuCoordinates ,
232
234
) : FlexibleConnectedPositionStrategy {
235
+ // In cases where the first menu item in the context menu is a trigger the submenu opens on a
236
+ // hover event. We offset the context menu 2px by default to prevent this from occurring.
233
237
return this . _overlay
234
238
. position ( )
235
239
. flexibleConnectedTo ( coordinates )
236
- . withDefaultOffsetX ( this . _options . offsetX )
237
- . withDefaultOffsetY ( this . _options . offsetY )
238
- . withPositions ( this . _getOverlayPositions ( ) ) ;
239
- }
240
-
241
- /**
242
- * Determine and return where to position the opened menu relative to the mouse location.
243
- */
244
- private _getOverlayPositions ( ) : ConnectedPosition [ ] {
245
- // TODO: this should be configurable through the injected context menu options
246
- return [
247
- { originX : 'end' , originY : 'top' , overlayX : 'start' , overlayY : 'top' } ,
248
- { originX : 'start' , originY : 'top' , overlayX : 'end' , overlayY : 'top' } ,
249
- { originX : 'end' , originY : 'bottom' , overlayX : 'start' , overlayY : 'bottom' } ,
250
- { originX : 'start' , originY : 'bottom' , overlayX : 'end' , overlayY : 'bottom' } ,
251
- ] ;
240
+ . withDefaultOffsetX ( this . _options ?. offsetX ?? 2 )
241
+ . withDefaultOffsetY ( this . _options ?. offsetY ?? 2 )
242
+ . withPositions (
243
+ this . _options ?. preferredPositions ?? [
244
+ { originX : 'end' , originY : 'top' , overlayX : 'start' , overlayY : 'top' } ,
245
+ { originX : 'start' , originY : 'top' , overlayX : 'end' , overlayY : 'top' } ,
246
+ { originX : 'end' , originY : 'bottom' , overlayX : 'start' , overlayY : 'bottom' } ,
247
+ { originX : 'start' , originY : 'bottom' , overlayX : 'end' , overlayY : 'bottom' } ,
248
+ ] ,
249
+ ) ;
252
250
}
253
251
254
252
/**
0 commit comments