@angular/cdk 21.0.0-next.9 → 21.0.0-rc.1
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/_adev_assets/cdk_drag_drop.json +13 -12
- package/_adev_assets/cdk_testing.json +9 -9
- package/_adev_assets/cdk_testing_protractor.json +1 -1
- package/_adev_assets/cdk_testing_selenium_webdriver.json +1 -1
- package/_adev_assets/cdk_testing_testbed.json +1 -1
- package/fesm2022/_a11y-module-chunk.mjs +755 -869
- package/fesm2022/_a11y-module-chunk.mjs.map +1 -1
- package/fesm2022/_activedescendant-key-manager-chunk.mjs +8 -8
- package/fesm2022/_activedescendant-key-manager-chunk.mjs.map +1 -1
- package/fesm2022/_array-chunk.mjs +1 -1
- package/fesm2022/_array-chunk.mjs.map +1 -1
- package/fesm2022/_breakpoints-observer-chunk.mjs +149 -152
- package/fesm2022/_breakpoints-observer-chunk.mjs.map +1 -1
- package/fesm2022/_css-pixel-value-chunk.mjs +4 -5
- package/fesm2022/_css-pixel-value-chunk.mjs.map +1 -1
- package/fesm2022/_data-source-chunk.mjs +2 -8
- package/fesm2022/_data-source-chunk.mjs.map +1 -1
- package/fesm2022/_directionality-chunk.mjs +54 -54
- package/fesm2022/_directionality-chunk.mjs.map +1 -1
- package/fesm2022/_dispose-view-repeater-strategy-chunk.mjs +25 -36
- package/fesm2022/_dispose-view-repeater-strategy-chunk.mjs.map +1 -1
- package/fesm2022/_element-chunk.mjs +6 -17
- package/fesm2022/_element-chunk.mjs.map +1 -1
- package/fesm2022/_fake-event-detection-chunk.mjs +3 -17
- package/fesm2022/_fake-event-detection-chunk.mjs.map +1 -1
- package/fesm2022/_focus-key-manager-chunk.mjs +10 -14
- package/fesm2022/_focus-key-manager-chunk.mjs.map +1 -1
- package/fesm2022/_focus-monitor-chunk.mjs +376 -566
- package/fesm2022/_focus-monitor-chunk.mjs.map +1 -1
- package/fesm2022/_id-generator-chunk.mjs +37 -27
- package/fesm2022/_id-generator-chunk.mjs.map +1 -1
- package/fesm2022/_keycodes-chunk.mjs +9 -9
- package/fesm2022/_keycodes-chunk.mjs.map +1 -1
- package/fesm2022/_list-key-manager-chunk.mjs +248 -336
- package/fesm2022/_list-key-manager-chunk.mjs.map +1 -1
- package/fesm2022/_overlay-module-chunk.mjs +2535 -2947
- package/fesm2022/_overlay-module-chunk.mjs.map +1 -1
- package/fesm2022/_passive-listeners-chunk.mjs +10 -22
- package/fesm2022/_passive-listeners-chunk.mjs.map +1 -1
- package/fesm2022/_platform-chunk.mjs +42 -65
- package/fesm2022/_platform-chunk.mjs.map +1 -1
- package/fesm2022/_recycle-view-repeater-strategy-chunk.mjs +78 -134
- package/fesm2022/_recycle-view-repeater-strategy-chunk.mjs.map +1 -1
- package/fesm2022/_scrolling-chunk.mjs +44 -85
- package/fesm2022/_scrolling-chunk.mjs.map +1 -1
- package/fesm2022/_selection-model-chunk.mjs +138 -209
- package/fesm2022/_selection-model-chunk.mjs.map +1 -1
- package/fesm2022/_shadow-dom-chunk.mjs +21 -35
- package/fesm2022/_shadow-dom-chunk.mjs.map +1 -1
- package/fesm2022/_style-loader-chunk.mjs +50 -37
- package/fesm2022/_style-loader-chunk.mjs.map +1 -1
- package/fesm2022/_test-environment-chunk.mjs +2 -14
- package/fesm2022/_test-environment-chunk.mjs.map +1 -1
- package/fesm2022/_tree-key-manager-chunk.mjs +229 -308
- package/fesm2022/_tree-key-manager-chunk.mjs.map +1 -1
- package/fesm2022/_typeahead-chunk.mjs +52 -74
- package/fesm2022/_typeahead-chunk.mjs.map +1 -1
- package/fesm2022/_unique-selection-dispatcher-chunk.mjs +43 -40
- package/fesm2022/_unique-selection-dispatcher-chunk.mjs.map +1 -1
- package/fesm2022/a11y.mjs +351 -449
- package/fesm2022/a11y.mjs.map +1 -1
- package/fesm2022/accordion.mjs +254 -192
- package/fesm2022/accordion.mjs.map +1 -1
- package/fesm2022/bidi.mjs +121 -64
- package/fesm2022/bidi.mjs.map +1 -1
- package/fesm2022/cdk.mjs +1 -2
- package/fesm2022/cdk.mjs.map +1 -1
- package/fesm2022/clipboard.mjs +208 -186
- package/fesm2022/clipboard.mjs.map +1 -1
- package/fesm2022/coercion-private.mjs +4 -8
- package/fesm2022/coercion-private.mjs.map +1 -1
- package/fesm2022/coercion.mjs +11 -29
- package/fesm2022/coercion.mjs.map +1 -1
- package/fesm2022/dialog.mjs +660 -808
- package/fesm2022/dialog.mjs.map +1 -1
- package/fesm2022/drag-drop.mjs +3347 -4286
- package/fesm2022/drag-drop.mjs.map +1 -1
- package/fesm2022/keycodes.mjs +4 -8
- package/fesm2022/keycodes.mjs.map +1 -1
- package/fesm2022/layout.mjs +44 -26
- package/fesm2022/layout.mjs.map +1 -1
- package/fesm2022/listbox.mjs +841 -895
- package/fesm2022/listbox.mjs.map +1 -1
- package/fesm2022/menu.mjs +1942 -1858
- package/fesm2022/menu.mjs.map +1 -1
- package/fesm2022/observers-private.mjs +88 -106
- package/fesm2022/observers-private.mjs.map +1 -1
- package/fesm2022/observers.mjs +262 -184
- package/fesm2022/observers.mjs.map +1 -1
- package/fesm2022/overlay.mjs +72 -68
- package/fesm2022/overlay.mjs.map +1 -1
- package/fesm2022/platform.mjs +43 -54
- package/fesm2022/platform.mjs.map +1 -1
- package/fesm2022/portal.mjs +402 -560
- package/fesm2022/portal.mjs.map +1 -1
- package/fesm2022/private.mjs +38 -10
- package/fesm2022/private.mjs.map +1 -1
- package/fesm2022/scrolling.mjs +1323 -1400
- package/fesm2022/scrolling.mjs.map +1 -1
- package/fesm2022/stepper.mjs +758 -590
- package/fesm2022/stepper.mjs.map +1 -1
- package/fesm2022/table.mjs +2327 -2319
- package/fesm2022/table.mjs.map +1 -1
- package/fesm2022/testing-selenium-webdriver.mjs +252 -325
- package/fesm2022/testing-selenium-webdriver.mjs.map +1 -1
- package/fesm2022/testing-testbed.mjs +592 -709
- package/fesm2022/testing-testbed.mjs.map +1 -1
- package/fesm2022/testing.mjs +368 -889
- package/fesm2022/testing.mjs.map +1 -1
- package/fesm2022/text-field.mjs +459 -388
- package/fesm2022/text-field.mjs.map +1 -1
- package/fesm2022/tree.mjs +1483 -1731
- package/fesm2022/tree.mjs.map +1 -1
- package/overlay/_index.scss +30 -0
- package/overlay-prebuilt.css +1 -1
- package/package.json +1 -1
- package/schematics/ng-add/index.js +1 -1
- package/types/_overlay-module-chunk.d.ts +69 -7
- package/types/_portal-directives-chunk.d.ts +2 -18
- package/types/a11y.d.ts +3 -1
- package/types/accordion.d.ts +3 -1
- package/types/dialog.d.ts +1 -1
- package/types/overlay.d.ts +1 -1
- package/types/portal.d.ts +1 -1
package/fesm2022/menu.mjs
CHANGED
|
@@ -29,1971 +29,2055 @@ import './_passive-listeners-chunk.mjs';
|
|
|
29
29
|
import './_list-key-manager-chunk.mjs';
|
|
30
30
|
import './_typeahead-chunk.mjs';
|
|
31
31
|
|
|
32
|
-
/**
|
|
33
|
-
* A grouping container for `CdkMenuItemRadio` instances, similar to a `role="radiogroup"` element.
|
|
34
|
-
*/
|
|
35
32
|
class CdkMenuGroup {
|
|
36
|
-
|
|
37
|
-
|
|
33
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
34
|
+
minVersion: "12.0.0",
|
|
35
|
+
version: "20.2.0-next.2",
|
|
36
|
+
ngImport: i0,
|
|
37
|
+
type: CdkMenuGroup,
|
|
38
|
+
deps: [],
|
|
39
|
+
target: i0.ɵɵFactoryTarget.Directive
|
|
40
|
+
});
|
|
41
|
+
static ɵdir = i0.ɵɵngDeclareDirective({
|
|
42
|
+
minVersion: "14.0.0",
|
|
43
|
+
version: "20.2.0-next.2",
|
|
44
|
+
type: CdkMenuGroup,
|
|
45
|
+
isStandalone: true,
|
|
46
|
+
selector: "[cdkMenuGroup]",
|
|
47
|
+
host: {
|
|
48
|
+
attributes: {
|
|
49
|
+
"role": "group"
|
|
50
|
+
},
|
|
51
|
+
classAttribute: "cdk-menu-group"
|
|
52
|
+
},
|
|
53
|
+
providers: [{
|
|
54
|
+
provide: UniqueSelectionDispatcher,
|
|
55
|
+
useClass: UniqueSelectionDispatcher
|
|
56
|
+
}],
|
|
57
|
+
exportAs: ["cdkMenuGroup"],
|
|
58
|
+
ngImport: i0
|
|
59
|
+
});
|
|
38
60
|
}
|
|
39
|
-
i0.ɵɵngDeclareClassMetadata({
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
61
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
62
|
+
minVersion: "12.0.0",
|
|
63
|
+
version: "20.2.0-next.2",
|
|
64
|
+
ngImport: i0,
|
|
65
|
+
type: CdkMenuGroup,
|
|
66
|
+
decorators: [{
|
|
67
|
+
type: Directive,
|
|
68
|
+
args: [{
|
|
69
|
+
selector: '[cdkMenuGroup]',
|
|
70
|
+
exportAs: 'cdkMenuGroup',
|
|
71
|
+
host: {
|
|
72
|
+
'role': 'group',
|
|
73
|
+
'class': 'cdk-menu-group'
|
|
74
|
+
},
|
|
75
|
+
providers: [{
|
|
76
|
+
provide: UniqueSelectionDispatcher,
|
|
77
|
+
useClass: UniqueSelectionDispatcher
|
|
78
|
+
}]
|
|
79
|
+
}]
|
|
80
|
+
}]
|
|
81
|
+
});
|
|
51
82
|
|
|
52
|
-
/** Injection token used to return classes implementing the Menu interface */
|
|
53
83
|
const CDK_MENU = new InjectionToken('cdk-menu');
|
|
54
84
|
|
|
55
|
-
/** The relative item in the inline menu to focus after closing all popup menus. */
|
|
56
85
|
var FocusNext;
|
|
57
86
|
(function (FocusNext) {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
87
|
+
FocusNext[FocusNext["nextItem"] = 0] = "nextItem";
|
|
88
|
+
FocusNext[FocusNext["previousItem"] = 1] = "previousItem";
|
|
89
|
+
FocusNext[FocusNext["currentItem"] = 2] = "currentItem";
|
|
61
90
|
})(FocusNext || (FocusNext = {}));
|
|
62
|
-
/** Injection token used for an implementation of MenuStack. */
|
|
63
91
|
const MENU_STACK = new InjectionToken('cdk-menu-stack');
|
|
64
|
-
/** Provider that provides the parent menu stack, or a new menu stack if there is no parent one. */
|
|
65
92
|
const PARENT_OR_NEW_MENU_STACK_PROVIDER = {
|
|
66
|
-
|
|
67
|
-
|
|
93
|
+
provide: MENU_STACK,
|
|
94
|
+
useFactory: () => inject(MENU_STACK, {
|
|
95
|
+
optional: true,
|
|
96
|
+
skipSelf: true
|
|
97
|
+
}) || new MenuStack()
|
|
68
98
|
};
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
99
|
+
const PARENT_OR_NEW_INLINE_MENU_STACK_PROVIDER = orientation => ({
|
|
100
|
+
provide: MENU_STACK,
|
|
101
|
+
useFactory: () => inject(MENU_STACK, {
|
|
102
|
+
optional: true,
|
|
103
|
+
skipSelf: true
|
|
104
|
+
}) || MenuStack.inline(orientation)
|
|
73
105
|
});
|
|
74
|
-
/**
|
|
75
|
-
* MenuStack allows subscribers to listen for close events (when a MenuStackItem is popped off
|
|
76
|
-
* of the stack) in order to perform closing actions. Upon the MenuStack being empty it emits
|
|
77
|
-
* from the `empty` observable specifying the next focus action which the listener should perform
|
|
78
|
-
* as requested by the closer.
|
|
79
|
-
*/
|
|
80
106
|
class MenuStack {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
if (this._elements.indexOf(lastItem) >= 0) {
|
|
147
|
-
removed = this.peek() !== lastItem;
|
|
148
|
-
while (this.peek() !== lastItem) {
|
|
149
|
-
this._close.next({ item: this._elements.pop() });
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
return removed;
|
|
153
|
-
}
|
|
154
|
-
/**
|
|
155
|
-
* Pop off all MenuStackItems and emit each one on the `close` observable one by one.
|
|
156
|
-
* @param options Options that configure behavior on close.
|
|
157
|
-
*/
|
|
158
|
-
closeAll(options) {
|
|
159
|
-
const { focusNextOnEmpty, focusParentTrigger } = { ...options };
|
|
160
|
-
if (!this.isEmpty()) {
|
|
161
|
-
while (!this.isEmpty()) {
|
|
162
|
-
const menuStackItem = this._elements.pop();
|
|
163
|
-
if (menuStackItem) {
|
|
164
|
-
this._close.next({ item: menuStackItem, focusParentTrigger });
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
this._empty.next(focusNextOnEmpty);
|
|
107
|
+
id = inject(_IdGenerator).getId('cdk-menu-stack-');
|
|
108
|
+
_elements = [];
|
|
109
|
+
_close = new Subject();
|
|
110
|
+
_empty = new Subject();
|
|
111
|
+
_hasFocus = new Subject();
|
|
112
|
+
closed = this._close;
|
|
113
|
+
hasFocus = this._hasFocus.pipe(startWith(false), debounceTime(0), distinctUntilChanged());
|
|
114
|
+
emptied = this._empty;
|
|
115
|
+
_inlineMenuOrientation = null;
|
|
116
|
+
static inline(orientation) {
|
|
117
|
+
const stack = new MenuStack();
|
|
118
|
+
stack._inlineMenuOrientation = orientation;
|
|
119
|
+
return stack;
|
|
120
|
+
}
|
|
121
|
+
push(menu) {
|
|
122
|
+
this._elements.push(menu);
|
|
123
|
+
}
|
|
124
|
+
close(lastItem, options) {
|
|
125
|
+
const {
|
|
126
|
+
focusNextOnEmpty,
|
|
127
|
+
focusParentTrigger
|
|
128
|
+
} = {
|
|
129
|
+
...options
|
|
130
|
+
};
|
|
131
|
+
if (this._elements.indexOf(lastItem) >= 0) {
|
|
132
|
+
let poppedElement;
|
|
133
|
+
do {
|
|
134
|
+
poppedElement = this._elements.pop();
|
|
135
|
+
this._close.next({
|
|
136
|
+
item: poppedElement,
|
|
137
|
+
focusParentTrigger
|
|
138
|
+
});
|
|
139
|
+
} while (poppedElement !== lastItem);
|
|
140
|
+
if (this.isEmpty()) {
|
|
141
|
+
this._empty.next(focusNextOnEmpty);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
closeSubMenuOf(lastItem) {
|
|
146
|
+
let removed = false;
|
|
147
|
+
if (this._elements.indexOf(lastItem) >= 0) {
|
|
148
|
+
removed = this.peek() !== lastItem;
|
|
149
|
+
while (this.peek() !== lastItem) {
|
|
150
|
+
this._close.next({
|
|
151
|
+
item: this._elements.pop()
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return removed;
|
|
156
|
+
}
|
|
157
|
+
closeAll(options) {
|
|
158
|
+
const {
|
|
159
|
+
focusNextOnEmpty,
|
|
160
|
+
focusParentTrigger
|
|
161
|
+
} = {
|
|
162
|
+
...options
|
|
163
|
+
};
|
|
164
|
+
if (!this.isEmpty()) {
|
|
165
|
+
while (!this.isEmpty()) {
|
|
166
|
+
const menuStackItem = this._elements.pop();
|
|
167
|
+
if (menuStackItem) {
|
|
168
|
+
this._close.next({
|
|
169
|
+
item: menuStackItem,
|
|
170
|
+
focusParentTrigger
|
|
171
|
+
});
|
|
168
172
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
173
|
+
}
|
|
174
|
+
this._empty.next(focusNextOnEmpty);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
isEmpty() {
|
|
178
|
+
return !this._elements.length;
|
|
179
|
+
}
|
|
180
|
+
length() {
|
|
181
|
+
return this._elements.length;
|
|
182
|
+
}
|
|
183
|
+
peek() {
|
|
184
|
+
return this._elements[this._elements.length - 1];
|
|
185
|
+
}
|
|
186
|
+
hasInlineMenu() {
|
|
187
|
+
return this._inlineMenuOrientation != null;
|
|
188
|
+
}
|
|
189
|
+
inlineMenuOrientation() {
|
|
190
|
+
return this._inlineMenuOrientation;
|
|
191
|
+
}
|
|
192
|
+
setHasFocus(hasFocus) {
|
|
193
|
+
this._hasFocus.next(hasFocus);
|
|
194
|
+
}
|
|
195
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
196
|
+
minVersion: "12.0.0",
|
|
197
|
+
version: "20.2.0-next.2",
|
|
198
|
+
ngImport: i0,
|
|
199
|
+
type: MenuStack,
|
|
200
|
+
deps: [],
|
|
201
|
+
target: i0.ɵɵFactoryTarget.Injectable
|
|
202
|
+
});
|
|
203
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({
|
|
204
|
+
minVersion: "12.0.0",
|
|
205
|
+
version: "20.2.0-next.2",
|
|
206
|
+
ngImport: i0,
|
|
207
|
+
type: MenuStack
|
|
208
|
+
});
|
|
196
209
|
}
|
|
197
|
-
i0.ɵɵngDeclareClassMetadata({
|
|
198
|
-
|
|
199
|
-
|
|
210
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
211
|
+
minVersion: "12.0.0",
|
|
212
|
+
version: "20.2.0-next.2",
|
|
213
|
+
ngImport: i0,
|
|
214
|
+
type: MenuStack,
|
|
215
|
+
decorators: [{
|
|
216
|
+
type: Injectable
|
|
217
|
+
}]
|
|
218
|
+
});
|
|
200
219
|
|
|
201
|
-
/** Injection token used for an implementation of MenuStack. */
|
|
202
220
|
const MENU_TRIGGER = new InjectionToken('cdk-menu-trigger');
|
|
203
|
-
/** Injection token used to configure the behavior of the menu when the page is scrolled. */
|
|
204
221
|
const MENU_SCROLL_STRATEGY = new InjectionToken('cdk-menu-scroll-strategy', {
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
222
|
+
providedIn: 'root',
|
|
223
|
+
factory: () => {
|
|
224
|
+
const injector = inject(Injector);
|
|
225
|
+
return () => createRepositionScrollStrategy(injector);
|
|
226
|
+
}
|
|
210
227
|
});
|
|
211
|
-
/** Tracks the last open menu trigger across the entire application. */
|
|
212
228
|
class MenuTracker {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
229
|
+
static _openMenuTrigger;
|
|
230
|
+
update(trigger) {
|
|
231
|
+
if (MenuTracker._openMenuTrigger !== trigger) {
|
|
232
|
+
MenuTracker._openMenuTrigger?.close();
|
|
233
|
+
MenuTracker._openMenuTrigger = trigger;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
237
|
+
minVersion: "12.0.0",
|
|
238
|
+
version: "20.2.0-next.2",
|
|
239
|
+
ngImport: i0,
|
|
240
|
+
type: MenuTracker,
|
|
241
|
+
deps: [],
|
|
242
|
+
target: i0.ɵɵFactoryTarget.Injectable
|
|
243
|
+
});
|
|
244
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({
|
|
245
|
+
minVersion: "12.0.0",
|
|
246
|
+
version: "20.2.0-next.2",
|
|
247
|
+
ngImport: i0,
|
|
248
|
+
type: MenuTracker,
|
|
249
|
+
providedIn: 'root'
|
|
250
|
+
});
|
|
227
251
|
}
|
|
228
|
-
i0.ɵɵngDeclareClassMetadata({
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
252
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
253
|
+
minVersion: "12.0.0",
|
|
254
|
+
version: "20.2.0-next.2",
|
|
255
|
+
ngImport: i0,
|
|
256
|
+
type: MenuTracker,
|
|
257
|
+
decorators: [{
|
|
258
|
+
type: Injectable,
|
|
259
|
+
args: [{
|
|
260
|
+
providedIn: 'root'
|
|
261
|
+
}]
|
|
262
|
+
}]
|
|
263
|
+
});
|
|
236
264
|
class CdkMenuTriggerBase {
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
/** Whether the attached menu is open. */
|
|
276
|
-
isOpen() {
|
|
277
|
-
return !!this.overlayRef?.hasAttached();
|
|
278
|
-
}
|
|
279
|
-
/** Registers a child menu as having been opened by this trigger. */
|
|
280
|
-
registerChildMenu(child) {
|
|
281
|
-
this.childMenu = child;
|
|
282
|
-
}
|
|
283
|
-
/**
|
|
284
|
-
* Get the portal to be attached to the overlay which contains the menu. Allows for the menu
|
|
285
|
-
* content to change dynamically and be reflected in the application.
|
|
286
|
-
*/
|
|
287
|
-
getMenuContentPortal() {
|
|
288
|
-
const hasMenuContentChanged = this.menuTemplateRef !== this._menuPortal?.templateRef;
|
|
289
|
-
if (this.menuTemplateRef && (!this._menuPortal || hasMenuContentChanged)) {
|
|
290
|
-
this._menuPortal = new TemplatePortal(this.menuTemplateRef, this.viewContainerRef, this.menuData, this._getChildMenuInjector());
|
|
291
|
-
}
|
|
292
|
-
return this._menuPortal;
|
|
293
|
-
}
|
|
294
|
-
/**
|
|
295
|
-
* Whether the given element is inside the scope of this trigger's menu stack.
|
|
296
|
-
* @param element The element to check.
|
|
297
|
-
* @return Whether the element is inside the scope of this trigger's menu stack.
|
|
298
|
-
*/
|
|
299
|
-
isElementInsideMenuStack(element) {
|
|
300
|
-
for (let el = element; el; el = el?.parentElement ?? null) {
|
|
301
|
-
if (el.getAttribute('data-cdk-menu-stack-id') === this.menuStack.id) {
|
|
302
|
-
return true;
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
return false;
|
|
306
|
-
}
|
|
307
|
-
/** Destroy and unset the overlay reference it if exists */
|
|
308
|
-
_destroyOverlay() {
|
|
309
|
-
if (this.overlayRef) {
|
|
310
|
-
this.overlayRef.dispose();
|
|
311
|
-
this.overlayRef = null;
|
|
312
|
-
}
|
|
265
|
+
injector = inject(Injector);
|
|
266
|
+
viewContainerRef = inject(ViewContainerRef);
|
|
267
|
+
menuStack = inject(MENU_STACK);
|
|
268
|
+
menuScrollStrategy = inject(MENU_SCROLL_STRATEGY);
|
|
269
|
+
menuPosition;
|
|
270
|
+
opened = new EventEmitter();
|
|
271
|
+
closed = new EventEmitter();
|
|
272
|
+
menuTemplateRef;
|
|
273
|
+
menuData;
|
|
274
|
+
overlayRef = null;
|
|
275
|
+
destroyed = new Subject();
|
|
276
|
+
stopOutsideClicksListener = merge(this.closed, this.destroyed);
|
|
277
|
+
childMenu;
|
|
278
|
+
_menuPortal;
|
|
279
|
+
_childMenuInjector;
|
|
280
|
+
ngOnDestroy() {
|
|
281
|
+
this._destroyOverlay();
|
|
282
|
+
this.destroyed.next();
|
|
283
|
+
this.destroyed.complete();
|
|
284
|
+
}
|
|
285
|
+
isOpen() {
|
|
286
|
+
return !!this.overlayRef?.hasAttached();
|
|
287
|
+
}
|
|
288
|
+
registerChildMenu(child) {
|
|
289
|
+
this.childMenu = child;
|
|
290
|
+
}
|
|
291
|
+
getMenuContentPortal() {
|
|
292
|
+
const hasMenuContentChanged = this.menuTemplateRef !== this._menuPortal?.templateRef;
|
|
293
|
+
if (this.menuTemplateRef && (!this._menuPortal || hasMenuContentChanged)) {
|
|
294
|
+
this._menuPortal = new TemplatePortal(this.menuTemplateRef, this.viewContainerRef, this.menuData, this._getChildMenuInjector());
|
|
295
|
+
}
|
|
296
|
+
return this._menuPortal;
|
|
297
|
+
}
|
|
298
|
+
isElementInsideMenuStack(element) {
|
|
299
|
+
for (let el = element; el; el = el?.parentElement ?? null) {
|
|
300
|
+
if (el.getAttribute('data-cdk-menu-stack-id') === this.menuStack.id) {
|
|
301
|
+
return true;
|
|
302
|
+
}
|
|
313
303
|
}
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
304
|
+
return false;
|
|
305
|
+
}
|
|
306
|
+
_destroyOverlay() {
|
|
307
|
+
if (this.overlayRef) {
|
|
308
|
+
this.overlayRef.dispose();
|
|
309
|
+
this.overlayRef = null;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
_getChildMenuInjector() {
|
|
313
|
+
this._childMenuInjector = this._childMenuInjector || Injector.create({
|
|
314
|
+
providers: [{
|
|
315
|
+
provide: MENU_TRIGGER,
|
|
316
|
+
useValue: this
|
|
317
|
+
}, {
|
|
318
|
+
provide: MENU_STACK,
|
|
319
|
+
useValue: this.menuStack
|
|
320
|
+
}],
|
|
321
|
+
parent: this.injector
|
|
322
|
+
});
|
|
323
|
+
return this._childMenuInjector;
|
|
324
|
+
}
|
|
325
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
326
|
+
minVersion: "12.0.0",
|
|
327
|
+
version: "20.2.0-next.2",
|
|
328
|
+
ngImport: i0,
|
|
329
|
+
type: CdkMenuTriggerBase,
|
|
330
|
+
deps: [],
|
|
331
|
+
target: i0.ɵɵFactoryTarget.Directive
|
|
332
|
+
});
|
|
333
|
+
static ɵdir = i0.ɵɵngDeclareDirective({
|
|
334
|
+
minVersion: "14.0.0",
|
|
335
|
+
version: "20.2.0-next.2",
|
|
336
|
+
type: CdkMenuTriggerBase,
|
|
337
|
+
isStandalone: true,
|
|
338
|
+
host: {
|
|
339
|
+
properties: {
|
|
340
|
+
"attr.aria-controls": "childMenu?.id",
|
|
341
|
+
"attr.data-cdk-menu-stack-id": "menuStack.id"
|
|
342
|
+
}
|
|
343
|
+
},
|
|
344
|
+
ngImport: i0
|
|
345
|
+
});
|
|
329
346
|
}
|
|
330
|
-
i0.ɵɵngDeclareClassMetadata({
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
347
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
348
|
+
minVersion: "12.0.0",
|
|
349
|
+
version: "20.2.0-next.2",
|
|
350
|
+
ngImport: i0,
|
|
351
|
+
type: CdkMenuTriggerBase,
|
|
352
|
+
decorators: [{
|
|
353
|
+
type: Directive,
|
|
354
|
+
args: [{
|
|
355
|
+
host: {
|
|
356
|
+
'[attr.aria-controls]': 'childMenu?.id',
|
|
357
|
+
'[attr.data-cdk-menu-stack-id]': 'menuStack.id'
|
|
358
|
+
}
|
|
359
|
+
}]
|
|
360
|
+
}]
|
|
361
|
+
});
|
|
339
362
|
|
|
340
|
-
/**
|
|
341
|
-
* Throws an exception when an instance of the PointerFocusTracker is not provided.
|
|
342
|
-
* @docs-private
|
|
343
|
-
*/
|
|
344
363
|
function throwMissingPointerFocusTracker() {
|
|
345
|
-
|
|
364
|
+
throw Error('expected an instance of PointerFocusTracker to be provided');
|
|
346
365
|
}
|
|
347
|
-
/**
|
|
348
|
-
* Throws an exception when a reference to the parent menu is not provided.
|
|
349
|
-
* @docs-private
|
|
350
|
-
*/
|
|
351
366
|
function throwMissingMenuReference() {
|
|
352
|
-
|
|
367
|
+
throw Error('expected a reference to the parent menu');
|
|
353
368
|
}
|
|
354
369
|
|
|
355
|
-
/** Injection token used for an implementation of MenuAim. */
|
|
356
370
|
const MENU_AIM = new InjectionToken('cdk-menu-aim');
|
|
357
|
-
/** Capture every nth mouse move event. */
|
|
358
371
|
const MOUSE_MOVE_SAMPLE_FREQUENCY = 3;
|
|
359
|
-
/** The number of mouse move events to track. */
|
|
360
372
|
const NUM_POINTS = 5;
|
|
361
|
-
/**
|
|
362
|
-
* How long to wait before closing a sibling menu if a user stops short of the submenu they were
|
|
363
|
-
* predicted to go into.
|
|
364
|
-
*/
|
|
365
373
|
const CLOSE_DELAY = 300;
|
|
366
|
-
/** Calculate the slope between point a and b. */
|
|
367
374
|
function getSlope(a, b) {
|
|
368
|
-
|
|
375
|
+
return (b.y - a.y) / (b.x - a.x);
|
|
369
376
|
}
|
|
370
|
-
/** Calculate the y intercept for the given point and slope. */
|
|
371
377
|
function getYIntercept(point, slope) {
|
|
372
|
-
|
|
378
|
+
return point.y - slope * point.x;
|
|
373
379
|
}
|
|
374
|
-
/**
|
|
375
|
-
* Whether the given mouse trajectory line defined by the slope and y intercept falls within the
|
|
376
|
-
* submenu as defined by `submenuPoints`
|
|
377
|
-
* @param submenuPoints the submenu DOMRect points.
|
|
378
|
-
* @param m the slope of the trajectory line.
|
|
379
|
-
* @param b the y intercept of the trajectory line.
|
|
380
|
-
* @return true if any point on the line falls within the submenu.
|
|
381
|
-
*/
|
|
382
380
|
function isWithinSubmenu(submenuPoints, m, b) {
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
((bottom - b) / m >= left && (bottom - b) / m <= right));
|
|
381
|
+
const {
|
|
382
|
+
left,
|
|
383
|
+
right,
|
|
384
|
+
top,
|
|
385
|
+
bottom
|
|
386
|
+
} = submenuPoints;
|
|
387
|
+
return m * left + b >= top && m * left + b <= bottom || m * right + b >= top && m * right + b <= bottom || (top - b) / m >= left && (top - b) / m <= right || (bottom - b) / m >= left && (bottom - b) / m <= right;
|
|
391
388
|
}
|
|
392
|
-
/**
|
|
393
|
-
* TargetMenuAim predicts if a user is moving into a submenu. It calculates the
|
|
394
|
-
* trajectory of the user's mouse movement in the current menu to determine if the
|
|
395
|
-
* mouse is moving towards an open submenu.
|
|
396
|
-
*
|
|
397
|
-
* The determination is made by calculating the slope of the users last NUM_POINTS moves where each
|
|
398
|
-
* pair of points determines if the trajectory line points into the submenu. It uses consensus
|
|
399
|
-
* approach by checking if at least NUM_POINTS / 2 pairs determine that the user is moving towards
|
|
400
|
-
* to submenu.
|
|
401
|
-
*/
|
|
402
389
|
class TargetMenuAim {
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
for (let i = this._points.length - 2; i >= 0; i--) {
|
|
490
|
-
const previous = this._points[i];
|
|
491
|
-
const slope = getSlope(currPoint, previous);
|
|
492
|
-
if (isWithinSubmenu(submenuPoints, slope, getYIntercept(currPoint, slope))) {
|
|
493
|
-
numMoving++;
|
|
494
|
-
}
|
|
390
|
+
_ngZone = inject(NgZone);
|
|
391
|
+
_renderer = inject(RendererFactory2).createRenderer(null, null);
|
|
392
|
+
_cleanupMousemove;
|
|
393
|
+
_points = [];
|
|
394
|
+
_menu;
|
|
395
|
+
_pointerTracker;
|
|
396
|
+
_timeoutId;
|
|
397
|
+
_destroyed = new Subject();
|
|
398
|
+
ngOnDestroy() {
|
|
399
|
+
this._cleanupMousemove?.();
|
|
400
|
+
this._destroyed.next();
|
|
401
|
+
this._destroyed.complete();
|
|
402
|
+
}
|
|
403
|
+
initialize(menu, pointerTracker) {
|
|
404
|
+
this._menu = menu;
|
|
405
|
+
this._pointerTracker = pointerTracker;
|
|
406
|
+
this._subscribeToMouseMoves();
|
|
407
|
+
}
|
|
408
|
+
toggle(doToggle) {
|
|
409
|
+
if (this._menu.orientation === 'horizontal') {
|
|
410
|
+
doToggle();
|
|
411
|
+
}
|
|
412
|
+
this._checkConfigured();
|
|
413
|
+
const siblingItemIsWaiting = !!this._timeoutId;
|
|
414
|
+
const hasPoints = this._points.length > 1;
|
|
415
|
+
if (hasPoints && !siblingItemIsWaiting) {
|
|
416
|
+
if (this._isMovingToSubmenu()) {
|
|
417
|
+
this._startTimeout(doToggle);
|
|
418
|
+
} else {
|
|
419
|
+
doToggle();
|
|
420
|
+
}
|
|
421
|
+
} else if (!siblingItemIsWaiting) {
|
|
422
|
+
doToggle();
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
_startTimeout(doToggle) {
|
|
426
|
+
const timeoutId = setTimeout(() => {
|
|
427
|
+
if (this._pointerTracker.activeElement && timeoutId === this._timeoutId) {
|
|
428
|
+
doToggle();
|
|
429
|
+
}
|
|
430
|
+
this._timeoutId = null;
|
|
431
|
+
}, CLOSE_DELAY);
|
|
432
|
+
this._timeoutId = timeoutId;
|
|
433
|
+
}
|
|
434
|
+
_isMovingToSubmenu() {
|
|
435
|
+
const submenuPoints = this._getSubmenuBounds();
|
|
436
|
+
if (!submenuPoints) {
|
|
437
|
+
return false;
|
|
438
|
+
}
|
|
439
|
+
let numMoving = 0;
|
|
440
|
+
const currPoint = this._points[this._points.length - 1];
|
|
441
|
+
for (let i = this._points.length - 2; i >= 0; i--) {
|
|
442
|
+
const previous = this._points[i];
|
|
443
|
+
const slope = getSlope(currPoint, previous);
|
|
444
|
+
if (isWithinSubmenu(submenuPoints, slope, getYIntercept(currPoint, slope))) {
|
|
445
|
+
numMoving++;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
return numMoving >= Math.floor(NUM_POINTS / 2);
|
|
449
|
+
}
|
|
450
|
+
_getSubmenuBounds() {
|
|
451
|
+
return this._pointerTracker?.previousElement?.getMenu()?.nativeElement.getBoundingClientRect();
|
|
452
|
+
}
|
|
453
|
+
_checkConfigured() {
|
|
454
|
+
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
|
455
|
+
if (!this._pointerTracker) {
|
|
456
|
+
throwMissingPointerFocusTracker();
|
|
457
|
+
}
|
|
458
|
+
if (!this._menu) {
|
|
459
|
+
throwMissingMenuReference();
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
_subscribeToMouseMoves() {
|
|
464
|
+
this._cleanupMousemove?.();
|
|
465
|
+
this._cleanupMousemove = this._ngZone.runOutsideAngular(() => {
|
|
466
|
+
let eventIndex = 0;
|
|
467
|
+
return this._renderer.listen(this._menu.nativeElement, 'mousemove', event => {
|
|
468
|
+
if (eventIndex % MOUSE_MOVE_SAMPLE_FREQUENCY === 0) {
|
|
469
|
+
this._points.push({
|
|
470
|
+
x: event.clientX,
|
|
471
|
+
y: event.clientY
|
|
472
|
+
});
|
|
473
|
+
if (this._points.length > NUM_POINTS) {
|
|
474
|
+
this._points.shift();
|
|
475
|
+
}
|
|
495
476
|
}
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
}
|
|
515
|
-
}
|
|
516
|
-
/** Subscribe to the root menus mouse move events and update the tracked mouse points. */
|
|
517
|
-
_subscribeToMouseMoves() {
|
|
518
|
-
this._cleanupMousemove?.();
|
|
519
|
-
this._cleanupMousemove = this._ngZone.runOutsideAngular(() => {
|
|
520
|
-
let eventIndex = 0;
|
|
521
|
-
return this._renderer.listen(this._menu.nativeElement, 'mousemove', (event) => {
|
|
522
|
-
if (eventIndex % MOUSE_MOVE_SAMPLE_FREQUENCY === 0) {
|
|
523
|
-
this._points.push({ x: event.clientX, y: event.clientY });
|
|
524
|
-
if (this._points.length > NUM_POINTS) {
|
|
525
|
-
this._points.shift();
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
eventIndex++;
|
|
529
|
-
});
|
|
530
|
-
});
|
|
531
|
-
}
|
|
532
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0-next.2", ngImport: i0, type: TargetMenuAim, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
533
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.2.0-next.2", ngImport: i0, type: TargetMenuAim });
|
|
477
|
+
eventIndex++;
|
|
478
|
+
});
|
|
479
|
+
});
|
|
480
|
+
}
|
|
481
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
482
|
+
minVersion: "12.0.0",
|
|
483
|
+
version: "20.2.0-next.2",
|
|
484
|
+
ngImport: i0,
|
|
485
|
+
type: TargetMenuAim,
|
|
486
|
+
deps: [],
|
|
487
|
+
target: i0.ɵɵFactoryTarget.Injectable
|
|
488
|
+
});
|
|
489
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({
|
|
490
|
+
minVersion: "12.0.0",
|
|
491
|
+
version: "20.2.0-next.2",
|
|
492
|
+
ngImport: i0,
|
|
493
|
+
type: TargetMenuAim
|
|
494
|
+
});
|
|
534
495
|
}
|
|
535
|
-
i0.ɵɵngDeclareClassMetadata({
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
496
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
497
|
+
minVersion: "12.0.0",
|
|
498
|
+
version: "20.2.0-next.2",
|
|
499
|
+
ngImport: i0,
|
|
500
|
+
type: TargetMenuAim,
|
|
501
|
+
decorators: [{
|
|
502
|
+
type: Injectable
|
|
503
|
+
}]
|
|
504
|
+
});
|
|
542
505
|
class CdkTargetMenuAim {
|
|
543
|
-
|
|
544
|
-
|
|
506
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
507
|
+
minVersion: "12.0.0",
|
|
508
|
+
version: "20.2.0-next.2",
|
|
509
|
+
ngImport: i0,
|
|
510
|
+
type: CdkTargetMenuAim,
|
|
511
|
+
deps: [],
|
|
512
|
+
target: i0.ɵɵFactoryTarget.Directive
|
|
513
|
+
});
|
|
514
|
+
static ɵdir = i0.ɵɵngDeclareDirective({
|
|
515
|
+
minVersion: "14.0.0",
|
|
516
|
+
version: "20.2.0-next.2",
|
|
517
|
+
type: CdkTargetMenuAim,
|
|
518
|
+
isStandalone: true,
|
|
519
|
+
selector: "[cdkTargetMenuAim]",
|
|
520
|
+
providers: [{
|
|
521
|
+
provide: MENU_AIM,
|
|
522
|
+
useClass: TargetMenuAim
|
|
523
|
+
}],
|
|
524
|
+
exportAs: ["cdkTargetMenuAim"],
|
|
525
|
+
ngImport: i0
|
|
526
|
+
});
|
|
545
527
|
}
|
|
546
|
-
i0.ɵɵngDeclareClassMetadata({
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
528
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
529
|
+
minVersion: "12.0.0",
|
|
530
|
+
version: "20.2.0-next.2",
|
|
531
|
+
ngImport: i0,
|
|
532
|
+
type: CdkTargetMenuAim,
|
|
533
|
+
decorators: [{
|
|
534
|
+
type: Directive,
|
|
535
|
+
args: [{
|
|
536
|
+
selector: '[cdkTargetMenuAim]',
|
|
537
|
+
exportAs: 'cdkTargetMenuAim',
|
|
538
|
+
providers: [{
|
|
539
|
+
provide: MENU_AIM,
|
|
540
|
+
useClass: TargetMenuAim
|
|
541
|
+
}]
|
|
542
|
+
}]
|
|
543
|
+
}]
|
|
544
|
+
});
|
|
554
545
|
|
|
555
|
-
/** Checks whether a keyboard event will trigger a native `click` event on an element. */
|
|
556
546
|
function eventDispatchesNativeClick(elementRef, event) {
|
|
557
|
-
|
|
558
|
-
if (!event.isTrusted) {
|
|
559
|
-
return false;
|
|
560
|
-
}
|
|
561
|
-
const el = elementRef.nativeElement;
|
|
562
|
-
const keyCode = event.keyCode;
|
|
563
|
-
// Buttons trigger clicks both on space and enter events.
|
|
564
|
-
if (el.nodeName === 'BUTTON' && !el.disabled) {
|
|
565
|
-
return keyCode === ENTER || keyCode === SPACE;
|
|
566
|
-
}
|
|
567
|
-
// Links only trigger clicks on enter.
|
|
568
|
-
if (el.nodeName === 'A') {
|
|
569
|
-
return keyCode === ENTER;
|
|
570
|
-
}
|
|
571
|
-
// Any other elements won't dispatch clicks from keyboard events.
|
|
547
|
+
if (!event.isTrusted) {
|
|
572
548
|
return false;
|
|
549
|
+
}
|
|
550
|
+
const el = elementRef.nativeElement;
|
|
551
|
+
const keyCode = event.keyCode;
|
|
552
|
+
if (el.nodeName === 'BUTTON' && !el.disabled) {
|
|
553
|
+
return keyCode === ENTER || keyCode === SPACE;
|
|
554
|
+
}
|
|
555
|
+
if (el.nodeName === 'A') {
|
|
556
|
+
return keyCode === ENTER;
|
|
557
|
+
}
|
|
558
|
+
return false;
|
|
573
559
|
}
|
|
574
560
|
|
|
575
|
-
/**
|
|
576
|
-
* A directive that turns its host element into a trigger for a popup menu.
|
|
577
|
-
* It can be combined with cdkMenuItem to create sub-menus. If the element is in a top level
|
|
578
|
-
* MenuBar it will open the menu on click, or if a sibling is already opened it will open on hover.
|
|
579
|
-
* If it is inside of a Menu it will open the attached Submenu on hover regardless of its sibling
|
|
580
|
-
* state.
|
|
581
|
-
*/
|
|
582
561
|
class CdkMenuTrigger extends CdkMenuTriggerBase {
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
562
|
+
_elementRef = inject(ElementRef);
|
|
563
|
+
_ngZone = inject(NgZone);
|
|
564
|
+
_changeDetectorRef = inject(ChangeDetectorRef);
|
|
565
|
+
_inputModalityDetector = inject(InputModalityDetector);
|
|
566
|
+
_directionality = inject(Directionality, {
|
|
567
|
+
optional: true
|
|
568
|
+
});
|
|
569
|
+
_renderer = inject(Renderer2);
|
|
570
|
+
_injector = inject(Injector);
|
|
571
|
+
_cleanupMouseenter;
|
|
572
|
+
_menuTracker = inject(MenuTracker);
|
|
573
|
+
_parentMenu = inject(CDK_MENU, {
|
|
574
|
+
optional: true
|
|
575
|
+
});
|
|
576
|
+
_menuAim = inject(MENU_AIM, {
|
|
577
|
+
optional: true
|
|
578
|
+
});
|
|
579
|
+
constructor() {
|
|
580
|
+
super();
|
|
581
|
+
this._setRole();
|
|
582
|
+
this._registerCloseHandler();
|
|
583
|
+
this._subscribeToMenuStackClosed();
|
|
584
|
+
this._subscribeToMouseEnter();
|
|
585
|
+
this._subscribeToMenuStackHasFocus();
|
|
586
|
+
this._setType();
|
|
587
|
+
}
|
|
588
|
+
toggle() {
|
|
589
|
+
this.isOpen() ? this.close() : this.open();
|
|
590
|
+
}
|
|
591
|
+
open() {
|
|
592
|
+
if (!this._parentMenu) {
|
|
593
|
+
this._menuTracker.update(this);
|
|
594
|
+
}
|
|
595
|
+
if (!this.isOpen() && this.menuTemplateRef != null) {
|
|
596
|
+
this.opened.next();
|
|
597
|
+
this.overlayRef = this.overlayRef || createOverlayRef(this._injector, this._getOverlayConfig());
|
|
598
|
+
this.overlayRef.attach(this.getMenuContentPortal());
|
|
599
|
+
this._changeDetectorRef.markForCheck();
|
|
600
|
+
this._subscribeToOutsideClicks();
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
close() {
|
|
604
|
+
if (this.isOpen()) {
|
|
605
|
+
this.closed.next();
|
|
606
|
+
this.overlayRef.detach();
|
|
607
|
+
this._changeDetectorRef.markForCheck();
|
|
608
|
+
}
|
|
609
|
+
this._closeSiblingTriggers();
|
|
610
|
+
}
|
|
611
|
+
getMenu() {
|
|
612
|
+
return this.childMenu;
|
|
613
|
+
}
|
|
614
|
+
ngOnChanges(changes) {
|
|
615
|
+
if (changes['menuPosition'] && this.overlayRef) {
|
|
616
|
+
this.overlayRef.updatePositionStrategy(this._getOverlayPositionStrategy());
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
ngOnDestroy() {
|
|
620
|
+
this._cleanupMouseenter();
|
|
621
|
+
super.ngOnDestroy();
|
|
622
|
+
}
|
|
623
|
+
_toggleOnKeydown(event) {
|
|
624
|
+
const isParentVertical = this._parentMenu?.orientation === 'vertical';
|
|
625
|
+
switch (event.keyCode) {
|
|
626
|
+
case SPACE:
|
|
627
|
+
case ENTER:
|
|
628
|
+
if (!hasModifierKey(event) && !eventDispatchesNativeClick(this._elementRef, event)) {
|
|
629
|
+
this.toggle();
|
|
630
|
+
this.childMenu?.focusFirstItem('keyboard');
|
|
614
631
|
}
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
this.
|
|
621
|
-
this.
|
|
632
|
+
break;
|
|
633
|
+
case RIGHT_ARROW:
|
|
634
|
+
if (!hasModifierKey(event)) {
|
|
635
|
+
if (this._parentMenu && isParentVertical && this._directionality?.value !== 'rtl') {
|
|
636
|
+
event.preventDefault();
|
|
637
|
+
this.open();
|
|
638
|
+
this.childMenu?.focusFirstItem('keyboard');
|
|
639
|
+
}
|
|
622
640
|
}
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
this.
|
|
629
|
-
this.
|
|
641
|
+
break;
|
|
642
|
+
case LEFT_ARROW:
|
|
643
|
+
if (!hasModifierKey(event)) {
|
|
644
|
+
if (this._parentMenu && isParentVertical && this._directionality?.value === 'rtl') {
|
|
645
|
+
event.preventDefault();
|
|
646
|
+
this.open();
|
|
647
|
+
this.childMenu?.focusFirstItem('keyboard');
|
|
648
|
+
}
|
|
630
649
|
}
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
if (changes['menuPosition'] && this.overlayRef) {
|
|
641
|
-
this.overlayRef.updatePositionStrategy(this._getOverlayPositionStrategy());
|
|
650
|
+
break;
|
|
651
|
+
case DOWN_ARROW:
|
|
652
|
+
case UP_ARROW:
|
|
653
|
+
if (!hasModifierKey(event)) {
|
|
654
|
+
if (!isParentVertical) {
|
|
655
|
+
event.preventDefault();
|
|
656
|
+
this.open();
|
|
657
|
+
event.keyCode === DOWN_ARROW ? this.childMenu?.focusFirstItem('keyboard') : this.childMenu?.focusLastItem('keyboard');
|
|
658
|
+
}
|
|
642
659
|
}
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
this.childMenu?.focusFirstItem('keyboard');
|
|
669
|
-
}
|
|
670
|
-
}
|
|
671
|
-
break;
|
|
672
|
-
case LEFT_ARROW:
|
|
673
|
-
if (!hasModifierKey(event)) {
|
|
674
|
-
if (this._parentMenu && isParentVertical && this._directionality?.value === 'rtl') {
|
|
675
|
-
event.preventDefault();
|
|
676
|
-
this.open();
|
|
677
|
-
this.childMenu?.focusFirstItem('keyboard');
|
|
678
|
-
}
|
|
679
|
-
}
|
|
680
|
-
break;
|
|
681
|
-
case DOWN_ARROW:
|
|
682
|
-
case UP_ARROW:
|
|
683
|
-
if (!hasModifierKey(event)) {
|
|
684
|
-
if (!isParentVertical) {
|
|
685
|
-
event.preventDefault();
|
|
686
|
-
this.open();
|
|
687
|
-
event.keyCode === DOWN_ARROW
|
|
688
|
-
? this.childMenu?.focusFirstItem('keyboard')
|
|
689
|
-
: this.childMenu?.focusLastItem('keyboard');
|
|
690
|
-
}
|
|
691
|
-
}
|
|
692
|
-
break;
|
|
660
|
+
break;
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
_handleClick() {
|
|
664
|
+
this.toggle();
|
|
665
|
+
this.childMenu?.focusFirstItem('mouse');
|
|
666
|
+
}
|
|
667
|
+
_setHasFocus(hasFocus) {
|
|
668
|
+
if (!this._parentMenu) {
|
|
669
|
+
this.menuStack.setHasFocus(hasFocus);
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
_subscribeToMouseEnter() {
|
|
673
|
+
this._cleanupMouseenter = this._ngZone.runOutsideAngular(() => {
|
|
674
|
+
return this._renderer.listen(this._elementRef.nativeElement, 'mouseenter', () => {
|
|
675
|
+
if (this._inputModalityDetector.mostRecentModality !== 'touch' && !this.menuStack.isEmpty() && !this.isOpen()) {
|
|
676
|
+
const toggleMenus = () => this._ngZone.run(() => {
|
|
677
|
+
this._closeSiblingTriggers();
|
|
678
|
+
this.open();
|
|
679
|
+
});
|
|
680
|
+
if (this._menuAim) {
|
|
681
|
+
this._menuAim.toggle(toggleMenus);
|
|
682
|
+
} else {
|
|
683
|
+
toggleMenus();
|
|
684
|
+
}
|
|
693
685
|
}
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
686
|
+
});
|
|
687
|
+
});
|
|
688
|
+
}
|
|
689
|
+
_closeSiblingTriggers() {
|
|
690
|
+
if (this._parentMenu) {
|
|
691
|
+
const isParentMenuBar = !this.menuStack.closeSubMenuOf(this._parentMenu) && this.menuStack.peek() !== this._parentMenu;
|
|
692
|
+
if (isParentMenuBar) {
|
|
693
|
+
this.menuStack.closeAll();
|
|
694
|
+
}
|
|
695
|
+
} else {
|
|
696
|
+
this.menuStack.closeAll();
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
_getOverlayConfig() {
|
|
700
|
+
return new OverlayConfig({
|
|
701
|
+
positionStrategy: this._getOverlayPositionStrategy(),
|
|
702
|
+
scrollStrategy: this.menuScrollStrategy(),
|
|
703
|
+
direction: this._directionality || undefined
|
|
704
|
+
});
|
|
705
|
+
}
|
|
706
|
+
_getOverlayPositionStrategy() {
|
|
707
|
+
return createFlexibleConnectedPositionStrategy(this._injector, this._elementRef).withLockedPosition().withFlexibleDimensions(false).withPositions(this._getOverlayPositions());
|
|
708
|
+
}
|
|
709
|
+
_getOverlayPositions() {
|
|
710
|
+
return this.menuPosition ?? (!this._parentMenu || this._parentMenu.orientation === 'horizontal' ? STANDARD_DROPDOWN_BELOW_POSITIONS : STANDARD_DROPDOWN_ADJACENT_POSITIONS);
|
|
711
|
+
}
|
|
712
|
+
_registerCloseHandler() {
|
|
713
|
+
if (!this._parentMenu) {
|
|
714
|
+
this.menuStack.closed.pipe(takeUntil(this.destroyed)).subscribe(({
|
|
715
|
+
item
|
|
716
|
+
}) => {
|
|
717
|
+
if (item === this.childMenu) {
|
|
718
|
+
this.close();
|
|
707
719
|
}
|
|
720
|
+
});
|
|
708
721
|
}
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
// Skip fake `mouseenter` events dispatched by touch devices.
|
|
718
|
-
this._inputModalityDetector.mostRecentModality !== 'touch' &&
|
|
719
|
-
!this.menuStack.isEmpty() &&
|
|
720
|
-
!this.isOpen()) {
|
|
721
|
-
// Closes any sibling menu items and opens the menu associated with this trigger.
|
|
722
|
-
const toggleMenus = () => this._ngZone.run(() => {
|
|
723
|
-
this._closeSiblingTriggers();
|
|
724
|
-
this.open();
|
|
725
|
-
});
|
|
726
|
-
if (this._menuAim) {
|
|
727
|
-
this._menuAim.toggle(toggleMenus);
|
|
728
|
-
}
|
|
729
|
-
else {
|
|
730
|
-
toggleMenus();
|
|
731
|
-
}
|
|
732
|
-
}
|
|
733
|
-
});
|
|
734
|
-
});
|
|
735
|
-
}
|
|
736
|
-
/** Close out any sibling menu trigger menus. */
|
|
737
|
-
_closeSiblingTriggers() {
|
|
738
|
-
if (this._parentMenu) {
|
|
739
|
-
// If nothing was removed from the stack and the last element is not the parent item
|
|
740
|
-
// that means that the parent menu is a menu bar since we don't put the menu bar on the
|
|
741
|
-
// stack
|
|
742
|
-
const isParentMenuBar = !this.menuStack.closeSubMenuOf(this._parentMenu) &&
|
|
743
|
-
this.menuStack.peek() !== this._parentMenu;
|
|
744
|
-
if (isParentMenuBar) {
|
|
745
|
-
this.menuStack.closeAll();
|
|
746
|
-
}
|
|
747
|
-
}
|
|
748
|
-
else {
|
|
722
|
+
}
|
|
723
|
+
_subscribeToOutsideClicks() {
|
|
724
|
+
if (this.overlayRef) {
|
|
725
|
+
this.overlayRef.outsidePointerEvents().pipe(takeUntil(this.stopOutsideClicksListener)).subscribe(event => {
|
|
726
|
+
const target = _getEventTarget(event);
|
|
727
|
+
const element = this._elementRef.nativeElement;
|
|
728
|
+
if (target !== element && !element.contains(target)) {
|
|
729
|
+
if (!this.isElementInsideMenuStack(target)) {
|
|
749
730
|
this.menuStack.closeAll();
|
|
731
|
+
} else {
|
|
732
|
+
this._closeSiblingTriggers();
|
|
733
|
+
}
|
|
750
734
|
}
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
}
|
|
760
|
-
/** Build the position strategy for the overlay which specifies where to place the menu. */
|
|
761
|
-
_getOverlayPositionStrategy() {
|
|
762
|
-
return createFlexibleConnectedPositionStrategy(this._injector, this._elementRef)
|
|
763
|
-
.withLockedPosition()
|
|
764
|
-
.withFlexibleDimensions(false)
|
|
765
|
-
.withPositions(this._getOverlayPositions());
|
|
766
|
-
}
|
|
767
|
-
/** Get the preferred positions for the opened menu relative to the menu item. */
|
|
768
|
-
_getOverlayPositions() {
|
|
769
|
-
return (this.menuPosition ??
|
|
770
|
-
(!this._parentMenu || this._parentMenu.orientation === 'horizontal'
|
|
771
|
-
? STANDARD_DROPDOWN_BELOW_POSITIONS
|
|
772
|
-
: STANDARD_DROPDOWN_ADJACENT_POSITIONS));
|
|
773
|
-
}
|
|
774
|
-
/**
|
|
775
|
-
* Subscribe to the MenuStack close events if this is a standalone trigger and close out the menu
|
|
776
|
-
* this triggers when requested.
|
|
777
|
-
*/
|
|
778
|
-
_registerCloseHandler() {
|
|
779
|
-
if (!this._parentMenu) {
|
|
780
|
-
this.menuStack.closed.pipe(takeUntil(this.destroyed)).subscribe(({ item }) => {
|
|
781
|
-
if (item === this.childMenu) {
|
|
782
|
-
this.close();
|
|
783
|
-
}
|
|
784
|
-
});
|
|
735
|
+
});
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
_subscribeToMenuStackHasFocus() {
|
|
739
|
+
if (!this._parentMenu) {
|
|
740
|
+
this.menuStack.hasFocus.pipe(takeUntil(this.destroyed)).subscribe(hasFocus => {
|
|
741
|
+
if (!hasFocus) {
|
|
742
|
+
this.menuStack.closeAll();
|
|
785
743
|
}
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
.subscribe(event => {
|
|
797
|
-
const target = _getEventTarget(event);
|
|
798
|
-
const element = this._elementRef.nativeElement;
|
|
799
|
-
if (target !== element && !element.contains(target)) {
|
|
800
|
-
if (!this.isElementInsideMenuStack(target)) {
|
|
801
|
-
this.menuStack.closeAll();
|
|
802
|
-
}
|
|
803
|
-
else {
|
|
804
|
-
this._closeSiblingTriggers();
|
|
805
|
-
}
|
|
806
|
-
}
|
|
807
|
-
});
|
|
808
|
-
}
|
|
809
|
-
}
|
|
810
|
-
/** Subscribe to the MenuStack hasFocus events. */
|
|
811
|
-
_subscribeToMenuStackHasFocus() {
|
|
812
|
-
if (!this._parentMenu) {
|
|
813
|
-
this.menuStack.hasFocus.pipe(takeUntil(this.destroyed)).subscribe(hasFocus => {
|
|
814
|
-
if (!hasFocus) {
|
|
815
|
-
this.menuStack.closeAll();
|
|
816
|
-
}
|
|
817
|
-
});
|
|
744
|
+
});
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
_subscribeToMenuStackClosed() {
|
|
748
|
+
if (!this._parentMenu) {
|
|
749
|
+
this.menuStack.closed.subscribe(({
|
|
750
|
+
focusParentTrigger
|
|
751
|
+
}) => {
|
|
752
|
+
if (focusParentTrigger && !this.menuStack.length()) {
|
|
753
|
+
this._elementRef.nativeElement.focus();
|
|
818
754
|
}
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
755
|
+
});
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
_setRole() {
|
|
759
|
+
if (!this._parentMenu) {
|
|
760
|
+
this._elementRef.nativeElement.setAttribute('role', 'button');
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
_setType() {
|
|
764
|
+
const element = this._elementRef.nativeElement;
|
|
765
|
+
if (element.nodeName === 'BUTTON' && !element.getAttribute('type')) {
|
|
766
|
+
element.setAttribute('type', 'button');
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
770
|
+
minVersion: "12.0.0",
|
|
771
|
+
version: "20.2.0-next.2",
|
|
772
|
+
ngImport: i0,
|
|
773
|
+
type: CdkMenuTrigger,
|
|
774
|
+
deps: [],
|
|
775
|
+
target: i0.ɵɵFactoryTarget.Directive
|
|
776
|
+
});
|
|
777
|
+
static ɵdir = i0.ɵɵngDeclareDirective({
|
|
778
|
+
minVersion: "14.0.0",
|
|
779
|
+
version: "20.2.0-next.2",
|
|
780
|
+
type: CdkMenuTrigger,
|
|
781
|
+
isStandalone: true,
|
|
782
|
+
selector: "[cdkMenuTriggerFor]",
|
|
783
|
+
inputs: {
|
|
784
|
+
menuTemplateRef: ["cdkMenuTriggerFor", "menuTemplateRef"],
|
|
785
|
+
menuPosition: ["cdkMenuPosition", "menuPosition"],
|
|
786
|
+
menuData: ["cdkMenuTriggerData", "menuData"]
|
|
787
|
+
},
|
|
788
|
+
outputs: {
|
|
789
|
+
opened: "cdkMenuOpened",
|
|
790
|
+
closed: "cdkMenuClosed"
|
|
791
|
+
},
|
|
792
|
+
host: {
|
|
793
|
+
listeners: {
|
|
794
|
+
"focusin": "_setHasFocus(true)",
|
|
795
|
+
"focusout": "_setHasFocus(false)",
|
|
796
|
+
"keydown": "_toggleOnKeydown($event)",
|
|
797
|
+
"click": "_handleClick()"
|
|
798
|
+
},
|
|
799
|
+
properties: {
|
|
800
|
+
"attr.aria-haspopup": "menuTemplateRef ? \"menu\" : null",
|
|
801
|
+
"attr.aria-expanded": "menuTemplateRef == null ? null : isOpen()"
|
|
802
|
+
},
|
|
803
|
+
classAttribute: "cdk-menu-trigger"
|
|
804
|
+
},
|
|
805
|
+
providers: [{
|
|
806
|
+
provide: MENU_TRIGGER,
|
|
807
|
+
useExisting: CdkMenuTrigger
|
|
808
|
+
}, PARENT_OR_NEW_MENU_STACK_PROVIDER],
|
|
809
|
+
exportAs: ["cdkMenuTriggerFor"],
|
|
810
|
+
usesInheritance: true,
|
|
811
|
+
usesOnChanges: true,
|
|
812
|
+
ngImport: i0
|
|
813
|
+
});
|
|
851
814
|
}
|
|
852
|
-
i0.ɵɵngDeclareClassMetadata({
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
815
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
816
|
+
minVersion: "12.0.0",
|
|
817
|
+
version: "20.2.0-next.2",
|
|
818
|
+
ngImport: i0,
|
|
819
|
+
type: CdkMenuTrigger,
|
|
820
|
+
decorators: [{
|
|
821
|
+
type: Directive,
|
|
822
|
+
args: [{
|
|
823
|
+
selector: '[cdkMenuTriggerFor]',
|
|
824
|
+
exportAs: 'cdkMenuTriggerFor',
|
|
825
|
+
host: {
|
|
826
|
+
'class': 'cdk-menu-trigger',
|
|
827
|
+
'[attr.aria-haspopup]': 'menuTemplateRef ? "menu" : null',
|
|
828
|
+
'[attr.aria-expanded]': 'menuTemplateRef == null ? null : isOpen()',
|
|
829
|
+
'(focusin)': '_setHasFocus(true)',
|
|
830
|
+
'(focusout)': '_setHasFocus(false)',
|
|
831
|
+
'(keydown)': '_toggleOnKeydown($event)',
|
|
832
|
+
'(click)': '_handleClick()'
|
|
833
|
+
},
|
|
834
|
+
inputs: [{
|
|
835
|
+
name: 'menuTemplateRef',
|
|
836
|
+
alias: 'cdkMenuTriggerFor'
|
|
837
|
+
}, {
|
|
838
|
+
name: 'menuPosition',
|
|
839
|
+
alias: 'cdkMenuPosition'
|
|
840
|
+
}, {
|
|
841
|
+
name: 'menuData',
|
|
842
|
+
alias: 'cdkMenuTriggerData'
|
|
843
|
+
}],
|
|
844
|
+
outputs: ['opened: cdkMenuOpened', 'closed: cdkMenuClosed'],
|
|
845
|
+
providers: [{
|
|
846
|
+
provide: MENU_TRIGGER,
|
|
847
|
+
useExisting: CdkMenuTrigger
|
|
848
|
+
}, PARENT_OR_NEW_MENU_STACK_PROVIDER]
|
|
849
|
+
}]
|
|
850
|
+
}],
|
|
851
|
+
ctorParameters: () => []
|
|
852
|
+
});
|
|
878
853
|
|
|
879
|
-
/**
|
|
880
|
-
* Directive which provides the ability for an element to be focused and navigated to using the
|
|
881
|
-
* keyboard when residing in a CdkMenu, CdkMenuBar, or CdkMenuGroup. It performs user defined
|
|
882
|
-
* behavior when clicked.
|
|
883
|
-
*/
|
|
884
854
|
class CdkMenuItem {
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
destroyed
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
}
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
*/
|
|
984
|
-
_setTabIndex(event) {
|
|
985
|
-
if (this.disabled) {
|
|
986
|
-
return;
|
|
987
|
-
}
|
|
988
|
-
// don't set the tabindex if there are no open sibling or parent menus
|
|
989
|
-
if (!event || !this._menuStack.isEmpty()) {
|
|
990
|
-
this._tabindex = 0;
|
|
991
|
-
}
|
|
992
|
-
}
|
|
993
|
-
/** Handles click events on the item. */
|
|
994
|
-
_handleClick(event) {
|
|
995
|
-
if (this.disabled) {
|
|
996
|
-
event.preventDefault();
|
|
997
|
-
event.stopPropagation();
|
|
998
|
-
}
|
|
999
|
-
else {
|
|
1000
|
-
this.trigger();
|
|
1001
|
-
}
|
|
1002
|
-
}
|
|
1003
|
-
/**
|
|
1004
|
-
* Handles keyboard events for the menu item, specifically either triggering the user defined
|
|
1005
|
-
* callback or opening/closing the current menu based on whether the left or right arrow key was
|
|
1006
|
-
* pressed.
|
|
1007
|
-
* @param event the keyboard event to handle
|
|
1008
|
-
*/
|
|
1009
|
-
_onKeydown(event) {
|
|
1010
|
-
switch (event.keyCode) {
|
|
1011
|
-
case SPACE:
|
|
1012
|
-
case ENTER:
|
|
1013
|
-
// Skip events that will trigger clicks so the handler doesn't get triggered twice.
|
|
1014
|
-
if (!hasModifierKey(event) && !eventDispatchesNativeClick(this._elementRef, event)) {
|
|
1015
|
-
const nodeName = this._elementRef.nativeElement.nodeName;
|
|
1016
|
-
// Avoid repeat events on non-native elements (see #30250). Note that we don't do this
|
|
1017
|
-
// on the native elements so we don't interfere with their behavior (see #26296).
|
|
1018
|
-
if (nodeName !== 'A' && nodeName !== 'BUTTON') {
|
|
1019
|
-
event.preventDefault();
|
|
1020
|
-
}
|
|
1021
|
-
this.trigger({ keepOpen: event.keyCode === SPACE && !this.closeOnSpacebarTrigger });
|
|
1022
|
-
}
|
|
1023
|
-
break;
|
|
1024
|
-
case RIGHT_ARROW:
|
|
1025
|
-
if (!hasModifierKey(event)) {
|
|
1026
|
-
if (this._parentMenu && this._isParentVertical()) {
|
|
1027
|
-
if (this._dir?.value !== 'rtl') {
|
|
1028
|
-
this._forwardArrowPressed(event);
|
|
1029
|
-
}
|
|
1030
|
-
else {
|
|
1031
|
-
this._backArrowPressed(event);
|
|
1032
|
-
}
|
|
1033
|
-
}
|
|
1034
|
-
}
|
|
1035
|
-
break;
|
|
1036
|
-
case LEFT_ARROW:
|
|
1037
|
-
if (!hasModifierKey(event)) {
|
|
1038
|
-
if (this._parentMenu && this._isParentVertical()) {
|
|
1039
|
-
if (this._dir?.value !== 'rtl') {
|
|
1040
|
-
this._backArrowPressed(event);
|
|
1041
|
-
}
|
|
1042
|
-
else {
|
|
1043
|
-
this._forwardArrowPressed(event);
|
|
1044
|
-
}
|
|
1045
|
-
}
|
|
1046
|
-
}
|
|
1047
|
-
break;
|
|
1048
|
-
}
|
|
1049
|
-
}
|
|
1050
|
-
/** Whether this menu item is standalone or within a menu or menu bar. */
|
|
1051
|
-
_isStandaloneItem() {
|
|
1052
|
-
return !this._parentMenu;
|
|
1053
|
-
}
|
|
1054
|
-
/**
|
|
1055
|
-
* Handles the user pressing the back arrow key.
|
|
1056
|
-
* @param event The keyboard event.
|
|
1057
|
-
*/
|
|
1058
|
-
_backArrowPressed(event) {
|
|
1059
|
-
const parentMenu = this._parentMenu;
|
|
1060
|
-
if (this._menuStack.hasInlineMenu() || this._menuStack.length() > 1) {
|
|
855
|
+
_dir = inject(Directionality, {
|
|
856
|
+
optional: true
|
|
857
|
+
});
|
|
858
|
+
_elementRef = inject(ElementRef);
|
|
859
|
+
_ngZone = inject(NgZone);
|
|
860
|
+
_inputModalityDetector = inject(InputModalityDetector);
|
|
861
|
+
_renderer = inject(Renderer2);
|
|
862
|
+
_cleanupMouseEnter;
|
|
863
|
+
_menuAim = inject(MENU_AIM, {
|
|
864
|
+
optional: true
|
|
865
|
+
});
|
|
866
|
+
_menuStack = inject(MENU_STACK);
|
|
867
|
+
_parentMenu = inject(CDK_MENU, {
|
|
868
|
+
optional: true
|
|
869
|
+
});
|
|
870
|
+
_menuTrigger = inject(CdkMenuTrigger, {
|
|
871
|
+
optional: true,
|
|
872
|
+
self: true
|
|
873
|
+
});
|
|
874
|
+
disabled = false;
|
|
875
|
+
typeaheadLabel;
|
|
876
|
+
triggered = new EventEmitter();
|
|
877
|
+
get hasMenu() {
|
|
878
|
+
return this._menuTrigger?.menuTemplateRef != null;
|
|
879
|
+
}
|
|
880
|
+
_tabindex = -1;
|
|
881
|
+
closeOnSpacebarTrigger = true;
|
|
882
|
+
destroyed = new Subject();
|
|
883
|
+
constructor() {
|
|
884
|
+
this._setupMouseEnter();
|
|
885
|
+
this._setType();
|
|
886
|
+
if (this._isStandaloneItem()) {
|
|
887
|
+
this._tabindex = 0;
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
ngOnDestroy() {
|
|
891
|
+
this._cleanupMouseEnter?.();
|
|
892
|
+
this.destroyed.next();
|
|
893
|
+
this.destroyed.complete();
|
|
894
|
+
}
|
|
895
|
+
focus() {
|
|
896
|
+
this._elementRef.nativeElement.focus();
|
|
897
|
+
}
|
|
898
|
+
trigger(options) {
|
|
899
|
+
const {
|
|
900
|
+
keepOpen
|
|
901
|
+
} = {
|
|
902
|
+
...options
|
|
903
|
+
};
|
|
904
|
+
if (!this.disabled && !this.hasMenu) {
|
|
905
|
+
this.triggered.next();
|
|
906
|
+
if (!keepOpen) {
|
|
907
|
+
this._menuStack.closeAll({
|
|
908
|
+
focusParentTrigger: true
|
|
909
|
+
});
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
isMenuOpen() {
|
|
914
|
+
return !!this._menuTrigger?.isOpen();
|
|
915
|
+
}
|
|
916
|
+
getMenu() {
|
|
917
|
+
return this._menuTrigger?.getMenu();
|
|
918
|
+
}
|
|
919
|
+
getMenuTrigger() {
|
|
920
|
+
return this._menuTrigger;
|
|
921
|
+
}
|
|
922
|
+
getLabel() {
|
|
923
|
+
return this.typeaheadLabel || this._elementRef.nativeElement.textContent?.trim() || '';
|
|
924
|
+
}
|
|
925
|
+
_resetTabIndex() {
|
|
926
|
+
if (!this._isStandaloneItem()) {
|
|
927
|
+
this._tabindex = -1;
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
_setTabIndex(event) {
|
|
931
|
+
if (this.disabled) {
|
|
932
|
+
return;
|
|
933
|
+
}
|
|
934
|
+
if (!event || !this._menuStack.isEmpty()) {
|
|
935
|
+
this._tabindex = 0;
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
_handleClick(event) {
|
|
939
|
+
if (this.disabled) {
|
|
940
|
+
event.preventDefault();
|
|
941
|
+
event.stopPropagation();
|
|
942
|
+
} else {
|
|
943
|
+
this.trigger();
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
_onKeydown(event) {
|
|
947
|
+
switch (event.keyCode) {
|
|
948
|
+
case SPACE:
|
|
949
|
+
case ENTER:
|
|
950
|
+
if (!hasModifierKey(event) && !eventDispatchesNativeClick(this._elementRef, event)) {
|
|
951
|
+
const nodeName = this._elementRef.nativeElement.nodeName;
|
|
952
|
+
if (nodeName !== 'A' && nodeName !== 'BUTTON') {
|
|
1061
953
|
event.preventDefault();
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
focusParentTrigger: true,
|
|
1067
|
-
});
|
|
954
|
+
}
|
|
955
|
+
this.trigger({
|
|
956
|
+
keepOpen: event.keyCode === SPACE && !this.closeOnSpacebarTrigger
|
|
957
|
+
});
|
|
1068
958
|
}
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
focusParentTrigger: true,
|
|
1080
|
-
});
|
|
959
|
+
break;
|
|
960
|
+
case RIGHT_ARROW:
|
|
961
|
+
if (!hasModifierKey(event)) {
|
|
962
|
+
if (this._parentMenu && this._isParentVertical()) {
|
|
963
|
+
if (this._dir?.value !== 'rtl') {
|
|
964
|
+
this._forwardArrowPressed(event);
|
|
965
|
+
} else {
|
|
966
|
+
this._backArrowPressed(event);
|
|
967
|
+
}
|
|
968
|
+
}
|
|
1081
969
|
}
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
if (this._inputModalityDetector.mostRecentModality !== 'touch' &&
|
|
1093
|
-
!this._menuStack.isEmpty() &&
|
|
1094
|
-
!this.hasMenu) {
|
|
1095
|
-
if (this._menuAim) {
|
|
1096
|
-
this._menuAim.toggle(closeOpenSiblings);
|
|
1097
|
-
}
|
|
1098
|
-
else {
|
|
1099
|
-
closeOpenSiblings();
|
|
1100
|
-
}
|
|
1101
|
-
}
|
|
1102
|
-
}));
|
|
970
|
+
break;
|
|
971
|
+
case LEFT_ARROW:
|
|
972
|
+
if (!hasModifierKey(event)) {
|
|
973
|
+
if (this._parentMenu && this._isParentVertical()) {
|
|
974
|
+
if (this._dir?.value !== 'rtl') {
|
|
975
|
+
this._backArrowPressed(event);
|
|
976
|
+
} else {
|
|
977
|
+
this._forwardArrowPressed(event);
|
|
978
|
+
}
|
|
979
|
+
}
|
|
1103
980
|
}
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
981
|
+
break;
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
_isStandaloneItem() {
|
|
985
|
+
return !this._parentMenu;
|
|
986
|
+
}
|
|
987
|
+
_backArrowPressed(event) {
|
|
988
|
+
const parentMenu = this._parentMenu;
|
|
989
|
+
if (this._menuStack.hasInlineMenu() || this._menuStack.length() > 1) {
|
|
990
|
+
event.preventDefault();
|
|
991
|
+
this._menuStack.close(parentMenu, {
|
|
992
|
+
focusNextOnEmpty: this._menuStack.inlineMenuOrientation() === 'horizontal' ? FocusNext.previousItem : FocusNext.currentItem,
|
|
993
|
+
focusParentTrigger: true
|
|
994
|
+
});
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
_forwardArrowPressed(event) {
|
|
998
|
+
if (!this.hasMenu && this._menuStack.inlineMenuOrientation() === 'horizontal') {
|
|
999
|
+
event.preventDefault();
|
|
1000
|
+
this._menuStack.closeAll({
|
|
1001
|
+
focusNextOnEmpty: FocusNext.nextItem,
|
|
1002
|
+
focusParentTrigger: true
|
|
1003
|
+
});
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
_setupMouseEnter() {
|
|
1007
|
+
if (!this._isStandaloneItem()) {
|
|
1008
|
+
const closeOpenSiblings = () => this._ngZone.run(() => this._menuStack.closeSubMenuOf(this._parentMenu));
|
|
1009
|
+
this._cleanupMouseEnter = this._ngZone.runOutsideAngular(() => this._renderer.listen(this._elementRef.nativeElement, 'mouseenter', () => {
|
|
1010
|
+
if (this._inputModalityDetector.mostRecentModality !== 'touch' && !this._menuStack.isEmpty() && !this.hasMenu) {
|
|
1011
|
+
if (this._menuAim) {
|
|
1012
|
+
this._menuAim.toggle(closeOpenSiblings);
|
|
1013
|
+
} else {
|
|
1014
|
+
closeOpenSiblings();
|
|
1015
|
+
}
|
|
1118
1016
|
}
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1017
|
+
}));
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
_isParentVertical() {
|
|
1021
|
+
return this._parentMenu?.orientation === 'vertical';
|
|
1022
|
+
}
|
|
1023
|
+
_setType() {
|
|
1024
|
+
const element = this._elementRef.nativeElement;
|
|
1025
|
+
if (element.nodeName === 'BUTTON' && !element.getAttribute('type')) {
|
|
1026
|
+
element.setAttribute('type', 'button');
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
1030
|
+
minVersion: "12.0.0",
|
|
1031
|
+
version: "20.2.0-next.2",
|
|
1032
|
+
ngImport: i0,
|
|
1033
|
+
type: CdkMenuItem,
|
|
1034
|
+
deps: [],
|
|
1035
|
+
target: i0.ɵɵFactoryTarget.Directive
|
|
1036
|
+
});
|
|
1037
|
+
static ɵdir = i0.ɵɵngDeclareDirective({
|
|
1038
|
+
minVersion: "16.1.0",
|
|
1039
|
+
version: "20.2.0-next.2",
|
|
1040
|
+
type: CdkMenuItem,
|
|
1041
|
+
isStandalone: true,
|
|
1042
|
+
selector: "[cdkMenuItem]",
|
|
1043
|
+
inputs: {
|
|
1044
|
+
disabled: ["cdkMenuItemDisabled", "disabled", booleanAttribute],
|
|
1045
|
+
typeaheadLabel: ["cdkMenuitemTypeaheadLabel", "typeaheadLabel"]
|
|
1046
|
+
},
|
|
1047
|
+
outputs: {
|
|
1048
|
+
triggered: "cdkMenuItemTriggered"
|
|
1049
|
+
},
|
|
1050
|
+
host: {
|
|
1051
|
+
attributes: {
|
|
1052
|
+
"role": "menuitem"
|
|
1053
|
+
},
|
|
1054
|
+
listeners: {
|
|
1055
|
+
"blur": "_resetTabIndex()",
|
|
1056
|
+
"focus": "_setTabIndex()",
|
|
1057
|
+
"click": "_handleClick($event)",
|
|
1058
|
+
"keydown": "_onKeydown($event)"
|
|
1059
|
+
},
|
|
1060
|
+
properties: {
|
|
1061
|
+
"class.cdk-menu-item-disabled": "disabled",
|
|
1062
|
+
"tabindex": "_tabindex",
|
|
1063
|
+
"attr.aria-disabled": "disabled || null"
|
|
1064
|
+
},
|
|
1065
|
+
classAttribute: "cdk-menu-item"
|
|
1066
|
+
},
|
|
1067
|
+
exportAs: ["cdkMenuItem"],
|
|
1068
|
+
ngImport: i0
|
|
1069
|
+
});
|
|
1122
1070
|
}
|
|
1123
|
-
i0.ɵɵngDeclareClassMetadata({
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1071
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
1072
|
+
minVersion: "12.0.0",
|
|
1073
|
+
version: "20.2.0-next.2",
|
|
1074
|
+
ngImport: i0,
|
|
1075
|
+
type: CdkMenuItem,
|
|
1076
|
+
decorators: [{
|
|
1077
|
+
type: Directive,
|
|
1078
|
+
args: [{
|
|
1079
|
+
selector: '[cdkMenuItem]',
|
|
1080
|
+
exportAs: 'cdkMenuItem',
|
|
1081
|
+
host: {
|
|
1082
|
+
'role': 'menuitem',
|
|
1083
|
+
'class': 'cdk-menu-item',
|
|
1084
|
+
'[class.cdk-menu-item-disabled]': 'disabled',
|
|
1085
|
+
'[tabindex]': '_tabindex',
|
|
1086
|
+
'[attr.aria-disabled]': 'disabled || null',
|
|
1087
|
+
'(blur)': '_resetTabIndex()',
|
|
1088
|
+
'(focus)': '_setTabIndex()',
|
|
1089
|
+
'(click)': '_handleClick($event)',
|
|
1090
|
+
'(keydown)': '_onKeydown($event)'
|
|
1091
|
+
}
|
|
1092
|
+
}]
|
|
1093
|
+
}],
|
|
1094
|
+
ctorParameters: () => [],
|
|
1095
|
+
propDecorators: {
|
|
1096
|
+
disabled: [{
|
|
1097
|
+
type: Input,
|
|
1098
|
+
args: [{
|
|
1099
|
+
alias: 'cdkMenuItemDisabled',
|
|
1100
|
+
transform: booleanAttribute
|
|
1101
|
+
}]
|
|
1102
|
+
}],
|
|
1103
|
+
typeaheadLabel: [{
|
|
1104
|
+
type: Input,
|
|
1105
|
+
args: ['cdkMenuitemTypeaheadLabel']
|
|
1106
|
+
}],
|
|
1107
|
+
triggered: [{
|
|
1108
|
+
type: Output,
|
|
1109
|
+
args: ['cdkMenuItemTriggered']
|
|
1110
|
+
}]
|
|
1111
|
+
}
|
|
1112
|
+
});
|
|
1150
1113
|
|
|
1151
|
-
/**
|
|
1152
|
-
* PointerFocusTracker keeps track of the currently active item under mouse focus. It also has
|
|
1153
|
-
* observables which emit when the users mouse enters and leaves a tracked element.
|
|
1154
|
-
*/
|
|
1155
1114
|
class PointerFocusTracker {
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
});
|
|
1197
|
-
});
|
|
1198
|
-
}
|
|
1199
|
-
/** Cleans up the currently-bound events. */
|
|
1200
|
-
_cleanupEvents() {
|
|
1201
|
-
this._eventCleanups?.forEach(cleanup => cleanup());
|
|
1202
|
-
this._eventCleanups = undefined;
|
|
1203
|
-
}
|
|
1115
|
+
_renderer;
|
|
1116
|
+
_items;
|
|
1117
|
+
_eventCleanups;
|
|
1118
|
+
_itemsSubscription;
|
|
1119
|
+
entered = new Subject();
|
|
1120
|
+
exited = new Subject();
|
|
1121
|
+
activeElement;
|
|
1122
|
+
previousElement;
|
|
1123
|
+
constructor(_renderer, _items) {
|
|
1124
|
+
this._renderer = _renderer;
|
|
1125
|
+
this._items = _items;
|
|
1126
|
+
this._bindEvents();
|
|
1127
|
+
this.entered.subscribe(element => this.activeElement = element);
|
|
1128
|
+
this.exited.subscribe(() => {
|
|
1129
|
+
this.previousElement = this.activeElement;
|
|
1130
|
+
this.activeElement = undefined;
|
|
1131
|
+
});
|
|
1132
|
+
}
|
|
1133
|
+
destroy() {
|
|
1134
|
+
this._cleanupEvents();
|
|
1135
|
+
this._itemsSubscription?.unsubscribe();
|
|
1136
|
+
}
|
|
1137
|
+
_bindEvents() {
|
|
1138
|
+
this._itemsSubscription = this._items.changes.pipe(startWith(this._items)).subscribe(() => {
|
|
1139
|
+
this._cleanupEvents();
|
|
1140
|
+
this._eventCleanups = [];
|
|
1141
|
+
this._items.forEach(item => {
|
|
1142
|
+
const element = item._elementRef.nativeElement;
|
|
1143
|
+
this._eventCleanups.push(this._renderer.listen(element, 'mouseenter', () => {
|
|
1144
|
+
this.entered.next(item);
|
|
1145
|
+
}), this._renderer.listen(element, 'mouseout', () => {
|
|
1146
|
+
this.exited.next(item);
|
|
1147
|
+
}));
|
|
1148
|
+
});
|
|
1149
|
+
});
|
|
1150
|
+
}
|
|
1151
|
+
_cleanupEvents() {
|
|
1152
|
+
this._eventCleanups?.forEach(cleanup => cleanup());
|
|
1153
|
+
this._eventCleanups = undefined;
|
|
1154
|
+
}
|
|
1204
1155
|
}
|
|
1205
1156
|
|
|
1206
|
-
/**
|
|
1207
|
-
* Abstract directive that implements shared logic common to all menus.
|
|
1208
|
-
* This class can be extended to create custom menu types.
|
|
1209
|
-
*/
|
|
1210
1157
|
class CdkMenuBase extends CdkMenuGroup {
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
this.keyManager?.setActiveItem(item);
|
|
1290
|
-
}
|
|
1291
|
-
/** Gets the tabindex for this menu. */
|
|
1292
|
-
_getTabIndex() {
|
|
1293
|
-
return this._tabIndexSignal();
|
|
1294
|
-
}
|
|
1295
|
-
/**
|
|
1296
|
-
* Close the open menu if the current active item opened the requested MenuStackItem.
|
|
1297
|
-
* @param menu The menu requested to be closed.
|
|
1298
|
-
* @param options Options to configure the behavior on close.
|
|
1299
|
-
* - `focusParentTrigger` Whether to focus the parent trigger after closing the menu.
|
|
1300
|
-
*/
|
|
1301
|
-
closeOpenMenu(menu, options) {
|
|
1302
|
-
const { focusParentTrigger } = { ...options };
|
|
1303
|
-
const keyManager = this.keyManager;
|
|
1304
|
-
const trigger = this.triggerItem;
|
|
1305
|
-
if (menu === trigger?.getMenuTrigger()?.getMenu()) {
|
|
1306
|
-
trigger?.getMenuTrigger()?.close();
|
|
1307
|
-
// If the user has moused over a sibling item we want to focus the element under mouse focus
|
|
1308
|
-
// not the trigger which previously opened the now closed menu.
|
|
1309
|
-
if (focusParentTrigger) {
|
|
1310
|
-
if (trigger) {
|
|
1311
|
-
keyManager.setActiveItem(trigger);
|
|
1312
|
-
}
|
|
1313
|
-
else {
|
|
1314
|
-
keyManager.setFirstItemActive();
|
|
1315
|
-
}
|
|
1316
|
-
}
|
|
1317
|
-
}
|
|
1318
|
-
}
|
|
1319
|
-
/** Sets up the subscription that keeps the items list in sync. */
|
|
1320
|
-
_setItems() {
|
|
1321
|
-
// Since the items query has `descendants: true`, we need
|
|
1322
|
-
// to filter out items belonging to a different menu.
|
|
1323
|
-
this._allItems.changes
|
|
1324
|
-
.pipe(startWith(this._allItems), takeUntil(this.destroyed))
|
|
1325
|
-
.subscribe((items) => {
|
|
1326
|
-
this.items.reset(items.filter(item => item._parentMenu === this));
|
|
1327
|
-
this.items.notifyOnChanges();
|
|
1328
|
-
});
|
|
1329
|
-
}
|
|
1330
|
-
/** Setup the FocusKeyManager with the correct orientation for the menu. */
|
|
1331
|
-
_setKeyManager() {
|
|
1332
|
-
this.keyManager = new FocusKeyManager(this.items)
|
|
1333
|
-
.withWrap()
|
|
1334
|
-
.withTypeAhead()
|
|
1335
|
-
.withHomeAndEnd()
|
|
1336
|
-
.skipPredicate(() => false);
|
|
1337
|
-
if (this.orientation === 'horizontal') {
|
|
1338
|
-
this.keyManager.withHorizontalOrientation(this.dir?.value || 'ltr');
|
|
1339
|
-
}
|
|
1340
|
-
else {
|
|
1341
|
-
this.keyManager.withVerticalOrientation();
|
|
1342
|
-
}
|
|
1343
|
-
}
|
|
1344
|
-
/**
|
|
1345
|
-
* Subscribe to the menu trigger's open events in order to track the trigger which opened the menu
|
|
1346
|
-
* and stop tracking it when the menu is closed.
|
|
1347
|
-
*/
|
|
1348
|
-
_subscribeToMenuOpen() {
|
|
1349
|
-
const exitCondition = merge(this.items.changes, this.destroyed);
|
|
1350
|
-
this.items.changes
|
|
1351
|
-
.pipe(startWith(this.items), mergeMap((list) => list
|
|
1352
|
-
.filter(item => item.hasMenu)
|
|
1353
|
-
.map(item => item.getMenuTrigger().opened.pipe(mapTo(item), takeUntil(exitCondition)))), mergeAll(), switchMap((item) => {
|
|
1354
|
-
this.triggerItem = item;
|
|
1355
|
-
return item.getMenuTrigger().closed;
|
|
1356
|
-
}), takeUntil(this.destroyed))
|
|
1357
|
-
.subscribe(() => (this.triggerItem = undefined));
|
|
1358
|
-
}
|
|
1359
|
-
/** Subscribe to the MenuStack close events. */
|
|
1360
|
-
_subscribeToMenuStackClosed() {
|
|
1361
|
-
this.menuStack.closed
|
|
1362
|
-
.pipe(takeUntil(this.destroyed))
|
|
1363
|
-
.subscribe(({ item, focusParentTrigger }) => this.closeOpenMenu(item, { focusParentTrigger }));
|
|
1364
|
-
}
|
|
1365
|
-
/** Subscribe to the MenuStack hasFocus events. */
|
|
1366
|
-
_subscribeToMenuStackHasFocus() {
|
|
1367
|
-
if (this.isInline) {
|
|
1368
|
-
this.menuStack.hasFocus.pipe(takeUntil(this.destroyed)).subscribe(hasFocus => {
|
|
1369
|
-
this._menuStackHasFocus.set(hasFocus);
|
|
1370
|
-
});
|
|
1371
|
-
}
|
|
1372
|
-
}
|
|
1373
|
-
/**
|
|
1374
|
-
* Set the PointerFocusTracker and ensure that when mouse focus changes the key manager is updated
|
|
1375
|
-
* with the latest menu item under mouse focus.
|
|
1376
|
-
*/
|
|
1377
|
-
_setUpPointerTracker() {
|
|
1378
|
-
if (this.menuAim) {
|
|
1379
|
-
this.ngZone.runOutsideAngular(() => {
|
|
1380
|
-
this.pointerTracker = new PointerFocusTracker(this._renderer, this.items);
|
|
1381
|
-
});
|
|
1382
|
-
this.menuAim.initialize(this, this.pointerTracker);
|
|
1158
|
+
_focusMonitor = inject(FocusMonitor);
|
|
1159
|
+
ngZone = inject(NgZone);
|
|
1160
|
+
_renderer = inject(Renderer2);
|
|
1161
|
+
nativeElement = inject(ElementRef).nativeElement;
|
|
1162
|
+
menuStack = inject(MENU_STACK);
|
|
1163
|
+
menuAim = inject(MENU_AIM, {
|
|
1164
|
+
optional: true,
|
|
1165
|
+
self: true
|
|
1166
|
+
});
|
|
1167
|
+
dir = inject(Directionality, {
|
|
1168
|
+
optional: true
|
|
1169
|
+
});
|
|
1170
|
+
_allItems;
|
|
1171
|
+
id = inject(_IdGenerator).getId('cdk-menu-');
|
|
1172
|
+
items = new QueryList();
|
|
1173
|
+
orientation = 'vertical';
|
|
1174
|
+
isInline = false;
|
|
1175
|
+
keyManager;
|
|
1176
|
+
destroyed = new Subject();
|
|
1177
|
+
triggerItem;
|
|
1178
|
+
pointerTracker;
|
|
1179
|
+
_menuStackHasFocus = signal(false, ...(ngDevMode ? [{
|
|
1180
|
+
debugName: "_menuStackHasFocus"
|
|
1181
|
+
}] : []));
|
|
1182
|
+
_tabIndexSignal = computed(() => {
|
|
1183
|
+
const tabindexIfInline = this._menuStackHasFocus() ? -1 : 0;
|
|
1184
|
+
return this.isInline ? tabindexIfInline : null;
|
|
1185
|
+
}, ...(ngDevMode ? [{
|
|
1186
|
+
debugName: "_tabIndexSignal"
|
|
1187
|
+
}] : []));
|
|
1188
|
+
ngAfterContentInit() {
|
|
1189
|
+
if (!this.isInline) {
|
|
1190
|
+
this.menuStack.push(this);
|
|
1191
|
+
}
|
|
1192
|
+
this._setItems();
|
|
1193
|
+
this._setKeyManager();
|
|
1194
|
+
this._handleFocus();
|
|
1195
|
+
this._subscribeToMenuStackHasFocus();
|
|
1196
|
+
this._subscribeToMenuOpen();
|
|
1197
|
+
this._subscribeToMenuStackClosed();
|
|
1198
|
+
this._setUpPointerTracker();
|
|
1199
|
+
}
|
|
1200
|
+
ngOnDestroy() {
|
|
1201
|
+
this._focusMonitor.stopMonitoring(this.nativeElement);
|
|
1202
|
+
this.keyManager?.destroy();
|
|
1203
|
+
this.destroyed.next();
|
|
1204
|
+
this.destroyed.complete();
|
|
1205
|
+
this.pointerTracker?.destroy();
|
|
1206
|
+
}
|
|
1207
|
+
focusFirstItem(focusOrigin = 'program') {
|
|
1208
|
+
this.keyManager.setFocusOrigin(focusOrigin);
|
|
1209
|
+
this.keyManager.setFirstItemActive();
|
|
1210
|
+
}
|
|
1211
|
+
focusLastItem(focusOrigin = 'program') {
|
|
1212
|
+
this.keyManager.setFocusOrigin(focusOrigin);
|
|
1213
|
+
this.keyManager.setLastItemActive();
|
|
1214
|
+
}
|
|
1215
|
+
setActiveMenuItem(item) {
|
|
1216
|
+
this.keyManager?.setActiveItem(item);
|
|
1217
|
+
}
|
|
1218
|
+
_getTabIndex() {
|
|
1219
|
+
return this._tabIndexSignal();
|
|
1220
|
+
}
|
|
1221
|
+
closeOpenMenu(menu, options) {
|
|
1222
|
+
const {
|
|
1223
|
+
focusParentTrigger
|
|
1224
|
+
} = {
|
|
1225
|
+
...options
|
|
1226
|
+
};
|
|
1227
|
+
const keyManager = this.keyManager;
|
|
1228
|
+
const trigger = this.triggerItem;
|
|
1229
|
+
if (menu === trigger?.getMenuTrigger()?.getMenu()) {
|
|
1230
|
+
trigger?.getMenuTrigger()?.close();
|
|
1231
|
+
if (focusParentTrigger) {
|
|
1232
|
+
if (trigger) {
|
|
1233
|
+
keyManager.setActiveItem(trigger);
|
|
1234
|
+
} else {
|
|
1235
|
+
keyManager.setFirstItemActive();
|
|
1383
1236
|
}
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
}
|
|
1398
|
-
|
|
1399
|
-
|
|
1237
|
+
}
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
_setItems() {
|
|
1241
|
+
this._allItems.changes.pipe(startWith(this._allItems), takeUntil(this.destroyed)).subscribe(items => {
|
|
1242
|
+
this.items.reset(items.filter(item => item._parentMenu === this));
|
|
1243
|
+
this.items.notifyOnChanges();
|
|
1244
|
+
});
|
|
1245
|
+
}
|
|
1246
|
+
_setKeyManager() {
|
|
1247
|
+
this.keyManager = new FocusKeyManager(this.items).withWrap().withTypeAhead().withHomeAndEnd().skipPredicate(() => false);
|
|
1248
|
+
if (this.orientation === 'horizontal') {
|
|
1249
|
+
this.keyManager.withHorizontalOrientation(this.dir?.value || 'ltr');
|
|
1250
|
+
} else {
|
|
1251
|
+
this.keyManager.withVerticalOrientation();
|
|
1252
|
+
}
|
|
1253
|
+
}
|
|
1254
|
+
_subscribeToMenuOpen() {
|
|
1255
|
+
const exitCondition = merge(this.items.changes, this.destroyed);
|
|
1256
|
+
this.items.changes.pipe(startWith(this.items), mergeMap(list => list.filter(item => item.hasMenu).map(item => item.getMenuTrigger().opened.pipe(mapTo(item), takeUntil(exitCondition)))), mergeAll(), switchMap(item => {
|
|
1257
|
+
this.triggerItem = item;
|
|
1258
|
+
return item.getMenuTrigger().closed;
|
|
1259
|
+
}), takeUntil(this.destroyed)).subscribe(() => this.triggerItem = undefined);
|
|
1260
|
+
}
|
|
1261
|
+
_subscribeToMenuStackClosed() {
|
|
1262
|
+
this.menuStack.closed.pipe(takeUntil(this.destroyed)).subscribe(({
|
|
1263
|
+
item,
|
|
1264
|
+
focusParentTrigger
|
|
1265
|
+
}) => this.closeOpenMenu(item, {
|
|
1266
|
+
focusParentTrigger
|
|
1267
|
+
}));
|
|
1268
|
+
}
|
|
1269
|
+
_subscribeToMenuStackHasFocus() {
|
|
1270
|
+
if (this.isInline) {
|
|
1271
|
+
this.menuStack.hasFocus.pipe(takeUntil(this.destroyed)).subscribe(hasFocus => {
|
|
1272
|
+
this._menuStackHasFocus.set(hasFocus);
|
|
1273
|
+
});
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
_setUpPointerTracker() {
|
|
1277
|
+
if (this.menuAim) {
|
|
1278
|
+
this.ngZone.runOutsideAngular(() => {
|
|
1279
|
+
this.pointerTracker = new PointerFocusTracker(this._renderer, this.items);
|
|
1280
|
+
});
|
|
1281
|
+
this.menuAim.initialize(this, this.pointerTracker);
|
|
1282
|
+
}
|
|
1283
|
+
}
|
|
1284
|
+
_handleFocus() {
|
|
1285
|
+
this._focusMonitor.monitor(this.nativeElement, false).pipe(takeUntil(this.destroyed)).subscribe(origin => {
|
|
1286
|
+
if (origin !== null && origin !== 'mouse') {
|
|
1287
|
+
this.focusFirstItem(origin);
|
|
1288
|
+
}
|
|
1289
|
+
});
|
|
1290
|
+
}
|
|
1291
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
1292
|
+
minVersion: "12.0.0",
|
|
1293
|
+
version: "20.2.0-next.2",
|
|
1294
|
+
ngImport: i0,
|
|
1295
|
+
type: CdkMenuBase,
|
|
1296
|
+
deps: null,
|
|
1297
|
+
target: i0.ɵɵFactoryTarget.Directive
|
|
1298
|
+
});
|
|
1299
|
+
static ɵdir = i0.ɵɵngDeclareDirective({
|
|
1300
|
+
minVersion: "14.0.0",
|
|
1301
|
+
version: "20.2.0-next.2",
|
|
1302
|
+
type: CdkMenuBase,
|
|
1303
|
+
isStandalone: true,
|
|
1304
|
+
inputs: {
|
|
1305
|
+
id: "id"
|
|
1306
|
+
},
|
|
1307
|
+
host: {
|
|
1308
|
+
attributes: {
|
|
1309
|
+
"role": "menu"
|
|
1310
|
+
},
|
|
1311
|
+
listeners: {
|
|
1312
|
+
"focusin": "menuStack.setHasFocus(true)",
|
|
1313
|
+
"focusout": "menuStack.setHasFocus(false)"
|
|
1314
|
+
},
|
|
1315
|
+
properties: {
|
|
1316
|
+
"tabindex": "_getTabIndex()",
|
|
1317
|
+
"id": "id",
|
|
1318
|
+
"attr.aria-orientation": "orientation",
|
|
1319
|
+
"attr.data-cdk-menu-stack-id": "menuStack.id"
|
|
1320
|
+
}
|
|
1321
|
+
},
|
|
1322
|
+
queries: [{
|
|
1323
|
+
propertyName: "_allItems",
|
|
1324
|
+
predicate: CdkMenuItem,
|
|
1325
|
+
descendants: true
|
|
1326
|
+
}],
|
|
1327
|
+
usesInheritance: true,
|
|
1328
|
+
ngImport: i0
|
|
1329
|
+
});
|
|
1400
1330
|
}
|
|
1401
|
-
i0.ɵɵngDeclareClassMetadata({
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1331
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
1332
|
+
minVersion: "12.0.0",
|
|
1333
|
+
version: "20.2.0-next.2",
|
|
1334
|
+
ngImport: i0,
|
|
1335
|
+
type: CdkMenuBase,
|
|
1336
|
+
decorators: [{
|
|
1337
|
+
type: Directive,
|
|
1338
|
+
args: [{
|
|
1339
|
+
host: {
|
|
1340
|
+
'role': 'menu',
|
|
1341
|
+
'class': '',
|
|
1342
|
+
'[tabindex]': '_getTabIndex()',
|
|
1343
|
+
'[id]': 'id',
|
|
1344
|
+
'[attr.aria-orientation]': 'orientation',
|
|
1345
|
+
'[attr.data-cdk-menu-stack-id]': 'menuStack.id',
|
|
1346
|
+
'(focusin)': 'menuStack.setHasFocus(true)',
|
|
1347
|
+
'(focusout)': 'menuStack.setHasFocus(false)'
|
|
1348
|
+
}
|
|
1349
|
+
}]
|
|
1350
|
+
}],
|
|
1351
|
+
propDecorators: {
|
|
1352
|
+
_allItems: [{
|
|
1353
|
+
type: ContentChildren,
|
|
1354
|
+
args: [CdkMenuItem, {
|
|
1355
|
+
descendants: true
|
|
1356
|
+
}]
|
|
1357
|
+
}],
|
|
1358
|
+
id: [{
|
|
1359
|
+
type: Input
|
|
1360
|
+
}]
|
|
1361
|
+
}
|
|
1362
|
+
});
|
|
1421
1363
|
|
|
1422
|
-
/**
|
|
1423
|
-
* Directive which configures the element as a Menu which should contain child elements marked as
|
|
1424
|
-
* CdkMenuItem or CdkMenuGroup. Sets the appropriate role and aria-attributes for a menu and
|
|
1425
|
-
* contains accessible keyboard and mouse handling logic.
|
|
1426
|
-
*
|
|
1427
|
-
* It also acts as a RadioGroup for elements marked with role `menuitemradio`.
|
|
1428
|
-
*/
|
|
1429
1364
|
class CdkMenu extends CdkMenuBase {
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
ngAfterContentInit()
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
ngOnDestroy()
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
case RIGHT_ARROW:
|
|
1459
|
-
if (!hasModifierKey(event)) {
|
|
1460
|
-
event.preventDefault();
|
|
1461
|
-
keyManager.setFocusOrigin('keyboard');
|
|
1462
|
-
keyManager.onKeydown(event);
|
|
1463
|
-
}
|
|
1464
|
-
break;
|
|
1465
|
-
case ESCAPE:
|
|
1466
|
-
if (!hasModifierKey(event)) {
|
|
1467
|
-
event.preventDefault();
|
|
1468
|
-
this.menuStack.close(this, {
|
|
1469
|
-
focusNextOnEmpty: FocusNext.currentItem,
|
|
1470
|
-
focusParentTrigger: true,
|
|
1471
|
-
});
|
|
1472
|
-
}
|
|
1473
|
-
break;
|
|
1474
|
-
case TAB:
|
|
1475
|
-
if (!hasModifierKey(event, 'altKey', 'metaKey', 'ctrlKey')) {
|
|
1476
|
-
this.menuStack.closeAll({ focusParentTrigger: true });
|
|
1477
|
-
}
|
|
1478
|
-
break;
|
|
1479
|
-
default:
|
|
1480
|
-
keyManager.onKeydown(event);
|
|
1365
|
+
_parentTrigger = inject(MENU_TRIGGER, {
|
|
1366
|
+
optional: true
|
|
1367
|
+
});
|
|
1368
|
+
closed = new EventEmitter();
|
|
1369
|
+
orientation = 'vertical';
|
|
1370
|
+
isInline = !this._parentTrigger;
|
|
1371
|
+
constructor() {
|
|
1372
|
+
super();
|
|
1373
|
+
this.destroyed.subscribe(this.closed);
|
|
1374
|
+
this._parentTrigger?.registerChildMenu(this);
|
|
1375
|
+
}
|
|
1376
|
+
ngAfterContentInit() {
|
|
1377
|
+
super.ngAfterContentInit();
|
|
1378
|
+
this._subscribeToMenuStackEmptied();
|
|
1379
|
+
}
|
|
1380
|
+
ngOnDestroy() {
|
|
1381
|
+
super.ngOnDestroy();
|
|
1382
|
+
this.closed.complete();
|
|
1383
|
+
}
|
|
1384
|
+
_handleKeyEvent(event) {
|
|
1385
|
+
const keyManager = this.keyManager;
|
|
1386
|
+
switch (event.keyCode) {
|
|
1387
|
+
case LEFT_ARROW:
|
|
1388
|
+
case RIGHT_ARROW:
|
|
1389
|
+
if (!hasModifierKey(event)) {
|
|
1390
|
+
event.preventDefault();
|
|
1391
|
+
keyManager.setFocusOrigin('keyboard');
|
|
1392
|
+
keyManager.onKeydown(event);
|
|
1481
1393
|
}
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
case FocusNext.nextItem:
|
|
1491
|
-
keyManager.setFocusOrigin('keyboard');
|
|
1492
|
-
keyManager.setNextItemActive();
|
|
1493
|
-
break;
|
|
1494
|
-
case FocusNext.previousItem:
|
|
1495
|
-
keyManager.setFocusOrigin('keyboard');
|
|
1496
|
-
keyManager.setPreviousItemActive();
|
|
1497
|
-
break;
|
|
1498
|
-
case FocusNext.currentItem:
|
|
1499
|
-
if (keyManager.activeItem) {
|
|
1500
|
-
keyManager.setFocusOrigin('keyboard');
|
|
1501
|
-
keyManager.setActiveItem(keyManager.activeItem);
|
|
1502
|
-
}
|
|
1503
|
-
break;
|
|
1394
|
+
break;
|
|
1395
|
+
case ESCAPE:
|
|
1396
|
+
if (!hasModifierKey(event)) {
|
|
1397
|
+
event.preventDefault();
|
|
1398
|
+
this.menuStack.close(this, {
|
|
1399
|
+
focusNextOnEmpty: FocusNext.currentItem,
|
|
1400
|
+
focusParentTrigger: true
|
|
1401
|
+
});
|
|
1504
1402
|
}
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1403
|
+
break;
|
|
1404
|
+
case TAB:
|
|
1405
|
+
if (!hasModifierKey(event, 'altKey', 'metaKey', 'ctrlKey')) {
|
|
1406
|
+
this.menuStack.closeAll({
|
|
1407
|
+
focusParentTrigger: true
|
|
1408
|
+
});
|
|
1409
|
+
}
|
|
1410
|
+
break;
|
|
1411
|
+
default:
|
|
1412
|
+
keyManager.onKeydown(event);
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1415
|
+
_toggleMenuFocus(focusNext) {
|
|
1416
|
+
const keyManager = this.keyManager;
|
|
1417
|
+
switch (focusNext) {
|
|
1418
|
+
case FocusNext.nextItem:
|
|
1419
|
+
keyManager.setFocusOrigin('keyboard');
|
|
1420
|
+
keyManager.setNextItemActive();
|
|
1421
|
+
break;
|
|
1422
|
+
case FocusNext.previousItem:
|
|
1423
|
+
keyManager.setFocusOrigin('keyboard');
|
|
1424
|
+
keyManager.setPreviousItemActive();
|
|
1425
|
+
break;
|
|
1426
|
+
case FocusNext.currentItem:
|
|
1427
|
+
if (keyManager.activeItem) {
|
|
1428
|
+
keyManager.setFocusOrigin('keyboard');
|
|
1429
|
+
keyManager.setActiveItem(keyManager.activeItem);
|
|
1430
|
+
}
|
|
1431
|
+
break;
|
|
1432
|
+
}
|
|
1433
|
+
}
|
|
1434
|
+
_subscribeToMenuStackEmptied() {
|
|
1435
|
+
this.menuStack.emptied.pipe(takeUntil(this.destroyed)).subscribe(event => this._toggleMenuFocus(event));
|
|
1436
|
+
}
|
|
1437
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
1438
|
+
minVersion: "12.0.0",
|
|
1439
|
+
version: "20.2.0-next.2",
|
|
1440
|
+
ngImport: i0,
|
|
1441
|
+
type: CdkMenu,
|
|
1442
|
+
deps: [],
|
|
1443
|
+
target: i0.ɵɵFactoryTarget.Directive
|
|
1444
|
+
});
|
|
1445
|
+
static ɵdir = i0.ɵɵngDeclareDirective({
|
|
1446
|
+
minVersion: "14.0.0",
|
|
1447
|
+
version: "20.2.0-next.2",
|
|
1448
|
+
type: CdkMenu,
|
|
1449
|
+
isStandalone: true,
|
|
1450
|
+
selector: "[cdkMenu]",
|
|
1451
|
+
outputs: {
|
|
1452
|
+
closed: "closed"
|
|
1453
|
+
},
|
|
1454
|
+
host: {
|
|
1455
|
+
attributes: {
|
|
1456
|
+
"role": "menu"
|
|
1457
|
+
},
|
|
1458
|
+
listeners: {
|
|
1459
|
+
"keydown": "_handleKeyEvent($event)"
|
|
1460
|
+
},
|
|
1461
|
+
properties: {
|
|
1462
|
+
"class.cdk-menu-inline": "isInline"
|
|
1463
|
+
},
|
|
1464
|
+
classAttribute: "cdk-menu"
|
|
1465
|
+
},
|
|
1466
|
+
providers: [{
|
|
1467
|
+
provide: CdkMenuGroup,
|
|
1468
|
+
useExisting: CdkMenu
|
|
1469
|
+
}, {
|
|
1470
|
+
provide: CDK_MENU,
|
|
1471
|
+
useExisting: CdkMenu
|
|
1472
|
+
}, PARENT_OR_NEW_INLINE_MENU_STACK_PROVIDER('vertical')],
|
|
1473
|
+
exportAs: ["cdkMenu"],
|
|
1474
|
+
usesInheritance: true,
|
|
1475
|
+
ngImport: i0
|
|
1476
|
+
});
|
|
1518
1477
|
}
|
|
1519
|
-
i0.ɵɵngDeclareClassMetadata({
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1478
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
1479
|
+
minVersion: "12.0.0",
|
|
1480
|
+
version: "20.2.0-next.2",
|
|
1481
|
+
ngImport: i0,
|
|
1482
|
+
type: CdkMenu,
|
|
1483
|
+
decorators: [{
|
|
1484
|
+
type: Directive,
|
|
1485
|
+
args: [{
|
|
1486
|
+
selector: '[cdkMenu]',
|
|
1487
|
+
exportAs: 'cdkMenu',
|
|
1488
|
+
host: {
|
|
1489
|
+
'role': 'menu',
|
|
1490
|
+
'class': 'cdk-menu',
|
|
1491
|
+
'[class.cdk-menu-inline]': 'isInline',
|
|
1492
|
+
'(keydown)': '_handleKeyEvent($event)'
|
|
1493
|
+
},
|
|
1494
|
+
providers: [{
|
|
1495
|
+
provide: CdkMenuGroup,
|
|
1496
|
+
useExisting: CdkMenu
|
|
1497
|
+
}, {
|
|
1498
|
+
provide: CDK_MENU,
|
|
1499
|
+
useExisting: CdkMenu
|
|
1500
|
+
}, PARENT_OR_NEW_INLINE_MENU_STACK_PROVIDER('vertical')]
|
|
1501
|
+
}]
|
|
1502
|
+
}],
|
|
1503
|
+
ctorParameters: () => [],
|
|
1504
|
+
propDecorators: {
|
|
1505
|
+
closed: [{
|
|
1506
|
+
type: Output
|
|
1507
|
+
}]
|
|
1508
|
+
}
|
|
1509
|
+
});
|
|
1539
1510
|
|
|
1540
|
-
/**
|
|
1541
|
-
* Directive applied to an element which configures it as a MenuBar by setting the appropriate
|
|
1542
|
-
* role, aria attributes, and accessible keyboard and mouse handling logic. The component that
|
|
1543
|
-
* this directive is applied to should contain components marked with CdkMenuItem.
|
|
1544
|
-
*
|
|
1545
|
-
*/
|
|
1546
1511
|
class CdkMenuBar extends CdkMenuBase {
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
event.preventDefault();
|
|
1573
|
-
const prevIsOpen = keyManager.activeItem?.isMenuOpen();
|
|
1574
|
-
keyManager.activeItem?.getMenuTrigger()?.close();
|
|
1575
|
-
keyManager.setFocusOrigin('keyboard');
|
|
1576
|
-
keyManager.onKeydown(event);
|
|
1577
|
-
if (prevIsOpen) {
|
|
1578
|
-
keyManager.activeItem?.getMenuTrigger()?.open();
|
|
1579
|
-
}
|
|
1580
|
-
}
|
|
1581
|
-
}
|
|
1582
|
-
break;
|
|
1583
|
-
case ESCAPE:
|
|
1584
|
-
if (!hasModifierKey(event)) {
|
|
1585
|
-
event.preventDefault();
|
|
1586
|
-
keyManager.activeItem?.getMenuTrigger()?.close();
|
|
1587
|
-
}
|
|
1588
|
-
break;
|
|
1589
|
-
case TAB:
|
|
1590
|
-
if (!hasModifierKey(event, 'altKey', 'metaKey', 'ctrlKey')) {
|
|
1591
|
-
keyManager.activeItem?.getMenuTrigger()?.close();
|
|
1592
|
-
}
|
|
1593
|
-
break;
|
|
1594
|
-
default:
|
|
1595
|
-
keyManager.onKeydown(event);
|
|
1512
|
+
orientation = 'horizontal';
|
|
1513
|
+
isInline = true;
|
|
1514
|
+
ngAfterContentInit() {
|
|
1515
|
+
super.ngAfterContentInit();
|
|
1516
|
+
this._subscribeToMenuStackEmptied();
|
|
1517
|
+
}
|
|
1518
|
+
_handleKeyEvent(event) {
|
|
1519
|
+
const keyManager = this.keyManager;
|
|
1520
|
+
switch (event.keyCode) {
|
|
1521
|
+
case UP_ARROW:
|
|
1522
|
+
case DOWN_ARROW:
|
|
1523
|
+
case LEFT_ARROW:
|
|
1524
|
+
case RIGHT_ARROW:
|
|
1525
|
+
if (!hasModifierKey(event)) {
|
|
1526
|
+
const horizontalArrows = event.keyCode === LEFT_ARROW || event.keyCode === RIGHT_ARROW;
|
|
1527
|
+
if (horizontalArrows) {
|
|
1528
|
+
event.preventDefault();
|
|
1529
|
+
const prevIsOpen = keyManager.activeItem?.isMenuOpen();
|
|
1530
|
+
keyManager.activeItem?.getMenuTrigger()?.close();
|
|
1531
|
+
keyManager.setFocusOrigin('keyboard');
|
|
1532
|
+
keyManager.onKeydown(event);
|
|
1533
|
+
if (prevIsOpen) {
|
|
1534
|
+
keyManager.activeItem?.getMenuTrigger()?.open();
|
|
1535
|
+
}
|
|
1536
|
+
}
|
|
1596
1537
|
}
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
*/
|
|
1603
|
-
_toggleOpenMenu(focusNext) {
|
|
1604
|
-
const keyManager = this.keyManager;
|
|
1605
|
-
switch (focusNext) {
|
|
1606
|
-
case FocusNext.nextItem:
|
|
1607
|
-
keyManager.setFocusOrigin('keyboard');
|
|
1608
|
-
keyManager.setNextItemActive();
|
|
1609
|
-
keyManager.activeItem?.getMenuTrigger()?.open();
|
|
1610
|
-
break;
|
|
1611
|
-
case FocusNext.previousItem:
|
|
1612
|
-
keyManager.setFocusOrigin('keyboard');
|
|
1613
|
-
keyManager.setPreviousItemActive();
|
|
1614
|
-
keyManager.activeItem?.getMenuTrigger()?.open();
|
|
1615
|
-
break;
|
|
1616
|
-
case FocusNext.currentItem:
|
|
1617
|
-
if (keyManager.activeItem) {
|
|
1618
|
-
keyManager.setFocusOrigin('keyboard');
|
|
1619
|
-
keyManager.setActiveItem(keyManager.activeItem);
|
|
1620
|
-
}
|
|
1621
|
-
break;
|
|
1538
|
+
break;
|
|
1539
|
+
case ESCAPE:
|
|
1540
|
+
if (!hasModifierKey(event)) {
|
|
1541
|
+
event.preventDefault();
|
|
1542
|
+
keyManager.activeItem?.getMenuTrigger()?.close();
|
|
1622
1543
|
}
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1544
|
+
break;
|
|
1545
|
+
case TAB:
|
|
1546
|
+
if (!hasModifierKey(event, 'altKey', 'metaKey', 'ctrlKey')) {
|
|
1547
|
+
keyManager.activeItem?.getMenuTrigger()?.close();
|
|
1548
|
+
}
|
|
1549
|
+
break;
|
|
1550
|
+
default:
|
|
1551
|
+
keyManager.onKeydown(event);
|
|
1552
|
+
}
|
|
1553
|
+
}
|
|
1554
|
+
_toggleOpenMenu(focusNext) {
|
|
1555
|
+
const keyManager = this.keyManager;
|
|
1556
|
+
switch (focusNext) {
|
|
1557
|
+
case FocusNext.nextItem:
|
|
1558
|
+
keyManager.setFocusOrigin('keyboard');
|
|
1559
|
+
keyManager.setNextItemActive();
|
|
1560
|
+
keyManager.activeItem?.getMenuTrigger()?.open();
|
|
1561
|
+
break;
|
|
1562
|
+
case FocusNext.previousItem:
|
|
1563
|
+
keyManager.setFocusOrigin('keyboard');
|
|
1564
|
+
keyManager.setPreviousItemActive();
|
|
1565
|
+
keyManager.activeItem?.getMenuTrigger()?.open();
|
|
1566
|
+
break;
|
|
1567
|
+
case FocusNext.currentItem:
|
|
1568
|
+
if (keyManager.activeItem) {
|
|
1569
|
+
keyManager.setFocusOrigin('keyboard');
|
|
1570
|
+
keyManager.setActiveItem(keyManager.activeItem);
|
|
1571
|
+
}
|
|
1572
|
+
break;
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1575
|
+
_subscribeToMenuStackEmptied() {
|
|
1576
|
+
this.menuStack?.emptied.pipe(takeUntil(this.destroyed)).subscribe(event => this._toggleOpenMenu(event));
|
|
1577
|
+
}
|
|
1578
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
1579
|
+
minVersion: "12.0.0",
|
|
1580
|
+
version: "20.2.0-next.2",
|
|
1581
|
+
ngImport: i0,
|
|
1582
|
+
type: CdkMenuBar,
|
|
1583
|
+
deps: null,
|
|
1584
|
+
target: i0.ɵɵFactoryTarget.Directive
|
|
1585
|
+
});
|
|
1586
|
+
static ɵdir = i0.ɵɵngDeclareDirective({
|
|
1587
|
+
minVersion: "14.0.0",
|
|
1588
|
+
version: "20.2.0-next.2",
|
|
1589
|
+
type: CdkMenuBar,
|
|
1590
|
+
isStandalone: true,
|
|
1591
|
+
selector: "[cdkMenuBar]",
|
|
1592
|
+
host: {
|
|
1593
|
+
attributes: {
|
|
1594
|
+
"role": "menubar"
|
|
1595
|
+
},
|
|
1596
|
+
listeners: {
|
|
1597
|
+
"keydown": "_handleKeyEvent($event)"
|
|
1598
|
+
},
|
|
1599
|
+
classAttribute: "cdk-menu-bar"
|
|
1600
|
+
},
|
|
1601
|
+
providers: [{
|
|
1602
|
+
provide: CdkMenuGroup,
|
|
1603
|
+
useExisting: CdkMenuBar
|
|
1604
|
+
}, {
|
|
1605
|
+
provide: CDK_MENU,
|
|
1606
|
+
useExisting: CdkMenuBar
|
|
1607
|
+
}, {
|
|
1608
|
+
provide: MENU_STACK,
|
|
1609
|
+
useFactory: () => MenuStack.inline('horizontal')
|
|
1610
|
+
}],
|
|
1611
|
+
exportAs: ["cdkMenuBar"],
|
|
1612
|
+
usesInheritance: true,
|
|
1613
|
+
ngImport: i0
|
|
1614
|
+
});
|
|
1636
1615
|
}
|
|
1637
|
-
i0.ɵɵngDeclareClassMetadata({
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1616
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
1617
|
+
minVersion: "12.0.0",
|
|
1618
|
+
version: "20.2.0-next.2",
|
|
1619
|
+
ngImport: i0,
|
|
1620
|
+
type: CdkMenuBar,
|
|
1621
|
+
decorators: [{
|
|
1622
|
+
type: Directive,
|
|
1623
|
+
args: [{
|
|
1624
|
+
selector: '[cdkMenuBar]',
|
|
1625
|
+
exportAs: 'cdkMenuBar',
|
|
1626
|
+
host: {
|
|
1627
|
+
'role': 'menubar',
|
|
1628
|
+
'class': 'cdk-menu-bar',
|
|
1629
|
+
'(keydown)': '_handleKeyEvent($event)'
|
|
1630
|
+
},
|
|
1631
|
+
providers: [{
|
|
1632
|
+
provide: CdkMenuGroup,
|
|
1633
|
+
useExisting: CdkMenuBar
|
|
1634
|
+
}, {
|
|
1635
|
+
provide: CDK_MENU,
|
|
1636
|
+
useExisting: CdkMenuBar
|
|
1637
|
+
}, {
|
|
1638
|
+
provide: MENU_STACK,
|
|
1639
|
+
useFactory: () => MenuStack.inline('horizontal')
|
|
1640
|
+
}]
|
|
1641
|
+
}]
|
|
1642
|
+
}]
|
|
1643
|
+
});
|
|
1654
1644
|
|
|
1655
|
-
/** Base class providing checked state for selectable MenuItems. */
|
|
1656
1645
|
class CdkMenuItemSelectable extends CdkMenuItem {
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1646
|
+
checked = false;
|
|
1647
|
+
closeOnSpacebarTrigger = false;
|
|
1648
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
1649
|
+
minVersion: "12.0.0",
|
|
1650
|
+
version: "20.2.0-next.2",
|
|
1651
|
+
ngImport: i0,
|
|
1652
|
+
type: CdkMenuItemSelectable,
|
|
1653
|
+
deps: null,
|
|
1654
|
+
target: i0.ɵɵFactoryTarget.Directive
|
|
1655
|
+
});
|
|
1656
|
+
static ɵdir = i0.ɵɵngDeclareDirective({
|
|
1657
|
+
minVersion: "16.1.0",
|
|
1658
|
+
version: "20.2.0-next.2",
|
|
1659
|
+
type: CdkMenuItemSelectable,
|
|
1660
|
+
isStandalone: true,
|
|
1661
|
+
inputs: {
|
|
1662
|
+
checked: ["cdkMenuItemChecked", "checked", booleanAttribute]
|
|
1663
|
+
},
|
|
1664
|
+
host: {
|
|
1665
|
+
properties: {
|
|
1666
|
+
"attr.aria-checked": "!!checked",
|
|
1667
|
+
"attr.aria-disabled": "disabled || null"
|
|
1668
|
+
}
|
|
1669
|
+
},
|
|
1670
|
+
usesInheritance: true,
|
|
1671
|
+
ngImport: i0
|
|
1672
|
+
});
|
|
1663
1673
|
}
|
|
1664
|
-
i0.ɵɵngDeclareClassMetadata({
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1674
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
1675
|
+
minVersion: "12.0.0",
|
|
1676
|
+
version: "20.2.0-next.2",
|
|
1677
|
+
ngImport: i0,
|
|
1678
|
+
type: CdkMenuItemSelectable,
|
|
1679
|
+
decorators: [{
|
|
1680
|
+
type: Directive,
|
|
1681
|
+
args: [{
|
|
1682
|
+
host: {
|
|
1683
|
+
'[attr.aria-checked]': '!!checked',
|
|
1684
|
+
'[attr.aria-disabled]': 'disabled || null'
|
|
1685
|
+
}
|
|
1686
|
+
}]
|
|
1687
|
+
}],
|
|
1688
|
+
propDecorators: {
|
|
1689
|
+
checked: [{
|
|
1690
|
+
type: Input,
|
|
1691
|
+
args: [{
|
|
1692
|
+
alias: 'cdkMenuItemChecked',
|
|
1693
|
+
transform: booleanAttribute
|
|
1694
|
+
}]
|
|
1695
|
+
}]
|
|
1696
|
+
}
|
|
1697
|
+
});
|
|
1676
1698
|
|
|
1677
|
-
/**
|
|
1678
|
-
* A directive providing behavior for the "menuitemradio" ARIA role, which behaves similarly to
|
|
1679
|
-
* a conventional radio-button. Any sibling `CdkMenuItemRadio` instances within the same `CdkMenu`
|
|
1680
|
-
* or `CdkMenuGroup` comprise a radio group with unique selection enforced.
|
|
1681
|
-
*/
|
|
1682
1699
|
class CdkMenuItemRadio extends CdkMenuItemSelectable {
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1700
|
+
_selectionDispatcher = inject(UniqueSelectionDispatcher);
|
|
1701
|
+
_id = inject(_IdGenerator).getId('cdk-menu-item-radio-');
|
|
1702
|
+
_removeDispatcherListener;
|
|
1703
|
+
constructor() {
|
|
1704
|
+
super();
|
|
1705
|
+
this._registerDispatcherListener();
|
|
1706
|
+
}
|
|
1707
|
+
ngOnDestroy() {
|
|
1708
|
+
super.ngOnDestroy();
|
|
1709
|
+
this._removeDispatcherListener();
|
|
1710
|
+
}
|
|
1711
|
+
trigger(options) {
|
|
1712
|
+
super.trigger(options);
|
|
1713
|
+
if (!this.disabled) {
|
|
1714
|
+
this._selectionDispatcher.notify(this._id, '');
|
|
1715
|
+
}
|
|
1716
|
+
}
|
|
1717
|
+
_registerDispatcherListener() {
|
|
1718
|
+
this._removeDispatcherListener = this._selectionDispatcher.listen(id => {
|
|
1719
|
+
this.checked = this._id === id;
|
|
1720
|
+
});
|
|
1721
|
+
}
|
|
1722
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
1723
|
+
minVersion: "12.0.0",
|
|
1724
|
+
version: "20.2.0-next.2",
|
|
1725
|
+
ngImport: i0,
|
|
1726
|
+
type: CdkMenuItemRadio,
|
|
1727
|
+
deps: [],
|
|
1728
|
+
target: i0.ɵɵFactoryTarget.Directive
|
|
1729
|
+
});
|
|
1730
|
+
static ɵdir = i0.ɵɵngDeclareDirective({
|
|
1731
|
+
minVersion: "14.0.0",
|
|
1732
|
+
version: "20.2.0-next.2",
|
|
1733
|
+
type: CdkMenuItemRadio,
|
|
1734
|
+
isStandalone: true,
|
|
1735
|
+
selector: "[cdkMenuItemRadio]",
|
|
1736
|
+
host: {
|
|
1737
|
+
attributes: {
|
|
1738
|
+
"role": "menuitemradio"
|
|
1739
|
+
},
|
|
1740
|
+
properties: {
|
|
1741
|
+
"class.cdk-menu-item-radio": "true"
|
|
1742
|
+
}
|
|
1743
|
+
},
|
|
1744
|
+
providers: [{
|
|
1745
|
+
provide: CdkMenuItemSelectable,
|
|
1746
|
+
useExisting: CdkMenuItemRadio
|
|
1747
|
+
}, {
|
|
1748
|
+
provide: CdkMenuItem,
|
|
1749
|
+
useExisting: CdkMenuItemSelectable
|
|
1750
|
+
}],
|
|
1751
|
+
exportAs: ["cdkMenuItemRadio"],
|
|
1752
|
+
usesInheritance: true,
|
|
1753
|
+
ngImport: i0
|
|
1754
|
+
});
|
|
1719
1755
|
}
|
|
1720
|
-
i0.ɵɵngDeclareClassMetadata({
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1756
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
1757
|
+
minVersion: "12.0.0",
|
|
1758
|
+
version: "20.2.0-next.2",
|
|
1759
|
+
ngImport: i0,
|
|
1760
|
+
type: CdkMenuItemRadio,
|
|
1761
|
+
decorators: [{
|
|
1762
|
+
type: Directive,
|
|
1763
|
+
args: [{
|
|
1764
|
+
selector: '[cdkMenuItemRadio]',
|
|
1765
|
+
exportAs: 'cdkMenuItemRadio',
|
|
1766
|
+
host: {
|
|
1767
|
+
'role': 'menuitemradio',
|
|
1768
|
+
'[class.cdk-menu-item-radio]': 'true'
|
|
1769
|
+
},
|
|
1770
|
+
providers: [{
|
|
1771
|
+
provide: CdkMenuItemSelectable,
|
|
1772
|
+
useExisting: CdkMenuItemRadio
|
|
1773
|
+
}, {
|
|
1774
|
+
provide: CdkMenuItem,
|
|
1775
|
+
useExisting: CdkMenuItemSelectable
|
|
1776
|
+
}]
|
|
1777
|
+
}]
|
|
1778
|
+
}],
|
|
1779
|
+
ctorParameters: () => []
|
|
1780
|
+
});
|
|
1735
1781
|
|
|
1736
|
-
/**
|
|
1737
|
-
* A directive providing behavior for the "menuitemcheckbox" ARIA role, which behaves similarly to a
|
|
1738
|
-
* conventional checkbox.
|
|
1739
|
-
*/
|
|
1740
1782
|
class CdkMenuItemCheckbox extends CdkMenuItemSelectable {
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1783
|
+
trigger(options) {
|
|
1784
|
+
super.trigger(options);
|
|
1785
|
+
if (!this.disabled) {
|
|
1786
|
+
this.checked = !this.checked;
|
|
1787
|
+
}
|
|
1788
|
+
}
|
|
1789
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
1790
|
+
minVersion: "12.0.0",
|
|
1791
|
+
version: "20.2.0-next.2",
|
|
1792
|
+
ngImport: i0,
|
|
1793
|
+
type: CdkMenuItemCheckbox,
|
|
1794
|
+
deps: null,
|
|
1795
|
+
target: i0.ɵɵFactoryTarget.Directive
|
|
1796
|
+
});
|
|
1797
|
+
static ɵdir = i0.ɵɵngDeclareDirective({
|
|
1798
|
+
minVersion: "14.0.0",
|
|
1799
|
+
version: "20.2.0-next.2",
|
|
1800
|
+
type: CdkMenuItemCheckbox,
|
|
1801
|
+
isStandalone: true,
|
|
1802
|
+
selector: "[cdkMenuItemCheckbox]",
|
|
1803
|
+
host: {
|
|
1804
|
+
attributes: {
|
|
1805
|
+
"role": "menuitemcheckbox"
|
|
1806
|
+
},
|
|
1807
|
+
properties: {
|
|
1808
|
+
"class.cdk-menu-item-checkbox": "true"
|
|
1809
|
+
}
|
|
1810
|
+
},
|
|
1811
|
+
providers: [{
|
|
1812
|
+
provide: CdkMenuItemSelectable,
|
|
1813
|
+
useExisting: CdkMenuItemCheckbox
|
|
1814
|
+
}, {
|
|
1815
|
+
provide: CdkMenuItem,
|
|
1816
|
+
useExisting: CdkMenuItemSelectable
|
|
1817
|
+
}],
|
|
1818
|
+
exportAs: ["cdkMenuItemCheckbox"],
|
|
1819
|
+
usesInheritance: true,
|
|
1820
|
+
ngImport: i0
|
|
1821
|
+
});
|
|
1757
1822
|
}
|
|
1758
|
-
i0.ɵɵngDeclareClassMetadata({
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1823
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
1824
|
+
minVersion: "12.0.0",
|
|
1825
|
+
version: "20.2.0-next.2",
|
|
1826
|
+
ngImport: i0,
|
|
1827
|
+
type: CdkMenuItemCheckbox,
|
|
1828
|
+
decorators: [{
|
|
1829
|
+
type: Directive,
|
|
1830
|
+
args: [{
|
|
1831
|
+
selector: '[cdkMenuItemCheckbox]',
|
|
1832
|
+
exportAs: 'cdkMenuItemCheckbox',
|
|
1833
|
+
host: {
|
|
1834
|
+
'role': 'menuitemcheckbox',
|
|
1835
|
+
'[class.cdk-menu-item-checkbox]': 'true'
|
|
1836
|
+
},
|
|
1837
|
+
providers: [{
|
|
1838
|
+
provide: CdkMenuItemSelectable,
|
|
1839
|
+
useExisting: CdkMenuItemCheckbox
|
|
1840
|
+
}, {
|
|
1841
|
+
provide: CdkMenuItem,
|
|
1842
|
+
useExisting: CdkMenuItemSelectable
|
|
1843
|
+
}]
|
|
1844
|
+
}]
|
|
1845
|
+
}]
|
|
1846
|
+
});
|
|
1773
1847
|
|
|
1774
|
-
/** The preferred menu positions for the context menu. */
|
|
1775
1848
|
const CONTEXT_MENU_POSITIONS = STANDARD_DROPDOWN_BELOW_POSITIONS.map(position => {
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1849
|
+
const offsetX = position.overlayX === 'start' ? 2 : -2;
|
|
1850
|
+
const offsetY = position.overlayY === 'top' ? 2 : -2;
|
|
1851
|
+
return {
|
|
1852
|
+
...position,
|
|
1853
|
+
offsetX,
|
|
1854
|
+
offsetY
|
|
1855
|
+
};
|
|
1781
1856
|
});
|
|
1782
|
-
/**
|
|
1783
|
-
* A directive that opens a menu when a user right-clicks within its host element.
|
|
1784
|
-
* It is aware of nested context menus and will trigger only the lowest level non-disabled context menu.
|
|
1785
|
-
*/
|
|
1786
1857
|
class CdkContextMenuTrigger extends CdkMenuTriggerBase {
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1858
|
+
_injector = inject(Injector);
|
|
1859
|
+
_directionality = inject(Directionality, {
|
|
1860
|
+
optional: true
|
|
1861
|
+
});
|
|
1862
|
+
_menuTracker = inject(MenuTracker);
|
|
1863
|
+
_changeDetectorRef = inject(ChangeDetectorRef);
|
|
1864
|
+
disabled = false;
|
|
1865
|
+
constructor() {
|
|
1866
|
+
super();
|
|
1867
|
+
this._setMenuStackCloseListener();
|
|
1868
|
+
}
|
|
1869
|
+
open(coordinates) {
|
|
1870
|
+
this._open(null, coordinates);
|
|
1871
|
+
this._changeDetectorRef.markForCheck();
|
|
1872
|
+
}
|
|
1873
|
+
close() {
|
|
1874
|
+
this.menuStack.closeAll();
|
|
1875
|
+
}
|
|
1876
|
+
_openOnContextMenu(event) {
|
|
1877
|
+
if (!this.disabled) {
|
|
1878
|
+
event.preventDefault();
|
|
1879
|
+
event.stopPropagation();
|
|
1880
|
+
this._menuTracker.update(this);
|
|
1881
|
+
this._open(event, {
|
|
1882
|
+
x: event.clientX,
|
|
1883
|
+
y: event.clientY
|
|
1884
|
+
});
|
|
1885
|
+
if (event.button === 2) {
|
|
1886
|
+
this.childMenu?.focusFirstItem('mouse');
|
|
1887
|
+
} else if (event.button === 0) {
|
|
1888
|
+
this.childMenu?.focusFirstItem('keyboard');
|
|
1889
|
+
} else {
|
|
1890
|
+
this.childMenu?.focusFirstItem('program');
|
|
1891
|
+
}
|
|
1892
|
+
}
|
|
1893
|
+
}
|
|
1894
|
+
_getOverlayConfig(coordinates) {
|
|
1895
|
+
return new OverlayConfig({
|
|
1896
|
+
positionStrategy: this._getOverlayPositionStrategy(coordinates),
|
|
1897
|
+
scrollStrategy: this.menuScrollStrategy(),
|
|
1898
|
+
direction: this._directionality || undefined
|
|
1899
|
+
});
|
|
1900
|
+
}
|
|
1901
|
+
_getOverlayPositionStrategy(coordinates) {
|
|
1902
|
+
return createFlexibleConnectedPositionStrategy(this._injector, coordinates).withLockedPosition().withGrowAfterOpen().withPositions(this.menuPosition ?? CONTEXT_MENU_POSITIONS);
|
|
1903
|
+
}
|
|
1904
|
+
_setMenuStackCloseListener() {
|
|
1905
|
+
this.menuStack.closed.pipe(takeUntil(this.destroyed)).subscribe(({
|
|
1906
|
+
item
|
|
1907
|
+
}) => {
|
|
1908
|
+
if (item === this.childMenu && this.isOpen()) {
|
|
1909
|
+
this.closed.next();
|
|
1910
|
+
this.overlayRef.detach();
|
|
1911
|
+
this.childMenu = undefined;
|
|
1804
1912
|
this._changeDetectorRef.markForCheck();
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
// resulting in multiple stacked context menus being displayed.
|
|
1821
|
-
event.stopPropagation();
|
|
1822
|
-
this._menuTracker.update(this);
|
|
1823
|
-
this._open(event, { x: event.clientX, y: event.clientY });
|
|
1824
|
-
// A context menu can be triggered via a mouse right click or a keyboard shortcut.
|
|
1825
|
-
if (event.button === 2) {
|
|
1826
|
-
this.childMenu?.focusFirstItem('mouse');
|
|
1827
|
-
}
|
|
1828
|
-
else if (event.button === 0) {
|
|
1829
|
-
this.childMenu?.focusFirstItem('keyboard');
|
|
1830
|
-
}
|
|
1831
|
-
else {
|
|
1832
|
-
this.childMenu?.focusFirstItem('program');
|
|
1833
|
-
}
|
|
1913
|
+
}
|
|
1914
|
+
});
|
|
1915
|
+
}
|
|
1916
|
+
_subscribeToOutsideClicks(userEvent) {
|
|
1917
|
+
if (this.overlayRef) {
|
|
1918
|
+
let outsideClicks = this.overlayRef.outsidePointerEvents();
|
|
1919
|
+
if (userEvent) {
|
|
1920
|
+
const [auxClicks, nonAuxClicks] = partition(outsideClicks, ({
|
|
1921
|
+
type
|
|
1922
|
+
}) => type === 'auxclick');
|
|
1923
|
+
outsideClicks = merge(nonAuxClicks.pipe(skipWhile((event, index) => userEvent.ctrlKey && index === 0 && event.ctrlKey)), auxClicks.pipe(skip(1)));
|
|
1924
|
+
}
|
|
1925
|
+
outsideClicks.pipe(takeUntil(this.stopOutsideClicksListener)).subscribe(event => {
|
|
1926
|
+
if (!this.isElementInsideMenuStack(_getEventTarget(event))) {
|
|
1927
|
+
this.menuStack.closeAll();
|
|
1834
1928
|
}
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
}
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
}
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
}
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
*/
|
|
1902
|
-
_open(userEvent, coordinates) {
|
|
1903
|
-
if (this.disabled) {
|
|
1904
|
-
return;
|
|
1905
|
-
}
|
|
1906
|
-
if (this.isOpen()) {
|
|
1907
|
-
// since we're moving this menu we need to close any submenus first otherwise they end up
|
|
1908
|
-
// disconnected from this one.
|
|
1909
|
-
this.menuStack.closeSubMenuOf(this.childMenu);
|
|
1910
|
-
this.overlayRef.getConfig().positionStrategy.setOrigin(coordinates);
|
|
1911
|
-
this.overlayRef.updatePosition();
|
|
1912
|
-
}
|
|
1913
|
-
else {
|
|
1914
|
-
this.opened.next();
|
|
1915
|
-
if (this.overlayRef) {
|
|
1916
|
-
this.overlayRef.getConfig().positionStrategy.setOrigin(coordinates);
|
|
1917
|
-
this.overlayRef.updatePosition();
|
|
1918
|
-
}
|
|
1919
|
-
else {
|
|
1920
|
-
this.overlayRef = createOverlayRef(this._injector, this._getOverlayConfig(coordinates));
|
|
1921
|
-
}
|
|
1922
|
-
this.overlayRef.attach(this.getMenuContentPortal());
|
|
1923
|
-
this._subscribeToOutsideClicks(userEvent);
|
|
1924
|
-
}
|
|
1925
|
-
}
|
|
1926
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0-next.2", ngImport: i0, type: CdkContextMenuTrigger, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
1927
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "20.2.0-next.2", type: CdkContextMenuTrigger, isStandalone: true, selector: "[cdkContextMenuTriggerFor]", inputs: { menuTemplateRef: ["cdkContextMenuTriggerFor", "menuTemplateRef"], menuPosition: ["cdkContextMenuPosition", "menuPosition"], menuData: ["cdkContextMenuTriggerData", "menuData"], disabled: ["cdkContextMenuDisabled", "disabled", booleanAttribute] }, outputs: { opened: "cdkContextMenuOpened", closed: "cdkContextMenuClosed" }, host: { listeners: { "contextmenu": "_openOnContextMenu($event)" }, properties: { "attr.data-cdk-menu-stack-id": "null" } }, providers: [
|
|
1928
|
-
{ provide: MENU_TRIGGER, useExisting: CdkContextMenuTrigger },
|
|
1929
|
-
{ provide: MENU_STACK, useClass: MenuStack },
|
|
1930
|
-
], exportAs: ["cdkContextMenuTriggerFor"], usesInheritance: true, ngImport: i0 });
|
|
1929
|
+
});
|
|
1930
|
+
}
|
|
1931
|
+
}
|
|
1932
|
+
_open(userEvent, coordinates) {
|
|
1933
|
+
if (this.disabled) {
|
|
1934
|
+
return;
|
|
1935
|
+
}
|
|
1936
|
+
if (this.isOpen()) {
|
|
1937
|
+
this.menuStack.closeSubMenuOf(this.childMenu);
|
|
1938
|
+
this.overlayRef.getConfig().positionStrategy.setOrigin(coordinates);
|
|
1939
|
+
this.overlayRef.updatePosition();
|
|
1940
|
+
} else {
|
|
1941
|
+
this.opened.next();
|
|
1942
|
+
if (this.overlayRef) {
|
|
1943
|
+
this.overlayRef.getConfig().positionStrategy.setOrigin(coordinates);
|
|
1944
|
+
this.overlayRef.updatePosition();
|
|
1945
|
+
} else {
|
|
1946
|
+
this.overlayRef = createOverlayRef(this._injector, this._getOverlayConfig(coordinates));
|
|
1947
|
+
}
|
|
1948
|
+
this.overlayRef.attach(this.getMenuContentPortal());
|
|
1949
|
+
this._subscribeToOutsideClicks(userEvent);
|
|
1950
|
+
}
|
|
1951
|
+
}
|
|
1952
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
1953
|
+
minVersion: "12.0.0",
|
|
1954
|
+
version: "20.2.0-next.2",
|
|
1955
|
+
ngImport: i0,
|
|
1956
|
+
type: CdkContextMenuTrigger,
|
|
1957
|
+
deps: [],
|
|
1958
|
+
target: i0.ɵɵFactoryTarget.Directive
|
|
1959
|
+
});
|
|
1960
|
+
static ɵdir = i0.ɵɵngDeclareDirective({
|
|
1961
|
+
minVersion: "16.1.0",
|
|
1962
|
+
version: "20.2.0-next.2",
|
|
1963
|
+
type: CdkContextMenuTrigger,
|
|
1964
|
+
isStandalone: true,
|
|
1965
|
+
selector: "[cdkContextMenuTriggerFor]",
|
|
1966
|
+
inputs: {
|
|
1967
|
+
menuTemplateRef: ["cdkContextMenuTriggerFor", "menuTemplateRef"],
|
|
1968
|
+
menuPosition: ["cdkContextMenuPosition", "menuPosition"],
|
|
1969
|
+
menuData: ["cdkContextMenuTriggerData", "menuData"],
|
|
1970
|
+
disabled: ["cdkContextMenuDisabled", "disabled", booleanAttribute]
|
|
1971
|
+
},
|
|
1972
|
+
outputs: {
|
|
1973
|
+
opened: "cdkContextMenuOpened",
|
|
1974
|
+
closed: "cdkContextMenuClosed"
|
|
1975
|
+
},
|
|
1976
|
+
host: {
|
|
1977
|
+
listeners: {
|
|
1978
|
+
"contextmenu": "_openOnContextMenu($event)"
|
|
1979
|
+
},
|
|
1980
|
+
properties: {
|
|
1981
|
+
"attr.data-cdk-menu-stack-id": "null"
|
|
1982
|
+
}
|
|
1983
|
+
},
|
|
1984
|
+
providers: [{
|
|
1985
|
+
provide: MENU_TRIGGER,
|
|
1986
|
+
useExisting: CdkContextMenuTrigger
|
|
1987
|
+
}, {
|
|
1988
|
+
provide: MENU_STACK,
|
|
1989
|
+
useClass: MenuStack
|
|
1990
|
+
}],
|
|
1991
|
+
exportAs: ["cdkContextMenuTriggerFor"],
|
|
1992
|
+
usesInheritance: true,
|
|
1993
|
+
ngImport: i0
|
|
1994
|
+
});
|
|
1931
1995
|
}
|
|
1932
|
-
i0.ɵɵngDeclareClassMetadata({
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1996
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
1997
|
+
minVersion: "12.0.0",
|
|
1998
|
+
version: "20.2.0-next.2",
|
|
1999
|
+
ngImport: i0,
|
|
2000
|
+
type: CdkContextMenuTrigger,
|
|
2001
|
+
decorators: [{
|
|
2002
|
+
type: Directive,
|
|
2003
|
+
args: [{
|
|
2004
|
+
selector: '[cdkContextMenuTriggerFor]',
|
|
2005
|
+
exportAs: 'cdkContextMenuTriggerFor',
|
|
2006
|
+
host: {
|
|
2007
|
+
'[attr.data-cdk-menu-stack-id]': 'null',
|
|
2008
|
+
'(contextmenu)': '_openOnContextMenu($event)'
|
|
2009
|
+
},
|
|
2010
|
+
inputs: [{
|
|
2011
|
+
name: 'menuTemplateRef',
|
|
2012
|
+
alias: 'cdkContextMenuTriggerFor'
|
|
2013
|
+
}, {
|
|
2014
|
+
name: 'menuPosition',
|
|
2015
|
+
alias: 'cdkContextMenuPosition'
|
|
2016
|
+
}, {
|
|
2017
|
+
name: 'menuData',
|
|
2018
|
+
alias: 'cdkContextMenuTriggerData'
|
|
2019
|
+
}],
|
|
2020
|
+
outputs: ['opened: cdkContextMenuOpened', 'closed: cdkContextMenuClosed'],
|
|
2021
|
+
providers: [{
|
|
2022
|
+
provide: MENU_TRIGGER,
|
|
2023
|
+
useExisting: CdkContextMenuTrigger
|
|
2024
|
+
}, {
|
|
2025
|
+
provide: MENU_STACK,
|
|
2026
|
+
useClass: MenuStack
|
|
2027
|
+
}]
|
|
2028
|
+
}]
|
|
2029
|
+
}],
|
|
2030
|
+
ctorParameters: () => [],
|
|
2031
|
+
propDecorators: {
|
|
2032
|
+
disabled: [{
|
|
2033
|
+
type: Input,
|
|
2034
|
+
args: [{
|
|
2035
|
+
alias: 'cdkContextMenuDisabled',
|
|
2036
|
+
transform: booleanAttribute
|
|
2037
|
+
}]
|
|
2038
|
+
}]
|
|
2039
|
+
}
|
|
2040
|
+
});
|
|
1956
2041
|
|
|
1957
|
-
const MENU_DIRECTIVES = [
|
|
1958
|
-
CdkMenuBar,
|
|
1959
|
-
CdkMenu,
|
|
1960
|
-
CdkMenuItem,
|
|
1961
|
-
CdkMenuItemRadio,
|
|
1962
|
-
CdkMenuItemCheckbox,
|
|
1963
|
-
CdkMenuTrigger,
|
|
1964
|
-
CdkMenuGroup,
|
|
1965
|
-
CdkContextMenuTrigger,
|
|
1966
|
-
CdkTargetMenuAim,
|
|
1967
|
-
];
|
|
1968
|
-
/** Module that declares components and directives for the CDK menu. */
|
|
2042
|
+
const MENU_DIRECTIVES = [CdkMenuBar, CdkMenu, CdkMenuItem, CdkMenuItemRadio, CdkMenuItemCheckbox, CdkMenuTrigger, CdkMenuGroup, CdkContextMenuTrigger, CdkTargetMenuAim];
|
|
1969
2043
|
class CdkMenuModule {
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
2044
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
2045
|
+
minVersion: "12.0.0",
|
|
2046
|
+
version: "20.2.0-next.2",
|
|
2047
|
+
ngImport: i0,
|
|
2048
|
+
type: CdkMenuModule,
|
|
2049
|
+
deps: [],
|
|
2050
|
+
target: i0.ɵɵFactoryTarget.NgModule
|
|
2051
|
+
});
|
|
2052
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({
|
|
2053
|
+
minVersion: "14.0.0",
|
|
2054
|
+
version: "20.2.0-next.2",
|
|
2055
|
+
ngImport: i0,
|
|
2056
|
+
type: CdkMenuModule,
|
|
2057
|
+
imports: [OverlayModule, CdkMenuBar, CdkMenu, CdkMenuItem, CdkMenuItemRadio, CdkMenuItemCheckbox, CdkMenuTrigger, CdkMenuGroup, CdkContextMenuTrigger, CdkTargetMenuAim],
|
|
2058
|
+
exports: [CdkMenuBar, CdkMenu, CdkMenuItem, CdkMenuItemRadio, CdkMenuItemCheckbox, CdkMenuTrigger, CdkMenuGroup, CdkContextMenuTrigger, CdkTargetMenuAim]
|
|
2059
|
+
});
|
|
2060
|
+
static ɵinj = i0.ɵɵngDeclareInjector({
|
|
2061
|
+
minVersion: "12.0.0",
|
|
2062
|
+
version: "20.2.0-next.2",
|
|
2063
|
+
ngImport: i0,
|
|
2064
|
+
type: CdkMenuModule,
|
|
2065
|
+
imports: [OverlayModule]
|
|
2066
|
+
});
|
|
1989
2067
|
}
|
|
1990
|
-
i0.ɵɵngDeclareClassMetadata({
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
2068
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
2069
|
+
minVersion: "12.0.0",
|
|
2070
|
+
version: "20.2.0-next.2",
|
|
2071
|
+
ngImport: i0,
|
|
2072
|
+
type: CdkMenuModule,
|
|
2073
|
+
decorators: [{
|
|
2074
|
+
type: NgModule,
|
|
2075
|
+
args: [{
|
|
2076
|
+
imports: [OverlayModule, ...MENU_DIRECTIVES],
|
|
2077
|
+
exports: MENU_DIRECTIVES
|
|
2078
|
+
}]
|
|
2079
|
+
}]
|
|
2080
|
+
});
|
|
1997
2081
|
|
|
1998
2082
|
export { CDK_MENU, CdkContextMenuTrigger, CdkMenu, CdkMenuBar, CdkMenuBase, CdkMenuGroup, CdkMenuItem, CdkMenuItemCheckbox, CdkMenuItemRadio, CdkMenuItemSelectable, CdkMenuModule, CdkMenuTrigger, CdkMenuTriggerBase, CdkTargetMenuAim, MenuTracker as ContextMenuTracker, FocusNext, MENU_AIM, MENU_SCROLL_STRATEGY, MENU_STACK, MENU_TRIGGER, MenuStack, MenuTracker, PARENT_OR_NEW_INLINE_MENU_STACK_PROVIDER, PARENT_OR_NEW_MENU_STACK_PROVIDER, PointerFocusTracker, TargetMenuAim };
|
|
1999
2083
|
//# sourceMappingURL=menu.mjs.map
|