@angular/cdk-experimental 14.0.0-next.8 → 14.0.0-next.9

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 (95) hide show
  1. package/dialog/dialog-config.d.ts +6 -1
  2. package/esm2020/column-resize/column-resize-directives/column-resize-flex.mjs +3 -3
  3. package/esm2020/column-resize/column-resize-directives/column-resize.mjs +3 -3
  4. package/esm2020/column-resize/column-resize-directives/default-enabled-column-resize-flex.mjs +3 -3
  5. package/esm2020/column-resize/column-resize-directives/default-enabled-column-resize.mjs +3 -3
  6. package/esm2020/column-resize/column-resize-module.mjs +8 -8
  7. package/esm2020/column-resize/column-resize-notifier.mjs +6 -6
  8. package/esm2020/column-resize/column-resize.mjs +3 -3
  9. package/esm2020/column-resize/column-size-store.mjs +3 -3
  10. package/esm2020/column-resize/event-dispatcher.mjs +3 -3
  11. package/esm2020/column-resize/overlay-handle.mjs +3 -3
  12. package/esm2020/column-resize/resizable.mjs +3 -3
  13. package/esm2020/column-resize/resize-strategy.mjs +9 -9
  14. package/esm2020/combobox/combobox-module.mjs +4 -4
  15. package/esm2020/combobox/combobox-popup.mjs +3 -3
  16. package/esm2020/combobox/combobox.mjs +3 -3
  17. package/esm2020/dialog/dialog-config.mjs +1 -1
  18. package/esm2020/dialog/dialog-container.mjs +5 -5
  19. package/esm2020/dialog/dialog-module.mjs +4 -4
  20. package/esm2020/dialog/dialog.mjs +5 -5
  21. package/esm2020/listbox/listbox-module.mjs +4 -4
  22. package/esm2020/listbox/listbox.mjs +6 -6
  23. package/esm2020/menu/context-menu.mjs +12 -48
  24. package/esm2020/menu/menu-aim.mjs +6 -6
  25. package/esm2020/menu/menu-bar.mjs +39 -130
  26. package/esm2020/menu/menu-base.mjs +129 -0
  27. package/esm2020/menu/menu-group.mjs +9 -9
  28. package/esm2020/menu/menu-interface.mjs +1 -1
  29. package/esm2020/menu/menu-item-checkbox.mjs +3 -3
  30. package/esm2020/menu/menu-item-radio.mjs +4 -6
  31. package/esm2020/menu/menu-item-selectable.mjs +3 -3
  32. package/esm2020/menu/menu-item-trigger.mjs +30 -90
  33. package/esm2020/menu/menu-item.mjs +36 -22
  34. package/esm2020/menu/menu-module.mjs +4 -4
  35. package/esm2020/menu/menu-stack.mjs +26 -5
  36. package/esm2020/menu/menu-trigger.mjs +35 -8
  37. package/esm2020/menu/menu.mjs +43 -127
  38. package/esm2020/popover-edit/edit-event-dispatcher.mjs +3 -3
  39. package/esm2020/popover-edit/edit-ref.mjs +3 -3
  40. package/esm2020/popover-edit/edit-services.mjs +3 -3
  41. package/esm2020/popover-edit/focus-dispatcher.mjs +3 -3
  42. package/esm2020/popover-edit/focus-escape-notifier.mjs +3 -3
  43. package/esm2020/popover-edit/lens-directives.mjs +9 -9
  44. package/esm2020/popover-edit/popover-edit-module.mjs +4 -4
  45. package/esm2020/popover-edit/popover-edit-position-strategy-factory.mjs +6 -6
  46. package/esm2020/popover-edit/table-directives.mjs +15 -15
  47. package/esm2020/scrolling/auto-size-virtual-scroll.mjs +3 -3
  48. package/esm2020/scrolling/scrolling-module.mjs +4 -4
  49. package/esm2020/selection/row-selection.mjs +3 -3
  50. package/esm2020/selection/select-all.mjs +3 -3
  51. package/esm2020/selection/selection-column.mjs +3 -3
  52. package/esm2020/selection/selection-module.mjs +4 -4
  53. package/esm2020/selection/selection-toggle.mjs +3 -3
  54. package/esm2020/selection/selection.mjs +3 -3
  55. package/esm2020/table-scroll-container/table-scroll-container-module.mjs +4 -4
  56. package/esm2020/table-scroll-container/table-scroll-container.mjs +3 -3
  57. package/esm2020/version.mjs +1 -1
  58. package/fesm2015/cdk-experimental.mjs +1 -1
  59. package/fesm2015/cdk-experimental.mjs.map +1 -1
  60. package/fesm2015/column-resize.mjs +50 -50
  61. package/fesm2015/combobox.mjs +10 -10
  62. package/fesm2015/dialog.mjs +13 -12
  63. package/fesm2015/dialog.mjs.map +1 -1
  64. package/fesm2015/listbox.mjs +10 -10
  65. package/fesm2015/menu.mjs +353 -445
  66. package/fesm2015/menu.mjs.map +1 -1
  67. package/fesm2015/popover-edit.mjs +49 -49
  68. package/fesm2015/scrolling.mjs +7 -7
  69. package/fesm2015/selection.mjs +19 -19
  70. package/fesm2015/table-scroll-container.mjs +7 -7
  71. package/fesm2020/cdk-experimental.mjs +1 -1
  72. package/fesm2020/cdk-experimental.mjs.map +1 -1
  73. package/fesm2020/column-resize.mjs +50 -50
  74. package/fesm2020/combobox.mjs +10 -10
  75. package/fesm2020/dialog.mjs +12 -12
  76. package/fesm2020/dialog.mjs.map +1 -1
  77. package/fesm2020/listbox.mjs +10 -10
  78. package/fesm2020/menu.mjs +345 -435
  79. package/fesm2020/menu.mjs.map +1 -1
  80. package/fesm2020/popover-edit.mjs +49 -49
  81. package/fesm2020/scrolling.mjs +7 -7
  82. package/fesm2020/selection.mjs +19 -19
  83. package/fesm2020/table-scroll-container.mjs +7 -7
  84. package/menu/context-menu.d.ts +3 -24
  85. package/menu/menu-bar.d.ts +9 -50
  86. package/menu/menu-base.d.ts +64 -0
  87. package/menu/menu-group.d.ts +2 -2
  88. package/menu/menu-interface.d.ts +1 -1
  89. package/menu/menu-item-radio.d.ts +2 -2
  90. package/menu/menu-item-trigger.d.ts +4 -27
  91. package/menu/menu-item.d.ts +3 -3
  92. package/menu/menu-stack.d.ts +17 -2
  93. package/menu/menu-trigger.d.ts +29 -5
  94. package/menu/menu.d.ts +9 -49
  95. package/package.json +2 -2
package/fesm2020/menu.mjs CHANGED
@@ -1,16 +1,16 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, Injectable, Directive, Injector, Inject, EventEmitter, Optional, SkipSelf, Input, Output, Self, ContentChildren, NgModule } from '@angular/core';
2
+ import { InjectionToken, Optional, SkipSelf, Inject, Injectable, Directive, EventEmitter, Injector, Self, Input, Output, ContentChildren, NgModule } from '@angular/core';
3
3
  import * as i1 from '@angular/cdk/overlay';
4
4
  import { OverlayConfig, STANDARD_DROPDOWN_BELOW_POSITIONS, STANDARD_DROPDOWN_ADJACENT_POSITIONS, OverlayModule } from '@angular/cdk/overlay';
5
- import { FocusKeyManager } from '@angular/cdk/a11y';
6
5
  import { UP_ARROW, DOWN_ARROW, LEFT_ARROW, RIGHT_ARROW, ENTER, SPACE, TAB, ESCAPE, hasModifierKey } from '@angular/cdk/keycodes';
7
6
  import * as i1$1 from '@angular/cdk/bidi';
8
- import { Subject, fromEvent, merge, defer, partition } from 'rxjs';
9
- import { filter, takeUntil, startWith, mergeMap, mapTo, mergeAll, take, switchMap, skip } from 'rxjs/operators';
7
+ import { filter, takeUntil, startWith, mergeMap, mapTo, mergeAll, switchMap, take, skip } from 'rxjs/operators';
10
8
  import * as i1$2 from '@angular/cdk/collections';
11
9
  import { UniqueSelectionDispatcher } from '@angular/cdk/collections';
12
10
  import { coerceBooleanProperty } from '@angular/cdk/coercion';
11
+ import { Subject, fromEvent, merge, defer, partition } from 'rxjs';
13
12
  import { TemplatePortal } from '@angular/cdk/portal';
13
+ import { FocusKeyManager } from '@angular/cdk/a11y';
14
14
 
15
15
  /**
16
16
  * @license
@@ -31,6 +31,18 @@ const CDK_MENU = new InjectionToken('cdk-menu');
31
31
  */
32
32
  /** Injection token used for an implementation of MenuStack. */
33
33
  const MENU_STACK = new InjectionToken('cdk-menu-stack');
34
+ /** A provider that provides the parent menu stack, or a new menu stack if there is no parent one. */
35
+ const PARENT_OR_NEW_MENU_STACK_PROVIDER = {
36
+ provide: MENU_STACK,
37
+ deps: [[new Optional(), new SkipSelf(), new Inject(MENU_STACK)]],
38
+ useFactory: (parentMenuStack) => parentMenuStack || new MenuStack(),
39
+ };
40
+ /** A provider that provides the parent menu stack, or a new menu stack if there is no parent one. */
41
+ const PARENT_OR_NEW_INLINE_MENU_STACK_PROVIDER = {
42
+ provide: MENU_STACK,
43
+ deps: [[new Optional(), new SkipSelf(), new Inject(MENU_STACK)]],
44
+ useFactory: (parentMenuStack) => parentMenuStack || MenuStack.inline(),
45
+ };
34
46
  /**
35
47
  * MenuStack allows subscribers to listen for close events (when a MenuStackItem is popped off
36
48
  * of the stack) in order to perform closing actions. Upon the MenuStack being empty it emits
@@ -53,6 +65,12 @@ class MenuStack {
53
65
  * perform.
54
66
  */
55
67
  this.emptied = this._empty;
68
+ this._hasInlineMenu = false;
69
+ }
70
+ static inline() {
71
+ const stack = new MenuStack();
72
+ stack._hasInlineMenu = true;
73
+ return stack;
56
74
  }
57
75
  /** @param menu the MenuStackItem to put on the stack. */
58
76
  push(menu) {
@@ -122,10 +140,13 @@ class MenuStack {
122
140
  peek() {
123
141
  return this._elements[this._elements.length - 1];
124
142
  }
143
+ hasInlineMenu() {
144
+ return this._hasInlineMenu;
145
+ }
125
146
  }
126
- MenuStack.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.6", ngImport: i0, type: MenuStack, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
127
- MenuStack.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.6", ngImport: i0, type: MenuStack });
128
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.6", ngImport: i0, type: MenuStack, decorators: [{
147
+ MenuStack.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: MenuStack, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
148
+ MenuStack.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: MenuStack });
149
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: MenuStack, decorators: [{
129
150
  type: Injectable
130
151
  }] });
