@angular/material 19.1.0-next.1 → 19.1.0-next.3

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.
Files changed (98) hide show
  1. package/autocomplete/index.d.ts +5 -5
  2. package/button/index.d.ts +2 -0
  3. package/core/index.d.ts +1 -0
  4. package/core/theming/_theming.scss +1 -1
  5. package/datepicker/index.d.ts +1 -0
  6. package/expansion/index.d.ts +11 -8
  7. package/fesm2022/autocomplete.mjs +54 -50
  8. package/fesm2022/autocomplete.mjs.map +1 -1
  9. package/fesm2022/badge.mjs +10 -10
  10. package/fesm2022/badge.mjs.map +1 -1
  11. package/fesm2022/bottom-sheet.mjs +10 -10
  12. package/fesm2022/bottom-sheet.mjs.map +1 -1
  13. package/fesm2022/button-toggle.mjs +10 -10
  14. package/fesm2022/button-toggle.mjs.map +1 -1
  15. package/fesm2022/button.mjs +39 -37
  16. package/fesm2022/button.mjs.map +1 -1
  17. package/fesm2022/card.mjs +46 -46
  18. package/fesm2022/card.mjs.map +1 -1
  19. package/fesm2022/checkbox.mjs +14 -14
  20. package/fesm2022/checkbox.mjs.map +1 -1
  21. package/fesm2022/chips.mjs +40 -40
  22. package/fesm2022/chips.mjs.map +1 -1
  23. package/fesm2022/core.mjs +73 -75
  24. package/fesm2022/core.mjs.map +1 -1
  25. package/fesm2022/datepicker.mjs +104 -111
  26. package/fesm2022/datepicker.mjs.map +1 -1
  27. package/fesm2022/dialog.mjs +25 -25
  28. package/fesm2022/dialog.mjs.map +1 -1
  29. package/fesm2022/divider.mjs +7 -7
  30. package/fesm2022/divider.mjs.map +1 -1
  31. package/fesm2022/expansion.mjs +114 -105
  32. package/fesm2022/expansion.mjs.map +1 -1
  33. package/fesm2022/form-field.mjs +39 -37
  34. package/fesm2022/form-field.mjs.map +1 -1
  35. package/fesm2022/grid-list.mjs +22 -22
  36. package/fesm2022/grid-list.mjs.map +1 -1
  37. package/fesm2022/icon/testing.mjs +7 -7
  38. package/fesm2022/icon/testing.mjs.map +1 -1
  39. package/fesm2022/icon.mjs +10 -10
  40. package/fesm2022/icon.mjs.map +1 -1
  41. package/fesm2022/input.mjs +26 -32
  42. package/fesm2022/input.mjs.map +1 -1
  43. package/fesm2022/list.mjs +58 -55
  44. package/fesm2022/list.mjs.map +1 -1
  45. package/fesm2022/menu.mjs +219 -192
  46. package/fesm2022/menu.mjs.map +1 -1
  47. package/fesm2022/paginator.mjs +40 -31
  48. package/fesm2022/paginator.mjs.map +1 -1
  49. package/fesm2022/progress-bar.mjs +12 -10
  50. package/fesm2022/progress-bar.mjs.map +1 -1
  51. package/fesm2022/progress-spinner.mjs +7 -7
  52. package/fesm2022/progress-spinner.mjs.map +1 -1
  53. package/fesm2022/radio.mjs +15 -14
  54. package/fesm2022/radio.mjs.map +1 -1
  55. package/fesm2022/select.mjs +24 -13
  56. package/fesm2022/select.mjs.map +1 -1
  57. package/fesm2022/sidenav.mjs +28 -27
  58. package/fesm2022/sidenav.mjs.map +1 -1
  59. package/fesm2022/slide-toggle.mjs +14 -14
  60. package/fesm2022/slide-toggle.mjs.map +1 -1
  61. package/fesm2022/slider.mjs +38 -39
  62. package/fesm2022/slider.mjs.map +1 -1
  63. package/fesm2022/snack-bar.mjs +22 -22
  64. package/fesm2022/snack-bar.mjs.map +1 -1
  65. package/fesm2022/sort.mjs +13 -13
  66. package/fesm2022/sort.mjs.map +1 -1
  67. package/fesm2022/stepper.mjs +31 -31
  68. package/fesm2022/stepper.mjs.map +1 -1
  69. package/fesm2022/table.mjs +59 -70
  70. package/fesm2022/table.mjs.map +1 -1
  71. package/fesm2022/tabs.mjs +58 -66
  72. package/fesm2022/tabs.mjs.map +1 -1
  73. package/fesm2022/timepicker.mjs +58 -41
  74. package/fesm2022/timepicker.mjs.map +1 -1
  75. package/fesm2022/toolbar.mjs +10 -10
  76. package/fesm2022/toolbar.mjs.map +1 -1
  77. package/fesm2022/tooltip.mjs +54 -76
  78. package/fesm2022/tooltip.mjs.map +1 -1
  79. package/fesm2022/tree.mjs +25 -25
  80. package/fesm2022/tree.mjs.map +1 -1
  81. package/form-field/index.d.ts +1 -0
  82. package/input/index.d.ts +8 -5
  83. package/list/index.d.ts +2 -0
  84. package/menu/index.d.ts +20 -19
  85. package/package.json +2 -2
  86. package/paginator/index.d.ts +8 -0
  87. package/progress-bar/index.d.ts +2 -0
  88. package/radio/index.d.ts +4 -2
  89. package/schematics/ng-add/index.js +1 -1
  90. package/schematics/ng-add/index.mjs +1 -1
  91. package/schematics/ng-generate/theme-color/index_bundled.js +2 -2
  92. package/schematics/ng-update/index_bundled.js +31 -31
  93. package/select/index.d.ts +15 -2
  94. package/sidenav/index.d.ts +1 -0
  95. package/slider/index.d.ts +4 -1
  96. package/tabs/index.d.ts +4 -2
  97. package/timepicker/index.d.ts +4 -0
  98. package/tooltip/index.d.ts +4 -5
package/fesm2022/menu.mjs CHANGED
@@ -1,18 +1,18 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, inject, ElementRef, ChangeDetectorRef, booleanAttribute, Component, ChangeDetectionStrategy, ViewEncapsulation, Input, TemplateRef, ApplicationRef, Injector, ViewContainerRef, Directive, QueryList, EventEmitter, afterNextRender, ContentChildren, ViewChild, ContentChild, Output, NgZone, NgModule } from '@angular/core';
2
+ import { InjectionToken, inject, ElementRef, ChangeDetectorRef, booleanAttribute, Component, ChangeDetectionStrategy, ViewEncapsulation, Input, TemplateRef, ApplicationRef, Injector, ViewContainerRef, Directive, QueryList, EventEmitter, ANIMATION_MODULE_TYPE, afterNextRender, ContentChildren, ViewChild, ContentChild, Output, NgZone, Renderer2, NgModule } from '@angular/core';
3
3
  import { FocusMonitor, _IdGenerator, FocusKeyManager, isFakeTouchstartFromScreenReader, isFakeMousedownFromScreenReader } from '@angular/cdk/a11y';
4
4
  import { UP_ARROW, DOWN_ARROW, RIGHT_ARROW, LEFT_ARROW, ESCAPE, hasModifierKey, ENTER, SPACE } from '@angular/cdk/keycodes';
5
- import { Subject, merge, Subscription, of, asapScheduler } from 'rxjs';
6
- import { startWith, switchMap, takeUntil, filter, take, delay } from 'rxjs/operators';
5
+ import { Subject, merge, Subscription, of } from 'rxjs';
6
+ import { startWith, switchMap, takeUntil, take, filter } from 'rxjs/operators';
7
7
  import { DOCUMENT } from '@angular/common';
8
8
  import { _StructuralStylesLoader, MatRipple, MatRippleModule, MatCommonModule } from '@angular/material/core';
9
9
  import { _CdkPrivateStyleLoader } from '@angular/cdk/private';
10
10
  import { TemplatePortal, DomPortalOutlet } from '@angular/cdk/portal';
11
- import { trigger, state, style, transition, animate } from '@angular/animations';
12
11
  import { Directionality } from '@angular/cdk/bidi';
13
12
  import { Overlay, OverlayConfig, OverlayModule } from '@angular/cdk/overlay';
14
- import { normalizePassiveListenerOptions } from '@angular/cdk/platform';
13
+ import { _bindEventWithOptions } from '@angular/cdk/platform';
15
14
  import { CdkScrollableModule } from '@angular/cdk/scrolling';
15
+ import { trigger, state, style, transition, animate } from '@angular/animations';
16
16
 
