primeng 16.0.2 → 16.1.0

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 (222) hide show
  1. package/accordion/accordion.d.ts +35 -11
  2. package/api/translation.d.ts +23 -0
  3. package/api/treenode.d.ts +1 -1
  4. package/avatar/avatar.d.ts +11 -1
  5. package/breadcrumb/breadcrumb.d.ts +5 -1
  6. package/button/button.d.ts +3 -0
  7. package/chip/chip.d.ts +1 -0
  8. package/contextmenu/contextmenu.d.ts +157 -67
  9. package/dock/dock.d.ts +47 -2
  10. package/dom/domhandler.d.ts +1 -0
  11. package/esm2022/accordion/accordion.mjs +177 -43
  12. package/esm2022/api/primengconfig.mjs +75 -2
  13. package/esm2022/api/translation.mjs +1 -1
  14. package/esm2022/api/treenode.mjs +1 -1
  15. package/esm2022/autocomplete/autocomplete.mjs +3 -3
  16. package/esm2022/avatar/avatar.mjs +18 -4
  17. package/esm2022/blockui/blockui.mjs +19 -3
  18. package/esm2022/breadcrumb/breadcrumb.mjs +50 -33
  19. package/esm2022/button/button.mjs +4 -1
  20. package/esm2022/card/card.mjs +3 -3
  21. package/esm2022/chip/chip.mjs +18 -13
  22. package/esm2022/contextmenu/contextmenu.mjs +993 -547
  23. package/esm2022/divider/divider.mjs +3 -3
  24. package/esm2022/dock/dock.mjs +284 -86
  25. package/esm2022/dom/domhandler.mjs +19 -7
  26. package/esm2022/dynamicdialog/dynamicdialog-ref.mjs +4 -1
  27. package/esm2022/fieldset/fieldset.mjs +59 -32
  28. package/esm2022/image/image.mjs +11 -3
  29. package/esm2022/inplace/inplace.mjs +18 -11
  30. package/esm2022/megamenu/megamenu.mjs +997 -348
  31. package/esm2022/menu/menu.mjs +397 -166
  32. package/esm2022/menubar/menubar.mjs +895 -282
  33. package/esm2022/orderlist/orderlist.mjs +9 -15
  34. package/esm2022/panel/panel.mjs +44 -33
  35. package/esm2022/panelmenu/panelmenu.mjs +982 -344
  36. package/esm2022/progressbar/progressbar.mjs +19 -15
  37. package/esm2022/progressspinner/progressspinner.mjs +5 -5
  38. package/esm2022/ripple/ripple.mjs +3 -1
  39. package/esm2022/scrollpanel/scrollpanel.mjs +195 -23
  40. package/esm2022/scrolltop/scrolltop.mjs +11 -2
  41. package/esm2022/skeleton/skeleton.mjs +3 -3
  42. package/esm2022/slidemenu/slidemenu.mjs +1059 -372
  43. package/esm2022/splitbutton/splitbutton.mjs +2 -2
  44. package/esm2022/splitter/splitter.mjs +160 -29
  45. package/esm2022/steps/steps.mjs +112 -22
  46. package/esm2022/table/table.mjs +13 -7
  47. package/esm2022/tabmenu/tabmenu.mjs +191 -63
  48. package/esm2022/tabview/tabview.mjs +173 -39
  49. package/esm2022/terminal/terminal.mjs +3 -3
  50. package/esm2022/tieredmenu/tieredmenu.mjs +868 -392
  51. package/esm2022/toolbar/toolbar.mjs +17 -10
  52. package/esm2022/tooltip/tooltip.mjs +1 -1
  53. package/esm2022/tree/tree.mjs +3 -3
  54. package/esm2022/treetable/treetable.mjs +17 -17
  55. package/esm2022/utils/objectutils.mjs +31 -1
  56. package/esm2022/utils/uniquecomponentid.mjs +2 -3
  57. package/fesm2022/primeng-accordion.mjs +176 -42
  58. package/fesm2022/primeng-accordion.mjs.map +1 -1
  59. package/fesm2022/primeng-api.mjs +74 -1
  60. package/fesm2022/primeng-api.mjs.map +1 -1
  61. package/fesm2022/primeng-autocomplete.mjs +2 -2
  62. package/fesm2022/primeng-autocomplete.mjs.map +1 -1
  63. package/fesm2022/primeng-avatar.mjs +17 -3
  64. package/fesm2022/primeng-avatar.mjs.map +1 -1
  65. package/fesm2022/primeng-blockui.mjs +18 -2
  66. package/fesm2022/primeng-blockui.mjs.map +1 -1
  67. package/fesm2022/primeng-breadcrumb.mjs +49 -32
  68. package/fesm2022/primeng-breadcrumb.mjs.map +1 -1
  69. package/fesm2022/primeng-button.mjs +3 -0
  70. package/fesm2022/primeng-button.mjs.map +1 -1
  71. package/fesm2022/primeng-card.mjs +2 -2
  72. package/fesm2022/primeng-card.mjs.map +1 -1
  73. package/fesm2022/primeng-chip.mjs +17 -12
  74. package/fesm2022/primeng-chip.mjs.map +1 -1
  75. package/fesm2022/primeng-contextmenu.mjs +992 -546
  76. package/fesm2022/primeng-contextmenu.mjs.map +1 -1
  77. package/fesm2022/primeng-divider.mjs +2 -2
  78. package/fesm2022/primeng-divider.mjs.map +1 -1
  79. package/fesm2022/primeng-dock.mjs +283 -85
  80. package/fesm2022/primeng-dock.mjs.map +1 -1
  81. package/fesm2022/primeng-dom.mjs +18 -6
  82. package/fesm2022/primeng-dom.mjs.map +1 -1
  83. package/fesm2022/primeng-dynamicdialog.mjs +3 -0
  84. package/fesm2022/primeng-dynamicdialog.mjs.map +1 -1
  85. package/fesm2022/primeng-fieldset.mjs +57 -30
  86. package/fesm2022/primeng-fieldset.mjs.map +1 -1
  87. package/fesm2022/primeng-image.mjs +10 -2
  88. package/fesm2022/primeng-image.mjs.map +1 -1
  89. package/fesm2022/primeng-inplace.mjs +17 -10
  90. package/fesm2022/primeng-inplace.mjs.map +1 -1
  91. package/fesm2022/primeng-megamenu.mjs +996 -348
  92. package/fesm2022/primeng-megamenu.mjs.map +1 -1
  93. package/fesm2022/primeng-menu.mjs +396 -165
  94. package/fesm2022/primeng-menu.mjs.map +1 -1
  95. package/fesm2022/primeng-menubar.mjs +894 -281
  96. package/fesm2022/primeng-menubar.mjs.map +1 -1
  97. package/fesm2022/primeng-orderlist.mjs +8 -14
  98. package/fesm2022/primeng-orderlist.mjs.map +1 -1
  99. package/fesm2022/primeng-panel.mjs +44 -33
  100. package/fesm2022/primeng-panel.mjs.map +1 -1
  101. package/fesm2022/primeng-panelmenu.mjs +981 -344
  102. package/fesm2022/primeng-panelmenu.mjs.map +1 -1
  103. package/fesm2022/primeng-progressbar.mjs +18 -14
  104. package/fesm2022/primeng-progressbar.mjs.map +1 -1
  105. package/fesm2022/primeng-progressspinner.mjs +4 -4
  106. package/fesm2022/primeng-progressspinner.mjs.map +1 -1
  107. package/fesm2022/primeng-ripple.mjs +2 -0
  108. package/fesm2022/primeng-ripple.mjs.map +1 -1
  109. package/fesm2022/primeng-scrollpanel.mjs +194 -22
  110. package/fesm2022/primeng-scrollpanel.mjs.map +1 -1
  111. package/fesm2022/primeng-scrolltop.mjs +10 -1
  112. package/fesm2022/primeng-scrolltop.mjs.map +1 -1
  113. package/fesm2022/primeng-skeleton.mjs +2 -2
  114. package/fesm2022/primeng-skeleton.mjs.map +1 -1
  115. package/fesm2022/primeng-slidemenu.mjs +1058 -371
  116. package/fesm2022/primeng-slidemenu.mjs.map +1 -1
  117. package/fesm2022/primeng-splitbutton.mjs +1 -1
  118. package/fesm2022/primeng-splitbutton.mjs.map +1 -1
  119. package/fesm2022/primeng-splitter.mjs +160 -29
  120. package/fesm2022/primeng-splitter.mjs.map +1 -1
  121. package/fesm2022/primeng-steps.mjs +111 -21
  122. package/fesm2022/primeng-steps.mjs.map +1 -1
  123. package/fesm2022/primeng-table.mjs +12 -6
  124. package/fesm2022/primeng-table.mjs.map +1 -1
  125. package/fesm2022/primeng-tabmenu.mjs +190 -62
  126. package/fesm2022/primeng-tabmenu.mjs.map +1 -1
  127. package/fesm2022/primeng-tabview.mjs +172 -38
  128. package/fesm2022/primeng-tabview.mjs.map +1 -1
  129. package/fesm2022/primeng-terminal.mjs +2 -2
  130. package/fesm2022/primeng-terminal.mjs.map +1 -1
  131. package/fesm2022/primeng-tieredmenu.mjs +867 -391
  132. package/fesm2022/primeng-tieredmenu.mjs.map +1 -1
  133. package/fesm2022/primeng-toolbar.mjs +16 -9
  134. package/fesm2022/primeng-toolbar.mjs.map +1 -1
  135. package/fesm2022/primeng-tooltip.mjs.map +1 -1
  136. package/fesm2022/primeng-tree.mjs +2 -2
  137. package/fesm2022/primeng-tree.mjs.map +1 -1
  138. package/fesm2022/primeng-treetable.mjs +16 -16
  139. package/fesm2022/primeng-treetable.mjs.map +1 -1
  140. package/fesm2022/primeng-utils.mjs +31 -2
  141. package/fesm2022/primeng-utils.mjs.map +1 -1
  142. package/fieldset/fieldset.d.ts +6 -5
  143. package/image/image.d.ts +1 -0
  144. package/inplace/inplace.d.ts +6 -1
  145. package/megamenu/megamenu.d.ts +137 -15
  146. package/menu/menu.d.ts +64 -7
  147. package/menubar/menubar.d.ts +116 -22
  148. package/orderlist/orderlist.d.ts +2 -1
  149. package/package.json +124 -124
  150. package/panel/panel.d.ts +6 -5
  151. package/panelmenu/panelmenu.d.ts +134 -22
  152. package/resources/components/autocomplete/autocomplete.css +9 -8
  153. package/resources/components/breadcrumb/breadcrumb.css +9 -3
  154. package/resources/components/common/common.css +1 -1
  155. package/resources/components/contextmenu/contextmenu.css +1 -7
  156. package/resources/components/dock/dock.css +1 -1
  157. package/resources/components/megamenu/megamenu.css +9 -10
  158. package/resources/components/panelmenu/panelmenu.css +4 -2
  159. package/resources/components/slidemenu/slidemenu.css +40 -41
  160. package/resources/primeng.css +1 -1
  161. package/resources/primeng.min.css +1 -1
  162. package/resources/themes/arya-blue/theme.css +342 -390
  163. package/resources/themes/arya-green/theme.css +342 -390
  164. package/resources/themes/arya-orange/theme.css +342 -390
  165. package/resources/themes/arya-purple/theme.css +342 -390
  166. package/resources/themes/bootstrap4-dark-blue/theme.css +357 -416
  167. package/resources/themes/bootstrap4-dark-purple/theme.css +357 -416
  168. package/resources/themes/bootstrap4-light-blue/theme.css +369 -428
  169. package/resources/themes/bootstrap4-light-purple/theme.css +369 -428
  170. package/resources/themes/fluent-light/theme.css +352 -400
  171. package/resources/themes/lara-dark-blue/theme.css +344 -392
  172. package/resources/themes/lara-dark-indigo/theme.css +344 -392
  173. package/resources/themes/lara-dark-purple/theme.css +344 -392
  174. package/resources/themes/lara-dark-teal/theme.css +344 -392
  175. package/resources/themes/lara-light-blue/theme.css +370 -418
  176. package/resources/themes/lara-light-indigo/theme.css +370 -418
  177. package/resources/themes/lara-light-purple/theme.css +370 -418
  178. package/resources/themes/lara-light-teal/theme.css +370 -418
  179. package/resources/themes/luna-amber/theme.css +360 -408
  180. package/resources/themes/luna-blue/theme.css +360 -408
  181. package/resources/themes/luna-green/theme.css +360 -408
  182. package/resources/themes/luna-pink/theme.css +360 -408
  183. package/resources/themes/md-dark-deeppurple/theme.css +373 -403
  184. package/resources/themes/md-dark-indigo/theme.css +373 -403
  185. package/resources/themes/md-light-deeppurple/theme.css +373 -403
  186. package/resources/themes/md-light-indigo/theme.css +373 -403
  187. package/resources/themes/mdc-dark-deeppurple/theme.css +373 -403
  188. package/resources/themes/mdc-dark-indigo/theme.css +373 -403
  189. package/resources/themes/mdc-light-deeppurple/theme.css +373 -403
  190. package/resources/themes/mdc-light-indigo/theme.css +373 -403
  191. package/resources/themes/mira/theme.css +347 -395
  192. package/resources/themes/nano/theme.css +348 -396
  193. package/resources/themes/nova/theme.css +336 -384
  194. package/resources/themes/nova-accent/theme.css +336 -384
  195. package/resources/themes/nova-alt/theme.css +336 -384
  196. package/resources/themes/rhea/theme.css +336 -384
  197. package/resources/themes/saga-blue/theme.css +348 -396
  198. package/resources/themes/saga-green/theme.css +348 -396
  199. package/resources/themes/saga-orange/theme.css +348 -396
  200. package/resources/themes/saga-purple/theme.css +348 -396
  201. package/resources/themes/soho-dark/theme.css +362 -410
  202. package/resources/themes/soho-light/theme.css +370 -418
  203. package/resources/themes/tailwind-light/theme.css +361 -409
  204. package/resources/themes/vela-blue/theme.css +348 -396
  205. package/resources/themes/vela-green/theme.css +348 -396
  206. package/resources/themes/vela-orange/theme.css +348 -396
  207. package/resources/themes/vela-purple/theme.css +348 -396
  208. package/resources/themes/viva-dark/theme.css +342 -390
  209. package/resources/themes/viva-light/theme.css +348 -396
  210. package/scrollpanel/scrollpanel.d.ts +22 -4
  211. package/scrolltop/scrolltop.d.ts +6 -1
  212. package/slidemenu/slidemenu.d.ts +192 -88
  213. package/splitter/splitter.d.ts +18 -5
  214. package/steps/steps.d.ts +20 -3
  215. package/table/table.d.ts +3 -1
  216. package/tabmenu/tabmenu.d.ts +24 -1
  217. package/tabview/tabview.d.ts +26 -3
  218. package/tieredmenu/tieredmenu.d.ts +134 -50
  219. package/toolbar/toolbar.d.ts +6 -1
  220. package/tooltip/tooltip.d.ts +1 -1
  221. package/utils/objectutils.d.ts +4 -0
  222. package/utils/uniquecomponentid.d.ts +1 -1