131
152
 
@@ -323,9 +344,9 @@ class TargetMenuAim {
323
344
  this._destroyed.complete();
324
345
  }
325
346
  }
326
- TargetMenuAim.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.6", ngImport: i0, type: TargetMenuAim, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
327
- TargetMenuAim.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.6", ngImport: i0, type: TargetMenuAim });
328
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.6", ngImport: i0, type: TargetMenuAim, decorators: [{
347
+ TargetMenuAim.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: TargetMenuAim, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
348
+ TargetMenuAim.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: TargetMenuAim });
349
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: TargetMenuAim, decorators: [{
329
350
  type: Injectable
330
351
  }], ctorParameters: function () { return [{ type: i0.NgZone }]; } });
331
352
  /**
@@ -334,9 +355,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.6",
334
355
  */
335
356
  class CdkTargetMenuAim {
336
357
  }
337
- CdkTargetMenuAim.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.6", ngImport: i0, type: CdkTargetMenuAim, deps: [], target: i0.ɵɵFactoryTarget.Directive });
338
- CdkTargetMenuAim.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.6", type: CdkTargetMenuAim, selector: "[cdkTargetMenuAim]", providers: [{ provide: MENU_AIM, useClass: TargetMenuAim }], exportAs: ["cdkTargetMenuAim"], ngImport: i0 });
339
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.6", ngImport: i0, type: CdkTargetMenuAim, decorators: [{
358
+ CdkTargetMenuAim.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: CdkTargetMenuAim, deps: [], target: i0.ɵɵFactoryTarget.Directive });
359
+ CdkTargetMenuAim.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.9", type: CdkTargetMenuAim, selector: "[cdkTargetMenuAim]", providers: [{ provide: MENU_AIM, useClass: TargetMenuAim }], exportAs: ["cdkTargetMenuAim"], ngImport: i0 });
360
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: CdkTargetMenuAim, decorators: [{
340
361
  type: Directive,
341
362
  args: [{
342
363
  selector: '[cdkTargetMenuAim]',
@@ -358,6 +379,28 @@ class MenuTrigger {
358
379
  constructor(injector, menuStack) {
359
380
  this.injector = injector;
360
381
  this.menuStack = menuStack;
382
+ /** Emits when the attached menu is requested to open */
383
+ this.opened = new EventEmitter();
384
+ /** Emits when the attached menu is requested to close */
385
+ this.closed = new EventEmitter();
386
+ /** A reference to the overlay which manages the triggered menu */
387
+ this._overlayRef = null;
388
+ /** Emits when this trigger is destroyed. */
389
+ this._destroyed = new Subject();
390
+ /** Emits when the outside pointer events listener on the overlay should be stopped. */
391
+ this._stopOutsideClicksListener = merge(this.closed, this._destroyed);
392
+ }
393
+ ngOnDestroy() {
394
+ this._destroyOverlay();
395
+ this._destroyed.next();
396
+ this._destroyed.complete();
397
+ }
398
+ /** Whether the attached menu is open. */
399
+ isOpen() {
400
+ return !!this._overlayRef?.hasAttached();
401
+ }
402
+ registerChildMenu(child) {
403
+ this.childMenu = child;
361
404
  }
362
405
  getChildMenuInjector() {
363
406
  this._childMenuInjector =
@@ -371,14 +414,18 @@ class MenuTrigger {
371
414
  });
372
415
  return this._childMenuInjector;
373
416
  }
374
- registerChildMenu(child) {
375
- this.childMenu = child;
417
+ /** Destroy and unset the overlay reference it if exists */
418
+ _destroyOverlay() {
419
+ if (this._overlayRef) {
420
+ this._overlayRef.dispose();
421
+ this._overlayRef = null;
422
+ }
376
423
  }
377
424
  }
378
- MenuTrigger.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.6", ngImport: i0, type: MenuTrigger, deps: [{ token: i0.Injector }, { token: MENU_STACK }], target: i0.ɵɵFactoryTarget.Injectable });
379
- MenuTrigger.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.6", ngImport: i0, type: MenuTrigger });
380
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.6", ngImport: i0, type: MenuTrigger, decorators: [{
381
- type: Injectable
425
+ MenuTrigger.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: MenuTrigger, deps: [{ token: i0.Injector }, { token: MENU_STACK }], target: i0.ɵɵFactoryTarget.Directive });
426
+ MenuTrigger.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.9", type: MenuTrigger, ngImport: i0 });
427
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: MenuTrigger, decorators: [{
428
+ type: Directive
382
429
  }], ctorParameters: function () { return [{ type: i0.Injector }, { type: MenuStack, decorators: [{
383
430
  type: Inject,
384
431
  args: [MENU_STACK]
@@ -425,28 +472,16 @@ class CdkMenuItemTrigger extends MenuTrigger {
425
472
  this._parentMenu = _parentMenu;
426
473
  this._menuAim = _menuAim;
427
474
  this._directionality = _directionality;
428
- /** Emits when the attached menu is requested to open */
429
- this.opened = new EventEmitter();
430
- /** Emits when the attached menu is requested to close */
431
- this.closed = new EventEmitter();
432
- /** A reference to the overlay which manages the triggered menu */
433
- this._overlayRef = null;
434
- /** Emits when this trigger is destroyed. */
435
- this._destroyed = new Subject();
436
- /** Emits when the outside pointer events listener on the overlay should be stopped. */
437
- this._stopOutsideClicksListener = merge(this.closed, this._destroyed);
438
475
  this._registerCloseHandler();
439
476
  this._subscribeToMouseEnter();
440
477
  }
441
478
  /** Open/close the attached menu if the trigger has been configured with one */
442
479
  toggle() {
443
- if (this.hasMenu()) {
444
- this.isMenuOpen() ? this.closeMenu() : this.openMenu();
445
- }
480
+ this.isOpen() ? this.close() : this.open();
446
481
  }
447
482
  /** Open the attached menu. */
448
- openMenu() {
449
- if (!this.isMenuOpen()) {
483
+ open() {
484
+ if (!this.isOpen()) {
450
485
  this.opened.next();
451
486
  this._overlayRef = this._overlayRef || this._overlay.create(this._getOverlayConfig());
452
487
  this._overlayRef.attach(this._getPortal());
@@ -454,21 +489,13 @@ class CdkMenuItemTrigger extends MenuTrigger {
454
489
  }
455
490
  }
456
491
  /** Close the opened menu. */
457
- closeMenu() {
458
- if (this.isMenuOpen()) {
492
+ close() {
493
+ if (this.isOpen()) {
459
494
  this.closed.next();
460
495
  this._overlayRef.detach();
461
496
  }
462
497
  this._closeSiblingTriggers();
463
498
  }
464
- /** Return true if the trigger has an attached menu */
465
- hasMenu() {
466
- return !!this._menuTemplateRef;
467
- }
468
- /** Whether the menu this button is a trigger for is open */
469
- isMenuOpen() {
470
- return this._overlayRef ? this._overlayRef.hasAttached() : false;
471
- }
472
499
  /**
473
500
  * Get a reference to the rendered Menu if the Menu is open and it is visible in the DOM.
474
501
  * @return the menu if it is open, otherwise undefined.
@@ -484,11 +511,11 @@ class CdkMenuItemTrigger extends MenuTrigger {
484
511
  // Closes any sibling menu items and opens the menu associated with this trigger.
485
512
  const toggleMenus = () => this._ngZone.run(() => {
486
513
  this._closeSiblingTriggers();
487
- this.openMenu();
514
+ this.open();
488
515
  });
489
516
  this._ngZone.runOutsideAngular(() => {
490
517
  fromEvent(this._elementRef.nativeElement, 'mouseenter')
491
- .pipe(filter(() => !this.menuStack.isEmpty() && !this.isMenuOpen()), takeUntil(this._destroyed))
518
+ .pipe(filter(() => !this.menuStack.isEmpty() && !this.isOpen()), takeUntil(this._destroyed))
492
519
  .subscribe(() => {
493
520
  if (this._menuAim) {
494
521
  this._menuAim.toggle(toggleMenus);
@@ -514,34 +541,24 @@ class CdkMenuItemTrigger extends MenuTrigger {
514
541
  this.childMenu?.focusFirstItem('keyboard');
515
542
  break;
516
543
  case RIGHT_ARROW:
517
- if (this._parentMenu && this._isParentVertical()) {
544
+ if (this._parentMenu && this._isParentVertical() && this._directionality?.value !== 'rtl') {
518
545
  event.preventDefault();
519
- if (this._directionality?.value === 'rtl') {
520
- this.menuStack.close(this._parentMenu, 2 /* currentItem */);
521
- }
522
- else {
523
- this.openMenu();
524
- this.childMenu?.focusFirstItem('keyboard');
525
- }
546
+ this.open();
547
+ this.childMenu?.focusFirstItem('keyboard');
526
548
  }
527
549
  break;
528
550
  case LEFT_ARROW:
529
- if (this._parentMenu && this._isParentVertical()) {
551
+ if (this._parentMenu && this._isParentVertical() && this._directionality?.value === 'rtl') {
530
552
  event.preventDefault();
531
- if (this._directionality?.value === 'rtl') {
532
- this.openMenu();
533
- this.childMenu?.focusFirstItem('keyboard');
534
- }
535
- else {
536
- this.menuStack.close(this._parentMenu, 2 /* currentItem */);
537
- }
553
+ this.open();
554
+ this.childMenu?.focusFirstItem('keyboard');
538
555
  }
539
556
  break;
540
557
  case DOWN_ARROW:
541
558
  case UP_ARROW:
542
559
  if (!this._isParentVertical()) {
543
560
  event.preventDefault();
544
- this.openMenu();
561
+ this.open();
545
562
  keyCode === DOWN_ARROW
546
563
  ? this.childMenu?.focusFirstItem('keyboard')
547
564
  : this.childMenu?.focusLastItem('keyboard');
@@ -612,16 +629,11 @@ class CdkMenuItemTrigger extends MenuTrigger {
612
629
  if (!this._parentMenu) {
613
630
  this.menuStack.closed.pipe(takeUntil(this._destroyed)).subscribe(item => {
614
631
  if (item === this.childMenu) {
615
- this.closeMenu();
632
+ this.close();
616
633
  }
617
634
  });
618
635
  }
619
636
  }
620
- ngOnDestroy() {
621
- this._destroyOverlay();
622
- this._destroyed.next();
623
- this._destroyed.complete();
624
- }
625
637
  /**
626
638
  * Subscribe to the overlays outside pointer events stream and handle closing out the stack if a
627
639
  * click occurs outside the menus.
@@ -638,42 +650,29 @@ class CdkMenuItemTrigger extends MenuTrigger {
638
650
  });
639
651
  }
640
652
  }
641
- /** Destroy and unset the overlay reference it if exists */
642
- _destroyOverlay() {
643
- if (this._overlayRef) {
644
- this._overlayRef.dispose();
645
- this._overlayRef = null;
646
- }
647
- }
648
653
  }
649
- CdkMenuItemTrigger.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.6", ngImport: i0, type: CdkMenuItemTrigger, deps: [{ token: i0.Injector }, { token: i0.ElementRef }, { token: i0.ViewContainerRef }, { token: i1.Overlay }, { token: i0.NgZone }, { token: MENU_STACK }, { token: CDK_MENU, optional: true }, { token: MENU_AIM, optional: true }, { token: i1$1.Directionality, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
650
- CdkMenuItemTrigger.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.6", type: CdkMenuItemTrigger, selector: "[cdkMenuTriggerFor]", inputs: { _menuTemplateRef: ["cdkMenuTriggerFor", "_menuTemplateRef"], menuPosition: ["cdkMenuPosition", "menuPosition"] }, outputs: { opened: "cdkMenuOpened", closed: "cdkMenuClosed" }, host: { attributes: { "aria-haspopup": "menu" }, listeners: { "keydown": "_toggleOnKeydown($event)", "click": "toggle()" }, properties: { "attr.aria-expanded": "isMenuOpen()" }, classAttribute: "cdk-menu-trigger" }, providers: [
654
+ CdkMenuItemTrigger.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: CdkMenuItemTrigger, deps: [{ token: i0.Injector }, { token: i0.ElementRef }, { token: i0.ViewContainerRef }, { token: i1.Overlay }, { token: i0.NgZone }, { token: MENU_STACK }, { token: CDK_MENU, optional: true }, { token: MENU_AIM, optional: true }, { token: i1$1.Directionality, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
655
+ CdkMenuItemTrigger.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.9", type: CdkMenuItemTrigger, selector: "[cdkMenuTriggerFor]", inputs: { _menuTemplateRef: ["cdkMenuTriggerFor", "_menuTemplateRef"], menuPosition: ["cdkMenuPosition", "menuPosition"] }, outputs: { opened: "cdkMenuOpened", closed: "cdkMenuClosed" }, host: { attributes: { "aria-haspopup": "menu" }, listeners: { "keydown": "_toggleOnKeydown($event)", "click": "toggle()" }, properties: { "attr.aria-expanded": "isOpen()" }, classAttribute: "cdk-menu-trigger" }, providers: [
651
656
  { provide: MENU_TRIGGER, useExisting: CdkMenuItemTrigger },
652
- {
653
- provide: MENU_STACK,
654
- deps: [[new Optional(), new SkipSelf(), new Inject(MENU_STACK)]],
655
- useFactory: (parentMenuStack) => parentMenuStack || new MenuStack(),
656
- },
657
+ PARENT_OR_NEW_MENU_STACK_PROVIDER,
657
658
  ], exportAs: ["cdkMenuTriggerFor"], usesInheritance: true, ngImport: i0 });
658
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.6", ngImport: i0, type: CdkMenuItemTrigger, decorators: [{
659
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: CdkMenuItemTrigger, decorators: [{
659
660
  type: Directive,
660
661
  args: [{
661
662
  selector: '[cdkMenuTriggerFor]',
662
663
  exportAs: 'cdkMenuTriggerFor',
663
664
  host: {
664
- '(keydown)': '_toggleOnKeydown($event)',
665
- '(click)': 'toggle()',
666
665
  'class': 'cdk-menu-trigger',
667
666
  'aria-haspopup': 'menu',
668
- '[attr.aria-expanded]': 'isMenuOpen()',
667
+ '(keydown)': '_toggleOnKeydown($event)',
668
+ '(click)': 'toggle()',
669
+ '[attr.aria-expanded]': 'isOpen()',
669
670
  },
671
+ inputs: ['_menuTemplateRef: cdkMenuTriggerFor', 'menuPosition: cdkMenuPosition'],
672
+ outputs: ['opened: cdkMenuOpened', 'closed: cdkMenuClosed'],
670
673
  providers: [
671
674
  { provide: MENU_TRIGGER, useExisting: CdkMenuItemTrigger },
672
- {
673
- provide: MENU_STACK,
674
- deps: [[new Optional(), new SkipSelf(), new Inject(MENU_STACK)]],
675
- useFactory: (parentMenuStack) => parentMenuStack || new MenuStack(),
676
- },
675
+ PARENT_OR_NEW_MENU_STACK_PROVIDER,
677
676
  ],
678
677
  }]
679
678
  }], ctorParameters: function () { return [{ type: i0.Injector }, { type: i0.ElementRef }, { type: i0.ViewContainerRef }, { type: i1.Overlay }, { type: i0.NgZone }, { type: MenuStack, decorators: [{
@@ -691,19 +690,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.6",
691
690
  args: [MENU_AIM]
692
691
  }] }, { type: i1$1.Directionality, decorators: [{
693
692
  type: Optional
694
- }] }]; }, propDecorators: { _menuTemplateRef: [{
695
- type: Input,
696
- args: ['cdkMenuTriggerFor']
697
- }], menuPosition: [{
698
- type: Input,
699
- args: ['cdkMenuPosition']
700
- }], opened: [{
701
- type: Output,
702
- args: ['cdkMenuOpened']
703
- }], closed: [{
704
- type: Output,
705
- args: ['cdkMenuClosed']
706
- }] } });
693
+ }] }]; } });
707
694
 