17
17
  /**
18
18
  * Injection token used to provide the parent menu to menu-specific components.
@@ -118,10 +118,10 @@ class MatMenuItem {
118
118
  _hasFocus() {
119
119
  return this._document && this._document.activeElement === this._getHostElement();
120
120
  }
121
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: MatMenuItem, deps: [], target: i0.ɵɵFactoryTarget.Component });
122
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.0", type: MatMenuItem, isStandalone: true, selector: "[mat-menu-item]", inputs: { role: "role", disabled: ["disabled", "disabled", booleanAttribute], disableRipple: ["disableRipple", "disableRipple", booleanAttribute] }, host: { listeners: { "click": "_checkDisabled($event)", "mouseenter": "_handleMouseEnter()" }, properties: { "attr.role": "role", "class.mat-mdc-menu-item-highlighted": "_highlighted", "class.mat-mdc-menu-item-submenu-trigger": "_triggersSubmenu", "attr.tabindex": "_getTabIndex()", "attr.aria-disabled": "disabled", "attr.disabled": "disabled || null" }, classAttribute: "mat-mdc-menu-item mat-focus-indicator" }, exportAs: ["matMenuItem"], ngImport: i0, template: "<ng-content select=\"mat-icon, [matMenuItemIcon]\"></ng-content>\n<span class=\"mat-mdc-menu-item-text\"><ng-content></ng-content></span>\n<div class=\"mat-mdc-menu-ripple\" matRipple\n [matRippleDisabled]=\"disableRipple || disabled\"\n [matRippleTrigger]=\"_getHostElement()\">\n</div>\n\n@if (_triggersSubmenu) {\n <svg\n class=\"mat-mdc-menu-submenu-icon\"\n viewBox=\"0 0 5 10\"\n focusable=\"false\"\n aria-hidden=\"true\"><polygon points=\"0,0 5,5 0,10\"/></svg>\n}\n", dependencies: [{ kind: "directive", type: MatRipple, selector: "[mat-ripple], [matRipple]", inputs: ["matRippleColor", "matRippleUnbounded", "matRippleCentered", "matRippleRadius", "matRippleAnimation", "matRippleDisabled", "matRippleTrigger"], exportAs: ["matRipple"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
121
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.0-next.3", ngImport: i0, type: MatMenuItem, deps: [], target: i0.ɵɵFactoryTarget.Component });
122
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.1.0-next.3", type: MatMenuItem, isStandalone: true, selector: "[mat-menu-item]", inputs: { role: "role", disabled: ["disabled", "disabled", booleanAttribute], disableRipple: ["disableRipple", "disableRipple", booleanAttribute] }, host: { listeners: { "click": "_checkDisabled($event)", "mouseenter": "_handleMouseEnter()" }, properties: { "attr.role": "role", "class.mat-mdc-menu-item-highlighted": "_highlighted", "class.mat-mdc-menu-item-submenu-trigger": "_triggersSubmenu", "attr.tabindex": "_getTabIndex()", "attr.aria-disabled": "disabled", "attr.disabled": "disabled || null" }, classAttribute: "mat-mdc-menu-item mat-focus-indicator" }, exportAs: ["matMenuItem"], ngImport: i0, template: "<ng-content select=\"mat-icon, [matMenuItemIcon]\"></ng-content>\n<span class=\"mat-mdc-menu-item-text\"><ng-content></ng-content></span>\n<div class=\"mat-mdc-menu-ripple\" matRipple\n [matRippleDisabled]=\"disableRipple || disabled\"\n [matRippleTrigger]=\"_getHostElement()\">\n</div>\n\n@if (_triggersSubmenu) {\n <svg\n class=\"mat-mdc-menu-submenu-icon\"\n viewBox=\"0 0 5 10\"\n focusable=\"false\"\n aria-hidden=\"true\"><polygon points=\"0,0 5,5 0,10\"/></svg>\n}\n", dependencies: [{ kind: "directive", type: MatRipple, selector: "[mat-ripple], [matRipple]", inputs: ["matRippleColor", "matRippleUnbounded", "matRippleCentered", "matRippleRadius", "matRippleAnimation", "matRippleDisabled", "matRippleTrigger"], exportAs: ["matRipple"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
123
123
  }
124
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: MatMenuItem, decorators: [{
124
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.0-next.3", ngImport: i0, type: MatMenuItem, decorators: [{
125
125
  type: Component,
126
126
  args: [{ selector: '[mat-menu-item]', exportAs: 'matMenuItem', host: {
127
127
  '[attr.role]': 'role',
@@ -222,19 +222,18 @@ class MatMenuContent {
222
222
  * @docs-private
223
223
  */
224
224
  detach() {
225
- if (this._portal.isAttached) {
225
+ if (this._portal?.isAttached) {
226
226
  this._portal.detach();
227
227
  }
228
228
  }
229
229
  ngOnDestroy() {
230
- if (this._outlet) {
231
- this._outlet.dispose();
232
- }
230
+ this.detach();
231
+ this._outlet?.dispose();
233
232
  }
234
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: MatMenuContent, deps: [], target: i0.ɵɵFactoryTarget.Directive });
235
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.0.0", type: MatMenuContent, isStandalone: true, selector: "ng-template[matMenuContent]", providers: [{ provide: MAT_MENU_CONTENT, useExisting: MatMenuContent }], ngImport: i0 });
233
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.0-next.3", ngImport: i0, type: MatMenuContent, deps: [], target: i0.ɵɵFactoryTarget.Directive });
234
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.1.0-next.3", type: MatMenuContent, isStandalone: true, selector: "ng-template[matMenuContent]", providers: [{ provide: MAT_MENU_CONTENT, useExisting: MatMenuContent }], ngImport: i0 });
236
235
  }
237
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: MatMenuContent, decorators: [{
236
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.0-next.3", ngImport: i0, type: MatMenuContent, decorators: [{
238
237
  type: Directive,
239
238
  args: [{
240
239
  selector: 'ng-template[matMenuContent]',
@@ -242,59 +241,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImpor
242
241
  }]
243
242
  }], ctorParameters: () => [] });
244
243
 
245
- /**
246
- * Animations used by the mat-menu component.
247
- * Animation duration and timing values are based on:
248
- * https://material.io/guidelines/components/menus.html#menus-usage
249
- * @docs-private
250
- */
251
- const matMenuAnimations = {
252
- /**
253
- * This animation controls the menu panel's entry and exit from the page.
254
- *
255
- * When the menu panel is added to the DOM, it scales in and fades in its border.
256
- *
257
- * When the menu panel is removed from the DOM, it simply fades out after a brief
258
- * delay to display the ripple.
259
- */
260
- transformMenu: trigger('transformMenu', [
261
- state('void', style({
262
- opacity: 0,
263
- transform: 'scale(0.8)',
264
- })),
265
- transition('void => enter', animate('120ms cubic-bezier(0, 0, 0.2, 1)', style({
266
- opacity: 1,
267
- transform: 'scale(1)',
268
- }))),
269
- transition('* => void', animate('100ms 25ms linear', style({ opacity: 0 }))),
270
- ]),
271
- /**
272
- * This animation fades in the background color and content of the menu panel
273
- * after its containing element is scaled in.
274
- */
275
- fadeInItems: trigger('fadeInItems', [
276
- // TODO(crisbeto): this is inside the `transformMenu`
277
- // now. Remove next time we do breaking changes.
278
- state('showing', style({ opacity: 1 })),
279
- transition('void => *', [
280
- style({ opacity: 0 }),
281
- animate('400ms 100ms cubic-bezier(0.55, 0, 0.55, 0.2)'),
282
- ]),
283
- ]),
284
- };
285
- /**
286
- * @deprecated
287
- * @breaking-change 8.0.0
288
- * @docs-private
289
- */
290
- const fadeInItems = matMenuAnimations.fadeInItems;
291
- /**
292
- * @deprecated
293
- * @breaking-change 8.0.0
294
- * @docs-private
295
- */
296
- const transformMenu = matMenuAnimations.transformMenu;
297
-
298
244
  /** Injection token to be used to override the default options for `mat-menu`. */