@@ -1,298 +1,477 @@
1
+ import { trigger, transition, style, animate } from '@angular/animations';
1
2
  import * as i1 from '@angular/common';
2
- import { DOCUMENT, CommonModule } from '@angular/common';
3
+ import { DOCUMENT, isPlatformBrowser, CommonModule } from '@angular/common';
3
4
  import * as i0 from '@angular/core';
4
- import { EventEmitter, forwardRef, Component, ViewEncapsulation, Inject, Input, Output, ViewChild, ChangeDetectionStrategy, ContentChildren, NgModule } from '@angular/core';
5
+ import { EventEmitter, Component, ViewEncapsulation, Inject, Input, Output, ViewChild, signal, effect, PLATFORM_ID, ChangeDetectionStrategy, ContentChildren, NgModule } from '@angular/core';
5
6
  import * as i2 from '@angular/router';
6
7
  import { RouterModule } from '@angular/router';
7
8
  import * as i5 from 'primeng/api';
8
- import { PrimeTemplate, SharedModule, ContextMenuService } from 'primeng/api';
9
+ import { PrimeTemplate, SharedModule } from 'primeng/api';
9
10
  import { DomHandler } from 'primeng/dom';
10
11
  import { AngleRightIcon } from 'primeng/icons/angleright';
11
12
  import * as i3 from 'primeng/ripple';
12
13
  import { RippleModule } from 'primeng/ripple';
13
14
  import * as i4 from 'primeng/tooltip';
14
15
  import { TooltipModule } from 'primeng/tooltip';
15
- import { ZIndexUtils } from 'primeng/utils';
16
- import { Subject } from 'rxjs';
17
- import { takeUntil } from 'rxjs/operators';
16
+ import { ObjectUtils, UniqueComponentId, ZIndexUtils } from 'primeng/utils';
18
17
 