708
695
  /**
709
696
  * @license
@@ -774,7 +761,7 @@ class CdkMenuItem {
774
761
  return;
775
762
  }
776
763
  // don't set the tabindex if there are no open sibling or parent menus
777
- if (!event || !this._menuStack?.isEmpty()) {
764
+ if (!event || !this._menuStack.isEmpty()) {
778
765
  this._tabindex = 0;
779
766
  }
780
767
  }
@@ -789,16 +776,16 @@ class CdkMenuItem {
789
776
  trigger() {
790
777
  if (!this.disabled && !this.hasMenu()) {
791
778
  this.triggered.next();
792
- this._menuStack?.closeAll();
779
+ this._menuStack.closeAll();
793
780
  }
794
781
  }
795
782
  /** Whether the menu item opens a menu. */
796
783
  hasMenu() {
797
- return !!this._menuTrigger?.hasMenu();
784
+ return !!this._menuTrigger;
798
785
  }
799
786
  /** Return true if this MenuItem has an attached menu and it is open. */
800
787
  isMenuOpen() {
801
- return !!this._menuTrigger?.isMenuOpen();
788
+ return !!this._menuTrigger?.isOpen();
802
789
  }
803
790
  /**
804
791
  * Get a reference to the rendered Menu if the Menu is open and it is visible in the DOM.
@@ -829,19 +816,35 @@ class CdkMenuItem {
829
816
  this.trigger();
830
817
  break;
831
818
  case RIGHT_ARROW:
832
- if (this._parentMenu && this._isParentVertical() && !this.hasMenu()) {
833
- event.preventDefault();
834
- this._dir?.value === 'rtl'
835
- ? this._menuStack?.close(this._parentMenu, 1 /* previousItem */)
836
- : this._menuStack?.closeAll(0 /* nextItem */);
819
+ if (this._parentMenu && this._isParentVertical()) {
820
+ if (this._dir?.value === 'rtl') {
821
+ if (this._menuStack.hasInlineMenu() || this._menuStack.length() > 1) {
822
+ event.preventDefault();
823
+ this._menuStack.close(this._parentMenu, 1 /* previousItem */);
824
+ }
825
+ }
826
+ else if (!this.hasMenu()) {
827
+ if (this._menuStack.hasInlineMenu()) {
828
+ event.preventDefault();
829
+ this._menuStack.closeAll(0 /* nextItem */);
830
+ }
831
+ }
837
832
  }
838
833
  break;
839
834
  case LEFT_ARROW:
840
- if (this._parentMenu && this._isParentVertical() && !this.hasMenu()) {
841
- event.preventDefault();
842
- this._dir?.value === 'rtl'
843
- ? this._menuStack?.closeAll(0 /* nextItem */)
844
- : this._menuStack?.close(this._parentMenu, 1 /* previousItem */);
835
+ if (this._parentMenu && this._isParentVertical()) {
836
+ if (this._dir?.value !== 'rtl') {
837
+ if (this._menuStack.hasInlineMenu() || this._menuStack.length() > 1) {
838
+ event.preventDefault();
839
+ this._menuStack.close(this._parentMenu, 1 /* previousItem */);
840
+ }
841
+ }
842
+ else if (!this.hasMenu()) {
843
+ if (this._menuStack.hasInlineMenu()) {
844
+ event.preventDefault();
845
+ this._menuStack.closeAll(0 /* nextItem */);
846
+ }
847
+ }
845
848
  }
846
849
  break;
847
850
  }
