/
context-menu.service.ts
80 lines (69 loc) · 2.89 KB
/
context-menu.service.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
/**
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
*/
import { ConnectionPositionPair, Overlay, OverlayRef } from '@angular/cdk/overlay';
import { TemplatePortal } from '@angular/cdk/portal';
import { Injectable, NgZone } from '@angular/core';
import { fromEvent, Subscription } from 'rxjs';
import { filter, take } from 'rxjs/operators';
import { NzContextMenuServiceModule } from './context-menu.service.module';
import { NzDropdownMenuComponent } from './dropdown-menu.component';
const listOfPositions = [
new ConnectionPositionPair({ originX: 'start', originY: 'top' }, { overlayX: 'start', overlayY: 'top' }),
new ConnectionPositionPair({ originX: 'start', originY: 'top' }, { overlayX: 'start', overlayY: 'bottom' }),
new ConnectionPositionPair({ originX: 'start', originY: 'top' }, { overlayX: 'end', overlayY: 'bottom' }),
new ConnectionPositionPair({ originX: 'start', originY: 'top' }, { overlayX: 'end', overlayY: 'top' })
];
@Injectable({
providedIn: NzContextMenuServiceModule
})
export class NzContextMenuService {
private overlayRef: OverlayRef | null = null;
private closeSubscription = Subscription.EMPTY;
constructor(private ngZone: NgZone, private overlay: Overlay) {}
create($event: MouseEvent | { x: number; y: number }, nzDropdownMenuComponent: NzDropdownMenuComponent): void {
this.close(true);
const { x, y } = $event;
if ($event instanceof MouseEvent) {
$event.preventDefault();
}
const positionStrategy = this.overlay
.position()
.flexibleConnectedTo({ x, y })
.withPositions(listOfPositions)
.withTransformOriginOn('.ant-dropdown');
this.overlayRef = this.overlay.create({
positionStrategy,
disposeOnNavigation: true,
scrollStrategy: this.overlay.scrollStrategies.close()
});
this.closeSubscription = new Subscription();
this.closeSubscription.add(nzDropdownMenuComponent.descendantMenuItemClick$.subscribe(() => this.close()));
this.closeSubscription.add(
this.ngZone.runOutsideAngular(() =>
fromEvent<MouseEvent>(document, 'click')
.pipe(
filter(event => !!this.overlayRef && !this.overlayRef.overlayElement.contains(event.target as HTMLElement)),
/** handle firefox contextmenu event **/
filter(event => event.button !== 2),
take(1)
)
.subscribe(() => this.ngZone.run(() => this.close()))
)
);
this.overlayRef.attach(
new TemplatePortal(nzDropdownMenuComponent.templateRef, nzDropdownMenuComponent.viewContainerRef)
);
}
close(clear: boolean = false): void {
if (this.overlayRef) {
this.overlayRef.detach();
if (clear) {
this.overlayRef.dispose();
}
this.overlayRef = null;
this.closeSubscription.unsubscribe();
}
}
}