ngx-mat-menu-hover 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -0
- package/esm2022/lib/mat-menu-hover.directive.mjs +83 -0
- package/esm2022/ngx-mat-menu-hover.mjs +5 -0
- package/esm2022/public-api.mjs +5 -0
- package/fesm2022/ngx-mat-menu-hover.mjs +94 -0
- package/fesm2022/ngx-mat-menu-hover.mjs.map +1 -0
- package/index.d.ts +5 -0
- package/lib/mat-menu-hover.directive.d.ts +29 -0
- package/package.json +26 -0
- package/public-api.d.ts +1 -0
package/README.md
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# mat-menu-hover - An Angular Material directive
|
|
2
|
+
This Angular directive provides functionality to handle hover menu behavior, allowing menus to open when hovered over and close when the mouse leaves.
|
|
3
|
+
|
|
4
|
+
## Installation
|
|
5
|
+
|
|
6
|
+
npm install mat-menu-hover@latest
|
|
7
|
+
|
|
8
|
+
Since the directive is marked as standalone you can directly import it into a module.
|
|
9
|
+
|
|
10
|
+
import { NgModule } from '@angular/core';
|
|
11
|
+
import { HoverMenuDirective } from 'mat-menu-hover';
|
|
12
|
+
|
|
13
|
+
@NgModule({
|
|
14
|
+
declarations: [...],
|
|
15
|
+
imports: [
|
|
16
|
+
HoverMenuDirective
|
|
17
|
+
],
|
|
18
|
+
exports: [...]
|
|
19
|
+
})
|
|
20
|
+
export class AppModule { }
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
|
|
24
|
+
<button mat-button [matMenuTriggerFor]="menu" matHoverMenu>Menu</button>
|
|
25
|
+
<mat-menu #menu="matMenu">
|
|
26
|
+
<!-- Menu content goes here -->
|
|
27
|
+
</mat-menu>
|
|
28
|
+
|
|
29
|
+
## Optional inputs/outputs
|
|
30
|
+
|Keyword |Function |Note |
|
|
31
|
+
|------------|-----------------------------------|--------------|
|
|
32
|
+
|[closeDelay]|Adds a delay before the menu closed|Default = 50ms|
|
|
33
|
+
|(opened) |Emits if the menu is opened/closed | |
|
|
34
|
+
|
|
35
|
+
## Known issues
|
|
36
|
+
- Currently it is not possible to nest menus. It will only work with single-level mat-menus.
|
|
37
|
+
|
|
38
|
+
## License
|
|
39
|
+
This project is licensed under the MIT License - see the LICENSE file for details.
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { DestroyRef, Directive, EventEmitter, HostListener, Input, Output, Self, inject } from '@angular/core';
|
|
2
|
+
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
3
|
+
import { BehaviorSubject, filter, fromEvent, mergeMap, tap } from 'rxjs';
|
|
4
|
+
import * as i0 from "@angular/core";
|
|
5
|
+
import * as i1 from "@angular/material/menu";
|
|
6
|
+
/**
|
|
7
|
+
* Directive to handle hover menu behavior.
|
|
8
|
+
*/
|
|
9
|
+
export class MatMenuHoverDirective {
|
|
10
|
+
onMouseEnter() {
|
|
11
|
+
this.openMenu();
|
|
12
|
+
// Get the menu element by ID and emit it to the observable
|
|
13
|
+
const element = document.querySelector(`#${this.menu.panelId}`);
|
|
14
|
+
if (element) {
|
|
15
|
+
this.menuElement$.next(element);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
onMouseLeave() {
|
|
19
|
+
this.closeMenu();
|
|
20
|
+
}
|
|
21
|
+
constructor(matMenuTrigger) {
|
|
22
|
+
this.matMenuTrigger = matMenuTrigger;
|
|
23
|
+
this.destroyRef = inject(DestroyRef);
|
|
24
|
+
this.menuElement$ = new BehaviorSubject(null); // Observable for menu element
|
|
25
|
+
/**
|
|
26
|
+
* Delay (in milliseconds) before closing the menu after mouseleave.
|
|
27
|
+
*/
|
|
28
|
+
this.closeDelay = 50; // Delay before closing the menu on mouseleave
|
|
29
|
+
/**
|
|
30
|
+
* Event emitter for notifying when the menu is opened.
|
|
31
|
+
*/
|
|
32
|
+
this.opened = new EventEmitter();
|
|
33
|
+
}
|
|
34
|
+
ngOnInit() {
|
|
35
|
+
// Ensure MatMenuTrigger is present
|
|
36
|
+
if (!this.matMenuTrigger) {
|
|
37
|
+
console.error('There must be a MatMenuTrigger present.');
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
// Assign the menu and disable backdrop
|
|
41
|
+
this.menu = this.matMenuTrigger.menu;
|
|
42
|
+
this.menu.hasBackdrop = false;
|
|
43
|
+
// Subscribe to mouseleave event on the menu element to close the menu
|
|
44
|
+
this.menuElement$.pipe(takeUntilDestroyed(this.destroyRef), filter(element => !!element), mergeMap(element => fromEvent(element, 'mouseleave')), tap(() => this.closeMenu()))
|
|
45
|
+
.subscribe();
|
|
46
|
+
// Subscribe to mouseenter event on the menu element to open the menu
|
|
47
|
+
this.menuElement$.pipe(takeUntilDestroyed(this.destroyRef), filter(element => !!element), mergeMap(element => fromEvent(element, 'mouseenter')), tap(() => this.openMenu()))
|
|
48
|
+
.subscribe();
|
|
49
|
+
}
|
|
50
|
+
closeMenu() {
|
|
51
|
+
this.closer = setTimeout(() => {
|
|
52
|
+
this.matMenuTrigger.closeMenu();
|
|
53
|
+
}, this.closeDelay);
|
|
54
|
+
}
|
|
55
|
+
openMenu() {
|
|
56
|
+
if (this.closer) {
|
|
57
|
+
clearTimeout(this.closer);
|
|
58
|
+
}
|
|
59
|
+
this.matMenuTrigger.openMenu();
|
|
60
|
+
}
|
|
61
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.1", ngImport: i0, type: MatMenuHoverDirective, deps: [{ token: i1.MatMenuTrigger, self: true }], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
62
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.2.1", type: MatMenuHoverDirective, isStandalone: true, selector: "[matHoverMenu]", inputs: { closeDelay: "closeDelay" }, outputs: { opened: "opened" }, host: { listeners: { "mouseenter": "onMouseEnter()", "mouseleave": "onMouseLeave()" } }, ngImport: i0 }); }
|
|
63
|
+
}
|
|
64
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.1", ngImport: i0, type: MatMenuHoverDirective, decorators: [{
|
|
65
|
+
type: Directive,
|
|
66
|
+
args: [{
|
|
67
|
+
selector: '[matHoverMenu]',
|
|
68
|
+
standalone: true
|
|
69
|
+
}]
|
|
70
|
+
}], ctorParameters: () => [{ type: i1.MatMenuTrigger, decorators: [{
|
|
71
|
+
type: Self
|
|
72
|
+
}] }], propDecorators: { closeDelay: [{
|
|
73
|
+
type: Input
|
|
74
|
+
}], opened: [{
|
|
75
|
+
type: Output
|
|
76
|
+
}], onMouseEnter: [{
|
|
77
|
+
type: HostListener,
|
|
78
|
+
args: ['mouseenter']
|
|
79
|
+
}], onMouseLeave: [{
|
|
80
|
+
type: HostListener,
|
|
81
|
+
args: ['mouseleave']
|
|
82
|
+
}] } });
|
|
83
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWF0LW1lbnUtaG92ZXIuZGlyZWN0aXZlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvbWF0LW1lbnUtaG92ZXIvc3JjL2xpYi9tYXQtbWVudS1ob3Zlci5kaXJlY3RpdmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFLFlBQVksRUFBRSxLQUFLLEVBQVUsTUFBTSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDdkgsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFFaEUsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLFFBQVEsRUFBRSxHQUFHLEVBQUUsTUFBTSxNQUFNLENBQUM7OztBQUV6RTs7R0FFRztBQUtILE1BQU0sT0FBTyxxQkFBcUI7SUFpQmhDLFlBQVk7UUFDVixJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7UUFFaEIsMkRBQTJEO1FBQzNELE1BQU0sT0FBTyxHQUFHLFFBQVEsQ0FBQyxhQUFhLENBQUMsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFtQixDQUFDO1FBQ2xGLElBQUksT0FBTyxFQUFFLENBQUM7WUFDWixJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNsQyxDQUFDO0lBQ0gsQ0FBQztJQUdELFlBQVk7UUFDVixJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7SUFDbkIsQ0FBQztJQUVELFlBQTRCLGNBQThCO1FBQTlCLG1CQUFjLEdBQWQsY0FBYyxDQUFnQjtRQS9CbEQsZUFBVSxHQUFHLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUVoQyxpQkFBWSxHQUFHLElBQUksZUFBZSxDQUFpQixJQUFJLENBQUMsQ0FBQyxDQUFDLDhCQUE4QjtRQUdoRzs7VUFFRTtRQUNPLGVBQVUsR0FBRyxFQUFFLENBQUMsQ0FBQyw4Q0FBOEM7UUFFeEU7O1NBRUM7UUFDUyxXQUFNLEdBQUcsSUFBSSxZQUFZLEVBQVcsQ0FBQztJQWtCZSxDQUFDO0lBRS9ELFFBQVE7UUFDTixtQ0FBbUM7UUFDbkMsSUFBSSxDQUFDLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztZQUN6QixPQUFPLENBQUMsS0FBSyxDQUFDLHlDQUF5QyxDQUFDLENBQUM7WUFDekQsT0FBTztRQUNULENBQUM7UUFFRCx1Q0FBdUM7UUFDdkMsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQztRQUNyQyxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsR0FBRyxLQUFLLENBQUM7UUFFOUIsc0VBQXNFO1FBQ3RFLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUNwQixrQkFBa0IsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLEVBQ25DLE1BQU0sQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsRUFDNUIsUUFBUSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLE9BQU8sRUFBRSxZQUFZLENBQUMsQ0FBQyxFQUNyRCxHQUFHLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDLENBQzVCO2FBQ0UsU0FBUyxFQUFFLENBQUM7UUFFZixxRUFBcUU7UUFDckUsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQ3BCLGtCQUFrQixDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsRUFDbkMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxFQUM1QixRQUFRLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMsT0FBTyxFQUFFLFlBQVksQ0FBQyxDQUFDLEVBQ3JELEdBQUcsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FDM0I7YUFDRSxTQUFTLEVBQUUsQ0FBQztJQUNqQixDQUFDO0lBRU8sU0FBUztRQUNmLElBQUksQ0FBQyxNQUFNLEdBQUcsVUFBVSxDQUFDLEdBQUcsRUFBRTtZQUM1QixJQUFJLENBQUMsY0FBYyxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBQ2xDLENBQUMsRUFBRSxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDdEIsQ0FBQztJQUVPLFFBQVE7UUFDZCxJQUFJLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNoQixZQUFZLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQzVCLENBQUM7UUFFRCxJQUFJLENBQUMsY0FBYyxDQUFDLFFBQVEsRUFBRSxDQUFDO0lBQ2pDLENBQUM7OEdBNUVVLHFCQUFxQjtrR0FBckIscUJBQXFCOzsyRkFBckIscUJBQXFCO2tCQUpqQyxTQUFTO21CQUFDO29CQUNULFFBQVEsRUFBRSxnQkFBZ0I7b0JBQzFCLFVBQVUsRUFBRSxJQUFJO2lCQUNqQjs7MEJBaUNjLElBQUk7eUNBdkJSLFVBQVU7c0JBQWxCLEtBQUs7Z0JBS0ksTUFBTTtzQkFBZixNQUFNO2dCQUdQLFlBQVk7c0JBRFgsWUFBWTt1QkFBQyxZQUFZO2dCQVkxQixZQUFZO3NCQURYLFlBQVk7dUJBQUMsWUFBWSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IERlc3Ryb3lSZWYsIERpcmVjdGl2ZSwgRXZlbnRFbWl0dGVyLCBIb3N0TGlzdGVuZXIsIElucHV0LCBPbkluaXQsIE91dHB1dCwgU2VsZiwgaW5qZWN0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IHRha2VVbnRpbERlc3Ryb3llZCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUvcnhqcy1pbnRlcm9wJztcclxuaW1wb3J0IHsgTWF0TWVudVBhbmVsLCBNYXRNZW51VHJpZ2dlciB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL21lbnUnO1xyXG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QsIGZpbHRlciwgZnJvbUV2ZW50LCBtZXJnZU1hcCwgdGFwIH0gZnJvbSAncnhqcyc7XHJcblxyXG4vKipcclxuICogRGlyZWN0aXZlIHRvIGhhbmRsZSBob3ZlciBtZW51IGJlaGF2aW9yLlxyXG4gKi9cclxuQERpcmVjdGl2ZSh7XHJcbiAgc2VsZWN0b3I6ICdbbWF0SG92ZXJNZW51XScsXHJcbiAgc3RhbmRhbG9uZTogdHJ1ZVxyXG59KVxyXG5leHBvcnQgY2xhc3MgTWF0TWVudUhvdmVyRGlyZWN0aXZlIGltcGxlbWVudHMgT25Jbml0IHtcclxuICBwcml2YXRlIGRlc3Ryb3lSZWYgPSBpbmplY3QoRGVzdHJveVJlZik7XHJcbiAgcHJpdmF0ZSBtZW51OiBNYXRNZW51UGFuZWw8YW55PjsgLy8gUmVmZXJlbmNlIHRvIHRoZSBNYXRNZW51UGFuZWxcclxuICBwcml2YXRlIG1lbnVFbGVtZW50JCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8SFRNTERpdkVsZW1lbnQ+KG51bGwpOyAvLyBPYnNlcnZhYmxlIGZvciBtZW51IGVsZW1lbnRcclxuICBwcml2YXRlIGNsb3NlcjogYW55O1xyXG5cclxuICAvKipcclxuICAqIERlbGF5IChpbiBtaWxsaXNlY29uZHMpIGJlZm9yZSBjbG9zaW5nIHRoZSBtZW51IGFmdGVyIG1vdXNlbGVhdmUuXHJcbiAgKi9cclxuICBASW5wdXQoKSBjbG9zZURlbGF5ID0gNTA7IC8vIERlbGF5IGJlZm9yZSBjbG9zaW5nIHRoZSBtZW51IG9uIG1vdXNlbGVhdmVcclxuXHJcbiAgLyoqXHJcbiAqIEV2ZW50IGVtaXR0ZXIgZm9yIG5vdGlmeWluZyB3aGVuIHRoZSBtZW51IGlzIG9wZW5lZC5cclxuICovXHJcbiAgQE91dHB1dCgpIG9wZW5lZCA9IG5ldyBFdmVudEVtaXR0ZXI8Ym9vbGVhbj4oKTtcclxuXHJcbiAgQEhvc3RMaXN0ZW5lcignbW91c2VlbnRlcicpXHJcbiAgb25Nb3VzZUVudGVyKCk6IHZvaWQge1xyXG4gICAgdGhpcy5vcGVuTWVudSgpO1xyXG5cclxuICAgIC8vIEdldCB0aGUgbWVudSBlbGVtZW50IGJ5IElEIGFuZCBlbWl0IGl0IHRvIHRoZSBvYnNlcnZhYmxlXHJcbiAgICBjb25zdCBlbGVtZW50ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihgIyR7dGhpcy5tZW51LnBhbmVsSWR9YCkgYXMgSFRNTERpdkVsZW1lbnQ7XHJcbiAgICBpZiAoZWxlbWVudCkge1xyXG4gICAgICB0aGlzLm1lbnVFbGVtZW50JC5uZXh0KGVsZW1lbnQpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgQEhvc3RMaXN0ZW5lcignbW91c2VsZWF2ZScpXHJcbiAgb25Nb3VzZUxlYXZlKCk6IHZvaWQge1xyXG4gICAgdGhpcy5jbG9zZU1lbnUoKTtcclxuICB9XHJcblxyXG4gIGNvbnN0cnVjdG9yKEBTZWxmKCkgcHJpdmF0ZSBtYXRNZW51VHJpZ2dlcjogTWF0TWVudVRyaWdnZXIpIHsgfVxyXG5cclxuICBuZ09uSW5pdCgpOiB2b2lkIHtcclxuICAgIC8vIEVuc3VyZSBNYXRNZW51VHJpZ2dlciBpcyBwcmVzZW50XHJcbiAgICBpZiAoIXRoaXMubWF0TWVudVRyaWdnZXIpIHtcclxuICAgICAgY29uc29sZS5lcnJvcignVGhlcmUgbXVzdCBiZSBhIE1hdE1lbnVUcmlnZ2VyIHByZXNlbnQuJyk7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICAvLyBBc3NpZ24gdGhlIG1lbnUgYW5kIGRpc2FibGUgYmFja2Ryb3BcclxuICAgIHRoaXMubWVudSA9IHRoaXMubWF0TWVudVRyaWdnZXIubWVudTtcclxuICAgIHRoaXMubWVudS5oYXNCYWNrZHJvcCA9IGZhbHNlO1xyXG5cclxuICAgIC8vIFN1YnNjcmliZSB0byBtb3VzZWxlYXZlIGV2ZW50IG9uIHRoZSBtZW51IGVsZW1lbnQgdG8gY2xvc2UgdGhlIG1lbnVcclxuICAgIHRoaXMubWVudUVsZW1lbnQkLnBpcGUoXHJcbiAgICAgIHRha2VVbnRpbERlc3Ryb3llZCh0aGlzLmRlc3Ryb3lSZWYpLFxyXG4gICAgICBmaWx0ZXIoZWxlbWVudCA9PiAhIWVsZW1lbnQpLFxyXG4gICAgICBtZXJnZU1hcChlbGVtZW50ID0+IGZyb21FdmVudChlbGVtZW50LCAnbW91c2VsZWF2ZScpKSxcclxuICAgICAgdGFwKCgpID0+IHRoaXMuY2xvc2VNZW51KCkpXHJcbiAgICApXHJcbiAgICAgIC5zdWJzY3JpYmUoKTtcclxuXHJcbiAgICAvLyBTdWJzY3JpYmUgdG8gbW91c2VlbnRlciBldmVudCBvbiB0aGUgbWVudSBlbGVtZW50IHRvIG9wZW4gdGhlIG1lbnVcclxuICAgIHRoaXMubWVudUVsZW1lbnQkLnBpcGUoXHJcbiAgICAgIHRha2VVbnRpbERlc3Ryb3llZCh0aGlzLmRlc3Ryb3lSZWYpLFxyXG4gICAgICBmaWx0ZXIoZWxlbWVudCA9PiAhIWVsZW1lbnQpLFxyXG4gICAgICBtZXJnZU1hcChlbGVtZW50ID0+IGZyb21FdmVudChlbGVtZW50LCAnbW91c2VlbnRlcicpKSxcclxuICAgICAgdGFwKCgpID0+IHRoaXMub3Blbk1lbnUoKSlcclxuICAgIClcclxuICAgICAgLnN1YnNjcmliZSgpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBjbG9zZU1lbnUoKTogdm9pZCB7XHJcbiAgICB0aGlzLmNsb3NlciA9IHNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICB0aGlzLm1hdE1lbnVUcmlnZ2VyLmNsb3NlTWVudSgpO1xyXG4gICAgfSwgdGhpcy5jbG9zZURlbGF5KTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgb3Blbk1lbnUoKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy5jbG9zZXIpIHtcclxuICAgICAgY2xlYXJUaW1lb3V0KHRoaXMuY2xvc2VyKTtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLm1hdE1lbnVUcmlnZ2VyLm9wZW5NZW51KCk7XHJcbiAgfVxyXG59XHJcblxyXG4iXX0=
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generated bundle index. Do not edit.
|
|
3
|
+
*/
|
|
4
|
+
export * from './public-api';
|
|
5
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LW1hdC1tZW51LWhvdmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vcHJvamVjdHMvbWF0LW1lbnUtaG92ZXIvc3JjL25neC1tYXQtbWVudS1ob3Zlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7R0FFRztBQUVILGNBQWMsY0FBYyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBHZW5lcmF0ZWQgYnVuZGxlIGluZGV4LiBEbyBub3QgZWRpdC5cbiAqL1xuXG5leHBvcnQgKiBmcm9tICcuL3B1YmxpYy1hcGknO1xuIl19
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Public API Surface of mat-menu-hover
|
|
3
|
+
*/
|
|
4
|
+
export * from './lib/mat-menu-hover.directive';
|
|
5
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHVibGljLWFwaS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Byb2plY3RzL21hdC1tZW51LWhvdmVyL3NyYy9wdWJsaWMtYXBpLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBRUgsY0FBYyxnQ0FBZ0MsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qXHJcbiAqIFB1YmxpYyBBUEkgU3VyZmFjZSBvZiBtYXQtbWVudS1ob3ZlclxyXG4gKi9cclxuXHJcbmV4cG9ydCAqIGZyb20gJy4vbGliL21hdC1tZW51LWhvdmVyLmRpcmVjdGl2ZSc7XHJcblxyXG4iXX0=
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { inject, DestroyRef, EventEmitter, Directive, Self, Input, Output, HostListener } from '@angular/core';
|
|
3
|
+
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
4
|
+
import { BehaviorSubject, filter, mergeMap, fromEvent, tap } from 'rxjs';
|
|
5
|
+
import * as i1 from '@angular/material/menu';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Directive to handle hover menu behavior.
|
|
9
|
+
*/
|
|
10
|
+
class MatMenuHoverDirective {
|
|
11
|
+
onMouseEnter() {
|
|
12
|
+
this.openMenu();
|
|
13
|
+
// Get the menu element by ID and emit it to the observable
|
|
14
|
+
const element = document.querySelector(`#${this.menu.panelId}`);
|
|
15
|
+
if (element) {
|
|
16
|
+
this.menuElement$.next(element);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
onMouseLeave() {
|
|
20
|
+
this.closeMenu();
|
|
21
|
+
}
|
|
22
|
+
constructor(matMenuTrigger) {
|
|
23
|
+
this.matMenuTrigger = matMenuTrigger;
|
|
24
|
+
this.destroyRef = inject(DestroyRef);
|
|
25
|
+
this.menuElement$ = new BehaviorSubject(null); // Observable for menu element
|
|
26
|
+
/**
|
|
27
|
+
* Delay (in milliseconds) before closing the menu after mouseleave.
|
|
28
|
+
*/
|
|
29
|
+
this.closeDelay = 50; // Delay before closing the menu on mouseleave
|
|
30
|
+
/**
|
|
31
|
+
* Event emitter for notifying when the menu is opened.
|
|
32
|
+
*/
|
|
33
|
+
this.opened = new EventEmitter();
|
|
34
|
+
}
|
|
35
|
+
ngOnInit() {
|
|
36
|
+
// Ensure MatMenuTrigger is present
|
|
37
|
+
if (!this.matMenuTrigger) {
|
|
38
|
+
console.error('There must be a MatMenuTrigger present.');
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
// Assign the menu and disable backdrop
|
|
42
|
+
this.menu = this.matMenuTrigger.menu;
|
|
43
|
+
this.menu.hasBackdrop = false;
|
|
44
|
+
// Subscribe to mouseleave event on the menu element to close the menu
|
|
45
|
+
this.menuElement$.pipe(takeUntilDestroyed(this.destroyRef), filter(element => !!element), mergeMap(element => fromEvent(element, 'mouseleave')), tap(() => this.closeMenu()))
|
|
46
|
+
.subscribe();
|
|
47
|
+
// Subscribe to mouseenter event on the menu element to open the menu
|
|
48
|
+
this.menuElement$.pipe(takeUntilDestroyed(this.destroyRef), filter(element => !!element), mergeMap(element => fromEvent(element, 'mouseenter')), tap(() => this.openMenu()))
|
|
49
|
+
.subscribe();
|
|
50
|
+
}
|
|
51
|
+
closeMenu() {
|
|
52
|
+
this.closer = setTimeout(() => {
|
|
53
|
+
this.matMenuTrigger.closeMenu();
|
|
54
|
+
}, this.closeDelay);
|
|
55
|
+
}
|
|
56
|
+
openMenu() {
|
|
57
|
+
if (this.closer) {
|
|
58
|
+
clearTimeout(this.closer);
|
|
59
|
+
}
|
|
60
|
+
this.matMenuTrigger.openMenu();
|
|
61
|
+
}
|
|
62
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.1", ngImport: i0, type: MatMenuHoverDirective, deps: [{ token: i1.MatMenuTrigger, self: true }], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
63
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.2.1", type: MatMenuHoverDirective, isStandalone: true, selector: "[matHoverMenu]", inputs: { closeDelay: "closeDelay" }, outputs: { opened: "opened" }, host: { listeners: { "mouseenter": "onMouseEnter()", "mouseleave": "onMouseLeave()" } }, ngImport: i0 }); }
|
|
64
|
+
}
|
|
65
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.1", ngImport: i0, type: MatMenuHoverDirective, decorators: [{
|
|
66
|
+
type: Directive,
|
|
67
|
+
args: [{
|
|
68
|
+
selector: '[matHoverMenu]',
|
|
69
|
+
standalone: true
|
|
70
|
+
}]
|
|
71
|
+
}], ctorParameters: () => [{ type: i1.MatMenuTrigger, decorators: [{
|
|
72
|
+
type: Self
|
|
73
|
+
}] }], propDecorators: { closeDelay: [{
|
|
74
|
+
type: Input
|
|
75
|
+
}], opened: [{
|
|
76
|
+
type: Output
|
|
77
|
+
}], onMouseEnter: [{
|
|
78
|
+
type: HostListener,
|
|
79
|
+
args: ['mouseenter']
|
|
80
|
+
}], onMouseLeave: [{
|
|
81
|
+
type: HostListener,
|
|
82
|
+
args: ['mouseleave']
|
|
83
|
+
}] } });
|
|
84
|
+
|
|
85
|
+
/*
|
|
86
|
+
* Public API Surface of mat-menu-hover
|
|
87
|
+
*/
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Generated bundle index. Do not edit.
|
|
91
|
+
*/
|
|
92
|
+
|
|
93
|
+
export { MatMenuHoverDirective };
|
|
94
|
+
//# sourceMappingURL=ngx-mat-menu-hover.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ngx-mat-menu-hover.mjs","sources":["../../../projects/mat-menu-hover/src/lib/mat-menu-hover.directive.ts","../../../projects/mat-menu-hover/src/public-api.ts","../../../projects/mat-menu-hover/src/ngx-mat-menu-hover.ts"],"sourcesContent":["import { DestroyRef, Directive, EventEmitter, HostListener, Input, OnInit, Output, Self, inject } from '@angular/core';\r\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\r\nimport { MatMenuPanel, MatMenuTrigger } from '@angular/material/menu';\r\nimport { BehaviorSubject, filter, fromEvent, mergeMap, tap } from 'rxjs';\r\n\r\n/**\r\n * Directive to handle hover menu behavior.\r\n */\r\n@Directive({\r\n selector: '[matHoverMenu]',\r\n standalone: true\r\n})\r\nexport class MatMenuHoverDirective implements OnInit {\r\n private destroyRef = inject(DestroyRef);\r\n private menu: MatMenuPanel<any>; // Reference to the MatMenuPanel\r\n private menuElement$ = new BehaviorSubject<HTMLDivElement>(null); // Observable for menu element\r\n private closer: any;\r\n\r\n /**\r\n * Delay (in milliseconds) before closing the menu after mouseleave.\r\n */\r\n @Input() closeDelay = 50; // Delay before closing the menu on mouseleave\r\n\r\n /**\r\n * Event emitter for notifying when the menu is opened.\r\n */\r\n @Output() opened = new EventEmitter<boolean>();\r\n\r\n @HostListener('mouseenter')\r\n onMouseEnter(): void {\r\n this.openMenu();\r\n\r\n // Get the menu element by ID and emit it to the observable\r\n const element = document.querySelector(`#${this.menu.panelId}`) as HTMLDivElement;\r\n if (element) {\r\n this.menuElement$.next(element);\r\n }\r\n }\r\n\r\n @HostListener('mouseleave')\r\n onMouseLeave(): void {\r\n this.closeMenu();\r\n }\r\n\r\n constructor(@Self() private matMenuTrigger: MatMenuTrigger) { }\r\n\r\n ngOnInit(): void {\r\n // Ensure MatMenuTrigger is present\r\n if (!this.matMenuTrigger) {\r\n console.error('There must be a MatMenuTrigger present.');\r\n return;\r\n }\r\n\r\n // Assign the menu and disable backdrop\r\n this.menu = this.matMenuTrigger.menu;\r\n this.menu.hasBackdrop = false;\r\n\r\n // Subscribe to mouseleave event on the menu element to close the menu\r\n this.menuElement$.pipe(\r\n takeUntilDestroyed(this.destroyRef),\r\n filter(element => !!element),\r\n mergeMap(element => fromEvent(element, 'mouseleave')),\r\n tap(() => this.closeMenu())\r\n )\r\n .subscribe();\r\n\r\n // Subscribe to mouseenter event on the menu element to open the menu\r\n this.menuElement$.pipe(\r\n takeUntilDestroyed(this.destroyRef),\r\n filter(element => !!element),\r\n mergeMap(element => fromEvent(element, 'mouseenter')),\r\n tap(() => this.openMenu())\r\n )\r\n .subscribe();\r\n }\r\n\r\n private closeMenu(): void {\r\n this.closer = setTimeout(() => {\r\n this.matMenuTrigger.closeMenu();\r\n }, this.closeDelay);\r\n }\r\n\r\n private openMenu(): void {\r\n if (this.closer) {\r\n clearTimeout(this.closer);\r\n }\r\n\r\n this.matMenuTrigger.openMenu();\r\n }\r\n}\r\n\r\n","/*\r\n * Public API Surface of mat-menu-hover\r\n */\r\n\r\nexport * from './lib/mat-menu-hover.directive';\r\n\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { EventEmitter, OnInit } from '@angular/core';
|
|
2
|
+
import { MatMenuTrigger } from '@angular/material/menu';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
/**
|
|
5
|
+
* Directive to handle hover menu behavior.
|
|
6
|
+
*/
|
|
7
|
+
export declare class MatMenuHoverDirective implements OnInit {
|
|
8
|
+
private matMenuTrigger;
|
|
9
|
+
private destroyRef;
|
|
10
|
+
private menu;
|
|
11
|
+
private menuElement$;
|
|
12
|
+
private closer;
|
|
13
|
+
/**
|
|
14
|
+
* Delay (in milliseconds) before closing the menu after mouseleave.
|
|
15
|
+
*/
|
|
16
|
+
closeDelay: number;
|
|
17
|
+
/**
|
|
18
|
+
* Event emitter for notifying when the menu is opened.
|
|
19
|
+
*/
|
|
20
|
+
opened: EventEmitter<boolean>;
|
|
21
|
+
onMouseEnter(): void;
|
|
22
|
+
onMouseLeave(): void;
|
|
23
|
+
constructor(matMenuTrigger: MatMenuTrigger);
|
|
24
|
+
ngOnInit(): void;
|
|
25
|
+
private closeMenu;
|
|
26
|
+
private openMenu;
|
|
27
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<MatMenuHoverDirective, [{ self: true; }]>;
|
|
28
|
+
static ɵdir: i0.ɵɵDirectiveDeclaration<MatMenuHoverDirective, "[matHoverMenu]", never, { "closeDelay": { "alias": "closeDelay"; "required": false; }; }, { "opened": "opened"; }, never, never, true, never>;
|
|
29
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ngx-mat-menu-hover",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"peerDependencies": {
|
|
5
|
+
"@angular/common": "^17.2.0",
|
|
6
|
+
"@angular/core": "^17.2.0",
|
|
7
|
+
"@angular/material": "^17.2.0"
|
|
8
|
+
},
|
|
9
|
+
"dependencies": {
|
|
10
|
+
"tslib": "^2.3.0"
|
|
11
|
+
},
|
|
12
|
+
"sideEffects": false,
|
|
13
|
+
"module": "fesm2022/ngx-mat-menu-hover.mjs",
|
|
14
|
+
"typings": "index.d.ts",
|
|
15
|
+
"exports": {
|
|
16
|
+
"./package.json": {
|
|
17
|
+
"default": "./package.json"
|
|
18
|
+
},
|
|
19
|
+
".": {
|
|
20
|
+
"types": "./index.d.ts",
|
|
21
|
+
"esm2022": "./esm2022/ngx-mat-menu-hover.mjs",
|
|
22
|
+
"esm": "./esm2022/ngx-mat-menu-hover.mjs",
|
|
23
|
+
"default": "./fesm2022/ngx-mat-menu-hover.mjs"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
package/public-api.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './lib/mat-menu-hover.directive';
|