@@ -852,9 +855,9 @@ class CdkMenuItem {
852
855
  */
853
856
  _setupMouseEnter() {
854
857
  if (!this._isStandaloneItem()) {
855
- const closeOpenSiblings = () => this._ngZone.run(() => this._menuStack?.closeSubMenuOf(this._parentMenu));
858
+ const closeOpenSiblings = () => this._ngZone.run(() => this._menuStack.closeSubMenuOf(this._parentMenu));
856
859
  this._ngZone.runOutsideAngular(() => fromEvent(this._elementRef.nativeElement, 'mouseenter')
857
- .pipe(filter(() => !this._menuStack?.isEmpty() && !this.hasMenu()), takeUntil(this._destroyed))
860
+ .pipe(filter(() => !this._menuStack.isEmpty() && !this.hasMenu()), takeUntil(this._destroyed))
858
861
  .subscribe(() => {
859
862
  if (this._menuAim) {
860
863
  this._menuAim.toggle(closeOpenSiblings);
@@ -876,9 +879,9 @@ class CdkMenuItem {
876
879
  this._destroyed.next();
877
880
  }
878
881
  }
879
- CdkMenuItem.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.6", ngImport: i0, type: CdkMenuItem, deps: [{ token: i0.ElementRef }, { token: i0.NgZone }, { token: MENU_STACK, optional: true }, { token: CDK_MENU, optional: true }, { token: MENU_AIM, optional: true }, { token: i1$1.Directionality, optional: true }, { token: CdkMenuItemTrigger, optional: true, self: true }], target: i0.ɵɵFactoryTarget.Directive });
880
- CdkMenuItem.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.6", type: CdkMenuItem, selector: "[cdkMenuItem]", inputs: { disabled: "disabled", typeahead: "typeahead" }, outputs: { triggered: "cdkMenuItemTriggered" }, host: { attributes: { "type": "button", "role": "menuitem" }, listeners: { "blur": "_resetTabIndex()", "mouseout": "_resetTabIndex()", "focus": "_setTabIndex()", "mouseenter": "_setTabIndex($event)", "click": "trigger()", "keydown": "_onKeydown($event)" }, properties: { "tabindex": "_tabindex", "attr.aria-disabled": "disabled || null" }, classAttribute: "cdk-menu-item" }, exportAs: ["cdkMenuItem"], ngImport: i0 });
881
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.6", ngImport: i0, type: CdkMenuItem, decorators: [{
882
+ CdkMenuItem.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: CdkMenuItem, deps: [{ token: i0.ElementRef }, { token: i0.NgZone }, { token: MENU_STACK }, { token: CDK_MENU, optional: true }, { token: MENU_AIM, optional: true }, { token: i1$1.Directionality, optional: true }, { token: CdkMenuItemTrigger, optional: true, self: true }], target: i0.ɵɵFactoryTarget.Directive });
883
+ CdkMenuItem.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.9", type: CdkMenuItem, selector: "[cdkMenuItem]", inputs: { disabled: "disabled", typeahead: "typeahead" }, outputs: { triggered: "cdkMenuItemTriggered" }, host: { attributes: { "type": "button", "role": "menuitem" }, listeners: { "blur": "_resetTabIndex()", "mouseout": "_resetTabIndex()", "focus": "_setTabIndex()", "mouseenter": "_setTabIndex($event)", "click": "trigger()", "keydown": "_onKeydown($event)" }, properties: { "tabindex": "_tabindex", "attr.aria-disabled": "disabled || null" }, classAttribute: "cdk-menu-item" }, exportAs: ["cdkMenuItem"], ngImport: i0 });
884
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: CdkMenuItem, decorators: [{
882
885
  type: Directive,
883
886
  args: [{
884
887
  selector: '[cdkMenuItem]',
@@ -898,8 +901,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.6",
898
901
  },
899
902
  }]
900
903
  }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.NgZone }, { type: MenuStack, decorators: [{
901
- type: Optional
902
- }, {
903
904
  type: Inject,
904
905
  args: [MENU_STACK]
905
906
  }] }, { type: undefined, decorators: [{
@@ -965,9 +966,9 @@ class CdkMenuItemSelectable extends CdkMenuItem {
965
966
  }
966
967
  }
967
968
  }
968
- CdkMenuItemSelectable.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.6", ngImport: i0, type: CdkMenuItemSelectable, deps: null, target: i0.ɵɵFactoryTarget.Directive });
969
- CdkMenuItemSelectable.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.6", type: CdkMenuItemSelectable, inputs: { checked: "checked", name: "name", id: "id" }, outputs: { toggled: "cdkMenuItemToggled" }, usesInheritance: true, ngImport: i0 });
970
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.6", ngImport: i0, type: CdkMenuItemSelectable, decorators: [{
969
+ CdkMenuItemSelectable.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: CdkMenuItemSelectable, deps: null, target: i0.ɵɵFactoryTarget.Directive });
970
+ CdkMenuItemSelectable.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.9", type: CdkMenuItemSelectable, inputs: { checked: "checked", name: "name", id: "id" }, outputs: { toggled: "cdkMenuItemToggled" }, usesInheritance: true, ngImport: i0 });
971
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: CdkMenuItemSelectable, decorators: [{
971
972
  type: Directive
972
973
  }], propDecorators: { toggled: [{
973
974
  type: Output,
@@ -1001,6 +1002,10 @@ class CdkMenuGroup {
1001
1002
  ngAfterContentInit() {
1002
1003
  this._registerMenuSelectionListeners();
1003
1004
  }
1005
+ ngOnDestroy() {
1006
+ this._selectableChanges.next();
1007
+ this._selectableChanges.complete();
1008
+ }
1004
1009
  /**
1005
1010
  * Register the child selectable elements with the change emitter and ensure any new child
1006
1011
  * elements do so as well.
@@ -1018,14 +1023,10 @@ class CdkMenuGroup {
1018
1023
  .pipe(takeUntil(this._selectableChanges))
1019
1024
  .subscribe(() => this.change.next(selectable));
1020
1025
  }
1021
- ngOnDestroy() {
1022
- this._selectableChanges.next();
1023
- this._selectableChanges.complete();
1024
- }
1025
1026
  }
1026
- CdkMenuGroup.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.6", ngImport: i0, type: CdkMenuGroup, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1027
- CdkMenuGroup.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.6", type: CdkMenuGroup, selector: "[cdkMenuGroup]", outputs: { change: "change" }, host: { attributes: { "role": "group" }, classAttribute: "cdk-menu-group" }, providers: [{ provide: UniqueSelectionDispatcher, useClass: UniqueSelectionDispatcher }], queries: [{ propertyName: "_selectableItems", predicate: CdkMenuItemSelectable, descendants: true }], exportAs: ["cdkMenuGroup"], ngImport: i0 });
1028
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.6", ngImport: i0, type: CdkMenuGroup, decorators: [{
1027
+ CdkMenuGroup.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: CdkMenuGroup, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1028
+ CdkMenuGroup.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.9", type: CdkMenuGroup, selector: "[cdkMenuGroup]", outputs: { change: "change" }, host: { attributes: { "role": "group" }, classAttribute: "cdk-menu-group" }, providers: [{ provide: UniqueSelectionDispatcher, useClass: UniqueSelectionDispatcher }], queries: [{ propertyName: "_selectableItems", predicate: CdkMenuItemSelectable, descendants: true }], exportAs: ["cdkMenuGroup"], ngImport: i0 });
1029
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: CdkMenuGroup, decorators: [{
1029
1030
  type: Directive,
1030
1031
  args: [{
1031
1032
  selector: '[cdkMenuGroup]',
@@ -1090,6 +1091,124 @@ class PointerFocusTracker {
1090
1091
  }
1091
1092
  }
1092
1093
 
1094
+ /**
1095
+ * @license
1096
+ * Copyright Google LLC All Rights Reserved.
1097
+ *
1098
+ * Use of this source code is governed by an MIT-style license that can be
1099
+ * found in the LICENSE file at https://angular.io/license
1100
+ */
1101
+ class CdkMenuBase extends CdkMenuGroup {
1102
+ constructor(_elementRef, menuStack, dir) {
1103
+ super();
1104
+ this._elementRef = _elementRef;
1105
+ this.menuStack = menuStack;
1106
+ this.dir = dir;
1107
+ /**
1108
+ * Sets the aria-orientation attribute and determines where menus will be opened.
1109
+ * Does not affect styling/layout.
1110
+ */
1111
+ this.orientation = 'vertical';
1112
+ /** Emits when the MenuBar is destroyed. */
1113
+ this.destroyed = new Subject();
1114
+ }
1115
+ ngAfterContentInit() {
1116
+ super.ngAfterContentInit();
1117
+ this._setKeyManager();
1118
+ this._subscribeToMenuOpen();
1119
+ this._subscribeToMenuStackClosed();
1120
+ }
1121
+ ngOnDestroy() {
1122
+ super.ngOnDestroy();
1123
+ this.destroyed.next();
1124
+ this.destroyed.complete();
1125
+ }
1126
+ /** Place focus on the first MenuItem in the menu and set the focus origin. */
1127
+ focusFirstItem(focusOrigin = 'program') {
1128
+ this.keyManager.setFocusOrigin(focusOrigin);
1129
+ this.keyManager.setFirstItemActive();
1130
+ }
1131
+ /** Place focus on the last MenuItem in the menu and set the focus origin. */
1132
+ focusLastItem(focusOrigin = 'program') {
1133
+ this.keyManager.setFocusOrigin(focusOrigin);
1134
+ this.keyManager.setLastItemActive();
1135
+ }
1136
+ /** Return true if this menu has been configured in a horizontal orientation. */
1137
+ isHorizontal() {
1138
+ return this.orientation === 'horizontal';
1139
+ }
1140
+ /** Return true if the MenuBar has an open submenu. */
1141
+ hasOpenSubmenu() {
1142
+ return !!this.openItem;
1143
+ }
1144
+ /**
1145
+ * Close the open menu if the current active item opened the requested MenuStackItem.
1146
+ * @param item the MenuStackItem requested to be closed.
1147
+ */
1148
+ closeOpenMenu(menu) {
1149
+ const keyManager = this.keyManager;
1150
+ const trigger = this.openItem;
1151
+ if (menu === trigger?.getMenuTrigger()?.getMenu()) {
1152
+ trigger?.getMenuTrigger()?.close();
1153
+ // If the user has moused over a sibling item we want to focus the element under mouse focus
1154
+ // not the trigger which previously opened the now closed menu.
1155
+ if (trigger) {
1156
+ keyManager.setActiveItem(this.pointerTracker?.activeElement || trigger);
1157
+ }
1158
+ }
1159
+ }
1160
+ /** Setup the FocusKeyManager with the correct orientation for the menu. */
1161
+ _setKeyManager() {
1162
+ this.keyManager = new FocusKeyManager(this.items).withWrap().withTypeAhead().withHomeAndEnd();
1163
+ if (this.isHorizontal()) {
1164
+ this.keyManager.withHorizontalOrientation(this.dir?.value || 'ltr');
1165
+ }
1166
+ else {
1167
+ this.keyManager.withVerticalOrientation();
1168
+ }
1169
+ }
1170
+ /**
1171
+ * Subscribe to the menu trigger's open events in order to track the trigger which opened the menu
1172
+ * and stop tracking it when the menu is closed.
1173
+ */
1174
+ _subscribeToMenuOpen() {
1175
+ const exitCondition = merge(this.items.changes, this.destroyed);
1176
+ this.items.changes
1177
+ .pipe(startWith(this.items), mergeMap((list) => list
1178
+ .filter(item => item.hasMenu())
1179
+ .map(item => item.getMenuTrigger().opened.pipe(mapTo(item), takeUntil(exitCondition)))), mergeAll(), switchMap((item) => {
1180
+ this.openItem = item;
1181
+ return item.getMenuTrigger().closed;
1182
+ }), takeUntil(this.destroyed))
1183
+ .subscribe(() => (this.openItem = undefined));
1184
+ }
1185
+ /** Subscribe to the MenuStack close and empty observables. */
1186
+ _subscribeToMenuStackClosed() {
1187
+ this.menuStack.closed
1188
+ .pipe(takeUntil(this.destroyed))
1189
+ .subscribe(item => this.closeOpenMenu(item));
1190
+ }
1191
+ }
1192
+ CdkMenuBase.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: CdkMenuBase, deps: [{ token: i0.ElementRef }, { token: MENU_STACK }, { token: i1$1.Directionality, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
1193
+ CdkMenuBase.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.9", type: CdkMenuBase, host: { listeners: { "focus": "focusFirstItem()" }, properties: { "attr.aria-orientation": "orientation" } }, queries: [{ propertyName: "items", predicate: CdkMenuItem, descendants: true }], usesInheritance: true, ngImport: i0 });
1194
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: CdkMenuBase, decorators: [{
1195
+ type: Directive,
1196
+ args: [{
1197
+ host: {
1198
+ '[attr.aria-orientation]': 'orientation',
1199
+ '(focus)': 'focusFirstItem()',
1200
+ },
1201
+ }]
1202
+ }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: MenuStack, decorators: [{
1203
+ type: Inject,
1204
+ args: [MENU_STACK]
1205
+ }] }, { type: i1$1.Directionality, decorators: [{
1206
+ type: Optional
1207
+ }] }]; }, propDecorators: { items: [{
1208
+ type: ContentChildren,
1209
+ args: [CdkMenuItem, { descendants: true }]
1210
+ }] } });
1211
+
1093
1212
  /**
1094
1213
  * @license
1095
1214
  * Copyright Google LLC All Rights Reserved.
@@ -1104,53 +1223,39 @@ class PointerFocusTracker {
1104
1223
  *
1105
1224
  * It also acts as a RadioGroup for elements marked with role `menuitemradio`.
1106
1225
  */
1107
- class CdkMenu extends CdkMenuGroup {
1108
- constructor(_ngZone, _elementRef, _menuStack, _parentTrigger, _menuAim, _dir) {
1109
- super();
1226
+ class CdkMenu extends CdkMenuBase {
1227
+ constructor(_ngZone, elementRef, menuStack, _parentTrigger, _menuAim, dir) {
1228
+ super(elementRef, menuStack, dir);
1110
1229
  this._ngZone = _ngZone;
1111
- this._elementRef = _elementRef;
1112
- this._menuStack = _menuStack;
1113
1230
  this._parentTrigger = _parentTrigger;
1114
1231
  this._menuAim = _menuAim;
1115
- this._dir = _dir;
1116
- /**
1117
- * Sets the aria-orientation attribute and determines where menus will be opened.
1118
- * Does not affect styling/layout.
1119
- */
1120
- this.orientation = 'vertical';
1121
1232
  /** Event emitted when the menu is closed. */
1122
1233
  this.closed = new EventEmitter();
1123
- }
1124
- ngOnInit() {
1125
- this._menuStack?.push(this);
1234
+ this.destroyed.subscribe(this.closed);
1235
+ if (!this._isInline()) {
1236
+ this.menuStack.push(this);
1237
+ }
1126
1238
  this._parentTrigger?.registerChildMenu(this);
1127
1239
  }
1128
1240
  ngAfterContentInit() {
1129
1241
  super.ngAfterContentInit();
1130
1242
  this._completeChangeEmitter();
1131
- this._setKeyManager();
1132
- this._subscribeToMenuOpen();
1133
- this._subscribeToMenuStack();
1243
+ this._subscribeToMenuStackEmptied();
1134
1244
  this._subscribeToMouseManager();
1135
- this._menuAim?.initialize(this, this._pointerTracker);
1245
+ this._menuAim?.initialize(this, this.pointerTracker);
1136
1246
  }
1137
- /** Place focus on the first MenuItem in the menu and set the focus origin. */
1138
- focusFirstItem(focusOrigin = 'program') {
1139
- this._keyManager.setFocusOrigin(focusOrigin);
1140
- this._keyManager.setFirstItemActive();
1141
- }
1142
- /** Place focus on the last MenuItem in the menu and set the focus origin. */
1143
- focusLastItem(focusOrigin = 'program') {
1144
- this._keyManager.setFocusOrigin(focusOrigin);
1145
- this._keyManager.setLastItemActive();
1247
+ ngOnDestroy() {
1248
+ super.ngOnDestroy();
1249
+ this.closed.complete();
1250
+ this.pointerTracker?.destroy();
1146
1251
  }
1147
1252
  /** Handle keyboard events for the Menu. */
1148
1253
  _handleKeyEvent(event) {
1149
- const keyManager = this._keyManager;
1254
+ const keyManager = this.keyManager;
1150
1255
  switch (event.keyCode) {
1151
1256
  case LEFT_ARROW:
1152
1257
  case RIGHT_ARROW:
1153
- if (this._isHorizontal()) {
1258
+ if (this.isHorizontal()) {
1154
1259
  event.preventDefault();
1155
1260
  keyManager.setFocusOrigin('keyboard');
1156
1261
  keyManager.onKeydown(event);
@@ -1158,7 +1263,7 @@ class CdkMenu extends CdkMenuGroup {
1158
1263
  break;
1159
1264
  case UP_ARROW:
1160
1265
  case DOWN_ARROW:
1161
- if (!this._isHorizontal()) {
1266
+ if (!this.isHorizontal()) {
1162
1267
  event.preventDefault();
1163
1268
  keyManager.setFocusOrigin('keyboard');
1164
1269
  keyManager.onKeydown(event);
@@ -1167,11 +1272,11 @@ class CdkMenu extends CdkMenuGroup {
1167
1272
  case ESCAPE:
1168
1273
  if (!hasModifierKey(event)) {
1169
1274
  event.preventDefault();
1170
- this._menuStack?.close(this, 2 /* currentItem */);
1275
+ this.menuStack.close(this, 2 /* currentItem */);
1171
1276
  }
1172
1277
  break;
1173
1278
  case TAB:
1174
- this._menuStack?.closeAll();
1279
+ this.menuStack.closeAll();
1175
1280
  break;
1176
1281
  default:
1177
1282
  keyManager.onKeydown(event);
@@ -1181,6 +1286,9 @@ class CdkMenu extends CdkMenuGroup {
1181
1286
  * Complete the change emitter if there are any nested MenuGroups or register to complete the
1182
1287
  * change emitter if a MenuGroup is rendered at some point
1183
1288
  */
1289
+ // TODO(mmalerba): This doesnt' quite work. It causes change events to stop
1290
+ // firing for radio items directly in the menu if a second group of options
1291
+ // is added in a menu-group.
1184
1292
  _completeChangeEmitter() {
1185
1293
  if (this._hasNestedGroups()) {
1186
1294
  this.change.complete();
@@ -1197,59 +1305,21 @@ class CdkMenu extends CdkMenuGroup {
1197
1305
  // order to ensure that we return true iff there are child CdkMenuGroup elements.
1198
1306
  return this._nestedGroups.length > 0 && !(this._nestedGroups.first instanceof CdkMenu);
1199
1307
  }
1200
- /** Setup the FocusKeyManager with the correct orientation for the menu. */
1201
- _setKeyManager() {
1202
- this._keyManager = new FocusKeyManager(this._allItems)
1203
- .withWrap()
1204
- .withTypeAhead()
1205
- .withHomeAndEnd();
1206
- if (this._isHorizontal()) {
1207
- this._keyManager.withHorizontalOrientation(this._dir?.value || 'ltr');
1208
- }
1209
- else {
1210
- this._keyManager.withVerticalOrientation();
1211
- }
1212
- }
1213
1308
  /**
1214
1309
  * Set the PointerFocusTracker and ensure that when mouse focus changes the key manager is updated
1215
1310
  * with the latest menu item under mouse focus.
1216
1311
  */
1217
1312
  _subscribeToMouseManager() {
1218
1313
  this._ngZone.runOutsideAngular(() => {
1219
- this._pointerTracker = new PointerFocusTracker(this._allItems);
1220
- this._pointerTracker.entered
1314
+ this.pointerTracker = new PointerFocusTracker(this.items);
1315
+ this.pointerTracker.entered
1221
1316
  .pipe(takeUntil(this.closed))
1222
- .subscribe(item => this._keyManager.setActiveItem(item));
1317
+ .subscribe(item => this.keyManager.setActiveItem(item));
1223
1318
  });
1224
1319
  }
1225
- /** Subscribe to the MenuStack close and empty observables. */
1226
- _subscribeToMenuStack() {
1227
- this._menuStack?.closed
1228
- .pipe(takeUntil(this.closed))
1229
- .subscribe(item => this._closeOpenMenu(item));
1230
- this._menuStack?.emptied
1231
- .pipe(takeUntil(this.closed))
1232
- .subscribe(event => this._toggleMenuFocus(event));
1233
- }
1234
- /**
1235
- * Close the open menu if the current active item opened the requested MenuStackItem.
1236
- * @param item the MenuStackItem requested to be closed.
1237
- */
1238
- _closeOpenMenu(menu) {
1239
- const keyManager = this._keyManager;
1240
- const trigger = this._openItem;
1241
- if (menu === trigger?.getMenuTrigger()?.getMenu()) {
1242
- trigger?.getMenuTrigger()?.closeMenu();
1243
- // If the user has moused over a sibling item we want to focus the element under mouse focus
1244
- // not the trigger which previously opened the now closed menu.
1245
- if (trigger) {
1246
- keyManager.setActiveItem(this._pointerTracker?.activeElement || trigger);
1247
- }
1248
- }
1249
- }
1250
1320
  /** Set focus the either the current, previous or next item based on the FocusNext event. */
1251
1321
  _toggleMenuFocus(event) {
1252
- const keyManager = this._keyManager;
1322
+ const keyManager = this.keyManager;
1253
1323
  switch (event) {
1254
1324
  case 0 /* nextItem */:
1255
1325
  keyManager.setFocusOrigin('keyboard');
@@ -1267,71 +1337,44 @@ class CdkMenu extends CdkMenuGroup {
1267
1337
  break;
1268
1338
  }
1269
1339
  }
1270
- // TODO(andy9775): remove duplicate logic between menu an menu bar
1271
- /**
1272
- * Subscribe to the menu trigger's open events in order to track the trigger which opened the menu
1273
- * and stop tracking it when the menu is closed.
1274
- */
1275
- _subscribeToMenuOpen() {
1276
- const exitCondition = merge(this._allItems.changes, this.closed);
1277
- this._allItems.changes
1278
- .pipe(startWith(this._allItems), mergeMap((list) => list
1279
- .filter(item => item.hasMenu())
1280
- .map(item => item.getMenuTrigger().opened.pipe(mapTo(item), takeUntil(exitCondition)))), mergeAll(), switchMap((item) => {
1281
- this._openItem = item;
1282
- return item.getMenuTrigger().closed;
1283
- }), takeUntil(this.closed))
1284
- .subscribe(() => (this._openItem = undefined));
1285
- }
1286
- /** Return true if this menu has been configured in a horizontal orientation. */
1287
- _isHorizontal() {
1288
- return this.orientation === 'horizontal';
1289
- }
1290
1340
  /**
1291
1341
  * Return true if this menu is an inline menu. That is, it does not exist in a pop-up and is
1292
1342
  * always visible in the dom.
1293
1343
  */
1294
1344
  _isInline() {
1295
- return !this._menuStack;
1296
- }
1297
- ngOnDestroy() {
1298
- super.ngOnDestroy();
1299
- this._emitClosedEvent();
1300
- this._pointerTracker?.destroy();
1345
+ return !this._parentTrigger;
1301
1346
  }
1302
- /** Emit and complete the closed event emitter */
1303
- _emitClosedEvent() {
1304
- this.closed.next();
1305
- this.closed.complete();
1347
+ _subscribeToMenuStackEmptied() {
1348
+ this.menuStack.emptied
1349
+ .pipe(takeUntil(this.destroyed))
1350
+ .subscribe(event => this._toggleMenuFocus(event));
1306
1351
  }
1307
1352
  }
1308
- CdkMenu.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.6", ngImport: i0, type: CdkMenu, deps: [{ token: i0.NgZone }, { token: i0.ElementRef }, { token: MENU_STACK, optional: true }, { token: MENU_TRIGGER, optional: true }, { token: MENU_AIM, optional: true, self: true }, { token: i1$1.Directionality, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
1309
- CdkMenu.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.6", type: CdkMenu, selector: "[cdkMenu]", inputs: { orientation: ["cdkMenuOrientation", "orientation"] }, outputs: { closed: "closed" }, host: { attributes: { "role": "menu" }, listeners: { "focus": "focusFirstItem()", "keydown": "_handleKeyEvent($event)" }, properties: { "tabindex": "_isInline() ? 0 : null", "class.cdk-menu-inline": "_isInline()", "attr.aria-orientation": "orientation" }, classAttribute: "cdk-menu" }, providers: [
1353
+ CdkMenu.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: CdkMenu, deps: [{ token: i0.NgZone }, { token: i0.ElementRef }, { token: MENU_STACK }, { token: MENU_TRIGGER, optional: true }, { token: MENU_AIM, optional: true, self: true }, { token: i1$1.Directionality, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
1354
+ CdkMenu.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.9", type: CdkMenu, selector: "[cdkMenu]", outputs: { closed: "closed" }, host: { attributes: { "role": "menu" }, listeners: { "keydown": "_handleKeyEvent($event)" }, properties: { "tabindex": "_isInline() ? 0 : null", "class.cdk-menu-inline": "_isInline()" }, classAttribute: "cdk-menu" }, providers: [
1310
1355
  { provide: CdkMenuGroup, useExisting: CdkMenu },
1311
1356
  { provide: CDK_MENU, useExisting: CdkMenu },
1312
- ], queries: [{ propertyName: "_nestedGroups", predicate: CdkMenuGroup, descendants: true }, { propertyName: "_allItems", predicate: CdkMenuItem, descendants: true }], exportAs: ["cdkMenu"], usesInheritance: true, ngImport: i0 });
1313
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.6", ngImport: i0, type: CdkMenu, decorators: [{
1357
+ PARENT_OR_NEW_INLINE_MENU_STACK_PROVIDER,
1358
+ ], queries: [{ propertyName: "_nestedGroups", predicate: CdkMenuGroup, descendants: true }], exportAs: ["cdkMenu"], usesInheritance: true, ngImport: i0 });
1359
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: CdkMenu, decorators: [{
1314
1360
  type: Directive,
1315
1361
  args: [{
1316
1362
  selector: '[cdkMenu]',
1317
1363
  exportAs: 'cdkMenu',
1318
1364
  host: {
1319
- '[tabindex]': '_isInline() ? 0 : null',
1320
1365
  'role': 'menu',
1321
1366
  'class': 'cdk-menu',
1367
+ '[tabindex]': '_isInline() ? 0 : null',
1322
1368
  '[class.cdk-menu-inline]': '_isInline()',
1323
- '[attr.aria-orientation]': 'orientation',
1324
- '(focus)': 'focusFirstItem()',
1325
1369
  '(keydown)': '_handleKeyEvent($event)',
1326
1370
  },
1327
1371
  providers: [
1328
1372
  { provide: CdkMenuGroup, useExisting: CdkMenu },
1329
1373
  { provide: CDK_MENU, useExisting: CdkMenu },
1374
+ PARENT_OR_NEW_INLINE_MENU_STACK_PROVIDER,
1330
1375
  ],
1331
1376
  }]
1332
1377
  }], ctorParameters: function () { return [{ type: i0.NgZone }, { type: i0.ElementRef }, { type: MenuStack, decorators: [{
1333
- type: Optional
1334
- }, {
1335
1378
  type: Inject,
1336
1379
  args: [MENU_STACK]
1337
1380
  }] }, { type: MenuTrigger, decorators: [{
@@ -1348,17 +1391,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.6",
1348
1391
  args: [MENU_AIM]
1349
1392
  }] }, { type: i1$1.Directionality, decorators: [{
1350
1393
  type: Optional
1351
- }] }]; }, propDecorators: { orientation: [{
1352
- type: Input,
1353
- args: ['cdkMenuOrientation']
1354
- }], closed: [{
1394
+ }] }]; }, propDecorators: { closed: [{
1355
1395
  type: Output
1356
1396
  }], _nestedGroups: [{
1357
1397
  type: ContentChildren,
1358
1398
  args: [CdkMenuGroup, { descendants: true }]
1359
- }], _allItems: [{
1360
- type: ContentChildren,
1361
- args: [CdkMenuItem, { descendants: true }]
1362
1399
  }] } });
1363
1400
 
1364
1401
  /**
@@ -1374,39 +1411,22 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.6",
1374
1411
  * this directive is applied to should contain components marked with CdkMenuItem.
1375
1412
  *
1376
1413
  */
1377
- class CdkMenuBar extends CdkMenuGroup {
1378
- constructor(_ngZone, _elementRef, _menuStack, _menuAim, _dir) {
1379
- super();
1414
+ class CdkMenuBar extends CdkMenuBase {
1415
+ constructor(_ngZone, elementRef, menuStack, _menuAim, dir) {
1416
+ super(elementRef, menuStack, dir);
1380
1417
  this._ngZone = _ngZone;
1381
- this._elementRef = _elementRef;
1382
- this._menuStack = _menuStack;
1383
1418
  this._menuAim = _menuAim;
1384
- this._dir = _dir;
1385
- /**
1386
- * Sets the aria-orientation attribute and determines where menus will be opened.
1387
- * Does not affect styling/layout.
1388
- */
1389
1419
  this.orientation = 'horizontal';
1390
- /** Emits when the MenuBar is destroyed. */
1391
- this._destroyed = new Subject();
1392
1420
  }
1393
1421
  ngAfterContentInit() {
1394
1422
  super.ngAfterContentInit();
1395
- this._setKeyManager();
1396
- this._subscribeToMenuOpen();
1397
- this._subscribeToMenuStack();
1423
+ this._subscribeToMenuStackEmptied();
1398
1424
  this._subscribeToMouseManager();
1399
- this._menuAim?.initialize(this, this._pointerTracker);
1400
- }
1401
- /** Place focus on the first MenuItem in the menu and set the focus origin. */
1402
- focusFirstItem(focusOrigin = 'program') {
1403
- this._keyManager.setFocusOrigin(focusOrigin);
1404
- this._keyManager.setFirstItemActive();
1425
+ this._menuAim?.initialize(this, this.pointerTracker);
1405
1426
  }
1406
- /** Place focus on the last MenuItem in the menu and set the focus origin. */
1407
- focusLastItem(focusOrigin = 'program') {
1408
- this._keyManager.setFocusOrigin(focusOrigin);
1409
- this._keyManager.setLastItemActive();
1427
+ ngOnDestroy() {
1428
+ super.ngOnDestroy();
1429
+ this.pointerTracker?.destroy();
1410
1430
  }
1411
1431
  /**
1412
1432
  * Handle keyboard events, specifically changing the focused element and/or toggling the active
@@ -1414,7 +1434,7 @@ class CdkMenuBar extends CdkMenuGroup {
1414
1434
  * @param event the KeyboardEvent to handle.
1415
1435
  */
1416
1436
  _handleKeyEvent(event) {
1417
- const keyManager = this._keyManager;
1437
+ const keyManager = this.keyManager;
1418
1438
  switch (event.keyCode) {
1419
1439
  case UP_ARROW:
1420
1440
  case DOWN_ARROW:
@@ -1424,97 +1444,59 @@ class CdkMenuBar extends CdkMenuGroup {
1424
1444
  // For a horizontal menu if the left/right keys were clicked, or a vertical menu if the
1425
1445
  // up/down keys were clicked: if the current menu is open, close it then focus and open the
1426
1446
  // next menu.
1427
- if ((this._isHorizontal() && horizontalArrows) ||
1428
- (!this._isHorizontal() && !horizontalArrows)) {
1447
+ if ((this.isHorizontal() && horizontalArrows) ||
1448
+ (!this.isHorizontal() && !horizontalArrows)) {
1429
1449
  event.preventDefault();
1430
1450
  const prevIsOpen = keyManager.activeItem?.isMenuOpen();
1431
- keyManager.activeItem?.getMenuTrigger()?.closeMenu();
1451
+ keyManager.activeItem?.getMenuTrigger()?.close();
1432
1452
  keyManager.setFocusOrigin('keyboard');
1433
1453
  keyManager.onKeydown(event);
1434
1454
  if (prevIsOpen) {
1435
- keyManager.activeItem?.getMenuTrigger()?.openMenu();
1455
+ keyManager.activeItem?.getMenuTrigger()?.open();
1436
1456
  }
1437
1457
  }
1438
1458
  break;
1439
1459
  case ESCAPE:
1440
1460
  event.preventDefault();
1441
- keyManager.activeItem?.getMenuTrigger()?.closeMenu();
1461
+ keyManager.activeItem?.getMenuTrigger()?.close();
1442
1462
  break;
1443
1463
  case TAB:
1444
- keyManager.activeItem?.getMenuTrigger()?.closeMenu();
1464
+ keyManager.activeItem?.getMenuTrigger()?.close();
1445
1465
  break;
1446
1466
  default:
1447
1467
  keyManager.onKeydown(event);
1448
1468
  }
1449
1469
  }
1450
- /** Setup the FocusKeyManager with the correct orientation for the menu bar. */
1451
- _setKeyManager() {
1452
- this._keyManager = new FocusKeyManager(this._allItems)
1453
- .withWrap()
1454
- .withTypeAhead()
1455
- .withHomeAndEnd();
1456
- if (this._isHorizontal()) {
1457
- this._keyManager.withHorizontalOrientation(this._dir?.value || 'ltr');
1458
- }
1459
- else {
1460
- this._keyManager.withVerticalOrientation();
1461
- }
1462
- }
1463
1470
  /**
1464
1471
  * Set the PointerFocusTracker and ensure that when mouse focus changes the key manager is updated
1465
1472
  * with the latest menu item under mouse focus.
1466
1473
  */
1467
1474
  _subscribeToMouseManager() {
1468
1475
  this._ngZone.runOutsideAngular(() => {
1469
- this._pointerTracker = new PointerFocusTracker(this._allItems);
1470
- this._pointerTracker.entered.pipe(takeUntil(this._destroyed)).subscribe(item => {
1471
- if (this._hasOpenSubmenu()) {
1472
- this._keyManager.setActiveItem(item);
1476
+ this.pointerTracker = new PointerFocusTracker(this.items);
1477
+ this.pointerTracker.entered.pipe(takeUntil(this.destroyed)).subscribe(item => {
1478
+ if (this.hasOpenSubmenu()) {
1479
+ this.keyManager.setActiveItem(item);
1473
1480
  }
1474
1481
  });
1475
1482
  });
1476
1483
  }
1477
- /** Subscribe to the MenuStack close and empty observables. */
1478
- _subscribeToMenuStack() {
1479
- this._menuStack.closed
1480
- .pipe(takeUntil(this._destroyed))
1481
- .subscribe(item => this._closeOpenMenu(item));
1482
- this._menuStack.emptied
1483
- .pipe(takeUntil(this._destroyed))
1484
- .subscribe(event => this._toggleOpenMenu(event));
1485
- }
1486
- /**
1487
- * Close the open menu if the current active item opened the requested MenuStackItem.
1488
- * @param item the MenuStackItem requested to be closed.
1489
- */
1490
- _closeOpenMenu(menu) {
1491
- const trigger = this._openItem;
1492
- const keyManager = this._keyManager;
1493
- if (menu === trigger?.getMenuTrigger()?.getMenu()) {
1494
- trigger?.getMenuTrigger()?.closeMenu();
1495
- // If the user has moused over a sibling item we want to focus the element under mouse focus
1496
- // not the trigger which previously opened the now closed menu.
1497
- if (trigger) {
1498
- keyManager.setActiveItem(this._pointerTracker?.activeElement || trigger);
1499
- }
1500
- }
1501
- }
1502
1484
  /**
1503
1485
  * Set focus to either the current, previous or next item based on the FocusNext event, then
1504
1486
  * open the previous or next item.
1505
1487
  */
1506
1488
  _toggleOpenMenu(event) {
1507
- const keyManager = this._keyManager;
1489
+ const keyManager = this.keyManager;
1508
1490
  switch (event) {
1509
1491
  case 0 /* nextItem */:
1510
1492
  keyManager.setFocusOrigin('keyboard');
1511
1493
  keyManager.setNextItemActive();
1512
- keyManager.activeItem?.getMenuTrigger()?.openMenu();
1494
+ keyManager.activeItem?.getMenuTrigger()?.open();
1513
1495
  break;
1514
1496
  case 1 /* previousItem */:
1515
1497
  keyManager.setFocusOrigin('keyboard');
1516
1498
  keyManager.setPreviousItemActive();
1517
- keyManager.activeItem?.getMenuTrigger()?.openMenu();
1499
+ keyManager.activeItem?.getMenuTrigger()?.open();
1518
1500
  break;
1519
1501
  case 2 /* currentItem */:
1520
1502
  if (keyManager.activeItem) {
@@ -1524,45 +1506,19 @@ class CdkMenuBar extends CdkMenuGroup {
1524
1506
  break;
1525
1507
  }
1526
1508
  }
1527
- /**
1528
- * @return true if the menu bar is configured to be horizontal.
1529
- */
1530
- _isHorizontal() {
1531
- return this.orientation === 'horizontal';
1532
- }
1533
- /**
1534
- * Subscribe to the menu trigger's open events in order to track the trigger which opened the menu
1535
- * and stop tracking it when the menu is closed.
1536
- */
1537
- _subscribeToMenuOpen() {
1538
- const exitCondition = merge(this._allItems.changes, this._destroyed);
1539
- this._allItems.changes
1540
- .pipe(startWith(this._allItems), mergeMap((list) => list
1541
- .filter(item => item.hasMenu())
1542
- .map(item => item.getMenuTrigger().opened.pipe(mapTo(item), takeUntil(exitCondition)))), mergeAll(), switchMap((item) => {
1543
- this._openItem = item;
1544
- return item.getMenuTrigger().closed;
1545
- }), takeUntil(this._destroyed))
1546
- .subscribe(() => (this._openItem = undefined));
1547
- }
1548
- /** Return true if the MenuBar has an open submenu. */
1549
- _hasOpenSubmenu() {
1550
- return !!this._openItem;
1551
- }
1552
- ngOnDestroy() {
1553
- super.ngOnDestroy();
1554
- this._destroyed.next();
1555
- this._destroyed.complete();
1556
- this._pointerTracker?.destroy();
1509
+ _subscribeToMenuStackEmptied() {
1510
+ this.menuStack?.emptied
1511
+ .pipe(takeUntil(this.destroyed))
1512
+ .subscribe(event => this._toggleOpenMenu(event));
1557
1513
  }
1558
1514
  }
1559
- CdkMenuBar.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.6", ngImport: i0, type: CdkMenuBar, deps: [{ token: i0.NgZone }, { token: i0.ElementRef }, { token: MENU_STACK }, { token: MENU_AIM, optional: true, self: true }, { token: i1$1.Directionality, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
1560
- CdkMenuBar.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.6", type: CdkMenuBar, selector: "[cdkMenuBar]", inputs: { orientation: ["cdkMenuBarOrientation", "orientation"] }, host: { attributes: { "role": "menubar", "tabindex": "0" }, listeners: { "focus": "focusFirstItem()", "keydown": "_handleKeyEvent($event)" }, properties: { "attr.aria-orientation": "orientation" }, classAttribute: "cdk-menu-bar" }, providers: [
1515
+ CdkMenuBar.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: CdkMenuBar, deps: [{ token: i0.NgZone }, { token: i0.ElementRef }, { token: MENU_STACK }, { token: MENU_AIM, optional: true, self: true }, { token: i1$1.Directionality, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
1516
+ CdkMenuBar.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.9", type: CdkMenuBar, selector: "[cdkMenuBar]", host: { attributes: { "role": "menubar", "tabindex": "0" }, listeners: { "keydown": "_handleKeyEvent($event)" }, classAttribute: "cdk-menu-bar" }, providers: [
1561
1517
  { provide: CdkMenuGroup, useExisting: CdkMenuBar },
1562
1518
  { provide: CDK_MENU, useExisting: CdkMenuBar },
1563
- { provide: MENU_STACK, useClass: MenuStack },
1564
- ], queries: [{ propertyName: "_allItems", predicate: CdkMenuItem, descendants: true }], exportAs: ["cdkMenuBar"], usesInheritance: true, ngImport: i0 });
1565
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.6", ngImport: i0, type: CdkMenuBar, decorators: [{
1519
+ { provide: MENU_STACK, useFactory: () => MenuStack.inline() },
1520
+ ], exportAs: ["cdkMenuBar"], usesInheritance: true, ngImport: i0 });
1521
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: CdkMenuBar, decorators: [{
1566
1522
  type: Directive,
1567
1523
  args: [{
1568
1524
  selector: '[cdkMenuBar]',
@@ -1571,14 +1527,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.6",
1571
1527
  'role': 'menubar',
1572
1528
  'class': 'cdk-menu-bar',
1573
1529
  'tabindex': '0',
1574
- '[attr.aria-orientation]': 'orientation',
1575
- '(focus)': 'focusFirstItem()',
1576
1530
  '(keydown)': '_handleKeyEvent($event)',
1577
1531
  },
1578
1532
  providers: [
1579
1533
  { provide: CdkMenuGroup, useExisting: CdkMenuBar },
1580
1534
  { provide: CDK_MENU, useExisting: CdkMenuBar },
1581
- { provide: MENU_STACK, useClass: MenuStack },
1535
+ { provide: MENU_STACK, useFactory: () => MenuStack.inline() },
1582
1536
  ],
1583
1537
  }]
1584
1538
  }], ctorParameters: function () { return [{ type: i0.NgZone }, { type: i0.ElementRef }, { type: MenuStack, decorators: [{
@@ -1593,13 +1547,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.6",
1593
1547
  args: [MENU_AIM]
1594
1548
  }] }, { type: i1$1.Directionality, decorators: [{
1595
1549
  type: Optional
1596
- }] }]; }, propDecorators: { orientation: [{
1597
- type: Input,
1598
- args: ['cdkMenuBarOrientation']
1599
- }], _allItems: [{
1600
- type: ContentChildren,
1601
- args: [CdkMenuItem, { descendants: true }]
1602
- }] } });
1550
+ }] }]; } });
1603
1551
 
1604
1552
  /**
1605
1553
  * @license
@@ -1639,12 +1587,12 @@ class CdkMenuItemRadio extends CdkMenuItemSelectable {
1639
1587
  this._removeDispatcherListener();
1640
1588
  }
1641
1589
  }
1642
- CdkMenuItemRadio.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.6", ngImport: i0, type: CdkMenuItemRadio, deps: [{ token: i1$2.UniqueSelectionDispatcher }, { token: i0.ElementRef }, { token: i0.NgZone }, { token: MENU_STACK, optional: true }, { token: CDK_MENU, optional: true }, { token: MENU_AIM, optional: true }, { token: i1$1.Directionality, optional: true }, { token: CdkMenuItemTrigger, optional: true, self: true }], target: i0.ɵɵFactoryTarget.Directive });
1643
- CdkMenuItemRadio.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.6", type: CdkMenuItemRadio, selector: "[cdkMenuItemRadio]", host: { attributes: { "type": "button", "role": "menuitemradio" }, properties: { "tabindex": "_tabindex", "attr.aria-checked": "checked || null", "attr.aria-disabled": "disabled || null" } }, providers: [
1590
+ CdkMenuItemRadio.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: CdkMenuItemRadio, deps: [{ token: i1$2.UniqueSelectionDispatcher }, { token: i0.ElementRef }, { token: i0.NgZone }, { token: MENU_STACK }, { token: CDK_MENU, optional: true }, { token: MENU_AIM, optional: true }, { token: i1$1.Directionality, optional: true }, { token: CdkMenuItemTrigger, optional: true, self: true }], target: i0.ɵɵFactoryTarget.Directive });
1591
+ CdkMenuItemRadio.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.9", type: CdkMenuItemRadio, selector: "[cdkMenuItemRadio]", host: { attributes: { "type": "button", "role": "menuitemradio" }, properties: { "tabindex": "_tabindex", "attr.aria-checked": "checked || null", "attr.aria-disabled": "disabled || null" } }, providers: [
1644
1592
  { provide: CdkMenuItemSelectable, useExisting: CdkMenuItemRadio },
1645
1593
  { provide: CdkMenuItem, useExisting: CdkMenuItemSelectable },
1646
1594
  ], exportAs: ["cdkMenuItemRadio"], usesInheritance: true, ngImport: i0 });
1647
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.6", ngImport: i0, type: CdkMenuItemRadio, decorators: [{
1595
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: CdkMenuItemRadio, decorators: [{
1648
1596
  type: Directive,
1649
1597
  args: [{
1650
1598
  selector: '[cdkMenuItemRadio]',
@@ -1662,8 +1610,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.6",
1662
1610
  ],
1663
1611
  }]
1664
1612
  }], ctorParameters: function () { return [{ type: i1$2.UniqueSelectionDispatcher }, { type: i0.ElementRef }, { type: i0.NgZone }, { type: MenuStack, decorators: [{
1665
- type: Optional
1666
- }, {
1667
1613
  type: Inject,
1668
1614
  args: [MENU_STACK]
1669
1615
  }] }, { type: undefined, decorators: [{
@@ -1704,12 +1650,12 @@ class CdkMenuItemCheckbox extends CdkMenuItemSelectable {
1704
1650
  }
1705
1651
  }
1706
1652
  }
1707
- CdkMenuItemCheckbox.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.6", ngImport: i0, type: CdkMenuItemCheckbox, deps: null, target: i0.ɵɵFactoryTarget.Directive });
1708
- CdkMenuItemCheckbox.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.6", type: CdkMenuItemCheckbox, selector: "[cdkMenuItemCheckbox]", host: { attributes: { "type": "button", "role": "menuitemcheckbox" }, properties: { "tabindex": "_tabindex", "attr.aria-checked": "checked || null", "attr.aria-disabled": "disabled || null" } }, providers: [
1653
+ CdkMenuItemCheckbox.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: CdkMenuItemCheckbox, deps: null, target: i0.ɵɵFactoryTarget.Directive });
1654
+ CdkMenuItemCheckbox.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.9", type: CdkMenuItemCheckbox, selector: "[cdkMenuItemCheckbox]", host: { attributes: { "type": "button", "role": "menuitemcheckbox" }, properties: { "tabindex": "_tabindex", "attr.aria-checked": "checked || null", "attr.aria-disabled": "disabled || null" } }, providers: [
1709
1655
  { provide: CdkMenuItemSelectable, useExisting: CdkMenuItemCheckbox },
1710
1656
  { provide: CdkMenuItem, useExisting: CdkMenuItemSelectable },
1711
1657
  ], exportAs: ["cdkMenuItemCheckbox"], usesInheritance: true, ngImport: i0 });
1712
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.6", ngImport: i0, type: CdkMenuItemCheckbox, decorators: [{
1658
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: CdkMenuItemCheckbox, decorators: [{
1713
1659
  type: Directive,
1714
1660
  args: [{
1715
1661
  selector: '[cdkMenuItemCheckbox]',
@@ -1755,9 +1701,9 @@ class ContextMenuTracker {
1755
1701
  }
1756
1702
  }
1757
1703
  }
1758
- ContextMenuTracker.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.6", ngImport: i0, type: ContextMenuTracker, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1759
- ContextMenuTracker.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.6", ngImport: i0, type: ContextMenuTracker, providedIn: 'root' });
1760
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.6", ngImport: i0, type: ContextMenuTracker, decorators: [{
1704
+ ContextMenuTracker.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: ContextMenuTracker, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1705
+ ContextMenuTracker.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: ContextMenuTracker, providedIn: 'root' });
1706
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: ContextMenuTracker, decorators: [{
1761
1707
  type: Injectable,
1762
1708
  args: [{ providedIn: 'root' }]
1763
1709
  }] });
@@ -1773,17 +1719,7 @@ class CdkContextMenuTrigger extends MenuTrigger {
1773
1719
  this._overlay = _overlay;
1774
1720
  this._contextMenuTracker = _contextMenuTracker;
1775
1721
  this._directionality = _directionality;
1776
- /** Emits when the attached menu is requested to open. */
1777
- this.opened = new EventEmitter();
1778
- /** Emits when the attached menu is requested to close. */
1779
- this.closed = new EventEmitter();
1780
1722
  this._disabled = false;
1781
- /** A reference to the overlay which manages the triggered menu. */
1782
- this._overlayRef = null;
1783
- /** Emits when the element is destroyed. */
1784
- this._destroyed = new Subject();
1785
- /** Emits when the outside pointer events listener on the overlay should be stopped. */
1786
- this._stopOutsideClicksListener = merge(this.closed, this._destroyed);
1787
1723
  this._setMenuStackListener();
1788
1724
  }
1789
1725
  /** Whether the context menu should be disabled. */
@@ -1854,10 +1790,6 @@ class CdkContextMenuTrigger extends MenuTrigger {
1854
1790
  }
1855
1791
  }
1856
1792
  }
1857
- /** Whether the attached menu is open. */
1858
- isOpen() {
1859
- return !!this._overlayRef?.hasAttached();
1860
- }
1861
1793
  /**
1862
1794
  * Get the configuration object used to create the overlay.
1863
1795
  * @param coordinates the location to place the opened menu
@@ -1919,25 +1851,13 @@ class CdkContextMenuTrigger extends MenuTrigger {
1919
1851
  });
1920
1852
  }
1921
1853
  }
1922
- ngOnDestroy() {
1923
- this._destroyOverlay();
1924
- this._destroyed.next();
1925
- this._destroyed.complete();
1926
- }
1927
- /** Destroy and unset the overlay reference it if exists. */
1928
- _destroyOverlay() {
1929
- if (this._overlayRef) {
1930
- this._overlayRef.dispose();
1931
- this._overlayRef = null;
1932
- }
1933
- }
1934
1854
  }
1935
- CdkContextMenuTrigger.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.6", ngImport: i0, type: CdkContextMenuTrigger, deps: [{ token: i0.Injector }, { token: i0.ViewContainerRef }, { token: i1.Overlay }, { token: ContextMenuTracker }, { token: MENU_STACK }, { token: i1$1.Directionality, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
1936
- CdkContextMenuTrigger.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.6", type: CdkContextMenuTrigger, selector: "[cdkContextMenuTriggerFor]", inputs: { _menuTemplateRef: ["cdkContextMenuTriggerFor", "_menuTemplateRef"], menuPosition: ["cdkMenuPosition", "menuPosition"], disabled: ["cdkContextMenuDisabled", "disabled"] }, outputs: { opened: "cdkContextMenuOpened", closed: "cdkContextMenuClosed" }, host: { listeners: { "contextmenu": "_openOnContextMenu($event)" } }, providers: [
1855
+ CdkContextMenuTrigger.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: CdkContextMenuTrigger, deps: [{ token: i0.Injector }, { token: i0.ViewContainerRef }, { token: i1.Overlay }, { token: ContextMenuTracker }, { token: MENU_STACK }, { token: i1$1.Directionality, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
1856
+ CdkContextMenuTrigger.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.9", type: CdkContextMenuTrigger, selector: "[cdkContextMenuTriggerFor]", inputs: { _menuTemplateRef: ["cdkContextMenuTriggerFor", "_menuTemplateRef"], menuPosition: ["cdkContextMenuPosition", "menuPosition"], disabled: ["cdkContextMenuDisabled", "disabled"] }, outputs: { opened: "cdkContextMenuOpened", closed: "cdkContextMenuClosed" }, host: { listeners: { "contextmenu": "_openOnContextMenu($event)" } }, providers: [
1937
1857
  { provide: MENU_TRIGGER, useExisting: CdkContextMenuTrigger },
1938
1858
  { provide: MENU_STACK, useClass: MenuStack },
1939
1859
  ], exportAs: ["cdkContextMenuTriggerFor"], usesInheritance: true, ngImport: i0 });
1940
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.6", ngImport: i0, type: CdkContextMenuTrigger, decorators: [{
1860
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: CdkContextMenuTrigger, decorators: [{
1941
1861
  type: Directive,
1942
1862
  args: [{
1943
1863
  selector: '[cdkContextMenuTriggerFor]',
@@ -1945,6 +1865,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.6",
1945
1865
  host: {
1946
1866
  '(contextmenu)': '_openOnContextMenu($event)',
1947
1867
  },
1868
+ inputs: ['_menuTemplateRef: cdkContextMenuTriggerFor', 'menuPosition: cdkContextMenuPosition'],
1869
+ outputs: ['opened: cdkContextMenuOpened', 'closed: cdkContextMenuClosed'],
1948
1870
  providers: [
1949
1871
  { provide: MENU_TRIGGER, useExisting: CdkContextMenuTrigger },
1950
1872
  { provide: MENU_STACK, useClass: MenuStack },
@@ -1955,19 +1877,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.6",
1955
1877
  args: [MENU_STACK]
1956
1878
  }] }, { type: i1$1.Directionality, decorators: [{
1957
1879
  type: Optional
1958
- }] }]; }, propDecorators: { _menuTemplateRef: [{
1959
- type: Input,
1960
- args: ['cdkContextMenuTriggerFor']
1961
- }], menuPosition: [{
1962
- type: Input,
1963
- args: ['cdkMenuPosition']
1964
- }], opened: [{
1965
- type: Output,
1966
- args: ['cdkContextMenuOpened']
1967
- }], closed: [{
1968
- type: Output,
1969
- args: ['cdkContextMenuClosed']
1970
- }], disabled: [{
1880
+ }] }]; }, propDecorators: { disabled: [{
1971
1881
  type: Input,
1972
1882
  args: ['cdkContextMenuDisabled']
1973
1883
  }] } });
