@angular/cdk-experimental 13.0.0-next.7 → 13.0.0-rc.2

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 (329) hide show
  1. package/column-resize/column-resize-directives/column-resize-flex.d.ts +3 -0
  2. package/column-resize/column-resize-directives/column-resize.d.ts +3 -0
  3. package/column-resize/column-resize-directives/default-enabled-column-resize-flex.d.ts +3 -0
  4. package/column-resize/column-resize-directives/default-enabled-column-resize.d.ts +3 -0
  5. package/column-resize/column-resize-module.d.ts +11 -7
  6. package/column-resize/column-resize-notifier.d.ts +5 -7
  7. package/column-resize/column-resize.d.ts +3 -0
  8. package/column-resize/column-resize_public_index.d.ts +4 -0
  9. package/column-resize/column-size-store.d.ts +3 -7
  10. package/column-resize/event-dispatcher.d.ts +3 -0
  11. package/column-resize/index.d.ts +5 -2
  12. package/column-resize/overlay-handle.d.ts +3 -0
  13. package/column-resize/package.json +6 -6
  14. package/column-resize/resizable.d.ts +3 -0
  15. package/column-resize/resize-strategy.d.ts +7 -0
  16. package/combobox/combobox-module.d.ts +8 -7
  17. package/combobox/combobox-panel.d.ts +5 -2
  18. package/combobox/combobox-popup.d.ts +3 -0
  19. package/combobox/combobox.d.ts +8 -5
  20. package/combobox/combobox_public_index.d.ts +4 -0
  21. package/combobox/index.d.ts +5 -1
  22. package/combobox/package.json +6 -6
  23. package/dialog/dialog-container.d.ts +4 -1
  24. package/dialog/dialog-module.d.ts +8 -7
  25. package/dialog/dialog.d.ts +3 -0
  26. package/dialog/dialog_public_index.d.ts +4 -0
  27. package/dialog/index.d.ts +5 -1
  28. package/dialog/package.json +6 -6
  29. package/esm2020/column-resize/column-resize-directives/column-resize-flex.mjs +42 -0
  30. package/esm2020/column-resize/column-resize-directives/column-resize.mjs +42 -0
  31. package/{esm2015/column-resize/column-resize-directives/constants.js → esm2020/column-resize/column-resize-directives/constants.mjs} +0 -0
  32. package/esm2020/column-resize/column-resize-directives/default-enabled-column-resize-flex.mjs +48 -0
  33. package/esm2020/column-resize/column-resize-directives/default-enabled-column-resize.mjs +48 -0
  34. package/esm2020/column-resize/column-resize-module.mjs +46 -0
  35. package/esm2020/column-resize/column-resize-notifier.mjs +52 -0
  36. package/esm2020/column-resize/column-resize.mjs +82 -0
  37. package/esm2020/column-resize/column-resize_public_index.mjs +5 -0
  38. package/esm2020/column-resize/column-size-store.mjs +20 -0
  39. package/esm2020/column-resize/event-dispatcher.mjs +70 -0
  40. package/esm2020/column-resize/index.mjs +9 -0
  41. package/esm2020/column-resize/overlay-handle.mjs +146 -0
  42. package/{esm2015/column-resize/public-api.js → esm2020/column-resize/public-api.mjs} +0 -0
  43. package/esm2020/column-resize/resizable.mjs +195 -0
  44. package/{esm2015/column-resize/resize-ref.js → esm2020/column-resize/resize-ref.mjs} +1 -1
  45. package/esm2020/column-resize/resize-strategy.mjs +230 -0
  46. package/{esm2015/column-resize/selectors.js → esm2020/column-resize/selectors.mjs} +0 -0
  47. package/esm2020/combobox/combobox-module.mjs +28 -0
  48. package/esm2020/combobox/combobox-panel.mjs +48 -0
  49. package/esm2020/combobox/combobox-popup.mjs +83 -0
  50. package/esm2020/combobox/combobox.mjs +261 -0
  51. package/esm2020/combobox/combobox_public_index.mjs +5 -0
  52. package/esm2020/combobox/index.mjs +9 -0
  53. package/{esm2015/combobox/public-api.js → esm2020/combobox/public-api.mjs} +0 -0
  54. package/{esm2015/dialog/dialog-config.js → esm2020/dialog/dialog-config.mjs} +0 -0
  55. package/esm2020/dialog/dialog-container.mjs +310 -0
  56. package/esm2020/dialog/dialog-injectors.mjs +30 -0
  57. package/esm2020/dialog/dialog-module.mjs +57 -0
  58. package/esm2020/dialog/dialog-ref.mjs +116 -0
  59. package/esm2020/dialog/dialog.mjs +252 -0
  60. package/esm2020/dialog/dialog_public_index.mjs +5 -0
  61. package/esm2020/dialog/index.mjs +9 -0
  62. package/{esm2015/dialog/public-api.js → esm2020/dialog/public-api.mjs} +0 -0
  63. package/{esm2015/index.js → esm2020/index.mjs} +0 -0
  64. package/esm2020/listbox/index.mjs +9 -0
  65. package/esm2020/listbox/listbox-module.mjs +24 -0
  66. package/esm2020/listbox/listbox.mjs +499 -0
  67. package/esm2020/listbox/listbox_public_index.mjs +5 -0
  68. package/{esm2015/listbox/public-api.js → esm2020/listbox/public-api.mjs} +0 -0
  69. package/esm2020/menu/context-menu.mjs +287 -0
  70. package/esm2020/menu/index.mjs +9 -0
  71. package/esm2020/menu/menu-aim.mjs +199 -0
  72. package/esm2020/menu/menu-bar.mjs +272 -0
  73. package/{esm2015/menu/menu-errors.js → esm2020/menu/menu-errors.mjs} +1 -1
  74. package/esm2020/menu/menu-group.mjs +68 -0
  75. package/{esm2015/menu/menu-interface.js → esm2020/menu/menu-interface.mjs} +0 -0
  76. package/esm2020/menu/menu-item-checkbox.mjs +48 -0
  77. package/esm2020/menu/menu-item-radio.mjs +90 -0
  78. package/esm2020/menu/menu-item-selectable.mjs +57 -0
  79. package/esm2020/menu/menu-item-trigger.mjs +361 -0
  80. package/esm2020/menu/menu-item.mjs +291 -0
  81. package/esm2020/menu/menu-module.mjs +64 -0
  82. package/esm2020/menu/menu-panel.mjs +37 -0
  83. package/{esm2015/menu/menu-stack.js → esm2020/menu/menu-stack.mjs} +0 -0
  84. package/esm2020/menu/menu.mjs +316 -0
  85. package/esm2020/menu/menu_public_index.mjs +5 -0
  86. package/{esm2015/menu/pointer-focus-tracker.js → esm2020/menu/pointer-focus-tracker.mjs} +1 -1
  87. package/{esm2015/menu/public-api.js → esm2020/menu/public-api.mjs} +0 -0
  88. package/{esm2015/popover-edit/constants.js → esm2020/popover-edit/constants.mjs} +0 -0
  89. package/esm2020/popover-edit/edit-event-dispatcher.mjs +215 -0
  90. package/esm2020/popover-edit/edit-ref.mjs +84 -0
  91. package/esm2020/popover-edit/edit-services.mjs +48 -0
  92. package/esm2020/popover-edit/focus-dispatcher.mjs +82 -0
  93. package/esm2020/popover-edit/focus-escape-notifier.mjs +63 -0
  94. package/{esm2015/popover-edit/form-value-container.js → esm2020/popover-edit/form-value-container.mjs} +0 -0
  95. package/esm2020/popover-edit/index.mjs +9 -0
  96. package/esm2020/popover-edit/lens-directives.mjs +210 -0
  97. package/esm2020/popover-edit/polyfill.mjs +37 -0
  98. package/esm2020/popover-edit/popover-edit-module.mjs +62 -0
  99. package/esm2020/popover-edit/popover-edit-position-strategy-factory.mjs +76 -0
  100. package/esm2020/popover-edit/popover-edit_public_index.mjs +5 -0
  101. package/{esm2015/popover-edit/public-api.js → esm2020/popover-edit/public-api.mjs} +0 -0
  102. package/esm2020/popover-edit/table-directives.mjs +400 -0
  103. package/{esm2015/public-api.js → esm2020/public-api.mjs} +0 -0
  104. package/esm2020/scrolling/auto-size-virtual-scroll.mjs +421 -0
  105. package/esm2020/scrolling/index.mjs +9 -0
  106. package/{esm2015/scrolling/public-api.js → esm2020/scrolling/public-api.mjs} +0 -0
  107. package/esm2020/scrolling/scrolling-module.mjs +23 -0
  108. package/esm2020/scrolling/scrolling_public_index.mjs +5 -0
  109. package/esm2020/selection/index.mjs +9 -0
  110. package/{esm2015/selection/public-api.js → esm2020/selection/public-api.mjs} +0 -0
  111. package/esm2020/selection/row-selection.mjs +49 -0
  112. package/esm2020/selection/select-all.mjs +109 -0
  113. package/esm2020/selection/selection-column.mjs +134 -0
  114. package/esm2020/selection/selection-module.mjs +40 -0
  115. package/{esm2015/selection/selection-set.js → esm2020/selection/selection-set.mjs} +1 -1
  116. package/esm2020/selection/selection-toggle.mjs +101 -0
  117. package/esm2020/selection/selection.mjs +186 -0
  118. package/esm2020/selection/selection_public_index.mjs +5 -0
  119. package/esm2020/table-scroll-container/index.mjs +9 -0
  120. package/{esm2015/table-scroll-container/public-api.js → esm2020/table-scroll-container/public-api.mjs} +0 -0
  121. package/esm2020/table-scroll-container/table-scroll-container-module.mjs +23 -0
  122. package/esm2020/table-scroll-container/table-scroll-container.mjs +131 -0
  123. package/esm2020/table-scroll-container/table-scroll-container_public_index.mjs +5 -0
  124. package/{esm2015/version.js → esm2020/version.mjs} +1 -1
  125. package/fesm2015/{cdk-experimental.js → cdk-experimental.mjs} +2 -2
  126. package/fesm2015/cdk-experimental.mjs.map +1 -0
  127. package/fesm2015/{column-resize.js → column-resize.mjs} +213 -175
  128. package/fesm2015/column-resize.mjs.map +1 -0
  129. package/fesm2015/{combobox.js → combobox.mjs} +134 -102
  130. package/fesm2015/combobox.mjs.map +1 -0
  131. package/fesm2015/dialog.mjs +813 -0
  132. package/fesm2015/dialog.mjs.map +1 -0
  133. package/fesm2015/{listbox.js → listbox.mjs} +128 -91
  134. package/fesm2015/listbox.mjs.map +1 -0
  135. package/fesm2015/{menu.js → menu.mjs} +576 -397
  136. package/fesm2015/menu.mjs.map +1 -0
  137. package/fesm2015/{popover-edit.js → popover-edit.mjs} +257 -230
  138. package/fesm2015/popover-edit.mjs.map +1 -0
  139. package/fesm2015/{scrolling.js → scrolling.mjs} +66 -36
  140. package/fesm2015/scrolling.mjs.map +1 -0
  141. package/fesm2015/selection.mjs +693 -0
  142. package/fesm2015/selection.mjs.map +1 -0
  143. package/fesm2015/{table-scroll-container.js → table-scroll-container.mjs} +43 -30
  144. package/fesm2015/table-scroll-container.mjs.map +1 -0
  145. package/fesm2020/cdk-experimental.mjs +30 -0
  146. package/fesm2020/cdk-experimental.mjs.map +1 -0
  147. package/fesm2020/column-resize.mjs +1016 -0
  148. package/fesm2020/column-resize.mjs.map +1 -0
  149. package/fesm2020/combobox.mjs +430 -0
  150. package/fesm2020/combobox.mjs.map +1 -0
  151. package/{fesm2015/dialog.js → fesm2020/dialog.mjs} +156 -104
  152. package/fesm2020/dialog.mjs.map +1 -0
  153. package/fesm2020/listbox.mjs +541 -0
  154. package/fesm2020/listbox.mjs.map +1 -0
  155. package/fesm2020/menu.mjs +2202 -0
  156. package/fesm2020/menu.mjs.map +1 -0
  157. package/fesm2020/popover-edit.mjs +1289 -0
  158. package/fesm2020/popover-edit.mjs.map +1 -0
  159. package/fesm2020/scrolling.mjs +464 -0
  160. package/fesm2020/scrolling.mjs.map +1 -0
  161. package/{fesm2015/selection.js → fesm2020/selection.mjs} +195 -107
  162. package/fesm2020/selection.mjs.map +1 -0
  163. package/fesm2020/table-scroll-container.mjs +173 -0
  164. package/fesm2020/table-scroll-container.mjs.map +1 -0
  165. package/listbox/index.d.ts +5 -1
  166. package/listbox/listbox-module.d.ts +5 -7
  167. package/listbox/listbox.d.ts +5 -0
  168. package/listbox/listbox_public_index.d.ts +4 -0
  169. package/listbox/package.json +6 -6
  170. package/menu/context-menu.d.ts +5 -0
  171. package/menu/index.d.ts +5 -3
  172. package/menu/menu-aim.d.ts +5 -0
  173. package/menu/menu-bar.d.ts +3 -0
  174. package/menu/menu-group.d.ts +3 -0
  175. package/menu/menu-item-checkbox.d.ts +3 -7
  176. package/menu/menu-item-radio.d.ts +3 -0
  177. package/menu/menu-item-selectable.d.ts +3 -0
  178. package/menu/menu-item-trigger.d.ts +3 -0
  179. package/menu/menu-item.d.ts +3 -0
  180. package/menu/menu-module.d.ts +15 -7
  181. package/menu/menu-panel.d.ts +3 -0
  182. package/menu/menu.d.ts +3 -0
  183. package/menu/menu_public_index.d.ts +4 -0
  184. package/menu/package.json +6 -6
  185. package/package.json +94 -8
  186. package/popover-edit/edit-event-dispatcher.d.ts +3 -0
  187. package/popover-edit/edit-ref.d.ts +3 -0
  188. package/popover-edit/edit-services.d.ts +3 -0
  189. package/popover-edit/focus-dispatcher.d.ts +3 -0
  190. package/popover-edit/focus-escape-notifier.d.ts +3 -0
  191. package/popover-edit/index.d.ts +5 -3
  192. package/popover-edit/lens-directives.d.ts +7 -0
  193. package/popover-edit/package.json +6 -6
  194. package/popover-edit/popover-edit-module.d.ts +7 -7
  195. package/popover-edit/popover-edit-position-strategy-factory.d.ts +5 -0
  196. package/popover-edit/popover-edit_public_index.d.ts +4 -0
  197. package/popover-edit/table-directives.d.ts +11 -0
  198. package/scrolling/auto-size-virtual-scroll.d.ts +3 -0
  199. package/scrolling/index.d.ts +5 -1
  200. package/scrolling/package.json +6 -6
  201. package/scrolling/scrolling-module.d.ts +5 -7
  202. package/scrolling/scrolling_public_index.d.ts +4 -0
  203. package/selection/index.d.ts +5 -1
  204. package/selection/package.json +6 -6
  205. package/selection/row-selection.d.ts +3 -0
  206. package/selection/select-all.d.ts +3 -0
  207. package/selection/selection-column.d.ts +3 -0
  208. package/selection/selection-module.d.ts +11 -7
  209. package/selection/selection-toggle.d.ts +3 -0
  210. package/selection/selection.d.ts +3 -0
  211. package/selection/selection_public_index.d.ts +4 -0
  212. package/table-scroll-container/index.d.ts +5 -1
  213. package/table-scroll-container/package.json +6 -6
  214. package/table-scroll-container/table-scroll-container-module.d.ts +5 -7
  215. package/table-scroll-container/table-scroll-container.d.ts +3 -0
  216. package/table-scroll-container/table-scroll-container_public_index.d.ts +4 -0
  217. package/bundles/cdk-experimental-column-resize.umd.js +0 -1324
  218. package/bundles/cdk-experimental-column-resize.umd.js.map +0 -1
  219. package/bundles/cdk-experimental-combobox.umd.js +0 -443
  220. package/bundles/cdk-experimental-combobox.umd.js.map +0 -1
  221. package/bundles/cdk-experimental-dialog.umd.js +0 -1113
  222. package/bundles/cdk-experimental-dialog.umd.js.map +0 -1
  223. package/bundles/cdk-experimental-listbox.umd.js +0 -935
  224. package/bundles/cdk-experimental-listbox.umd.js.map +0 -1
  225. package/bundles/cdk-experimental-menu.umd.js +0 -2461
  226. package/bundles/cdk-experimental-menu.umd.js.map +0 -1
  227. package/bundles/cdk-experimental-popover-edit.umd.js +0 -1679
  228. package/bundles/cdk-experimental-popover-edit.umd.js.map +0 -1
  229. package/bundles/cdk-experimental-scrolling.umd.js +0 -459
  230. package/bundles/cdk-experimental-scrolling.umd.js.map +0 -1
  231. package/bundles/cdk-experimental-selection.umd.js +0 -961
  232. package/bundles/cdk-experimental-selection.umd.js.map +0 -1
  233. package/bundles/cdk-experimental-table-scroll-container.umd.js +0 -499
  234. package/bundles/cdk-experimental-table-scroll-container.umd.js.map +0 -1
  235. package/bundles/cdk-experimental.umd.js +0 -38
  236. package/bundles/cdk-experimental.umd.js.map +0 -1
  237. package/column-resize/index.metadata.json +0 -1
  238. package/combobox/index.metadata.json +0 -1
  239. package/dialog/index.metadata.json +0 -1
  240. package/esm2015/cdk-experimental.externs.js +0 -0
  241. package/esm2015/column-resize/column-resize-directives/column-resize-flex.js +0 -46
  242. package/esm2015/column-resize/column-resize-directives/column-resize.js +0 -46
  243. package/esm2015/column-resize/column-resize-directives/default-enabled-column-resize-flex.js +0 -46
  244. package/esm2015/column-resize/column-resize-directives/default-enabled-column-resize.js +0 -46
  245. package/esm2015/column-resize/column-resize-module.js +0 -37
  246. package/esm2015/column-resize/column-resize-notifier.js +0 -45
  247. package/esm2015/column-resize/column-resize.externs.js +0 -6
  248. package/esm2015/column-resize/column-resize.js +0 -71
  249. package/esm2015/column-resize/column-size-store.js +0 -17
  250. package/esm2015/column-resize/event-dispatcher.js +0 -70
  251. package/esm2015/column-resize/index.js +0 -6
  252. package/esm2015/column-resize/overlay-handle.js +0 -139
  253. package/esm2015/column-resize/resizable.js +0 -185
  254. package/esm2015/column-resize/resize-strategy.js +0 -227
  255. package/esm2015/combobox/combobox-module.js +0 -23
  256. package/esm2015/combobox/combobox-panel.js +0 -55
  257. package/esm2015/combobox/combobox-popup.js +0 -74
  258. package/esm2015/combobox/combobox.externs.js +0 -6
  259. package/esm2015/combobox/combobox.js +0 -248
  260. package/esm2015/combobox/index.js +0 -5
  261. package/esm2015/dialog/dialog-container.js +0 -289
  262. package/esm2015/dialog/dialog-injectors.js +0 -30
  263. package/esm2015/dialog/dialog-module.js +0 -47
  264. package/esm2015/dialog/dialog-ref.js +0 -115
  265. package/esm2015/dialog/dialog.externs.js +0 -6
  266. package/esm2015/dialog/dialog.js +0 -238
  267. package/esm2015/dialog/index.js +0 -5
  268. package/esm2015/listbox/index.js +0 -5
  269. package/esm2015/listbox/listbox-module.js +0 -19
  270. package/esm2015/listbox/listbox.externs.js +0 -6
  271. package/esm2015/listbox/listbox.js +0 -481
  272. package/esm2015/menu/context-menu.js +0 -280
  273. package/esm2015/menu/index.js +0 -6
  274. package/esm2015/menu/menu-aim.js +0 -195
  275. package/esm2015/menu/menu-bar.js +0 -252
  276. package/esm2015/menu/menu-group.js +0 -63
  277. package/esm2015/menu/menu-item-checkbox.js +0 -41
  278. package/esm2015/menu/menu-item-radio.js +0 -73
  279. package/esm2015/menu/menu-item-selectable.js +0 -51
  280. package/esm2015/menu/menu-item-trigger.js +0 -354
  281. package/esm2015/menu/menu-item.js +0 -253
  282. package/esm2015/menu/menu-module.js +0 -41
  283. package/esm2015/menu/menu-panel.js +0 -37
  284. package/esm2015/menu/menu.externs.js +0 -6
  285. package/esm2015/menu/menu.js +0 -293
  286. package/esm2015/popover-edit/edit-event-dispatcher.js +0 -215
  287. package/esm2015/popover-edit/edit-ref.js +0 -82
  288. package/esm2015/popover-edit/edit-services.js +0 -49
  289. package/esm2015/popover-edit/focus-dispatcher.js +0 -83
  290. package/esm2015/popover-edit/focus-escape-notifier.js +0 -64
  291. package/esm2015/popover-edit/index.js +0 -7
  292. package/esm2015/popover-edit/lens-directives.js +0 -199
  293. package/esm2015/popover-edit/polyfill.js +0 -35
  294. package/esm2015/popover-edit/popover-edit-module.js +0 -38
  295. package/esm2015/popover-edit/popover-edit-position-strategy-factory.js +0 -70
  296. package/esm2015/popover-edit/popover-edit.externs.js +0 -6
  297. package/esm2015/popover-edit/table-directives.js +0 -390
  298. package/esm2015/scrolling/auto-size-virtual-scroll.js +0 -403
  299. package/esm2015/scrolling/index.js +0 -5
  300. package/esm2015/scrolling/scrolling-module.js +0 -18
  301. package/esm2015/scrolling/scrolling.externs.js +0 -6
  302. package/esm2015/selection/index.js +0 -5
  303. package/esm2015/selection/row-selection.js +0 -41
  304. package/esm2015/selection/select-all.js +0 -96
  305. package/esm2015/selection/selection-column.js +0 -93
  306. package/esm2015/selection/selection-module.js +0 -40
  307. package/esm2015/selection/selection-toggle.js +0 -82
  308. package/esm2015/selection/selection.externs.js +0 -6
  309. package/esm2015/selection/selection.js +0 -176
  310. package/esm2015/table-scroll-container/index.js +0 -5
  311. package/esm2015/table-scroll-container/table-scroll-container-module.js +0 -18
  312. package/esm2015/table-scroll-container/table-scroll-container.externs.js +0 -6
  313. package/esm2015/table-scroll-container/table-scroll-container.js +0 -133
  314. package/fesm2015/cdk-experimental.js.map +0 -1
  315. package/fesm2015/column-resize.js.map +0 -1
  316. package/fesm2015/combobox.js.map +0 -1
  317. package/fesm2015/dialog.js.map +0 -1
  318. package/fesm2015/listbox.js.map +0 -1
  319. package/fesm2015/menu.js.map +0 -1
  320. package/fesm2015/popover-edit.js.map +0 -1
  321. package/fesm2015/scrolling.js.map +0 -1
  322. package/fesm2015/selection.js.map +0 -1
  323. package/fesm2015/table-scroll-container.js.map +0 -1
  324. package/listbox/index.metadata.json +0 -1
  325. package/menu/index.metadata.json +0 -1
  326. package/popover-edit/index.metadata.json +0 -1
  327. package/scrolling/index.metadata.json +0 -1
  328. package/selection/index.metadata.json +0 -1
  329. package/table-scroll-container/index.metadata.json +0 -1
