@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.
Files changed (124) hide show
  1. package/_adev_assets/cdk_drag_drop.json +13 -12
  2. package/_adev_assets/cdk_testing.json +9 -9
  3. package/_adev_assets/cdk_testing_protractor.json +1 -1
  4. package/_adev_assets/cdk_testing_selenium_webdriver.json +1 -1
  5. package/_adev_assets/cdk_testing_testbed.json +1 -1
  6. package/fesm2022/_a11y-module-chunk.mjs +755 -869
  7. package/fesm2022/_a11y-module-chunk.mjs.map +1 -1
  8. package/fesm2022/_activedescendant-key-manager-chunk.mjs +8 -8
  9. package/fesm2022/_activedescendant-key-manager-chunk.mjs.map +1 -1
  10. package/fesm2022/_array-chunk.mjs +1 -1
  11. package/fesm2022/_array-chunk.mjs.map +1 -1
  12. package/fesm2022/_breakpoints-observer-chunk.mjs +149 -152
  13. package/fesm2022/_breakpoints-observer-chunk.mjs.map +1 -1
  14. package/fesm2022/_css-pixel-value-chunk.mjs +4 -5
  15. package/fesm2022/_css-pixel-value-chunk.mjs.map +1 -1
  16. package/fesm2022/_data-source-chunk.mjs +2 -8
  17. package/fesm2022/_data-source-chunk.mjs.map +1 -1
  18. package/fesm2022/_directionality-chunk.mjs +54 -54
  19. package/fesm2022/_directionality-chunk.mjs.map +1 -1
  20. package/fesm2022/_dispose-view-repeater-strategy-chunk.mjs +25 -36
  21. package/fesm2022/_dispose-view-repeater-strategy-chunk.mjs.map +1 -1
  22. package/fesm2022/_element-chunk.mjs +6 -17
  23. package/fesm2022/_element-chunk.mjs.map +1 -1
  24. package/fesm2022/_fake-event-detection-chunk.mjs +3 -17
  25. package/fesm2022/_fake-event-detection-chunk.mjs.map +1 -1
  26. package/fesm2022/_focus-key-manager-chunk.mjs +10 -14
  27. package/fesm2022/_focus-key-manager-chunk.mjs.map +1 -1
  28. package/fesm2022/_focus-monitor-chunk.mjs +376 -566
  29. package/fesm2022/_focus-monitor-chunk.mjs.map +1 -1
  30. package/fesm2022/_id-generator-chunk.mjs +37 -27
  31. package/fesm2022/_id-generator-chunk.mjs.map +1 -1
  32. package/fesm2022/_keycodes-chunk.mjs +9 -9
  33. package/fesm2022/_keycodes-chunk.mjs.map +1 -1
  34. package/fesm2022/_list-key-manager-chunk.mjs +248 -336
  35. package/fesm2022/_list-key-manager-chunk.mjs.map +1 -1
  36. package/fesm2022/_overlay-module-chunk.mjs +2535 -2947
  37. package/fesm2022/_overlay-module-chunk.mjs.map +1 -1
  38. package/fesm2022/_passive-listeners-chunk.mjs +10 -22
  39. package/fesm2022/_passive-listeners-chunk.mjs.map +1 -1
  40. package/fesm2022/_platform-chunk.mjs +42 -65
  41. package/fesm2022/_platform-chunk.mjs.map +1 -1
  42. package/fesm2022/_recycle-view-repeater-strategy-chunk.mjs +78 -134
  43. package/fesm2022/_recycle-view-repeater-strategy-chunk.mjs.map +1 -1
  44. package/fesm2022/_scrolling-chunk.mjs +44 -85
  45. package/fesm2022/_scrolling-chunk.mjs.map +1 -1
  46. package/fesm2022/_selection-model-chunk.mjs +138 -209
  47. package/fesm2022/_selection-model-chunk.mjs.map +1 -1
  48. package/fesm2022/_shadow-dom-chunk.mjs +21 -35
  49. package/fesm2022/_shadow-dom-chunk.mjs.map +1 -1
  50. package/fesm2022/_style-loader-chunk.mjs +50 -37
  51. package/fesm2022/_style-loader-chunk.mjs.map +1 -1
  52. package/fesm2022/_test-environment-chunk.mjs +2 -14
  53. package/fesm2022/_test-environment-chunk.mjs.map +1 -1
  54. package/fesm2022/_tree-key-manager-chunk.mjs +229 -308
  55. package/fesm2022/_tree-key-manager-chunk.mjs.map +1 -1
  56. package/fesm2022/_typeahead-chunk.mjs +52 -74
  57. package/fesm2022/_typeahead-chunk.mjs.map +1 -1
  58. package/fesm2022/_unique-selection-dispatcher-chunk.mjs +43 -40
  59. package/fesm2022/_unique-selection-dispatcher-chunk.mjs.map +1 -1
  60. package/fesm2022/a11y.mjs +351 -449
  61. package/fesm2022/a11y.mjs.map +1 -1
  62. package/fesm2022/accordion.mjs +254 -192
  63. package/fesm2022/accordion.mjs.map +1 -1
  64. package/fesm2022/bidi.mjs +121 -64
  65. package/fesm2022/bidi.mjs.map +1 -1
  66. package/fesm2022/cdk.mjs +1 -2
  67. package/fesm2022/cdk.mjs.map +1 -1
  68. package/fesm2022/clipboard.mjs +208 -186
  69. package/fesm2022/clipboard.mjs.map +1 -1
  70. package/fesm2022/coercion-private.mjs +4 -8
  71. package/fesm2022/coercion-private.mjs.map +1 -1
  72. package/fesm2022/coercion.mjs +11 -29
  73. package/fesm2022/coercion.mjs.map +1 -1
  74. package/fesm2022/dialog.mjs +660 -808
  75. package/fesm2022/dialog.mjs.map +1 -1
  76. package/fesm2022/drag-drop.mjs +3347 -4286
  77. package/fesm2022/drag-drop.mjs.map +1 -1
  78. package/fesm2022/keycodes.mjs +4 -8
  79. package/fesm2022/keycodes.mjs.map +1 -1
  80. package/fesm2022/layout.mjs +44 -26
  81. package/fesm2022/layout.mjs.map +1 -1
  82. package/fesm2022/listbox.mjs +841 -895
  83. package/fesm2022/listbox.mjs.map +1 -1
  84. package/fesm2022/menu.mjs +1942 -1858
  85. package/fesm2022/menu.mjs.map +1 -1
  86. package/fesm2022/observers-private.mjs +88 -106
  87. package/fesm2022/observers-private.mjs.map +1 -1
  88. package/fesm2022/observers.mjs +262 -184
  89. package/fesm2022/observers.mjs.map +1 -1
  90. package/fesm2022/overlay.mjs +72 -68
  91. package/fesm2022/overlay.mjs.map +1 -1
  92. package/fesm2022/platform.mjs +43 -54
  93. package/fesm2022/platform.mjs.map +1 -1
  94. package/fesm2022/portal.mjs +402 -560
  95. package/fesm2022/portal.mjs.map +1 -1
  96. package/fesm2022/private.mjs +38 -10
  97. package/fesm2022/private.mjs.map +1 -1
  98. package/fesm2022/scrolling.mjs +1323 -1400
  99. package/fesm2022/scrolling.mjs.map +1 -1
  100. package/fesm2022/stepper.mjs +758 -590
  101. package/fesm2022/stepper.mjs.map +1 -1
  102. package/fesm2022/table.mjs +2327 -2319
  103. package/fesm2022/table.mjs.map +1 -1
  104. package/fesm2022/testing-selenium-webdriver.mjs +252 -325
  105. package/fesm2022/testing-selenium-webdriver.mjs.map +1 -1
  106. package/fesm2022/testing-testbed.mjs +592 -709
  107. package/fesm2022/testing-testbed.mjs.map +1 -1
  108. package/fesm2022/testing.mjs +368 -889
  109. package/fesm2022/testing.mjs.map +1 -1
  110. package/fesm2022/text-field.mjs +459 -388
  111. package/fesm2022/text-field.mjs.map +1 -1
  112. package/fesm2022/tree.mjs +1483 -1731
  113. package/fesm2022/tree.mjs.map +1 -1
  114. package/overlay/_index.scss +30 -0
  115. package/overlay-prebuilt.css +1 -1
  116. package/package.json +1 -1
  117. package/schematics/ng-add/index.js +1 -1
  118. package/types/_overlay-module-chunk.d.ts +69 -7
  119. package/types/_portal-directives-chunk.d.ts +2 -18
  120. package/types/a11y.d.ts +3 -1
  121. package/types/accordion.d.ts +3 -1
  122. package/types/dialog.d.ts +1 -1
  123. package/types/overlay.d.ts +1 -1
  124. 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
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0-next.2", ngImport: i0, type: CdkMenuGroup, deps: [], target: i0.ɵɵFactoryTarget.Directive });
37
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.2.0-next.2", type: CdkMenuGroup, isStandalone: true, selector: "[cdkMenuGroup]", host: { attributes: { "role": "group" }, classAttribute: "cdk-menu-group" }, providers: [{ provide: UniqueSelectionDispatcher, useClass: UniqueSelectionDispatcher }], exportAs: ["cdkMenuGroup"], ngImport: i0 });
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({ minVersion: "12.0.0", version: "20.2.0-next.2", ngImport: i0, type: CdkMenuGroup, decorators: [{
40
- type: Directive,
41
- args: [{
42
- selector: '[cdkMenuGroup]',
43
- exportAs: 'cdkMenuGroup',
44
- host: {
45
- 'role': 'group',
46
- 'class': 'cdk-menu-group',
47
- },
48
- providers: [{ provide: UniqueSelectionDispatcher, useClass: UniqueSelectionDispatcher }],
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
- FocusNext[FocusNext["nextItem"] = 0] = "nextItem";
59
- FocusNext[FocusNext["previousItem"] = 1] = "previousItem";
60
- FocusNext[FocusNext["currentItem"] = 2] = "currentItem";
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
- provide: MENU_STACK,
67
- useFactory: () => inject(MENU_STACK, { optional: true, skipSelf: true }) || new MenuStack(),
93
+ provide: MENU_STACK,
94
+ useFactory: () => inject(MENU_STACK, {
95
+ optional: true,
96
+ skipSelf: true
97
+ }) || new MenuStack()
68
98
  };
69
- /** Provider that provides the parent menu stack, or a new inline menu stack if there is no parent one. */
70
- const PARENT_OR_NEW_INLINE_MENU_STACK_PROVIDER = (orientation) => ({
71
- provide: MENU_STACK,
72
- useFactory: () => inject(MENU_STACK, { optional: true, skipSelf: true }) || MenuStack.inline(orientation),
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
- /** The ID of this menu stack. */
82
- id = inject(_IdGenerator).getId('cdk-menu-stack-');
83
- /** All MenuStackItems tracked by this MenuStack. */
84
- _elements = [];
85
- /** Emits the element which was popped off of the stack when requested by a closer. */
86
- _close = new Subject();
87
- /** Emits once the MenuStack has become empty after popping off elements. */
88
- _empty = new Subject();
89
- /** Emits whether any menu in the menu stack has focus. */
90
- _hasFocus = new Subject();
91
- /** Observable which emits the MenuStackItem which has been requested to close. */
92
- closed = this._close;
93
- /** Observable which emits whether any menu in the menu stack has focus. */
94
- hasFocus = this._hasFocus.pipe(startWith(false), debounceTime(0), distinctUntilChanged());
95
- /**
96
- * Observable which emits when the MenuStack is empty after popping off the last element. It
97
- * emits a FocusNext event which specifies the action the closer has requested the listener
98
- * perform.
99
- */
100
- emptied = this._empty;
101
- /**
102
- * Whether the inline menu associated with this menu stack is vertical or horizontal.
103
- * `null` indicates there is no inline menu associated with this menu stack.
104
- */
105
- _inlineMenuOrientation = null;
106
- /** Creates a menu stack that originates from an inline menu. */
107
- static inline(orientation) {
108
- const stack = new MenuStack();
109
- stack._inlineMenuOrientation = orientation;
110
- return stack;
111
- }
112
- /**
113
- * Adds an item to the menu stack.
114
- * @param menu the MenuStackItem to put on the stack.
115
- */
116
- push(menu) {
117
- this._elements.push(menu);
118
- }
119
- /**
120
- * Pop items off of the stack up to and including `lastItem` and emit each on the close
121
- * observable. If the stack is empty or `lastItem` is not on the stack it does nothing.
122
- * @param lastItem the last item to pop off the stack.
123
- * @param options Options that configure behavior on close.
124
- */
125
- close(lastItem, options) {
126
- const { focusNextOnEmpty, focusParentTrigger } = { ...options };
127
- if (this._elements.indexOf(lastItem) >= 0) {
128
- let poppedElement;
129
- do {
130
- poppedElement = this._elements.pop();
131
- this._close.next({ item: poppedElement, focusParentTrigger });
132
- } while (poppedElement !== lastItem);
133
- if (this.isEmpty()) {
134
- this._empty.next(focusNextOnEmpty);
135
- }
136
- }
137
- }
138
- /**
139
- * Pop items off of the stack up to but excluding `lastItem` and emit each on the close
140
- * observable. If the stack is empty or `lastItem` is not on the stack it does nothing.
141
- * @param lastItem the element which should be left on the stack
142
- * @return whether or not an item was removed from the stack
143
- */
144
- closeSubMenuOf(lastItem) {
145
- let removed = false;
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
- /** Return true if this stack is empty. */
171
- isEmpty() {
172
- return !this._elements.length;
173
- }
174
- /** Return the length of the stack. */
175
- length() {
176
- return this._elements.length;
177
- }
178
- /** Get the top most element on the stack. */
179
- peek() {
180
- return this._elements[this._elements.length - 1];
181
- }
182
- /** Whether the menu stack is associated with an inline menu. */
183
- hasInlineMenu() {
184
- return this._inlineMenuOrientation != null;
185
- }
186
- /** The orientation of the associated inline menu. */
187
- inlineMenuOrientation() {
188
- return this._inlineMenuOrientation;
189
- }
190
- /** Sets whether the menu stack contains the focused element. */
191
- setHasFocus(hasFocus) {
192
- this._hasFocus.next(hasFocus);
193
- }
194
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0-next.2", ngImport: i0, type: MenuStack, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
195
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.2.0-next.2", ngImport: i0, type: MenuStack });
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({ minVersion: "12.0.0", version: "20.2.0-next.2", ngImport: i0, type: MenuStack, decorators: [{
198
- type: Injectable
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
- providedIn: 'root',
206
- factory: () => {
207
- const injector = inject(Injector);
208
- return () => createRepositionScrollStrategy(injector);
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
- /** The last open menu trigger. */
214
- static _openMenuTrigger;
215
- /**
216
- * Close the previous open menu and set the given one as being open.
217
- * @param trigger The trigger for the currently open Menu.
218
- */
219
- update(trigger) {
220
- if (MenuTracker._openMenuTrigger !== trigger) {
221
- MenuTracker._openMenuTrigger?.close();
222
- MenuTracker._openMenuTrigger = trigger;
223
- }
224
- }
225
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0-next.2", ngImport: i0, type: MenuTracker, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
226
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.2.0-next.2", ngImport: i0, type: MenuTracker, providedIn: 'root' });
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({ minVersion: "12.0.0", version: "20.2.0-next.2", ngImport: i0, type: MenuTracker, decorators: [{
229
- type: Injectable,
230
- args: [{ providedIn: 'root' }]
231
- }] });
232
- /**
233
- * Abstract directive that implements shared logic common to all menu triggers.
234
- * This class can be extended to create custom menu trigger types.
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
- /** The DI injector for this component. */
238
- injector = inject(Injector);
239
- /** The view container ref for this component */
240
- viewContainerRef = inject(ViewContainerRef);
241
- /** The menu stack in which this menu resides. */
242
- menuStack = inject(MENU_STACK);
243
- /** Function used to configure the scroll strategy for the menu. */
244
- menuScrollStrategy = inject(MENU_SCROLL_STRATEGY);
245
- /**
246
- * A list of preferred menu positions to be used when constructing the
247
- * `FlexibleConnectedPositionStrategy` for this trigger's menu.
248
- */
249
- menuPosition;
250
- /** Emits when the attached menu is requested to open */
251
- opened = new EventEmitter();
252
- /** Emits when the attached menu is requested to close */
253
- closed = new EventEmitter();
254
- /** Template reference variable to the menu this trigger opens */
255
- menuTemplateRef;
256
- /** Context data to be passed along to the menu template */
257
- menuData;
258
- /** A reference to the overlay which manages the triggered menu */
259
- overlayRef = null;
260
- /** Emits when this trigger is destroyed. */
261
- destroyed = new Subject();
262
- /** Emits when the outside pointer events listener on the overlay should be stopped. */
263
- stopOutsideClicksListener = merge(this.closed, this.destroyed);
264
- /** The child menu opened by this trigger. */
265
- childMenu;
266
- /** The content of the menu panel opened by this trigger. */
267
- _menuPortal;
268
- /** The injector to use for the child menu opened by this trigger. */
269
- _childMenuInjector;
270
- ngOnDestroy() {
271
- this._destroyOverlay();
272
- this.destroyed.next();
273
- this.destroyed.complete();
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
- /** Gets the injector to use when creating a child menu. */
315
- _getChildMenuInjector() {
316
- this._childMenuInjector =
317
- this._childMenuInjector ||
318
- Injector.create({
319
- providers: [
320
- { provide: MENU_TRIGGER, useValue: this },
321
- { provide: MENU_STACK, useValue: this.menuStack },
322
- ],
323
- parent: this.injector,
324
- });
325
- return this._childMenuInjector;
326
- }
327
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0-next.2", ngImport: i0, type: CdkMenuTriggerBase, deps: [], target: i0.ɵɵFactoryTarget.Directive });
328
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.2.0-next.2", type: CdkMenuTriggerBase, isStandalone: true, host: { properties: { "attr.aria-controls": "childMenu?.id", "attr.data-cdk-menu-stack-id": "menuStack.id" } }, ngImport: i0 });
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({ minVersion: "12.0.0", version: "20.2.0-next.2", ngImport: i0, type: CdkMenuTriggerBase, decorators: [{
331
- type: Directive,
332
- args: [{
333
- host: {
334
- '[attr.aria-controls]': 'childMenu?.id',
335
- '[attr.data-cdk-menu-stack-id]': 'menuStack.id',
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
- throw Error('expected an instance of PointerFocusTracker to be provided');
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
- throw Error('expected a reference to the parent menu');
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
- return (b.y - a.y) / (b.x - a.x);
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
- return point.y - slope * point.x;
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
- const { left, right, top, bottom } = submenuPoints;
384
- // Check for intersection with each edge of the submenu (left, right, top, bottom)
385
- // by fixing one coordinate to that edge's coordinate (either x or y) and checking if the
386
- // other coordinate is within bounds.
387
- return ((m * left + b >= top && m * left + b <= bottom) ||
388
- (m * right + b >= top && m * right + b <= bottom) ||
389
- ((top - b) / m >= left && (top - b) / m <= right) ||
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
- _ngZone = inject(NgZone);
404
- _renderer = inject(RendererFactory2).createRenderer(null, null);
405
- _cleanupMousemove;
406
- /** The last NUM_POINTS mouse move events. */
407
- _points = [];
408
- /** Reference to the root menu in which we are tracking mouse moves. */
409
- _menu;
410
- /** Reference to the root menu's mouse manager. */
411
- _pointerTracker;
412
- /** The id associated with the current timeout call waiting to resolve. */
413
- _timeoutId;
414
- /** Emits when this service is destroyed. */
415
- _destroyed = new Subject();
416
- ngOnDestroy() {
417
- this._cleanupMousemove?.();
418
- this._destroyed.next();
419
- this._destroyed.complete();
420
- }
421
- /**
422
- * Set the Menu and its PointerFocusTracker.
423
- * @param menu The menu that this menu aim service controls.
424
- * @param pointerTracker The `PointerFocusTracker` for the given menu.
425
- */
426
- initialize(menu, pointerTracker) {
427
- this._menu = menu;
428
- this._pointerTracker = pointerTracker;
429
- this._subscribeToMouseMoves();
430
- }
431
- /**
432
- * Calls the `doToggle` callback when it is deemed that the user is not moving towards
433
- * the submenu.
434
- * @param doToggle the function called when the user is not moving towards the submenu.
435
- */
436
- toggle(doToggle) {
437
- // If the menu is horizontal the sub-menus open below and there is no risk of premature
438
- // closing of any sub-menus therefore we automatically resolve the callback.
439
- if (this._menu.orientation === 'horizontal') {
440
- doToggle();
441
- }
442
- this._checkConfigured();
443
- const siblingItemIsWaiting = !!this._timeoutId;
444
- const hasPoints = this._points.length > 1;
445
- if (hasPoints && !siblingItemIsWaiting) {
446
- if (this._isMovingToSubmenu()) {
447
- this._startTimeout(doToggle);
448
- }
449
- else {
450
- doToggle();
451
- }
452
- }
453
- else if (!siblingItemIsWaiting) {
454
- doToggle();
455
- }
456
- }
457
- /**
458
- * Start the delayed toggle handler if one isn't running already.
459
- *
460
- * The delayed toggle handler executes the `doToggle` callback after some period of time iff the
461
- * users mouse is on an item in the current menu.
462
- *
463
- * @param doToggle the function called when the user is not moving towards the submenu.
464
- */
465
- _startTimeout(doToggle) {
466
- // If the users mouse is moving towards a submenu we don't want to immediately resolve.
467
- // Wait for some period of time before determining if the previous menu should close in
468
- // cases where the user may have moved towards the submenu but stopped on a sibling menu
469
- // item intentionally.
470
- const timeoutId = setTimeout(() => {
471
- // Resolve if the user is currently moused over some element in the root menu
472
- if (this._pointerTracker.activeElement && timeoutId === this._timeoutId) {
473
- doToggle();
474
- }
475
- this._timeoutId = null;
476
- }, CLOSE_DELAY);
477
- this._timeoutId = timeoutId;
478
- }
479
- /** Whether the user is heading towards the open submenu. */
480
- _isMovingToSubmenu() {
481
- const submenuPoints = this._getSubmenuBounds();
482
- if (!submenuPoints) {
483
- return false;
484
- }
485
- let numMoving = 0;
486
- const currPoint = this._points[this._points.length - 1];
487
- // start from the second last point and calculate the slope between each point and the last
488
- // point.
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
- return numMoving >= Math.floor(NUM_POINTS / 2);
497
- }
498
- /** Get the bounding DOMRect for the open submenu. */
499
- _getSubmenuBounds() {
500
- return this._pointerTracker?.previousElement?.getMenu()?.nativeElement.getBoundingClientRect();
501
- }
502
- /**
503
- * Check if a reference to the PointerFocusTracker and menu element is provided.
504
- * @throws an error if neither reference is provided.
505
- */
506
- _checkConfigured() {
507
- if (typeof ngDevMode === 'undefined' || ngDevMode) {
508
- if (!this._pointerTracker) {
509
- throwMissingPointerFocusTracker();
510
- }
511
- if (!this._menu) {
512
- throwMissingMenuReference();
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({ minVersion: "12.0.0", version: "20.2.0-next.2", ngImport: i0, type: TargetMenuAim, decorators: [{
536
- type: Injectable
537
- }] });
538
- /**
539
- * CdkTargetMenuAim is a provider for the TargetMenuAim service. It can be added to an
540
- * element with either the `cdkMenu` or `cdkMenuBar` directive and child menu items.
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
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0-next.2", ngImport: i0, type: CdkTargetMenuAim, deps: [], target: i0.ɵɵFactoryTarget.Directive });
544
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.2.0-next.2", type: CdkTargetMenuAim, isStandalone: true, selector: "[cdkTargetMenuAim]", providers: [{ provide: MENU_AIM, useClass: TargetMenuAim }], exportAs: ["cdkTargetMenuAim"], ngImport: i0 });
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({ minVersion: "12.0.0", version: "20.2.0-next.2", ngImport: i0, type: CdkTargetMenuAim, decorators: [{
547
- type: Directive,
548
- args: [{
549
- selector: '[cdkTargetMenuAim]',
550
- exportAs: 'cdkTargetMenuAim',
551
- providers: [{ provide: MENU_AIM, useClass: TargetMenuAim }],
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
- // Synthetic events won't trigger clicks.
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
- _elementRef = inject(ElementRef);
584
- _ngZone = inject(NgZone);
585
- _changeDetectorRef = inject(ChangeDetectorRef);
586
- _inputModalityDetector = inject(InputModalityDetector);
587
- _directionality = inject(Directionality, { optional: true });
588
- _renderer = inject(Renderer2);
589
- _injector = inject(Injector);
590
- _cleanupMouseenter;
591
- /** The app's menu tracking registry */
592
- _menuTracker = inject(MenuTracker);
593
- /** The parent menu this trigger belongs to. */
594
- _parentMenu = inject(CDK_MENU, { optional: true });
595
- /** The menu aim service used by this menu. */
596
- _menuAim = inject(MENU_AIM, { optional: true });
597
- constructor() {
598
- super();
599
- this._setRole();
600
- this._registerCloseHandler();
601
- this._subscribeToMenuStackClosed();
602
- this._subscribeToMouseEnter();
603
- this._subscribeToMenuStackHasFocus();
604
- this._setType();
605
- }
606
- /** Toggle the attached menu. */
607
- toggle() {
608
- this.isOpen() ? this.close() : this.open();
609
- }
610
- /** Open the attached menu. */
611
- open() {
612
- if (!this._parentMenu) {
613
- this._menuTracker.update(this);
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
- if (!this.isOpen() && this.menuTemplateRef != null) {
616
- this.opened.next();
617
- this.overlayRef =
618
- this.overlayRef || createOverlayRef(this._injector, this._getOverlayConfig());
619
- this.overlayRef.attach(this.getMenuContentPortal());
620
- this._changeDetectorRef.markForCheck();
621
- this._subscribeToOutsideClicks();
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
- /** Close the opened menu. */
625
- close() {
626
- if (this.isOpen()) {
627
- this.closed.next();
628
- this.overlayRef.detach();
629
- this._changeDetectorRef.markForCheck();
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
- this._closeSiblingTriggers();
632
- }
633
- /**
634
- * Get a reference to the rendered Menu if the Menu is open and rendered in the DOM.
635
- */
636
- getMenu() {
637
- return this.childMenu;
638
- }
639
- ngOnChanges(changes) {
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
- ngOnDestroy() {
645
- this._cleanupMouseenter();
646
- super.ngOnDestroy();
647
- }
648
- /**
649
- * Handles keyboard events for the menu item.
650
- * @param event The keyboard event to handle
651
- */
652
- _toggleOnKeydown(event) {
653
- const isParentVertical = this._parentMenu?.orientation === 'vertical';
654
- switch (event.keyCode) {
655
- case SPACE:
656
- case ENTER:
657
- // Skip events that will trigger clicks so the handler doesn't get triggered twice.
658
- if (!hasModifierKey(event) && !eventDispatchesNativeClick(this._elementRef, event)) {
659
- this.toggle();
660
- this.childMenu?.focusFirstItem('keyboard');
661
- }
662
- break;
663
- case RIGHT_ARROW:
664
- if (!hasModifierKey(event)) {
665
- if (this._parentMenu && isParentVertical && this._directionality?.value !== 'rtl') {
666
- event.preventDefault();
667
- this.open();
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
- /** Handles clicks on the menu trigger. */
696
- _handleClick() {
697
- this.toggle();
698
- this.childMenu?.focusFirstItem('mouse');
699
- }
700
- /**
701
- * Sets whether the trigger's menu stack has focus.
702
- * @param hasFocus Whether the menu stack has focus.
703
- */
704
- _setHasFocus(hasFocus) {
705
- if (!this._parentMenu) {
706
- this.menuStack.setHasFocus(hasFocus);
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
- * Subscribe to the mouseenter events and close any sibling menu items if this element is moused
711
- * into.
712
- */
713
- _subscribeToMouseEnter() {
714
- this._cleanupMouseenter = this._ngZone.runOutsideAngular(() => {
715
- return this._renderer.listen(this._elementRef.nativeElement, 'mouseenter', () => {
716
- if (
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
- /** Get the configuration object used to create the overlay. */
753
- _getOverlayConfig() {
754
- return new OverlayConfig({
755
- positionStrategy: this._getOverlayPositionStrategy(),
756
- scrollStrategy: this.menuScrollStrategy(),
757
- direction: this._directionality || undefined,
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
- * Subscribe to the overlays outside pointer events stream and handle closing out the stack if a
789
- * click occurs outside the menus.
790
- */
791
- _subscribeToOutsideClicks() {
792
- if (this.overlayRef) {
793
- this.overlayRef
794
- .outsidePointerEvents()
795
- .pipe(takeUntil(this.stopOutsideClicksListener))
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
- /** Subscribe to the MenuStack closed events. */
821
- _subscribeToMenuStackClosed() {
822
- if (!this._parentMenu) {
823
- this.menuStack.closed.subscribe(({ focusParentTrigger }) => {
824
- if (focusParentTrigger && !this.menuStack.length()) {
825
- this._elementRef.nativeElement.focus();
826
- }
827
- });
828
- }
829
- }
830
- /** Sets the role attribute for this trigger if needed. */
831
- _setRole() {
832
- // If this trigger is part of another menu, the cdkMenuItem directive will handle setting the
833
- // role, otherwise this is a standalone trigger, and we should ensure it has role="button".
834
- if (!this._parentMenu) {
835
- this._elementRef.nativeElement.setAttribute('role', 'button');
836
- }
837
- }
838
- /** Sets thte `type` attribute of the trigger. */
839
- _setType() {
840
- const element = this._elementRef.nativeElement;
841
- if (element.nodeName === 'BUTTON' && !element.getAttribute('type')) {
842
- // Prevents form submissions.
843
- element.setAttribute('type', 'button');
844
- }
845
- }
846
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0-next.2", ngImport: i0, type: CdkMenuTrigger, deps: [], target: i0.ɵɵFactoryTarget.Directive });
847
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.2.0-next.2", type: CdkMenuTrigger, isStandalone: true, selector: "[cdkMenuTriggerFor]", inputs: { menuTemplateRef: ["cdkMenuTriggerFor", "menuTemplateRef"], menuPosition: ["cdkMenuPosition", "menuPosition"], menuData: ["cdkMenuTriggerData", "menuData"] }, outputs: { opened: "cdkMenuOpened", closed: "cdkMenuClosed" }, host: { listeners: { "focusin": "_setHasFocus(true)", "focusout": "_setHasFocus(false)", "keydown": "_toggleOnKeydown($event)", "click": "_handleClick()" }, properties: { "attr.aria-haspopup": "menuTemplateRef ? \"menu\" : null", "attr.aria-expanded": "menuTemplateRef == null ? null : isOpen()" }, classAttribute: "cdk-menu-trigger" }, providers: [
848
- { provide: MENU_TRIGGER, useExisting: CdkMenuTrigger },
849
- PARENT_OR_NEW_MENU_STACK_PROVIDER,
850
- ], exportAs: ["cdkMenuTriggerFor"], usesInheritance: true, usesOnChanges: true, ngImport: i0 });
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({ minVersion: "12.0.0", version: "20.2.0-next.2", ngImport: i0, type: CdkMenuTrigger, decorators: [{
853
- type: Directive,
854
- args: [{
855
- selector: '[cdkMenuTriggerFor]',
856
- exportAs: 'cdkMenuTriggerFor',
857
- host: {
858
- 'class': 'cdk-menu-trigger',
859
- '[attr.aria-haspopup]': 'menuTemplateRef ? "menu" : null',
860
- '[attr.aria-expanded]': 'menuTemplateRef == null ? null : isOpen()',
861
- '(focusin)': '_setHasFocus(true)',
862
- '(focusout)': '_setHasFocus(false)',
863
- '(keydown)': '_toggleOnKeydown($event)',
864
- '(click)': '_handleClick()',
865
- },
866
- inputs: [
867
- { name: 'menuTemplateRef', alias: 'cdkMenuTriggerFor' },
868
- { name: 'menuPosition', alias: 'cdkMenuPosition' },
869
- { name: 'menuData', alias: 'cdkMenuTriggerData' },
870
- ],
871
- outputs: ['opened: cdkMenuOpened', 'closed: cdkMenuClosed'],
872
- providers: [
873
- { provide: MENU_TRIGGER, useExisting: CdkMenuTrigger },
874
- PARENT_OR_NEW_MENU_STACK_PROVIDER,
875
- ],
876
- }]
877
- }], ctorParameters: () => [] });
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
- _dir = inject(Directionality, { optional: true });
886
- _elementRef = inject(ElementRef);
887
- _ngZone = inject(NgZone);
888
- _inputModalityDetector = inject(InputModalityDetector);
889
- _renderer = inject(Renderer2);
890
- _cleanupMouseEnter;
891
- /** The menu aim service used by this menu. */
892
- _menuAim = inject(MENU_AIM, { optional: true });
893
- /** The stack of menus this menu belongs to. */
894
- _menuStack = inject(MENU_STACK);
895
- /** The parent menu in which this menuitem resides. */
896
- _parentMenu = inject(CDK_MENU, { optional: true });
897
- /** Reference to the CdkMenuItemTrigger directive if one is added to the same element */
898
- _menuTrigger = inject(CdkMenuTrigger, { optional: true, self: true });
899
- /** Whether the CdkMenuItem is disabled - defaults to false */
900
- disabled = false;
901
- /**
902
- * The text used to locate this item during menu typeahead. If not specified,
903
- * the `textContent` of the item will be used.
904
- */
905
- typeaheadLabel;
906
- /**
907
- * If this MenuItem is a regular MenuItem, outputs when it is triggered by a keyboard or mouse
908
- * event.
909
- */
910
- triggered = new EventEmitter();
911
- /** Whether the menu item opens a menu. */
912
- get hasMenu() {
913
- return this._menuTrigger?.menuTemplateRef != null;
914
- }
915
- /**
916
- * The tabindex for this menu item managed internally and used for implementing roving a
917
- * tab index.
918
- */
919
- _tabindex = -1;
920
- /** Whether the item should close the menu if triggered by the spacebar. */
921
- closeOnSpacebarTrigger = true;
922
- /** Emits when the menu item is destroyed. */
923
- destroyed = new Subject();
924
- constructor() {
925
- this._setupMouseEnter();
926
- this._setType();
927
- if (this._isStandaloneItem()) {
928
- this._tabindex = 0;
929
- }
930
- }
931
- ngOnDestroy() {
932
- this._cleanupMouseEnter?.();
933
- this.destroyed.next();
934
- this.destroyed.complete();
935
- }
936
- /** Place focus on the element. */
937
- focus() {
938
- this._elementRef.nativeElement.focus();
939
- }
940
- /**
941
- * If the menu item is not disabled and the element does not have a menu trigger attached, emit
942
- * on the cdkMenuItemTriggered emitter and close all open menus.
943
- * @param options Options the configure how the item is triggered
944
- * - keepOpen: specifies that the menu should be kept open after triggering the item.
945
- */
946
- trigger(options) {
947
- const { keepOpen } = { ...options };
948
- if (!this.disabled && !this.hasMenu) {
949
- this.triggered.next();
950
- if (!keepOpen) {
951
- this._menuStack.closeAll({ focusParentTrigger: true });
952
- }
953
- }
954
- }
955
- /** Return true if this MenuItem has an attached menu and it is open. */
956
- isMenuOpen() {
957
- return !!this._menuTrigger?.isOpen();
958
- }
959
- /**
960
- * Get a reference to the rendered Menu if the Menu is open and it is visible in the DOM.
961
- * @return the menu if it is open, otherwise undefined.
962
- */
963
- getMenu() {
964
- return this._menuTrigger?.getMenu();
965
- }
966
- /** Get the CdkMenuTrigger associated with this element. */
967
- getMenuTrigger() {
968
- return this._menuTrigger;
969
- }
970
- /** Get the label for this element which is required by the FocusableOption interface. */
971
- getLabel() {
972
- return this.typeaheadLabel || this._elementRef.nativeElement.textContent?.trim() || '';
973
- }
974
- /** Reset the tabindex to -1. */
975
- _resetTabIndex() {
976
- if (!this._isStandaloneItem()) {
977
- this._tabindex = -1;
978
- }
979
- }
980
- /**
981
- * Set the tab index to 0 if not disabled and it's a focus event, or a mouse enter if this element
982
- * is not in a menu bar.
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
- this._menuStack.close(parentMenu, {
1063
- focusNextOnEmpty: this._menuStack.inlineMenuOrientation() === 'horizontal'
1064
- ? FocusNext.previousItem
1065
- : FocusNext.currentItem,
1066
- focusParentTrigger: true,
1067
- });
954
+ }
955
+ this.trigger({
956
+ keepOpen: event.keyCode === SPACE && !this.closeOnSpacebarTrigger
957
+ });
1068
958
  }
1069
- }
1070
- /**
1071
- * Handles the user pressing the forward arrow key.
1072
- * @param event The keyboard event.
1073
- */
1074
- _forwardArrowPressed(event) {
1075
- if (!this.hasMenu && this._menuStack.inlineMenuOrientation() === 'horizontal') {
1076
- event.preventDefault();
1077
- this._menuStack.closeAll({
1078
- focusNextOnEmpty: FocusNext.nextItem,
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
- * Subscribe to the mouseenter events and close any sibling menu items if this element is moused
1085
- * into.
1086
- */
1087
- _setupMouseEnter() {
1088
- if (!this._isStandaloneItem()) {
1089
- const closeOpenSiblings = () => this._ngZone.run(() => this._menuStack.closeSubMenuOf(this._parentMenu));
1090
- this._cleanupMouseEnter = this._ngZone.runOutsideAngular(() => this._renderer.listen(this._elementRef.nativeElement, 'mouseenter', () => {
1091
- // Skip fake `mouseenter` events dispatched by touch devices.
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
- * Return true if the enclosing parent menu is configured in a horizontal orientation, false
1107
- * otherwise or if no parent.
1108
- */
1109
- _isParentVertical() {
1110
- return this._parentMenu?.orientation === 'vertical';
1111
- }
1112
- /** Sets the `type` attribute of the menu item. */
1113
- _setType() {
1114
- const element = this._elementRef.nativeElement;
1115
- if (element.nodeName === 'BUTTON' && !element.getAttribute('type')) {
1116
- // Prevent form submissions.
1117
- element.setAttribute('type', 'button');
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
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0-next.2", ngImport: i0, type: CdkMenuItem, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1121
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "20.2.0-next.2", type: CdkMenuItem, isStandalone: true, selector: "[cdkMenuItem]", inputs: { disabled: ["cdkMenuItemDisabled", "disabled", booleanAttribute], typeaheadLabel: ["cdkMenuitemTypeaheadLabel", "typeaheadLabel"] }, outputs: { triggered: "cdkMenuItemTriggered" }, host: { attributes: { "role": "menuitem" }, listeners: { "blur": "_resetTabIndex()", "focus": "_setTabIndex()", "click": "_handleClick($event)", "keydown": "_onKeydown($event)" }, properties: { "class.cdk-menu-item-disabled": "disabled", "tabindex": "_tabindex", "attr.aria-disabled": "disabled || null" }, classAttribute: "cdk-menu-item" }, exportAs: ["cdkMenuItem"], ngImport: i0 });
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({ minVersion: "12.0.0", version: "20.2.0-next.2", ngImport: i0, type: CdkMenuItem, decorators: [{
1124
- type: Directive,
1125
- args: [{
1126
- selector: '[cdkMenuItem]',
1127
- exportAs: 'cdkMenuItem',
1128
- host: {
1129
- 'role': 'menuitem',
1130
- 'class': 'cdk-menu-item',
1131
- '[class.cdk-menu-item-disabled]': 'disabled',
1132
- '[tabindex]': '_tabindex',
1133
- '[attr.aria-disabled]': 'disabled || null',
1134
- '(blur)': '_resetTabIndex()',
1135
- '(focus)': '_setTabIndex()',
1136
- '(click)': '_handleClick($event)',
1137
- '(keydown)': '_onKeydown($event)',
1138
- },
1139
- }]
1140
- }], ctorParameters: () => [], propDecorators: { disabled: [{
1141
- type: Input,
1142
- args: [{ alias: 'cdkMenuItemDisabled', transform: booleanAttribute }]
1143
- }], typeaheadLabel: [{
1144
- type: Input,
1145
- args: ['cdkMenuitemTypeaheadLabel']
1146
- }], triggered: [{
1147
- type: Output,
1148
- args: ['cdkMenuItemTriggered']
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
- _renderer;
1157
- _items;
1158
- _eventCleanups;
1159
- _itemsSubscription;
1160
- /** Emits when an element is moused into. */
1161
- entered = new Subject();
1162
- /** Emits when an element is moused out. */
1163
- exited = new Subject();
1164
- /** The element currently under mouse focus. */
1165
- activeElement;
1166
- /** The element previously under mouse focus. */
1167
- previousElement;
1168
- constructor(_renderer, _items) {
1169
- this._renderer = _renderer;
1170
- this._items = _items;
1171
- this._bindEvents();
1172
- this.entered.subscribe(element => (this.activeElement = element));
1173
- this.exited.subscribe(() => {
1174
- this.previousElement = this.activeElement;
1175
- this.activeElement = undefined;
1176
- });
1177
- }
1178
- /** Stop the managers listeners. */
1179
- destroy() {
1180
- this._cleanupEvents();
1181
- this._itemsSubscription?.unsubscribe();
1182
- }
1183
- /** Binds the enter/exit events on all the items. */
1184
- _bindEvents() {
1185
- // TODO(crisbeto): this can probably be simplified by binding a single event on a parent node.
1186
- this._itemsSubscription = this._items.changes.pipe(startWith(this._items)).subscribe(() => {
1187
- this._cleanupEvents();
1188
- this._eventCleanups = [];
1189
- this._items.forEach(item => {
1190
- const element = item._elementRef.nativeElement;
1191
- this._eventCleanups.push(this._renderer.listen(element, 'mouseenter', () => {
1192
- this.entered.next(item);
1193
- }), this._renderer.listen(element, 'mouseout', () => {
1194
- this.exited.next(item);
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
- _focusMonitor = inject(FocusMonitor);
1212
- ngZone = inject(NgZone);
1213
- _renderer = inject(Renderer2);
1214
- /** The menu's native DOM host element. */
1215
- nativeElement = inject(ElementRef).nativeElement;
1216
- /** The stack of menus this menu belongs to. */
1217
- menuStack = inject(MENU_STACK);
1218
- /** The menu aim service used by this menu. */
1219
- menuAim = inject(MENU_AIM, { optional: true, self: true });
1220
- /** The directionality (text direction) of the current page. */
1221
- dir = inject(Directionality, { optional: true });
1222
- /** All items inside the menu, including ones that belong to other menus. */
1223
- _allItems;
1224
- /** The id of the menu's host element. */
1225
- id = inject(_IdGenerator).getId('cdk-menu-');
1226
- /** All child MenuItem elements belonging to this Menu. */
1227
- items = new QueryList();
1228
- /** The direction items in the menu flow. */
1229
- orientation = 'vertical';
1230
- /**
1231
- * Whether the menu is displayed inline (i.e. always present vs a conditional popup that the
1232
- * user triggers with a trigger element).
1233
- */
1234
- isInline = false;
1235
- /** Handles keyboard events for the menu. */
1236
- keyManager;
1237
- /** Emits when the MenuBar is destroyed. */
1238
- destroyed = new Subject();
1239
- /** The Menu Item which triggered the open submenu. */
1240
- triggerItem;
1241
- /** Tracks the users mouse movements over the menu. */
1242
- pointerTracker;
1243
- /** Whether this menu's menu stack has focus. */
1244
- _menuStackHasFocus = signal(false, ...(ngDevMode ? [{ debugName: "_menuStackHasFocus" }] : []));
1245
- _tabIndexSignal = computed(() => {
1246
- const tabindexIfInline = this._menuStackHasFocus() ? -1 : 0;
1247
- return this.isInline ? tabindexIfInline : null;
1248
- }, ...(ngDevMode ? [{ debugName: "_tabIndexSignal" }] : []));
1249
- ngAfterContentInit() {
1250
- if (!this.isInline) {
1251
- this.menuStack.push(this);
1252
- }
1253
- this._setItems();
1254
- this._setKeyManager();
1255
- this._handleFocus();
1256
- this._subscribeToMenuStackHasFocus();
1257
- this._subscribeToMenuOpen();
1258
- this._subscribeToMenuStackClosed();
1259
- this._setUpPointerTracker();
1260
- }
1261
- ngOnDestroy() {
1262
- this._focusMonitor.stopMonitoring(this.nativeElement);
1263
- this.keyManager?.destroy();
1264
- this.destroyed.next();
1265
- this.destroyed.complete();
1266
- this.pointerTracker?.destroy();
1267
- }
1268
- /**
1269
- * Place focus on the first MenuItem in the menu and set the focus origin.
1270
- * @param focusOrigin The origin input mode of the focus event.
1271
- */
1272
- focusFirstItem(focusOrigin = 'program') {
1273
- this.keyManager.setFocusOrigin(focusOrigin);
1274
- this.keyManager.setFirstItemActive();
1275
- }
1276
- /**
1277
- * Place focus on the last MenuItem in the menu and set the focus origin.
1278
- * @param focusOrigin The origin input mode of the focus event.
1279
- */
1280
- focusLastItem(focusOrigin = 'program') {
1281
- this.keyManager.setFocusOrigin(focusOrigin);
1282
- this.keyManager.setLastItemActive();
1283
- }
1284
- /**
1285
- * Sets the active item to the item at the specified index and focuses the newly active item.
1286
- * @param item The index of the item to be set as active, or the CdkMenuItem instance.
1287
- */
1288
- setActiveMenuItem(item) {
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
- /** Handles focus landing on the host element of the menu. */
1386
- _handleFocus() {
1387
- this._focusMonitor
1388
- .monitor(this.nativeElement, false)
1389
- .pipe(takeUntil(this.destroyed))
1390
- .subscribe(origin => {
1391
- // Don't forward focus on mouse interactions, because it can
1392
- // mess with the user's scroll position. See #30130.
1393
- if (origin !== null && origin !== 'mouse') {
1394
- this.focusFirstItem(origin);
1395
- }
1396
- });
1397
- }
1398
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0-next.2", ngImport: i0, type: CdkMenuBase, deps: null, target: i0.ɵɵFactoryTarget.Directive });
1399
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.2.0-next.2", type: CdkMenuBase, isStandalone: true, inputs: { id: "id" }, host: { attributes: { "role": "menu" }, listeners: { "focusin": "menuStack.setHasFocus(true)", "focusout": "menuStack.setHasFocus(false)" }, properties: { "tabindex": "_getTabIndex()", "id": "id", "attr.aria-orientation": "orientation", "attr.data-cdk-menu-stack-id": "menuStack.id" } }, queries: [{ propertyName: "_allItems", predicate: CdkMenuItem, descendants: true }], usesInheritance: true, ngImport: i0 });
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({ minVersion: "12.0.0", version: "20.2.0-next.2", ngImport: i0, type: CdkMenuBase, decorators: [{
1402
- type: Directive,
1403
- args: [{
1404
- host: {
1405
- 'role': 'menu',
1406
- 'class': '', // reset the css class added by the super-class
1407
- '[tabindex]': '_getTabIndex()',
1408
- '[id]': 'id',
1409
- '[attr.aria-orientation]': 'orientation',
1410
- '[attr.data-cdk-menu-stack-id]': 'menuStack.id',
1411
- '(focusin)': 'menuStack.setHasFocus(true)',
1412
- '(focusout)': 'menuStack.setHasFocus(false)',
1413
- },
1414
- }]
1415
- }], propDecorators: { _allItems: [{
1416
- type: ContentChildren,
1417
- args: [CdkMenuItem, { descendants: true }]
1418
- }], id: [{
1419
- type: Input
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
- _parentTrigger = inject(MENU_TRIGGER, { optional: true });
1431
- /** Event emitted when the menu is closed. */
1432
- closed = new EventEmitter();
1433
- /** The direction items in the menu flow. */
1434
- orientation = 'vertical';
1435
- /** Whether the menu is displayed inline (i.e. always present vs a conditional popup that the user triggers with a trigger element). */
1436
- isInline = !this._parentTrigger;
1437
- constructor() {
1438
- super();
1439
- this.destroyed.subscribe(this.closed);
1440
- this._parentTrigger?.registerChildMenu(this);
1441
- }
1442
- ngAfterContentInit() {
1443
- super.ngAfterContentInit();
1444
- this._subscribeToMenuStackEmptied();
1445
- }
1446
- ngOnDestroy() {
1447
- super.ngOnDestroy();
1448
- this.closed.complete();
1449
- }
1450
- /**
1451
- * Handle keyboard events for the Menu.
1452
- * @param event The keyboard event to be handled.
1453
- */
1454
- _handleKeyEvent(event) {
1455
- const keyManager = this.keyManager;
1456
- switch (event.keyCode) {
1457
- case LEFT_ARROW:
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
- * Set focus the either the current, previous or next item based on the FocusNext event.
1485
- * @param focusNext The element to focus.
1486
- */
1487
- _toggleMenuFocus(focusNext) {
1488
- const keyManager = this.keyManager;
1489
- switch (focusNext) {
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
- /** Subscribe to the MenuStack emptied events. */
1507
- _subscribeToMenuStackEmptied() {
1508
- this.menuStack.emptied
1509
- .pipe(takeUntil(this.destroyed))
1510
- .subscribe(event => this._toggleMenuFocus(event));
1511
- }
1512
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0-next.2", ngImport: i0, type: CdkMenu, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1513
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.2.0-next.2", type: CdkMenu, isStandalone: true, selector: "[cdkMenu]", outputs: { closed: "closed" }, host: { attributes: { "role": "menu" }, listeners: { "keydown": "_handleKeyEvent($event)" }, properties: { "class.cdk-menu-inline": "isInline" }, classAttribute: "cdk-menu" }, providers: [
1514
- { provide: CdkMenuGroup, useExisting: CdkMenu },
1515
- { provide: CDK_MENU, useExisting: CdkMenu },
1516
- PARENT_OR_NEW_INLINE_MENU_STACK_PROVIDER('vertical'),
1517
- ], exportAs: ["cdkMenu"], usesInheritance: true, ngImport: i0 });
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({ minVersion: "12.0.0", version: "20.2.0-next.2", ngImport: i0, type: CdkMenu, decorators: [{
1520
- type: Directive,
1521
- args: [{
1522
- selector: '[cdkMenu]',
1523
- exportAs: 'cdkMenu',
1524
- host: {
1525
- 'role': 'menu',
1526
- 'class': 'cdk-menu',
1527
- '[class.cdk-menu-inline]': 'isInline',
1528
- '(keydown)': '_handleKeyEvent($event)',
1529
- },
1530
- providers: [
1531
- { provide: CdkMenuGroup, useExisting: CdkMenu },
1532
- { provide: CDK_MENU, useExisting: CdkMenu },
1533
- PARENT_OR_NEW_INLINE_MENU_STACK_PROVIDER('vertical'),
1534
- ],
1535
- }]
1536
- }], ctorParameters: () => [], propDecorators: { closed: [{
1537
- type: Output
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
- /** The direction items in the menu flow. */
1548
- orientation = 'horizontal';
1549
- /** Whether the menu is displayed inline (i.e. always present vs a conditional popup that the user triggers with a trigger element). */
1550
- isInline = true;
1551
- ngAfterContentInit() {
1552
- super.ngAfterContentInit();
1553
- this._subscribeToMenuStackEmptied();
1554
- }
1555
- /**
1556
- * Handle keyboard events for the Menu.
1557
- * @param event The keyboard event to be handled.
1558
- */
1559
- _handleKeyEvent(event) {
1560
- const keyManager = this.keyManager;
1561
- switch (event.keyCode) {
1562
- case UP_ARROW:
1563
- case DOWN_ARROW:
1564
- case LEFT_ARROW:
1565
- case RIGHT_ARROW:
1566
- if (!hasModifierKey(event)) {
1567
- const horizontalArrows = event.keyCode === LEFT_ARROW || event.keyCode === RIGHT_ARROW;
1568
- // For a horizontal menu if the left/right keys were clicked, or a vertical menu if the
1569
- // up/down keys were clicked: if the current menu is open, close it then focus and open the
1570
- // next menu.
1571
- if (horizontalArrows) {
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
- * Set focus to either the current, previous or next item based on the FocusNext event, then
1600
- * open the previous or next item.
1601
- * @param focusNext The element to focus.
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
- /** Subscribe to the MenuStack emptied events. */
1625
- _subscribeToMenuStackEmptied() {
1626
- this.menuStack?.emptied
1627
- .pipe(takeUntil(this.destroyed))
1628
- .subscribe(event => this._toggleOpenMenu(event));
1629
- }
1630
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0-next.2", ngImport: i0, type: CdkMenuBar, deps: null, target: i0.ɵɵFactoryTarget.Directive });
1631
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.2.0-next.2", type: CdkMenuBar, isStandalone: true, selector: "[cdkMenuBar]", host: { attributes: { "role": "menubar" }, listeners: { "keydown": "_handleKeyEvent($event)" }, classAttribute: "cdk-menu-bar" }, providers: [
1632
- { provide: CdkMenuGroup, useExisting: CdkMenuBar },
1633
- { provide: CDK_MENU, useExisting: CdkMenuBar },
1634
- { provide: MENU_STACK, useFactory: () => MenuStack.inline('horizontal') },
1635
- ], exportAs: ["cdkMenuBar"], usesInheritance: true, ngImport: i0 });
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({ minVersion: "12.0.0", version: "20.2.0-next.2", ngImport: i0, type: CdkMenuBar, decorators: [{
1638
- type: Directive,
1639
- args: [{
1640
- selector: '[cdkMenuBar]',
1641
- exportAs: 'cdkMenuBar',
1642
- host: {
1643
- 'role': 'menubar',
1644
- 'class': 'cdk-menu-bar',
1645
- '(keydown)': '_handleKeyEvent($event)',
1646
- },
1647
- providers: [
1648
- { provide: CdkMenuGroup, useExisting: CdkMenuBar },
1649
- { provide: CDK_MENU, useExisting: CdkMenuBar },
1650
- { provide: MENU_STACK, useFactory: () => MenuStack.inline('horizontal') },
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
- /** Whether the element is checked */
1658
- checked = false;
1659
- /** Whether the item should close the menu if triggered by the spacebar. */
1660
- closeOnSpacebarTrigger = false;
1661
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0-next.2", ngImport: i0, type: CdkMenuItemSelectable, deps: null, target: i0.ɵɵFactoryTarget.Directive });
1662
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "20.2.0-next.2", type: CdkMenuItemSelectable, isStandalone: true, inputs: { checked: ["cdkMenuItemChecked", "checked", booleanAttribute] }, host: { properties: { "attr.aria-checked": "!!checked", "attr.aria-disabled": "disabled || null" } }, usesInheritance: true, ngImport: i0 });
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({ minVersion: "12.0.0", version: "20.2.0-next.2", ngImport: i0, type: CdkMenuItemSelectable, decorators: [{
1665
- type: Directive,
1666
- args: [{
1667
- host: {
1668
- '[attr.aria-checked]': '!!checked',
1669
- '[attr.aria-disabled]': 'disabled || null',
1670
- },
1671
- }]
1672
- }], propDecorators: { checked: [{
1673
- type: Input,
1674
- args: [{ alias: 'cdkMenuItemChecked', transform: booleanAttribute }]
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
- /** The unique selection dispatcher for this radio's `CdkMenuGroup`. */
1684
- _selectionDispatcher = inject(UniqueSelectionDispatcher);
1685
- /** An ID to identify this radio item to the `UniqueSelectionDispatcher`. */
1686
- _id = inject(_IdGenerator).getId('cdk-menu-item-radio-');
1687
- /** Function to unregister the selection dispatcher */
1688
- _removeDispatcherListener;
1689
- constructor() {
1690
- super();
1691
- this._registerDispatcherListener();
1692
- }
1693
- ngOnDestroy() {
1694
- super.ngOnDestroy();
1695
- this._removeDispatcherListener();
1696
- }
1697
- /**
1698
- * Toggles the checked state of the radio-button.
1699
- * @param options Options the configure how the item is triggered
1700
- * - keepOpen: specifies that the menu should be kept open after triggering the item.
1701
- */
1702
- trigger(options) {
1703
- super.trigger(options);
1704
- if (!this.disabled) {
1705
- this._selectionDispatcher.notify(this._id, '');
1706
- }
1707
- }
1708
- /** Configure the unique selection dispatcher listener in order to toggle the checked state */
1709
- _registerDispatcherListener() {
1710
- this._removeDispatcherListener = this._selectionDispatcher.listen((id) => {
1711
- this.checked = this._id === id;
1712
- });
1713
- }
1714
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0-next.2", ngImport: i0, type: CdkMenuItemRadio, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1715
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.2.0-next.2", type: CdkMenuItemRadio, isStandalone: true, selector: "[cdkMenuItemRadio]", host: { attributes: { "role": "menuitemradio" }, properties: { "class.cdk-menu-item-radio": "true" } }, providers: [
1716
- { provide: CdkMenuItemSelectable, useExisting: CdkMenuItemRadio },
1717
- { provide: CdkMenuItem, useExisting: CdkMenuItemSelectable },
1718
- ], exportAs: ["cdkMenuItemRadio"], usesInheritance: true, ngImport: i0 });
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({ minVersion: "12.0.0", version: "20.2.0-next.2", ngImport: i0, type: CdkMenuItemRadio, decorators: [{
1721
- type: Directive,
1722
- args: [{
1723
- selector: '[cdkMenuItemRadio]',
1724
- exportAs: 'cdkMenuItemRadio',
1725
- host: {
1726
- 'role': 'menuitemradio',
1727
- '[class.cdk-menu-item-radio]': 'true',
1728
- },
1729
- providers: [
1730
- { provide: CdkMenuItemSelectable, useExisting: CdkMenuItemRadio },
1731
- { provide: CdkMenuItem, useExisting: CdkMenuItemSelectable },
1732
- ],
1733
- }]
1734
- }], ctorParameters: () => [] });
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
- * Toggle the checked state of the checkbox.
1743
- * @param options Options the configure how the item is triggered
1744
- * - keepOpen: specifies that the menu should be kept open after triggering the item.
1745
- */
1746
- trigger(options) {
1747
- super.trigger(options);
1748
- if (!this.disabled) {
1749
- this.checked = !this.checked;
1750
- }
1751
- }
1752
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0-next.2", ngImport: i0, type: CdkMenuItemCheckbox, deps: null, target: i0.ɵɵFactoryTarget.Directive });
1753
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.2.0-next.2", type: CdkMenuItemCheckbox, isStandalone: true, selector: "[cdkMenuItemCheckbox]", host: { attributes: { "role": "menuitemcheckbox" }, properties: { "class.cdk-menu-item-checkbox": "true" } }, providers: [
1754
- { provide: CdkMenuItemSelectable, useExisting: CdkMenuItemCheckbox },
1755
- { provide: CdkMenuItem, useExisting: CdkMenuItemSelectable },
1756
- ], exportAs: ["cdkMenuItemCheckbox"], usesInheritance: true, ngImport: i0 });
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({ minVersion: "12.0.0", version: "20.2.0-next.2", ngImport: i0, type: CdkMenuItemCheckbox, decorators: [{
1759
- type: Directive,
1760
- args: [{
1761
- selector: '[cdkMenuItemCheckbox]',
1762
- exportAs: 'cdkMenuItemCheckbox',
1763
- host: {
1764
- 'role': 'menuitemcheckbox',
1765
- '[class.cdk-menu-item-checkbox]': 'true',
1766
- },
1767
- providers: [
1768
- { provide: CdkMenuItemSelectable, useExisting: CdkMenuItemCheckbox },
1769
- { provide: CdkMenuItem, useExisting: CdkMenuItemSelectable },
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
- // In cases where the first menu item in the context menu is a trigger the submenu opens on a
1777
- // hover event. We offset the context menu 2px by default to prevent this from occurring.
1778
- const offsetX = position.overlayX === 'start' ? 2 : -2;
1779
- const offsetY = position.overlayY === 'top' ? 2 : -2;
1780
- return { ...position, offsetX, offsetY };
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
- _injector = inject(Injector);
1788
- _directionality = inject(Directionality, { optional: true });
1789
- /** The app's menu tracking registry */
1790
- _menuTracker = inject(MenuTracker);
1791
- _changeDetectorRef = inject(ChangeDetectorRef);
1792
- /** Whether the context menu is disabled. */
1793
- disabled = false;
1794
- constructor() {
1795
- super();
1796
- this._setMenuStackCloseListener();
1797
- }
1798
- /**
1799
- * Open the attached menu at the specified location.
1800
- * @param coordinates where to open the context menu
1801
- */
1802
- open(coordinates) {
1803
- this._open(null, coordinates);
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
- /** Close the currently opened context menu. */
1807
- close() {
1808
- this.menuStack.closeAll();
1809
- }
1810
- /**
1811
- * Open the context menu and closes any previously open menus.
1812
- * @param event the mouse event which opens the context menu.
1813
- */
1814
- _openOnContextMenu(event) {
1815
- if (!this.disabled) {
1816
- // Prevent the native context menu from opening because we're opening a custom one.
1817
- event.preventDefault();
1818
- // Stop event propagation to ensure that only the closest enabled context menu opens.
1819
- // Otherwise, any context menus attached to containing elements would *also* open,
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
- * Get the configuration object used to create the overlay.
1838
- * @param coordinates the location to place the opened menu
1839
- */
1840
- _getOverlayConfig(coordinates) {
1841
- return new OverlayConfig({
1842
- positionStrategy: this._getOverlayPositionStrategy(coordinates),
1843
- scrollStrategy: this.menuScrollStrategy(),
1844
- direction: this._directionality || undefined,
1845
- });
1846
- }
1847
- /**
1848
- * Get the position strategy for the overlay which specifies where to place the menu.
1849
- * @param coordinates the location to place the opened menu
1850
- */
1851
- _getOverlayPositionStrategy(coordinates) {
1852
- return createFlexibleConnectedPositionStrategy(this._injector, coordinates)
1853
- .withLockedPosition()
1854
- .withGrowAfterOpen()
1855
- .withPositions(this.menuPosition ?? CONTEXT_MENU_POSITIONS);
1856
- }
1857
- /** Subscribe to the menu stack close events and close this menu when requested. */
1858
- _setMenuStackCloseListener() {
1859
- this.menuStack.closed.pipe(takeUntil(this.destroyed)).subscribe(({ item }) => {
1860
- if (item === this.childMenu && this.isOpen()) {
1861
- this.closed.next();
1862
- this.overlayRef.detach();
1863
- this.childMenu = undefined;
1864
- this._changeDetectorRef.markForCheck();
1865
- }
1866
- });
1867
- }
1868
- /**
1869
- * Subscribe to the overlays outside pointer events stream and handle closing out the stack if a
1870
- * click occurs outside the menus.
1871
- * @param userEvent User-generated event that opened the menu.
1872
- */
1873
- _subscribeToOutsideClicks(userEvent) {
1874
- if (this.overlayRef) {
1875
- let outsideClicks = this.overlayRef.outsidePointerEvents();
1876
- if (userEvent) {
1877
- const [auxClicks, nonAuxClicks] = partition(outsideClicks, ({ type }) => type === 'auxclick');
1878
- outsideClicks = merge(
1879
- // Using a mouse, the `contextmenu` event can fire either when pressing the right button
1880
- // or left button + control. Most browsers won't dispatch a `click` event right after
1881
- // a `contextmenu` event triggered by left button + control, but Safari will (see #27832).
1882
- // This closes the menu immediately. To work around it, we check that both the triggering
1883
- // event and the current outside click event both had the control key pressed, and that
1884
- // that this is the first outside click event.
1885
- nonAuxClicks.pipe(skipWhile((event, index) => userEvent.ctrlKey && index === 0 && event.ctrlKey)),
1886
- // If the menu was triggered by the `contextmenu` event, skip the first `auxclick` event
1887
- // because it fires when the mouse is released on the same click that opened the menu.
1888
- auxClicks.pipe(skip(1)));
1889
- }
1890
- outsideClicks.pipe(takeUntil(this.stopOutsideClicksListener)).subscribe(event => {
1891
- if (!this.isElementInsideMenuStack(_getEventTarget(event))) {
1892
- this.menuStack.closeAll();
1893
- }
1894
- });
1895
- }
1896
- }
1897
- /**
1898
- * Open the attached menu at the specified location.
1899
- * @param userEvent User-generated event that opened the menu
1900
- * @param coordinates where to open the context menu
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({ minVersion: "12.0.0", version: "20.2.0-next.2", ngImport: i0, type: CdkContextMenuTrigger, decorators: [{
1933
- type: Directive,
1934
- args: [{
1935
- selector: '[cdkContextMenuTriggerFor]',
1936
- exportAs: 'cdkContextMenuTriggerFor',
1937
- host: {
1938
- '[attr.data-cdk-menu-stack-id]': 'null',
1939
- '(contextmenu)': '_openOnContextMenu($event)',
1940
- },
1941
- inputs: [
1942
- { name: 'menuTemplateRef', alias: 'cdkContextMenuTriggerFor' },
1943
- { name: 'menuPosition', alias: 'cdkContextMenuPosition' },
1944
- { name: 'menuData', alias: 'cdkContextMenuTriggerData' },
1945
- ],
1946
- outputs: ['opened: cdkContextMenuOpened', 'closed: cdkContextMenuClosed'],
1947
- providers: [
1948
- { provide: MENU_TRIGGER, useExisting: CdkContextMenuTrigger },
1949
- { provide: MENU_STACK, useClass: MenuStack },
1950
- ],
1951
- }]
1952
- }], ctorParameters: () => [], propDecorators: { disabled: [{
1953
- type: Input,
1954
- args: [{ alias: 'cdkContextMenuDisabled', transform: booleanAttribute }]
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
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0-next.2", ngImport: i0, type: CdkMenuModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1971
- static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.2.0-next.2", ngImport: i0, type: CdkMenuModule, imports: [OverlayModule, CdkMenuBar,
1972
- CdkMenu,
1973
- CdkMenuItem,
1974
- CdkMenuItemRadio,
1975
- CdkMenuItemCheckbox,
1976
- CdkMenuTrigger,
1977
- CdkMenuGroup,
1978
- CdkContextMenuTrigger,
1979
- CdkTargetMenuAim], exports: [CdkMenuBar,
1980
- CdkMenu,
1981
- CdkMenuItem,
1982
- CdkMenuItemRadio,
1983
- CdkMenuItemCheckbox,
1984
- CdkMenuTrigger,
1985
- CdkMenuGroup,
1986
- CdkContextMenuTrigger,
1987
- CdkTargetMenuAim] });
1988
- static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.2.0-next.2", ngImport: i0, type: CdkMenuModule, imports: [OverlayModule] });
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({ minVersion: "12.0.0", version: "20.2.0-next.2", ngImport: i0, type: CdkMenuModule, decorators: [{
1991
- type: NgModule,
1992
- args: [{
1993
- imports: [OverlayModule, ...MENU_DIRECTIVES],
1994
- exports: MENU_DIRECTIVES,
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