@@ -1992,8 +1902,8 @@ const EXPORTED_DECLARATIONS = [
1992
1902
  ];
1993
1903
  class CdkMenuModule {
1994
1904
  }
1995
- CdkMenuModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.6", ngImport: i0, type: CdkMenuModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1996
- CdkMenuModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "14.0.0-next.6", ngImport: i0, type: CdkMenuModule, declarations: [CdkMenuBar,
1905
+ CdkMenuModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: CdkMenuModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1906
+ CdkMenuModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: CdkMenuModule, declarations: [CdkMenuBar,
1997
1907
  CdkMenu,
1998
1908
  CdkMenuItem,
1999
1909
  CdkMenuItemRadio,
@@ -2010,8 +1920,8 @@ CdkMenuModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version:
2010
1920
  CdkMenuGroup,
2011
1921
  CdkContextMenuTrigger,
2012
1922
  CdkTargetMenuAim] });
2013
- CdkMenuModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.0.0-next.6", ngImport: i0, type: CdkMenuModule, imports: [[OverlayModule]] });
2014
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.6", ngImport: i0, type: CdkMenuModule, decorators: [{
1923
+ CdkMenuModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: CdkMenuModule, imports: [[OverlayModule]] });
1924
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: CdkMenuModule, decorators: [{
2015
1925
  type: NgModule,
2016
1926
  args: [{
2017
1927
  imports: [OverlayModule],