@@ -0,0 +1,2202 @@
1
+ import * as i0 from '@angular/core';
2
+ import { InjectionToken, Injectable, Directive, EventEmitter, Optional, Inject, Input, Output, Self, HostListener, ContentChildren, NgModule } from '@angular/core';
3
+ import * as i1 from '@angular/cdk/overlay';
4
+ import { OverlayConfig, OverlayModule } from '@angular/cdk/overlay';
5
+ import { FocusKeyManager } from '@angular/cdk/a11y';
6
+ import { UP_ARROW, DOWN_ARROW, LEFT_ARROW, RIGHT_ARROW, ENTER, SPACE, TAB, ESCAPE, hasModifierKey } from '@angular/cdk/keycodes';
7
+ import * as i2 from '@angular/cdk/bidi';
8
+ import { Subject, fromEvent, merge, defer } from 'rxjs';
9
+ import { filter, takeUntil, startWith, mergeMap, mapTo, mergeAll, take, switchMap } from 'rxjs/operators';
10
+ import * as i1$1 from '@angular/cdk/collections';
11
+ import { UniqueSelectionDispatcher } from '@angular/cdk/collections';
12
+ import { coerceBooleanProperty } from '@angular/cdk/coercion';
13
+ import { TemplatePortal } from '@angular/cdk/portal';
14
+
15
+ /**
16
+ * @license
17
+ * Copyright Google LLC All Rights Reserved.
18
+ *
19
+ * Use of this source code is governed by an MIT-style license that can be
20
+ * found in the LICENSE file at https://angular.io/license
21
+ */
22
+ /** Injection token used to return classes implementing the Menu interface */
23
+ const CDK_MENU = new InjectionToken('cdk-menu');
24
+
25
+ /**
26
+ * @license
27
+ * Copyright Google LLC All Rights Reserved.
28
+ *
29
+ * Use of this source code is governed by an MIT-style license that can be
30
+ * found in the LICENSE file at https://angular.io/license
31
+ */
32
+ /**
33
+ * MenuStack allows subscribers to listen for close events (when a MenuStackItem is popped off
34
+ * of the stack) in order to perform closing actions. Upon the MenuStack being empty it emits
35
+ * from the `empty` observable specifying the next focus action which the listener should perform
36
+ * as requested by the closer.
37
+ */
38
+ class MenuStack {
39
+ constructor() {
40
+ /** All MenuStackItems tracked by this MenuStack. */
41
+ this._elements = [];
42
+ /** Emits the element which was popped off of the stack when requested by a closer. */
43
+ this._close = new Subject();
44
+ /** Emits once the MenuStack has become empty after popping off elements. */
45
+ this._empty = new Subject();
46
+ /** Observable which emits the MenuStackItem which has been requested to close. */
47
+ this.closed = this._close;
48
+ /**
49
+ * Observable which emits when the MenuStack is empty after popping off the last element. It
50
+ * emits a FocusNext event which specifies the action the closer has requested the listener
51
+ * perform.
52
+ */
53
+ this.emptied = this._empty;
54
+ }
55
+ /** @param menu the MenuStackItem to put on the stack. */
56
+ push(menu) {
57
+ this._elements.push(menu);
58
+ }
59
+ /**
60
+ * Pop items off of the stack up to and including `lastItem` and emit each on the close
61
+ * observable. If the stack is empty or `lastItem` is not on the stack it does nothing.
62
+ * @param lastItem the last item to pop off the stack.
63
+ * @param focusNext the event to emit on the `empty` observable if the method call resulted in an
64
+ * empty stack. Does not emit if the stack was initially empty or if `lastItem` was not on the
65
+ * stack.
66
+ */
67
+ close(lastItem, focusNext) {
68
+ if (this._elements.indexOf(lastItem) >= 0) {
69
+ let poppedElement;
70
+ do {
71
+ poppedElement = this._elements.pop();
72
+ this._close.next(poppedElement);
73
+ } while (poppedElement !== lastItem);
74
+ if (this.isEmpty()) {
75
+ this._empty.next(focusNext);
76
+ }
77
+ }
78
+ }
79
+ /**
80
+ * Pop items off of the stack up to but excluding `lastItem` and emit each on the close
81
+ * observable. If the stack is empty or `lastItem` is not on the stack it does nothing.
82
+ * @param lastItem the element which should be left on the stack
83
+ * @return whether or not an item was removed from the stack
84
+ */
85
+ closeSubMenuOf(lastItem) {
86
+ let removed = false;
87
+ if (this._elements.indexOf(lastItem) >= 0) {
88
+ removed = this.peek() !== lastItem;
89
+ while (this.peek() !== lastItem) {
90
+ this._close.next(this._elements.pop());
91
+ }
92
+ }
93
+ return removed;
94
+ }
95
+ /**
96
+ * Pop off all MenuStackItems and emit each one on the `close` observable one by one.
97
+ * @param focusNext the event to emit on the `empty` observable once the stack is emptied. Does
98
+ * not emit if the stack was initially empty.
99
+ */
100
+ closeAll(focusNext) {
101
+ if (!this.isEmpty()) {
102
+ while (!this.isEmpty()) {
103
+ const menuStackItem = this._elements.pop();
104
+ if (menuStackItem) {
105
+ this._close.next(menuStackItem);
106
+ }
107
+ }
108
+ this._empty.next(focusNext);
109
+ }
110
+ }
111
+ /** Return true if this stack is empty. */
112
+ isEmpty() {
113
+ return !this._elements.length;
114
+ }
115
+ /** Return the length of the stack. */
116
+ length() {
117
+ return this._elements.length;
118
+ }
119
+ /** Get the top most element on the stack. */
120
+ peek() {
121
+ return this._elements[this._elements.length - 1];
122
+ }
123
+ }
124
+ /** NoopMenuStack is a placeholder MenuStack used for inline menus. */
125
+ class NoopMenuStack extends MenuStack {
126
+ /** Noop push - does not add elements to the MenuStack. */
127
+ push(_) { }
128
+ }
129
+
130
+ /**
131
+ * @license
132
+ * Copyright Google LLC All Rights Reserved.
133
+ *
134
+ * Use of this source code is governed by an MIT-style license that can be
135
+ * found in the LICENSE file at https://angular.io/license
136
+ */
137
+ /**
138
+ * Throws an exception when a menu panel already has a menu stack.
139
+ * @docs-private
140
+ */
141
+ function throwExistingMenuStackError() {
142
+ throw Error('CdkMenuPanel is already referenced by different CdkMenuTrigger. Ensure that a menu is' +
143
+ ' opened by a single trigger only.');
144
+ }
145
+ /**
146
+ * Throws an exception when an instance of the PointerFocusTracker is not provided.
147
+ * @docs-private
148
+ */
149
+ function throwMissingPointerFocusTracker() {
150
+ throw Error('expected an instance of PointerFocusTracker to be provided');
151
+ }
152
+ /**
153
+ * Throws an exception when a reference to the parent menu is not provided.
154
+ * @docs-private
155
+ */
156
+ function throwMissingMenuReference() {
157
+ throw Error('expected a reference to the parent menu');
158
+ }
159
+
160
+ /**
161
+ * @license
162
+ * Copyright Google LLC All Rights Reserved.
163
+ *
164
+ * Use of this source code is governed by an MIT-style license that can be
165
+ * found in the LICENSE file at https://angular.io/license
166
+ */
167
+ /** Injection token used for an implementation of MenuAim. */
168
+ const MENU_AIM = new InjectionToken('cdk-menu-aim');
169
+ /** Capture every nth mouse move event. */
170
+ const MOUSE_MOVE_SAMPLE_FREQUENCY = 3;
171
+ /** The number of mouse move events to track. */
172
+ const NUM_POINTS = 5;
173
+ /**
174
+ * How long to wait before closing a sibling menu if a user stops short of the submenu they were
175
+ * predicted to go into.
176
+ */
177
+ const CLOSE_DELAY = 300;
178
+ /** Calculate the slope between point a and b. */
179
+ function getSlope(a, b) {
180
+ return (b.y - a.y) / (b.x - a.x);
181
+ }
182
+ /** Calculate the y intercept for the given point and slope. */
183
+ function getYIntercept(point, slope) {
184
+ return point.y - slope * point.x;
185
+ }
186
+ /**
187
+ * Whether the given mouse trajectory line defined by the slope and y intercept falls within the
188
+ * submenu as defined by `submenuPoints`
189
+ * @param submenuPoints the submenu DOMRect points.
190
+ * @param m the slope of the trajectory line.
191
+ * @param b the y intercept of the trajectory line.
192
+ *
193
+ * @return true if any point on the line falls within the submenu.
194
+ */
195
+ function isWithinSubmenu(submenuPoints, m, b) {
196
+ const { left, right, top, bottom } = submenuPoints;
197
+ // Check for intersection with each edge of the submenu (left, right, top, bottom)
198
+ // by fixing one coordinate to that edge's coordinate (either x or y) and checking if the
199
+ // other coordinate is within bounds.
200
+ return ((m * left + b >= top && m * left + b <= bottom) ||
201
+ (m * right + b >= top && m * right + b <= bottom) ||
202
+ ((top - b) / m >= left && (top - b) / m <= right) ||
203
+ ((bottom - b) / m >= left && (bottom - b) / m <= right));
204
+ }
205
+ /**
206
+ * TargetMenuAim predicts if a user is moving into a submenu. It calculates the
207
+ * trajectory of the user's mouse movement in the current menu to determine if the
208
+ * mouse is moving towards an open submenu.
209
+ *
210
+ * The determination is made by calculating the slope of the users last NUM_POINTS moves where each
211
+ * pair of points determines if the trajectory line points into the submenu. It uses consensus
212
+ * approach by checking if at least NUM_POINTS / 2 pairs determine that the user is moving towards
213
+ * to submenu.
214
+ */
215
+ class TargetMenuAim {
216
+ constructor(_ngZone) {
217
+ this._ngZone = _ngZone;
218
+ /** The last NUM_POINTS mouse move events. */
219
+ this._points = [];
220
+ /** Emits when this service is destroyed. */
221
+ this._destroyed = new Subject();
222
+ }
223
+ /** Set the Menu and its PointerFocusTracker. */
224
+ initialize(menu, pointerTracker) {
225
+ this._menu = menu;
226
+ this._pointerTracker = pointerTracker;
227
+ this._subscribeToMouseMoves();
228
+ }
229
+ /**
230
+ * Calls the `doToggle` callback when it is deemed that the user is not moving towards
231
+ * the submenu.
232
+ * @param doToggle the function called when the user is not moving towards the submenu.
233
+ */
234
+ toggle(doToggle) {
235
+ // If the menu is horizontal the sub-menus open below and there is no risk of premature
236
+ // closing of any sub-menus therefore we automatically resolve the callback.
237
+ if (this._menu.orientation === 'horizontal') {
238
+ doToggle();
239
+ }
240
+ this._checkConfigured();
241
+ const siblingItemIsWaiting = !!this._timeoutId;
242
+ const hasPoints = this._points.length > 1;
243
+ if (hasPoints && !siblingItemIsWaiting) {
244
+ if (this._isMovingToSubmenu()) {
245
+ this._startTimeout(doToggle);
246
+ }
247
+ else {
248
+ doToggle();
249
+ }
250
+ }
251
+ else if (!siblingItemIsWaiting) {
252
+ doToggle();
253
+ }
254
+ }
255
+ /**
256
+ * Start the delayed toggle handler if one isn't running already.
257
+ *
258
+ * The delayed toggle handler executes the `doToggle` callback after some period of time iff the
259
+ * users mouse is on an item in the current menu.
260
+ */
261
+ _startTimeout(doToggle) {
262
+ // If the users mouse is moving towards a submenu we don't want to immediately resolve.
263
+ // Wait for some period of time before determining if the previous menu should close in
264
+ // cases where the user may have moved towards the submenu but stopped on a sibling menu
265
+ // item intentionally.
266
+ const timeoutId = setTimeout(() => {
267
+ // Resolve if the user is currently moused over some element in the root menu
268
+ if (this._pointerTracker.activeElement && timeoutId === this._timeoutId) {
269
+ doToggle();
270
+ }
271
+ this._timeoutId = null;
272
+ }, CLOSE_DELAY);
273
+ this._timeoutId = timeoutId;
274
+ }
275
+ /** Whether the user is heading towards the open submenu. */
276
+ _isMovingToSubmenu() {
277
+ const submenuPoints = this._getSubmenuBounds();
278
+ if (!submenuPoints) {
279
+ return false;
280
+ }
281
+ let numMoving = 0;
282
+ const currPoint = this._points[this._points.length - 1];
283
+ // start from the second last point and calculate the slope between each point and the last
284
+ // point.
285
+ for (let i = this._points.length - 2; i >= 0; i--) {
286
+ const previous = this._points[i];
287
+ const slope = getSlope(currPoint, previous);
288
+ if (isWithinSubmenu(submenuPoints, slope, getYIntercept(currPoint, slope))) {
289
+ numMoving++;
290
+ }
291
+ }
292
+ return numMoving >= Math.floor(NUM_POINTS / 2);
293
+ }
294
+ /** Get the bounding DOMRect for the open submenu. */
295
+ _getSubmenuBounds() {
296
+ return this._pointerTracker?.previousElement
297
+ ?.getMenu()
298
+ ?._elementRef.nativeElement.getBoundingClientRect();
299
+ }
300
+ /**
301
+ * Check if a reference to the PointerFocusTracker and menu element is provided.
302
+ * @throws an error if neither reference is provided.
303
+ */
304
+ _checkConfigured() {
305
+ if (typeof ngDevMode === 'undefined' || ngDevMode) {
306
+ if (!this._pointerTracker) {
307
+ throwMissingPointerFocusTracker();
308
+ }
309
+ if (!this._menu) {
310
+ throwMissingMenuReference();
311
+ }
312
+ }
313
+ }
314
+ /** Subscribe to the root menus mouse move events and update the tracked mouse points. */
315
+ _subscribeToMouseMoves() {
316
+ this._ngZone.runOutsideAngular(() => {
317
+ fromEvent(this._menu._elementRef.nativeElement, 'mousemove')
318
+ .pipe(filter((_, index) => index % MOUSE_MOVE_SAMPLE_FREQUENCY === 0), takeUntil(this._destroyed))
319
+ .subscribe((event) => {
320
+ this._points.push({ x: event.clientX, y: event.clientY });
321
+ if (this._points.length > NUM_POINTS) {
322
+ this._points.shift();
323
+ }
324
+ });
325
+ });
326
+ }
327
+ ngOnDestroy() {
328
+ this._destroyed.next();
329
+ this._destroyed.complete();
330
+ }
331
+ }
332
+ TargetMenuAim.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.0-next.15", ngImport: i0, type: TargetMenuAim, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
333
+ TargetMenuAim.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.0.0-next.15", ngImport: i0, type: TargetMenuAim });
334
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.0-next.15", ngImport: i0, type: TargetMenuAim, decorators: [{
335
+ type: Injectable
336
+ }], ctorParameters: function () { return [{ type: i0.NgZone }]; } });
337
+ /**
338
+ * CdkTargetMenuAim is a provider for the TargetMenuAim service. It should be added to an
339
+ * element with either the `cdkMenu` or `cdkMenuBar` directive and child menu items.
340
+ */
341
+ class CdkTargetMenuAim {
342
+ }
343
+ CdkTargetMenuAim.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.0-next.15", ngImport: i0, type: CdkTargetMenuAim, deps: [], target: i0.ɵɵFactoryTarget.Directive });
344
+ CdkTargetMenuAim.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.0.0-next.15", type: CdkTargetMenuAim, selector: "[cdkTargetMenuAim]", providers: [{ provide: MENU_AIM, useClass: TargetMenuAim }], exportAs: ["cdkTargetMenuAim"], ngImport: i0 });
345
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.0-next.15", ngImport: i0, type: CdkTargetMenuAim, decorators: [{
346
+ type: Directive,
347
+ args: [{
348
+ selector: '[cdkTargetMenuAim]',
349
+ exportAs: 'cdkTargetMenuAim',
350
+ providers: [{ provide: MENU_AIM, useClass: TargetMenuAim }],
351
+ }]
352
+ }] });
353
+
354
+ /**
355
+ * @license
356
+ * Copyright Google LLC All Rights Reserved.
357
+ *
358
+ * Use of this source code is governed by an MIT-style license that can be
359
+ * found in the LICENSE file at https://angular.io/license
360
+ */
361
+ /**
362
+ * Whether the target element is a menu item to be ignored by the overlay background click handler.
363
+ */
364
+ function isClickInsideMenuOverlay(target) {
365
+ while (target?.parentElement) {
366
+ const isOpenTrigger = target.getAttribute('aria-expanded') === 'true' &&
367
+ target.classList.contains('cdk-menu-trigger');
368
+ const isOverlayMenu = target.classList.contains('cdk-menu') && !target.classList.contains('cdk-menu-inline');
369
+ if (isOpenTrigger || isOverlayMenu) {
370
+ return true;
371
+ }
372
+ target = target.parentElement;
373
+ }
374
+ return false;
375
+ }
376
+ /**
377
+ * A directive to be combined with CdkMenuItem which opens the Menu it is bound to. If the
378
+ * element is in a top level MenuBar it will open the menu on click, or if a sibling is already
379
+ * opened it will open on hover. If it is inside of a Menu it will open the attached Submenu on
380
+ * hover regardless of its sibling state.
381
+ *
382
+ * The directive must be placed along with the `cdkMenuItem` directive in order to enable full
383
+ * functionality.
384
+ */
385
+ class CdkMenuItemTrigger {
386
+ constructor(_elementRef, _viewContainerRef, _overlay, _ngZone, _parentMenu, _menuAim, _directionality) {
387
+ this._elementRef = _elementRef;
388
+ this._viewContainerRef = _viewContainerRef;
389
+ this._overlay = _overlay;
390
+ this._ngZone = _ngZone;
391
+ this._parentMenu = _parentMenu;
392
+ this._menuAim = _menuAim;
393
+ this._directionality = _directionality;
394
+ /** Emits when the attached menu is requested to open */
395
+ this.opened = new EventEmitter();
396
+ /** Emits when the attached menu is requested to close */
397
+ this.closed = new EventEmitter();
398
+ /** The menu stack for this trigger and its sub-menus. */
399
+ this._menuStack = new MenuStack();
400
+ /** A reference to the overlay which manages the triggered menu */
401
+ this._overlayRef = null;
402
+ /** Emits when this trigger is destroyed. */
403
+ this._destroyed = new Subject();
404
+ /** Emits when the outside pointer events listener on the overlay should be stopped. */
405
+ this._stopOutsideClicksListener = merge(this.closed, this._destroyed);
406
+ this._registerCloseHandler();
407
+ this._subscribeToMouseEnter();
408
+ }
409
+ /** Template reference variable to the menu this trigger opens */
410
+ get menuPanel() {
411
+ return this._menuPanel;
412
+ }
413
+ set menuPanel(panel) {
414
+ // If the provided panel already has a stack, that means it already has a trigger configured.
415
+ // Note however that there are some edge cases where two triggers **may** share the same menu,
416
+ // e.g. two triggers in two separate menus.
417
+ if ((typeof ngDevMode === 'undefined' || ngDevMode) && panel?._menuStack) {
418
+ throwExistingMenuStackError();
419
+ }
420
+ this._menuPanel = panel;
421
+ if (this._menuPanel) {
422
+ this._menuPanel._menuStack = this._getMenuStack();
423
+ }
424
+ }
425
+ /** Open/close the attached menu if the trigger has been configured with one */
426
+ toggle() {
427
+ if (this.hasMenu()) {
428
+ this.isMenuOpen() ? this.closeMenu() : this.openMenu();
429
+ }
430
+ }
431
+ /** Open the attached menu. */
432
+ openMenu() {
433
+ if (!this.isMenuOpen()) {
434
+ this.opened.next();
435
+ this._overlayRef = this._overlayRef || this._overlay.create(this._getOverlayConfig());
436
+ this._overlayRef.attach(this._getPortal());
437
+ this._subscribeToOutsideClicks();
438
+ }
439
+ }
440
+ /** Close the opened menu. */
441
+ closeMenu() {
442
+ if (this.isMenuOpen()) {
443
+ this.closed.next();
444
+ this._overlayRef.detach();
445
+ }
446
+ this._closeSiblingTriggers();
447
+ }
448
+ /** Return true if the trigger has an attached menu */
449
+ hasMenu() {
450
+ return !!this.menuPanel;
451
+ }
452
+ /** Whether the menu this button is a trigger for is open */
453
+ isMenuOpen() {
454
+ return this._overlayRef ? this._overlayRef.hasAttached() : false;
455
+ }
456
+ /**
457
+ * Get a reference to the rendered Menu if the Menu is open and it is visible in the DOM.
458
+ * @return the menu if it is open, otherwise undefined.
459
+ */
460
+ getMenu() {
461
+ return this.menuPanel?._menu;
462
+ }
463
+ /**
464
+ * Subscribe to the mouseenter events and close any sibling menu items if this element is moused
465
+ * into.
466
+ */
467
+ _subscribeToMouseEnter() {
468
+ // Closes any sibling menu items and opens the menu associated with this trigger.
469
+ const toggleMenus = () => this._ngZone.run(() => {
470
+ this._closeSiblingTriggers();
471
+ this.openMenu();
472
+ });
473
+ this._ngZone.runOutsideAngular(() => {
474
+ fromEvent(this._elementRef.nativeElement, 'mouseenter')
475
+ .pipe(filter(() => !this._getMenuStack()?.isEmpty() && !this.isMenuOpen()), takeUntil(this._destroyed))
476
+ .subscribe(() => {
477
+ if (this._menuAim) {
478
+ this._menuAim.toggle(toggleMenus);
479
+ }
480
+ else {
481
+ toggleMenus();
482
+ }
483
+ });
484
+ });
485
+ }
486
+ /**
487
+ * Handles keyboard events for the menu item, specifically opening/closing the attached menu and
488
+ * focusing the appropriate submenu item.
489
+ * @param event the keyboard event to handle
490
+ */
491
+ _toggleOnKeydown(event) {
492
+ const keyCode = event.keyCode;
493
+ switch (keyCode) {
494
+ case SPACE:
495
+ case ENTER:
496
+ event.preventDefault();
497
+ this.toggle();
498
+ this.menuPanel?._menu?.focusFirstItem('keyboard');
499
+ break;
500
+ case RIGHT_ARROW:
501
+ if (this._parentMenu && this._isParentVertical()) {
502
+ event.preventDefault();
503
+ if (this._directionality?.value === 'rtl') {
504
+ this._getMenuStack().close(this._parentMenu, 2 /* currentItem */);
505
+ }
506
+ else {
507
+ this.openMenu();
508
+ this.menuPanel?._menu?.focusFirstItem('keyboard');
509
+ }
510
+ }
511
+ break;
512
+ case LEFT_ARROW:
513
+ if (this._parentMenu && this._isParentVertical()) {
514
+ event.preventDefault();
515
+ if (this._directionality?.value === 'rtl') {
516
+ this.openMenu();
517
+ this.menuPanel?._menu?.focusFirstItem('keyboard');
518
+ }
519
+ else {
520
+ this._getMenuStack().close(this._parentMenu, 2 /* currentItem */);
521
+ }
522
+ }
523
+ break;
524
+ case DOWN_ARROW:
525
+ case UP_ARROW:
526
+ if (!this._isParentVertical()) {
527
+ event.preventDefault();
528
+ this.openMenu();
529
+ keyCode === DOWN_ARROW
530
+ ? this.menuPanel?._menu?.focusFirstItem('keyboard')
531
+ : this.menuPanel?._menu?.focusLastItem('keyboard');
532
+ }
533
+ break;
534
+ }
535
+ }
536
+ /** Close out any sibling menu trigger menus. */
537
+ _closeSiblingTriggers() {
538
+ if (this._parentMenu) {
539
+ const menuStack = this._getMenuStack();
540
+ // If nothing was removed from the stack and the last element is not the parent item
541
+ // that means that the parent menu is a menu bar since we don't put the menu bar on the
542
+ // stack
543
+ const isParentMenuBar = !menuStack.closeSubMenuOf(this._parentMenu) && menuStack.peek() !== this._parentMenu;
544
+ if (isParentMenuBar) {
545
+ menuStack.closeAll();
546
+ }
547
+ }
548
+ else {
549
+ this._getMenuStack().closeAll();
550
+ }
551
+ }
552
+ /** Get the configuration object used to create the overlay */
553
+ _getOverlayConfig() {
554
+ return new OverlayConfig({
555
+ positionStrategy: this._getOverlayPositionStrategy(),
556
+ scrollStrategy: this._overlay.scrollStrategies.block(),
557
+ direction: this._directionality,
558
+ });
559
+ }
560
+ /** Build the position strategy for the overlay which specifies where to place the menu */
561
+ _getOverlayPositionStrategy() {
562
+ return this._overlay
563
+ .position()
564
+ .flexibleConnectedTo(this._elementRef)
565
+ .withPositions(this._getOverlayPositions());
566
+ }
567
+ /** Determine and return where to position the opened menu relative to the menu item */
568
+ _getOverlayPositions() {
569
+ // TODO: use a common positioning config from (possibly) cdk/overlay
570
+ return !this._parentMenu || this._parentMenu.orientation === 'horizontal'
571
+ ? [
572
+ { originX: 'start', originY: 'bottom', overlayX: 'start', overlayY: 'top' },
573
+ { originX: 'start', originY: 'top', overlayX: 'start', overlayY: 'bottom' },
574
+ { originX: 'end', originY: 'bottom', overlayX: 'end', overlayY: 'top' },
575
+ { originX: 'end', originY: 'top', overlayX: 'end', overlayY: 'bottom' },
576
+ ]
577
+ : [
578
+ { originX: 'end', originY: 'top', overlayX: 'start', overlayY: 'top' },
579
+ { originX: 'end', originY: 'bottom', overlayX: 'start', overlayY: 'bottom' },
580
+ { originX: 'start', originY: 'top', overlayX: 'end', overlayY: 'top' },
581
+ { originX: 'start', originY: 'bottom', overlayX: 'end', overlayY: 'bottom' },
582
+ ];
583
+ }
584
+ /**
585
+ * Get the portal to be attached to the overlay which contains the menu. Allows for the menu
586
+ * content to change dynamically and be reflected in the application.
587
+ */
588
+ _getPortal() {
589
+ const hasMenuContentChanged = this.menuPanel?._templateRef !== this._panelContent?.templateRef;
590
+ if (this.menuPanel && (!this._panelContent || hasMenuContentChanged)) {
591
+ this._panelContent = new TemplatePortal(this.menuPanel._templateRef, this._viewContainerRef);
592
+ }
593
+ return this._panelContent;
594
+ }
595
+ /**
596
+ * @return true if if the enclosing parent menu is configured in a vertical orientation.
597
+ */
598
+ _isParentVertical() {
599
+ return this._parentMenu?.orientation === 'vertical';
600
+ }
601
+ /**
602
+ * Subscribe to the MenuStack close events if this is a standalone trigger and close out the menu
603
+ * this triggers when requested.
604
+ */
605
+ _registerCloseHandler() {
606
+ if (!this._parentMenu) {
607
+ this._menuStack.closed.pipe(takeUntil(this._destroyed)).subscribe(item => {
608
+ if (item === this._menuPanel?._menu) {
609
+ this.closeMenu();
610
+ }
611
+ });
612
+ }
613
+ }
614
+ /** Get the menu stack for this trigger - either from the parent or this trigger. */
615
+ _getMenuStack() {
616
+ // We use a function since at the construction of the MenuItemTrigger the parent Menu won't have
617
+ // its menu stack set. Therefore we need to reference the menu stack from the parent each time
618
+ // we want to use it.
619
+ return this._parentMenu?._menuStack || this._menuStack;
620
+ }
621
+ ngOnDestroy() {
622
+ this._destroyOverlay();
623
+ this._resetPanelMenuStack();
624
+ this._destroyed.next();
625
+ this._destroyed.complete();
626
+ }
627
+ /** Set the menu panels menu stack back to null. */
628
+ _resetPanelMenuStack() {
629
+ // If a CdkMenuTrigger is placed in a submenu, each time the trigger is rendered (its parent
630
+ // menu is opened) the panel setter for CdkMenuPanel is called. From the first render onward,
631
+ // the attached CdkMenuPanel has the MenuStack set. Since we throw an error if a panel already
632
+ // has a stack set, we want to reset the attached stack here to prevent the error from being
633
+ // thrown if the trigger re-configures its attached panel (in the case where there is a 1:1
634
+ // relationship between the panel and trigger).
635
+ if (this._menuPanel) {
636
+ this._menuPanel._menuStack = null;
637
+ }
638
+ }
639
+ /**
640
+ * Subscribe to the overlays outside pointer events stream and handle closing out the stack if a
641
+ * click occurs outside the menus.
642
+ */
643
+ _subscribeToOutsideClicks() {
644
+ if (this._overlayRef) {
645
+ this._overlayRef
646
+ .outsidePointerEvents()
647
+ .pipe(takeUntil(this._stopOutsideClicksListener))
648
+ .subscribe(event => {
649
+ if (!isClickInsideMenuOverlay(event.target)) {
650
+ this._getMenuStack().closeAll();
651
+ }
652
+ });
653
+ }
654
+ }
655
+ /** Destroy and unset the overlay reference it if exists */
656
+ _destroyOverlay() {
657
+ if (this._overlayRef) {
658
+ this._overlayRef.dispose();
659
+ this._overlayRef = null;
660
+ }
661
+ }
662
+ }
663
+ CdkMenuItemTrigger.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.0-next.15", ngImport: i0, type: CdkMenuItemTrigger, deps: [{ token: i0.ElementRef }, { token: i0.ViewContainerRef }, { token: i1.Overlay }, { token: i0.NgZone }, { token: CDK_MENU, optional: true }, { token: MENU_AIM, optional: true }, { token: i2.Directionality, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
664
+ CdkMenuItemTrigger.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.0.0-next.15", type: CdkMenuItemTrigger, selector: "[cdkMenuTriggerFor]", inputs: { menuPanel: ["cdkMenuTriggerFor", "menuPanel"] }, outputs: { opened: "cdkMenuOpened", closed: "cdkMenuClosed" }, host: { attributes: { "aria-haspopup": "menu" }, listeners: { "keydown": "_toggleOnKeydown($event)", "click": "toggle()" }, properties: { "attr.aria-expanded": "isMenuOpen()" }, classAttribute: "cdk-menu-trigger" }, exportAs: ["cdkMenuTriggerFor"], ngImport: i0 });
665
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.0-next.15", ngImport: i0, type: CdkMenuItemTrigger, decorators: [{
666
+ type: Directive,
667
+ args: [{
668
+ selector: '[cdkMenuTriggerFor]',
669
+ exportAs: 'cdkMenuTriggerFor',
670
+ host: {
671
+ '(keydown)': '_toggleOnKeydown($event)',
672
+ '(click)': 'toggle()',
673
+ 'class': 'cdk-menu-trigger',
674
+ 'aria-haspopup': 'menu',
675
+ '[attr.aria-expanded]': 'isMenuOpen()',
676
+ },
677
+ }]
678
+ }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.ViewContainerRef }, { type: i1.Overlay }, { type: i0.NgZone }, { type: undefined, decorators: [{
679
+ type: Optional
680
+ }, {
681
+ type: Inject,
682
+ args: [CDK_MENU]
683
+ }] }, { type: undefined, decorators: [{
684
+ type: Optional
685
+ }, {
686
+ type: Inject,
687
+ args: [MENU_AIM]
688
+ }] }, { type: i2.Directionality, decorators: [{
689
+ type: Optional
690
+ }] }]; }, propDecorators: { menuPanel: [{
691
+ type: Input,
692
+ args: ['cdkMenuTriggerFor']
693
+ }], opened: [{
694
+ type: Output,
695
+ args: ['cdkMenuOpened']
696
+ }], closed: [{
697
+ type: Output,
698
+ args: ['cdkMenuClosed']
699
+ }] } });
700
+
701
+ /**
702
+ * @license
703
+ * Copyright Google LLC All Rights Reserved.
704
+ *
705
+ * Use of this source code is governed by an MIT-style license that can be
706
+ * found in the LICENSE file at https://angular.io/license
707
+ */
708
+ // TODO refactor this to be configurable allowing for custom elements to be removed
709
+ /** Removes all icons from within the given element. */
710
+ function removeIcons(element) {
711
+ for (const icon of Array.from(element.querySelectorAll('mat-icon, .material-icons'))) {
712
+ icon.remove();
713
+ }
714
+ }
715
+ /**
716
+ * Directive which provides the ability for an element to be focused and navigated to using the
717
+ * keyboard when residing in a CdkMenu, CdkMenuBar, or CdkMenuGroup. It performs user defined
718
+ * behavior when clicked.
719
+ */
720
+ class CdkMenuItem {
721
+ constructor(_elementRef, _ngZone, _parentMenu, _menuAim, _dir,
722
+ /** Reference to the CdkMenuItemTrigger directive if one is added to the same element */
723
+ // `CdkMenuItem` is commonly used in combination with a `CdkMenuItemTrigger`.
724
+ // tslint:disable-next-line: lightweight-tokens
725
+ _menuTrigger) {
726
+ this._elementRef = _elementRef;
727
+ this._ngZone = _ngZone;
728
+ this._parentMenu = _parentMenu;
729
+ this._menuAim = _menuAim;
730
+ this._dir = _dir;
731
+ this._menuTrigger = _menuTrigger;
732
+ this._disabled = false;
733
+ /**
734
+ * If this MenuItem is a regular MenuItem, outputs when it is triggered by a keyboard or mouse
735
+ * event.
736
+ */
737
+ this.triggered = new EventEmitter();
738
+ /**
739
+ * The tabindex for this menu item managed internally and used for implementing roving a
740
+ * tab index.
741
+ */
742
+ this._tabindex = -1;
743
+ /** Emits when the menu item is destroyed. */
744
+ this._destroyed = new Subject();
745
+ this._setupMouseEnter();
746
+ if (this._isStandaloneItem()) {
747
+ this._tabindex = 0;
748
+ }
749
+ }
750
+ /** Whether the CdkMenuItem is disabled - defaults to false */
751
+ get disabled() {
752
+ return this._disabled;
753
+ }
754
+ set disabled(value) {
755
+ this._disabled = coerceBooleanProperty(value);
756
+ }
757
+ /** Place focus on the element. */
758
+ focus() {
759
+ this._elementRef.nativeElement.focus();
760
+ }
761
+ // In Ivy the `host` metadata will be merged, whereas in ViewEngine it is overridden. In order
762
+ // to avoid double event listeners, we need to use `HostListener`. Once Ivy is the default, we
763
+ // can move this back into `host`.
764
+ // tslint:disable:no-host-decorator-in-concrete
765
+ /** Reset the _tabindex to -1. */
766
+ _resetTabIndex() {
767
+ if (!this._isStandaloneItem()) {
768
+ this._tabindex = -1;
769
+ }
770
+ }
771
+ // In Ivy the `host` metadata will be merged, whereas in ViewEngine it is overridden. In order
772
+ // to avoid double event listeners, we need to use `HostListener`. Once Ivy is the default, we
773
+ // can move this back into `host`.
774
+ // tslint:disable:no-host-decorator-in-concrete
775
+ /**
776
+ * Set the tab index to 0 if not disabled and it's a focus event, or a mouse enter if this element
777
+ * is not in a menu bar.
778
+ */
779
+ _setTabIndex(event) {
780
+ if (this.disabled) {
781
+ return;
782
+ }
783
+ // don't set the tabindex if there are no open sibling or parent menus
784
+ if (!event || !this._getMenuStack()?.isEmpty()) {
785
+ this._tabindex = 0;
786
+ }
787
+ }
788
+ /** Whether this menu item is standalone or within a menu or menu bar. */
789
+ _isStandaloneItem() {
790
+ return !this._parentMenu;
791
+ }
792
+ // In Ivy the `host` metadata will be merged, whereas in ViewEngine it is overridden. In order
793
+ // to avoid double event listeners, we need to use `HostListener`. Once Ivy is the default, we
794
+ // can move this back into `host`.
795
+ // tslint:disable:no-host-decorator-in-concrete
796
+ /**
797
+ * If the menu item is not disabled and the element does not have a menu trigger attached, emit
798
+ * on the cdkMenuItemTriggered emitter and close all open menus.
799
+ */
800
+ trigger() {
801
+ if (!this.disabled && !this.hasMenu()) {
802
+ this.triggered.next();
803
+ this._getMenuStack()?.closeAll();
804
+ }
805
+ }
806
+ /** Whether the menu item opens a menu. */
807
+ hasMenu() {
808
+ return !!this._menuTrigger?.hasMenu();
809
+ }
810
+ /** Return true if this MenuItem has an attached menu and it is open. */
811
+ isMenuOpen() {
812
+ return !!this._menuTrigger?.isMenuOpen();
813
+ }
814
+ /**
815
+ * Get a reference to the rendered Menu if the Menu is open and it is visible in the DOM.
816
+ * @return the menu if it is open, otherwise undefined.
817
+ */
818
+ getMenu() {
819
+ return this._menuTrigger?.getMenu();
820
+ }
821
+ /** Get the MenuItemTrigger associated with this element. */
822
+ getMenuTrigger() {
823
+ return this._menuTrigger;
824
+ }
825
+ /** Get the label for this element which is required by the FocusableOption interface. */
826
+ getLabel() {
827
+ // TODO cloning the tree may be expensive; implement a better method
828
+ // we know that the current node is an element type
829
+ const clone = this._elementRef.nativeElement.cloneNode(true);
830
+ removeIcons(clone);
831
+ return clone.textContent?.trim() || '';
832
+ }
833
+ // In Ivy the `host` metadata will be merged, whereas in ViewEngine it is overridden. In order
834
+ // to avoid double event listeners, we need to use `HostListener`. Once Ivy is the default, we
835
+ // can move this back into `host`.
836
+ // tslint:disable:no-host-decorator-in-concrete
837
+ /**
838
+ * Handles keyboard events for the menu item, specifically either triggering the user defined
839
+ * callback or opening/closing the current menu based on whether the left or right arrow key was
840
+ * pressed.
841
+ * @param event the keyboard event to handle
842
+ */
843
+ _onKeydown(event) {
844
+ switch (event.keyCode) {
845
+ case SPACE:
846
+ case ENTER:
847
+ event.preventDefault();
848
+ this.trigger();
849
+ break;
850
+ case RIGHT_ARROW:
851
+ if (this._parentMenu && this._isParentVertical() && !this.hasMenu()) {
852
+ event.preventDefault();
853
+ this._dir?.value === 'rtl'
854
+ ? this._getMenuStack()?.close(this._parentMenu, 1 /* previousItem */)
855
+ : this._getMenuStack()?.closeAll(0 /* nextItem */);
856
+ }
857
+ break;
858
+ case LEFT_ARROW:
859
+ if (this._parentMenu && this._isParentVertical() && !this.hasMenu()) {
860
+ event.preventDefault();
861
+ this._dir?.value === 'rtl'
862
+ ? this._getMenuStack()?.closeAll(0 /* nextItem */)
863
+ : this._getMenuStack()?.close(this._parentMenu, 1 /* previousItem */);
864
+ }
865
+ break;
866
+ }
867
+ }
868
+ /**
869
+ * Subscribe to the mouseenter events and close any sibling menu items if this element is moused
870
+ * into.
871
+ */
872
+ _setupMouseEnter() {
873
+ if (!this._isStandaloneItem()) {
874
+ const closeOpenSiblings = () => this._ngZone.run(() => this._getMenuStack()?.closeSubMenuOf(this._parentMenu));
875
+ this._ngZone.runOutsideAngular(() => fromEvent(this._elementRef.nativeElement, 'mouseenter')
876
+ .pipe(filter(() => !this._getMenuStack()?.isEmpty() && !this.hasMenu()), takeUntil(this._destroyed))
877
+ .subscribe(() => {
878
+ if (this._menuAim) {
879
+ this._menuAim.toggle(closeOpenSiblings);
880
+ }
881
+ else {
882
+ closeOpenSiblings();
883
+ }
884
+ }));
885
+ }
886
+ }
887
+ /**
888
+ * Return true if the enclosing parent menu is configured in a horizontal orientation, false
889
+ * otherwise or if no parent.
890
+ */
891
+ _isParentVertical() {
892
+ return this._parentMenu?.orientation === 'vertical';
893
+ }
894
+ /** Get the MenuStack from the parent menu. */
895
+ _getMenuStack() {
896
+ // We use a function since at the construction of the MenuItemTrigger the parent Menu won't have
897
+ // its menu stack set. Therefore we need to reference the menu stack from the parent each time
898
+ // we want to use it.
899
+ return this._parentMenu?._menuStack;
900
+ }
901
+ ngOnDestroy() {
902
+ this._destroyed.next();
903
+ }
904
+ }
905
+ CdkMenuItem.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.0-next.15", ngImport: i0, type: CdkMenuItem, deps: [{ token: i0.ElementRef }, { token: i0.NgZone }, { token: CDK_MENU, optional: true }, { token: MENU_AIM, optional: true }, { token: i2.Directionality, optional: true }, { token: CdkMenuItemTrigger, optional: true, self: true }], target: i0.ɵɵFactoryTarget.Directive });
906
+ CdkMenuItem.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.0.0-next.15", type: CdkMenuItem, selector: "[cdkMenuItem]", inputs: { disabled: "disabled" }, outputs: { triggered: "cdkMenuItemTriggered" }, host: { attributes: { "type": "button", "role": "menuitem" }, listeners: { "blur": "_resetTabIndex()", "mouseout": "_resetTabIndex()", "focus": "_setTabIndex()", "mouseenter": "_setTabIndex($event)", "click": "trigger()", "keydown": "_onKeydown($event)" }, properties: { "tabindex": "_tabindex", "attr.aria-disabled": "disabled || null" }, classAttribute: "cdk-menu-item" }, exportAs: ["cdkMenuItem"], ngImport: i0 });
907
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.0-next.15", ngImport: i0, type: CdkMenuItem, decorators: [{
908
+ type: Directive,
909
+ args: [{
910
+ selector: '[cdkMenuItem]',
911
+ exportAs: 'cdkMenuItem',
912
+ host: {
913
+ '[tabindex]': '_tabindex',
914
+ 'type': 'button',
915
+ 'role': 'menuitem',
916
+ 'class': 'cdk-menu-item',
917
+ '[attr.aria-disabled]': 'disabled || null',
918
+ },
919
+ }]
920
+ }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.NgZone }, { type: undefined, decorators: [{
921
+ type: Optional
922
+ }, {
923
+ type: Inject,
924
+ args: [CDK_MENU]
925
+ }] }, { type: undefined, decorators: [{
926
+ type: Optional
927
+ }, {
928
+ type: Inject,
929
+ args: [MENU_AIM]
930
+ }] }, { type: i2.Directionality, decorators: [{
931
+ type: Optional
932
+ }] }, { type: CdkMenuItemTrigger, decorators: [{
933
+ type: Self
934
+ }, {
935
+ type: Optional
936
+ }] }]; }, propDecorators: { disabled: [{
937
+ type: Input
938
+ }], triggered: [{
939
+ type: Output,
940
+ args: ['cdkMenuItemTriggered']
941
+ }],
942
+ /** Reset the _tabindex to -1. */
943
+ _resetTabIndex: [{
944
+ type: HostListener,
945
+ args: ['blur']
946
+ }, {
947
+ type: HostListener,
948
+ args: ['mouseout']
949
+ }],
950
+ /**
951
+ * Set the tab index to 0 if not disabled and it's a focus event, or a mouse enter if this element
952
+ * is not in a menu bar.
953
+ */
954
+ _setTabIndex: [{
955
+ type: HostListener,
956
+ args: ['focus']
957
+ }, {
958
+ type: HostListener,
959
+ args: ['mouseenter', ['$event']]
960
+ }],
961
+ /**
962
+ * If the menu item is not disabled and the element does not have a menu trigger attached, emit
963
+ * on the cdkMenuItemTriggered emitter and close all open menus.
964
+ */
965
+ trigger: [{
966
+ type: HostListener,
967
+ args: ['click']
968
+ }],
969
+ /**
970
+ * Handles keyboard events for the menu item, specifically either triggering the user defined
971
+ * callback or opening/closing the current menu based on whether the left or right arrow key was
972
+ * pressed.
973
+ * @param event the keyboard event to handle
974
+ */
975
+ _onKeydown: [{
976
+ type: HostListener,
977
+ args: ['keydown', ['$event']]
978
+ }] } });
979
+
980
+ /**
981
+ * @license
982
+ * Copyright Google LLC All Rights Reserved.
983
+ *
984
+ * Use of this source code is governed by an MIT-style license that can be
985
+ * found in the LICENSE file at https://angular.io/license
986
+ */
987
+ /** Counter used to set a unique id and name for a selectable item */
988
+ let nextId = 0;
989
+ /**
990
+ * Base class providing checked state for MenuItems along with outputting a clicked event when the
991
+ * element is triggered. It provides functionality for selectable elements.
992
+ */
993
+ class CdkMenuItemSelectable extends CdkMenuItem {
994
+ constructor() {
995
+ super(...arguments);
996
+ /** Event emitted when the selectable item is clicked */
997
+ this.toggled = new EventEmitter();
998
+ this._checked = false;
999
+ /** The name of the selectable element with a default value */
1000
+ this.name = `cdk-selectable-item-${nextId++}`;
1001
+ /** The id of the selectable element with a default value */
1002
+ this.id = `cdk-selectable-item-${nextId++}`;
1003
+ }
1004
+ /** Whether the element is checked */
1005
+ get checked() {
1006
+ return this._checked;
1007
+ }
1008
+ set checked(value) {
1009
+ this._checked = coerceBooleanProperty(value);
1010
+ }
1011
+ /** If the element is not disabled emit the click event */
1012
+ trigger() {
1013
+ if (!this.disabled) {
1014
+ this.toggled.next(this);
1015
+ }
1016
+ }
1017
+ }
1018
+ CdkMenuItemSelectable.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.0-next.15", ngImport: i0, type: CdkMenuItemSelectable, deps: null, target: i0.ɵɵFactoryTarget.Directive });
1019
+ CdkMenuItemSelectable.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.0.0-next.15", type: CdkMenuItemSelectable, inputs: { checked: "checked", name: "name", id: "id" }, outputs: { toggled: "cdkMenuItemToggled" }, usesInheritance: true, ngImport: i0 });
1020
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.0-next.15", ngImport: i0, type: CdkMenuItemSelectable, decorators: [{
1021
+ type: Directive
1022
+ }], propDecorators: { toggled: [{
1023
+ type: Output,
1024
+ args: ['cdkMenuItemToggled']
1025
+ }], checked: [{
1026
+ type: Input
1027
+ }], name: [{
1028
+ type: Input
1029
+ }], id: [{
1030
+ type: Input
1031
+ }] } });
1032
+
1033
+ /**
1034
+ * @license
1035
+ * Copyright Google LLC All Rights Reserved.
1036
+ *
1037
+ * Use of this source code is governed by an MIT-style license that can be
1038
+ * found in the LICENSE file at https://angular.io/license
1039
+ */
1040
+ /**
1041
+ * Directive which acts as a grouping container for `CdkMenuItem` instances with
1042
+ * `role="menuitemradio"`, similar to a `role="radiogroup"` element.
1043
+ */
1044
+ class CdkMenuGroup {
1045
+ constructor() {
1046
+ /** Emits the element when checkbox or radiobutton state changed */
1047
+ this.change = new EventEmitter();
1048
+ /** Emits when the _selectableItems QueryList triggers a change */
1049
+ this._selectableChanges = new EventEmitter();
1050
+ }
1051
+ ngAfterContentInit() {
1052
+ this._registerMenuSelectionListeners();
1053
+ }
1054
+ /**
1055
+ * Register the child selectable elements with the change emitter and ensure any new child
1056
+ * elements do so as well.
1057
+ */
1058
+ _registerMenuSelectionListeners() {
1059
+ this._selectableItems.forEach(selectable => this._registerClickListener(selectable));
1060
+ this._selectableItems.changes.subscribe((selectableItems) => {
1061
+ this._selectableChanges.next();
1062
+ selectableItems.forEach(selectable => this._registerClickListener(selectable));
1063
+ });
1064
+ }
1065
+ /** Register each selectable to emit on the change Emitter when clicked */
1066
+ _registerClickListener(selectable) {
1067
+ selectable.toggled
1068
+ .pipe(takeUntil(this._selectableChanges))
1069
+ .subscribe(() => this.change.next(selectable));
1070
+ }
1071
+ ngOnDestroy() {
1072
+ this._selectableChanges.next();
1073
+ this._selectableChanges.complete();
1074
+ }
1075
+ }
1076
+ CdkMenuGroup.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.0-next.15", ngImport: i0, type: CdkMenuGroup, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1077
+ CdkMenuGroup.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.0.0-next.15", type: CdkMenuGroup, selector: "[cdkMenuGroup]", outputs: { change: "change" }, host: { attributes: { "role": "group" }, classAttribute: "cdk-menu-group" }, providers: [{ provide: UniqueSelectionDispatcher, useClass: UniqueSelectionDispatcher }], queries: [{ propertyName: "_selectableItems", predicate: CdkMenuItemSelectable, descendants: true }], exportAs: ["cdkMenuGroup"], ngImport: i0 });
1078
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.0-next.15", ngImport: i0, type: CdkMenuGroup, decorators: [{
1079
+ type: Directive,
1080
+ args: [{
1081
+ selector: '[cdkMenuGroup]',
1082
+ exportAs: 'cdkMenuGroup',
1083
+ host: {
1084
+ 'role': 'group',
1085
+ 'class': 'cdk-menu-group',
1086
+ },
1087
+ providers: [{ provide: UniqueSelectionDispatcher, useClass: UniqueSelectionDispatcher }],
1088
+ }]
1089
+ }], propDecorators: { change: [{
1090
+ type: Output
1091
+ }], _selectableItems: [{
1092
+ type: ContentChildren,
1093
+ args: [CdkMenuItemSelectable, { descendants: true }]
1094
+ }] } });
1095
+
1096
+ /**
1097
+ * @license
1098
+ * Copyright Google LLC All Rights Reserved.
1099
+ *
1100
+ * Use of this source code is governed by an MIT-style license that can be
1101
+ * found in the LICENSE file at https://angular.io/license
1102
+ */
1103
+ /**
1104
+ * Directive applied to an ng-template which wraps a CdkMenu and provides a reference to the
1105
+ * child element it wraps which allows for opening of the CdkMenu in an overlay.
1106
+ */
1107
+ class CdkMenuPanel {
1108
+ constructor(_templateRef) {
1109
+ this._templateRef = _templateRef;
1110
+ }
1111
+ /**
1112
+ * Set the Menu component on the menu panel. Since we cannot use ContentChild to fetch the
1113
+ * child Menu component, the child Menu must register its self with the parent MenuPanel.
1114
+ */
1115
+ _registerMenu(child) {
1116
+ this._menu = child;
1117
+ // The ideal solution would be to affect the CdkMenuPanel injector from the CdkMenuTrigger and
1118
+ // inject the menu stack reference into the child menu and menu items, however this isn't
1119
+ // possible at this time.
1120
+ this._menu._menuStack = this._menuStack;
1121
+ this._menuStack?.push(child);
1122
+ }
1123
+ }
1124
+ CdkMenuPanel.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.0-next.15", ngImport: i0, type: CdkMenuPanel, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
1125
+ CdkMenuPanel.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.0.0-next.15", type: CdkMenuPanel, selector: "ng-template[cdkMenuPanel]", exportAs: ["cdkMenuPanel"], ngImport: i0 });
1126
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.0-next.15", ngImport: i0, type: CdkMenuPanel, decorators: [{
1127
+ type: Directive,
1128
+ args: [{ selector: 'ng-template[cdkMenuPanel]', exportAs: 'cdkMenuPanel' }]
1129
+ }], ctorParameters: function () { return [{ type: i0.TemplateRef }]; } });
1130
+
1131
+ /**
1132
+ * @license
1133
+ * Copyright Google LLC All Rights Reserved.
1134
+ *
1135
+ * Use of this source code is governed by an MIT-style license that can be
1136
+ * found in the LICENSE file at https://angular.io/license
1137
+ */
1138
+ /**
1139
+ * PointerFocusTracker keeps track of the currently active item under mouse focus. It also has
1140
+ * observables which emit when the users mouse enters and leaves a tracked element.
1141
+ */
1142
+ class PointerFocusTracker {
1143
+ constructor(_items) {
1144
+ this._items = _items;
1145
+ /** Emits when an element is moused into. */
1146
+ this.entered = this._getItemPointerEntries();
1147
+ /** Emits when an element is moused out. */
1148
+ this.exited = this._getItemPointerExits();
1149
+ /** Emits when this is destroyed. */
1150
+ this._destroyed = new Subject();
1151
+ this.entered.subscribe(element => (this.activeElement = element));
1152
+ this.exited.subscribe(() => {
1153
+ this.previousElement = this.activeElement;
1154
+ this.activeElement = undefined;
1155
+ });
1156
+ }
1157
+ /**
1158
+ * Gets a stream of pointer (mouse) entries into the given items.
1159
+ * This should typically run outside the Angular zone.
1160
+ */
1161
+ _getItemPointerEntries() {
1162
+ return defer(() => this._items.changes.pipe(startWith(this._items), mergeMap((list) => list.map(element => fromEvent(element._elementRef.nativeElement, 'mouseenter').pipe(mapTo(element), takeUntil(this._items.changes)))), mergeAll()));
1163
+ }
1164
+ /**
1165
+ * Gets a stream of pointer (mouse) exits out of the given items.
1166
+ * This should typically run outside the Angular zone.
1167
+ */
1168
+ _getItemPointerExits() {
1169
+ return defer(() => this._items.changes.pipe(startWith(this._items), mergeMap((list) => list.map(element => fromEvent(element._elementRef.nativeElement, 'mouseout').pipe(mapTo(element), takeUntil(this._items.changes)))), mergeAll()));
1170
+ }
1171
+ /** Stop the managers listeners. */
1172
+ destroy() {
1173
+ this._destroyed.next();
1174
+ this._destroyed.complete();
1175
+ }
1176
+ }
1177
+
1178
+ /**
1179
+ * @license
1180
+ * Copyright Google LLC All Rights Reserved.
1181
+ *
1182
+ * Use of this source code is governed by an MIT-style license that can be
1183
+ * found in the LICENSE file at https://angular.io/license
1184
+ */
1185
+ /**
1186
+ * Directive which configures the element as a Menu which should contain child elements marked as
1187
+ * CdkMenuItem or CdkMenuGroup. Sets the appropriate role and aria-attributes for a menu and
1188
+ * contains accessible keyboard and mouse handling logic.
1189
+ *
1190
+ * It also acts as a RadioGroup for elements marked with role `menuitemradio`.
1191
+ */
1192
+ class CdkMenu extends CdkMenuGroup {
1193
+ constructor(_ngZone, _elementRef, _menuAim, _dir,
1194
+ // `CdkMenuPanel` is always used in combination with a `CdkMenu`.
1195
+ // tslint:disable-next-line: lightweight-tokens
1196
+ _menuPanel) {
1197
+ super();
1198
+ this._ngZone = _ngZone;
1199
+ this._elementRef = _elementRef;
1200
+ this._menuAim = _menuAim;
1201
+ this._dir = _dir;
1202
+ this._menuPanel = _menuPanel;
1203
+ /**
1204
+ * Sets the aria-orientation attribute and determines where menus will be opened.
1205
+ * Does not affect styling/layout.
1206
+ */
1207
+ this.orientation = 'vertical';
1208
+ /** Event emitted when the menu is closed. */
1209
+ this.closed = new EventEmitter();
1210
+ // We provide a default MenuStack implementation in case the menu is an inline menu.
1211
+ // For Menus part of a MenuBar nested within a MenuPanel this will be overwritten
1212
+ // to the correct parent MenuStack.
1213
+ /** Track the Menus making up the open menu stack. */
1214
+ this._menuStack = new NoopMenuStack();
1215
+ }
1216
+ ngOnInit() {
1217
+ this._registerWithParentPanel();
1218
+ }
1219
+ ngAfterContentInit() {
1220
+ super.ngAfterContentInit();
1221
+ this._completeChangeEmitter();
1222
+ this._setKeyManager();
1223
+ this._subscribeToMenuOpen();
1224
+ this._subscribeToMenuStack();
1225
+ this._subscribeToMouseManager();
1226
+ this._menuAim?.initialize(this, this._pointerTracker);
1227
+ }
1228
+ // In Ivy the `host` metadata will be merged, whereas in ViewEngine it is overridden. In order
1229
+ // to avoid double event listeners, we need to use `HostListener`. Once Ivy is the default, we
1230
+ // can move this back into `host`.
1231
+ // tslint:disable:no-host-decorator-in-concrete
1232
+ /** Place focus on the first MenuItem in the menu and set the focus origin. */
1233
+ focusFirstItem(focusOrigin = 'program') {
1234
+ this._keyManager.setFocusOrigin(focusOrigin);
1235
+ this._keyManager.setFirstItemActive();
1236
+ }
1237
+ /** Place focus on the last MenuItem in the menu and set the focus origin. */
1238
+ focusLastItem(focusOrigin = 'program') {
1239
+ this._keyManager.setFocusOrigin(focusOrigin);
1240
+ this._keyManager.setLastItemActive();
1241
+ }
1242
+ // In Ivy the `host` metadata will be merged, whereas in ViewEngine it is overridden. In order
1243
+ // to avoid double event listeners, we need to use `HostListener`. Once Ivy is the default, we
1244
+ // can move this back into `host`.
1245
+ // tslint:disable:no-host-decorator-in-concrete
1246
+ /** Handle keyboard events for the Menu. */
1247
+ _handleKeyEvent(event) {
1248
+ const keyManager = this._keyManager;
1249
+ switch (event.keyCode) {
1250
+ case LEFT_ARROW:
1251
+ case RIGHT_ARROW:
1252
+ if (this._isHorizontal()) {
1253
+ event.preventDefault();
1254
+ keyManager.setFocusOrigin('keyboard');
1255
+ keyManager.onKeydown(event);
1256
+ }
1257
+ break;
1258
+ case UP_ARROW:
1259
+ case DOWN_ARROW:
1260
+ if (!this._isHorizontal()) {
1261
+ event.preventDefault();
1262
+ keyManager.setFocusOrigin('keyboard');
1263
+ keyManager.onKeydown(event);
1264
+ }
1265
+ break;
1266
+ case ESCAPE:
1267
+ if (!hasModifierKey(event)) {
1268
+ event.preventDefault();
1269
+ this._menuStack.close(this, 2 /* currentItem */);
1270
+ }
1271
+ break;
1272
+ case TAB:
1273
+ this._menuStack.closeAll();
1274
+ break;
1275
+ default:
1276
+ keyManager.onKeydown(event);
1277
+ }
1278
+ }
1279
+ /** Register this menu with its enclosing parent menu panel */
1280
+ _registerWithParentPanel() {
1281
+ this._getMenuPanel()?._registerMenu(this);
1282
+ }
1283
+ /**
1284
+ * Get the enclosing CdkMenuPanel defaulting to the injected reference over the developer
1285
+ * provided reference.
1286
+ */
1287
+ _getMenuPanel() {
1288
+ return this._menuPanel || this._explicitPanel;
1289
+ }
1290
+ /**
1291
+ * Complete the change emitter if there are any nested MenuGroups or register to complete the
1292
+ * change emitter if a MenuGroup is rendered at some point
1293
+ */
1294
+ _completeChangeEmitter() {
1295
+ if (this._hasNestedGroups()) {
1296
+ this.change.complete();
1297
+ }
1298
+ else {
1299
+ this._nestedGroups.changes.pipe(take(1)).subscribe(() => this.change.complete());
1300
+ }
1301
+ }
1302
+ /** Return true if there are nested CdkMenuGroup elements within the Menu */
1303
+ _hasNestedGroups() {
1304
+ // view engine has a bug where @ContentChildren will return the current element
1305
+ // along with children if the selectors match - not just the children.
1306
+ // Here, if there is at least one element, we check to see if the first element is a CdkMenu in
1307
+ // order to ensure that we return true iff there are child CdkMenuGroup elements.
1308
+ return this._nestedGroups.length > 0 && !(this._nestedGroups.first instanceof CdkMenu);
1309
+ }
1310
+ /** Setup the FocusKeyManager with the correct orientation for the menu. */
1311
+ _setKeyManager() {
1312
+ this._keyManager = new FocusKeyManager(this._allItems)
1313
+ .withWrap()
1314
+ .withTypeAhead()
1315
+ .withHomeAndEnd();
1316
+ if (this._isHorizontal()) {
1317
+ this._keyManager.withHorizontalOrientation(this._dir?.value || 'ltr');
1318
+ }
1319
+ else {
1320
+ this._keyManager.withVerticalOrientation();
1321
+ }
1322
+ }
1323
+ /**
1324
+ * Set the PointerFocusTracker and ensure that when mouse focus changes the key manager is updated
1325
+ * with the latest menu item under mouse focus.
1326
+ */
1327
+ _subscribeToMouseManager() {
1328
+ this._ngZone.runOutsideAngular(() => {
1329
+ this._pointerTracker = new PointerFocusTracker(this._allItems);
1330
+ this._pointerTracker.entered
1331
+ .pipe(takeUntil(this.closed))
1332
+ .subscribe(item => this._keyManager.setActiveItem(item));
1333
+ });
1334
+ }
1335
+ /** Subscribe to the MenuStack close and empty observables. */
1336
+ _subscribeToMenuStack() {
1337
+ this._menuStack.closed
1338
+ .pipe(takeUntil(this.closed))
1339
+ .subscribe(item => this._closeOpenMenu(item));
1340
+ this._menuStack.emptied
1341
+ .pipe(takeUntil(this.closed))
1342
+ .subscribe(event => this._toggleMenuFocus(event));
1343
+ }
1344
+ /**
1345
+ * Close the open menu if the current active item opened the requested MenuStackItem.
1346
+ * @param item the MenuStackItem requested to be closed.
1347
+ */
1348
+ _closeOpenMenu(menu) {
1349
+ const keyManager = this._keyManager;
1350
+ const trigger = this._openItem;
1351
+ if (menu === trigger?.getMenuTrigger()?.getMenu()) {
1352
+ trigger?.getMenuTrigger()?.closeMenu();
1353
+ // If the user has moused over a sibling item we want to focus the element under mouse focus
1354
+ // not the trigger which previously opened the now closed menu.
1355
+ if (trigger) {
1356
+ keyManager.setActiveItem(this._pointerTracker?.activeElement || trigger);
1357
+ }
1358
+ }
1359
+ }
1360
+ /** Set focus the either the current, previous or next item based on the FocusNext event. */
1361
+ _toggleMenuFocus(event) {
1362
+ const keyManager = this._keyManager;
1363
+ switch (event) {
1364
+ case 0 /* nextItem */:
1365
+ keyManager.setFocusOrigin('keyboard');
1366
+ keyManager.setNextItemActive();
1367
+ break;
1368
+ case 1 /* previousItem */:
1369
+ keyManager.setFocusOrigin('keyboard');
1370
+ keyManager.setPreviousItemActive();
1371
+ break;
1372
+ case 2 /* currentItem */:
1373
+ if (keyManager.activeItem) {
1374
+ keyManager.setFocusOrigin('keyboard');
1375
+ keyManager.setActiveItem(keyManager.activeItem);
1376
+ }
1377
+ break;
1378
+ }
1379
+ }
1380
+ // TODO(andy9775): remove duplicate logic between menu an menu bar
1381
+ /**
1382
+ * Subscribe to the menu trigger's open events in order to track the trigger which opened the menu
1383
+ * and stop tracking it when the menu is closed.
1384
+ */
1385
+ _subscribeToMenuOpen() {
1386
+ const exitCondition = merge(this._allItems.changes, this.closed);
1387
+ this._allItems.changes
1388
+ .pipe(startWith(this._allItems), mergeMap((list) => list
1389
+ .filter(item => item.hasMenu())
1390
+ .map(item => item.getMenuTrigger().opened.pipe(mapTo(item), takeUntil(exitCondition)))), mergeAll(), switchMap((item) => {
1391
+ this._openItem = item;
1392
+ return item.getMenuTrigger().closed;
1393
+ }), takeUntil(this.closed))
1394
+ .subscribe(() => (this._openItem = undefined));
1395
+ }
1396
+ /** Return true if this menu has been configured in a horizontal orientation. */
1397
+ _isHorizontal() {
1398
+ return this.orientation === 'horizontal';
1399
+ }
1400
+ /**
1401
+ * Return true if this menu is an inline menu. That is, it does not exist in a pop-up and is
1402
+ * always visible in the dom.
1403
+ */
1404
+ _isInline() {
1405
+ // NoopMenuStack is the default. If this menu is not inline than the NoopMenuStack is replaced
1406
+ // automatically.
1407
+ return this._menuStack instanceof NoopMenuStack;
1408
+ }
1409
+ ngOnDestroy() {
1410
+ this._emitClosedEvent();
1411
+ this._pointerTracker?.destroy();
1412
+ }
1413
+ /** Emit and complete the closed event emitter */
1414
+ _emitClosedEvent() {
1415
+ this.closed.next();
1416
+ this.closed.complete();
1417
+ }
1418
+ }
1419
+ CdkMenu.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.0-next.15", ngImport: i0, type: CdkMenu, deps: [{ token: i0.NgZone }, { token: i0.ElementRef }, { token: MENU_AIM, optional: true, self: true }, { token: i2.Directionality, optional: true }, { token: CdkMenuPanel, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
1420
+ CdkMenu.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.0.0-next.15", type: CdkMenu, selector: "[cdkMenu]", inputs: { orientation: ["cdkMenuOrientation", "orientation"], _explicitPanel: ["cdkMenuPanel", "_explicitPanel"] }, outputs: { closed: "closed" }, host: { attributes: { "role": "menu" }, listeners: { "focus": "focusFirstItem()", "keydown": "_handleKeyEvent($event)" }, properties: { "tabindex": "_isInline() ? 0 : null", "class.cdk-menu-inline": "_isInline()", "attr.aria-orientation": "orientation" }, classAttribute: "cdk-menu" }, providers: [
1421
+ { provide: CdkMenuGroup, useExisting: CdkMenu },
1422
+ { provide: CDK_MENU, useExisting: CdkMenu },
1423
+ ], queries: [{ propertyName: "_nestedGroups", predicate: CdkMenuGroup, descendants: true }, { propertyName: "_allItems", predicate: CdkMenuItem, descendants: true }], exportAs: ["cdkMenu"], usesInheritance: true, ngImport: i0 });
1424
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.0-next.15", ngImport: i0, type: CdkMenu, decorators: [{
1425
+ type: Directive,
1426
+ args: [{
1427
+ selector: '[cdkMenu]',
1428
+ exportAs: 'cdkMenu',
1429
+ host: {
1430
+ '[tabindex]': '_isInline() ? 0 : null',
1431
+ 'role': 'menu',
1432
+ 'class': 'cdk-menu',
1433
+ '[class.cdk-menu-inline]': '_isInline()',
1434
+ '[attr.aria-orientation]': 'orientation',
1435
+ },
1436
+ providers: [
1437
+ { provide: CdkMenuGroup, useExisting: CdkMenu },
1438
+ { provide: CDK_MENU, useExisting: CdkMenu },
1439
+ ],
1440
+ }]
1441
+ }], ctorParameters: function () { return [{ type: i0.NgZone }, { type: i0.ElementRef }, { type: undefined, decorators: [{
1442
+ type: Self
1443
+ }, {
1444
+ type: Optional
1445
+ }, {
1446
+ type: Inject,
1447
+ args: [MENU_AIM]
1448
+ }] }, { type: i2.Directionality, decorators: [{
1449
+ type: Optional
1450
+ }] }, { type: CdkMenuPanel, decorators: [{
1451
+ type: Optional
1452
+ }] }]; }, propDecorators: { orientation: [{
1453
+ type: Input,
1454
+ args: ['cdkMenuOrientation']
1455
+ }], closed: [{
1456
+ type: Output
1457
+ }], _nestedGroups: [{
1458
+ type: ContentChildren,
1459
+ args: [CdkMenuGroup, { descendants: true }]
1460
+ }], _allItems: [{
1461
+ type: ContentChildren,
1462
+ args: [CdkMenuItem, { descendants: true }]
1463
+ }], _explicitPanel: [{
1464
+ type: Input,
1465
+ args: ['cdkMenuPanel']
1466
+ }],
1467
+ /** Place focus on the first MenuItem in the menu and set the focus origin. */
1468
+ focusFirstItem: [{
1469
+ type: HostListener,
1470
+ args: ['focus']
1471
+ }],
1472
+ /** Handle keyboard events for the Menu. */
1473
+ _handleKeyEvent: [{
1474
+ type: HostListener,
1475
+ args: ['keydown', ['$event']]
1476
+ }] } });
1477
+
1478
+ /**
1479
+ * @license
1480
+ * Copyright Google LLC All Rights Reserved.
1481
+ *
1482
+ * Use of this source code is governed by an MIT-style license that can be
1483
+ * found in the LICENSE file at https://angular.io/license
1484
+ */
1485
+ /**
1486
+ * Directive applied to an element which configures it as a MenuBar by setting the appropriate
1487
+ * role, aria attributes, and accessible keyboard and mouse handling logic. The component that
1488
+ * this directive is applied to should contain components marked with CdkMenuItem.
1489
+ *
1490
+ */
1491
+ class CdkMenuBar extends CdkMenuGroup {
1492
+ constructor(_menuStack, _ngZone, _elementRef, _menuAim, _dir) {
1493
+ super();
1494
+ this._menuStack = _menuStack;
1495
+ this._ngZone = _ngZone;
1496
+ this._elementRef = _elementRef;
1497
+ this._menuAim = _menuAim;
1498
+ this._dir = _dir;
1499
+ /**
1500
+ * Sets the aria-orientation attribute and determines where menus will be opened.
1501
+ * Does not affect styling/layout.
1502
+ */
1503
+ this.orientation = 'horizontal';
1504
+ /** Emits when the MenuBar is destroyed. */
1505
+ this._destroyed = new Subject();
1506
+ }
1507
+ ngAfterContentInit() {
1508
+ super.ngAfterContentInit();
1509
+ this._setKeyManager();
1510
+ this._subscribeToMenuOpen();
1511
+ this._subscribeToMenuStack();
1512
+ this._subscribeToMouseManager();
1513
+ this._menuAim?.initialize(this, this._pointerTracker);
1514
+ }
1515
+ // In Ivy the `host` metadata will be merged, whereas in ViewEngine it is overridden. In order
1516
+ // to avoid double event listeners, we need to use `HostListener`. Once Ivy is the default, we
1517
+ // can move this back into `host`.
1518
+ // tslint:disable:no-host-decorator-in-concrete
1519
+ /** Place focus on the first MenuItem in the menu and set the focus origin. */
1520
+ focusFirstItem(focusOrigin = 'program') {
1521
+ this._keyManager.setFocusOrigin(focusOrigin);
1522
+ this._keyManager.setFirstItemActive();
1523
+ }
1524
+ /** Place focus on the last MenuItem in the menu and set the focus origin. */
1525
+ focusLastItem(focusOrigin = 'program') {
1526
+ this._keyManager.setFocusOrigin(focusOrigin);
1527
+ this._keyManager.setLastItemActive();
1528
+ }
1529
+ // In Ivy the `host` metadata will be merged, whereas in ViewEngine it is overridden. In order
1530
+ // to avoid double event listeners, we need to use `HostListener`. Once Ivy is the default, we
1531
+ // can move this back into `host`.
1532
+ // tslint:disable:no-host-decorator-in-concrete
1533
+ /**
1534
+ * Handle keyboard events, specifically changing the focused element and/or toggling the active
1535
+ * items menu.
1536
+ * @param event the KeyboardEvent to handle.
1537
+ */
1538
+ _handleKeyEvent(event) {
1539
+ const keyManager = this._keyManager;
1540
+ switch (event.keyCode) {
1541
+ case UP_ARROW:
1542
+ case DOWN_ARROW:
1543
+ case LEFT_ARROW:
1544
+ case RIGHT_ARROW:
1545
+ const horizontalArrows = event.keyCode === LEFT_ARROW || event.keyCode === RIGHT_ARROW;
1546
+ // For a horizontal menu if the left/right keys were clicked, or a vertical menu if the
1547
+ // up/down keys were clicked: if the current menu is open, close it then focus and open the
1548
+ // next menu.
1549
+ if ((this._isHorizontal() && horizontalArrows) ||
1550
+ (!this._isHorizontal() && !horizontalArrows)) {
1551
+ event.preventDefault();
1552
+ const prevIsOpen = keyManager.activeItem?.isMenuOpen();
1553
+ keyManager.activeItem?.getMenuTrigger()?.closeMenu();
1554
+ keyManager.setFocusOrigin('keyboard');
1555
+ keyManager.onKeydown(event);
1556
+ if (prevIsOpen) {
1557
+ keyManager.activeItem?.getMenuTrigger()?.openMenu();
1558
+ }
1559
+ }
1560
+ break;
1561
+ case ESCAPE:
1562
+ event.preventDefault();
1563
+ keyManager.activeItem?.getMenuTrigger()?.closeMenu();
1564
+ break;
1565
+ case TAB:
1566
+ keyManager.activeItem?.getMenuTrigger()?.closeMenu();
1567
+ break;
1568
+ default:
1569
+ keyManager.onKeydown(event);
1570
+ }
1571
+ }
1572
+ /** Setup the FocusKeyManager with the correct orientation for the menu bar. */
1573
+ _setKeyManager() {
1574
+ this._keyManager = new FocusKeyManager(this._allItems)
1575
+ .withWrap()
1576
+ .withTypeAhead()
1577
+ .withHomeAndEnd();
1578
+ if (this._isHorizontal()) {
1579
+ this._keyManager.withHorizontalOrientation(this._dir?.value || 'ltr');
1580
+ }
1581
+ else {
1582
+ this._keyManager.withVerticalOrientation();
1583
+ }
1584
+ }
1585
+ /**
1586
+ * Set the PointerFocusTracker and ensure that when mouse focus changes the key manager is updated
1587
+ * with the latest menu item under mouse focus.
1588
+ */
1589
+ _subscribeToMouseManager() {
1590
+ this._ngZone.runOutsideAngular(() => {
1591
+ this._pointerTracker = new PointerFocusTracker(this._allItems);
1592
+ this._pointerTracker.entered.pipe(takeUntil(this._destroyed)).subscribe(item => {
1593
+ if (this._hasOpenSubmenu()) {
1594
+ this._keyManager.setActiveItem(item);
1595
+ }
1596
+ });
1597
+ });
1598
+ }
1599
+ /** Subscribe to the MenuStack close and empty observables. */
1600
+ _subscribeToMenuStack() {
1601
+ this._menuStack.closed
1602
+ .pipe(takeUntil(this._destroyed))
1603
+ .subscribe(item => this._closeOpenMenu(item));
1604
+ this._menuStack.emptied
1605
+ .pipe(takeUntil(this._destroyed))
1606
+ .subscribe(event => this._toggleOpenMenu(event));
1607
+ }
1608
+ /**
1609
+ * Close the open menu if the current active item opened the requested MenuStackItem.
1610
+ * @param item the MenuStackItem requested to be closed.
1611
+ */
1612
+ _closeOpenMenu(menu) {
1613
+ const trigger = this._openItem;
1614
+ const keyManager = this._keyManager;
1615
+ if (menu === trigger?.getMenuTrigger()?.getMenu()) {
1616
+ trigger?.getMenuTrigger()?.closeMenu();
1617
+ // If the user has moused over a sibling item we want to focus the element under mouse focus
1618
+ // not the trigger which previously opened the now closed menu.
1619
+ if (trigger) {
1620
+ keyManager.setActiveItem(this._pointerTracker?.activeElement || trigger);
1621
+ }
1622
+ }
1623
+ }
1624
+ /**
1625
+ * Set focus to either the current, previous or next item based on the FocusNext event, then
1626
+ * open the previous or next item.
1627
+ */
1628
+ _toggleOpenMenu(event) {
1629
+ const keyManager = this._keyManager;
1630
+ switch (event) {
1631
+ case 0 /* nextItem */:
1632
+ keyManager.setFocusOrigin('keyboard');
1633
+ keyManager.setNextItemActive();
1634
+ keyManager.activeItem?.getMenuTrigger()?.openMenu();
1635
+ break;
1636
+ case 1 /* previousItem */:
1637
+ keyManager.setFocusOrigin('keyboard');
1638
+ keyManager.setPreviousItemActive();
1639
+ keyManager.activeItem?.getMenuTrigger()?.openMenu();
1640
+ break;
1641
+ case 2 /* currentItem */:
1642
+ if (keyManager.activeItem) {
1643
+ keyManager.setFocusOrigin('keyboard');
1644
+ keyManager.setActiveItem(keyManager.activeItem);
1645
+ }
1646
+ break;
1647
+ }
1648
+ }
1649
+ /**
1650
+ * @return true if the menu bar is configured to be horizontal.
1651
+ */
1652
+ _isHorizontal() {
1653
+ return this.orientation === 'horizontal';
1654
+ }
1655
+ /**
1656
+ * Subscribe to the menu trigger's open events in order to track the trigger which opened the menu
1657
+ * and stop tracking it when the menu is closed.
1658
+ */
1659
+ _subscribeToMenuOpen() {
1660
+ const exitCondition = merge(this._allItems.changes, this._destroyed);
1661
+ this._allItems.changes
1662
+ .pipe(startWith(this._allItems), mergeMap((list) => list
1663
+ .filter(item => item.hasMenu())
1664
+ .map(item => item.getMenuTrigger().opened.pipe(mapTo(item), takeUntil(exitCondition)))), mergeAll(), switchMap((item) => {
1665
+ this._openItem = item;
1666
+ return item.getMenuTrigger().closed;
1667
+ }), takeUntil(this._destroyed))
1668
+ .subscribe(() => (this._openItem = undefined));
1669
+ }
1670
+ /** Return true if the MenuBar has an open submenu. */
1671
+ _hasOpenSubmenu() {
1672
+ return !!this._openItem;
1673
+ }
1674
+ ngOnDestroy() {
1675
+ super.ngOnDestroy();
1676
+ this._destroyed.next();
1677
+ this._destroyed.complete();
1678
+ this._pointerTracker?.destroy();
1679
+ }
1680
+ }
1681
+ CdkMenuBar.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.0-next.15", ngImport: i0, type: CdkMenuBar, deps: [{ token: MenuStack }, { token: i0.NgZone }, { token: i0.ElementRef }, { token: MENU_AIM, optional: true, self: true }, { token: i2.Directionality, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
1682
+ CdkMenuBar.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.0.0-next.15", type: CdkMenuBar, selector: "[cdkMenuBar]", inputs: { orientation: ["cdkMenuBarOrientation", "orientation"] }, host: { attributes: { "role": "menubar", "tabindex": "0" }, listeners: { "focus": "focusFirstItem()", "keydown": "_handleKeyEvent($event)" }, properties: { "attr.aria-orientation": "orientation" }, classAttribute: "cdk-menu-bar" }, providers: [
1683
+ { provide: CdkMenuGroup, useExisting: CdkMenuBar },
1684
+ { provide: CDK_MENU, useExisting: CdkMenuBar },
1685
+ { provide: MenuStack, useClass: MenuStack },
1686
+ ], queries: [{ propertyName: "_allItems", predicate: CdkMenuItem, descendants: true }], exportAs: ["cdkMenuBar"], usesInheritance: true, ngImport: i0 });
1687
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.0-next.15", ngImport: i0, type: CdkMenuBar, decorators: [{
1688
+ type: Directive,
1689
+ args: [{
1690
+ selector: '[cdkMenuBar]',
1691
+ exportAs: 'cdkMenuBar',
1692
+ host: {
1693
+ 'role': 'menubar',
1694
+ 'class': 'cdk-menu-bar',
1695
+ 'tabindex': '0',
1696
+ '[attr.aria-orientation]': 'orientation',
1697
+ },
1698
+ providers: [
1699
+ { provide: CdkMenuGroup, useExisting: CdkMenuBar },
1700
+ { provide: CDK_MENU, useExisting: CdkMenuBar },
1701
+ { provide: MenuStack, useClass: MenuStack },
1702
+ ],
1703
+ }]
1704
+ }], ctorParameters: function () { return [{ type: MenuStack }, { type: i0.NgZone }, { type: i0.ElementRef }, { type: undefined, decorators: [{
1705
+ type: Self
1706
+ }, {
1707
+ type: Optional
1708
+ }, {
1709
+ type: Inject,
1710
+ args: [MENU_AIM]
1711
+ }] }, { type: i2.Directionality, decorators: [{
1712
+ type: Optional
1713
+ }] }]; }, propDecorators: { orientation: [{
1714
+ type: Input,
1715
+ args: ['cdkMenuBarOrientation']
1716
+ }], _allItems: [{
1717
+ type: ContentChildren,
1718
+ args: [CdkMenuItem, { descendants: true }]
1719
+ }],
1720
+ /** Place focus on the first MenuItem in the menu and set the focus origin. */
1721
+ focusFirstItem: [{
1722
+ type: HostListener,
1723
+ args: ['focus']
1724
+ }],
1725
+ /**
1726
+ * Handle keyboard events, specifically changing the focused element and/or toggling the active
1727
+ * items menu.
1728
+ * @param event the KeyboardEvent to handle.
1729
+ */
1730
+ _handleKeyEvent: [{
1731
+ type: HostListener,
1732
+ args: ['keydown', ['$event']]
1733
+ }] } });
1734
+
1735
+ /**
1736
+ * @license
1737
+ * Copyright Google LLC All Rights Reserved.
1738
+ *
1739
+ * Use of this source code is governed by an MIT-style license that can be
1740
+ * found in the LICENSE file at https://angular.io/license
1741
+ */
1742
+ /**
1743
+ * A directive providing behavior for the "menuitemradio" ARIA role, which behaves similarly to
1744
+ * a conventional radio-button. Any sibling `CdkMenuItemRadio` instances within the same `CdkMenu`
1745
+ * or `CdkMenuGroup` comprise a radio group with unique selection enforced.
1746
+ */
1747
+ class CdkMenuItemRadio extends CdkMenuItemSelectable {
1748
+ constructor(_selectionDispatcher, element, ngZone, parentMenu, menuAim, dir,
1749
+ /** Reference to the CdkMenuItemTrigger directive if one is added to the same element */
1750
+ // `CdkMenuItemRadio` is commonly used in combination with a `CdkMenuItemTrigger`.
1751
+ // tslint:disable-next-line: lightweight-tokens
1752
+ menuTrigger) {
1753
+ super(element, ngZone, parentMenu, menuAim, dir, menuTrigger);
1754
+ this._selectionDispatcher = _selectionDispatcher;
1755
+ this._registerDispatcherListener();
1756
+ }
1757
+ /** Configure the unique selection dispatcher listener in order to toggle the checked state */
1758
+ _registerDispatcherListener() {
1759
+ this._removeDispatcherListener = this._selectionDispatcher.listen((id, name) => (this.checked = this.id === id && this.name === name));
1760
+ }
1761
+ /** Toggles the checked state of the radio-button. */
1762
+ trigger() {
1763
+ super.trigger();
1764
+ if (!this.disabled) {
1765
+ this._selectionDispatcher.notify(this.id, this.name);
1766
+ }
1767
+ }
1768
+ ngOnDestroy() {
1769
+ super.ngOnDestroy();
1770
+ this._removeDispatcherListener();
1771
+ }
1772
+ }
1773
+ CdkMenuItemRadio.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.0-next.15", ngImport: i0, type: CdkMenuItemRadio, deps: [{ token: i1$1.UniqueSelectionDispatcher }, { token: i0.ElementRef }, { token: i0.NgZone }, { token: CDK_MENU, optional: true }, { token: MENU_AIM, optional: true }, { token: i2.Directionality, optional: true }, { token: CdkMenuItemTrigger, optional: true, self: true }], target: i0.ɵɵFactoryTarget.Directive });
1774
+ CdkMenuItemRadio.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.0.0-next.15", type: CdkMenuItemRadio, selector: "[cdkMenuItemRadio]", host: { attributes: { "type": "button", "role": "menuitemradio" }, properties: { "tabindex": "_tabindex", "attr.aria-checked": "checked || null", "attr.aria-disabled": "disabled || null" } }, providers: [
1775
+ { provide: CdkMenuItemSelectable, useExisting: CdkMenuItemRadio },
1776
+ { provide: CdkMenuItem, useExisting: CdkMenuItemSelectable },
1777
+ ], exportAs: ["cdkMenuItemRadio"], usesInheritance: true, ngImport: i0 });
1778
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.0-next.15", ngImport: i0, type: CdkMenuItemRadio, decorators: [{
1779
+ type: Directive,
1780
+ args: [{
1781
+ selector: '[cdkMenuItemRadio]',
1782
+ exportAs: 'cdkMenuItemRadio',
1783
+ host: {
1784
+ '[tabindex]': '_tabindex',
1785
+ 'type': 'button',
1786
+ 'role': 'menuitemradio',
1787
+ '[attr.aria-checked]': 'checked || null',
1788
+ '[attr.aria-disabled]': 'disabled || null',
1789
+ },
1790
+ providers: [
1791
+ { provide: CdkMenuItemSelectable, useExisting: CdkMenuItemRadio },
1792
+ { provide: CdkMenuItem, useExisting: CdkMenuItemSelectable },
1793
+ ],
1794
+ }]
1795
+ }], ctorParameters: function () { return [{ type: i1$1.UniqueSelectionDispatcher }, { type: i0.ElementRef }, { type: i0.NgZone }, { type: undefined, decorators: [{
1796
+ type: Optional
1797
+ }, {
1798
+ type: Inject,
1799
+ args: [CDK_MENU]
1800
+ }] }, { type: undefined, decorators: [{
1801
+ type: Optional
1802
+ }, {
1803
+ type: Inject,
1804
+ args: [MENU_AIM]
1805
+ }] }, { type: i2.Directionality, decorators: [{
1806
+ type: Optional
1807
+ }] }, { type: CdkMenuItemTrigger, decorators: [{
1808
+ type: Self
1809
+ }, {
1810
+ type: Optional
1811
+ }] }]; } });
1812
+
1813
+ /**
1814
+ * @license
1815
+ * Copyright Google LLC All Rights Reserved.
1816
+ *
1817
+ * Use of this source code is governed by an MIT-style license that can be
1818
+ * found in the LICENSE file at https://angular.io/license
1819
+ */
1820
+ /**
1821
+ * A directive providing behavior for the "menuitemcheckbox" ARIA role, which behaves similarly to a
1822
+ * conventional checkbox.
1823
+ */
1824
+ class CdkMenuItemCheckbox extends CdkMenuItemSelectable {
1825
+ /** Toggle the checked state of the checkbox. */
1826
+ trigger() {
1827
+ super.trigger();
1828
+ if (!this.disabled) {
1829
+ this.checked = !this.checked;
1830
+ }
1831
+ }
1832
+ }
1833
+ CdkMenuItemCheckbox.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.0-next.15", ngImport: i0, type: CdkMenuItemCheckbox, deps: null, target: i0.ɵɵFactoryTarget.Directive });
1834
+ CdkMenuItemCheckbox.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.0.0-next.15", type: CdkMenuItemCheckbox, selector: "[cdkMenuItemCheckbox]", host: { attributes: { "type": "button", "role": "menuitemcheckbox" }, properties: { "tabindex": "_tabindex", "attr.aria-checked": "checked || null", "attr.aria-disabled": "disabled || null" } }, providers: [
1835
+ { provide: CdkMenuItemSelectable, useExisting: CdkMenuItemCheckbox },
1836
+ { provide: CdkMenuItem, useExisting: CdkMenuItemSelectable },
1837
+ ], exportAs: ["cdkMenuItemCheckbox"], usesInheritance: true, ngImport: i0 });
1838
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.0-next.15", ngImport: i0, type: CdkMenuItemCheckbox, decorators: [{
1839
+ type: Directive,
1840
+ args: [{
1841
+ selector: '[cdkMenuItemCheckbox]',
1842
+ exportAs: 'cdkMenuItemCheckbox',
1843
+ host: {
1844
+ '[tabindex]': '_tabindex',
1845
+ 'type': 'button',
1846
+ 'role': 'menuitemcheckbox',
1847
+ '[attr.aria-checked]': 'checked || null',
1848
+ '[attr.aria-disabled]': 'disabled || null',
1849
+ },
1850
+ providers: [
1851
+ { provide: CdkMenuItemSelectable, useExisting: CdkMenuItemCheckbox },
1852
+ { provide: CdkMenuItem, useExisting: CdkMenuItemSelectable },
1853
+ ],
1854
+ }]
1855
+ }] });
1856
+
1857
+ /**
1858
+ * @license
1859
+ * Copyright Google LLC All Rights Reserved.
1860
+ *
1861
+ * Use of this source code is governed by an MIT-style license that can be
1862
+ * found in the LICENSE file at https://angular.io/license
1863
+ */
1864
+ /** Tracks the last open context menu trigger across the entire application. */
1865
+ class ContextMenuTracker {
1866
+ /**
1867
+ * Close the previous open context menu and set the given one as being open.
1868
+ * @param trigger the trigger for the currently open Context Menu.
1869
+ */
1870
+ update(trigger) {
1871
+ if (ContextMenuTracker._openContextMenuTrigger !== trigger) {
1872
+ ContextMenuTracker._openContextMenuTrigger?.close();
1873
+ ContextMenuTracker._openContextMenuTrigger = trigger;
1874
+ }
1875
+ }
1876
+ }
1877
+ ContextMenuTracker.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.0-next.15", ngImport: i0, type: ContextMenuTracker, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1878
+ ContextMenuTracker.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.0.0-next.15", ngImport: i0, type: ContextMenuTracker, providedIn: 'root' });
1879
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.0-next.15", ngImport: i0, type: ContextMenuTracker, decorators: [{
1880
+ type: Injectable,
1881
+ args: [{ providedIn: 'root' }]
1882
+ }] });
1883
+ /** Injection token for the ContextMenu options object. */
1884
+ const CDK_CONTEXT_MENU_DEFAULT_OPTIONS = new InjectionToken('cdk-context-menu-default-options');
1885
+ /**
1886
+ * A directive which when placed on some element opens a the Menu it is bound to when a user
1887
+ * right-clicks within that element. It is aware of nested Context Menus and the lowest level
1888
+ * non-disabled context menu will trigger.
1889
+ */
1890
+ class CdkContextMenuTrigger {
1891
+ constructor(_viewContainerRef, _overlay, _contextMenuTracker, _options, _directionality) {
1892
+ this._viewContainerRef = _viewContainerRef;
1893
+ this._overlay = _overlay;
1894
+ this._contextMenuTracker = _contextMenuTracker;
1895
+ this._options = _options;
1896
+ this._directionality = _directionality;
1897
+ /** Emits when the attached menu is requested to open. */
1898
+ this.opened = new EventEmitter();
1899
+ /** Emits when the attached menu is requested to close. */
1900
+ this.closed = new EventEmitter();
1901
+ this._disabled = false;
1902
+ /** A reference to the overlay which manages the triggered menu. */
1903
+ this._overlayRef = null;
1904
+ /** Emits when the element is destroyed. */
1905
+ this._destroyed = new Subject();
1906
+ /** The menu stack for this trigger and its associated menus. */
1907
+ this._menuStack = new MenuStack();
1908
+ /** Emits when the outside pointer events listener on the overlay should be stopped. */
1909
+ this._stopOutsideClicksListener = merge(this.closed, this._destroyed);
1910
+ this._setMenuStackListener();
1911
+ }
1912
+ /** Template reference variable to the menu to open on right click. */
1913
+ get menuPanel() {
1914
+ return this._menuPanel;
1915
+ }
1916
+ set menuPanel(panel) {
1917
+ if ((typeof ngDevMode === 'undefined' || ngDevMode) && panel._menuStack) {
1918
+ throwExistingMenuStackError();
1919
+ }
1920
+ this._menuPanel = panel;
1921
+ if (this._menuPanel) {
1922
+ this._menuPanel._menuStack = this._menuStack;
1923
+ }
1924
+ }
1925
+ /** Whether the context menu should be disabled. */
1926
+ get disabled() {
1927
+ return this._disabled;
1928
+ }
1929
+ set disabled(value) {
1930
+ this._disabled = coerceBooleanProperty(value);
1931
+ }
1932
+ /**
1933
+ * Open the attached menu at the specified location.
1934
+ * @param coordinates where to open the context menu
1935
+ */
1936
+ open(coordinates) {
1937
+ if (this.disabled) {
1938
+ return;
1939
+ }
1940
+ else if (this.isOpen()) {
1941
+ // since we're moving this menu we need to close any submenus first otherwise they end up
1942
+ // disconnected from this one.
1943
+ this._menuStack.closeSubMenuOf(this._menuPanel._menu);
1944
+ this._overlayRef.getConfig().positionStrategy.setOrigin(coordinates);
1945
+ this._overlayRef.updatePosition();
1946
+ }
1947
+ else {
1948
+ this.opened.next();
1949
+ if (this._overlayRef) {
1950
+ this._overlayRef.getConfig().positionStrategy.setOrigin(coordinates);
1951
+ this._overlayRef.updatePosition();
1952
+ }
1953
+ else {
1954
+ this._overlayRef = this._overlay.create(this._getOverlayConfig(coordinates));
1955
+ }
1956
+ this._overlayRef.attach(this._getMenuContent());
1957
+ this._subscribeToOutsideClicks();
1958
+ }
1959
+ }
1960
+ /** Close the opened menu. */
1961
+ close() {
1962
+ this._menuStack.closeAll();
1963
+ }
1964
+ /**
1965
+ * Open the context menu and close any previously open menus.
1966
+ * @param event the mouse event which opens the context menu.
1967
+ */
1968
+ _openOnContextMenu(event) {
1969
+ if (!this.disabled) {
1970
+ // Prevent the native context menu from opening because we're opening a custom one.
1971
+ event.preventDefault();
1972
+ // Stop event propagation to ensure that only the closest enabled context menu opens.
1973
+ // Otherwise, any context menus attached to containing elements would *also* open,
1974
+ // resulting in multiple stacked context menus being displayed.
1975
+ event.stopPropagation();
1976
+ this._contextMenuTracker.update(this);
1977
+ this.open({ x: event.clientX, y: event.clientY });
1978
+ // A context menu can be triggered via a mouse right click or a keyboard shortcut.
1979
+ if (event.button === 2) {
1980
+ this._menuPanel._menu?.focusFirstItem('mouse');
1981
+ }
1982
+ else if (event.button === 0) {
1983
+ this._menuPanel._menu?.focusFirstItem('keyboard');
1984
+ }
1985
+ else {
1986
+ this._menuPanel._menu?.focusFirstItem('program');
1987
+ }
1988
+ }
1989
+ }
1990
+ /** Whether the attached menu is open. */
1991
+ isOpen() {
1992
+ return !!this._overlayRef?.hasAttached();
1993
+ }
1994
+ /**
1995
+ * Get the configuration object used to create the overlay.
1996
+ * @param coordinates the location to place the opened menu
1997
+ */
1998
+ _getOverlayConfig(coordinates) {
1999
+ return new OverlayConfig({
2000
+ positionStrategy: this._getOverlayPositionStrategy(coordinates),
2001
+ scrollStrategy: this._overlay.scrollStrategies.block(),
2002
+ direction: this._directionality,
2003
+ });
2004
+ }
2005
+ /**
2006
+ * Build the position strategy for the overlay which specifies where to place the menu.
2007
+ * @param coordinates the location to place the opened menu
2008
+ */
2009
+ _getOverlayPositionStrategy(coordinates) {
2010
+ return this._overlay
2011
+ .position()
2012
+ .flexibleConnectedTo(coordinates)
2013
+ .withDefaultOffsetX(this._options.offsetX)
2014
+ .withDefaultOffsetY(this._options.offsetY)
2015
+ .withPositions(this._getOverlayPositions());
2016
+ }
2017
+ /**
2018
+ * Determine and return where to position the opened menu relative to the mouse location.
2019
+ */
2020
+ _getOverlayPositions() {
2021
+ // TODO: this should be configurable through the injected context menu options
2022
+ return [
2023
+ { originX: 'end', originY: 'top', overlayX: 'start', overlayY: 'top' },
2024
+ { originX: 'start', originY: 'top', overlayX: 'end', overlayY: 'top' },
2025
+ { originX: 'end', originY: 'bottom', overlayX: 'start', overlayY: 'bottom' },
2026
+ { originX: 'start', originY: 'bottom', overlayX: 'end', overlayY: 'bottom' },
2027
+ ];
2028
+ }
2029
+ /**
2030
+ * Get the portal to be attached to the overlay which contains the menu. Allows for the menu
2031
+ * content to change dynamically and be reflected in the application.
2032
+ */
2033
+ _getMenuContent() {
2034
+ const hasMenuContentChanged = this.menuPanel._templateRef !== this._panelContent?.templateRef;
2035
+ if (this.menuPanel && (!this._panelContent || hasMenuContentChanged)) {
2036
+ this._panelContent = new TemplatePortal(this.menuPanel._templateRef, this._viewContainerRef);
2037
+ }
2038
+ return this._panelContent;
2039
+ }
2040
+ /** Subscribe to the menu stack close events and close this menu when requested. */
2041
+ _setMenuStackListener() {
2042
+ this._menuStack.closed.pipe(takeUntil(this._destroyed)).subscribe(item => {
2043
+ if (item === this._menuPanel._menu && this.isOpen()) {
2044
+ this.closed.next();
2045
+ this._overlayRef.detach();
2046
+ }
2047
+ });
2048
+ }
2049
+ /**
2050
+ * Subscribe to the overlays outside pointer events stream and handle closing out the stack if a
2051
+ * click occurs outside the menus.
2052
+ */
2053
+ _subscribeToOutsideClicks() {
2054
+ if (this._overlayRef) {
2055
+ this._overlayRef
2056
+ .outsidePointerEvents()
2057
+ .pipe(takeUntil(this._stopOutsideClicksListener))
2058
+ .subscribe(event => {
2059
+ if (!isClickInsideMenuOverlay(event.target)) {
2060
+ this._menuStack.closeAll();
2061
+ }
2062
+ });
2063
+ }
2064
+ }
2065
+ ngOnDestroy() {
2066
+ this._destroyOverlay();
2067
+ this._resetPanelMenuStack();
2068
+ this._destroyed.next();
2069
+ this._destroyed.complete();
2070
+ }
2071
+ /** Destroy and unset the overlay reference it if exists. */
2072
+ _destroyOverlay() {
2073
+ if (this._overlayRef) {
2074
+ this._overlayRef.dispose();
2075
+ this._overlayRef = null;
2076
+ }
2077
+ }
2078
+ /** Set the menu panels menu stack back to null. */
2079
+ _resetPanelMenuStack() {
2080
+ // If a ContextMenuTrigger is placed in a conditionally rendered view, each time the trigger is
2081
+ // rendered the panel setter for ContextMenuTrigger is called. From the first render onward,
2082
+ // the attached CdkMenuPanel has the MenuStack set. Since we throw an error if a panel already
2083
+ // has a stack set, we want to reset the attached stack here to prevent the error from being
2084
+ // thrown if the trigger re-configures its attached panel (in the case where there is a 1:1
2085
+ // relationship between the panel and trigger).
2086
+ if (this._menuPanel) {
2087
+ this._menuPanel._menuStack = null;
2088
+ }
2089
+ }
2090
+ }
2091
+ CdkContextMenuTrigger.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.0-next.15", ngImport: i0, type: CdkContextMenuTrigger, deps: [{ token: i0.ViewContainerRef }, { token: i1.Overlay }, { token: ContextMenuTracker }, { token: CDK_CONTEXT_MENU_DEFAULT_OPTIONS }, { token: i2.Directionality, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
2092
+ CdkContextMenuTrigger.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.0.0-next.15", type: CdkContextMenuTrigger, selector: "[cdkContextMenuTriggerFor]", inputs: { menuPanel: ["cdkContextMenuTriggerFor", "menuPanel"], disabled: ["cdkContextMenuDisabled", "disabled"] }, outputs: { opened: "cdkContextMenuOpened", closed: "cdkContextMenuClosed" }, host: { listeners: { "contextmenu": "_openOnContextMenu($event)" } }, providers: [
2093
+ // In cases where the first menu item in the context menu is a trigger the submenu opens on a
2094
+ // hover event. Offsetting the opened context menu by 2px prevents this from occurring.
2095
+ { provide: CDK_CONTEXT_MENU_DEFAULT_OPTIONS, useValue: { offsetX: 2, offsetY: 2 } },
2096
+ ], exportAs: ["cdkContextMenuTriggerFor"], ngImport: i0 });
2097
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.0-next.15", ngImport: i0, type: CdkContextMenuTrigger, decorators: [{
2098
+ type: Directive,
2099
+ args: [{
2100
+ selector: '[cdkContextMenuTriggerFor]',
2101
+ exportAs: 'cdkContextMenuTriggerFor',
2102
+ host: {
2103
+ '(contextmenu)': '_openOnContextMenu($event)',
2104
+ },
2105
+ providers: [
2106
+ // In cases where the first menu item in the context menu is a trigger the submenu opens on a
2107
+ // hover event. Offsetting the opened context menu by 2px prevents this from occurring.
2108
+ { provide: CDK_CONTEXT_MENU_DEFAULT_OPTIONS, useValue: { offsetX: 2, offsetY: 2 } },
2109
+ ],
2110
+ }]
2111
+ }], ctorParameters: function () { return [{ type: i0.ViewContainerRef }, { type: i1.Overlay }, { type: ContextMenuTracker }, { type: undefined, decorators: [{
2112
+ type: Inject,
2113
+ args: [CDK_CONTEXT_MENU_DEFAULT_OPTIONS]
2114
+ }] }, { type: i2.Directionality, decorators: [{
2115
+ type: Optional
2116
+ }] }]; }, propDecorators: { menuPanel: [{
2117
+ type: Input,
2118
+ args: ['cdkContextMenuTriggerFor']
2119
+ }], opened: [{
2120
+ type: Output,
2121
+ args: ['cdkContextMenuOpened']
2122
+ }], closed: [{
2123
+ type: Output,
2124
+ args: ['cdkContextMenuClosed']
2125
+ }], disabled: [{
2126
+ type: Input,
2127
+ args: ['cdkContextMenuDisabled']
2128
+ }] } });
2129
+
2130
+ /**
2131
+ * @license
2132
+ * Copyright Google LLC All Rights Reserved.
2133
+ *
2134
+ * Use of this source code is governed by an MIT-style license that can be
2135
+ * found in the LICENSE file at https://angular.io/license
2136
+ */
2137
+ const EXPORTED_DECLARATIONS = [
2138
+ CdkMenuBar,
2139
+ CdkMenu,
2140
+ CdkMenuPanel,
2141
+ CdkMenuItem,
2142
+ CdkMenuItemRadio,
2143
+ CdkMenuItemCheckbox,
2144
+ CdkMenuItemTrigger,
2145
+ CdkMenuGroup,
2146
+ CdkContextMenuTrigger,
2147
+ CdkTargetMenuAim,
2148
+ ];
2149
+ class CdkMenuModule {
2150
+ }
2151
+ CdkMenuModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.0-next.15", ngImport: i0, type: CdkMenuModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
2152
+ CdkMenuModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.0.0-next.15", ngImport: i0, type: CdkMenuModule, declarations: [CdkMenuBar,
2153
+ CdkMenu,
2154
+ CdkMenuPanel,
2155
+ CdkMenuItem,
2156
+ CdkMenuItemRadio,
2157
+ CdkMenuItemCheckbox,
2158
+ CdkMenuItemTrigger,
2159
+ CdkMenuGroup,
2160
+ CdkContextMenuTrigger,
2161
+ CdkTargetMenuAim], imports: [OverlayModule], exports: [CdkMenuBar,
2162
+ CdkMenu,
2163
+ CdkMenuPanel,
2164
+ CdkMenuItem,
2165
+ CdkMenuItemRadio,
2166
+ CdkMenuItemCheckbox,
2167
+ CdkMenuItemTrigger,
2168
+ CdkMenuGroup,
2169
+ CdkContextMenuTrigger,
2170
+ CdkTargetMenuAim] });
2171
+ CdkMenuModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.0.0-next.15", ngImport: i0, type: CdkMenuModule, imports: [[OverlayModule]] });
2172
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.0-next.15", ngImport: i0, type: CdkMenuModule, decorators: [{
2173
+ type: NgModule,
2174
+ args: [{
2175
+ imports: [OverlayModule],
2176
+ exports: EXPORTED_DECLARATIONS,
2177
+ declarations: EXPORTED_DECLARATIONS,
2178
+ }]
2179
+ }] });
2180
+
2181
+ /**
2182
+ * @license
2183
+ * Copyright Google LLC All Rights Reserved.
2184
+ *
2185
+ * Use of this source code is governed by an MIT-style license that can be
2186
+ * found in the LICENSE file at https://angular.io/license
2187
+ */
2188
+
2189
+ /**
2190
+ * @license
2191
+ * Copyright Google LLC All Rights Reserved.
2192
+ *
2193
+ * Use of this source code is governed by an MIT-style license that can be
2194
+ * found in the LICENSE file at https://angular.io/license
2195
+ */
2196
+
2197
+ /**
2198
+ * Generated bundle index. Do not edit.
2199
+ */
2200
+
2201
+ export { CDK_CONTEXT_MENU_DEFAULT_OPTIONS, CDK_MENU, CdkContextMenuTrigger, CdkMenu, CdkMenuBar, CdkMenuGroup, CdkMenuItem, CdkMenuItemCheckbox, CdkMenuItemRadio, CdkMenuItemTrigger, CdkMenuModule, CdkMenuPanel, CdkTargetMenuAim, ContextMenuTracker, MENU_AIM, MenuStack, TargetMenuAim, isClickInsideMenuOverlay };
2202
+ //# sourceMappingURL=menu.mjs.map