19
18
  class ContextMenuSub {
20
- item;
21
- root;
22
- parentItemKey;
23
- leafClick = new EventEmitter();
24
- sublistViewChild;
25
- menuitemViewChild;
19
+ document;
20
+ el;
21
+ renderer;
22
+ cd;
26
23
  contextMenu;
27
- activeItemKey;
28
- hideTimeout;
29
- activeItemKeyChangeSubscription;
30
- constructor(contextMenu) {
24
+ ref;
25
+ visible = false;
26
+ items;
27
+ root = false;
28
+ autoZIndex = true;
29
+ baseZIndex = 0;
30
+ popup;
31
+ menuId;
32
+ ariaLabel;
33
+ ariaLabelledBy;
34
+ level = 0;
35
+ focusedItemId;
36
+ activeItemPath;
37
+ tabindex = 0;
38
+ itemClick = new EventEmitter();
39
+ itemMouseEnter = new EventEmitter();
40
+ menuFocus = new EventEmitter();
41
+ menuBlur = new EventEmitter();
42
+ menuKeydown = new EventEmitter();
43
+ sublistViewChild;
44
+ constructor(document, el, renderer, cd, contextMenu, ref) {
45
+ this.document = document;
46
+ this.el = el;
47
+ this.renderer = renderer;
48
+ this.cd = cd;
31
49
  this.contextMenu = contextMenu;
50
+ this.ref = ref;
32
51
  }
33
- ngOnInit() {
34
- this.activeItemKeyChangeSubscription = this.contextMenu.contextMenuService.activeItemKeyChange$.pipe(takeUntil(this.contextMenu.ngDestroy$)).subscribe((activeItemKey) => {
35
- this.activeItemKey = activeItemKey;
36
- if (this.isActive(this.parentItemKey) && DomHandler.hasClass(this.sublistViewChild?.nativeElement, 'p-submenu-list-active')) {
37
- this.contextMenu.positionSubmenu(this.sublistViewChild?.nativeElement);
38
- }
39
- this.contextMenu.cd.markForCheck();
40
- });
52
+ getItemProp(processedItem, name, params = null) {
53
+ return processedItem && processedItem.item ? ObjectUtils.getItemValue(processedItem.item[name], params) : undefined;
41
54
  }
42
- onItemMouseEnter(event, item, key) {
43
- if (this.hideTimeout) {
44
- clearTimeout(this.hideTimeout);
45
- this.hideTimeout = null;
46
- }
47
- if (item.disabled) {
48
- this.activeItemKey = null;
49
- return;
50
- }
51
- if (item.items) {
52
- let childSublist = DomHandler.findSingle(event.currentTarget, '.p-submenu-list');
53
- DomHandler.addClass(childSublist, 'p-submenu-list-active');
54
- }
55
- this.contextMenu.contextMenuService.changeKey(key);
55
+ getItemId(processedItem) {
56
+ return `${this.menuId}_${processedItem.key}`;
56
57
  }
57
- onItemMouseLeave(event, item) {
58
- if (item.disabled) {
59
- return;
60
- }
61
- if (this.contextMenu.el.nativeElement.contains(event.target)) {
62
- if (item.items) {
63
- this.contextMenu.removeActiveFromSubLists(event.currentTarget);
64
- }
65
- if (!this.root) {
66
- this.contextMenu.contextMenuService.changeKey(this.parentItemKey);
67
- }
68
- }
58
+ getItemKey(processedItem) {
59
+ return this.getItemId(processedItem);
69
60
  }
70
- onItemClick(event, item, menuitem, key) {
71
- if (item.disabled) {
72
- event.preventDefault();
73
- return;
74
- }
75
- if (!item.url && !item.routerLink) {
76
- event.preventDefault();
77
- }
78
- if (item.command) {
79
- item.command({
80
- originalEvent: event,
81
- item: item
82
- });
83
- }
84
- if (item.items) {
85
- let childSublist = DomHandler.findSingle(menuitem, '.p-submenu-list');
86
- if (childSublist) {
87
- if (this.isActive(key) && DomHandler.hasClass(childSublist, 'p-submenu-list-active')) {
88
- this.contextMenu.removeActiveFromSubLists(menuitem);
89
- }
90
- else {
91
- DomHandler.addClass(childSublist, 'p-submenu-list-active');
92
- }
93
- this.contextMenu.contextMenuService.changeKey(key);
94
- }
95
- }
96
- if (!item.items) {
97
- this.onLeafClick();
98
- }
61
+ getItemClass(processedItem) {
62
+ return {
63
+ ...this.getItemProp(processedItem, 'class'),
64
+ 'p-menuitem': true,
65
+ 'p-highlight': this.isItemActive(processedItem),
66
+ 'p-menuitem-active': this.isItemActive(processedItem),
67
+ 'p-focus': this.isItemFocused(processedItem),
68
+ 'p-disabled': this.isItemDisabled(processedItem)
69
+ };
70
+ }
71
+ getItemLabel(processedItem) {
72
+ return this.getItemProp(processedItem, 'label');
73
+ }
74
+ getSeparatorItemClass(processedItem) {
75
+ return {
76
+ ...this.getItemProp(processedItem, 'class'),
77
+ 'p-menuitem-separator': true
78
+ };
79
+ }
80
+ getAriaSetSize() {
81
+ return this.items.filter((processedItem) => this.isItemVisible(processedItem) && !this.getItemProp(processedItem, 'separator')).length;
82
+ }
83
+ getAriaPosInset(index) {
84
+ return index - this.items.slice(0, index).filter((processedItem) => this.isItemVisible(processedItem) && this.getItemProp(processedItem, 'separator')).length + 1;
99
85
  }
100
- onLeafClick() {
101
- if (this.root) {
102
- this.contextMenu.hide();
86
+ isItemVisible(processedItem) {
87
+ return this.getItemProp(processedItem, 'visible') !== false;
88
+ }
89
+ isItemActive(processedItem) {
90
+ if (this.activeItemPath) {
91
+ return this.activeItemPath.some((path) => path.key === processedItem.key);
103
92
  }
104
- this.leafClick.emit();
105
93
  }
106
- getKey(index) {
107
- return this.root ? String(index) : this.parentItemKey + '_' + index;
94
+ isItemDisabled(processedItem) {
95
+ return this.getItemProp(processedItem, 'disabled');
96
+ }
97
+ isItemFocused(processedItem) {
98
+ return this.focusedItemId === this.getItemId(processedItem);
99
+ }
100
+ isItemGroup(processedItem) {
101
+ return ObjectUtils.isNotEmpty(processedItem.items);
102
+ }
103
+ onItemMouseEnter(param) {
104
+ const { event, processedItem } = param;
105
+ this.itemMouseEnter.emit({ originalEvent: event, processedItem });
108
106
  }
109
- isActive(key) {
110
- return this.activeItemKey && (this.activeItemKey.startsWith(key + '_') || this.activeItemKey === key);
107
+ onItemClick(event, processedItem) {
108
+ this.getItemProp(processedItem, 'command', { originalEvent: event, item: processedItem.item });
109
+ this.itemClick.emit({ originalEvent: event, processedItem, isFocus: true });
111
110
  }
112
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.2", ngImport: i0, type: ContextMenuSub, deps: [{ token: forwardRef(() => ContextMenu) }], target: i0.ɵɵFactoryTarget.Component });
113
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.0.2", type: ContextMenuSub, selector: "p-contextMenuSub", inputs: { item: "item", root: "root", parentItemKey: "parentItemKey" }, outputs: { leafClick: "leafClick" }, host: { classAttribute: "p-element" }, viewQueries: [{ propertyName: "sublistViewChild", first: true, predicate: ["sublist"], descendants: true }, { propertyName: "menuitemViewChild", first: true, predicate: ["menuitem"], descendants: true }], ngImport: i0, template: `
114
- <ul #sublist [ngClass]="{ 'p-submenu-list': !root }">
115
- <ng-template ngFor let-child let-index="index" [ngForOf]="root ? item : item?.items">
116
- <li *ngIf="child.separator" #menuitem class="p-menu-separator" [ngClass]="{ 'p-hidden': child.visible === false }" role="separator"></li>
111
+ onEnter(event, sublist) {
112
+ if (event.fromState === 'void' && event.toState) {
113
+ const sublist = event.element;
114
+ this.position(sublist);
115
+ }
116
+ }
117
+ position(sublist) {
118
+ const parentItem = sublist.parentElement.parentElement;
119
+ const containerOffset = DomHandler.getOffset(sublist.parentElement.parentElement);
120
+ const viewport = DomHandler.getViewport();
121
+ const sublistWidth = sublist.offsetParent ? sublist.offsetWidth : DomHandler.getHiddenElementOuterWidth(sublist);
122
+ const itemOuterWidth = DomHandler.getOuterWidth(parentItem.children[0]);
123
+ sublist.style.top = '0px';
124
+ if (parseInt(containerOffset.left, 10) + itemOuterWidth + sublistWidth > viewport.width - DomHandler.calculateScrollbarWidth()) {
125
+ sublist.style.left = -1 * sublistWidth + 'px';
126
+ }
127
+ else {
128
+ sublist.style.left = itemOuterWidth + 'px';
129
+ }
130
+ }
131
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.2", ngImport: i0, type: ContextMenuSub, deps: [{ token: DOCUMENT }, { token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i0.ChangeDetectorRef }, { token: ContextMenu }, { token: i0.ViewContainerRef }], target: i0.ɵɵFactoryTarget.Component });
132
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.0.2", type: ContextMenuSub, selector: "p-contextMenuSub", inputs: { visible: "visible", items: "items", root: "root", autoZIndex: "autoZIndex", baseZIndex: "baseZIndex", popup: "popup", menuId: "menuId", ariaLabel: "ariaLabel", ariaLabelledBy: "ariaLabelledBy", level: "level", focusedItemId: "focusedItemId", activeItemPath: "activeItemPath", tabindex: "tabindex" }, outputs: { itemClick: "itemClick", itemMouseEnter: "itemMouseEnter", menuFocus: "menuFocus", menuBlur: "menuBlur", menuKeydown: "menuKeydown" }, host: { classAttribute: "p-element" }, viewQueries: [{ propertyName: "sublistViewChild", first: true, predicate: ["sublist"], descendants: true }], ngImport: i0, template: `
133
+ <ul
134
+ *ngIf="root ? true : visible"
135
+ #sublist
136
+ role="menu"
137
+ [ngClass]="{ 'p-submenu-list': !root, 'p-contextmenu-root-list': root }"
138
+ [@overlayAnimation]="visible"
139
+ (@overlayAnimation.start)="onEnter($event, sublist)"
140
+ [id]="menuId + '_list'"
141
+ [tabindex]="tabindex"
142
+ [attr.aria-label]="ariaLabel"
143
+ [attr.aria-labelledBy]="ariaLabelledBy"
144
+ [attr.aria-activedescendant]="focusedItemId"
145
+ [attr.aria-orientation]="'vertical'"
146
+ [attr.data-pc-section]="'menu'"
147
+ (keydown)="menuKeydown.emit($event)"
148
+ (focus)="menuFocus.emit($event)"
149
+ (blur)="menuBlur.emit($event)"
150
+ >
151
+ <ng-template ngFor let-processedItem [ngForOf]="items" let-index="index">
152
+ <li
153
+ *ngIf="isItemVisible(processedItem) && getItemProp(processedItem, 'separator')"
154
+ [id]="getItemId(processedItem)"
155
+ [style]="getItemProp(processedItem, 'style')"
156
+ [ngClass]="getSeparatorItemClass(processedItem)"
157
+ role="separator"
158
+ [attr.data-pc-section]="'separator'"
159
+ ></li>
117
160
  <li
118
- *ngIf="!child.separator"
119
- #menuitem
120
- [ngClass]="{ 'p-menuitem': true, 'p-menuitem-active': isActive(getKey(index)), 'p-hidden': child.visible === false }"
121
- [ngStyle]="child.style"
122
- [class]="child.styleClass"
161
+ #listItem
162
+ *ngIf="isItemVisible(processedItem) && !getItemProp(processedItem, 'separator')"
163
+ role="menuitem"
164
+ [id]="getItemId(processedItem)"
165
+ [attr.data-pc-section]="'menuitem'"
166
+ [attr.data-p-highlight]="isItemActive(processedItem)"
167
+ [attr.data-p-focused]="isItemFocused(processedItem)"
168
+ [attr.data-p-disabled]="isItemDisabled(processedItem)"
169
+ [attr.aria-label]="getItemLabel(processedItem)"
170
+ [attr.aria-disabled]="isItemDisabled(processedItem) || undefined"
171
+ [attr.aria-haspopup]="isItemGroup(processedItem) && !getItemProp(processedItem, 'to') ? 'menu' : undefined"
172
+ [attr.aria-expanded]="isItemGroup(processedItem) ? isItemActive(processedItem) : undefined"
173
+ [attr.aria-level]="level + 1"
174
+ [attr.aria-setsize]="getAriaSetSize()"
175
+ [attr.aria-posinset]="getAriaPosInset(index)"
176
+ [ngStyle]="getItemProp(processedItem, 'style')"
177
+ [ngClass]="getItemClass(processedItem)"
178
+ [class]="getItemProp(processedItem, 'styleClass')"
123
179
  pTooltip
124
- [tooltipOptions]="child.tooltipOptions"
125
- (mouseenter)="onItemMouseEnter($event, child, getKey(index))"
126
- (mouseleave)="onItemMouseLeave($event, child)"
127
- role="none"
128
- [attr.data-ik]="getKey(index)"
180
+ [tooltipOptions]="getItemProp(processedItem, 'tooltipOptions')"
129
181
  >
130
- <a
131
- *ngIf="!child.routerLink"
132
- [attr.href]="child.url ? child.url : null"
133
- [target]="child.target"
134
- [attr.title]="child.title"
135
- [attr.id]="child.id"
136
- [attr.tabindex]="child.disabled ? null : '0'"
137
- (click)="onItemClick($event, child, menuitem, getKey(index))"
138
- [ngClass]="{ 'p-menuitem-link': true, 'p-disabled': child.disabled }"
139
- pRipple
140
- [attr.aria-haspopup]="item.items != null"
141
- [attr.aria-expanded]="isActive(getKey(index))"
142
- >
143
- <span class="p-menuitem-icon" *ngIf="child.icon" [ngClass]="child.icon" [ngStyle]="child.iconStyle"></span>
144
- <span class="p-menuitem-text" *ngIf="child.escape !== false; else htmlLabel">{{ child.label }}</span>
145
- <ng-template #htmlLabel><span class="p-menuitem-text" [innerHTML]="child.label"></span></ng-template>
146
- <span class="p-menuitem-badge" *ngIf="child.badge" [ngClass]="child.badgeStyleClass">{{ child.badge }}</span>
147
- <ng-container *ngIf="child.items">
148
- <AngleRightIcon *ngIf="!contextMenu.submenuIconTemplate" [styleClass]="'p-submenu-icon'" />
149
- <span *ngIf="contextMenu.submenuIconTemplate" class="p-submenu-icon">
150
- <ng-template *ngTemplateOutlet="contextMenu.submenuIconTemplate"></ng-template>
182
+ <div [attr.data-pc-section]="'content'" class="p-menuitem-content" (click)="onItemClick($event, processedItem)" (mouseenter)="onItemMouseEnter({$event, processedItem})">
183
+ <a
184
+ *ngIf="!getItemProp(processedItem, 'routerLink')"
185
+ [attr.href]="getItemProp(processedItem, 'url')"
186
+ [attr.aria-hidden]="true"
187
+ [attr.data-automationid]="getItemProp(processedItem, 'automationId')"
188
+ [attr.data-pc-section]="'action'"
189
+ [target]="getItemProp(processedItem, 'target')"
190
+ [ngClass]="{ 'p-menuitem-link': true, 'p-disabled': getItemProp(processedItem, 'disabled') }"
191
+ [attr.tabindex]="-1"
192
+ pRipple
193
+ >
194
+ <span
195
+ *ngIf="getItemProp(processedItem, 'icon')"
196
+ class="p-menuitem-icon"
197
+ [ngClass]="getItemProp(processedItem, 'icon')"
198
+ [ngStyle]="getItemProp(processedItem, 'iconStyle')"
199
+ [attr.data-pc-section]="'icon'"
200
+ [attr.aria-hidden]="true"
201
+ [attr.tabindex]="-1"
202
+ >
151
203
  </span>
152
- </ng-container>
153
- </a>
154
- <a
155
- *ngIf="child.routerLink"
156
- [routerLink]="child.routerLink"
157
- [queryParams]="child.queryParams"
158
- [routerLinkActive]="'p-menuitem-link-active'"
159
- role="menuitem"
160
- [routerLinkActiveOptions]="child.routerLinkActiveOptions || { exact: false }"
161
- [target]="child.target"
162
- [attr.title]="child.title"
163
- [attr.id]="child.id"
164
- [attr.tabindex]="child.disabled ? null : '0'"
165
- (click)="onItemClick($event, child, menuitem, getKey(index))"
166
- [ngClass]="{ 'p-menuitem-link': true, 'p-disabled': child.disabled }"
167
- pRipple
168
- [fragment]="child.fragment"
169
- [queryParamsHandling]="child.queryParamsHandling"
170
- [preserveFragment]="child.preserveFragment"
171
- [skipLocationChange]="child.skipLocationChange"
172
- [replaceUrl]="child.replaceUrl"
173
- [state]="child.state"
174
- >
175
- <span class="p-menuitem-icon" *ngIf="child.icon" [ngClass]="child.icon" [ngStyle]="child.iconStyle"></span>
176
- <span class="p-menuitem-text" *ngIf="child.escape !== false; else htmlRouteLabel">{{ child.label }}</span>
177
- <ng-template #htmlRouteLabel><span class="p-menuitem-text" [innerHTML]="child.label"></span></ng-template>
178
- <span class="p-menuitem-badge" *ngIf="child.badge" [ngClass]="child.badgeStyleClass">{{ child.badge }}</span>
179
- <ng-container *ngIf="child.items">
180
- <AngleRightIcon *ngIf="!contextMenu.submenuIconTemplate" [styleClass]="'p-submenu-icon'" />
181
- <span *ngIf="contextMenu.submenuIconTemplate" class="p-submenu-icon">
182
- <ng-template *ngTemplateOutlet="contextMenu.submenuIconTemplate"></ng-template>
204
+ <span *ngIf="getItemProp(processedItem, 'escape'); else htmlLabel" class="p-menuitem-text" [attr.data-pc-section]="'label'">
205
+ {{ getItemLabel(processedItem) }}
183
206
  </span>
184
- </ng-container>
185
- </a>
186
- <p-contextMenuSub [parentItemKey]="getKey(index)" [item]="child" *ngIf="child.items" (leafClick)="onLeafClick()"></p-contextMenuSub>
207
+ <ng-template #htmlLabel>
208
+ <span class="p-menuitem-text" [innerHTML]="getItemLabel(processedItem)" [attr.data-pc-section]="'label'"></span>
209
+ </ng-template>
210
+ <span class="p-menuitem-badge" *ngIf="getItemProp(processedItem, 'badge')" [ngClass]="getItemProp(processedItem, 'badgeStyleClass')">{{ child.badge }}</span>
211
+
212
+ <ng-container *ngIf="isItemGroup(processedItem)">
213
+ <AngleRightIcon *ngIf="!contextMenu.submenuIconTemplate" [styleClass]="'p-submenu-icon'" [attr.data-pc-section]="'submenuicon'" [attr.aria-hidden]="true" />
214
+ <ng-template *ngTemplateOutlet="contextMenu.submenuIconTemplate" [attr.data-pc-section]="'submenuicon'" [attr.aria-hidden]="true"></ng-template>
215
+ </ng-container>
216
+ </a>
217
+ <a
218
+ *ngIf="getItemProp(processedItem, 'routerLink')"
219
+ [routerLink]="getItemProp(processedItem, 'routerLink')"
220
+ [attr.data-automationid]="getItemProp(processedItem, 'automationId')"
221
+ [attr.tabindex]="-1"
222
+ [attr.aria-hidden]="true"
223
+ [attr.data-pc-section]="'action'"
224
+ [queryParams]="getItemProp(processedItem, 'queryParams')"
225
+ [routerLinkActive]="'p-menuitem-link-active'"
226
+ [routerLinkActiveOptions]="getItemProp(processedItem, 'routerLinkActiveOptions') || { exact: false }"
227
+ [target]="getItemProp(processedItem, 'target')"
228
+ [ngClass]="{ 'p-menuitem-link': true, 'p-disabled': getItemProp(processedItem, 'disabled') }"
229
+ [fragment]="getItemProp(processedItem, 'fragment')"
230
+ [queryParamsHandling]="getItemProp(processedItem, 'queryParamsHandling')"
231
+ [preserveFragment]="getItemProp(processedItem, 'preserveFragment')"
232
+ [skipLocationChange]="getItemProp(processedItem, 'skipLocationChange')"
233
+ [replaceUrl]="getItemProp(processedItem, 'replaceUrl')"
234
+ [state]="getItemProp(processedItem, 'state')"
235
+ pRipple
236
+ >
237
+ <span
238
+ *ngIf="getItemProp(processedItem, 'icon')"
239
+ class="p-menuitem-icon"
240
+ [ngClass]="getItemProp(processedItem, 'icon')"
241
+ [ngStyle]="getItemProp(processedItem, 'iconStyle')"
242
+ [attr.data-pc-section]="'icon'"
243
+ [attr.aria-hidden]="true"
244
+ [attr.tabindex]="-1"
245
+ >
246
+ </span>
247
+ <span *ngIf="getItemProp(processedItem, 'escape'); else htmlLabel" class="p-menuitem-text" [attr.data-pc-section]="'label'">
248
+ {{ getItemLabel(processedItem) }}
249
+ </span>
250
+ <ng-template #htmlLabel>
251
+ <span class="p-menuitem-text" [innerHTML]="getItemLabel(processedItem)" [attr.data-pc-section]="'label'"></span>
252
+ </ng-template>
253
+ <span class="p-menuitem-badge" *ngIf="getItemProp(processedItem, 'badge')" [ngClass]="getItemProp(processedItem, 'badgeStyleClass')">{{ child.badge }}</span>
254
+
255
+ <ng-container *ngIf="isItemGroup(processedItem)">
256
+ <AngleRightIcon *ngIf="!contextMenu.submenuIconTemplate" [styleClass]="'p-submenu-icon'" [attr.data-pc-section]="'submenuicon'" [attr.aria-hidden]="true" />
257
+ <ng-template *ngTemplateOutlet="contextMenu.submenuIconTemplate" [attr.data-pc-section]="'submenuicon'" [attr.aria-hidden]="true"></ng-template>
258
+ </ng-container>
259
+ </a>
260
+ </div>
261
+
262
+ <p-contextMenuSub
263
+ *ngIf="isItemVisible(processedItem) && isItemGroup(processedItem)"
264
+ [items]="processedItem.items"
265
+ [menuId]="menuId"
266
+ [visible]="isItemActive(processedItem) && isItemGroup(processedItem)"
267
+ [activeItemPath]="activeItemPath"
268
+ [focusedItemId]="focusedItemId"
269
+ [level]="level + 1"
270
+ (itemClick)="itemClick.emit($event)"
271
+ (itemMouseEnter)="onItemMouseEnter($event)"
272
+ ></p-contextMenuSub>
187
273
  </li>
188
274
  </ng-template>
189
275
  </ul>
190
- `, isInline: true, dependencies: [{ kind: "directive", type: i0.forwardRef(function () { return i1.NgClass; }), selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i0.forwardRef(function () { return i1.NgForOf; }), selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i0.forwardRef(function () { return i1.NgIf; }), selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i0.forwardRef(function () { return i1.NgTemplateOutlet; }), selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i0.forwardRef(function () { return i1.NgStyle; }), selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i0.forwardRef(function () { return i2.RouterLink; }), selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i0.forwardRef(function () { return i2.RouterLinkActive; }), selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "directive", type: i0.forwardRef(function () { return i3.Ripple; }), selector: "[pRipple]" }, { kind: "directive", type: i0.forwardRef(function () { return i4.Tooltip; }), selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions"] }, { kind: "component", type: i0.forwardRef(function () { return AngleRightIcon; }), selector: "AngleRightIcon" }, { kind: "component", type: i0.forwardRef(function () { return ContextMenuSub; }), selector: "p-contextMenuSub", inputs: ["item", "root", "parentItemKey"], outputs: ["leafClick"] }], encapsulation: i0.ViewEncapsulation.None });
276
+ `, isInline: true, dependencies: [{ kind: "directive", type: i0.forwardRef(function () { return i1.NgClass; }), selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i0.forwardRef(function () { return i1.NgForOf; }), selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i0.forwardRef(function () { return i1.NgIf; }), selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i0.forwardRef(function () { return i1.NgTemplateOutlet; }), selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i0.forwardRef(function () { return i1.NgStyle; }), selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i0.forwardRef(function () { return i2.RouterLink; }), selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i0.forwardRef(function () { return i2.RouterLinkActive; }), selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "directive", type: i0.forwardRef(function () { return i3.Ripple; }), selector: "[pRipple]" }, { kind: "directive", type: i0.forwardRef(function () { return i4.Tooltip; }), selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions"] }, { kind: "component", type: i0.forwardRef(function () { return AngleRightIcon; }), selector: "AngleRightIcon" }, { kind: "component", type: i0.forwardRef(function () { return ContextMenuSub; }), selector: "p-contextMenuSub", inputs: ["visible", "items", "root", "autoZIndex", "baseZIndex", "popup", "menuId", "ariaLabel", "ariaLabelledBy", "level", "focusedItemId", "activeItemPath", "tabindex"], outputs: ["itemClick", "itemMouseEnter", "menuFocus", "menuBlur", "menuKeydown"] }], animations: [trigger('overlayAnimation', [transition(':enter', [style({ opacity: 0 })]), transition(':leave', [style({ opacity: 0 })])])], encapsulation: i0.ViewEncapsulation.None });
191
277
  }
192
278
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.2", ngImport: i0, type: ContextMenuSub, decorators: [{
193
279
  type: Component,
194
280
  args: [{
195
281
  selector: 'p-contextMenuSub',
196
282
  template: `
197
- <ul #sublist [ngClass]="{ 'p-submenu-list': !root }">
198
- <ng-template ngFor let-child let-index="index" [ngForOf]="root ? item : item?.items">
199
- <li *ngIf="child.separator" #menuitem class="p-menu-separator" [ngClass]="{ 'p-hidden': child.visible === false }" role="separator"></li>
283
+ <ul
284
+ *ngIf="root ? true : visible"
285
+ #sublist
286
+ role="menu"
287
+ [ngClass]="{ 'p-submenu-list': !root, 'p-contextmenu-root-list': root }"
288
+ [@overlayAnimation]="visible"
289
+ (@overlayAnimation.start)="onEnter($event, sublist)"
290
+ [id]="menuId + '_list'"
291
+ [tabindex]="tabindex"
292
+ [attr.aria-label]="ariaLabel"
293
+ [attr.aria-labelledBy]="ariaLabelledBy"
294
+ [attr.aria-activedescendant]="focusedItemId"
295
+ [attr.aria-orientation]="'vertical'"
296
+ [attr.data-pc-section]="'menu'"
297
+ (keydown)="menuKeydown.emit($event)"
298
+ (focus)="menuFocus.emit($event)"
299
+ (blur)="menuBlur.emit($event)"
300
+ >
301
+ <ng-template ngFor let-processedItem [ngForOf]="items" let-index="index">
200
302
  <li
201
- *ngIf="!child.separator"
202
- #menuitem
203
- [ngClass]="{ 'p-menuitem': true, 'p-menuitem-active': isActive(getKey(index)), 'p-hidden': child.visible === false }"
204
- [ngStyle]="child.style"
205
- [class]="child.styleClass"
303
+ *ngIf="isItemVisible(processedItem) && getItemProp(processedItem, 'separator')"
304
+ [id]="getItemId(processedItem)"
305
+ [style]="getItemProp(processedItem, 'style')"
306
+ [ngClass]="getSeparatorItemClass(processedItem)"
307
+ role="separator"
308
+ [attr.data-pc-section]="'separator'"
309
+ ></li>
310
+ <li
311
+ #listItem
312
+ *ngIf="isItemVisible(processedItem) && !getItemProp(processedItem, 'separator')"
313
+ role="menuitem"
314
+ [id]="getItemId(processedItem)"
315
+ [attr.data-pc-section]="'menuitem'"
316
+ [attr.data-p-highlight]="isItemActive(processedItem)"
317
+ [attr.data-p-focused]="isItemFocused(processedItem)"
318
+ [attr.data-p-disabled]="isItemDisabled(processedItem)"
319
+ [attr.aria-label]="getItemLabel(processedItem)"
320
+ [attr.aria-disabled]="isItemDisabled(processedItem) || undefined"
321
+ [attr.aria-haspopup]="isItemGroup(processedItem) && !getItemProp(processedItem, 'to') ? 'menu' : undefined"
322
+ [attr.aria-expanded]="isItemGroup(processedItem) ? isItemActive(processedItem) : undefined"
323
+ [attr.aria-level]="level + 1"
324
+ [attr.aria-setsize]="getAriaSetSize()"
325
+ [attr.aria-posinset]="getAriaPosInset(index)"
326
+ [ngStyle]="getItemProp(processedItem, 'style')"
327
+ [ngClass]="getItemClass(processedItem)"
328
+ [class]="getItemProp(processedItem, 'styleClass')"
206
329
  pTooltip
207
- [tooltipOptions]="child.tooltipOptions"
208
- (mouseenter)="onItemMouseEnter($event, child, getKey(index))"
209
- (mouseleave)="onItemMouseLeave($event, child)"
210
- role="none"
211
- [attr.data-ik]="getKey(index)"
330
+ [tooltipOptions]="getItemProp(processedItem, 'tooltipOptions')"
212
331
  >
213
- <a
214
- *ngIf="!child.routerLink"
215
- [attr.href]="child.url ? child.url : null"
216
- [target]="child.target"
217
- [attr.title]="child.title"
218
- [attr.id]="child.id"
219
- [attr.tabindex]="child.disabled ? null : '0'"
220
- (click)="onItemClick($event, child, menuitem, getKey(index))"
221
- [ngClass]="{ 'p-menuitem-link': true, 'p-disabled': child.disabled }"
222
- pRipple
223
- [attr.aria-haspopup]="item.items != null"
224
- [attr.aria-expanded]="isActive(getKey(index))"
225
- >
226
- <span class="p-menuitem-icon" *ngIf="child.icon" [ngClass]="child.icon" [ngStyle]="child.iconStyle"></span>
227
- <span class="p-menuitem-text" *ngIf="child.escape !== false; else htmlLabel">{{ child.label }}</span>
228
- <ng-template #htmlLabel><span class="p-menuitem-text" [innerHTML]="child.label"></span></ng-template>
229
- <span class="p-menuitem-badge" *ngIf="child.badge" [ngClass]="child.badgeStyleClass">{{ child.badge }}</span>
230
- <ng-container *ngIf="child.items">
231
- <AngleRightIcon *ngIf="!contextMenu.submenuIconTemplate" [styleClass]="'p-submenu-icon'" />
232
- <span *ngIf="contextMenu.submenuIconTemplate" class="p-submenu-icon">
233
- <ng-template *ngTemplateOutlet="contextMenu.submenuIconTemplate"></ng-template>
332
+ <div [attr.data-pc-section]="'content'" class="p-menuitem-content" (click)="onItemClick($event, processedItem)" (mouseenter)="onItemMouseEnter({$event, processedItem})">
333
+ <a
334
+ *ngIf="!getItemProp(processedItem, 'routerLink')"
335
+ [attr.href]="getItemProp(processedItem, 'url')"
336
+ [attr.aria-hidden]="true"
337
+ [attr.data-automationid]="getItemProp(processedItem, 'automationId')"
338
+ [attr.data-pc-section]="'action'"
339
+ [target]="getItemProp(processedItem, 'target')"
340
+ [ngClass]="{ 'p-menuitem-link': true, 'p-disabled': getItemProp(processedItem, 'disabled') }"
341
+ [attr.tabindex]="-1"
342
+ pRipple
343
+ >
344
+ <span
345
+ *ngIf="getItemProp(processedItem, 'icon')"
346
+ class="p-menuitem-icon"
347
+ [ngClass]="getItemProp(processedItem, 'icon')"
348
+ [ngStyle]="getItemProp(processedItem, 'iconStyle')"
349
+ [attr.data-pc-section]="'icon'"
350
+ [attr.aria-hidden]="true"
351
+ [attr.tabindex]="-1"
352
+ >
353
+ </span>
354
+ <span *ngIf="getItemProp(processedItem, 'escape'); else htmlLabel" class="p-menuitem-text" [attr.data-pc-section]="'label'">
355
+ {{ getItemLabel(processedItem) }}
356
+ </span>
357
+ <ng-template #htmlLabel>
358
+ <span class="p-menuitem-text" [innerHTML]="getItemLabel(processedItem)" [attr.data-pc-section]="'label'"></span>
359
+ </ng-template>
360
+ <span class="p-menuitem-badge" *ngIf="getItemProp(processedItem, 'badge')" [ngClass]="getItemProp(processedItem, 'badgeStyleClass')">{{ child.badge }}</span>
361
+
362
+ <ng-container *ngIf="isItemGroup(processedItem)">
363
+ <AngleRightIcon *ngIf="!contextMenu.submenuIconTemplate" [styleClass]="'p-submenu-icon'" [attr.data-pc-section]="'submenuicon'" [attr.aria-hidden]="true" />
364
+ <ng-template *ngTemplateOutlet="contextMenu.submenuIconTemplate" [attr.data-pc-section]="'submenuicon'" [attr.aria-hidden]="true"></ng-template>
365
+ </ng-container>
366
+ </a>
367
+ <a
368
+ *ngIf="getItemProp(processedItem, 'routerLink')"
369
+ [routerLink]="getItemProp(processedItem, 'routerLink')"
370
+ [attr.data-automationid]="getItemProp(processedItem, 'automationId')"
371
+ [attr.tabindex]="-1"
372
+ [attr.aria-hidden]="true"
373
+ [attr.data-pc-section]="'action'"
374
+ [queryParams]="getItemProp(processedItem, 'queryParams')"
375
+ [routerLinkActive]="'p-menuitem-link-active'"
376
+ [routerLinkActiveOptions]="getItemProp(processedItem, 'routerLinkActiveOptions') || { exact: false }"
377
+ [target]="getItemProp(processedItem, 'target')"
378
+ [ngClass]="{ 'p-menuitem-link': true, 'p-disabled': getItemProp(processedItem, 'disabled') }"
379
+ [fragment]="getItemProp(processedItem, 'fragment')"
380
+ [queryParamsHandling]="getItemProp(processedItem, 'queryParamsHandling')"
381
+ [preserveFragment]="getItemProp(processedItem, 'preserveFragment')"
382
+ [skipLocationChange]="getItemProp(processedItem, 'skipLocationChange')"
383
+ [replaceUrl]="getItemProp(processedItem, 'replaceUrl')"
384
+ [state]="getItemProp(processedItem, 'state')"
385
+ pRipple
386
+ >
387
+ <span
388
+ *ngIf="getItemProp(processedItem, 'icon')"
389
+ class="p-menuitem-icon"
390
+ [ngClass]="getItemProp(processedItem, 'icon')"
391
+ [ngStyle]="getItemProp(processedItem, 'iconStyle')"
392
+ [attr.data-pc-section]="'icon'"
393
+ [attr.aria-hidden]="true"
394
+ [attr.tabindex]="-1"
395
+ >
234
396
  </span>
235
- </ng-container>
236
- </a>
237
- <a
238
- *ngIf="child.routerLink"
239
- [routerLink]="child.routerLink"
240
- [queryParams]="child.queryParams"
241
- [routerLinkActive]="'p-menuitem-link-active'"
242
- role="menuitem"
243
- [routerLinkActiveOptions]="child.routerLinkActiveOptions || { exact: false }"
244
- [target]="child.target"
245
- [attr.title]="child.title"
246
- [attr.id]="child.id"
247
- [attr.tabindex]="child.disabled ? null : '0'"
248
- (click)="onItemClick($event, child, menuitem, getKey(index))"
249
- [ngClass]="{ 'p-menuitem-link': true, 'p-disabled': child.disabled }"
250
- pRipple
251
- [fragment]="child.fragment"
252
- [queryParamsHandling]="child.queryParamsHandling"
253
- [preserveFragment]="child.preserveFragment"
254
- [skipLocationChange]="child.skipLocationChange"
255
- [replaceUrl]="child.replaceUrl"
256
- [state]="child.state"
257
- >
258
- <span class="p-menuitem-icon" *ngIf="child.icon" [ngClass]="child.icon" [ngStyle]="child.iconStyle"></span>
259
- <span class="p-menuitem-text" *ngIf="child.escape !== false; else htmlRouteLabel">{{ child.label }}</span>
260
- <ng-template #htmlRouteLabel><span class="p-menuitem-text" [innerHTML]="child.label"></span></ng-template>
261
- <span class="p-menuitem-badge" *ngIf="child.badge" [ngClass]="child.badgeStyleClass">{{ child.badge }}</span>
262
- <ng-container *ngIf="child.items">
263
- <AngleRightIcon *ngIf="!contextMenu.submenuIconTemplate" [styleClass]="'p-submenu-icon'" />
264
- <span *ngIf="contextMenu.submenuIconTemplate" class="p-submenu-icon">
265
- <ng-template *ngTemplateOutlet="contextMenu.submenuIconTemplate"></ng-template>
397
+ <span *ngIf="getItemProp(processedItem, 'escape'); else htmlLabel" class="p-menuitem-text" [attr.data-pc-section]="'label'">
398
+ {{ getItemLabel(processedItem) }}
266
399
  </span>
267
- </ng-container>
268
- </a>
269
- <p-contextMenuSub [parentItemKey]="getKey(index)" [item]="child" *ngIf="child.items" (leafClick)="onLeafClick()"></p-contextMenuSub>
400
+ <ng-template #htmlLabel>
401
+ <span class="p-menuitem-text" [innerHTML]="getItemLabel(processedItem)" [attr.data-pc-section]="'label'"></span>
402
+ </ng-template>
403
+ <span class="p-menuitem-badge" *ngIf="getItemProp(processedItem, 'badge')" [ngClass]="getItemProp(processedItem, 'badgeStyleClass')">{{ child.badge }}</span>
404
+
405
+ <ng-container *ngIf="isItemGroup(processedItem)">
406
+ <AngleRightIcon *ngIf="!contextMenu.submenuIconTemplate" [styleClass]="'p-submenu-icon'" [attr.data-pc-section]="'submenuicon'" [attr.aria-hidden]="true" />
407
+ <ng-template *ngTemplateOutlet="contextMenu.submenuIconTemplate" [attr.data-pc-section]="'submenuicon'" [attr.aria-hidden]="true"></ng-template>
408
+ </ng-container>
409
+ </a>
410
+ </div>
411
+
412
+ <p-contextMenuSub
413
+ *ngIf="isItemVisible(processedItem) && isItemGroup(processedItem)"
414
+ [items]="processedItem.items"
415
+ [menuId]="menuId"
416
+ [visible]="isItemActive(processedItem) && isItemGroup(processedItem)"
417
+ [activeItemPath]="activeItemPath"
418
+ [focusedItemId]="focusedItemId"
419
+ [level]="level + 1"
420
+ (itemClick)="itemClick.emit($event)"
421
+ (itemMouseEnter)="onItemMouseEnter($event)"
422
+ ></p-contextMenuSub>
270
423
  </li>
271
424
  </ng-template>
272
425
  </ul>
273
426
  `,
427
+ animations: [trigger('overlayAnimation', [transition(':enter', [style({ opacity: 0 })]), transition(':leave', [style({ opacity: 0 })])])],
274
428
  encapsulation: ViewEncapsulation.None,
275
429
  host: {
276
430
  class: 'p-element'
277
431
  }
278
432
  }]
279
- }], ctorParameters: function () { return [{ type: ContextMenu, decorators: [{
433
+ }], ctorParameters: function () { return [{ type: Document, decorators: [{
280
434
  type: Inject,
281
- args: [forwardRef(() => ContextMenu)]
282
- }] }]; }, propDecorators: { item: [{
435
+ args: [DOCUMENT]
436
+ }] }, { type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i0.ChangeDetectorRef }, { type: ContextMenu }, { type: i0.ViewContainerRef }]; }, propDecorators: { visible: [{
437
+ type: Input
438
+ }], items: [{
283
439
  type: Input
284
440
  }], root: [{
285
441
  type: Input
286
- }], parentItemKey: [{
442
+ }], autoZIndex: [{
443
+ type: Input
444
+ }], baseZIndex: [{
287
445
  type: Input
288
- }], leafClick: [{
446
+ }], popup: [{
447
+ type: Input
448
+ }], menuId: [{
449
+ type: Input
450
+ }], ariaLabel: [{
451
+ type: Input
452
+ }], ariaLabelledBy: [{
453
+ type: Input
454
+ }], level: [{
455
+ type: Input
456
+ }], focusedItemId: [{
457
+ type: Input
458
+ }], activeItemPath: [{
459
+ type: Input
460
+ }], tabindex: [{
461
+ type: Input
462
+ }], itemClick: [{
463
+ type: Output
464
+ }], itemMouseEnter: [{
465
+ type: Output
466
+ }], menuFocus: [{
467
+ type: Output
468
+ }], menuBlur: [{
469
+ type: Output
470
+ }], menuKeydown: [{
289
471
  type: Output
290
472
  }], sublistViewChild: [{
291
473
  type: ViewChild,
292
474
  args: ['sublist']
293
- }], menuitemViewChild: [{
294
- type: ViewChild,
295
- args: ['menuitem']
296
475
  }] } });
297
476
  /**
298
477
  * ContextMenu displays an overlay menu on right click of its target. Note that components like Table has special integration with ContextMenu.
@@ -300,39 +479,44 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.2", ngImpor
300
479
  */
301
480
  class ContextMenu {
302
481
  document;
482
+ platformId;
303
483
  el;
304
484
  renderer;
305
485
  cd;
306
- zone;
307
- contextMenuService;
308
486
  config;
487
+ overlayService;
309
488
  /**
310
489
  * An array of menuitems.
311
490
  * @group Props
312
491
  */
313
492
  model;
314
493
  /**
315
- * Attaches the menu to document instead of a particular item.
494
+ * Event for which the menu must be displayed.
316
495
  * @group Props
317
496
  */
318
- global;
497
+ triggerEvent = 'contextmenu';
319
498
  /**
320
499
  * Local template variable name of the element to attach the context menu.
321
500
  * @group Props
322
501
  */
323
502
  target;
324
503
  /**
325
- * Inline style of the element.
504
+ * Attaches the menu to document instead of a particular item.
505
+ * @group Props
506
+ */
507
+ global;
508
+ /**
509
+ * Inline style of the component.
326
510
  * @group Props
327
511
  */
328
512
  style;
329
513
  /**
330
- * Class of the element.
514
+ * Style class of the component.
331
515
  * @group Props
332
516
  */
333
517
  styleClass;
334
518
  /**
335
- * Target element to attach the overlay, valid values are "body" or a local ng-template variable of another element (note: use binding with brackets for template variables, e.g. [appendTo]="mydiv" for a div element having #mydiv as variable name).
519
+ * Target element to attach the overlay, valid values are "body" or a local ng-template variable of another element.
336
520
  * @group Props
337
521
  */
338
522
  appendTo;
@@ -347,328 +531,536 @@ class ContextMenu {
347
531
  */
348
532
  baseZIndex = 0;
349
533
  /**
350
- * Event for which the menu must be displayed.
534
+ * Current id state as a string.
351
535
  * @group Props
352
536
  */
353
- triggerEvent = 'contextmenu';
537
+ id;
354
538
  /**
355
- * Displays the popup menu.
539
+ * Defines a string value that labels an interactive element.
540
+ * @group Props
541
+ */
542
+ ariaLabel;
543
+ /**
544
+ * Identifier of the underlying input element.
545
+ * @group Props
546
+ */
547
+ ariaLabelledBy;
548
+ /**
549
+ * Callback to invoke when overlay menu is shown.
356
550
  * @group Emits
357
551
  */
358
552
  onShow = new EventEmitter();
359
553
  /**
360
- * Hides the popup menu.
554
+ * Callback to invoke when overlay menu is hidden.
361
555
  * @group Emits
362
556
  */
363
557
  onHide = new EventEmitter();
558
+ templates;
559
+ rootmenu;
364
560
  containerViewChild;
561
+ submenuIconTemplate;
562
+ container;
563
+ outsideClickListener;
564
+ resizeListener;
565
+ triggerEventListener;
365
566
  documentClickListener;
366
567
  documentTriggerListener;
367
- documentKeydownListener;
368
- windowResizeListener;
369
- triggerEventListener;
370
- ngDestroy$ = new Subject();
371
- preventDocumentDefault = false;
568
+ pageX;
569
+ pageY;
570
+ visible = signal(false);
571
+ relativeAlign;
372
572
  window;
373
- templates;
374
- submenuIconTemplate;
375
- constructor(document, el, renderer, cd, zone, contextMenuService, config) {
573
+ focused = false;
574
+ activeItemPath = signal([]);
575
+ focusedItemInfo = signal({ index: -1, level: 0, parentKey: '' });
576
+ submenuVisible = signal(false);
577
+ searchValue = '';
578
+ searchTimeout;
579
+ _processedItems;
580
+ get visibleItems() {
581
+ const processedItem = this.activeItemPath().find((p) => p.key === this.focusedItemInfo().parentKey);
582
+ return processedItem ? processedItem.items : this.processedItems;
583
+ }
584
+ get processedItems() {
585
+ if (!this._processedItems || !this._processedItems.length) {
586
+ this._processedItems = this.createProcessedItems(this.model || []);
587
+ }
588
+ return this._processedItems;
589
+ }
590
+ get focusedItemId() {
591
+ const focusedItemInfo = this.focusedItemInfo();
592
+ return focusedItemInfo.index !== -1 ? `${this.id}${ObjectUtils.isNotEmpty(focusedItemInfo.parentKey) ? '_' + focusedItemInfo.parentKey : ''}_${focusedItemInfo.index}` : null;
593
+ }
594
+ constructor(document, platformId, el, renderer, cd, config, overlayService) {
376
595
  this.document = document;
596
+ this.platformId = platformId;
377
597
  this.el = el;
378
598
  this.renderer = renderer;
379
599
  this.cd = cd;
380
- this.zone = zone;
381
- this.contextMenuService = contextMenuService;
382
600
  this.config = config;
601
+ this.overlayService = overlayService;
383
602
  this.window = this.document.defaultView;
603
+ effect(() => {
604
+ const path = this.activeItemPath();
605
+ if (ObjectUtils.isNotEmpty(path)) {
606
+ this.bindGlobalListeners();
607
+ }
608
+ else if (!this.visible()) {
609
+ this.unbindGlobalListeners();
610
+ }
611
+ });
384
612
  }
385
- ngAfterViewInit() {
386
- if (this.global) {
387
- const documentTarget = this.el ? this.el.nativeElement.ownerDocument : 'document';
388
- this.triggerEventListener = this.renderer.listen(documentTarget, this.triggerEvent, (event) => {
389
- if (this.containerViewChild && this.containerViewChild.nativeElement.style.display !== 'none') {
390
- this.hide();
613
+ ngOnInit() {
614
+ this.id = this.id || UniqueComponentId();
615
+ this.bindTriggerEventListener();
616
+ }
617
+ bindTriggerEventListener() {
618
+ if (isPlatformBrowser(this.platformId)) {
619
+ if (!this.triggerEventListener) {
620
+ if (this.global) {
621
+ this.triggerEventListener = this.renderer.listen(this.document, this.triggerEvent, (event) => {
622
+ this.show(event);
623
+ });
391
624
  }
392
- this.show(event);
393
- event.preventDefault();
394
- });
625
+ else if (this.target) {
626
+ this.triggerEventListener = this.renderer.listen(this.target, this.triggerEvent, (event) => {
627
+ this.show(event);
628
+ });
629
+ }
630
+ }
395
631
  }
396
- else if (this.target) {
397
- this.triggerEventListener = this.renderer.listen(this.target, this.triggerEvent, (event) => {
398
- if (this.containerViewChild && this.containerViewChild.nativeElement.style.display !== 'none') {
632
+ }
633
+ bindGlobalListeners() {
634
+ if (isPlatformBrowser(this.platformId)) {
635
+ if (!this.documentClickListener) {
636
+ const documentTarget = this.el ? this.el.nativeElement.ownerDocument : 'document';
637
+ this.documentClickListener = this.renderer.listen(documentTarget, 'click', (event) => {
638
+ if (this.containerViewChild.nativeElement.offsetParent && this.isOutsideClicked(event) && !event.ctrlKey && event.button !== 2 && this.triggerEvent !== 'click') {
639
+ this.hide();
640
+ }
641
+ });
642
+ this.documentTriggerListener = this.renderer.listen(documentTarget, this.triggerEvent, (event) => {
643
+ if (this.containerViewChild.nativeElement.offsetParent && this.isOutsideClicked(event)) {
644
+ this.hide();
645
+ }
646
+ });
647
+ }
648
+ if (!this.resizeListener) {
649
+ this.resizeListener = this.renderer.listen(this.document.defaultView, 'resize', (event) => {
399
650
  this.hide();
400
- }
401
- this.show(event);
402
- event.preventDefault();
651
+ });
652
+ }
653
+ }
654
+ }
655
+ ngAfterContentInit() {
656
+ this.templates?.forEach((item) => {
657
+ switch (item.getType()) {
658
+ case 'submenuicon':
659
+ this.submenuIconTemplate = item.template;
660
+ break;
661
+ }
662
+ });
663
+ }
664
+ createProcessedItems(items, level = 0, parent = {}, parentKey = '') {
665
+ const processedItems = [];
666
+ items &&
667
+ items.forEach((item, index) => {
668
+ const key = (parentKey !== '' ? parentKey + '_' : '') + index;
669
+ const newItem = {
670
+ item,
671
+ index,
672
+ level,
673
+ key,
674
+ parent,
675
+ parentKey
676
+ };
677
+ newItem['items'] = this.createProcessedItems(item.items, level + 1, newItem, key);
678
+ processedItems.push(newItem);
403
679
  });
680
+ return processedItems;
681
+ }
682
+ getItemProp(item, name) {
683
+ return item ? ObjectUtils.getItemValue(item[name]) : undefined;
684
+ }
685
+ getProccessedItemLabel(processedItem) {
686
+ return processedItem ? this.getItemLabel(processedItem.item) : undefined;
687
+ }
688
+ getItemLabel(item) {
689
+ return this.getItemProp(item, 'label');
690
+ }
691
+ isProcessedItemGroup(processedItem) {
692
+ return processedItem && ObjectUtils.isNotEmpty(processedItem.items);
693
+ }
694
+ isSelected(processedItem) {
695
+ return this.activeItemPath().some((p) => p.key === processedItem.key);
696
+ }
697
+ isValidSelectedItem(processedItem) {
698
+ return this.isValidItem(processedItem) && this.isSelected(processedItem);
699
+ }
700
+ isValidItem(processedItem) {
701
+ return !!processedItem && !this.isItemDisabled(processedItem.item) && !this.isItemSeparator(processedItem.item);
702
+ }
703
+ isItemDisabled(item) {
704
+ return this.getItemProp(item, 'disabled');
705
+ }
706
+ isItemSeparator(item) {
707
+ return this.getItemProp(item, 'separator');
708
+ }
709
+ isItemMatched(processedItem) {
710
+ return this.isValidItem(processedItem) && this.getProccessedItemLabel(processedItem).toLocaleLowerCase().startsWith(this.searchValue.toLocaleLowerCase());
711
+ }
712
+ isProccessedItemGroup(processedItem) {
713
+ return processedItem && ObjectUtils.isNotEmpty(processedItem.items);
714
+ }
715
+ onItemClick(event) {
716
+ const { processedItem } = event;
717
+ const grouped = this.isProcessedItemGroup(processedItem);
718
+ const selected = this.isSelected(processedItem);
719
+ if (selected) {
720
+ const { index, key, level, parentKey } = processedItem;
721
+ this.activeItemPath.set(this.activeItemPath().filter((p) => key !== p.key && key.startsWith(p.key)));
722
+ this.focusedItemInfo.set({ index, level, parentKey });
723
+ DomHandler.focus(this.rootmenu.sublistViewChild.nativeElement);
404
724
  }
405
- if (this.appendTo) {
406
- if (this.appendTo === 'body')
407
- this.renderer.appendChild(this.document.body, this.containerViewChild?.nativeElement);
408
- else
409
- DomHandler.appendChild(this.containerViewChild?.nativeElement, this.appendTo);
725
+ else {
726
+ grouped ? this.onItemChange(event) : this.hide();
410
727
  }
411
728
  }
412
- show(event) {
413
- this.clearActiveItem();
414
- this.position(event);
415
- this.moveOnTop();
416
- this.containerViewChild.nativeElement.style.display = 'block';
417
- this.preventDocumentDefault = true;
418
- DomHandler.fadeIn(this.containerViewChild?.nativeElement, 250);
419
- this.bindGlobalListeners();
420
- if (event) {
421
- event.preventDefault();
422
- }
423
- this.onShow.emit();
729
+ onItemMouseEnter(event) {
730
+ this.onItemChange(event);
424
731
  }
425
- hide() {
426
- this.containerViewChild.nativeElement.style.display = 'none';
427
- if (this.autoZIndex) {
428
- ZIndexUtils.clear(this.containerViewChild?.nativeElement);
732
+ onKeyDown(event) {
733
+ const metaKey = event.metaKey || event.ctrlKey;
734
+ switch (event.code) {
735
+ case 'ArrowDown':
736
+ this.onArrowDownKey(event);
737
+ break;
738
+ case 'ArrowUp':
739
+ this.onArrowUpKey(event);
740
+ break;
741
+ case 'ArrowLeft':
742
+ this.onArrowLeftKey(event);
743
+ break;
744
+ case 'ArrowRight':
745
+ this.onArrowRightKey(event);
746
+ break;
747
+ case 'Home':
748
+ this.onHomeKey(event);
749
+ break;
750
+ case 'End':
751
+ this.onEndKey(event);
752
+ break;
753
+ case 'Space':
754
+ this.onSpaceKey(event);
755
+ break;
756
+ case 'Enter':
757
+ this.onEnterKey(event);
758
+ break;
759
+ case 'Escape':
760
+ this.onEscapeKey(event);
761
+ break;
762
+ case 'Tab':
763
+ this.onTabKey(event);
764
+ break;
765
+ case 'PageDown':
766
+ case 'PageUp':
767
+ case 'Backspace':
768
+ case 'ShiftLeft':
769
+ case 'ShiftRight':
770
+ //NOOP
771
+ break;
772
+ default:
773
+ if (!metaKey && ObjectUtils.isPrintableCharacter(event.key)) {
774
+ this.searchItems(event, event.key);
775
+ }
776
+ break;
429
777
  }
430
- this.clearActiveItem();
431
- this.unbindGlobalListeners();
432
- this.onHide.emit();
433
778
  }
434
- moveOnTop() {
435
- if (this.autoZIndex && this.containerViewChild && this.containerViewChild.nativeElement.style.display !== 'block') {
436
- ZIndexUtils.set('menu', this.containerViewChild.nativeElement, this.baseZIndex + this.config.zIndex.menu);
437
- }
779
+ onArrowDownKey(event) {
780
+ const itemIndex = this.focusedItemInfo().index !== -1 ? this.findNextItemIndex(this.focusedItemInfo().index) : this.findFirstFocusedItemIndex();
781
+ this.changeFocusedItemIndex(event, itemIndex);
782
+ event.preventDefault();
438
783
  }
439
- toggle(event) {
440
- if (this.containerViewChild.nativeElement.offsetParent)
441
- this.hide();
442
- else
443
- this.show(event);
444
- }
445
- position(event) {
446
- if (event) {
447
- let left = event.pageX + 1;
448
- let top = event.pageY + 1;
449
- let width = this.containerViewChild?.nativeElement.offsetParent ? this.containerViewChild.nativeElement.offsetWidth : DomHandler.getHiddenElementOuterWidth(this.containerViewChild?.nativeElement);
450
- let height = this.containerViewChild?.nativeElement.offsetParent ? this.containerViewChild.nativeElement.offsetHeight : DomHandler.getHiddenElementOuterHeight(this.containerViewChild?.nativeElement);
451
- let viewport = DomHandler.getViewport();
452
- //flip
453
- if (left + width - this.document.scrollingElement.scrollLeft > viewport.width) {
454
- left -= width;
455
- }
456
- //flip
457
- if (top + height - this.document.scrollingElement.scrollTop > viewport.height) {
458
- top -= height;
459
- }
460
- //fit
461
- if (left < this.document.scrollingElement.scrollLeft) {
462
- left = this.document.scrollingElement.scrollLeft;
463
- }
464
- //fit
465
- if (top < this.document.scrollingElement.scrollTop) {
466
- top = this.document.scrollingElement.scrollTop;
467
- }
468
- this.containerViewChild.nativeElement.style.left = left + 'px';
469
- this.containerViewChild.nativeElement.style.top = top + 'px';
784
+ onArrowRightKey(event) {
785
+ const processedItem = this.visibleItems[this.focusedItemInfo().index];
786
+ const grouped = this.isProccessedItemGroup(processedItem);
787
+ if (grouped) {
788
+ this.onItemChange({ originalEvent: event, processedItem });
789
+ this.focusedItemInfo.set({ index: -1, parentKey: processedItem.key });
790
+ this.searchValue = '';
791
+ this.onArrowDownKey(event);
470
792
  }
793
+ event.preventDefault();
471
794
  }
472
- positionSubmenu(sublist) {
473
- let parentMenuItem = sublist.parentElement?.parentElement;
474
- let viewport = DomHandler.getViewport();
475
- let sublistWidth = sublist.offsetParent ? sublist.offsetWidth : DomHandler.getHiddenElementOuterWidth(sublist);
476
- let sublistHeight = sublist.offsetHeight ? sublist.offsetHeight : DomHandler.getHiddenElementOuterHeight(sublist);
477
- let itemOuterWidth = DomHandler.getOuterWidth(parentMenuItem?.children[0]);
478
- let itemOuterHeight = DomHandler.getOuterHeight(parentMenuItem?.children[0]);
479
- let containerOffset = DomHandler.getOffset(parentMenuItem?.parentElement);
480
- sublist.style.zIndex = (++DomHandler.zindex).toString();
481
- if (parseInt(containerOffset.top) + itemOuterHeight + sublistHeight > viewport.height - DomHandler.calculateScrollbarHeight()) {
482
- sublist.style.removeProperty('top');
483
- sublist.style.bottom = '0px';
795
+ onArrowUpKey(event) {
796
+ if (event.altKey) {
797
+ if (this.focusedItemInfo().index !== -1) {
798
+ const processedItem = this.visibleItems[this.focusedItemInfo().index];
799
+ const grouped = this.isProccessedItemGroup(processedItem);
800
+ !grouped && this.onItemChange({ originalEvent: event, processedItem });
801
+ }
802
+ this.hide();
803
+ event.preventDefault();
484
804
  }
485
805
  else {
486
- sublist.style.removeProperty('bottom');
487
- sublist.style.top = '0px';
488
- }
489
- if (parseInt(containerOffset.left) + itemOuterWidth + sublistWidth > viewport.width - DomHandler.calculateScrollbarWidth()) {
490
- sublist.style.left = -sublistWidth + 'px';
806
+ const itemIndex = this.focusedItemInfo().index !== -1 ? this.findPrevItemIndex(this.focusedItemInfo().index) : this.findLastFocusedItemIndex();
807
+ this.changeFocusedItemIndex(event, itemIndex);
808
+ event.preventDefault();
491
809
  }
492
- else {
493
- sublist.style.left = itemOuterWidth + 'px';
810
+ }
811
+ onArrowLeftKey(event) {
812
+ const processedItem = this.visibleItems[this.focusedItemInfo().index];
813
+ const parentItem = this.activeItemPath().find((p) => p.key === processedItem.parentKey);
814
+ const root = ObjectUtils.isEmpty(processedItem.parent);
815
+ if (!root) {
816
+ this.focusedItemInfo.set({ index: -1, parentKey: parentItem ? parentItem.parentKey : '' });
817
+ this.searchValue = '';
818
+ this.onArrowDownKey(event);
494
819
  }
820
+ const activeItemPath = this.activeItemPath().filter((p) => p.parentKey !== this.focusedItemInfo().parentKey);
821
+ this.activeItemPath.set(activeItemPath);
822
+ event.preventDefault();
495
823
  }
496
- isItemMatched(menuitem) {
497
- return DomHandler.hasClass(menuitem, 'p-menuitem') && !DomHandler.hasClass(menuitem.children[0], 'p-disabled');
824
+ onHomeKey(event) {
825
+ this.changeFocusedItemIndex(event, this.findFirstItemIndex());
826
+ event.preventDefault();
498
827
  }
499
- findNextItem(menuitem, isRepeated) {
500
- let nextMenuitem = menuitem.nextElementSibling;
501
- if (nextMenuitem) {
502
- return this.isItemMatched(nextMenuitem) ? nextMenuitem : this.findNextItem(nextMenuitem, isRepeated);
503
- }
504
- else {
505
- let firstItem = menuitem.parentElement?.children[0];
506
- return this.isItemMatched(firstItem) ? firstItem : !isRepeated ? this.findNextItem(firstItem, true) : null;
828
+ onEndKey(event) {
829
+ this.changeFocusedItemIndex(event, this.findLastItemIndex());
830
+ event.preventDefault();
831
+ }
832
+ onSpaceKey(event) {
833
+ this.onEnterKey(event);
834
+ }
835
+ onEscapeKey(event) {
836
+ this.hide();
837
+ this.focusedItemInfo.mutate((value) => {
838
+ value.index = this.findFirstFocusedItemIndex();
839
+ });
840
+ event.preventDefault();
841
+ }
842
+ onTabKey(event) {
843
+ if (this.focusedItemInfo().index !== -1) {
844
+ const processedItem = this.visibleItems[this.focusedItemInfo().index];
845
+ const grouped = this.isProccessedItemGroup(processedItem);
846
+ !grouped && this.onItemChange({ originalEvent: event, processedItem });
507
847
  }
848
+ this.hide();
508
849
  }
509
- findPrevItem(menuitem, isRepeated) {
510
- let prevMenuitem = menuitem.previousElementSibling;
511
- if (prevMenuitem) {
512
- return this.isItemMatched(prevMenuitem) ? prevMenuitem : this.findPrevItem(prevMenuitem, isRepeated);
850
+ onEnterKey(event) {
851
+ if (this.focusedItemInfo().index !== -1) {
852
+ const element = DomHandler.findSingle(this.rootmenu.el.nativeElement, `li[id="${`${this.focusedItemId}`}"]`);
853
+ const anchorElement = element && DomHandler.findSingle(element, 'a[data-pc-section="action"]');
854
+ anchorElement ? anchorElement.click() : element && element.click();
855
+ const processedItem = this.visibleItems[this.focusedItemInfo().index];
856
+ const grouped = this.isProccessedItemGroup(processedItem);
857
+ if (!grouped) {
858
+ this.focusedItemInfo.mutate((value) => {
859
+ value.index = this.findFirstFocusedItemIndex();
860
+ });
861
+ }
513
862
  }
514
- else {
515
- let lastItem = menuitem.parentElement?.children[menuitem.parentElement.children.length - 1];
516
- return this.isItemMatched(lastItem) ? lastItem : !isRepeated ? this.findPrevItem(lastItem, true) : null;
863
+ event.preventDefault();
864
+ }
865
+ onItemChange(event) {
866
+ const { processedItem, isFocus } = event;
867
+ if (ObjectUtils.isEmpty(processedItem))
868
+ return;
869
+ const { index, key, level, parentKey, items } = processedItem;
870
+ const grouped = ObjectUtils.isNotEmpty(items);
871
+ const activeItemPath = this.activeItemPath().filter((p) => p.parentKey !== parentKey && p.parentKey !== key);
872
+ if (grouped) {
873
+ activeItemPath.push(processedItem);
874
+ this.submenuVisible.set(true);
517
875
  }
876
+ this.focusedItemInfo.set({ index, level, parentKey });
877
+ this.activeItemPath.set(activeItemPath);
878
+ isFocus && DomHandler.focus(this.rootmenu.sublistViewChild.nativeElement);
518
879
  }
519
- getActiveItem() {
520
- let activeItemKey = this.contextMenuService.activeItemKey;
521
- return activeItemKey == null ? null : DomHandler.findSingle(this.containerViewChild?.nativeElement, '.p-menuitem[data-ik="' + activeItemKey + '"]');
880
+ onMenuFocus(event) {
881
+ this.focused = true;
882
+ const focusedItemInfo = this.focusedItemInfo().index !== -1 ? this.focusedItemInfo() : { index: -1, level: 0, parentKey: '' };
883
+ this.focusedItemInfo.set(focusedItemInfo);
522
884
  }
523
- clearActiveItem() {
524
- if (this.contextMenuService.activeItemKey) {
525
- this.removeActiveFromSubLists(this.containerViewChild?.nativeElement);
526
- this.contextMenuService.reset();
885
+ onMenuBlur(event) {
886
+ this.focused = false;
887
+ this.focusedItemInfo.set({ index: -1, level: 0, parentKey: '' });
888
+ this.searchValue = '';
889
+ }
890
+ onOverlayAnimationStart(event) {
891
+ switch (event.toState) {
892
+ case 'visible':
893
+ this.container = event.element;
894
+ this.position();
895
+ this.moveOnTop();
896
+ this.appendOverlay();
897
+ this.bindGlobalListeners();
898
+ this.onShow.emit();
899
+ DomHandler.focus(this.rootmenu.sublistViewChild.nativeElement);
900
+ break;
527
901
  }
528
902
  }
529
- removeActiveFromSubLists(el) {
530
- let sublists = DomHandler.find(el, '.p-submenu-list-active');
531
- for (let sublist of sublists) {
532
- DomHandler.removeClass(sublist, 'p-submenu-list-active');
903
+ onOverlayAnimationEnd(event) {
904
+ switch (event.toState) {
905
+ case 'void':
906
+ this.onOverlayHide();
907
+ break;
533
908
  }
534
909
  }
535
- removeActiveFromSublist(menuitem) {
536
- if (menuitem) {
537
- let sublist = DomHandler.findSingle(menuitem, '.p-submenu-list');
538
- if (sublist && DomHandler.hasClass(menuitem, 'p-submenu-list-active')) {
539
- DomHandler.removeClass(menuitem, 'p-submenu-list-active');
540
- }
910
+ appendOverlay() {
911
+ if (this.appendTo) {
912
+ if (this.appendTo === 'body')
913
+ this.renderer.appendChild(this.document.body, this.containerViewChild.nativeElement);
914
+ else
915
+ DomHandler.appendChild(this.containerViewChild.nativeElement, this.appendTo);
541
916
  }
542
917
  }
543
- bindGlobalListeners() {
544
- if (!this.documentClickListener) {
545
- const documentTarget = this.el ? this.el.nativeElement.ownerDocument : 'document';
546
- this.documentClickListener = this.renderer.listen(documentTarget, 'click', (event) => {
547
- if (this.containerViewChild?.nativeElement.offsetParent && this.isOutsideClicked(event) && !event.ctrlKey && event.button !== 2 && this.triggerEvent !== 'click') {
548
- this.hide();
549
- }
550
- });
551
- this.documentTriggerListener = this.renderer.listen(documentTarget, this.triggerEvent, (event) => {
552
- if (this.containerViewChild?.nativeElement.offsetParent && this.isOutsideClicked(event) && !this.preventDocumentDefault) {
553
- this.hide();
554
- }
555
- this.preventDocumentDefault = false;
556
- });
918
+ moveOnTop() {
919
+ if (this.autoZIndex && this.containerViewChild) {
920
+ ZIndexUtils.set('menu', this.containerViewChild.nativeElement, this.baseZIndex + this.config.zIndex.menu);
557
921
  }
558
- this.zone.runOutsideAngular(() => {
559
- if (!this.windowResizeListener) {
560
- this.renderer.listen(this.window, 'resize', this.onWindowResize.bind(this));
561
- }
562
- });
563
- if (!this.documentKeydownListener) {
564
- const documentTarget = this.el ? this.el.nativeElement.ownerDocument : 'document';
565
- this.documentKeydownListener = this.renderer.listen(documentTarget, 'keydown', (event) => {
566
- let activeItem = this.getActiveItem();
567
- switch (event.key) {
568
- case 'ArrowDown':
569
- if (activeItem) {
570
- this.removeActiveFromSublist(activeItem);
571
- activeItem = this.findNextItem(activeItem);
572
- }
573
- else {
574
- let firstItem = DomHandler.findSingle(this.containerViewChild?.nativeElement, '.p-menuitem-link').parentElement;
575
- activeItem = this.isItemMatched(firstItem) ? firstItem : this.findNextItem(firstItem);
576
- }
577
- if (activeItem) {
578
- this.contextMenuService.changeKey(activeItem.getAttribute('data-ik'));
579
- }
580
- event.preventDefault();
581
- break;
582
- case 'ArrowUp':
583
- if (activeItem) {
584
- this.removeActiveFromSublist(activeItem);
585
- activeItem = this.findPrevItem(activeItem);
586
- }
587
- else {
588
- let sublist = DomHandler.findSingle(this.containerViewChild?.nativeElement, 'ul');
589
- let lastItem = sublist.children[sublist.children.length - 1];
590
- activeItem = this.isItemMatched(lastItem) ? lastItem : this.findPrevItem(lastItem);
591
- }
592
- if (activeItem) {
593
- this.contextMenuService.changeKey(activeItem.getAttribute('data-ik'));
594
- }
595
- event.preventDefault();
596
- break;
597
- case 'ArrowRight':
598
- if (activeItem) {
599
- let sublist = DomHandler.findSingle(activeItem, '.p-submenu-list');
600
- if (sublist) {
601
- DomHandler.addClass(sublist, 'p-submenu-list-active');
602
- activeItem = DomHandler.findSingle(sublist, '.p-menuitem-link:not(.p-disabled)').parentElement;
603
- if (activeItem) {
604
- this.contextMenuService.changeKey(activeItem.getAttribute('data-ik'));
605
- }
606
- }
607
- }
608
- event.preventDefault();
609
- break;
610
- case 'ArrowLeft':
611
- if (activeItem) {
612
- let sublist = activeItem.parentElement;
613
- if (sublist && DomHandler.hasClass(sublist, 'p-submenu-list-active')) {
614
- DomHandler.removeClass(sublist, 'p-submenu-list-active');
615
- activeItem = sublist.parentElement.parentElement;
616
- if (activeItem) {
617
- this.contextMenuService.changeKey(activeItem.getAttribute('data-ik'));
618
- }
619
- }
620
- }
621
- event.preventDefault();
622
- break;
623
- case 'Escape':
624
- this.hide();
625
- event.preventDefault();
626
- break;
627
- case 'Enter':
628
- if (activeItem) {
629
- this.handleItemClick(event, this.findModelItemFromKey(this.contextMenuService.activeItemKey), activeItem);
630
- }
631
- event.preventDefault();
632
- break;
633
- default:
634
- break;
635
- }
636
- });
922
+ }
923
+ onOverlayHide() {
924
+ this.unbindGlobalListeners();
925
+ if (!this.cd.destroyed) {
926
+ this.target = null;
637
927
  }
928
+ if (this.appendTo) {
929
+ this.renderer.appendChild(this.el.nativeElement, this.containerViewChild?.nativeElement);
930
+ }
931
+ if (this.container && this.autoZIndex) {
932
+ ZIndexUtils.clear(this.container);
933
+ }
934
+ this.container = null;
935
+ this.onHide.emit();
936
+ }
937
+ hide() {
938
+ this.visible.set(false);
939
+ this.activeItemPath.set([]);
940
+ this.focusedItemInfo.set({ index: -1, level: 0, parentKey: '' });
941
+ }
942
+ toggle(event) {
943
+ this.visible() ? this.hide() : this.show(event);
944
+ }
945
+ show(event) {
946
+ this.activeItemPath.set([]);
947
+ this.focusedItemInfo.set({ index: -1, level: 0, parentKey: '' });
948
+ this.pageX = event.pageX;
949
+ this.pageY = event.pageY;
950
+ this.visible() ? this.position() : this.visible.set(true);
951
+ event.stopPropagation();
952
+ event.preventDefault();
638
953
  }
639
- findModelItemFromKey(key) {
640
- if (key == null || !this.model) {
641
- return null;
954
+ position() {
955
+ let left = this.pageX + 1;
956
+ let top = this.pageY + 1;
957
+ let width = this.containerViewChild.nativeElement.offsetParent ? this.containerViewChild.nativeElement.offsetWidth : DomHandler.getHiddenElementOuterWidth(this.containerViewChild.nativeElement);
958
+ let height = this.containerViewChild.nativeElement.offsetParent ? this.containerViewChild.nativeElement.offsetHeight : DomHandler.getHiddenElementOuterHeight(this.containerViewChild.nativeElement);
959
+ let viewport = DomHandler.getViewport();
960
+ //flip
961
+ if (left + width - this.document.scrollingElement.scrollLeft > viewport.width) {
962
+ left -= width;
963
+ }
964
+ //flip
965
+ if (top + height - this.document.scrollingElement.scrollTop > viewport.height) {
966
+ top -= height;
967
+ }
968
+ //fit
969
+ if (left < this.document.scrollingElement.scrollLeft) {
970
+ left = this.document.scrollingElement.scrollLeft;
971
+ }
972
+ //fit
973
+ if (top < this.document.scrollingElement.scrollTop) {
974
+ top = this.document.scrollingElement.scrollTop;
642
975
  }
643
- let indexes = key.split('_');
644
- return indexes.reduce((item, currentIndex) => {
645
- return item ? item.items[currentIndex] : this.model[currentIndex];
646
- }, null);
976
+ this.containerViewChild.nativeElement.style.left = left + 'px';
977
+ this.containerViewChild.nativeElement.style.top = top + 'px';
647
978
  }
648
- handleItemClick(event, item, menuitem) {
649
- if (!item || item.disabled) {
650
- return;
979
+ searchItems(event, char) {
980
+ this.searchValue = (this.searchValue || '') + char;
981
+ let itemIndex = -1;
982
+ let matched = false;
983
+ if (this.focusedItemInfo().index !== -1) {
984
+ itemIndex = this.visibleItems.slice(this.focusedItemInfo().index).findIndex((processedItem) => this.isItemMatched(processedItem));
985
+ itemIndex = itemIndex === -1 ? this.visibleItems.slice(0, this.focusedItemInfo().index).findIndex((processedItem) => this.isItemMatched(processedItem)) : itemIndex + this.focusedItemInfo().index;
986
+ }
987
+ else {
988
+ itemIndex = this.visibleItems.findIndex((processedItem) => this.isItemMatched(processedItem));
989
+ }
990
+ if (itemIndex !== -1) {
991
+ matched = true;
651
992
  }
652
- if (item.command) {
653
- item.command({
654
- originalEvent: event,
655
- item: item
993
+ if (itemIndex === -1 && this.focusedItemInfo().index === -1) {
994
+ itemIndex = this.findFirstFocusedItemIndex();
995
+ }
996
+ if (itemIndex !== -1) {
997
+ this.changeFocusedItemIndex(event, itemIndex);
998
+ }
999
+ if (this.searchTimeout) {
1000
+ clearTimeout(this.searchTimeout);
1001
+ }
1002
+ this.searchTimeout = setTimeout(() => {
1003
+ this.searchValue = '';
1004
+ this.searchTimeout = null;
1005
+ }, 500);
1006
+ return matched;
1007
+ }
1008
+ findLastFocusedItemIndex() {
1009
+ const selectedIndex = this.findSelectedItemIndex();
1010
+ return selectedIndex < 0 ? this.findLastItemIndex() : selectedIndex;
1011
+ }
1012
+ findLastItemIndex() {
1013
+ return ObjectUtils.findLastIndex(this.visibleItems, (processedItem) => this.isValidItem(processedItem));
1014
+ }
1015
+ findPrevItemIndex(index) {
1016
+ const matchedItemIndex = index > 0 ? ObjectUtils.findLastIndex(this.visibleItems.slice(0, index), (processedItem) => this.isValidItem(processedItem)) : -1;
1017
+ return matchedItemIndex > -1 ? matchedItemIndex : index;
1018
+ }
1019
+ findNextItemIndex(index) {
1020
+ const matchedItemIndex = index < this.visibleItems.length - 1 ? this.visibleItems.slice(index + 1).findIndex((processedItem) => this.isValidItem(processedItem)) : -1;
1021
+ return matchedItemIndex > -1 ? matchedItemIndex + index + 1 : index;
1022
+ }
1023
+ findFirstFocusedItemIndex() {
1024
+ const selectedIndex = this.findSelectedItemIndex();
1025
+ return selectedIndex < 0 ? this.findFirstItemIndex() : selectedIndex;
1026
+ }
1027
+ findFirstItemIndex() {
1028
+ return this.visibleItems.findIndex((processedItem) => this.isValidItem(processedItem));
1029
+ }
1030
+ findSelectedItemIndex() {
1031
+ return this.visibleItems.findIndex((processedItem) => this.isValidSelectedItem(processedItem));
1032
+ }
1033
+ changeFocusedItemIndex(event, index) {
1034
+ if (this.focusedItemInfo().index !== index) {
1035
+ this.focusedItemInfo.mutate((value) => {
1036
+ value.index = index;
656
1037
  });
1038
+ this.scrollInView();
657
1039
  }
658
- if (item.items) {
659
- let childSublist = DomHandler.findSingle(menuitem, '.p-submenu-list');
660
- if (childSublist) {
661
- if (DomHandler.hasClass(childSublist, 'p-submenu-list-active')) {
662
- this.removeActiveFromSubLists(menuitem);
663
- }
664
- else {
665
- DomHandler.addClass(childSublist, 'p-submenu-list-active');
666
- this.positionSubmenu(childSublist);
667
- }
1040
+ }
1041
+ scrollInView(index = -1) {
1042
+ const id = index !== -1 ? `${this.id}_${index}` : this.focusedItemId;
1043
+ const element = DomHandler.findSingle(this.rootmenu.el.nativeElement, `li[id="${id}"]`);
1044
+ if (element) {
1045
+ element.scrollIntoView && element.scrollIntoView({ block: 'nearest', inline: 'start' });
1046
+ }
1047
+ }
1048
+ bindResizeListener() {
1049
+ if (isPlatformBrowser(this.platformId)) {
1050
+ if (!this.resizeListener) {
1051
+ this.resizeListener = this.renderer.listen(this.document.defaultView, 'resize', (event) => {
1052
+ this.hide();
1053
+ });
668
1054
  }
669
1055
  }
670
- if (!item.items) {
671
- this.hide();
1056
+ }
1057
+ isOutsideClicked(event) {
1058
+ return !(this.containerViewChild.nativeElement.isSameNode(event.target) || this.containerViewChild.nativeElement.contains(event.target));
1059
+ }
1060
+ unbindResizeListener() {
1061
+ if (this.resizeListener) {
1062
+ this.resizeListener();
1063
+ this.resizeListener = null;
672
1064
  }
673
1065
  }
674
1066
  unbindGlobalListeners() {
@@ -680,63 +1072,111 @@ class ContextMenu {
680
1072
  this.documentTriggerListener();
681
1073
  this.documentTriggerListener = null;
682
1074
  }
683
- if (this.windowResizeListener) {
684
- this.windowResizeListener();
685
- this.windowResizeListener = null;
686
- }
687
- if (this.documentKeydownListener) {
688
- this.documentKeydownListener();
689
- this.documentKeydownListener = null;
1075
+ if (this.resizeListener) {
1076
+ this.resizeListener();
1077
+ this.resizeListener = null;
690
1078
  }
691
1079
  }
692
- onWindowResize() {
693
- if (this.containerViewChild?.nativeElement.offsetParent) {
694
- this.hide();
695
- }
696
- }
697
- isOutsideClicked(event) {
698
- return !(this.containerViewChild?.nativeElement.isSameNode(event.target) || this.containerViewChild?.nativeElement.contains(event.target));
699
- }
700
- ngOnDestroy() {
701
- this.unbindGlobalListeners();
1080
+ unbindTriggerEventListener() {
702
1081
  if (this.triggerEventListener) {
703
1082
  this.triggerEventListener();
704
1083
  this.triggerEventListener = null;
705
1084
  }
706
- if (this.containerViewChild && this.autoZIndex) {
707
- ZIndexUtils.clear(this.containerViewChild.nativeElement);
708
- }
709
- if (this.appendTo) {
710
- this.renderer.appendChild(this.el.nativeElement, this.containerViewChild?.nativeElement);
711
- }
712
- this.ngDestroy$.next(true);
713
- this.ngDestroy$.complete();
714
1085
  }
715
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.2", ngImport: i0, type: ContextMenu, deps: [{ token: DOCUMENT }, { token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i0.ChangeDetectorRef }, { token: i0.NgZone }, { token: i5.ContextMenuService }, { token: i5.PrimeNGConfig }], target: i0.ɵɵFactoryTarget.Component });
716
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.0.2", type: ContextMenu, selector: "p-contextMenu", inputs: { model: "model", global: "global", target: "target", style: "style", styleClass: "styleClass", appendTo: "appendTo", autoZIndex: "autoZIndex", baseZIndex: "baseZIndex", triggerEvent: "triggerEvent" }, outputs: { onShow: "onShow", onHide: "onHide" }, host: { classAttribute: "p-element" }, queries: [{ propertyName: "templates", predicate: PrimeTemplate }], viewQueries: [{ propertyName: "containerViewChild", first: true, predicate: ["container"], descendants: true }], ngImport: i0, template: `
717
- <div #container [ngClass]="'p-contextmenu p-component'" [class]="styleClass" [ngStyle]="style">
718
- <p-contextMenuSub [item]="model" [root]="true"></p-contextMenuSub>
1086
+ ngOnDestroy() {
1087
+ this.unbindGlobalListeners();
1088
+ this.unbindTriggerEventListener();
1089
+ }
1090
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.2", ngImport: i0, type: ContextMenu, deps: [{ token: DOCUMENT }, { token: PLATFORM_ID }, { token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i0.ChangeDetectorRef }, { token: i5.PrimeNGConfig }, { token: i5.OverlayService }], target: i0.ɵɵFactoryTarget.Component });
1091
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.0.2", type: ContextMenu, selector: "p-contextMenu", inputs: { model: "model", triggerEvent: "triggerEvent", target: "target", global: "global", style: "style", styleClass: "styleClass", appendTo: "appendTo", autoZIndex: "autoZIndex", baseZIndex: "baseZIndex", id: "id", ariaLabel: "ariaLabel", ariaLabelledBy: "ariaLabelledBy" }, outputs: { onShow: "onShow", onHide: "onHide" }, host: { classAttribute: "p-element" }, queries: [{ propertyName: "templates", predicate: PrimeTemplate }], viewQueries: [{ propertyName: "rootmenu", first: true, predicate: ["rootmenu"], descendants: true }, { propertyName: "containerViewChild", first: true, predicate: ["container"], descendants: true }], ngImport: i0, template: `
1092
+ <div
1093
+ #container
1094
+ [attr.data-pc-section]="'root'"
1095
+ [attr.data-pc-name]="'contextmenu'"
1096
+ [id]="id"
1097
+ [ngClass]="{ 'p-contextmenu p-component': true, 'p-contextmenu-overlay': true }"
1098
+ [class]="styleClass"
1099
+ [ngStyle]="style"
1100
+ [@overlayAnimation]="{ value: 'visible' }"
1101
+ (@overlayAnimation.start)="onOverlayAnimationStart($event)"
1102
+ (@overlayAnimation.done)="onOverlayAnimationEnd($event)"
1103
+ *ngIf="visible()"
1104
+ >
1105
+ <p-contextMenuSub
1106
+ #rootmenu
1107
+ [root]="true"
1108
+ [items]="processedItems"
1109
+ [menuId]="id"
1110
+ [tabindex]="!disabled ? tabindex : -1"
1111
+ [ariaLabel]="ariaLabel"
1112
+ [ariaLabelledBy]="ariaLabelledBy"
1113
+ [baseZIndex]="baseZIndex"
1114
+ [autoZIndex]="autoZIndex"
1115
+ [visible]="submenuVisible()"
1116
+ [focusedItemId]="focused ? focusedItemId : undefined"
1117
+ [activeItemPath]="activeItemPath()"
1118
+ (itemClick)="onItemClick($event)"
1119
+ (menuFocus)="onMenuFocus($event)"
1120
+ (menuBlur)="onMenuBlur($event)"
1121
+ (menuKeydown)="onKeyDown($event)"
1122
+ (itemMouseEnter)="onItemMouseEnter($event)"
1123
+ ></p-contextMenuSub>
719
1124
  </div>
720
- `, isInline: true, styles: [".p-contextmenu{position:absolute;display:none}.p-contextmenu ul{margin:0;padding:0;list-style:none}.p-contextmenu .p-submenu-list{position:absolute;min-width:100%;z-index:1;display:none}.p-contextmenu .p-menuitem-link{cursor:pointer;display:flex;align-items:center;text-decoration:none;overflow:hidden;position:relative}.p-contextmenu .p-menuitem-text{line-height:1}.p-contextmenu .p-menuitem{position:relative}.p-contextmenu .p-menuitem-link .p-submenu-icon:not(svg){margin-left:auto}.p-contextmenu .p-menuitem-link .p-icon-wrapper{margin-left:auto}.p-contextmenu .p-menuitem-active>p-contextmenusub>.p-submenu-list.p-submenu-list-active{display:block!important}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: ContextMenuSub, selector: "p-contextMenuSub", inputs: ["item", "root", "parentItemKey"], outputs: ["leafClick"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1125
+ `, isInline: true, styles: [".p-contextmenu{position:absolute}.p-contextmenu ul{margin:0;padding:0;list-style:none}.p-contextmenu .p-submenu-list{position:absolute;min-width:100%;z-index:1}.p-contextmenu .p-menuitem-link{cursor:pointer;display:flex;align-items:center;text-decoration:none;overflow:hidden;position:relative}.p-contextmenu .p-menuitem-text{line-height:1}.p-contextmenu .p-menuitem{position:relative}.p-contextmenu .p-menuitem-link .p-submenu-icon:not(svg){margin-left:auto}.p-contextmenu .p-menuitem-link .p-icon-wrapper{margin-left:auto}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: ContextMenuSub, selector: "p-contextMenuSub", inputs: ["visible", "items", "root", "autoZIndex", "baseZIndex", "popup", "menuId", "ariaLabel", "ariaLabelledBy", "level", "focusedItemId", "activeItemPath", "tabindex"], outputs: ["itemClick", "itemMouseEnter", "menuFocus", "menuBlur", "menuKeydown"] }], animations: [trigger('overlayAnimation', [transition(':enter', [style({ opacity: 0 }), animate('250ms')]), transition(':leave', [animate('.1s linear', style({ opacity: 0 }))])])], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
721
1126
  }
722
1127
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.2", ngImport: i0, type: ContextMenu, decorators: [{
723
1128
  type: Component,
724
1129
  args: [{ selector: 'p-contextMenu', template: `
725
- <div #container [ngClass]="'p-contextmenu p-component'" [class]="styleClass" [ngStyle]="style">
726
- <p-contextMenuSub [item]="model" [root]="true"></p-contextMenuSub>
1130
+ <div
1131
+ #container
1132
+ [attr.data-pc-section]="'root'"
1133
+ [attr.data-pc-name]="'contextmenu'"
1134
+ [id]="id"
1135
+ [ngClass]="{ 'p-contextmenu p-component': true, 'p-contextmenu-overlay': true }"
1136
+ [class]="styleClass"
1137
+ [ngStyle]="style"
1138
+ [@overlayAnimation]="{ value: 'visible' }"
1139
+ (@overlayAnimation.start)="onOverlayAnimationStart($event)"
1140
+ (@overlayAnimation.done)="onOverlayAnimationEnd($event)"
1141
+ *ngIf="visible()"
1142
+ >
1143
+ <p-contextMenuSub
1144
+ #rootmenu
1145
+ [root]="true"
1146
+ [items]="processedItems"
1147
+ [menuId]="id"
1148
+ [tabindex]="!disabled ? tabindex : -1"
1149
+ [ariaLabel]="ariaLabel"
1150
+ [ariaLabelledBy]="ariaLabelledBy"
1151
+ [baseZIndex]="baseZIndex"
1152
+ [autoZIndex]="autoZIndex"
1153
+ [visible]="submenuVisible()"
1154
+ [focusedItemId]="focused ? focusedItemId : undefined"
1155
+ [activeItemPath]="activeItemPath()"
1156
+ (itemClick)="onItemClick($event)"
1157
+ (menuFocus)="onMenuFocus($event)"
1158
+ (menuBlur)="onMenuBlur($event)"
1159
+ (menuKeydown)="onKeyDown($event)"
1160
+ (itemMouseEnter)="onItemMouseEnter($event)"
1161
+ ></p-contextMenuSub>
727
1162
  </div>
728
- `, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
1163
+ `, animations: [trigger('overlayAnimation', [transition(':enter', [style({ opacity: 0 }), animate('250ms')]), transition(':leave', [animate('.1s linear', style({ opacity: 0 }))])])], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
729
1164
  class: 'p-element'
730
- }, styles: [".p-contextmenu{position:absolute;display:none}.p-contextmenu ul{margin:0;padding:0;list-style:none}.p-contextmenu .p-submenu-list{position:absolute;min-width:100%;z-index:1;display:none}.p-contextmenu .p-menuitem-link{cursor:pointer;display:flex;align-items:center;text-decoration:none;overflow:hidden;position:relative}.p-contextmenu .p-menuitem-text{line-height:1}.p-contextmenu .p-menuitem{position:relative}.p-contextmenu .p-menuitem-link .p-submenu-icon:not(svg){margin-left:auto}.p-contextmenu .p-menuitem-link .p-icon-wrapper{margin-left:auto}.p-contextmenu .p-menuitem-active>p-contextmenusub>.p-submenu-list.p-submenu-list-active{display:block!important}\n"] }]
1165
+ }, styles: [".p-contextmenu{position:absolute}.p-contextmenu ul{margin:0;padding:0;list-style:none}.p-contextmenu .p-submenu-list{position:absolute;min-width:100%;z-index:1}.p-contextmenu .p-menuitem-link{cursor:pointer;display:flex;align-items:center;text-decoration:none;overflow:hidden;position:relative}.p-contextmenu .p-menuitem-text{line-height:1}.p-contextmenu .p-menuitem{position:relative}.p-contextmenu .p-menuitem-link .p-submenu-icon:not(svg){margin-left:auto}.p-contextmenu .p-menuitem-link .p-icon-wrapper{margin-left:auto}\n"] }]
731
1166
  }], ctorParameters: function () { return [{ type: Document, decorators: [{
732
1167
  type: Inject,
733
1168
  args: [DOCUMENT]
734
- }] }, { type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i0.ChangeDetectorRef }, { type: i0.NgZone }, { type: i5.ContextMenuService }, { type: i5.PrimeNGConfig }]; }, propDecorators: { model: [{
1169
+ }] }, { type: undefined, decorators: [{
1170
+ type: Inject,
1171
+ args: [PLATFORM_ID]
1172
+ }] }, { type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i0.ChangeDetectorRef }, { type: i5.PrimeNGConfig }, { type: i5.OverlayService }]; }, propDecorators: { model: [{
735
1173
  type: Input
736
- }], global: [{
1174
+ }], triggerEvent: [{
737
1175
  type: Input
738
1176
  }], target: [{
739
1177
  type: Input
1178
+ }], global: [{
1179
+ type: Input
740
1180
  }], style: [{
741
1181
  type: Input
742
1182
  }], styleClass: [{
@@ -747,31 +1187,37 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.2", ngImpor
747
1187
  type: Input
748
1188
  }], baseZIndex: [{
749
1189
  type: Input
750
- }], triggerEvent: [{
1190
+ }], id: [{
1191
+ type: Input
1192
+ }], ariaLabel: [{
1193
+ type: Input
1194
+ }], ariaLabelledBy: [{
751
1195
  type: Input
752
1196
  }], onShow: [{
753
1197
  type: Output
754
1198
  }], onHide: [{
755
1199
  type: Output
756
- }], containerViewChild: [{
757
- type: ViewChild,
758
- args: ['container']
759
1200
  }], templates: [{
760
1201
  type: ContentChildren,
761
1202
  args: [PrimeTemplate]
1203
+ }], rootmenu: [{
1204
+ type: ViewChild,
1205
+ args: ['rootmenu']
1206
+ }], containerViewChild: [{
1207
+ type: ViewChild,
1208
+ args: ['container']
762
1209
  }] } });
763
1210
  class ContextMenuModule {
764
1211
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.2", ngImport: i0, type: ContextMenuModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
765
- static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.0.2", ngImport: i0, type: ContextMenuModule, declarations: [ContextMenu, ContextMenuSub], imports: [CommonModule, RouterModule, RippleModule, TooltipModule, SharedModule, AngleRightIcon], exports: [ContextMenu, RouterModule, TooltipModule, SharedModule] });
766
- static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.0.2", ngImport: i0, type: ContextMenuModule, providers: [ContextMenuService], imports: [CommonModule, RouterModule, RippleModule, TooltipModule, SharedModule, AngleRightIcon, RouterModule, TooltipModule, SharedModule] });
1212
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.0.2", ngImport: i0, type: ContextMenuModule, declarations: [ContextMenu, ContextMenuSub], imports: [CommonModule, RouterModule, RippleModule, TooltipModule, AngleRightIcon, SharedModule], exports: [ContextMenu, RouterModule, TooltipModule, SharedModule] });
1213
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.0.2", ngImport: i0, type: ContextMenuModule, imports: [CommonModule, RouterModule, RippleModule, TooltipModule, AngleRightIcon, SharedModule, RouterModule, TooltipModule, SharedModule] });
767
1214
  }
768
1215
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.2", ngImport: i0, type: ContextMenuModule, decorators: [{
769
1216
  type: NgModule,
770
1217
  args: [{
771
- imports: [CommonModule, RouterModule, RippleModule, TooltipModule, SharedModule, AngleRightIcon],
1218
+ imports: [CommonModule, RouterModule, RippleModule, TooltipModule, AngleRightIcon, SharedModule],
772
1219
  exports: [ContextMenu, RouterModule, TooltipModule, SharedModule],
773
- declarations: [ContextMenu, ContextMenuSub],
774
- providers: [ContextMenuService]
1220
+ declarations: [ContextMenu, ContextMenuSub]
775
1221
  }]
776
1222
  }] });
777
1223