@angular/cdk-experimental 14.0.0-next.6 → 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.
- package/combobox/combobox-module.d.ts +3 -4
- package/combobox/combobox-popup.d.ts +6 -8
- package/combobox/combobox.d.ts +15 -18
- package/combobox/public-api.d.ts +0 -1
- package/dialog/dialog-config.d.ts +6 -1
- package/esm2020/column-resize/column-resize-directives/column-resize-flex.mjs +3 -3
- package/esm2020/column-resize/column-resize-directives/column-resize.mjs +3 -3
- package/esm2020/column-resize/column-resize-directives/default-enabled-column-resize-flex.mjs +3 -3
- package/esm2020/column-resize/column-resize-directives/default-enabled-column-resize.mjs +3 -3
- package/esm2020/column-resize/column-resize-module.mjs +8 -8
- package/esm2020/column-resize/column-resize-notifier.mjs +6 -6
- package/esm2020/column-resize/column-resize.mjs +3 -3
- package/esm2020/column-resize/column-size-store.mjs +3 -3
- package/esm2020/column-resize/event-dispatcher.mjs +3 -3
- package/esm2020/column-resize/overlay-handle.mjs +3 -3
- package/esm2020/column-resize/resizable.mjs +3 -3
- package/esm2020/column-resize/resize-strategy.mjs +9 -9
- package/esm2020/combobox/combobox-module.mjs +6 -7
- package/esm2020/combobox/combobox-popup.mjs +12 -23
- package/esm2020/combobox/combobox.mjs +50 -34
- package/esm2020/combobox/public-api.mjs +1 -2
- package/esm2020/dialog/dialog-config.mjs +1 -1
- package/esm2020/dialog/dialog-container.mjs +12 -7
- package/esm2020/dialog/dialog-module.mjs +4 -4
- package/esm2020/dialog/dialog.mjs +5 -5
- package/esm2020/listbox/listbox-module.mjs +4 -4
- package/esm2020/listbox/listbox.mjs +26 -44
- package/esm2020/menu/context-menu.mjs +46 -118
- package/esm2020/menu/menu-aim.mjs +6 -6
- package/esm2020/menu/menu-bar.mjs +46 -134
- package/esm2020/menu/menu-base.mjs +129 -0
- package/esm2020/menu/menu-errors.mjs +1 -9
- package/esm2020/menu/menu-group.mjs +9 -9
- package/esm2020/menu/menu-interface.mjs +1 -1
- package/esm2020/menu/menu-item-checkbox.mjs +3 -3
- package/esm2020/menu/menu-item-radio.mjs +13 -8
- package/esm2020/menu/menu-item-selectable.mjs +3 -3
- package/esm2020/menu/menu-item-trigger.mjs +66 -151
- package/esm2020/menu/menu-item.mjs +51 -45
- package/esm2020/menu/menu-module.mjs +5 -9
- package/esm2020/menu/menu-stack.mjs +31 -6
- package/esm2020/menu/menu-trigger.mjs +70 -0
- package/esm2020/menu/menu.mjs +58 -155
- package/esm2020/menu/public-api.mjs +3 -3
- package/esm2020/popover-edit/edit-event-dispatcher.mjs +3 -3
- package/esm2020/popover-edit/edit-ref.mjs +3 -3
- package/esm2020/popover-edit/edit-services.mjs +3 -3
- package/esm2020/popover-edit/focus-dispatcher.mjs +3 -3
- package/esm2020/popover-edit/focus-escape-notifier.mjs +3 -3
- package/esm2020/popover-edit/lens-directives.mjs +9 -9
- package/esm2020/popover-edit/popover-edit-module.mjs +4 -4
- package/esm2020/popover-edit/popover-edit-position-strategy-factory.mjs +6 -6
- package/esm2020/popover-edit/table-directives.mjs +15 -15
- package/esm2020/scrolling/auto-size-virtual-scroll.mjs +3 -3
- package/esm2020/scrolling/scrolling-module.mjs +4 -4
- package/esm2020/selection/row-selection.mjs +3 -3
- package/esm2020/selection/select-all.mjs +3 -3
- package/esm2020/selection/selection-column.mjs +3 -3
- package/esm2020/selection/selection-module.mjs +4 -4
- package/esm2020/selection/selection-toggle.mjs +3 -3
- package/esm2020/selection/selection.mjs +3 -3
- package/esm2020/table-scroll-container/table-scroll-container-module.mjs +4 -4
- package/esm2020/table-scroll-container/table-scroll-container.mjs +3 -3
- package/esm2020/version.mjs +1 -1
- package/fesm2015/cdk-experimental.mjs +1 -1
- package/fesm2015/cdk-experimental.mjs.map +1 -1
- package/fesm2015/column-resize.mjs +50 -50
- package/fesm2015/combobox.mjs +63 -106
- package/fesm2015/combobox.mjs.map +1 -1
- package/fesm2015/dialog.mjs +20 -14
- package/fesm2015/dialog.mjs.map +1 -1
- package/fesm2015/listbox.mjs +31 -47
- package/fesm2015/listbox.mjs.map +1 -1
- package/fesm2015/menu.mjs +587 -766
- package/fesm2015/menu.mjs.map +1 -1
- package/fesm2015/popover-edit.mjs +49 -49
- package/fesm2015/scrolling.mjs +7 -7
- package/fesm2015/selection.mjs +19 -19
- package/fesm2015/table-scroll-container.mjs +7 -7
- package/fesm2020/cdk-experimental.mjs +1 -1
- package/fesm2020/cdk-experimental.mjs.map +1 -1
- package/fesm2020/column-resize.mjs +50 -50
- package/fesm2020/combobox.mjs +62 -103
- package/fesm2020/combobox.mjs.map +1 -1
- package/fesm2020/dialog.mjs +19 -14
- package/fesm2020/dialog.mjs.map +1 -1
- package/fesm2020/listbox.mjs +29 -46
- package/fesm2020/listbox.mjs.map +1 -1
- package/fesm2020/menu.mjs +482 -655
- package/fesm2020/menu.mjs.map +1 -1
- package/fesm2020/popover-edit.mjs +49 -49
- package/fesm2020/scrolling.mjs +7 -7
- package/fesm2020/selection.mjs +19 -19
- package/fesm2020/table-scroll-container.mjs +7 -7
- package/listbox/listbox.d.ts +16 -13
- package/menu/context-menu.d.ts +7 -46
- package/menu/menu-bar.d.ts +9 -50
- package/menu/menu-base.d.ts +64 -0
- package/menu/menu-errors.d.ts +0 -5
- package/menu/menu-group.d.ts +2 -2
- package/menu/menu-interface.d.ts +1 -1
- package/menu/menu-item-radio.d.ts +4 -3
- package/menu/menu-item-trigger.d.ts +8 -38
- package/menu/menu-item.d.ts +11 -6
- package/menu/menu-module.d.ts +9 -10
- package/menu/menu-stack.d.ts +22 -6
- package/menu/menu-trigger.d.ts +48 -0
- package/menu/menu.d.ts +11 -67
- package/menu/public-api.d.ts +2 -2
- package/package.json +2 -2
- package/combobox/combobox-panel.d.ts +0 -27
- package/esm2020/combobox/combobox-panel.mjs +0 -48
- package/esm2020/menu/menu-panel.mjs +0 -37
- package/menu/menu-panel.d.ts +0 -30
package/fesm2020/menu.mjs
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { InjectionToken, Injectable, Directive, EventEmitter,
|
|
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
|
-
import { OverlayConfig, OverlayModule } from '@angular/cdk/overlay';
|
|
5
|
-
import { FocusKeyManager } from '@angular/cdk/a11y';
|
|
4
|
+
import { OverlayConfig, STANDARD_DROPDOWN_BELOW_POSITIONS, STANDARD_DROPDOWN_ADJACENT_POSITIONS, OverlayModule } from '@angular/cdk/overlay';
|
|
6
5
|
import { UP_ARROW, DOWN_ARROW, LEFT_ARROW, RIGHT_ARROW, ENTER, SPACE, TAB, ESCAPE, hasModifierKey } from '@angular/cdk/keycodes';
|
|
7
|
-
import * as
|
|
8
|
-
import {
|
|
9
|
-
import
|
|
10
|
-
import * as i1$1 from '@angular/cdk/collections';
|
|
6
|
+
import * as i1$1 from '@angular/cdk/bidi';
|
|
7
|
+
import { filter, takeUntil, startWith, mergeMap, mapTo, mergeAll, switchMap, take, skip } from 'rxjs/operators';
|
|
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
|
|
@@ -29,6 +29,20 @@ const CDK_MENU = new InjectionToken('cdk-menu');
|
|
|
29
29
|
* Use of this source code is governed by an MIT-style license that can be
|
|
30
30
|
* found in the LICENSE file at https://angular.io/license
|
|
31
31
|
*/
|
|
32
|
+
/** Injection token used for an implementation of MenuStack. */
|
|
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
|
+
};
|
|
32
46
|
/**
|
|
33
47
|
* MenuStack allows subscribers to listen for close events (when a MenuStackItem is popped off
|
|
34
48
|
* of the stack) in order to perform closing actions. Upon the MenuStack being empty it emits
|
|
@@ -51,6 +65,12 @@ class MenuStack {
|
|
|
51
65
|
* perform.
|
|
52
66
|
*/
|
|
53
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;
|
|
54
74
|
}
|
|
55
75
|
/** @param menu the MenuStackItem to put on the stack. */
|
|
56
76
|
push(menu) {
|
|
@@ -120,12 +140,15 @@ class MenuStack {
|
|
|
120
140
|
peek() {
|
|
121
141
|
return this._elements[this._elements.length - 1];
|
|
122
142
|
}
|
|
143
|
+
hasInlineMenu() {
|
|
144
|
+
return this._hasInlineMenu;
|
|
145
|
+
}
|
|
123
146
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
}
|
|
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: [{
|
|
150
|
+
type: Injectable
|
|
151
|
+
}] });
|
|
129
152
|
|
|
130
153
|
/**
|
|
131
154
|
* @license
|
|
@@ -134,14 +157,6 @@ class NoopMenuStack extends MenuStack {
|
|
|
134
157
|
* Use of this source code is governed by an MIT-style license that can be
|
|
135
158
|
* found in the LICENSE file at https://angular.io/license
|
|
136
159
|
*/
|
|
137
|
-
/**
|
|
138
|
-
* Throws an exception when a menu panel already has a menu stack.
|
|
139
|
-
* @docs-private
|
|
140
|
-
*/
|
|
141
|
-
function throwExistingMenuStackError() {
|
|
142
|
-
throw Error('CdkMenuPanel is already referenced by different CdkMenuTrigger. Ensure that a menu is' +
|
|
143
|
-
' opened by a single trigger only.');
|
|
144
|
-
}
|
|
145
160
|
/**
|
|
146
161
|
* Throws an exception when an instance of the PointerFocusTracker is not provided.
|
|
147
162
|
* @docs-private
|
|
@@ -329,9 +344,9 @@ class TargetMenuAim {
|
|
|
329
344
|
this._destroyed.complete();
|
|
330
345
|
}
|
|
331
346
|
}
|
|
332
|
-
TargetMenuAim.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
333
|
-
TargetMenuAim.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
334
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
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: [{
|
|
335
350
|
type: Injectable
|
|
336
351
|
}], ctorParameters: function () { return [{ type: i0.NgZone }]; } });
|
|
337
352
|
/**
|
|
@@ -340,9 +355,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.5",
|
|
|
340
355
|
*/
|
|
341
356
|
class CdkTargetMenuAim {
|
|
342
357
|
}
|
|
343
|
-
CdkTargetMenuAim.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
344
|
-
CdkTargetMenuAim.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
345
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
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: [{
|
|
346
361
|
type: Directive,
|
|
347
362
|
args: [{
|
|
348
363
|
selector: '[cdkTargetMenuAim]',
|
|
@@ -351,6 +366,71 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.5",
|
|
|
351
366
|
}]
|
|
352
367
|
}] });
|
|
353
368
|
|
|
369
|
+
/**
|
|
370
|
+
* @license
|
|
371
|
+
* Copyright Google LLC All Rights Reserved.
|
|
372
|
+
*
|
|
373
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
374
|
+
* found in the LICENSE file at https://angular.io/license
|
|
375
|
+
*/
|
|
376
|
+
/** Injection token used for an implementation of MenuStack. */
|
|
377
|
+
const MENU_TRIGGER = new InjectionToken('cdk-menu-trigger');
|
|
378
|
+
class MenuTrigger {
|
|
379
|
+
constructor(injector, menuStack) {
|
|
380
|
+
this.injector = injector;
|
|
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;
|
|
404
|
+
}
|
|
405
|
+
getChildMenuInjector() {
|
|
406
|
+
this._childMenuInjector =
|
|
407
|
+
this._childMenuInjector ||
|
|
408
|
+
Injector.create({
|
|
409
|
+
providers: [
|
|
410
|
+
{ provide: MENU_TRIGGER, useValue: this },
|
|
411
|
+
{ provide: MENU_STACK, useValue: this.menuStack },
|
|
412
|
+
],
|
|
413
|
+
parent: this.injector,
|
|
414
|
+
});
|
|
415
|
+
return this._childMenuInjector;
|
|
416
|
+
}
|
|
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
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|
|
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
|
|
429
|
+
}], ctorParameters: function () { return [{ type: i0.Injector }, { type: MenuStack, decorators: [{
|
|
430
|
+
type: Inject,
|
|
431
|
+
args: [MENU_STACK]
|
|
432
|
+
}] }]; } });
|
|
433
|
+
|
|
354
434
|
/**
|
|
355
435
|
* @license
|
|
356
436
|
* Copyright Google LLC All Rights Reserved.
|
|
@@ -382,8 +462,9 @@ function isClickInsideMenuOverlay(target) {
|
|
|
382
462
|
* The directive must be placed along with the `cdkMenuItem` directive in order to enable full
|
|
383
463
|
* functionality.
|
|
384
464
|
*/
|
|
385
|
-
class CdkMenuItemTrigger {
|
|
386
|
-
constructor(_elementRef, _viewContainerRef, _overlay, _ngZone, _parentMenu, _menuAim, _directionality) {
|
|
465
|
+
class CdkMenuItemTrigger extends MenuTrigger {
|
|
466
|
+
constructor(injector, _elementRef, _viewContainerRef, _overlay, _ngZone, menuStack, _parentMenu, _menuAim, _directionality) {
|
|
467
|
+
super(injector, menuStack);
|
|
387
468
|
this._elementRef = _elementRef;
|
|
388
469
|
this._viewContainerRef = _viewContainerRef;
|
|
389
470
|
this._overlay = _overlay;
|
|
@@ -391,46 +472,16 @@ class CdkMenuItemTrigger {
|
|
|
391
472
|
this._parentMenu = _parentMenu;
|
|
392
473
|
this._menuAim = _menuAim;
|
|
393
474
|
this._directionality = _directionality;
|
|
394
|
-
/** Emits when the attached menu is requested to open */
|
|
395
|
-
this.opened = new EventEmitter();
|
|
396
|
-
/** Emits when the attached menu is requested to close */
|
|
397
|
-
this.closed = new EventEmitter();
|
|
398
|
-
/** The menu stack for this trigger and its sub-menus. */
|
|
399
|
-
this._menuStack = new MenuStack();
|
|
400
|
-
/** A reference to the overlay which manages the triggered menu */
|
|
401
|
-
this._overlayRef = null;
|
|
402
|
-
/** Emits when this trigger is destroyed. */
|
|
403
|
-
this._destroyed = new Subject();
|
|
404
|
-
/** Emits when the outside pointer events listener on the overlay should be stopped. */
|
|
405
|
-
this._stopOutsideClicksListener = merge(this.closed, this._destroyed);
|
|
406
475
|
this._registerCloseHandler();
|
|
407
476
|
this._subscribeToMouseEnter();
|
|
408
477
|
}
|
|
409
|
-
/** Template reference variable to the menu this trigger opens */
|
|
410
|
-
get menuPanel() {
|
|
411
|
-
return this._menuPanel;
|
|
412
|
-
}
|
|
413
|
-
set menuPanel(panel) {
|
|
414
|
-
// If the provided panel already has a stack, that means it already has a trigger configured.
|
|
415
|
-
// Note however that there are some edge cases where two triggers **may** share the same menu,
|
|
416
|
-
// e.g. two triggers in two separate menus.
|
|
417
|
-
if ((typeof ngDevMode === 'undefined' || ngDevMode) && panel?._menuStack) {
|
|
418
|
-
throwExistingMenuStackError();
|
|
419
|
-
}
|
|
420
|
-
this._menuPanel = panel;
|
|
421
|
-
if (this._menuPanel) {
|
|
422
|
-
this._menuPanel._menuStack = this._getMenuStack();
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
478
|
/** Open/close the attached menu if the trigger has been configured with one */
|
|
426
479
|
toggle() {
|
|
427
|
-
|
|
428
|
-
this.isMenuOpen() ? this.closeMenu() : this.openMenu();
|
|
429
|
-
}
|
|
480
|
+
this.isOpen() ? this.close() : this.open();
|
|
430
481
|
}
|
|
431
482
|
/** Open the attached menu. */
|
|
432
|
-
|
|
433
|
-
if (!this.
|
|
483
|
+
open() {
|
|
484
|
+
if (!this.isOpen()) {
|
|
434
485
|
this.opened.next();
|
|
435
486
|
this._overlayRef = this._overlayRef || this._overlay.create(this._getOverlayConfig());
|
|
436
487
|
this._overlayRef.attach(this._getPortal());
|
|
@@ -438,27 +489,19 @@ class CdkMenuItemTrigger {
|
|
|
438
489
|
}
|
|
439
490
|
}
|
|
440
491
|
/** Close the opened menu. */
|
|
441
|
-
|
|
442
|
-
if (this.
|
|
492
|
+
close() {
|
|
493
|
+
if (this.isOpen()) {
|
|
443
494
|
this.closed.next();
|
|
444
495
|
this._overlayRef.detach();
|
|
445
496
|
}
|
|
446
497
|
this._closeSiblingTriggers();
|
|
447
498
|
}
|
|
448
|
-
/** Return true if the trigger has an attached menu */
|
|
449
|
-
hasMenu() {
|
|
450
|
-
return !!this.menuPanel;
|
|
451
|
-
}
|
|
452
|
-
/** Whether the menu this button is a trigger for is open */
|
|
453
|
-
isMenuOpen() {
|
|
454
|
-
return this._overlayRef ? this._overlayRef.hasAttached() : false;
|
|
455
|
-
}
|
|
456
499
|
/**
|
|
457
500
|
* Get a reference to the rendered Menu if the Menu is open and it is visible in the DOM.
|
|
458
501
|
* @return the menu if it is open, otherwise undefined.
|
|
459
502
|
*/
|
|
460
503
|
getMenu() {
|
|
461
|
-
return this.
|
|
504
|
+
return this.childMenu;
|
|
462
505
|
}
|
|
463
506
|
/**
|
|
464
507
|
* Subscribe to the mouseenter events and close any sibling menu items if this element is moused
|
|
@@ -468,11 +511,11 @@ class CdkMenuItemTrigger {
|
|
|
468
511
|
// Closes any sibling menu items and opens the menu associated with this trigger.
|
|
469
512
|
const toggleMenus = () => this._ngZone.run(() => {
|
|
470
513
|
this._closeSiblingTriggers();
|
|
471
|
-
this.
|
|
514
|
+
this.open();
|
|
472
515
|
});
|
|
473
516
|
this._ngZone.runOutsideAngular(() => {
|
|
474
517
|
fromEvent(this._elementRef.nativeElement, 'mouseenter')
|
|
475
|
-
.pipe(filter(() => !this.
|
|
518
|
+
.pipe(filter(() => !this.menuStack.isEmpty() && !this.isOpen()), takeUntil(this._destroyed))
|
|
476
519
|
.subscribe(() => {
|
|
477
520
|
if (this._menuAim) {
|
|
478
521
|
this._menuAim.toggle(toggleMenus);
|
|
@@ -495,40 +538,30 @@ class CdkMenuItemTrigger {
|
|
|
495
538
|
case ENTER:
|
|
496
539
|
event.preventDefault();
|
|
497
540
|
this.toggle();
|
|
498
|
-
this.
|
|
541
|
+
this.childMenu?.focusFirstItem('keyboard');
|
|
499
542
|
break;
|
|
500
543
|
case RIGHT_ARROW:
|
|
501
|
-
if (this._parentMenu && this._isParentVertical()) {
|
|
544
|
+
if (this._parentMenu && this._isParentVertical() && this._directionality?.value !== 'rtl') {
|
|
502
545
|
event.preventDefault();
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
}
|
|
506
|
-
else {
|
|
507
|
-
this.openMenu();
|
|
508
|
-
this.menuPanel?._menu?.focusFirstItem('keyboard');
|
|
509
|
-
}
|
|
546
|
+
this.open();
|
|
547
|
+
this.childMenu?.focusFirstItem('keyboard');
|
|
510
548
|
}
|
|
511
549
|
break;
|
|
512
550
|
case LEFT_ARROW:
|
|
513
|
-
if (this._parentMenu && this._isParentVertical()) {
|
|
551
|
+
if (this._parentMenu && this._isParentVertical() && this._directionality?.value === 'rtl') {
|
|
514
552
|
event.preventDefault();
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
this.menuPanel?._menu?.focusFirstItem('keyboard');
|
|
518
|
-
}
|
|
519
|
-
else {
|
|
520
|
-
this._getMenuStack().close(this._parentMenu, 2 /* currentItem */);
|
|
521
|
-
}
|
|
553
|
+
this.open();
|
|
554
|
+
this.childMenu?.focusFirstItem('keyboard');
|
|
522
555
|
}
|
|
523
556
|
break;
|
|
524
557
|
case DOWN_ARROW:
|
|
525
558
|
case UP_ARROW:
|
|
526
559
|
if (!this._isParentVertical()) {
|
|
527
560
|
event.preventDefault();
|
|
528
|
-
this.
|
|
561
|
+
this.open();
|
|
529
562
|
keyCode === DOWN_ARROW
|
|
530
|
-
? this.
|
|
531
|
-
: this.
|
|
563
|
+
? this.childMenu?.focusFirstItem('keyboard')
|
|
564
|
+
: this.childMenu?.focusLastItem('keyboard');
|
|
532
565
|
}
|
|
533
566
|
break;
|
|
534
567
|
}
|
|
@@ -536,17 +569,17 @@ class CdkMenuItemTrigger {
|
|
|
536
569
|
/** Close out any sibling menu trigger menus. */
|
|
537
570
|
_closeSiblingTriggers() {
|
|
538
571
|
if (this._parentMenu) {
|
|
539
|
-
const menuStack = this._getMenuStack();
|
|
540
572
|
// If nothing was removed from the stack and the last element is not the parent item
|
|
541
573
|
// that means that the parent menu is a menu bar since we don't put the menu bar on the
|
|
542
574
|
// stack
|
|
543
|
-
const isParentMenuBar = !menuStack.closeSubMenuOf(this._parentMenu) &&
|
|
575
|
+
const isParentMenuBar = !this.menuStack.closeSubMenuOf(this._parentMenu) &&
|
|
576
|
+
this.menuStack.peek() !== this._parentMenu;
|
|
544
577
|
if (isParentMenuBar) {
|
|
545
|
-
menuStack.closeAll();
|
|
578
|
+
this.menuStack.closeAll();
|
|
546
579
|
}
|
|
547
580
|
}
|
|
548
581
|
else {
|
|
549
|
-
this.
|
|
582
|
+
this.menuStack.closeAll();
|
|
550
583
|
}
|
|
551
584
|
}
|
|
552
585
|
/** Get the configuration object used to create the overlay */
|
|
@@ -566,31 +599,21 @@ class CdkMenuItemTrigger {
|
|
|
566
599
|
}
|
|
567
600
|
/** Determine and return where to position the opened menu relative to the menu item */
|
|
568
601
|
_getOverlayPositions() {
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
{ originX: 'start', originY: 'top', overlayX: 'start', overlayY: 'bottom' },
|
|
574
|
-
{ originX: 'end', originY: 'bottom', overlayX: 'end', overlayY: 'top' },
|
|
575
|
-
{ originX: 'end', originY: 'top', overlayX: 'end', overlayY: 'bottom' },
|
|
576
|
-
]
|
|
577
|
-
: [
|
|
578
|
-
{ originX: 'end', originY: 'top', overlayX: 'start', overlayY: 'top' },
|
|
579
|
-
{ originX: 'end', originY: 'bottom', overlayX: 'start', overlayY: 'bottom' },
|
|
580
|
-
{ originX: 'start', originY: 'top', overlayX: 'end', overlayY: 'top' },
|
|
581
|
-
{ originX: 'start', originY: 'bottom', overlayX: 'end', overlayY: 'bottom' },
|
|
582
|
-
];
|
|
602
|
+
return (this.menuPosition ??
|
|
603
|
+
(!this._parentMenu || this._parentMenu.orientation === 'horizontal'
|
|
604
|
+
? STANDARD_DROPDOWN_BELOW_POSITIONS
|
|
605
|
+
: STANDARD_DROPDOWN_ADJACENT_POSITIONS));
|
|
583
606
|
}
|
|
584
607
|
/**
|
|
585
608
|
* Get the portal to be attached to the overlay which contains the menu. Allows for the menu
|
|
586
609
|
* content to change dynamically and be reflected in the application.
|
|
587
610
|
*/
|
|
588
611
|
_getPortal() {
|
|
589
|
-
const hasMenuContentChanged = this.
|
|
590
|
-
if (this.
|
|
591
|
-
this.
|
|
612
|
+
const hasMenuContentChanged = this._menuTemplateRef !== this._menuPortal?.templateRef;
|
|
613
|
+
if (this._menuTemplateRef && (!this._menuPortal || hasMenuContentChanged)) {
|
|
614
|
+
this._menuPortal = new TemplatePortal(this._menuTemplateRef, this._viewContainerRef, undefined, this.getChildMenuInjector());
|
|
592
615
|
}
|
|
593
|
-
return this.
|
|
616
|
+
return this._menuPortal;
|
|
594
617
|
}
|
|
595
618
|
/**
|
|
596
619
|
* @return true if if the enclosing parent menu is configured in a vertical orientation.
|
|
@@ -604,38 +627,13 @@ class CdkMenuItemTrigger {
|
|
|
604
627
|
*/
|
|
605
628
|
_registerCloseHandler() {
|
|
606
629
|
if (!this._parentMenu) {
|
|
607
|
-
this.
|
|
608
|
-
if (item === this.
|
|
609
|
-
this.
|
|
630
|
+
this.menuStack.closed.pipe(takeUntil(this._destroyed)).subscribe(item => {
|
|
631
|
+
if (item === this.childMenu) {
|
|
632
|
+
this.close();
|
|
610
633
|
}
|
|
611
634
|
});
|
|
612
635
|
}
|
|
613
636
|
}
|
|
614
|
-
/** Get the menu stack for this trigger - either from the parent or this trigger. */
|
|
615
|
-
_getMenuStack() {
|
|
616
|
-
// We use a function since at the construction of the MenuItemTrigger the parent Menu won't have
|
|
617
|
-
// its menu stack set. Therefore we need to reference the menu stack from the parent each time
|
|
618
|
-
// we want to use it.
|
|
619
|
-
return this._parentMenu?._menuStack || this._menuStack;
|
|
620
|
-
}
|
|
621
|
-
ngOnDestroy() {
|
|
622
|
-
this._destroyOverlay();
|
|
623
|
-
this._resetPanelMenuStack();
|
|
624
|
-
this._destroyed.next();
|
|
625
|
-
this._destroyed.complete();
|
|
626
|
-
}
|
|
627
|
-
/** Set the menu panels menu stack back to null. */
|
|
628
|
-
_resetPanelMenuStack() {
|
|
629
|
-
// If a CdkMenuTrigger is placed in a submenu, each time the trigger is rendered (its parent
|
|
630
|
-
// menu is opened) the panel setter for CdkMenuPanel is called. From the first render onward,
|
|
631
|
-
// the attached CdkMenuPanel has the MenuStack set. Since we throw an error if a panel already
|
|
632
|
-
// has a stack set, we want to reset the attached stack here to prevent the error from being
|
|
633
|
-
// thrown if the trigger re-configures its attached panel (in the case where there is a 1:1
|
|
634
|
-
// relationship between the panel and trigger).
|
|
635
|
-
if (this._menuPanel) {
|
|
636
|
-
this._menuPanel._menuStack = null;
|
|
637
|
-
}
|
|
638
|
-
}
|
|
639
637
|
/**
|
|
640
638
|
* Subscribe to the overlays outside pointer events stream and handle closing out the stack if a
|
|
641
639
|
* click occurs outside the menus.
|
|
@@ -647,35 +645,40 @@ class CdkMenuItemTrigger {
|
|
|
647
645
|
.pipe(takeUntil(this._stopOutsideClicksListener))
|
|
648
646
|
.subscribe(event => {
|
|
649
647
|
if (!isClickInsideMenuOverlay(event.target)) {
|
|
650
|
-
this.
|
|
648
|
+
this.menuStack.closeAll();
|
|
651
649
|
}
|
|
652
650
|
});
|
|
653
651
|
}
|
|
654
652
|
}
|
|
655
|
-
/** Destroy and unset the overlay reference it if exists */
|
|
656
|
-
_destroyOverlay() {
|
|
657
|
-
if (this._overlayRef) {
|
|
658
|
-
this._overlayRef.dispose();
|
|
659
|
-
this._overlayRef = null;
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
653
|
}
|
|
663
|
-
CdkMenuItemTrigger.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
664
|
-
CdkMenuItemTrigger.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
665
|
-
|
|
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: [
|
|
656
|
+
{ provide: MENU_TRIGGER, useExisting: CdkMenuItemTrigger },
|
|
657
|
+
PARENT_OR_NEW_MENU_STACK_PROVIDER,
|
|
658
|
+
], exportAs: ["cdkMenuTriggerFor"], usesInheritance: true, ngImport: i0 });
|
|
659
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: CdkMenuItemTrigger, decorators: [{
|
|
666
660
|
type: Directive,
|
|
667
661
|
args: [{
|
|
668
662
|
selector: '[cdkMenuTriggerFor]',
|
|
669
663
|
exportAs: 'cdkMenuTriggerFor',
|
|
670
664
|
host: {
|
|
671
|
-
'(keydown)': '_toggleOnKeydown($event)',
|
|
672
|
-
'(click)': 'toggle()',
|
|
673
665
|
'class': 'cdk-menu-trigger',
|
|
674
666
|
'aria-haspopup': 'menu',
|
|
675
|
-
'
|
|
667
|
+
'(keydown)': '_toggleOnKeydown($event)',
|
|
668
|
+
'(click)': 'toggle()',
|
|
669
|
+
'[attr.aria-expanded]': 'isOpen()',
|
|
676
670
|
},
|
|
671
|
+
inputs: ['_menuTemplateRef: cdkMenuTriggerFor', 'menuPosition: cdkMenuPosition'],
|
|
672
|
+
outputs: ['opened: cdkMenuOpened', 'closed: cdkMenuClosed'],
|
|
673
|
+
providers: [
|
|
674
|
+
{ provide: MENU_TRIGGER, useExisting: CdkMenuItemTrigger },
|
|
675
|
+
PARENT_OR_NEW_MENU_STACK_PROVIDER,
|
|
676
|
+
],
|
|
677
677
|
}]
|
|
678
|
-
}], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.ViewContainerRef }, { type: i1.Overlay }, { type: i0.NgZone }, { type:
|
|
678
|
+
}], ctorParameters: function () { return [{ type: i0.Injector }, { type: i0.ElementRef }, { type: i0.ViewContainerRef }, { type: i1.Overlay }, { type: i0.NgZone }, { type: MenuStack, decorators: [{
|
|
679
|
+
type: Inject,
|
|
680
|
+
args: [MENU_STACK]
|
|
681
|
+
}] }, { type: undefined, decorators: [{
|
|
679
682
|
type: Optional
|
|
680
683
|
}, {
|
|
681
684
|
type: Inject,
|
|
@@ -685,18 +688,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.5",
|
|
|
685
688
|
}, {
|
|
686
689
|
type: Inject,
|
|
687
690
|
args: [MENU_AIM]
|
|
688
|
-
}] }, { type:
|
|
691
|
+
}] }, { type: i1$1.Directionality, decorators: [{
|
|
689
692
|
type: Optional
|
|
690
|
-
}] }]; }
|
|
691
|
-
type: Input,
|
|
692
|
-
args: ['cdkMenuTriggerFor']
|
|
693
|
-
}], opened: [{
|
|
694
|
-
type: Output,
|
|
695
|
-
args: ['cdkMenuOpened']
|
|
696
|
-
}], closed: [{
|
|
697
|
-
type: Output,
|
|
698
|
-
args: ['cdkMenuClosed']
|
|
699
|
-
}] } });
|
|
693
|
+
}] }]; } });
|
|
700
694
|
|
|
701
695
|
/**
|
|
702
696
|
* @license
|
|
@@ -705,26 +699,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.5",
|
|
|
705
699
|
* Use of this source code is governed by an MIT-style license that can be
|
|
706
700
|
* found in the LICENSE file at https://angular.io/license
|
|
707
701
|
*/
|
|
708
|
-
// TODO refactor this to be configurable allowing for custom elements to be removed
|
|
709
|
-
/** Removes all icons from within the given element. */
|
|
710
|
-
function removeIcons(element) {
|
|
711
|
-
for (const icon of Array.from(element.querySelectorAll('mat-icon, .material-icons'))) {
|
|
712
|
-
icon.remove();
|
|
713
|
-
}
|
|
714
|
-
}
|
|
715
702
|
/**
|
|
716
703
|
* Directive which provides the ability for an element to be focused and navigated to using the
|
|
717
704
|
* keyboard when residing in a CdkMenu, CdkMenuBar, or CdkMenuGroup. It performs user defined
|
|
718
705
|
* behavior when clicked.
|
|
719
706
|
*/
|
|
720
707
|
class CdkMenuItem {
|
|
721
|
-
constructor(_elementRef, _ngZone, _parentMenu, _menuAim, _dir,
|
|
708
|
+
constructor(_elementRef, _ngZone, _menuStack, _parentMenu, _menuAim, _dir,
|
|
722
709
|
/** Reference to the CdkMenuItemTrigger directive if one is added to the same element */
|
|
723
710
|
// `CdkMenuItem` is commonly used in combination with a `CdkMenuItemTrigger`.
|
|
724
711
|
// tslint:disable-next-line: lightweight-tokens
|
|
725
712
|
_menuTrigger) {
|
|
726
713
|
this._elementRef = _elementRef;
|
|
727
714
|
this._ngZone = _ngZone;
|
|
715
|
+
this._menuStack = _menuStack;
|
|
728
716
|
this._parentMenu = _parentMenu;
|
|
729
717
|
this._menuAim = _menuAim;
|
|
730
718
|
this._dir = _dir;
|
|
@@ -773,7 +761,7 @@ class CdkMenuItem {
|
|
|
773
761
|
return;
|
|
774
762
|
}
|
|
775
763
|
// don't set the tabindex if there are no open sibling or parent menus
|
|
776
|
-
if (!event || !this.
|
|
764
|
+
if (!event || !this._menuStack.isEmpty()) {
|
|
777
765
|
this._tabindex = 0;
|
|
778
766
|
}
|
|
779
767
|
}
|
|
@@ -788,16 +776,16 @@ class CdkMenuItem {
|
|
|
788
776
|
trigger() {
|
|
789
777
|
if (!this.disabled && !this.hasMenu()) {
|
|
790
778
|
this.triggered.next();
|
|
791
|
-
this.
|
|
779
|
+
this._menuStack.closeAll();
|
|
792
780
|
}
|
|
793
781
|
}
|
|
794
782
|
/** Whether the menu item opens a menu. */
|
|
795
783
|
hasMenu() {
|
|
796
|
-
return !!this._menuTrigger
|
|
784
|
+
return !!this._menuTrigger;
|
|
797
785
|
}
|
|
798
786
|
/** Return true if this MenuItem has an attached menu and it is open. */
|
|
799
787
|
isMenuOpen() {
|
|
800
|
-
return !!this._menuTrigger?.
|
|
788
|
+
return !!this._menuTrigger?.isOpen();
|
|
801
789
|
}
|
|
802
790
|
/**
|
|
803
791
|
* Get a reference to the rendered Menu if the Menu is open and it is visible in the DOM.
|
|
@@ -812,11 +800,7 @@ class CdkMenuItem {
|
|
|
812
800
|
}
|
|
813
801
|
/** Get the label for this element which is required by the FocusableOption interface. */
|
|
814
802
|
getLabel() {
|
|
815
|
-
|
|
816
|
-
// we know that the current node is an element type
|
|
817
|
-
const clone = this._elementRef.nativeElement.cloneNode(true);
|
|
818
|
-
removeIcons(clone);
|
|
819
|
-
return clone.textContent?.trim() || '';
|
|
803
|
+
return this.typeahead || this._elementRef.nativeElement.textContent?.trim() || '';
|
|
820
804
|
}
|
|
821
805
|
/**
|
|
822
806
|
* Handles keyboard events for the menu item, specifically either triggering the user defined
|
|
@@ -832,19 +816,35 @@ class CdkMenuItem {
|
|
|
832
816
|
this.trigger();
|
|
833
817
|
break;
|
|
834
818
|
case RIGHT_ARROW:
|
|
835
|
-
if (this._parentMenu && this._isParentVertical()
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
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
|
+
}
|
|
840
832
|
}
|
|
841
833
|
break;
|
|
842
834
|
case LEFT_ARROW:
|
|
843
|
-
if (this._parentMenu && this._isParentVertical()
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
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
|
+
}
|
|
848
848
|
}
|
|
849
849
|
break;
|
|
850
850
|
}
|
|
@@ -855,9 +855,9 @@ class CdkMenuItem {
|
|
|
855
855
|
*/
|
|
856
856
|
_setupMouseEnter() {
|
|
857
857
|
if (!this._isStandaloneItem()) {
|
|
858
|
-
const closeOpenSiblings = () => this._ngZone.run(() => this.
|
|
858
|
+
const closeOpenSiblings = () => this._ngZone.run(() => this._menuStack.closeSubMenuOf(this._parentMenu));
|
|
859
859
|
this._ngZone.runOutsideAngular(() => fromEvent(this._elementRef.nativeElement, 'mouseenter')
|
|
860
|
-
.pipe(filter(() => !this.
|
|
860
|
+
.pipe(filter(() => !this._menuStack.isEmpty() && !this.hasMenu()), takeUntil(this._destroyed))
|
|
861
861
|
.subscribe(() => {
|
|
862
862
|
if (this._menuAim) {
|
|
863
863
|
this._menuAim.toggle(closeOpenSiblings);
|
|
@@ -875,20 +875,13 @@ class CdkMenuItem {
|
|
|
875
875
|
_isParentVertical() {
|
|
876
876
|
return this._parentMenu?.orientation === 'vertical';
|
|
877
877
|
}
|
|
878
|
-
/** Get the MenuStack from the parent menu. */
|
|
879
|
-
_getMenuStack() {
|
|
880
|
-
// We use a function since at the construction of the MenuItemTrigger the parent Menu won't have
|
|
881
|
-
// its menu stack set. Therefore we need to reference the menu stack from the parent each time
|
|
882
|
-
// we want to use it.
|
|
883
|
-
return this._parentMenu?._menuStack;
|
|
884
|
-
}
|
|
885
878
|
ngOnDestroy() {
|
|
886
879
|
this._destroyed.next();
|
|
887
880
|
}
|
|
888
881
|
}
|
|
889
|
-
CdkMenuItem.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
890
|
-
CdkMenuItem.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
891
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
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: [{
|
|
892
885
|
type: Directive,
|
|
893
886
|
args: [{
|
|
894
887
|
selector: '[cdkMenuItem]',
|
|
@@ -907,7 +900,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.5",
|
|
|
907
900
|
'(keydown)': '_onKeydown($event)',
|
|
908
901
|
},
|
|
909
902
|
}]
|
|
910
|
-
}], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.NgZone }, { type:
|
|
903
|
+
}], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.NgZone }, { type: MenuStack, decorators: [{
|
|
904
|
+
type: Inject,
|
|
905
|
+
args: [MENU_STACK]
|
|
906
|
+
}] }, { type: undefined, decorators: [{
|
|
911
907
|
type: Optional
|
|
912
908
|
}, {
|
|
913
909
|
type: Inject,
|
|
@@ -917,7 +913,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.5",
|
|
|
917
913
|
}, {
|
|
918
914
|
type: Inject,
|
|
919
915
|
args: [MENU_AIM]
|
|
920
|
-
}] }, { type:
|
|
916
|
+
}] }, { type: i1$1.Directionality, decorators: [{
|
|
921
917
|
type: Optional
|
|
922
918
|
}] }, { type: CdkMenuItemTrigger, decorators: [{
|
|
923
919
|
type: Self
|
|
@@ -925,6 +921,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.5",
|
|
|
925
921
|
type: Optional
|
|
926
922
|
}] }]; }, propDecorators: { disabled: [{
|
|
927
923
|
type: Input
|
|
924
|
+
}], typeahead: [{
|
|
925
|
+
type: Input
|
|
928
926
|
}], triggered: [{
|
|
929
927
|
type: Output,
|
|
930
928
|
args: ['cdkMenuItemTriggered']
|
|
@@ -968,9 +966,9 @@ class CdkMenuItemSelectable extends CdkMenuItem {
|
|
|
968
966
|
}
|
|
969
967
|
}
|
|
970
968
|
}
|
|
971
|
-
CdkMenuItemSelectable.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
972
|
-
CdkMenuItemSelectable.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
973
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
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: [{
|
|
974
972
|
type: Directive
|
|
975
973
|
}], propDecorators: { toggled: [{
|
|
976
974
|
type: Output,
|
|
@@ -1004,6 +1002,10 @@ class CdkMenuGroup {
|
|
|
1004
1002
|
ngAfterContentInit() {
|
|
1005
1003
|
this._registerMenuSelectionListeners();
|
|
1006
1004
|
}
|
|
1005
|
+
ngOnDestroy() {
|
|
1006
|
+
this._selectableChanges.next();
|
|
1007
|
+
this._selectableChanges.complete();
|
|
1008
|
+
}
|
|
1007
1009
|
/**
|
|
1008
1010
|
* Register the child selectable elements with the change emitter and ensure any new child
|
|
1009
1011
|
* elements do so as well.
|
|
@@ -1021,14 +1023,10 @@ class CdkMenuGroup {
|
|
|
1021
1023
|
.pipe(takeUntil(this._selectableChanges))
|
|
1022
1024
|
.subscribe(() => this.change.next(selectable));
|
|
1023
1025
|
}
|
|
1024
|
-
ngOnDestroy() {
|
|
1025
|
-
this._selectableChanges.next();
|
|
1026
|
-
this._selectableChanges.complete();
|
|
1027
|
-
}
|
|
1028
1026
|
}
|
|
1029
|
-
CdkMenuGroup.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
1030
|
-
CdkMenuGroup.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
1031
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
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: [{
|
|
1032
1030
|
type: Directive,
|
|
1033
1031
|
args: [{
|
|
1034
1032
|
selector: '[cdkMenuGroup]',
|
|
@@ -1046,41 +1044,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.5",
|
|
|
1046
1044
|
args: [CdkMenuItemSelectable, { descendants: true }]
|
|
1047
1045
|
}] } });
|
|
1048
1046
|
|
|
1049
|
-
/**
|
|
1050
|
-
* @license
|
|
1051
|
-
* Copyright Google LLC All Rights Reserved.
|
|
1052
|
-
*
|
|
1053
|
-
* Use of this source code is governed by an MIT-style license that can be
|
|
1054
|
-
* found in the LICENSE file at https://angular.io/license
|
|
1055
|
-
*/
|
|
1056
|
-
/**
|
|
1057
|
-
* Directive applied to an ng-template which wraps a CdkMenu and provides a reference to the
|
|
1058
|
-
* child element it wraps which allows for opening of the CdkMenu in an overlay.
|
|
1059
|
-
*/
|
|
1060
|
-
class CdkMenuPanel {
|
|
1061
|
-
constructor(_templateRef) {
|
|
1062
|
-
this._templateRef = _templateRef;
|
|
1063
|
-
}
|
|
1064
|
-
/**
|
|
1065
|
-
* Set the Menu component on the menu panel. Since we cannot use ContentChild to fetch the
|
|
1066
|
-
* child Menu component, the child Menu must register its self with the parent MenuPanel.
|
|
1067
|
-
*/
|
|
1068
|
-
_registerMenu(child) {
|
|
1069
|
-
this._menu = child;
|
|
1070
|
-
// The ideal solution would be to affect the CdkMenuPanel injector from the CdkMenuTrigger and
|
|
1071
|
-
// inject the menu stack reference into the child menu and menu items, however this isn't
|
|
1072
|
-
// possible at this time.
|
|
1073
|
-
this._menu._menuStack = this._menuStack;
|
|
1074
|
-
this._menuStack?.push(child);
|
|
1075
|
-
}
|
|
1076
|
-
}
|
|
1077
|
-
CdkMenuPanel.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.5", ngImport: i0, type: CdkMenuPanel, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
|
|
1078
|
-
CdkMenuPanel.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.5", type: CdkMenuPanel, selector: "ng-template[cdkMenuPanel]", exportAs: ["cdkMenuPanel"], ngImport: i0 });
|
|
1079
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.5", ngImport: i0, type: CdkMenuPanel, decorators: [{
|
|
1080
|
-
type: Directive,
|
|
1081
|
-
args: [{ selector: 'ng-template[cdkMenuPanel]', exportAs: 'cdkMenuPanel' }]
|
|
1082
|
-
}], ctorParameters: function () { return [{ type: i0.TemplateRef }]; } });
|
|
1083
|
-
|
|
1084
1047
|
/**
|
|
1085
1048
|
* @license
|
|
1086
1049
|
* Copyright Google LLC All Rights Reserved.
|
|
@@ -1135,66 +1098,164 @@ class PointerFocusTracker {
|
|
|
1135
1098
|
* Use of this source code is governed by an MIT-style license that can be
|
|
1136
1099
|
* found in the LICENSE file at https://angular.io/license
|
|
1137
1100
|
*/
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
* CdkMenuItem or CdkMenuGroup. Sets the appropriate role and aria-attributes for a menu and
|
|
1141
|
-
* contains accessible keyboard and mouse handling logic.
|
|
1142
|
-
*
|
|
1143
|
-
* It also acts as a RadioGroup for elements marked with role `menuitemradio`.
|
|
1144
|
-
*/
|
|
1145
|
-
class CdkMenu extends CdkMenuGroup {
|
|
1146
|
-
constructor(_ngZone, _elementRef, _menuAim, _dir,
|
|
1147
|
-
// `CdkMenuPanel` is always used in combination with a `CdkMenu`.
|
|
1148
|
-
// tslint:disable-next-line: lightweight-tokens
|
|
1149
|
-
_menuPanel) {
|
|
1101
|
+
class CdkMenuBase extends CdkMenuGroup {
|
|
1102
|
+
constructor(_elementRef, menuStack, dir) {
|
|
1150
1103
|
super();
|
|
1151
|
-
this._ngZone = _ngZone;
|
|
1152
1104
|
this._elementRef = _elementRef;
|
|
1153
|
-
this.
|
|
1154
|
-
this.
|
|
1155
|
-
this._menuPanel = _menuPanel;
|
|
1105
|
+
this.menuStack = menuStack;
|
|
1106
|
+
this.dir = dir;
|
|
1156
1107
|
/**
|
|
1157
1108
|
* Sets the aria-orientation attribute and determines where menus will be opened.
|
|
1158
1109
|
* Does not affect styling/layout.
|
|
1159
1110
|
*/
|
|
1160
1111
|
this.orientation = 'vertical';
|
|
1161
|
-
/**
|
|
1162
|
-
this.
|
|
1163
|
-
// We provide a default MenuStack implementation in case the menu is an inline menu.
|
|
1164
|
-
// For Menus part of a MenuBar nested within a MenuPanel this will be overwritten
|
|
1165
|
-
// to the correct parent MenuStack.
|
|
1166
|
-
/** Track the Menus making up the open menu stack. */
|
|
1167
|
-
this._menuStack = new NoopMenuStack();
|
|
1168
|
-
}
|
|
1169
|
-
ngOnInit() {
|
|
1170
|
-
this._registerWithParentPanel();
|
|
1112
|
+
/** Emits when the MenuBar is destroyed. */
|
|
1113
|
+
this.destroyed = new Subject();
|
|
1171
1114
|
}
|
|
1172
1115
|
ngAfterContentInit() {
|
|
1173
1116
|
super.ngAfterContentInit();
|
|
1174
|
-
this._completeChangeEmitter();
|
|
1175
1117
|
this._setKeyManager();
|
|
1176
1118
|
this._subscribeToMenuOpen();
|
|
1177
|
-
this.
|
|
1178
|
-
|
|
1179
|
-
|
|
1119
|
+
this._subscribeToMenuStackClosed();
|
|
1120
|
+
}
|
|
1121
|
+
ngOnDestroy() {
|
|
1122
|
+
super.ngOnDestroy();
|
|
1123
|
+
this.destroyed.next();
|
|
1124
|
+
this.destroyed.complete();
|
|
1180
1125
|
}
|
|
1181
1126
|
/** Place focus on the first MenuItem in the menu and set the focus origin. */
|
|
1182
1127
|
focusFirstItem(focusOrigin = 'program') {
|
|
1183
|
-
this.
|
|
1184
|
-
this.
|
|
1128
|
+
this.keyManager.setFocusOrigin(focusOrigin);
|
|
1129
|
+
this.keyManager.setFirstItemActive();
|
|
1185
1130
|
}
|
|
1186
1131
|
/** Place focus on the last MenuItem in the menu and set the focus origin. */
|
|
1187
1132
|
focusLastItem(focusOrigin = 'program') {
|
|
1188
|
-
this.
|
|
1189
|
-
this.
|
|
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
|
+
|
|
1212
|
+
/**
|
|
1213
|
+
* @license
|
|
1214
|
+
* Copyright Google LLC All Rights Reserved.
|
|
1215
|
+
*
|
|
1216
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
1217
|
+
* found in the LICENSE file at https://angular.io/license
|
|
1218
|
+
*/
|
|
1219
|
+
/**
|
|
1220
|
+
* Directive which configures the element as a Menu which should contain child elements marked as
|
|
1221
|
+
* CdkMenuItem or CdkMenuGroup. Sets the appropriate role and aria-attributes for a menu and
|
|
1222
|
+
* contains accessible keyboard and mouse handling logic.
|
|
1223
|
+
*
|
|
1224
|
+
* It also acts as a RadioGroup for elements marked with role `menuitemradio`.
|
|
1225
|
+
*/
|
|
1226
|
+
class CdkMenu extends CdkMenuBase {
|
|
1227
|
+
constructor(_ngZone, elementRef, menuStack, _parentTrigger, _menuAim, dir) {
|
|
1228
|
+
super(elementRef, menuStack, dir);
|
|
1229
|
+
this._ngZone = _ngZone;
|
|
1230
|
+
this._parentTrigger = _parentTrigger;
|
|
1231
|
+
this._menuAim = _menuAim;
|
|
1232
|
+
/** Event emitted when the menu is closed. */
|
|
1233
|
+
this.closed = new EventEmitter();
|
|
1234
|
+
this.destroyed.subscribe(this.closed);
|
|
1235
|
+
if (!this._isInline()) {
|
|
1236
|
+
this.menuStack.push(this);
|
|
1237
|
+
}
|
|
1238
|
+
this._parentTrigger?.registerChildMenu(this);
|
|
1239
|
+
}
|
|
1240
|
+
ngAfterContentInit() {
|
|
1241
|
+
super.ngAfterContentInit();
|
|
1242
|
+
this._completeChangeEmitter();
|
|
1243
|
+
this._subscribeToMenuStackEmptied();
|
|
1244
|
+
this._subscribeToMouseManager();
|
|
1245
|
+
this._menuAim?.initialize(this, this.pointerTracker);
|
|
1246
|
+
}
|
|
1247
|
+
ngOnDestroy() {
|
|
1248
|
+
super.ngOnDestroy();
|
|
1249
|
+
this.closed.complete();
|
|
1250
|
+
this.pointerTracker?.destroy();
|
|
1190
1251
|
}
|
|
1191
1252
|
/** Handle keyboard events for the Menu. */
|
|
1192
1253
|
_handleKeyEvent(event) {
|
|
1193
|
-
const keyManager = this.
|
|
1254
|
+
const keyManager = this.keyManager;
|
|
1194
1255
|
switch (event.keyCode) {
|
|
1195
1256
|
case LEFT_ARROW:
|
|
1196
1257
|
case RIGHT_ARROW:
|
|
1197
|
-
if (this.
|
|
1258
|
+
if (this.isHorizontal()) {
|
|
1198
1259
|
event.preventDefault();
|
|
1199
1260
|
keyManager.setFocusOrigin('keyboard');
|
|
1200
1261
|
keyManager.onKeydown(event);
|
|
@@ -1202,7 +1263,7 @@ class CdkMenu extends CdkMenuGroup {
|
|
|
1202
1263
|
break;
|
|
1203
1264
|
case UP_ARROW:
|
|
1204
1265
|
case DOWN_ARROW:
|
|
1205
|
-
if (!this.
|
|
1266
|
+
if (!this.isHorizontal()) {
|
|
1206
1267
|
event.preventDefault();
|
|
1207
1268
|
keyManager.setFocusOrigin('keyboard');
|
|
1208
1269
|
keyManager.onKeydown(event);
|
|
@@ -1211,31 +1272,23 @@ class CdkMenu extends CdkMenuGroup {
|
|
|
1211
1272
|
case ESCAPE:
|
|
1212
1273
|
if (!hasModifierKey(event)) {
|
|
1213
1274
|
event.preventDefault();
|
|
1214
|
-
this.
|
|
1275
|
+
this.menuStack.close(this, 2 /* currentItem */);
|
|
1215
1276
|
}
|
|
1216
1277
|
break;
|
|
1217
1278
|
case TAB:
|
|
1218
|
-
this.
|
|
1279
|
+
this.menuStack.closeAll();
|
|
1219
1280
|
break;
|
|
1220
1281
|
default:
|
|
1221
1282
|
keyManager.onKeydown(event);
|
|
1222
1283
|
}
|
|
1223
1284
|
}
|
|
1224
|
-
/** Register this menu with its enclosing parent menu panel */
|
|
1225
|
-
_registerWithParentPanel() {
|
|
1226
|
-
this._getMenuPanel()?._registerMenu(this);
|
|
1227
|
-
}
|
|
1228
|
-
/**
|
|
1229
|
-
* Get the enclosing CdkMenuPanel defaulting to the injected reference over the developer
|
|
1230
|
-
* provided reference.
|
|
1231
|
-
*/
|
|
1232
|
-
_getMenuPanel() {
|
|
1233
|
-
return this._menuPanel || this._explicitPanel;
|
|
1234
|
-
}
|
|
1235
1285
|
/**
|
|
1236
1286
|
* Complete the change emitter if there are any nested MenuGroups or register to complete the
|
|
1237
1287
|
* change emitter if a MenuGroup is rendered at some point
|
|
1238
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.
|
|
1239
1292
|
_completeChangeEmitter() {
|
|
1240
1293
|
if (this._hasNestedGroups()) {
|
|
1241
1294
|
this.change.complete();
|
|
@@ -1252,59 +1305,21 @@ class CdkMenu extends CdkMenuGroup {
|
|
|
1252
1305
|
// order to ensure that we return true iff there are child CdkMenuGroup elements.
|
|
1253
1306
|
return this._nestedGroups.length > 0 && !(this._nestedGroups.first instanceof CdkMenu);
|
|
1254
1307
|
}
|
|
1255
|
-
/** Setup the FocusKeyManager with the correct orientation for the menu. */
|
|
1256
|
-
_setKeyManager() {
|
|
1257
|
-
this._keyManager = new FocusKeyManager(this._allItems)
|
|
1258
|
-
.withWrap()
|
|
1259
|
-
.withTypeAhead()
|
|
1260
|
-
.withHomeAndEnd();
|
|
1261
|
-
if (this._isHorizontal()) {
|
|
1262
|
-
this._keyManager.withHorizontalOrientation(this._dir?.value || 'ltr');
|
|
1263
|
-
}
|
|
1264
|
-
else {
|
|
1265
|
-
this._keyManager.withVerticalOrientation();
|
|
1266
|
-
}
|
|
1267
|
-
}
|
|
1268
1308
|
/**
|
|
1269
1309
|
* Set the PointerFocusTracker and ensure that when mouse focus changes the key manager is updated
|
|
1270
1310
|
* with the latest menu item under mouse focus.
|
|
1271
1311
|
*/
|
|
1272
1312
|
_subscribeToMouseManager() {
|
|
1273
1313
|
this._ngZone.runOutsideAngular(() => {
|
|
1274
|
-
this.
|
|
1275
|
-
this.
|
|
1314
|
+
this.pointerTracker = new PointerFocusTracker(this.items);
|
|
1315
|
+
this.pointerTracker.entered
|
|
1276
1316
|
.pipe(takeUntil(this.closed))
|
|
1277
|
-
.subscribe(item => this.
|
|
1317
|
+
.subscribe(item => this.keyManager.setActiveItem(item));
|
|
1278
1318
|
});
|
|
1279
1319
|
}
|
|
1280
|
-
/** Subscribe to the MenuStack close and empty observables. */
|
|
1281
|
-
_subscribeToMenuStack() {
|
|
1282
|
-
this._menuStack.closed
|
|
1283
|
-
.pipe(takeUntil(this.closed))
|
|
1284
|
-
.subscribe(item => this._closeOpenMenu(item));
|
|
1285
|
-
this._menuStack.emptied
|
|
1286
|
-
.pipe(takeUntil(this.closed))
|
|
1287
|
-
.subscribe(event => this._toggleMenuFocus(event));
|
|
1288
|
-
}
|
|
1289
|
-
/**
|
|
1290
|
-
* Close the open menu if the current active item opened the requested MenuStackItem.
|
|
1291
|
-
* @param item the MenuStackItem requested to be closed.
|
|
1292
|
-
*/
|
|
1293
|
-
_closeOpenMenu(menu) {
|
|
1294
|
-
const keyManager = this._keyManager;
|
|
1295
|
-
const trigger = this._openItem;
|
|
1296
|
-
if (menu === trigger?.getMenuTrigger()?.getMenu()) {
|
|
1297
|
-
trigger?.getMenuTrigger()?.closeMenu();
|
|
1298
|
-
// If the user has moused over a sibling item we want to focus the element under mouse focus
|
|
1299
|
-
// not the trigger which previously opened the now closed menu.
|
|
1300
|
-
if (trigger) {
|
|
1301
|
-
keyManager.setActiveItem(this._pointerTracker?.activeElement || trigger);
|
|
1302
|
-
}
|
|
1303
|
-
}
|
|
1304
|
-
}
|
|
1305
1320
|
/** Set focus the either the current, previous or next item based on the FocusNext event. */
|
|
1306
1321
|
_toggleMenuFocus(event) {
|
|
1307
|
-
const keyManager = this.
|
|
1322
|
+
const keyManager = this.keyManager;
|
|
1308
1323
|
switch (event) {
|
|
1309
1324
|
case 0 /* nextItem */:
|
|
1310
1325
|
keyManager.setFocusOrigin('keyboard');
|
|
@@ -1322,95 +1337,65 @@ class CdkMenu extends CdkMenuGroup {
|
|
|
1322
1337
|
break;
|
|
1323
1338
|
}
|
|
1324
1339
|
}
|
|
1325
|
-
// TODO(andy9775): remove duplicate logic between menu an menu bar
|
|
1326
|
-
/**
|
|
1327
|
-
* Subscribe to the menu trigger's open events in order to track the trigger which opened the menu
|
|
1328
|
-
* and stop tracking it when the menu is closed.
|
|
1329
|
-
*/
|
|
1330
|
-
_subscribeToMenuOpen() {
|
|
1331
|
-
const exitCondition = merge(this._allItems.changes, this.closed);
|
|
1332
|
-
this._allItems.changes
|
|
1333
|
-
.pipe(startWith(this._allItems), mergeMap((list) => list
|
|
1334
|
-
.filter(item => item.hasMenu())
|
|
1335
|
-
.map(item => item.getMenuTrigger().opened.pipe(mapTo(item), takeUntil(exitCondition)))), mergeAll(), switchMap((item) => {
|
|
1336
|
-
this._openItem = item;
|
|
1337
|
-
return item.getMenuTrigger().closed;
|
|
1338
|
-
}), takeUntil(this.closed))
|
|
1339
|
-
.subscribe(() => (this._openItem = undefined));
|
|
1340
|
-
}
|
|
1341
|
-
/** Return true if this menu has been configured in a horizontal orientation. */
|
|
1342
|
-
_isHorizontal() {
|
|
1343
|
-
return this.orientation === 'horizontal';
|
|
1344
|
-
}
|
|
1345
1340
|
/**
|
|
1346
1341
|
* Return true if this menu is an inline menu. That is, it does not exist in a pop-up and is
|
|
1347
1342
|
* always visible in the dom.
|
|
1348
1343
|
*/
|
|
1349
1344
|
_isInline() {
|
|
1350
|
-
|
|
1351
|
-
// automatically.
|
|
1352
|
-
return this._menuStack instanceof NoopMenuStack;
|
|
1345
|
+
return !this._parentTrigger;
|
|
1353
1346
|
}
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
}
|
|
1359
|
-
/** Emit and complete the closed event emitter */
|
|
1360
|
-
_emitClosedEvent() {
|
|
1361
|
-
this.closed.next();
|
|
1362
|
-
this.closed.complete();
|
|
1347
|
+
_subscribeToMenuStackEmptied() {
|
|
1348
|
+
this.menuStack.emptied
|
|
1349
|
+
.pipe(takeUntil(this.destroyed))
|
|
1350
|
+
.subscribe(event => this._toggleMenuFocus(event));
|
|
1363
1351
|
}
|
|
1364
1352
|
}
|
|
1365
|
-
CdkMenu.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
1366
|
-
CdkMenu.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
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: [
|
|
1367
1355
|
{ provide: CdkMenuGroup, useExisting: CdkMenu },
|
|
1368
1356
|
{ provide: CDK_MENU, useExisting: CdkMenu },
|
|
1369
|
-
|
|
1370
|
-
|
|
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: [{
|
|
1371
1360
|
type: Directive,
|
|
1372
1361
|
args: [{
|
|
1373
1362
|
selector: '[cdkMenu]',
|
|
1374
1363
|
exportAs: 'cdkMenu',
|
|
1375
1364
|
host: {
|
|
1376
|
-
'[tabindex]': '_isInline() ? 0 : null',
|
|
1377
1365
|
'role': 'menu',
|
|
1378
1366
|
'class': 'cdk-menu',
|
|
1367
|
+
'[tabindex]': '_isInline() ? 0 : null',
|
|
1379
1368
|
'[class.cdk-menu-inline]': '_isInline()',
|
|
1380
|
-
'[attr.aria-orientation]': 'orientation',
|
|
1381
|
-
'(focus)': 'focusFirstItem()',
|
|
1382
1369
|
'(keydown)': '_handleKeyEvent($event)',
|
|
1383
1370
|
},
|
|
1384
1371
|
providers: [
|
|
1385
1372
|
{ provide: CdkMenuGroup, useExisting: CdkMenu },
|
|
1386
1373
|
{ provide: CDK_MENU, useExisting: CdkMenu },
|
|
1374
|
+
PARENT_OR_NEW_INLINE_MENU_STACK_PROVIDER,
|
|
1387
1375
|
],
|
|
1388
1376
|
}]
|
|
1389
|
-
}], ctorParameters: function () { return [{ type: i0.NgZone }, { type: i0.ElementRef }, { type:
|
|
1377
|
+
}], ctorParameters: function () { return [{ type: i0.NgZone }, { type: i0.ElementRef }, { type: MenuStack, decorators: [{
|
|
1378
|
+
type: Inject,
|
|
1379
|
+
args: [MENU_STACK]
|
|
1380
|
+
}] }, { type: MenuTrigger, decorators: [{
|
|
1381
|
+
type: Optional
|
|
1382
|
+
}, {
|
|
1383
|
+
type: Inject,
|
|
1384
|
+
args: [MENU_TRIGGER]
|
|
1385
|
+
}] }, { type: undefined, decorators: [{
|
|
1390
1386
|
type: Self
|
|
1391
1387
|
}, {
|
|
1392
1388
|
type: Optional
|
|
1393
1389
|
}, {
|
|
1394
1390
|
type: Inject,
|
|
1395
1391
|
args: [MENU_AIM]
|
|
1396
|
-
}] }, { type:
|
|
1392
|
+
}] }, { type: i1$1.Directionality, decorators: [{
|
|
1397
1393
|
type: Optional
|
|
1398
|
-
}] },
|
|
1399
|
-
type: Optional
|
|
1400
|
-
}] }]; }, propDecorators: { orientation: [{
|
|
1401
|
-
type: Input,
|
|
1402
|
-
args: ['cdkMenuOrientation']
|
|
1403
|
-
}], closed: [{
|
|
1394
|
+
}] }]; }, propDecorators: { closed: [{
|
|
1404
1395
|
type: Output
|
|
1405
1396
|
}], _nestedGroups: [{
|
|
1406
1397
|
type: ContentChildren,
|
|
1407
1398
|
args: [CdkMenuGroup, { descendants: true }]
|
|
1408
|
-
}], _allItems: [{
|
|
1409
|
-
type: ContentChildren,
|
|
1410
|
-
args: [CdkMenuItem, { descendants: true }]
|
|
1411
|
-
}], _explicitPanel: [{
|
|
1412
|
-
type: Input,
|
|
1413
|
-
args: ['cdkMenuPanel']
|
|
1414
1399
|
}] } });
|
|
1415
1400
|
|
|
1416
1401
|
/**
|
|
@@ -1426,39 +1411,22 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.5",
|
|
|
1426
1411
|
* this directive is applied to should contain components marked with CdkMenuItem.
|
|
1427
1412
|
*
|
|
1428
1413
|
*/
|
|
1429
|
-
class CdkMenuBar extends
|
|
1430
|
-
constructor(
|
|
1431
|
-
super();
|
|
1432
|
-
this._menuStack = _menuStack;
|
|
1414
|
+
class CdkMenuBar extends CdkMenuBase {
|
|
1415
|
+
constructor(_ngZone, elementRef, menuStack, _menuAim, dir) {
|
|
1416
|
+
super(elementRef, menuStack, dir);
|
|
1433
1417
|
this._ngZone = _ngZone;
|
|
1434
|
-
this._elementRef = _elementRef;
|
|
1435
1418
|
this._menuAim = _menuAim;
|
|
1436
|
-
this._dir = _dir;
|
|
1437
|
-
/**
|
|
1438
|
-
* Sets the aria-orientation attribute and determines where menus will be opened.
|
|
1439
|
-
* Does not affect styling/layout.
|
|
1440
|
-
*/
|
|
1441
1419
|
this.orientation = 'horizontal';
|
|
1442
|
-
/** Emits when the MenuBar is destroyed. */
|
|
1443
|
-
this._destroyed = new Subject();
|
|
1444
1420
|
}
|
|
1445
1421
|
ngAfterContentInit() {
|
|
1446
1422
|
super.ngAfterContentInit();
|
|
1447
|
-
this.
|
|
1448
|
-
this._subscribeToMenuOpen();
|
|
1449
|
-
this._subscribeToMenuStack();
|
|
1423
|
+
this._subscribeToMenuStackEmptied();
|
|
1450
1424
|
this._subscribeToMouseManager();
|
|
1451
|
-
this._menuAim?.initialize(this, this.
|
|
1452
|
-
}
|
|
1453
|
-
/** Place focus on the first MenuItem in the menu and set the focus origin. */
|
|
1454
|
-
focusFirstItem(focusOrigin = 'program') {
|
|
1455
|
-
this._keyManager.setFocusOrigin(focusOrigin);
|
|
1456
|
-
this._keyManager.setFirstItemActive();
|
|
1425
|
+
this._menuAim?.initialize(this, this.pointerTracker);
|
|
1457
1426
|
}
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
this.
|
|
1461
|
-
this._keyManager.setLastItemActive();
|
|
1427
|
+
ngOnDestroy() {
|
|
1428
|
+
super.ngOnDestroy();
|
|
1429
|
+
this.pointerTracker?.destroy();
|
|
1462
1430
|
}
|
|
1463
1431
|
/**
|
|
1464
1432
|
* Handle keyboard events, specifically changing the focused element and/or toggling the active
|
|
@@ -1466,7 +1434,7 @@ class CdkMenuBar extends CdkMenuGroup {
|
|
|
1466
1434
|
* @param event the KeyboardEvent to handle.
|
|
1467
1435
|
*/
|
|
1468
1436
|
_handleKeyEvent(event) {
|
|
1469
|
-
const keyManager = this.
|
|
1437
|
+
const keyManager = this.keyManager;
|
|
1470
1438
|
switch (event.keyCode) {
|
|
1471
1439
|
case UP_ARROW:
|
|
1472
1440
|
case DOWN_ARROW:
|
|
@@ -1476,97 +1444,59 @@ class CdkMenuBar extends CdkMenuGroup {
|
|
|
1476
1444
|
// For a horizontal menu if the left/right keys were clicked, or a vertical menu if the
|
|
1477
1445
|
// up/down keys were clicked: if the current menu is open, close it then focus and open the
|
|
1478
1446
|
// next menu.
|
|
1479
|
-
if ((this.
|
|
1480
|
-
(!this.
|
|
1447
|
+
if ((this.isHorizontal() && horizontalArrows) ||
|
|
1448
|
+
(!this.isHorizontal() && !horizontalArrows)) {
|
|
1481
1449
|
event.preventDefault();
|
|
1482
1450
|
const prevIsOpen = keyManager.activeItem?.isMenuOpen();
|
|
1483
|
-
keyManager.activeItem?.getMenuTrigger()?.
|
|
1451
|
+
keyManager.activeItem?.getMenuTrigger()?.close();
|
|
1484
1452
|
keyManager.setFocusOrigin('keyboard');
|
|
1485
1453
|
keyManager.onKeydown(event);
|
|
1486
1454
|
if (prevIsOpen) {
|
|
1487
|
-
keyManager.activeItem?.getMenuTrigger()?.
|
|
1455
|
+
keyManager.activeItem?.getMenuTrigger()?.open();
|
|
1488
1456
|
}
|
|
1489
1457
|
}
|
|
1490
1458
|
break;
|
|
1491
1459
|
case ESCAPE:
|
|
1492
1460
|
event.preventDefault();
|
|
1493
|
-
keyManager.activeItem?.getMenuTrigger()?.
|
|
1461
|
+
keyManager.activeItem?.getMenuTrigger()?.close();
|
|
1494
1462
|
break;
|
|
1495
1463
|
case TAB:
|
|
1496
|
-
keyManager.activeItem?.getMenuTrigger()?.
|
|
1464
|
+
keyManager.activeItem?.getMenuTrigger()?.close();
|
|
1497
1465
|
break;
|
|
1498
1466
|
default:
|
|
1499
1467
|
keyManager.onKeydown(event);
|
|
1500
1468
|
}
|
|
1501
1469
|
}
|
|
1502
|
-
/** Setup the FocusKeyManager with the correct orientation for the menu bar. */
|
|
1503
|
-
_setKeyManager() {
|
|
1504
|
-
this._keyManager = new FocusKeyManager(this._allItems)
|
|
1505
|
-
.withWrap()
|
|
1506
|
-
.withTypeAhead()
|
|
1507
|
-
.withHomeAndEnd();
|
|
1508
|
-
if (this._isHorizontal()) {
|
|
1509
|
-
this._keyManager.withHorizontalOrientation(this._dir?.value || 'ltr');
|
|
1510
|
-
}
|
|
1511
|
-
else {
|
|
1512
|
-
this._keyManager.withVerticalOrientation();
|
|
1513
|
-
}
|
|
1514
|
-
}
|
|
1515
1470
|
/**
|
|
1516
1471
|
* Set the PointerFocusTracker and ensure that when mouse focus changes the key manager is updated
|
|
1517
1472
|
* with the latest menu item under mouse focus.
|
|
1518
1473
|
*/
|
|
1519
1474
|
_subscribeToMouseManager() {
|
|
1520
1475
|
this._ngZone.runOutsideAngular(() => {
|
|
1521
|
-
this.
|
|
1522
|
-
this.
|
|
1523
|
-
if (this.
|
|
1524
|
-
this.
|
|
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);
|
|
1525
1480
|
}
|
|
1526
1481
|
});
|
|
1527
1482
|
});
|
|
1528
1483
|
}
|
|
1529
|
-
/** Subscribe to the MenuStack close and empty observables. */
|
|
1530
|
-
_subscribeToMenuStack() {
|
|
1531
|
-
this._menuStack.closed
|
|
1532
|
-
.pipe(takeUntil(this._destroyed))
|
|
1533
|
-
.subscribe(item => this._closeOpenMenu(item));
|
|
1534
|
-
this._menuStack.emptied
|
|
1535
|
-
.pipe(takeUntil(this._destroyed))
|
|
1536
|
-
.subscribe(event => this._toggleOpenMenu(event));
|
|
1537
|
-
}
|
|
1538
|
-
/**
|
|
1539
|
-
* Close the open menu if the current active item opened the requested MenuStackItem.
|
|
1540
|
-
* @param item the MenuStackItem requested to be closed.
|
|
1541
|
-
*/
|
|
1542
|
-
_closeOpenMenu(menu) {
|
|
1543
|
-
const trigger = this._openItem;
|
|
1544
|
-
const keyManager = this._keyManager;
|
|
1545
|
-
if (menu === trigger?.getMenuTrigger()?.getMenu()) {
|
|
1546
|
-
trigger?.getMenuTrigger()?.closeMenu();
|
|
1547
|
-
// If the user has moused over a sibling item we want to focus the element under mouse focus
|
|
1548
|
-
// not the trigger which previously opened the now closed menu.
|
|
1549
|
-
if (trigger) {
|
|
1550
|
-
keyManager.setActiveItem(this._pointerTracker?.activeElement || trigger);
|
|
1551
|
-
}
|
|
1552
|
-
}
|
|
1553
|
-
}
|
|
1554
1484
|
/**
|
|
1555
1485
|
* Set focus to either the current, previous or next item based on the FocusNext event, then
|
|
1556
1486
|
* open the previous or next item.
|
|
1557
1487
|
*/
|
|
1558
1488
|
_toggleOpenMenu(event) {
|
|
1559
|
-
const keyManager = this.
|
|
1489
|
+
const keyManager = this.keyManager;
|
|
1560
1490
|
switch (event) {
|
|
1561
1491
|
case 0 /* nextItem */:
|
|
1562
1492
|
keyManager.setFocusOrigin('keyboard');
|
|
1563
1493
|
keyManager.setNextItemActive();
|
|
1564
|
-
keyManager.activeItem?.getMenuTrigger()?.
|
|
1494
|
+
keyManager.activeItem?.getMenuTrigger()?.open();
|
|
1565
1495
|
break;
|
|
1566
1496
|
case 1 /* previousItem */:
|
|
1567
1497
|
keyManager.setFocusOrigin('keyboard');
|
|
1568
1498
|
keyManager.setPreviousItemActive();
|
|
1569
|
-
keyManager.activeItem?.getMenuTrigger()?.
|
|
1499
|
+
keyManager.activeItem?.getMenuTrigger()?.open();
|
|
1570
1500
|
break;
|
|
1571
1501
|
case 2 /* currentItem */:
|
|
1572
1502
|
if (keyManager.activeItem) {
|
|
@@ -1576,45 +1506,19 @@ class CdkMenuBar extends CdkMenuGroup {
|
|
|
1576
1506
|
break;
|
|
1577
1507
|
}
|
|
1578
1508
|
}
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
return this.orientation === 'horizontal';
|
|
1584
|
-
}
|
|
1585
|
-
/**
|
|
1586
|
-
* Subscribe to the menu trigger's open events in order to track the trigger which opened the menu
|
|
1587
|
-
* and stop tracking it when the menu is closed.
|
|
1588
|
-
*/
|
|
1589
|
-
_subscribeToMenuOpen() {
|
|
1590
|
-
const exitCondition = merge(this._allItems.changes, this._destroyed);
|
|
1591
|
-
this._allItems.changes
|
|
1592
|
-
.pipe(startWith(this._allItems), mergeMap((list) => list
|
|
1593
|
-
.filter(item => item.hasMenu())
|
|
1594
|
-
.map(item => item.getMenuTrigger().opened.pipe(mapTo(item), takeUntil(exitCondition)))), mergeAll(), switchMap((item) => {
|
|
1595
|
-
this._openItem = item;
|
|
1596
|
-
return item.getMenuTrigger().closed;
|
|
1597
|
-
}), takeUntil(this._destroyed))
|
|
1598
|
-
.subscribe(() => (this._openItem = undefined));
|
|
1599
|
-
}
|
|
1600
|
-
/** Return true if the MenuBar has an open submenu. */
|
|
1601
|
-
_hasOpenSubmenu() {
|
|
1602
|
-
return !!this._openItem;
|
|
1603
|
-
}
|
|
1604
|
-
ngOnDestroy() {
|
|
1605
|
-
super.ngOnDestroy();
|
|
1606
|
-
this._destroyed.next();
|
|
1607
|
-
this._destroyed.complete();
|
|
1608
|
-
this._pointerTracker?.destroy();
|
|
1509
|
+
_subscribeToMenuStackEmptied() {
|
|
1510
|
+
this.menuStack?.emptied
|
|
1511
|
+
.pipe(takeUntil(this.destroyed))
|
|
1512
|
+
.subscribe(event => this._toggleOpenMenu(event));
|
|
1609
1513
|
}
|
|
1610
1514
|
}
|
|
1611
|
-
CdkMenuBar.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
1612
|
-
CdkMenuBar.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
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: [
|
|
1613
1517
|
{ provide: CdkMenuGroup, useExisting: CdkMenuBar },
|
|
1614
1518
|
{ provide: CDK_MENU, useExisting: CdkMenuBar },
|
|
1615
|
-
{ provide:
|
|
1616
|
-
],
|
|
1617
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
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: [{
|
|
1618
1522
|
type: Directive,
|
|
1619
1523
|
args: [{
|
|
1620
1524
|
selector: '[cdkMenuBar]',
|
|
@@ -1623,32 +1527,27 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.5",
|
|
|
1623
1527
|
'role': 'menubar',
|
|
1624
1528
|
'class': 'cdk-menu-bar',
|
|
1625
1529
|
'tabindex': '0',
|
|
1626
|
-
'[attr.aria-orientation]': 'orientation',
|
|
1627
|
-
'(focus)': 'focusFirstItem()',
|
|
1628
1530
|
'(keydown)': '_handleKeyEvent($event)',
|
|
1629
1531
|
},
|
|
1630
1532
|
providers: [
|
|
1631
1533
|
{ provide: CdkMenuGroup, useExisting: CdkMenuBar },
|
|
1632
1534
|
{ provide: CDK_MENU, useExisting: CdkMenuBar },
|
|
1633
|
-
{ provide:
|
|
1535
|
+
{ provide: MENU_STACK, useFactory: () => MenuStack.inline() },
|
|
1634
1536
|
],
|
|
1635
1537
|
}]
|
|
1636
|
-
}], ctorParameters: function () { return [{ type:
|
|
1538
|
+
}], ctorParameters: function () { return [{ type: i0.NgZone }, { type: i0.ElementRef }, { type: MenuStack, decorators: [{
|
|
1539
|
+
type: Inject,
|
|
1540
|
+
args: [MENU_STACK]
|
|
1541
|
+
}] }, { type: undefined, decorators: [{
|
|
1637
1542
|
type: Self
|
|
1638
1543
|
}, {
|
|
1639
1544
|
type: Optional
|
|
1640
1545
|
}, {
|
|
1641
1546
|
type: Inject,
|
|
1642
1547
|
args: [MENU_AIM]
|
|
1643
|
-
}] }, { type:
|
|
1548
|
+
}] }, { type: i1$1.Directionality, decorators: [{
|
|
1644
1549
|
type: Optional
|
|
1645
|
-
}] }]; }
|
|
1646
|
-
type: Input,
|
|
1647
|
-
args: ['cdkMenuBarOrientation']
|
|
1648
|
-
}], _allItems: [{
|
|
1649
|
-
type: ContentChildren,
|
|
1650
|
-
args: [CdkMenuItem, { descendants: true }]
|
|
1651
|
-
}] } });
|
|
1550
|
+
}] }]; } });
|
|
1652
1551
|
|
|
1653
1552
|
/**
|
|
1654
1553
|
* @license
|
|
@@ -1663,12 +1562,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.5",
|
|
|
1663
1562
|
* or `CdkMenuGroup` comprise a radio group with unique selection enforced.
|
|
1664
1563
|
*/
|
|
1665
1564
|
class CdkMenuItemRadio extends CdkMenuItemSelectable {
|
|
1666
|
-
constructor(_selectionDispatcher, element, ngZone, parentMenu, menuAim, dir,
|
|
1565
|
+
constructor(_selectionDispatcher, element, ngZone, menuStack, parentMenu, menuAim, dir,
|
|
1667
1566
|
/** Reference to the CdkMenuItemTrigger directive if one is added to the same element */
|
|
1668
1567
|
// `CdkMenuItemRadio` is commonly used in combination with a `CdkMenuItemTrigger`.
|
|
1669
1568
|
// tslint:disable-next-line: lightweight-tokens
|
|
1670
1569
|
menuTrigger) {
|
|
1671
|
-
super(element, ngZone, parentMenu, menuAim, dir, menuTrigger);
|
|
1570
|
+
super(element, ngZone, menuStack, parentMenu, menuAim, dir, menuTrigger);
|
|
1672
1571
|
this._selectionDispatcher = _selectionDispatcher;
|
|
1673
1572
|
this._registerDispatcherListener();
|
|
1674
1573
|
}
|
|
@@ -1688,12 +1587,12 @@ class CdkMenuItemRadio extends CdkMenuItemSelectable {
|
|
|
1688
1587
|
this._removeDispatcherListener();
|
|
1689
1588
|
}
|
|
1690
1589
|
}
|
|
1691
|
-
CdkMenuItemRadio.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
1692
|
-
CdkMenuItemRadio.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
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: [
|
|
1693
1592
|
{ provide: CdkMenuItemSelectable, useExisting: CdkMenuItemRadio },
|
|
1694
1593
|
{ provide: CdkMenuItem, useExisting: CdkMenuItemSelectable },
|
|
1695
1594
|
], exportAs: ["cdkMenuItemRadio"], usesInheritance: true, ngImport: i0 });
|
|
1696
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
1595
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: CdkMenuItemRadio, decorators: [{
|
|
1697
1596
|
type: Directive,
|
|
1698
1597
|
args: [{
|
|
1699
1598
|
selector: '[cdkMenuItemRadio]',
|
|
@@ -1710,7 +1609,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.5",
|
|
|
1710
1609
|
{ provide: CdkMenuItem, useExisting: CdkMenuItemSelectable },
|
|
1711
1610
|
],
|
|
1712
1611
|
}]
|
|
1713
|
-
}], ctorParameters: function () { return [{ type: i1$
|
|
1612
|
+
}], ctorParameters: function () { return [{ type: i1$2.UniqueSelectionDispatcher }, { type: i0.ElementRef }, { type: i0.NgZone }, { type: MenuStack, decorators: [{
|
|
1613
|
+
type: Inject,
|
|
1614
|
+
args: [MENU_STACK]
|
|
1615
|
+
}] }, { type: undefined, decorators: [{
|
|
1714
1616
|
type: Optional
|
|
1715
1617
|
}, {
|
|
1716
1618
|
type: Inject,
|
|
@@ -1720,7 +1622,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.5",
|
|
|
1720
1622
|
}, {
|
|
1721
1623
|
type: Inject,
|
|
1722
1624
|
args: [MENU_AIM]
|
|
1723
|
-
}] }, { type:
|
|
1625
|
+
}] }, { type: i1$1.Directionality, decorators: [{
|
|
1724
1626
|
type: Optional
|
|
1725
1627
|
}] }, { type: CdkMenuItemTrigger, decorators: [{
|
|
1726
1628
|
type: Self
|
|
@@ -1748,12 +1650,12 @@ class CdkMenuItemCheckbox extends CdkMenuItemSelectable {
|
|
|
1748
1650
|
}
|
|
1749
1651
|
}
|
|
1750
1652
|
}
|
|
1751
|
-
CdkMenuItemCheckbox.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
1752
|
-
CdkMenuItemCheckbox.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
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: [
|
|
1753
1655
|
{ provide: CdkMenuItemSelectable, useExisting: CdkMenuItemCheckbox },
|
|
1754
1656
|
{ provide: CdkMenuItem, useExisting: CdkMenuItemSelectable },
|
|
1755
1657
|
], exportAs: ["cdkMenuItemCheckbox"], usesInheritance: true, ngImport: i0 });
|
|
1756
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
1658
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: CdkMenuItemCheckbox, decorators: [{
|
|
1757
1659
|
type: Directive,
|
|
1758
1660
|
args: [{
|
|
1759
1661
|
selector: '[cdkMenuItemCheckbox]',
|
|
@@ -1779,6 +1681,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.5",
|
|
|
1779
1681
|
* Use of this source code is governed by an MIT-style license that can be
|
|
1780
1682
|
* found in the LICENSE file at https://angular.io/license
|
|
1781
1683
|
*/
|
|
1684
|
+
// In cases where the first menu item in the context menu is a trigger the submenu opens on a
|
|
1685
|
+
// hover event. We offset the context menu 2px by default to prevent this from occurring.
|
|
1686
|
+
const CONTEXT_MENU_POSITIONS = STANDARD_DROPDOWN_BELOW_POSITIONS.map(position => {
|
|
1687
|
+
const offsetX = position.overlayX === 'start' ? 2 : -2;
|
|
1688
|
+
const offsetY = position.overlayY === 'top' ? 2 : -2;
|
|
1689
|
+
return { ...position, offsetX, offsetY };
|
|
1690
|
+
});
|
|
1782
1691
|
/** Tracks the last open context menu trigger across the entire application. */
|
|
1783
1692
|
class ContextMenuTracker {
|
|
1784
1693
|
/**
|
|
@@ -1792,54 +1701,27 @@ class ContextMenuTracker {
|
|
|
1792
1701
|
}
|
|
1793
1702
|
}
|
|
1794
1703
|
}
|
|
1795
|
-
ContextMenuTracker.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
1796
|
-
ContextMenuTracker.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
1797
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
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: [{
|
|
1798
1707
|
type: Injectable,
|
|
1799
1708
|
args: [{ providedIn: 'root' }]
|
|
1800
1709
|
}] });
|
|
1801
|
-
/** Injection token for the ContextMenu options object. */
|
|
1802
|
-
const CDK_CONTEXT_MENU_DEFAULT_OPTIONS = new InjectionToken('cdk-context-menu-default-options');
|
|
1803
1710
|
/**
|
|
1804
1711
|
* A directive which when placed on some element opens a the Menu it is bound to when a user
|
|
1805
1712
|
* right-clicks within that element. It is aware of nested Context Menus and the lowest level
|
|
1806
1713
|
* non-disabled context menu will trigger.
|
|
1807
1714
|
*/
|
|
1808
|
-
class CdkContextMenuTrigger {
|
|
1809
|
-
constructor(_viewContainerRef, _overlay, _contextMenuTracker,
|
|
1715
|
+
class CdkContextMenuTrigger extends MenuTrigger {
|
|
1716
|
+
constructor(injector, _viewContainerRef, _overlay, _contextMenuTracker, menuStack, _directionality) {
|
|
1717
|
+
super(injector, menuStack);
|
|
1810
1718
|
this._viewContainerRef = _viewContainerRef;
|
|
1811
1719
|
this._overlay = _overlay;
|
|
1812
1720
|
this._contextMenuTracker = _contextMenuTracker;
|
|
1813
|
-
this._options = _options;
|
|
1814
1721
|
this._directionality = _directionality;
|
|
1815
|
-
/** Emits when the attached menu is requested to open. */
|
|
1816
|
-
this.opened = new EventEmitter();
|
|
1817
|
-
/** Emits when the attached menu is requested to close. */
|
|
1818
|
-
this.closed = new EventEmitter();
|
|
1819
1722
|
this._disabled = false;
|
|
1820
|
-
/** A reference to the overlay which manages the triggered menu. */
|
|
1821
|
-
this._overlayRef = null;
|
|
1822
|
-
/** Emits when the element is destroyed. */
|
|
1823
|
-
this._destroyed = new Subject();
|
|
1824
|
-
/** The menu stack for this trigger and its associated menus. */
|
|
1825
|
-
this._menuStack = new MenuStack();
|
|
1826
|
-
/** Emits when the outside pointer events listener on the overlay should be stopped. */
|
|
1827
|
-
this._stopOutsideClicksListener = merge(this.closed, this._destroyed);
|
|
1828
1723
|
this._setMenuStackListener();
|
|
1829
1724
|
}
|
|
1830
|
-
/** Template reference variable to the menu to open on right click. */
|
|
1831
|
-
get menuPanel() {
|
|
1832
|
-
return this._menuPanel;
|
|
1833
|
-
}
|
|
1834
|
-
set menuPanel(panel) {
|
|
1835
|
-
if ((typeof ngDevMode === 'undefined' || ngDevMode) && panel._menuStack) {
|
|
1836
|
-
throwExistingMenuStackError();
|
|
1837
|
-
}
|
|
1838
|
-
this._menuPanel = panel;
|
|
1839
|
-
if (this._menuPanel) {
|
|
1840
|
-
this._menuPanel._menuStack = this._menuStack;
|
|
1841
|
-
}
|
|
1842
|
-
}
|
|
1843
1725
|
/** Whether the context menu should be disabled. */
|
|
1844
1726
|
get disabled() {
|
|
1845
1727
|
return this._disabled;
|
|
@@ -1861,7 +1743,7 @@ class CdkContextMenuTrigger {
|
|
|
1861
1743
|
else if (this.isOpen()) {
|
|
1862
1744
|
// since we're moving this menu we need to close any submenus first otherwise they end up
|
|
1863
1745
|
// disconnected from this one.
|
|
1864
|
-
this.
|
|
1746
|
+
this.menuStack.closeSubMenuOf(this.childMenu);
|
|
1865
1747
|
this._overlayRef.getConfig().positionStrategy.setOrigin(coordinates);
|
|
1866
1748
|
this._overlayRef.updatePosition();
|
|
1867
1749
|
}
|
|
@@ -1880,7 +1762,7 @@ class CdkContextMenuTrigger {
|
|
|
1880
1762
|
}
|
|
1881
1763
|
/** Close the opened menu. */
|
|
1882
1764
|
close() {
|
|
1883
|
-
this.
|
|
1765
|
+
this.menuStack.closeAll();
|
|
1884
1766
|
}
|
|
1885
1767
|
/**
|
|
1886
1768
|
* Open the context menu and close any previously open menus.
|
|
@@ -1898,20 +1780,16 @@ class CdkContextMenuTrigger {
|
|
|
1898
1780
|
this._open({ x: event.clientX, y: event.clientY }, true);
|
|
1899
1781
|
// A context menu can be triggered via a mouse right click or a keyboard shortcut.
|
|
1900
1782
|
if (event.button === 2) {
|
|
1901
|
-
this.
|
|
1783
|
+
this.childMenu?.focusFirstItem('mouse');
|
|
1902
1784
|
}
|
|
1903
1785
|
else if (event.button === 0) {
|
|
1904
|
-
this.
|
|
1786
|
+
this.childMenu?.focusFirstItem('keyboard');
|
|
1905
1787
|
}
|
|
1906
1788
|
else {
|
|
1907
|
-
this.
|
|
1789
|
+
this.childMenu?.focusFirstItem('program');
|
|
1908
1790
|
}
|
|
1909
1791
|
}
|
|
1910
1792
|
}
|
|
1911
|
-
/** Whether the attached menu is open. */
|
|
1912
|
-
isOpen() {
|
|
1913
|
-
return !!this._overlayRef?.hasAttached();
|
|
1914
|
-
}
|
|
1915
1793
|
/**
|
|
1916
1794
|
* Get the configuration object used to create the overlay.
|
|
1917
1795
|
* @param coordinates the location to place the opened menu
|
|
@@ -1931,37 +1809,23 @@ class CdkContextMenuTrigger {
|
|
|
1931
1809
|
return this._overlay
|
|
1932
1810
|
.position()
|
|
1933
1811
|
.flexibleConnectedTo(coordinates)
|
|
1934
|
-
.
|
|
1935
|
-
.withDefaultOffsetY(this._options.offsetY)
|
|
1936
|
-
.withPositions(this._getOverlayPositions());
|
|
1937
|
-
}
|
|
1938
|
-
/**
|
|
1939
|
-
* Determine and return where to position the opened menu relative to the mouse location.
|
|
1940
|
-
*/
|
|
1941
|
-
_getOverlayPositions() {
|
|
1942
|
-
// TODO: this should be configurable through the injected context menu options
|
|
1943
|
-
return [
|
|
1944
|
-
{ originX: 'end', originY: 'top', overlayX: 'start', overlayY: 'top' },
|
|
1945
|
-
{ originX: 'start', originY: 'top', overlayX: 'end', overlayY: 'top' },
|
|
1946
|
-
{ originX: 'end', originY: 'bottom', overlayX: 'start', overlayY: 'bottom' },
|
|
1947
|
-
{ originX: 'start', originY: 'bottom', overlayX: 'end', overlayY: 'bottom' },
|
|
1948
|
-
];
|
|
1812
|
+
.withPositions(this.menuPosition ?? CONTEXT_MENU_POSITIONS);
|
|
1949
1813
|
}
|
|
1950
1814
|
/**
|
|
1951
1815
|
* Get the portal to be attached to the overlay which contains the menu. Allows for the menu
|
|
1952
1816
|
* content to change dynamically and be reflected in the application.
|
|
1953
1817
|
*/
|
|
1954
1818
|
_getMenuContent() {
|
|
1955
|
-
const hasMenuContentChanged = this.
|
|
1956
|
-
if (this.
|
|
1957
|
-
this.
|
|
1819
|
+
const hasMenuContentChanged = this._menuTemplateRef !== this._menuPortal?.templateRef;
|
|
1820
|
+
if (this._menuTemplateRef && (!this._menuPortal || hasMenuContentChanged)) {
|
|
1821
|
+
this._menuPortal = new TemplatePortal(this._menuTemplateRef, this._viewContainerRef, undefined, this.getChildMenuInjector());
|
|
1958
1822
|
}
|
|
1959
|
-
return this.
|
|
1823
|
+
return this._menuPortal;
|
|
1960
1824
|
}
|
|
1961
1825
|
/** Subscribe to the menu stack close events and close this menu when requested. */
|
|
1962
1826
|
_setMenuStackListener() {
|
|
1963
|
-
this.
|
|
1964
|
-
if (item === this.
|
|
1827
|
+
this.menuStack.closed.pipe(takeUntil(this._destroyed)).subscribe(item => {
|
|
1828
|
+
if (item === this.childMenu && this.isOpen()) {
|
|
1965
1829
|
this.closed.next();
|
|
1966
1830
|
this._overlayRef.detach();
|
|
1967
1831
|
}
|
|
@@ -1982,44 +1846,18 @@ class CdkContextMenuTrigger {
|
|
|
1982
1846
|
}
|
|
1983
1847
|
outsideClicks.pipe(takeUntil(this._stopOutsideClicksListener)).subscribe(event => {
|
|
1984
1848
|
if (!isClickInsideMenuOverlay(event.target)) {
|
|
1985
|
-
this.
|
|
1849
|
+
this.menuStack.closeAll();
|
|
1986
1850
|
}
|
|
1987
1851
|
});
|
|
1988
1852
|
}
|
|
1989
1853
|
}
|
|
1990
|
-
ngOnDestroy() {
|
|
1991
|
-
this._destroyOverlay();
|
|
1992
|
-
this._resetPanelMenuStack();
|
|
1993
|
-
this._destroyed.next();
|
|
1994
|
-
this._destroyed.complete();
|
|
1995
|
-
}
|
|
1996
|
-
/** Destroy and unset the overlay reference it if exists. */
|
|
1997
|
-
_destroyOverlay() {
|
|
1998
|
-
if (this._overlayRef) {
|
|
1999
|
-
this._overlayRef.dispose();
|
|
2000
|
-
this._overlayRef = null;
|
|
2001
|
-
}
|
|
2002
|
-
}
|
|
2003
|
-
/** Set the menu panels menu stack back to null. */
|
|
2004
|
-
_resetPanelMenuStack() {
|
|
2005
|
-
// If a ContextMenuTrigger is placed in a conditionally rendered view, each time the trigger is
|
|
2006
|
-
// rendered the panel setter for ContextMenuTrigger is called. From the first render onward,
|
|
2007
|
-
// the attached CdkMenuPanel has the MenuStack set. Since we throw an error if a panel already
|
|
2008
|
-
// has a stack set, we want to reset the attached stack here to prevent the error from being
|
|
2009
|
-
// thrown if the trigger re-configures its attached panel (in the case where there is a 1:1
|
|
2010
|
-
// relationship between the panel and trigger).
|
|
2011
|
-
if (this._menuPanel) {
|
|
2012
|
-
this._menuPanel._menuStack = null;
|
|
2013
|
-
}
|
|
2014
|
-
}
|
|
2015
1854
|
}
|
|
2016
|
-
CdkContextMenuTrigger.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
2017
|
-
CdkContextMenuTrigger.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.5", ngImport: i0, type: CdkContextMenuTrigger, decorators: [{
|
|
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: [
|
|
1857
|
+
{ provide: MENU_TRIGGER, useExisting: CdkContextMenuTrigger },
|
|
1858
|
+
{ provide: MENU_STACK, useClass: MenuStack },
|
|
1859
|
+
], exportAs: ["cdkContextMenuTriggerFor"], usesInheritance: true, ngImport: i0 });
|
|
1860
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.9", ngImport: i0, type: CdkContextMenuTrigger, decorators: [{
|
|
2023
1861
|
type: Directive,
|
|
2024
1862
|
args: [{
|
|
2025
1863
|
selector: '[cdkContextMenuTriggerFor]',
|
|
@@ -2027,27 +1865,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.5",
|
|
|
2027
1865
|
host: {
|
|
2028
1866
|
'(contextmenu)': '_openOnContextMenu($event)',
|
|
2029
1867
|
},
|
|
1868
|
+
inputs: ['_menuTemplateRef: cdkContextMenuTriggerFor', 'menuPosition: cdkContextMenuPosition'],
|
|
1869
|
+
outputs: ['opened: cdkContextMenuOpened', 'closed: cdkContextMenuClosed'],
|
|
2030
1870
|
providers: [
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
{ provide: CDK_CONTEXT_MENU_DEFAULT_OPTIONS, useValue: { offsetX: 2, offsetY: 2 } },
|
|
1871
|
+
{ provide: MENU_TRIGGER, useExisting: CdkContextMenuTrigger },
|
|
1872
|
+
{ provide: MENU_STACK, useClass: MenuStack },
|
|
2034
1873
|
],
|
|
2035
1874
|
}]
|
|
2036
|
-
}], ctorParameters: function () { return [{ type: i0.ViewContainerRef }, { type: i1.Overlay }, { type: ContextMenuTracker }, { type:
|
|
1875
|
+
}], ctorParameters: function () { return [{ type: i0.Injector }, { type: i0.ViewContainerRef }, { type: i1.Overlay }, { type: ContextMenuTracker }, { type: MenuStack, decorators: [{
|
|
2037
1876
|
type: Inject,
|
|
2038
|
-
args: [
|
|
2039
|
-
}] }, { type:
|
|
1877
|
+
args: [MENU_STACK]
|
|
1878
|
+
}] }, { type: i1$1.Directionality, decorators: [{
|
|
2040
1879
|
type: Optional
|
|
2041
|
-
}] }]; }, propDecorators: {
|
|
2042
|
-
type: Input,
|
|
2043
|
-
args: ['cdkContextMenuTriggerFor']
|
|
2044
|
-
}], opened: [{
|
|
2045
|
-
type: Output,
|
|
2046
|
-
args: ['cdkContextMenuOpened']
|
|
2047
|
-
}], closed: [{
|
|
2048
|
-
type: Output,
|
|
2049
|
-
args: ['cdkContextMenuClosed']
|
|
2050
|
-
}], disabled: [{
|
|
1880
|
+
}] }]; }, propDecorators: { disabled: [{
|
|
2051
1881
|
type: Input,
|
|
2052
1882
|
args: ['cdkContextMenuDisabled']
|
|
2053
1883
|
}] } });
|
|
@@ -2062,7 +1892,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.5",
|
|
|
2062
1892
|
const EXPORTED_DECLARATIONS = [
|
|
2063
1893
|
CdkMenuBar,
|
|
2064
1894
|
CdkMenu,
|
|
2065
|
-
CdkMenuPanel,
|
|
2066
1895
|
CdkMenuItem,
|
|
2067
1896
|
CdkMenuItemRadio,
|
|
2068
1897
|
CdkMenuItemCheckbox,
|
|
@@ -2073,10 +1902,9 @@ const EXPORTED_DECLARATIONS = [
|
|
|
2073
1902
|
];
|
|
2074
1903
|
class CdkMenuModule {
|
|
2075
1904
|
}
|
|
2076
|
-
CdkMenuModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
2077
|
-
CdkMenuModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
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,
|
|
2078
1907
|
CdkMenu,
|
|
2079
|
-
CdkMenuPanel,
|
|
2080
1908
|
CdkMenuItem,
|
|
2081
1909
|
CdkMenuItemRadio,
|
|
2082
1910
|
CdkMenuItemCheckbox,
|
|
@@ -2085,7 +1913,6 @@ CdkMenuModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version:
|
|
|
2085
1913
|
CdkContextMenuTrigger,
|
|
2086
1914
|
CdkTargetMenuAim], imports: [OverlayModule], exports: [CdkMenuBar,
|
|
2087
1915
|
CdkMenu,
|
|
2088
|
-
CdkMenuPanel,
|
|
2089
1916
|
CdkMenuItem,
|
|
2090
1917
|
CdkMenuItemRadio,
|
|
2091
1918
|
CdkMenuItemCheckbox,
|
|
@@ -2093,8 +1920,8 @@ CdkMenuModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version:
|
|
|
2093
1920
|
CdkMenuGroup,
|
|
2094
1921
|
CdkContextMenuTrigger,
|
|
2095
1922
|
CdkTargetMenuAim] });
|
|
2096
|
-
CdkMenuModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
2097
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.
|
|
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: [{
|
|
2098
1925
|
type: NgModule,
|
|
2099
1926
|
args: [{
|
|
2100
1927
|
imports: [OverlayModule],
|
|
@@ -2123,5 +1950,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0-next.5",
|
|
|
2123
1950
|
* Generated bundle index. Do not edit.
|
|
2124
1951
|
*/
|
|
2125
1952
|
|
|
2126
|
-
export {
|
|
1953
|
+
export { CDK_MENU, CdkContextMenuTrigger, CdkMenu, CdkMenuBar, CdkMenuGroup, CdkMenuItem, CdkMenuItemCheckbox, CdkMenuItemRadio, CdkMenuItemTrigger, CdkMenuModule, CdkTargetMenuAim, ContextMenuTracker, MENU_AIM, MENU_STACK, MENU_TRIGGER, MenuStack, MenuTrigger, TargetMenuAim, isClickInsideMenuOverlay };
|
|
2127
1954
|
//# sourceMappingURL=menu.mjs.map
|