299
245
  const MAT_MENU_DEFAULT_OPTIONS = new InjectionToken('mat-menu-default-options', {
300
246
  providedIn: 'root',
@@ -309,13 +255,21 @@ function MAT_MENU_DEFAULT_OPTIONS_FACTORY() {
309
255
  backdropClass: 'cdk-overlay-transparent-backdrop',
310
256
  };
311
257
  }
258
+ /** Name of the enter animation `@keyframes`. */
259
+ const ENTER_ANIMATION = '_mat-menu-enter';
260
+ /** Name of the exit animation `@keyframes`. */
261
+ const EXIT_ANIMATION = '_mat-menu-exit';
312
262
  class MatMenu {
313
263
  _elementRef = inject(ElementRef);
314
264
  _changeDetectorRef = inject(ChangeDetectorRef);
265
+ _injector = inject(Injector);
315
266
  _keyManager;
316
267
  _xPosition;
317
268
  _yPosition;
318
269
  _firstItemFocusRef;
270
+ _exitFallbackTimeout;
271
+ /** Whether animations are currently disabled. */
272
+ _animationsDisabled;
319
273
  /** All items inside the menu. Includes items nested inside another menu. */
320
274
  _allItems;
321
275
  /** Only the direct descendant menu items. */
@@ -327,7 +281,7 @@ class MatMenu {
327
281
  /** Emits whenever an animation on the menu completes. */
328
282
  _animationDone = new Subject();
329
283
  /** Whether the menu is animating. */
330
- _isAnimating;
284
+ _isAnimating = false;
331
285
  /** Parent menu of the current menu panel. */
332
286
  parentMenu;
333
287
  /** Layout direction of the menu. */
@@ -429,7 +383,6 @@ class MatMenu {
429
383
  */
430
384
  close = this.closed;
431
385
  panelId = inject(_IdGenerator).getId('mat-menu-panel-');
432
- _injector = inject(Injector);
433
386
  constructor() {
434
387
  const defaultOptions = inject(MAT_MENU_DEFAULT_OPTIONS);
435
388
  this.overlayPanelClass = defaultOptions.overlayPanelClass || '';
@@ -438,6 +391,7 @@ class MatMenu {
438
391
  this.backdropClass = defaultOptions.backdropClass;
439
392
  this.overlapTrigger = defaultOptions.overlapTrigger;
440
393
  this.hasBackdrop = defaultOptions.hasBackdrop;
394
+ this._animationsDisabled = inject(ANIMATION_MODULE_TYPE, { optional: true }) === 'NoopAnimations';
441
395
  }
442
396
  ngOnInit() {
443
397
  this.setPositionClasses();
@@ -477,6 +431,7 @@ class MatMenu {
477
431
  this._directDescendantItems.destroy();
478
432
  this.closed.complete();
479
433
  this._firstItemFocusRef?.destroy();
434
+ clearTimeout(this._exitFallbackTimeout);
480
435
  }
481
436
  /** Stream that emits whenever the hovered menu item changes. */
482
437
  _hovered() {
@@ -535,14 +490,7 @@ class MatMenu {
535
490
  // Wait for `afterNextRender` to ensure iOS VoiceOver screen reader focuses the first item (#24735).
536
491
  this._firstItemFocusRef?.destroy();
537
492
  this._firstItemFocusRef = afterNextRender(() => {
538
- let menuPanel = null;
539
- if (this._directDescendantItems.length) {
540
- // Because the `mat-menuPanel` is at the DOM insertion point, not inside the overlay, we don't
541
- // have a nice way of getting a hold of the menuPanel panel. We can't use a `ViewChild` either
542
- // because the panel is inside an `ng-template`. We work around it by starting from one of
543
- // the items and walking up the DOM.
544
- menuPanel = this._directDescendantItems.first._getHostElement().closest('[role="menu"]');
545
- }
493
+ const menuPanel = this._resolvePanel();
546
494
  // If an item in the menuPanel is already focused, avoid overriding the focus.
547
495
  if (!menuPanel || !menuPanel.contains(document.activeElement)) {
548
496
  const manager = this._keyManager;
@@ -585,32 +533,52 @@ class MatMenu {
585
533
  };
586
534
  this._changeDetectorRef.markForCheck();
587
535
  }
588
- /** Starts the enter animation. */
589
- _startAnimation() {
590
- // @breaking-change 8.0.0 Combine with _resetAnimation.
591
- this._panelAnimationState = 'enter';
536
+ /** Callback that is invoked when the panel animation completes. */
537
+ _onAnimationDone(state) {
538
+ const isExit = state === EXIT_ANIMATION;
539
+ if (isExit || state === ENTER_ANIMATION) {
540
+ if (isExit) {
541
+ clearTimeout(this._exitFallbackTimeout);
542
+ this._exitFallbackTimeout = undefined;
543
+ }
544
+ this._animationDone.next(isExit ? 'void' : 'enter');
545
+ this._isAnimating = false;
546
+ }
592
547
  }
593
- /** Resets the panel animation to its initial state. */
594
- _resetAnimation() {
595
- // @breaking-change 8.0.0 Combine with _startAnimation.
596
- this._panelAnimationState = 'void';
548
+ _onAnimationStart(state) {
549
+ if (state === ENTER_ANIMATION || state === EXIT_ANIMATION) {
550
+ this._isAnimating = true;
551
+ }
597
552
  }
598
- /** Callback that is invoked when the panel animation completes. */
599
- _onAnimationDone(event) {
600
- this._animationDone.next(event);
601
- this._isAnimating = false;
602
- }
603
- _onAnimationStart(event) {
604
- this._isAnimating = true;
605
- // Scroll the content element to the top as soon as the animation starts. This is necessary,
606
- // because we move focus to the first item while it's still being animated, which can throw
607
- // the browser off when it determines the scroll position. Alternatively we can move focus
608
- // when the animation is done, however moving focus asynchronously will interrupt screen
609
- // readers which are in the process of reading out the menu already. We take the `element`
610
- // from the `event` since we can't use a `ViewChild` to access the pane.
611
- if (event.toState === 'enter' && this._keyManager.activeItemIndex === 0) {
612
- event.element.scrollTop = 0;
553
+ _setIsOpen(isOpen) {
554
+ this._panelAnimationState = isOpen ? 'enter' : 'void';
555
+ if (isOpen) {
556
+ if (this._keyManager.activeItemIndex === 0) {
557
+ // Scroll the content element to the top as soon as the animation starts. This is necessary,
558
+ // because we move focus to the first item while it's still being animated, which can throw
559
+ // the browser off when it determines the scroll position. Alternatively we can move focus
560
+ // when the animation is done, however moving focus asynchronously will interrupt screen
561
+ // readers which are in the process of reading out the menu already. We take the `element`
562
+ // from the `event` since we can't use a `ViewChild` to access the pane.
563
+ const menuPanel = this._resolvePanel();
564
+ if (menuPanel) {
565
+ menuPanel.scrollTop = 0;
566
+ }
567
+ }
568
+ }
569
+ else if (!this._animationsDisabled) {
570
+ // Some apps do `* { animation: none !important; }` in tests which will prevent the
571
+ // `animationend` event from firing. Since the exit animation is loading-bearing for
572
+ // removing the content from the DOM, add a fallback timer.
573
+ this._exitFallbackTimeout = setTimeout(() => this._onAnimationDone(EXIT_ANIMATION), 200);
613
574
  }
575
+ // Animation events won't fire when animations are disabled so we simulate them.
576
+ if (this._animationsDisabled) {
577
+ setTimeout(() => {
578
+ this._onAnimationDone(isOpen ? ENTER_ANIMATION : EXIT_ANIMATION);
579
+ });
580
+ }
581
+ this._changeDetectorRef.markForCheck();
614
582
  }
615
583
  /**
616
584
  * Sets up a stream that will keep track of any newly-added menu items and will update the list
@@ -626,16 +594,28 @@ class MatMenu {
626
594
  this._directDescendantItems.notifyOnChanges();
627
595
  });
628
596
  }
629
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: MatMenu, deps: [], target: i0.ɵɵFactoryTarget.Component });
630
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "16.1.0", version: "19.0.0", type: MatMenu, isStandalone: true, selector: "mat-menu", inputs: { backdropClass: "backdropClass", ariaLabel: ["aria-label", "ariaLabel"], ariaLabelledby: ["aria-labelledby", "ariaLabelledby"], ariaDescribedby: ["aria-describedby", "ariaDescribedby"], xPosition: "xPosition", yPosition: "yPosition", overlapTrigger: ["overlapTrigger", "overlapTrigger", booleanAttribute], hasBackdrop: ["hasBackdrop", "hasBackdrop", (value) => (value == null ? null : booleanAttribute(value))], panelClass: ["class", "panelClass"], classList: "classList" }, outputs: { closed: "closed", close: "close" }, host: { properties: { "attr.aria-label": "null", "attr.aria-labelledby": "null", "attr.aria-describedby": "null" } }, providers: [{ provide: MAT_MENU_PANEL, useExisting: MatMenu }], queries: [{ propertyName: "lazyContent", first: true, predicate: MAT_MENU_CONTENT, descendants: true }, { propertyName: "_allItems", predicate: MatMenuItem, descendants: true }, { propertyName: "items", predicate: MatMenuItem }], viewQueries: [{ propertyName: "templateRef", first: true, predicate: TemplateRef, descendants: true }], exportAs: ["matMenu"], ngImport: i0, template: "<ng-template>\n <div\n class=\"mat-mdc-menu-panel\"\n [id]=\"panelId\"\n [class]=\"_classList\"\n (click)=\"closed.emit('click')\"\n [@transformMenu]=\"_panelAnimationState\"\n (@transformMenu.start)=\"_onAnimationStart($event)\"\n (@transformMenu.done)=\"_onAnimationDone($event)\"\n tabindex=\"-1\"\n role=\"menu\"\n [attr.aria-label]=\"ariaLabel || null\"\n [attr.aria-labelledby]=\"ariaLabelledby || null\"\n [attr.aria-describedby]=\"ariaDescribedby || null\">\n <div class=\"mat-mdc-menu-content\">\n <ng-content></ng-content>\n </div>\n </div>\n</ng-template>\n", styles: ["mat-menu{display:none}.mat-mdc-menu-content{margin:0;padding:8px 0;outline:0}.mat-mdc-menu-content,.mat-mdc-menu-content .mat-mdc-menu-item .mat-mdc-menu-item-text{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;flex:1;white-space:normal;font-family:var(--mat-menu-item-label-text-font, var(--mat-sys-label-large-font));line-height:var(--mat-menu-item-label-text-line-height, var(--mat-sys-label-large-line-height));font-size:var(--mat-menu-item-label-text-size, var(--mat-sys-label-large-size));letter-spacing:var(--mat-menu-item-label-text-tracking, var(--mat-sys-label-large-tracking));font-weight:var(--mat-menu-item-label-text-weight, var(--mat-sys-label-large-weight))}.mat-mdc-menu-panel{min-width:112px;max-width:280px;overflow:auto;box-sizing:border-box;outline:0;border-radius:var(--mat-menu-container-shape, var(--mat-sys-corner-extra-small));background-color:var(--mat-menu-container-color, var(--mat-sys-surface-container));box-shadow:var(--mat-menu-container-elevation-shadow, 0px 3px 1px -2px rgba(0, 0, 0, 0.2), 0px 2px 2px 0px rgba(0, 0, 0, 0.14), 0px 1px 5px 0px rgba(0, 0, 0, 0.12));will-change:transform,opacity}.mat-mdc-menu-panel.ng-animating{pointer-events:none}.mat-mdc-menu-panel.ng-animating:has(.mat-mdc-menu-content:empty){display:none}@media(forced-colors: active){.mat-mdc-menu-panel{outline:solid 1px}}.mat-mdc-menu-panel .mat-divider{color:var(--mat-menu-divider-color, var(--mat-sys-surface-variant));margin-bottom:var(--mat-menu-divider-bottom-spacing, 8px);margin-top:var(--mat-menu-divider-top-spacing, 8px)}.mat-mdc-menu-item{display:flex;position:relative;align-items:center;justify-content:flex-start;overflow:hidden;padding:0;cursor:pointer;width:100%;text-align:left;box-sizing:border-box;color:inherit;font-size:inherit;background:none;text-decoration:none;margin:0;min-height:48px;padding-left:var(--mat-menu-item-leading-spacing, 12px);padding-right:var(--mat-menu-item-trailing-spacing, 12px);-webkit-user-select:none;user-select:none;cursor:pointer;outline:none;border:none;-webkit-tap-highlight-color:rgba(0,0,0,0)}.mat-mdc-menu-item::-moz-focus-inner{border:0}[dir=rtl] .mat-mdc-menu-item{padding-left:var(--mat-menu-item-trailing-spacing, 12px);padding-right:var(--mat-menu-item-leading-spacing, 12px)}.mat-mdc-menu-item:has(.material-icons,mat-icon,[matButtonIcon]){padding-left:var(--mat-menu-item-with-icon-leading-spacing, 12px);padding-right:var(--mat-menu-item-with-icon-trailing-spacing, 12px)}[dir=rtl] .mat-mdc-menu-item:has(.material-icons,mat-icon,[matButtonIcon]){padding-left:var(--mat-menu-item-with-icon-trailing-spacing, 12px);padding-right:var(--mat-menu-item-with-icon-leading-spacing, 12px)}.mat-mdc-menu-item,.mat-mdc-menu-item:visited,.mat-mdc-menu-item:link{color:var(--mat-menu-item-label-text-color, var(--mat-sys-on-surface))}.mat-mdc-menu-item .mat-icon-no-color,.mat-mdc-menu-item .mat-mdc-menu-submenu-icon{color:var(--mat-menu-item-icon-color, var(--mat-sys-on-surface-variant))}.mat-mdc-menu-item[disabled]{cursor:default;opacity:.38}.mat-mdc-menu-item[disabled]::after{display:block;position:absolute;content:\"\";top:0;left:0;bottom:0;right:0}.mat-mdc-menu-item:focus{outline:0}.mat-mdc-menu-item .mat-icon{flex-shrink:0;margin-right:var(--mat-menu-item-spacing, 12px);height:var(--mat-menu-item-icon-size, 24px);width:var(--mat-menu-item-icon-size, 24px)}[dir=rtl] .mat-mdc-menu-item{text-align:right}[dir=rtl] .mat-mdc-menu-item .mat-icon{margin-right:0;margin-left:var(--mat-menu-item-spacing, 12px)}.mat-mdc-menu-item:not([disabled]):hover{background-color:var(--mat-menu-item-hover-state-layer-color, color-mix(in srgb, var(--mat-sys-on-surface) calc(var(--mat-sys-hover-state-layer-opacity) * 100%), transparent))}.mat-mdc-menu-item:not([disabled]).cdk-program-focused,.mat-mdc-menu-item:not([disabled]).cdk-keyboard-focused,.mat-mdc-menu-item:not([disabled]).mat-mdc-menu-item-highlighted{background-color:var(--mat-menu-item-focus-state-layer-color, color-mix(in srgb, var(--mat-sys-on-surface) calc(var(--mat-sys-focus-state-layer-opacity) * 100%), transparent))}@media(forced-colors: active){.mat-mdc-menu-item{margin-top:1px}}.mat-mdc-menu-submenu-icon{width:var(--mat-menu-item-icon-size, 24px);height:10px;fill:currentColor;padding-left:var(--mat-menu-item-spacing, 12px)}[dir=rtl] .mat-mdc-menu-submenu-icon{padding-right:var(--mat-menu-item-spacing, 12px);padding-left:0}[dir=rtl] .mat-mdc-menu-submenu-icon polygon{transform:scaleX(-1);transform-origin:center}@media(forced-colors: active){.mat-mdc-menu-submenu-icon{fill:CanvasText}}.mat-mdc-menu-item .mat-mdc-menu-ripple{top:0;left:0;right:0;bottom:0;position:absolute;pointer-events:none}"], animations: [matMenuAnimations.transformMenu, matMenuAnimations.fadeInItems], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
597
+ /** Gets the menu panel DOM node. */
598
+ _resolvePanel() {
599
+ let menuPanel = null;
600
+ if (this._directDescendantItems.length) {
601
+ // Because the `mat-menuPanel` is at the DOM insertion point, not inside the overlay, we don't
602
+ // have a nice way of getting a hold of the menuPanel panel. We can't use a `ViewChild` either
603
+ // because the panel is inside an `ng-template`. We work around it by starting from one of
604
+ // the items and walking up the DOM.
605
+ menuPanel = this._directDescendantItems.first._getHostElement().closest('[role="menu"]');
606
+ }
607
+ return menuPanel;
608
+ }
609
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.0-next.3", ngImport: i0, type: MatMenu, deps: [], target: i0.ɵɵFactoryTarget.Component });
610
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "16.1.0", version: "19.1.0-next.3", type: MatMenu, isStandalone: true, selector: "mat-menu", inputs: { backdropClass: "backdropClass", ariaLabel: ["aria-label", "ariaLabel"], ariaLabelledby: ["aria-labelledby", "ariaLabelledby"], ariaDescribedby: ["aria-describedby", "ariaDescribedby"], xPosition: "xPosition", yPosition: "yPosition", overlapTrigger: ["overlapTrigger", "overlapTrigger", booleanAttribute], hasBackdrop: ["hasBackdrop", "hasBackdrop", (value) => (value == null ? null : booleanAttribute(value))], panelClass: ["class", "panelClass"], classList: "classList" }, outputs: { closed: "closed", close: "close" }, host: { properties: { "attr.aria-label": "null", "attr.aria-labelledby": "null", "attr.aria-describedby": "null" } }, providers: [{ provide: MAT_MENU_PANEL, useExisting: MatMenu }], queries: [{ propertyName: "lazyContent", first: true, predicate: MAT_MENU_CONTENT, descendants: true }, { propertyName: "_allItems", predicate: MatMenuItem, descendants: true }, { propertyName: "items", predicate: MatMenuItem }], viewQueries: [{ propertyName: "templateRef", first: true, predicate: TemplateRef, descendants: true }], exportAs: ["matMenu"], ngImport: i0, template: "<ng-template>\n <div\n class=\"mat-mdc-menu-panel\"\n [id]=\"panelId\"\n [class]=\"_classList\"\n [class.mat-menu-panel-animations-disabled]=\"_animationsDisabled\"\n [class.mat-menu-panel-exit-animation]=\"_panelAnimationState === 'void'\"\n [class.mat-menu-panel-animating]=\"_isAnimating\"\n (click)=\"closed.emit('click')\"\n tabindex=\"-1\"\n role=\"menu\"\n (animationstart)=\"_onAnimationStart($event.animationName)\"\n (animationend)=\"_onAnimationDone($event.animationName)\"\n (animationcancel)=\"_onAnimationDone($event.animationName)\"\n [attr.aria-label]=\"ariaLabel || null\"\n [attr.aria-labelledby]=\"ariaLabelledby || null\"\n [attr.aria-describedby]=\"ariaDescribedby || null\">\n <div class=\"mat-mdc-menu-content\">\n <ng-content></ng-content>\n </div>\n </div>\n</ng-template>\n", styles: ["mat-menu{display:none}.mat-mdc-menu-content{margin:0;padding:8px 0;outline:0}.mat-mdc-menu-content,.mat-mdc-menu-content .mat-mdc-menu-item .mat-mdc-menu-item-text{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;flex:1;white-space:normal;font-family:var(--mat-menu-item-label-text-font, var(--mat-sys-label-large-font));line-height:var(--mat-menu-item-label-text-line-height, var(--mat-sys-label-large-line-height));font-size:var(--mat-menu-item-label-text-size, var(--mat-sys-label-large-size));letter-spacing:var(--mat-menu-item-label-text-tracking, var(--mat-sys-label-large-tracking));font-weight:var(--mat-menu-item-label-text-weight, var(--mat-sys-label-large-weight))}@keyframes _mat-menu-enter{from{opacity:0;transform:scale(0.8)}to{opacity:1;transform:none}}@keyframes _mat-menu-exit{from{opacity:1}to{opacity:0}}.mat-mdc-menu-panel{min-width:112px;max-width:280px;overflow:auto;box-sizing:border-box;outline:0;animation:_mat-menu-enter 120ms cubic-bezier(0, 0, 0.2, 1);border-radius:var(--mat-menu-container-shape, var(--mat-sys-corner-extra-small));background-color:var(--mat-menu-container-color, var(--mat-sys-surface-container));box-shadow:var(--mat-menu-container-elevation-shadow, 0px 3px 1px -2px rgba(0, 0, 0, 0.2), 0px 2px 2px 0px rgba(0, 0, 0, 0.14), 0px 1px 5px 0px rgba(0, 0, 0, 0.12));will-change:transform,opacity}.mat-mdc-menu-panel.mat-menu-panel-exit-animation{animation:_mat-menu-exit 100ms 25ms linear forwards}.mat-mdc-menu-panel.mat-menu-panel-animations-disabled{animation:none}.mat-mdc-menu-panel.mat-menu-panel-animating{pointer-events:none}.mat-mdc-menu-panel.mat-menu-panel-animating:has(.mat-mdc-menu-content:empty){display:none}@media(forced-colors: active){.mat-mdc-menu-panel{outline:solid 1px}}.mat-mdc-menu-panel .mat-divider{color:var(--mat-menu-divider-color, var(--mat-sys-surface-variant));margin-bottom:var(--mat-menu-divider-bottom-spacing, 8px);margin-top:var(--mat-menu-divider-top-spacing, 8px)}.mat-mdc-menu-item{display:flex;position:relative;align-items:center;justify-content:flex-start;overflow:hidden;padding:0;cursor:pointer;width:100%;text-align:left;box-sizing:border-box;color:inherit;font-size:inherit;background:none;text-decoration:none;margin:0;min-height:48px;padding-left:var(--mat-menu-item-leading-spacing, 12px);padding-right:var(--mat-menu-item-trailing-spacing, 12px);-webkit-user-select:none;user-select:none;cursor:pointer;outline:none;border:none;-webkit-tap-highlight-color:rgba(0,0,0,0)}.mat-mdc-menu-item::-moz-focus-inner{border:0}[dir=rtl] .mat-mdc-menu-item{padding-left:var(--mat-menu-item-trailing-spacing, 12px);padding-right:var(--mat-menu-item-leading-spacing, 12px)}.mat-mdc-menu-item:has(.material-icons,mat-icon,[matButtonIcon]){padding-left:var(--mat-menu-item-with-icon-leading-spacing, 12px);padding-right:var(--mat-menu-item-with-icon-trailing-spacing, 12px)}[dir=rtl] .mat-mdc-menu-item:has(.material-icons,mat-icon,[matButtonIcon]){padding-left:var(--mat-menu-item-with-icon-trailing-spacing, 12px);padding-right:var(--mat-menu-item-with-icon-leading-spacing, 12px)}.mat-mdc-menu-item,.mat-mdc-menu-item:visited,.mat-mdc-menu-item:link{color:var(--mat-menu-item-label-text-color, var(--mat-sys-on-surface))}.mat-mdc-menu-item .mat-icon-no-color,.mat-mdc-menu-item .mat-mdc-menu-submenu-icon{color:var(--mat-menu-item-icon-color, var(--mat-sys-on-surface-variant))}.mat-mdc-menu-item[disabled]{cursor:default;opacity:.38}.mat-mdc-menu-item[disabled]::after{display:block;position:absolute;content:\"\";top:0;left:0;bottom:0;right:0}.mat-mdc-menu-item:focus{outline:0}.mat-mdc-menu-item .mat-icon{flex-shrink:0;margin-right:var(--mat-menu-item-spacing, 12px);height:var(--mat-menu-item-icon-size, 24px);width:var(--mat-menu-item-icon-size, 24px)}[dir=rtl] .mat-mdc-menu-item{text-align:right}[dir=rtl] .mat-mdc-menu-item .mat-icon{margin-right:0;margin-left:var(--mat-menu-item-spacing, 12px)}.mat-mdc-menu-item:not([disabled]):hover{background-color:var(--mat-menu-item-hover-state-layer-color, color-mix(in srgb, var(--mat-sys-on-surface) calc(var(--mat-sys-hover-state-layer-opacity) * 100%), transparent))}.mat-mdc-menu-item:not([disabled]).cdk-program-focused,.mat-mdc-menu-item:not([disabled]).cdk-keyboard-focused,.mat-mdc-menu-item:not([disabled]).mat-mdc-menu-item-highlighted{background-color:var(--mat-menu-item-focus-state-layer-color, color-mix(in srgb, var(--mat-sys-on-surface) calc(var(--mat-sys-focus-state-layer-opacity) * 100%), transparent))}@media(forced-colors: active){.mat-mdc-menu-item{margin-top:1px}}.mat-mdc-menu-submenu-icon{width:var(--mat-menu-item-icon-size, 24px);height:10px;fill:currentColor;padding-left:var(--mat-menu-item-spacing, 12px)}[dir=rtl] .mat-mdc-menu-submenu-icon{padding-right:var(--mat-menu-item-spacing, 12px);padding-left:0}[dir=rtl] .mat-mdc-menu-submenu-icon polygon{transform:scaleX(-1);transform-origin:center}@media(forced-colors: active){.mat-mdc-menu-submenu-icon{fill:CanvasText}}.mat-mdc-menu-item .mat-mdc-menu-ripple{top:0;left:0;right:0;bottom:0;position:absolute;pointer-events:none}"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
631
611
  }
632
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: MatMenu, decorators: [{
612
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.0-next.3", ngImport: i0, type: MatMenu, decorators: [{
633
613
  type: Component,
634
614
  args: [{ selector: 'mat-menu', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, exportAs: 'matMenu', host: {
635
615
  '[attr.aria-label]': 'null',
636
616
  '[attr.aria-labelledby]': 'null',
637
617
  '[attr.aria-describedby]': 'null',
638
- }, animations: [matMenuAnimations.transformMenu, matMenuAnimations.fadeInItems], providers: [{ provide: MAT_MENU_PANEL, useExisting: MatMenu }], template: "<ng-template>\n <div\n class=\"mat-mdc-menu-panel\"\n [id]=\"panelId\"\n [class]=\"_classList\"\n (click)=\"closed.emit('click')\"\n [@transformMenu]=\"_panelAnimationState\"\n (@transformMenu.start)=\"_onAnimationStart($event)\"\n (@transformMenu.done)=\"_onAnimationDone($event)\"\n tabindex=\"-1\"\n role=\"menu\"\n [attr.aria-label]=\"ariaLabel || null\"\n [attr.aria-labelledby]=\"ariaLabelledby || null\"\n [attr.aria-describedby]=\"ariaDescribedby || null\">\n <div class=\"mat-mdc-menu-content\">\n <ng-content></ng-content>\n </div>\n </div>\n</ng-template>\n", styles: ["mat-menu{display:none}.mat-mdc-menu-content{margin:0;padding:8px 0;outline:0}.mat-mdc-menu-content,.mat-mdc-menu-content .mat-mdc-menu-item .mat-mdc-menu-item-text{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;flex:1;white-space:normal;font-family:var(--mat-menu-item-label-text-font, var(--mat-sys-label-large-font));line-height:var(--mat-menu-item-label-text-line-height, var(--mat-sys-label-large-line-height));font-size:var(--mat-menu-item-label-text-size, var(--mat-sys-label-large-size));letter-spacing:var(--mat-menu-item-label-text-tracking, var(--mat-sys-label-large-tracking));font-weight:var(--mat-menu-item-label-text-weight, var(--mat-sys-label-large-weight))}.mat-mdc-menu-panel{min-width:112px;max-width:280px;overflow:auto;box-sizing:border-box;outline:0;border-radius:var(--mat-menu-container-shape, var(--mat-sys-corner-extra-small));background-color:var(--mat-menu-container-color, var(--mat-sys-surface-container));box-shadow:var(--mat-menu-container-elevation-shadow, 0px 3px 1px -2px rgba(0, 0, 0, 0.2), 0px 2px 2px 0px rgba(0, 0, 0, 0.14), 0px 1px 5px 0px rgba(0, 0, 0, 0.12));will-change:transform,opacity}.mat-mdc-menu-panel.ng-animating{pointer-events:none}.mat-mdc-menu-panel.ng-animating:has(.mat-mdc-menu-content:empty){display:none}@media(forced-colors: active){.mat-mdc-menu-panel{outline:solid 1px}}.mat-mdc-menu-panel .mat-divider{color:var(--mat-menu-divider-color, var(--mat-sys-surface-variant));margin-bottom:var(--mat-menu-divider-bottom-spacing, 8px);margin-top:var(--mat-menu-divider-top-spacing, 8px)}.mat-mdc-menu-item{display:flex;position:relative;align-items:center;justify-content:flex-start;overflow:hidden;padding:0;cursor:pointer;width:100%;text-align:left;box-sizing:border-box;color:inherit;font-size:inherit;background:none;text-decoration:none;margin:0;min-height:48px;padding-left:var(--mat-menu-item-leading-spacing, 12px);padding-right:var(--mat-menu-item-trailing-spacing, 12px);-webkit-user-select:none;user-select:none;cursor:pointer;outline:none;border:none;-webkit-tap-highlight-color:rgba(0,0,0,0)}.mat-mdc-menu-item::-moz-focus-inner{border:0}[dir=rtl] .mat-mdc-menu-item{padding-left:var(--mat-menu-item-trailing-spacing, 12px);padding-right:var(--mat-menu-item-leading-spacing, 12px)}.mat-mdc-menu-item:has(.material-icons,mat-icon,[matButtonIcon]){padding-left:var(--mat-menu-item-with-icon-leading-spacing, 12px);padding-right:var(--mat-menu-item-with-icon-trailing-spacing, 12px)}[dir=rtl] .mat-mdc-menu-item:has(.material-icons,mat-icon,[matButtonIcon]){padding-left:var(--mat-menu-item-with-icon-trailing-spacing, 12px);padding-right:var(--mat-menu-item-with-icon-leading-spacing, 12px)}.mat-mdc-menu-item,.mat-mdc-menu-item:visited,.mat-mdc-menu-item:link{color:var(--mat-menu-item-label-text-color, var(--mat-sys-on-surface))}.mat-mdc-menu-item .mat-icon-no-color,.mat-mdc-menu-item .mat-mdc-menu-submenu-icon{color:var(--mat-menu-item-icon-color, var(--mat-sys-on-surface-variant))}.mat-mdc-menu-item[disabled]{cursor:default;opacity:.38}.mat-mdc-menu-item[disabled]::after{display:block;position:absolute;content:\"\";top:0;left:0;bottom:0;right:0}.mat-mdc-menu-item:focus{outline:0}.mat-mdc-menu-item .mat-icon{flex-shrink:0;margin-right:var(--mat-menu-item-spacing, 12px);height:var(--mat-menu-item-icon-size, 24px);width:var(--mat-menu-item-icon-size, 24px)}[dir=rtl] .mat-mdc-menu-item{text-align:right}[dir=rtl] .mat-mdc-menu-item .mat-icon{margin-right:0;margin-left:var(--mat-menu-item-spacing, 12px)}.mat-mdc-menu-item:not([disabled]):hover{background-color:var(--mat-menu-item-hover-state-layer-color, color-mix(in srgb, var(--mat-sys-on-surface) calc(var(--mat-sys-hover-state-layer-opacity) * 100%), transparent))}.mat-mdc-menu-item:not([disabled]).cdk-program-focused,.mat-mdc-menu-item:not([disabled]).cdk-keyboard-focused,.mat-mdc-menu-item:not([disabled]).mat-mdc-menu-item-highlighted{background-color:var(--mat-menu-item-focus-state-layer-color, color-mix(in srgb, var(--mat-sys-on-surface) calc(var(--mat-sys-focus-state-layer-opacity) * 100%), transparent))}@media(forced-colors: active){.mat-mdc-menu-item{margin-top:1px}}.mat-mdc-menu-submenu-icon{width:var(--mat-menu-item-icon-size, 24px);height:10px;fill:currentColor;padding-left:var(--mat-menu-item-spacing, 12px)}[dir=rtl] .mat-mdc-menu-submenu-icon{padding-right:var(--mat-menu-item-spacing, 12px);padding-left:0}[dir=rtl] .mat-mdc-menu-submenu-icon polygon{transform:scaleX(-1);transform-origin:center}@media(forced-colors: active){.mat-mdc-menu-submenu-icon{fill:CanvasText}}.mat-mdc-menu-item .mat-mdc-menu-ripple{top:0;left:0;right:0;bottom:0;position:absolute;pointer-events:none}"] }]
618
+ }, providers: [{ provide: MAT_MENU_PANEL, useExisting: MatMenu }], template: "<ng-template>\n <div\n class=\"mat-mdc-menu-panel\"\n [id]=\"panelId\"\n [class]=\"_classList\"\n [class.mat-menu-panel-animations-disabled]=\"_animationsDisabled\"\n [class.mat-menu-panel-exit-animation]=\"_panelAnimationState === 'void'\"\n [class.mat-menu-panel-animating]=\"_isAnimating\"\n (click)=\"closed.emit('click')\"\n tabindex=\"-1\"\n role=\"menu\"\n (animationstart)=\"_onAnimationStart($event.animationName)\"\n (animationend)=\"_onAnimationDone($event.animationName)\"\n (animationcancel)=\"_onAnimationDone($event.animationName)\"\n [attr.aria-label]=\"ariaLabel || null\"\n [attr.aria-labelledby]=\"ariaLabelledby || null\"\n [attr.aria-describedby]=\"ariaDescribedby || null\">\n <div class=\"mat-mdc-menu-content\">\n <ng-content></ng-content>\n </div>\n </div>\n</ng-template>\n", styles: ["mat-menu{display:none}.mat-mdc-menu-content{margin:0;padding:8px 0;outline:0}.mat-mdc-menu-content,.mat-mdc-menu-content .mat-mdc-menu-item .mat-mdc-menu-item-text{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;flex:1;white-space:normal;font-family:var(--mat-menu-item-label-text-font, var(--mat-sys-label-large-font));line-height:var(--mat-menu-item-label-text-line-height, var(--mat-sys-label-large-line-height));font-size:var(--mat-menu-item-label-text-size, var(--mat-sys-label-large-size));letter-spacing:var(--mat-menu-item-label-text-tracking, var(--mat-sys-label-large-tracking));font-weight:var(--mat-menu-item-label-text-weight, var(--mat-sys-label-large-weight))}@keyframes _mat-menu-enter{from{opacity:0;transform:scale(0.8)}to{opacity:1;transform:none}}@keyframes _mat-menu-exit{from{opacity:1}to{opacity:0}}.mat-mdc-menu-panel{min-width:112px;max-width:280px;overflow:auto;box-sizing:border-box;outline:0;animation:_mat-menu-enter 120ms cubic-bezier(0, 0, 0.2, 1);border-radius:var(--mat-menu-container-shape, var(--mat-sys-corner-extra-small));background-color:var(--mat-menu-container-color, var(--mat-sys-surface-container));box-shadow:var(--mat-menu-container-elevation-shadow, 0px 3px 1px -2px rgba(0, 0, 0, 0.2), 0px 2px 2px 0px rgba(0, 0, 0, 0.14), 0px 1px 5px 0px rgba(0, 0, 0, 0.12));will-change:transform,opacity}.mat-mdc-menu-panel.mat-menu-panel-exit-animation{animation:_mat-menu-exit 100ms 25ms linear forwards}.mat-mdc-menu-panel.mat-menu-panel-animations-disabled{animation:none}.mat-mdc-menu-panel.mat-menu-panel-animating{pointer-events:none}.mat-mdc-menu-panel.mat-menu-panel-animating:has(.mat-mdc-menu-content:empty){display:none}@media(forced-colors: active){.mat-mdc-menu-panel{outline:solid 1px}}.mat-mdc-menu-panel .mat-divider{color:var(--mat-menu-divider-color, var(--mat-sys-surface-variant));margin-bottom:var(--mat-menu-divider-bottom-spacing, 8px);margin-top:var(--mat-menu-divider-top-spacing, 8px)}.mat-mdc-menu-item{display:flex;position:relative;align-items:center;justify-content:flex-start;overflow:hidden;padding:0;cursor:pointer;width:100%;text-align:left;box-sizing:border-box;color:inherit;font-size:inherit;background:none;text-decoration:none;margin:0;min-height:48px;padding-left:var(--mat-menu-item-leading-spacing, 12px);padding-right:var(--mat-menu-item-trailing-spacing, 12px);-webkit-user-select:none;user-select:none;cursor:pointer;outline:none;border:none;-webkit-tap-highlight-color:rgba(0,0,0,0)}.mat-mdc-menu-item::-moz-focus-inner{border:0}[dir=rtl] .mat-mdc-menu-item{padding-left:var(--mat-menu-item-trailing-spacing, 12px);padding-right:var(--mat-menu-item-leading-spacing, 12px)}.mat-mdc-menu-item:has(.material-icons,mat-icon,[matButtonIcon]){padding-left:var(--mat-menu-item-with-icon-leading-spacing, 12px);padding-right:var(--mat-menu-item-with-icon-trailing-spacing, 12px)}[dir=rtl] .mat-mdc-menu-item:has(.material-icons,mat-icon,[matButtonIcon]){padding-left:var(--mat-menu-item-with-icon-trailing-spacing, 12px);padding-right:var(--mat-menu-item-with-icon-leading-spacing, 12px)}.mat-mdc-menu-item,.mat-mdc-menu-item:visited,.mat-mdc-menu-item:link{color:var(--mat-menu-item-label-text-color, var(--mat-sys-on-surface))}.mat-mdc-menu-item .mat-icon-no-color,.mat-mdc-menu-item .mat-mdc-menu-submenu-icon{color:var(--mat-menu-item-icon-color, var(--mat-sys-on-surface-variant))}.mat-mdc-menu-item[disabled]{cursor:default;opacity:.38}.mat-mdc-menu-item[disabled]::after{display:block;position:absolute;content:\"\";top:0;left:0;bottom:0;right:0}.mat-mdc-menu-item:focus{outline:0}.mat-mdc-menu-item .mat-icon{flex-shrink:0;margin-right:var(--mat-menu-item-spacing, 12px);height:var(--mat-menu-item-icon-size, 24px);width:var(--mat-menu-item-icon-size, 24px)}[dir=rtl] .mat-mdc-menu-item{text-align:right}[dir=rtl] .mat-mdc-menu-item .mat-icon{margin-right:0;margin-left:var(--mat-menu-item-spacing, 12px)}.mat-mdc-menu-item:not([disabled]):hover{background-color:var(--mat-menu-item-hover-state-layer-color, color-mix(in srgb, var(--mat-sys-on-surface) calc(var(--mat-sys-hover-state-layer-opacity) * 100%), transparent))}.mat-mdc-menu-item:not([disabled]).cdk-program-focused,.mat-mdc-menu-item:not([disabled]).cdk-keyboard-focused,.mat-mdc-menu-item:not([disabled]).mat-mdc-menu-item-highlighted{background-color:var(--mat-menu-item-focus-state-layer-color, color-mix(in srgb, var(--mat-sys-on-surface) calc(var(--mat-sys-focus-state-layer-opacity) * 100%), transparent))}@media(forced-colors: active){.mat-mdc-menu-item{margin-top:1px}}.mat-mdc-menu-submenu-icon{width:var(--mat-menu-item-icon-size, 24px);height:10px;fill:currentColor;padding-left:var(--mat-menu-item-spacing, 12px)}[dir=rtl] .mat-mdc-menu-submenu-icon{padding-right:var(--mat-menu-item-spacing, 12px);padding-left:0}[dir=rtl] .mat-mdc-menu-submenu-icon polygon{transform:scaleX(-1);transform-origin:center}@media(forced-colors: active){.mat-mdc-menu-submenu-icon{fill:CanvasText}}.mat-mdc-menu-item .mat-mdc-menu-ripple{top:0;left:0;right:0;bottom:0;position:absolute;pointer-events:none}"] }]
639
619
  }], ctorParameters: () => [], propDecorators: { _allItems: [{
640
620
  type: ContentChildren,
641
621
  args: [MatMenuItem, { descendants: true }]
@@ -699,13 +679,15 @@ const MAT_MENU_SCROLL_STRATEGY_FACTORY_PROVIDER = {
699
679
  useFactory: MAT_MENU_SCROLL_STRATEGY_FACTORY,
700
680
  };
701
681
  /** Options for binding a passive event listener. */
702
- const passiveEventListenerOptions = normalizePassiveListenerOptions({ passive: true });
682
+ const passiveEventListenerOptions = { passive: true };
703
683
  /**
704
684
  * Default top padding of the menu panel.
705
685
  * @deprecated No longer being used. Will be removed.
706
686
  * @breaking-change 15.0.0
707
687
  */
708
688
  const MENU_PANEL_TOP_PADDING = 8;
689
+ /** Mapping between menu panels and the last trigger that opened them. */
690
+ const PANELS_TO_TRIGGERS = new WeakMap();
709
691
  /** Directive applied to an element that should trigger a `mat-menu`. */
710
692
  class MatMenuTrigger {
711
693
  _overlay = inject(Overlay);
@@ -717,12 +699,14 @@ class MatMenuTrigger {
717
699
  _ngZone = inject(NgZone);
718
700
  _scrollStrategy = inject(MAT_MENU_SCROLL_STRATEGY);
719
701
  _changeDetectorRef = inject(ChangeDetectorRef);
702
+ _cleanupTouchstart;
720
703
  _portal;
721
704
  _overlayRef = null;
722
705
  _menuOpen = false;
723
706
  _closingActionsSubscription = Subscription.EMPTY;
724
707
  _hoverSubscription = Subscription.EMPTY;
725
708
  _menuCloseSubscription = Subscription.EMPTY;
709
+ _pendingRemoval;
726
710
  /**
727
711
  * We're specifically looking for a `MatMenu` here since the generic `MatMenuPanel`
728
712
  * interface lacks some functionality around nested menus and animations.
@@ -733,15 +717,6 @@ class MatMenuTrigger {
733
717
  * Used to offset sub-menus to compensate for the padding.
734
718
  */
735
719
  _parentInnerPadding;
736
- /**
737
- * Handles touch start events on the trigger.
738
- * Needs to be an arrow function so we can easily use addEventListener and removeEventListener.
739
- */
740
- _handleTouchStart = (event) => {
741
- if (!isFakeTouchstartFromScreenReader(event)) {
742
- this._openedBy = 'touch';
743
- }
744
- };
745
720
  // Tracking input type is necessary so it's possible to only auto-focus
746
721
  // the first item of the list when the menu is opened via the keyboard
747
722
  _openedBy = undefined;
@@ -808,21 +783,30 @@ class MatMenuTrigger {
808
783
  onMenuClose = this.menuClosed;
809
784
  constructor() {
810
785
  const parentMenu = inject(MAT_MENU_PANEL, { optional: true });
786
+ const renderer = inject(Renderer2);
811
787
  this._parentMaterialMenu = parentMenu instanceof MatMenu ? parentMenu : undefined;
812
- this._element.nativeElement.addEventListener('touchstart', this._handleTouchStart, passiveEventListenerOptions);
788
+ this._cleanupTouchstart = _bindEventWithOptions(renderer, this._element.nativeElement, 'touchstart', (event) => {
789
+ if (!isFakeTouchstartFromScreenReader(event)) {
790
+ this._openedBy = 'touch';
791
+ }
792
+ }, passiveEventListenerOptions);
813
793
  }
814
794
  ngAfterContentInit() {
815
795
  this._handleHover();
816
796
  }
817
797
  ngOnDestroy() {
818
- if (this._overlayRef) {
819
- this._overlayRef.dispose();
820
- this._overlayRef = null;
798
+ if (this.menu && this._ownsMenu(this.menu)) {
799
+ PANELS_TO_TRIGGERS.delete(this.menu);
821
800
  }
822
- this._element.nativeElement.removeEventListener('touchstart', this._handleTouchStart, passiveEventListenerOptions);
801
+ this._cleanupTouchstart();
802
+ this._pendingRemoval?.unsubscribe();
823
803
  this._menuCloseSubscription.unsubscribe();
824
804
  this._closingActionsSubscription.unsubscribe();
825
805
  this._hoverSubscription.unsubscribe();
806
+ if (this._overlayRef) {
807
+ this._overlayRef.dispose();
808
+ this._overlayRef = null;
809
+ }
826
810
  }
827
811
  /** Whether the menu is open. */
828
812
  get menuOpen() {
@@ -846,20 +830,33 @@ class MatMenuTrigger {
846
830
  if (this._menuOpen || !menu) {
847
831
  return;
848
832
  }
833
+ this._pendingRemoval?.unsubscribe();
834
+ const previousTrigger = PANELS_TO_TRIGGERS.get(menu);
835
+ PANELS_TO_TRIGGERS.set(menu, this);
836
+ // If the same menu is currently attached to another trigger,
837
+ // we need to close it so it doesn't end up in a broken state.
838
+ if (previousTrigger && previousTrigger !== this) {
839
+ previousTrigger.closeMenu();
840
+ }
849
841
  const overlayRef = this._createOverlay(menu);
850
842
  const overlayConfig = overlayRef.getConfig();
851
843
  const positionStrategy = overlayConfig.positionStrategy;
852
844
  this._setPosition(menu, positionStrategy);
853
845
  overlayConfig.hasBackdrop =
854
846
  menu.hasBackdrop == null ? !this.triggersSubmenu() : menu.hasBackdrop;
855
- overlayRef.attach(this._getPortal(menu));
856
- if (menu.lazyContent) {
857
- menu.lazyContent.attach(this.menuData);
847
+ // We need the `hasAttached` check for the case where the user kicked off a removal animation,
848
+ // but re-entered the menu. Re-attaching the same portal will trigger an error otherwise.
849
+ if (!overlayRef.hasAttached()) {
850
+ overlayRef.attach(this._getPortal(menu));
851
+ menu.lazyContent?.attach(this.menuData);
858
852
  }
859
853
  this._closingActionsSubscription = this._menuClosingActions().subscribe(() => this.closeMenu());
860
- this._initMenu(menu);
854
+ menu.parentMenu = this.triggersSubmenu() ? this._parentMaterialMenu : undefined;
855
+ menu.direction = this.dir;
856
+ menu.focusFirstItem(this._openedBy || 'program');
857
+ this._setIsMenuOpen(true);
861
858
  if (menu instanceof MatMenu) {
862
- menu._startAnimation();
859
+ menu._setIsOpen(true);
863
860
  menu._directDescendantItems.changes.pipe(takeUntil(menu.close)).subscribe(() => {
864
861
  // Re-adjust the position without locking when the amount of items
865
862
  // changes so that the overlay is allowed to pick a new optimal position.
@@ -892,12 +889,25 @@ class MatMenuTrigger {
892
889
  }
893
890
  /** Closes the menu and does the necessary cleanup. */
894
891
  _destroyMenu(reason) {
895
- if (!this._overlayRef || !this.menuOpen) {
892
+ const overlayRef = this._overlayRef;
893
+ const menu = this._menu;
894
+ if (!overlayRef || !this.menuOpen) {
896
895
  return;
897
896
  }
898
- const menu = this.menu;
899
897
  this._closingActionsSubscription.unsubscribe();
900
- this._overlayRef.detach();
898
+ this._pendingRemoval?.unsubscribe();
899
+ // Note that we don't wait for the animation to finish if another trigger took
900
+ // over the menu, because the panel will end up empty which looks glitchy.
901
+ if (menu instanceof MatMenu && this._ownsMenu(menu)) {
902
+ this._pendingRemoval = menu._animationDone.pipe(take(1)).subscribe(() => overlayRef.detach());
903
+ menu._setIsOpen(false);
904
+ }
905
+ else {
906
+ overlayRef.detach();
907
+ }
908
+ if (menu && this._ownsMenu(menu)) {
909
+ PANELS_TO_TRIGGERS.delete(menu);
910
+ }
901
911
  // Always restore focus if the user is navigating using the keyboard or the menu was opened
902
912
  // programmatically. We don't restore for non-root triggers, because it can prevent focus
903
913
  // from making it back to the root trigger when closing a long chain of menus by clicking
@@ -906,38 +916,7 @@ class MatMenuTrigger {
906
916
  this.focus(this._openedBy);
907
917
  }
908
918
  this._openedBy = undefined;
909
- if (menu instanceof MatMenu) {
910
- menu._resetAnimation();
911
- if (menu.lazyContent) {
912
- // Wait for the exit animation to finish before detaching the content.
913
- menu._animationDone
914
- .pipe(filter(event => event.toState === 'void'), take(1),
915
- // Interrupt if the content got re-attached.
916
- takeUntil(menu.lazyContent._attached))
917
- .subscribe({
918
- next: () => menu.lazyContent.detach(),
919
- // No matter whether the content got re-attached, reset the menu.
920
- complete: () => this._setIsMenuOpen(false),
921
- });
922
- }
923
- else {
924
- this._setIsMenuOpen(false);
925
- }
926
- }
927
- else {
928
- this._setIsMenuOpen(false);
929
- menu?.lazyContent?.detach();
930
- }
931
- }
932
- /**
933
- * This method sets the menu state to open and focuses the first item if
934
- * the menu was opened via the keyboard.
935
- */
936
- _initMenu(menu) {
937
- menu.parentMenu = this.triggersSubmenu() ? this._parentMaterialMenu : undefined;
938
- menu.direction = this.dir;
939
- menu.focusFirstItem(this._openedBy || 'program');
940
- this._setIsMenuOpen(true);
919
+ this._setIsMenuOpen(false);
941
920
  }
942
921
  // set state rather than toggle to support triggers sharing a menu
943
922
  _setIsMenuOpen(isOpen) {
@@ -1054,7 +1033,9 @@ class MatMenuTrigger {
1054
1033
  const detachments = this._overlayRef.detachments();
1055
1034
  const parentClose = this._parentMaterialMenu ? this._parentMaterialMenu.closed : of();
1056
1035
  const hover = this._parentMaterialMenu
1057
- ? this._parentMaterialMenu._hovered().pipe(filter(active => active !== this._menuItemInstance), filter(() => this._menuOpen))
1036
+ ? this._parentMaterialMenu
1037
+ ._hovered()
1038
+ .pipe(filter(active => this._menuOpen && active !== this._menuItemInstance))
1058
1039
  : of();
1059
1040
  return merge(backdrop, parentClose, hover, detachments);
1060
1041
  }
@@ -1100,31 +1081,14 @@ class MatMenuTrigger {
1100
1081
  /** Handles the cases where the user hovers over the trigger. */
1101
1082
  _handleHover() {
1102
1083
  // Subscribe to changes in the hovered item in order to toggle the panel.
1103
- if (!this.triggersSubmenu() || !this._parentMaterialMenu) {
1104
- return;
1084
+ if (this.triggersSubmenu() && this._parentMaterialMenu) {
1085
+ this._hoverSubscription = this._parentMaterialMenu._hovered().subscribe(active => {
1086
+ if (active === this._menuItemInstance && !active.disabled) {
1087
+ this._openedBy = 'mouse';
1088
+ this.openMenu();
1089
+ }
1090
+ });
1105
1091
  }
1106
- this._hoverSubscription = this._parentMaterialMenu
1107
- ._hovered()
1108
- // Since we might have multiple competing triggers for the same menu (e.g. a sub-menu
1109
- // with different data and triggers), we have to delay it by a tick to ensure that
1110
- // it won't be closed immediately after it is opened.
1111
- .pipe(filter(active => active === this._menuItemInstance && !active.disabled), delay(0, asapScheduler))
1112
- .subscribe(() => {
1113
- this._openedBy = 'mouse';
1114
- // If the same menu is used between multiple triggers, it might still be animating
1115
- // while the new trigger tries to re-open it. Wait for the animation to finish
1116
- // before doing so. Also interrupt if the user moves to another item.
1117
- if (this.menu instanceof MatMenu && this.menu._isAnimating) {
1118
- // We need the `delay(0)` here in order to avoid
1119
- // 'changed after checked' errors in some cases. See #12194.
1120
- this.menu._animationDone
1121
- .pipe(take(1), delay(0, asapScheduler), takeUntil(this._parentMaterialMenu._hovered()))
1122
- .subscribe(() => this.openMenu());
1123
- }
1124
- else {
1125
- this.openMenu();
1126
- }
1127
- });
1128
1092
  }
1129
1093
  /** Gets the portal that should be attached to the overlay. */
1130
1094
  _getPortal(menu) {
@@ -1136,10 +1100,18 @@ class MatMenuTrigger {
1136
1100
  }
1137
1101
  return this._portal;
1138
1102
  }
1139
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: MatMenuTrigger, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1140
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.0.0", type: MatMenuTrigger, isStandalone: true, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: { _deprecatedMatMenuTriggerFor: ["mat-menu-trigger-for", "_deprecatedMatMenuTriggerFor"], menu: ["matMenuTriggerFor", "menu"], menuData: ["matMenuTriggerData", "menuData"], restoreFocus: ["matMenuTriggerRestoreFocus", "restoreFocus"] }, outputs: { menuOpened: "menuOpened", onMenuOpen: "onMenuOpen", menuClosed: "menuClosed", onMenuClose: "onMenuClose" }, host: { listeners: { "click": "_handleClick($event)", "mousedown": "_handleMousedown($event)", "keydown": "_handleKeydown($event)" }, properties: { "attr.aria-haspopup": "menu ? \"menu\" : null", "attr.aria-expanded": "menuOpen", "attr.aria-controls": "menuOpen ? menu.panelId : null" }, classAttribute: "mat-mdc-menu-trigger" }, exportAs: ["matMenuTrigger"], ngImport: i0 });
1103
+ /**
1104
+ * Determines whether the trigger owns a specific menu panel, at the current point in time.
1105
+ * This allows us to distinguish the case where the same panel is passed into multiple triggers
1106
+ * and multiple are open at a time.
1107
+ */
1108
+ _ownsMenu(menu) {
1109
+ return PANELS_TO_TRIGGERS.get(menu) === this;
1110
+ }
1111
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.0-next.3", ngImport: i0, type: MatMenuTrigger, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1112
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.1.0-next.3", type: MatMenuTrigger, isStandalone: true, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: { _deprecatedMatMenuTriggerFor: ["mat-menu-trigger-for", "_deprecatedMatMenuTriggerFor"], menu: ["matMenuTriggerFor", "menu"], menuData: ["matMenuTriggerData", "menuData"], restoreFocus: ["matMenuTriggerRestoreFocus", "restoreFocus"] }, outputs: { menuOpened: "menuOpened", onMenuOpen: "onMenuOpen", menuClosed: "menuClosed", onMenuClose: "onMenuClose" }, host: { listeners: { "click": "_handleClick($event)", "mousedown": "_handleMousedown($event)", "keydown": "_handleKeydown($event)" }, properties: { "attr.aria-haspopup": "menu ? \"menu\" : null", "attr.aria-expanded": "menuOpen", "attr.aria-controls": "menuOpen ? menu.panelId : null" }, classAttribute: "mat-mdc-menu-trigger" }, exportAs: ["matMenuTrigger"], ngImport: i0 });
1141
1113
  }
1142
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: MatMenuTrigger, decorators: [{
1114
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.0-next.3", ngImport: i0, type: MatMenuTrigger, decorators: [{
1143
1115
  type: Directive,
1144
1116
  args: [{
1145
1117
  selector: `[mat-menu-trigger-for], [matMenuTriggerFor]`,
@@ -1177,8 +1149,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImpor
1177
1149
  }] } });
1178
1150
 
1179
1151
  class MatMenuModule {
1180
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: MatMenuModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1181
- static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.0.0", ngImport: i0, type: MatMenuModule, imports: [MatRippleModule,
1152
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.0-next.3", ngImport: i0, type: MatMenuModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1153
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.1.0-next.3", ngImport: i0, type: MatMenuModule, imports: [MatRippleModule,
1182
1154
  MatCommonModule,
1183
1155
  OverlayModule,
1184
1156
  MatMenu,
@@ -1190,12 +1162,12 @@ class MatMenuModule {
1190
1162
  MatMenuItem,
1191
1163
  MatMenuContent,
1192
1164
  MatMenuTrigger] });
1193
- static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: MatMenuModule, providers: [MAT_MENU_SCROLL_STRATEGY_FACTORY_PROVIDER], imports: [MatRippleModule,
1165
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.1.0-next.3", ngImport: i0, type: MatMenuModule, providers: [MAT_MENU_SCROLL_STRATEGY_FACTORY_PROVIDER], imports: [MatRippleModule,
1194
1166
  MatCommonModule,
1195
1167
  OverlayModule, CdkScrollableModule,
1196
1168
  MatCommonModule] });
1197
1169
  }
1198
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: MatMenuModule, decorators: [{
1170
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.0-next.3", ngImport: i0, type: MatMenuModule, decorators: [{
1199
1171
  type: NgModule,
1200
1172
  args: [{
1201
1173
  imports: [
@@ -1219,6 +1191,61 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImpor
1219
1191
  }]
1220
1192
  }] });
1221
1193
 
1194
+ /**
1195
+ * Animations used by the mat-menu component.
1196
+ * Animation duration and timing values are based on:
1197
+ * https://material.io/guidelines/components/menus.html#menus-usage
1198
+ * @docs-private
1199
+ * @deprecated No longer used, will be removed.
1200
+ * @breaking-change 21.0.0
1201
+ */
1202
+ const matMenuAnimations = {
1203
+ /**
1204
+ * This animation controls the menu panel's entry and exit from the page.
1205
+ *
1206
+ * When the menu panel is added to the DOM, it scales in and fades in its border.
1207
+ *
1208
+ * When the menu panel is removed from the DOM, it simply fades out after a brief
1209
+ * delay to display the ripple.
1210
+ */
1211
+ transformMenu: trigger('transformMenu', [
1212
+ state('void', style({
1213
+ opacity: 0,
1214
+ transform: 'scale(0.8)',
1215
+ })),
1216
+ transition('void => enter', animate('120ms cubic-bezier(0, 0, 0.2, 1)', style({
1217
+ opacity: 1,
1218
+ transform: 'scale(1)',
1219
+ }))),
1220
+ transition('* => void', animate('100ms 25ms linear', style({ opacity: 0 }))),
1221
+ ]),
1222
+ /**
1223
+ * This animation fades in the background color and content of the menu panel
1224
+ * after its containing element is scaled in.
1225
+ */
1226
+ fadeInItems: trigger('fadeInItems', [
1227
+ // TODO(crisbeto): this is inside the `transformMenu`
1228
+ // now. Remove next time we do breaking changes.
1229
+ state('showing', style({ opacity: 1 })),
1230
+ transition('void => *', [
1231
+ style({ opacity: 0 }),
1232
+ animate('400ms 100ms cubic-bezier(0.55, 0, 0.55, 0.2)'),
1233
+ ]),
1234
+ ]),
1235
+ };
1236
+ /**
1237
+ * @deprecated
1238
+ * @breaking-change 8.0.0
1239
+ * @docs-private
1240
+ */
1241
+ const fadeInItems = matMenuAnimations.fadeInItems;
1242
+ /**
1243
+ * @deprecated
1244
+ * @breaking-change 8.0.0
1245
+ * @docs-private
1246
+ */
1247
+ const transformMenu = matMenuAnimations.transformMenu;
1248
+
1222
1249
  /**
1223
1250
  * Generated bundle index. Do not edit.
1224
1251
  */