@@ -11,7 +11,6 @@ import {
11
11
EventEmitter ,
12
12
Inject ,
13
13
Injectable ,
14
- InjectionToken ,
15
14
Injector ,
16
15
Input ,
17
16
OnDestroy ,
@@ -27,6 +26,7 @@ import {
27
26
Overlay ,
28
27
OverlayConfig ,
29
28
OverlayRef ,
29
+ STANDARD_DROPDOWN_BELOW_POSITIONS ,
30
30
} from '@angular/cdk/overlay' ;
31
31
import { Portal , TemplatePortal } from '@angular/cdk/portal' ;
32
32
import { BooleanInput , coerceBooleanProperty } from '@angular/cdk/coercion' ;
@@ -36,6 +36,14 @@ import {MENU_STACK, MenuStack} from './menu-stack';
36
36
import { isClickInsideMenuOverlay } from './menu-item-trigger' ;
37
37
import { MENU_TRIGGER , MenuTrigger } from './menu-trigger' ;
38
38
39
+ // In cases where the first menu item in the context menu is a trigger the submenu opens on a
40
+ // hover event. We offset the context menu 2px by default to prevent this from occurring.
41
+ const CONTEXT_MENU_POSITIONS = STANDARD_DROPDOWN_BELOW_POSITIONS . map ( position => {
42
+ const offsetX = position . overlayX === 'start' ? 2 : - 2 ;
43
+ const offsetY = position . overlayY === 'top' ? 2 : - 2 ;
44
+ return { ...position , offsetX, offsetY} ;
45
+ } ) ;
46
+
39
47
/** Tracks the last open context menu trigger across the entire application. */
40
48
@Injectable ( { providedIn : 'root' } )
41
49
export class ContextMenuTracker {
@@ -54,20 +62,6 @@ export class ContextMenuTracker {
54
62
}
55
63
}
56
64
57
- /** Configuration options passed to the context menu. */
58
- export type ContextMenuOptions = {
59
- /** The opened menus X coordinate offset from the triggering position. */
60
- offsetX : number ;
61
-
62
- /** The opened menus Y coordinate offset from the triggering position. */
63
- offsetY : number ;
64
- } ;
65
-
66
- /** Injection token for the ContextMenu options object. */
67
- export const CDK_CONTEXT_MENU_DEFAULT_OPTIONS = new InjectionToken < ContextMenuOptions > (
68
- 'cdk-context-menu-default-options' ,
69
- ) ;
70
-
71
65
/** The coordinates of where the context menu should open. */
72
66
export type ContextMenuCoordinates = { x : number ; y : number } ;
73
67
@@ -83,9 +77,6 @@ export type ContextMenuCoordinates = {x: number; y: number};
83
77
'(contextmenu)' : '_openOnContextMenu($event)' ,
84
78
} ,
85
79
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
80
{ provide : MENU_TRIGGER , useExisting : CdkContextMenuTrigger } ,
90
81
{ provide : MENU_STACK , useClass : MenuStack } ,
91
82
] ,
@@ -95,6 +86,9 @@ export class CdkContextMenuTrigger extends MenuTrigger implements OnDestroy {
95
86
@Input ( 'cdkContextMenuTriggerFor' )
96
87
private _menuTemplateRef : TemplateRef < unknown > ;
97
88
89
+ /** A list of preferred menu positions to be used when constructing the `FlexibleConnectedPositionStrategy` for this trigger's menu. */
90
+ @Input ( 'cdkMenuPosition' ) menuPosition : ConnectedPosition [ ] ;
91
+
98
92
/** Emits when the attached menu is requested to open. */
99
93
@Output ( 'cdkContextMenuOpened' ) readonly opened : EventEmitter < void > = new EventEmitter ( ) ;
100
94
@@ -129,7 +123,6 @@ export class CdkContextMenuTrigger extends MenuTrigger implements OnDestroy {
129
123
private readonly _overlay : Overlay ,
130
124
private readonly _contextMenuTracker : ContextMenuTracker ,
131
125
@Inject ( MENU_STACK ) menuStack : MenuStack ,
132
- @Inject ( CDK_CONTEXT_MENU_DEFAULT_OPTIONS ) private readonly _options : ContextMenuOptions ,
133
126
@Optional ( ) private readonly _directionality ?: Directionality ,
134
127
) {
135
128
super ( injector , menuStack ) ;
@@ -233,22 +226,7 @@ export class CdkContextMenuTrigger extends MenuTrigger implements OnDestroy {
233
226
return this . _overlay
234
227
. position ( )
235
228
. 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
- ] ;
229
+ . withPositions ( this . menuPosition ?? CONTEXT_MENU_POSITIONS ) ;
252
230
}
253
231
254
232
/**
0 commit comments